PSCF v1.4.0
AmIterator.cpp
1/*
2* PSCF - Polymer Self-Consistent Field
3*
4* Copyright 2015 - 2025, The Regents of the University of Minnesota
5* Distributed under the terms of the GNU General Public License.
6*/
7
8#include "AmIterator.h"
9#include <r1d/system/System.h>
10#include <r1d/solvers/Mixture.h>
11#include <r1d/solvers/Polymer.h>
12#include <r1d/solvers/Solvent.h>
13#include <pscf/chem/Ensemble.h>
14#include <pscf/iterator/NanException.h>
15#include <pscf/cpu/VecOp.h>
16#include <pscf/cpu/Reduce.h>
17#include <util/global.h>
18
19#include <pscf/iterator/AmIteratorTmpl.tpp>
20
21// Explicit instantiation of base class
22namespace Pscf {
24}
25
26namespace Pscf {
27namespace R1d {
28
29 using namespace Util;
30
31 // Public member functions
32
33 /*
34 * Constructor.
35 */
37 : Iterator(system),
38 interaction_()
39 { ParamComposite::setClassName("AmIterator"); }
40
41 /*
42 * Destructor.
43 */
46
47 /*
48 * Read parameters from file.
49 */
50 void AmIterator::readParameters(std::istream& in)
51 {
53 AmTmpl::readParameters(in);
54 AmTmpl::readErrorType(in);
55 AmTmpl::readMixingParameters(in);
56
57 const int nMonomer = system().mixture().nMonomer();
58 interaction_.setNMonomer(nMonomer);
59 }
60
61 // Protected virtual function
62
63 /*
64 * Setup before entering iteration loop.
65 */
66 void AmIterator::setup(bool isContinuation)
67 {
69 interaction_.update(system().interaction());
70 }
71
72 // Private virtual functions that interact with parent System
73
74 // Compute and return the number of elements in a field vector
75 int AmIterator::nElements()
76 {
77 const int nm = system().mixture().nMonomer(); // # of monomers
78 const int nx = domain().nx(); // # of grid points
79 return nm*nx;
80 }
81
82 bool AmIterator::hasInitialGuess()
83 {
84 // R1d::System doesn't have an appropriate query function
85 return true;
86 }
87
88 // Get the current fields from the system as a 1D array
89 void AmIterator::getCurrent(DArray<double>& curr)
90 {
91 const int nm = system().mixture().nMonomer(); // # of monomers
92 const int nx = domain().nx(); // # of grid points
93 const DArray< DArray<double> > * currSys = &system().wFields();
94
95 // Straighten out fields into linear arrays
96 for (int i = 0; i < nm; i++) {
97 for (int k = 0; k < nx; k++) {
98 curr[i*nx+k] = (*currSys)[i][k];
99 }
100 }
101 }
102
103 /*
104 * Solve the MDEs for the current system w fields.
105 */
106 void AmIterator::evaluate()
107 { mixture().compute(system().wFields(), system().cFields()); }
108
109 /*
110 * Check whether this is canonical ensemble.
111 */
112 bool AmIterator::isCanonical()
113 {
114 Ensemble ensemble;
115
116 // Check ensemble of all polymers
117 for (int i = 0; i < mixture().nPolymer(); ++i) {
118 ensemble = mixture().polymer(i).ensemble();
119 if (ensemble == Ensemble::Open) {
120 return false;
121 }
122 if (ensemble == Ensemble::Unknown) {
123 UTIL_THROW("Unknown species ensemble");
124 }
125 }
126
127 // Check ensemble of all solvents
128 for (int i = 0; i < mixture().nSolvent(); ++i) {
129 ensemble = mixture().solvent(i).ensemble();
130 if (ensemble == Ensemble::Open) {
131 return false;
132 }
133 if (ensemble == Ensemble::Unknown) {
134 UTIL_THROW("Unknown species ensemble");
135 }
136 }
137
138 // Return true if no species had an open ensemble
139 return true;
140 }
141
142 // Compute the residual for the current system state
143 void AmIterator::getResidual(DArray<double>& resid)
144 {
145 const int nm = system().mixture().nMonomer();
146 const int nx = domain().nx();
147 const int nr = nm*nx;
148
149 // Initialize residuals
150 const double shift = -1.0/interaction_.sumChiInverse();
151 for (int i = 0 ; i < nr; ++i) {
152 resid[i] = shift;
153 }
154
155 // Compute SCF residual vector elements
156 double chi, p;
157 int i, j, k;
158 for (i = 0; i < nm; ++i) {
159 for (j = 0; j < nm; ++j) {
160 DArray<double>& cField = system().cField(j);
161 DArray<double>& wField = system().wField(j);
162 chi = interaction_.chi(i,j);
163 p = interaction_.p(i,j);
164 for (k = 0; k < nx; ++k) {
165 int idx = i*nx + k;
166 resid[idx] += chi*cField[k] - p*wField[k];
167 }
168 }
169 }
170
171 }
172
173 // Update the current system field coordinates
174 void AmIterator::update(DArray<double>& newGuess)
175 {
176 const int nm = mixture().nMonomer(); // # of monomers
177 const int nx = domain().nx(); // # of grid points
178
179 // Set current w fields in system
180 // If canonical, shift to as to set last element to zero
181 const double shift = newGuess[nm*nx - 1];
182 for (int i = 0; i < nm; i++) {
183 DArray<double>& wField = system().wField(i);
184 if (isCanonical()) {
185 for (int k = 0; k < nx; k++) {
186 wField[k] = newGuess[i*nx + k] - shift;
187 }
188 } else {
189 for (int k = 0; k < nx; k++) {
190 wField[k] = newGuess[i*nx + k];
191 }
192 }
193 }
194
195 }
196
197 void AmIterator::outputToLog()
198 {}
199
200}
201}
Template for Anderson mixing iterator algorithm.
void readParameters(std::istream &in) override
Read all parameters and initialize.
AmIterator(System &system)
Constructor.
~AmIterator()
Destructor.
void setup(bool isContinuation) override
Setup iterator just before entering iteration loop.
Base class for iterative solvers for SCF equations.
Main class in SCFT simulation of one system.
Dynamically allocatable contiguous array template.
Definition DArray.h:32
void setClassName(const char *className)
Set class name string.
File containing preprocessor macros for error handling.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
Ensemble
Statistical ensemble type for the number of molecules of one species.
Definition Ensemble.h:23
SCFT with real 1D fields.
PSCF package top-level namespace.