46 double threshold)
const {
53 std::vector<libint2::Engine> engines;
54 engines.reserve(nthreads);
56 for (
Index i = 1; i != nthreads; ++i) {
57 engines.push_back(engines[0]);
60 std::vector<std::vector<Index>> pairs(shells.size());
62#pragma omp parallel for schedule(dynamic)
63 for (
Index s1 = 0; s1 <
Index(shells.size()); ++s1) {
66 libint2::Engine& engine = engines[thread_id];
67 const libint2::Engine::target_ptr_vec& buf = engine.results();
68 Index n1 = shells[s1].size();
70 for (
Index s2 = 0; s2 <= s1; ++s2) {
71 bool on_same_center = (shells[s1].O == shells[s2].O);
72 bool significant = on_same_center;
73 if (!on_same_center) {
74 Index n2 = shells[s2].size();
75 engine.compute(shells[s1], shells[s2]);
76 Eigen::Map<const Eigen::MatrixXd> buf_mat(buf[0], n1, n2);
77 significant = (buf_mat.norm() >= threshold);
80 pairs[s1].push_back(s2);
83 std::sort(pairs[s1].
begin(), pairs[s1].
end());
96 OperatorParams oparams = OperatorParams()) {
103 Index nopers =
static_cast<Index>(libint2::operator_traits<obtype>::nopers);
104 std::array<MatrixLibInt, libint2::operator_traits<obtype>::nopers> result;
109 std::vector<libint2::Engine> engines(nthreads);
110 engines[0] = libint2::Engine(obtype, aobasis.
getMaxNprim(),
111 static_cast<int>(aobasis.
getMaxL()), 0);
112 engines[0].set_params(oparams);
113 for (
Index i = 1; i < nthreads; ++i) {
114 engines[i] = engines[0];
119#pragma omp parallel for schedule(dynamic)
122 libint2::Engine& engine = engines[thread_id];
123 const libint2::Engine::target_ptr_vec& buf = engine.results();
125 Index bf1 = shell2bf[s1];
126 Index n1 = shells[s1].size();
128 for (
Index s2 : shellpair_list[s1]) {
130 engine.compute(shells[s1], shells[s2]);
131 if (buf[0] ==
nullptr) {
134 Index bf2 = shell2bf[s2];
135 Index n2 = shells[s2].size();
136 for (
unsigned int op = 0; op != nopers; ++op) {
137 Eigen::Map<const MatrixLibInt> buf_mat(buf[op], n1, n2);
138 result[op].block(bf1, bf2, n1, n2) = buf_mat;
141 result[op].block(bf2, bf1, n2, n1) = buf_mat.transpose();
164 libint2::Shell::do_enforce_unit_normalization(
false);
165 libint2::Operator obtype = libint2::Operator::overlap;
167 libint2::Engine engine(obtype, shell.
getSize(),
168 static_cast<int>(shell.
getL()), 0);
170 const libint2::Engine::target_ptr_vec& buf = engine.results();
173 engine.compute(s, s);
175 Eigen::Map<const MatrixLibInt> buf_mat(buf[0], shell.
getNumFunc(),
178 }
catch (
const libint2::Engine::lmax_exceeded& error) {
179 std::ostringstream oss;
180 oss <<
"\nA libint error occured:\n"
181 << error.what() <<
"\n"
182 <<
"\nYou requested a computation for a shell with angular momentum "
183 << error.lmax_requested()
184 <<
",\nbut your libint package only supports angular momenta upto "
185 << error.lmax_limit() - 1 <<
".\n"
186 <<
"\nTo fix this error you will need to reinstall libint with "
188 "for higher angular momenta. If you installed your own libint it\n"
189 "should be reconfigured and installed with the option "
190 "--with-max-am=<maxAngularMomentum>.\n"
191 "If you installed libint with your OS package manager, you will\n"
192 "need to setup you own libint installation with the \n"
193 "--with-max-am=<maxAngularMomentum> option set."
195 throw std::runtime_error(oss.str());
229 std::vector<libint2::Engine> engines(nthreads);
231 libint2::Engine(libint2::Operator::coulomb, aobasis.
getMaxNprim(),
232 static_cast<int>(aobasis.
getMaxL()), 0);
233 engines[0].set(libint2::BraKet::xs_xs);
234 for (
Index i = 1; i != nthreads; ++i) {
235 engines[i] = engines[0];
238#pragma omp parallel for schedule(dynamic)
241 const libint2::Engine::target_ptr_vec& buf = engine.results();
243 Index bf1 = shell2bf[s1];
244 Index n1 = shells[s1].size();
247 for (
Index s2 = 0; s2 <= s1; ++s2) {
249 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xs, 0>(
250 shells[s1], libint2::Shell::unit(), shells[s2],
251 libint2::Shell::unit());
253 if (buf[0] ==
nullptr) {
256 Index bf2 = shell2bf[s2];
257 Index n2 = shells[s2].size();
259 Eigen::Map<const MatrixLibInt> buf_mat(buf[0], n1, n2);
260 aomatrix_.block(bf1, bf2, n1, n2) = buf_mat;
263 aomatrix_.block(bf2, bf1, n2, n1) = buf_mat.transpose();
273 Eigen::MatrixXd result = Eigen::MatrixXd::Zero(noshells, noshells);
275 std::vector<libint2::Engine> engines(nthreads);
276 double epsilon = 0.0;
277 engines[0] = libint2::Engine(libint2::Operator::coulomb, basis.
getMaxNprim(),
278 static_cast<int>(basis.
getMaxL()), 0, epsilon);
280 for (
Index i = 1; i < nthreads; ++i) {
281 engines[i] = engines[0];
286#pragma omp parallel for schedule(dynamic)
289 libint2::Engine& engine = engines[thread_id];
290 const libint2::Engine::target_ptr_vec& buf = engine.results();
291 Index n1 = shells[s1].size();
293 for (
Index s2 = 0l; s2 <= s1; ++s2) {
294 Index n2 = shells[s2].size();
298 .compute2<libint2::Operator::coulomb, libint2::BraKet::xx_xx, 0>(
299 shells[s1], shells[s2], shells[s1], shells[s2]);
301 Eigen::Map<const MatrixLibInt> buf_mat(buf[0], n12, n12);
303 result(s2, s1) = std::sqrt(buf_mat.cwiseAbs().maxCoeff());
306 return result.selfadjointView<Eigen::Upper>();
311 double error)
const {
313 "Please call Initialize_4c before running this");
316 Eigen::MatrixXd hartree = Eigen::MatrixXd::Zero(dmat.rows(), dmat.cols());
317 Eigen::MatrixXd exchange;
319 exchange = Eigen::MatrixXd::Zero(dmat.rows(), dmat.cols());
322 double fock_precision = error;
326 double engine_precision = std::min(fock_precision / dnorm_block.maxCoeff(),
327 std::numeric_limits<double>::epsilon()) /
329 std::vector<libint2::Engine> engines(nthreads);
330 engines[0] = libint2::Engine(libint2::Operator::coulomb,
int(
maxnprim_),
332 engines[0].set_precision(engine_precision);
336 for (
Index i = 1; i < nthreads; ++i) {
337 engines[i] = engines[0];
341#pragma omp parallel for schedule(dynamic) reduction(+ : hartree) \
342 reduction(+ : exchange)
343 for (
Index s1 = 0; s1 < nshells; ++s1) {
345 libint2::Engine& engine = engines[thread_id];
346 const auto& buf = engine.results();
348 const libint2::Shell& shell1 =
basis_[s1];
349 Index n1 = shell1.size();
354 const libint2::Shell& shell2 =
basis_[s2];
355 Index n2 = shell2.size();
356 double dnorm_12 = dnorm_block(s1, s2);
357 const libint2::ShellPair* sp12 = &(*sp12_iter);
360 for (
Index s3 = 0; s3 <= s1; ++s3) {
363 const libint2::Shell& shell3 =
basis_[s3];
364 Index n3 = shell3.size();
366 double dnorm_123 = std::max(dnorm_block(s1, s3),
367 std::max(dnorm_block(s2, s3), dnorm_12));
368 Index s4max = (s1 == s3) ? s2 : s3;
375 const libint2::ShellPair* sp34 = &(*sp34_iter);
379 std::max(dnorm_block(s1, s4),
380 std::max(dnorm_block(s2, s4),
381 std::max(dnorm_block(s3, s4), dnorm_123)));
388 const libint2::Shell& shell4 =
basis_[s4];
390 .compute2<libint2::Operator::coulomb, libint2::BraKet::xx_xx, 0>(
391 shell1, shell2, shell3, shell4, sp12, sp34);
392 const auto* buf_1234 = buf[0];
393 if (buf_1234 ==
nullptr) {
397 Index n4 = shell4.size();
398 Index s12_deg = (s1 == s2) ? 1 : 2;
399 Index s34_deg = (s3 == s4) ? 1 : 2;
400 Index s12_34_deg = (s1 == s3) ? (s2 == s4 ? 1 : 2) : 2;
401 Index s1234_deg = s12_deg * s34_deg * s12_34_deg;
403 for (
Index f1 = 0, f1234 = 0; f1 != n1; ++f1) {
404 const Index bf1 = f1 + start_1;
405 for (
Index f2 = 0; f2 != n2; ++f2) {
406 const Index bf2 = f2 + start_2;
407 for (
Index f3 = 0; f3 != n3; ++f3) {
408 const Index bf3 = f3 + start_3;
409 for (
Index f4 = 0; f4 != n4; ++f4, ++f1234) {
410 const Index bf4 = f4 + start_4;
412 const double value = buf_1234[f1234];
414 const double value_scal_by_deg = value * double(s1234_deg);
416 hartree(bf1, bf2) += dmat(bf3, bf4) * value_scal_by_deg;
417 hartree(bf3, bf4) += dmat(bf1, bf2) * value_scal_by_deg;
419 exchange(bf1, bf3) -= dmat(bf2, bf4) * value_scal_by_deg;
420 exchange(bf2, bf3) -= dmat(bf1, bf4) * value_scal_by_deg;
421 exchange(bf2, bf4) -= dmat(bf1, bf3) * value_scal_by_deg;
422 exchange(bf1, bf4) -= dmat(bf2, bf3) * value_scal_by_deg;
432 std::array<Eigen::MatrixXd, 2> result2;
434 result2[0] = 0.25 * (hartree + hartree.transpose());
437 result2[1] = 0.125 * (exchange + exchange.transpose());
450 auxAOcoulomb.
Fill(auxbasis);
456#pragma omp parallel for schedule(dynamic, 4)
464 std::vector<libint2::Engine> engines(nthreads);
465 engines[0] = libint2::Engine(
466 libint2::Operator::coulomb,
468 static_cast<int>(std::max(dftbasis.
getMaxL(), auxbasis.
getMaxL())), 0);
469 engines[0].set(libint2::BraKet::xs_xx);
470 for (
Index i = 1; i < nthreads; ++i) {
471 engines[i] = engines[0];
477#pragma omp parallel for schedule(dynamic)
481 const libint2::Engine::target_ptr_vec& buf = engine.results();
482 const libint2::Shell& dftshell = dftshells[is];
483 Index start = shell2bf[is];
484 std::vector<Eigen::MatrixXd> block(dftshell.size());
485 for (
Index i = 0; i <
Index(dftshell.size()); i++) {
491 const libint2::Shell& auxshell = auxshells[aux];
492 Index aux_start = auxshell2bf[aux];
494 for (
Index dis = 0; dis <= is; dis++) {
496 const libint2::Shell& shell_col = dftshells[dis];
497 Index col_start = shell2bf[dis];
498 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xx, 0>(
499 auxshell, libint2::Shell::unit(), dftshell, shell_col);
501 if (buf[0] ==
nullptr) {
504 Eigen::TensorMap<Eigen::Tensor<const double, 3, Eigen::RowMajor>
const>
505 result(buf[0], auxshell.size(), dftshell.size(), shell_col.size());
507 for (
size_t left = 0; left < dftshell.size(); left++) {
508 for (
size_t auxf = 0; auxf < auxshell.size(); auxf++) {
509 for (
size_t col = 0; col < shell_col.size(); col++) {
511 if ((col_start + col) > (start + left)) {
514 block[left](aux_start + auxf, col_start + col) =
515 result(auxf, left, col);
522 for (
Index i = 0; i <
Index(block.size()); ++i) {
523 Eigen::MatrixXd temp =
inv_sqrt_ * block[i];
524 for (
Index mu = 0; mu < temp.rows(); ++mu) {
525 for (
Index j = 0; j < temp.cols(); ++j) {
526 matrix_[mu](i + start, j) = temp(mu, j);
542 libint2::Engine& engine) {
543 std::vector<Eigen::MatrixXd> ao3c = std::vector<Eigen::MatrixXd>(
550 const libint2::Engine::target_ptr_vec& buf = engine.results();
552 for (
Index row = 0; row <
Index(dftshells.size()); row++) {
554 const libint2::Shell& shell_row = dftshells[row];
555 const Index row_start = shell2bf[row];
558 for (
Index col = 0; col <= row; col++) {
559 const libint2::Shell& shell_col = dftshells[col];
560 const Index col_start = shell2bf[col];
562 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xx, 0>(
563 auxshell, libint2::Shell::unit(), shell_col, shell_row);
565 if (buf[0] ==
nullptr) {
568 Eigen::TensorMap<Eigen::Tensor<const double, 3, Eigen::RowMajor>
const>
569 result(buf[0], auxshell.size(), shell_col.size(), shell_row.size());
571 for (
size_t aux_c = 0; aux_c < auxshell.size(); aux_c++) {
572 for (
size_t col_c = 0; col_c < shell_col.size(); col_c++) {
573 for (
size_t row_c = 0; row_c < shell_row.size(); row_c++) {
575 ao3c[aux_c](row_start + row_c, col_start + col_c) =
576 result(aux_c, col_c, row_c);
584 for (Eigen::MatrixXd& mat : ao3c) {
585 mat.triangularView<Eigen::Upper>() =
586 mat.triangularView<Eigen::Lower>().transpose();
592 const Eigen::MatrixXd& dft_orbitals) {
594 const Eigen::MatrixXd dftm = dft_orbitals.middleCols(
mmin_,
mtotal_);
595 const Eigen::MatrixXd dftn =
603 std::vector<libint2::Engine> engines(nthreads);
604 engines[0] = libint2::Engine(
605 libint2::Operator::coulomb,
607 static_cast<int>(std::max(dftbasis.
getMaxL(), auxbasis.
getMaxL())), 0);
608 engines[0].set(libint2::BraKet::xs_xx);
609 for (
Index i = 1; i < nthreads; ++i) {
610 engines[i] = engines[0];
617#pragma omp for schedule(dynamic)
618 for (
Index aux = 0; aux <
Index(auxshells.size()); aux++) {
619 const libint2::Shell& auxshell = auxshells[aux];
621 std::vector<Eigen::MatrixXd> ao3c =
629 std::vector<Eigen::MatrixXd> block = std::vector<Eigen::MatrixXd>(
633 for (
Index k = 0; k < dim; ++k) {
635 for (
Index i = 0; i < ao3c[k].cols(); ++i) {
636 block[i].col(k) = ao3c[k].col(i);
642 matrix_[m_level].middleCols(auxshell2bf[aux], auxshell.size()) =