PSCF v1.1
SweepTmpl.tpp
1#ifndef PSCF_SWEEP_TMPL_TPP
2#define PSCF_SWEEP_TMPL_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field Theory
6*
7* Copyright 2016 - 2022, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "SweepTmpl.h"
12#include <util/misc/Log.h>
13
14namespace Pscf {
15
16 using namespace Util;
17
18 /*
19 * Constructor
20 */
21 template <class State>
22 SweepTmpl<State>::SweepTmpl(int historyCapacity)
23 : ns_(0),
24 baseFileName_(),
25 historyCapacity_(historyCapacity),
26 historySize_(0),
27 nAccept_(0),
28 reuseState_(true)
29 { setClassName("SweepTmpl"); }
30
31 /*
32 * Destructor.
33 */
34 template <class State>
36 {}
37
38 /*
39 * Read parameters.
40 */
41 template <class State>
42 void SweepTmpl<State>::readParameters(std::istream& in)
43 {
44 // Default values
45 baseFileName_ = "";
46
47 // Read parameters
48 read<int>(in, "ns", ns_);
49 readOptional<std::string>(in, "baseFileName", baseFileName_);
50 readOptional<int>(in, "historyCapacity", historyCapacity_);
51 readOptional<bool>(in, "reuseState", reuseState_);
52
53 // Allocate required arrays
54 UTIL_CHECK(historyCapacity_ > 0);
55 states_.allocate(historyCapacity_);
56 stateHistory_.allocate(historyCapacity_);
57 sHistory_.allocate(historyCapacity_);
58 c_.allocate(historyCapacity_);
59 }
60
61 template <class State>
63 {
64
65 // Compute and output ds
66 double ds = 1.0/double(ns_);
67 double ds0 = ds;
68 Log::file() << std::endl;
69 Log::file() << "ns = " << ns_ << std::endl;
70 Log::file() << "ds = " << ds << std::endl;
71
72 // Initial setup, before a sweep
73 setup();
74
75 // Solve for initial state of sweep
76 double sNew = 0.0;
77 Log::file() << std::endl;
78 Log::file() << "===========================================\n";
79 Log::file() << "Attempt s = " << sNew << std::endl;
80
81 int error;
82 bool isContinuation = false; // False on first step
83 error = solve(isContinuation);
84
85 if (error) {
86 UTIL_THROW("Failure to converge initial state of sweep");
87 } else {
88 accept(sNew);
89 }
90
91 // Loop over states on path
92 bool finished = false; // Are we finished with the loop?
93 while (!finished) {
94
95 // Loop over iteration attempts, with decreasing ds as needed
96 error = 1;
97 while (error) {
98
99 // Set a new contour variable value sNew
100 sNew = s(0) + ds;
101 Log::file() << std::endl;
102 Log::file() << "===========================================\n";
103 Log::file() << "Attempt s = " << sNew << std::endl;
104
105 // Set non-adjustable system parameters to new values
106 setParameters(sNew);
107
108 // Guess new state variables by polynomial extrapolation.
109 // This function must both compute the extrapolation and
110 // set initial guess values in the parent system.
111 extrapolate(sNew);
112
113 // Attempt iterative SCFT solution
114 isContinuation = reuseState_;
115 error = solve(isContinuation);
116
117 // Process success or failure
118 if (error) {
119 Log::file() << "Backtrack and halve sweep step size:"
120 << std::endl;
121
122 // Upon failure, reset state to last converged solution
123 reset();
124
125 // Decrease ds by half
126 ds *= 0.50;
127 if (ds < 0.1*ds0) {
128 UTIL_THROW("Sweep decreased ds too many times.");
129 }
130
131 } else {
132
133 // Upon successful convergence, update history and nAccept
134 accept(sNew);
135
136 }
137 }
138 if (sNew + ds > 1.0000001) {
139 finished = true;
140 }
141 }
142 Log::file() << "===========================================\n";
143
144 // Clean up after end of the entire sweep
145 cleanup();
146
147 }
148
149 /*
150 * Initialize history variables (must be called by setup function).
151 */
152 template <class State>
155 UTIL_CHECK(historyCapacity_ > 1);
156 UTIL_CHECK(states_.capacity() == historyCapacity_);
157 UTIL_CHECK(sHistory_.capacity() == historyCapacity_);
158 UTIL_CHECK(stateHistory_.capacity() == historyCapacity_);
159
160 // Check allocation of all states, allocate if necessary
161 for (int i = 0; i < historyCapacity_; ++i) {
162 checkAllocation(states_[i]);
163 }
164
165 // Set pointers in stateHistory_ to refer to objects in array states_
166 nAccept_ = 0;
167 historySize_ = 0;
168 for (int i = 0; i < historyCapacity_; ++i) {
169 sHistory_[i] = 0.0;
170 stateHistory_[i] = &states_[i];
171 }
172 }
173
174 template <class State>
175 void SweepTmpl<State>::accept(double sNew)
176 {
177
178 // Shift elements of sHistory_
179 for (int i = historyCapacity_ - 1; i > 0; --i) {
180 sHistory_[i] = sHistory_[i-1];
181 }
182 sHistory_[0] = sNew;
183
184 // Shift elements of stateHistory_ (pointers to stored solutions)
185 State* temp;
186 temp = stateHistory_[historyCapacity_-1];
187 for (int i = historyCapacity_ - 1; i > 0; --i) {
188 stateHistory_[i] = stateHistory_[i-1];
189 }
190 stateHistory_[0] = temp;
191
192 // Update counters nAccept_ and historySize_
193 ++nAccept_;
194 if (historySize_ < historyCapacity_) {
195 ++historySize_;
196 }
197
198 // Call getSolution to copy system state to state(0).
199 getSolution();
200 }
201
202 /*
203 * Use Lagrange polynomials to compute coefficients for continuation.
204 */
205 template <class State>
207 {
208 UTIL_CHECK(historySize_ <= historyCapacity_);
209 if (historySize_ == 1) {
210 c_[0] = 1.0;
211 } else {
212 double num, den;
213 int i, j;
214 for (i = 0; i < historySize_; ++i) {
215 num = 1.0;
216 den = 1.0;
217 for (j = 0; j < historySize_; ++j) {
218 if (j != i) {
219 num *= (sNew - s(j));
220 den *= (s(i) - s(j));
221 }
222 }
223 c_[i] = num/den;
225 }
226 // Theory: The coefficient c_[i] is a Lagrange polynomial
227 // function c_[i](sNew) of sNew that is defined such that
228 // c_[i](s(i)) = 1 and c_[i](s(j)) = 0 for any j != i.
229 // Given a set of values y(i) previously obtained at contour
230 // variable values s(i) for all 0 <= i < historySize_, a
231 // linear combination f(sNew) = \sum_i c_[i](sNew)*y(i) summed
232 // over i = 0, ..., historySize_ - 1 gives a polynomial in
233 // sNew that passes through all previous values, such that
234 // f(sNew) = y(i) for sNew = s(i).
235 }
236
237 /*
238 * Clean up after the end of a sweep (empty default implementation).
239 */
240 template <class State>
242 {}
243
244} // namespace Pscf
245#endif
Solve a sequence of problems along a path through parameter space.
Definition: SweepTmpl.h:24
~SweepTmpl()
Destructor.
Definition: SweepTmpl.tpp:35
virtual void cleanup()
Clean up operation at the end of a sweep.
Definition: SweepTmpl.tpp:241
void initialize()
Initialize variables that track history of solutions.
Definition: SweepTmpl.tpp:153
void setCoefficients(double sNew)
Compute coefficients of previous states for continuation.
Definition: SweepTmpl.tpp:206
virtual void sweep()
Iterate to solution.
Definition: SweepTmpl.tpp:62
virtual void readParameters(std::istream &in)
Read ns and baseFileName parameters.
Definition: SweepTmpl.tpp:42
static std::ostream & file()
Get log ostream by reference.
Definition: Log.cpp:57
void setClassName(const char *className)
Set class name string.
#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
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1