PSCF v1.1
fd1d/sweep/Sweep.cpp
1/*
2* PSCF - Polymer Self-Consistent Field Theory
3*
4* Copyright 2016 - 2022, The Regents of the University of Minnesota
5* Distributed under the terms of the GNU General Public License.
6*/
7
8#include "Sweep.h"
9//#include <pscf/sweep/SweepTmpl.h>
10#include <fd1d/System.h>
11#include <fd1d/domain/Domain.h>
12#include <fd1d/solvers/Mixture.h>
13#include <fd1d/iterator/Iterator.h>
14#include <util/misc/ioUtil.h>
15#include <util/format/Int.h>
16#include <util/format/Dbl.h>
17
18namespace Pscf {
19namespace Fd1d
20{
21
22 using namespace Util;
23
24 // Define maximum number of stored states = order of continuation + 1
25 #define FD1D_HISTORY_CAPACITY 3
26
27 /*
28 * Constructor.
29 */
31 : Base(FD1D_HISTORY_CAPACITY),
32 SystemAccess(system),
33 homogeneousMode_(-1),
34 comparison_(system),
35 fieldIo_()
36 {
37 setClassName("Sweep");
39 }
40
41 /*
42 * Destructor.
43 */
45 {}
46
47 /*
48 * Read parameters.
49 */
50 void Sweep::readParameters(std::istream& in)
51 {
53 homogeneousMode_ = -1; // default value
54 readOptional<int>(in, "homogeneousMode", homogeneousMode_);
55 }
56
57 /*
58 * Check allocation of a state, allocate if necessary.
59 */
61 {
62 int nm = mixture().nMonomer();
63 int nx = domain().nx();
64 UTIL_CHECK(nm > 0);
65 UTIL_CHECK(nx > 0);
66
67 if (state.isAllocated()) {
68 UTIL_CHECK(state.capacity() == nm);
69 } else {
70 state.allocate(nm);
71 }
72 for (int j = 0; j < nm; ++j) {
73 if (state[j].isAllocated()) {
74 UTIL_CHECK(state[j].capacity() == nx);
75 } else {
76 state[j].allocate(nx);
77 }
78 }
79
80 };
81
82 /*
83 * Setup operation at beginning sweep.
84 *
85 * Must call initializeHistory.
86 */
88 {
89 // Initialize history
90 initialize();
91
92 // Open log summary file
93 std::string fileName = baseFileName_;
94 fileName += "log";
95 fileMaster().openOutputFile(fileName, logFile_);
96
97 };
98
99 /*
100 * Set non-adjustable system parameters to new values.
101 *
102 * \param s path length coordinate, in range [0,1]
103 */
104 void Sweep::setParameters(double s)
105 {
106 UTIL_THROW("Called un-implemented Fd1d::Sweep::setParameters");
107 };
108
109 /*
110 * Create guess for adjustable variables by polynomial extrapolation.
111 */
112 void Sweep::extrapolate(double sNew)
113 {
114 int nm = mixture().nMonomer();
115 int nx = domain().nx();
116 UTIL_CHECK(nm > 0);
117 UTIL_CHECK(nx > 0);
118
119 if (historySize() > 1) {
120
121 // Compute an array of coefficients for polynomial extrapolation
122 setCoefficients(sNew);
123
124 // Set System::wField to a linear combination of previous values
125 // Note: wField(i) is accessed through SystemAccess base class.
126 double coeff;
127 int i, j, k;
128 for (i = 0; i < nm; ++i) {
129 coeff = c(0);
130 for (j = 0; j < nx; ++j) {
131 wField(i)[j] = coeff*state(0)[i][j];
132 }
133 for (k = 1; k < historySize(); ++k) {
134 coeff = c(k);
135 for (j = 0; j < nx; ++j) {
136 wField(i)[j] += coeff*state(k)[i][j];
137 }
138 }
139 }
140 }
141 };
142
148 int Sweep::solve(bool isContinuation)
149 { return system().iterate(isContinuation); };
150
158 { assignFields(wFields(), state(0)); };
159
168 {
169 // Assign current wFields to state(0)
170 assignFields(state(0), wFields());
171
172 if (homogeneousMode_ >= 0) {
173 comparison_.compute(homogeneousMode_);
174 }
175
176 // Output solution
177 int i = nAccept() - 1;
178 std::string fileName = baseFileName_;
179 fileName += toString(i);
180 outputSolution(fileName);
181
182 // Output brief summary to log file
183 outputSummary(logFile_);
184 };
185
186 void Sweep::outputSolution(std::string const & fileName)
187 {
188 std::ofstream out;
189 std::string outFileName;
190
191 // Write parameter file, with thermodynamic properties at end
192 outFileName = fileName;
193 outFileName += ".stt";
194 fileMaster().openOutputFile(outFileName, out);
195 system().writeParam(out);
196 out << std::endl;
197 system().writeThermo(out);
198
199 if (homogeneousMode_ >= 0) {
200 comparison_.output(homogeneousMode_, out);
201 }
202 out.close();
203
204 // Write concentration fields
205 outFileName = fileName;
206 outFileName += ".c";
207 fieldIo_.writeFields(cFields(), outFileName);
208
209 // Write chemical potential fields
210 outFileName = fileName;
211 outFileName += ".w";
212 fieldIo_.writeFields(wFields(), outFileName);
213 }
214
215 void Sweep::outputSummary(std::ostream& out)
216 {
217 int i = nAccept() - 1;
218 double sNew = s(0);
219 out << Int(i,5) << Dbl(sNew)
220 << Dbl(system().fHelmholtz(),16)
221 << Dbl(system().pressure(),16);
222 #if 0
223 if (homogeneousMode_ != -1) {
224 if (homogeneousMode_ == 0) {
225 double dF = system().fHelmholtz()
227 out << Dbl(dF, 16);
228 } else {
229 double dP = system().pressure()
231 double dOmega = -1.0*dP*domain().volume();
232 out << Dbl(dOmega, 16);
233 }
234 }
235 #endif
236 out << std::endl;
237 }
238
240 { logFile_.close(); }
241
242 void Sweep::assignFields(DArray<System::Field>& lhs,
243 DArray<System::Field> const & rhs) const
244 {
245
246 int nm = mixture().nMonomer();
247 int nx = domain().nx();
248
249 UTIL_CHECK(lhs.capacity() == nm);
250 UTIL_CHECK(rhs.capacity() == nm);
251 int i, j;
252 for (i = 0; i < nm; ++i) {
253 UTIL_CHECK(rhs[i].isAllocated());
254 UTIL_CHECK(rhs[i].capacity() == nx);
255 UTIL_CHECK(lhs[i].isAllocated());
256 UTIL_CHECK(lhs[i].capacity() == nx);
257 for (j = 0; j < nx; ++j) {
258 lhs[i][j] = rhs[i][j];
259 }
260 }
261 }
262
263} // namespace Fd1d
264} // namespace Pscf
int nx() const
Get number of spatial grid points, including both endpoints.
double volume() const
Get generalized volume of domain.
void associate(Domain const &domain, FileMaster const &fileMaster)
Get and store addresses of associated objects.
void writeFields(DArray< Field > const &fields, std::ostream &out, bool writeHeader=true)
Write a set of fields, one per monomer type, to an output stream.
void compute(int mode)
Compute properties of a homogeneous reference system.
void output(int mode, std::ostream &out)
Output comparison to a homogeneous reference system.
virtual void outputSolution(std::string const &stateFileName)
Output information after obtaining a converged solution.
virtual void outputSummary(std::ostream &outFile)
Output data to a running summary.
virtual int solve(bool isContinuation)
Call the current iterator to solve one SCFT problem.
virtual void readParameters(std::istream &in)
Read ns and baseFileName parameters.
int homogeneousMode_
Mode for comparison to homogeneous system (none -> -1)
virtual void reset()
Reset system to previous solution after iterature failure.
virtual void cleanup()
Close log file after end of sweep.
virtual void checkAllocation(State &state)
Check allocation of w fields in one state, allocate if needed.
Sweep(System &system)
Constructor.
virtual void setParameters(double s)
Set non-adjustable system parameters to new values.
virtual void extrapolate(double s)
Create initial guess for new w fields by polynomial extrapolation.
virtual void getSolution()
Update state(0) and output data after successful convergence.
virtual void setup()
Setup operation at beginning sweep.
Concise accesss to an associated System.
Definition: SystemAccess.h:28
DArray< System::CField > & cFields()
Get array of all chemical potential fields.
Definition: SystemAccess.h:270
System::WField & wField(int monomerId)
Get chemical potential field for a specific monomer type.
Definition: SystemAccess.h:260
const Domain & domain() const
Get spatial domain (including grid info) by reference.
Definition: SystemAccess.h:194
const System & system() const
Get parent System by reference.
Definition: SystemAccess.h:158
const Mixture & mixture() const
Get Mixture by reference.
Definition: SystemAccess.h:176
FileMaster & fileMaster()
Get FileMaster by reference.
Definition: SystemAccess.h:230
DArray< System::WField > & wFields()
Get array of all chemical potential fields.
Definition: SystemAccess.h:250
Main class in SCFT simulation of one system.
Definition: fd1d/System.h:63
void writeThermo(std::ostream &out)
Write thermodynamic properties to a file.
int iterate(bool isContinuation=false)
Iteratively solve a SCFT problem.
Homogeneous::Mixture & homogeneous()
Get homogeneous mixture (for reference calculations).
Definition: fd1d/System.h:574
Domain & domain()
Get spatial domain (including grid info) by reference.
Definition: fd1d/System.h:567
double fHelmholtz() const
Get precomputed Helmholtz free energy per monomer / kT.
Definition: fd1d/System.h:622
double pressure() const
Get precomputed pressure x monomer volume kT.
Definition: fd1d/System.h:628
FileMaster & fileMaster()
Get FileMaster by reference.
Definition: fd1d/System.h:589
double pressure() const
Return pressure in units of kT / monomer volume.
double fHelmholtz() const
Return Helmholtz free energy per monomer / kT.
int nMonomer() const
Get number of monomer types.
Definition: MixtureTmpl.h:190
Solve a sequence of problems along a path through parameter space.
Definition: SweepTmpl.h:24
int historySize() const
Get the current number of stored previous states.
Definition: SweepTmpl.h:125
DArray< System::WField > & state(int i)
Get reference to a stored state, with i=0 being most recent.
Definition: SweepTmpl.h:75
std::string baseFileName_
Base name for output files.
Definition: SweepTmpl.h:53
double c(int i) const
Get a coefficient of a previous state in a continuation.
Definition: SweepTmpl.h:115
void initialize()
Initialize variables that track history of solutions.
Definition: SweepTmpl.tpp:153
int nAccept() const
Get the number of converged solutions accepted thus far.
Definition: SweepTmpl.h:146
void setCoefficients(double sNew)
Compute coefficients of previous states for continuation.
Definition: SweepTmpl.tpp:206
virtual void readParameters(std::istream &in)
Read ns and baseFileName parameters.
Definition: SweepTmpl.tpp:42
double s(int i) const
Get the value of s for a stored solution, with i = 0 most recent.
Definition: SweepTmpl.h:90
int capacity() const
Return allocated size.
Definition: Array.h:159
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:199
bool isAllocated() const
Return true if this DArray has been allocated, false otherwise.
Definition: DArray.h:247
Wrapper for a double precision number, for formatted ostream output.
Definition: Dbl.h:40
void openOutputFile(const std::string &filename, std::ofstream &out, std::ios_base::openmode mode=std::ios_base::out) const
Open an output file.
Definition: FileMaster.cpp:290
Wrapper for an int, for formatted ostream output.
Definition: Int.h:37
void setClassName(const char *className)
Set class name string.
virtual void writeParam(std::ostream &out) const
Write all parameters to an output stream.
#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