PSCF v1.1
pspc/sweep/Sweep.tpp
1#ifndef PSPC_SWEEP_TPP
2/*
3* PSCF - Polymer Self-Consistent Field Theory
4*
5* Copyright 2016 - 2022, The Regents of the University of Minnesota
6* Distributed under the terms of the GNU General Public License.
7*/
8
9#include "Sweep.h"
10#include <pspc/System.h>
11#include <pscf/inter/Interaction.h>
12#include <pscf/sweep/SweepTmpl.tpp>
13#include <util/misc/FileMaster.h>
14#include <util/misc/ioUtil.h>
15
16namespace Pscf {
17namespace Pspc {
18
19 using namespace Util;
20
21 // Maximum number of previous states = order of continuation + 1
22 # define PSPC_HISTORY_CAPACITY 3
23
24 /*
25 * Default constructor (for unit testing).
26 */
27 template <int D>
29 : SweepTmpl< BasisFieldState<D> >(PSPC_HISTORY_CAPACITY),
30 writeCRGrid_(false),
31 writeCBasis_(false),
32 writeWRGrid_(false),
33 systemPtr_(0)
34 {}
35
36 /*
37 * Constructor, creates association with parent system.
38 */
39 template <int D>
41 : SweepTmpl< BasisFieldState<D> >(PSPC_HISTORY_CAPACITY),
42 writeCRGrid_(false),
43 writeCBasis_(false),
44 writeWRGrid_(false),
45 systemPtr_(&system)
46 {}
47
48 /*
49 * Destructor.
50 */
51 template <int D>
53 {}
54
55 /*
56 * Set association with a parent system (for unit testing).
57 */
58 template <int D>
60 { systemPtr_ = &system; }
61
62 /*
63 * Read parameters
64 */
65 template <int D>
66 void Sweep<D>::readParameters(std::istream& in)
67 {
68 // Call the base class's readParameters function.
69 SweepTmpl< BasisFieldState<D> >::readParameters(in);
70
71 // Read optional flags indicating which field types to output
72 readOptional(in, "writeCRGrid", writeCRGrid_);
73 readOptional(in, "writeCBasis", writeCBasis_);
74 readOptional(in, "writeWRGrid", writeWRGrid_);
75 }
76
77 /*
78 * Check allocation of one state object, allocate if necessary.
79 */
80 template <int D>
82 {
83 UTIL_CHECK(hasSystem());
84 state.setSystem(system());
85 state.allocate();
86 state.unitCell() = system().unitCell();
87 }
88
89 /*
90 * Setup operations at the beginning of a sweep.
91 */
92 template <int D>
94 {
95 initialize();
96 checkAllocation(trial_);
97
98 // Open log summary file
99 std::string fileName = baseFileName_;
100 fileName += "sweep.log";
101 system().fileMaster().openOutputFile(fileName, logFile_);
102 logFile_ << " step ds free_energy pressure"
103 << std::endl;
104 };
105
106 /*
107 * Set non-adjustable system parameters to new values.
108 *
109 * \param s path length coordinate, in range [0,1]
110 */
111 template <int D>
113 {
114 // Empty default implementation allows Sweep<D> to be compiled.
115 UTIL_THROW("Calling unimplemented function Sweep::setParameters");
116 };
117
118 /*
119 * Create guess for adjustable variables by polynomial extrapolation.
120 */
121 template <int D>
122 void Sweep<D>::extrapolate(double sNew)
123 {
124 UTIL_CHECK(historySize() > 0);
125
126 // If historySize() == 1, do nothing: Use previous system state
127 // as trial for the new state.
128
129 if (historySize() > 1) {
130 UTIL_CHECK(historySize() <= historyCapacity());
131
132 // Does the iterator allow a flexible unit cell ?
133 bool isFlexible = system().iterator().isFlexible();
134
135 // Compute coefficients of polynomial extrapolation to sNew
136 setCoefficients(sNew);
137
138 // Set extrapolated trial w fields
139 double coeff;
140 int nMonomer = system().mixture().nMonomer();
141 int nBasis = system().basis().nBasis();
142 DArray<double>* newFieldPtr;
143 DArray<double>* oldFieldPtr;
144 int i, j, k;
145 for (i=0; i < nMonomer; ++i) {
146 newFieldPtr = &(trial_.field(i));
147
148 // Previous state k = 0 (most recent)
149 oldFieldPtr = &state(0).field(i);
150 coeff = c(0);
151 for (j=0; j < nBasis; ++j) {
152 (*newFieldPtr)[j] = coeff*(*oldFieldPtr)[j];
153 }
154
155 // Previous states k >= 1 (older)
156 for (k = 1; k < historySize(); ++k) {
157 oldFieldPtr = &state(k).field(i);
158 coeff = c(k);
159 for (j=0; j < nBasis; ++j) {
160 (*newFieldPtr)[j] += coeff*(*oldFieldPtr)[j];
161 }
162 }
163 }
164
165 // Make sure unitCellParameters_ is up to date with system
166 // (if we are sweeping in a lattice parameter, then the system
167 // parameters will be up-to-date but unitCellParameters_ wont be)
168 FSArray<double, 6> oldParameters = unitCellParameters_;
169 unitCellParameters_ = system().unitCell().parameters();
170
171 // If isFlexible, then extrapolate the flexible unit cell parameters
172 if (isFlexible) {
173
174 double coeff;
175 double parameter;
176
177 const FSArray<bool,6> flexParams =
178 system().iterator().flexibleParams();
179 const int nParameter = system().unitCell().nParameter();
180 UTIL_CHECK(flexParams.size() == nParameter);
181
182 // Add contributions from all previous states
183 for (k = 0; k < historySize(); ++k) {
184 coeff = c(k);
185 for (int i = 0; i < nParameter; ++i) {
186 if (flexParams[i]) {
187 if (k == 0) {
188 unitCellParameters_[i] = 0;
189 }
190 parameter = state(k).unitCell().parameter(i);
191 unitCellParameters_[i] += coeff*parameter;
192 }
193 }
194 }
195 }
196
197 // Reset trial_.unitCell() object
198 trial_.unitCell().setParameters(unitCellParameters_);
199
200 // Check if any unit cell parameters have changed
201 bool newCellParams(true);
202 for (int i = 0; i < oldParameters.size(); i++) {
203 if (fabs(oldParameters[i] - unitCellParameters_[i]) < 1e-10) {
204 newCellParams = false;
205 break;
206 }
207 }
208
209 // Transfer data from trial_ state to parent system
210 trial_.setSystemState(newCellParams);
211 }
212
213
214 };
215
216 /*
217 * Call current iterator to solve SCFT problem.
218 *
219 * Return 0 for sucessful solution, 1 on failure to converge.
220 */
221 template <int D>
222 int Sweep<D>::solve(bool isContinuation)
223 { return system().iterate(isContinuation); };
224
225 /*
226 * Reset system to previous solution after iterature failure.
227 *
228 * The implementation of this function should reset the system state
229 * to correspond to that stored in state(0).
230 */
231 template <int D>
233 {
234 bool isFlexible = system().iterator().isFlexible();
235 state(0).setSystemState(isFlexible);
236 }
237
238 /*
239 * Update state(0) and output data after successful convergence
240 *
241 * The implementation of this function should copy the current
242 * system state into state(0) and output any desired information
243 * about the current converged solution.
244 */
245 template <int D>
247 {
248 state(0).setSystem(system());
249 state(0).getSystemState();
250
251 // Output converged solution to several files
252 outputSolution();
253
254 // Output summary to log file
255 outputSummary(logFile_);
256
257 };
258
259 template <int D>
261 {
262 std::ofstream out;
263 std::string outFileName;
264 std::string indexString = toString(nAccept() - 1);
265
266 // Open parameter file, with thermodynamic properties at end
267 outFileName = baseFileName_;
268 outFileName += indexString;
269 outFileName += ".stt";
270 system().fileMaster().openOutputFile(outFileName, out);
271
272 // Write data file, with thermodynamic properties at end
273 system().writeParamNoSweep(out);
274 out << std::endl;
275 system().writeThermo(out);
276 out.close();
277
278 // Write w fields
279 outFileName = baseFileName_;
280 outFileName += indexString;
281 outFileName += "_w";
282 outFileName += ".bf";
283 UTIL_CHECK(system().w().hasData());
284 UTIL_CHECK(system().w().isSymmetric());
285 system().fieldIo().writeFieldsBasis(outFileName,
286 system().w().basis(),
287 system().unitCell());
288
289 // Optionally write c rgrid files
290 if (writeCRGrid_) {
291 outFileName = baseFileName_;
292 outFileName += indexString;
293 outFileName += "_c";
294 outFileName += ".rf";
295 system().fieldIo().writeFieldsRGrid(outFileName,
296 system().c().rgrid(),
297 system().unitCell());
298 }
299
300 // Optionally write c basis files
301 if (writeCBasis_) {
302 outFileName = baseFileName_;
303 outFileName += indexString;
304 outFileName += "_c";
305 outFileName += ".bf";
306 UTIL_CHECK(system().hasCFields());
307 system().fieldIo().writeFieldsBasis(outFileName,
308 system().c().basis(),
309 system().unitCell());
310 }
311
312 // Optionally write w rgrid files
313 if (writeWRGrid_) {
314 outFileName = baseFileName_;
315 outFileName += indexString;
316 outFileName += "_w";
317 outFileName += ".rf";
318 system().fieldIo().writeFieldsRGrid(outFileName,
319 system().w().rgrid(),
320 system().unitCell());
321 }
322 }
323
324 template <int D>
325 void Sweep<D>::outputSummary(std::ostream& out)
326 {
327 int i = nAccept() - 1;
328 double sNew = s(0);
329 if (!system().hasFreeEnergy()) system().computeFreeEnergy();
330 out << Int(i,5) << Dbl(sNew)
331 << Dbl(system().fHelmholtz(),16)
332 << Dbl(system().pressure(),16);
333 out << std::endl;
334 }
335
336 template <int D>
338 { logFile_.close(); }
339
340} // namespace Pspc
341} // namespace Pscf
342#endif
FieldState for fields in symmetry-adapted basis format.
void allocate()
Allocate all fields.
const UnitCell< D > & unitCell() const
Get UnitCell (i.e., lattice type and parameters) by const reference.
void setSystem(System< D > &system)
Set association with System, after default construction.
Solve a sequence of problems along a line in parameter space.
virtual void setup()
Setup operation at the beginning of a sweep.
virtual int solve(bool isContinuation)
Call current iterator to solve SCFT problem.
void setSystem(System< D > &system)
Set association with parent System.
virtual void setParameters(double sNew)=0
Set non-adjustable system parameters to new values.
virtual void extrapolate(double sNew)
Create a guess for adjustable variables by continuation.
Sweep()
Default Constructor.
virtual void cleanup()
Cleanup operation at the beginning of a sweep.
virtual void reset()
Reset system to previous solution after iterature failure.
virtual void checkAllocation(BasisFieldState< D > &state)
Check allocation state of fields in one state, allocate if necessary.
virtual void getSolution()
Update state(0) and output data after successful convergence.
virtual void readParameters(std::istream &in)
Read parameters from param file.
Main class for SCFT simulation of one system.
Definition: pspc/System.h:76
Solve a sequence of problems along a path through parameter space.
Definition: SweepTmpl.h:24
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:51
std::string toString(int n)
Return string representation of an integer.
Definition: ioUtil.cpp:52
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1