PSCF v1.4.0
rpc/field/FieldIo.tpp
1#ifndef RPC_FIELD_IO_TPP
2#define RPC_FIELD_IO_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 "FieldIo.h" // class header
12
13#include <prdc/cpu/RFieldComparison.h>
14#include <pscf/cpu/complex.h>
15
16#include <rp/field/FieldIo.tpp> // base class template implementation
17
18namespace Pscf {
19namespace Rpc {
20
21 using namespace Util;
22 using namespace Pscf::Prdc;
23 using namespace Pscf::Prdc::Cpu;
24
25 /*
26 * Read an array of fields in r-grid format.
27 */
28 template <int D>
30 std::istream &in,
31 DArray< RField<D> >& fields,
32 UnitCell<D>& unitCell) const
33 {
34 // Read header
35 int nMonomer;
36 bool isSymmetric;
37 Base::readFieldHeader(in, nMonomer, unitCell, isSymmetric);
38 readMeshDimensions(in, Base::mesh().dimensions());
39 checkAllocateFields(fields, nMonomer, Base::mesh().dimensions());
40
41 // Read data
42 // Rpg:: Allocate host arrays
43 Prdc::readRGridData(in, fields, nMonomer, Base::mesh().dimensions());
44 // Rpg:: Copy host -> device
45
46 return isSymmetric;
47 }
48
49 /*
50 * Read the data section of an array of fields in r-grid format.
51 */
52 template <int D>
54 std::istream& in,
55 DArray< RField<D> >& fields,
56 int nMonomer) const
57 {
58 checkAllocateFields(fields, nMonomer, Base::mesh().dimensions());
59 // Rpg:: Allocate host arrays
60 Prdc::readRGridData(in, fields, nMonomer, Base::mesh().dimensions());
61 // Rpg:: Copy host -> device
62 }
63
64 /*
65 * Read a single field in r-grid format.
66 */
67 template <int D>
69 std::istream &in,
70 RField<D> & field,
71 UnitCell<D>& unitCell) const
72 {
73 // Read header
74 int nMonomer;
75 bool isSymmetric;
76 Base::readFieldHeader(in, nMonomer, unitCell, isSymmetric);
77 UTIL_CHECK(nMonomer == 1);
78 readMeshDimensions(in, Base::mesh().dimensions());
79
80 // Read data
81 // Rpg:: Allocate host arrays
82 checkAllocateField(field, Base::mesh().dimensions());
83 Prdc::readRGridData(in, field, Base::mesh().dimensions());
84 // Rpg:: Copy host -> device
85
86 return isSymmetric;
87 }
88
89 /*
90 * Write an array of fields in r-grid format.
91 */
92 template <int D>
94 std::ostream &out,
95 DArray< RField<D> > const & fields,
96 UnitCell<D> const & unitCell,
97 bool writeHeader,
98 bool isSymmetric,
99 bool writeMeshSize) const
100 {
101 // Inspect fields array, infer nMonomer and meshDimensions
102 int nMonomer;
103 IntVec<D> meshDimensions;
104 inspectFields(fields, nMonomer, meshDimensions);
105
106 // Write header
107 if (writeHeader){
108 Base::writeFieldHeader(out, nMonomer, unitCell, isSymmetric);
109 }
110 if (writeMeshSize){
111 writeMeshDimensions(out, meshDimensions);
112 }
113
114 // Write data section
115 // Rpg:: Allocate host arrays
116 // Rpg:: Copy device -> host
117 Prdc::writeRGridData(out, fields, nMonomer, meshDimensions);
118 }
119
120 /*
121 * Write a single field in r-grid format.
122 */
123 template <int D>
125 std::ostream &out,
126 RField<D> const & field,
127 UnitCell<D> const & unitCell,
128 bool writeHeader,
129 bool isSymmetric) const
130 {
131 IntVec<D> meshDimensions = field.meshDimensions();
132
133 // Write header
134 if (writeHeader) {
135 Base::writeFieldHeader(out, 1, unitCell, isSymmetric);
136 writeMeshDimensions(out, meshDimensions);
137 }
138
139 // Write data
140 // Rpg:: Allocate host array
141 // Rpg:: Copy device -> host
142 Prdc::writeRGridData(out, field, meshDimensions);
143 }
144
145 /*
146 * Read an array of fields in k-grid format
147 */
148 template <int D>
150 std::istream &in,
151 DArray< RFieldDft<D> >& fields,
152 UnitCell<D>& unitCell) const
153 {
154 // Read header
155 int nMonomer;
156 bool isSymmetric;
157 Base::readFieldHeader(in, nMonomer, unitCell, isSymmetric);
158 readMeshDimensions(in, Base::mesh().dimensions());
159
160 checkAllocateFields(fields, nMonomer, Base::mesh().dimensions());
161 IntVec<D> dftDimensions = fields[0].dftDimensions();
162
163 // Read data
164 // Rpg:: Allocate host arrays
165 Prdc::readKGridData(in, fields, nMonomer, dftDimensions);
166 // Rpg:: Copy host -> device
167 }
168
169 /*
170 * Write an array of fields in k-grid format
171 */
172 template <int D>
174 std::ostream &out,
175 DArray< RFieldDft<D> > const & fields,
176 UnitCell<D> const & unitCell,
177 bool isSymmetric) const
178 {
179 // Inspect fields array - infer nMonomer and dimensions
180 int nMonomer;
181 IntVec<D> meshDimensions;
182 inspectFields(fields, nMonomer, meshDimensions);
183 IntVec<D> dftDimensions = fields[0].dftDimensions();
184
185 // Write file
186 Base::writeFieldHeader(out, nMonomer, unitCell, isSymmetric);
187 writeMeshDimensions(out, meshDimensions);
188
189 // Write data
190 // Rpg:: Allocate host arrays
191 // Rpg:: Copy device -> host
192 Prdc::writeKGridData(out, fields, nMonomer, dftDimensions);
193 }
194
195 /*
196 * Convert an array of fields from basis to k-grid format.
197 */
198 template <int D>
200 DArray<double> const & in,
201 RFieldDft<D>& out) const
202 {
203 // Rpg: Allocate host array
205 // Rpg: Copy host -> device
206 }
207
208 /*
209 * Convert an array of fields from k-grid to basis format.
210 */
211 template <int D>
213 RFieldDft<D> const & in,
214 DArray<double>& out,
215 bool checkSymmetry,
216 double epsilon) const
217 {
218 // Rpg: Allocate host arrays
219 // Rpg: Copy device -> host
221 checkSymmetry, epsilon);
222 }
223
224 /*
225 * Test if an real field DFT has the declared space group symmetry.
226 */
227 template <int D>
229 RFieldDft<D> const & in,
230 double epsilon,
231 bool verbose) const
232 {
233 // Rpg:: Allocate host array
234 // Rpg: Copy device -> host
236 epsilon, verbose);
237 }
238
239 /*
240 * Compare two fields in r-grid format, output report to Log file.
241 */
242 template <int D>
244 DArray< RField<D> > const & field2)
245 const
246 {
247 RFieldComparison<D> comparison;
248 comparison.compare(field1, field2);
249
250 Log::file() << "\n Real-space field comparison results"
251 << std::endl;
252 Log::file() << " Maximum Absolute Difference: "
253 << comparison.maxDiff() << std::endl;
254 Log::file() << " Root-Mean-Square Difference: "
255 << comparison.rmsDiff() << "\n" << std::endl;
256 }
257
258 /*
259 * Multiply a field in r-grid format by a constant factor.
260 */
261 template <int D>
263 RField<D> & field,
264 double factor) const
265 {
266 int n = field.capacity();
267 for (int i = 0; i < n; ++i) {
268 field[i] *= factor;
269 }
270 }
271
272 /*
273 * Replicate the unit cell for an array of r-grid fields.
274 */
275 template <int D>
277 std::ostream &out,
278 DArray< RField<D> > const & fields,
279 UnitCell<D> const & unitCell,
280 IntVec<D> const & replicas) const
281
282 {
283 // Inspect fields to obtain nMonomer and meshDimensions
284 int nMonomer;
285 IntVec<D> meshDimensions;
286 inspectFields(fields, nMonomer, meshDimensions);
287
288 // Rpg: Allocate hostArrays
289 // Rpg: Copy device -> host
290 Prdc::replicateUnitCell(out, fields, meshDimensions,
291 unitCell, replicas);
292 }
293
294 /*
295 * Expand spatial dimension of an array of r-grid fields.
296 */
297 template <int D>
299 std::ostream &out,
300 DArray< RField<D> > const & fields,
301 UnitCell<D> const & unitCell,
302 int d,
303 DArray<int> const& newGridDimensions) const
304 {
305 IntVec<D> meshDimensions = fields[0].meshDimensions();
306
307 // Rpg: Allocate hostArrays
308 // Rpg: Copy device -> host
309 Prdc::expandRGridDimension(out, fields, meshDimensions,
310 unitCell, d, newGridDimensions);
311 }
312
313}
314}
315#endif
double rmsDiff() const
Return the precomputed root-mean-squared difference.
double compare(FT const &a, FT const &b)
Compare individual fields.
double maxDiff() const
Return the precomputed maximum element-by-element difference.
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Comparator for fields in real-space (r-grid) format.
Fourier transform of a real field on an FFT mesh.
IntVec< D > const & dftDimensions() const
Return vector of dft (Fourier) grid dimensions by constant reference.
Field of real double precision values on an FFT mesh.
Definition cpu/RField.h:27
const IntVec< D > & meshDimensions() const
Return mesh dimensions by constant reference.
Definition cpu/RField.h:111
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition UnitCell.h:56
void writeFieldHeader(std::ostream &out, int nMonomer, UnitCell< D > const &unitCell, bool isSymmetric=true) const
void readFieldHeader(std::istream &in, int &nMonomer, UnitCell< D > &unitCell, bool &isSymmetric) const
void expandRGridDimension(std::ostream &out, DArray< RField< D > > const &fields, UnitCell< D > const &unitCell, int d, DArray< int > const &newGridDimensions) const override
Expand spatial dimension of an array of r-grid fields.
void replicateUnitCell(std::ostream &out, DArray< RField< D > > const &fields, UnitCell< D > const &unitCell, IntVec< D > const &replicas) const override
Write r-grid fields in a replicated unit cell to std::ostream.
bool hasSymmetry(RFieldDft< D > const &in, double epsilon=1.0e-8, bool verbose=true) const override
Check if a k-grid field has the declared space group symmetry.
void compareFieldsRGrid(DArray< RField< D > > const &field1, DArray< RField< D > > const &field2) const override
Compare two fields in r-grid format, output a report.
void scaleFieldRGrid(RField< D > &field, double factor) const override
Rescale a single r-grid field by a scalar factor.
void writeFieldsKGrid(std::ostream &out, DArray< RFieldDft< D > > const &fields, UnitCell< D > const &unitCell, bool isSymmetric=true) const override
Write array of RFieldDft objects (k-space fields) to file.
bool readFieldsRGrid(std::istream &in, DArray< RField< D > > &fields, UnitCell< D > &unitCell) const override
Read array of RField objects (r-grid fields) from a stream.
void convertBasisToKGrid(DArray< double > const &components, RFieldDft< D > &dft) const override
Convert a field from symmetrized basis to Fourier grid (k-grid).
void readFieldsRGridData(std::istream &in, DArray< RField< D > > &fields, int nMonomer) const override
Read data for an array of r-grid fields, with no header section.
void readFieldsKGrid(std::istream &in, DArray< RFieldDft< D > > &fields, UnitCell< D > &unitCell) const override
Read array of RFieldDft objects (k-space fields) from a stream.
void convertKGridToBasis(RFieldDft< D > const &in, DArray< double > &out, bool checkSymmetry=true, double epsilon=1.0e-8) const override
Convert a field from Fourier (k-grid) to symmetrized basis form.
void writeFieldsRGrid(std::ostream &out, DArray< RField< D > > const &fields, UnitCell< D > const &unitCell, bool writeHeader=true, bool isSymmetric=true, bool writeMeshSize=true) const override
Write array of RField objects (fields on r-space grid) to a stream.
void writeFieldRGrid(std::ostream &out, RField< D > const &field, UnitCell< D > const &unitCell, bool writeHeader=true, bool isSymmetric=true) const override
Write a single RField (field on an r-space grid) to a stream.
bool readFieldRGrid(std::istream &in, RField< D > &field, UnitCell< D > &unitCell) const override
Read a single RField (field on an r-space grid) from a stream.
int capacity() const
Return allocated size.
Definition Array.h:144
Dynamically allocatable contiguous array template.
Definition DArray.h:32
static std::ostream & file()
Get log ostream by reference.
Definition Log.cpp:59
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
void replicateUnitCell(IntVec< 1 > const &replicas, UnitCell< 1 > const &cellIn, UnitCell< 1 > &cellOut)
Create a replicated UnitCell<1>.
void writeKGridData(std::ostream &out, DArray< AT > const &fields, int nMonomer, IntVec< D > const &dftDimensions)
Write data for array of k-grid fields, with no header section.
bool hasSymmetry(AT const &in, Basis< D > const &basis, IntVec< D > const &dftDimensions, double epsilon=1.0e-8, bool verbose=true)
Check if a k-grid field has the declared space group symmetry.
void inspectFields(DArray< FT > const &fields, int &nMonomer, IntVec< D > &dimensions)
Inspect dimensions of a DArray of fields, each of type FT.
void readKGridData(std::istream &in, DArray< AT > &fields, int nMonomer, IntVec< D > const &dftDimensions)
Read data for array of k-grid fields, with no header section.
void convertBasisToKGrid(DArray< double > const &components, AT &dft, Basis< D > const &basis, IntVec< D > const &dftDimensions)
Convert a real field from symmetrized basis to Fourier grid.
void writeMeshDimensions(std::ostream &out, IntVec< D > const &meshDimensions)
Write mesh dimensions to a field file header.
void expandRGridDimension(std::ostream &out, DArray< AT > const &fields, IntVec< D > const &meshDimensions, UnitCell< D > const &unitCell, int d, DArray< int > newGridDimensions)
Expand the dimensionality of space from D to d.
Definition rFieldIo.tpp:971
void writeRGridData(std::ostream &out, DArray< AT > const &fields, int nMonomer, IntVec< D > const &dimensions)
Write data for array of r-grid fields, with no header section.
Definition rFieldIo.tpp:78
void convertKGridToBasis(AT const &in, DArray< double > &out, Basis< D > const &basis, IntVec< D > const &dftDimensions, bool checkSymmetry=true, double epsilon=1.0e-8)
Convert a real field from Fourier grid to symmetrized basis.
void readRGridData(std::istream &in, DArray< AT > &fields, int nMonomer, IntVec< D > const &dimensions)
Read data for array of r-grid fields, with no header section.
Definition rFieldIo.tpp:38
void readMeshDimensions(std::istream &in, IntVec< D > const &meshDimensions)
Read mesh dimensions from a field file header.
void checkAllocateFields(DArray< FT > &fields, int nMonomer, IntVec< D > const &dimensions)
Check allocation of an array of fields, allocate if necessary.
void checkAllocateField(FT &field, IntVec< D > const &dimensions)
Check allocation of a single field, allocate if necessary.
Fields and FFTs for periodic boundary conditions (CPU)
Definition complex.cpp:12
Periodic fields and crystallography.
Definition complex.cpp:11
Real periodic fields, SCFT and PS-FTS (CPU).
Definition param_pc.dox:2
PSCF package top-level namespace.