1#ifndef RPC_LR_COMPRESSOR_TPP
2#define RPC_LR_COMPRESSOR_TPP
11#include "LrCompressor.h"
12#include <rpc/system/System.h>
13#include <prdc/crystal/shiftToMinimum.h>
14#include <pscf/mesh/MeshIterator.h>
15#include <pscf/iterator/NanException.h>
17#include <util/format/Dbl.h>
36 isIntraCalculated_(false),
53 read(in,
"epsilon", epsilon_);
63 const int nMonomer =
system().mixture().nMonomer();
65 for (
int i = 0; i < D; ++i) {
67 kMeshDimensions_[i] = dimensions[i];
69 kMeshDimensions_[i] = dimensions[i]/2 + 1;
75 resid_.allocate(dimensions);
76 residK_.allocate(dimensions);
77 wFieldTmp_.allocate(nMonomer);
78 intraCorrelationK_.allocate(kMeshDimensions_);
79 for (
int i = 0; i < nMonomer; ++i) {
80 wFieldTmp_[i].allocate(dimensions);
86 if (!isIntraCalculated_){
87 intra_.computeIntraCorrelations(intraCorrelationK_);
88 isIntraCalculated_ =
true;
112 for (itr_ = 0; itr_ < maxItr_; ++itr_) {
115 Log::file() <<
"------------------------------- \n";
126 error = computeError(verbose_);
128 Log::file() <<
", error = NaN" << std::endl;
132 Log::file() <<
", error = " <<
Dbl(error, 15) << std::endl;
136 if (error < epsilon_) {
142 Log::file() <<
"-------------------------------\n";
172 Log::file() <<
"Iterator failed to converge.\n";
181 void LrCompressor<D>::getResidual()
183 const int nMonomer = system().mixture().nMonomer();
184 const int meshSize = system().domain().mesh().size();
187 for (
int i = 0 ; i < meshSize; ++i) {
192 for (
int j = 0; j < nMonomer; ++j) {
193 for (
int k = 0; k < meshSize; ++k) {
194 resid_[k] += system().c().rgrid(j)[k];
201 void LrCompressor<D>::updateWFields()
203 const int nMonomer = system().mixture().nMonomer();
204 const int meshSize = system().domain().mesh().size();
205 const double vMonomer = system().mixture().vMonomer();
208 system().domain().fft().forwardTransform(resid_, residK_);
211 for (iter.begin(); !iter.atEnd(); ++iter) {
212 residK_[iter.rank()][0] *= 1.0 / (vMonomer * intraCorrelationK_[iter.rank()]);
213 residK_[iter.rank()][1] *= 1.0 / (vMonomer * intraCorrelationK_[iter.rank()]);
217 system().domain().fft().inverseTransformUnsafe(residK_, resid_);
219 for (
int i = 0; i < nMonomer; i++){
220 for (
int k = 0; k < meshSize; k++){
221 wFieldTmp_[i][k] = system().w().rgrid(i)[k] + resid_[k];
224 system().w().setRGrid(wFieldTmp_);
228 void LrCompressor<D>::outputToLog()
235 double total = timerTotal_.time();
237 out <<
"LrCompressor time contributions:\n";
239 out <<
"Total" << std::setw(22)<<
"Per Iteration"
240 << std::setw(9) <<
"Fraction" <<
"\n";
241 out <<
"MDE solution: "
242 <<
Dbl(timerMDE_.time(), 9, 3) <<
" s, "
243 <<
Dbl(timerMDE_.time()/totalItr_, 9, 3) <<
" s, "
244 <<
Dbl(timerMDE_.time()/total, 9, 3) <<
"\n";
258 double LrCompressor<D>::maxAbs(
RField<D> const & a)
263 for (
int i = 0; i < n; i++) {
265 if (std::isnan(value)) {
266 throw NanException(
"LrCompressor::dotProduct",__FILE__,__LINE__,0);
268 if (fabs(value) > max) {
277 double LrCompressor<D>::dotProduct(
RField<D> const & a,
280 const int n = a.capacity();
283 for (
int i = 0; i < n; i++) {
285 if (std::isnan(a[i]) || std::isnan(b[i])) {
286 throw NanException(
"AmCompressor::dotProduct",__FILE__,__LINE__,0);
295 double LrCompressor<D>::norm(
RField<D> const & a)
297 double normSq = dotProduct(a, a);
303 double LrCompressor<D>::computeError(
int verbose)
305 const int meshSize = system().domain().mesh().size();
309 double maxRes =
maxAbs(resid_);
311 double normRes = norm(resid_);
313 double rmsRes = normRes/sqrt(meshSize);
314 if (errorType_ ==
"max") {
316 }
else if (errorType_ ==
"norm") {
318 }
else if (errorType_ ==
"rms") {
321 UTIL_THROW(
"Invalid iterator error type in parameter file.");
326 Log::file() <<
"Max Residual = " <<
Dbl(maxRes,15) <<
"\n";
327 Log::file() <<
"Residual Norm = " <<
Dbl(normRes,15) <<
"\n";
328 Log::file() <<
"RMS Residual = " <<
Dbl(rmsRes,15) <<
"\n";
An IntVec<D, T> is a D-component vector of elements of integer type T.
Iterator over points in a Mesh<D>.
void setDimensions(const IntVec< D > &dimensions)
Set the grid dimensions in all directions.
Exception thrown when not-a-number (NaN) is encountered.
Field of real double precision values on an FFT mesh.
System< D > const & system() const
Return const reference to parent system.
Compressor()
Default constructor.
int mdeCounter_
Count how many times MDE has been solved.
ScalarParam< Type > & read(std::istream &in, const char *label, Type &value)
Add and read a new required ScalarParam < Type > object.
void setClassName(const char *className)
Set class name string.
LrCompressor(System< D > &system)
Constructor.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
~LrCompressor()
Destructor.
int compress()
Iterate pressure field to obtain partial saddle point.
void clearTimers()
Clear timers.
void readParameters(std::istream &in)
Read all parameters and initialize.
void setup()
Initialize just before entry to iterative loop.
void outputTimers(std::ostream &out) const
Return compressor times contributions.
Main class, representing a complete physical system.
int capacity() const
Return allocated size.
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.
File containing preprocessor macros for error handling.
#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 maxAbs(Array< double > const &in)
Get maximum absolute magnitude of array elements .
double max(Array< double > const &in)
Get maximum of array elements .
Real periodic fields, SCFT and PS-FTS (CPU).
PSCF package top-level namespace.
float product(float a, float b)
Product for float Data.