PSCF v1.2
rpg/field/FieldIo.tpp
1#ifndef RPG_FIELD_IO_TPP
2#define RPG_FIELD_IO_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field Theory
6*
7* Copyright 2016 - 2022, 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
13#include <rpg/field/HostDArrayComplex.h>
14
15#include <pscf/math/complex.h>
16
17#include <prdc/field/FieldIoReal.tpp> // base class implementation
18#include <prdc/field/fieldIoUtil.h>
19#include <prdc/field/fieldArrayUtil.h>
20#include <prdc/crystal/fieldHeader.h>
21#include <prdc/crystal/Basis.h>
22#include <prdc/crystal/UnitCell.h>
23#include <prdc/cuda/types.h>
24#include <prdc/cuda/complex.h>
25#include <prdc/cuda/resources.h>
26
27#include <pscf/mesh/Mesh.h>
28#include <pscf/math/IntVec.h>
29#include <pscf/cuda/HostDArray.h>
30
31
32namespace Pscf {
33namespace Rpg {
34
35 using namespace Util;
36 using namespace Pscf;
37 using namespace Pscf::Prdc;
38 using namespace Pscf::Prdc::Cuda;
39
40 /*
41 * Constructor.
42 */
43 template <int D>
45 : FieldIoReal< D, Prdc::Cuda::RField<D>, Prdc::Cuda::RFieldDft<D>, Prdc::Cuda::FFT<D> >()
46 {}
47
48 /*
49 * Destructor.
50 */
51 template <int D>
54
55 /*
56 * Read an array of fields in r-grid format.
57 */
58 template <int D>
60 std::istream &in,
61 DArray<RField<D> >& fields,
62 UnitCell<D>& unitCell) const
63 {
64 // Read header
65 int nMonomer;
66 bool isSymmetric;
67 readFieldHeader(in, nMonomer, unitCell, isSymmetric);
68 readMeshDimensions(in, mesh().dimensions());
69 checkAllocateFields(fields, nMonomer, mesh().dimensions());
70
71 // Allocate host arrays
73 allocateArrays(hostFields, nMonomer, mesh().size());
74
75 // Read data
76 Prdc::readRGridData(in, hostFields, nMonomer, mesh().dimensions());
77
78 // Copy device <- host
79 copyArrays(fields, hostFields);
80 }
81
82 /*
83 * Read the data section of an array of fields in r-grid format.
84 */
85 template <int D>
87 std::istream& in,
88 DArray< RField<D> >& fields,
89 int nMonomer) const
90 {
91 checkAllocateFields(fields, nMonomer, mesh().dimensions());
92
93 // Allocate host arrays
95 allocateArrays(hostFields, nMonomer, mesh().size());
96
97 // Read data section of file
98 Prdc::readRGridData(in, hostFields, nMonomer, mesh().dimensions());
99
100 // Copy device <- host
101 copyArrays(fields, hostFields);
102 }
103
104 /*
105 * Read a single field in r-grid format.
106 */
107 template <int D>
109 std::istream &in,
110 RField<D> & field,
111 UnitCell<D>& unitCell) const
112 {
113
114 // Read header
115 int nMonomer;
116 bool isSymmetric;
117 readFieldHeader(in, nMonomer, unitCell, isSymmetric);
118 UTIL_CHECK(nMonomer == 1);
119 readMeshDimensions(in, mesh().dimensions());
120 checkAllocateField(field, mesh().dimensions());
121
122 // Allocate host field
123 HostDArray<cudaReal> hostField;
124 hostField.allocate(mesh().size());
125
126 // Read data section with one field
127 Prdc::readRGridData(in, hostField, mesh().dimensions());
128
129 // Copy device <- host
130 field = hostField;
131 }
132
133 /*
134 * Write an array of fields in r-grid format.
135 */
136 template <int D>
138 std::ostream &out,
139 DArray<RField<D> > const & fields,
140 UnitCell<D> const & unitCell,
141 bool writeHeader,
142 bool isSymmetric,
143 bool writeMeshSize) const
144 {
145 // Inspect fields array, infer nMonomer and meshDimensions
146 int nMonomer;
147 IntVec<D> meshDimensions;
148 inspectFields(fields, nMonomer, meshDimensions);
149
150 // Write header
151 if (writeHeader){
152 writeFieldHeader(out, nMonomer, unitCell, isSymmetric);
153 }
154 if (writeMeshSize){
155 writeMeshDimensions(out, meshDimensions);
156 }
157
158 // Copy field data to host container
159 DArray< HostDArray<cudaReal> > hostFields;
160 allocateArrays(hostFields, nMonomer, mesh().size());
161 copyArrays(hostFields, fields);
162
163 // Write data section
164 Prdc::writeRGridData(out, hostFields, nMonomer, meshDimensions);
165 }
166
167 /*
168 * Write a single field in r-grid format.
169 */
170 template <int D>
172 std::ostream &out,
173 RField<D> const & field,
174 UnitCell<D> const & unitCell,
175 bool writeHeader,
176 bool isSymmetric) const
177 {
178 IntVec<D> meshDimensions = field.meshDimensions();
179
180 // Write header
181 if (writeHeader) {
182 writeFieldHeader(out, 1, unitCell, isSymmetric);
183 writeMeshDimensions(out, meshDimensions);
184 }
185
186 // Copy field (device) to hostField
187 HostDArray<cudaReal> hostField;
188 hostField.allocate(mesh().size());
189 hostField = field;
190
191 // Write data from hostField
192 Prdc::writeRGridData(out, hostField, meshDimensions);
193 }
194
195 /*
196 * Read an array of fields in k-grid format
197 */
198 template <int D>
200 std::istream &in,
201 DArray<RFieldDft<D> >& fields,
202 UnitCell<D>& unitCell) const
203 {
204 // Read header
205 int nMonomer;
206 bool isSymmetric;
207 readFieldHeader(in, nMonomer, unitCell, isSymmetric);
208 readMeshDimensions(in, mesh().dimensions());
209 checkAllocateFields(fields, nMonomer, mesh().dimensions());
210 IntVec<D> dftDimensions = fields[0].dftDimensions();
211 int capacity = fields[0].capacity();
212
213 // Allocate hostFields
215 allocateArrays(hostFields, nMonomer, capacity);
216
217 // Read data into hostFields
218 Prdc::readKGridData(in, hostFields, nMonomer, dftDimensions);
219
220 // Copy device <- host
221 copyArrays(fields, hostFields);
222 }
223
224 /*
225 * Write an array of fields in k-grid format
226 */
227 template <int D>
229 std::ostream &out,
230 DArray<RFieldDft<D> > const & fields,
231 UnitCell<D> const & unitCell,
232 bool isSymmetric) const
233 {
234 // Inspect fields array - infer nMonomer and dimensions
235 int nMonomer;
236 IntVec<D> meshDimensions;
237 inspectFields(fields, nMonomer, meshDimensions);
238 IntVec<D> dftDimensions = fields[0].dftDimensions();
239 int capacity = fields[0].capacity();
240
241 // Write header
242 writeFieldHeader(out, nMonomer, unitCell, isSymmetric);
243 writeMeshDimensions(out, meshDimensions);
244
245 // Copy data from device to hostFields
247 allocateArrays(hostFields, nMonomer, capacity);
248 copyArrays(hostFields, fields);
249
250 // Write data from hostFields
251 Prdc::writeKGridData(out, hostFields, nMonomer, dftDimensions);
252 }
253
254 /*
255 * Write a fields from basis to k-grid format.
256 */
257 template <int D>
259 DArray<double> const & in,
260 RFieldDft<D>& out) const
261 {
262 // Allocate hostField
263 HostDArrayComplex hostField;
264 hostField.allocate(out.capacity());
265
266 // Convert basis to k-grid on hostField
267 Prdc::convertBasisToKGrid(in, hostField, basis(),
268 out.dftDimensions());
269
270 // Copy out (device) <- host
271 out = hostField;
272 }
273
274 /*
275 * Write an array of fields from k-grid to basis format.
276 */
277 template <int D>
279 RFieldDft<D> const & in,
280 DArray<double>& out,
281 bool checkSymmetry,
282 double epsilon) const
283 {
284 // Copy k-grid input to hostField
285 HostDArrayComplex hostField;
286 hostField.allocate(in.capacity());
287 hostField = in;
288
289 // Convert k-grid host field to basis format
290 Prdc::convertKGridToBasis(hostField, out, basis(),
291 in.dftDimensions(),
292 checkSymmetry, epsilon);
293 }
294
295 /*
296 * Test if an real field DFT has the declared space group symmetry.
297 */
298 template <int D>
300 RFieldDft<D> const & in,
301 double epsilon,
302 bool verbose) const
303 {
304 // Copy k-grid input to hostField
305 HostDArrayComplex hostField;
306 hostField.allocate(in.capacity());
307 hostField = in;
308
309 // Check symmetry of hostField
310 return Prdc::hasSymmetry(hostField, basis(), in.dftDimensions(),
311 epsilon, verbose);
312 }
313
314 /*
315 * Test if an real field DFT has the declared space group symmetry.
316 */
317 template <int D>
319 DArray<double> & field,
320 double factor) const
321 {
322 int n = field.capacity();
323 for (int i = 0; i < n; ++i) {
324 field[i] *= factor;
325 }
326 }
327
328 /*
329 * Test if an real field DFT has the declared space group symmetry.
330 */
331 template <int D>
333 RField<D> & field,
334 double factor) const
335 {
336 VecOp::mulEqS(field, factor);
337 }
338
339 /*
340 * Replicate the unit cell for an array of r-grid fields.
341 */
342 template <int D>
344 std::ostream &out,
345 DArray< RField<D> > const & fields,
346 UnitCell<D> const & unitCell,
347 IntVec<D> const & replicas) const
348
349 {
350 // Inspect fields to obtain nMonomer and meshDimensions
351 int nMonomer;
352 IntVec<D> meshDimensions;
353 inspectFields(fields, nMonomer, meshDimensions);
354 int capacity = fields[0].capacity();
355
356 // Copy k-grid input to hostField
357 DArray< HostDArray<cudaReal> > hostFields;
358 allocateArrays(hostFields, nMonomer, capacity);
359 copyArrays(hostFields, fields);
360
361 Prdc::replicateUnitCell(out, hostFields, meshDimensions,
362 unitCell, replicas);
363 }
364
365 /*
366 * Expand spatial dimension of an array of r-grid fields.
367 */
368 template <int D>
370 std::ostream &out,
371 DArray< RField<D> > const & fields,
372 UnitCell<D> const & unitCell,
373 int d,
374 DArray<int> const& newGridDimensions) const
375 {
376 // Inspect fields to obtain nMonomer and meshDimensions
377 int nMonomer;
378 IntVec<D> meshDimensions;
379 inspectFields(fields, nMonomer, meshDimensions);
380 int capacity = fields[0].capacity();
381
382 // Copy k-grid input fields to hostFields
383 DArray< HostDArray<cudaReal> > hostFields;
384 allocateArrays(hostFields, nMonomer, capacity);
385 copyArrays(hostFields, fields);
386
387 Prdc::expandRGridDimension(out, hostFields, meshDimensions,
388 unitCell, d, newGridDimensions);
389 }
390
391}
392}
393#endif
Template for dynamic array stored in host CPU memory.
Definition HostDArray.h:43
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Fourier transform wrapper.
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.
const IntVec< D > & meshDimensions() const
Return mesh dimensions by constant reference.
Definition cpu/RField.h:112
File input/output operations and format conversions for fields.
Definition FieldIoReal.h:68
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition rpg/System.h:34
void writeFieldsKGrid(std::ostream &out, DArray< RFieldDft< D > > const &fields, UnitCell< D > const &unitCell, bool isSymmetric=true) const
Write array of RFieldDft objects (k-space fields) to file.
FieldIo()
Default constructor.
void expandRGridDimension(std::ostream &out, DArray< RField< D > > const &fields, UnitCell< D > const &unitCell, int d, DArray< int > const &newGridDimensions) const
Expand spatial dimension of an array of r-grid fields.
void readFieldsKGrid(std::istream &in, DArray< RFieldDft< D > > &fields, UnitCell< D > &unitCell) const
Read array of RFieldDft objects (k-space fields) from a stream.
void replicateUnitCell(std::ostream &out, DArray< RField< D > > const &fields, UnitCell< D > const &unitCell, IntVec< D > const &replicas) const
Write r-grid fields in a replicated unit cell to std::ostream.
void scaleFieldBasis(DArray< double > &field, double factor) const
Rescale a single field in basis format by a scalar factor.
void scaleFieldRGrid(RField< D > &field, double factor) const
Rescale a single r-grid field by a scalar factor.
bool hasSymmetry(RFieldDft< D > const &in, double epsilon=1.0e-8, bool verbose=true) const
Check if a k-grid field has the declared space group symmetry.
void readFieldsRGridData(std::istream &in, DArray< RField< D > > &fields, int nMonomer) const
Read data for an array of r-grid fields, with no header section.
void writeFieldRGrid(std::ostream &out, RField< D > const &field, UnitCell< D > const &unitCell, bool writeHeader=true, bool isSymmetric=true) const
Write a single RField (field on an r-space grid) to a stream.
void convertKGridToBasis(RFieldDft< D > const &in, DArray< double > &out, bool checkSymmetry=true, double epsilon=1.0e-8) const
Convert a field from Fourier (k-grid) to symmetrized basis form.
void readFieldRGrid(std::istream &in, RField< D > &field, UnitCell< D > &unitCell) const
Read a single RField (field on an r-space grid) from a stream.
void writeFieldsRGrid(std::ostream &out, DArray< RField< D > > const &fields, UnitCell< D > const &unitCell, bool writeHeader=true, bool isSymmetric=true, bool writeMeshSize=true) const
Write array of RField objects (fields on r-space grid) to a stream.
void convertBasisToKGrid(DArray< double > const &components, RFieldDft< D > &dft) const
Convert a field from symmetrized basis to Fourier grid (k-grid).
void readFieldsRGrid(std::istream &in, DArray< RField< D > > &fields, UnitCell< D > &unitCell) const
Read array of RField objects (r-grid fields) from a stream.
HostDArray containing cudaComplex elements.
int capacity() const
Return allocated size.
Definition Array.h:159
Dynamically allocatable contiguous array template.
void allocate(int capacity)
Allocate the underlying C array.
Definition DArray.h:199
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
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 replicateUnitCell(std::ostream &out, DArray< AT > const &fields, IntVec< D > const &meshDimensions, UnitCell< D > const &unitCell, IntVec< D > const &replicas)
Write r-grid fields in a replicated unit cell to std::ostream.
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.
void mulEqS(DeviceArray< cudaReal > &a, cudaReal const b, const int beginIdA, const int n)
Vector multiplication in-place, a[i] *= b, kernel wrapper (cudaReal).
Definition VecOp.cu:1875
Fields, FFTs, and utilities for periodic boundary conditions (CUDA)
Definition CField.cu:12
Periodic fields and crystallography.
Definition CField.cpp:11
PSCF package top-level namespace.
Definition param_pc.dox:1
Utility classes for scientific computation.