|
| void | Prepare (Orbitals &orb, Index numofelectrons=-1) |
| Vxc_Potential< Vxc_Grid > | SetupVxc (const QMMolecule &mol) |
| Eigen::MatrixXd | OrthogonalizeGuess (const Eigen::MatrixXd &GuessMOs) const |
| | Orthonormalize an initial MO guess with respect to the AO overlap matrix.
|
| void | PrintMOs (const Eigen::VectorXd &MOEnergies, Log::Level level) |
| | Print a one-spin list of orbital energies and occupations to the logger.
|
| void | PrintMOsUKS (const Eigen::VectorXd &alpha_energies, const Eigen::VectorXd &beta_energies, Log::Level level) const |
| | Print separate alpha and beta orbital energies for a UKS calculation.
|
| void | CalcElDipole (const Orbitals &orb) const |
| | Evaluate and print the electronic dipole moment from the final density.
|
| std::array< Eigen::MatrixXd, 2 > | CalcERIs_EXX (const Eigen::MatrixXd &MOCoeff, const Eigen::MatrixXd &Dmat, double error) const |
| Eigen::MatrixXd | CalcERIs (const Eigen::MatrixXd &Dmat, double error) const |
| | Build the Coulomb matrix contribution from the current density matrix.
|
| void | ConfigOrbfile (Orbitals &orb) |
| | Propagate basis-set, XC, and metadata settings into the orbital container.
|
| void | SetupInvariantMatrices () |
| | Precompute AO matrices that remain unchanged throughout the SCF procedure.
|
| Eigen::MatrixXd | McWeenyPurification (Eigen::MatrixXd &Dmat_in, AOOverlap &overlap) |
| Mat_p_Energy | SetupH0 (const QMMolecule &mol) const |
| | Assemble the one-electron core Hamiltonian for the current molecule.
|
| Mat_p_Energy | IntegrateExternalMultipoles (const QMMolecule &mol, const std::vector< std::unique_ptr< StaticSite > > &multipoles) const |
| Mat_p_Energy | IntegrateExternalDensity (const QMMolecule &mol, const Orbitals &extdensity) const |
| Eigen::MatrixXd | IntegrateExternalField (const QMMolecule &mol) const |
| | Integrate a homogeneous external electric field into the AO basis.
|
| tools::EigenSystem | IndependentElectronGuess (const Mat_p_Energy &H0) const |
| | Generate an initial guess by diagonalizing the core Hamiltonian only.
|
| tools::EigenSystem | ModelPotentialGuess (const Mat_p_Energy &H0, const QMMolecule &mol, const Vxc_Potential< Vxc_Grid > &vxcpotential) const |
| Eigen::MatrixXd | AtomicGuess (const QMMolecule &mol) const |
| | Build an atomic-density based initial guess in the AO basis.
|
| Eigen::VectorXd | BuildEHTOrbitalEnergies (const QMMolecule &mol) const |
| | Build orbital energies used in the extended-Hückel starting guess.
|
| Eigen::MatrixXd | BuildEHTHamiltonian (const QMMolecule &mol) const |
| | Build the extended-Hückel Hamiltonian for the current molecule.
|
| tools::EigenSystem | ExtendedHuckelGuess (const QMMolecule &mol) const |
| tools::EigenSystem | ExtendedHuckelDFTGuess (const Mat_p_Energy &H0, const QMMolecule &mol, const Vxc_Potential< Vxc_Grid > &vxcpotential) const |
| Orbitals | BuildDimerGuessFromMonomerFiles (const QMMolecule &dimer_mol) const |
| Eigen::MatrixXd | RunAtomicDFT_unrestricted (const QMAtom &uniqueAtom, bool use_hunds_rule_occupation=false) const |
| std::map< std::string, Eigen::MatrixXd > | ComputeHirshfeldReferenceDensities (const QMMolecule &mol) const |
| HirshfeldPartition::Constraint | BuildCDFTConstraint (const QMMolecule &mol, const CDFTConstraintSpec &spec) const |
| double | NuclearRepulsion (const QMMolecule &mol) const |
| | Compute the classical nucleus-nucleus repulsion energy.
|
| double | ExternalRepulsion (const QMMolecule &mol, const std::vector< std::unique_ptr< StaticSite > > &multipoles) const |
| Eigen::MatrixXd | SphericalAverageShells (const Eigen::MatrixXd &dmat, const AOBasis &dftbasis) const |
| void | TruncateBasis (Orbitals &orb, std::vector< Index > &activeatoms, Mat_p_Energy &H0, Eigen::MatrixXd InitialActiveDensityMatrix, Eigen::MatrixXd v_embedding, Eigen::MatrixXd InitialInactiveMOs) |
| void | TruncMOsFullBasis (Orbitals &orb, std::vector< Index > activeatoms, std::vector< Index > numfuncpatom) |
| Eigen::MatrixXd | InsertZeroCols (Eigen::MatrixXd MOsMatrix, Index startidx, Index numofzerocols) |
| Eigen::MatrixXd | InsertZeroRows (Eigen::MatrixXd MOsMatrix, Index startidx, Index numofzerorows) |
| | Insert zero rows into an MO coefficient matrix at the requested position.
|
| bool | EvaluateClosedShell (Orbitals &orb, const Mat_p_Energy &H0, const Vxc_Potential< Vxc_Grid > &vxcpotential) |
| | Run the restricted closed-shell SCF loop and store the converged result.
|
| bool | EvaluateUKS (Orbitals &orb, const Mat_p_Energy &H0, const Vxc_Potential< Vxc_Grid > &vxcpotential) |
| void | ComputeAndStoreForces (Orbitals &orb, const Eigen::MatrixXd &Dmat, const Vxc_Potential< Vxc_Grid > &vxcpotential) const |
| Eigen::MatrixXd | ComputeOverlapPulayGradientUKS (const QMMolecule &mol, const tools::EigenSystem &MOs_alpha, const tools::EigenSystem &MOs_beta) const |
| Eigen::MatrixXd | ComputeNonXCGradientUKS (const QMMolecule &mol, const UKSConvergenceAcc::SpinDensity &Dspin, const tools::EigenSystem &MOs_alpha, const tools::EigenSystem &MOs_beta) const |
| void | ComputeAndStoreForcesUKS (Orbitals &orb, const UKSConvergenceAcc::SpinDensity &Dspin, const tools::EigenSystem &MOs_alpha, const tools::EigenSystem &MOs_beta, const Vxc_Potential< Vxc_Grid > &vxcpotential) const |
Electronic ground-state via Density-Functional Theory.
This class assembles the one- and two-electron matrix contributions needed for self-consistent Kohn-Sham calculations in a Gaussian AO basis. The SCF machinery supports restricted closed-shell calculations and unrestricted spin-polarized calculations, while reusing the same integral and numerical XC infrastructure whenever possible.
Definition at line 73 of file dftengine.h.
| Orbitals votca::xtp::DFTEngine::BuildDimerGuessFromMonomerFiles |
( |
const QMMolecule & | dimer_mol | ) |
const |
|
private |
Build a dimer guess (both alpha and beta MOs, genuinely different from each other in general) by loading two independently-converged monomer .orb files (dimer_guess_orbA_name_/dimer_guess_orbB_name_) and combining them via Orbitals::PrepareDimerGuessMixedSpin.
Runs two sanity checks against dimer_mol (this calculation's own, real molecule) before trusting either monomer file at all: (1) element-sequence match – monomer A's own elements, in order, must exactly match dimer_mol's first N_A atoms, and monomer B's must match the remaining atoms; (2) internal-geometry match – every pairwise interatomic distance WITHIN monomer A must match the corresponding pairwise distance within dimer_mol's own first N_A atoms, to a tight numerical tolerance (and likewise for monomer B against the remaining atoms). Deliberately NOT an absolute-position comparison: after being optimized as a standalone monomer and then placed into the dimer, a monomer's atoms are expected to be translated/rotated relative to their own, independent optimization – only the INTERNAL geometry (bond lengths/angles, which no translation or rotation changes) should still match if the supplied file genuinely corresponds to that fragment.
Definition at line 2686 of file dftengine.cc.
| void votca::xtp::DFTEngine::ComputeAndStoreForces |
( |
Orbitals & | orb, |
|
|
const Eigen::MatrixXd & | Dmat, |
|
|
const Vxc_Potential< Vxc_Grid > & | vxcpotential ) const |
|
private |
Assemble the total ground-state nuclear gradient (one-electron [kinetic + nuclear attraction] + overlap "Pulay force" + nuclear repulsion + RI-J Coulomb + RI-K exact exchange [hybrid functionals]
- XC, LDA or GGA) from a converged density matrix and store it in the orbital container via Orbitals::setForces(), as the physical force (-dE/dR, matching the convention external tools such as ASE expect from a Calculator's getForces()).
The one-electron term and the overlap Pulay force were initially MISSING entirely – discovered by the first genuine end-to-end SCF+forces test (test_dftengine_forces.cc), since every earlier gradient test in this branch validated individual terms against fixed density matrices without ever checking the complete gradient against a real total SCF energy. The overlap Pulay force (arising because the MO orthonormality constraint C^T S C = I depends on geometry through the moving basis functions, weighted by orbital energies rather than occupation) is a standard part of any Gaussian-basis SCF gradient, distinct from the "PulayGradient" naming used elsewhere in this codebase for the XC-integral basis-function term.
RI-K/hybrid-functional support was added after DFTGradient:: RIKGradient's energy convention was fixed (a self-introduced regression during that work: a plausible-looking hand-algebra "correction" to a half-transformed structure was wrong, caught by directly, numerically simulating ERIs::CalculateEXX_mos's real algorithm before committing to it – the original fully-MO- transformed structure was correct, needing only a missing factor of 2) and then verified via a real C++ finite-difference test against ERIs::CalculateEXX_mos itself, not just a self-consistent formula. Also confirmed (numerically, to machine precision): CalculateEXX_mos's symmetric V^-1/2 RI fitting and RIKGradient's simpler asymmetric V^-1 fitting give IDENTICAL exchange energies (an exact algebraic identity for symmetric positive-definite V), so no matrix square root derivative was ever actually needed.
SCOPE, explicitly checked and logged rather than silently producing a wrong result: only supported when RI is actually in use for the SCF (auxbasis_name_ non-empty – DFTGradient::RIJGradient/RIKGradient only implement the RI path, not conventional 4-center ERIs).
OPT-IN: only called at all if compute_forces_ is true (see its declaration below), settable via <xtpdft><compute_forces>true</compute_forces></xtpdft> in the options tree, defaulting to false. Computing forces adds real, non-trivial cost to every converged SCF, so this is deliberately not silently always-on – added after this was pointed out as an unflagged side effect of the original, unconditional wiring.
Definition at line 421 of file dftengine.cc.
UKS (open-shell) analog of ComputeAndStoreForces.
STATUS: PARTIAL, deliberately. Four of the five non-XC-adjacent terms generalize cleanly to UKS and are implemented here: nuclear repulsion (unchanged), one-electron [kinetic + nuclear attraction] (uses D_total = Dspin.alpha + Dspin.beta, exactly the same convention RKS's Dmat already uses), the overlap Pulay force (W = W_alpha + W_beta, each WITHOUT the factor of 2 RKS uses, since UKS spin densities are not pre-doubled), and RI-K exact exchange for hybrids (0.5 * ScaHFX_ * [RIKGradient(C_alpha_occ,...) + RIKGradient(C_beta_occ,...)] – the extra factor of 0.5 relative to the naive guess of ScaHFX_*(...) confirmed both algebraically and numerically: ERIs::CalculateEXX_dmat(P) == 0.5 * ERIs::CalculateEXX_mos(C) when P = C*C^T, checked directly rather than assumed, since UKS's exact exchange goes through CalculateEXX_dmat, a different code path than the one RIKGradient/CalculateEXX_mos were validated against).
The XC gradient (PulayGradientUKS + GridWeightGradientUKS, LDA and GGA) is now included too – initially deferred as new derivation work (spin-polarized rho_alpha/rho_beta, and for GGA a genuinely new sigma_alpha-alpha/alpha-beta/beta-beta cross-term structure with no analog in the spin-restricted case), then completed and validated (Python-verified formulas first, then a real C++ finite- difference test against IntegrateVXCSpin – caught and fixed one real transcription bug, a missing factor of 2 in the GGA sigma term's Hessian contraction, found by careful line-by-line comparison against the verified Python once the first real test run showed a partial, non-catastrophic discrepancy). With XC now included, this function DOES call Orbitals::setForces(), same as the RKS ComputeAndStoreForces.
Definition at line 714 of file dftengine.cc.
Read DFT, grid, and SCF settings from the user options tree.
Self-consistent Kohn-Sham implementation.
The SCF cycle solves F C = S C eps in a Gaussian AO basis. In the restricted branch a single density matrix is iterated, whereas in the UKS branch separate alpha and beta densities are propagated while sharing the same one-electron Hamiltonian, Coulomb term, and AO overlap matrix.
Relative to the earlier restricted implementation, the UKS extension keeps the spin channels separate only where the equations require it: exchange, spin-resolved XC potentials, occupations, and convergence acceleration.
Definition at line 100 of file dftengine.cc.
| Eigen::MatrixXd votca::xtp::DFTEngine::RunAtomicDFT_unrestricted |
( |
const QMAtom & | uniqueAtom, |
|
|
bool | use_hunds_rule_occupation = false ) const |
|
private |
Run an unrestricted atomic reference calculation used in open-shell atomic guesses.
use_hunds_rule_occupation (default false, preserving all EXISTING callers' behavior exactly): when true, use a small, explicit Hund's-rule ground-state alpha/beta electron-count table for common main-group (s/p-block) elements, instead of the simpler parity-based split (odd nuclear charge -> one extra alpha electron; even -> alpha == beta) used by default. That default split is wrong for many real ground states – e.g. carbon (true ground state alpha=4,beta=2, a triplet) gets alpha=beta=3 (an artificial singlet) – but this does not matter for a SAD initial-guess starting DENSITY MATRIX SHAPE (AtomicGuess, this function's only existing caller), since the full molecule's own SCF reshapes the density regardless of the isolated reference atom's spin state. It DOES matter for promolecular reference densities used in Hirshfeld-based CDFT constraints, which is what this parameter exists for. Falls back to the default, parity-based split (with a logged warning) for any element not covered by the table – currently d/f-block only, where the ground-state configuration is genuinely ambiguous/functional-dependent rather than a simple, textbook Hund's-rule case; see HundsRuleAlphaBetaElectrons's own comment in dftengine.cc.
Definition at line 1873 of file dftengine.cc.
Run a single, charge-constrained DFT (CDFT) calculation: finds the Lagrange multiplier lambda such that Tr[(P_alpha + P_beta) * constraint.weight_matrix] equals constraint.target_population, then converges the SCF at that lambda – the standard Wu-Van Voorhis outer loop, warm-started (matching CP2K's own documented approach: each new trial's SCF is restarted from the PREVIOUS trial's converged density, not a cold start) via the existing "orbfile" initial-guess mechanism, reusing it exactly as written rather than building new warm-start machinery. Only ever wires through EvaluateUKS (never EvaluateClosedShell) – CDFT charge constraints are built on UKS from the start, per the design discussion that preceded this: a localized extra charge is almost always naturally an open-shell/ radical situation regardless of whether spin constraints are ever added later.
constraint.lambda is used as the initial guess for the bisection search (0.0 is a reasonable default for most systems) and is left holding the converged value on return. Returns false (with constraints_ left populated, holding the last-attempted lambda) if EITHER a root cannot be bracketed at all, OR the outer bisection loop exhausts max_cdft_iterations_ without reaching cdft_population_tolerance_. If any individual INNER SCF call itself fails to converge, this throws std::runtime_error instead (does not return false) – an inner SCF failure means something more fundamental than "the outer loop needs more iterations" is wrong (e.g. a genuinely bad initial guess, or too tight an SCF convergence threshold for this system), and silently returning false would look identical to the ordinary "ran out of outer
iterations" case, which it is not.
Definition at line 971 of file dftengine.cc.