3#include "plumbing/lattice.h"
9void report_too_large_node() {
11 hila::out <<
"Node size too large: size = " << lattice.mynode.size[0];
12 for (
int d = 1; d < NDIM; d++)
13 hila::out <<
" x " << lattice.mynode.size[d];
14 hila::out <<
" + communication buffers = " << lattice.mynode.field_alloc_size;
15 hila::out <<
"\nConsider using more nodes (smaller node size).\n";
16 hila::out <<
"[TODO: allow 64bit index?]\n";
28std::vector<lattice_struct *> lattices;
30static int lattice_count = 0;
35 l_label = lattice_count++;
38 lattices.push_back(
this);
54 initialize_wait_arrays();
56#ifdef SPECIAL_BOUNDARY_CONDITIONS
58 init_special_boundaries();
62 if (mynode.field_alloc_size % 256 > 0)
63 mynode.field_alloc_size += 256 - mynode.field_alloc_size % 256;
68 backend_lattice->
setup(*
this);
71 if (hila::check_input) {
72 hila::out <<
"***** Input check done *****\n";
104 i = (loc[NDIM - 1] * nodes.n_divisions[NDIM - 1]) / l_size[NDIM - 1];
105 for (dir = NDIM - 2; dir >= 0; dir--) {
106 i = i * nodes.n_divisions[dir] + ((loc[dir] * nodes.n_divisions[dir]) / l_size[dir]);
121 for (
int dir = 0; dir < NDIM; dir++) {
122 d = loc[dir] - mynode.min[dir];
123 if (d < 0 || d >= mynode.size[dir])
134#ifndef SUBNODE_LAYOUT
138 unsigned i = loc[NDIM - 1] - mynode.min[NDIM - 1];
139 int s = loc[NDIM - 1];
140 for (
int dir = NDIM - 2; dir >= 0; dir--) {
141 int l = loc[dir] - mynode.min[dir];
142 i = i * mynode.size[dir] + l;
147#if defined(EVEN_SITES_FIRST)
151 return (i / 2 + mynode.evensites);
163 const node_info &ni = nodes.nodelist[nodeid];
165 unsigned i = loc[NDIM - 1] - ni.min[NDIM - 1];
166 int s = loc[NDIM - 1];
167 for (
int dir = NDIM - 2; dir >= 0; dir--) {
168 int l = loc[dir] - ni.min[dir];
169 i = i * ni.size[dir] + l;
174#if defined(EVEN_SITES_FIRST)
178 return (i / 2 + ni.evensites);
233 assert(nodeid < nodes.number);
234 const node_info &ni = nodes.nodelist[nodeid];
242 subsize.
asArray() = ni.size.
asArray() / mynode.subnodes.divisions.asArray();
244 dir = mynode.subnodes.merged_subnodes_dir;
245 l = loc[dir] - ni.min[dir];
246 subl = l / subsize[dir];
249 subl = subl / 2 + (subl % 2) * (mynode.subnodes.divisions[dir] / 2);
254 for (dir = NDIM - 1; dir >= 0; dir--) {
255 l = loc[dir] - ni.min[dir];
256 if (dir != mynode.subnodes.merged_subnodes_dir) {
257 subl = subl * mynode.subnodes.divisions[dir] + l / subsize[dir];
259 i = i * subsize[dir] + l % subsize[dir];
263#if defined(EVEN_SITES_FIRST)
267 i = i / 2 + ni.evensites / number_of_subnodes;
270 return (subl + number_of_subnodes * i);
291 nodes.nodelist.resize(nodes.number);
299 for (
int i = 0; i < nodes.number; i++) {
301 foralldir(d) l[d] = nodes.divisors[d][n[d]];
303 int nn = node_rank(l);
307 ni.min[d] = nodes.divisors[d][n[d]];
308 ni.size[d] = nodes.divisors[d][n[d] + 1] - nodes.divisors[d][n[d]];
311 if (ni.size[d] > nodes.max_size[d])
312 nodes.max_size[d] = ni.size[d];
315 if (v >= (1ULL << 32)) {
317 report_too_large_node();
321 ni.evensites = ni.oddsites = v / 2;
324 if (l.parity() ==
EVEN) {
325 ni.evensites = v / 2 + 1;
328 ni.evensites = v / 2;
329 ni.oddsites = v / 2 + 1;
336 if (n[d] < nodes.n_divisions[d])
343 mynode.
setup(ni, lattice);
359 evensites = ni.evensites;
360 oddsites = ni.oddsites;
361 sites = ni.evensites + ni.oddsites;
363 first_site_even = (min.parity() ==
EVEN);
368 l[d] = (min[d] + size[d]) % lattice.l_size[d];
369 nn[d] = lattice.node_rank(l);
370 l[d] = (lattice.l_size[d] + min[d] - 1) % lattice.l_size[d];
371 nn[opp_dir(d)] = lattice.node_rank(l);
377#ifdef EVEN_SITES_FIRST
378 coordinates.resize(sites);
380 for (
unsigned i = 0; i < sites; i++) {
384 if (++l[d] < (min[d] + size[d]))
402 subnodes.setup(*
this);
411void lattice_struct::node_struct::subnode_struct::setup(
const node_struct &tn) {
412 size.asArray() = tn.size.
asArray() / divisions.asArray();
413 evensites = tn.evensites / number_of_subnodes;
414 oddsites = tn.oddsites / number_of_subnodes;
415 sites = evensites + oddsites;
431 for (
int d = 0; d <
NDIRS; d++) {
432 neighb[d] = (
unsigned *)memalloc(((
size_t)mynode.sites) *
sizeof(unsigned));
435 size_t c_offset = mynode.sites;
438 int too_large_node = 0;
450 from_node.rank = to_node.rank = mynode.rank;
454 from_node.sites = from_node.evensites = from_node.oddsites = 0;
458 for (
int i = 0; i < mynode.sites; i++) {
463 ln = (l + d).mod(size());
472 neighb[d][i] = mynode.sites;
476 unsigned rank = node_rank(ln);
477 if (from_node.rank == mynode.rank) {
478 from_node.rank = rank;
479 }
else if (from_node.rank != rank) {
480 hila::out <<
"Internal error in nn-communication setup\n";
485 if (l.parity() ==
EVEN)
486 from_node.evensites++;
488 from_node.oddsites++;
495 from_node.buffer = c_offset;
497 to_node.rank = from_node.rank;
498 to_node.sites = from_node.sites;
500 to_node.evensites = from_node.oddsites;
501 to_node.oddsites = from_node.evensites;
505 to_node.sitelist = (
unsigned *)memalloc(to_node.sites *
sizeof(
unsigned));
509 from_node.sitelist = (
unsigned *)memalloc(from_node.sites *
sizeof(
unsigned));
512 to_node.sitelist =
nullptr;
520 size_t c_even, c_odd;
523 for (
size_t i = 0; i < mynode.sites; i++) {
524 if (
neighb[d][i] == mynode.sites) {
528 if (l.parity() ==
EVEN) {
530 neighb[d][i] = c_offset + c_even;
531 if (c_offset + c_even >= (1ULL << 32))
535 from_node.sitelist[c_even] = i;
539 to_node.sitelist[c_even + to_node.evensites] = i;
544 neighb[d][i] = c_offset + from_node.evensites + c_odd;
545 if (c_offset + from_node.evensites + c_odd >= (1ULL << 32))
549 from_node.sitelist[c_odd + from_node.evensites] = i;
553 to_node.sitelist[c_odd] = i;
561 c_offset += from_node.sites;
563 if (c_offset >= (1ULL << 32))
569 mynode.field_alloc_size = c_offset;
572 report_too_large_node();
585static_assert(NDIM <= 4 &&
"Dimensions at most 4 in dir_mask_t = unsigned char! Use "
586 "larger type to circumvent");
588void lattice_struct::initialize_wait_arrays() {
598 for (
size_t i = 0; i < mynode.sites; i++) {
602 if (
neighb[dir][i] >= mynode.sites)
604 if (
neighb[odir][i] >= mynode.sites)
611#ifdef SPECIAL_BOUNDARY_CONDITIONS
620void lattice_struct::init_special_boundaries() {
624 special_boundaries[d].n_even = special_boundaries[d].n_odd = special_boundaries[d].n_total =
626 special_boundaries[d].is_needed =
false;
631 if (is_up_dir(d) && mynode.min[d] + mynode.size[d] == size(d))
633 if (is_up_dir(od) && mynode.min[od] == 0)
639 if (nodes.n_divisions[
abs(d)] == 1) {
640 special_boundaries[d].is_needed =
true;
641 special_boundaries[d].offset = mynode.field_alloc_size;
643 for (
unsigned i = 0; i < mynode.sites; i++)
644 if (coordinate(i,
abs(d)) == coord) {
646 special_boundaries[d].n_total++;
647 if (site_parity(i) ==
EVEN)
648 special_boundaries[d].n_even++;
650 special_boundaries[d].n_odd++;
652 mynode.field_alloc_size += special_boundaries[d].n_total;
661 special_boundaries[d].neighbours =
nullptr;
665 if (mynode.field_alloc_size >= (1ULL << 32))
668 report_too_large_node();
677#ifndef SPECIAL_BOUNDARY_CONDITIONS
678 assert(bc == hila::bc::PERIODIC &&
679 "non-periodic BC only if SPECIAL_BOUNDARY_CONDITIONS defined");
684 if (special_boundaries[d].is_needed ==
false || bc == hila::bc::PERIODIC)
687 if (special_boundaries[d].neighbours ==
nullptr) {
688 setup_special_boundary_array(d);
690 return special_boundaries[d].neighbours;
699void lattice_struct::setup_special_boundary_array(
Direction d) {
701 if (special_boundaries[d].is_needed ==
false || special_boundaries[d].neighbours !=
nullptr)
705 special_boundaries[d].neighbours = (
unsigned *)memalloc(
sizeof(
unsigned) * mynode.sites);
706 special_boundaries[d].move_index =
707 (
unsigned *)memalloc(
sizeof(
unsigned) * special_boundaries[d].n_total);
710 int offs = special_boundaries[d].offset;
717 for (
int i = 0; i < mynode.sites; i++) {
718 if (coordinate(i,
abs(d)) != coord) {
719 special_boundaries[d].neighbours[i] =
neighb[d][i];
721 special_boundaries[d].neighbours[i] = offs++;
722 special_boundaries[d].move_index[k++] =
neighb[d][i];
726 assert(k == special_boundaries[d].n_total);
744std::vector<lattice_struct::comm_node_struct>
745lattice_struct::create_comm_node_vector(
CoordinateVector offset,
unsigned *index,
753 std::vector<unsigned> np_even(nodes.number);
754 std::vector<unsigned> np_odd(nodes.number);
761 for (
unsigned i = 0; i < mynode.sites; i++) {
764 ln = (l + offset).mod(size());
772 unsigned r = node_rank(ln);
775 index[i] = mynode.sites + r;
778 if (l.parity() ==
EVEN)
785 if (ln.parity() ==
EVEN)
797 for (
int r = 0; r < nodes.number; r++) {
798 if (np_even[r] > 0 || np_odd[r] > 0)
803 std::vector<comm_node_struct> node_v(nnodes);
807 for (
int r = 0; r < nodes.number; r++) {
808 if (np_even[r] > 0 || np_odd[r] > 0) {
811 node_v[n].evensites = np_even[r];
812 node_v[n].oddsites = np_odd[r];
813 node_v[n].sites = np_even[r] + np_odd[r];
818 (
unsigned *)memalloc(node_v[n].sites *
sizeof(
unsigned));
822 c_buffer += node_v[n].sites;
830 for (
int i = 0; i < nnodes; i++)
831 np_even[i] = np_odd[i] = 0;
836 for (
unsigned i = 0; i < mynode.sites; i++) {
839 ln = (l + offset).mod(size());
842 unsigned r = node_rank(ln);
845 while (node_v[n].rank != r)
850 if (ln.parity() ==
EVEN)
853 k = node_v[n].evensites + np_odd[n]++;
856 node_v[n].sitelist[k] = i;
864 for (
unsigned i = 0; i < mynode.sites; i++) {
865 if (index[i] >= mynode.sites) {
866 int r = index[i] - mynode.sites;
869 while (node_v[n].rank != r)
873 if (l.parity() ==
EVEN)
874 index[i] = node_v[n].buffer + (np_even[n]++);
876 index[i] = node_v[n].buffer + node_v[n].evensites + (np_odd[n]++);
889 gen_comminfo_struct ci;
892 ci.index = (
unsigned *)memalloc(mynode.sites *
sizeof(
unsigned));
895 create_comm_node_vector(offset, ci.index,
true);
896 ci.to_node = create_comm_node_vector(offset,
nullptr,
false);
899 const comm_node_struct &r = ci.from_node[ci.from_node.size() - 1];
900 ci.receive_buf_size = r.buffer + r.sites;
const Array< n, m, T > & asArray() const
Cast Matrix to Array.
dir_mask_t *__restrict__ wait_arr_
implement waiting using mask_t - unsigned char is good for up to 4 dim.
void setup_nodes()
invert the mynode index -> location (only on this node)
void setup(const CoordinateVector &siz)
General lattice setup.
bool is_on_mynode(const CoordinateVector &c) const
Is the coordinate on THIS node.
unsigned *__restrict__ neighb[NDIRS]
Main neighbour index array.
void create_std_gathers()
std::array< nn_comminfo_struct, NDIRS > nn_comminfo
nearest neighbour comminfo struct
unsigned site_index(const CoordinateVector &c) const
T abs(const Complex< T > &a)
Return absolute value of Complex number.
constexpr Parity EVEN
bit pattern: 001
#define foralldir(d)
Macro to loop over (all) Direction(s)
constexpr unsigned NDIRS
Number of directions.
Direction
Enumerator for direction that assigns integer to direction to be interpreted as unit vector.
This file defines all includes for HILA.
This files containts definitions for the Field class and the classes required to define it such as fi...
int myrank()
rank of this node
int number_of_nodes()
how many nodes there are
void reduce_node_sum(T *value, int send_count, bool allreduce=true)
Reduce an array across nodes.
std::ostream out
this is our default output file stream
bc
list of field boundary conditions - used only if SPECIAL_BOUNDARY_CONDITIONS defined
void finishrun()
Normal, controlled exit - all nodes must call this. Prints timing information and information about c...
Helper class for loading the vectorized lattice.
void setup(lattice_struct *lattice)
unsigned remap(unsigned i) const
And the call interface for remapping.
Information necessary to communicate with a node.
Information about the node stored on this process.
void setup(node_info &ni, lattice_struct &lattice)
Fill in mynode fields – node_rank() must be set up OK.
useful information about a node