PSCF v1.1
pspg/sweep/Sweep.tpp
1#ifndef PSPG_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 <pscf/sweep/SweepTmpl.tpp>
11#include <pspg/System.h>
12#include <pspg/iterator/Iterator.h>
13#include <pscf/inter/Interaction.h>
14
15#include <util/misc/FileMaster.h>
16#include <util/misc/ioUtil.h>
17
18namespace Pscf {
19namespace Pspg {
20
21 using namespace Util;
22
23 // Maximum number of previous states = order of continuation + 1
24 #define PSPG_HISTORY_CAPACITY 3
25
26 /*
27 * Default constructor.
28 */
29 template <int D>
31 : SweepTmpl< BasisFieldState<D> >(PSPG_HISTORY_CAPACITY),
32 writeCRGrid_(false),
33 writeCBasis_(false),
34 writeWRGrid_(false),
35 systemPtr_(0)
36 {}
37
38 /*
39 * Constructor, creates association with parent system.
40 */
41 template <int D>
43 : SweepTmpl< BasisFieldState<D> >(PSPG_HISTORY_CAPACITY),
44 writeCRGrid_(false),
45 writeCBasis_(false),
46 writeWRGrid_(false),
47 systemPtr_(&system)
48 {}
49
50 /*
51 * Destructor.
52 */
53 template <int D>
55 {}
56
57 /*
58 * Set association with a parent system.
59 */
60 template <int D>
62 { systemPtr_ = &system; }
63
64 /*
65 * Read parameters
66 */
67 template <int D>
68 void Sweep<D>::readParameters(std::istream& in)
69 {
70 // Call the base class's readParameters function.
71 SweepTmpl< BasisFieldState<D> >::readParameters(in);
72
73 // Read optional flags indicating which field types to output
74 readOptional(in, "writeCRGrid", writeCRGrid_);
75 readOptional(in, "writeCBasis", writeCBasis_);
76 readOptional(in, "writeWRGrid", writeWRGrid_);
77 }
78
79 /*
80 * Check allocation of one state object, allocate if necessary.
81 */
82 template <int D>
84 {
85 UTIL_CHECK(hasSystem());
86 state.setSystem(system());
87 state.allocate();
88 state.unitCell() = system().unitCell();
89 }
90
91 /*
92 * Setup operations at the beginning of a sweep.
93 */
94 template <int D>
96 {
97 initialize();
98 checkAllocation(trial_);
99
100 // Open log summary file
101 std::string fileName = baseFileName_;
102 fileName += "sweep.log";
103 system().fileMaster().openOutputFile(fileName, logFile_);
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 #if 0
178 const FSArray<int,6> indices = system().iterator().flexibleParams();
179 const int nParameter = indices.size();
180
181 // Add contributions from all previous states
182 for (k = 0; k < historySize(); ++k) {
183 coeff = c(k);
184 for (int i = 0; i < nParameter; ++i) {
185 if (k == 0) {
186 unitCellParameters_[indices[i]] = 0;
187 }
188 parameter = state(k).unitCell().parameter(indices[i]);
189 unitCellParameters_[indices[i]] += coeff*parameter;
190 }
191 }
192 #endif
193
194 // Add contributions from all previous states
195 const int nParameter = unitCellParameters_.size();
196 for (k = 0; k < historySize(); ++k) {
197 coeff = c(k);
198 for (int i = 0; i < nParameter; ++i) {
199 if (k == 0) {
200 unitCellParameters_[i] = 0.0;
201 }
202 parameter = state(k).unitCell().parameter(i);
203 unitCellParameters_[i] += coeff*parameter;
204 }
205 }
206
207 }
208
209 // Reset trial_.unitCell() object
210 trial_.unitCell().setParameters(unitCellParameters_);
211
212 // Check if any unit cell parameters have changed
213 bool newCellParams(true);
214 for (int i = 0; i < oldParameters.size(); i++) {
215 if (fabs(oldParameters[i] - unitCellParameters_[i]) < 1e-10) {
216 newCellParams = false;
217 break;
218 }
219 }
220
221 // Transfer data from trial_ state to parent system
222 trial_.setSystemState(newCellParams);
223 }
224
225 };
226
227 /*
228 * Call current iterator to solve SCFT problem.
229 *
230 * Return 0 for sucessful solution, 1 on failure to converge.
231 */
232 template <int D>
233 int Sweep<D>::solve(bool isContinuation)
234 { return system().iterate(isContinuation); };
235
236 /*
237 * Reset system to previous solution after iterature failure.
238 *
239 * The implementation of this function should reset the system state
240 * to correspond to that stored in state(0).
241 */
242 template <int D>
244 {
245 bool isFlexible = system().iterator().isFlexible();
246 state(0).setSystemState(isFlexible);
247 }
248
249 /*
250 * Update state(0) and output data after successful convergence
251 *
252 * The implementation of this function should copy the current
253 * system state into state(0) and output any desired information
254 * about the current converged solution.
255 */
256 template <int D>
258 {
259 state(0).setSystem(system());
260 state(0).getSystemState();
261
262 // Output converged solution to several files
263 outputSolution();
264
265 // Output summary to log file
266 outputSummary(logFile_);
267
268 };
269
270 template <int D>
272 {
273 std::ofstream out;
274 std::string outFileName;
275 std::string indexString = toString(nAccept() - 1);
276
277 // Open parameter file, with thermodynamic properties at end
278 outFileName = baseFileName_;
279 outFileName += indexString;
280 outFileName += ".stt";
281 system().fileMaster().openOutputFile(outFileName, out);
282
283 // Write data file, with thermodynamic properties at end
284 out << "System{" << std::endl;
285 system().mixture().writeParam(out);
286 system().interaction().writeParam(out);
287 out << "}" << std::endl;
288 out << std::endl;
289 out << "unitCell " << system().unitCell();
290 system().writeThermo(out);
291 out.close();
292
293 // Write w fields
294 outFileName = baseFileName_;
295 outFileName += indexString;
296 outFileName += "_w";
297 outFileName += ".bf";
298 system().writeWBasis(outFileName);
299
300 // Optionally write c rgrid files
301 if (writeCRGrid_) {
302 outFileName = baseFileName_;
303 outFileName += indexString;
304 outFileName += "_c";
305 outFileName += ".rf";
306 system().writeCRGrid(outFileName);
307 }
308
309 // Optionally write c basis files
310 if (writeCBasis_) {
311 outFileName = baseFileName_;
312 outFileName += indexString;
313 outFileName += "_c";
314 outFileName += ".bf";
315 system().writeCBasis(outFileName);
316 }
317
318 // Optionally write w rgrid files
319 if (writeWRGrid_) {
320 outFileName = baseFileName_;
321 outFileName += indexString;
322 outFileName += "_w";
323 outFileName += ".rf";
324 system().writeWRGrid(outFileName);
325 }
326 }
327
328 template <int D>
329 void Sweep<D>::outputSummary(std::ostream& out)
330 {
331 int i = nAccept() - 1;
332 double sNew = s(0);
333 out << Int(i,5) << Dbl(sNew)
334 << Dbl(system().fHelmholtz(),16)
335 << Dbl(system().pressure(),16);
336 out << std::endl;
337 }
338
339 template <int D>
341 { logFile_.close(); }
342
343} // namespace Pspg
344} // namespace Pscf
345#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 getSolution()
Update state(0) and output data after successful convergence.
virtual void setParameters(double sNew)=0
Set non-adjustable system parameters to new values.
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 setup()
Setup operation at the beginning of a sweep.
virtual void checkAllocation(BasisFieldState< D > &state)
Check allocation state of fields in one state, allocate if necessary.
virtual void reset()
Reset system to previous solution after iterature failure.
virtual void cleanup()
Cleanup operation at the beginning of a sweep.
void setSystem(System< D > &system)
Set association with parent System.
Sweep()
Default Constructor.
virtual void extrapolate(double sNew)
Create a guess for adjustable variables by continuation.
Main class in SCFT simulation of one system.
Definition: pspg/System.h:71
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