72 <<
TimeStamp() <<
" Starting Projection based dft-in-dft embedding"
77 <<
TimeStamp() <<
" Passing localized orbitals as the initial guess"
79 Eigen::MatrixXd LMOs = orb.
getLMOs();
84 std::vector<Index> activeatoms =
91 const Eigen::MatrixXd InitialActiveDensityMatrix = DMAT_A.
compute_Dmat_A()[0];
95 <<
TimeStamp() <<
" Active density formation done" << std::flush;
97 Eigen::MatrixXd InactiveDensityMatrix =
98 FullDensityMatrix - InitialActiveDensityMatrix;
105 overlap.
Fill(aobasis);
108 std::round(FullDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
110 InitialActiveDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
111 Index inactive_electrons =
static_cast<Index>(
112 std::round(InactiveDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
115 <<
TimeStamp() <<
" Total electrons: " << all_electrons << std::flush;
120 <<
TimeStamp() <<
" Inactive electrons: " << inactive_electrons
125 throw std::runtime_error(
126 " Sum of active and inactive electrons does "
127 "not match full number of electrons!");
138 const double E0_full = FullDensityMatrix.cwiseProduct(H0.
matrix()).sum();
139 const double E0_initial_active =
140 InitialActiveDensityMatrix.cwiseProduct(H0.
matrix()).sum();
151 Eigen::MatrixXd J_full =
152 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
153 Eigen::MatrixXd J_initial_active =
154 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
155 Eigen::MatrixXd K_full =
156 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
157 Eigen::MatrixXd K_initial_active =
158 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
160 std::array<Eigen::MatrixXd, 2> JandK_full =
162 std::array<Eigen::MatrixXd, 2> JandK_initial_active =
CalcERIs_EXX(
163 embeddingMOs.
eigenvectors(), InitialActiveDensityMatrix, 1
e-12);
164 J_full = JandK_full[0];
165 K_full = 0.5 *
ScaHFX_ * JandK_full[1];
166 J_initial_active = JandK_initial_active[0];
167 K_initial_active = 0.5 *
ScaHFX_ * JandK_initial_active[1];
169 J_full =
CalcERIs(FullDensityMatrix, 1
e-12);
170 J_initial_active =
CalcERIs(InitialActiveDensityMatrix, 1
e-12);
173 const double E_Hartree_full =
174 0.5 * FullDensityMatrix.cwiseProduct(J_full + K_full).sum();
175 const double E_Hartree_initial_active =
176 0.5 * InitialActiveDensityMatrix
177 .cwiseProduct(J_initial_active + K_initial_active)
185 <<
" Reference total energy full electron system: " <<
Total_E_full_
186 <<
" Ha" << std::flush;
189 Eigen::MatrixXd ProjectionOperator =
190 overlap.
Matrix() * InactiveDensityMatrix * overlap.
Matrix();
193 const Eigen::MatrixXd v_embedding = J_full + K_full + xc_full.
matrix() -
194 J_initial_active - K_initial_active -
195 xc_initial_active.
matrix();
197 const double constant_embedding_energy =
Total_E_full_ - E0_initial_active -
198 E_Hartree_initial_active -
199 xc_initial_active.
energy();
202 <<
TimeStamp() <<
" Constant energy embedding terms: " << std::flush;
206 <<
TimeStamp() <<
" 2) E_0[initial active]: " << E0_initial_active
209 <<
TimeStamp() <<
" 3) E_H[initial active]: " << E_Hartree_initial_active
212 << xc_initial_active.
energy() << std::flush;
214 <<
TimeStamp() <<
" Total 1 -2 -3 -4: " << constant_embedding_energy
219 TruncateBasis(orb, activeatoms, H0, InitialActiveDensityMatrix, v_embedding,
230 <<
TimeStamp() <<
" Iteration " << this_iter + 1 <<
" of "
235 double E_xc_active = xc_active.
energy();
238 Eigen::MatrixXd J_active = Eigen::MatrixXd::Zero(
240 Eigen::MatrixXd K_active = Eigen::MatrixXd::Zero(
243 std::array<Eigen::MatrixXd, 2> JandK_active =
CalcERIs_EXX(
245 J_active = JandK_active[0];
246 K_active = 0.5 *
ScaHFX_ * JandK_active[1];
251 double E_Hartree_active =
255 const Eigen::MatrixXd Level_Shift_Operator =
257 Eigen::MatrixXd H_active = H0.
matrix() + v_embedding +
258 Level_Shift_Operator + xc_active.
matrix() +
261 const double E0_active =
263 const double E_embedding =
265 .cwiseProduct(v_embedding)
267 const double E_levelshift =
270 double TotalEnergy = E0_active + E_Hartree_active + E_xc_active +
271 constant_embedding_energy + E_levelshift +
275 <<
TimeStamp() <<
" Total Energy after embedding: " << TotalEnergy
278 <<
TimeStamp() <<
" I) E_0[active]: " << E0_active << std::flush;
280 <<
TimeStamp() <<
" II) E_H[active]: " << E_Hartree_active
283 <<
TimeStamp() <<
" III) E_xc[active]: " << E_xc_active << std::flush;
285 <<
TimeStamp() <<
" IV) E_ext_emb :" << constant_embedding_energy
288 <<
TimeStamp() <<
" V) E_corr_emb :" << E_embedding << std::flush;
290 <<
TimeStamp() <<
" VI) E_levelshift :" << E_levelshift
293 <<
TimeStamp() <<
" Total I + II + III + IV + V +VI :" << TotalEnergy
299 <<
"Active electrons in = "
306 <<
"Active electrons out= "
314 <<
TimeStamp() <<
" Total embedding energy has converged to "
316 <<
"[Ha] after " << this_iter + 1
317 <<
" iterations. DIIS error is converged up to "
320 <<
TimeStamp() <<
" Final Single Point Energy of embedding "
321 << std::setprecision(12) << TotalEnergy <<
" Ha" << std::flush;
323 <<
"The difference between the reference energy and the embedding "
329 <<
"Warning!! The difference is greater than 1e-03 Ha"
341 <<
" DFT calculation for active region has not converged after "
343 <<
" iterations. Use more iterations or another convergence "
344 "acceleration scheme."
362 overlap.
Fill(aobasis);
364 const double E0_initial_truncated =
368 Eigen::MatrixXd J_initial_truncated = Eigen::MatrixXd::Zero(
370 Eigen::MatrixXd K_initial_truncated = Eigen::MatrixXd::Zero(
377 std::array<Eigen::MatrixXd, 2> JandK_initial_truncated =
CalcERIs_EXX(
379 J_initial_truncated = JandK_initial_truncated[0];
380 K_initial_truncated = 0.5 *
ScaHFX_ * JandK_initial_truncated[1];
385 const double E_Hartree_initial_truncated =
387 .cwiseProduct(J_initial_truncated + K_initial_truncated)
389 const double Initial_truncated_energy = E0_initial_truncated +
390 E_Hartree_initial_truncated +
391 xc_initial_truncated.
energy();
393 <<
"Initial truncated energy = " << Initial_truncated_energy
396 Eigen::MatrixXd PurifiedActiveDmat_trunc =
398 Eigen::MatrixXd TruncatedDensityMatrix = PurifiedActiveDmat_trunc;
403 <<
TimeStamp() <<
" Iteration " << this_iter + 1 <<
" of "
409 double E_xc_truncated = xc_truncated.
energy();
412 Eigen::MatrixXd J_truncated = Eigen::MatrixXd::Zero(
413 TruncatedDensityMatrix.rows(), TruncatedDensityMatrix.cols());
414 Eigen::MatrixXd K_truncated = Eigen::MatrixXd::Zero(
415 TruncatedDensityMatrix.rows(), TruncatedDensityMatrix.cols());
417 std::array<Eigen::MatrixXd, 2> JandK_truncated =
CalcERIs_EXX(
419 J_truncated = JandK_truncated[0];
420 K_truncated = 0.5 *
ScaHFX_ * JandK_truncated[1];
423 J_truncated =
CalcERIs(TruncatedDensityMatrix, 1
e-12);
425 double E_Hartree_truncated =
427 TruncatedDensityMatrix.cwiseProduct(J_truncated + K_truncated).sum();
429 Eigen::MatrixXd H_truncated =
432 double TruncatedTotalEnergy =
433 TruncatedDensityMatrix.cwiseProduct(
H0_trunc_).sum() +
435 Initial_truncated_energy +
442 << TruncatedDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()
445 TruncatedDensityMatrix, H_truncated, MOs_trunc, TruncatedTotalEnergy);
447 <<
"Electrons out = "
448 << TruncatedDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()
453 << TruncatedDensityMatrix.cwiseProduct(
H0_trunc_).sum() +
454 E_Hartree_truncated + E_xc_truncated
457 <<
" E_initial_trunc(Ha) = " << Initial_truncated_energy
459 <<
" E_embedding_correction(Ha) = "
466 <<
" Truncated Energy of the system: E_trunc + E_fullDFT - "
468 <<
" E_initial_trunc + E_embedding_correction = "
469 << TruncatedTotalEnergy << std::flush;
475 <<
TimeStamp() <<
" Total embedding energy has converged to "
477 <<
"[Ha] after " << this_iter + 1
478 <<
" iterations. DIIS error is converged up to "
481 <<
TimeStamp() <<
" Final Single Point Energy of embedding "
482 << std::setprecision(12) << TruncatedTotalEnergy <<
" Ha"
498 Eigen::MatrixXd InitialActiveDensityMatrix,
499 Eigen::MatrixXd v_embedding,
500 Eigen::MatrixXd InitialInactiveMOs) {
504 overlap.
Fill(aobasis);
506 Eigen::VectorXd DiagonalofDmatA = InitialActiveDensityMatrix.diagonal();
507 Eigen::VectorXd DiagonalofOverlap = overlap.
Matrix().diagonal();
508 Eigen::VectorXd MnP = DiagonalofDmatA.cwiseProduct(DiagonalofOverlap);
511 const std::vector<Index>& numfuncpatom = aobasis.
getFuncPerAtom();
513 Index numofactivebasisfunction = 0;
515 std::vector<Index> start_indices, start_indices_activemolecule;
516 Index start_idx = 0, start_idx_activemolecule = 0;
517 std::vector<Index> borderatoms;
518 for (
Index atom_num = 0; atom_num < orb.
QMAtoms().size(); atom_num++) {
519 start_indices.push_back(start_idx);
523 (std::find(activeatoms.begin(), activeatoms.end(),
525 if (partOfActive ==
true) {
529 start_indices_activemolecule.push_back(start_idx_activemolecule);
530 start_idx_activemolecule += numfuncpatom[atom_num];
531 numofactivebasisfunction += numfuncpatom[atom_num];
533 std::vector<const AOShell*> inactiveshell =
535 bool loop_break =
false;
536 for (
const AOShell* shell : inactiveshell) {
537 for (
Index shell_fn_no = shell->getStartIndex();
538 shell_fn_no < shell->getStartIndex() + shell->getNumFunc();
541 activeatoms.push_back(atom_num);
542 borderatoms.push_back(atom_num);
547 start_indices_activemolecule.push_back(start_idx_activemolecule);
548 start_idx_activemolecule += numfuncpatom[atom_num];
549 numofactivebasisfunction += numfuncpatom[atom_num];
553 if (loop_break)
break;
556 start_idx += numfuncpatom[atom_num];
560 sort(activeatoms.begin(), activeatoms.end());
561 sort(borderatoms.begin(), borderatoms.end());
565 <<
"Active + Border Molecule Size = " << activeatoms.size() <<
"\n \t \t "
566 <<
"Border Molecule Size = " << borderatoms.size() << std::flush;
567 Eigen::MatrixXd ProjectionOperator =
568 overlap.
Matrix() * InactiveDensityMatrix * overlap.
Matrix();
570 Eigen::MatrixXd H_embedding =
573 if (borderatoms.size() != 0) {
574 Eigen::MatrixXd BorderMOs;
575 for (
Index lmo_index = 0; lmo_index < InitialInactiveMOs.cols();
577 double mullikenpop_lmo_borderatoms = 0;
578 for (
Index borderatom : borderatoms) {
579 Index start = start_indices[borderatom];
580 Index size = numfuncpatom[borderatom];
581 mullikenpop_lmo_borderatoms +=
582 (InitialInactiveMOs.col(lmo_index) *
583 InitialInactiveMOs.col(lmo_index).transpose() * overlap.
Matrix())
585 .segment(start, size)
591 if (mullikenpop_lmo_borderatoms > 0.25) {
592 BorderMOs.conservativeResize(InitialInactiveMOs.rows(),
593 BorderMOs.cols() + 1);
594 BorderMOs.col(BorderMOs.cols() - 1) = InitialInactiveMOs.col(lmo_index);
598 Eigen::MatrixXd BorderDmat = 2 * BorderMOs * BorderMOs.transpose();
599 Eigen::MatrixXd BorderProjectionOperator =
601 Eigen::MatrixXd DistantProjectionOperator =
602 ProjectionOperator - BorderProjectionOperator;
605 1
e+2 * BorderProjectionOperator +
606 levelshift_ * (DistantProjectionOperator - ProjectionOperator);
611 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
613 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
615 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
618 for (
Index activeatom1_idx = 0; activeatom1_idx <
Index(activeatoms.size());
620 Index activeatom1 = activeatoms[activeatom1_idx];
621 for (
Index activeatom2_idx = 0; activeatom2_idx <
Index(activeatoms.size());
623 Index activeatom2 = activeatoms[activeatom2_idx];
625 H0_trunc_.block(start_indices_activemolecule[activeatom1_idx],
626 start_indices_activemolecule[activeatom2_idx],
627 numfuncpatom[activeatom1], numfuncpatom[activeatom2]) =
629 start_indices[activeatom1], start_indices[activeatom2],
630 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);
632 start_indices_activemolecule[activeatom1_idx],
633 start_indices_activemolecule[activeatom2_idx],
634 numfuncpatom[activeatom1], numfuncpatom[activeatom2]) =
635 InitialActiveDensityMatrix.block(
636 start_indices[activeatom1], start_indices[activeatom2],
637 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);
639 start_indices_activemolecule[activeatom2_idx],
640 numfuncpatom[activeatom1],
641 numfuncpatom[activeatom2]) =
643 start_indices[activeatom1], start_indices[activeatom2],
644 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);