1#ifndef PSCF_AM_ITERATOR_TMPL_TPP
2#define PSCF_AM_ITERATOR_TMPL_TPP
11#include <pscf/inter/Interaction.h>
12#include <pscf/math/LuSolver.h>
13#include "NanException.h"
14#include <util/format/Dbl.h>
15#include <util/format/Int.h>
16#include <util/misc/Timer.h>
17#include <util/misc/FileMaster.h>
30 template <
typename Iterator,
typename T>
43 { setClassName(
"AmIteratorTmpl"); }
48 template <
typename Iterator,
typename T>
55 template <
typename Iterator,
typename T>
59 read(in,
"epsilon", epsilon_);
90 template <
typename Iterator,
typename T>
94 setup(isContinuation);
109 nBasis_ = fieldBasis_.size();
110 for (itr_ = 0; itr_ < maxItr_; ++itr_) {
114 fieldHists_.append(temp_);
119 Log::file() <<
"------------------------------- \n";
126 lambda_ = computeLambda(r_);
133 resHists_.append(temp_);
141 Log::file() <<
", error = NaN" << std::endl;
144 if (verbose_ > 0 && verbose_ < 3) {
159 projectionRatio_ += projectionError_/preError_;
160 correctionRatio_ += correctionError_/preError_;
163 preError_ = correctionError_;
168 if (error_ < epsilon_) {
175 Log::file() <<
"-------------------------------\n";
218 Log::file() <<
"Iterator failed to converge.\n";
228 template <
typename Iterator,
typename T>
230 { maxItr_ = maxItr; }
235 template <
typename Iterator,
typename T>
237 { maxHist_ = maxHist; }
242 template <
typename Iterator,
typename T>
252 std::string msg =
"Invalid iterator error type [";
254 msg +=
"] input in AmIteratorTmpl::setErrorType";
262 template <
typename Iterator,
typename T>
275 std::string msg =
"Invalid iterator error type [";
277 msg +=
"] in parameter file";
286 template <
typename Iterator,
typename T>
309 template <
typename Iterator,
typename T>
313 if (isAllocatedAM_)
return;
316 nElem_ = nElements();
319 fieldHists_.allocate(maxHist_+1);
320 resHists_.allocate(maxHist_+1);
321 fieldBasis_.allocate(maxHist_);
322 resBasis_.allocate(maxHist_);
325 fieldTrial_.allocate(nElem_);
326 resTrial_.allocate(nElem_);
327 temp_.allocate(nElem_);
330 U_.allocate(maxHist_, maxHist_);
331 v_.allocate(maxHist_);
332 coeffs_.allocate(maxHist_);
334 isAllocatedAM_ =
true;
340 template <
typename Iterator,
typename T>
343 if (!isAllocatedAM_)
return;
347 Log::file() <<
"Clearing AM field history and basis vectors.\n";
362 template <
typename Iterator,
typename T>
363 void AmIteratorTmpl<Iterator,T>::computeResidCoeff()
367 if (itr_ == 0 && nBasis_ == 0) {
369 for (m = 0; m < maxHist_; ++m) {
372 for (n = 0; n < maxHist_; ++n) {
379 if (itr_ == 0)
return;
382 if (fieldHists_.size() > 1) {
385 updateBasis(fieldBasis_, fieldHists_);
388 updateBasis(resBasis_, resHists_);
391 nBasis_ = fieldBasis_.size();
395 updateU(U_, resBasis_, nBasis_);
401 updateV(v_, resHists_[0], resBasis_, nBasis_);
407 coeffs_[0] = v_[0] / U_(0,0);
409 if (nBasis_ < maxHist_) {
418 for (
int i = 0; i < nBasis_; ++i) {
420 for (
int j = 0; j < nBasis_; ++j) {
421 tempU(i,j) = U_(i,j);
428 solver.computeLU(tempU);
429 solver.solve(tempv,tempcoeffs);
432 for (
int i = 0; i < nBasis_; ++i) {
433 coeffs_[i] = tempcoeffs[i];
437 if (nBasis_ == maxHist_) {
440 solver.computeLU(U_);
441 solver.solve(v_, coeffs_);
447 template <
typename Iterator,
typename T>
448 void AmIteratorTmpl<Iterator,T>::updateGuess()
452 setEqual(fieldTrial_, fieldHists_[0]);
453 setEqual(resTrial_, resHists_[0]);
459 addHistories(fieldTrial_, fieldBasis_, coeffs_, nBasis_);
460 addHistories(resTrial_, resBasis_, coeffs_, nBasis_);
482 projectionError_ = computeError(temp_, fieldTrial_, errorType_, 0);
489 addPredictedError(fieldTrial_, resTrial_,lambda_);
504 template <
typename Iterator,
typename T>
513 if (!isContinuation) {
525 template <
typename Iterator,
typename T>
529 if (nBasis_ < maxHist_) {
530 lambda = 1.0 - pow(r, nBasis_ + 1);
540 template <
typename Iterator,
typename T>
543 double normSq = dotProduct(a, a);
548 template <
typename Iterator,
typename T>
556 for (
int m = maxHist-1; m > 0; --m) {
557 for (
int n = maxHist-1; n > 0; --n) {
563 for (
int m = 0; m < nHist; ++m) {
564 double dotprod = dotProduct(resBasis[0],resBasis[m]);
570 template <
typename Iterator,
typename T>
573 T
const & resCurrent,
577 for (
int m = 0; m < nHist; ++m) {
578 v[m] = dotProduct(resCurrent, resBasis[m]);
582 template <
typename Iterator,
typename T>
590 double maxRes = maxAbs(residTrial);
593 double normRes =
norm(residTrial);
599 double rmsRes = normRes/sqrt(nElements());
602 double normField =
norm(fieldTrial);
603 double relNormRes = normRes/normField;
612 }
else if (
errorType ==
"relNormResid") {
615 UTIL_THROW(
"Invalid iterator error type in parameter file.");
620 Log::file() <<
"Max Residual = " <<
Dbl(maxRes,15) <<
"\n";
621 Log::file() <<
"Residual Norm = " <<
Dbl(normRes,15) <<
"\n";
622 Log::file() <<
"RMS Residual = " <<
Dbl(rmsRes,15) <<
"\n";
630 template <
typename Iterator,
typename T>
636 template <
typename Iterator,
typename T>
640 double total = timerTotal_.time();
643 out <<
"Total" << std::setw(22)<<
"Per Iteration"
644 << std::setw(9) <<
"Fraction" <<
"\n";
645 out <<
"MDE solution: "
646 <<
Dbl(timerMDE_.time(), 9, 3) <<
" s, "
647 <<
Dbl(timerMDE_.time()/totalItr_, 9, 3) <<
" s, "
648 <<
Dbl(timerMDE_.time()/total, 9, 3) <<
"\n";
649 out <<
"residual computation: "
650 <<
Dbl(timerResid_.time(), 9, 3) <<
" s, "
651 <<
Dbl(timerResid_.time()/totalItr_, 9, 3) <<
" s, "
652 <<
Dbl(timerResid_.time()/total, 9, 3) <<
"\n";
653 out <<
"mixing coefficients: "
654 <<
Dbl(timerCoeff_.time(), 9, 3) <<
" s, "
655 <<
Dbl(timerCoeff_.time()/totalItr_, 9, 3) <<
" s, "
656 <<
Dbl(timerCoeff_.time()/total, 9, 3) <<
"\n";
657 out <<
"checking convergence: "
658 <<
Dbl(timerError_.time(), 9, 3) <<
" s, "
659 <<
Dbl(timerError_.time()/totalItr_, 9, 3) <<
" s, "
660 <<
Dbl(timerError_.time()/total, 9, 3) <<
"\n";
661 out <<
"updating guess: "
662 <<
Dbl(timerOmega_.time(), 9, 3) <<
" s, "
663 <<
Dbl(timerOmega_.time()/totalItr_, 9, 3) <<
" s, "
664 <<
Dbl(timerOmega_.time()/total, 9, 3)<<
"\n";
665 out <<
"total time: "
666 <<
Dbl(total, 9, 3) <<
" s, "
667 <<
Dbl(total/totalItr_, 9, 3) <<
" s \n";
672 out <<
"Average Projection Step Reduction Ratio: "
673 <<
Dbl(projectionRatio_/testCounter, 3, 3)<<
"\n";
674 out <<
"Average Correction Step Reduction Ratio: "
675 <<
Dbl(correctionRatio_/testCounter, 3, 3)<<
"\n";
680 template <
typename Iterator,
typename T>
Template for Anderson mixing iterator algorithm.
virtual void setup(bool isContinuation)
Initialize just before entry to iterative loop.
ScalarParam< Type > & read(std::istream &in, const char *label, Type &value)
Add and read a new required ScalarParam < Type > object.
void setMaxHist(int maxHist)
Set value of maxHist (number of retained previous states)
virtual double computeLambda(double r)
Compute mixing parameter for correction step of Anderson mixing.
virtual double computeError(DArray< double > &residTrial, DArray< double > &fieldTrial, std::string errorType, int verbose)
void allocateAM()
Allocate memory required by AM algorithm, if necessary.
bool isAllocatedAM() const
Have data structures required by the AM algorithm been allocated?
virtual void clear()
Clear information about history.
void outputTimers(std::ostream &out) const
Log output timing results.
void setErrorType(std::string errorType)
Set and validate value of errorType string.
std::string errorType() const
Obtain error type.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
void clearTimers()
Clear timers.
int verbose() const
Verbosity level, allowed values 0, 1, or 2.
~AmIteratorTmpl()
Destructor.
void readErrorType(std::istream &in)
Read and validate the optional errorType string parameter.
void setMaxItr(int maxItr)
Set value of maxItr.
AmIteratorTmpl()
Constructor.
virtual bool isValidErrorType()
Checks if a string is a valid error type.
std::string errorType_
Type of error criterion used to test convergence.
void readParameters(std::istream &in)
Read all parameters and initialize.
int solve(bool isContinuation=false)
Iterate to a solution.
virtual double norm(T const &hist)
Find the L2 norm of a vector.
Solve Ax=b by LU decomposition of A.
void allocate(int n)
Allocate memory.
Exception thrown when not-a-number (NaN) is encountered.
Dynamically allocatable contiguous array template.
void allocate(int capacity)
Allocate the underlying C array.
Dynamically allocated Matrix.
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
Wrapper for a double precision number, for formatted ostream output.
Wrapper for an int, for formatted ostream output.
static std::ostream & file()
Get log ostream by reference.
int capacity1() const
Get number of rows (range of the first array index).
Class for storing history of previous values in an array.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
PSCF package top-level namespace.