HILA
Loading...
Searching...
No Matches
coordinates.h
Go to the documentation of this file.
1/**
2 * @file coordinates.h
3 * @brief This header file defines:
4 * - enum ::Direction
5 * - enum class ::Parity
6 * - class CoordinateVector
7 *
8 * These are used to traverse the lattice coordinate systems
9 *
10 */
11
12#ifndef COORDINATES_H_
13#define COORDINATES_H_
14
15#include "plumbing/defs.h"
16#include "datatypes/matrix.h"
17
18#if NDIM == 4
19/**
20 * @enum Direction
21 * @brief Enumerator for direction that assigns integer to direction to be interpreted as unit
22 * vector.
23 * @details In NDIM\f$=4\f$ (max dimensionality) we have:
24 *
25 * \f$\{e_x = 0, e_y = 1, e_z = 2, e_t = 3\}\f$
26 *
27 * Negative directions are defined as \f$ e_{-i} = \f$ NDIM \f$\cdot2 - 1 - e_i\f$
28 *
29 * Defined as unsigned, but note that Direction + int is not defined. To operate with int, Direction
30 * must be first cast to int
31 *
32 * Direction can be used as an array index (interchangably with int)
33 */
34enum Direction : unsigned {
35 e_x = 0,
36 e_y,
37 e_z,
38 e_t,
39 e_t_down,
40 e_z_down,
41 e_y_down,
42 e_x_down,
43 NDIRECTIONS
44};
45#elif NDIM == 3
46enum Direction : unsigned { e_x = 0, e_y, e_z, e_z_down, e_y_down, e_x_down, NDIRECTIONS };
47#elif NDIM == 2
48enum Direction : unsigned { e_x = 0, e_y, e_y_down, e_x_down, NDIRECTIONS };
49#elif NDIM == 1
50enum Direction : unsigned { e_x = 0, e_x_down, NDIRECTIONS };
51#endif
52
53/**
54 * @brief Number of directions
55 *
56 */
57constexpr unsigned NDIRS = NDIRECTIONS;
58
59// Increment for directions: ++dir, dir++ does the obvious
60// dir-- not defined, should we?
61
62static inline Direction next_direction(Direction dir) {
63 return static_cast<Direction>(static_cast<unsigned>(dir) + 1);
64}
65static inline Direction &operator++(Direction &dir) {
66 return dir = next_direction(dir);
67}
68static inline Direction operator++(Direction &dir, int) {
69 Direction d = dir;
70 ++dir;
71 return d;
72}
73
74/**
75 * @brief Macro to loop over (all) ::Direction(s)
76 *
77 */
78#define foralldir(d) for (Direction d = e_x; d < NDIM; ++d)
79
80inline Direction opp_dir(const Direction d) {
81 return static_cast<Direction>(NDIRS - 1 - static_cast<int>(d));
82}
83
84inline Direction opp_dir(const int d) {
85 return static_cast<Direction>(NDIRS - 1 - d);
86}
87
88/// unary + and -
89inline Direction operator-(const Direction d) {
90 return opp_dir(d);
91}
92
93static inline Direction operator+(const Direction d) {
94 return d;
95}
96
97/// is_up_dir is true if the dir is "up" to coord Direction
98static inline bool is_up_dir(const Direction d) {
99 return d < NDIM;
100}
101static inline bool is_up_dir(const int d) {
102 return d < NDIM;
103}
104
105static inline Direction abs(Direction dir) {
106 if (is_up_dir(dir))
107 return dir;
108 else
109 return -dir;
110}
111
112inline int dir_dot_product(Direction d1, Direction d2) {
113 if (d1 == d2)
114 return 1;
115 else if (d1 == -d2)
116 return -1;
117 else
118 return 0;
119}
120
121/// dir_mask_t type used in masking directions
122/// unsigned char is ok up to 4 dim (2*4 bits)
123using dir_mask_t = unsigned char;
124
125inline dir_mask_t get_dir_mask(const Direction d) {
126 return (dir_mask_t)(1 << d);
127}
128
129/// define hila::direction_name() and hila::prettyprint(Direction)
130namespace hila {
131
132constexpr inline const char *direction_name(Direction d) {
133 const char *dirnames[NDIRS] = {
134 "e_x",
135 "e_y",
136#if NDIM > 2
137 "e_z",
138#if NDIM > 3
139 "e_t",
140 "-e_t",
141#endif
142 "-e_z",
143#endif
144 "-e_y",
145 "-e_x"
146 };
147 return dirnames[d];
148}
149
150inline std::string prettyprint(Direction d) {
151 return direction_name(d);
152}
153} // namespace hila
154
155// This should not be used from loops ...
156inline std::ostream &operator<<(std::ostream &os, const Direction d) {
157 os << hila::direction_name(d);
158 return os;
159}
160
161
162/**
163 * @brief Parity enum with values EVEN, ODD, ALL; refers to parity of the site. Parity of site
164 * (x,y,z,t) is even if `(x+y+z+t)` is even, odd otherwise.
165 */
166enum class Parity : unsigned { none = 0, even, odd, all };
167
168// should use here #define instead of const Parity? Makes EVEN a protected symbol
169
170/**
171 * @name Parity constexpr aliases
172 * @brief Aliases for contents of ::Parity
173 */
174/** @{ */
175/** @brief bit pattern: 001*/
176constexpr Parity EVEN = Parity::even;
177/** @brief bit pattern: 010*/
178constexpr Parity ODD = Parity::odd;
179/** @brief bit pattern: 011*/
180constexpr Parity ALL = Parity::all;
181/** @} */
182
183// this is used in diagnostics - make static inline so can be defd here
184namespace hila {
185inline const char *parity_name(Parity p) {
186 const char *parity_name_s[4] = {"Parity::none", "EVEN", "ODD", "ALL"};
187 return parity_name_s[(int)p];
188}
189
190inline std::string prettyprint(Parity p) {
191 return hila::parity_name(p);
192}
193
194} // namespace hila
195
196// This should not be used from loops ...
197inline std::ostream &operator<<(std::ostream &os, const Parity p) {
198 os << hila::parity_name(p);
199 return os;
200}
201
202// utilities for getting the bit patterns
203static inline unsigned parity_bits(Parity p) {
204 return 0x3 & static_cast<unsigned>(p);
205}
206static inline unsigned parity_bits_inverse(Parity p) {
207 return 0x3 & ~static_cast<unsigned>(p);
208}
209
210// turns EVEN <-> ODD, ALL remains. X->none, none->none
211static inline Parity opp_parity(const Parity p) {
212 unsigned u = parity_bits(p);
213 return static_cast<Parity>(0x3 & ((u << 1) | (u >> 1)));
214}
215
216// Define ~parity as opp_parity
217static inline Parity operator~(const Parity p) {
218 return opp_parity(p);
219}
220
221static inline bool is_even_odd_parity(Parity p) {
222 return (p == EVEN || p == ODD);
223}
224
225
226/// Positive mod(): we define here the positive mod utility function pmod(a,b).
227/// It mods the arguments 0 <= a < m. This is not the standard
228/// for integer operator% in c++, which gives negative results if a<0. This is useful
229/// in calculating lattice vector additions on a periodic box
230
231inline int pmod(const int a, const int b) {
232 int r = a % b;
233 if (r < 0)
234 r += b;
235 return r;
236}
237
238
239/**
240 * @brief Class for coordinate vector useful in indexing lattice
241 *
242 * @details Defined as Vector<NDIM, int> meaning that all operations from Matrix class are inherited
243 *
244 * Note: this is defined as a template, with generic "int" type T, and the type is defined below as alias:
245* @code{.cpp}
246 * using CoordinateVector = CoordinateVector_t<int>
247 * @endcode
248 * Reason for this is that if CoordinateVector is used in Field variables (Field<CoordinateVector>)
249 * hilapp is able to upgrade the int to vectorized int when vectorized compilation are used (AVX2, AVX512)
250 *
251 * @tparam T int
252 */
253template <typename T>
254class CoordinateVector_t : public Vector<NDIM, T> {
255
256 public:
257 // std incantation for field types
258 using base_type = hila::arithmetic_type<T>;
259 using argument_type = T;
260
261 // define these to ensure std::is_trivial
262 CoordinateVector_t() = default;
263
264 ~CoordinateVector_t() = default;
265 CoordinateVector_t(const CoordinateVector_t &v) = default;
266
267 /// Construct from site index
268 // CoordinateVector_t(SiteIndex s);
269
270 // initialize with Direction -- useful for automatic conversion
271 explicit inline CoordinateVector_t(const Direction dir) {
272 foralldir(d) this->e(d) = dir_dot_product(d, dir);
273 }
274
275 // construct from vector - make this not explicit so that
276 // conversions from Vector methods are automatic
277 inline CoordinateVector_t(const Vector<NDIM, T> &v) {
278 foralldir(d) this->e(d) = v.e(d);
279 }
280
281 /// Construct CV automatically from right-size initializer list
282 /// This does not seem to be dangerous, so keep non-explicit
283 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value, int> = 0>
284 inline CoordinateVector_t(std::initializer_list<S> rhs) {
285 assert(rhs.size() == NDIM && "CoordinateVector initializer list size does not match");
286 int i = 0;
287 for (auto it = rhs.begin(); it != rhs.end(); it++, i++)
288 this->e(i) = *it;
289 }
290
291 /// Construct from 0, using nullptr_t autocast
292 inline CoordinateVector_t(std::nullptr_t z) {
293 foralldir(d) this->e(d) = 0;
294 }
295
296 // /// cast to vector<NDIM,int> - useful for method inheritance
297 // #pragma hila loop_function
298 // inline operator Vector<NDIM, int>() {
299 // Vector<NDIM, int> v;
300 // foralldir(d) v.e(d) = this->e(d);
301 // return v;
302 // }
303
304 /// Assign from 0
305#pragma hila loop_function
306 inline CoordinateVector_t &operator=(std::nullptr_t z) {
307 foralldir(d) this->e(d) = 0;
308 return *this;
309 }
310
311 /// Assign from initializer list
312 template <typename S, std::enable_if_t<hila::is_assignable<T &, S>::value, int> = 0>
313 inline CoordinateVector_t &operator=(std::initializer_list<S> rhs) {
314 assert(rhs.size() == NDIM && "Initializer list has a wrong size in assignment");
315 int i = 0;
316 for (auto it = rhs.begin(); it != rhs.end(); it++, i++) {
317 this->e(i) = *it;
318 }
319 return *this;
320 }
321
322 // Assign
323
324 bool operator==(const CoordinateVector_t<T> &rhs) const {
325 foralldir(d) {
326 if (this->e(d) != rhs.e(d))
327 return false;
328 }
329 return true;
330 }
331
332 // #pragma hila loop function
333 T &operator[](const int i) {
334 return this->e(i);
335 }
336 // #pragma hila loop function
337 T &operator[](const Direction d) {
338 return this->e((int)d);
339 }
340 // #pragma hila loop function
341 T operator[](const int i) const {
342 return this->e(i);
343 }
344 // #pragma hila loop function
345 T operator[](const Direction d) const {
346 return this->e((int)d);
347 }
348
349 // Parity of this coordinate
350 ::Parity parity() const {
351 int s = 0;
352 foralldir(d) s += this->e(d);
353 if (s % 2 == 0)
354 return Parity::even;
355 else
356 return Parity::odd;
357 }
358
359 // cast to std::array
360 // operator std::array<int, NDIM>() {
361 // std::array<int, NDIM> a;
362 // for (int d = 0; d < NDIM; d++)
363 // a[d] = this->e(d);
364 // return a;
365 // }
366
367 // cast to Vector - make this only explicit.
368 // S can be any type, because int is convertible to it
369
370 template <typename S>
371 explicit operator Vector<NDIM, S>() {
373 for (int d = 0; d < NDIM; d++)
374 a[d] = this->e(d);
375 return a;
376 }
377
378 // add coordinate vector -- def explicit as loop_function
379 // #pragma hila loop function //TODO
380 CoordinateVector_t &operator+=(const CoordinateVector_t &rhs) {
381 foralldir(d) this->e(d) += rhs.e(d);
382 return *this;
383 }
384
385 CoordinateVector_t &operator-=(const CoordinateVector_t &rhs) {
386 foralldir(d) this->e(d) -= rhs.e(d);
387 return *this;
388 }
389
390 // and also additions for Direction -- dir acts like a unit vector
391 // #pragma hila loop function //TODO
392 CoordinateVector_t &operator+=(const Direction dir) {
393 if (is_up_dir(dir))
394 ++this->e(dir);
395 else
396 --this->e(-dir);
397 return *this;
398 }
399
400 CoordinateVector_t &operator-=(const Direction dir) {
401 if (is_up_dir(dir))
402 --this->e(dir);
403 else
404 ++this->e(-dir);
405 return *this;
406 }
407
408 // unary - -explicitly loop_function
409 inline CoordinateVector_t operator-() const {
411 foralldir(d) res.e(d) = -this->e(d);
412 return res;
413 }
414
415 // unary + -explicitly loop_function
416 inline CoordinateVector_t operator+() const {
417 return *this;
418 }
419
420 inline T dot(const CoordinateVector_t &v) const {
421 T res(0);
422 foralldir(d) res += v.e(d) * this->e(d);
423 return res;
424 }
425
426
427 /// Positive mod for coordinate vector, see int mod(int a, int b). If
428 /// 2nd argument m is lattice.size(), this mods the vector a to periodic lattice.
429
432 foralldir(d) {
433 r.e(d) = pmod((*this)[d], m[d]);
434 }
435 return r;
436 }
437
438 /// Return site index of the coordinate vector -- assumes a valid lattice vector
439
440 // #pragma hila loop_function
441 // inline SiteIndex index() const;
442};
443
444/**
445 * @brief CoordinateVector alias for CoordinateVector_t
446 *
447 */
449
450template <typename T>
452 const CoordinateVector_t<T> &cv2) {
453 cv1 += cv2;
454 return cv1;
455}
456
457template <typename T>
459 const CoordinateVector_t<T> &cv2) {
460 cv1 -= cv2;
461 return cv1;
462}
463
464/// Special Direction operators: dir + dir -> CoordinateVector
465inline CoordinateVector operator+(const Direction d1, const Direction d2) {
467 foralldir(d) {
468 r.e(d) = dir_dot_product(d1, d);
469 r.e(d) += dir_dot_product(d2, d);
470 }
471 return r;
472}
473
474inline CoordinateVector operator-(const Direction d1, const Direction d2) {
476 foralldir(d) {
477 r.e(d) = dir_dot_product(d1, d);
478 r.e(d) -= dir_dot_product(d2, d);
479 }
480 return r;
481}
482
483/// Special operators: int*Direction -> CoordinateVector (of type int!)
484inline CoordinateVector operator*(const int i, const Direction dir) {
486 foralldir(d) r.e(d) = i * dir_dot_product(d, dir);
487 return r;
488}
489
490inline CoordinateVector operator*(const Direction d, const int i) {
491 return i * d;
492}
493
494// coordinate vector + Direction -- dir is a unit vector
495template <typename T>
496inline CoordinateVector_t<T> operator+(CoordinateVector_t<T> cv, const Direction dir) {
497 cv += dir;
498 return cv;
499}
500
501template <typename T>
503 cv -= dir;
504 return cv;
505}
506
507template <typename T>
508inline CoordinateVector_t<T> operator+(const Direction dir, CoordinateVector_t<T> cv) {
509 cv += dir;
510 return cv;
511}
512
513template <typename T>
515 foralldir(d) cv.e(d) = dir_dot_product(dir, d) - cv.e(d);
516 return cv;
517}
518
519
520/**
521 * @brief X-coordinate type - "dummy" class
522 * @details used only in loop index and is removed by code analysis. Generally empty except for
523 * method deceleration
524 */
526 public:
527 /**
528 * @brief Returns coordinate of site at index X
529 *
530 * @return const CoordinateVector&
531 */
533
534 /**
535 * @brief Returns dth dimension coordinate of X
536 *
537 * @param d direction to probe
538 * @return int
539 */
540 int coordinate(Direction d) const;
541
542 int x() const;
543 int y() const;
544#if NDIM > 2
545 int z() const;
546#if NDIM > 3
547 int t() const;
548#endif
549#endif
550
551 /**
552 * @brief Returns parity of site at index X
553 *
554 * @return ::Parity
555 */
557};
558
559/// this defines the "point" dummy variable!
560static const X_index_type X;
561
562/// X + dir -type: used in expressions of type f[X+dir]
563/// It's a dummy type, is not used in final code
564
566/// X + coordinate offset, used in f[X+CoordinateVector] or f[X+dir1+dir2] etc.
568
569/// Declarations X+smth, no need to implement these (type removed by hilapp)
570
571const X_plus_direction operator+(const X_index_type x, const Direction d);
572const X_plus_direction operator-(const X_index_type x, const Direction d);
573const X_plus_offset operator+(const X_index_type x, const CoordinateVector &cv);
574const X_plus_offset operator-(const X_index_type x, const CoordinateVector &cv);
575const X_plus_offset operator+(const X_plus_direction, const Direction d);
577const X_plus_offset operator+(const X_plus_direction, const CoordinateVector &cv);
579const X_plus_offset operator+(const X_plus_offset, const Direction d);
580const X_plus_offset operator-(const X_plus_offset, const Direction d);
581const X_plus_offset operator+(const X_plus_offset, const CoordinateVector &cv);
583
584#endif
std::ostream & operator<<(std::ostream &strm, const Array< n, m, T > &A)
Stream operator.
Definition array.h:916
Class for coordinate vector useful in indexing lattice.
CoordinateVector_t & operator=(std::nullptr_t z)
Assign from 0.
CoordinateVector_t mod(const CoordinateVector_t &m) const
CoordinateVector_t(const Direction dir)
Construct from site index.
CoordinateVector_t(std::nullptr_t z)
Construct from 0, using nullptr_t autocast.
CoordinateVector_t(std::initializer_list< S > rhs)
CoordinateVector_t & operator=(std::initializer_list< S > rhs)
Assign from initializer list.
T e(const int i, const int j) const
Standard array indexing operation for matrices.
Definition matrix.h:272
Matrix class which defines matrix operations.
Definition matrix.h:1679
X-coordinate type - "dummy" class.
::Parity parity() const
Returns parity of site at index X.
int coordinate(Direction d) const
Returns dth dimension coordinate of X.
const CoordinateVector & coordinates() const
Returns coordinate of site at index X.
T abs(const Complex< T > &a)
Return absolute value of Complex number.
Definition cmplx.h:1322
Parity
Parity enum with values EVEN, ODD, ALL; refers to parity of the site. Parity of site (x,...
int pmod(const int a, const int b)
constexpr Parity EVEN
bit pattern: 001
#define foralldir(d)
Macro to loop over (all) Direction(s)
Definition coordinates.h:78
constexpr unsigned NDIRS
Number of directions.
Definition coordinates.h:57
constexpr Parity ODD
bit pattern: 010
unsigned char dir_mask_t
Direction
Enumerator for direction that assigns integer to direction to be interpreted as unit vector.
Definition coordinates.h:34
constexpr Parity ALL
bit pattern: 011
CoordinateVector operator*(const int i, const Direction dir)
Special operators: int*Direction -> CoordinateVector (of type int!)
Direction operator-(const Direction d)
unary + and -
Definition coordinates.h:89
This file defines all includes for HILA.
Definition of Matrix types.
Invert diagonal + const. matrix using Sherman-Morrison formula.
Definition array.h:920
X + coordinate offset, used in f[X+CoordinateVector] or f[X+dir1+dir2] etc.