PSCF v1.4.0
Sweep.tpp
1#ifndef RP_SWEEP_TPP
2#define RP_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" // class template header
12
13#include <prdc/environment/Environment.h>
14#include <prdc/crystal/Basis.h>
15#include <prdc/crystal/UnitCell.h>
16#include <pscf/interaction/Interaction.h>
17#include <util/misc/FileMaster.h>
18#include <util/misc/ioUtil.h>
19
20#include <pscf/sweep/SweepTmpl.tpp> // base class template implementation
21
22namespace Pscf {
23namespace Rp {
24
25 using namespace Util;
26
27 // Maximum number of previous states = order of continuation + 1
28 #define RP_HISTORY_CAPACITY 3
29
30 /*
31 * Default constructor (for unit testing).
32 */
33 template <int D, class T>
35 : SweepTmplT(RP_HISTORY_CAPACITY),
36 writeCRGrid_(false),
37 writeCBasis_(false),
38 writeWRGrid_(false),
39 systemPtr_(nullptr)
40 {}
41
42 /*
43 * Constructor, creates association with parent system.
44 */
45 template <int D, class T>
46 Sweep<D,T>::Sweep(typename T::System & sys)
47 : SweepTmplT(RP_HISTORY_CAPACITY),
48 writeCRGrid_(false),
49 writeCBasis_(false),
50 writeWRGrid_(false),
51 systemPtr_(&sys)
52 {
53 // Get specialized sweep parameters from Environment
54 if (system().hasEnvironment()) {
56 system().environment().getParameterTypes());
57 }
58 }
59
60 /*
61 * Destructor.
62 */
63 template <int D, class T>
66
67 /*
68 * Set association with a parent system (for unit testing).
69 */
70 template <int D, class T>
71 void Sweep<D,T>::setSystem(typename T::System& system)
72 { systemPtr_ = &system; }
73
74 /*
75 * Read parameters.
76 */
77 template <int D, class T>
78 void Sweep<D,T>::readParameters(std::istream& in)
79 {
80 // Call the base class's readParameters function.
82
83 // Read optional flags indicating which field types to output
87 }
88
89 /*
90 * Check allocation of one state object, allocate if necessary.
91 */
92 template <int D, class T>
93 void Sweep<D,T>::checkAllocation(typename T::BasisFieldState& state)
94 {
96 state.setSystem(system());
97 state.allocate();
98 state.unitCell() = system().domain().unitCell();
99 }
100
101 /*
102 * Setup operations at the beginning of a sweep.
103 */
104 template <int D, class T>
106 {
108 checkAllocation(trial_);
109
110 // Open log summary file
111 std::string fileName = SweepTmplT::baseFileName_;
112 fileName += "sweep.log";
113 system().fileMaster().openOutputFile(fileName, logFile_);
114 logFile_ << " step ds free_energy pressure"
115 << std::endl;
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, class T>
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, class T>
134 void Sweep<D,T>::extrapolate(double sNew)
135 {
139 // If historySize == 1, do nothing: Use previous system state
140 // as trial for the new state.
141
142 if (historySize > 1) {
144
145 // Does the iterator allow a flexible unit cell ?
146 bool isFlexible = system().iterator().isFlexible();
147
148 // Compute coefficients of polynomial extrapolation to sNew
150
151 // Set extrapolated trial w fields
152 double coeff;
153 int nMonomer = system().mixture().nMonomer();
154 int nBasis = system().domain().basis().nBasis();
155 DArray<double>* newFieldPtr;
156 DArray<double>* oldFieldPtr;
157 int i, j, k;
158 for (i=0; i < nMonomer; ++i) {
159 newFieldPtr = &(trial_.field(i));
160
161 // Previous state k = 0 (most recent)
162 oldFieldPtr = &SweepTmplT::state(0).field(i);
163 coeff = SweepTmplT::c(0);
164 for (j=0; j < nBasis; ++j) {
165 (*newFieldPtr)[j] = coeff*(*oldFieldPtr)[j];
166 }
167
168 // Previous states k >= 1 (older)
169 for (k = 1; k < historySize; ++k) {
170 oldFieldPtr = &SweepTmplT::state(k).field(i);
171 coeff = SweepTmplT::c(k);
172 for (j=0; j < nBasis; ++j) {
173 (*newFieldPtr)[j] += coeff*(*oldFieldPtr)[j];
174 }
175 }
176 }
177
178 // Make sure unitCellParameters_ is up to date with system
179 // (if we are sweeping in a lattice parameter, then the system
180 // parameters will be up-to-date but unitCellParameters_ wont be)
181 FSArray<double, 6> oldParameters = unitCellParameters_;
182 unitCellParameters_ = system().domain().unitCell().parameters();
183
184 // If isFlexible, extrapolate the flexible unit cell parameters
185 if (isFlexible) {
186
187 double coeff;
188 double parameter;
189 const FSArray<bool,6> flexParams
190 = system().iterator().flexibleParams();
191 const int nParameter
192 = system().domain().unitCell().nParameter();
193 UTIL_CHECK(flexParams.size() == nParameter);
194
195 // Add contributions from all previous states
196 for (k = 0; k < historySize; ++k) {
197 coeff = SweepTmplT::c(k);
198 for (int i = 0; i < nParameter; ++i) {
199 if (flexParams[i]) {
200 if (k == 0) {
201 unitCellParameters_[i] = 0.0;
202 }
203 parameter
204 = SweepTmplT::state(k).unitCell().parameter(i);
205 unitCellParameters_[i] += coeff*parameter;
206 }
207 }
208 }
209
210 }
211
212 // Reset trial_.unitCell() object
213 trial_.unitCell().setParameters(unitCellParameters_);
214
215 // Check if any unit cell parameters have changed
216 bool newCellParams(true);
217 for (int i = 0; i < oldParameters.size(); i++) {
218 if (fabs(oldParameters[i] - unitCellParameters_[i]) < 1e-10) {
219 newCellParams = false;
220 break;
221 }
222 }
223
224 // Transfer data from trial_ state to parent system
225 trial_.setSystemState(newCellParams);
226 }
227
228 };
229
230 /*
231 * Call current iterator to solve SCFT problem.
232 *
233 * Return 0 for sucessful solution, 1 on failure to converge.
234 */
235 template <int D, class T>
236 int Sweep<D,T>::solve(bool isContinuation)
237 { return system().iterate(isContinuation); };
238
239 /*
240 * Reset system to previous solution after iterature failure.
241 *
242 * The implementation of this function should reset the system state
243 * to correspond to that stored in state(0).
244 */
245 template <int D, class T>
247 {
248 bool isFlexible = system().iterator().isFlexible();
249 SweepTmplT::state(0).setSystemState(isFlexible);
250 }
251
252 /*
253 * Update state(0) and output data after successful convergence
254 *
255 * The implementation of this function should copy the current
256 * system state into state(0) and output any desired information
257 * about the current converged solution.
258 */
259 template <int D, class T>
261 {
262 SweepTmplT::state(0).setSystem(system());
263 SweepTmplT::state(0).getSystemState();
264
265 // Output converged solution to several files
266 outputSolution();
267
268 // Output summary to log file
269 outputSummary(logFile_);
270
271 };
272
273 template <int D, class T>
274 void Sweep<D,T>::outputSolution()
275 {
276 std::ofstream out;
277 std::string outFileName;
278 std::string indexString = toString(SweepTmplT::nAccept() - 1);
279
280 // Open parameter file, with thermodynamic properties at end
281 outFileName = SweepTmplT::baseFileName_;
282 outFileName += indexString;
283 outFileName += ".stt";
284 system().fileMaster().openOutputFile(outFileName, out);
285
286 // Write data file, with thermodynamic properties at end
287 system().writeParamNoSweep(out);
288 out << std::endl;
289 system().scft().write(out);
290 out.close();
291
292 // Write w fields
293 UTIL_CHECK(system().w().hasData());
294 outFileName = SweepTmplT::baseFileName_;
295 outFileName += indexString;
296 outFileName += "_w";
297 if (system().w().isSymmetric()) {
298 outFileName += ".bf";
299 system().w().writeBasis(outFileName);
300 } else {
301 outFileName += ".rf";
302 system().w().writeRGrid(outFileName);
303 }
304
305 // Optionally write c rgrid files
306 if (writeCRGrid_) {
307 UTIL_CHECK(system().c().hasData());
308 outFileName = SweepTmplT::baseFileName_;
309 outFileName += indexString;
310 outFileName += "_c";
311 outFileName += ".rf";
312 system().c().writeRGrid(outFileName);
313 }
314
315 // Optionally write c basis files
316 if (writeCBasis_ && system().c().isSymmetric()) {
317 UTIL_CHECK(system().c().hasData());
318 outFileName = SweepTmplT::baseFileName_;
319 outFileName += indexString;
320 outFileName += "_c";
321 outFileName += ".bf";
322 system().c().writeBasis(outFileName);
323 }
324
325 // Optionally write w rgrid files
326 if (writeWRGrid_ && system().w().isSymmetric()) {
327 outFileName = SweepTmplT::baseFileName_;
328 outFileName += indexString;
329 outFileName += "_w";
330 outFileName += ".rf";
331 system().w().writeRGrid(outFileName);
332 }
333
334 }
335
336 template <int D, class T>
337 void Sweep<D,T>::outputSummary(std::ostream& out)
338 {
339 int i = SweepTmplT::nAccept() - 1;
340 double sNew = SweepTmplT::s(0);
341 if (!system().scft().hasData()) system().scft().compute();
342 out << Int(i,5) << Dbl(sNew)
343 << Dbl(system().scft().fHelmholtz(),16)
344 << Dbl(system().scft().pressure(),16);
345 out << std::endl;
346 }
347
348 template <int D, class T>
350 { logFile_.close(); }
351
352} // namespace Rp
353} // namespace Pscf
354#endif
bool writeWRGrid_
Should converged w fields be written to file in r-grid format?
Sweep()
Default constructor.
Definition Sweep.tpp:34
virtual void setup()
Setup operation at the beginning of a sweep.
Definition Sweep.tpp:105
bool hasSystem()
Does an association with the parent system exist?
void setSystem(typename T::System &system)
Set association with parent system.
Definition Sweep.tpp:71
virtual void getSolution()
Update state(0) and output data after successful convergence.
Definition Sweep.tpp:260
bool writeCRGrid_
Should concentration fields be written to file in r-grid format?
virtual void cleanup()
Cleanup operation at the beginning of a sweep.
Definition Sweep.tpp:349
virtual int solve(bool isContinuation)
Call current iterator to solve SCFT problem.
Definition Sweep.tpp:236
virtual void setParameters(double sNew)=0
Set system parameters to new values.
Definition Sweep.tpp:124
virtual void readParameters(std::istream &in)
Read parameters from param file.
Definition Sweep.tpp:78
bool writeCBasis_
Should concentration fields be written to file in basis format?
virtual void extrapolate(double sNew)
Create a guess for adjustable variables by continuation.
Definition Sweep.tpp:134
virtual void reset()
Reset system to previous solution after iterature failure.
Definition Sweep.tpp:246
~Sweep()
Destructor.
Definition Sweep.tpp:64
virtual void checkAllocation(typename T::BasisFieldState &state)
Check allocation of fields in one state, allocate if necessary.
Definition Sweep.tpp:93
void addParameterTypes(GArray< ParameterType > paramTypes)
Declare an array of specialized sweep parameter types.
T::BasisFieldState & state(int i)
Definition SweepTmpl.h:107
std::string baseFileName_
Base name for output files.
Definition SweepTmpl.h:297
double c(int i) const
Get a coefficient of a previous state in a continuation.
Definition SweepTmpl.h:147
void initialize()
Initialize variables that track history of solutions.
void setCoefficients(double sNew)
Compute coefficients of previous states for continuation.
virtual void readParameters(std::istream &in)
double s(int i) const
Get the value of s for a stored solution, with i = 0 most recent.
Definition SweepTmpl.h:122
int historyCapacity() const
Get the maximum number of stored previous states.
Definition SweepTmpl.h:168
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
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
#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
Class templates for real-valued periodic fields.
PSCF package top-level namespace.