PSCF v1.1
pspc/sweep/SweepParameter.tpp
1#ifndef PSPC_SWEEP_PARAMETER_TPP
2#define PSPC_SWEEP_PARAMETER_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 <pspc/solvers/Block.h>
12#include <pspc/solvers/Mixture.h>
13#include <pspc/solvers/Polymer.h>
14#include <pspc/iterator/AmIterator.h>
15#include <pspc/iterator/FilmIterator.h>
16#include <pspc/System.h>
17#include <pscf/crystal/UnitCell.h>
18#include <pscf/inter/Interaction.h>
19#include <util/global.h>
20#include <util/containers/FSArray.h>
21#include <algorithm>
22#include <iomanip>
23
24namespace Pscf {
25namespace Pspc {
26
27 using namespace Util;
28
29 /*
30 * Default constructor.
31 */
32 template <int D>
34 : type_(SweepParameter<D>::Null),
35 nID_(0),
36 id_(),
37 initial_(0.0),
38 change_(0.0),
39 systemPtr_(0)
40 {}
41
42 /*
43 * Constructor, creates association with system.
44 */
45 template <int D>
47 : type_(SweepParameter<D>::Null),
48 nID_(0),
49 id_(),
50 initial_(0.0),
51 change_(0.0),
52 systemPtr_(&system)
53 {}
54
55 /*
56 * Read type, set nId and allocate id_ array.
57 */
58 template <int D>
59 void SweepParameter<D>::readParamType(std::istream& in)
60 {
61 std::string buffer;
62 in >> buffer;
63 std::transform(buffer.begin(), buffer.end(),
64 buffer.begin(), ::tolower);
65
66 if (buffer == "block" || buffer == "block_length") {
67 type_ = Block;
68 nID_ = 2; // polymer and block identifiers
69 } else if (buffer == "chi") {
70 type_ = Chi;
71 nID_ = 2; // two monomer type identifiers
72 } else if (buffer == "kuhn") {
73 type_ = Kuhn;
74 nID_ = 1; // monomer type identifier
75 } else if (buffer == "phi_polymer") {
76 type_ = Phi_Polymer;
77 nID_ = 1; // species identifier.
78 } else if (buffer == "phi_solvent") {
79 type_ = Phi_Solvent;
80 nID_ = 1; // species identifier.
81 } else if (buffer == "mu_polymer") {
82 type_ = Mu_Polymer;
83 nID_ = 1; // species identifier.
84 } else if (buffer == "mu_solvent") {
85 type_ = Mu_Solvent;
86 nID_ = 1; // species identifier.
87 } else if (buffer == "solvent" || buffer == "solvent_size") {
88 type_ = Solvent;
89 nID_ = 1; // species identifier.
90 } else if (buffer == "cell_param") {
91 type_ = Cell_Param;
92 nID_ = 1; // lattice parameter identifier.
93 } else if (buffer == "chi_bottom") {
94 // Note: this option is only relevant for thin film systems
95 type_ = Chi_Bottom;
96 nID_ = 1; // monomer type
97 } else if (buffer == "chi_top") {
98 // Note: this option is only relevant for thin film systems
99 type_ = Chi_Top;
100 nID_ = 1; // monomer type
101 } else {
102 UTIL_THROW("Invalid SweepParameter::ParamType value");
103 }
104
105 if (id_.isAllocated()) id_.deallocate();
106 id_.allocate(nID_);
107
108 }
109
110 /*
111 * Write type enum value
112 */
113 template <int D>
114 void SweepParameter<D>::writeParamType(std::ostream& out) const
115 {
116 out << type();
117 }
118
119 /*
120 * Get the current value from the parent system.
121 */
122 template <int D>
124 {
125 initial_ = get_();
126 }
127
128 /*
129 * Set a new value in the parent system.
130 */
131 template <int D>
132 void SweepParameter<D>::update(double newVal)
133 {
134 set_(newVal);
135 }
136
137 /*
138 * Get string representation of type enum value.
139 */
140 template <int D>
141 std::string SweepParameter<D>::type() const
142 {
143 if (type_ == Block) {
144 return "block";
145 } else if (type_ == Chi) {
146 return "chi";
147 } else if (type_ == Kuhn) {
148 return "kuhn";
149 } else if (type_ == Phi_Polymer) {
150 return "phi_polymer";
151 } else if (type_ == Phi_Solvent) {
152 return "phi_solvent";
153 } else if (type_ == Mu_Polymer) {
154 return "mu_polymer";
155 } else if (type_ == Mu_Solvent) {
156 return "mu_solvent";
157 } else if (type_ == Solvent) {
158 return "solvent_size";
159 } else if (type_ == Cell_Param) {
160 return "cell_param";
161 } else if (type_ == Chi_Bottom) {
162 return "chi_bottom";
163 } else if (type_ == Chi_Top) {
164 return "chi_top";
165 } else {
166 UTIL_THROW("This should never happen.");
167 }
168 }
169
170 template <int D>
172 {
173 if (type_ == Block) {
174 return systemPtr_->mixture().polymer(id(0)).block(id(1)).length();
175 } else if (type_ == Chi) {
176 return systemPtr_->interaction().chi(id(0), id(1));
177 } else if (type_ == Kuhn) {
178 return systemPtr_->mixture().monomer(id(0)).kuhn();
179 } else if (type_ == Phi_Polymer) {
180 return systemPtr_->mixture().polymer(id(0)).phi();
181 } else if (type_ == Phi_Solvent) {
182 return systemPtr_->mixture().solvent(id(0)).phi();
183 } else if (type_ == Mu_Polymer) {
184 return systemPtr_->mixture().polymer(id(0)).mu();
185 } else if (type_ == Mu_Solvent) {
186 return systemPtr_->mixture().solvent(id(0)).mu();
187 } else if (type_ == Solvent) {
188 return systemPtr_->mixture().solvent(id(0)).size();
189 } else if (type_ == Cell_Param) {
190 return systemPtr_->unitCell().parameter(id(0));
191 } else if (type_ == Chi_Bottom) {
192 // Note: this option is only relevant for thin film systems
193 UTIL_CHECK(isFilmIterator());
194 if (systemPtr_->iterator().className() == "AmIteratorFilm") {
195 FilmIterator<D, AmIterator<D> >* itrPtr_(0);
196 itrPtr_ = static_cast<FilmIterator<D, AmIterator<D> >* >(&(systemPtr_->iterator()));
197 return itrPtr_->chiBottom(id(0));
198 } else {
199 UTIL_THROW("Iterator type is not compatible with this sweep parameter.");
200 }
201 } else if (type_ == Chi_Top) {
202 // Note: this option is only relevant for thin film systems
203 UTIL_CHECK(isFilmIterator());
204 if (systemPtr_->iterator().className() == "AmIteratorFilm") {
205 FilmIterator<D, AmIterator<D> >* itrPtr_(0);
206 itrPtr_ = static_cast<FilmIterator<D, AmIterator<D> >* >(&(systemPtr_->iterator()));
207 return itrPtr_->chiTop(id(0));
208 } else {
209 UTIL_THROW("Iterator type is not compatible with this sweep parameter.");
210 }
211 } else {
212 UTIL_THROW("This should never happen.");
213 }
214 }
215
216 template <int D>
217 void SweepParameter<D>::set_(double newVal)
218 {
219 if (type_ == Block) {
220 systemPtr_->mixture().polymer(id(0)).block(id(1)).setLength(newVal);
221 } else if (type_ == Chi) {
222 systemPtr_->interaction().setChi(id(0), id(1), newVal);
223 } else if (type_ == Kuhn) {
224 systemPtr_->mixture().setKuhn(id(0), newVal);
225 } else if (type_ == Phi_Polymer) {
226 systemPtr_->mixture().polymer(id(0)).setPhi(newVal);
227 } else if (type_ == Phi_Solvent) {
228 systemPtr_->mixture().solvent(id(0)).setPhi(newVal);
229 } else if (type_ == Mu_Polymer) {
230 systemPtr_->mixture().polymer(id(0)).setMu(newVal);
231 } else if (type_ == Mu_Solvent) {
232 systemPtr_->mixture().solvent(id(0)).setMu(newVal);
233 } else if (type_ == Solvent) {
234 systemPtr_->mixture().solvent(id(0)).setSize(newVal);
235 } else if (type_ == Cell_Param) {
236 FSArray<double,6> params = systemPtr_->unitCell().parameters();
237 params[id(0)] = newVal;
238 systemPtr_->setUnitCell(params);
239 } else if (type_ == Chi_Bottom) {
240 // Note: this option is only relevant for thin film systems
241 UTIL_CHECK(isFilmIterator());
242 if (systemPtr_->iterator().className() == "AmIteratorFilm") {
243 FilmIterator<D, AmIterator<D> >* itrPtr_(0);
244 itrPtr_ = static_cast<FilmIterator<D, AmIterator<D> >* >(&(systemPtr_->iterator()));
245 itrPtr_->setChiBottom(id(0), newVal);
246 } else {
247 UTIL_THROW("Iterator type is not compatible with this sweep parameter.");
248 }
249 } else if (type_ == Chi_Top) {
250 // Note: this option is only relevant for thin film systems
251 UTIL_CHECK(isFilmIterator());
252 if (systemPtr_->iterator().className() == "AmIteratorFilm") {
253 FilmIterator<D, AmIterator<D> >* itrPtr_(0);
254 itrPtr_ = static_cast<FilmIterator<D, AmIterator<D> >* >(&(systemPtr_->iterator()));
255 itrPtr_->setChiTop(id(0), newVal);
256 } else {
257 UTIL_THROW("Iterator type is not compatible with this sweep parameter.");
258 }
259 } else {
260 UTIL_THROW("This should never happen.");
261 }
262 }
263
264 /*
265 * Check if the system iterator is a thin film iterator.
266 */
267 template <int D>
268 bool SweepParameter<D>::isFilmIterator() const
269 {
270 std::string name = systemPtr_->iterator().className();
271 if (name.size() < 4) {
272 return false;
273 } else {
274 return (name.substr(name.size() - 4) == "Film");
275 }
276 }
277
278 template <int D>
279 template <class Archive>
280 void SweepParameter<D>::serialize(Archive ar, const unsigned int version)
281 {
282 serializeEnum(ar, type_, version);
283 ar & nID_;
284 for (int i = 0; i < nID_; ++i) {
285 ar & id_[i];
286 }
287 ar & initial_;
288 ar & change_;
289 }
290
291 // Definitions of operators, with no explicit instantiations.
292
293 /*
294 * Inserter for reading a SweepParameter from an istream.
295 */
296 template <int D>
297 std::istream& operator >> (std::istream& in,
298 SweepParameter<D>& param)
299 {
300 // Read the parameter type.
301 param.readParamType(in);
302 // Read the identifiers associated with this parameter type.
303 for (int i = 0; i < param.nID_; ++i) {
304 in >> param.id_[i];
305 }
306 // Read in the range in the parameter to sweep over
307 in >> param.change_;
308
309 return in;
310 }
311
312 /*
313 * Extractor for writing a SweepParameter to ostream.
314 */
315 template <int D>
316 std::ostream& operator << (std::ostream& out,
317 SweepParameter<D> const & param)
318 {
319 param.writeParamType(out);
320 out << " ";
321 for (int i = 0; i < param.nID_; ++i) {
322 out << param.id(i);
323 out << " ";
324 }
325 out << param.change_;
326
327 return out;
328 }
329
330}
331}
332
333#endif
Block within a branched polymer.
Solver and descriptor for a solvent species.
Class for storing data about an individual sweep parameter.
std::string type() const
Return a string representation of the parameter type.
void getInitial()
Store the pre-sweep value of the corresponding parameter.
void serialize(Archive ar, const unsigned int version)
Serialize to or from an archive.
int id(int i) const
Get a id for a sub-object or element to which this is applied.
void update(double newVal)
Update the corresponding parameter value in the system.
void writeParamType(std::ostream &out) const
Write the parameter type to an output stream.
Main class for SCFT simulation of one system.
Definition: pspc/System.h:76
A fixed capacity (static) contiguous array with a variable logical size.
Definition: FSArray.h:38
File containing preprocessor macros for error handling.
#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
void serializeEnum(Archive &ar, T &data, const unsigned int version=0)
Serialize an enumeration value.
Definition: serialize.h:42
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1
std::istream & operator>>(std::istream &in, Pair< Data > &pair)
Input a Pair from an istream.
Definition: Pair.h:44
std::ostream & operator<<(std::ostream &out, const Pair< Data > &pair)
Output a Pair to an ostream, without line breaks.
Definition: Pair.h:57