1#ifndef PSPG_FIELD_IO_TPP
2#define PSPG_FIELD_IO_TPP
13#include <pscf/crystal/shiftToMinimum.h>
14#include <pscf/crystal/UnitCell.h>
15#include <pscf/mesh/MeshIterator.h>
16#include <pscf/math/IntVec.h>
18#include <util/misc/Log.h>
19#include <util/format/Str.h>
20#include <util/format/Int.h>
21#include <util/format/Dbl.h>
61 std::string& groupName,
68 latticePtr_ = &lattice;
69 groupNamePtr_ = &groupName;
72 fileMasterPtr_ = &fileMaster;
90 if (label !=
"N_star" && label !=
"N_basis") {
91 std::string msg =
"\n";
92 msg +=
"Error reading field file:\n";
93 msg +=
"Expected N_basis or N_star, but found [";
103 int nMonomerFields = fields.capacity();
106 int fieldCapacity = fields[0].capacity();
107 for (i = 0; i < nMonomer; ++i) {
108 UTIL_CHECK(fields[i].capacity() == fieldCapacity);
112 int nStar = basis().nStar();
113 int nBasis = basis().nBasis();
116 for (j = 0; j < nMonomer; ++j) {
118 for (i = 0; i < nBasis; ++i) {
133 int basisId, basisId2;
136 std::complex<double> coeff, phasor;
139 int nReversedPair = 0;
144 while (i < nStarIn) {
147 for (
int j = 0; j < nMonomer; ++j) {
154 waveBz = shiftToMinimum(waveIn, mesh().dimensions(), unitCell);
155 waveExists = (waveIn == waveBz);
168 mesh().shift(waveDft);
169 waveId = basis().waveId(waveDft);
170 starId = basis().wave(waveId).starId;
171 starPtr = &basis().star(starId);
178 if (starPtr->
waveBz == waveIn) {
181 for (
int j = 0; j < nMonomer; ++j) {
182 fields[j][basisId] = temp[j];
187 <<
"Inconsistent wave of closed star on input\n"
188 <<
"wave from file = " << waveIn <<
"\n"
189 <<
"starId of wave = " << starId <<
"\n"
190 <<
"waveBz of star = " << starPtr->
waveBz <<
"\n";
198 for (
int j = 0; j < nMonomer; ++j) {
206 shiftToMinimum(waveIn2, mesh().dimensions(), unitCell);
211 mesh().shift(waveDft);
212 waveId2 = basis().waveId(waveDft);
213 starId2 = basis().wave(waveId2).starId;
214 starPtr2 = &basis().star(starId2);
230 for (
int j = 0; j < nMonomer; ++j) {
231 fields[j][basisId] = temp[j];
232 fields[j][basisId2] = temp2[j];
249 shiftToMinimum(nVec, mesh().dimensions(), unitCell);
297 phasor = basis().wave(waveId2).coeff;
298 phasor = phasor/std::abs(phasor);
299 for (
int j = 0; j < nMonomer; ++j) {
300 coeff = std::complex<double>(temp[j],-temp2[j]);
302 fields[j][basisId2] = real(coeff);
303 fields[j][basisId ] = imag(coeff);
320 if (nReversedPair > 0) {
322 Log::file() << nReversedPair <<
" reversed pairs of open stars"
323 <<
" detected in FieldIo::readFieldsBasis\n";
336 fileMaster().openInputFile(filename, file);
337 readFieldsBasis(file, fields, unitCell);
348 int nMonomer = fields.capacity();
353 writeFieldHeader(out, nMonomer, unitCell);
354 out <<
"N_basis " << std::endl
355 <<
" " << basis().nBasis() << std::endl;
358 int nStar = basis().nStar();
360 int nBasis = basis().nBasis();
364 for (
int i = 0; i < nStar; ++i) {
365 if (!basis().star(i).cancel) {
367 for (
int j = 0; j < nMonomer; ++j) {
368 out <<
Dbl(fields[j][ib], 20, 10);
371 for (
int j = 0; j < D; ++j) {
372 out <<
Int(basis().star(i).waveBz[j], 5);
374 out <<
Int(basis().star(i).size, 5) << std::endl;
389 fileMaster().openOutputFile(filename, file);
390 writeFieldsBasis(file, fields, unitCell);
409 if (label !=
"mesh" && label !=
"ngrid") {
410 std::string msg =
"\n";
411 msg +=
"Error reading field file:\n";
412 msg +=
"Expected mesh or ngrid, but found [";
423 for(
int i = 0; i < nMonomer; ++i) {
424 temp_out[i] =
new cudaReal[mesh().size()];
429 for(
int i = D - 1 ; i > 0; --i ) {
430 offsets[i - 1] = offsets[i] * mesh().dimension(i);
433 for(
int i = 0; i < D; ++i) {
439 for(
int i = 0; i < mesh().size(); i++) {
441 for(
int dim = 0; dim < D; ++dim) {
442 rank += offsets[dim] * position[dim];
444 for(
int k = 0; k < nMonomer; ++k) {
445 in >> std::setprecision(15)>> temp_out[k][rank];
449 while( positionId < D) {
450 position[positionId]++;
451 if ( position[positionId] == mesh().dimension(positionId) ) {
452 position[positionId] = 0;
460 for (
int i = 0; i < nMonomer; i++) {
461 cudaMemcpy(fields[i].cDField(), temp_out[i],
462 mesh().size() *
sizeof(cudaReal), cudaMemcpyHostToDevice);
463 delete[] temp_out[i];
464 temp_out[i] =
nullptr;
475 fileMaster().openInputFile(filename, file);
476 readFieldsRGrid(file, fields, unitCell);
486 int nMonomer = fields.capacity();
489 writeFieldHeader(out, nMonomer, unitCell);
490 out <<
"mesh " << std::endl
491 <<
" " << mesh().dimensions() << std::endl;
495 for (
int i = 0; i < nMonomer; ++i) {
496 temp_out[i] =
new cudaReal[mesh().size()];
497 cudaMemcpy(temp_out[i], fields[i].cDField(),
498 mesh().size() *
sizeof(cudaReal), cudaMemcpyDeviceToHost);
503 for(
int i = D - 1 ; i > 0; --i ) {
504 offsets[i - 1] = offsets[i] * mesh().dimension(i);
507 for(
int i = 0; i < D; ++i) {
513 for(
int i = 0; i < mesh().size(); i++) {
515 for(
int dim = 0; dim < D; ++dim) {
516 rank += offsets[dim] * position[dim];
518 for(
int k = 0; k < nMonomer; ++k) {
519 out <<
" " <<
Dbl(temp_out[k][rank], 18, 15);
524 while( positionId < D) {
525 position[positionId]++;
526 if ( position[positionId] == mesh().dimension(positionId) ) {
527 position[positionId] = 0;
535 for(
int i = 0; i < nMonomer; ++i) {
536 delete[] temp_out[i];
537 temp_out[i] =
nullptr;
549 fileMaster().openOutputFile(filename, file);
550 writeFieldsRGrid(file, fields, unitCell);
566 if (label !=
"mesh" && label !=
"ngrid") {
567 std::string msg =
"\n";
568 msg +=
"Error reading field file:\n";
569 msg +=
"Expected mesh or ngrid, but found [";
578 cudaReal* temp_out =
new cudaReal[mesh().size()];
582 for(
int i = D - 1 ; i > 0; --i ) {
583 offsets[i - 1] = offsets[i] * mesh().dimension(i);
586 for(
int i = 0; i < D; ++i) {
592 for(
int i = 0; i < mesh().size(); i++) {
594 for(
int dim = 0; dim < D; ++dim) {
595 rank += offsets[dim] * position[dim];
597 in >> std::setprecision(15) >> temp_out[rank];
601 while( positionId < D) {
602 position[positionId]++;
603 if ( position[positionId] == mesh().dimension(positionId) ) {
604 position[positionId] = 0;
612 cudaMemcpy(field.
cDField(), temp_out,
613 mesh().size() *
sizeof(cudaReal), cudaMemcpyHostToDevice);
626 fileMaster().openInputFile(filename, file);
627 readFieldRGrid(file, field, unitCell);
640 writeFieldHeader(out, 1, unitCell);
641 out <<
"mesh " << std::endl
642 <<
" " << mesh().dimensions() << std::endl;
645 cudaReal* temp_out =
new cudaReal[mesh().size()];;
646 cudaMemcpy(temp_out, field.
cDField(),
647 mesh().size() *
sizeof(cudaReal), cudaMemcpyDeviceToHost);
651 for(
int i = D - 1 ; i > 0; --i ) {
652 offsets[i - 1] = offsets[i] * mesh().dimension(i);
655 for(
int i = 0; i < D; ++i) {
661 for(
int i = 0; i < mesh().size(); i++) {
663 for(
int dim = 0; dim < D; ++dim) {
664 rank += offsets[dim] * position[dim];
666 out <<
" " <<
Dbl(temp_out[rank], 18, 15);
670 while( positionId < D) {
671 position[positionId]++;
672 if ( position[positionId] == mesh().dimension(positionId) ) {
673 position[positionId] = 0;
692 fileMaster().openOutputFile(filename, file);
693 writeFieldRGrid(file, field, unitCell);
706 readFieldHeader(in, nMonomer, unitCell);
711 if (label !=
"mesh" && label !=
"ngrid") {
712 std::string msg =
"\n";
713 msg +=
"Error reading field file:\n";
714 msg +=
"Expected mesh or ngrid, but found [";
727 for (
int i = 0; i < D; i++) {
729 kSize *= (mesh().dimension(i) / 2 + 1);
732 kSize *= mesh().dimension(i);
736 for(
int i = 0; i < nMonomer; ++i) {
737 temp_out[i] =
new cudaComplex[kSize];
743 for (
int i = 0; i < kSize; ++i) {
745 for (
int j = 0; j < nMonomer; ++j) {
746 in >> temp_out [j][i].x;
747 in >> temp_out [j][i].y;
751 for(
int i = 0; i < nMonomer; ++i) {
752 cudaMemcpy(fields[i].cDField(), temp_out[i],
753 kSize *
sizeof(cudaComplex), cudaMemcpyHostToDevice);
754 delete[] temp_out[i];
755 temp_out[i] =
nullptr;
766 fileMaster().openInputFile(filename, file);
767 readFieldsKGrid(file, fields, unitCell);
777 int nMonomer = fields.capacity();
781 writeFieldHeader(out, nMonomer, unitCell);
782 out <<
"mesh " << std::endl
783 <<
" " << mesh().dimensions() << std::endl;
787 for (
int i = 0; i < D; i++) {
789 kSize *= (mesh().dimension(i) / 2 + 1);
792 kSize *= mesh().dimension(i);
796 for(
int i = 0; i < nMonomer; ++i) {
797 temp_out[i] =
new cudaComplex[kSize];
798 cudaMemcpy(temp_out[i], fields[i].cDField(),
799 kSize *
sizeof(cudaComplex), cudaMemcpyDeviceToHost);
804 for (
int i = 0; i < kSize; i++) {
806 for (
int j = 0; j < nMonomer; ++j) {
807 out <<
" " <<
Dbl(temp_out[j][i].x, 18, 11)
808 <<
Dbl(temp_out[j][i].y, 18, 11);
813 for(
int i = 0; i < nMonomer; ++i) {
814 delete[] temp_out[i];
815 temp_out[i] =
nullptr;
826 fileMaster().openOutputFile(filename, file);
827 writeFieldsKGrid(file, fields, unitCell);
842 std::string groupNameIn;
843 Pscf::readFieldHeader(in, ver1, ver2, unitCell, groupNameIn, nMonomer);
854 if (groupNameIn != groupName()) {
857 <<
"Mismatched group names in FieldIo::readFieldHeader \n"
858 <<
" FieldIo::groupName :" << groupName() <<
"\n"
859 <<
" Field file groupName :" << groupNameIn <<
"\n";
892 std::string groupNameIn;
894 Pscf::readFieldHeader(in, ver1, ver2, unitCell,
895 groupNameIn, nMonomer);
907 lattice() = unitCell.lattice();
909 if (lattice() != unitCell.lattice()) {
912 <<
"Mismatched lattice types, FieldIo::readFieldHeader:\n"
913 <<
" FieldIo::lattice :" << lattice() <<
"\n"
914 <<
" Unit cell lattice :" << unitCell.lattice()
921 if (groupName() ==
"") {
922 groupName() = groupNameIn;
924 if (groupNameIn != groupName()) {
927 <<
"Mismatched group names in FieldIo::readFieldHeader:\n"
928 <<
" FieldIo::groupName :" << groupName() <<
"\n"
929 <<
" Field file header :" << groupNameIn <<
"\n";
936 if (group().size() == 1) {
937 if (groupName() !=
"I") {
938 readGroup(groupName(), group());
944 if (!basis().isInitialized()) {
945 basisPtr_->makeBasis(mesh(), unitCell, group());
957 out <<
"format 1 0" << std::endl;
958 out <<
"dim" << std::endl
959 <<
" " << D << std::endl;
961 out <<
"group_name" << std::endl
962 <<
" " << groupName() << std::endl;
963 out <<
"N_monomer" << std::endl
964 <<
" " << nMonomer << std::endl;
974 const int nBasis = basis().nBasis();
975 const int nStar = basis().nStar();
981 for (
int i = 0; i < D; i++) {
983 kSize *= (mesh().dimension(i) / 2 + 1);
986 kSize *= mesh().dimension(i);
992 cudaComplex* dft_out;
993 dft_out =
new cudaComplex[kSize];
1001 std::complex<double> component;
1002 std::complex<double> coeff;
1010 for (rank = 0; rank < dftMesh.
size(); ++rank) {
1011 dft_out[rank].x = 0.0;
1012 dft_out[rank].y = 0.0;
1017 while (is < basis().nStar()) {
1018 starPtr = &(basis().star(is));
1033 component = std::complex<double>(components[ib], 0.0);
1036 for (iw = starPtr->
beginId; iw < starPtr->endId; ++iw) {
1037 wavePtr = &basis().wave(iw);
1039 coeff = component*(wavePtr->
coeff);
1043 rank = dftMesh.
rank(indices);
1044 dft_out[rank].x = coeff.real();
1045 dft_out[rank].y = coeff.imag();
1059 component = std::complex<double>(components[ib],
1061 component /= sqrt(2.0);
1062 starPtr = &(basis().star(is));
1063 for (iw = starPtr->
beginId; iw < starPtr->endId; ++iw) {
1064 wavePtr = &basis().wave(iw);
1066 coeff = component*(wavePtr->
coeff);
1070 rank = dftMesh.
rank(indices);
1071 dft_out[rank].x = (cudaReal)coeff.real();
1072 dft_out[rank].y = (cudaReal)coeff.imag();
1077 starPtr = &(basis().star(is+1));
1079 component = std::complex<double>(components[ib],
1081 component /= sqrt(2.0);
1082 for (iw = starPtr->
beginId; iw < starPtr->endId; ++iw) {
1083 wavePtr = &basis().wave(iw);
1085 coeff = component*(wavePtr->
coeff);
1089 rank = dftMesh.
rank(indices);
1090 dft_out[rank].x = (cudaReal)coeff.real();
1091 dft_out[rank].y = (cudaReal)coeff.imag();
1106 cudaMemcpy(dft.
cDField(), dft_out,
1107 kSize *
sizeof(cudaComplex), cudaMemcpyHostToDevice);
1119 const int nStar = basis().nStar();
1120 const int nBasis = basis().nBasis();
1124 for (
int i = 0; i < D; i++) {
1126 kSize *= (mesh().dimension(i) / 2 + 1);
1129 kSize *= mesh().dimension(i);
1132 cudaComplex* dft_in;
1133 dft_in =
new cudaComplex[kSize];
1136 cudaMemcpy(dft_in, dft.
cDField(),
1137 kSize *
sizeof(cudaComplex), cudaMemcpyDeviceToHost);
1145 std::complex<double> component;
1146 std::complex<double> coefficient;
1154 for (is = 0; is < nBasis; ++is) {
1155 components[is] = 0.0;
1160 while (is < nStar) {
1161 starPtr = &(basis().star(is));
1177 int beginId = starPtr->
beginId;
1178 int endId = starPtr->
endId;
1181 while (isImplicit) {
1182 wavePtr = &basis().wave(beginId + iw);
1187 wavePtr = &basis().wave(endId - 1 - iw);
1199 std::complex<double>(dft_in[rank].x, dft_in[rank].y);
1200 bool componentError =
false;
1202 if (std::isnan(component.real())) componentError =
true;
1203 if (std::isnan(component.imag())) componentError =
true;
1205 coefficient = wavePtr->
coeff;
1207 if (std::isnan(coefficient.real())) componentError =
true;
1208 if (std::isnan(coefficient.imag())) componentError =
true;
1209 if (std::isnormal(coefficient)) componentError =
true;
1211 component /= coefficient;
1213 if (std::isnan(component.real())) componentError =
true;
1214 if (std::isnan(component.imag())) componentError =
true;
1215 if (std::isinf(component.real())) componentError =
true;
1216 if (std::isinf(component.imag())) componentError =
true;
1220 #ifdef SINGLE_PRECISION
1221 if (abs(component.imag()) > 1.0E-4) componentError =
true;
1223 if (abs(component.imag()) > 1.0E-8) componentError =
true;
1227 if (componentError) {
1228 std::complex<double> waveComponent =
1229 std::complex<double>(dft_in[rank].x, dft_in[rank].y);
1231 <<
" Error in FieldIo::convertKGridToBasis\n"
1232 <<
"Star Id " << starPtr->
starId <<
"\n"
1233 <<
"Basis Id " << starPtr->
basisId <<
"\n"
1234 <<
"Star WaveBz " << starPtr->
waveBz <<
"\n"
1235 <<
"Wave indices " << wavePtr->
indicesDft <<
"\n"
1236 <<
"Wave coeff " << wavePtr->
indicesDft <<
"\n"
1237 <<
"Wave component " <<
Dbl(waveComponent.real())
1238 <<
Dbl(waveComponent.imag()) <<
"\n"
1239 <<
"Wave coefficient" <<
Dbl(coefficient.real())
1240 <<
Dbl(coefficient.imag()) <<
"\n"
1241 <<
"Star component " <<
Dbl(component.real())
1242 <<
Dbl(component.imag()) <<
"\n";
1243 UTIL_THROW(
"Error: Component error in FieldIo::convertKGridToBasis");
1247 components[ib] = component.real();
1255 wavePtr = &basis().wave(starPtr->
beginId);
1257 starPtr = &(basis().star(is+1));
1259 wavePtr = &basis().wave(starPtr->
endId - 1);
1267 std::complex<double>(dft_in[rank].x, dft_in[rank].y);
1269 component /= wavePtr->
coeff;
1270 component *= sqrt(2.0);
1274 components[ib] = component.real();
1275 components[ib+1] = -component.imag();
1277 components[ib] = component.real();
1278 components[ib+1] = component.imag();
1303 const int n = in.capacity();
1305 for (
int i = 0; i < n; ++i) {
1306 convertBasisToKGrid(in[i], out[i]);
1318 int n = in.capacity();
1320 for (
int i = 0; i < n; ++i) {
1321 convertKGridToBasis(in[i], out[i]);
1333 const int nMonomer = in.capacity();
1337 for(
int i = 0; i < nMonomer; ++i) {
1338 workDft[i].
allocate(mesh().dimensions());
1341 convertBasisToKGrid(in, workDft);
1343 for (
int i = 0; i < nMonomer; ++i) {
1344 fft().inverseTransformSafe(workDft[i], out[i]);
1356 const int nMonomer = in.capacity();
1361 for(
int i = 0; i < nMonomer; ++i) {
1362 workDft[i].
allocate(mesh().dimensions());
1366 for (
int i = 0; i < nMonomer; ++i) {
1367 fft().forwardTransformSafe(in[i], workDft [i]);
1369 convertKGridToBasis(workDft, out);
1372 for (
int i = 0; i < nMonomer; ++i) {
1383 int n = in.capacity();
1384 for (
int i = 0; i < n; ++i) {
1385 fft().inverseTransformSafe(in[i], out[i]);
1395 int n = in.capacity();
1396 for (
int i = 0; i < n; ++i) {
1397 fft().forwardTransformSafe(in[i], out[i]);
1404 if (!workDft_.isAllocated()) {
1405 workDft_.allocate(mesh().dimensions());
1407 UTIL_CHECK(workDft_.meshDimensions() == fft().meshDimensions());
A list of wavevectors that are related by space-group symmetries.
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.
int starId
Index of this star in ordered array of all stars.
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>.
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.
Data * cDField()
Return pointer to underlying C array.
int capacity() const
Return allocated size.
Fourier transform wrapper for real data.
File input/output operations for fields in several file formats.
void writeFieldsKGrid(std::ostream &out, DArray< RDFieldDft< D > > const &fields, UnitCell< D > const &unitCell) const
Write array of RDFieldDft objects (k-space fields) to file.
void convertKGridToRGrid(DArray< RDFieldDft< D > > const &in, DArray< RDField< D > > &out) const
Convert fields from k-grid (DFT) to real space (rgrid) format.
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 writeFieldHeader(std::ostream &out, int nMonomer, UnitCell< D > const &unitCell) const
Write header for field file (fortran pscf format)
void convertRGridToKGrid(DArray< RDField< D > > const &in, DArray< RDFieldDft< D > > &out) const
Convert fields from spatial grid (rgrid) to k-grid format.
void writeFieldRGrid(std::ostream &out, RDField< D > const &field, UnitCell< D > const &unitCell, bool writeHeader=true) const
Write a single RField objects (field on an r-space grid) to file.
void convertRGridToBasis(DArray< RDField< D > > const &in, DArray< DArray< double > > &out) const
Convert fields from spatial grid (rgrid) to symmetrized basis.
void convertBasisToRGrid(DArray< DArray< double > > const &in, DArray< RDField< D > > &out) const
Convert fields from symmetrized basis to spatial grid (rgrid).
void writeFieldsRGrid(std::ostream &out, DArray< RDField< D > > const &fields, UnitCell< D > const &unitCell) const
Write array of RField objects (fields on an r-space grid) to file.
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 readFieldsKGrid(std::istream &in, DArray< RDFieldDft< D > > &fields, UnitCell< D > &unitCell) const
Read array of RDFieldDft objects (k-space fields) from file.
void readFieldsBasis(std::istream &in, DArray< DArray< double > > &fields, UnitCell< D > &unitCell) const
Read concentration or chemical potential field components from file.
void convertKGridToBasis(RDFieldDft< D > const &dft, DArray< double > &components) const
Convert field from Fourier transform (k-grid) to symmetrized basis.
void readFieldRGrid(std::istream &in, RDField< D > &field, UnitCell< D > &unitCell) const
Read a single RField objects (field on an r-space grid) from file.
void convertBasisToKGrid(DArray< double > const &components, RDFieldDft< D > &dft) const
Convert field from symmetrized basis to Fourier transform (k-grid).
void readFieldHeader(std::istream &in, int &nMonomer, UnitCell< D > &unitCell) const
Reader header of field file (fortran pscf format)
void readFieldsRGrid(std::istream &in, DArray< RDField< D > > &fields, UnitCell< D > &unitCell) const
Read array of RField objects (fields on an r-space grid) from file.
Discrete Fourier Transform (DFT) of a real field on an FFT mesh.
const IntVec< D > & meshDimensions() const
Return vector of mesh dimensions by constant reference.
const IntVec< D > & dftDimensions() const
Return vector of dft (Fourier) grid dimensions by const reference.
Field of real single precision values on an FFT mesh on a device.
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.
Dynamically allocatable contiguous array template.
void allocate(int capacity)
Allocate the underlying C array.
void deallocate()
Dellocate the underlying C array.
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.
void writeUnitCellHeader(std::ostream &out, UnitCell< D > const &cell)
Write UnitCell<D> to a field file header (fortran PSCF format).
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.