35#define LIBINT2_CONSTEXPR_STATICS 0
37#pragma clang diagnostic push
38#pragma clang diagnostic ignored "-W#warnings"
39#elif defined(__GNUC__)
40#pragma GCC diagnostic push
41#pragma GCC diagnostic ignored "-Warray-bounds"
42#pragma GCC diagnostic ignored "-Wcpp"
45#include <libint2/statics_definition.h>
47#pragma clang diagnostic pop
48#elif defined(__GNUC__)
49#pragma GCC diagnostic pop
56 double threshold)
const {
63 std::vector<libint2::Engine> engines;
64 engines.reserve(nthreads);
66 for (
Index i = 1; i != nthreads; ++i) {
67 engines.push_back(engines[0]);
70 std::vector<std::vector<Index>> pairs(shells.size());
72#pragma omp parallel for schedule(dynamic)
73 for (
Index s1 = 0; s1 <
Index(shells.size()); ++s1) {
76 libint2::Engine& engine = engines[thread_id];
77 const libint2::Engine::target_ptr_vec& buf = engine.results();
78 Index n1 = shells[s1].size();
80 for (
Index s2 = 0; s2 <= s1; ++s2) {
81 bool on_same_center = (shells[s1].O == shells[s2].O);
82 bool significant = on_same_center;
83 if (!on_same_center) {
84 Index n2 = shells[s2].size();
85 engine.compute(shells[s1], shells[s2]);
86 Eigen::Map<const Eigen::MatrixXd> buf_mat(buf[0], n1, n2);
87 significant = (buf_mat.norm() >= threshold);
90 pairs[s1].push_back(s2);
93 std::sort(pairs[s1].
begin(), pairs[s1].
end());
99 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
101template <libint2::Operator obtype,
102 typename OperatorParams =
103 typename libint2::operator_traits<obtype>::oper_params_type>
104std::array<MatrixLibInt, libint2::operator_traits<obtype>::nopers>
106 OperatorParams oparams = OperatorParams()) {
113 Index nopers =
static_cast<Index>(libint2::operator_traits<obtype>::nopers);
114 std::array<MatrixLibInt, libint2::operator_traits<obtype>::nopers> result;
119 std::vector<libint2::Engine> engines(nthreads);
120 engines[0] = libint2::Engine(obtype, aobasis.
getMaxNprim(),
121 static_cast<int>(aobasis.
getMaxL()), 0);
122 engines[0].set_params(oparams);
123 for (
Index i = 1; i < nthreads; ++i) {
124 engines[i] = engines[0];
129#pragma omp parallel for schedule(dynamic)
132 libint2::Engine& engine = engines[thread_id];
133 const libint2::Engine::target_ptr_vec& buf = engine.results();
135 Index bf1 = shell2bf[s1];
136 Index n1 = shells[s1].size();
138 for (
Index s2 : shellpair_list[s1]) {
140 engine.compute(shells[s1], shells[s2]);
141 if (buf[0] ==
nullptr) {
144 Index bf2 = shell2bf[s2];
145 Index n2 = shells[s2].size();
146 for (
unsigned int op = 0; op != nopers; ++op) {
147 Eigen::Map<const MatrixLibInt> buf_mat(buf[op], n1, n2);
148 result[op].block(bf1, bf2, n1, n2) = buf_mat;
151 result[op].block(bf2, bf1, n2, n1) = buf_mat.transpose();
174 libint2::Shell::do_enforce_unit_normalization(
false);
175 libint2::Operator obtype = libint2::Operator::overlap;
177 libint2::Engine engine(obtype, shell.
getSize(),
178 static_cast<int>(shell.
getL()), 0);
180 const libint2::Engine::target_ptr_vec& buf = engine.results();
183 engine.compute(s, s);
185 Eigen::Map<const MatrixLibInt> buf_mat(buf[0], shell.
getNumFunc(),
188 }
catch (
const libint2::Engine::lmax_exceeded& error) {
189 std::ostringstream oss;
190 oss <<
"\nA libint error occured:\n"
191 << error.what() <<
"\n"
192 <<
"\nYou requested a computation for a shell with angular momentum "
193 << error.lmax_requested()
194 <<
",\nbut your libint package only supports angular momenta upto "
195 << error.lmax_limit() - 1 <<
".\n"
196 <<
"\nTo fix this error you will need to reinstall libint with "
198 "for higher angular momenta. If you installed your own libint it\n"
199 "should be reconfigured and installed with the option "
200 "--with-max-am=<maxAngularMomentum>.\n"
201 "If you installed libint with your OS package manager, you will\n"
202 "need to setup you own libint installation with the \n"
203 "--with-max-am=<maxAngularMomentum> option set."
205 throw std::runtime_error(oss.str());
214 std::array<libint2::Shell::real_t, 3>>(
217 for (
Index i = 0; i < 3; i++) {
239 std::vector<libint2::Engine> engines(nthreads);
241 libint2::Engine(libint2::Operator::coulomb, aobasis.
getMaxNprim(),
242 static_cast<int>(aobasis.
getMaxL()), 0);
243 engines[0].set(libint2::BraKet::xs_xs);
244 for (
Index i = 1; i != nthreads; ++i) {
245 engines[i] = engines[0];
248#pragma omp parallel for schedule(dynamic)
251 const libint2::Engine::target_ptr_vec& buf = engine.results();
253 Index bf1 = shell2bf[s1];
254 Index n1 = shells[s1].size();
257 for (
Index s2 = 0; s2 <= s1; ++s2) {
259 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xs, 0>(
260 shells[s1], libint2::Shell::unit(), shells[s2],
261 libint2::Shell::unit());
263 if (buf[0] ==
nullptr) {
266 Index bf2 = shell2bf[s2];
267 Index n2 = shells[s2].size();
269 Eigen::Map<const MatrixLibInt> buf_mat(buf[0], n1, n2);
270 aomatrix_.block(bf1, bf2, n1, n2) = buf_mat;
273 aomatrix_.block(bf2, bf1, n2, n1) = buf_mat.transpose();
283 Eigen::MatrixXd result = Eigen::MatrixXd::Zero(noshells, noshells);
285 std::vector<libint2::Engine> engines(nthreads);
286 double epsilon = 0.0;
287 engines[0] = libint2::Engine(libint2::Operator::coulomb, basis.
getMaxNprim(),
288 static_cast<int>(basis.
getMaxL()), 0, epsilon);
290 for (
Index i = 1; i < nthreads; ++i) {
291 engines[i] = engines[0];
296#pragma omp parallel for schedule(dynamic)
299 libint2::Engine& engine = engines[thread_id];
300 const libint2::Engine::target_ptr_vec& buf = engine.results();
301 Index n1 = shells[s1].size();
303 for (
Index s2 = 0l; s2 <= s1; ++s2) {
304 Index n2 = shells[s2].size();
308 .compute2<libint2::Operator::coulomb, libint2::BraKet::xx_xx, 0>(
309 shells[s1], shells[s2], shells[s1], shells[s2]);
311 Eigen::Map<const MatrixLibInt> buf_mat(buf[0], n12, n12);
313 result(s2, s1) = std::sqrt(buf_mat.cwiseAbs().maxCoeff());
316 return result.selfadjointView<Eigen::Upper>();
319template <
bool with_exchange>
321 double error)
const {
323 "Please call Initialize_4c before running this");
326 Eigen::MatrixXd hartree = Eigen::MatrixXd::Zero(dmat.rows(), dmat.cols());
327 Eigen::MatrixXd exchange;
329 exchange = Eigen::MatrixXd::Zero(dmat.rows(), dmat.cols());
332 double fock_precision = error;
336 double engine_precision = std::min(fock_precision / dnorm_block.maxCoeff(),
337 std::numeric_limits<double>::epsilon()) /
339 std::vector<libint2::Engine> engines(nthreads);
340 engines[0] = libint2::Engine(libint2::Operator::coulomb,
int(
maxnprim_),
342 engines[0].set_precision(engine_precision);
346 for (
Index i = 1; i < nthreads; ++i) {
347 engines[i] = engines[0];
351#pragma omp parallel for schedule(dynamic) reduction(+ : hartree) \
352 reduction(+ : exchange)
353 for (
Index s1 = 0; s1 < nshells; ++s1) {
355 libint2::Engine& engine = engines[thread_id];
356 const auto& buf = engine.results();
358 const libint2::Shell& shell1 =
basis_[s1];
359 Index n1 = shell1.size();
364 const libint2::Shell& shell2 =
basis_[s2];
365 Index n2 = shell2.size();
366 double dnorm_12 = dnorm_block(s1, s2);
367 const libint2::ShellPair* sp12 = &(*sp12_iter);
370 for (
Index s3 = 0; s3 <= s1; ++s3) {
373 const libint2::Shell& shell3 =
basis_[s3];
374 Index n3 = shell3.size();
376 double dnorm_123 = std::max(dnorm_block(s1, s3),
377 std::max(dnorm_block(s2, s3), dnorm_12));
378 Index s4max = (s1 == s3) ? s2 : s3;
385 const libint2::ShellPair* sp34 = &(*sp34_iter);
389 std::max(dnorm_block(s1, s4),
390 std::max(dnorm_block(s2, s4),
391 std::max(dnorm_block(s3, s4), dnorm_123)));
398 const libint2::Shell& shell4 =
basis_[s4];
400 .compute2<libint2::Operator::coulomb, libint2::BraKet::xx_xx, 0>(
401 shell1, shell2, shell3, shell4, sp12, sp34);
402 const auto* buf_1234 = buf[0];
403 if (buf_1234 ==
nullptr) {
407 Index n4 = shell4.size();
408 Index s12_deg = (s1 == s2) ? 1 : 2;
409 Index s34_deg = (s3 == s4) ? 1 : 2;
410 Index s12_34_deg = (s1 == s3) ? (s2 == s4 ? 1 : 2) : 2;
411 Index s1234_deg = s12_deg * s34_deg * s12_34_deg;
413 for (
Index f1 = 0, f1234 = 0; f1 != n1; ++f1) {
414 const Index bf1 = f1 + start_1;
415 for (
Index f2 = 0; f2 != n2; ++f2) {
416 const Index bf2 = f2 + start_2;
417 for (
Index f3 = 0; f3 != n3; ++f3) {
418 const Index bf3 = f3 + start_3;
419 for (
Index f4 = 0; f4 != n4; ++f4, ++f1234) {
420 const Index bf4 = f4 + start_4;
422 const double value = buf_1234[f1234];
424 const double value_scal_by_deg = value * double(s1234_deg);
426 hartree(bf1, bf2) += dmat(bf3, bf4) * value_scal_by_deg;
427 hartree(bf3, bf4) += dmat(bf1, bf2) * value_scal_by_deg;
429 exchange(bf1, bf3) -= dmat(bf2, bf4) * value_scal_by_deg;
430 exchange(bf2, bf3) -= dmat(bf1, bf4) * value_scal_by_deg;
431 exchange(bf2, bf4) -= dmat(bf1, bf3) * value_scal_by_deg;
432 exchange(bf1, bf4) -= dmat(bf2, bf3) * value_scal_by_deg;
442 std::array<Eigen::MatrixXd, 2> result2;
444 result2[0] = 0.25 * (hartree + hartree.transpose());
447 result2[1] = 0.125 * (exchange + exchange.transpose());
453 const Eigen::MatrixXd& dmat,
double error)
const;
455 const Eigen::MatrixXd& dmat,
double error)
const;
458 const AOBasis& dftbasis,
const Eigen::MatrixXd& metric,
459 double pair_threshold)
const {
461 std::vector<std::vector<Index>> kept(nshells);
462 if (pair_threshold <= 0.0) {
463 for (
Index a = 0; a < nshells; ++a) {
464 kept[a].resize(a + 1);
465 std::iota(kept[a].begin(), kept[a].end(),
Index(0));
470 const double max_aux = std::sqrt(metric.diagonal().cwiseAbs().maxCoeff());
472 std::vector<libint2::Engine> engines(nthreads);
474 libint2::Engine(libint2::Operator::coulomb, dftbasis.
getMaxNprim(),
475 static_cast<int>(dftbasis.
getMaxL()), 0, 0.0);
476 for (
Index i = 1; i < nthreads; ++i) {
477 engines[i] = engines[0];
480#pragma omp parallel for schedule(dynamic)
481 for (
Index a = nshells - 1; a >= 0; --a) {
483 const libint2::Engine::target_ptr_vec& buf = engine.results();
484 for (
Index b = 0; b < a; ++b) {
485 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xx_xx, 0>(
486 shells[a], shells[b], shells[a], shells[b]);
487 if (buf[0] ==
nullptr) {
491 const double schwarz =
492 std::sqrt(Eigen::Map<const Eigen::MatrixXd>(buf[0], n, n)
495 if (max_aux * schwarz >= pair_threshold) {
496 kept[a].push_back(b);
499 kept[a].push_back(a);
505 double pair_threshold,
Index build_columns) {
506 std::vector<std::vector<Index>> kept;
508 auto metric_start = std::chrono::steady_clock::now();
510 auxAOcoulomb.
Fill(auxbasis);
514 std::chrono::steady_clock::now() - metric_start)
538 std::vector<Unit> units;
548 rows + na *
Index(dftshells[kept[a][last]].
size()) <=
550 rows += na *
Index(dftshells[kept[a][last]].
size());
553 max_rows = std::max(max_rows, rows);
554 units.push_back({a, first, last});
560 std::vector<libint2::Engine> engines(nthreads);
561 engines[0] = libint2::Engine(
562 libint2::Operator::coulomb,
564 static_cast<int>(std::max(dftbasis.
getMaxL(), auxbasis.
getMaxL())), 0);
565 engines[0].set(libint2::BraKet::xs_xx);
566 for (
Index i = 1; i < nthreads; ++i) {
567 engines[i] = engines[0];
573 const libint2::Engine::target_ptr_vec& buf = engine.results();
575 Eigen::MatrixXd raw(max_rows, naux);
576 Eigen::MatrixXd transformed(max_rows, naux);
577 std::vector<Index> row_start;
578 std::vector<Index> chunk_pos;
580#pragma omp for schedule(dynamic)
581 for (
Index u = 0; u <
Index(units.size()); ++u) {
582 const Unit& unit = units[u];
583 const libint2::Shell& shell_a = dftshells[unit.a];
585 const Index start_a = shell2bf[unit.a];
586 const bool has_diagonal = kept[unit.a][unit.last - 1] == unit.a;
589 chunk_pos.assign(1, 0);
590 for (
Index k = unit.first; k < unit.last; ++k) {
591 chunk_pos.push_back(chunk_pos.back() +
592 Index(dftshells[kept[unit.a][k]].size()));
594 const Index width = chunk_pos.back();
596 row_start.assign(1, 0);
597 for (
Index i = 0; i < na; ++i) {
598 const Index len = has_diagonal ? width - (na - i - 1) : width;
599 row_start.push_back(row_start.back() + len);
601 const Index rows = row_start.back();
602 raw.topRows(rows).setZero();
604 for (
Index aux = 0; aux <
Index(auxshells.size()); ++aux) {
605 const libint2::Shell& auxshell = auxshells[aux];
606 const Index aux_start = auxshell2bf[aux];
607 for (
Index k = unit.first; k < unit.last; ++k) {
608 const Index b = kept[unit.a][k];
609 const libint2::Shell& shell_b = dftshells[b];
611 .compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xx, 0>(
612 auxshell, libint2::Shell::unit(), shell_a, shell_b);
613 if (buf[0] ==
nullptr) {
617 Eigen::Tensor<const double, 3, Eigen::RowMajor>
const>
618 result(buf[0], auxshell.size(), shell_a.size(), shell_b.size());
620 const Index pos = chunk_pos[k - unit.first];
621 for (
Index i = 0; i < na; ++i) {
623 const Index ncol = (b == unit.a) ? std::min(nb, i + 1) : nb;
624 for (
Index c = 0; c < ncol; ++c) {
625 for (
Index f = 0; f <
Index(auxshell.size()); ++f) {
626 raw(row_start[i] + pos + c, aux_start + f) = result(f, i, c);
634 transformed.topRows(rows).noalias() =
635 raw.topRows(rows) *
inv_sqrt_.transpose();
638 for (
Index k = 0; k < unit.first; ++k) {
639 before +=
Index(dftshells[kept[unit.a][k]].size());
641 for (
Index i = 0; i < na; ++i) {
642 const Index len = row_start[i + 1] - row_start[i];
644 transformed.middleRows(row_start[i], len);
657 libint2::Engine& engine) {
658 std::vector<Eigen::MatrixXd> ao3c = std::vector<Eigen::MatrixXd>(
665 const libint2::Engine::target_ptr_vec& buf = engine.results();
667 for (
Index row = 0; row <
Index(dftshells.size()); row++) {
669 const libint2::Shell& shell_row = dftshells[row];
670 const Index row_start = shell2bf[row];
673 for (
Index col = 0; col <= row; col++) {
674 const libint2::Shell& shell_col = dftshells[col];
675 const Index col_start = shell2bf[col];
677 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xx, 0>(
678 auxshell, libint2::Shell::unit(), shell_col, shell_row);
680 if (buf[0] ==
nullptr) {
683 Eigen::TensorMap<Eigen::Tensor<const double, 3, Eigen::RowMajor>
const>
684 result(buf[0], auxshell.size(), shell_col.size(), shell_row.size());
686 for (
size_t aux_c = 0; aux_c < auxshell.size(); aux_c++) {
687 for (
size_t col_c = 0; col_c < shell_col.size(); col_c++) {
688 for (
size_t row_c = 0; row_c < shell_row.size(); row_c++) {
690 ao3c[aux_c](row_start + row_c, col_start + col_c) =
691 result(aux_c, col_c, row_c);
699 for (Eigen::MatrixXd& mat : ao3c) {
700 mat.triangularView<Eigen::Upper>() =
701 mat.triangularView<Eigen::Lower>().transpose();
713struct GaussianSiteShells {
718 GaussianSiteShells(
const Eigen::Vector3d& pos,
double width) {
719 const double beta = 1.0 / (width * width);
720 const std::array<double, 3> O = {pos.x(), pos.y(), pos.z()};
721 s = libint2::Shell{{beta}, {{0,
false, {1.0}}}, O};
722 p = libint2::Shell{{beta}, {{1,
false, {1.0}}}, O};
723 const double n_s = std::pow(2.0 * beta / M_PI, 0.75);
724 s_factor = 1.0 / (n_s * std::pow(M_PI / beta, 1.5));
725 const double n_p = n_s * 2.0 * std::sqrt(beta);
726 p_factor = 2.0 * beta * std::pow(beta / M_PI, 1.5) / n_p;
730std::vector<libint2::Engine> GaussianSiteEngines(
const AOBasis& basis) {
732 engines[0] = libint2::Engine(libint2::Operator::coulomb,
733 int(std::max<Index>(basis.getMaxNprim(), 1)),
734 int(std::max<Index>(basis.getMaxL(), 1)), 0);
735 engines[0].set(libint2::BraKet::xs_xx);
736 for (std::size_t i = 1; i < engines.size(); ++i) {
737 engines[i] = engines[0];
744 const std::vector<Source>& sources) {
746 Eigen::MatrixXd
V = Eigen::MatrixXd::Zero(nao, nao);
747 for (
const Source& src : sources) {
748 if (!(src.width > 0.0)) {
749 throw std::runtime_error(
750 "AOGaussianSites: Gaussian sites need a positive width");
753 std::vector<libint2::Engine> engines = GaussianSiteEngines(basis);
754#pragma omp parallel for schedule(dynamic) reduction(+ : V)
755 for (
Index k = 0; k <
Index(sources.size()); ++k) {
756 const Source& src = sources[std::size_t(k)];
757 const GaussianSiteShells sh(src.
pos, src.
width);
763 if (src.
dipole.squaredNorm() > 0.0) {
765 for (
Index c = 0; c < 3; ++c) {
766 V += (src.
dipole(c) * sh.p_factor) * p[std::size_t(c)];
774 const AOBasis& basis,
const Eigen::MatrixXd&
D,
775 const std::vector<Eigen::Vector3d>& points,
776 const std::vector<double>& widths) {
777 if (widths.size() != points.size()) {
778 throw std::runtime_error(
779 "AOGaussianSites: " + std::to_string(widths.size()) +
" widths for " +
780 std::to_string(points.size()) +
" points");
783 for (
double w : widths) {
785 throw std::runtime_error(
786 "AOGaussianSites: Gaussian sites need a positive width");
789 Eigen::MatrixXd result = Eigen::MatrixXd::Zero(n, 4);
790 std::vector<libint2::Engine> engines = GaussianSiteEngines(basis);
791#pragma omp parallel for schedule(dynamic)
792 for (
Index k = 0; k < n; ++k) {
793 const GaussianSiteShells sh(points[std::size_t(k)], widths[std::size_t(k)]);
800 for (
Index c = 0; c < 3; ++c) {
801 result(k, 1 + c) = sh.p_factor * p[std::size_t(c)].cwiseProduct(
D).sum();
812Eigen::MatrixXd MultiplyLeftRight(
const Eigen::MatrixXd&
L,
813 const Eigen::MatrixXd& A,
814 const Eigen::MatrixXd& R) {
815 const double left_first =
816 double(
L.rows()) * double(A.rows()) * double(A.cols()) +
817 double(
L.rows()) * double(A.cols()) * double(R.cols());
818 const double right_first =
819 double(A.rows()) * double(A.cols()) * double(R.cols()) +
820 double(
L.rows()) * double(A.rows()) * double(R.cols());
821 if (right_first < left_first) {
829 const Eigen::MatrixXd& dft_orbitals) {
831 const Eigen::MatrixXd dftm = dft_orbitals.middleCols(
mmin_,
mtotal_);
832 const Eigen::MatrixXd dftn =
838 std::vector<libint2::Engine> engines(nthreads);
839 engines[0] = libint2::Engine(
840 libint2::Operator::coulomb,
842 static_cast<int>(std::max(dftbasis.
getMaxL(), auxbasis.
getMaxL())), 0);
843 engines[0].set(libint2::BraKet::xs_xx);
844 for (
Index i = 1; i < nthreads; ++i) {
845 engines[i] = engines[0];
852#pragma omp for schedule(dynamic)
853 for (
Index aux = 0; aux <
Index(auxshells.size()); aux++) {
854 const libint2::Shell& auxshell = auxshells[aux];
856 std::vector<Eigen::MatrixXd> ao3c =
862 const Index dim =
static_cast<Index>(ao3c.size());
863 const Index aux0 = auxshell2bf[aux];
864 for (
Index k = 0; k < dim; ++k) {
865 ao3c[k] = MultiplyLeftRight(dftn, ao3c[k], dftm);
867 matrix_[m_level].col(aux0 + k) = ao3c[k].col(m_level);
869 ao3c[k].resize(0, 0);
881 const AOBasis& auxbasis,
const std::vector<Eigen::Vector3d>& points,
882 const std::vector<double>& widths) {
883 if (!widths.empty() && widths.size() != points.size()) {
884 throw std::runtime_error(
"EnvironmentScreening::AuxFieldAtPoints: " +
885 std::to_string(widths.size()) +
" widths for " +
886 std::to_string(points.size()) +
" points.");
897 Eigen::MatrixXd::Zero(auxbasis.
AOBasisSize(), 3 * n_points);
898 if (n_points == 0 || shells.empty()) {
903 std::vector<libint2::Engine> engines(nthreads);
905 libint2::Engine(libint2::Operator::nuclear,
int(auxbasis.
getMaxNprim()),
907 for (
Index i = 1; i < nthreads; ++i) {
908 engines[i] = engines[0];
912 std::vector<libint2::Engine> coulomb(nthreads);
914 libint2::Engine(libint2::Operator::coulomb,
int(auxbasis.
getMaxNprim()),
916 coulomb[0].set(libint2::BraKet::xs_xs);
917 for (
Index i = 1; i < nthreads; ++i) {
918 coulomb[i] = coulomb[0];
923 const double h = 1
e-3;
924 const std::array<double, 4> offset = {2.0 * h, h, -h, -2.0 * h};
925 const std::array<double, 4> weight = {-1.0 / (12.0 * h), 8.0 / (12.0 * h),
926 -8.0 / (12.0 * h), 1.0 / (12.0 * h)};
933#pragma omp parallel for schedule(dynamic)
934 for (
Index p = 0; p < n_points; ++p) {
935 const double width = widths.empty() ? 0.0 : widths[std::size_t(p)];
943 const libint2::Engine::target_ptr_vec& buf = engine.results();
944 const double beta = 1.0 / (width * width);
945 const double charge =
946 std::pow(2.0 * beta / M_PI, 0.75) * std::pow(M_PI / beta, 1.5);
947 for (
Index k = 0; k < 3; ++k) {
948 for (std::size_t s = 0; s < offset.size(); ++s) {
949 Eigen::Vector3d C = points[std::size_t(p)];
951 const libint2::Shell g{
952 {beta}, {{0,
false, {1.0}}}, {{C.x(), C.y(), C.z()}}};
953 for (std::size_t sh = 0; sh < shells.size(); ++sh) {
954 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xs,
955 0>(shells[sh], libint2::Shell::unit(), g,
956 libint2::Shell::unit());
957 if (buf[0] ==
nullptr) {
960 const Index start = shell2bf[sh];
961 for (std::size_t f = 0; f < shells[sh].size(); ++f) {
962 F(start +
Index(f), 3 * p + k) -= weight[s] * buf[0][f] / charge;
970 const libint2::Engine::target_ptr_vec& buf = engine.results();
971 for (
Index k = 0; k < 3; ++k) {
972 for (std::size_t s = 0; s < offset.size(); ++s) {
973 Eigen::Vector3d C = points[std::size_t(p)];
975 std::vector<std::pair<double, std::array<double, 3>>> charge{
976 {1.0, {C.x(), C.y(), C.z()}}};
977 engine.set_params(charge);
978 for (std::size_t sh = 0; sh < shells.size(); ++sh) {
979 engine.compute(shells[sh], libint2::Shell::unit());
980 if (buf[0] ==
nullptr) {
983 const Index start = shell2bf[sh];
984 for (std::size_t f = 0; f < shells[sh].size(); ++f) {
985 F(start +
Index(f), 3 * p + k) += weight[s] * buf[0][f];
998 const AOBasis& auxbasis,
const std::vector<Eigen::Vector3d>& points,
999 const std::vector<double>& widths) {
1000 if (widths.size() != points.size()) {
1001 throw std::runtime_error(
"EnvironmentScreening::AuxPotentialAtPoints: " +
1002 std::to_string(widths.size()) +
" widths for " +
1003 std::to_string(points.size()) +
" points.");
1008 Eigen::MatrixXd
P = Eigen::MatrixXd::Zero(auxbasis.
AOBasisSize(), n_points);
1009 if (n_points == 0 || shells.empty()) {
1013 std::vector<libint2::Engine> engines(nthreads);
1015 libint2::Engine(libint2::Operator::nuclear,
int(auxbasis.
getMaxNprim()),
1017 std::vector<libint2::Engine> coulomb(nthreads);
1019 libint2::Engine(libint2::Operator::coulomb,
int(auxbasis.
getMaxNprim()),
1021 coulomb[0].set(libint2::BraKet::xs_xs);
1022 for (
Index i = 1; i < nthreads; ++i) {
1023 engines[i] = engines[0];
1024 coulomb[i] = coulomb[0];
1030#pragma omp parallel for schedule(dynamic)
1031 for (
Index p = 0; p < n_points; ++p) {
1032 const Eigen::Vector3d& C = points[std::size_t(p)];
1033 const double width = widths[std::size_t(p)];
1036 const libint2::Engine::target_ptr_vec& buf = engine.results();
1037 const double beta = 1.0 / (width * width);
1038 const double charge =
1039 std::pow(2.0 * beta / M_PI, 0.75) * std::pow(M_PI / beta, 1.5);
1040 const libint2::Shell g{
1041 {beta}, {{0,
false, {1.0}}}, {{C.x(), C.y(), C.z()}}};
1042 for (std::size_t sh = 0; sh < shells.size(); ++sh) {
1043 engine.compute2<libint2::Operator::coulomb, libint2::BraKet::xs_xs, 0>(
1044 shells[sh], libint2::Shell::unit(), g, libint2::Shell::unit());
1045 if (buf[0] ==
nullptr) {
1048 for (std::size_t f = 0; f < shells[sh].size(); ++f) {
1049 P(shell2bf[sh] +
Index(f), p) = buf[0][f] / charge;
1055 const libint2::Engine::target_ptr_vec& buf = engine.results();
1056 std::vector<std::pair<double, std::array<double, 3>>> charge{
1057 {1.0, {C.x(), C.y(), C.z()}}};
1058 engine.set_params(charge);
1059 for (std::size_t sh = 0; sh < shells.size(); ++sh) {
1060 engine.compute(shells[sh], libint2::Shell::unit());
1061 if (buf[0] ==
nullptr) {
1064 for (std::size_t f = 0; f < shells[sh].size(); ++f) {
1065 P(shell2bf[sh] +
Index(f), p) = -buf[0][f];
1075 Eigen::VectorXd q = Eigen::VectorXd::Zero(auxbasis.
AOBasisSize());
1076 libint2::Engine engine(libint2::Operator::overlap,
1079 const libint2::Engine::target_ptr_vec& buf = engine.results();
1080 for (std::size_t sh = 0; sh < shells.size(); ++sh) {
1081 engine.compute(shells[sh], libint2::Shell::unit());
1082 if (buf[0] ==
nullptr) {
1085 for (std::size_t f = 0; f < shells[sh].size(); ++f) {
1086 q(shell2bf[sh] +
Index(f)) = buf[0][f];
Container to hold Basisfunctions for all atoms.
AOShellIterator begin() const
Index AOBasisSize() const
AOShellIterator end() const
std::vector< Index > getMapToBasisFunctions() const
Index getNumofShells() const
Index getMaxNprim() const
std::vector< std::vector< Index > > ComputeShellPairs(double threshold=1e-20) const
std::vector< libint2::Shell > GenerateLibintBasis() const
void Fill(const AOBasis &aobasis) final
Eigen::MatrixXd aomatrix_
const Eigen::MatrixXd & Matrix() const
void computeCoulombIntegrals(const AOBasis &aobasis)
Eigen::MatrixXd Pseudo_InvSqrt(double etol)
Index Removedfunctions() const
std::array< Eigen::MatrixXd, 3 > aomatrix_
std::array< libint2::Shell::real_t, 3 > r_
void Fill(const AOBasis &aobasis) final
static Eigen::MatrixXd Potential(const AOBasis &basis, const std::vector< Source > &sources)
static Eigen::MatrixXd PotentialAndGradientAt(const AOBasis &basis, const Eigen::MatrixXd &D, const std::vector< Eigen::Vector3d > &points, const std::vector< double > &widths)
void Fill(const AOBasis &aobasis) final
Eigen::MatrixXd aomatrix_
void Fill(const AOBasis &aobasis) final
Eigen::MatrixXd singleShellOverlap(const AOShell &shell) const
Eigen::MatrixXd aomatrix_
libint2::Shell LibintShell() const
std::vector< std::vector< libint2::ShellPair > > shellpairdata_
std::vector< libint2::Shell > basis_
Eigen::MatrixXd ComputeSchwarzShells(const AOBasis &dftbasis) const
std::vector< std::vector< Index > > shellpairs_
std::array< Eigen::MatrixXd, 2 > Compute4c(const Eigen::MatrixXd &dmat, double error) const
Eigen::MatrixXd schwarzscreen_
Eigen::MatrixXd ComputeShellBlockNorm(const Eigen::MatrixXd &dmat) const
std::vector< Index > starts_
static Eigen::VectorXd AuxCharges(const AOBasis &auxbasis)
static Eigen::MatrixXd AuxPotentialAtPoints(const AOBasis &auxbasis, const std::vector< Eigen::Vector3d > &points, const std::vector< double > &widths)
The electrostatic potential of each auxiliary function (as a charge density) at each point,...
static Eigen::MatrixXd AuxFieldAtPoints(const AOBasis &auxbasis, const std::vector< Eigen::Vector3d > &points, const std::vector< double > &widths={})
F: the electric field at each point produced by each auxiliary basis function, taken as a charge dens...
std::vector< Index > col_offset_
std::vector< std::vector< Index > > SignificantPairs(const AOBasis &dftbasis, const Eigen::MatrixXd &metric, double pair_threshold) const
Index size() const
Number of aux functions.
void Fill(const AOBasis &auxbasis, const AOBasis &dftbasis, double pair_threshold=0.0, Index build_columns=kBuildColumns)
void SetupLayout(const AOBasis &dftbasis, const std::vector< std::vector< Index > > &kept)
void Fill3cMO(const AOBasis &auxbasis, const AOBasis &dftbasis, const Eigen::MatrixXd &dft_orbitals)
std::vector< Eigen::MatrixXd > matrix_
Eigen::MatrixXd inv_sqrt_
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > MatrixLibInt
std::vector< Eigen::MatrixXd > ComputeAO3cBlock(const libint2::Shell &auxshell, const AOBasis &dftbasis, libint2::Engine &engine)
std::array< MatrixLibInt, libint2::operator_traits< obtype >::nopers > computeOneBodyIntegrals(const AOBasis &aobasis, OperatorParams oparams=OperatorParams())
Provides a means for comparing floating point numbers.