14bool report_pass(std::string message,
double eps,
double limit) {
16 static int is_terminal = -1;
17 static std::string ok_string, fail_string;
19 if (is_terminal < 0) {
20 is_terminal = isatty(fileno(stdout));
23 ok_string =
"\x1B[32m --- \033[0m ";
24 fail_string =
"\x1B[31m *** \033[0m ";
27 fail_string =
" *** ";
32 hila::out0 << ok_string << message <<
" passed" << std::endl;
35 hila::out0 << fail_string << message <<
" FAILED: eps " << eps <<
" limit " << limit
43void test_functions() {
46 report_pass(
"Field functions: real exp",
exp(df).sum() - lattice.volume(), 1e-8);
49 report_pass(
"Field functions: complex exp",
abs(
exp(cf).sum() - lattice.volume()), 1e-8);
51 df[
ALL] =
sin(X.x() * 2 * M_PI / lattice.size(e_x));
52 report_pass(
"Field functions: sin", df.
sum(), 1e-8);
58void check_reductions() {
64 f[
ALL] =
expi(2 * M_PI * X.coordinate(e_x) / lattice.size(e_x));
67 onsites(
ALL) sum += f[X];
69 sum /= lattice.volume();
70 report_pass(
"Complex reduction value " + hila::prettyprint(sum),
abs(sum), 1e-4);
75 rv[X.coordinate(e_x)] += f[X];
79 for (
int i = 0; i < lattice.size(e_x); i++) {
81 expi(2 * M_PI * i / lattice.size(e_x)) - rv[i] / (lattice.volume() / lattice.size(e_x));
83 report_pass(
"Vector reduction, sum " + hila::prettyprint(sum),
abs(sum), 1e-4);
96 sum /= lattice.volume();
98 rv[0] -= lattice.volume();
99 rv[1] += 0.01 * lattice.volume();
101 for (
int i = 0; i < lattice.size(e_x); i++) {
103 expi(2 * M_PI * i / lattice.size(e_x)) - rv[i] / (lattice.volume() / lattice.size(e_x));
105 report_pass(
"Combined reductions, sum " + hila::prettyprint(sum) +
", sum2 " +
106 hila::prettyprint(sum2),
107 abs(sum) +
abs(sum2), 1e-4);
114void test_site_access() {
120 for (
int i = 0; i < 3; i++) {
126 report_pass(
"Setting and reading a value at " + hila::prettyprint(c.
transpose()),
127 abs(sum - 4), 1e-10);
145 report_pass(
"Maxloc is " + hila::prettyprint(loc.
transpose()), (c - loc).norm(), 1e-8);
146 report_pass(
"Max value " + hila::prettyprint(v), v - 2, 1e-9);
153 report_pass(
"Minloc is " + hila::prettyprint(loc.
transpose()), (c - loc).norm(), 1e-8);
154 report_pass(
"Min value " + hila::prettyprint(v), v + 1, 1e-9);
163 constexpr int n_loops = 100;
167 double fsum = 0, fsqr = 0;
168 for (
int i = 0; i < n_loops; i++) {
170 double s = 0, s2 = 0;
175 fsum += s / lattice.volume();
176 fsqr += s2 / lattice.volume();
182 report_pass(
"Gaussian random average (6 sigma limit) " + hila::prettyprint(fsum),
abs(fsum),
183 6 /
sqrt(((
double)n_loops) * lattice.volume()));
185 report_pass(
"Gaussian random width^2 " + hila::prettyprint(fsqr), fsqr - 1,
186 6 /
sqrt(((
double)n_loops) * lattice.volume()));
193void test_set_elements_and_select() {
198 std::vector<CoordinateVector> cvec;
199 std::vector<Complex<double>> vals;
204 for (
int i = 0; i <= 50; i++) {
223 f.set_elements(vals, cvec);
228 for (
int i = 0; i < vals.size(); i++) {
232 report_pass(
"Field set_elements and get_elements with " + hila::prettyprint(vals.size()) +
239 SiteValueSelect<Complex<double>> sv;
248 report_pass(
"SiteSelect size " + hila::prettyprint(s.size()), s.size() - cvec.size(), 1e-3);
249 report_pass(
"SiteValueSelect size " + hila::prettyprint(sv.size()), sv.size() - cvec.size(),
254 for (
auto &c : cvec) {
256 for (
int i = 0; !found && i < s.size(); i++) {
257 if (s.coordinates(i) == c)
264 report_pass(
"SiteSelect content", 1 - ok, 1e-6);
267 for (
int k = 0; k < cvec.size(); k++) {
270 for (
int i = 0; !found && i < sv.size(); i++) {
271 if (sv.coordinates(i) == cvec[k] && sv.value(i) == vals[k])
278 report_pass(
"SiteValueSelect content", 1 - ok, 1e-6);
286void test_subvolumes() {
289 for (
int i = 0; i < 20; i++) {
293 if (si.coordinates() != c)
297 report_pass(
"SiteIndex", ok ==
false, 1e-2);
305 size_t vol = lattice.volume();
312 vol /= lattice.size(d);
315 report_pass(hila::prettyprint(NDIM - (
int)d - 1) +
"-dimensional slice size " +
316 hila::prettyprint(vol),
317 slice.size() - vol, 1e-3);
334 for (
auto s : slice) {
339 if (add && c[d2] < 0) {
341 if (mycoord[d2] < lattice.size(d2)) {
349 if (pass && mycoord != s.coordinates()) {
351 << hila::prettyprint(mycoord.
transpose()) <<
" is "
352 << hila::prettyprint(s.coordinates().transpose()) <<
" slice is "
353 << hila::prettyprint(c.
transpose()) <<
'\n';
359 report_pass(
"slice content", pass ==
false, 1e-2);
380 p2[{0, 0, 0}] = lattice.volume();
384 double eps = squarenorm_relative(p, p2);
386 report_pass(
"FFT constant field", eps, 1e-13 *
sqrt(lattice.volume()));
396 sum += (f[X] - lattice.volume()).
squarenorm();
400 eps = fabs(sum / tnorm);
402 report_pass(
"FFT inverse transform", eps, 1e-10);
405 for (
int iter = 0; iter < 5; iter++) {
416 double d = kv.
dot(X.coordinates());
423 p2[kx] = lattice.volume();
425 eps = squarenorm_relative(p, p2);
427 report_pass(
"FFT of wave vector " + hila::prettyprint(kx.
transpose()), eps,
428 1e-13 *
sqrt(lattice.volume()));
438 p = f.FFT(fft_direction::back) / lattice.volume();
439 eps = squarenorm_relative(r, p);
441 report_pass(
"FFT real to complex", eps, 1e-13 *
sqrt(lattice.volume()));
443 auto r2 = f.FFT_complex_to_real(fft_direction::back) / lattice.volume();
444 eps = squarenorm_relative(r, r2);
446 report_pass(
"FFT complex to real", eps, 1e-13 *
sqrt(lattice.volume()));
454 p[X] =
hila::random() *
exp(-X.coordinates().convert_to_k().squarenorm());
456 f = p.FFT(fft_direction::back) /
sqrt(lattice.volume());
460 report_pass(
"Norm of field = " + hila::prettyprint(nf) +
" and FFT = " + hila::prettyprint(np),
461 (nf - np) / nf, 1e-10);
474 report_pass(
"Norm of binned FFT = " + hila::prettyprint(s), (s - np) / np, 1e-10);
479void spectraldensity_test() {
491 for (
int iter = 0; iter < 3; iter++) {
498 auto absk = kv.
norm();
507 for (
int i = 0; i < b.
bins(); i++) {
508 if (b.
bin_min(i) <= absk && b.bin_max(i) > absk) {
516 report_pass(
"Binning test at vector " + hila::prettyprint(kx.
transpose()), sum, 1e-10);
521 double d = kv.
dot(X.coordinates());
528 for (
int i = 0; i < b.
bins(); i++) {
529 if (b.
bin_min(i) <= absk && b.bin_max(i) > absk) {
531 sum += fabs(fsd[i] /
pow(lattice.volume(), 2) - 1);
537 report_pass(
"Spectral density test with above vector ", sum, 1e-10);
543void test_field_slices() {
553void test_matrix_operations() {
557 onsites(
ALL) mf[X].fill(1 +
I);
566 report_pass(
"matrix multiply and addition", sum, 1e-8);
568 auto dm = cm *
I - 2*
I;
570 dm = ((dm - 2).asArray() + 4).asMatrix();
571 report_pass(
"Array and imaginary unit operations", dm.squarenorm(), 1e-8);
583void test_matrix_algebra() {
590 M.gaussian_random(2.0);
596 auto H = M[X] * M[X].
dagger();
598 auto r = H.eigen_hermitean();
599 delta[X] = (H - r.eigenvectors * r.eigenvalues * r.eigenvectors.
dagger()).norm();
602 auto max_delta = delta.
max();
604 report_pass(
"Eigenvalue analysis with " + hila::prettyprint(myMatrix::rows()) +
"x" +
605 hila::prettyprint(myMatrix::columns()) +
" Hermitean matrix",
612 delta[X] = (M[X] - r.U * r.singularvalues * r.V.
dagger()).norm();
615 max_delta = delta.
max();
617 report_pass(
"SVD with " + hila::prettyprint(myMatrix::rows()) +
"x" +
618 hila::prettyprint(myMatrix::columns()) +
" Complex matrix",
626 auto r = M[X].svd_pivot(hila::sort::ascending);
627 delta[X] = (M[X] - r.U * r.singularvalues * r.V.
dagger()).norm();
630 max_delta = delta.
max();
632 report_pass(
"Fully pivoted SVD with " + hila::prettyprint(myMatrix::rows()) +
"x" +
633 hila::prettyprint(myMatrix::columns()) +
" Complex matrix",
640int main(
int argc,
char **argv) {
647 long seed = par.get(
"random seed");
653 lattice.
setup(lsize);
672 test_set_elements_and_select();
676 test_matrix_operations();
680 spectraldensity_test();
682 test_matrix_algebra();
Array< n, m, T > exp(Array< n, m, T > a)
Exponential.
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Array< n, m, T > sqrt(Array< n, m, T > a)
Square root.
Array< n, m, T > pow(Array< n, m, T > a, int b)
Power.
Array< n, m, T > sin(Array< n, m, T > a)
Sine.
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
and get a slice (subvolume)
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.
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.
void setup(const CoordinateVector &siz)
General lattice setup.
constexpr Imaginary_t< double > I(1.0)
Imaginary unit I - global variable.
T abs(const Complex< T > &a)
Return absolute value of Complex number.
#define foralldir(d)
Macro to loop over (all) Direction(s)
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)
int myrank()
rank of this node
double random()
Real valued uniform random number generator.
double gaussrand()
Gaussian random generation routine.
std::ostream out0
This writes output only from main process (node 0)
void initialize(int argc, char **argv)
Read in command line arguments. Initialise default stream and MPI communication.
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...