MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
test_exchange.c
Go to the documentation of this file.
1 /*Simple test for the exchange function*/
2 
3 #include <stdarg.h>
4 #include <stddef.h>
5 #include <setjmp.h>
6 #include <cmocka.h>
7 #include <math.h>
8 #include <mpi.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <time.h>
12 #include <gsl/gsl_rng.h>
13 
14 #define qsort_openmp qsort
15 
16 #include <libgadget/exchange.h>
17 #include <libgadget/domain.h>
18 #include <libgadget/slotsmanager.h>
19 #include <libgadget/partmanager.h>
20 #include "stub.h"
21 #include <libgadget/walltime.h>
22 
25 
26 static struct ClockTable Clocks;
27 
28 #define NUMPART1 8
29 static int
30 setup_particles(int64_t NType[6])
31 {
33  MPI_Barrier(MPI_COMM_WORLD);
34  PartManager->MaxPart = 1024;
35  int ptype;
36  PartManager->NumPart = 0;
37  for(ptype = 0; ptype < 6; ptype ++) {
38  PartManager->NumPart += NType[ptype];
39  }
40  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
41  MPI_Comm_size(MPI_COMM_WORLD, &NTask);
42 
43  P = (struct particle_data *) mymalloc("P", PartManager->MaxPart * sizeof(struct particle_data));
44  memset(P, 0, sizeof(struct particle_data) * PartManager->MaxPart);
45 
50 
51 
52  slots_reserve(1, NType, SlotsManager);
53 
55 
56  int i;
57  #pragma omp parallel for
58  for(i = 0; i < PartManager->NumPart; i ++) {
59  P[i].ID = i + PartManager->NumPart * ThisTask;
60  }
61 
63 
64  MPI_Allreduce(&PartManager->NumPart, &TotNumPart, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
65 
66  return 0;
67 }
68 
69 static int
70 teardown_particles(void **state)
71 {
72  int TotNumPart2;
73 
74  MPI_Allreduce(&PartManager->NumPart, &TotNumPart2, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
75 
76  assert_int_equal(TotNumPart2, TotNumPart);
77 
79  myfree(P);
80  MPI_Barrier(MPI_COMM_WORLD);
81  return 0;
82 }
83 
84 
85 static int
86 test_exchange_layout_func(int i, const void * userdata)
87 {
88  return P[i].ID % NTask;
89 }
90 
91 static void
92 test_exchange(void **state)
93 {
94  int64_t newSlots[6] = {NUMPART1, NUMPART1, NUMPART1, NUMPART1, NUMPART1, NUMPART1};
95 
96  setup_particles(newSlots);
97 
98  int i;
99 
100  int fail = domain_exchange(&test_exchange_layout_func, NULL, 1, NULL, PartManager, SlotsManager,10000, MPI_COMM_WORLD);
101 
102  assert_all_true(!fail);
103 
106 
107  for(i = 0; i < PartManager->NumPart; i ++) {
108  assert_true(P[i].ID % NTask == 1Lu * ThisTask);
109  }
110 
111  teardown_particles(state);
112  return;
113 }
114 
115 static void
117 {
118  int64_t newSlots[6] = {NUMPART1, 0, NUMPART1, 0, NUMPART1, 0};
119 
120  setup_particles(newSlots);
121 
122  int i;
123 
124  int fail = domain_exchange(&test_exchange_layout_func, NULL, 1, NULL, PartManager, SlotsManager, 10000, MPI_COMM_WORLD);
125 
126  assert_all_true(!fail);
127 
130 
131  for(i = 0; i < PartManager->NumPart; i ++) {
132  assert_true (P[i].ID % NTask == 1Lu*ThisTask);
133  }
134 
135  teardown_particles(state);
136  return;
137 }
138 
139 static void
141 {
142  int64_t newSlots[6] = {NUMPART1, NUMPART1, NUMPART1, NUMPART1, NUMPART1, NUMPART1};
143 
144  setup_particles(newSlots);
145  int i;
146 
147  slots_mark_garbage(0, PartManager, SlotsManager); /* watch out! this propagates the garbage flag to children */
148  TotNumPart -= NTask;
149 
150  int fail = domain_exchange(&test_exchange_layout_func, NULL, 1, NULL, PartManager, SlotsManager, 10000, MPI_COMM_WORLD);
151 
152  assert_all_true(!fail);
153 
156 
157  for(i = 0; i < PartManager->NumPart; i ++) {
158  assert_true (P[i].ID % NTask == 1Lu * ThisTask);
159  }
160 
161  for(i = 0; i < PartManager->NumPart; i ++) {
162  assert_true (P[i].IsGarbage == 0);
163  }
164 
165  teardown_particles(state);
166  return;
167 }
168 
169 static int
170 test_exchange_layout_func_uneven(int i, const void * userdata)
171 {
172  if(P[i].Type == 0) return 0;
173 
174  return P[i].ID % NTask;
175 }
176 
177 static void
178 test_exchange_uneven(void **state)
179 {
180  int64_t newSlots[6] = {NUMPART1, NUMPART1, NUMPART1, NUMPART1, NUMPART1, NUMPART1};
181 
182  setup_particles(newSlots);
183  int i;
184 
185  /* this will trigger a slot growth on slot type 0 due to the inbalance */
186  int fail = domain_exchange(&test_exchange_layout_func_uneven, NULL, 1, NULL, PartManager, SlotsManager, 10000, MPI_COMM_WORLD);
187 
188  assert_all_true(!fail);
189 
190  if(ThisTask == 0) {
191  /* the slot type must have grown automatically to handle the new particles. */
192  assert_int_equal(SlotsManager->info[0].size, NUMPART1 * NTask);
193  }
194 
197 
198  for(i = 0; i < PartManager->NumPart; i ++) {
199  if(P[i].Type == 0) {
200  assert_true (ThisTask == 0);
201  } else {
202  assert_true(P[i].ID % NTask == 1Lu * ThisTask);
203  }
204  }
205 
206  teardown_particles(state);
207  return;
208 }
209 
210 int main(void) {
211  const struct CMUnitTest tests[] = {
212  cmocka_unit_test(test_exchange_with_garbage),
213  cmocka_unit_test(test_exchange),
214  cmocka_unit_test(test_exchange_zero_slots),
215  cmocka_unit_test(test_exchange_uneven),
216  };
217  return cmocka_run_group_tests_mpi(tests, NULL, NULL);
218 }
void domain_test_id_uniqueness(struct part_manager_type *pman)
Definition: exchange.c:570
int domain_exchange(ExchangeLayoutFunc layoutfunc, const void *layout_userdata, int do_gc, struct DriftData *drift, struct part_manager_type *pman, struct slots_manager_type *sman, int maxiter, MPI_Comm Comm)
Definition: exchange.c:103
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define myfree(x)
Definition: mymalloc.h:19
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define P
Definition: partmanager.h:88
void slots_setup_id(const struct part_manager_type *pman, struct slots_manager_type *sman)
Definition: slotsmanager.c:653
size_t slots_reserve(int where, int64_t atleast[6], struct slots_manager_type *sman)
Definition: slotsmanager.c:475
void slots_set_enabled(int ptype, size_t elsize, struct slots_manager_type *sman)
Definition: slotsmanager.c:560
void slots_mark_garbage(int i, struct part_manager_type *pman, struct slots_manager_type *sman)
Definition: slotsmanager.c:577
void slots_free(struct slots_manager_type *sman)
Definition: slotsmanager.c:570
void slots_setup_topology(struct part_manager_type *pman, int64_t *NLocal, struct slots_manager_type *sman)
Definition: slotsmanager.c:624
void slots_check_id_consistency(struct part_manager_type *pman, struct slots_manager_type *sman)
Definition: slotsmanager.c:587
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
void slots_init(double increase, struct slots_manager_type *sman)
Definition: slotsmanager.c:550
MyIDType ID
Definition: partmanager.h:38
unsigned int Type
Definition: partmanager.h:17
unsigned int IsGarbage
Definition: partmanager.h:19
int64_t size
Definition: slotsmanager.h:12
struct slot_info info[6]
Definition: slotsmanager.h:112
static int test_exchange_layout_func(int i, const void *userdata)
Definition: test_exchange.c:86
static struct ClockTable Clocks
Definition: test_exchange.c:26
static void test_exchange_uneven(void **state)
static int test_exchange_layout_func_uneven(int i, const void *userdata)
int ThisTask
Definition: test_exchange.c:23
static void test_exchange_with_garbage(void **state)
int NTask
Definition: test_exchange.c:23
static int setup_particles(int64_t NType[6])
Definition: test_exchange.c:30
int TotNumPart
Definition: test_exchange.c:24
static int teardown_particles(void **state)
Definition: test_exchange.c:70
int main(void)
#define NUMPART1
Definition: test_exchange.c:28
static void test_exchange(void **state)
Definition: test_exchange.c:92
static void test_exchange_zero_slots(void **state)
void walltime_init(struct ClockTable *ct)
Definition: walltime.c:19
static enum TransferType ptype
Definition: zeldovich.c:146