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 ||
282 sizeof(hila::arithmetic_type<T>) == 8,
283 "In vectorized arch (e.g. AVX2), only 4 or 8 byte (32 or 64 bit) numbers for "
284 "Field<> implemented, sorry!");
286#if defined(CUDA) || defined(HIP)
287 static_assert(!std::is_same<hila::arithmetic_type<T>,
long double>::value,
288 "Type 'long double' numbers in Field<> not supported by cuda/hip");
301 (*this)[
ALL] = other[X];
309 template <typename A, std::enable_if_t<std::is_convertible<A, T>::value,
int> = 0>
313 (*this)[
ALL] = other[X];
322 template <
typename A,
324 hila::is_assignable<T &, A>::value || std::is_convertible<A, T>::value,
int> = 0>
356 ensure_field_operators_exist<T>();
365 assert(
fs ==
nullptr);
366 if (lattice.volume() == 0) {
367 hila::out0 <<
"Can not allocate Field variables before lattice.setup()\n";
370 fs = (field_struct *)memalloc(
sizeof(field_struct));
371 fs->lattice_id = lattice.id();
372 fs->allocate_payload();
373 fs->initialize_communication();
379#if !defined(CUDA) && !defined(HIP)
380 fs->neighbours[d] = lattice.
neighb[d];
382 fs->payload.neighbours[d] = lattice.backend_lattice->
d_neighb[d];
386#ifdef SPECIAL_BOUNDARY_CONDITIONS
388 fs->boundary_condition[dir] = hila::bc::PERIODIC;
389 fs->boundary_condition[-dir] = hila::bc::PERIODIC;
395 fs->vector_lattice = lattice.backend_lattice
398 fs->vector_lattice =
nullptr;
408 if (
fs !=
nullptr && !hila::about_to_finish) {
412 fs->free_communication();
423 return (
fs !=
nullptr);
432 return fs !=
nullptr && ((
fs->assigned_to & parity_bits(p)) != 0);
442 gather_status_t gather_status(
Parity p,
int d)
const {
443 assert(parity_bits(p) && d >= 0 && d <
NDIRS);
444 return fs->gather_status_arr[(int)p - 1][d];
446 void set_gather_status(
Parity p,
int d, gather_status_t stat)
const {
447 assert(parity_bits(p) && d >= 0 && d <
NDIRS);
448 fs->gather_status_arr[(int)p - 1][d] = stat;
479 void mark_changed(
const Parity p)
const {
483 drop_comms(i, opp_parity(p));
485 set_gather_status(opp_parity(p), i, gather_status_t::NOT_DONE);
487 set_gather_status(
ALL, i, gather_status_t::NOT_DONE);
489 set_gather_status(
EVEN, i, gather_status_t::NOT_DONE);
490 set_gather_status(
ODD, i, gather_status_t::NOT_DONE);
493 fs->assigned_to |= parity_bits(p);
509 void mark_gathered(
int dir,
const Parity p)
const {
510 set_gather_status(p, dir, gather_status_t::DONE);
523 bool is_gathered(
int dir,
Parity par)
const {
525 return gather_status(par, dir) == gather_status_t::DONE ||
526 gather_status(
ALL, dir) == gather_status_t::DONE;
528 return gather_status(
ALL, dir) == gather_status_t::DONE ||
529 (gather_status(
EVEN, dir) == gather_status_t::DONE &&
530 gather_status(
ODD, dir) == gather_status_t::DONE);
540 void mark_gather_started(
int dir,
Parity p)
const {
541 set_gather_status(p, dir, gather_status_t::STARTED);
551 bool is_gather_started(
int dir,
Parity par)
const {
552 return gather_status(par, dir) == gather_status_t::STARTED;
555 bool gather_not_done(
int dir,
Parity par)
const {
556 return gather_status(par, dir) == gather_status_t::NOT_DONE;
564 bool boundary_need_to_communicate(
const Direction dir)
const {
565#ifdef SPECIAL_BOUNDARY_CONDITIONS
582#ifdef SPECIAL_BOUNDARY_CONDITIONS
590 "BC possible only for types which implement unary "
591 "minus (-) -operator and are not unsigned");
593 ensure_unary_minus_is_loop_function<T>();
598 fs->boundary_condition[dir] = bc;
599 fs->boundary_condition[-dir] = bc;
600#if !defined(CUDA) && !defined(HIP)
601 fs->neighbours[dir] = lattice.get_neighbour_array(dir, bc);
602 fs->neighbours[-dir] = lattice.get_neighbour_array(-dir, bc);
604 if (bc == hila::bc::PERIODIC) {
605 fs->payload.neighbours[dir] = lattice.backend_lattice->
d_neighb[dir];
606 fs->payload.neighbours[-dir] = lattice.backend_lattice->
d_neighb[-dir];
608 fs->payload.neighbours[dir] = lattice.backend_lattice->d_neighb_special[dir];
609 fs->payload.neighbours[-dir] = lattice.backend_lattice->d_neighb_special[-dir];
616 assert(bc == hila::bc::PERIODIC &&
617 "Only periodic bondary conditions when SPECIAL_BOUNDARY_CONDITIONS is undefined");
627#ifdef SPECIAL_BOUNDARY_CONDITIONS
628 return fs->boundary_condition[dir];
630 return hila::bc::PERIODIC;
634 void print_boundary_condition() {
637 for (
int dir = 0; dir <
NDIRS; dir++) {
649 template <
typename A>
659 T operator[](
const Parity p)
const;
664 T &operator[](
const Parity p);
671 inline auto field_buffer()
const {
672 return fs->payload.get_buffer();
685 return fs->get_element(i);
689 return fs->get_element(i);
691 template <
typename vecT>
692 inline auto get_vector_at(
unsigned i)
const {
693 return fs->template get_vector<vecT>(i);
695 inline auto get_value_at_nb_site(
Direction d,
unsigned i)
const {
696 return fs->get_element(
fs->vector_lattice->site_neighbour(d, i));
708 template <
typename A>
710 fs->set_element(value, i);
714 template <
typename vecT>
715 inline void set_vector_at(
const vecT &value,
unsigned i) {
716 fs->set_vector(value, i);
719 template <
typename A>
721 fs->set_element(value, i);
756 (*this)[
ALL] = rhs[X];
786 template <
typename A,
788 hila::is_assignable<T &, A>::value || std::is_convertible<A, T>::value,
int> = 0>
790 (*this)[
ALL] = rhs[X];
802 template <
typename A,
804 hila::is_assignable<T &, A>::value || std::is_convertible<A, T>::value,
int> = 0>
863 template <
typename A,
864 std::enable_if_t<std::is_convertible<hila::type_plus<T, A>, T>::value,
int> = 0>
866 (*this)[
ALL] += rhs[X];
896 template <
typename A,
897 std::enable_if_t<std::is_convertible<hila::type_minus<T, A>, T>::value,
int> = 0>
899 (*this)[
ALL] -= rhs[X];
929 template <
typename A,
930 std::enable_if_t<std::is_convertible<hila::type_mul<T, A>, T>::value,
int> = 0>
932 (*this)[
ALL] *= rhs[X];
962 template <
typename A,
963 std::enable_if_t<std::is_convertible<hila::type_div<T, A>, T>::value,
int> = 0>
965 (*this)[
ALL] /= rhs[X];
978 template <
typename A,
979 std::enable_if_t<std::is_convertible<hila::type_plus<T, A>, T>::value,
int> = 0>
993 template <
typename A,
994 std::enable_if_t<std::is_convertible<hila::type_minus<T, A>, T>::value,
int> = 0>
1008 template <
typename A,
1009 std::enable_if_t<std::is_convertible<hila::type_mul<T, A>, T>::value,
int> = 0>
1011 (*this)[
ALL] *= rhs;
1023 template <
typename A,
1024 std::enable_if_t<std::is_convertible<hila::type_div<T, A>, T>::value,
int> = 0>
1026 (*this)[
ALL] /= rhs;
1048 f[
ALL] = -(*this)[X];
1060 template <
typename S>
1063 onsites(
ALL) s += !((*this)[X] == rhs[X]);
1067 template <
typename S>
1068 bool operator!=(
const Field<S> &rhs)
const {
1069 return !(*
this == rhs);
1122 template <typename R = T, typename A = decltype(::dagger(std::declval<R>()))>
1136 template <typename R = T, typename A = decltype(::real(std::declval<R>()))>
1150 template <typename R = T, typename A = decltype(::imag(std::declval<R>()))>
1203 template <typename A, std::enable_if_t<std::is_assignable<T &, A>::value,
int> = 0>
1211 mark_changed(coord.parity());
1225 int owner = lattice.node_rank(coord);
1245 void set_elements(
const std::vector<T> &elements,
1246 const std::vector<CoordinateVector> &coord_list);
1254 std::vector<T>
get_elements(
const std::vector<CoordinateVector> &coord_list,
1255 bool broadcast =
false)
const;
1258 bool broadcast =
false)
const;
1262 void copy_local_data(std::vector<T> &buffer)
const;
1263 void set_local_data(
const std::vector<T> &buffer);
1265 void copy_local_data_with_halo(std::vector<T> &buffer)
const;
1283 template <
typename A,
1284 std::enable_if_t<std::is_assignable<T &, hila::type_plus<T, A>>::value,
int> = 0>
1285 inline void compound_add_element(
const CoordinateVector &coord,
const A &av) {
1293 mark_changed(coord.parity());
1296 template <
typename A,
1297 std::enable_if_t<std::is_assignable<T &, hila::type_minus<T, A>>::value,
int> = 0>
1298 inline void compound_sub_element(
const CoordinateVector &coord,
const A &av) {
1306 mark_changed(coord.parity());
1309 template <
typename A,
1310 std::enable_if_t<std::is_assignable<T &, hila::type_mul<T, A>>::value,
int> = 0>
1311 inline void compound_mul_element(
const CoordinateVector &coord,
const A &av) {
1319 mark_changed(coord.parity());
1322 template <
typename A,
1323 std::enable_if_t<std::is_assignable<T &, hila::type_div<T, A>>::value,
int> = 0>
1324 inline void compound_div_element(
const CoordinateVector &coord,
const A &av) {
1332 mark_changed(coord.parity());
1381 FFT_complex_to_real(
fft_direction fdir = fft_direction::forward)
const;
1390 void write(std::ofstream &outputfile,
bool binary =
true,
int precision = 8)
const;
1391 void write(
const std::string &filename,
bool binary =
true,
int precision = 8)
const;
1393 void read(std::ifstream &inputfile);
1394 void read(
const std::string &filename);
1401 template <
typename Out>
1402 void write_slice(Out &outputfile,
const CoordinateVector &slice,
int precision = 6)
const;
1411 T
sum(
Parity par = Parity::all,
bool allreduce =
true)
const;
1420 T
product(
Parity par = Parity::all,
bool allreduce =
true)
const;
1470 void gaussian_random(
double width = 1.0);
1485template <
typename A,
typename B,
1486 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, A>::value &&
1487 !std::is_same<hila::type_plus<A, B>, B>::value,
1491 tmp[
ALL] = lhs[X] + rhs[X];
1496template <
typename A,
typename B,
1497 std::enable_if_t<std::is_same<hila::type_plus<A, B>, A>::value,
int> = 0>
1504template <
typename A,
typename B,
1505 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, A>::value &&
1506 std::is_same<hila::type_plus<A, B>, B>::value,
1516template <
typename A,
typename B,
1517 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, A>::value,
int> = 0>
1520 tmp[
ALL] = lhs[X] + rhs;
1524template <
typename A,
typename B,
1525 std::enable_if_t<std::is_same<hila::type_plus<A, B>, A>::value,
int> = 0>
1535template <
typename A,
typename B,
1536 std::enable_if_t<!std::is_same<hila::type_plus<A, B>, B>::value,
int> = 0>
1541template <
typename A,
typename B,
1542 std::enable_if_t<std::is_same<hila::type_plus<A, B>, B>::value,
int> = 0>
1550template <
typename A,
typename B,
1551 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, A>::value &&
1552 !std::is_same<hila::type_minus<A, B>, B>::value,
1556 tmp[
ALL] = lhs[X] - rhs[X];
1561template <
typename A,
typename B,
1562 std::enable_if_t<std::is_same<hila::type_minus<A, B>, A>::value,
int> = 0>
1569template <
typename A,
typename B,
1570 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, A>::value &&
1571 std::is_same<hila::type_minus<A, B>, B>::value,
1574 rhs[
ALL] = lhs[X] - rhs[X];
1581template <
typename A,
typename B,
1582 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, A>::value,
int> = 0>
1585 tmp[
ALL] = lhs[X] - rhs;
1589template <
typename A,
typename B,
1590 std::enable_if_t<std::is_same<hila::type_minus<A, B>, A>::value,
int> = 0>
1599template <
typename A,
typename B,
1600 std::enable_if_t<!std::is_same<hila::type_minus<A, B>, B>::value,
int> = 0>
1603 tmp[
ALL] = lhs - rhs[X];
1607template <
typename A,
typename B,
1608 std::enable_if_t<std::is_same<hila::type_minus<A, B>, B>::value,
int> = 0>
1610 rhs[
ALL] = lhs - rhs[X];
1617template <
typename A,
typename B,
1618 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, A>::value &&
1619 !std::is_same<hila::type_mul<A, B>, B>::value,
1623 tmp[
ALL] = lhs[X] * rhs[X];
1628template <
typename A,
typename B,
1629 std::enable_if_t<std::is_same<hila::type_mul<A, B>, A>::value,
int> = 0>
1631 lhs[
ALL] = lhs[X] * rhs[X];
1636template <
typename A,
typename B,
1637 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, A>::value &&
1638 std::is_same<hila::type_mul<A, B>, B>::value,
1641 rhs[
ALL] = lhs[X] * rhs[X];
1648template <
typename A,
typename B,
1649 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, B>::value,
int> = 0>
1652 tmp[
ALL] = lhs * rhs[X];
1656template <
typename A,
typename B,
1657 std::enable_if_t<std::is_same<hila::type_mul<A, B>, B>::value,
int> = 0>
1659 rhs[
ALL] = lhs * rhs[X];
1666template <
typename A,
typename B,
1667 std::enable_if_t<!std::is_same<hila::type_mul<A, B>, A>::value,
int> = 0>
1670 tmp[
ALL] = lhs[X] * rhs;
1674template <
typename A,
typename B,
1675 std::enable_if_t<std::is_same<hila::type_mul<A, B>, A>::value,
int> = 0>
1677 lhs[
ALL] = lhs[X] * rhs;
1684template <
typename A,
typename B,
1685 std::enable_if_t<!std::is_same<hila::type_div<A, B>, A>::value &&
1686 !std::is_same<hila::type_div<A, B>, B>::value,
1690 tmp[
ALL] = l[X] / r[X];
1695template <
typename A,
typename B,
1696 std::enable_if_t<std::is_same<hila::type_div<A, B>, A>::value,
int> = 0>
1698 l[
ALL] = l[X] / r[X];
1703template <
typename A,
typename B,
1704 std::enable_if_t<!std::is_same<hila::type_div<A, B>, A>::value &&
1705 std::is_same<hila::type_div<A, B>, B>::value,
1708 r[
ALL] = l[X] / r[X];
1714template <
typename A,
typename B,
1715 std::enable_if_t<!std::is_same<hila::type_div<A, B>, B>::value,
int> = 0>
1718 tmp[
ALL] = lhs / rhs[X];
1722template <
typename A,
typename B,
1723 std::enable_if_t<std::is_same<hila::type_div<A, B>, B>::value,
int> = 0>
1725 rhs[
ALL] = lhs / rhs[X];
1731template <
typename A,
typename B,
1732 std::enable_if_t<!std::is_same<hila::type_div<A, B>, A>::value,
int> = 0>
1735 tmp[
ALL] = lhs[X] / rhs;
1739template <
typename A,
typename B,
1740 std::enable_if_t<std::is_same<hila::type_div<A, B>, A>::value,
int> = 0>
1742 lhs[
ALL] = lhs[X] / rhs;
1751template <
typename T>
1753 std::swap(A.
fs, B.
fs);
1761template <typename T, typename R = decltype(exp(std::declval<T>()))>
1770template <typename T, typename R = decltype(log(std::declval<T>()))>
1779template <typename T, typename R = decltype(sin(std::declval<T>()))>
1788template <typename T, typename R = decltype(cos(std::declval<T>()))>
1797template <typename T, typename R = decltype(tan(std::declval<T>()))>
1806template <typename T, typename R = decltype(asin(std::declval<T>()))>
1815template <typename T, typename R = decltype(acos(std::declval<T>()))>
1824template <typename T, typename R = decltype(atan(std::declval<T>()))>
1833template <typename T, typename R = decltype(abs(std::declval<T>()))>
1842template <typename T, typename P, typename R = decltype(pow(std::declval<T>()), std::declval<P>())>
1851template <
typename T>
1860template <
typename T>
1865template <
typename T>
1870template <typename T, typename A = decltype(::dagger(std::declval<T>()))>
1872 return arg.dagger();
1875template <typename T, typename A = decltype(::real(std::declval<T>()))>
1880template <typename T, typename A = decltype(::imag(std::declval<T>()))>
1886template <typename A, typename B, typename R = decltype(std::declval<A>() - std::declval<B>())>
1896template <
typename T>
1913template <
typename T>
1916 if (is_comm_initialized()) {
1917 if (is_gather_started(d,
ALL)) {
1918 drop_comms_timer.start();
1919 wait_gather(d,
ALL);
1920 drop_comms_timer.stop();
1923 if (is_gather_started(d, p)) {
1924 drop_comms_timer.start();
1926 drop_comms_timer.stop();
1929 if (is_gather_started(d,
EVEN)) {
1930 drop_comms_timer.start();
1931 wait_gather(d,
EVEN);
1932 drop_comms_timer.stop();
1934 if (is_gather_started(d,
ODD)) {
1935 drop_comms_timer.start();
1936 wait_gather(d,
ODD);
1937 drop_comms_timer.stop();
1945template <
typename T>
1957template <
typename T>
1960#if defined(CUDA) || defined(HIP)
1964 std::vector<T> rng_buffer(lattice.mynode.volume());
1965 for (
auto &element : rng_buffer)
1967 (*this).set_local_data(rng_buffer);
1983template <
typename T>
1986#if defined(CUDA) || defined(HIP)
1990 std::vector<T> rng_buffer(lattice.mynode.volume());
1991 for (
auto &element : rng_buffer)
1993 (*this).set_local_data(rng_buffer);
2023inline void dummy_X_f() {
2045 vec[e_x] = vec[0] + vec[e_y] + vec.
e(e_y);
2055template <
typename T>
2056inline void ensure_field_operators_exist() {
2058 ensure_unary_minus_is_loop_function<T>();
2059 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.
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.
double random()
Real valued uniform random number generator.
int myrank()
rank of this node
bool is_device_rng_on()
Check if the RNG on GPU is allocated and ready to use.
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.
vectorized_lattice_struct< vector_size > * get_vectorized_lattice()
Returns a vectorized lattice with given vector size.
unsigned * d_neighb[NDIRS]
Storage for the neighbour indexes. Stored on device.
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