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 <prdc/crystal/UnitCell.h>
14#include <prdc/cuda/resources.h>
15#include <pscf/inter/Interaction.h>
16#include <pscf/iterator/NanException.h>
26 using namespace Prdc::Cuda;
51 interaction_.setNMonomer(system().mixture().nMonomer());
57 int np = system().domain().unitCell().nParameter();
68 flexibleParams_.clear();
69 for (
int i = 0; i < np; i++) {
70 flexibleParams_.append(
true);
74 if (nFlexibleParams() == 0) isFlexible_ =
false;
76 flexibleParams_.clear();
77 for (
int i = 0; i < np; i++) {
78 flexibleParams_.append(
false);
92 out <<
"Iterator times contributions:\n";
103 interaction_.update(system().interaction());
110 void AmIteratorGrid<D>::setEqual(FieldCUDA& a, FieldCUDA
const & b)
118 double AmIteratorGrid<D>::dotProduct(FieldCUDA
const & a,
122 double val = Reduce::innerProduct(a, b);
123 if (std::isnan(val)) {
124 throw NanException(
"AmIteratorGrid::dotProduct", __FILE__,
132 double AmIteratorGrid<D>::maxAbs(FieldCUDA
const & a)
134 double val = Reduce::maxAbs(a);
135 if (std::isnan(val)) {
136 throw NanException(
"AmIteratorGrid::maxAbs", __FILE__, __LINE__, 0);
151 if (basis[0].isAllocated()) {
152 UTIL_CHECK(basis[0].capacity() == hists[0].capacity());
154 basis[0].
allocate(hists[0].capacity());
164 AmIteratorGrid<D>::addHistories(FieldCUDA& trial,
168 for (
int i = 0; i < nHist; i++) {
175 void AmIteratorGrid<D>::addPredictedError(FieldCUDA& fieldTrial,
176 FieldCUDA
const & resTrial,
184 bool AmIteratorGrid<D>::hasInitialGuess()
185 {
return system().w().hasData(); }
189 int AmIteratorGrid<D>::nElements()
191 const int nMonomer = system().mixture().nMonomer();
192 const int nMesh = system().domain().mesh().size();
194 int nEle = nMonomer*nMesh;
197 nEle += nFlexibleParams();
205 void AmIteratorGrid<D>::getCurrent(FieldCUDA& curr)
207 const int nMonomer = system().mixture().nMonomer();
208 const int nMesh = system().domain().mesh().size();
209 const int n = nElements();
213 for (
int i = 0; i < nMonomer; i++) {
214 VecOp::eqV(curr, system().w().rgrid(i), i*nMesh, 0, nMesh);
219 const int nParam = system().domain().unitCell().nParameter();
221 = system().domain().unitCell().parameters();
226 for (
int i = 0; i < nParam; i++) {
227 if (flexibleParams_[i]) {
228 tempH[counter] = scaleStress_ * parameters[i];
236 tempD.associate(curr, nMonomer*nMesh, tempH.capacity());
243 void AmIteratorGrid<D>::evaluate()
246 system().compute(isFlexible_);
251 void AmIteratorGrid<D>::getResidual(FieldCUDA& resid)
253 const int n = nElements();
254 const int nMonomer = system().mixture().nMonomer();
255 const int nMesh = system().domain().mesh().size();
265 for (
int i = 0; i < nMonomer; i++) {
266 residSlices[i].associate(resid, i*nMesh, nMesh);
270 for (
int i = 0; i < nMonomer; i++) {
271 for (
int j = 0; j < nMonomer; j++) {
273 system().c().rgrid(j), interaction_.chi(i, j),
274 system().w().rgrid(j), -interaction_.p(i, j));
279 if (system().mask().hasData()) {
280 double coeff = -1.0 / interaction_.sumChiInverse();
281 for (
int i = 0; i < nMonomer; ++i) {
288 if (system().h().hasData()) {
289 for (
int i = 0; i < nMonomer; ++i) {
290 for (
int j = 0; j < nMonomer; ++j) {
291 double p = interaction_.p(i,j);
298 if (!system().mixture().isCanonical()) {
299 cudaReal factor = 1.0 / interaction_.sumChiInverse();
302 for (
int i = 0; i < nMonomer; i++) {
304 cudaReal average = findAverage(residSlices[i]);
312 const int nParam = system().domain().unitCell().nParameter();
316 for (
int i = 0; i < nParam; i++) {
317 if (flexibleParams_[i]) {
318 double str = stress(i);
319 stressH[counter] = -1 * scaleStress_ * str;
326 stressD.associate(resid, nMonomer*nMesh, stressH.capacity());
333 void AmIteratorGrid<D>::update(FieldCUDA& newGuess)
335 const int nMonomer = system().mixture().nMonomer();
336 const int nMesh = system().domain().mesh().size();
339 if (system().mixture().isCanonical()) {
340 cudaReal average, wAverage, cAverage;
341 for (
int i = 0; i < nMonomer; i++) {
344 ngSlice.associate(newGuess, i*nMesh, nMesh);
347 average = findAverage(ngSlice);
354 for (
int j = 0; j < nMonomer; j++) {
356 if (system().w().isSymmetric()) {
358 cAverage = system().c().basis(j)[0];
360 cAverage = findAverage(system().c().rgrid(j));
362 wAverage += interaction_.chi(i,j) * cAverage;
366 if (system().h().hasData()) {
367 if (system().h().isSymmetric()) {
369 wAverage += system().h().basis(i)[0];
371 wAverage += findAverage(system().h().rgrid(i));
380 system().w().setRGrid(newGuess);
381 system().w().symmetrize();
386 parameters = system().domain().unitCell().parameters();
387 const int nParam = system().domain().unitCell().nParameter();
391 tempH.copySlice(newGuess, nMonomer*nMesh);
393 const double coeff = 1.0 / scaleStress_;
395 for (
int i = 0; i < nParam; i++) {
396 if (flexibleParams_[i]) {
397 parameters[i] = coeff * tempH[i];
403 system().setUnitCell(parameters);
409 void AmIteratorGrid<D>::outputToLog()
411 if (isFlexible_ && verbose() > 1) {
412 const int nParam = system().domain().unitCell().nParameter();
413 const int nMonomer = system().mixture().nMonomer();
414 const int nMesh = system().domain().mesh().size();
418 tempH.copySlice(residual(), nMonomer*nMesh);
421 for (
int i = 0; i < nParam; i++) {
422 if (flexibleParams_[i]) {
423 double str = tempH[counter] / (-1.0 * scaleStress_);
425 <<
" Cell Param " << i <<
" = "
426 <<
Dbl(system().domain().unitCell().parameters()[i], 15)
440 cudaReal AmIteratorGrid<D>::findAverage(FieldCUDA
const & field)
442 return Reduce::sum(field) / field.capacity();
void readErrorType(std::istream &in)
int capacity() const
Return allocated capacity.
Template for dynamic array stored in host CPU memory.
Exception thrown when not-a-number (NaN) is encountered.
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 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.
void setup(bool isContinuation)
Setup iterator just before entering iteration loop.
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 one complete 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.
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.
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
void eqV(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, const int beginIdA, const int beginIdB, const int n)
Vector assignment, a[i] = b[i], kernel wrapper (cudaReal).
void eqS(DeviceArray< cudaReal > &a, const cudaReal b, const int beginIdA, const int n)
Vector assignment, a[i] = b, kernel wrapper (cudaReal).
void addEqS(DeviceArray< cudaReal > &a, const cudaReal b, const int beginIdA, const int n)
Vector addition in-place, a[i] += b, kernel wrapper (cudaReal).
void subEqS(DeviceArray< cudaReal > &a, const cudaReal b, const int beginIdA, const int n)
Vector subtraction in-place, a[i] -= b, kernel wrapper (cudaReal).
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 subVV(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, DeviceArray< cudaReal > const &c, const int beginIdA, const int beginIdB, const int beginIdC, const int n)
Vector subtraction, a[i] = b[i] - c[i], kernel wrapper (cudaReal).
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.