PSCF v1.1
FilmIterator.tpp
1#ifndef PSPC_FILM_ITERATOR_TPP
2#define PSPC_FILM_ITERATOR_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field Theory
6*
7* Copyright 2016 - 2021, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "FilmIterator.h"
12#include "pscf/crystal/UnitCell.h"
13#include "pscf/math/RealVec.h"
14#include "pspc/System.h"
15
16namespace Pscf {
17namespace Pspc
18{
19 using namespace Util;
20
21 // 1D Partial Specializations
22
23 /*
24 * Constructor.
25 */
26 template <typename IteratorType>
28 : FilmIteratorBase<1, IteratorType>(system)
29 { setClassName(iterator().className().append("Film").c_str()); }
30
31 /*
32 * Construct an array indicating whether each lattice parameter is
33 * flexible, based on normalVecId and unitCell definitions in param
34 * file as well as the optional user input flexibleParams. Store this
35 * array in flexibleParams_ member of this object, as well the
36 * flexibleParams_ member of the iterator within this object.
37 * Uses the flexibleParams_ member of the iterator within this object
38 * as a starting point.
39 */
40 template <typename IteratorType>
42 {
43 // Create flexibleParams array
44 FSArray<bool,6> params;
45 params.append(false); // parameter is not flexible
46
47 if (iterator().flexibleParams()[0]) {
48 Log::file()
49 << "Warning - The lattice parameter is not allowed "
50 << "to be flexible for a 1D thin film system."
51 << std::endl;
52 }
53
54 // Store params in flexibleParams_ member of this object
55 setFlexibleParams(params);
56
57 // Pass params into the iterator member of this object
58 iterator().setFlexibleParams(params);
59 }
60
61 /*
62 * Check that user-defined lattice basis vectors are compatible with
63 * the thin film constraint (in 1D, there is nothing to do; the lattice
64 * basis vector is correct in all cases).
65 */
66 template <typename IteratorType>
68 {} // do nothing
69
70
71 // 2D Partial Specializations
72
73 /*
74 * Constructor.
75 */
76 template <typename IteratorType>
78 : FilmIteratorBase<2, IteratorType>(system)
79 { setClassName(iterator().className().append("Film").c_str()); }
80
81 /*
82 * Construct an array indicating whether each lattice parameter is
83 * flexible, based on normalVecId and unitCell definitions in param
84 * file as well as the optional user input flexibleParams. Store this
85 * array in flexibleParams_ member of this object, as well the
86 * flexibleParams_ member of the iterator within this object.
87 * Uses the flexibleParams_ member of the iterator within this object
88 * as a starting point.
89 */
90 template <typename IteratorType>
92 {
93 FSArray<bool,6> params;
94 FSArray<bool,6> current = iterator().flexibleParams();
95 UTIL_CHECK(current.size() == system().unitCell().nParameter());
96
97 if (iterator().nFlexibleParams() == 0) { // lattice is already rigid
98 setFlexibleParams(current);
99 return;
100 }
101
102 // Initialize params to an array of false values
103 for (int i = 0; i < current.size(); i++) {
104 params.append(false);
105 }
106
107 // If the lattice system is square, no params are flexible. Otherwise,
108 // params should, at most, contain only the index of the lattice basis
109 // vector that is not normalVecId. The length of normalVecId is fixed
110 //and gamma = 90 degrees for all 2D thin film calculations.
111 if (system().domain().unitCell().lattice() != UnitCell<2>::Square) {
112 for (int i = 0; i < params.size(); i++) {
113 if ((i != normalVecId()) && (i < 2)) {
114 params[i] = true;
115 }
116 }
117 }
118
119 // Store params in flexibleParams_ member of this object
120 setFlexibleParams(params);
121
122 // Before updating iterator_.flexibleParams_, check if the number
123 // of flexible lattice parameters has changed during this function.
124 if (nFlexibleParams() < iterator().nFlexibleParams()) {
125 Log::file()
126 << "***Notice - Some lattice parameters will be held constant\n"
127 << "to comply with the thin film constraint.***"
128 << std::endl;
129 }
130
131 // Pass params into the iterator member of this object
132 iterator().setFlexibleParams(params);
133 }
134
135 /*
136 * Check that user-defined lattice basis vectors are compatible with
137 * the thin film constraint (in 2D, we require that gamma = 90°)
138 */
139 template <typename IteratorType>
141 {
142 RealVec<2> a, b;
143 a = system().domain().unitCell().rBasis(0);
144 b = system().domain().unitCell().rBasis(1);
145
146 double gamma = dot(a,b);
147 if (gamma > 1e-8) { // Dot product between a and b should be 0
148 UTIL_THROW("ERROR: Lattice basis vectors must be orthogonal when wall is present");
149 }
150 }
151
152
153 // 3D Partial Specializations
154
155 /*
156 * Constructor.
157 */
158 template <typename IteratorType>
160 : FilmIteratorBase<3, IteratorType>(system)
161 { setClassName(iterator().className().append("Film").c_str()); }
162
163 /*
164 * Construct an array indicating whether each lattice parameter is
165 * flexible, based on normalVecId and unitCell definitions in param
166 * file as well as the optional user input flexibleParams. Store this
167 * array in flexibleParams_ member of this object, as well the
168 * flexibleParams_ member of the iterator within this object.
169 * Uses the flexibleParams_ member of the iterator within this object
170 * as a starting point.
171 */
172 template <typename IteratorType>
174 {
175 FSArray<bool,6> params;
176 FSArray<bool,6> current = iterator().flexibleParams();
177 UTIL_CHECK(current.size() == system().unitCell().nParameter());
178
180 system().domain().unitCell().lattice();
181
182 // Initialize params to an array of false values
183 for (int i = 0; i < current.size(); i++) {
184 params.append(false);
185 }
186
187 if (iterator().nFlexibleParams() == 0) { // lattice is already rigid
188 setFlexibleParams(params);
189 return;
190 }
191
192 // There can be up to 3 flexible lattice parameters in 3D: the length
193 // of the two lattice vectors that are not normalVecId, and the angle
194 // between them. The other two angles must be 90 degrees, and the
195 // length of normalVecId is fixed. The crystal system determines which
196 // parameters are flexible.
197 if (lattice == UnitCell<3>::Rhombohedral) {
198
199 Log::file() << "Rhombohedral lattice systems are not compatible "
200 << "with a thin film constraint.\n"
201 << "See thin film documentation for more details.\n";
202 UTIL_THROW("Cannot use rhombohedral lattice in a thin film system.");
203
204 } else if (lattice == UnitCell<3>::Hexagonal) {
205
206 UTIL_CHECK(normalVecId() == 2); // this is required for hexagonal
207 if (current[0]) {
208 params[0] = true; // a is the only allowed flexible parameter
209 }
210
211 } else if (lattice == UnitCell<3>::Tetragonal) {
212
213 // if normalVecId = 2, the only allowed flexibleParam is 0
214 // if normalVecId < 2, the only allowed flexibleParam is 1
215 if (current[0] && normalVecId() == 2) {
216 params[0] = true;
217 } else if (current[1] && normalVecId() < 2) {
218 params[1] = true;
219 }
220
221 } else if (lattice != UnitCell<3>::Cubic) {
222
223 for (int i = 0; i < 3; i++) {
224 // This if-statement applies for orthorhombic/monoclinic/triclinic
225 if (i != normalVecId() && current[i]) {
226 params[i] = true;
227 }
228 }
229
230 // beta can be flexible in a monoclinic lattice if normalVecId = 1
231 if (lattice == UnitCell<3>::Monoclinic && normalVecId() == 1
232 && current[3]) {
233 params[3] = true;
234 }
235
236 // The angle between the two lattice basis vectors that are not
237 // normalVecId can be flexible in a triclinic lattice
238 if (lattice == UnitCell<3>::Triclinic && current[normalVecId()+3]) {
239 params[normalVecId()+3] = true;
240 }
241
242 }
243
244 // Store params in flexibleParams_ member of this object
245 setFlexibleParams(params);
246
247 // Before updating iterator_.flexibleParams_, check if the number
248 // of flexible lattice parameters has changed during this function.
249 if (nFlexibleParams() < iterator().nFlexibleParams()) {
250 Log::file()
251 << "***Notice - Some lattice parameters will be held constant\n"
252 << "to comply with the thin film constraint.***"
253 << std::endl;
254 }
255
256 // Pass params into the iterator member of this object
257 iterator().setFlexibleParams(params);
258 }
259
260 /*
261 * Check that user-defined lattice basis vectors are compatible with
262 * the thin film constraint (in 3D, we require that there be one
263 * lattice basis vector that is orthogonal to the walls, and two that
264 * are parallel to the walls; the orthogonal vector is normalVecId).
265 */
266 template <typename IteratorType>
268 {
269 RealVec<3> a, b, c;
270 a = system().domain().unitCell().rBasis(0);
271 b = system().domain().unitCell().rBasis(1);
272 c = system().domain().unitCell().rBasis(2);
273 double alpha, beta, gamma;
274 gamma = dot(a,b);
275 beta = dot(a,c);
276 alpha = dot(b,c);
277
278 if (normalVecId() == 0) {
279 if (beta > 1e-8 || gamma > 1e-8) {
280 UTIL_THROW("ERROR: If normalVecId = 0, beta and gamma must be 90 degrees");
281 }
282 } else if (normalVecId() == 1) {
283 if (alpha > 1e-8 || gamma > 1e-8) {
284 UTIL_THROW("ERROR: If normalVecId = 1, alpha and gamma must be 90 degrees");
285 }
286 } else { // normalVecId == 2
287 if (alpha > 1e-8 || beta > 1e-8) {
288 UTIL_THROW("ERROR: If normalVecId = 2, alpha and beta must be 90 degrees");
289 }
290 }
291 }
292
293} // namespace Pspc
294} // namespace Pscf
295#endif
Descriptor for a FilmIterator object.
IteratorType const & iterator() const
Return const reference to the real iterator within this FilmIterator.
virtual void setFlexibleParams()=0
Modifies flexibleParams_ to be compatible with thin film constraint.
virtual void checkLatticeVectors() const =0
Check that lattice vectors are compatible with thin film constraint.
Iterator for a thin film (empty base template).
Definition: FilmIterator.h:51
Main class for SCFT simulation of one system.
Definition: pspc/System.h:76
A RealVec<D, T> is D-component vector with elements of floating type T.
Definition: RealVec.h:28
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition: UnitCell.h:44
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
void append(Data const &data)
Append data to the end of the array.
Definition: FSArray.h:258
static std::ostream & file()
Get log ostream by reference.
Definition: Log.cpp:57
void setClassName(const char *className)
Set class name string.
std::string className() const
Get 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).
T dot(Vec< D, T > const &v1, Vec< D, T > const &v2)
Return dot product of two vectors.
Definition: Vec.h:285
Utility classes for scientific computation.
Definition: accumulators.mod:1