36 const Eigen::MatrixXd& mos,
39 const Index qptotal = qpmax - qpmin + 1;
40 Eigen::MatrixXd X = Eigen::MatrixXd::Zero(qptotal, qptotal);
41 if (ncore <= 0 || qptotal <= 0) {
48 Mc.
Fill(auxbasis, dftbasis, mos);
49 Eigen::MatrixXd Z(qptotal, Mc.
auxsize());
50 for (
Index c = 0; c < ncore; ++c) {
51 for (
Index m = 0; m < qptotal; ++m) {
52 Z.row(m) = Mc[m].row(c);
54 X.selfadjointView<Eigen::Upper>().rankUpdate(Z, -1.0);
56 return X.selfadjointView<Eigen::Upper>();
74#pragma omp parallel for schedule(dynamic, 4)
85#pragma omp parallel for schedule(dynamic)
89 if (matrix.rows() != matrix.cols()) {
100 if (U.rows() != U.cols()) {
104 const Index lead_rows = std::clamp<Index>(lead, 0,
nsize());
105 const Index lead_slices = std::clamp<Index>(lead, 0,
msize());
106 full_slices = std::clamp<Index>(full_slices, 0, lead_slices);
107#pragma omp parallel for schedule(dynamic)
108 for (
Index i = 0; i < lead_slices; i++) {
109 const Index rows = (i < full_slices) ?
nsize() : lead_rows;
110 Eigen::MatrixXd rotated =
matrix_[i].topRows(rows) * U;
111 matrix_[i].topRows(rows) = rotated;
116 if (full_slices <
msize() && (lead_slices <
msize() || lead_rows <
nsize())) {
136 throw std::runtime_error(
137 "TCMatrix_gwbse: cannot dress the auxiliary index after only part of "
138 "the tensor was rotated (MultiplyRightWithAuxMatrixLeading). Rebuild "
142 throw std::runtime_error(
143 "TCMatrix_gwbse: cannot dress the auxiliary index after a non-square "
144 "MultiplyRightWithAuxMatrix. Rebuild first.");
151 const Eigen::PartialPivLU<Eigen::MatrixXd> lu(
aux_frame_);
157 throw std::runtime_error(
158 "TCMatrix_gwbse::DressAuxIndex: already dressed. Undress first.");
161 throw std::runtime_error(
162 "TCMatrix_gwbse::DressAuxIndex: S is " + std::to_string(
S.rows()) +
163 "x" + std::to_string(
S.cols()) +
", auxiliary basis has " +
179 const Eigen::MatrixXd& K)
const {
181 throw std::runtime_error(
182 "TCMatrix_gwbse::ToCurrentAuxFrame: the auxiliary index of the "
183 "three-centre integrals was multiplied by a non-square matrix, so "
184 "there is no frame to bring the kernel into. Apply it before that, "
191 throw std::runtime_error(
192 "TCMatrix_gwbse::ToCurrentAuxFrame: kernel is " +
193 std::to_string(K.rows()) +
"x" + std::to_string(K.cols()) +
194 ", auxiliary frame is " + std::to_string(
aux_frame_.rows()) +
"x" +
198 const double off_orthogonal =
202 Eigen::MatrixXd result;
203 if (off_orthogonal < 1
e-10) {
206 const Eigen::PartialPivLU<Eigen::MatrixXd> lu(
aux_frame_);
207 const Eigen::MatrixXd X = lu.solve(K);
208 result = lu.solve(Eigen::MatrixXd(X.transpose())).transpose();
219 const Eigen::MatrixXd& dft_orbitals) {
225 Fill3cMO(auxbasis, dftbasis, dft_orbitals);
228 auxoverlap.
Fill(auxbasis);
230 auxcoulomb.
Fill(auxbasis);
245 const Index window = last - first + 1;
248 assert(U.rows() == window && U.cols() == window);
255 const Eigen::MatrixXd Ut = U.transpose();
256#pragma omp parallel for schedule(dynamic)
258 auto block =
matrix_[m].middleRows(row0, window);
264 const Index chunk = std::max<Index>(
265 1, std::min<Index>(aux,
Index(8e6 /
double(rows * window + 1))));
268 for (
Index c0 = 0; c0 < aux; c0 += chunk) {
269 const Index nc = std::min(chunk, aux - c0);
270 const Index len = rows * nc;
271 X.resize(len, window);
272#pragma omp parallel for
273 for (
Index k = 0; k < window; k++) {
274 X.col(k) = Eigen::Map<const Eigen::VectorXd>(
275 matrix_[slice0 + k].col(c0).data(), len);
278#pragma omp parallel for
279 for (
Index i = 0; i < window; i++) {
280 Eigen::Map<Eigen::VectorXd>(
matrix_[slice0 + i].col(c0).data(), len) =
287 const std::vector<std::vector<Index>>& kept) {
293 for (
Index a = 0; a <
Index(kept.size()); ++a) {
294 const Index start = shell2bf[a];
297 const Index mu = start + i;
302 Index b_first = kept[a][k];
303 Index b_last = b_first;
304 while (k + 1 <
Index(kept[a].
size()) && kept[a][k + 1] == b_last + 1) {
309 const Index row = shell2bf[b_first];
310 const Index end = std::min(
312 runs_.push_back({mu, row, end - row, offset});
321 const double* src =
data_.col(
P).data();
323 std::copy(src + r.offset, src + r.offset + r.length,
326 full.triangularView<Eigen::StrictlyLower>() = full.transpose();
337 Eigen::VectorXd packed(
data_.rows());
339 for (
Index k = 0; k < r.length; ++k) {
340 const Index row = r.row + k;
341 packed(r.offset + k) =
342 (row == r.col) ? full(r.col, row) : 2.0 * full(r.col, row);
349 assert(packed.size() ==
data_.rows());
352 full.block(r.row, r.col, r.length, 1) = packed.segment(r.offset, r.length);
354 full.triangularView<Eigen::StrictlyLower>() = full.transpose();
Container to hold Basisfunctions for all atoms.
Index AOBasisSize() const
std::vector< Index > getMapToBasisFunctions() const
const AOShell & getShell(Index idx) const
void Fill(const AOBasis &aobasis) final
Index Removedfunctions() const
Eigen::MatrixXd Pseudo_InvSqrt_GWBSE(const AOOverlap &auxoverlap, double etol)
void Fill(const AOBasis &aobasis) final
std::vector< Index > col_offset_
Index size() const
Number of aux functions.
Eigen::VectorXd PackWeighted(const Eigen::MatrixXd &full) const
Eigen::MatrixXd FullMatrix(Index P) const
B_P as a full symmetric matrix, zero for the dropped pairs.
void SetupLayout(const AOBasis &dftbasis, const std::vector< std::vector< Index > > &kept)
void FillFullMatrix(Index P, Eigen::MatrixXd &full) const
Eigen::MatrixXd Unpack(const Eigen::VectorXd &packed) const
void Fill(const AOBasis &auxbasis, const AOBasis &dftbasis, const Eigen::MatrixXd &dft_orbitals)
const AOBasis * auxbasis_
static constexpr double metric_tolerance
void DressAuxIndex(const Eigen::MatrixXd &S)
Dress the auxiliary index with S: M_fill -> M_fill S.
void MultiplyRightWithAuxMatrixLeading(const Eigen::MatrixXd &U, Index full_slices, Index lead)
Rotate the auxiliary index of only the part of the tensor a consumer reads: all rows of slices [0,...
Eigen::MatrixXd aux_frame_
Eigen::MatrixXd dressing_
const Eigen::MatrixXd * dft_orbitals_
bool AuxFrameIsOrthogonal() const
void Fill3cMO(const AOBasis &auxbasis, const AOBasis &dftbasis, const Eigen::MatrixXd &dft_orbitals)
void Initialize(Index basissize, Index mmin, Index mmax, Index nmin, Index nmax)
void MultiplyRightWithAuxMatrix(const Eigen::MatrixXd &matrix)
std::vector< Eigen::MatrixXd > matrix_
static Eigen::MatrixXd CoreExchange(const AOBasis &auxbasis, const AOBasis &dftbasis, const Eigen::MatrixXd &mos, Index ncore, Index qpmin, Index qpmax)
void RotateOrbitals(const Eigen::MatrixXd &U, Index first, Index last)
Change the orbital basis of levels [first, last] for QSGW: phi_i = sum_k U_ki psi_k,...
const AOBasis * dftbasis_
void MultiplyInFillFrame(const Eigen::MatrixXd &A)
Eigen::MatrixXd ToCurrentAuxFrame(const Eigen::MatrixXd &K) const
Eigen::MatrixXd inv_sqrt_
Charge transport classes.
Provides a means for comparing floating point numbers.