PSCF v1.3
r1d/sweep/Sweep.cpp
1/*
2* PSCF - Polymer Self-Consistent Field
3*
4* Copyright 2015 - 2025, 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 <r1d/System.h>
11#include <r1d/domain/Domain.h>
12#include <r1d/solvers/Mixture.h>
13#include <r1d/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 R1d
20{
21
22 using namespace Util;
23
24 // Define maximum number of stored states = order of continuation + 1
25 #define R1D_HISTORY_CAPACITY 3
26
27 /*
28 * Constructor.
29 */
31 : Base(R1D_HISTORY_CAPACITY),
32 SystemAccess(sys),
34 comparison_(sys),
35 fieldIo_()
36 {
37 setClassName("Sweep");
38 fieldIo_.associate(sys.domain(), sys.fileMaster());
39
40 addParameterTypes(system().iterator().getParameterTypes());
41 }
42
43 /*
44 * Destructor.
45 */
48
49 /*
50 * Read parameters.
51 */
52 void Sweep::readParameters(std::istream& in)
53 {
55 homogeneousMode_ = -1; // default value
56 readOptional<int>(in, "homogeneousMode", homogeneousMode_);
57 }
58
59 /*
60 * Check allocation of a state, allocate if necessary.
61 */
62 void Sweep::checkAllocation(Sweep::State& state)
63 {
64 int nm = mixture().nMonomer();
65 int nx = domain().nx();
66 UTIL_CHECK(nm > 0);
67 UTIL_CHECK(nx > 0);
68
69 if (state.isAllocated()) {
70 UTIL_CHECK(state.capacity() == nm);
71 } else {
72 state.allocate(nm);
73 }
74 for (int j = 0; j < nm; ++j) {
75 if (state[j].isAllocated()) {
76 UTIL_CHECK(state[j].capacity() == nx);
77 } else {
78 state[j].allocate(nx);
79 }
80 }
81
82 };
83
84 /*
85 * Setup operation at beginning sweep.
86 *
87 * Must call initializeHistory.
88 */
90 {
91 // Initialize history
92 initialize();
93
94 // Open log summary file
95 std::string fileName = baseFileName_;
96 fileName += "log";
97 fileMaster().openOutputFile(fileName, logFile_);
98
99 };
100
101 /*
102 * Set non-adjustable system parameters to new values.
103 *
104 * \param s path length coordinate, in range [0,1]
105 */
107 {
108 UTIL_THROW("Called un-implemented R1d::Sweep::setParameters");
109 };
110
111 /*
112 * Create guess for adjustable variables by polynomial extrapolation.
113 */
114 void Sweep::extrapolate(double sNew)
115 {
116 int nm = mixture().nMonomer();
117 int nx = domain().nx();
118 UTIL_CHECK(nm > 0);
119 UTIL_CHECK(nx > 0);
120
121 if (historySize() > 1) {
122
123 // Compute an array of coefficients for polynomial extrapolation
124 setCoefficients(sNew);
125
126 // Set System::wField to a linear combination of previous values
127 // Note: wField(i) is accessed through SystemAccess base class.
128 double coeff;
129 int i, j, k;
130 for (i = 0; i < nm; ++i) {
131 coeff = c(0);
132 for (j = 0; j < nx; ++j) {
133 wField(i)[j] = coeff*state(0)[i][j];
134 }
135 for (k = 1; k < historySize(); ++k) {
136 coeff = c(k);
137 for (j = 0; j < nx; ++j) {
138 wField(i)[j] += coeff*state(k)[i][j];
139 }
140 }
141 }
142 }
143 };
144
150 int Sweep::solve(bool isContinuation)
151 { return system().iterate(isContinuation); };
152
160 { assignFields(wFields(), state(0)); };
161
170 {
171 // Assign current wFields to state(0)
172 assignFields(state(0), wFields());
173
174 if (homogeneousMode_ >= 0) {
175 comparison_.compute(homogeneousMode_);
176 }
177
178 // Output solution
179 int i = nAccept() - 1;
180 std::string fileName = baseFileName_;
181 fileName += toString(i);
182 outputSolution(fileName);
183
184 // Output brief summary to log file
185 outputSummary(logFile_);
186 };
187
188 void Sweep::outputSolution(std::string const & fileName)
189 {
190 std::ofstream out;
191 std::string outFileName;
192
193 // Write parameter file, with thermodynamic properties at end
194 outFileName = fileName;
195 outFileName += ".stt";
196 fileMaster().openOutputFile(outFileName, out);
197 system().writeParam(out);
198 out << std::endl;
199 system().writeThermo(out);
200
201 if (homogeneousMode_ >= 0) {
202 comparison_.output(homogeneousMode_, out);
203 }
204 out.close();
205
206 // Write concentration fields
207 outFileName = fileName;
208 outFileName += ".c";
209 fieldIo_.writeFields(cFields(), outFileName);
210
211 // Write chemical potential fields
212 outFileName = fileName;
213 outFileName += ".w";
214 fieldIo_.writeFields(wFields(), outFileName);
215 }
216
217 void Sweep::outputSummary(std::ostream& out)
218 {
219 int i = nAccept() - 1;
220 double sNew = s(0);
221 out << Int(i,5) << Dbl(sNew)
222 << Dbl(system().fHelmholtz(),16)
223 << Dbl(system().pressure(),16);
224 #if 0
225 if (homogeneousMode_ != -1) {
226 if (homogeneousMode_ == 0) {
227 double dF = system().fHelmholtz()
229 out << Dbl(dF, 16);
230 } else {
231 double dP = system().pressure()
233 double dOmega = -1.0*dP*domain().volume();
234 out << Dbl(dOmega, 16);
235 }
236 }
237 #endif
238 out << std::endl;
239 }
240
242 { logFile_.close(); }
243
244 void Sweep::assignFields(DArray<System::Field>& lhs,
245 DArray<System::Field> const & rhs) const
246 {
247
248 int nm = mixture().nMonomer();
249 int nx = domain().nx();
250
251 UTIL_CHECK(lhs.capacity() == nm);
252 UTIL_CHECK(rhs.capacity() == nm);
253 int i, j;
254 for (i = 0; i < nm; ++i) {
255 UTIL_CHECK(rhs[i].isAllocated());
256 UTIL_CHECK(rhs[i].capacity() == nx);
257 UTIL_CHECK(lhs[i].isAllocated());
258 UTIL_CHECK(lhs[i].capacity() == nx);
259 for (j = 0; j < nx; ++j) {
260 lhs[i][j] = rhs[i][j];
261 }
262 }
263 }
264
265} // namespace R1d
266} // namespace Pscf
double fHelmholtz() const
Return Helmholtz free energy per monomer / kT.
double pressure() const
Return pressure in units of kT / monomer volume.
int nMonomer() const
Get number of monomer types.
int nx() const
Get number of spatial grid points, including both endpoints.
double volume() const
Get generalized volume of domain.
int homogeneousMode_
Mode for comparison to homogeneous system (none -> -1)
virtual void outputSolution(std::string const &stateFileName)
Output information after obtaining a converged solution.
virtual void getSolution()
Update state(0) and output data after successful convergence.
virtual void outputSummary(std::ostream &outFile)
Output data to a running summary.
virtual void extrapolate(double s)
Create initial guess for new w fields by polynomial extrapolation.
virtual void readParameters(std::istream &in)
Read ns and baseFileName parameters.
virtual void reset()
Reset system to previous solution after iterature failure.
virtual void setParameters(double s)
Set non-adjustable system parameters to new values.
virtual void checkAllocation(State &state)
Check allocation of w fields in one state, allocate if needed.
Sweep(System &system)
Constructor.
virtual void setup()
Setup operation at beginning sweep.
virtual void cleanup()
Close log file after end of sweep.
virtual int solve(bool isContinuation)
Call the current iterator to solve one SCFT problem.
System::WField & wField(int monomerId)
Get chemical potential field for a specific monomer type.
SystemAccess()
Default constructor.
const Domain & domain() const
Get spatial domain (including grid info) by reference.
DArray< System::CField > & cFields()
Get array of all chemical potential fields.
DArray< System::WField > & wFields()
Get array of all chemical potential fields.
FileMaster & fileMaster()
Get FileMaster by reference.
const System & system() const
Get parent System by reference.
const Mixture & mixture() const
Get Mixture by reference.
Main class in SCFT simulation of one system.
Definition r1d/System.h:65
double fHelmholtz() const
Get precomputed Helmholtz free energy per monomer / kT.
Definition r1d/System.h:674
double pressure() const
Get precomputed pressure x monomer volume kT.
Definition r1d/System.h:680
int iterate(bool isContinuation=false)
Iteratively solve a SCFT problem.
FloryHuggins::Mixture & homogeneous()
Get the homogeneous Flory-Huggins mixture (for reference calculations).
Definition r1d/System.h:599
Domain & domain()
Get spatial domain (including grid info) by reference.
Definition r1d/System.h:592
FileMaster & fileMaster()
Get FileMaster by reference.
Definition r1d/System.h:614
void writeThermo(std::ostream &out) const
Write thermodynamic properties to a file.
void addParameterTypes(GArray< ParameterType > paramTypes)
DArray< System::WField > & state(int i)
Definition SweepTmpl.h:127
virtual void readParameters(std::istream &in)
Read ns and baseFileName parameters.
Definition SweepTmpl.tpp:42
int capacity() const
Return allocated size.
Definition Array.h:159
Dynamically allocatable contiguous array template.
Definition DArray.h:32
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.
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.
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
SCFT with real 1D fields.
PSCF package top-level namespace.
Definition param_pc.dox:1