1#ifndef RPC_AM_ITERATOR_GRID_TPP
2#define RPC_AM_ITERATOR_GRID_TPP
11#include "AmIteratorGrid.h"
12#include <rpc/system/System.h>
13#include <rpc/solvers/Mixture.h>
14#include <rpc/field/Domain.h>
15#include <prdc/crystal/UnitCell.h>
16#include <prdc/cpu/Reduce.h>
17#include <prdc/cpu/VecOp.h>
18#include <pscf/inter/Interaction.h>
19#include <pscf/iterator/NanException.h>
20#include <util/containers/RingBuffer.h>
21#include <util/containers/DArray.h>
30 using namespace Prdc::Cpu;
62 UnitCell<D> const & unitCell = system().domain().unitCell();
75 flexibleParams_.clear();
76 for (
int i = 0; i < np; i++) {
77 flexibleParams_.append(
true);
81 if (nFlexibleParams() == 0) {
85 flexibleParams_.clear();
86 for (
int i = 0; i < np; i++) {
87 flexibleParams_.append(
false);
99 const int nMonomer = system().mixture().nMonomer();
100 interaction_.setNMonomer(nMonomer);
111 out <<
"Iterator times contributions:\n";
122 interaction_.update(system().interaction());
131 int AmIteratorGrid<D>::nElements()
133 const int nMonomer = system().mixture().nMonomer();
134 const int nMesh = system().domain().mesh().size();
136 int nEle = nMonomer*nMesh;
138 nEle += nFlexibleParams();
147 bool AmIteratorGrid<D>::hasInitialGuess()
148 {
return system().w().hasData(); }
156 const int nMonomer = system().mixture().nMonomer();
157 const int nMesh = system().domain().mesh().size();
158 const int nEle = nElements();
163 for (
int i = 0; i < nMonomer; i++) {
164 const RField<D>& field = system().w().rgrid(i);
166 for (
int k = 0; k < nMesh; k++) {
167 state[begin + k] = field[k];
174 UnitCell<D> const & unitCell = system().domain().unitCell();
176 const int nParam = unitCell.nParameter();
177 begin = nMonomer*nMesh;
179 for (
int i = 0; i < nParam; i++) {
180 if (flexibleParams_[i]) {
181 state[begin + counter] = scaleStress_ * parameters[i];
194 void AmIteratorGrid<D>::evaluate()
195 { system().compute(isFlexible_); }
203 const int nMonomer = system().mixture().nMonomer();
204 const int nMesh = system().domain().mesh().size();
205 const int n = nElements();
213 for (i = 0 ; i < n; ++i) {
218 for (i = 0; i < nMonomer; ++i) {
220 for (j = 0; j < nMonomer; ++j) {
221 chi = interaction_.chi(i,j);
222 p = interaction_.p(i,j);
223 RField<D> const & c = system().c().rgrid(j);
224 RField<D> const & w = system().w().rgrid(j);
225 if (system().h().hasData()) {
226 RField<D> const & h = system().h().rgrid(j);
227 for (k = 0; k < nMesh; ++k) {
228 resid[begin + k] += chi*c[k] + p*(h[k] - w[k]) ;
231 for (k = 0; k < nMesh; ++k) {
232 resid[begin + k] += chi*c[k] - p*w[k];
239 double shift = -1.0 / interaction_.sumChiInverse();
240 if (system().mask().hasData()) {
241 RField<D> const & mask = system().mask().rgrid();
242 for (i = 0; i < nMonomer; ++i) {
244 for (k = 0; k < nMesh; ++k) {
245 resid[begin + k] += shift*mask[k];
249 for (i = 0; i < nMonomer; ++i) {
251 for (k = 0; k < nMesh; ++k) {
252 resid[begin + k] += shift;
258 if (system().mixture().isCanonical()) {
260 for (i = 0; i < nMonomer; ++i) {
263 for (k = 0; k < nMesh; ++k) {
264 average += resid[begin + k];
266 average /= double(nMesh);
267 for (k = 0; k < nMesh; ++k) {
268 resid[begin + k] -= average;
285 const double coeff = -1.0 * scaleStress_;
286 const int nParam = system().domain().unitCell().nParameter();
287 begin = nMonomer*nMesh;
289 for (i = 0; i < nParam ; i++) {
290 if (flexibleParams_[i]) {
291 resid[begin + counter] = coeff * stress(i);
308 Domain<D> const & domain = system().domain();
309 Mesh<D> const & mesh = domain.mesh();
310 IntVec<D> const & meshDimensions = mesh.dimensions();
313 const int nMonomer = system().mixture().nMonomer();
314 const int nMesh = mesh.size();
319 for (
int i = 0; i < nMonomer; i++) {
320 wFields[i].
allocate(meshDimensions);
326 for (
int i = 0; i < nMonomer; i++) {
328 for (
int k = 0; k < nMesh; k++) {
329 wFields[i][k] = newState[begin + k];
334 if (system().mixture().isCanonical()) {
338 for (
int i = 0; i < nMonomer; ++i) {
340 wAve /= double(nMesh);
347 for (
int i = 0; i < nMonomer; ++i) {
349 cAve[i] /= double(nMesh);
354 for (
int i = 0; i < nMonomer; ++i) {
356 for (
int j = 0; j < nMonomer; ++j) {
357 chi = interaction_.chi(i,j);
358 wAve += chi * cAve[j];
364 if (system().h().hasData()) {
366 for (
int i = 0; i < nMonomer; ++i) {
368 hAve /= double(nMesh);
375 system().w().setRGrid(wFields);
382 parameters = domain.unitCell().parameters();
385 const int nParam = domain.unitCell().nParameter();
386 double coeff = 1.0 / scaleStress_;
387 const int begin = nMonomer*nMesh;
389 for (
int i = 0; i < nParam; i++) {
390 if (flexibleParams_[i]) {
391 parameters[i] = coeff * newState[begin + counter];
398 system().setUnitCell(parameters);
407 void AmIteratorGrid<D>::outputToLog()
409 if (isFlexible() && verbose() > 1) {
411 UnitCell<D> const & unitCell = system().domain().unitCell();
413 const int nMonomer = system().mixture().nMonomer();
414 const int nMesh = system().domain().mesh().size();
415 const int begin = nMonomer*nMesh;
417 for (
int i = 0; i < nParam; i++) {
418 if (flexibleParams_[i]) {
419 str = - 1.0 * residual()[begin + counter] / scaleStress_;
421 <<
" Cell Param " << i <<
" = "
422 <<
Dbl(unitCell.parameters()[i], 15)
virtual void setup(bool isContinuation)
void readMixingParameters(std::istream &in, bool useLambdaRamp=true)
void outputTimers(std::ostream &out) const
void readErrorType(std::istream &in)
virtual void readParameters(std::istream &in)
An IntVec<D, T> is a D-component vector of elements of integer type T.
Description of a regular grid of points in a periodic domain.
Field of real double precision values on an FFT mesh.
int nParameter() const
Get the number of parameters in the unit cell.
Base template for UnitCell<D> classes, D=1, 2 or 3.
FSArrayParam< Type, N > & readOptionalFSArray(std::istream &in, const char *label, FSArray< Type, N > &array, int size)
Add and read an optional FSArray < Type, N > array parameter.
AmIteratorGrid(System< D > &system)
Constructor.
void readParameters(std::istream &in) override
Read all parameters and initialize.
void outputTimers(std::ostream &out) const override
Output timing results to log file.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
void setup(bool isContinuation) override
Setup iterator just before entering iteration loop.
~AmIteratorGrid()
Destructor.
Spatial domain for a periodic structure with real fields, on a CPU.
Base class for iterative solvers for SCF equations.
Main class, representing a complete physical system.
int capacity() const
Return allocated size.
Dynamically allocatable contiguous array template.
void allocate(int capacity)
Allocate the underlying C array.
Wrapper for a double precision number, for formatted ostream output.
A fixed capacity (static) contiguous array with a variable logical size.
static std::ostream & file()
Get log ostream by reference.
void setClassName(const char *className)
Set class name string.
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
double sum(Array< double > const &in)
Compute sum of array elements .
void addEqS(Array< double > &a, double b)
Vector addition in-place, a[i] += b.
void subEqS(Array< double > &a, double b)
Vector subtraction in-place, a[i] -= b.
Periodic fields and crystallography.
Real periodic fields, SCFT and PS-FTS (CPU).
PSCF package top-level namespace.