PSCF v1.3
MaskReal.tpp
1#ifndef PRDC_MASK_TMPL_TPP
2#define PRDC_MASK_TMPL_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field
6*
7* Copyright 2015 - 2025, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "MaskReal.h"
12#include <prdc/field/fieldIoUtil.h>
13#include <prdc/crystal/Basis.h>
14#include <prdc/crystal/UnitCell.h>
15#include <pscf/mesh/Mesh.h>
16#include <util/signal/Signal.h>
17#include <util/misc/FileMaster.h>
18
19namespace Pscf {
20namespace Prdc {
21
22 using namespace Util;
23
24 /*
25 * Constructor.
26 */
27 template <int D, class RFT, class FIT>
29 : basis_(),
30 rgrid_(),
31 meshDimensions_(),
32 meshSize_(0),
33 nBasis_(0),
34 readUnitCellPtr_(nullptr),
35 writeUnitCellPtr_(nullptr),
36 fieldIoPtr_(nullptr),
37 signalPtr_(nullptr),
38 isAllocatedBasis_(false),
39 isAllocatedRGrid_(false),
40 hasData_(false),
41 isSymmetric_(false)
42 {
43 signalPtr_ = new Signal<void>();
44 }
45
46 /*
47 * Destructor.
48 */
49 template <int D, class RFT, class FIT>
51 {
52 delete signalPtr_;
53 }
54
55 /*
56 * Create an association with a FieldIo object.
57 */
58 template <int D, class RFT, class FIT>
60 { fieldIoPtr_ = &fieldIo; }
61
62 /*
63 * Set the unit cell that is modified by reading a field file.
64 */
65 template <int D, class RFT, class FIT>
67 {
68 UTIL_CHECK(!readUnitCellPtr_);
69 readUnitCellPtr_ = &cell;
70 }
71
72 /*
73 * Set the unit cell that whose parameters are written to a field header.
74 */
75 template <int D, class RFT, class FIT>
76 void
78 {
79 UTIL_CHECK(!writeUnitCellPtr_);
80 writeUnitCellPtr_ = &cell;
81 }
82
83 /*
84 * Allocate memory for a field in basis format.
85 */
86 template <int D, class RFT, class FIT>
88 {
89 UTIL_CHECK(!isAllocatedBasis_);
90
91 // Set basis dimensions
92 nBasis_ = nBasis;
93
94 // Allocate field array, basis format
95 basis_.allocate(nBasis);
96 isAllocatedBasis_ = true;
97 }
98
99 /*
100 * Allocate memory for field in basis format.
101 */
102 template <int D, class RFT, class FIT>
103 void
105 {
106 UTIL_CHECK(!isAllocatedRGrid_);
107
108 // Set mesh dimensions
109 meshDimensions_ = meshDimensions;
110 meshSize_ = 1;
111 for (int i = 0; i < D; ++i) {
113 meshSize_ *= meshDimensions[i];
114 }
115
116 // Allocate field array, rgrid format
117 rgrid_.allocate(meshDimensions);
118 isAllocatedRGrid_ = true;
119 }
120
121 /*
122 * Set new field values, in basis form.
123 */
124 template <int D, class RFT, class FIT>
126 {
127 // Allocate fields as needed
128 if (!isAllocatedRGrid_) {
129 Mesh<D> const & mesh = fieldIo().mesh();
130 UTIL_CHECK(mesh.size() > 0);
132 }
133 if (!isAllocatedBasis_) {
134 Basis<D> const & basis = fieldIo().basis();
135 UTIL_CHECK(basis.isInitialized());
136 allocateBasis(basis.nBasis());
137 }
138 UTIL_CHECK(isAllocatedRGrid_);
139 UTIL_CHECK(isAllocatedBasis_);
140
141 // Set components in basis form (array basis_)
142 UTIL_CHECK(field.capacity() == nBasis_);
143 for (int j = 0; j < nBasis_; ++j) {
144 basis_[j] = field[j];
145 }
146
147 // Convert to r-grid form (update array rgrid_)
148 fieldIo().convertBasisToRGrid(basis_, rgrid_);
149
150 hasData_ = true;
151 isSymmetric_ = true;
152
153 // Notify observers of field modification
154 signal().notify();
155 }
156
157 /*
158 * Set new field values, in r-grid form.
159 */
160 template <int D, class RFT, class FIT>
161 void MaskReal<D,RFT,FIT>::setRGrid(RFT const & field,
162 bool isSymmetric)
163 {
164 // Allocate rgrid_ field as needed
165 if (!isAllocatedRGrid_) {
166 Mesh<D> const & mesh = fieldIo().mesh();
168 }
169 UTIL_CHECK(isAllocatedRGrid_);
170
171 // Copy input field data to member variable rgrid_
172 rgrid_ = field; // deep copy by assignment operator
173
174 // Optionally convert to basis form
175 if (isSymmetric) {
176 if (!isAllocatedBasis_) {
177 Basis<D> const & basis = fieldIo().basis();
178 UTIL_CHECK(basis.isInitialized());
179 allocateBasis(basis.nBasis());
180 }
181 UTIL_CHECK(isAllocatedBasis_);
182 fieldIo().convertRGridToBasis(rgrid_, basis_);
183 }
184
185 hasData_ = true;
186 isSymmetric_ = isSymmetric;
187
188 // Notify observers of field modification
189 signal().notify();
190 }
191
192 /*
193 * Read field from an input stream in basis format.
194 *
195 * This function also computes and stores the corresponding r-grid
196 * representation. On return, hasData and isSymmetric are both true.
197 */
198 template <int D, class RFT, class FIT>
199 void MaskReal<D,RFT,FIT>::readBasis(std::istream& in)
200 {
201 // Preconditions
202 UTIL_CHECK(readUnitCellPtr_);
203
204 // Read field file header
205 int nMonomerIn;
206 bool isSymmetricIn;
207 fieldIo().readFieldHeader(in, nMonomerIn, *readUnitCellPtr_,
208 isSymmetricIn);
209 UTIL_CHECK(1 == nMonomerIn);
210 UTIL_CHECK(isSymmetricIn);
211 UTIL_CHECK(fieldIo().basis().isInitialized());
212 // Note: FIT::readFieldHeader will initialize basis if needed
213 int nBasisIn = readNBasis(in);
214
215 // Local references to mesh and basis
216 Mesh<D> const & mesh = fieldIo().mesh();
217 Basis<D> const & basis = fieldIo().basis();
218 UTIL_CHECK(mesh.size() > 0);
219 UTIL_CHECK(basis.isInitialized());
220
221 // If necessary, allocate fields
222 if (!isAllocatedRGrid_) {
224 }
225 if (!isAllocatedBasis_) {
226 allocateBasis(basis.nBasis());
227 }
228 UTIL_CHECK(isAllocatedRGrid_);
229 UTIL_CHECK(isAllocatedBasis_);
230
231 // Read field data in basis form (array basis_)
232 Prdc::readBasisData(in, basis_, *readUnitCellPtr_,
233 mesh, basis, nBasisIn);
234
235 // Convert r-grid form (array rgrid_)
236 fieldIo().convertBasisToRGrid(basis_, rgrid_);
237
238 hasData_ = true;
239 isSymmetric_ = true;
240
241 // Notify observers of field modification
242 signal().notify();
243 }
244
245 /*
246 * Read field components from a file basis format, by filename.
247 */
248 template <int D, class RFT, class FIT>
249 void MaskReal<D,RFT,FIT>::readBasis(std::string filename)
250 {
251 std::ifstream file;
252 fieldIo().fileMaster().openInputFile(filename, file);
253 readBasis(file);
254 file.close();
255 }
256
257 /*
258 * Reads field from an input stream in r-grid format.
259 *
260 * If the isSymmetric parameter is true, this function assumes that
261 * the field is known to be symmetric and so computes and stores
262 * the corresponding basis format. If isSymmetric is false, it
263 * only sets the values in the r-grid format.
264 */
265 template <int D, class RFT, class FIT>
266 void MaskReal<D,RFT,FIT>::readRGrid(std::istream& in,
267 bool isSymmetric)
268 {
269 // Preconditions
270 UTIL_CHECK(readUnitCellPtr_);
271
272 // If necessary, allocate rgrid_ fields
273 if (!isAllocatedRGrid_) {
274 Mesh<D> const & mesh = fieldIo().mesh();
275 UTIL_CHECK(mesh.size() > 0);
277 }
278 UTIL_CHECK(isAllocatedRGrid_);
279
280 // Read field file in r-grid format (array rgrid_)
281 fieldIo().readFieldRGrid(in, rgrid_, *readUnitCellPtr_);
282
283 // Optionally convert to basis form
284 if (isSymmetric) {
285 if (!isAllocatedBasis_) {
286 Basis<D> const & basis = fieldIo().basis();
287 UTIL_CHECK(basis.isInitialized());
288 allocateBasis(basis.nBasis());
289 }
290 fieldIo().convertRGridToBasis(rgrid_, basis_);
291 }
292
293 hasData_ = true;
294 isSymmetric_ = isSymmetric;
295
296 // Notify observers of field modification
297 signal().notify();
298 }
299
300 /*
301 * Read field from a file in r-grid format, by filename.
302 */
303 template <int D, class RFT, class FIT>
304 void MaskReal<D,RFT,FIT>::readRGrid(std::string filename,
305 bool isSymmetric)
306 {
307 std::ifstream file;
308 fieldIo().fileMaster().openInputFile(filename, file);
309 readRGrid(file, isSymmetric);
310 file.close();
311 }
312
313 /*
314 * Return volume fraction of the unit cell occupied by the
315 * polymers/solvents.
316 */
317 template <int D, class RFT, class FIT>
319 {
320 if (isSymmetric() && hasData()) {
321 // Data in basis format is available
322 return basis()[0];
323 } else if (!hasData()) {
324 // system does not have a mask
325 return 1.0;
326 } else { // Data is only available in r-grid format
327 return rGridAverage();
328 }
329 }
330
331 // Field output to file
332
333 /*
334 * Write fields to an output stream in basis format.
335 */
336 template <int D, class RFT, class FIT>
337 void MaskReal<D,RFT,FIT>::writeBasis(std::ostream& out) const
338 {
339 // Preconditions
340 UTIL_CHECK(fieldIoPtr_);
341 UTIL_CHECK(writeUnitCellPtr_);
342 UTIL_CHECK(isAllocatedBasis_);
343 UTIL_CHECK(hasData_);
344 UTIL_CHECK(isSymmetric_);
345
346 fieldIo().writeFieldBasis(out, basis_, *writeUnitCellPtr_);
347 }
348
349 /*
350 * Write fields to a file in basis format, by filename.
351 */
352 template <int D, class RFT, class FIT>
353 void MaskReal<D,RFT,FIT>::writeBasis(std::string filename) const
354 {
355 std::ofstream file;
356 fieldIo().fileMaster().openOutputFile(filename, file);
357 writeBasis(file);
358 file.close();
359 }
360
361 /*
362 * Write fields to an output stream in real-space (r-grid) format.
363 */
364 template <int D, class RFT, class FIT>
365 void MaskReal<D,RFT,FIT>::writeRGrid(std::ostream& out) const
366 {
367 // Preconditions
368 UTIL_CHECK(writeUnitCellPtr_);
369 UTIL_CHECK(fieldIoPtr_);
370 UTIL_CHECK(isAllocatedRGrid_);
371 UTIL_CHECK(hasData_);
372
373 fieldIo().writeFieldRGrid(out, rgrid_,
374 *writeUnitCellPtr_,
375 isSymmetric_);
376 }
377
378 /*
379 * Write fields to a file in r-grid format, by filename.
380 */
381 template <int D, class RFT, class FIT>
382 void MaskReal<D,RFT,FIT>::writeRGrid(std::string filename) const
383 {
384 std::ofstream file;
385 fieldIo().fileMaster().openOutputFile(filename, file);
386 writeRGrid(file);
387 file.close();
388 }
389
390 // Signal accessor
391
392 /*
393 * Get a signal that is triggered by field modification.
394 */
395 template <int D, class RFT, class FIT>
397 {
398 UTIL_CHECK(signalPtr_);
399 return *signalPtr_;
400 }
401
402} // namespace Prdc
403} // namespace Pscf
404#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Description of a regular grid of points in a periodic domain.
Definition Mesh.h:61
IntVec< D > dimensions() const
Get an IntVec<D> of the grid dimensions.
Definition Mesh.h:217
int size() const
Get total number of grid points.
Definition Mesh.h:229
Symmetry-adapted Fourier basis for pseudo-spectral SCFT.
Definition Basis.h:383
bool hasData() const
Has field data been set in either format?
Definition MaskReal.h:507
void writeBasis(std::ostream &out) const
Write fields to an input stream in symmetrized basis format.
Definition MaskReal.tpp:337
~MaskReal()
Destructor.
Definition MaskReal.tpp:50
void setReadUnitCell(UnitCell< D > &cell)
Set unit cell used when reading a mask field file.
Definition MaskReal.tpp:66
int nBasis() const
Number of basis functions, set by allocation.
Definition MaskReal.h:382
double phiTot() const
Return the volume fraction of unit cell occupied by material.
Definition MaskReal.tpp:318
virtual double rGridAverage() const =0
Calculate the average value of the rgrid_ member.
FIT const & fieldIo() const
Associated FieldIo object (const reference).
Definition MaskReal.h:388
void setRGrid(RFT const &field, bool isSymmetric=false)
Set field values in real-space (r-grid) format.
Definition MaskReal.tpp:161
bool isSymmetric() const
Are field symmetric under all elements of the space group?
Definition MaskReal.h:512
void setBasis(DArray< double > const &field)
Set field component values, in symmetrized Fourier format.
Definition MaskReal.tpp:125
MaskReal()
Constructor.
Definition MaskReal.tpp:28
IntVec< D > const & meshDimensions() const
Mesh dimensions in each direction, set by allocation.
Definition MaskReal.h:370
void readRGrid(std::istream &in, bool isSymmetric=false)
Reads field from an input stream in real-space (r-grid) format.
Definition MaskReal.tpp:266
DArray< double > const & basis() const
Get the field in basis format.
Definition MaskReal.h:480
void writeRGrid(std::ostream &out) const
Writes fields to an input stream in real-space (r-grid) format.
Definition MaskReal.tpp:365
void allocateRGrid(IntVec< D > const &dimensions)
Allocate memory for the field in rgrid format.
Definition MaskReal.tpp:104
void setWriteUnitCell(UnitCell< D > const &cell)
Set unit cell used when writing a mask field file.
Definition MaskReal.tpp:77
void setFieldIo(FIT const &fieldIo)
Create association with FieldIo (store pointer).
Definition MaskReal.tpp:59
Signal< void > & signal()
Get a signal that notifies observers of field modification.
Definition MaskReal.tpp:396
void readBasis(std::istream &in)
Read field from input stream in symmetrized basis format.
Definition MaskReal.tpp:199
void allocateBasis(int nBasis)
Allocate memory for the field in basis format.
Definition MaskReal.tpp:87
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition UnitCell.h:56
int capacity() const
Return allocated size.
Definition Array.h:159
Dynamically allocatable contiguous array template.
Definition DArray.h:32
Notifier (or subject) in the Observer design pattern.
Definition Signal.h:39
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
int readNBasis(std::istream &in)
Read the number of basis functions from a basis field file header.
void readBasisData(std::istream &in, DArray< DArray< double > > &fields, UnitCell< D > const &unitCell, Mesh< D > const &mesh, Basis< D > const &basis, int nStarIn)
Read an array of fields in basis format, without a header.
Periodic fields and crystallography.
Definition CField.cpp:11
PSCF package top-level namespace.
Definition param_pc.dox:1