PSCF v1.3
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"
12#include <prdc/field/FieldIoReal.tpp> // base class implementation
13
14#include <rpc/field/Domain.h>
15
16#include <prdc/field/fieldIoUtil.h>
17#include <prdc/crystal/Basis.h>
18#include <prdc/crystal/UnitCell.h>
19#include <prdc/cpu/RFieldComparison.h>
20#include <prdc/cpu/complex.h>
21#include <prdc/cpu/types.h>
22
23#include <pscf/mesh/Mesh.h>
24#include <pscf/math/IntVec.h>
25
26namespace Pscf {
27namespace Rpc {
28
29 using namespace Util;
30 using namespace Pscf::Prdc;
31 using namespace Pscf::Prdc::Cpu;
32
33 /*
34 * Read an array of fields in r-grid format.
35 */
36 template <int D>
38 std::istream &in,
39 DArray<RField<D> >& fields,
40 UnitCell<D>& unitCell) const
41 {
42 // Read header
43 int nMonomer;
44 bool isSymmetric;
45 readFieldHeader(in, nMonomer, unitCell, isSymmetric);
46 readMeshDimensions(in, mesh().dimensions());
47 checkAllocateFields(fields, nMonomer, mesh().dimensions());
48
49 // Read data
50 // Rpg:: Allocate host arrays
51 Prdc::readRGridData(in, fields, nMonomer, mesh().dimensions());
52 // Rpg:: Copy host -> device
53
54 return isSymmetric;
55 }
56
57 /*
58 * Read the data section of an array of fields in r-grid format.
59 */
60 template <int D>
62 std::istream& in,
63 DArray< RField<D> >& fields,
64 int nMonomer) const
65 {
66 checkAllocateFields(fields, nMonomer, mesh().dimensions());
67 // Rpg:: Allocate host arrays
68 Prdc::readRGridData(in, fields, nMonomer, mesh().dimensions());
69 // Rpg:: Copy host -> device
70 }
71
72 /*
73 * Read a single field in r-grid format.
74 */
75 template <int D>
77 std::istream &in,
78 RField<D> & field,
79 UnitCell<D>& unitCell) const
80 {
81 // Read header
82 int nMonomer;
83 bool isSymmetric;
84 readFieldHeader(in, nMonomer, unitCell, isSymmetric);
85 UTIL_CHECK(nMonomer == 1);
86 readMeshDimensions(in, mesh().dimensions());
87
88 // Read data
89 // Rpg:: Allocate host arrays
90 checkAllocateField(field, mesh().dimensions());
91 Prdc::readRGridData(in, field, mesh().dimensions());
92 // Rpg:: Copy host -> device
93
94 return isSymmetric;
95 }
96
97 /*
98 * Write an array of fields in r-grid format.
99 */
100 template <int D>
102 std::ostream &out,
103 DArray<RField<D> > const & fields,
104 UnitCell<D> const & unitCell,
105 bool writeHeader,
106 bool isSymmetric,
107 bool writeMeshSize) const
108 {
109 // Inspect fields array, infer nMonomer and meshDimensions
110 int nMonomer;
111 IntVec<D> meshDimensions;
112 inspectFields(fields, nMonomer, meshDimensions);
113
114 // Write header
115 if (writeHeader){
116 writeFieldHeader(out, nMonomer, unitCell, isSymmetric);
117 }
118 if (writeMeshSize){
119 writeMeshDimensions(out, meshDimensions);
120 }
121
122 // Write data section
123 // Rpg:: Allocate host arrays
124 // Rpg:: Copy device -> host
125 Prdc::writeRGridData(out, fields, nMonomer, meshDimensions);
126 }
127
128 /*
129 * Write a single field in r-grid format.
130 */
131 template <int D>
133 std::ostream &out,
134 RField<D> const & field,
135 UnitCell<D> const & unitCell,
136 bool writeHeader,
137 bool isSymmetric) const
138 {
139 IntVec<D> meshDimensions = field.meshDimensions();
140
141 // Write header
142 if (writeHeader) {
143 writeFieldHeader(out, 1, unitCell, isSymmetric);
144 writeMeshDimensions(out, meshDimensions);
145 }
146
147 // Write data
148 // Rpg:: Allocate host array
149 // Rpg:: Copy device -> host
150 Prdc::writeRGridData(out, field, meshDimensions);
151 }
152
153 /*
154 * Read an array of fields in k-grid format
155 */
156 template <int D>
158 std::istream &in,
159 DArray<RFieldDft<D> >& fields,
160 UnitCell<D>& unitCell) const
161 {
162 // Read header
163 int nMonomer;
164 bool isSymmetric;
165 readFieldHeader(in, nMonomer, unitCell, isSymmetric);
166 readMeshDimensions(in, mesh().dimensions());
167
168 checkAllocateFields(fields, nMonomer, mesh().dimensions());
169 IntVec<D> dftDimensions = fields[0].dftDimensions();
170
171 // Read data
172 // Rpg:: Allocate host arrays
173 Prdc::readKGridData(in, fields, nMonomer, dftDimensions);
174 // Rpg:: Copy host -> device
175 }
176
177 /*
178 * Write an array of fields in k-grid format
179 */
180 template <int D>
182 std::ostream &out,
183 DArray<RFieldDft<D> > const & fields,
184 UnitCell<D> const & unitCell,
185 bool isSymmetric) const
186 {
187 // Inspect fields array - infer nMonomer and dimensions
188 int nMonomer;
189 IntVec<D> meshDimensions;
190 inspectFields(fields, nMonomer, meshDimensions);
191 IntVec<D> dftDimensions = fields[0].dftDimensions();
192
193 // Write file
194 writeFieldHeader(out, nMonomer, unitCell, isSymmetric);
195 writeMeshDimensions(out, meshDimensions);
196
197 // Write data
198 // Rpg:: Allocate host arrays
199 // Rpg:: Copy device -> host
200 Prdc::writeKGridData(out, fields, nMonomer, dftDimensions);
201 }
202
203 /*
204 * Convert an array of fields from basis to k-grid format.
205 */
206 template <int D>
208 DArray<double> const & in,
209 RFieldDft<D>& out) const
210 {
211 // Rpg: Allocate host array
213 // Rpg: Copy host -> device
214 }
215
216 /*
217 * Convert an array of fields from k-grid to basis format.
218 */
219 template <int D>
221 RFieldDft<D> const & in,
222 DArray<double>& out,
223 bool checkSymmetry,
224 double epsilon) const
225 {
226 // Rpg: Allocate host arrays
227 // Rpg: Copy device -> host
229 checkSymmetry, epsilon);
230 }
231
232 /*
233 * Test if an real field DFT has the declared space group symmetry.
234 */
235 template <int D>
237 RFieldDft<D> const & in,
238 double epsilon,
239 bool verbose) const
240 {
241 // Rpg:: Allocate host array
242 // Rpg: Copy device -> host
243 return Prdc::hasSymmetry(in, basis(), in.dftDimensions(),
244 epsilon, verbose);
245 }
246
247 /*
248 * Compare two fields in r-grid format, output report to Log file.
249 */
250 template <int D>
252 DArray< RField<D> > const & field2)
253 const
254 {
255 RFieldComparison<D> comparison;
256 comparison.compare(field1, field2);
257
258 Log::file() << "\n Real-space field comparison results"
259 << std::endl;
260 Log::file() << " Maximum Absolute Difference: "
261 << comparison.maxDiff() << std::endl;
262 Log::file() << " Root-Mean-Square Difference: "
263 << comparison.rmsDiff() << "\n" << std::endl;
264 }
265
266 /*
267 * Multiply a field in r-grid format by a constant factor.
268 */
269 template <int D>
271 RField<D> & field,
272 double factor) const
273 {
274 int n = field.capacity();
275 for (int i = 0; i < n; ++i) {
276 field[i] *= factor;
277 }
278 }
279
280 /*
281 * Replicate the unit cell for an array of r-grid fields.
282 */
283 template <int D>
285 std::ostream &out,
286 DArray< RField<D> > const & fields,
287 UnitCell<D> const & unitCell,
288 IntVec<D> const & replicas) const
289
290 {
291 // Inspect fields to obtain nMonomer and meshDimensions
292 int nMonomer;
293 IntVec<D> meshDimensions;
294 inspectFields(fields, nMonomer, meshDimensions);
295
296 // Rpg: Allocate hostArrays
297 // Rpg: Copy device -> host
298 Prdc::replicateUnitCell(out, fields, meshDimensions,
299 unitCell, replicas);
300 }
301
302 /*
303 * Expand spatial dimension of an array of r-grid fields.
304 */
305 template <int D>
307 std::ostream &out,
308 DArray< RField<D> > const & fields,
309 UnitCell<D> const & unitCell,
310 int d,
311 DArray<int> const& newGridDimensions) const
312 {
313 IntVec<D> meshDimensions = fields[0].meshDimensions();
314
315 // Rpg: Allocate hostArrays
316 // Rpg: Copy device -> host
317 Prdc::expandRGridDimension(out, fields, meshDimensions,
318 unitCell, d, newGridDimensions);
319 }
320
321}
322}
323#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:29
const IntVec< D > & meshDimensions() const
Return mesh dimensions by constant reference.
Definition cpu/RField.h:112
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition UnitCell.h:56
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).
Basis< D > const & basis() const
Get the associated Basis by const reference.
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.
Mesh< D > const & mesh() const
Get spatial discretization mesh by const reference.
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:159
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 writeFieldHeader(std::ostream &out, int ver1, int ver2, UnitCell< D > const &cell, std::string const &groupName, int nMonomer)
Write common part of field header (fortran PSCF format).
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).
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.
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.
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.
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 CField.cpp:12
Periodic fields and crystallography.
Definition CField.cpp:11
Real periodic fields, SCFT and PS-FTS (CPU).
Definition param_pc.dox:2
PSCF package top-level namespace.
Definition param_pc.dox:1