20 #ifndef JDFTX_CORE_PULAY_H 21 #define JDFTX_CORE_PULAY_H 23 #include <core/PulayParams.h> 25 #include <electronic/matrix.h> 33 template<
typename Variable>
class Pulay 45 double minimize(
double Eprev=+DBL_MAX, std::vector<string> extraNames=std::vector<string>(), std::vector<double> extraThresh=std::vector<double>());
48 void saveState(
const char* filename)
const;
52 virtual double sync(
double x)
const {
return x; }
65 virtual double cycle(
double dEprev, std::vector<double>& extraValues)=0;
68 virtual void axpy(
double alpha,
const Variable& X, Variable& Y)
const=0;
69 virtual double dot(
const Variable& X,
const Variable& Y)
const=0;
72 virtual void writeVariable(
const Variable&, FILE*)
const=0;
76 virtual Variable
applyMetric(
const Variable&)
const=0;
80 std::vector<Variable> pastVariables;
81 std::vector<Variable> pastResiduals;
89 #include <core/Minimize_linmin.h> 95 {
unsigned nCheck;
double threshold;
96 std::deque<bool> history;
98 NormCheck(
unsigned nCheck,
double threshold) : nCheck(nCheck), threshold(fabs(threshold)) {}
99 bool checkConvergence(
double norm)
100 { history.push_back(fabs(norm)<threshold);
101 if(history.size()==nCheck+1) history.pop_front();
102 if(history.size()==nCheck)
103 {
for(
bool converged: history)
117 template<
typename Variable>
double Pulay<Variable>::minimize(
double Eprev, std::vector<string> extraNames, std::vector<double> extraThresh)
119 double E =
sync(Eprev); Eprev = 0.;
121 assert(extraNames.size()==extraThresh.size());
126 std::vector<std::shared_ptr<NormCheck> > extraCheck(extraNames.size());
127 for(
size_t iExtra=0; iExtra<extraNames.size(); iExtra++)
128 extraCheck[iExtra] = std::make_shared<NormCheck>(2, extraThresh[iExtra]);
133 assert(pastResiduals.size() == pastVariables.size());
134 if((
int)pastResiduals.size() >= pp.
history)
135 {
size_t ndim = pastResiduals.size();
136 if(ndim>1) overlap.set(0,ndim-1, 0,ndim-1, overlap(1,ndim, 1,ndim));
137 pastVariables.erase(pastVariables.begin());
138 pastResiduals.erase(pastResiduals.begin());
146 std::vector<double> extraValues(extraThresh.size());
149 for(
auto& v: extraValues) v =
sync(v);
152 double residualNorm = 0.;
153 { Variable residual =
getVariable();
axpy(-1., pastVariables.back(), residual);
154 pastResiduals.push_back(residual);
162 fprintf(pp.
fpLog,
" |Residual|: %.3e", residualNorm);
163 for(
size_t iExtra=0; iExtra<extraNames.size(); iExtra++)
164 fprintf(pp.
fpLog,
" |%s|: %.3e", extraNames[iExtra].c_str(), extraValues[iExtra]);
176 bool converged =
false;
177 if(!converged && ediffCheck.checkConvergence(E))
181 if(!converged && resCheck.checkConvergence(residualNorm))
185 if(!converged && extraNames.size())
186 for(
size_t iExtra=0; iExtra<extraNames.size(); iExtra++)
187 if(extraCheck[iExtra]->checkConvergence(extraValues[iExtra]))
188 { fprintf(pp.
fpLog,
"%sConverged (|%s|<%le for 2 iters).\n\n", pp.
linePrefix, extraNames[iExtra].c_str(), extraThresh[iExtra]);
198 size_t ndim = pastResiduals.size();
199 Variable MlastResidual =
applyMetric(pastResiduals.back());
200 for(
size_t j=0; j<ndim; j++)
201 {
double thisOverlap =
dot(pastResiduals[j], MlastResidual);
202 overlap.set(j, ndim-1, thisOverlap);
203 overlap.set(ndim-1, j, thisOverlap);
207 matrix cOverlap(ndim+1, ndim+1);
208 cOverlap.
set(0, ndim, 0, ndim, overlap(0, ndim, 0, ndim));
209 for(
size_t j=0; j<ndim; j++)
210 { cOverlap.
set(j, ndim, 1);
211 cOverlap.
set(ndim, j, 1);
213 cOverlap.
set(ndim, ndim, 0);
219 for(
size_t j=0; j<ndim; j++)
220 {
double alpha = coefs[cOverlap_inv.
index(j, ndim)].real();
221 axpy(alpha, pastVariables[j], v);
232 size_t nBytesFile =
fileSize(filename);
233 size_t ndim = nBytesFile / nBytesCycle;
234 size_t dimOffset = 0;
236 { dimOffset = ndim - pp.
history;
239 if(nBytesFile % nBytesCycle != 0)
240 die(
"Pulay history file '%s' does not contain an integral multiple of the mixed variables and residuals.\n", filename);
241 fprintf(pp.
fpLog,
"%sReading %lu past variables and residuals from '%s' ... ", pp.
linePrefix, ndim, filename);
logFlush();
242 pastVariables.resize(ndim);
243 pastResiduals.resize(ndim);
244 FILE* fp = fopen(filename,
"r");
245 if(dimOffset) fseek(fp, dimOffset*nBytesCycle, SEEK_SET);
246 for(
size_t idim=0; idim<ndim; idim++)
251 fprintf(pp.
fpLog,
"done.\n"); fflush(pp.
fpLog);
253 for(
size_t i=0; i<ndim; i++)
254 { Variable Mresidual_i =
applyMetric(pastResiduals[i]);
255 for(
size_t j=0; j<=i; j++)
256 {
double thisOverlap =
dot(pastResiduals[j], Mresidual_i);
257 overlap.set(i,j, thisOverlap);
258 overlap.set(j,i, thisOverlap);
266 { FILE* fp = fopen(filename,
"w");
267 for(
size_t idim=0; idim<pastVariables.size(); idim++)
268 { writeVariable(pastVariables[idim], fp);
269 writeVariable(pastResiduals[idim], fp);
276 { pastVariables.clear();
277 pastResiduals.clear();
282 #endif //JDFTX_CORE_PULAY_H Pulay mixing to optimize self-consistent field optimization .
Definition: Pulay.h:35
Definition: Minimize_linmin.h:27
ScalarField sqrt(const ScalarField &)
Elementwise square root (preserve input)
virtual Variable applyMetric(const Variable &) const =0
Apply metric to variable/residual.
double energyDiffThreshold
convergence threshold for energy difference between successive iterations
Definition: PulayParams.h:34
General complex matrix.
Definition: matrix.h:58
#define logFlush()
fflush() for log files
Definition: Util.h:111
virtual double dot(const Variable &X, const Variable &Y) const =0
Euclidean dot product. Metric applied separately for efficiency.
int nIterations
maximum iterations (single point calculation if 0)
Definition: PulayParams.h:33
bool isHead() const
whether this is the root process (makes code more readable)
Definition: MPIUtil.h:39
const char * linePrefix
prefix for each output line of Pulay (default "Pulay: ")
Definition: PulayParams.h:29
int index(int i, int j) const
Index into data()
Definition: matrix.h:66
void set(int i, int j, complex m)
set element to m
off_t fileSize(const char *filename)
Get the size of a file.
virtual Variable precondition(const Variable &) const =0
Apply preconditioner to variable/residual.
virtual void setVariable(const Variable &)=0
Set the state of system to specified variable.
virtual void readVariable(Variable &, FILE *) const =0
Read variable from stream.
Parameters to control Pulay mixing.
Definition: PulayParams.h:26
virtual void report(int iter)
Override to perform optional reporting.
Definition: Pulay.h:67
double clock_sec()
Elapsed time in microseconds (from start of program)
const char * energyFormat
printf format for the minimized quantity (default "%22.15le")
Definition: PulayParams.h:31
void clearState()
remove past variables and residuals
bool killFlag
Flag set by signal handlers - all compute loops should quit cleanly when this is set.
FILE * fpLog
Stream to log iterations to.
Definition: PulayParams.h:28
double residualThreshold
convergence threshold on the residual
Definition: PulayParams.h:35
void loadState(const char *filename)
Load the state from a single binary file.
#define die(...)
Quit with an error message (formatted using printf()). Must be called from all processes.
Definition: Util.h:114
ScalarField inv(const ScalarField &)
Elementwise reciprocal (preserve input)
void saveState(const char *filename) const
Save the state to a single binary file.
virtual Variable getVariable() const =0
Write variable to stream.
virtual double cycle(double dEprev, std::vector< double > &extraValues)=0
Single cycle of the self-consistency loop. In each subsequent cycle, Pulay will try to zero the diffe...
int history
Number of past residuals and vectors that are cached and used for mixing.
Definition: PulayParams.h:37
complex * data()
Return a pointer to the actual data Return a CPU pointer to the actual data, will move data from GPU ...
virtual double sync(double x) const
Override to synchronize scalars over MPI processes (if the same minimization is happening in sync ove...
Definition: Pulay.h:52
Complex number (need to define our own because we need operators for gpu code as well) ...
Definition: scalar.h:49
double minimize(double Eprev=+DBL_MAX, std::vector< string > extraNames=std::vector< string >(), std::vector< double > extraThresh=std::vector< double >())
Minimize energy using a self-consistent iteration.
const char * energyLabel
Label for the minimized quantity (default "E")
Definition: PulayParams.h:30
virtual void axpy(double alpha, const Variable &X, Variable &Y) const =0
Scaled accumulate on variable.
virtual size_t variableSize() const =0
Number of bytes per variable.
#define assert(expr)
A custom assertion with stack trace (NOTE: enabled in release modes as well)
Definition: Util.h:100