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;
51 virtual double sync(
double x)
const {
return x; }
64 virtual double cycle(
double dEprev, std::vector<double>& extraValues)=0;
67 virtual void axpy(
double alpha,
const Variable& X, Variable& Y)
const=0;
68 virtual double dot(
const Variable& X,
const Variable& Y)
const=0;
71 virtual void writeVariable(
const Variable&, FILE*)
const=0;
75 virtual Variable
applyMetric(
const Variable&)
const=0;
79 std::vector<Variable> pastVariables;
80 std::vector<Variable> pastResiduals;
88 #include <core/Minimize_linmin.h> 94 {
unsigned nCheck;
double threshold;
95 std::deque<bool> history;
97 NormCheck(
unsigned nCheck,
double threshold) : nCheck(nCheck), threshold(fabs(threshold)) {}
98 bool checkConvergence(
double norm)
99 { history.push_back(fabs(norm)<threshold);
100 if(history.size()==nCheck+1) history.pop_front();
101 if(history.size()==nCheck)
102 {
for(
bool converged: history)
116 template<
typename Variable>
double Pulay<Variable>::minimize(
double Eprev, std::vector<string> extraNames, std::vector<double> extraThresh)
118 double E =
sync(Eprev); Eprev = 0.;
120 assert(extraNames.size()==extraThresh.size());
125 std::vector<std::shared_ptr<NormCheck> > extraCheck(extraNames.size());
126 for(
size_t iExtra=0; iExtra<extraNames.size(); iExtra++)
127 extraCheck[iExtra] = std::make_shared<NormCheck>(2, extraThresh[iExtra]);
132 assert(pastResiduals.size() == pastVariables.size());
133 if((
int)pastResiduals.size() >= pp.
history)
134 {
size_t ndim = pastResiduals.size();
135 if(ndim>1) overlap.set(0,ndim-1, 0,ndim-1, overlap(1,ndim, 1,ndim));
136 pastVariables.erase(pastVariables.begin());
137 pastResiduals.erase(pastResiduals.begin());
145 std::vector<double> extraValues(extraThresh.size());
148 for(
auto& v: extraValues) v =
sync(v);
151 double residualNorm = 0.;
152 { Variable residual =
getVariable();
axpy(-1., pastVariables.back(), residual);
153 pastResiduals.push_back(residual);
161 fprintf(pp.
fpLog,
" |Residual|: %.3e", residualNorm);
162 for(
size_t iExtra=0; iExtra<extraNames.size(); iExtra++)
163 fprintf(pp.
fpLog,
" |%s|: %.3e", extraNames[iExtra].c_str(), extraValues[iExtra]);
170 bool converged =
false;
171 if(!converged && ediffCheck.checkConvergence(E))
175 if(!converged && resCheck.checkConvergence(residualNorm))
179 if(!converged && extraNames.size())
180 for(
size_t iExtra=0; iExtra<extraNames.size(); iExtra++)
181 if(extraCheck[iExtra]->checkConvergence(extraValues[iExtra]))
182 { fprintf(pp.
fpLog,
"%sConverged (|%s|<%le for 2 iters).\n\n", pp.
linePrefix, extraNames[iExtra].c_str(), extraThresh[iExtra]);
192 size_t ndim = pastResiduals.size();
193 Variable MlastResidual =
applyMetric(pastResiduals.back());
194 for(
size_t j=0; j<ndim; j++)
195 {
double thisOverlap =
dot(pastResiduals[j], MlastResidual);
196 overlap.set(j, ndim-1, thisOverlap);
197 overlap.set(ndim-1, j, thisOverlap);
201 matrix cOverlap(ndim+1, ndim+1);
202 cOverlap.
set(0, ndim, 0, ndim, overlap(0, ndim, 0, ndim));
203 for(
size_t j=0; j<ndim; j++)
204 { cOverlap.
set(j, ndim, 1);
205 cOverlap.
set(ndim, j, 1);
207 cOverlap.
set(ndim, ndim, 0);
213 for(
size_t j=0; j<ndim; j++)
214 {
double alpha = coefs[cOverlap_inv.
index(j, ndim)].real();
215 axpy(alpha, pastVariables[j], v);
226 size_t nBytesFile =
fileSize(filename);
227 size_t ndim = nBytesFile / nBytesCycle;
228 size_t dimOffset = 0;
230 { dimOffset = ndim - pp.
history;
233 if(nBytesFile % nBytesCycle != 0)
234 die(
"Pulay history file '%s' does not contain an integral multiple of the mixed variables and residuals.\n", filename);
235 fprintf(pp.
fpLog,
"%sReading %lu past variables and residuals from '%s' ... ", pp.
linePrefix, ndim, filename);
logFlush();
236 pastVariables.resize(ndim);
237 pastResiduals.resize(ndim);
238 FILE* fp = fopen(filename,
"r");
239 if(dimOffset) fseek(fp, dimOffset*nBytesCycle, SEEK_SET);
240 for(
size_t idim=0; idim<ndim; idim++)
245 fprintf(pp.
fpLog,
"done.\n"); fflush(pp.
fpLog);
247 for(
size_t i=0; i<ndim; i++)
248 { Variable Mresidual_i =
applyMetric(pastResiduals[i]);
249 for(
size_t j=0; j<=i; j++)
250 {
double thisOverlap =
dot(pastResiduals[j], Mresidual_i);
251 overlap.set(i,j, thisOverlap);
252 overlap.set(j,i, thisOverlap);
260 { FILE* fp = fopen(filename,
"w");
261 for(
size_t idim=0; idim<pastVariables.size(); idim++)
262 { writeVariable(pastVariables[idim], fp);
263 writeVariable(pastResiduals[idim], fp);
271 #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:57
#define logFlush()
fflush() for log files
Definition: Util.h:115
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:65
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:66
const char * energyFormat
printf format for the minimized quantity (default "%22.15le")
Definition: PulayParams.h:31
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:118
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:51
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:104