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