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