18#include "plumbing/lattice.h"
21#include "plumbing/backend_vector/vector_types.h"
23#include "plumbing/com_mpi.h"
27#define onsites(p) for (Parity par_dummy__(p); par_dummy__ == EVEN; par_dummy__ = ODD)
33void ensure_field_operators_exist();
35#include "plumbing/ensure_loop_functions.h"
64 enum class gather_status_t :
unsigned { NOT_DONE, STARTED, DONE };
84 gather_status_t gather_status_arr[3][
NDIRS];
91 MPI_Request receive_request[3][
NDIRS];
92 MPI_Request send_request[3][
NDIRS];
95 T *receive_buffer[
NDIRS];
97 T *send_buffer[
NDIRS];
102 void initialize_communication() {
103 for (
int d = 0; d <
NDIRS; d++) {
104 for (
int p = 0; p < 3; p++)
105 gather_status_arr[p][d] = gather_status_t::NOT_DONE;
106 send_buffer[d] =
nullptr;
108 receive_buffer[d] =
nullptr;
118 void free_communication() {
119 for (
int d = 0; d <
NDIRS; d++) {
120 if (send_buffer[d] !=
nullptr)
121 payload.free_mpi_buffer(send_buffer[d]);
123 if (receive_buffer[d] !=
nullptr)
124 payload.free_mpi_buffer(receive_buffer[d]);
133 void allocate_payload() {
134 payload.allocate_field(lattice);
141 void free_payload() {
142 payload.free_field();
153 inline auto get(
const unsigned i)
const {
154 return payload.get(i, lattice.field_alloc_size());
157 template <
typename A>
158 inline void set(
const A &value,
const unsigned i) {
159 payload.set(value, i, lattice.field_alloc_size());
167 inline auto get_element(
const unsigned i)
const {
171 template <
typename A>
172 inline void set_element(
const A &value,
const unsigned i) {
173 payload.set_element(value, i, lattice);
176 template <
typename vecT>
177 inline vecT get_vector(
const unsigned i)
const {
178 return payload.template get_vector<vecT>(i);
180 inline T get_element(
const unsigned i)
const {
184 template <
typename vecT>
185 inline void set_vector(
const vecT &val,
const unsigned i) {
186 return payload.set_vector(val, i);
188 inline void set_element(
const T &val,
const unsigned i) {
189 return payload.set_element(val, i);
220 void gather_elements(T *buffer,
const std::vector<CoordinateVector> &coord_list,
222 void scatter_elements(T *buffer,
const std::vector<CoordinateVector> &coord_list,
233 static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
234 "Field expects only pod-type elements (plain data): default "
235 "constructor, copy and delete");
281 static_assert(
sizeof(hila::arithmetic_type<T>) == 4 ||
sizeof(hila::arithmetic_type<T>) == 8,
282 "In vectorized arch (e.g. AVX2), only 4 or 8 byte (32 or 64 bit) numbers for "
283 "Field<> implemented, sorry!");
285#if defined(CUDA) || defined(HIP)
286 static_assert(!std::is_same<hila::arithmetic_type<T>,
long double>::value,
287 "Type 'long double' numbers in Field<> not supported by cuda/hip");
300 (*this)[
ALL] = other[X];
308 template <typename A, std::enable_if_t<std::is_convertible<A, T>::value,
int> = 0>
312 (*this)[
ALL] = other[X];
321 template <
typename A,
323 hila::is_assignable<T &, A>::value || std::is_convertible<A, T>::value,
int> = 0>
355 ensure_field_operators_exist<T>();
364 assert(
fs ==
nullptr);
365 if (lattice.volume() == 0) {
366 hila::out0 <<
"Can not allocate Field variables before lattice.setup()\n";
369 fs = (field_struct *)memalloc(
sizeof(field_struct));
370 fs->lattice_id = lattice.id();
371 fs->allocate_payload();
372 fs->initialize_communication();
378#if !defined(CUDA) && !defined(HIP)
379 fs->neighbours[d] = lattice.
neighb[d];
381 fs->payload.neighbours[d] = lattice.backend_lattice->d_neighb[d];
385#ifdef SPECIAL_BOUNDARY_CONDITIONS
387 fs->boundary_condition[dir] = hila::bc::PERIODIC;
388 fs->boundary_condition[-dir] = hila::bc::PERIODIC;
394 fs->vector_lattice = lattice.backend_lattice
397 fs->vector_lattice =
nullptr;
407 if (
fs !=
nullptr && !hila::about_to_finish) {
411 fs->free_communication();
422 return (
fs !=
nullptr);
431 return fs !=
nullptr && ((
fs->assigned_to & parity_bits(p)) != 0);
441 gather_status_t gather_status(
Parity p,
int d)
const {
442 assert(parity_bits(p) && d >= 0 && d <
NDIRS);
443 return fs->gather_status_arr[(int)p - 1][d];
445 void set_gather_status(
Parity p,
int d, gather_status_t stat)
const {
446 assert(parity_bits(p) && d >= 0 && d <
NDIRS);
447 fs->gather_status_arr[(int)p - 1][d] = stat;
478 void mark_changed(
const Parity p)
const {
482 drop_comms(i, opp_parity(p));
484 set_gather_status(opp_parity(p), i, gather_status_t::NOT_DONE);
486 set_gather_status(
ALL, i, gather_status_t::NOT_DONE);
488 set_gather_status(
EVEN, i, gather_status_t::NOT_DONE);
489 set_gather_status(
ODD, i, gather_status_t::NOT_DONE);
492 fs->assigned_to |= parity_bits(p);
508 void mark_gathered(
int dir,
const Parity p)
const {
509 set_gather_status(p, dir, gather_status_t::DONE);
522 bool is_gathered(
int dir,
Parity par)
const {
524 return gather_status(par, dir) == gather_status_t::DONE ||
525 gather_status(
ALL, dir) == gather_status_t::DONE;
527 return gather_status(
ALL, dir) == gather_status_t::DONE ||
528 (gather_status(
EVEN, dir) == gather_status_t::DONE &&
529 gather_status(
ODD, dir) == gather_status_t::DONE);
539 void mark_gather_started(
int dir,
Parity p)
const {
540 set_gather_status(p, dir, gather_status_t::STARTED);
550 bool is_gather_started(
int dir,
Parity par)
const {
551 return gather_status(par, dir) == gather_status_t::STARTED;
554 bool gather_not_done(
int dir,
Parity par)
const {
555 return gather_status(par, dir) == gather_status_t::NOT_DONE;
563 bool boundary_need_to_communicate(
const Direction dir)
const {
564#ifdef SPECIAL_BOUNDARY_CONDITIONS
581#ifdef SPECIAL_BOUNDARY_CONDITIONS
589 "BC possible only for types which implement unary "
590 "minus (-) -operator and are not unsigned");
592 ensure_unary_minus_is_loop_function<T>();
597 fs->boundary_condition[dir] = bc;
598 fs->boundary_condition[-dir] = bc;
599#if !defined(CUDA) && !defined(HIP)
600 fs->neighbours[dir] = lattice.get_neighbour_array(dir, bc);
601 fs->neighbours[-dir] = lattice.get_neighbour_array(-dir, bc);
603 if (bc == hila::bc::PERIODIC) {
604 fs->payload.neighbours[dir] = lattice.backend_lattice->d_neighb[dir];
605 fs->payload.neighbours[-dir] = lattice.backend_lattice->d_neighb[-dir];
607 fs->payload.neighbours[dir] = lattice.backend_lattice->d_neighb_special[dir];
608 fs->payload.neighbours[-dir] = lattice.backend_lattice->d_neighb_special[-dir];
615 assert(bc == hila::bc::PERIODIC &&
616 "Only periodic bondary conditions when SPECIAL_BOUNDARY_CONDITIONS is undefined");
626#ifdef SPECIAL_BOUNDARY_CONDITIONS
627 return fs->boundary_condition[dir];
629 return hila::bc::PERIODIC;
633 void print_boundary_condition() {
636 for (
int dir = 0; dir <
NDIRS; dir++) {
648 template <
typename A>
658 T operator[](
const Parity p)
const;
663 T &operator[](
const Parity p);
670 inline auto field_buffer()
const {
671 return fs->payload.get_buffer();
684 return fs->get_element(i);
688 return fs->get_element(i);
690 template <
typename vecT>
691 inline auto get_vector_at(
unsigned i)
const {
692 return fs->template get_vector<vecT>(i);
694 inline auto get_value_at_nb_site(
Direction d,
unsigned i)
const {
695 return fs->get_element(
fs->vector_lattice->site_neighbour(d, i));
707 template <
typename A>
709 fs->set_element(value, i);
713 template <
typename vecT>
714 inline void set_vector_at(
const vecT &value,
unsigned i) {
715 fs->set_vector(value, i);
718 template <
typename A>
720 fs->set_element(value, i);
755 (*this)[
ALL] = rhs[X];
767 template <
typename A,
769 hila::is_assignable<T &, A>::value || std::is_convertible<A, T>::value,
int> = 0>
771 (*this)[
ALL] = rhs[X];
783 template <
typename A,
785 hila::is_assignable<T &, A>::value || std::is_convertible<A, T>::value,
int> = 0>
844 template <
typename A,
845 std::enable_if_t<std::is_convertible<hila::type_plus<T, A>, T>::value,
int> = 0>
847 (*this)[
ALL] += rhs[X];
877 template <
typename A,
878 std::enable_if_t<std::is_convertible<hila::type_minus<T, A>, T>::value,
int> = 0>
880 (*this)[
ALL] -= rhs[X];
910 template <
typename A,
911 std::enable_if_t<std::is_convertible<hila::type_mul<T, A>, T>::value,
int> = 0>
913 (*this)[
ALL] *= rhs[X];
943 template <
typename A,
944 std::enable_if_t<std::is_convertible<hila::type_div<T, A>, T>::value,
int> = 0>
946 (*this)[
ALL] /= rhs[X];
959 template <
typename A,
960 std::enable_if_t<std::is_convertible<hila::type_plus<T, A>, T>::value,
int> = 0>
974 template <
typename A,
975 std::enable_if_t<std::is_convertible<hila::type_minus<T, A>, T>::value,
int> = 0>
989 template <
typename A,
990 std::enable_if_t<std::is_convertible<hila::type_mul<T, A>, T>::value,
int> = 0>
1004 template <
typename A,
1005 std::enable_if_t<std::is_convertible<hila::type_div<T, A>, T>::value,
int> = 0>
1007 (*this)[
ALL] /= rhs;
1029 f[
ALL] = -(*this)[X];
1041 template <
typename S>
1044 onsites(
ALL) s += !((*this)[X] == rhs[X]);
1048 template <
typename S>
1049 bool operator!=(
const Field<S> &rhs)
const {
1050 return !(*
this == rhs);
1103 template <typename R = T, typename A = decltype(::dagger(std::declval<R>()))>
1117 template <typename R = T, typename A = decltype(::real(std::declval<R>()))>
1131 template <typename R = T, typename A = decltype(::imag(std::declval<R>()))>
1185 template <typename A, std::enable_if_t<std::is_assignable<T &, A>::value,
int> = 0>
1193 mark_changed(coord.parity());
1207 int owner = lattice.node_rank(coord);
1227 void set_elements(
const std::vector<T> &elements,
1228 const std::vector<CoordinateVector> &coord_list);
1236 std::vector<T>
get_elements(
const std::vector<CoordinateVector> &coord_list,
1237 bool broadcast =
false)
const;
1240 bool broadcast =
false)
const;
1244 void copy_local_data(std::vector<T> &buffer)
const;
1245 void set_local_data(
const std::vector<T> &buffer);
1247 void copy_local_data_with_halo(std::vector<T> &buffer)
const;
1265 template <
typename A,
1266 std::enable_if_t<std::is_assignable<T &, hila::type_plus<T, A>>::value,
int> = 0>
1267 inline void compound_add_element(
const CoordinateVector &coord,
const A &av) {
1275 mark_changed(coord.parity());
1278 template <
typename A,
1279 std::enable_if_t<std::is_assignable<T &, hila::type_minus<T, A>>::value,
int> = 0>
1280 inline void compound_sub_element(
const CoordinateVector &coord,
const A &av) {
1288 mark_changed(coord.parity());
1291 template <
typename A,
1292 std::enable_if_t<std::is_assignable<T &, hila::type_mul<T, A>>::value,
int> = 0>
1293 inline void compound_mul_element(
const CoordinateVector &coord,
const A &av) {
1301 mark_changed(coord.parity());
1304 template <
typename A,
1305 std::enable_if_t<std::is_assignable<T &, hila::type_div<T, A>>::value,
int> = 0>
1306 inline void compound_div_element(
const CoordinateVector &coord,
const A &av) {
1314 mark_changed(coord.parity());
1363 FFT_complex_to_real(
fft_direction fdir = fft_direction::forward)
const;
1372 void write(std::ofstream &outputfile,
bool binary =
true,
int precision = 8)
const;
1373 void write(
const std::string &filename,
bool binary =
true,
int precision = 8)
const;
1375 void read(std::ifstream &inputfile);
1376 void read(
const std::string &filename);
1383 template <
typename Out>
1384 void write_slice(Out &outputfile,
const CoordinateVector &slice,
int precision = 6)
const;
1393 T
sum(
Parity par = Parity::all,
bool allreduce =
true)
const;
1402 T
product(
Parity par = Parity::all,
bool allreduce =
true)
const;
1452 void gaussian_random(
double width = 1.0);
1467template <
typename A,
typename B,
1468 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, A>::value &&
1469 !std::is_same<hila::type_plus<A, B>, B>::value,
1473 tmp[
ALL] = lhs[X] + rhs[X];
1478template <
typename A,
typename B,
1479 std::enable_if_t<std::is_same<hila::type_plus<A, B>, A>::value,
int> = 0>
1486template <
typename A,
typename B,
1487 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, A>::value &&
1488 std::is_same<hila::type_plus<A, B>, B>::value,
1498template <
typename A,
typename B,
1499 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, A>::value,
int> = 0>
1502 tmp[
ALL] = lhs[X] + rhs;
1506template <
typename A,
typename B,
1507 std::enable_if_t<std::is_same<hila::type_plus<A, B>, A>::value,
int> = 0>
1517template <
typename A,
typename B,
1518 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, B>::value,
int> = 0>
1523template <
typename A,
typename B,
1524 std::enable_if_t<std::is_same<hila::type_plus<A, B>, B>::value,
int> = 0>
1532template <
typename A,
typename B,
1533 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, A>::value &&
1534 !std::is_same<hila::type_minus<A, B>, B>::value,
1538 tmp[
ALL] = lhs[X] - rhs[X];
1543template <
typename A,
typename B,
1544 std::enable_if_t<std::is_same<hila::type_minus<A, B>, A>::value,
int> = 0>
1551template <
typename A,
typename B,
1552 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, A>::value &&
1553 std::is_same<hila::type_minus<A, B>, B>::value,
1556 rhs[
ALL] = lhs[X] - rhs[X];
1563template <
typename A,
typename B,
1564 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, A>::value,
int> = 0>
1567 tmp[
ALL] = lhs[X] - rhs;
1571template <
typename A,
typename B,
1572 std::enable_if_t<std::is_same<hila::type_minus<A, B>, A>::value,
int> = 0>
1581template <
typename A,
typename B,
1582 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, B>::value,
int> = 0>
1585 tmp[
ALL] = lhs - rhs[X];
1589template <
typename A,
typename B,
1590 std::enable_if_t<std::is_same<hila::type_minus<A, B>, B>::value,
int> = 0>
1592 rhs[
ALL] = lhs - rhs[X];
1599template <
typename A,
typename B,
1600 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, A>::value &&
1601 !std::is_same<hila::type_mul<A, B>, B>::value,
1605 tmp[
ALL] = lhs[X] * rhs[X];
1610template <
typename A,
typename B,
1611 std::enable_if_t<std::is_same<hila::type_mul<A, B>, A>::value,
int> = 0>
1613 lhs[
ALL] = lhs[X] * rhs[X];
1618template <
typename A,
typename B,
1619 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, A>::value &&
1620 std::is_same<hila::type_mul<A, B>, B>::value,
1623 rhs[
ALL] = lhs[X] * rhs[X];
1630template <
typename A,
typename B,
1631 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, B>::value,
int> = 0>
1634 tmp[
ALL] = lhs * rhs[X];
1638template <
typename A,
typename B,
1639 std::enable_if_t<std::is_same<hila::type_mul<A, B>, B>::value,
int> = 0>
1641 rhs[
ALL] = lhs * rhs[X];
1648template <
typename A,
typename B,
1649 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, A>::value,
int> = 0>
1652 tmp[
ALL] = lhs[X] * rhs;
1656template <
typename A,
typename B,
1657 std::enable_if_t<std::is_same<hila::type_mul<A, B>, A>::value,
int> = 0>
1659 lhs[
ALL] = lhs[X] * rhs;
1666template <
typename A,
typename B,
1667 std::enable_if_t<!std::is_same<hila::type_div<A, B>, A>::value &&
1668 !std::is_same<hila::type_div<A, B>, B>::value,
1672 tmp[
ALL] = l[X] / r[X];
1677template <
typename A,
typename B,
1678 std::enable_if_t<std::is_same<hila::type_div<A, B>, A>::value,
int> = 0>
1680 l[
ALL] = l[X] / r[X];
1685template <
typename A,
typename B,
1686 std::enable_if_t<!std::is_same<hila::type_div<A, B>, A>::value &&
1687 std::is_same<hila::type_div<A, B>, B>::value,
1690 r[
ALL] = l[X] / r[X];
1696template <
typename A,
typename B,
1697 std::enable_if_t<!std::is_same<hila::type_div<A, B>, B>::value,
int> = 0>
1700 tmp[
ALL] = lhs / rhs[X];
1704template <
typename A,
typename B,
1705 std::enable_if_t<std::is_same<hila::type_div<A, B>, B>::value,
int> = 0>
1707 rhs[
ALL] = lhs / rhs[X];
1713template <
typename A,
typename B,
1714 std::enable_if_t<!std::is_same<hila::type_div<A, B>, A>::value,
int> = 0>
1717 tmp[
ALL] = lhs[X] / rhs;
1721template <
typename A,
typename B,
1722 std::enable_if_t<std::is_same<hila::type_div<A, B>, A>::value,
int> = 0>
1724 lhs[
ALL] = lhs[X] / rhs;
1733template <
typename T>
1735 std::swap(A.
fs, B.
fs);
1743template <typename T, typename R = decltype(exp(std::declval<T>()))>
1752template <typename T, typename R = decltype(log(std::declval<T>()))>
1761template <typename T, typename R = decltype(sin(std::declval<T>()))>
1770template <typename T, typename R = decltype(cos(std::declval<T>()))>
1779template <typename T, typename R = decltype(tan(std::declval<T>()))>
1788template <typename T, typename R = decltype(asin(std::declval<T>()))>
1797template <typename T, typename R = decltype(acos(std::declval<T>()))>
1806template <typename T, typename R = decltype(atan(std::declval<T>()))>
1815template <typename T, typename R = decltype(abs(std::declval<T>()))>
1824template <typename T, typename P, typename R = decltype(pow(std::declval<T>()), std::declval<P>())>
1833template <
typename T>
1842template <
typename T>
1847template <
typename T>
1852template <typename T, typename A = decltype(::dagger(std::declval<T>()))>
1854 return arg.dagger();
1857template <typename T, typename A = decltype(::real(std::declval<T>()))>
1862template <typename T, typename A = decltype(::imag(std::declval<T>()))>
1868template <typename A, typename B, typename R = decltype(std::declval<A>() - std::declval<B>())>
1878template <
typename T>
1890template <
typename T>
1893 if (is_comm_initialized()) {
1894 if (is_gather_started(d,
ALL))
1895 cancel_comm(d,
ALL);
1897 if (is_gather_started(d, p))
1900 if (is_gather_started(d,
EVEN))
1901 cancel_comm(d,
EVEN);
1902 if (is_gather_started(d,
ODD))
1903 cancel_comm(d,
ODD);
1909template <
typename T>
1912 cancel_receive_timer.start();
1913 MPI_Cancel(&fs->receive_request[(
int)p - 1][d]);
1914 cancel_receive_timer.stop();
1917 cancel_send_timer.start();
1918 MPI_Cancel(&fs->send_request[(
int)p - 1][d]);
1919 cancel_send_timer.stop();
1925template <
typename T>
1937template <
typename T>
1940#if defined(CUDA) || defined(HIP)
1944 std::vector<T> rng_buffer(lattice.mynode.volume());
1945 for (
auto &element : rng_buffer)
1947 (*this).set_local_data(rng_buffer);
1963template <
typename T>
1966#if defined(CUDA) || defined(HIP)
1970 std::vector<T> rng_buffer(lattice.mynode.volume());
1971 for (
auto &element : rng_buffer)
1973 (*this).set_local_data(rng_buffer);
2003inline void dummy_X_f() {
2025 vec[e_x] = vec[0] + vec[e_y] + vec.
e(e_y);
2035template <
typename T>
2036inline void ensure_field_operators_exist() {
2038 ensure_unary_minus_is_loop_function<T>();
2039 ensure_assign_zero_is_loop_function<T>();
Array< n, m, T > conj(const Array< n, m, T > &arg)
Return conjugate Array.
Array< n, m, T > asin(Array< n, m, T > a)
Inverse Sine.
Array< n, m, T > exp(Array< n, m, T > a)
Exponential.
Array< n, m, hila::arithmetic_type< T > > imag(const Array< n, m, T > &arg)
Return imaginary part of Array.
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Array< n, m, T > tan(Array< n, m, T > a)
Tangent.
Array< n, m, T > cos(Array< n, m, T > a)
Cosine.
Array< n, m, T > acos(Array< n, m, T > a)
Inverse Cosine.
Array< n, m, T > sqrt(Array< n, m, T > a)
Square root.
Array< n, m, T > atan(Array< n, m, T > a)
Inverse Tangent.
Array< n, m, T > pow(Array< n, m, T > a, int b)
Power.
Array< n, m, T > sin(Array< n, m, T > a)
Sine.
Array< n, m, hila::arithmetic_type< T > > real(const Array< n, m, T > &arg)
Return real part of Array.
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Field< T > & operator=(const Field< T > &rhs)
Assignment operator.
Field()
Field constructor.
Field< A > real() const
Returns real part of Field.
std::vector< T > get_subvolume(const CoordinateVector &cmin, const CoordinateVector &cmax, bool broadcast=false) const
get a subvolume of the field elements to all nodes
Field< T > & shift(const CoordinateVector &v, Field< T > &r, Parity par) const
Create a periodically shifted copy of the field.
void set_boundary_condition(Direction dir, hila::bc bc)
Set the boundary condition in a given Direction (periodic or antiperiodic)
void write_subvolume(std::ofstream &outputfile, const CoordinateVector &cmin, const CoordinateVector &cmax, int precision=6) const
const T get_element(const CoordinateVector &coord) const
Get singular element which will be broadcast to all nodes.
hila::bc get_boundary_condition(Direction dir) const
Get the boundary condition of the Field.
Field< A > imag() const
Returns imaginary part of Field.
T gpu_minmax(bool min_or_max, Parity par, CoordinateVector &loc) const
Declare gpu_reduce here, defined only for GPU targets.
Field< A > dagger() const
Returns dagger or Hermitian conjugate of Field depending on how it is defined for Field type T.
const T set_element(const CoordinateVector &coord, const A &value)
Get singular element which will be broadcast to all nodes.
T max(Parity par=ALL) const
Find maximum value from Field.
bool is_initialized(Parity p) const
Returns true if the Field has been assigned to.
auto get_value_at(const unsigned i) const
Get an individual element outside a loop. This is also used as a getter in the vanilla code.
field_struct *__restrict__ fs
Field::fs holds all of the field content in Field::field_struct.
void set_value_at(const A &value, unsigned i)
Set an individual element outside a loop. This is also used as a getter in the vanilla code.
void free()
Destroys field data.
Field< T > operator+() const
Unary + operator, acts as Identity.
Field< Complex< hila::arithmetic_type< T > > > FFT_real_to_complex(fft_direction fdir=fft_direction::forward) const
Field< T > & operator=(Field< T > &&rhs)
Move Assignment.
Field< T > & operator*=(const Field< A > &rhs)
Product assignment operator.
bool is_allocated() const
Returns true if the Field data has been allocated.
void copy_boundary_condition(const Field< A > &rhs)
Copy the boundary condition from another field.
Field< T > conj() const
Returns field with all elements conjugated depending how conjugate is defined for type.
T product(Parity par=Parity::all, bool allreduce=true) const
Product reduction of Field.
void check_alloc()
Allocate Field if it is not already allocated.
bool operator==(const Field< S > &rhs) const
Field comparison operator.
double squarenorm() const
Squarenorm.
dir_mask_t start_gather(Direction d, Parity p=ALL) const
Field< T > & operator-=(const Field< A > &rhs)
Subtraction assignment operator.
Field< T > operator-() const
Unary - operator, acts as negation to all field elements.
void write(std::ofstream &outputfile, bool binary=true, int precision=8) const
Write the field to a file stream.
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 minmax(bool is_min, Parity par, CoordinateVector &loc) const
Function to perform min or max operations.
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.
void read(std::ifstream &inputfile)
Read the Field from a stream.
std::vector< T > get_slice(const CoordinateVector &c, bool broadcast=false) const
and get a slice (subvolume)
Field< T > & operator/=(const Field< A > &rhs)
Division assignment operator.
Field< T > & operator+=(const Field< A > &rhs)
Addition assignment operator.
T e(const int i, const int j) const
Standard array indexing operation for matrices and vectors.
X-coordinate type - "dummy" class.
The field_storage struct contains minimal information for using the field in a loop....
auto get_element(const unsigned i, const lattice_struct &lattice) const
Conditionally reture bool type false if type T does't have unary - operator.
bool is_on_mynode(const CoordinateVector &c) const
Is the coordinate on THIS node.
unsigned *__restrict__ neighb[NDIRS]
Main neighbour index array.
std::array< nn_comminfo_struct, NDIRS > nn_comminfo
nearest neighbour comminfo struct
unsigned site_index(const CoordinateVector &c) const
Complex< T > dagger(const Complex< T > &val)
Return dagger of Complex number.
T abs(const Complex< T > &a)
Return absolute value of Complex number.
T arg(const Complex< T > &a)
Return argument of Complex number.
This header file defines:
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 unsigned NDIRS
Number of directions.
constexpr Parity ODD
bit pattern: 010
Direction
Enumerator for direction that assigns integer to direction to be interpreted as unit vector.
constexpr Parity ALL
bit pattern: 011
This file defines all includes for HILA.
fft_direction
define a class for FFT direction
auto operator/(const Field< A > &l, const Field< B > &r) -> Field< hila::type_div< A, B > >
auto operator+(const Field< A > &lhs, const Field< B > &rhs) -> Field< hila::type_plus< A, B > >
operator + (Field + Field) -generic
auto operator-(const Field< A > &lhs, const Field< B > &rhs) -> Field< hila::type_minus< A, B > >
operator - Field - Field -generic
auto operator*(const Field< A > &lhs, const Field< B > &rhs) -> Field< hila::type_mul< A, B > >
Implement hila::swap for gauge fields.
T gaussian_random()
Template function T hila::gaussian_random<T>(),generates gaussian random value of type T,...
logger_class log
Now declare the logger.
int myrank()
rank of this node
bool is_device_rng_on()
Check if the RNG on GPU is allocated and ready to use.
double random()
Real valued uniform random number generator.
std::ostream out0
This writes output only from main process (node 0)
bc
list of field boundary conditions - used only if SPECIAL_BOUNDARY_CONDITIONS defined
T broadcast(T &var, int rank=0)
Broadcast the value of var to all MPI ranks from rank (default=0).
bool bc_need_communication(hila::bc bc)
False if we have b.c. which does not require communication.
void terminate(int status)
T gaussian_random(out_only T &val, double w=1.0)
Template function const T & hila::gaussian_random(T & variable,double width=1)
X + coordinate offset, used in f[X+CoordinateVector] or f[X+dir1+dir2] etc.
is_vectorizable_type<T>::value is always false if the target is not vectorizable
Information necessary to communicate with a node.
bool is_on_edge(Direction d) const
true if this node is on the edge of the lattice to dir d