71 <<
TimeStamp() <<
" Starting Projection based dft-in-dft embedding"
76 <<
TimeStamp() <<
" Passing localized orbitals as the initial guess"
78 Eigen::MatrixXd LMOs = orb.
getLMOs();
83 std::vector<Index> activeatoms =
90 const Eigen::MatrixXd InitialActiveDensityMatrix = DMAT_A.
compute_Dmat_A()[0];
94 <<
TimeStamp() <<
" Active density formation done" << std::flush;
96 Eigen::MatrixXd InactiveDensityMatrix =
97 FullDensityMatrix - InitialActiveDensityMatrix;
104 overlap.
Fill(aobasis);
107 std::round(FullDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
109 InitialActiveDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
110 Index inactive_electrons =
static_cast<Index>(
111 std::round(InactiveDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()));
114 <<
TimeStamp() <<
" Total electrons: " << all_electrons << std::flush;
119 <<
TimeStamp() <<
" Inactive electrons: " << inactive_electrons
124 throw std::runtime_error(
125 " Sum of active and inactive electrons does "
126 "not match full number of electrons!");
137 const double E0_full = FullDensityMatrix.cwiseProduct(H0.
matrix()).sum();
138 const double E0_initial_active =
139 InitialActiveDensityMatrix.cwiseProduct(H0.
matrix()).sum();
150 Eigen::MatrixXd J_full =
151 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
152 Eigen::MatrixXd J_initial_active =
153 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
154 Eigen::MatrixXd K_full =
155 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
156 Eigen::MatrixXd K_initial_active =
157 Eigen::MatrixXd::Zero(FullDensityMatrix.rows(), FullDensityMatrix.cols());
159 std::array<Eigen::MatrixXd, 2> JandK_full =
161 std::array<Eigen::MatrixXd, 2> JandK_initial_active =
CalcERIs_EXX(
162 embeddingMOs.
eigenvectors(), InitialActiveDensityMatrix, 1
e-12);
163 J_full = JandK_full[0];
164 K_full = 0.5 *
ScaHFX_ * JandK_full[1];
165 J_initial_active = JandK_initial_active[0];
166 K_initial_active = 0.5 *
ScaHFX_ * JandK_initial_active[1];
168 J_full =
CalcERIs(FullDensityMatrix, 1
e-12);
169 J_initial_active =
CalcERIs(InitialActiveDensityMatrix, 1
e-12);
172 const double E_Hartree_full =
173 0.5 * FullDensityMatrix.cwiseProduct(J_full + K_full).sum();
174 const double E_Hartree_initial_active =
175 0.5 * InitialActiveDensityMatrix
176 .cwiseProduct(J_initial_active + K_initial_active)
184 <<
" Reference total energy full electron system: " <<
Total_E_full_
185 <<
" Ha" << std::flush;
188 Eigen::MatrixXd ProjectionOperator =
189 overlap.
Matrix() * InactiveDensityMatrix * overlap.
Matrix();
192 const Eigen::MatrixXd v_embedding = J_full + K_full + xc_full.
matrix() -
193 J_initial_active - K_initial_active -
194 xc_initial_active.
matrix();
196 const double constant_embedding_energy =
Total_E_full_ - E0_initial_active -
197 E_Hartree_initial_active -
198 xc_initial_active.
energy();
201 <<
TimeStamp() <<
" Constant energy embedding terms: " << std::flush;
205 <<
TimeStamp() <<
" 2) E_0[initial active]: " << E0_initial_active
208 <<
TimeStamp() <<
" 3) E_H[initial active]: " << E_Hartree_initial_active
211 << xc_initial_active.
energy() << std::flush;
213 <<
TimeStamp() <<
" Total 1 -2 -3 -4: " << constant_embedding_energy
218 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;
404 <<
TimeStamp() <<
" Iteration " << this_iter + 1 <<
" of "
410 double E_xc_truncated = xc_truncated.
energy();
413 Eigen::MatrixXd J_truncated = Eigen::MatrixXd::Zero(
414 TruncatedDensityMatrix.rows(), TruncatedDensityMatrix.cols());
415 Eigen::MatrixXd K_truncated = Eigen::MatrixXd::Zero(
416 TruncatedDensityMatrix.rows(), TruncatedDensityMatrix.cols());
418 std::array<Eigen::MatrixXd, 2> JandK_truncated =
CalcERIs_EXX(
420 J_truncated = JandK_truncated[0];
421 K_truncated = 0.5 *
ScaHFX_ * JandK_truncated[1];
424 J_truncated =
CalcERIs(TruncatedDensityMatrix, 1
e-12);
426 double E_Hartree_truncated =
428 TruncatedDensityMatrix.cwiseProduct(J_truncated + K_truncated).sum();
430 Eigen::MatrixXd H_truncated =
433 double TruncatedTotalEnergy =
434 TruncatedDensityMatrix.cwiseProduct(
H0_trunc_).sum() +
436 Initial_truncated_energy +
443 << TruncatedDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()
446 TruncatedDensityMatrix, H_truncated, MOs_trunc, TruncatedTotalEnergy);
448 <<
"Electrons out = "
449 << TruncatedDensityMatrix.cwiseProduct(overlap.
Matrix()).sum()
454 << TruncatedDensityMatrix.cwiseProduct(
H0_trunc_).sum() +
455 E_Hartree_truncated + E_xc_truncated
458 <<
" E_initial_trunc(Ha) = " << Initial_truncated_energy
459 <<
"\n \t \t \t" <<
" E_embedding_correction(Ha) = "
466 <<
" Truncated Energy of the system: E_trunc + E_fullDFT - "
467 <<
"\n \t \t" <<
" E_initial_trunc + E_embedding_correction = "
468 << TruncatedTotalEnergy << std::flush;
474 <<
TimeStamp() <<
" Total embedding energy has converged to "
476 <<
"[Ha] after " << this_iter + 1
477 <<
" iterations. DIIS error is converged up to "
480 <<
TimeStamp() <<
" Final Single Point Energy of embedding "
481 << std::setprecision(12) << TruncatedTotalEnergy <<
" Ha"
497 Eigen::MatrixXd InitialActiveDensityMatrix,
498 Eigen::MatrixXd v_embedding,
499 Eigen::MatrixXd InitialInactiveMOs) {
503 overlap.
Fill(aobasis);
505 Eigen::VectorXd DiagonalofDmatA = InitialActiveDensityMatrix.diagonal();
506 Eigen::VectorXd DiagonalofOverlap = overlap.
Matrix().diagonal();
507 Eigen::VectorXd MnP = DiagonalofDmatA.cwiseProduct(DiagonalofOverlap);
510 const std::vector<Index>& numfuncpatom = aobasis.
getFuncPerAtom();
512 Index numofactivebasisfunction = 0;
514 std::vector<Index> start_indices, start_indices_activemolecule;
515 Index start_idx = 0, start_idx_activemolecule = 0;
516 std::vector<Index> borderatoms;
517 for (
Index atom_num = 0; atom_num < orb.
QMAtoms().size(); atom_num++) {
518 start_indices.push_back(start_idx);
522 (std::find(activeatoms.begin(), activeatoms.end(),
524 if (partOfActive ==
true) {
528 start_indices_activemolecule.push_back(start_idx_activemolecule);
529 start_idx_activemolecule += numfuncpatom[atom_num];
530 numofactivebasisfunction += numfuncpatom[atom_num];
532 std::vector<const AOShell*> inactiveshell =
534 bool loop_break =
false;
535 for (
const AOShell* shell : inactiveshell) {
536 for (
Index shell_fn_no = shell->getStartIndex();
537 shell_fn_no < shell->getStartIndex() + shell->getNumFunc();
540 activeatoms.push_back(atom_num);
541 borderatoms.push_back(atom_num);
546 start_indices_activemolecule.push_back(start_idx_activemolecule);
547 start_idx_activemolecule += numfuncpatom[atom_num];
548 numofactivebasisfunction += numfuncpatom[atom_num];
552 if (loop_break)
break;
555 start_idx += numfuncpatom[atom_num];
559 sort(activeatoms.begin(), activeatoms.end());
560 sort(borderatoms.begin(), borderatoms.end());
564 <<
"Active + Border Molecule Size = " << activeatoms.size() <<
"\n \t \t "
565 <<
"Border Molecule Size = " << borderatoms.size() << std::flush;
566 Eigen::MatrixXd ProjectionOperator =
567 overlap.
Matrix() * InactiveDensityMatrix * overlap.
Matrix();
569 Eigen::MatrixXd H_embedding =
572 if (borderatoms.size() != 0) {
573 Eigen::MatrixXd BorderMOs;
574 for (
Index lmo_index = 0; lmo_index < InitialInactiveMOs.cols();
576 double mullikenpop_lmo_borderatoms = 0;
577 for (
Index borderatom : borderatoms) {
578 Index start = start_indices[borderatom];
579 Index size = numfuncpatom[borderatom];
580 mullikenpop_lmo_borderatoms +=
581 (InitialInactiveMOs.col(lmo_index) *
582 InitialInactiveMOs.col(lmo_index).transpose() * overlap.
Matrix())
584 .segment(start, size)
590 if (mullikenpop_lmo_borderatoms > 0.25) {
591 BorderMOs.conservativeResize(InitialInactiveMOs.rows(),
592 BorderMOs.cols() + 1);
593 BorderMOs.col(BorderMOs.cols() - 1) = InitialInactiveMOs.col(lmo_index);
597 Eigen::MatrixXd BorderDmat = 2 * BorderMOs * BorderMOs.transpose();
598 Eigen::MatrixXd BorderProjectionOperator =
600 Eigen::MatrixXd DistantProjectionOperator =
601 ProjectionOperator - BorderProjectionOperator;
604 1
e+2 * BorderProjectionOperator +
605 levelshift_ * (DistantProjectionOperator - ProjectionOperator);
610 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
612 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
614 Eigen::MatrixXd::Zero(numofactivebasisfunction, numofactivebasisfunction);
617 for (
Index activeatom1_idx = 0; activeatom1_idx <
Index(activeatoms.size());
619 Index activeatom1 = activeatoms[activeatom1_idx];
620 for (
Index activeatom2_idx = 0; activeatom2_idx <
Index(activeatoms.size());
622 Index activeatom2 = activeatoms[activeatom2_idx];
624 H0_trunc_.block(start_indices_activemolecule[activeatom1_idx],
625 start_indices_activemolecule[activeatom2_idx],
626 numfuncpatom[activeatom1], numfuncpatom[activeatom2]) =
628 start_indices[activeatom1], start_indices[activeatom2],
629 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);
631 start_indices_activemolecule[activeatom1_idx],
632 start_indices_activemolecule[activeatom2_idx],
633 numfuncpatom[activeatom1], numfuncpatom[activeatom2]) =
634 InitialActiveDensityMatrix.block(
635 start_indices[activeatom1], start_indices[activeatom2],
636 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);
638 start_indices_activemolecule[activeatom2_idx],
639 numfuncpatom[activeatom1],
640 numfuncpatom[activeatom2]) =
642 start_indices[activeatom1], start_indices[activeatom2],
643 numfuncpatom[activeatom1], numfuncpatom[activeatom2]);