13#include <prdc/field/fieldCheck.h>
14#include <prdc/field/rFieldIo.h>
15#include <prdc/crystal/shiftToMinimum.h>
16#include <prdc/crystal/UnitCell.h>
17#include <prdc/crystal/Basis.h>
18#include <prdc/crystal/SpaceGroup.h>
19#include <prdc/crystal/UnitCell.h>
20#include <prdc/crystal/BFieldComparison.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/containers/DMatrix.h>
29#include <util/misc/FileMaster.h>
30#include <util/misc/Log.h>
31#include <util/format/Str.h>
32#include <util/format/Int.h>
33#include <util/format/Dbl.h>
47 template <
int D,
class RFT,
class KFT,
class FFT>
51 hasGroupPtr_(nullptr),
52 groupNamePtr_(nullptr),
55 fileMasterPtr_(nullptr),
57 isAllocatedBasis_(false),
58 isAllocatedRGrid_(false),
59 isAllocatedKGrid_(false)
67 template <
int D,
class RFT,
class KFT,
class FFT>
90 template <
int D,
class RFT,
class KFT,
class FFT>
98 template <
int D,
class RFT,
class KFT,
class FFT>
105 nMonomer_ = nMonomer;
113 template <
int D,
class RFT,
class KFT,
class FFT>
132 if (fields.isAllocated()) {
133 int nMonomerFields, fieldCapacity;
138 fields.allocate(nMonomer);
139 for (
int i = 0; i < nMonomer; ++i) {
140 fields[i].allocate(basis().nBasis());
151 template <
int D,
class RFT,
class KFT,
class FFT>
184 template <
int D,
class RFT,
class KFT,
class FFT>
198 int nBasis = fieldCapacity;
201 bool isSymmetric =
true;
212 template <
int D,
class RFT,
class KFT,
class FFT>
241 template <
int D,
class RFT,
class KFT,
class FFT>
243 std::string filename,
257 template <
int D,
class RFT,
class KFT,
class FFT>
259 std::string filename,
272 template <
int D,
class RFT,
class KFT,
class FFT>
274 std::string filename,
287 template <
int D,
class RFT,
class KFT,
class FFT>
289 std::string filename,
302 template <
int D,
class RFT,
class KFT,
class FFT>
304 std::string filename,
319 template <
int D,
class RFT,
class KFT,
class FFT>
321 std::string filename,
336 template <
int D,
class RFT,
class KFT,
class FFT>
338 std::string filename,
341 bool isSymmetric)
const
345 bool writeHeader =
true;
346 bool writeMeshSize =
true;
348 writeHeader, isSymmetric, writeMeshSize);
355 template <
int D,
class RFT,
class KFT,
class FFT>
357 std::string filename,
360 bool isSymmetric)
const
371 template <
int D,
class RFT,
class KFT,
class FFT>
373 std::string filename,
386 template <
int D,
class RFT,
class KFT,
class FFT>
388 std::string filename,
391 bool isSymmetric)
const
404 template <
int D,
class RFT,
class KFT,
class FFT>
406 DArray< DArray <double> >
const & in,
410 int nMonomer, nMonomerOut, capacity;
419 for (
int i = 0; i < nMonomer; ++i) {
427 template <
int D,
class RFT,
class KFT,
class FFT>
430 DArray< DArray <double> > & out,
432 double epsilon)
const
435 int nMonomer, nMonomerOut, capacity;
442 for (
int i = 0; i < nMonomer; ++i) {
450 template <
int D,
class RFT,
class KFT,
class FFT>
452 std::string
const & inFileName,
453 std::string
const & outFileName)
const
466 template <
int D,
class RFT,
class KFT,
class FFT>
468 std::string
const & inFileName,
469 std::string
const & outFileName)
const
484 template <
int D,
class RFT,
class KFT,
class FFT>
493 fft().inverseTransformUnsafe(workDft_, out);
499 template <
int D,
class RFT,
class KFT,
class FFT>
501 DArray< DArray <double> >
const & in,
509 int n = in.capacity();
510 for (
int i = 0; i < n; ++i) {
512 fft().inverseTransformUnsafe(workDft_, out[i]);
519 template <
int D,
class RFT,
class KFT,
class FFT>
524 double epsilon)
const
527 fft().forwardTransform(in, workDft_);
534 template <
int D,
class RFT,
class KFT,
class FFT>
537 DArray< DArray <double> > & out,
539 double epsilon)
const
542 int nMonomer, nMonomerOut, capacity;
551 for (
int i = 0; i < nMonomer; ++i) {
552 fft().forwardTransform(in[i], workDft_);
560 template <
int D,
class RFT,
class KFT,
class FFT>
562 std::string
const & inFileName,
563 std::string
const & outFileName)
const
577 template <
int D,
class RFT,
class KFT,
class FFT>
579 std::string
const & inFileName,
580 std::string
const & outFileName)
const
595 template <
int D,
class RFT,
class KFT,
class FFT>
602 for (
int i = 0; i < n; ++i) {
603 fft().inverseTransformSafe(in[i], out[i]);
610 template <
int D,
class RFT,
class KFT,
class FFT>
612 KFT
const & in, RFT& out)
const
614 fft().inverseTransformSafe(in, out);
620 template <
int D,
class RFT,
class KFT,
class FFT>
627 for (
int i = 0; i < n; ++i) {
628 fft().forwardTransform(in[i], out[i]);
635 template <
int D,
class RFT,
class KFT,
class FFT>
639 {
fft().forwardTransform(in, out); }
644 template <
int D,
class RFT,
class KFT,
class FFT>
646 std::string
const & inFileName,
647 std::string
const & outFileName)
const
653 for (
int i = 0; i < nMonomer_; ++i) {
654 fft().inverseTransformUnsafe(tmpFieldsKGrid_[i],
663 template <
int D,
class RFT,
class KFT,
class FFT>
665 std::string
const & inFileName,
666 std::string
const & outFileName)
const
683 template <
int D,
class RFT,
class KFT,
class FFT>
690 fft().forwardTransform(in, workDft_);
697 template <
int D,
class RFT,
class KFT,
class FFT>
699 std::string
const & inFileName,
700 double epsilon)
const
709 for (
int i = 0; i < nMonomer_; ++i) {
711 symmetric =
hasSymmetry(tmpFieldsRGrid_[i], epsilon);
722 template <
int D,
class RFT,
class KFT,
class FFT>
728 comparison.
compare(field1, field2);
730 Log::file() <<
"\n Basis expansion field comparison results"
732 Log::file() <<
" Maximum Absolute Difference: "
733 << comparison.
maxDiff() << std::endl;
734 Log::file() <<
" Root-Mean-Square Difference: "
735 << comparison.
rmsDiff() <<
"\n" << std::endl;
738 template <
int D,
class RFT,
class KFT,
class FFT>
740 std::string
const & filename1,
741 std::string
const & filename2)
const
751 template <
int D,
class RFT,
class KFT,
class FFT>
753 std::string
const & filename1,
754 std::string
const & filename2)
const
769 template <
int D,
class RFT,
class KFT,
class FFT>
776 for (
int i = 0; i < n; ++i) {
784 template <
int D,
class RFT,
class KFT,
class FFT>
789 int n = fields.capacity();
791 int m = fields[0].capacity();
792 for (
int i = 0; i < n; ++i) {
801 template <
int D,
class RFT,
class KFT,
class FFT>
803 std::string
const & inFileName,
804 std::string
const & outFileName,
817 template <
int D,
class RFT,
class KFT,
class FFT>
823 for (
int i = 0; i < n; ++i) {
831 template <
int D,
class RFT,
class KFT,
class FFT>
833 std::string
const & inFileName,
834 std::string
const & outFileName,
852 template <
int D,
class RFT,
class KFT,
class FFT>
861 const int nb = fields[0].capacity();
862 for (
int i = 0; i < nMonomer_; ++i) {
872 for (i = 0; i < nb; ++i) {
873 for (j = 0; j < nMonomer_; ++j) {
875 for (k = 0; k < nMonomer_; ++k) {
876 wtmp[j] += chi(j,k)*fields[k][i];
879 for (j = 0; j < nMonomer_; ++j) {
880 fields[j][i] = wtmp[j];
889 template <
int D,
class RFT,
class KFT,
class FFT>
891 std::string
const & inFileName,
892 std::string
const & outFileName,
902 const int nb =
basis().nBasis();
928 fileMaster().openOutputFile(outFileName, out);
938 template <
int D,
class RFT,
class KFT,
class FFT>
940 std::string filename,
954 template <
int D,
class RFT,
class KFT,
class FFT>
956 std::string
const & inFileName,
957 std::string
const & outFileName,
970 template <
int D,
class RFT,
class KFT,
class FFT>
972 std::string filename,
986 template <
int D,
class RFT,
class KFT,
class FFT>
988 std::string
const & inFileName,
989 std::string
const & outFileName,
997 d, newGridDimensions);
1012 template <
int D,
class RFT,
class KFT,
class FFT>
1017 bool & isSymmetric)
const
1030 std::string groupNameIn;
1033 groupNameIn, nMonomer);
1040 UTIL_CHECK(unitCell.lattice() != UnitCell<D>::Null);
1044 if (lattice() != unitCell.lattice()) {
1046 <<
"Error - Mismatched lattice types "
1047 <<
"in FieldIo function readFieldHeader:\n"
1048 <<
" FieldIo::lattice :" << lattice() <<
"\n"
1049 <<
" Unit cell lattice :" << unitCell.lattice()
1055 isSymmetric =
false;
1056 if (groupNameIn !=
"") {
1066 if (groupNameIn != groupName()) {
1068 <<
"Error - Mismatched group names in "
1069 <<
"FieldIo member function readFieldHeader:\n"
1070 <<
" FieldIo::groupName :" << groupName() <<
"\n"
1071 <<
" Field file header :" << groupNameIn <<
"\n";
1078 if (!basis().isInitialized()) {
1079 basisPtr_->makeBasis(mesh(), unitCell, group());
1087 <<
"Warning: Group name found in a field file header"
1088 <<
"but no group declared in the parameter file.\n";
1098 template <
int D,
class RFT,
class KFT,
class FFT>
1103 bool isSymmetric)
const
1107 std::string gName =
"";
1122 template <
int D,
class RFT,
class KFT,
class FFT>
1125 if (isAllocatedRGrid_)
return;
1130 tmpFieldsRGrid_.allocate(nMonomer_);
1131 for (
int i = 0; i < nMonomer_; ++i) {
1132 tmpFieldsRGrid_[i].allocate(meshDimensions);
1134 isAllocatedRGrid_ =
true;
1140 template <
int D,
class RFT,
class KFT,
class FFT>
1143 if (isAllocatedKGrid_)
return;
1148 tmpFieldsKGrid_.allocate(nMonomer_);
1149 for (
int i = 0; i < nMonomer_; ++i) {
1150 tmpFieldsKGrid_[i].allocate(meshDimensions);
1152 isAllocatedKGrid_ =
true;
1158 template <
int D,
class RFT,
class KFT,
class FFT>
1161 std::string
const & inFileName)
const
1163 if (isAllocatedBasis_)
return;
1167 if (!
basis().isInitialized()) {
1170 fileMaster().openInputFile(inFileName, file);
1179 int nBasis =
basis().nBasis();
1181 tmpFieldsBasis_.allocate(nMonomer_);
1182 for (
int i = 0; i < nMonomer_; ++i) {
1185 for (
int j = 0; j < nBasis; ++j) {
1189 isAllocatedBasis_ =
true;
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.
Description of a regular grid of points in a periodic domain.
Comparator for fields in symmetry-adapted basis format.
Symmetry-adapted Fourier basis for pseudo-spectral SCFT.
Fourier transform wrapper.
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.
virtual void scaleFieldRGrid(RFT &field, double factor) const =0
Multiply a single field in r-grid format by a scalar.
virtual void writeFieldsRGrid(std::ostream &out, DArray< RFT > const &fields, UnitCell< D > const &unitCell, bool writeHeader=true, bool isSymmetric=true, bool writeMeshSize=true) const =0
Write an array of r-grid fields to an output stream.
virtual void scaleFieldBasis(DArray< double > &field, double factor) const
Multiply a single field in basis form by a real scalar.
virtual void convertKGridToBasis(KFT const &in, DArray< double > &out, bool checkSymmetry=true, double epsilon=1.0e-8) const =0
Convert a single field from Fourier (k-grid) to basis form.
Mesh< D > const & mesh() const
Get spatial discretization mesh by const reference.
virtual bool readFieldRGrid(std::istream &in, RFT &field, UnitCell< D > &unitCell) const =0
Read a single r-grid field from an input stream.
virtual void convertBasisToKGrid(DArray< double > const &components, KFT &dft) const =0
Convert a single field from basis to Fourier (k-grid) form.
virtual void compareFieldsRGrid(DArray< RFT > const &field1, DArray< RFT > const &field2) const =0
Compare two fields in r-grid form, write a report to Log file.
void compareFieldsBasis(DArray< DArray< double > > const &field1, DArray< DArray< double > > const &field2) const
Compare array of fields in basis form, write a report to Log file.
void checkAllocateBasis(std::string const &inFileName) const
Check if basis workspace is allocated, allocate if necessary.
void setNMonomer(int nMonomer)
Set the number of monomer types.
virtual bool hasSymmetry(KFT const &in, double epsilon=1.0e-8, bool verbose=true) const =0
Check if a k-grid field has the declared space group symmetry.
void scaleFieldsBasis(DArray< DArray< double > > &fields, double factor) const
Multiply an array of fields in basis format by a real scalar.
virtual void replicateUnitCell(std::ostream &out, DArray< RFT > const &fields, UnitCell< D > const &unitCell, IntVec< D > const &replicas) const =0
Write r-grid fields in a replicated unit cell to std::ostream.
void readFieldBasis(std::istream &in, DArray< double > &field, UnitCell< D > &unitCell) const
Read a single field in basis format from an input stream.
void checkAllocateRGrid() const
Check if r-grid workspace is allocated, allocate if necessary.
void convertRGridToKGrid(DArray< RFT > const &in, DArray< KFT > &out) const
Convert an array of fields from r-grid to k-grid (Fourier) format.
FileMaster const & fileMaster() const
Get associated FileMaster by const reference.
void convertRGridToBasis(RFT const &in, DArray< double > &out, bool checkSymmetry=true, double epsilon=1.0e-8) const
Convert a single field from r-grid to basis form.
void checkAllocateKGrid() const
Check if k-grid workspace is allocated, allocate if necessary.
void estimateWBasis(DMatrix< double > const &chi, DArray< DArray< double > > &fields) const
Convert c fields to estimated w fields, in basis format.
void convertBasisToRGrid(DArray< double > const &in, RFT &out) const
Convert a single field from basis to r-grid format.
void writeFieldBasis(std::ostream &out, DArray< double > const &field, UnitCell< D > const &unitCell) const
Write a single field in basis format to an output stream.
void writeFieldsBasis(std::ostream &out, DArray< DArray< double > > const &fields, UnitCell< D > const &unitCell) const
Write an array of fields in basis format to an output stream.
void scaleFieldsRGrid(DArray< RFT > &fields, double factor) const
Scale an array of r-grid fields by a 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 void readFieldsKGrid(std::istream &in, DArray< KFT > &fields, UnitCell< D > &unitCell) const =0
Read an array of k-grid fields from an input stream.
void readFieldsBasis(std::istream &in, DArray< DArray< double > > &fields, UnitCell< D > &unitCell) const
Read an array of fields in basis format from an input stream.
UnitCell< D >::LatticeSystem const & lattice() const
Get the lattice type enum value by const reference.
virtual void expandRGridDimension(std::ostream &out, DArray< RFT > const &fields, UnitCell< D > const &unitCell, int d, DArray< int > const &newGridDimensions) const =0
Increase D for an array of r-grid fields, write to ostream.
FFT const & fft() const
Get FFT object by const reference.
void associate(Mesh< D > const &mesh, FFT const &fft, typename UnitCell< D >::LatticeSystem const &lattice, bool const &hasGroup, std::string const &groupName, SpaceGroup< D > const &group, Basis< D > &basis)
Create associations with other members of the parent Domain.
std::string const & groupName() const
Get an associated group name string by const reference.
void convertKGridToRGrid(DArray< KFT > const &in, DArray< RFT > &out) const
Convert an array of field from k-grid to r-grid format.
virtual void writeFieldRGrid(std::ostream &out, RFT const &field, UnitCell< D > const &unitCell, bool writeHeader=true, bool isSymmetric=true) const =0
Write a single r-grid field to an an output stream.
bool hasGroup() const
Has a space group been declared externally ?
void readFieldHeader(std::istream &in, int &nMonomer, UnitCell< D > &unitCell, bool &isSymmetric) const
Reader header of field file (fortran PSCF format)
SpaceGroup< D > const & group() const
Get an associated SpaceGroup<D> by const reference.
void setFileMaster(FileMaster const &fileMaster)
Create an association with a FileMaster.
Basis< D > const & basis() const
Get the associated Basis by const reference.
virtual bool readFieldsRGrid(std::istream &in, DArray< RFT > &fields, UnitCell< D > &unitCell) const =0
Read array of r-grid fields from an input stream.
virtual void writeFieldsKGrid(std::ostream &out, DArray< KFT > const &fields, UnitCell< D > const &unitCell, bool isSymmetric=true) const =0
Write an array of k-grid fields to a output stream.
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.
Dynamically allocated Matrix.
A FileMaster manages input and output files for a simulation.
static std::ostream & file()
Get log ostream by reference.
int capacity2() const
Get number of columns (range of the second array index).
int capacity1() const
Get number of rows (range of the first array index).
#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 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 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 data section of an array of fields in basis format.
void readBasisData(std::istream &in, DArray< DArray< double > > &fields, UnitCell< D > const &unitCell, Mesh< D > const &mesh, Basis< D > const &basis, int nStarIn)
Read an array of fields in basis format, without a header.
void checkAllocateField(FT &field, IntVec< D > const &dimensions)
Check allocation of a single field, allocate if necessary.
Periodic fields and crystallography.
Class templates for real-valued periodic fields.
PSCF package top-level namespace.