41 <<
TimeStamp() <<
" Smallest value of AOOverlap matrix is "
42 <<
S_->SmallestEigenValue() << std::flush;
44 <<
TimeStamp() <<
" Removed " <<
S_->Removedfunctions()
45 <<
" basisfunction from inverse overlap matrix" << std::flush;
63 Eigen::MatrixXd H_guess = Eigen::MatrixXd::Zero(
H.rows(),
H.cols());
71 totE_.push_back(totE);
81 const Eigen::MatrixXd&
S =
S_->Matrix();
82 Eigen::MatrixXd errormatrix =
84 diiserror_ = errormatrix.cwiseAbs().maxCoeff();
97 bool diis_error =
false;
106 Eigen::VectorXd coeffs;
112 diis_error = !
adiis_.Info();
114 <<
TimeStamp() <<
" Using ADIIS for next guess" << std::flush;
117 coeffs =
diis_.CalcCoeff();
118 diis_error = !
diis_.Info();
120 <<
TimeStamp() <<
" Using DIIS for next guess" << std::flush;
124 <<
TimeStamp() <<
" (A)DIIS failed using mixing instead"
128 for (
Index i = 0; i < coeffs.size(); i++) {
129 if (std::abs(coeffs(i)) < 1
e-8) {
147 opt_.mixingparameter * dmat + (1.0 -
opt_.mixingparameter) * dmatout;
149 <<
TimeStamp() <<
" Using Mixing with alpha=" <<
opt_.mixingparameter
159 <<
TimeStamp() <<
" Convergence Options:" << std::flush;
161 <<
"\t\t Delta E [Ha]: " <<
opt_.Econverged << std::flush;
163 <<
"\t\t DIIS max error: " <<
opt_.error_converged << std::flush;
166 <<
"\t\t DIIS histlength: " <<
opt_.histlength << std::flush;
168 <<
"\t\t ADIIS start: " <<
opt_.adiis_start << std::flush;
170 <<
"\t\t DIIS start: " <<
opt_.diis_start << std::flush;
171 std::string del =
"oldest";
176 <<
"\t\t Deleting " << del <<
" element from DIIS hist" << std::flush;
179 <<
"\t\t Levelshift[Ha]: " <<
opt_.levelshift << std::flush;
181 <<
"\t\t Levelshift end: " <<
opt_.levelshiftend << std::flush;
183 <<
"\t\t Mixing Parameter alpha: " <<
opt_.mixingparameter << std::flush;
193 const Eigen::MatrixXd&
H)
const {
196 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(H_ortho);
198 if (es.info() != Eigen::ComputationInfo::Success) {
199 throw std::runtime_error(
"Matrix Diagonalisation failed. DiagInfo" +
200 std::to_string(es.info()));
218 const Eigen::MatrixXd& MOs_old)
const {
219 if (
opt_.levelshift < 1
e-9) {
222 Eigen::VectorXd virt = Eigen::VectorXd::Zero(
H.rows());
224 virt(i) =
opt_.levelshift;
228 <<
TimeStamp() <<
" Using levelshift:" <<
opt_.levelshift <<
" Hartree"
230 Eigen::MatrixXd vir =
S_->Matrix() * MOs_old * virt.asDiagonal() *
231 MOs_old.transpose() *
S_->Matrix();
257 const Eigen::MatrixXd& MOs)
const {
258 const Eigen::MatrixXd occstates = MOs.leftCols(
nocclevels_);
259 Eigen::MatrixXd dmatGS = 2.0 * occstates * occstates.transpose();
269 const Eigen::MatrixXd& MOs)
const {
271 return Eigen::MatrixXd::Zero(MOs.rows(), MOs.rows());
273 Eigen::MatrixXd occstates = MOs.leftCols(
nocclevels_);
274 Eigen::MatrixXd dmatGS = occstates * occstates.transpose();
292 if (
opt_.numberofelectrons == 0) {
297 Eigen::VectorXd occupation = Eigen::VectorXd::Zero(MOs.
eigenvalues().size());
298 std::vector<std::vector<Index> > degeneracies;
299 double buffer = 1
e-4;
300 degeneracies.push_back(std::vector<Index>{0});
301 for (
Index i = 1; i < occupation.size(); i++) {
303 MOs.
eigenvalues()(degeneracies[degeneracies.size() - 1][0]) + buffer) {
304 degeneracies[degeneracies.size() - 1].push_back(i);
306 degeneracies.push_back(std::vector<Index>{i});
309 Index numofelec =
opt_.numberofelectrons;
310 for (
const std::vector<Index>& deglevel : degeneracies) {
311 Index numofpossibleelectrons = 2 *
Index(deglevel.size());
312 if (numofpossibleelectrons <= numofelec) {
313 for (
Index i : deglevel) {
316 numofelec -= numofpossibleelectrons;
318 double occ = double(numofelec) / double(deglevel.size());
319 for (
Index i : deglevel) {
325 Eigen::MatrixXd dmatGS = MOs.
eigenvectors() * occupation.asDiagonal() *
336 const Eigen::MatrixXd& MOs)
const {
339 std::min(
opt_.number_alpha_electrons,
opt_.number_beta_electrons);
340 const Index n_socc_alpha =
opt_.number_alpha_electrons - n_docc;
343 result.
alpha = Eigen::MatrixXd::Zero(MOs.rows(), MOs.rows());
344 result.
beta = Eigen::MatrixXd::Zero(MOs.rows(), MOs.rows());
347 const Eigen::MatrixXd docc = MOs.leftCols(n_docc);
348 const Eigen::MatrixXd d_docc = docc * docc.transpose();
349 result.
alpha += d_docc;
350 result.
beta += d_docc;
353 if (n_socc_alpha > 0) {
354 const Eigen::MatrixXd socc = MOs.middleCols(n_docc, n_socc_alpha);
355 result.
alpha += socc * socc.transpose();
371 return {0.5 * d, 0.5 * d};
374 return {d, Eigen::MatrixXd::Zero(d.rows(), d.cols())};
377 return {0.5 * d, 0.5 * d};
384 return spin_dmat.
total();
Eigen::MatrixXd DensityMatrix(const tools::EigenSystem &MOs) const
Eigen::MatrixXd DensityMatrixGroundState_unres(const Eigen::MatrixXd &MOs) const
std::vector< Eigen::MatrixXd > mathist_
Eigen::MatrixXd Iterate(const Eigen::MatrixXd &dmat, Eigen::MatrixXd &H, tools::EigenSystem &MOs, double totE)
double getDIIsError() const
Return the DIIS commutator norm from the latest iteration.
tools::EigenSystem SolveFockmatrix(const Eigen::MatrixXd &H) const
Solve the generalized eigenvalue problem for the current Fock matrix.
Eigen::MatrixXd Sminusahalf
void PrintConfigOptions() const
Print the active convergence-acceleration settings to the logger.
void Levelshift(Eigen::MatrixXd &H, const Eigen::MatrixXd &MOs_old) const
Apply a virtual-space level shift in the molecular-orbital basis.
double getDeltaE() const
Return the total-energy change between the two most recent SCF iterations.
Eigen::MatrixXd DensityMatrixGroundState_frac(const tools::EigenSystem &MOs) const
Construct a fractional-occupation density matrix from orbital occupations.
std::vector< double > totE_
void setOverlap(AOOverlap &S, double etol)
Precompute overlap-dependent quantities used when solving the Fock matrix.
Eigen::MatrixXd DensityMatrixGroundState(const Eigen::MatrixXd &MOs) const
std::vector< Eigen::MatrixXd > dmatHist_
SpinDensity DensityMatrixSpinResolved(const tools::EigenSystem &MOs) const
SpinDensity DensityMatrixGroundState_restricted_open(const Eigen::MatrixXd &MOs) const
Timestamp returns the current time as a string Example: cout << TimeStamp()
#define XTP_LOG(level, log)
Charge transport classes.
Provides a means for comparing floating point numbers.
Spin-resolved density matrices returned for open-shell SCF updates.
Eigen::MatrixXd total() const
Return the total density P = P^alpha + P^beta.