1#ifndef _BACKEND_LATTICE_H_
2#define _BACKEND_LATTICE_H_
5#include "vector_types.h"
8static_assert(0,
"SUBNODE_LAYOUT needs to be defined to use vectorized lattice");
18template <
int vector_size>
20 static_assert(vector_size > 0,
"Vector size in vectorized_lattice_struct");
51 using int_vector_t =
typename hila::vector_base_type<int, vector_size>::type;
52 int_vector_t coordinate_offset[NDIM];
68 v = v.
mod(lattice.size());
94 v_sites = lattice.mynode.volume() / vector_size;
96 subnode_size = lattice.mynode.subnodes.size;
105 if (vector_size == VECTOR_SIZE /
sizeof(
double)) {
106 subdivisions[lattice.mynode.subnodes.merged_subnodes_dir] /= 2;
107 subnode_size[lattice.mynode.subnodes.merged_subnodes_dir] *= 2;
110 hila::out0 <<
"Setting up lattice struct with vector of size " << vector_size
138 int step = 1, sdmul = 1;
148 assert(idx % vector_size == 0);
151 for (
int i = 0; i < vector_size; i++) {
157 h = h.
mod(lattice.size());
158 int rank = lattice.node_rank(h);
164 for (
int i = 0; i < vector_size; i++)
201 for (
int i = 0; i <
v_sites; i++) {
202 int j = vector_size * i;
208 assert(lattice.
neighb[d][j] % vector_size == 0);
212 ((is_up_dir(d) && here[ad] == lattice.size(ad) - 1) ||
213 (is_up_dir(-d) && here[ad] == 0))) {
224 halo_offset_odd[d] =
halo_offset[d] + n_halo_vectors[d] / 2;
225 assert(n_halo_vectors[d] % 2 == 0);
232 halo_index[d] = (
unsigned *)memalloc(n_halo_vectors[d] *
sizeof(
unsigned));
234 for (
int i = 0; i <
v_sites; i++) {
240 for (k = 0; k < vector_size; k++) {
241 if (lattice.
neighb[d][i * vector_size + k] < lattice.mynode.sites) {
243 n = lattice.
neighb[d][i * vector_size + k] / vector_size;
247 lattice.
neighb[d][i * vector_size + k] / vector_size);
254 assert(j == n_halo_vectors[d]);
259 halo_index[d] = (
unsigned *)memalloc(n_halo_vectors[d] *
sizeof(
unsigned));
261 for (
int i = 0; i <
v_sites; i++) {
264 assert(lattice.
neighb[d][i * vector_size] % vector_size == 0);
276 report_too_large_node();
297 for (
int i = 0; i < lattice.mynode.sites; i++) {
298 if (lattice.
neighb[d][i] >= lattice.mynode.sites) {
306 neighbours[d][i / vector_size] * vector_size + (i % vector_size);
326 for (
int i = 0; i < vector_size; i++) {
329 coordinate_offset[d].insert(i, diff[d]);
334 for (
int i = 0; i <
v_sites; i++) {
335 coordinate_base[i] = lattice.coordinates(vector_size * i);
346 for (
int i = 0; i <
v_sites; i++) {
350 if (lattice.nodes.n_divisions[dir] > 1) {
363 return lattice.get_comminfo(d);
376 return vector_size *
neighbours[d][idx / vector_size] + idx % vector_size;
394 r.
e(d) = coordinate_offset[d] + coordinate_base[idx][d];
398 auto coordinate(
unsigned idx,
Direction d)
const {
399 return coordinate_offset[d] + coordinate_base[idx][d];
404 return coordinate_base[idx].parity();
435 template <
int vector_size>
439 assert(lattice.id() == 0 &&
440 "Vectorized lattice layout only possible with main (original) lattice");
444 if (vlat ==
nullptr) {
CoordinateVector_t mod(const CoordinateVector_t &m) const
T e(const int i, const int j) const
Standard array indexing operation for matrices and vectors.
const Array< n, m, T > & asArray() const
Cast Matrix to Array.
unsigned *__restrict__ neighb[NDIRS]
Main neighbour index array.
unsigned site_index(const CoordinateVector &c) const
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 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.
std::ostream out0
This writes output only from main process (node 0)
Helper class for loading the vectorized lattice.
void setup(lattice_struct *lattice)
vectorized_lattice_struct< vector_size > * get_vectorized_lattice()
Returns a vectorized lattice with given vector size.
nn-communication has only 1 node to talk to
unsigned loop_end(::Parity P) const
Last index in a lattice loop.
void get_receive_lists()
Get neighbour receive indices for MPI.
unsigned char *__restrict__ vec_wait_arr_
A wait array for the vectorized field.
void set_coordinates()
Build the structs for coordinates.
bool only_local_boundary_copy[NDIRS]
True if the boundary elements are local.
unsigned * recv_list[NDIRS]
CoordinateVector subnode_origin
origin of the 1st subnode = origin of mynode
unsigned field_alloc_size() const
bool is_boundary_permutation[4]
True if boundary needs a permutation.
lattice_struct::nn_comminfo_struct get_comminfo(int d)
Return the communication info.
CoordinateVector subdivisions
subnode divisions to different directions
bool is_on_first_subnode(CoordinateVector v)
Check if this is the first subnode.
size_t v_sites
pointer to the original lattice
unsigned *__restrict__ halo_index[NDIRS]
storage for indexes to halo sites
void get_neighbours_and_local_halo()
size_t alloc_size
The storage size of a field.
auto coordinates(int idx) const
unsigned vector_neighbour(Direction d, int idx) const
void get_boundary_permutations()
Find the boundary permutations to different directions.
unsigned recv_list_size[NDIRS]
The size of the receive list in each direction.
unsigned halo_offset[NDIRS]
offsets to boundary halos
int boundary_permutation[NDIRS][vector_size]
permutation vectors
unsigned site_neighbour(Direction d, int idx) const
unsigned *__restrict__ neighbours[NDIRS]
Storage for neighbour indexes on each site.
vectorized_lattice_struct()
unsigned loop_begin(::Parity P) const
First index in a lattice loop.