MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
test_density.c
Go to the documentation of this file.
1 /*Simple test for the tree building functions*/
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 <time.h>
11 #include <gsl/gsl_rng.h>
12 
13 #include <libgadget/partmanager.h>
14 #include <libgadget/walltime.h>
15 #include <libgadget/slotsmanager.h>
17 #include <libgadget/density.h>
18 #include <libgadget/domain.h>
19 #include <libgadget/forcetree.h>
20 #include <libgadget/timestep.h>
21 #include <libgadget/gravity.h>
22 
23 #include "stub.h"
24 
25 /* The true struct for the state variable*/
27 {
28  struct sph_pred_data sph_pred;
30  struct density_params dp;
31  gsl_rng * r;
32 };
33 
34 static void set_init_hsml(ForceTree * Tree)
35 {
36  int i;
37  #pragma omp parallel for
38  for(i = 0; i < PartManager->NumPart; i++)
39  {
40  int no = force_get_father(i, Tree);
41 
42  double DesNumNgb = GetNumNgb(GetDensityKernelType());
43  while(10 * DesNumNgb * P[i].Mass > Tree->Nodes[no].mom.mass)
44  {
45  int p = force_get_father(no, Tree);
46 
47  if(p < 0)
48  break;
49 
50  no = p;
51  }
52 
53  P[i].Hsml =
54  pow(3.0 / (4 * M_PI) * DesNumNgb * P[i].Mass / (Tree->Nodes[no].mom.mass),
55  1.0 / 3) * Tree->Nodes[no].len;
56  }
57 }
58 
59 /* Perform some simple checks on the densities*/
60 static void check_densities(double MinGasHsml)
61 {
62  int i;
63  double maxHsml=P[0].Hsml, minHsml= P[0].Hsml;
64  #pragma omp parallel for reduction(min:minHsml) reduction(max:maxHsml)
65  for(i=0; i<PartManager->NumPart; i++) {
66  assert_true(isfinite(P[i].Hsml));
67  assert_true(isfinite(SPHP(i).Density));
68  assert_true(SPHP(i).Density > 0);
69  if(P[i].Hsml < minHsml)
70  minHsml = P[i].Hsml;
71  if(P[i].Hsml > maxHsml)
72  maxHsml = P[i].Hsml;
73  }
74  assert_true(isfinite(minHsml));
75  assert_true(minHsml >= MinGasHsml);
76  assert_true(maxHsml <= PartManager->BoxSize);
77 
78 }
79 
80 static void do_density_test(void ** state, const int numpart, double expectedhsml, double hsmlerr)
81 {
82  int i, npbh=0;
83  #pragma omp parallel for reduction(+: npbh)
84  for(i=0; i<numpart; i++) {
85  int j;
86  P[i].Key = PEANO(P[i].Pos, PartManager->BoxSize);
87  P[i].Mass = 1;
88  P[i].TimeBin = 0;
89  P[i].Ti_drift = 0;
90  for(j=0; j<3; j++)
91  P[i].Vel[j] = 1.5;
92  if(P[i].Type == 0) {
93  SPHP(i).Entropy = 1;
94  SPHP(i).DtEntropy = 0;
95  SPHP(i).Density = 1;
96  }
97  if(P[i].Type == 5)
98  npbh++;
99  }
100 
101  SlotsManager->info[0].size = numpart-npbh;
102  SlotsManager->info[5].size = npbh;
103  PartManager->NumPart = numpart;
104  ActiveParticles act = {0};
105  act.NumActiveParticle = numpart;
106  act.ActiveParticle = NULL;
107  struct density_testdata * data = * (struct density_testdata **) state;
108  DomainDecomp ddecomp = data->ddecomp;
110 
111  ForceTree tree = {0};
112  force_tree_rebuild(&tree, &ddecomp, 0, 1, NULL);
113  set_init_hsml(&tree);
114  /* Rebuild without moments to check it works*/
115  force_tree_rebuild(&tree, &ddecomp, 0, 0, NULL);
116  /*Time doing the density finding*/
117  double start, end;
118  start = MPI_Wtime();
119  /*Find the density*/
120  DriftKickTimes kick = {0};
121  Cosmology CP = {0};
122  CP.CMBTemperature = 2.7255;
123  CP.Omega0 = 0.3;
124  CP.OmegaLambda = 1- CP.Omega0;
125  CP.OmegaBaryon = 0.045;
126  CP.HubbleParam = 0.7;
127  CP.RadiationOn = 0;
128  CP.w0_fld = -1; /*Dark energy equation of state parameter*/
129  /*Should be 0.1*/
130  struct UnitSystem units = get_unitsystem(3.085678e21, 1.989e43, 1e5);
131  init_cosmology(&CP,0.01, units);
132 
133  density(&act, 1, 0, 0, 0, kick, &CP, &data->sph_pred, NULL, &tree);
134  end = MPI_Wtime();
135  double ms = (end - start)*1000;
136  message(0, "Found densities in %.3g ms\n", ms);
138 
139  double avghsml = 0;
140  #pragma omp parallel for reduction(+:avghsml)
141  for(i=0; i<numpart; i++) {
142  avghsml += P[i].Hsml;
143  }
144  message(0, "Average Hsml: %g Expected %g +- %g\n",avghsml/numpart, expectedhsml, hsmlerr);
145  assert_true(fabs(avghsml/numpart - expectedhsml) < hsmlerr);
146  /* Make MaxNumNgbDeviation smaller and check we get a consistent result.*/
147  double * Hsml = mymalloc2("Hsml", numpart * sizeof(double));
148  #pragma omp parallel for
149  for(i=0; i<numpart; i++) {
150  Hsml[i] = P[i].Hsml;
151  }
152  data->dp.MaxNumNgbDeviation = 0.5;
153  set_densitypar(data->dp);
154 
155  start = MPI_Wtime();
156  /*Find the density*/
157  density(&act, 1, 0, 0, 0, kick, &CP, &data->sph_pred, NULL, &tree);
158  end = MPI_Wtime();
159  ms = (end - start)*1000;
160  message(0, "Found 1 dev densities in %.3g ms\n", ms);
161  double diff = 0;
162  double DesNumNgb = GetNumNgb(GetDensityKernelType());
163  /* Free tree before checks so that we still recover if checks fail*/
164  force_tree_free(&tree);
165 
166  #pragma omp parallel for reduction(max:diff)
167  for(i=0; i<numpart; i++) {
168  assert_true(fabs(Hsml[i]/P[i].Hsml-1) < data->dp.MaxNumNgbDeviation / DesNumNgb);
169  if(fabs(Hsml[i] - P[i].Hsml) > diff)
170  diff = fabs(Hsml[i] - P[i].Hsml);
171  }
172  message(0, "Max diff between Hsml: %g\n",diff);
173  myfree(Hsml);
174 
176 }
177 
178 static void test_density_flat(void ** state) {
179  /*Set up the particle data*/
180  int ncbrt = 32;
181  int numpart = ncbrt*ncbrt*ncbrt;
182  /* Create a regular grid of particles, 8x8x8, all of type 1,
183  * in a box 8 kpc across.*/
184  int i;
185  #pragma omp parallel for
186  for(i=0; i<numpart; i++) {
187  P[i].Type = 0;
188  P[i].PI = i;
189  P[i].Hsml = 1.5*PartManager->BoxSize/cbrt(numpart);
190  P[i].Pos[0] = (PartManager->BoxSize/ncbrt) * (i/ncbrt/ncbrt);
191  P[i].Pos[1] = (PartManager->BoxSize/ncbrt) * ((i/ncbrt) % ncbrt);
192  P[i].Pos[2] = (PartManager->BoxSize/ncbrt) * (i % ncbrt);
193  }
194  do_density_test(state, numpart, 0.501747, 1e-4);
195 }
196 
197 static void test_density_close(void ** state) {
198  /*Set up the particle data*/
199  int ncbrt = 32;
200  int numpart = ncbrt*ncbrt*ncbrt;
201  double close = 500.;
202  int i;
203  /* A few particles scattered about the place so the tree is not sparse*/
204  #pragma omp parallel for
205  for(i=0; i<numpart/4; i++) {
206  P[i].Type = 0;
207  P[i].PI = i;
208  P[i].Hsml = 4*PartManager->BoxSize/cbrt(numpart/8);
209  P[i].Pos[0] = (PartManager->BoxSize/ncbrt) * (i/(ncbrt/2.)/(ncbrt/2.));
210  P[i].Pos[1] = (PartManager->BoxSize/ncbrt) * ((i*2/ncbrt) % (ncbrt/2));
211  P[i].Pos[2] = (PartManager->BoxSize/ncbrt) * (i % (ncbrt/2));
212  }
213 
214  /* Create particles clustered in one place, all of type 0.*/
215  #pragma omp parallel for
216  for(i=numpart/4; i<numpart; i++) {
217  P[i].Type = 0;
218  P[i].PI = i;
219  P[i].Hsml = 2*ncbrt/close;
220  P[i].Pos[0] = 4.1 + (i/ncbrt/ncbrt)/close;
221  P[i].Pos[1] = 4.1 + ((i/ncbrt) % ncbrt) /close;
222  P[i].Pos[2] = 4.1 + (i % ncbrt)/close;
223  }
224  P[numpart-1].Type = 5;
225  P[numpart-1].PI = 0;
226 
227  do_density_test(state, numpart, 0.131726, 1e-4);
228 }
229 
230 void do_random_test(void **state, gsl_rng * r, const int numpart)
231 {
232  /* Create a randomly space set of particles, 8x8x8, all of type 0. */
233  int i;
234  for(i=0; i<numpart/4; i++) {
235  P[i].Type = 0;
236  P[i].PI = i;
237  P[i].Hsml = PartManager->BoxSize/cbrt(numpart);
238 
239  int j;
240  for(j=0; j<3; j++)
241  P[i].Pos[j] = PartManager->BoxSize * gsl_rng_uniform(r);
242  }
243  for(i=numpart/4; i<3*numpart/4; i++) {
244  P[i].Type = 0;
245  P[i].PI = i;
246  P[i].Hsml = PartManager->BoxSize/cbrt(numpart);
247  int j;
248  for(j=0; j<3; j++)
249  P[i].Pos[j] = PartManager->BoxSize/2 + PartManager->BoxSize/8 * exp(pow(gsl_rng_uniform(r)-0.5,2));
250  }
251  for(i=3*numpart/4; i<numpart; i++) {
252  P[i].Type = 0;
253  P[i].PI = i;
254  P[i].Hsml = PartManager->BoxSize/cbrt(numpart);
255  int j;
256  for(j=0; j<3; j++)
257  P[i].Pos[j] = PartManager->BoxSize*0.1 + PartManager->BoxSize/32 * exp(pow(gsl_rng_uniform(r)-0.5,2));
258  }
259  do_density_test(state, numpart, 0.187515, 1e-3);
260 }
261 
262 static void test_density_random(void ** state) {
263  /*Set up the particle data*/
264  int ncbrt = 32;
265  struct density_testdata * data = * (struct density_testdata **) state;
266  gsl_rng * r = (gsl_rng *) data->r;
267  int numpart = ncbrt*ncbrt*ncbrt;
268  /*Allocate tree*/
269  /*Base pointer*/
270  int i;
271  for(i=0; i<2; i++) {
272  do_random_test(state, r, numpart);
273  }
274 }
275 
276 
277 /*Make a simple trivial domain for all data on a single processor*/
279 {
280  /* The whole tree goes into one topnode.
281  * Set up just enough of the TopNode structure that
282  * domain_get_topleaf works*/
284  ddecomp->NTopNodes = 1;
285  ddecomp->NTopLeaves = 1;
286  ddecomp->TopNodes = mymalloc("topnode", sizeof(struct topnode_data));
287  ddecomp->TopNodes[0].Daughter = -1;
288  ddecomp->TopNodes[0].Leaf = 0;
289  ddecomp->TopLeaves = mymalloc("topleaf",sizeof(struct topleaf_data));
290  ddecomp->TopLeaves[0].Task = 0;
291  ddecomp->TopLeaves[0].topnode = 0;
292  /*These are not used*/
293  ddecomp->TopNodes[0].StartKey = 0;
295  /*To tell the code we are in serial*/
296  ddecomp->Tasks = mymalloc("task",sizeof(struct task_data));
297  ddecomp->Tasks[0].StartLeaf = 0;
298  ddecomp->Tasks[0].EndLeaf = 1;
299 }
300 
301 static int teardown_density(void **state) {
302  struct density_testdata * data = (struct density_testdata * ) *state;
304  myfree(data->ddecomp.Tasks);
305  myfree(data->ddecomp.TopLeaves);
306  myfree(data->ddecomp.TopNodes);
307  free(data->r);
308  myfree(data);
309  return 0;
310 }
311 
312 static struct ClockTable CT;
313 
314 static int setup_density(void **state) {
315  /* Needed so the integer timeline works*/
316  setup_sync_points(0.01, 0.1, 0.0, 0);
317 
318  /*Reserve space for the slots*/
322  int64_t atleast[6] = {0};
323  atleast[0] = pow(32,3);
324  atleast[5] = 2;
325  int64_t maxpart = 0;
326  int i;
327  for(i = 0; i < 6; i++)
328  maxpart+=atleast[i];
329  const double BoxSize = 8;
330  particle_alloc_memory(PartManager, BoxSize, maxpart);
331  slots_reserve(1, atleast, SlotsManager);
332  walltime_init(&CT);
334  struct density_testdata *data = mymalloc("data", sizeof(struct density_testdata));
335  data->sph_pred = slots_allocate_sph_pred_data(maxpart);
336  /*Set up the top-level domain grid*/
337  trivial_domain(&data->ddecomp);
338  data->dp.DensityResolutionEta = 1.;
339  data->dp.BlackHoleNgbFactor = 2;
340  data->dp.MaxNumNgbDeviation = 2;
342  data->dp.MinGasHsmlFractional = 0.006;
343  struct gravshort_tree_params tree_params = {0};
344  tree_params.FractionalGravitySoftening = 1;
345  set_gravshort_treepar(tree_params);
346 
348  data->dp.BlackHoleMaxAccretionRadius = 99999.;
349 
350  set_densitypar(data->dp);
351  data->r = gsl_rng_alloc(gsl_rng_mt19937);
352  gsl_rng_set(data->r, 0);
353  *state = (void *) data;
354  return 0;
355 }
356 
357 int main(void) {
358  const struct CMUnitTest tests[] = {
359  cmocka_unit_test(test_density_flat),
360  cmocka_unit_test(test_density_close),
361  cmocka_unit_test(test_density_random),
362  };
363  return cmocka_run_group_tests_mpi(tests, setup_density, teardown_density);
364 }
void init_cosmology(Cosmology *CP, const double TimeBegin, const struct UnitSystem units)
Definition: cosmology.c:15
double GetNumNgb(enum DensityKernelType KernelType)
Definition: density.c:55
void set_densitypar(struct density_params dp)
Definition: density.c:25
struct sph_pred_data slots_allocate_sph_pred_data(int nsph)
Definition: density.c:654
void slots_free_sph_pred_data(struct sph_pred_data *sph_scratch)
Definition: density.c:665
enum DensityKernelType GetDensityKernelType(void)
Definition: density.c:63
void density(const ActiveParticles *act, int update_hsml, int DoEgyDensity, int BlackHoleOn, double MinEgySpec, const DriftKickTimes times, Cosmology *CP, struct sph_pred_data *SPH_predicted, MyFloat *GradRho, const ForceTree *const tree)
Definition: density.c:203
@ DENSITY_KERNEL_CUBIC_SPLINE
Definition: densitykernel.h:18
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void force_tree_rebuild(ForceTree *tree, DomainDecomp *ddecomp, const int HybridNuGrav, const int DoMoments, const char *EmergencyOutputDir)
Definition: forcetree.c:140
void init_forcetree_params(const int FastParticleType)
Definition: forcetree.c:43
void force_tree_free(ForceTree *tree)
Definition: forcetree.c:1409
int force_get_father(int no, const ForceTree *tree)
Definition: forcetree.c:905
void gravshort_set_softenings(double MeanDMSeparation)
void set_gravshort_treepar(struct gravshort_tree_params tree_params)
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define mymalloc2(name, size)
Definition: mymalloc.h:16
#define myfree(x)
Definition: mymalloc.h:19
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
void particle_alloc_memory(struct part_manager_type *PartManager, double BoxSize, int64_t MaxPart)
Definition: partmanager.c:14
#define P
Definition: partmanager.h:88
static peano_t PEANO(double *Pos, double BoxSize)
Definition: peano.h:14
#define BITS_PER_DIMENSION
Definition: peano.h:9
static Cosmology * CP
Definition: power.c:27
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
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
void slots_init(double increase, struct slots_manager_type *sman)
Definition: slotsmanager.c:550
#define SPHP(i)
Definition: slotsmanager.h:124
int * ActiveParticle
Definition: timestep.h:13
int64_t NumActiveParticle
Definition: timestep.h:12
double Omega0
Definition: cosmology.h:10
int RadiationOn
Definition: cosmology.h:23
double HubbleParam
Definition: cosmology.h:20
double CMBTemperature
Definition: cosmology.h:9
double OmegaLambda
Definition: cosmology.h:14
double OmegaBaryon
Definition: cosmology.h:19
double w0_fld
Definition: cosmology.h:16
struct topnode_data * TopNodes
Definition: domain.h:36
struct task_data * Tasks
Definition: domain.h:41
int NTopNodes
Definition: domain.h:39
struct topleaf_data * TopLeaves
Definition: domain.h:37
int NTopLeaves
Definition: domain.h:40
int domain_allocated_flag
Definition: domain.h:34
struct NODE * Nodes
Definition: forcetree.h:97
struct NODE::@9 mom
MyFloat mass
Definition: forcetree.h:56
MyFloat len
Definition: forcetree.h:42
double MaxNumNgbDeviation
Definition: density.h:12
double DensityResolutionEta
Definition: density.h:11
double MinGasHsmlFractional
Definition: density.h:22
double BlackHoleNgbFactor
Definition: density.h:15
enum DensityKernelType DensityKernelType
Definition: density.h:18
double BlackHoleMaxAccretionRadius
Definition: density.h:16
struct density_params dp
Definition: test_density.c:30
DomainDecomp ddecomp
Definition: test_density.c:29
struct sph_pred_data sph_pred
Definition: test_density.c:28
double FractionalGravitySoftening
Definition: gravity.h:18
int64_t size
Definition: slotsmanager.h:12
struct slot_info info[6]
Definition: slotsmanager.h:112
int EndLeaf
Definition: domain.h:30
int StartLeaf
Definition: domain.h:29
int topnode
Definition: domain.h:23
int Task
Definition: domain.h:21
peano_t StartKey
Definition: domain.h:14
int Leaf
Definition: domain.h:17
int Daughter
Definition: domain.h:15
int Shift
Definition: domain.h:16
static void test_density_close(void **state)
Definition: test_density.c:197
static void do_density_test(void **state, const int numpart, double expectedhsml, double hsmlerr)
Definition: test_density.c:80
static void set_init_hsml(ForceTree *Tree)
Definition: test_density.c:34
static struct ClockTable CT
Definition: test_density.c:312
static int teardown_density(void **state)
Definition: test_density.c:301
static void check_densities(double MinGasHsml)
Definition: test_density.c:60
static void test_density_random(void **state)
Definition: test_density.c:262
int main(void)
Definition: test_density.c:357
static int setup_density(void **state)
Definition: test_density.c:314
void trivial_domain(DomainDecomp *ddecomp)
Definition: test_density.c:278
void do_random_test(void **state, gsl_rng *r, const int numpart)
Definition: test_density.c:230
static void test_density_flat(void **state)
Definition: test_density.c:178
void setup_sync_points(double TimeIC, double TimeMax, double no_snapshot_until_time, int SnapshotWithFOF)
Definition: timebinmgr.c:97
struct UnitSystem get_unitsystem(double UnitLength_in_cm, double UnitMass_in_g, double UnitVelocity_in_cm_per_s)
Definition: unitsystem.c:6
void walltime_init(struct ClockTable *ct)
Definition: walltime.c:19