9#include <r1d/system/System.h>
10#include <r1d/solvers/Mixture.h>
11#include <r1d/solvers/Polymer.h>
12#include <pscf/interaction/Interaction.h>
13#include <pscf/chem/Ensemble.h>
14#include <util/misc/Log.h>
50 read(in,
"epsilon", epsilon_);
55 void NrIterator::setup()
72 wFieldsNew_.allocate(nm);
73 cFieldsNew_.allocate(nm);
74 for (
int i = 0; i < nm; ++i) {
75 wFieldsNew_[i].allocate(nx);
76 cFieldsNew_[i].allocate(nx);
83 void NrIterator::computeResidual(
Array<FieldT> const & wFields,
95 for (i = 0; i < nx; ++i) {
98 for (j = 0; j < nm; ++j) {
104 for (j = 0; j < nm; ++j) {
106 for (k = 0; k < nm; ++k) {
107 wArray_[j] += chi(j, k)*cArray_[k];
112 for (j = 0; j < nm; ++j) {
114 residual[ir] = wArray_[j] -
wFields[j][i];
118 for (j = 1; j < nm; ++j) {
120 residual[ir] = residual[ir] - residual[i];
125 for (j = 0; j < nm; ++j) {
126 residual[i] += cArray_[j];
141 residual[nx-1] =
wFields[nm-1][nx-1];
149 void NrIterator::computeJacobian()
157 for (i = 0; i < nm; ++i) {
158 for (j = 0; j < nx; ++j) {
166 double delta = 0.001;
170 for (i = 0; i < nm; ++i) {
171 for (j = 0; j < nx; ++j) {
172 wFieldsNew_[i][j] += delta;
174 computeResidual(wFieldsNew_, cFieldsNew_, residualNew_);
175 for (jr = 0; jr < nr; ++jr) {
177 (residualNew_[jr] - residual_[jr])/delta;
185 solver_.computeLU(jacobian_);
189 void NrIterator::incrementWFields(
Array<FieldT> const & wOld,
200 for (i = 0; i < nm; ++i) {
201 for (j = 0; j < nx; ++j) {
202 wNew[i][j] = wOld[i][j] - dW[k];
209 double shift = wNew[nm-1][nx-1];
210 for (i = 0; i < nm; ++i) {
211 for (j = 0; j < nx; ++j) {
219 double NrIterator::residualNorm(
Array<double> const & residual)
const
226 for (
int ir = 0; ir < nr; ++ir) {
227 value = fabs(residual[ir]);
245 for (
int i = 0; i < np; ++i) {
247 if (ensemble == Ensemble::Unknown) {
250 if (ensemble == Ensemble::Open) {
251 isCanonical_ =
false;
258 double shift =
wFields()[nm-1][nx-1];
260 for (i = 0; i < nm; ++i) {
261 for (j = 0; j < nx; ++j) {
270 double norm = residualNorm(residual_);
273 newJacobian_ =
false;
274 if (!isContinuation) {
275 needsJacobian_ =
true;
281 for (i = 0; i < maxItr_; ++i) {
283 <<
" , error = " << norm
286 if (norm < epsilon_) {
293 if (needsJacobian_) {
294 Log::file() <<
"Computing jacobian" << std::endl;;
297 needsJacobian_ =
false;
301 solver_.solve(residual_, dOmega_);
306 computeResidual(wFieldsNew_, cFieldsNew_, residualNew_);
307 normNew = residualNorm(residualNew_);
311 while (normNew > norm && j < 3) {
312 Log::file() <<
" decreasing increment, error = "
313 << normNew << std::endl;
314 needsJacobian_ =
true;
315 for (k = 0; k < nr; ++k) {
316 dOmega_[k] *= 0.66666666;
320 computeResidual(wFieldsNew_, cFieldsNew_, residualNew_);
321 normNew = residualNorm(residualNew_);
326 if (normNew > norm) {
327 Log::file() <<
" reversing increment, norm = "
328 << normNew << std::endl;
329 needsJacobian_ =
true;
330 for (k = 0; k < nr; ++k) {
331 dOmega_[k] *= -1.000;
335 computeResidual(wFieldsNew_, cFieldsNew_, residualNew_);
336 normNew = residualNorm(residualNew_);
340 if (normNew < norm) {
343 for (j = 0; j < nm; ++j) {
344 for (k = 0; k < nx; ++k) {
349 for (j = 0; j < nr; ++j) {
350 residual_[j] = residualNew_[j];
352 newJacobian_ =
false;
353 if (!needsJacobian_) {
354 if (normNew/norm > 0.5) {
355 needsJacobian_ =
true;
360 Log::file() <<
"Iteration failed, norm = "
361 << normNew << std::endl;
364 Log::file() <<
"Unrecoverable failure " << std::endl;
366 Log::file() <<
"Try rebuilding Jacobian" << std::endl;
367 needsJacobian_ =
true;
DMatrix< double > const & chi() const
Return the chi matrix by const reference.
void allocate(int n)
Allocate memory.
int nPolymer() const
Get number of polymer species.
int nMonomer() const
Get number of monomer types.
PolymerT & polymer(int id)
Get a polymer solver object by non-const reference.
int nx() const
Get number of spatial grid points, including both endpoints.
Iterator()
Default constructor.
void compute(DArray< FieldT > const &wFields, DArray< FieldT > &cFields)
Compute concentrations.
int solve(bool isContinuation=false)
Iterate self-consistent field equations to solution.
void readParameters(std::istream &in)
Read all parameters and initialize.
virtual ~NrIterator()
Destructor.
NrIterator()
Default constructor.
System::WField & wField(int monomerId)
Get chemical potential field for a specific monomer type.
const Domain & domain() const
Get spatial domain (including grid info) by reference.
DArray< System::CField > & cFields()
Get array of all chemical potential fields.
DArray< System::WField > & wFields()
Get array of all chemical potential fields.
const System & system() const
Get parent System by reference.
Main class in SCFT simulation of one system.
Interaction & interaction()
Get interaction (i.e., excess free energy) by reference.
void computeFreeEnergy()
Compute free energy density and pressure for current fields.
Field & cField(int monomerId)
Get chemical potential field for a specific monomer type.
WField & wField(int monomerId)
Get chemical potential field for a specific monomer type.
Mixture & mixture()
Get Mixture by reference.
Array container class template.
int capacity() const
Return allocated size.
void allocate(int capacity)
Allocate the underlying C array.
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
static std::ostream & file()
Get log ostream by reference.
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.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
#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.
Ensemble
Statistical ensemble type for the number of molecules of one species.
SCFT with real 1D fields.
PSCF package top-level namespace.