MADNESS 0.10.1
SCFProtocol.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 $Id$
33*/
34
35/// \file SCFProtocol.h
36/// \brief solution protocol for SCF calculations
37
38
39#ifndef MADNESS_CHEM_SCFPROTOCOL_H__INCLUDED
40#define MADNESS_CHEM_SCFPROTOCOL_H__INCLUDED
41
43
44namespace madness {
45
46/// struct for running a protocol of subsequently tightening precision
47
48/// The ladder is `CalculationParameters::protocol()` and nothing else -- the
49/// same list moldft walks, so both engines refine through identical steps and
50/// `k` follows from `SCF::set_protocol`'s thresh->k table. `econv` and `dconv`
51/// are convergence criteria applied at each rung, relaxed to the rung's own
52/// threshold the way `SCF::solve` already relaxes dconv: you cannot converge a
53/// quantity tighter than the basis represents it.
55public:
65
67
68 bool converged; ///< flag if protocol has converged
69
70 double start_prec; ///< starting precision, typically 1.e-4
71 double current_prec; ///< current precision
72 double end_prec; ///< final precision
73
74 double thresh; ///< numerical precision of representing functions
75 double econv; ///< energy convergence of SCF calculations
76 double dconv; ///< density convergence of SCF calculations
77
78 /// number of rungs in the ladder
79 std::size_t size() const {return protocol.size();}
80
81 /// index of the rung this protocol will start at
82 std::size_t start_index() const {return index;}
83
84 /// start at a given rung rather than at the first
85
86 /// used to skip rungs a restart has already converged through
87 void set_start_index(const std::size_t i) {
88 MADNESS_CHECK_THROW(i<protocol.size(), "start index beyond the protocol");
89 index=i;
93 }
94
95 /// start at the first rung that is tighter than an already-achieved precision
96
97 /// @param[in] achieved the threshold a restart is converged to
98 /// @return false if the ladder holds nothing tighter, i.e. nothing to do
99 bool set_start_from_achieved(const double achieved) {
100 for (std::size_t i=0; i<protocol.size(); ++i) {
101 if (protocol[i] < achieved*0.999) {
103 return true;
104 }
105 }
106 // every rung is already covered by what the restart achieved
107 converged=true;
108 return false;
109 }
110
111 /// drop the last rung, i.e. stop one step short of the full precision
112
113 /// used for cheap pre-iterations; never empties the ladder
115 if (protocol.size()<2) return;
116 protocol.pop_back();
117 end_prec=protocol.back();
118 if (index>=protocol.size()) set_start_index(protocol.size()-1);
119 }
120
121 void initialize() {
122
123 // don't do anything if this protocol is already converged
124 if (converged) return;
125
128
129 if (world.rank()==0) {
130 std::stringstream ss;
131 ss <<"\nstarting protocol at time" << std::setw(8) << std::setprecision(2)
132 << wall_time() << "s";
133 print(ss.str());
134 print("precision steps ",current_prec," --> ",end_prec,
135 " (rung",index,"of",protocol.size(),")");
136 print("protocol: thresh",thresh,"econv ",econv,"dconv",dconv);
137 }
138 }
139
140 bool finished() const {return converged;}
141
142 /// go to the next rung of the ladder
144 if (index+1<protocol.size()) {
145 ++index;
148 } else {
149 converged=true;
150 }
151
152 return *this;
153 }
154
155 /// true if the current rung is the last one
156 bool on_last_rung() const {return index+1==protocol.size();}
157
158 /// infer thresholds for a given rung of the ladder
159
160 /// The rung sets the representation threshold. econv and dconv are the
161 /// user's, but never tighter than the rung can support.
162 ///
163 /// dconv needs care. The BSH residual cannot fall much below the threshold
164 /// the orbitals are represented at, and nemo tests `bsh_norm < dconv`
165 /// strictly, so a dconv equal to the rung's threshold is unreachable and the
166 /// rung burns maxiter without converging. Intermediate rungs therefore use
167 /// the long-standing 0.1*sqrt(thresh) relaxation -- 1e-3 at thresh 1e-4,
168 /// 1e-4 at thresh 1e-6 -- which is comfortably looser than the rung; they
169 /// are only a stepping stone, so there is nothing to gain from converging
170 /// them tightly. The last rung is the answer, so it honours the user's dconv
171 /// (never demanding tighter than the representation supports).
172 void infer_thresholds(const double prec) {
173 thresh=prec;
174 econv=std::max(prec,user_econv);
175 if (on_last_rung()) dconv=std::max(prec,user_dconv);
176 else dconv=std::max(user_dconv,std::min(1.e-3,sqrt(prec)*0.1));
177 }
178
179 /// compare two positive doubles to be equal
180 bool approx(const double a, const double b) const {
181 return (std::abs(a/b-1.0)<1.e-12);
182 }
183
184private:
185 std::vector<double> protocol; ///< the ladder, from CalculationParameters
186 std::size_t index; ///< current rung
187 double user_econv; ///< energy convergence provided by user
188 double user_dconv; ///< density convergence provided by user
189};
190
191
192
193} // namespace madness
194
195
196#endif /* SRC_APPS_CHEM_SCFPROTOCOL_H_ */
double w(double t, double eps)
Definition DKops.h:22
struct for running a protocol of subsequently tightening precision
Definition SCFProtocol.h:54
bool set_start_from_achieved(const double achieved)
start at the first rung that is tighter than an already-achieved precision
Definition SCFProtocol.h:99
double user_dconv
density convergence provided by user
Definition SCFProtocol.h:188
double user_econv
energy convergence provided by user
Definition SCFProtocol.h:187
double end_prec
final precision
Definition SCFProtocol.h:72
World & world
Definition SCFProtocol.h:66
bool finished() const
Definition SCFProtocol.h:140
void initialize()
Definition SCFProtocol.h:121
std::vector< double > protocol
the ladder, from CalculationParameters
Definition SCFProtocol.h:185
void drop_last_rung()
drop the last rung, i.e. stop one step short of the full precision
Definition SCFProtocol.h:114
SCFProtocol & operator++()
go to the next rung of the ladder
Definition SCFProtocol.h:143
bool converged
flag if protocol has converged
Definition SCFProtocol.h:68
std::size_t start_index() const
index of the rung this protocol will start at
Definition SCFProtocol.h:82
std::size_t index
current rung
Definition SCFProtocol.h:186
double dconv
density convergence of SCF calculations
Definition SCFProtocol.h:76
double current_prec
current precision
Definition SCFProtocol.h:71
double thresh
numerical precision of representing functions
Definition SCFProtocol.h:74
void set_start_index(const std::size_t i)
start at a given rung rather than at the first
Definition SCFProtocol.h:87
double start_prec
starting precision, typically 1.e-4
Definition SCFProtocol.h:70
std::size_t size() const
number of rungs in the ladder
Definition SCFProtocol.h:79
bool on_last_rung() const
true if the current rung is the last one
Definition SCFProtocol.h:156
void infer_thresholds(const double prec)
infer thresholds for a given rung of the ladder
Definition SCFProtocol.h:172
bool approx(const double a, const double b) const
compare two positive doubles to be equal
Definition SCFProtocol.h:180
SCFProtocol(World &w, const CalculationParameters &param)
Definition SCFProtocol.h:56
double econv
energy convergence of SCF calculations
Definition SCFProtocol.h:75
A parallel world class.
Definition world.h:134
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:344
#define MADNESS_CHECK_THROW(condition, msg)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:207
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:227
double wall_time()
Returns the wall time in seconds relative to an arbitrary origin.
Definition timers.cc:48
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
static long abs(long a)
Definition tensor.h:219
static const double b
Definition nonlinschro.cc:119
static const double a
Definition nonlinschro.cc:118
Definition CalculationParameters.h:51
InputParameters param
Definition tdse.cc:203