1#ifndef RPC_FIELD_IO_REAL_TPP
2#define RPC_FIELD_IO_REAL_TPP
11#include "FieldIoReal.h"
13#include <prdc/field/fieldIoUtil.h>
14#include <prdc/crystal/fieldHeader.h>
16#include <prdc/crystal/shiftToMinimum.h>
17#include <prdc/crystal/UnitCell.h>
18#include <prdc/crystal/Basis.h>
19#include <prdc/crystal/SpaceGroup.h>
20#include <prdc/crystal/UnitCell.h>
22#include <pscf/mesh/Mesh.h>
23#include <pscf/mesh/MeshIterator.h>
24#include <pscf/mesh/MeshIteratorFortran.h>
25#include <pscf/math/IntVec.h>
27#include <util/containers/DArray.h>
28#include <util/misc/FileMaster.h>
29#include <util/misc/Log.h>
30#include <util/format/Str.h>
31#include <util/format/Int.h>
32#include <util/format/Dbl.h>
45 template <
int D,
class RFRT,
class RFKT,
class FFTT>
59 template <
int D,
class RFRT,
class RFKT,
class FFTT>
71 template <
int D,
class RFRT,
class RFKT,
class FFTT>
77 bool const & hasGroup,
78 std::string
const & groupName,
84 latticePtr_ = &lattice;
85 hasGroupPtr_ = &hasGroup;
86 groupNamePtr_ = &groupName;
94 template <
int D,
class RFRT,
class RFKT,
class FFTT>
97 { fileMasterPtr_ = &fileMaster; }
104 template <
int D,
class RFRT,
class RFKT,
class FFTT>
123 if (fields.isAllocated()) {
124 int nMonomerFields, fieldCapacity;
128 fields.allocate(nMonomer);
129 for (
int i = 0; i < nMonomer; ++i) {
130 fields[i].allocate(nBasisIn);
141 template <
int D,
class RFRT,
class RFKT,
class FFTT>
158 readFieldsBasis(in, fields, unitCell);
170 template <
int D,
class RFRT,
class RFKT,
class FFTT>
183 UTIL_CHECK(fieldCapacity <= basis().nBasis());
184 int nBasis = fieldCapacity;
187 bool isSymmetric =
true;
198 template <
int D,
class RFRT,
class RFKT,
class FFTT>
212 writeFieldsBasis(out, fields, unitCell);
220 template <
int D,
class RFRT,
class RFKT,
class FFTT>
222 DArray< DArray <double> >
const & in,
226 int nMonomer, nMonomerOut, capacity;
233 for (
int i = 0; i < nMonomer; ++i) {
238 template <
int D,
class RFRT,
class RFKT,
class FFTT>
241 DArray< DArray <double> > & out,
243 double epsilon)
const
246 int nMonomer, nMonomerOut, capacity;
253 for (
int i = 0; i < nMonomer; ++i) {
263 template <
int D,
class RFRT,
class RFKT,
class FFTT>
270 fft().forwardTransform(in, workDft_);
274 template <
int D,
class RFRT,
class RFKT,
class FFTT>
281 fft().inverseTransformUnsafe(workDft_, out);
284 template <
int D,
class RFRT,
class RFKT,
class FFTT>
286 DArray< DArray <double> >
const & in,
292 int n = in.capacity();
293 for (
int i = 0; i < n; ++i) {
295 fft().inverseTransformUnsafe(workDft_, out[i]);
299 template <
int D,
class RFRT,
class RFKT,
class FFTT>
304 double epsilon)
const
307 fft().forwardTransform(in, workDft_);
311 template <
int D,
class RFRT,
class RFKT,
class FFTT>
314 DArray< DArray <double> > & out,
316 double epsilon)
const
319 int nMonomer, nMonomerOut, capacity;
322 UTIL_CHECK(mesh().dimensions() == dimensions);
328 for (
int i = 0; i < nMonomer; ++i) {
329 fft().forwardTransform(in[i], workDft_);
339 template <
int D,
class RFRT,
class RFKT,
class FFTT>
346 for (
int i = 0; i < n; ++i) {
347 fft().inverseTransformSafe(in[i], out[i]);
354 template <
int D,
class RFRT,
class RFKT,
class FFTT>
356 RFKT
const & in, RFRT& out)
const
358 fft().inverseTransformSafe(in, out);
364 template <
int D,
class RFRT,
class RFKT,
class FFTT>
371 for (
int i = 0; i < n; ++i) {
372 fft().forwardTransform(in[i], out[i]);
379 template <
int D,
class RFRT,
class RFKT,
class FFTT>
384 fft().forwardTransform(in, out);
401 template <
int D,
class RFRT,
class RFKT,
class FFTT>
403 std::string filename,
409 fileMaster().openInputFile(filename, file);
410 readFieldsBasis(file, fields, unitCell);
417 template <
int D,
class RFRT,
class RFKT,
class FFTT>
419 std::string filename,
424 fileMaster().openInputFile(filename, file);
425 readFieldBasis(file, field, unitCell);
432 template <
int D,
class RFRT,
class RFKT,
class FFTT>
434 std::string filename,
439 fileMaster().openOutputFile(filename, file);
440 writeFieldsBasis(file, fields, unitCell);
447 template <
int D,
class RFRT,
class RFKT,
class FFTT>
449 std::string filename,
454 fileMaster().openOutputFile(filename, file);
455 writeFieldBasis(file, field, unitCell);
459 template <
int D,
class RFRT,
class RFKT,
class FFTT>
461 std::string filename,
466 fileMaster().openInputFile(filename, file);
467 readFieldsRGrid(file, fields, unitCell);
471 template <
int D,
class RFRT,
class RFKT,
class FFTT>
473 std::string filename,
478 fileMaster().openInputFile(filename, file);
479 readFieldRGrid(file, field, unitCell);
483 template <
int D,
class RFRT,
class RFKT,
class FFTT>
485 std::string filename,
488 bool isSymmetric)
const
491 fileMaster().openOutputFile(filename, file);
492 bool writeHeader =
true;
493 bool writeMeshSize =
true;
494 writeFieldsRGrid(file, fields, unitCell,
495 writeHeader, isSymmetric, writeMeshSize);
499 template <
int D,
class RFRT,
class RFKT,
class FFTT>
501 std::string filename,
504 bool isSymmetric)
const
507 fileMaster().openOutputFile(filename, file);
508 writeFieldRGrid(file, field, unitCell, isSymmetric);
512 template <
int D,
class RFRT,
class RFKT,
class FFTT>
514 std::string filename,
519 fileMaster().openInputFile(filename, file);
520 readFieldsKGrid(file, fields, unitCell);
524 template <
int D,
class RFRT,
class RFKT,
class FFTT>
526 std::string filename,
529 bool isSymmetric)
const
532 fileMaster().openOutputFile(filename, file);
533 writeFieldsKGrid(file, fields, unitCell, isSymmetric);
537 template <
int D,
class RFRT,
class RFKT,
class FFTT>
543 for (
int i = 0; i < n; ++i) {
544 scaleFieldBasis(fields[i], factor);
548 template <
int D,
class RFRT,
class RFKT,
class FFTT>
554 for (
int i = 0; i < n; ++i) {
555 scaleFieldRGrid(fields[i], factor);
559 template <
int D,
class RFRT,
class RFKT,
class FFTT>
561 std::string filename,
567 fileMaster().openOutputFile(filename, file);
572 template <
int D,
class RFRT,
class RFKT,
class FFTT>
574 std::string filename,
580 fileMaster().openOutputFile(filename, file);
591 template <
int D,
class RFRT,
class RFKT,
class FFTT>
596 bool & isSymmetric)
const
609 std::string groupNameIn;
612 groupNameIn, nMonomer);
623 if (lattice() != unitCell.lattice()) {
625 <<
"Error - Mismatched lattice types "
626 <<
"in FieldIo function readFieldHeader:\n"
627 <<
" FieldIo::lattice :" << lattice() <<
"\n"
628 <<
" Unit cell lattice :" << unitCell.lattice()
635 if (groupNameIn !=
"") {
645 if (groupNameIn != groupName()) {
647 <<
"Error - Mismatched group names in "
648 <<
"FieldIo member function readFieldHeader:\n"
649 <<
" FieldIo::groupName :" << groupName() <<
"\n"
650 <<
" Field file header :" << groupNameIn <<
"\n";
657 if (!basis().isInitialized()) {
658 basisPtr_->makeBasis(mesh(), unitCell, group());
666 template <
int D,
class RFRT,
class RFKT,
class FFTT>
671 bool isSymmetric)
const
675 std::string gName =
"";
702 template <
int D,
class RFRT,
class RFKT,
class FFTT>
707 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
712 template <
int D,
class RFRT,
class RFKT,
class FFTT>
717 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
722 template <
int D,
class RFRT,
class RFKT,
class FFTT>
727 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
732 template <
int D,
class RFRT,
class RFKT,
class FFTT>
739 bool writeMeshSize)
const
740 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
745 template <
int D,
class RFRT,
class RFKT,
class FFTT>
751 bool isSymmetric)
const
752 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
757 template <
int D,
class RFRT,
class RFKT,
class FFTT>
762 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
764 template <
int D,
class RFRT,
class RFKT,
class FFTT>
770 bool isSymmetric)
const
771 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
773 template <
int D,
class RFRT,
class RFKT,
class FFTT>
777 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
779 template <
int D,
class RFRT,
class RFKT,
class FFTT>
784 double epsilon)
const
785 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
790 template <
int D,
class RFRT,
class RFKT,
class FFTT>
795 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
797 template <
int D,
class RFRT,
class RFKT,
class FFTT>
801 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
803 template <
int D,
class RFRT,
class RFKT,
class FFTT>
807 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
809 template <
int D,
class RFRT,
class RFKT,
class FFTT>
815 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
820 template <
int D,
class RFRT,
class RFKT,
class FFTT>
827 {
UTIL_THROW(
"Unimplemented function in FieldIoReal base class"); }
An IntVec<D, T> is a D-component vector of elements of integer type T.
Description of a regular grid of points in a periodic domain.
Symmetry-adapted Fourier basis for pseudo-spectral scft.
FieldIoReal()
Constructor.
virtual void readFieldsRGridData(std::istream &in, DArray< RFRT > &fields, int nMonomer) const
Read data for array of r-grid fields, with no header section.
virtual void scaleFieldBasis(DArray< double > &field, double factor) const
Multiply a single field in basis format by a real scalar.
void scaleFieldsRGrid(DArray< RFRT > &fields, double factor) const
Scale an array of r-grid fields by a real scalar.
void writeFieldHeader(std::ostream &out, int nMonomer, UnitCell< D > const &unitCell, bool isSymmetric=true) const
Write header for field file (fortran pscf format)
virtual bool hasSymmetry(RFKT const &in, double epsilon=1.0e-8, bool verbose=true) const
Check if a k-grid field has the declared space group symmetry.
virtual void expandRGridDimension(std::ostream &out, DArray< RFRT > const &fields, UnitCell< D > const &unitCell, int d, DArray< int > const &newGridDimensions) const
Expand dimension of an array of r-grid fields, write to ostream.
virtual void writeFieldsRGrid(std::ostream &out, DArray< RFRT > 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 ostream.
virtual void replicateUnitCell(std::ostream &out, DArray< RFRT > const &fields, UnitCell< D > const &unitCell, IntVec< D > const &replicas) const
Write r-grid fields in a replicated unit cell to std::ostream.
virtual void convertBasisToKGrid(DArray< double > const &components, RFKT &dft) const
Convert a field from symmetrized basis to Fourier grid (k-grid).
virtual void convertKGridToBasis(RFKT 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.
virtual void scaleFieldRGrid(RFRT &field, double factor) const
Multiply a single field in r-grid format by a real scalar.
void convertBasisToRGrid(DArray< double > const &in, RFRT &out) const
Convert a field from symmetrized basis to spatial grid (r-grid).
virtual void readFieldRGrid(std::istream &in, RFRT &field, UnitCell< D > &unitCell) const
Read single RField (field on an r-space grid) from an istream.
virtual ~FieldIoReal()
Destructor.
virtual void writeFieldsKGrid(std::ostream &out, DArray< RFKT > const &fields, UnitCell< D > const &unitCell, bool isSymmetric=true) const
Write array of RFieldDft objects (k-space fields) to file.
void convertRGridToKGrid(DArray< RFRT > const &in, DArray< RFKT > &out) const
Convert fields from spatial grid (r-grid) to k-grid format.
virtual void writeFieldRGrid(std::ostream &out, RFRT const &field, UnitCell< D > const &unitCell, bool writeHeader=true, bool isSymmetric=true) const
Write a single RField (field on an r-space grid) to ostream.
void readFieldHeader(std::istream &in, int &nMonomer, UnitCell< D > &unitCell, bool &isSymmetric) const
Reader header of field file (fortran pscf format)
void setFileMaster(FileMaster const &fileMaster)
Create an association with a FileMaster.
void convertRGridToBasis(RFRT const &in, DArray< double > &out, bool checkSymmetry=true, double epsilon=1.0e-8) const
Convert a field from spatial grid (r-grid) to symmetrized basis.
void readFieldBasis(std::istream &in, DArray< double > &field, UnitCell< D > &unitCell) const
Read single concentration or chemical potential field from file.
void readFieldsBasis(std::istream &in, DArray< DArray< double > > &fields, UnitCell< D > &unitCell) const
Read concentration or chemical potential fields from file.
virtual void readFieldsRGrid(std::istream &in, DArray< RFRT > &fields, UnitCell< D > &unitCell) const
Read array of RField objects (r-grid fields) from an istream.
void scaleFieldsBasis(DArray< DArray< double > > &fields, double factor) const
Scale an array of fields in basis format by a real scalar.
void convertKGridToRGrid(DArray< RFKT > const &in, DArray< RFRT > &out) const
Convert fields from k-grid (DFT) to real space (r-grid) format.
void associate(Mesh< D > const &mesh, FFTT const &fft, typename UnitCell< D >::LatticeSystem const &lattice, bool const &hasGroup, std::string const &groupName, SpaceGroup< D > const &group, Basis< D > &basis)
Create association with other objects in parent Domain.
virtual void readFieldsKGrid(std::istream &in, DArray< RFKT > &fields, UnitCell< D > &unitCell) const
Read array of RFieldDft objects (k-space fields) from istream.
void writeFieldsBasis(std::ostream &out, DArray< DArray< double > > const &fields, UnitCell< D > const &unitCell) const
Write concentration or chemical potential field components to file.
void writeFieldBasis(std::string filename, DArray< double > const &field, UnitCell< D > const &unitCell) const
Write single concentration or chemical potential field to file.
Crystallographic space group.
bool isInitialized() const
Has this unit cell been initialized?
int nParameter() const
Get the number of parameters in the unit cell.
Base template for UnitCell<D> classes, D=1, 2 or 3.
int capacity() const
Return allocated size.
Dynamically allocatable contiguous array template.
void allocate(int capacity)
Allocate the underlying C array.
bool isAllocated() const
Return true if this DArray has been allocated, false otherwise.
A FileMaster manages input and output files for a simulation.
static std::ostream & file()
Get log ostream by reference.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
#define UTIL_ASSERT(condition)
Assertion macro suitable for debugging serial or parallel code.
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 writeNBasis(std::ostream &out, int nBasis)
Write the number of basis functions to a basis field file header.
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 inspectArrays(DArray< AT > const &arrays, int &nMonomer, int &capacity)
Inspect dimensions of a DArray of 1D arrays, each of type AT.
void inspectFields(DArray< FT > const &fields, int &nMonomer, IntVec< D > &dimensions)
Inspect dimensions of a DArray of fields, each of type FT.
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 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 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.
int readNBasis(std::istream &in)
Read the number of basis functions from a basis field file header.
void writeBasisData(std::ostream &out, DArray< DArray< double > > const &fields, Basis< D > const &basis)
Write array of fields in basis format, without a header.
void readBasisData(std::istream &in, DArray< DArray< double > > &fields, UnitCell< D > const &unitCell, Mesh< D > const &mesh, Basis< D > const &basis, int nStarIn)
Read a set of fields in basis format.
void checkAllocateField(FT &field, IntVec< D > const &dimensions)
Check allocation of a single field, allocate if necessary.
PSCF package top-level namespace.
Utility classes for scientific computation.