PSCF v1.3.3
rpg/scft/sweep/Sweep.tpp
1#ifndef RPG_SWEEP_TPP
2#define RPG_SWEEP_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field
6*
7* Copyright 2015 - 2025, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "Sweep.h"
12#include <rpg/system/System.h>
13#include <rpg/scft/iterator/Iterator.h>
14#include <rpg/scft/ScftThermo.h>
15#include <prdc/environment/Environment.h>
16#include <rpg/solvers/Mixture.h>
17#include <rpg/field/Domain.h>
18#include <prdc/crystal/Basis.h>
19#include <prdc/crystal/UnitCell.h>
20#include <pscf/inter/Interaction.h>
21#include <pscf/sweep/SweepTmpl.tpp>
22#include <util/misc/FileMaster.h>
23#include <util/misc/ioUtil.h>
24
25namespace Pscf {
26namespace Rpg {
27
28 using namespace Util;
29
30 // Maximum number of previous states = order of continuation + 1
31 #define RPG_HISTORY_CAPACITY 3
32
33 /*
34 * Default constructor.
35 */
36 template <int D>
38 : SweepTmpl< BasisFieldState<D> >(RPG_HISTORY_CAPACITY),
39 writeCRGrid_(false),
40 writeCBasis_(false),
41 writeWRGrid_(false),
42 systemPtr_(0)
43 {}
44
45 /*
46 * Constructor, creates association with parent system.
47 */
48 template <int D>
50 : SweepTmpl< BasisFieldState<D> >(RPG_HISTORY_CAPACITY),
51 writeCRGrid_(false),
52 writeCBasis_(false),
53 writeWRGrid_(false),
54 systemPtr_(&sys)
55 {
56 // Get specialized sweep parameters from Iterator
57 if (system().hasEnvironment()) {
58 addParameterTypes(system().environment().getParameterTypes());
59 }
60 }
61
62 /*
63 * Destructor.
64 */
65 template <int D>
68
69 /*
70 * Set association with a parent system.
71 */
72 template <int D>
74 { systemPtr_ = &system; }
75
76 /*
77 * Read parameters
78 */
79 template <int D>
80 void Sweep<D>::readParameters(std::istream& in)
81 {
82 // Call the base class's readParameters function.
84
85 // Read optional flags indicating which field types to output
86 readOptional(in, "writeCRGrid", writeCRGrid_);
87 readOptional(in, "writeCBasis", writeCBasis_);
88 readOptional(in, "writeWRGrid", writeWRGrid_);
89 }
90
91 /*
92 * Check allocation of one state object, allocate if necessary.
93 */
94 template <int D>
96 {
98 state.setSystem(system());
99 state.allocate();
100 state.unitCell() = system().domain().unitCell();
101 }
102
103 /*
104 * Setup operations at the beginning of a sweep.
105 */
106 template <int D>
108 {
109 initialize();
110 checkAllocation(trial_);
111
112 // Open log summary file
113 std::string fileName = baseFileName_;
114 fileName += "sweep.log";
115 system().fileMaster().openOutputFile(fileName, logFile_);
116 };
117
118 /*
119 * Set non-adjustable system parameters to new values.
120 *
121 * \param s path length coordinate, in range [0,1]
122 */
123 template <int D>
125 {
126 // Empty default implementation allows Sweep<D> to be compiled.
127 UTIL_THROW("Calling unimplemented function Sweep::setParameters");
128 };
129
130 /*
131 * Create guess for adjustable variables by polynomial extrapolation.
132 */
133 template <int D>
134 void Sweep<D>::extrapolate(double sNew)
135 {
136 UTIL_CHECK(historySize() > 0);
137
138 // If historySize() == 1, do nothing: Use previous system state
139 // as trial for the new state.
140
141 if (historySize() > 1) {
143
144 // Does the iterator allow a flexible unit cell ?
145 bool isFlexible = system().iterator().isFlexible();
146
147 // Compute coefficients of polynomial extrapolation to sNew
148 setCoefficients(sNew);
149
150 // Set extrapolated trial w fields
151 double coeff;
152 int nMonomer = system().mixture().nMonomer();
153 int nBasis = system().domain().basis().nBasis();
154 DArray<double>* newFieldPtr;
155 DArray<double>* oldFieldPtr;
156 int i, j, k;
157 for (i=0; i < nMonomer; ++i) {
158 newFieldPtr = &(trial_.field(i));
159
160 // Previous state k = 0 (most recent)
161 oldFieldPtr = &state(0).field(i);
162 coeff = c(0);
163 for (j=0; j < nBasis; ++j) {
164 (*newFieldPtr)[j] = coeff*(*oldFieldPtr)[j];
165 }
166
167 // Previous states k >= 1 (older)
168 for (k = 1; k < historySize(); ++k) {
169 oldFieldPtr = &state(k).field(i);
170 coeff = c(k);
171 for (j=0; j < nBasis; ++j) {
172 (*newFieldPtr)[j] += coeff*(*oldFieldPtr)[j];
173 }
174 }
175 }
176
177 // Make sure unitCellParameters_ is up to date with system
178 // (if we are sweeping in a lattice parameter, then the system
179 // parameters will be up-to-date but unitCellParameters_ wont be)
180 FSArray<double, 6> oldParameters = unitCellParameters_;
181 unitCellParameters_ = system().domain().unitCell().parameters();
182
183 // If isFlexible, then extrapolate the flexible unit cell parameters
184 if (isFlexible) {
185
186 double coeff;
187 double parameter;
188
189 #if 0
190 const FSArray<int,6> indices = system().iterator().flexibleParams();
191 const int nParameter = indices.size();
192
193 // Add contributions from all previous states
194 for (k = 0; k < historySize(); ++k) {
195 coeff = c(k);
196 for (int i = 0; i < nParameter; ++i) {
197 if (k == 0) {
198 unitCellParameters_[indices[i]] = 0;
199 }
200 parameter = state(k).unitCell().parameter(indices[i]);
201 unitCellParameters_[indices[i]] += coeff*parameter;
202 }
203 }
204 #endif
205
206 // Add contributions from all previous states
207 const int nParameter = unitCellParameters_.size();
208 for (k = 0; k < historySize(); ++k) {
209 coeff = c(k);
210 for (int i = 0; i < nParameter; ++i) {
211 if (k == 0) {
212 unitCellParameters_[i] = 0.0;
213 }
214 parameter = state(k).unitCell().parameter(i);
215 unitCellParameters_[i] += coeff*parameter;
216 }
217 }
218
219 }
220
221 // Reset trial_.unitCell() object
222 trial_.unitCell().setParameters(unitCellParameters_);
223
224 // Check if any unit cell parameters have changed
225 bool newCellParams(true);
226 for (int i = 0; i < oldParameters.size(); i++) {
227 if (fabs(oldParameters[i] - unitCellParameters_[i]) < 1e-10) {
228 newCellParams = false;
229 break;
230 }
231 }
232
233 // Transfer data from trial_ state to parent system
234 trial_.setSystemState(newCellParams);
235 }
236
237 };
238
239 /*
240 * Call current iterator to solve SCFT problem.
241 *
242 * Return 0 for sucessful solution, 1 on failure to converge.
243 */
244 template <int D>
245 int Sweep<D>::solve(bool isContinuation)
246 { return system().iterate(isContinuation); };
247
248 /*
249 * Reset system to previous solution after iterature failure.
250 *
251 * The implementation of this function should reset the system state
252 * to correspond to that stored in state(0).
253 */
254 template <int D>
256 {
257 bool isFlexible = system().iterator().isFlexible();
258 state(0).setSystemState(isFlexible);
259 }
260
261 /*
262 * Update state(0) and output data after successful convergence
263 *
264 * The implementation of this function should copy the current
265 * system state into state(0) and output any desired information
266 * about the current converged solution.
267 */
268 template <int D>
270 {
271 state(0).setSystem(system());
272 state(0).getSystemState();
273
274 // Output converged solution to several files
275 outputSolution();
276
277 // Output summary to log file
278 outputSummary(logFile_);
279
280 };
281
282 template <int D>
283 void Sweep<D>::outputSolution()
284 {
285 std::ofstream out;
286 std::string outFileName;
287 std::string indexString = toString(nAccept() - 1);
288
289 // Open parameter file, with thermodynamic properties at end
290 outFileName = baseFileName_;
291 outFileName += indexString;
292 outFileName += ".stt";
293 system().fileMaster().openOutputFile(outFileName, out);
294
295 // Write data file, with thermodynamic properties at end
296 system().writeParamNoSweep(out);
297 out << std::endl;
298 system().scft().write(out);
299 out.close();
300
301 // Write w fields
302 outFileName = baseFileName_;
303 outFileName += indexString;
304 outFileName += "_w";
305 if (system().w().isSymmetric()) {
306 outFileName += ".bf";
307 system().w().writeBasis(outFileName);
308 } else {
309 outFileName += ".rf";
310 system().w().writeRGrid(outFileName);
311 }
312
313 // Optionally write c rgrid files
314 if (writeCRGrid_) {
315 outFileName = baseFileName_;
316 outFileName += indexString;
317 outFileName += "_c";
318 outFileName += ".rf";
319 system().c().writeRGrid(outFileName);
320 }
321
322 // Optionally write c basis files
323 if (writeCBasis_ && system().c().isSymmetric()) {
324 outFileName = baseFileName_;
325 outFileName += indexString;
326 outFileName += "_c";
327 outFileName += ".bf";
328 system().c().writeBasis(outFileName);
329 }
330
331 // Optionally write w rgrid files
332 if (writeWRGrid_ && system().w().isSymmetric()) {
333 outFileName = baseFileName_;
334 outFileName += indexString;
335 outFileName += "_w";
336 outFileName += ".rf";
337 system().w().writeRGrid(outFileName);
338 }
339
340 }
341
342 template <int D>
343 void Sweep<D>::outputSummary(std::ostream& out)
344 {
345 int i = nAccept() - 1;
346 double sNew = s(0);
347 out << Int(i,5) << Dbl(sNew)
348 << Dbl(system().scft().fHelmholtz(),16)
349 << Dbl(system().scft().pressure(),16);
350 out << std::endl;
351 }
352
353 template <int D>
355 { logFile_.close(); }
356
357} // namespace Rpg
358} // namespace Pscf
359#endif
FieldState for fields in symmetry-adapted basis format.
virtual void getSolution()
Update state(0) and output data after successful convergence.
bool writeCBasis_
Whether to write concentration field files in basis format.
virtual int solve(bool isContinuation)
Call current iterator to solve SCFT problem.
virtual void readParameters(std::istream &in)
Read parameters from param file.
virtual void checkAllocation(BasisFieldState< D > &state)
Check allocation state of fields in one state, allocate if necessary.
virtual void extrapolate(double sNew)
Create a guess for adjustable variables by continuation.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
virtual void setup()
Setup operation at the beginning of a sweep.
bool writeWRGrid_
Whether to write real space potential field files.
bool writeCRGrid_
Whether to write real space concentration field files.
bool hasSystem()
Has an association with the parent System been set?
virtual void reset()
Reset system to previous solution after iterature failure.
virtual void setParameters(double sNew)=0
Set non-adjustable system parameters to new values.
Sweep()
Default Constructor.
System< D > & system()
Return the parent system by reference.
void setSystem(System< D > &system)
Set association with parent System.
virtual void cleanup()
Cleanup operation at the beginning of a sweep.
Main class, representing a complete physical system.
void addParameterTypes(GArray< ParameterType > paramTypes)
BasisFieldState< D > & state(int i)
Definition SweepTmpl.h:127
Dynamically allocatable contiguous array template.
Definition DArray.h:32
Wrapper for a double precision number, for formatted ostream output.
Definition Dbl.h:40
A fixed capacity (static) contiguous array with a variable logical size.
Definition FSArray.h:38
int size() const
Return logical size of this array (i.e., number of elements).
Definition FSArray.h:207
Wrapper for an int, for formatted ostream output.
Definition Int.h:37
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
std::string toString(int n)
Return string representation of an integer.
Definition ioUtil.cpp:52
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.