1#ifndef RPG_AM_ITERATOR_GRID_TPP
2#define RPG_AM_ITERATOR_GRID_TPP
11#include "AmIteratorGrid.h"
12#include <rpg/system/System.h>
13#include <rpg/solvers/Mixture.h>
14#include <rpg/field/Domain.h>
15#include <prdc/crystal/UnitCell.h>
16#include <prdc/cuda/resources.h>
17#include <pscf/inter/Interaction.h>
18#include <pscf/iterator/NanException.h>
27 using namespace Prdc::Cuda;
61 int np = system().domain().unitCell().nParameter();
64 UTIL_CHECK(system().domain().unitCell().lattice()
73 flexibleParams_.clear();
74 for (
int i = 0; i < np; i++) {
75 flexibleParams_.append(
true);
79 if (nFlexibleParams() == 0) isFlexible_ =
false;
81 flexibleParams_.clear();
82 for (
int i = 0; i < np; i++) {
83 flexibleParams_.append(
false);
94 interaction_.setNMonomer(system().mixture().nMonomer());
106 out <<
"Iterator times contributions:\n";
119 interaction_.update(system().interaction());
126 bool AmIteratorGrid<D>::hasInitialGuess()
127 {
return system().w().hasData(); }
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;
139 nEle += nFlexibleParams();
149 void AmIteratorGrid<D>::getCurrent(VectorT& curr)
151 const int nMonomer = system().mixture().nMonomer();
152 const int nMesh = system().domain().mesh().size();
153 const int n = nElements();
157 for (
int i = 0; i < nMonomer; i++) {
158 VecOp::eqV(curr, system().w().rgrid(i), i*nMesh, 0, nMesh);
163 const int nParam = system().domain().unitCell().nParameter();
165 = system().domain().unitCell().parameters();
170 for (
int i = 0; i < nParam; i++) {
171 if (flexibleParams_[i]) {
172 tempH[counter] = scaleStress_ * parameters[i];
180 tempD.associate(curr, nMonomer*nMesh, tempH.capacity());
189 void AmIteratorGrid<D>::evaluate()
192 system().compute(isFlexible_);
199 void AmIteratorGrid<D>::getResidual(VectorT& resid)
201 const int n = nElements();
202 const int nMonomer = system().mixture().nMonomer();
203 const int nMesh = system().domain().mesh().size();
213 for (
int i = 0; i < nMonomer; i++) {
214 residSlices[i].associate(resid, i*nMesh, nMesh);
218 for (
int i = 0; i < nMonomer; i++) {
219 for (
int j = 0; j < nMonomer; j++) {
221 system().c().rgrid(j), interaction_.chi(i, j),
222 system().w().rgrid(j), -interaction_.p(i, j));
227 if (system().mask().hasData()) {
228 double coeff = -1.0 / interaction_.sumChiInverse();
229 for (
int i = 0; i < nMonomer; ++i) {
236 if (system().h().hasData()) {
237 for (
int i = 0; i < nMonomer; ++i) {
238 for (
int j = 0; j < nMonomer; ++j) {
239 double p = interaction_.p(i,j);
246 if (!system().mixture().isCanonical()) {
247 cudaReal factor = 1.0 / interaction_.sumChiInverse();
250 for (
int i = 0; i < nMonomer; i++) {
252 cudaReal average = findAverage(residSlices[i]);
260 const int nParam = system().domain().unitCell().nParameter();
264 for (
int i = 0; i < nParam; i++) {
265 if (flexibleParams_[i]) {
266 double str = stress(i);
267 stressH[counter] = -1 * scaleStress_ * str;
274 stressD.associate(resid, nMonomer*nMesh, stressH.capacity());
283 void AmIteratorGrid<D>::update(VectorT& newGuess)
285 const int nMonomer = system().mixture().nMonomer();
286 const int nMesh = system().domain().mesh().size();
289 if (system().mixture().isCanonical()) {
290 cudaReal average, wAverage, cAverage;
291 for (
int i = 0; i < nMonomer; i++) {
295 ngSlice.associate(newGuess, i*nMesh, nMesh);
298 average = findAverage(ngSlice);
305 for (
int j = 0; j < nMonomer; j++) {
306 cAverage = findAverage(system().c().rgrid(j));
307 wAverage += interaction_.chi(i,j) * cAverage;
311 if (system().h().hasData()) {
312 wAverage += findAverage(system().h().rgrid(i));
321 system().w().setRGrid(newGuess);
326 parameters = system().domain().unitCell().parameters();
327 const int nParam = system().domain().unitCell().nParameter();
331 tempH.copySlice(newGuess, nMonomer*nMesh);
333 const double coeff = 1.0 / scaleStress_;
335 for (
int i = 0; i < nParam; i++) {
336 if (flexibleParams_[i]) {
337 parameters[i] = coeff * tempH[i];
343 system().setUnitCell(parameters);
351 void AmIteratorGrid<D>::outputToLog()
353 if (isFlexible_ && verbose() > 1) {
354 UnitCell<D> const & unitCell = system().domain().unitCell();
356 const int nMonomer = system().mixture().nMonomer();
357 const int nMesh = system().domain().mesh().size();
361 tempH.copySlice(residual(), nMonomer*nMesh);
364 for (
int i = 0; i < nParam; i++) {
365 if (flexibleParams_[i]) {
366 double str = tempH[counter] / (-1.0 * scaleStress_);
368 <<
" Cell Param " << i <<
" = "
369 <<
Dbl(unitCell.parameters()[i], 15)
385 void AmIteratorGrid<D>::setEqual(VectorT& a,
396 double AmIteratorGrid<D>::dotProduct(VectorT
const & a,
401 if (std::isnan(val)) {
403 __FILE__, __LINE__, 0);
412 double AmIteratorGrid<D>::maxAbs(VectorT
const & a)
415 if (std::isnan(val)) {
417 __FILE__, __LINE__, 0);
426 void AmIteratorGrid<D>::subVV(VectorT& a,
435 void AmIteratorGrid<D>::addEqVc(VectorT& a,
445 cudaReal AmIteratorGrid<D>::findAverage(VectorT
const & field)
446 {
return Reduce::sum(field) / (double) field.capacity(); }
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)
Template for dynamic array stored in host CPU memory.
Exception thrown when not-a-number (NaN) is encountered.
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)
Read all parameters and initialize.
void setup(bool isContinuation) override
Setup iterator just before entering iteration loop.
void setClassName(const char *className)
Set class name string.
DeviceArray< cudaReal > VectorT
Typename for state and residual vectors.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
void outputTimers(std::ostream &out) const
Output timing results to log file.
~AmIteratorGrid()
Destructor.
Base class for iterative solvers for SCF equations.
Main class, representing a complete physical system.
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.
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 .
double maxAbs(Array< double > const &in)
Get maximum absolute magnitude of array elements .
double innerProduct(Array< double > const &a, Array< double > const &b)
Compute inner product of two real arrays .
void subVV(Array< double > &a, Array< double > const &b, Array< double > const &c)
Vector subtraction, a[i] = b[i] - c[i].
void eqV(Array< double > &a, Array< double > const &b)
Vector assignment, a[i] = b[i].
void addEqS(Array< double > &a, double b)
Vector addition in-place, a[i] += b.
void eqS(Array< double > &a, double b)
Vector assignment, a[i] = b.
void subEqS(Array< double > &a, double b)
Vector subtraction in-place, a[i] -= b.
void addVcVcVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c, DeviceArray< cudaReal > const &d, cudaReal const e, DeviceArray< cudaReal > const &f, cudaReal const g)
3-vec addition w coeff, a[i] = (b[i]*c) + (d[i]*e) + (f[i]*g), kernel wrapper.
void addEqVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c)
Vector addition in-place w/ coefficient, a[i] += b[i] * c, kernel wrapper.
Periodic fields and crystallography.
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.