1#ifndef PSPC_FIELD_IO_TPP
2#define PSPC_FIELD_IO_TPP
13#include <pscf/crystal/shiftToMinimum.h>
14#include <pscf/mesh/MeshIterator.h>
15#include <pscf/math/IntVec.h>
17#include <util/misc/Log.h>
18#include <util/format/Str.h>
19#include <util/format/Int.h>
20#include <util/format/Dbl.h>
59 std::string & groupName,
66 latticePtr_ = &lattice;
67 groupNamePtr_ = &groupName;
70 fileMasterPtr_ = &fileMaster;
84 readFieldsBasis(in, fields, unitCell);
100 readFieldsBasis(filename, fields, unitCell);
115 writeFieldsBasis(out, fields, unitCell);
128 writeFieldsBasis(filename, fields, unitCell);
144 if (label !=
"N_star" && label !=
"N_basis") {
145 std::string msg =
"\n";
146 msg +=
"Error reading field file:\n";
147 msg +=
"Expected N_basis or N_star, but found [";
160 if (fields.isAllocated()) {
164 int nMonomerFields = fields.capacity();
170 fieldCapacity = fields[0].capacity();
171 for (
int i = 0; i < nMonomer; ++i) {
172 UTIL_CHECK( fields[i].capacity() == fieldCapacity );
177 fields.allocate(nMonomer);
178 fieldCapacity = nStarIn;
180 for (
int i = 0; i < nMonomer; ++i) {
181 fields[i].allocate(fieldCapacity);
186 for (
int i = 0; i < nMonomer; ++i) {
187 for (
int j = 0; j < fieldCapacity; ++j) {
193 if (fieldCapacity < nStarIn) {
194 nStarIn = fieldCapacity;
207 int basisId, basisId2;
210 std::complex<double> coeff, phasor;
212 int nReversedPair = 0;
213 bool waveExists, sizeMatches;
217 while (i < nStarIn) {
220 for (
int j = 0; j < nMonomer; ++j) {
231 waveBz = shiftToMinimum(waveIn, mesh().dimensions(), unitCell);
232 waveExists = (waveIn == waveBz);
238 mesh().shift(waveDft);
239 waveId = basis().waveId(waveDft);
240 starId = basis().wave(waveId).starId;
241 starPtr = &basis().star(starId);
245 if (starPtr->
size == sizeIn) {
249 <<
"Warning: Inconsistent star size (line ignored)\n"
250 <<
"wave from file = " << waveIn <<
"\n"
251 <<
"size from file = " << sizeIn <<
"\n"
252 <<
"size of star = " << starPtr->
size
259 if (waveExists && sizeMatches) {
263 if (starPtr->
waveBz == waveIn) {
266 for (
int j = 0; j < nMonomer; ++j) {
267 fields[j][basisId] = temp[j];
273 <<
"Inconsistent wave of closed star on input\n"
274 <<
"wave from file = " << waveIn <<
"\n"
275 <<
"starId of wave = " << starId <<
"\n"
276 <<
"waveBz of star = " << starPtr->
waveBz
284 for (
int j = 0; j < nMonomer; ++j) {
293 shiftToMinimum(waveIn2, mesh().dimensions(), unitCell);
298 mesh().shift(waveDft);
299 waveId2 = basis().waveId(waveDft);
300 starId2 = basis().wave(waveId2).starId;
301 starPtr2 = &basis().star(starId2);
318 for (
int j = 0; j < nMonomer; ++j) {
319 fields[j][basisId] = temp[j];
320 fields[j][basisId2] = temp2[j];
337 shiftToMinimum(nVec, mesh().dimensions(), unitCell);
385 phasor = basis().wave(waveId2).coeff;
386 phasor = phasor/std::abs(phasor);
387 for (
int j = 0; j < nMonomer; ++j) {
388 coeff = std::complex<double>(temp[j],-temp2[j]);
390 fields[j][basisId2] = real(coeff);
391 fields[j][basisId ] = imag(coeff);
407 if (nReversedPair > 0) {
409 Log::file() << nReversedPair <<
" reversed pairs of open stars"
410 <<
" detected in FieldIo::readFieldsBasis\n";
423 fileMaster().openInputFile(filename, file);
424 readFieldsBasis(file, fields, unitCell);
435 int nMonomer = fields.capacity();
440 writeFieldHeader(out, nMonomer, unitCell);
441 int nStar = basis().nStar();
442 int nBasis = basis().nBasis();
443 out <<
"N_basis " << std::endl
444 <<
" " << nBasis << std::endl;
448 for (
int i = 0; i < nStar; ++i) {
449 if (!basis().star(i).cancel) {
450 for (
int j = 0; j < nMonomer; ++j) {
451 out <<
Dbl(fields[j][ib], 20, 10);
454 for (
int j = 0; j < D; ++j) {
455 out <<
Int(basis().star(i).waveBz[j], 5);
457 out <<
Int(basis().star(i).size, 5) << std::endl;
472 fileMaster().openOutputFile(filename, file);
473 writeFieldsBasis(file, fields, unitCell);
489 if (fields.isAllocated()) {
490 int nMonomerFields = fields.capacity();
495 for (
int i = 0; i < nMonomer; ++i) {
496 UTIL_CHECK(fields[i].meshDimensions() == mesh().dimensions());
499 fields.allocate(nMonomer);
500 for (
int i = 0; i < nMonomer; ++i) {
501 fields[i].allocate(mesh().dimensions());
508 if (label !=
"mesh" && label !=
"ngrid") {
509 std::string msg =
"\n";
510 msg +=
"Error reading field file:\n";
511 msg +=
"Expected mesh or ngrid, but found [";
523 for (
int i = 0; i < nMonomer; ++i) {
524 temp[i].
allocate(mesh().dimensions());
530 for (
int i = 0; i < nMonomer; ++i) {
531 in >> std::setprecision(15) >> temp[i][itr.
rank()];
544 while (n1 < mesh().dimension(0)) {
547 while (n2 < mesh().dimension(1)) {
550 while (n3 < mesh().dimension(2)) {
551 for (
int i = 0; i < nMonomer; ++i) {
552 fields[i][s] = temp[i][r];
554 r = r + (mesh().dimension(0) * mesh().dimension(1));
558 q = q + mesh().dimension(0);
567 while (n1 < mesh().dimension(0)) {
570 while (n2 < mesh().dimension(1)) {
571 for (
int i = 0; i < nMonomer; ++i) {
572 fields[i][s] = temp[i][r];
574 r = r + (mesh().dimension(0));
585 while (n1 < mesh().dimension(0)) {
586 for (
int i = 0; i < nMonomer; ++i) {
587 fields[i][s] = temp[i][r];
608 fileMaster().openInputFile(filename, file);
609 readFieldsRGrid(file, fields, unitCell);
619 int nMonomer = fields.capacity();
622 writeFieldHeader(out, nMonomer, unitCell);
623 out <<
"mesh " << std::endl
624 <<
" " << mesh().dimensions() << std::endl;
628 for (
int i = 0; i < nMonomer; ++i) {
629 temp[i].
allocate(mesh().dimensions());
641 while (n3 < mesh().dimension(2)) {
644 while (n2 < mesh().dimension(1)) {
647 while (n1 < mesh().dimension(0)) {
648 for (
int i = 0; i < nMonomer; ++i) {
649 temp[i][s] = fields[i][r];
651 r = r + (mesh().dimension(1) * mesh().dimension(2));
655 q = q + mesh().dimension(2);
663 while (n2 < mesh().dimension(1)) {
666 while (n1 < mesh().dimension(0)) {
667 for (
int i = 0; i < nMonomer; ++i) {
668 temp[i][s] = fields[i][r];
670 r = r + (mesh().dimension(1));
679 while (n1 < mesh().dimension(0)) {
680 for (
int i = 0; i < nMonomer; ++i) {
681 temp[i][s] = fields[i][r];
694 for (
int j = 0; j < nMonomer; ++j) {
695 out <<
" " <<
Dbl(temp[j][itr.
rank()], 18, 15);
709 fileMaster().openOutputFile(filename, file);
710 writeFieldsRGrid(file, fields, unitCell);
732 field.
allocate(mesh().dimensions());
738 if (label !=
"mesh" && label !=
"ngrid") {
739 std::string msg =
"\n";
740 msg +=
"Error reading field file:\n";
741 msg +=
"Expected mesh or ngrid, but found [";
757 in >> std::setprecision(15) >> temp[itr.
rank()];
769 while (n1 < mesh().dimension(0)) {
772 while (n2 < mesh().dimension(1)) {
775 while (n3 < mesh().dimension(2)) {
777 r = r + (mesh().dimension(0) * mesh().dimension(1));
781 q = q + mesh().dimension(0);
790 while (n1 < mesh().dimension(0)) {
793 while (n2 < mesh().dimension(1)) {
795 r = r + (mesh().dimension(0));
806 while (n1 < mesh().dimension(0)) {
826 fileMaster().openInputFile(filename, file);
827 readFieldRGrid(file, field, unitCell);
839 writeFieldHeader(out, 1, unitCell);
840 out <<
"mesh " << std::endl
841 <<
" " << mesh().dimensions() << std::endl;
856 while (n3 < mesh().dimension(2)) {
859 while (n2 < mesh().dimension(1)) {
862 while (n1 < mesh().dimension(0)) {
864 r = r + (mesh().dimension(1) * mesh().dimension(2));
868 q = q + mesh().dimension(2);
876 while (n2 < mesh().dimension(1)) {
879 while (n1 < mesh().dimension(0)) {
881 r = r + (mesh().dimension(1));
890 while (n1 < mesh().dimension(0)) {
903 out <<
" " <<
Dbl(temp[itr.
rank()], 18, 15);
915 fileMaster().openOutputFile(filename, file);
916 writeFieldRGrid(file, field, unitCell);
932 if (fields.isAllocated()) {
934 int nMonomerFields = fields.capacity();
939 for (
int i = 0; i < nMonomer; ++i) {
940 UTIL_CHECK(fields[i].meshDimensions() == mesh().dimensions());
945 fields.allocate(nMonomer);
946 for (
int i = 0; i < nMonomer; ++i) {
947 fields[i].allocate(mesh().dimensions());
955 if (label !=
"mesh" && label !=
"ngrid") {
956 std::string msg =
"\n";
957 msg +=
"Error reading field file:\n";
958 msg +=
"Expected mesh or ngrid, but found [";
975 for (
int i = 0; i < nMonomer; ++i) {
976 for (
int j = 0; j < 2; ++j) {
977 in >> fields[i][itr.
rank()][j];
991 fileMaster().openInputFile(filename, file);
992 readFieldsKGrid(file, fields, unitCell);
1003 int nMonomer = fields.capacity();
1005 for (
int i = 0; i < nMonomer; ++i) {
1006 UTIL_CHECK(fields[i].meshDimensions() == mesh().dimensions());
1010 writeFieldHeader(out, nMonomer, unitCell);
1011 out <<
"mesh " << std::endl
1012 <<
" " << mesh().dimensions() << std::endl;
1020 for (
int j = 0; j < nMonomer; ++j) {
1022 <<
Dbl(fields[j][itr.
rank()][0], 20, 12)
1023 <<
Dbl(fields[j][itr.
rank()][1], 20, 12);
1037 fileMaster().openOutputFile(filename, file);
1038 writeFieldsKGrid(file, fields, unitCell);
1066 std::string groupNameIn;
1068 Pscf::readFieldHeader(in, ver1, ver2, unitCell,
1069 groupNameIn, nMonomer);
1081 lattice() = unitCell.lattice();
1083 if (lattice() != unitCell.lattice()) {
1086 <<
"Mismatched lattice types, FieldIo::readFieldHeader:\n"
1087 <<
" FieldIo::lattice :" << lattice() <<
"\n"
1088 <<
" Unit cell lattice :" << unitCell.lattice()
1095 if (groupName() ==
"") {
1096 groupName() = groupNameIn;
1098 if (groupNameIn != groupName()) {
1101 <<
"Mismatched group names in FieldIo::readFieldHeader:\n"
1102 <<
" FieldIo::groupName :" << groupName() <<
"\n"
1103 <<
" Field file header :" << groupNameIn <<
"\n";
1110 if (group().size() == 1) {
1111 if (groupName() !=
"I") {
1112 readGroup(groupName(), group());
1118 if (!basis().isInitialized()) {
1119 basisPtr_->makeBasis(mesh(), unitCell, group());
1131 Pscf::writeFieldHeader(out, ver1, ver2, unitCell,
1132 groupName(), nMonomer);
1147 std::complex<double> component;
1148 std::complex<double> coeff;
1156 for (rank = 0; rank < dftMesh.
size(); ++rank) {
1163 while (is < basis().nStar()) {
1164 starPtr = &(basis().star(is));
1177 component = std::complex<double>(in[ib], 0.0);
1180 for (iw = starPtr->
beginId; iw < starPtr->endId; ++iw) {
1181 wavePtr = &basis().wave(iw);
1183 coeff = component*(wavePtr->
coeff);
1185 rank = dftMesh.
rank(indices);
1186 out[rank][0] = coeff.real();
1187 out[rank][1] = coeff.imag();
1196 component = std::complex<double>(in[ib], -in[ib+1]);
1197 component /= sqrt(2.0);
1198 starPtr = &(basis().star(is));
1199 for (iw = starPtr->
beginId; iw < starPtr->endId; ++iw) {
1200 wavePtr = &basis().wave(iw);
1202 coeff = component*(wavePtr->
coeff);
1204 rank = dftMesh.
rank(indices);
1205 out[rank][0] = coeff.real();
1206 out[rank][1] = coeff.imag();
1211 starPtr = &(basis().star(is+1));
1213 component = std::complex<double>(in[ib], +in[ib+1]);
1214 component /= sqrt(2.0);
1215 for (iw = starPtr->
beginId; iw < starPtr->endId; ++iw) {
1216 wavePtr = &basis().wave(iw);
1218 coeff = component*(wavePtr->
coeff);
1220 rank = dftMesh.
rank(indices);
1221 out[rank][0] = coeff.real();
1222 out[rank][1] = coeff.imag();
1243 double epsilon)
const
1247 if (checkSymmetry) {
1249 bool symmetric = hasSymmetry(in, epsilon,
true);
1252 <<
"WARNING: non-negligible error in conversion to "
1253 <<
"symmetry-adapted basis format." << std::endl
1254 <<
" See error values printed above for each "
1255 <<
"asymmetric field." << std::endl
1256 <<
" The field that is output by the above operation "
1257 <<
"will be a" << std::endl
1258 <<
" symmetrized version of the input field."
1259 << std::endl << std::endl;
1268 std::complex<double> component;
1274 for (is = 0; is < basis().nBasis(); ++is) {
1280 while (is < basis().nStar()) {
1281 starPtr = &(basis().star(is));
1294 int beginId = starPtr->
beginId;
1295 int endId = starPtr->
endId;
1297 bool isImplicit =
true;
1298 while (isImplicit) {
1299 wavePtr = &basis().wave(beginId + iw);
1304 wavePtr = &basis().wave(endId - 1 - iw);
1315 component = std::complex<double>(in[rank][0], in[rank][1]);
1316 component /= wavePtr->
coeff;
1317 out[ib] = component.real();
1325 wavePtr = &basis().wave(starPtr->
beginId);
1328 starPtr = &(basis().star(is+1));
1330 wavePtr = &basis().wave(starPtr->
endId - 1);
1335 component = std::complex<double>(in[rank][0], in[rank][1]);
1337 component /= wavePtr->
coeff;
1338 component *= sqrt(2.0);
1342 out[ib] = component.real();
1343 out[ib+1] = -component.imag();
1345 out[ib] = component.real();
1346 out[ib+1] = component.imag();
1363 int n = in.capacity();
1364 for (
int i = 0; i < n; ++i) {
1365 convertBasisToKGrid(in[i], out[i]);
1371 DArray< DArray <double> > & out,
1373 double epsilon)
const
1376 int n = in.capacity();
1378 bool symmetric(
true);
1379 for (
int i = 0; i < n; ++i) {
1380 if (checkSymmetry) {
1382 bool tmp_sym = hasSymmetry(in[i], epsilon,
true);
1383 if (!tmp_sym) symmetric =
false;
1385 convertKGridToBasis(in[i], out[i],
false);
1391 <<
"WARNING: non-negligible error in conversion to "
1392 <<
"symmetry-adapted basis format." << std::endl
1393 <<
"See error values printed above for each asymmetric field."
1395 <<
"The field that is output by this operation will be "
1396 <<
"a symmetrized version of" << std::endl
1397 <<
"the input field." << std::endl << std::endl;
1407 convertBasisToKGrid(in, workDft_);
1408 fft().inverseTransformSafe(workDft_, out);
1419 int n = in.capacity();
1420 for (
int i = 0; i < n; ++i) {
1421 convertBasisToKGrid(in[i], workDft_);
1422 fft().inverseTransformSafe(workDft_, out[i]);
1431 double epsilon)
const
1434 fft().forwardTransform(in, workDft_);
1435 convertKGridToBasis(workDft_, out, checkSymmetry, epsilon);
1441 DArray< DArray <double> > & out,
1443 double epsilon)
const
1448 int n = in.capacity();
1450 bool symmetric(
true);
1451 for (
int i = 0; i < n; ++i) {
1452 fft().forwardTransform(in[i], workDft_);
1453 if (checkSymmetry) {
1455 bool tmp_sym = hasSymmetry(workDft_, epsilon,
true);
1456 if (!tmp_sym) symmetric =
false;
1458 convertKGridToBasis(workDft_, out[i],
false);
1464 <<
"WARNING: non-negligible error in conversion to "
1465 <<
"symmetry-adapted basis format." << std::endl
1466 <<
" See error values printed above for each "
1467 <<
"asymmetric field." << std::endl
1468 <<
" The field that is output by the above operation "
1469 <<
"will be a" << std::endl
1470 <<
" symmetrized version of the input field."
1471 << std::endl << std::endl;
1484 int n = in.capacity();
1485 for (
int i = 0; i < n; ++i) {
1486 fft().inverseTransformSafe(in[i], out[i]);
1497 fft().inverseTransformSafe(in, out);
1509 int n = in.capacity();
1510 for (
int i = 0; i < n; ++i) {
1511 fft().forwardTransform(in[i], out[i]);
1523 fft().forwardTransform(in, out);
1536 fft().forwardTransform(in, workDft_);
1537 return hasSymmetry(workDft_, epsilon, verbose);
1553 std::complex<double> waveCoeff;
1554 std::complex<double> rootCoeff;
1555 std::complex<double> diff;
1561 double cancelledError(0.0);
1562 double uncancelledError(0.0);
1568 for (is = 0; is < basis().nStar(); ++is) {
1569 starPtr = &(basis().star(is));
1575 endId = starPtr->
endId;
1576 for (iw = beginId; iw < endId; ++iw) {
1577 wavePtr = &basis().wave(iw);
1580 waveCoeff = std::complex<double>(in[rank][0], in[rank][1]);
1581 if (std::abs(waveCoeff) > cancelledError) {
1582 cancelledError = std::abs(waveCoeff);
1583 if ((!verbose) && (cancelledError > epsilon)) {
1593 bool hasRoot =
false;
1595 endId = starPtr->
endId;
1596 for (iw = beginId; iw < endId; ++iw) {
1597 wavePtr = &basis().wave(iw);
1600 waveCoeff = std::complex<double>(in[rank][0], in[rank][1]);
1601 waveCoeff /= wavePtr->
coeff;
1603 diff = waveCoeff - rootCoeff;
1604 if (std::abs(diff) > uncancelledError) {
1605 uncancelledError = std::abs(diff);
1606 if ((!verbose) && (uncancelledError > epsilon)) {
1611 rootCoeff = waveCoeff;
1621 if ((cancelledError < epsilon) && (uncancelledError < epsilon)) {
1623 }
else if (verbose) {
1625 <<
"Maximum coefficient of a cancelled star: "
1626 << cancelledError << std::endl
1627 <<
"Maximum error of coefficient for uncancelled star: "
1628 << uncancelledError << std::endl;
1636 if (!workDft_.isAllocated()) {
1637 workDft_.allocate(mesh().dimensions());
1639 UTIL_CHECK(workDft_.meshDimensions() == fft().meshDimensions());
A list of wavevectors that are related by space-group symmetries.
int size
Number of wavevectors in this star.
int invertFlag
Index for inversion symmetry of star.
IntVec< D > waveBz
Integer indices indexBz of a characteristic wave of this star.
int endId
Wave index of last wavevector in star.
int basisId
Index of basis function associated with this star.
int beginId
Wave index of first wavevector in star.
bool cancel
Is this star cancelled, i.e., associated with a zero function?
Wavevector used to construct a basis function.
bool implicit
Is this wave represented implicitly in DFT of real field?
std::complex< double > coeff
Coefficient of wave within the associated star basis function.
int starId
Index of the star that contains this wavevector.
IntVec< D > indicesDft
Integer indices of wave, on a discrete Fourier transform mesh.
Symmetry-adapted Fourier basis for pseudo-spectral scft.
An IntVec<D, T> is a D-component vector of elements of integer type T.
Iterator over points in a Mesh<D>.
int rank() const
Get the rank of current element.
void begin()
Set iterator to the first point in the mesh.
bool atEnd() const
Is this the end (i.e., one past the last point)?
Description of a regular grid of points in a periodic domain.
int size() const
Get total number of grid points.
int rank(IntVec< D > const &position) const
Get the rank of a grid point with specified position.
Fourier transform wrapper for real data.
File input/output operations and format conversions for fields.
void readFieldRGrid(std::istream &in, RField< D > &field, UnitCell< D > &unitCell) const
Read single RField (field on an r-space grid) 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 convertBasisToKGrid(DArray< double > const &components, RFieldDft< D > &dft) const
Convert a field from symmetrized basis to Fourier transform (k-grid).
void readFieldsKGrid(std::istream &in, DArray< RFieldDft< D > > &fields, UnitCell< D > &unitCell) const
Read array of RFieldDft objects (k-space fields) from file.
void readFieldHeader(std::istream &in, int &nMonomer, UnitCell< D > &unitCell) const
Reader header of field file (fortran pscf format)
void writeFieldHeader(std::ostream &out, int nMonomer, UnitCell< D > const &unitCell) const
Write header for field file (fortran pscf format)
void convertBasisToRGrid(DArray< double > const &in, RField< D > &out) const
Convert a field from symmetrized basis to spatial grid (r-grid).
void convertKGridToBasis(RFieldDft< D > const &in, DArray< double > &out, bool checkSymmetry=true, double epsilon=1.0e-8) const
Convert a field from Fourier transform (kgrid) to symmetrized basis.
void writeFieldsKGrid(std::ostream &out, DArray< RFieldDft< D > > const &fields, UnitCell< D > const &unitCell) const
Write array of RFieldDft objects (k-space fields) to file.
void writeFieldBasis(std::ostream &out, DArray< double > const &field, UnitCell< D > const &unitCell) const
Write single concentration or chemical potential field to output stream out.
void associate(Mesh< D > const &mesh, FFT< D > const &fft, typename UnitCell< D >::LatticeSystem &lattice, std::string &groupName, SpaceGroup< D > &group, Basis< D > &basis, FileMaster const &fileMaster)
Get and store addresses of associated objects.
void readFieldsRGrid(std::istream &in, DArray< RField< D > > &fields, UnitCell< D > &unitCell) const
Read array of RField objects (fields on r-space grid) from istream.
void convertRGridToBasis(RField< D > 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 writeFieldRGrid(std::ostream &out, RField< D > const &field, UnitCell< D > const &unitCell, bool writeHeader=true) const
Write a single RField (field on an r-space grid) to ostream.
void writeFieldsRGrid(std::ostream &out, DArray< RField< D > > const &fields, UnitCell< D > const &unitCell) const
Write array of RField objects (fields on r-space grid) to ostream.
void readFieldBasis(std::istream &in, DArray< double > &field, UnitCell< D > &unitCell) const
Read single concentration or chemical potential field from file.
void convertKGridToRGrid(DArray< RFieldDft< D > > &in, DArray< RField< D > > &out) const
Convert fields from k-grid (DFT) to real space (r-grid) format.
bool hasSymmetry(RField< D > const &in, double epsilon=1.0e-8, bool verbose=true) const
Check if an r-grid field has the declared space group symmetry.
void convertRGridToKGrid(DArray< RField< D > > const &in, DArray< RFieldDft< D > > &out) const
Convert fields from spatial grid (r-grid) to k-grid format.
void readFieldsBasis(std::istream &in, DArray< DArray< double > > &fields, UnitCell< D > &unitCell) const
Read concentration or chemical potential field components from file.
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.
void allocate(const IntVec< D > &meshDimensions)
Allocate the underlying C array for an FFT grid.
Crystallographic space group.
int nParameter() const
Get the number of parameters in the unit cell.
bool isInitialized() const
Has this unit cell been initialized?
Base template for UnitCell<D> classes, D=1, 2 or 3.
Vec< D, T > & negate(const Vec< D, T > &v)
Return negative of vector v.
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.
Wrapper for a double precision number, for formatted ostream output.
A FileMaster manages input and output files for a simulation.
Wrapper for an int, for formatted ostream output.
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.
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.