votca 2026-dev
Loading...
Searching...
No Matches
convergenceacc.h
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20#pragma once
21#ifndef VOTCA_XTP_CONVERGENCEACC_H
22#define VOTCA_XTP_CONVERGENCEACC_H
23
24// VOTCA includes
25#include <votca/tools/linalg.h>
26
27// Local VOTCA includes
28#include "adiis.h"
29#include "aomatrix.h"
30#include "diis.h"
31#include "logger.h"
32
33namespace votca {
34namespace xtp {
35
44 public:
47
50 struct options {
52 bool usediis;
53 bool noisy = false;
55 bool maxout;
57 double diis_start;
58 double levelshift;
60 // Independent from adiis_start deliberately -- see
61 // UKSConvergenceAcc::Iterate's own comment on where this is used
62 // for the full reasoning: ORCA's own DampErr is kept fully
63 // separate from its own DIISStart, and their own guidance for
64 // difficult systems is to make DampErr much SMALLER than default
65 // (keeping damping active LONGER), independent of when DIIS
66 // itself engages. Reusing adiis_start for both purposes could not
67 // represent that independently.
68 double mixingend;
71 // Ceiling mixingparameter can adaptively ramp up toward as the SCF
72 // struggles, rather than staying fixed at mixingparameter (the
73 // BASE/starting value) for the whole run -- matches ORCA's own
74 // static-damping design directly (confirmed from a real ORCA log's
75 // own resolved SCF settings, not the manual's generic defaults):
76 // DampFac (the base, 0.7 by default) and DampMax (the ceiling, 0.98
77 // by default) are two separate parameters there, not one fixed
78 // value. Notably, 0.98 is exactly the value this session's own
79 // hand-tuning independently landed on for a difficult water dimer
80 // case -- this adaptive design is a more principled way to obtain
81 // that same benefit only when actually needed, rather than paying
82 // its cost (slower convergence on easy iterations) for an entire
83 // run regardless of whether the system is struggling at all.
84 double mixingmax;
85 double Econverged;
89 // Maximum iterations for the Davidson eigensolver used by
90 // CoupledAugmentedHessianStep's own direct-minimization fallback --
91 // NOT CDFT-specific, since that fallback can engage for any
92 // sufficiently difficult UKS SCF (see this field's own XML help
93 // text, dftpackage.xml, for the real case that motivated exposing
94 // this at all: a strong CDFT constraint over a large fragment left
95 // the solver still short of its own convergence tolerance at the
96 // previous, hardcoded default of 50).
98 // Energy rise (Hartree) above the lowest energy reached so far at which
99 // the SCF discards its extrapolation history and restarts from the
100 // lowest-energy density. 0 disables.
101 double energy_reset = 1.0;
102 };
103
105 struct SpinDensity {
106 Eigen::MatrixXd alpha;
107 Eigen::MatrixXd beta;
108
110 Eigen::MatrixXd total() const { return alpha + beta; }
111
113 Eigen::MatrixXd spin() const { return alpha - beta; }
114 };
115
119 opt_ = opt;
120 if (opt_.mode == KSmode::closed) {
121 nocclevels_ = opt_.numberofelectrons / 2;
122 } else if (opt_.mode == KSmode::open) {
123 nocclevels_ = opt_.numberofelectrons;
124 } else if (opt_.mode == KSmode::fractional) {
125 nocclevels_ = 0;
126 } else if (opt_.mode == KSmode::restricted_open) {
128 std::max(opt_.number_alpha_electrons, opt_.number_beta_electrons);
129 }
130 diis_.setHistLength(opt_.histlength);
131 StartNewSCF();
132 }
133
134 // Forget the lowest-energy point used by the energy-rise reset. Called
135 // at the start of every SCF: successive SCFs on one accelerator (e.g.
136 // the stages of DFT-in-DFT embedding) need not share an energy scale.
137 // The extrapolation history itself is left as it was.
143
144 void setLogger(Logger* log) { log_ = log; }
145
147 void PrintConfigOptions() const;
148
151 bool isConverged() const {
152 if (totE_.size() < 2) {
153 return false;
154 } else {
155 return std::abs(getDeltaE()) < opt_.Econverged &&
156 getDIIsError() < opt_.error_converged;
157 }
158 }
159
161 double getDeltaE() const {
162 if (totE_.size() < 2) {
163 return 0;
164 } else {
165 return totE_.back() - totE_[totE_.size() - 2];
166 }
167 }
168
169 // Builds X = S^-1/2 for the orthogonal basis the Fock matrix is
170 // diagonalized in. Eigenvalues of S below etol are dropped from X; the
171 // directions they span are pushed to the top of every Fock spectrum
172 // (kRemovedShift) so that they can never be occupied or appear among the
173 // low virtuals. Their MO coefficient vectors are zero.
174 void setOverlap(AOOverlap& S, double etol);
175
177 double getDIIsError() const { return diiserror_; }
178
181 bool getUseMixing() const { return usedmixing_; }
182
183 // Consistency check of the extrapolation history: every stored
184 // (Fock, density) pair must still produce the error matrix DIIS holds at
185 // the same position. Used by the unit tests.
186 bool HistoryIsAligned() const;
187
190 Eigen::MatrixXd Iterate(const Eigen::MatrixXd& dmat, Eigen::MatrixXd& H,
191 tools::EigenSystem& MOs, double totE);
193 tools::EigenSystem SolveFockmatrix(const Eigen::MatrixXd& H) const;
195 void Levelshift(Eigen::MatrixXd& H, const Eigen::MatrixXd& MOs_old) const;
196
199 Eigen::MatrixXd DensityMatrix(const tools::EigenSystem& MOs) const;
200
203 SpinDensity DensityMatrixSpinResolved(const tools::EigenSystem& MOs) const;
204
205 private:
207
210 Eigen::MatrixXd DensityMatrixGroundState(const Eigen::MatrixXd& MOs) const;
213 Eigen::MatrixXd DensityMatrixGroundState_unres(
214 const Eigen::MatrixXd& MOs) const;
216 Eigen::MatrixXd DensityMatrixGroundState_frac(
217 const tools::EigenSystem& MOs) const;
218
222 const Eigen::MatrixXd& MOs) const;
223
224 bool usedmixing_ = true;
225 double diiserror_ = std::numeric_limits<double>::max();
227 const AOOverlap* S_;
228
229 Eigen::MatrixXd Sminusahalf;
230 // Projector onto the directions removed from Sminusahalf, in the
231 // orthogonal coordinates of SolveFockmatrix; empty if none were removed.
232 Eigen::MatrixXd removed_projector_;
233 static constexpr double kRemovedShift = 1e3; // Hartree
234
235 // Extrapolation history, all three aligned entry by entry: Fock matrix,
236 // the density it was built from, and that pair's DIIS error. DIIS keeps
237 // its own copy of the error matrices and is trimmed at the same index.
238 std::vector<Eigen::MatrixXd> mathist_;
239 std::vector<Eigen::MatrixXd> dmatHist_;
240 std::vector<double> errhist_;
241 // Every energy, in order. Not trimmed with the history: DeltaE and the
242 // energy tests compare consecutive iterations.
243 std::vector<double> totE_;
244
245 // Lowest-energy point so far, for the energy-rise reset.
246 bool have_best_ = false;
247 double best_energy_ = 0.0;
248 Eigen::MatrixXd best_dmat_;
249 Eigen::MatrixXd best_H_;
251 // A reset may not fire again until the history has rebuilt, and only a
252 // few times per SCF: returning to the same point over and over must be
253 // impossible.
254 static constexpr Index kResetCooldown = 3;
255 static constexpr Index kMaxEnergyResets = 5;
257
258 // ADIIS instead of DIIS once the energy rises by more than this
259 // (Hartree) between iterations, even below DIIS_start.
260 static constexpr double kEnergyRiseForADIIS = 1e-4;
261
265};
266
267} // namespace xtp
268} // namespace votca
269
270#endif // VOTCA_XTP_CONVERGENCEACC_H
Eigen::MatrixXd DensityMatrix(const tools::EigenSystem &MOs) const
void Configure(const ConvergenceAcc::options &opt)
static constexpr double kRemovedShift
Eigen::MatrixXd DensityMatrixGroundState_unres(const Eigen::MatrixXd &MOs) const
std::vector< Eigen::MatrixXd > mathist_
void setLogger(Logger *log)
Attach the logger used for convergence diagnostics.
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.
std::vector< double > errhist_
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.
static constexpr Index kResetCooldown
double getDeltaE() const
Return the total-energy change between the two most recent SCF iterations.
static constexpr Index kMaxEnergyResets
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 removed_projector_
Eigen::MatrixXd DensityMatrixGroundState(const Eigen::MatrixXd &MOs) const
std::vector< Eigen::MatrixXd > dmatHist_
KSmode
Occupation model used when constructing density matrices.
static constexpr double kEnergyRiseForADIIS
SpinDensity DensityMatrixSpinResolved(const tools::EigenSystem &MOs) const
SpinDensity DensityMatrixGroundState_restricted_open(const Eigen::MatrixXd &MOs) const
Logger is used for thread-safe output of messages.
Definition logger.h:164
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
Spin-resolved density matrices returned for open-shell SCF updates.
Eigen::MatrixXd total() const
Return the total density P = P^alpha + P^beta.
Eigen::MatrixXd spin() const
Return the spin density P^alpha - P^beta.