1#ifndef PSCF_AM_ITERATOR_TMPL_TPP
2#define PSCF_AM_ITERATOR_TMPL_TPP
11#include "AmIteratorTmpl.h"
12#include "NanException.h"
13#include <pscf/math/LuSolver.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>
31 template <
class Iterator,
class T>
52 template <
class Iterator,
class T>
59 template <
class Iterator,
class T>
97 template <
class Iterator,
class T>
101 setup(isContinuation);
116 nBasis_ = stateBasis_.size();
117 for (itr_ = 0; itr_ <
maxItr_; ++itr_) {
121 stateHistory_.append(temp_);
126 Log::file() <<
"------------------------------- \n";
138 residualHistory_.append(temp_);
146 Log::file() <<
", error = NaN" << std::endl;
149 if (verbose_ > 0 && verbose_ < 3) {
164 projectionRatio_ += projectionError_/preError_;
165 correctionRatio_ += correctionError_/preError_;
168 preError_ = correctionError_;
210 addCorrection(stateTrial_, residualTrial_);
229 Log::file() <<
"Iterator failed to converge.\n";
234 template <
class Iterator,
class T>
238 double total = timerTotal_.time();
241 out <<
"Total" << std::setw(22)<<
"Per Iteration"
242 << std::setw(9) <<
"Fraction" <<
"\n";
243 out <<
"MDE solution: "
244 <<
Dbl(timerMDE_.time(), 9, 3) <<
" s, "
245 <<
Dbl(timerMDE_.time()/totalItr_, 9, 3) <<
" s, "
246 <<
Dbl(timerMDE_.time()/total, 9, 3) <<
"\n";
247 out <<
"residual computation: "
248 <<
Dbl(timerResid_.time(), 9, 3) <<
" s, "
249 <<
Dbl(timerResid_.time()/totalItr_, 9, 3) <<
" s, "
250 <<
Dbl(timerResid_.time()/total, 9, 3) <<
"\n";
251 out <<
"mixing coefficients: "
252 <<
Dbl(timerCoeff_.time(), 9, 3) <<
" s, "
253 <<
Dbl(timerCoeff_.time()/totalItr_, 9, 3) <<
" s, "
254 <<
Dbl(timerCoeff_.time()/total, 9, 3) <<
"\n";
255 out <<
"checking convergence: "
256 <<
Dbl(timerError_.time(), 9, 3) <<
" s, "
257 <<
Dbl(timerError_.time()/totalItr_, 9, 3) <<
" s, "
258 <<
Dbl(timerError_.time()/total, 9, 3) <<
"\n";
259 out <<
"updating guess: "
260 <<
Dbl(timerOmega_.time(), 9, 3) <<
" s, "
261 <<
Dbl(timerOmega_.time()/totalItr_, 9, 3) <<
" s, "
262 <<
Dbl(timerOmega_.time()/total, 9, 3)<<
"\n";
263 out <<
"total time: "
264 <<
Dbl(total, 9, 3) <<
" s, "
265 <<
Dbl(total/totalItr_, 9, 3) <<
" s \n";
270 out <<
"Average Projection Step Reduction Ratio: "
271 <<
Dbl(projectionRatio_/testCounter, 3, 3)<<
"\n";
272 out <<
"Average Correction Step Reduction Ratio: "
273 <<
Dbl(correctionRatio_/testCounter, 3, 3)<<
"\n";
278 template <
class Iterator,
class T>
296 template <
class Iterator,
class T>
309 std::string msg =
"Invalid iterator error type [";
311 msg +=
"] in parameter file";
319 template <
class Iterator,
class T>
341 template <
class Iterator,
class T>
347 useLambdaRamp_ = useLambdaRamp;
352 if (useLambdaRamp_) {
361 template <
class Iterator,
class T>
365 if (isAllocatedAM_)
return;
368 nElem_ = nElements();
372 residualHistory_.allocate(
maxHist_+1);
377 stateTrial_.allocate(nElem_);
378 residualTrial_.allocate(nElem_);
379 temp_.allocate(nElem_);
386 isAllocatedAM_ =
true;
393 template <
class Iterator,
class T>
400 residualHistory_.clear();
401 stateHistory_.clear();
402 if (!isContinuation) {
404 residualBasis_.clear();
413 template <
class Iterator,
class T>
417 residualHistory_.clear();
418 stateHistory_.clear();
419 residualBasis_.clear();
428 template <
class Iterator,
class T>
429 void AmIteratorTmpl<Iterator,T>::computeTrialCoeff()
433 if (itr_ == 0 && nBasis_ == 0) {
435 for (m = 0; m < maxHist_; ++m) {
438 for (n = 0; n < maxHist_; ++n) {
446 if (itr_ == 0)
return;
449 if (stateHistory_.size() > 1) {
452 updateBasis(stateBasis_, stateHistory_);
455 updateBasis(residualBasis_, residualHistory_);
458 updateU(U_, residualBasis_);
463 nBasis_ = residualBasis_.size();
468 computeV(v_, residualHistory_[0], residualBasis_);
477 coeffs_[0] = v_[0] / U_(0,0);
479 if (nBasis_ < maxHist_) {
488 for (
int i = 0; i < nBasis_; ++i) {
490 for (
int j = 0; j < nBasis_; ++j) {
491 tempU(i,j) = U_(i,j);
498 solver.computeLU(tempU);
499 solver.solve(tempv, tempcoeffs);
502 for (
int i = 0; i < nBasis_; ++i) {
503 coeffs_[i] = tempcoeffs[i];
507 if (nBasis_ == maxHist_) {
511 solver.computeLU(U_);
512 solver.solve(v_, coeffs_);
517 for (
int i = 0; i < nBasis_; ++i) {
524 template <
class Iterator,
class T>
525 void AmIteratorTmpl<Iterator,T>::updateTrial()
529 setEqual(stateTrial_, stateHistory_[0]);
530 setEqual(residualTrial_, residualHistory_[0]);
536 addEqVectors(stateTrial_, stateBasis_, coeffs_);
537 addEqVectors(residualTrial_, residualBasis_, coeffs_);
559 projectionError_ = computeError(temp_, stateTrial_, errorType_, 0);
572 template <
class Iterator,
class T>
575 if (useLambdaRamp_ && (nBasis_ <
maxHist_)) {
576 double factor = 1.0 - pow(r_, nBasis_ + 1);
577 return factor*lambda_;
586 template <
class Iterator,
class T>
592 int nBasis = residualBasis.
size();
597 for (
int m = maxHist - 1; m > 0; --m) {
598 for (
int n = maxHist-1; n > 0; --n) {
604 for (
int m = 0; m < nBasis; ++m) {
605 double dotprod = dotProduct(residualBasis[0],residualBasis[m]);
619 template <
class Iterator,
class T>
620 void AmIteratorTmpl<Iterator, T>::computeV(
622 T
const & resCurrent,
625 int nBasis = residualBasis.
size();
627 for (
int m = 0; m < nBasis; ++m) {
628 v[m] = dotProduct(resCurrent, residualBasis[m]);
635 template <
class Iterator,
class T>
645 double maxRes = maxAbs(residTrial);
648 double normRes = norm(residTrial);
654 double rmsRes = normRes/sqrt(nElements());
657 double normField = norm(stateTrial);
658 double relNormRes = normRes/normField;
667 }
else if (
errorType ==
"relNormResid") {
670 UTIL_THROW(
"Invalid iterator error type in parameter file.");
675 Log::file() <<
"Max Residual = " <<
Dbl(maxRes,15) <<
"\n";
676 Log::file() <<
"Residual Norm = " <<
Dbl(normRes,15) <<
"\n";
677 Log::file() <<
"RMS Residual = " <<
Dbl(rmsRes,15) <<
"\n";
688 template <
class Iterator,
class T>
691 return computeError(residualHistory_[0], stateHistory_[0],
699 template <
class Iterator,
class T>
701 AmIteratorTmpl<Iterator,T>::updateBasis(
RingBuffer<T> & basis,
709 if (basis[0].isAllocated()) {
710 UTIL_CHECK(basis[0].capacity() == history[0].capacity());
712 basis[0].
allocate(history[0].capacity());
716 subVV(basis[0], history[0], history[1]);
722 template <
class Iterator,
class T>
724 AmIteratorTmpl<Iterator,T>::addEqVectors(T& v,
728 int nBasis = basis.
size();
730 for (
int i = 0; i < nBasis; i++) {
731 addEqVc(v, basis[i], coeffs[i]);
738 template <
class Iterator,
class T>
740 AmIteratorTmpl<Iterator,T>::addCorrection(T& stateTrial,
741 T
const & residualTrial)
743 double lambda = computeLambda();
744 addEqVc(stateTrial, residualTrial, lambda);
752 template <
class Iterator,
class T>
753 double AmIteratorTmpl<Iterator,T>::norm(T
const & a)
755 double normSq = dotProduct(a, a);
762 template <
class Iterator,
class T>
763 void AmIteratorTmpl<Iterator,T>::setEqual(T& a, T
const & b)
769 template <
class Iterator,
class T>
771 AmIteratorTmpl<Iterator,T>::dotProduct(T
const & a, T
const & b)
777 template <
class Iterator,
class T>
778 double AmIteratorTmpl<Iterator,T>::maxAbs(T
const & a)
784 template <
class Iterator,
class T>
785 void AmIteratorTmpl<Iterator,T>::subVV(T& a, T
const & b, T
const & c)
791 template <
class Iterator,
class T>
792 void AmIteratorTmpl<Iterator,T>::addEqVc(T& a, T
const & b,
double c)
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 readMixingParameters(std::istream &in, bool useLambdaRamp=true)
Read optional parameters used in default correction algorithm.
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.
std::string errorType() const
Get error type string.
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.
int verbose_
Verbosity level.
double epsilon_
Error tolerance.
AmIteratorTmpl()
Constructor.
virtual double computeLambda()
Compute mixing parameter for correction step of Anderson mixing.
virtual bool isValidErrorType()
Checks if a string is a valid error type.
int maxItr_
Maximum number of iterations to attempt.
virtual double computeError(DArray< double > &residTrial, DArray< double > &stateTrial, std::string errorType, int verbose)
std::string errorType_
Type of error criterion used to test convergence.
virtual void readParameters(std::istream &in)
Read all parameters and initialize.
int maxHist_
Maximum number of basis vectors in AM algorithm.
int solve(bool isContinuation=false)
Iterate to a solution.
Solve Ax=b by LU decomposition of A.
void allocate(int n)
Allocate memory.
Exception thrown when not-a-number (NaN) is encountered.
int capacity() const
Return allocated size.
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).
void setClassName(const char *className)
Set class name string.
Class for storing history of previous values in an array.
void allocate(int capacity)
Allocate a new empty buffer.
void advance()
Advances the pointer to an added element without assigning a value.
int size() const
Return number of values currently in the buffer.
#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.
double innerProduct(Array< double > const &a, Array< double > const &b)
Compute Euclidean inner product of two real arrays .
double maxAbs(Array< double > const &in)
Get maximum absolute magnitude of array elements .
void eqV(Array< double > &a, Array< double > const &b, const int beginIdA, const int beginIdB, const int n)
Vector assignment, a[i] = b[i] (real, slice).
void subVV(Array< double > &a, Array< double > const &b, Array< double > const &c)
Vector-vector subtraction, a[i] = b[i] - c[i] (real)
void addEqVc(Array< double > &a, Array< double > const &b, const double c)
Add scaled vector in-place, a[i] += b[i]*c (real).
PSCF package top-level namespace.