16bool report_pass(std::string message,
double eps,
double limit) {
18 static int is_terminal = -1;
19 static std::string ok_string, fail_string;
21 if (is_terminal < 0) {
22 is_terminal = isatty(fileno(stdout));
25 ok_string =
"\x1B[32m --- \033[0m ";
26 fail_string =
"\x1B[31m *** \033[0m ";
29 fail_string =
" *** ";
33 if (
abs(eps) < limit) {
34 hila::out0 << ok_string << message <<
" passed" << std::endl;
37 hila::out0 << fail_string << message <<
" FAILED: eps " << eps <<
" limit " << limit
51 report_pass(
"Field functions: real exp", exp(df).sum() - lattice.
volume(), 1e-8);
54 report_pass(
"Field functions: complex exp",
abs(exp(cf).sum() - lattice.
volume()), 1e-8);
56 df[
ALL] = sin(X.x() * 2 * M_PI / lattice.
size(e_x));
57 report_pass(
"Field functions: sin", df.
sum(), 1e-8);
76 f[
ALL] = expi(2 * M_PI * X.coordinate(e_x) / lattice.
size(e_x));
79 onsites(
ALL) sum += f[X];
82 report_pass(
"Complex reduction value " + hila::prettyprint(sum),
abs(sum), 1e-4);
87 rv[X.coordinate(e_x)] += f[X];
91 for (
int i = 0; i < lattice.
size(e_x); i++) {
92 sum += expi(2 * M_PI * i / lattice.
size(e_x)) -
93 rv[i] / (lattice.
volume() / lattice.
size(e_x));
95 report_pass(
"Complex ReductionVector, sum " + hila::prettyprint(sum),
abs(sum), 1e-4);
110 rv[0] -= lattice.
volume();
111 rv[1] += 0.01 * lattice.
volume();
113 for (
int i = 0; i < lattice.
size(e_x); i++) {
114 sum2 += expi(2 * M_PI * i / lattice.
size(e_x)) -
115 rv[i] / (lattice.
volume() / lattice.
size(e_x));
117 report_pass(
"Combined reductions, sum " + hila::prettyprint(sum) +
", sum2 " +
118 hila::prettyprint(sum2),
119 abs(sum) +
abs(sum2), 1e-4);
134 for (
int x = 0; x < rv.
size(); x++) {
135 s +=
abs(rv[x] - x * (lattice.
volume() / lattice.
size(e_x)));
138 report_pass(
"ReductionVector<int64_t>, sum " + hila::prettyprint(s), s, 1e-15);
142 if (X.parity() ==
EVEN)
148 report_pass(
"Reduction with parity", psum, 1e-15);
163 for (
int x = 0; x < rv.
size(); x++) {
164 s +=
abs(rv[x] - x * (lattice.
volume() / lattice.
size(e_x)));
167 report_pass(
"ReductionVector<int64_t>, sum " + hila::prettyprint(s), s, 1e-15);
187 for (
int i = 0; i < lattice.
size(e_x); i++) {
192 report_pass(
"SU(" + std::to_string(N) +
") ReductionVector", diff, 1e-8);
208 for (
int i = 0; i < 3; i++) {
214 report_pass(
"Setting and reading a value at " + hila::prettyprint(c.
transpose()),
215 abs(sum - 4), 1e-10);
235 }
while (!(par ==
ALL || c.parity() == par));
240 n[opp_parity(par)] = 3;
242 auto v = n.
max(par, loc);
243 report_pass(
"Maxloc parity " + hila::prettyprint(par) +
" is " +
245 (c - loc).norm(), 1e-8);
246 report_pass(
"Max parity " + hila::prettyprint(par) +
" value " + hila::prettyprint(v),
251 }
while (!(par ==
ALL || c.parity() == par));
256 n[opp_parity(par)] = -3;
259 report_pass(
"Minloc parity " + hila::prettyprint(par) +
" is " +
261 (c - loc).norm(), 1e-8);
262 report_pass(
"Min parity " + hila::prettyprint(par) +
" value " + hila::prettyprint(v),
274 constexpr int n_loops = 100;
278 double fsum = 0, fsqr = 0;
279 for (
int i = 0; i < n_loops; i++) {
281 double s = 0, s2 = 0;
286 fsum += s / lattice.
volume();
287 fsqr += s2 / lattice.
volume();
293 report_pass(
"Gaussian random average (6 sigma limit) " + hila::prettyprint(fsum),
abs(fsum),
294 6 / sqrt(((
double)n_loops) * lattice.
volume()));
296 report_pass(
"Gaussian random width^2 " + hila::prettyprint(fsqr), fsqr - 1,
297 6 / sqrt(((
double)n_loops) * lattice.
volume()));
311 std::vector<CoordinateVector> cvec;
312 std::vector<Complex<double>> vals;
317 for (
int i = 0; i <= 50; i++) {
336 f.set_elements(vals, cvec);
341 for (
int i = 0; i < vals.size(); i++) {
345 report_pass(
"Field set_elements and get_elements with " + hila::prettyprint(vals.size()) +
352 SiteValueSelect<Complex<double>> sv;
361 report_pass(
"SiteSelect size " + hila::prettyprint(s.size()), s.size() - cvec.size(), 1e-3);
362 report_pass(
"SiteValueSelect size " + hila::prettyprint(sv.size()), sv.size() - cvec.size(),
367 for (
auto &c : cvec) {
369 for (
int i = 0; !found && i < s.size(); i++) {
370 if (s.coordinates(i) == c)
377 report_pass(
"SiteSelect content", 1 - ok, 1e-6);
380 for (
int k = 0; k < cvec.size(); k++) {
383 for (
int i = 0; !found && i < sv.size(); i++) {
384 if (sv.coordinates(i) == cvec[k] && sv.value(i) == vals[k])
391 report_pass(
"SiteValueSelect content", 1 - ok, 1e-6);
405 for (
int i = 0; i < 20; i++) {
409 if (si.coordinates() != c)
414 report_pass(
"SiteIndex", ok ==
false, 1e-2);
422 size_t vol = lattice.
volume();
429 vol /= lattice.
size(d);
432 report_pass(hila::prettyprint(NDIM - (
int)d - 1) +
"-dimensional slice size " +
433 hila::prettyprint(vol),
434 slice.size() - vol, 1e-3);
451 for (
auto s : slice) {
456 if (add && c[d2] < 0) {
458 if (mycoord[d2] < lattice.
size(d2)) {
466 if (pass && mycoord != s.coordinates()) {
468 << hila::prettyprint(mycoord.
transpose()) <<
" is "
469 << hila::prettyprint(s.coordinates().transpose()) <<
" slice is "
470 << hila::prettyprint(c.
transpose()) <<
'\n';
476 report_pass(
"slice content", pass ==
false, 1e-2);
499 p2[{0, 0, 0}] = lattice.
volume();
503 double eps = squarenorm_relative(p, p2);
505 report_pass(
"FFT constant field", eps, 1e-13 * sqrt(lattice.
volume()));
519 eps = fabs(sum / tnorm);
521 report_pass(
"FFT inverse transform", eps, 1e-10);
524 for (
int iter = 0; iter < 5; iter++) {
535 double d = kv.
dot(X.coordinates());
542 p2[kx] = lattice.
volume();
544 eps = squarenorm_relative(p, p2);
546 report_pass(
"FFT of wave vector " + hila::prettyprint(kx.
transpose()), eps,
547 1e-13 * sqrt(lattice.
volume()));
557 p = f.FFT(fft_direction::back) / lattice.
volume();
558 eps = squarenorm_relative(r, p);
560 report_pass(
"FFT real to complex", eps, 1e-13 * sqrt(lattice.
volume()));
565 auto r2 = f.FFT_complex_to_real(fft_direction::back) / lattice.
volume();
566 eps = squarenorm_relative(r, r2);
568 report_pass(
"FFT complex to real", eps, 1e-13 * sqrt(lattice.
volume()));
570 hila::out0 <<
" ... Skipping FFT complex to real because lattice size is odd\n";
579 p[X] =
hila::random() * exp(-X.coordinates().convert_to_k().squarenorm());
581 f = p.FFT(fft_direction::back) / sqrt(lattice.
volume());
585 report_pass(
"Norm of field = " + hila::prettyprint(nf) +
" and FFT = " + hila::prettyprint(np),
586 (nf - np) / nf, 1e-10);
589 b.
k_max(M_PI * sqrt(3.0));
599 report_pass(
"Norm of binned FFT = " + hila::prettyprint(s), (s - np) / np, 1e-10);
615 b.
k_max(M_PI * sqrt(3.0));
619 for (
int iter = 0; iter < 3; iter++) {
626 auto absk = kv.
norm();
635 for (
int i = 0; i < b.
bins(); i++) {
636 if (b.
bin_min(i) <= absk && b.bin_max(i) > absk) {
644 report_pass(
"Binning test at vector " + hila::prettyprint(kx.
transpose()), sum, 1e-10);
649 double d = kv.
dot(X.coordinates());
656 for (
int i = 0; i < b.
bins(); i++) {
657 if (b.
bin_min(i) <= absk && b.bin_max(i) > absk) {
659 sum += fabs(fsd[i] / pow(lattice.
volume(), 2) - 1);
665 report_pass(
"Spectral density test with above vector ", sum, 1e-10);
671void test_field_slices() {
689 onsites(
ALL) mf[X].fill(1 +
I);
698 report_pass(
"matrix multiply and addition", sum, 1e-8);
700 auto dm = cm *
I - 2 *
I;
702 dm = ((dm - 2).asArray() + 4).asMatrix();
703 report_pass(
"Array and imaginary unit operations", dm.squarenorm(), 1e-8);
719 M.gaussian_random(2.0);
725 auto H = M[X] * M[X].
dagger();
727 auto r = H.eigen_hermitean();
728 delta[X] = (H - r.eigenvectors * r.eigenvalues * r.eigenvectors.dagger()).norm();
731 auto max_delta = delta.
max();
733 report_pass(
"Eigenvalue analysis with " + hila::prettyprint(myMatrix::rows()) +
"x" +
734 hila::prettyprint(myMatrix::columns()) +
" Hermitean matrix",
741 delta[X] = (M[X] - r.U * r.singularvalues * r.V.
dagger()).norm();
744 max_delta = delta.
max();
746 report_pass(
"SVD with " + hila::prettyprint(myMatrix::rows()) +
"x" +
747 hila::prettyprint(myMatrix::columns()) +
" Complex matrix",
755 auto r = M[X].svd_pivot(hila::sort::ascending);
756 delta[X] = (M[X] - r.U * r.singularvalues * r.V.
dagger()).norm();
759 max_delta = delta.
max();
761 report_pass(
"Fully pivoted SVD with " + hila::prettyprint(myMatrix::rows()) +
"x" +
762 hila::prettyprint(myMatrix::columns()) +
" Complex matrix",
776 ExtendedPrecision e = 2.4;
777 e = 5 * e - e - e - 3 * e;
778 report_pass(
"ExtendedPrecision basic arithmetics: " + hila::prettyprint(e), fabs(e.to_double()),
783 bool ok = (e > 1) && (e == e);
785 report_pass(
"ExtendedPrecision comparison ops", ok ? 0 : 1, 1e-20);
787 for (
double mag = 1e8; mag <= 1e+32; mag *= 1e8) {
789 size_t nsqr = 0, nmag = 0, n1 = 0;
792 if (X.x() % 2 == 0) {
793 if (X.y() % 2 == 0) {
805 ExtendedPrecision ev = 0;
812 double result = n1 + nmag * mag + nsqr *
sqr(mag);
821 ExtendedPrecision res = 0, r;
835 s -= res.to_double();
860 std::stringstream ssres;
861 ssres <<
"Extended reduction residual w. delta " << mag <<
" : " << ev.to_double() / result
862 <<
" (double " << s / result <<
")";
864 report_pass(ssres.str(), ev.to_double() / result, 1e-20);
871void test_clusters() {
875 m = hila::clusters::background;
878 auto c = X.coordinates();
879 if (c[e_x] == 0 && c[e_y] == 0)
881 else if (c[e_x] == 2 && c[e_z] == 2)
883 else if (c[e_x] == 4 && c[e_y] < 3 && c[e_z] > 1 && c[e_z] <= 4)
887 hila::clusters cl(m);
889 report_pass(
"Cluster test: number of clusters ", cl.number() - 3, 1e-10);
890 if (cl.number() == 3) {
892 fabs(cl.size(0) - (lattice.
volume() / (lattice.
size(e_x) * lattice.
size(e_y)))) +
893 fabs(cl.size(1) - (lattice.
volume() / (lattice.
size(e_x) * lattice.
size(e_z)))) +
894 fabs(cl.size(2) - 1 * 3 * 3);
895 report_pass(
"Cluster test: cluster sizes ", sumsize, 1e-10);
897 double types =
abs(cl.type(0) - 1) +
abs(cl.type(1) - 2) +
abs(cl.type(2) - 3);
898 report_pass(
"Cluster test: cluster types ", types, 1e-10);
901 double area =
abs(cl.area(0) - 4 * lattice.
size(e_z)) +
902 abs(cl.area(1) - 4 * lattice.
size(e_y)) +
903 abs(cl.area(2) - 2 * (1 * 3 + 1 * 3 + 3 * 3));
905 report_pass(
"Cluster test: cluster area ", area, 1e-10);
911void test_blocking() {
918 cvf[
ALL] = X.coordinates();
920 hila::print_dashed_line();
921 lattice.block(blocking);
922 hila::out0 <<
"Testing blocked lattice of size " << lattice.
size() <<
'\n';
924 cvfb.block_from(cvf);
927 sum += (cvfb[X] - 2*X.coordinates()).
squarenorm();
931 report_pass(
"Field blocking test",sum,1e-5);
939 hila::print_dashed_line();
940 hila::out0 <<
"Return lattice to size " << lattice.
size() <<
'\n';
945 if (X.coordinates().is_divisible({2,2,2})) {
946 sum += (X.coordinates() + cvf[X]).
squarenorm();
950 report_pass(
"Field unblocking test",sum,1e-5);
960int main(
int argc,
char **argv) {
967 long seed = par.get(
"random seed");
973 lattice.
setup(lsize);
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Vector< 4, double > convert_to_k() const
Convert momentum space CoordinateVector to wave number k, where -pi/2 < k_i <= pi_2 Utility function ...
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Field< A > dagger() const
Returns dagger or Hermitian conjugate of Field depending on how it is defined for Field type T.
T max(Parity par=ALL) const
Find maximum value from Field.
Field< Complex< hila::arithmetic_type< T > > > FFT_real_to_complex(fft_direction fdir=fft_direction::forward) const
Field< T > conj() const
Returns field with all elements conjugated depending how conjugate is defined for type.
double squarenorm() const
Squarenorm.
std::vector< T > get_elements(const std::vector< CoordinateVector > &coord_list, bool broadcast=false) const
Get a list of elements and store them into a vector.
T min(Parity par=ALL) const
Find minimum value from Field.
T sum(Parity par=Parity::all, bool allreduce=true) const
Sum reduction of Field.
std::vector< T > get_slice(const CoordinateVector &c, bool broadcast=false) const
Get a slice (subvolume)
void unblock_to(Field< T > &target) const
Copy content to the argument Field on blocked (sparse) sites. a.unblock_to(b) is the inverse of a....
void setup(const CoordinateVector &siz)
lattice.setup(CoordinateVector size) - set up the base lattice. Called at the beginning of the progra...
Lattice unblock()
Unblock lattice, returning to parent. Current lattice must be a blocked lattice.
int size(Direction d) const
lattice.size() -> CoordinateVector or lattice.size(d) -> int returns the dimensions of the lattice,...
bool can_block(const CoordinateVector &factor) const
Test if lattice can be blocked by factor given in argument.
int64_t volume() const
lattice.volume() returns lattice volume Can be used inside onsites()-loops
hila::arithmetic_type< T > norm() const
Calculate vector norm - sqrt of squarenorm.
const auto & fill(const S rhs)
Matrix fill.
Rtype transpose() const
Transpose of matrix.
R dot(const Matrix< p, q, S > &rhs) const
Dot product.
const Array< n, m, T > & asArray() const
Cast Matrix to Array.
Matrix class which defines matrix operations.
size_t size() const
methods from std::vector:
Running index for locating sites on the lattice.
std::vector< double > spectraldensity(const Field< T > &f)
k_binning & k_max(double km)
Max value of k.
std::vector< T > bin_k_field(const Field< T > &f)
Generic k-space field binner routine - returns field element type vector.
k_binning & bins(int n)
Set number of bins in histogram.
provides cluster finding tools
constexpr Imaginary_t< double > I(1.0)
Imaginary unit I - global variable.
T abs(const Complex< T > &a)
Return absolute value of Complex number.
Parity
Parity enum with values EVEN, ODD, ALL; refers to parity of the site. Parity of site (x,...
constexpr Parity EVEN
bit pattern: 001
#define foralldir(d)
Macro to loop over (all) Direction(s)
constexpr Parity ODD
bit pattern: 010
constexpr Parity ALL
bit pattern: 011
constexpr T sqr(const T &arg)
Define convenience function sqr(), returning square of argument.
void FFT_field(const Field< T > &input, Field< T > &result, const CoordinateVector &directions, fft_direction fftdir=fft_direction::forward)
void test_spectraldensity()
Test spectral density.
void test_minmax()
Test min and max operations on fields.
void test_matrix_algebra()
Test matrix decomposition.
void test_set_elements_and_select()
Test setting elements and selecting them.
void test_reductions()
Test reduction operations on fields.
void test_matrix_operations()
Test matrix operations.
void test_subvolumes()
Test subvolume operations.
void test_random()
Test Gaussian random field generation.
void test_site_access()
Test site access.
void test_extended()
Test extended type.
void test_functions()
Test various functions on fields.
double random()
Real valued uniform random number generator.
int myrank()
rank of this node
double gaussrand()
Gaussian random generation routine.
std::ostream out0
This writes output only from main process (node 0)
void initialize(int argc, char **argv)
Initial setup routines.
void seed_random(uint64_t seed, bool device_rng=true)
Seed random generators with 64-bit unsigned value. On MPI shuffles the seed so that different MPI ran...
T broadcast(T &var, int rank=0)
Broadcast the value of var to all MPI ranks from rank (default=0).
void finishrun()
Normal, controlled exit - all nodes must call this. Prints timing information and information about c...