MADNESS 0.10.1
dispersion.h
Go to the documentation of this file.
1/*
2 This file is part of MADNESS.
3
4 Copyright (C) 2007,2010 Oak Ridge National Laboratory
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 For more information please contact:
21
22 Robert J. Harrison
23 Oak Ridge National Laboratory
24 One Bethel Valley Road
25 P.O. Box 2008, MS-6367
26
27 email: harrisonrj@ornl.gov
28 tel: 865-241-3937
29 fax: 865-572-0680
30 */
31
32#ifndef SRC_MADNESS_CHEM_DISPERSION_H_
33#define SRC_MADNESS_CHEM_DISPERSION_H_
34
35#include <string>
36#include <vector>
37
39#include <madness/world/world.h>
41
42namespace madness {
43
44/// interface class to simple-dftd3, Grimme's D3 empirical dispersion correction
45
46/// The D3 correction is a closed-form function of the nuclear coordinates
47/// alone: it touches neither the density nor the Fock matrix, so it enters a
48/// calculation as one additive number in the total energy and one additive
49/// tensor in the nuclear gradient.
50///
51/// References
52/// - S. Grimme, J. Antony, S. Ehrlich, H. Krieg,
53/// J. Chem. Phys. 132, 154104 (2010), doi:10.1063/1.3382344 [the D3 model]
54/// - S. Grimme, S. Ehrlich, L. Goerigk,
55/// J. Comput. Chem. 32, 1456 (2011), doi:10.1002/jcc.21759 [BJ damping]
56/// - implementation: https://github.com/dftd3/simple-dftd3
57///
58/// Requires MADNESS to be configured against simple-dftd3
59/// (`-DENABLE_DFTD3=ON`, the default, plus a discoverable install); a default
60/// constructed object is inactive and returns zeros, but asking for an actual
61/// correction in a build without the library throws.
63public:
64
65 /// default ctor -- inactive, energy() is 0.0 and gradient() is all zeros
67
68 /// construct from the `dft` input group
69
70 /// @param[in] spec "none", "d3bj" or "d3zero" (the `dispersion` keyword)
71 /// @param[in] xc_line the `xc` input line; its first token is the fallback
72 /// source for the damping parameter set
73 /// @param[in] functional explicit functional name (the `dispersion_functional`
74 /// keyword); empty means derive it from @c xc_line
75 /// @param[in] atm include the three-body Axilrod-Teller-Muto term
76 DispersionCorrection(const std::string& spec, const std::string& xc_line,
77 const std::string& functional, const bool atm);
78
79 /// true if a correction is actually being applied
80 bool active() const { return damping != none; }
81
82 /// short human-readable tag, e.g. "D3(BJ)/pbe0" -- "none" if inactive
83 std::string description() const;
84
85 /// print the method and its primary references; a no-op if inactive
86
87 /// Prints at most once per object, so callers on a path that repeats per
88 /// geometry step (Nemo::value) need no guard of their own.
89 void print_citation(World& world) const;
90
91 /// the dispersion energy in Hartree; 0.0 if inactive
92 double energy(World& world, const Molecule& mol) const;
93
94 /// d E_disp / d R in Hartree/bohr, length 3*natom, laid out [3*atom + axis]
95
96 /// Same layout as SCF::derivatives and NemoBase::compute_gradient, so the
97 /// result can be added to those tensors directly. All zeros if inactive.
98 Tensor<double> gradient(World& world, const Molecule& mol) const;
99
100 /// d^2 E_disp / dR_i dR_j in Hartree/bohr^2, (3*natom, 3*natom)
101
102 /// Same [3*atom + axis] index convention as gradient(), so the result can be
103 /// added straight to Nemo::hessian's matrix. All zeros if inactive.
104 ///
105 /// Central differences of the *analytic* gradient. simple-dftd3 grew an
106 /// analytic Hessian (dftd3_get_dispersion_hessian) only in its 1.6 API,
107 /// which no release carries yet; differencing costs 6*natom library calls of
108 /// a few microseconds each and lands ~1e-9 Ha/bohr^2 from the exact result,
109 /// orders of magnitude below the error of the electronic Hessian it joins.
110 Tensor<double> hessian(World& world, const Molecule& mol) const;
111
112 /// throw if `spec` asks for a correction, naming the engine that cannot apply it
113
114 /// For engines whose energy expression has no dispersion term. Silently
115 /// dropping the correction would report an uncorrected energy as the answer
116 /// to a deck that asked for a corrected one. A no-op for "none"/"", so
117 /// call sites need no guard of their own.
118 ///
119 /// Takes the raw `dispersion` keyword because not every such engine owns an
120 /// SCF to ask -- Znemo carries a bare CalculationParameters.
121 static void reject(const std::string& spec, const char* engine);
122
123 /// same, for an already-constructed correction
124 void reject(const char* engine) const { reject(description(), engine); }
125
126 /// true if this build can compute a correction at all
127 static bool available();
128
129 /// linked simple-dftd3 version as "major.minor.patch", or "" if unavailable
130 static std::string library_version();
131
132private:
133
135
137
138 /// the method name handed to simple-dftd3's parameter tables
139 std::string method;
140
141 /// include the three-body ATM term
142 bool atm = false;
143
144 /// evaluate on rank 0 and broadcast; fills the cache below
145 void compute(World& world, const Molecule& mol) const;
146
147 /// the atomic numbers, ordered to match Molecule::get_all_coords()
148 static std::vector<int> atomic_numbers(const Molecule& mol);
149
150 /// one library call: energy and gradient for a geometry. Rank-local and
151 /// uncached, so the finite differences in hessian() neither communicate per
152 /// displacement nor evict the cache.
153 void evaluate(const std::vector<int>& numbers, const Tensor<double>& coords,
154 double& e, Tensor<double>& g) const;
155
156 /// memoized result -- SCF::solve asks once per iteration for a quantity
157 /// that only changes when the optimizer moves the nuclei
160 mutable double cached_energy = 0.0;
161 mutable bool cache_valid = false;
162 mutable bool citation_printed = false;
163};
164
165} // namespace madness
166
167#endif /* SRC_MADNESS_CHEM_DISPERSION_H_ */
interface class to simple-dftd3, Grimme's D3 empirical dispersion correction
Definition dispersion.h:62
void reject(const char *engine) const
same, for an already-constructed correction
Definition dispersion.h:124
void evaluate(const std::vector< int > &numbers, const Tensor< double > &coords, double &e, Tensor< double > &g) const
Definition dispersion.cc:232
static void reject(const std::string &spec, const char *engine)
throw if spec asks for a correction, naming the engine that cannot apply it
Definition dispersion.cc:194
double cached_energy
Definition dispersion.h:160
Damping
Definition dispersion.h:134
@ rational
Definition dispersion.h:134
@ zero
Definition dispersion.h:134
@ none
Definition dispersion.h:134
Tensor< double > gradient(World &world, const Molecule &mol) const
d E_disp / d R in Hartree/bohr, length 3*natom, laid out [3*atom + axis]
Definition dispersion.cc:364
static std::vector< int > atomic_numbers(const Molecule &mol)
the atomic numbers, ordered to match Molecule::get_all_coords()
Definition dispersion.cc:268
DispersionCorrection()=default
default ctor – inactive, energy() is 0.0 and gradient() is all zeros
std::string description() const
short human-readable tag, e.g. "D3(BJ)/pbe0" – "none" if inactive
Definition dispersion.cc:205
Tensor< double > cached_gradient
Definition dispersion.h:159
bool atm
include the three-body ATM term
Definition dispersion.h:142
static std::string library_version()
linked simple-dftd3 version as "major.minor.patch", or "" if unavailable
Definition dispersion.cc:128
bool cache_valid
Definition dispersion.h:161
Damping damping
Definition dispersion.h:136
bool active() const
true if a correction is actually being applied
Definition dispersion.h:80
void print_citation(World &world) const
print the method and its primary references; a no-op if inactive
Definition dispersion.cc:213
Tensor< double > cached_coords
Definition dispersion.h:158
std::string method
the method name handed to simple-dftd3's parameter tables
Definition dispersion.h:139
static bool available()
true if this build can compute a correction at all
Definition dispersion.cc:119
bool citation_printed
Definition dispersion.h:162
Tensor< double > hessian(World &world, const Molecule &mol) const
d^2 E_disp / dR_i dR_j in Hartree/bohr^2, (3*natom, 3*natom)
Definition dispersion.cc:302
void compute(World &world, const Molecule &mol) const
evaluate on rank 0 and broadcast; fills the cache below
Definition dispersion.cc:276
Definition molecule.h:129
A tensor is a multidimensional array.
Definition tensor.h:318
A parallel world class.
Definition world.h:134
double(* energy)()
Definition derivatives.cc:58
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
NDIM const Function< R, NDIM > & g
Definition mra.h:2622
static XNonlinearSolver< std::vector< Function< T, NDIM > >, T, vector_function_allocator< T, NDIM > > nonlinear_vector_solver(World &world, const long nvec)
Definition nonlinsol.h:371
Defines and implements most of Tensor.
void e()
Definition test_sig.cc:75
Declares the World class for the parallel runtime environment.