HILA
Loading...
Searching...
No Matches
test_fields.cpp
1#include "hila.h"
2#include "test.h"
3
4/////////////////////
5/// test_case 2
6/// Coverage:
7/// - directions, onsites and foralldir environments
8/// - operations between fields
9/// - foralldir env inside onsites
10/// - referring to an array of fields in a loop
11/// - calling a function with const parameters
12/// - requiring communication of a const field
13/// - calling a function from a loop
14/////////////////////
15
16template <typename A, typename B, typename C>
17void sum_test_function(A &a, const B &b, const C &c) {
18 onsites(ALL) { a[X] = b[X] + c[X + e_x]; }
19}
20
21template <typename T> T test_template_function(T a) { return 2 * a; }
22
23element<Complex<double>> test_nontemplate_function(element<Complex<double>> a) {
24 element<Complex<double>> b = a;
25 return 2 * a;
26}
27
28#include "dirac/staggered.h"
29
30int main(int argc, char **argv) {
31
32 // check that you can increment a Direction correctly
33 Direction d = e_x;
34 Direction d2 = (Direction)(NDIRS - 2);
35#if NDIM > 1
36 d = next_direction(d);
37 d2 = next_direction(d2);
38 assert(d == e_y);
39 assert(e_x == 0);
40 assert(d2 == -e_x);
41#endif
42 double sum = 0;
43
44 test_setup(argc, argv);
45
46 Field<Complex<double>> s1, s2, s3;
48
49 // Test field assingment
50 s1 = 0.0;
51 s2 = 1.0;
52 s3 = 1.0;
53
54 // Test sum and move constructor
55 s1 = s2 + s3;
56
57 sum = 0;
58 onsites(ALL) { sum += s1[X].re; }
59 assert(sum == 2 * (double)lattice.volume() && "onsites reduction");
60 s1 = 0;
61 s2 = 0;
62 s3 = 0;
63 sum = 0;
64
65 // Test field-parity expressions
66 s1[ALL] = 0.0;
67 s2[EVEN] = 1.0;
68 s3[ODD] = 1.0;
69
70 s1[ALL] = s2[X] + s3[X];
71
72 onsites(ALL) { sum += s1[X].re; }
73 assert(sum == (double)lattice.volume() && "test setting field with parity");
74
75 // Test communication functions
76 s1[ALL] = 0;
77
78 assert(s1.is_allocated());
79 assert(s1.is_initialized(EVEN));
80 assert(s1.is_initialized(ODD));
81
82 s1.mark_changed(ALL);
83
84 // Check initial state of communication functions
85 foralldir(d) {
86 assert(!s1.is_gathered(d, EVEN));
87 assert(!s1.is_gathered(d, ODD));
88 assert(!s1.is_gathered(d, ALL));
89 assert(!s1.is_move_started(d, EVEN));
90 assert(!s1.is_move_started(d, ODD));
91 assert(!s1.is_move_started(d, ALL));
92 assert(s1.move_not_done(d, EVEN) && "move not done initially");
93 assert(s1.move_not_done(d, ODD) && "move not done initially");
94 assert(s1.move_not_done(d, ALL) && "move not done initially");
95 }
96
97 // Test marking move started and gathered
98 foralldir(d) {
99 s1.mark_move_started(d, EVEN);
100 assert(s1.is_move_started(d, EVEN));
101 assert(!s1.is_gathered(d, EVEN));
102 assert(!s1.move_not_done(d, EVEN) && "move not done after starting");
103 assert(!s1.is_gathered(d, ODD));
104 assert(!s1.is_gathered(d, ALL));
105 assert(!s1.is_move_started(d, ODD));
106 assert(!s1.is_move_started(d, ALL));
107 assert(s1.move_not_done(d, ODD));
108 assert(s1.move_not_done(d, ALL));
109
110 s1.mark_gathered(d, EVEN);
111 assert(s1.is_gathered(d, EVEN));
112 assert(!s1.is_move_started(d, EVEN));
113 assert(!s1.move_not_done(d, EVEN));
114
115 s1.mark_changed(ALL);
116
117 s1.mark_move_started(d, ODD);
118 assert(s1.is_move_started(d, ODD));
119 assert(!s1.is_gathered(d, ODD));
120 assert(!s1.move_not_done(d, ODD) && "move not done after starting");
121
122 s1.mark_gathered(d, ODD);
123 assert(s1.is_gathered(d, ODD));
124 assert(!s1.is_move_started(d, ODD));
125 assert(!s1.move_not_done(d, ODD));
126
127 s1.mark_changed(ALL);
128
129 s1.mark_move_started(d, ALL);
130 assert(s1.is_move_started(d, ALL));
131 assert(!s1.is_gathered(d, ALL));
132 assert(!s1.move_not_done(d, ALL) && "move not done after starting");
133
134 s1.mark_gathered(d, ALL);
135 assert(s1.is_gathered(d, ALL));
136 assert(!s1.is_move_started(d, ALL));
137 assert(!s1.move_not_done(d, ALL));
138
139 s1.mark_changed(ALL);
140 }
141
142 // Try setting an element on node 0
143 CoordinateVector coord;
144 foralldir(d) { coord[d] = 0; }
145 s1.set_element(Complex<double>(1), coord);
146 Complex<double> elem = s1.get_element(coord);
147 assert(elem.re == 1 && elem.im == 0 && "set_element");
148
149 // Now try setting on a different node, if the lattice is split
150 foralldir(d) { coord[d] = nd[d] - 1; }
151 s1.set_element(Complex<double>(1), coord);
152 elem = s1.get_element(coord);
153 assert(elem.re == 1 && elem.im == 0 && "set_element on other node");
154
155 // Now try actually moving the data
156 foralldir(d) { coord[d] = 0; }
157 foralldir(d) {
158 // Move data up in Direction d
159 s2[ALL] = s1[X - d];
160
161 // Should still be on this node
162 CoordinateVector coord2 = coord;
163 coord2[d] += 1;
164 Complex<double> moved = s2.get_element(coord2);
165 assert(elem.re == 1 && elem.im == 0);
166
167 // Move data down
168 s2[ALL] = s1[X + d];
169
170 // Now it may be on a different node
171 coord2 = coord;
172 coord2[d] = (coord[d] - 1 + nd[d]) % nd[d];
173 moved = s2.get_element(coord2);
174 if (elem.re != 1 || elem.im != 0) {
175 hila::out0 << "Problem in communicating to Direction " << d << "\n";
176 hila::out0 << "Received " << moved << "\n";
177 assert(elem.re == 1 && elem.im == 0);
178 }
179 }
180
181 // Check boundary conditions by moving the data
182 {
183 Field<double> s1, s2;
184 CoordinateVector coord1 = 0;
185 CoordinateVector coord2 = 0;
186 coord1[0] = (nd[0] - 1) % nd[0];
187
188 // Move data up accross the X boundary
189 s1 = 0;
190 s2 = 0;
191 s1.set_element(1, coord1);
192 s2[ALL] = s1[X - Direction(0)];
193 double moved_element = s2.get_element(coord2);
194 assert(moved_element == 1 && "moved up");
195
196 // The other way
197 s1 = 0;
198 s2 = 0;
199 s1.set_element(1, coord2);
200 s2[ALL] = s1[X + Direction(0)];
201 moved_element = s2.get_element(coord1);
202 assert(moved_element == 1 && "moved down");
203
204 s1.set_boundary_condition(Direction(0), hila::bc::ANTIPERIODIC);
205 s2.set_boundary_condition(Direction(0), hila::bc::ANTIPERIODIC);
206
207 // Now try antiperiodic boundaries
208 s1 = 0;
209 s2 = 0;
210 s1.set_element(1, coord1);
211 s2[ALL] = s1[X - Direction(0)];
212 moved_element = s2.get_element(coord2);
213 assert(moved_element == -1 && "moved up antiperiodic");
214
215 // The other way
216 s1 = 0;
217 s2 = 0;
218 s1.set_element(1, coord2);
219 s2[ODD] = s1[X + Direction(0)];
220 moved_element = s2.get_element(coord1);
221 assert(moved_element == -1 && "moved down antiperiodic");
222
223 s1 = 0;
224 s1[EVEN] = s2[X - Direction(0)];
225 moved_element = s1.get_element(coord2);
226 assert(moved_element == 1 && "moved back antiperiodic");
227 }
228
229 // Communication and copy test with full field
230 foralldir(d) {
231 s1 = 1.0;
232 s2 = 1.0;
233 s3 = 1.0;
234 double sum = 0;
235 double sum2 = 0;
236 onsites(EVEN) {
237 double a = s1[X + d].re;
238 double b = s2[X].re;
239 sum += a - b;
240 }
241 assert(sum == 0 && "Test communicating a filled field");
242 }
243
244 // Test interleaving by calculating a sum of coordinates
245 // when a field is communicated
246 foralldir(d) {
247 s1 = 1;
248 s2 = 1;
249 sum = 0;
250 onsites(ALL) {
251 sum += X.coordinates()[0];
252 s1[X];
253 }
254
255 double result = lattice.volume() * (nd[0] - 1) / 2;
256 assert(sum == result && "Reproduce write problem 1");
257
258 s1 = 1;
259 s2 = 1;
260 sum = 0;
261 onsites(ALL) {
262 sum += X.coordinates()[0];
263 s1[X + d];
264 }
265
266 assert(sum == result && "Reproduce write problem 2");
267 }
268
269 // Check that communicated and changed fields get marked
270 // correctly
271 CoordinateVector c(0);
272 foralldir(dir) {
273 for (int i = 0; i < 2; i++) {
274 s1[EVEN] = 0;
275 s1[c] = i;
276
277 s2[ALL] = 0;
278 s2[ODD] = s2[X] - s1[X + dir];
279 s2[EVEN] = s2[X] + s2[X - dir];
280
281 double r = s2[c].re;
282 sum = (r + i) * (r + i);
283 if (hila::myrank() == 0) {
284 assert(sum < 1e-8 && "Even-odd comm test");
285 }
286 }
287 }
288
289 // Test starting communication manually
290
291 s1[EVEN] = 1.0;
292 s2[EVEN] = 1.0;
293 s2[ODD] = -s1[X + e_x];
294 s2.start_gather(e_x, ODD);
295
296 sum = 0;
297 onsites(ALL) { sum += s2[X].re; }
298 assert(sum == 0);
299
300 // Test referring to an array of fields
301
302 s4[0] = s1;
303 s4[1] = s1;
304
305 s4[2][ALL] = s4[0][X] - s4[1][X];
306
307 sum = 0;
308 onsites(ALL) { sum += (s4[2][X] * s4[2][X]).re; }
309 assert(sum == 0);
310
311 // Test function call outside loop
312 s1[ALL] = 0.0;
313 s2[ALL] = 1.0;
314 sum_test_function(s3, s1, s2); // s3 = s1 + s2
315 onsites(ALL) {
316 element<double> diff = s3[X].re - 1.0;
317 sum += diff * diff;
318 }
319 assert(sum == 0);
320
321 // Test function calls in loop
322 s1[ALL] = 1.0;
323 s2[ALL] = 1.0;
324 onsites(ALL) {
325 s1[X] = test_template_function(s1[X]);
326 s2[X] = test_nontemplate_function(s2[X]);
327 }
328 onsites(ALL) {
329 element<double> diff1 = s1[X].re - 2.0;
330 element<double> diff2 = s2[X].re - 2.0;
331 sum += diff1 * diff1 + diff2 * diff2;
332 }
333 assert(sum == 0);
334
335 // Test array reduction
336 Field<double> dfield;
337 dfield[ALL] = 1;
338
339#if NDIM == 4
340 ReductionVector<double> arraysum(nd[e_t]);
341 arraysum = 0;
342
343 onsites(ALL) {
344 CoordinateVector l = X.coordinates();
345 int t = l[e_t];
346
347 arraysum[t] += dfield[X];
348 }
349
350 for (int t = 0; t < nd[e_t]; t++) {
351 assert(arraysum[t] == nd[e_x] * nd[e_y] * nd[e_z]);
352 }
353#endif
354
356}
Complex definition.
Definition cmplx.h:56
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
void set_boundary_condition(Direction dir, hila::bc bc)
Set the boundary condition in a given Direction (periodic or antiperiodic)
Definition field.h:580
const T get_element(const CoordinateVector &coord) const
Get singular element which will be broadcast to all nodes.
Definition field.h:1221
const T set_element(const CoordinateVector &coord, const A &value)
Get singular element which will be broadcast to all nodes.
Definition field.h:1204
bool is_initialized(Parity p) const
Returns true if the Field has been assigned to.
Definition field.h:431
bool is_allocated() const
Returns true if the Field data has been allocated.
Definition field.h:422
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
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
int myrank()
rank of this node
Definition com_mpi.cpp:234
std::ostream out0
This writes output only from main process (node 0)
void finishrun()
Normal, controlled exit - all nodes must call this. Prints timing information and information about c...