PSCF v1.4.0
rp/field/Domain.tpp
1#ifndef RP_DOMAIN_TPP
2#define RP_DOMAIN_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 "Domain.h"
12#include <prdc/crystal/SpaceGroup.h>
13#include <prdc/crystal/Basis.h>
14#include <prdc/field/fieldHeader.h>
15#include <util/signal/Signal.h>
16#include <util/misc/FileMaster.h>
17
18namespace Pscf {
19namespace Rp {
20
21 using namespace Util;
22 using namespace Prdc;
23
24 /*
25 * Constructor.
26 */
27 template <int D, class FFT, class WLT, class FIT>
29 : mesh_(),
30 unitCell_(),
31 lattice_(UnitCell<D>::Null),
32 groupName_(""),
33 groupPtr_(nullptr),
34 basisPtr_(nullptr),
35 fftPtr_(nullptr),
36 waveListPtr_(nullptr),
37 fieldIoPtr_(nullptr),
38 signalPtr_(nullptr),
39 fileMasterPtr_(nullptr),
40 hasGroup_(false),
41 isInitialized_(false)
42 {
44
45 // Construct associated objects
46 groupPtr_ = new SpaceGroup<D>();
47 basisPtr_ = new Basis<D>();
48 fftPtr_ = new FFT();
49 waveListPtr_ = new WLT();
50 fieldIoPtr_ = new FIT();
51 signalPtr_ = new Signal<void>();
52
53 // Create associations between objects
54 fieldIo().associate(mesh_, fft(), lattice_,
55 hasGroup_, groupName_, group(), basis());
56 unitCell_.setSignal(*signalPtr_);
57 }
58
59 /*
60 * Destructor.
61 */
62 template <int D, class FFT, class WLT, class FIT>
64 {
65 delete basisPtr_;
66 delete fftPtr_;
67 delete waveListPtr_;
68 delete fieldIoPtr_;
69 delete signalPtr_;
70 }
71
72 /*
73 * Create association with a FileMaster.
74 */
75 template <int D, class FFT, class WLT, class FIT>
77 {
78 fileMasterPtr_ = &fileMaster;
79 fieldIo().setFileMaster(fileMaster);
80 }
81
82 /*
83 * Read parameters and initialize.
84 */
85 template <int D, class FFT, class WLT, class FIT>
87 {
88 // Preconditions
89 UTIL_CHECK(!isInitialized_);
90 UTIL_CHECK(fileMasterPtr_);
91
92 // Read computational mesh dimensions (required)
93 ParamComposite::read(in, "mesh", mesh_);
94 UTIL_CHECK(mesh_.size() > 0);
95 fft().setup(mesh_.dimensions());
96
97 // Read lattice system enumeration value (required)
98 ParamComposite::read(in, "lattice", lattice_);
99 unitCell_.set(lattice_);
100 UTIL_CHECK(unitCell_.lattice() != UnitCell<D>::Null);
101 UTIL_CHECK(unitCell_.nParameter() > 0);
102
103 // Allocate memory for WaveList
104 waveList().allocate(mesh_, unitCell_);
106 // Optionally read groupName_ (string identifier for space group)
107 hasGroup_ = false;
108 bool hasGroupName = false;
109 hasGroupName = ParamComposite::readOptional(
110 in, "groupName", groupName_).isActive();
111
112 // If groupName_ exists, read and construct group (space group)
113 if (hasGroupName) {
114 // Read group symmetry operations from file
115 // An Exception is thrown if groupName_ string is not recognized
116 readGroup(groupName_, *groupPtr_);
117 hasGroup_ = true;
118 }
119
120 isInitialized_ = true;
121 }
122
123 /*
124 * Read header of r-grid field to initialize the Domain.
125 *
126 * Alternative to parameter file, used only for unit testing.
127 */
128 template <int D, class FFT, class WLT, class FIT>
129 void
131 int& nMonomer)
132 {
133 // Preconditions - confirm that nothing is initialized
134 UTIL_CHECK(!isInitialized_);
135 UTIL_CHECK(lattice_ == UnitCell<D>::Null);
136 UTIL_CHECK(!unitCell_.isInitialized());
137 UTIL_CHECK(!hasGroup_);
138 UTIL_CHECK(groupName_ == "");
139
140 // Read common section of standard field header
141 int ver1, ver2;
142 Pscf::Prdc::readFieldHeader(in, ver1, ver2,
143 unitCell_, groupName_, nMonomer);
144
145 // Set lattice_ (lattice system identifier)
146 lattice_ = unitCell_.lattice();
147 UTIL_CHECK(lattice_ != UnitCell<D>::Null);
148 UTIL_CHECK(unitCell_.isInitialized());
149
150 // Read grid dimensions
151 std::string label;
152 in >> label;
153 if (label != "mesh" && label != "ngrid") {
154 std::string msg = "\n";
155 msg += "Error reading field file:\n";
156 msg += "Expected mesh or ngrid, but found [";
157 msg += label;
158 msg += "]";
159 UTIL_THROW(msg.c_str());
160 }
161 IntVec<D> nGrid;
162 in >> nGrid;
163
164 // Initialize mesh and fft
165 if (mesh_.size() == 0) {
166 mesh_.setDimensions(nGrid);
167 fft().setup(mesh_.dimensions());
168 }
169
170 // Allocate waveList
171 if (!waveList().isAllocated()) {
172 waveList().allocate(mesh_, unitCell_);
173 }
174
175 // If groupName is present, construct group and basis
176 if (groupName_ != "") {
177 readGroup(groupName_, *groupPtr_);
178 hasGroup_ = true;
179 basis().makeBasis(mesh_, unitCell_, group());
180 }
181
182 isInitialized_ = true;
183 }
184
185 /*
186 * Make basis if needed.
187 */
188 template <int D, class FFT, class WLT, class FIT>
190 {
191 UTIL_CHECK(mesh_.size() > 0);
192 UTIL_CHECK(unitCell_.lattice() != UnitCell<D>::Null);
193 UTIL_CHECK(unitCell_.isInitialized());
194 UTIL_CHECK(hasGroup_);
195
196 // Check basis, construct if not initialized
197 if (!basis().isInitialized()) {
198 basis().makeBasis(mesh_, unitCell_, group());
199 }
200 UTIL_CHECK(basis().isInitialized());
201 }
202
203 // Crystallographic Data Output
204
205 /*
206 * Write description of symmetry-adapted stars and basis to file.
207 */
208 template <int D, class FFT, class WLT, class FIT>
209 void
210 Domain<D,FFT,WLT,FIT>::writeStars(std::string const & filename)
211 const
214 UTIL_CHECK(basis().isInitialized());
215 std::ofstream file;
216 fileMaster().openOutputFile(filename, file);
217 bool isSymmetric = true;
218 int nMonomer = 0;
219 fieldIo().writeFieldHeader(file, nMonomer, unitCell_, isSymmetric);
220 basis().outputStars(file);
221 file.close();
223
224 /*
225 * Write a list of waves and associated stars to file.
226 */
227 template <int D, class FFT, class WLT, class FIT>
228 void
229 Domain<D,FFT,WLT,FIT>::writeWaves(std::string const & filename)
230 const
231 {
233 UTIL_CHECK(basis().isInitialized());
234 std::ofstream file;
235 fileMaster().openOutputFile(filename, file);
236 bool isSymmetric = true;
237 int nMonomer = 0;
238 fieldIo().writeFieldHeader(file, nMonomer, unitCell_, isSymmetric);
239 basis().outputWaves(file);
240 file.close();
241 }
242
243 /*
244 * Write all elements of the space group to a file.
245 */
246 template <int D, class FFT, class WLT, class FIT>
247 void
248 Domain<D,FFT,WLT,FIT>::writeGroup(std::string const & filename)
249 const
250 {
252 std::ofstream file;
253 fileMaster().openOutputFile(filename, file);
254 file << group();
255 file.close();
256 }
257
258 /*
259 * Has a symmetry-adapted Fourier basis been initialized ?
260 */
261 template <int D, class FFT, class WLT, class FIT>
263 { return basis().isInitialized(); }
264
265} // namespace Rp
266} // namespace Pscf
267#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Symmetry-adapted Fourier basis for pseudo-spectral SCFT.
Definition Basis.h:384
Fourier transform wrapper.
Definition cpu/FFT.h:39
Crystallographic space group.
Definition SpaceGroup.h:32
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition UnitCell.h:56
bool hasBasis() const
Has a symmetry-adapted Fourier basis been initialized?
SpaceGroup< D > const & group() const
Get the SpaceGroup by const reference.
void setFileMaster(FileMaster &fileMaster)
Create association with a FileMaster, needed by FieldIo.
FIT & fieldIo()
Get the FieldIo by non-const reference.
Domain()
Constructor.
Basis< D > & basis()
Get the Basis object by non-const reference.
void writeStars(std::string const &filename) const
Output information about stars and symmetrized basis functions.
virtual void readParameters(std::istream &in)
Read body of parameter block (without opening and closing lines).
FFT & fft()
Get the FFT by non-const reference.
void makeBasis()
Construct basis if not done already.
void writeGroup(std::string const &filename) const
Output all elements of the space group.
void readRGridFieldHeader(std::istream &in, int &nMonomer)
Read initialization data from header of an r-grid field file.
void writeWaves(std::string const &filename) const
Output information about waves.
A FileMaster manages input and output files for a simulation.
Definition FileMaster.h:143
ScalarParam< Type > & read(std::istream &in, const char *label, Type &value)
Add and read a new required ScalarParam < Type > object.
void setClassName(const char *className)
Set class name string.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
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
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
void readFieldHeader(std::istream &in, int &ver1, int &ver2, UnitCell< D > &cell, std::string &groupName, int &nMonomer)
Read common part of field header (fortran PSCF format).
Periodic fields and crystallography.
Definition complex.cpp:11
Class templates for real-valued periodic fields.
PSCF package top-level namespace.