1#ifndef RPG_AM_ITERATOR_BASIS_TPP
2#define RPG_AM_ITERATOR_BASIS_TPP
11#include "AmIteratorBasis.h"
12#include <rpg/system/System.h>
13#include <rpg/solvers/Mixture.h>
14#include <rpg/field/Domain.h>
15#include <prdc/crystal/Basis.h>
16#include <prdc/crystal/UnitCell.h>
17#include <pscf/inter/Interaction.h>
18#include <pscf/iterator/NanException.h>
63 int np = system().domain().unitCell().nParameter();
66 UTIL_CHECK(system().domain().unitCell().lattice()
72 flexibleParams_.clear();
73 for (
int i = 0; i < np; i++) {
74 flexibleParams_.append(
true);
78 if (nFlexibleParams() == 0) isFlexible_ =
false;
80 flexibleParams_.clear();
81 for (
int i = 0; i < np; i++) {
82 flexibleParams_.append(
false);
97 interaction_.setNMonomer(system().mixture().nMonomer());
108 out <<
"Iterator times contributions:\n";
122 interaction_.update(system().interaction());
131 int AmIteratorBasis<D>::nElements()
133 const int nMonomer = system().mixture().nMonomer();
134 const int nBasis = system().domain().basis().nBasis();
136 int nEle = nMonomer*nBasis;
139 nEle += nFlexibleParams();
149 bool AmIteratorBasis<D>::hasInitialGuess()
150 {
return system().w().hasData(); }
160 const int nMonomer = system().mixture().nMonomer();
161 const int nBasis = system().domain().basis().nBasis();
164 for (
int i = 0; i < nMonomer; i++) {
165 for (
int k = 0; k < nBasis; k++) {
166 curr[i*nBasis+k] = currSys[i][k];
171 const int begin = nMonomer*nBasis;
172 const int nParam = system().domain().unitCell().nParameter();
174 = system().domain().unitCell().parameters();
176 for (
int i = 0; i < nParam; i++) {
177 if (flexibleParams_[i]) {
178 curr[begin + counter] = scaleStress_ * parameters[i];
191 void AmIteratorBasis<D>::evaluate()
195 system().compute(isFlexible_);
204 UTIL_CHECK(system().domain().basis().isInitialized());
205 const int nMonomer = system().mixture().nMonomer();
206 const int nBasis = system().domain().basis().nBasis();
207 const int n = nElements();
210 for (
int i = 0 ; i < n; ++i) {
215 for (
int i = 0; i < nMonomer; ++i) {
216 for (
int j = 0; j < nMonomer; ++j) {
217 double chi = interaction_.chi(i,j);
218 double p = interaction_.p(i,j);
221 for (
int k = 0; k < nBasis; ++k) {
222 int idx = i*nBasis + k;
223 resid[idx] += chi*c[k] - p*w[k];
229 if (system().mask().hasData()) {
231 double sumChiInv = interaction_.sumChiInverse();
232 for (
int i = 0; i < nMonomer; ++i) {
233 for (
int k = 0; k < nBasis; ++k) {
234 int idx = i*nBasis + k;
235 resid[idx] -= mask[k] / sumChiInv;
242 if (system().h().hasData()) {
243 for (
int i = 0; i < nMonomer; ++i) {
244 for (
int j = 0; j < nMonomer; ++j) {
245 double p = interaction_.p(i,j);
247 for (
int k = 0; k < nBasis; ++k) {
248 int idx = i*nBasis + k;
249 resid[idx] += p * h[k];
256 if (!system().mixture().isCanonical()) {
257 for (
int i = 0; i < nMonomer; ++i) {
258 resid[i*nBasis] -= 1.0 / interaction_.sumChiInverse();
262 for (
int i = 0; i < nMonomer; ++i) {
263 resid[i*nBasis] = 0.0;
269 const int nParam = system().domain().unitCell().nParameter();
282 for (
int i = 0; i < nParam ; i++) {
283 if (flexibleParams_[i]) {
284 double str = stress(i);
286 resid[nMonomer*nBasis + counter] = -1 * scaleStress_ * str;
301 UTIL_CHECK(system().domain().basis().isInitialized());
302 const int nMonomer = system().mixture().nMonomer();
303 const int nBasis = system().domain().basis().nBasis();
309 for (
int i = 0; i < nMonomer; i++) {
311 for (
int k = 0; k < nBasis; k++) {
312 wField[i][k] = newGuess[i*nBasis + k];
317 if (system().mixture().isCanonical()) {
319 for (
int i = 0; i < nMonomer; ++i) {
321 for (
int j = 0; j < nMonomer; ++j) {
322 chi = interaction_.chi(i,j);
323 wField[i][0] += chi * system().c().basis(j)[0];
327 if (system().h().hasData()) {
328 for (
int i = 0; i < nMonomer; ++i) {
329 wField[i][0] += system().h().basis(i)[0];
333 system().w().setBasis(wField);
336 const int nParam = system().domain().unitCell().nParameter();
337 const int begin = nMonomer*nBasis;
340 parameters = system().domain().unitCell().parameters();
342 const double coeff = 1.0 / scaleStress_;
344 for (
int i = 0; i < nParam; i++) {
345 if (flexibleParams_[i]) {
346 parameters[i] = coeff * newGuess[begin + counter];
352 system().setUnitCell(parameters);
360 void AmIteratorBasis<D>::outputToLog()
362 if (isFlexible_ && verbose() > 1) {
363 const int nParam = system().domain().unitCell().nParameter();
364 const int nMonomer = system().mixture().nMonomer();
365 const int nBasis = system().domain().basis().nBasis();
367 for (
int i = 0; i < nParam; i++) {
368 if (flexibleParams_[i]) {
369 double str = residual()[nMonomer*nBasis + counter] /
370 (-1.0 * scaleStress_);
372 <<
" Cell Param " << i <<
" = "
373 <<
Dbl(system().domain().unitCell().parameters()[i], 15)
404 for (
int i=0; i < n; ++i) {
406 if (std::isnan(a[i]) || std::isnan(b[i])) {
407 throw NanException(
"AmIteratorBasis::dotProduct", __FILE__,
424 for (
int i = 0; i < n; i++) {
426 if (std::isnan(value)) {
427 throw NanException(
"AmIteratorBasis::dotProduct", __FILE__,
430 if (fabs(value) > max)
447 for (
int i = 0; i < n; i++) {
462 for (
int i = 0; i < n; i++) {
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)
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.
~AmIteratorBasis()
Destructor.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
AmIteratorBasis(System< D > &system)
Constructor.
void readParameters(std::istream &in)
Read all parameters and initialize.
void outputTimers(std::ostream &out) const
Output timing results to log file.
void setup(bool isContinuation)
Setup iterator just before entering iteration loop.
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 max(Array< double > const &in)
Get maximum of array elements .
Periodic fields and crystallography.
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.
float product(float a, float b)
Product for float Data.