74 <<
TimeStamp() <<
" Starting Projection based dft-in-dft embedding"
79 <<
TimeStamp() <<
" Passing localized orbitals as the initial guess"
81 Eigen::MatrixXd LMOs = orb.
getLMOs();
86 std::vector<Index> activeatoms =
93 const Eigen::MatrixXd InitialActiveDensityMatrix = DMAT_A.
compute_Dmat_A()[0];
97 <<
TimeStamp() <<
" Active density formation done" << std::flush;
99 Eigen::MatrixXd InactiveDensityMatrix =
100 FullDensityMatrix - InitialActiveDensityMatrix;
107 overlap.
Fill(aobasis);
110 std::round(FullDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
112 InitialActiveDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
113 Index inactive_electrons =
static_cast<Index>(
114 std::round(InactiveDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
117 <<
TimeStamp() <<
" Total electrons: " << all_electrons << std::flush;
122 <<
TimeStamp() <<
" Inactive electrons: " << inactive_electrons
127 throw std::runtime_error(
128 " Sum of active and inactive electrons does "
129 "not match full number of electrons!");
140 const double E0_full = FullDensityMatrix.cwiseProduct(H0.
matrix()).sum();
141 const double E0_initial_active =
142 InitialActiveDensityMatrix.cwiseProduct(H0.
matrix()).sum();
153 Eigen::MatrixXd J_full =
154 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
155 Eigen::MatrixXd J_initial_active =
156 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
157 Eigen::MatrixXd K_full =
158 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
159 Eigen::MatrixXd K_initial_active =
160 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
162 std::array<Eigen::MatrixXd, 2> JandK_full =
164 std::array<Eigen::MatrixXd, 2> JandK_initial_active =
CalcERIs_EXX(
165 embeddingMOs.
eigenvectors(), InitialActiveDensityMatrix, 1
e-12);
166 J_full = JandK_full[0];
167 K_full = 0.5 *
ScaHFX_ * JandK_full[1];
168 J_initial_active = JandK_initial_active[0];
169 K_initial_active = 0.5 *
ScaHFX_ * JandK_initial_active[1];
171 J_full =
CalcERIs(FullDensityMatrix, 1
e-12);
172 J_initial_active =
CalcERIs(InitialActiveDensityMatrix, 1
e-12);
175 const double E_Hartree_full =
176 0.5 * FullDensityMatrix.cwiseProduct(J_full + K_full).sum();
177 const double E_Hartree_initial_active =
178 0.5 * InitialActiveDensityMatrix
179 .cwiseProduct(J_initial_active + K_initial_active)
187 <<
" Reference total energy full electron system: " <<
Total_E_full_
188 <<
" Ha" << std::flush;
191 Eigen::MatrixXd ProjectionOperator =
192 overlap.
Matrix() * InactiveDensityMatrix * overlap.
Matrix();
195 const Eigen::MatrixXd v_embedding = J_full + K_full + xc_full.
matrix() -
196 J_initial_active - K_initial_active -
197 xc_initial_active.
matrix();
199 const double constant_embedding_energy =
Total_E_full_ - E0_initial_active -
200 E_Hartree_initial_active -
201 xc_initial_active.
energy();
204 <<
TimeStamp() <<
" Constant energy embedding terms: " << std::flush;
208 <<
TimeStamp() <<
" 2) E_0[initial active]: " << E0_initial_active
211 <<
TimeStamp() <<
" 3) E_H[initial active]: " << E_Hartree_initial_active
214 << xc_initial_active.
energy() << std::flush;
216 <<
TimeStamp() <<
" Total 1 -2 -3 -4: " << constant_embedding_energy
221 TruncateBasis(orb, activeatoms, H0, InitialActiveDensityMatrix, v_embedding,
233 <<
TimeStamp() <<
" Iteration " << this_iter + 1 <<
" of "
238 double E_xc_active = xc_active.
energy();
241 Eigen::MatrixXd J_active = Eigen::MatrixXd::Zero(
243 Eigen::MatrixXd K_active = Eigen::MatrixXd::Zero(
246 std::array<Eigen::MatrixXd, 2> JandK_active =
CalcERIs_EXX(
248 J_active = JandK_active[0];
249 K_active = 0.5 *
ScaHFX_ * JandK_active[1];
254 double E_Hartree_active =
258 const Eigen::MatrixXd Level_Shift_Operator =
260 Eigen::MatrixXd H_active = H0.
matrix() + v_embedding +
261 Level_Shift_Operator + xc_active.
matrix() +
264 const double E0_active =
266 const double E_embedding =
268 .cwiseProduct(v_embedding)
270 const double E_levelshift =
273 double TotalEnergy = E0_active + E_Hartree_active + E_xc_active +
274 constant_embedding_energy + E_levelshift +
278 <<
TimeStamp() <<
" Total Energy after embedding: " << TotalEnergy
281 <<
TimeStamp() <<
" I) E_0[active]: " << E0_active << std::flush;
283 <<
TimeStamp() <<
" II) E_H[active]: " << E_Hartree_active
286 <<
TimeStamp() <<
" III) E_xc[active]: " << E_xc_active << std::flush;
288 <<
TimeStamp() <<
" IV) E_ext_emb :" << constant_embedding_energy
291 <<
TimeStamp() <<
" V) E_corr_emb :" << E_embedding << std::flush;
293 <<
TimeStamp() <<
" VI) E_levelshift :" << E_levelshift
296 <<
TimeStamp() <<
" Total I + II + III + IV + V +VI :" << TotalEnergy
302 <<
"Active electrons in = "
309 <<
"Active electrons out= "
317 <<
TimeStamp() <<
" Total embedding energy has converged to "
319 <<
"[Ha] after " << this_iter + 1
320 <<
" iterations. DIIS error is converged up to "
323 <<
TimeStamp() <<
" Final Single Point Energy of embedding "
324 << std::setprecision(12) << TotalEnergy <<
" Ha" << std::flush;
326 <<
"The difference between the reference energy and the embedding "
332 <<
"Warning!! The difference is greater than 1e-03 Ha"
344 <<
" DFT calculation for active region has not converged after "
346 <<
" iterations. Use more iterations or another convergence "
347 "acceleration scheme."
365 overlap.
Fill(aobasis);
367 const double E0_initial_truncated =
371 Eigen::MatrixXd J_initial_truncated = Eigen::MatrixXd::Zero(
373 Eigen::MatrixXd K_initial_truncated = Eigen::MatrixXd::Zero(
380 std::array<Eigen::MatrixXd, 2> JandK_initial_truncated =
CalcERIs_EXX(
382 J_initial_truncated = JandK_initial_truncated[0];
383 K_initial_truncated = 0.5 *
ScaHFX_ * JandK_initial_truncated[1];
388 const double E_Hartree_initial_truncated =
390 .cwiseProduct(J_initial_truncated + K_initial_truncated)
392 const double Initial_truncated_energy = E0_initial_truncated +
393 E_Hartree_initial_truncated +
394 xc_initial_truncated.
energy();
396 <<
"Initial truncated energy = " << Initial_truncated_energy
399 Eigen::MatrixXd PurifiedActiveDmat_trunc =
401 Eigen::MatrixXd TruncatedDensityMatrix = PurifiedActiveDmat_trunc;
407 <<
TimeStamp() <<
" Iteration " << this_iter + 1 <<
" of "
413 double E_xc_truncated = xc_truncated.
energy();
416 Eigen::MatrixXd J_truncated = Eigen::MatrixXd::Zero(
417 TruncatedDensityMatrix.rows(), TruncatedDensityMatrix.cols());
418 Eigen::MatrixXd K_truncated = Eigen::MatrixXd::Zero(
419 TruncatedDensityMatrix.rows(), TruncatedDensityMatrix.cols());
421 std::array<Eigen::MatrixXd, 2> JandK_truncated =
CalcERIs_EXX(
423 J_truncated = JandK_truncated[0];
424 K_truncated = 0.5 *
ScaHFX_ * JandK_truncated[1];
427 J_truncated =
CalcERIs(TruncatedDensityMatrix, 1
e-12);
429 double E_Hartree_truncated =
431 TruncatedDensityMatrix.cwiseProduct(J_truncated + K_truncated).sum();
433 Eigen::MatrixXd H_truncated =
436 double TruncatedTotalEnergy =
437 TruncatedDensityMatrix.cwiseProduct(
H0_trunc_).sum() +
439 Initial_truncated_energy +
446 << TruncatedDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()
449 TruncatedDensityMatrix, H_truncated, MOs_trunc, TruncatedTotalEnergy);
451 <<
"Electrons out = "
452 << TruncatedDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()
457 << TruncatedDensityMatrix.cwiseProduct(
H0_trunc_).sum() +
458 E_Hartree_truncated + E_xc_truncated
461 <<
" E_initial_trunc(Ha) = " << Initial_truncated_energy
462 <<
"\n \t \t \t" <<
" E_embedding_correction(Ha) = "
469 <<
" Truncated Energy of the system: E_trunc + E_fullDFT - "
470 <<
"\n \t \t" <<
" E_initial_trunc + E_embedding_correction = "
471 << TruncatedTotalEnergy << std::flush;
477 <<
TimeStamp() <<
" Total embedding energy has converged to "
479 <<
"[Ha] after " << this_iter + 1
480 <<
" iterations. DIIS error is converged up to "
483 <<
TimeStamp() <<
" Final Single Point Energy of embedding "
484 << std::setprecision(12) << TruncatedTotalEnergy <<
" Ha"
500 Eigen::MatrixXd InitialActiveDensityMatrix,
501 Eigen::MatrixXd v_embedding,
502 Eigen::MatrixXd InitialInactiveMOs) {
506 overlap.
Fill(aobasis);
508 Eigen::VectorXd DiagonalofDmatA = InitialActiveDensityMatrix.diagonal();
509 Eigen::VectorXd DiagonalofOverlap = overlap.
Matrix().diagonal();
510 Eigen::VectorXd MnP = DiagonalofDmatA.cwiseProduct(DiagonalofOverlap);
513 const std::vector<Index>& numfuncpatom = aobasis.
getFuncPerAtom();
515 Index numofactivebasisfunction = 0;
517 std::vector<Index> start_indices, start_indices_activemolecule;
518 Index start_idx = 0, start_idx_activemolecule = 0;
519 std::vector<Index> borderatoms;
520 for (
Index atom_num = 0; atom_num < orb.
QMAtoms().size(); atom_num++) {
521 start_indices.push_back(start_idx);
525 (std::find(activeatoms.begin(), activeatoms.end(),
527 if (partOfActive ==
true) {
531 start_indices_activemolecule.push_back(start_idx_activemolecule);
532 start_idx_activemolecule += numfuncpatom[atom_num];
533 numofactivebasisfunction += numfuncpatom[atom_num];
535 std::vector<const AOShell*> inactiveshell =
537 bool loop_break =
false;
538 for (
const AOShell* shell : inactiveshell) {
539 for (
Index shell_fn_no = shell->getStartIndex();
540 shell_fn_no < shell->getStartIndex() + shell->getNumFunc();
543 activeatoms.push_back(atom_num);
544 borderatoms.push_back(atom_num);
549 start_indices_activemolecule.push_back(start_idx_activemolecule);
550 start_idx_activemolecule += numfuncpatom[atom_num];
551 numofactivebasisfunction += numfuncpatom[atom_num];
555 if (loop_break)
break;
558 start_idx += numfuncpatom[atom_num];
562 sort(activeatoms.begin(), activeatoms.end());
563 sort(borderatoms.begin(), borderatoms.end());
567 <<
"Active + Border Molecule Size = " << activeatoms.size() <<
"\n \t \t "
568 <<
"Border Molecule Size = " << borderatoms.size() << std::flush;
569 Eigen::MatrixXd ProjectionOperator =
570 overlap.
Matrix() * InactiveDensityMatrix * overlap.
Matrix();
572 Eigen::MatrixXd H_embedding =
575 if (borderatoms.size() != 0) {
576 Eigen::MatrixXd BorderMOs;
577 for (
Index lmo_index = 0; lmo_index < InitialInactiveMOs.cols();
579 double mullikenpop_lmo_borderatoms = 0;
580 for (
Index borderatom : borderatoms) {
581 Index start = start_indices[borderatom];
582 Index size = numfuncpatom[borderatom];
583 mullikenpop_lmo_borderatoms +=
584 (InitialInactiveMOs.col(lmo_index) *
585 InitialInactiveMOs.col(lmo_index).transpose() * overlap.
Matrix())
587 .segment(start, size)
593 if (mullikenpop_lmo_borderatoms > 0.25) {
594 BorderMOs.conservativeResize(InitialInactiveMOs.rows(),
595 BorderMOs.cols() + 1);
596 BorderMOs.col(BorderMOs.cols() - 1) = InitialInactiveMOs.col(lmo_index);
600 Eigen::MatrixXd BorderDmat = 2 * BorderMOs * BorderMOs.transpose();
601 Eigen::MatrixXd BorderProjectionOperator =
603 Eigen::MatrixXd DistantProjectionOperator =
604 ProjectionOperator - BorderProjectionOperator;
607 1
e+2 * BorderProjectionOperator +
608 levelshift_ * (DistantProjectionOperator - ProjectionOperator);
613 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
615 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
617 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
620 for (
Index activeatom1_idx = 0; activeatom1_idx <
Index(activeatoms.size());
622 Index activeatom1 = activeatoms[activeatom1_idx];
623 for (
Index activeatom2_idx = 0; activeatom2_idx <
Index(activeatoms.size());
625 Index activeatom2 = activeatoms[activeatom2_idx];
627 H0_trunc_.block(start_indices_activemolecule[activeatom1_idx],
628 start_indices_activemolecule[activeatom2_idx],
629 numfuncpatom[activeatom1], numfuncpatom[activeatom2]) =
631 start_indices[activeatom1], start_indices[activeatom2],
632 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);
634 start_indices_activemolecule[activeatom1_idx],
635 start_indices_activemolecule[activeatom2_idx],
636 numfuncpatom[activeatom1], numfuncpatom[activeatom2]) =
637 InitialActiveDensityMatrix.block(
638 start_indices[activeatom1], start_indices[activeatom2],
639 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);
641 start_indices_activemolecule[activeatom2_idx],
642 numfuncpatom[activeatom1],
643 numfuncpatom[activeatom2]) =
645 start_indices[activeatom1], start_indices[activeatom2],
646 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);