14#include <prdc/crystal/UnitCell.h>
15#include <prdc/crystal/SpaceGroup.h>
16#include <prdc/crystal/shiftToMinimum.h>
17#include <pscf/mesh/Mesh.h>
18#include <pscf/mesh/MeshIterator.h>
19#include <util/signal/Signal.h>
20#include <util/format/Dbl.h>
21#include <util/math/Constants.h>
67 std::string groupName)
70 readGroup(groupName, group);
87 unitCellPtr_ = &unitCell;
91 waves_.allocate(nWave_);
92 waveIds_.allocate(nWave_);
103 UTIL_THROW(
"Basis failed validity test suite");
107 isInitialized_ =
true;
122 void Basis<D>::makeWaves()
124 IntVec<D> meshDimensions = mesh().dimensions();
125 std::vector< BWave<D> > twaves;
126 twaves.reserve(nWave_);
132 for (itr.begin(); !itr.atEnd(); ++itr) {
133 w.indicesStd = itr.position();
134 v = shiftToMinimum(w.indicesStd, meshDimensions, *unitCellPtr_);
136 w.sqNorm = unitCell().ksq(v);
141 BWaveNormComp<D> comp;
142 std::sort(twaves.begin(), twaves.end(), comp);
145 for (
int i = 0; i < nWave_; ++i) {
146 waves_[i].sqNorm = twaves[i].sqNorm;
147 waves_[i].indicesStd = twaves[i].indicesStd;
148 waves_[i].indicesMin = twaves[i].indicesMin;
191 std::vector< BWave<D> > starList;
199 std::complex<double> coeff;
204 const double epsilon = 1.0E-8;
205 IntVec<D> meshDimensions = mesh().dimensions();
368 Gsq_max = waves_[0].sqNorm;
369 for (i = 1; i <= nWave_; ++i) {
372 bool newList =
false;
375 bunchSize = bunchEnd - bunchBegin;
378 Gsq = waves_[i].sqNorm;
379 if (Gsq > Gsq_max + epsilon) {
382 bunchSize = bunchEnd - bunchBegin;
393 for (j = bunchBegin; j < bunchEnd; ++j) {
394 wave.indicesStd = waves_[j].indicesStd;
395 wave.indicesMin = waves_[j].indicesMin;
396 wave.sqNorm = waves_[j].sqNorm;
397 if (j > bunchBegin) {
398 UTIL_CHECK( std::abs(wave.sqNorm-waves_[j].sqNorm)
413 rootItr = bunch.begin();
421 while (bunch.size() > 0) {
423 rootVecMin = rootItr->indicesMin;
424 rootVecStd = rootItr->indicesStd;
425 Gsq = rootItr->sqNorm;
431 for (j = 0; j < group.size(); ++j) {
435 vec = rootVecMin*group[j];
438 UTIL_CHECK(std::abs(Gsq - unitCell().ksq(vec)) < epsilon);
442 wave.indicesMin = shiftToMinimum(vec, meshDimensions,
444 wave.indicesStd = vec;
445 mesh().shift(wave.indicesStd);
450 for (k = 0; k < D; ++k) {
451 wave.phase += rootVecMin[k]*(group[j].t(k));
453 while (wave.phase > 0.5) {
456 while (wave.phase <= -0.5) {
467 if (wave.indicesStd == rootVecStd) {
468 if (std::abs(wave.phase) > 1.0E-6) {
475 setItr = star.find(wave);
477 if (setItr == star.end()) {
489 phase_diff = setItr->phase - wave.phase;
490 while (phase_diff > 0.5) {
493 while (phase_diff <= -0.5) {
496 if (std::abs(phase_diff) > 1.0E-6) {
506 setItr = star.begin();
507 for ( ; setItr != star.end(); ++setItr) {
508 starList.push_back(*setItr);
513 std::sort(starList.begin(), starList.end(), waveMinComp);
516 int starListSize = starList.size();
517 for (j = 0; j < starListSize; ++j) {
518 bunch.erase(starList[j]);
519 bunchList.
append(starList[j]);
527 nBasisWave_ += star.size();
532 newStar.beginId = starBegin;
533 newStar.endId = newStar.beginId + star.size();
534 newStar.size = star.size();
535 newStar.cancel = cancel;
539 if (nextInvert == -1) {
545 newStar.invertFlag = -1;
546 rootItr = bunch.begin();
555 nVec.negate(rootVecMin);
558 (*meshPtr_).shift(nVec);
561 bool inverseFound =
false;
562 setItr = star.begin();
563 for ( ; setItr != star.end(); ++setItr) {
564 if (nVec == setItr->indicesStd) {
576 newStar.invertFlag = 0;
577 rootItr = bunch.begin();
585 newStar.invertFlag = 1;
592 setItr = bunch.begin();
593 for ( ; setItr != bunch.end(); ++setItr) {
594 if (nVec == setItr->indicesStd) {
606 std::cout <<
"Inverse not found for: " <<
"\n";
607 std::cout <<
" vec (std):"
608 << rootVecStd <<
"\n";
609 std::cout <<
" vec (min):"
610 << rootVecMin <<
"\n";
611 std::cout <<
"-vec (std):" << nVec <<
"\n";
619 stars_.append(newStar);
620 starBegin = newStar.endId;
631 for (j = 0; j < bunchList.
size(); ++j) {
633 waves_[k].indicesStd = bunchList[j].indicesStd;
634 waves_[k].indicesMin = bunchList[j].indicesMin;
635 waves_[k].sqNorm = bunchList[j].sqNorm;
636 coeff = std::complex<double>(0.0, bunchList[j].phase);
638 if (std::abs(
imag(coeff)) < 1.0E-6) {
639 coeff = std::complex<double>(
real(coeff), 0.0);
641 if (std::abs(
real(coeff)) < 1.0E-6) {
642 coeff = std::complex<double>(0.0,
imag(coeff));
644 waves_[k].coeff = coeff;
653 bunchBegin = bunchEnd;
658 nStar_ = stars_.size();
675 std::complex<double> rootCoeff;
676 std::complex<double> partCoeff;
677 std::complex<double> d;
679 for (i = 0; i < nStar_; ++i) {
683 if (stars_[i].invertFlag == 0) {
686 for (j = stars_[i].beginId; j < stars_[i].endId; ++j) {
687 if (waves_[j].inverseId < 0) {
690 nVec.negate(waves_[j].indicesMin);
691 (*meshPtr_).shift(nVec);
697 k = stars_[i].endId - 1 - (j - stars_[i].beginId);
698 if (nVec == waves_[k].indicesStd) {
699 waves_[j].inverseId = k;
700 waves_[k].inverseId = j;
705 for (k = j; k < stars_[i].endId; ++k) {
706 if (nVec == waves_[k].indicesStd) {
707 waves_[j].inverseId = k;
708 waves_[k].inverseId = j;
716 if (waves_[j].inverseId < 0) {
718 std::cout <<
"Inverse not found in closed star"
720 std::cout <<
"G = " << waves_[j].indicesMin
721 <<
", coeff = " << waves_[j].coeff
723 std::cout <<
"All waves in star " << i
725 for (k=stars_[i].beginId; k < stars_[i].endId; ++k) {
726 std::cout << waves_[k].indicesMin <<
" "
727 << waves_[k].coeff << std::endl;
738 rootId = stars_[i].beginId;
739 stars_[i].waveMin = waves_[rootId].indicesMin;
741 if (stars_[i].cancel) {
744 std::complex<double> czero(0.0, 0.0);
745 for (j = stars_[i].beginId; j < stars_[i].endId; ++j) {
746 waves_[j].coeff = czero;
752 partId = waves_[rootId].inverseId;
755 rootCoeff = waves_[rootId].coeff;
756 for (j = stars_[i].beginId; j < stars_[i].endId; ++j) {
757 waves_[j].coeff /= rootCoeff;
759 rootCoeff = waves_[rootId].coeff;
764 if (partId != rootId) {
766 partCoeff = waves_[partId].coeff;
767 UTIL_CHECK(std::abs(std::abs(partCoeff) - 1.0) < 1.0E-9);
768 if (std::abs(partCoeff - rootCoeff) > 1.0E-6) {
770 if (
real(d) < -1.0E-4) {
773 if (std::abs(
real(d)) <= 1.0E-4) {
778 for (j=stars_[i].beginId; j < stars_[i].endId; ++j){
779 waves_[j].coeff /= d;
789 if (stars_[i].invertFlag == 1) {
794 UTIL_CHECK(stars_[i].size == stars_[i+1].size);
795 UTIL_CHECK(stars_[i].cancel == stars_[i+1].cancel);
799 for (j = stars_[i].beginId; j < stars_[i].endId; ++j) {
800 if (waves_[j].inverseId < 0) {
803 nVec.negate(waves_[j].indicesMin);
804 (*meshPtr_).shift(nVec);
810 k = stars_[i+1].endId - 1 - (j - stars_[i].beginId);
811 if (nVec == waves_[k].indicesStd) {
812 waves_[j].inverseId = k;
813 waves_[k].inverseId = j;
818 k = stars_[i+1].beginId;
819 for ( ; k < stars_[i+1].endId; ++k) {
820 if (nVec == waves_[k].indicesStd) {
821 waves_[j].inverseId = k;
822 waves_[k].inverseId = j;
837 for (j = stars_[i+1].beginId; j < stars_[i+1].endId; ++j) {
843 rootId = stars_[i].beginId;
844 stars_[i].waveMin = waves_[rootId].indicesMin;
848 partId = waves_[rootId].inverseId;
849 stars_[i+1].waveMin = waves_[partId].indicesMin;
851 if (stars_[i].cancel) {
853 std::complex<double> czero(0.0, 0.0);
854 for (j = stars_[i].beginId; j < stars_[i].endId; ++j) {
855 waves_[j].coeff = czero;
857 for (j = stars_[i+1].beginId; j < stars_[i+1].endId; ++j) {
858 waves_[j].coeff = czero;
864 rootCoeff = waves_[rootId].coeff;
865 for (j = stars_[i].beginId; j < stars_[i].endId; ++j) {
866 waves_[j].coeff /= rootCoeff;
870 partCoeff = waves_[partId].coeff;
871 for (j = stars_[i+1].beginId; j < stars_[i+1].endId; ++j) {
872 waves_[j].coeff /= partCoeff;
885 for (i = 0; i < nStar_; ++i) {
886 double snorm = 1.0/sqrt(
double(stars_[i].size));
887 for (j = stars_[i].beginId; j < stars_[i].endId; ++j) {
888 waves_[j].coeff *= snorm;
889 waves_[j].starId = i;
894 for (i = 0; i < nWave_; ++i) {
895 if (std::abs(
real(waves_[i].coeff)) < 1.0E-8) {
897 = std::complex<double>(0.0,
imag(waves_[i].coeff));
899 if (std::abs(
imag(waves_[i].coeff)) < 1.0E-8) {
901 = std::complex<double>(
real(waves_[i].coeff), 0.0);
906 for (i = 0; i < nWave_; ++i) {
907 vec = waves_[i].indicesStd;
910 for (j = 0; j < D; ++j) {
916 if ((vec[D-1] + 1) > (meshDimensions[D-1]/2 + 1)) {
917 waves_[i].implicit =
true;
919 waves_[i].implicit =
false;
923 waveIds_[mesh().rank(vec)] = i;
927 starIds_.allocate(nBasis_);
929 for (i = 0; i < nStar_; ++i) {
930 stars_[i].starId = i;
931 if (stars_[i].cancel) {
932 stars_[i].basisId = -1;
934 stars_[i].basisId = j;
953 out <<
"N_wave" << std::endl;
955 out <<
" " << nWave_ << std::endl;
957 out <<
" " << nBasisWave_ << std::endl;
961 for (i = 0; i < nWave_; ++i) {
962 starId = waves_[i].starId;
963 if (outputAll || (!stars_[starId].cancel)) {
966 for (j = 0; j < D; ++j) {
967 out <<
Int(waves_[i].indicesMin[j], 5);
969 out <<
Int(waves_[i].starId, 6);
970 out <<
" " <<
Dbl(waves_[i].coeff.real(), 15);
971 out <<
" " <<
Dbl(waves_[i].coeff.imag(), 15);
984 out <<
"N_star" << std::endl
985 <<
" " << nStar_ << std::endl;
987 out <<
"N_basis" << std::endl
988 <<
" " << nBasis_ << std::endl;
993 for (i = 0; i < nStar_; ++i) {
994 if (outputAll || (!stars_[i].cancel)) {
995 out <<
Int(stars_[i].basisId, 6);
997 out <<
Int(stars_[i].size, 5)
998 <<
Int(stars_[i].beginId, 8)
999 <<
Int(stars_[i].endId, 8)
1000 <<
Int(stars_[i].invertFlag, 4);
1002 out <<
Int(stars_[i].cancel, 4);
1004 for (j = 0; j < D; ++j) {
1005 out <<
Int(stars_[i].waveMin[j], 6);
1017 int is, ib, iw, iwp, j;
1020 if (nWave_ != mesh().size()) {
1021 std::cout <<
"nWave != size of mesh" << std::endl;
1030 if (
wave(iw).indicesStd != v) {
1031 std::cout <<
"Inconsistent waveId and Wave::indicesStd"
1038 for (iw = 0; iw < nWave_; ++iw) {
1041 v = waves_[iw].indicesMin;
1042 Gsq = unitCell().ksq(v);
1043 if (std::abs(Gsq - waves_[iw].sqNorm) > 1.0E-8) {
1045 std::cout <<
"Incorrect sqNorm:" <<
"\n"
1046 <<
"wave.indicesMin = " <<
"\n"
1047 <<
"wave.sqNorm = " << waves_[iw].sqNorm <<
"\n"
1048 <<
"|v|^{2} = " << Gsq <<
"\n";
1054 if (v != waves_[iw].indicesStd) {
1056 std::cout <<
"shift(indicesMin) != indicesStd" << std::endl;
1061 is = waves_[iw].starId;
1062 if (iw < stars_[is].beginId) {
1064 std::cout <<
"Wave::starId < Star::beginId" << std::endl;
1067 if (iw >= stars_[is].endId) {
1069 std::cout <<
"Wave::starId >= Star::endId" << std::endl;
1074 if (waves_[iw].inverseId < 0) {
1076 std::cout <<
"Wave::inverseId not assigned\n";
1077 std::cout <<
"G = " << waves_[iw].indicesMin << std::endl;
1082 v.
negate(waves_[iw].indicesMin);
1084 iwp = waves_[iw].inverseId;
1085 if (waves_[iwp].indicesStd != v) {
1087 std::cout <<
"Wave::inverseId is not inverse" << std::endl;
1088 std::cout <<
"G = " << waves_[iw].indicesMin << std::endl;
1089 std::cout <<
"-G (from inverseId) = "
1090 << waves_[iwp].indicesMin << std::endl;
1095 if (waves_[iwp].inverseId != iw) {
1097 std::cout <<
"Wave::inverseId values do not agree\n";
1098 std::cout <<
"+G = " << waves_[iw].indicesMin << std::endl;
1099 std::cout <<
"-G = " << waves_[iwp].indicesMin << std::endl;
1104 if (waves_[iw].implicit ==
true && waves_[iwp].implicit ==
true)
1107 std::cout <<
"Wave and its inverse are both implicit";
1108 std::cout <<
"+G = " << waves_[iw].indicesMin << std::endl;
1109 std::cout <<
"-G = " << waves_[iwp].indicesMin << std::endl;
1116 for (is = 0; is < nStar_; ++is) {
1119 nWave += stars_[is].size;
1120 if (stars_[is].size != stars_[is].endId - stars_[is].beginId) {
1122 std::cout <<
"Inconsistent Star::size:" << std::endl;
1123 std::cout <<
"Star id " << is << std::endl;
1124 std::cout <<
"star size " << stars_[is].size << std::endl;
1125 std::cout <<
"Star begin " << stars_[is].beginId << std::endl;
1126 std::cout <<
"Star end " << stars_[is].endId << std::endl;
1130 if (stars_[is].beginId != stars_[is-1].endId) {
1132 std::cout <<
"Star ranges not consecutive:" << std::endl;
1133 std::cout <<
"Star id " << is << std::endl;
1134 std::cout <<
"stars_[" << is <<
"]" <<
".beginId = "
1135 << stars_[is].beginId << std::endl;
1136 std::cout <<
"stars_[" << is-1 <<
"]" <<
".endId = "
1137 << stars_[is-1].endId << std::endl;
1143 if (stars_[is].invertFlag == -1) {
1144 v.
negate(stars_[is-1].waveMin);
1145 v = shiftToMinimum(v, mesh().dimensions(), *unitCellPtr_);
1146 if (stars_[is].waveMin != v) {
1148 std::cout <<
"waveMin of star is not inverse of waveMin "
1149 <<
"of previous star" << std::endl;
1150 std::cout <<
"star id " << is << std::endl;
1151 std::cout <<
"waveMin " << stars_[is].waveMin << std::endl;
1152 std::cout <<
"waveMin (previous star) "
1153 << stars_[is-1].waveMin << std::endl;
1157 v = waves_[stars_[is].beginId].indicesMin;
1158 if (stars_[is].waveMin != v) {
1160 std::cout <<
"waveMin of star != first wave of star"
1162 std::cout <<
"star id " << is << std::endl;
1163 std::cout <<
"waveMin " << stars_[is].waveMin
1165 std::cout <<
"first wave " << v << std::endl;
1171 for (iw = stars_[is].beginId; iw < stars_[is].endId; ++iw) {
1172 if (waves_[iw].starId != is) {
1174 std::cout <<
"Inconsistent Wave::starId :" << std::endl;
1175 std::cout <<
"star id " << is << std::endl;
1176 std::cout <<
"star beginId " << stars_[is].beginId <<
"\n";
1177 std::cout <<
"star endId " << stars_[is].endId <<
"\n";
1178 std::cout <<
"wave id " << iw <<
"\n";
1179 std::cout <<
"wave starId " << waves_[iw].starId <<
"\n";
1185 if (stars_[is].starId != is) {
1187 std::cout <<
"stars_[is].starId != is for "
1188 <<
"is = " << is <<
"\n";
1193 ib = stars_[is].basisId;
1194 if (stars_[is].cancel) {
1197 std::cout <<
"basisId != -1 for cancelled star\n";
1198 std::cout <<
"star id = " << is <<
"\n";
1202 if (starIds_[ib] != is) {
1204 std::cout <<
"starIds_[stars_[is].basisId] != is for: \n";
1205 std::cout <<
"is = " << is <<
"\n";
1206 std::cout <<
"ib = stars_[is].basisId = " << ib <<
"\n";
1207 std::cout <<
"starIds_[ib] = " << starIds_[ib]
1214 for (iw = stars_[is].beginId + 1; iw < stars_[is].endId; ++iw) {
1215 if (waves_[iw].indicesMin > waves_[iw-1].indicesMin) {
1217 std::cout <<
"Failure of ordering by indicesB within star"
1221 if (waves_[iw].indicesMin == waves_[iw-1].indicesMin) {
1223 std::cout <<
"Equal values of indicesMin within star"
1230 if (stars_[is].cancel) {
1231 for (iw = stars_[is].beginId + 1; iw < stars_[is].endId; ++iw)
1233 if (std::abs(waves_[iw].coeff) > 1.0E-8) {
1235 std::cout <<
"Nonzero coefficient in a cancelled star"
1237 std::cout <<
"G = " << waves_[iw].indicesMin
1238 <<
" coeff = " << waves_[iw].coeff
1248 if (stars_[nStar_-1].endId != mesh().size()) {
1250 std::cout <<
"Star endId of last star != mesh size" << std::endl;
1253 if (
nWave != mesh().size()) {
1255 std::cout <<
"Sum of star sizes != mesh size" << std::endl;
1261 std::complex<double> cdel;
1264 while (is < nStar_) {
1265 cancel = stars_[is].cancel;
1267 if (stars_[is].invertFlag == 0) {
1270 int begin = stars_[is].beginId;
1271 int end = stars_[is].endId;
1272 for (iw = begin; iw < end; ++iw) {
1273 iwp = waves_[iw].inverseId;
1274 if (waves_[iwp].starId != is) {
1276 std::cout <<
"Inverse not found in closed star"
1278 std::cout <<
"G = " << waves_[iw].indicesMin
1279 <<
"coeff = " << waves_[iw].coeff
1281 std::cout <<
"All waves in star " << is <<
"\n";
1282 for (j=begin; j < end; ++j) {
1283 std::cout << waves_[j].indicesMin <<
" "
1284 << waves_[j].coeff <<
"\n";
1289 cdel = std::conj(waves_[iwp].coeff);
1290 cdel -= waves_[iw].coeff;
1291 if (std::abs(cdel) > 1.0E-8) {
1293 std::cout <<
"Function for closed star is not real:"
1295 std::cout <<
"+G = " << waves_[iw].indicesMin
1296 <<
" coeff = " << waves_[iw].coeff
1298 std::cout <<
"-G = " << waves_[iwp].indicesMin
1299 <<
" coeff = " << waves_[iwp].coeff
1301 std::cout <<
"Coefficients are not conjugates."
1303 std::cout <<
"All waves in star " << is <<
"\n";
1304 for (j=begin; j < end; ++j) {
1305 std::cout << waves_[j].indicesMin <<
" "
1306 << waves_[j].coeff <<
"\n";
1320 if (stars_[is].invertFlag != 1) {
1322 std::cout <<
"Expected invertFlag == 1" << std::endl;
1325 if (stars_[is+1].invertFlag != -1) {
1327 std::cout <<
"Expected invertFlag == -1" << std::endl;
1330 if (stars_[is+1].size != stars_[is].size) {
1332 std::cout <<
"Partner stars of different size" << std::endl;
1335 if (stars_[is+1].cancel != stars_[is].cancel) {
1337 std::cout <<
"Partners stars with different cancel flags"
1343 int begin1 = stars_[is].beginId;
1344 int end1 = stars_[is].endId;
1345 int begin2 = stars_[is+1].beginId;
1346 int end2 = stars_[is+1].endId;
1352 for (iw = begin1; iw < end1; ++iw) {
1353 iwp = waves_[iw].inverseId;
1354 if (waves_[iwp].starId != is + 1) {
1356 std::cout <<
"Inverse not found for G in open star"
1358 std::cout <<
"First star id = " << is << std::endl;
1359 std::cout <<
"+G = " << waves_[iw].indicesMin
1360 <<
"coeff = " << waves_[iw].coeff
1362 std::cout <<
"Waves in star " << is
1363 <<
" (starInvert ==1):" <<
"\n";
1364 for (j = begin1; j < end1; ++j) {
1365 std::cout << waves_[j].indicesMin <<
" "
1366 << waves_[j].coeff <<
"\n";
1368 std::cout <<
"Waves in star " << is+1
1369 <<
" (starInvert == -1):" <<
"\n";
1370 for (j=begin2; j < end2; ++j) {
1371 std::cout << waves_[j].indicesMin <<
" "
1372 << waves_[j].coeff <<
"\n";
1377 cdel = std::conj(waves_[iwp].coeff);
1378 cdel -= waves_[iw].coeff;
1379 if (std::abs(cdel) > 1.0E-8) {
1381 std::cout <<
"Error of coefficients in open stars:"
1383 std::cout <<
"First star id = " << is << std::endl;
1384 std::cout <<
"+G = " << waves_[iw].indicesMin
1385 <<
" coeff = " << waves_[iw].coeff
1387 std::cout <<
"-G = " << waves_[iwp].indicesMin
1388 <<
" coeff = " << waves_[iwp].coeff
1390 std::cout <<
"Coefficients are not conjugates."
1392 std::cout <<
"Waves in star " << is
1393 <<
" (starInvert ==1):" <<
"\n";
1394 for (j = begin1; j < end1; ++j) {
1395 std::cout << waves_[j].indicesMin <<
" "
1396 << waves_[j].coeff <<
"\n";
1398 std::cout <<
"Waves in star " << is+1
1399 <<
" (starInvert == -1):" <<
"\n";
1400 for (j=begin2; j < end2; ++j) {
1401 std::cout << waves_[j].indicesMin <<
" "
1402 << waves_[j].coeff <<
"\n";
1417 for (ib = 0; ib < nBasis_; ++ib) {
1419 if (stars_[is].cancel) {
1421 std::cout <<
"Star referred to by starIds_ is cancelled\n";
1424 if (stars_[is].basisId != ib) {
1426 std::cout <<
"Error: stars_[starIds_[ib]].basisId != ib\n";
1427 std::cout <<
"Basis function index ib = " << ib <<
"\n";
1428 std::cout <<
"is = starIds_[ib] = " << is <<
"\n";
1429 std::cout <<
"stars_[is].basisId = "
1430 << stars_[is].basisId <<
"\n";
An IntVec<D, T> is a D-component vector of elements of integer type T.
Iterator over points in a Mesh<D>.
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)?
IntVec< D > position() const
Get current position in the grid, as integer vector.
Description of a regular grid of points in a periodic domain.
A list of wavevectors that are related by space-group symmetries.
Wave const & wave(int id) const
Get a specific Wave, access by integer index.
int nBasis() const
Total number of nonzero symmetry-adapted basis functions.
int waveId(IntVec< D > vector) const
Get the integer index of a wave, as required by wave(int id).
void makeBasis(Mesh< D > const &mesh, UnitCell< D > const &unitCell, SpaceGroup< D > const &group)
Construct basis for a specific mesh and space group.
Signal< void > & signal()
Get a Signal that is triggered by basis initialization.
void outputWaves(std::ostream &out, bool outputAll=false) const
Print a list of all waves to an output stream.
int nWave() const
Total number of wavevectors.
bool isValid() const
Returns true if this basis is valid, false otherwise.
void outputStars(std::ostream &out, bool outputAll=false) const
Print a list of all stars to an output stream.
Crystallographic space group.
void checkMeshDimensions(IntVec< D > const &dimensions) const
Check if input mesh dimensions are compatible with space group.
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.
static const double Pi
Trigonometric constant Pi.
Wrapper for a double precision number, for formatted ostream output.
An automatically growable array, analogous to a std::vector.
int size() const
Return logical size of this array (i.e., current number of elements).
void clear()
Reset to empty state.
void append(Data const &data)
Append an element to the end of the sequence.
Wrapper for an int, for formatted ostream output.
Notifier (or subject) in the Observer design pattern.
#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.
double imag(fftw_complex const &a)
Return the imaginary part of an fftw_complex number.
double real(fftw_complex const &a)
Return the real part of an fftw_complex number.
Periodic fields and crystallography.
PSCF package top-level namespace.
Comparator for BWave objects, based on BWave::indicesMin.
Comparator for BWave objects, based on BWave::indicesStd.
Wave struct designed for use within Basis construction.