GADGET-4
domain_box.cc
Go to the documentation of this file.
1 /*******************************************************************************
2  * \copyright This file is part of the GADGET4 N-body/SPH code developed
3  * \copyright by Volker Springel. Copyright (C) 2014-2020 by Volker Springel
4  * \copyright (vspringel@mpa-garching.mpg.de) and all contributing authors.
5  *******************************************************************************/
6 
12 #include "gadgetconfig.h"
13 
14 #include <mpi.h>
15 #include <algorithm>
16 #include <cmath>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 
21 #include "../data/allvars.h"
22 #include "../data/dtypes.h"
23 #include "../data/intposconvert.h"
24 #include "../data/mymalloc.h"
25 #include "../domain/domain.h"
26 #include "../logs/timer.h"
27 #include "../main/simulation.h"
28 #include "../pm/pm.h"
29 #include "../system/system.h"
30 
31 using namespace std;
32 
42 template <>
44 {
45  if(Mode != STANDARD)
46  return;
47 
48 #ifdef RANDOMIZE_DOMAINCENTER
49  /* remove previous shift vector */
50  for(int i = 0; i < Tp->NumPart; i++)
51  {
52  for(int j = 0; j < 3; j++)
53  Tp->P[i].IntPos[j] -= Tp->CurrentShiftVector[j];
54 
55  Tp->constrain_intpos(Tp->P[i].IntPos);
56  }
57 
58  for(int j = 0; j < 3; j++)
59  Tp->CurrentShiftVector[j] = 0;
60 #endif
61 
62 #ifndef PERIODIC
63  /* If we don't use periodic boundaries, check whether we lie outside the central 3/8 of the region chosen for the root node.
64  * This is based on the notion of using 1/4 for the initial region, leaving 1/4 as a safe buffer. Once half of this buffer
65  * is used up, we trigger an adjustment. */
66 
67  MyIntPosType leftbound = 5 * (((MyIntPosType)1) << (BITS_FOR_POSITIONS - 4)); /* 5/16 of full box length */
68  MyIntPosType rightbound = 11 * (((MyIntPosType)1) << (BITS_FOR_POSITIONS - 4)); /* 11/16 of full box length */
69 
70  int flag = 0;
71  int iter = 0;
72 
73  do
74  {
75  flag = 0;
76  for(int i = 0; i < Tp->NumPart; i++)
77  for(int j = 0; j < 3; j++)
78  {
79  if(Tp->P[i].IntPos[j] < leftbound)
80  flag = 1;
81 
82  if(Tp->P[i].IntPos[j] > rightbound)
83  flag = 1;
84  }
85 
86  MPI_Allreduce(MPI_IN_PLACE, &flag, 1, MPI_INT, MPI_MAX, Communicator);
87 
88  if(flag)
89  {
90  domain_printf("DOMAIN: Simulation region has enlarged, need to adjusted mapping.\n");
91 
92  for(int i = 0; i < Tp->NumPart; i++)
93  for(int j = 0; j < 3; j++)
94  Tp->P[i].IntPos[j] = (Tp->P[i].IntPos[j] >> 1) + (((MyIntPosType)1) << (BITS_FOR_POSITIONS - 2));
95 
96  Tp->FacCoordToInt *= 0.5;
97  Tp->FacIntToCoord *= 2.0;
98  Tp->RegionLen *= 2.0;
99 
100  for(int j = 0; j < 3; j++)
101  Tp->RegionCorner[j] = Tp->RegionCenter[j] - 0.5 * Tp->RegionLen;
102 
103 #if defined(PMGRID) && (!defined(PERIODIC) || defined(PLACEHIGHRESREGION))
104  /* make sure that we compute new kernels the next time we execute a non-periodic pm calculation */
105  Tp->OldMeshSize[0] = 0;
106  Tp->OldMeshSize[1] = 0;
107 #endif
108 
109  iter++;
110  }
111 
112  if(iter > 5)
113  Terminate("too many iterations");
114  }
115  while(flag);
116 
117 #endif
118 
119 #ifdef RANDOMIZE_DOMAINCENTER
120  /* determine new shift vector */
121 
122 #if defined(RANDOMIZE_DOMAINCENTER_TYPES) || defined(PLACEHIGHRESREGION)
123  domain_find_type_extension();
124 #endif
125 
126  if(ThisTask == 0)
127  {
128 #if defined(RANDOMIZE_DOMAINCENTER_TYPES) || defined(PLACEHIGHRESREGION)
129  int count = 0;
130 #endif
131 
132  for(int j = 0; j < 3; j++)
133  {
134  Tp->CurrentShiftVector[j] = get_random_number() * pow(2.0, 32);
135 #ifdef POSITIONS_IN_64BIT
136  Tp->CurrentShiftVector[j] <<= 32;
137  Tp->CurrentShiftVector[j] += get_random_number() * pow(2.0, 32);
138 #endif
139 #ifdef POSITIONS_IN_128BIT
140  Tp->CurrentShiftVector[j] <<= 32;
141  Tp->CurrentShiftVector[j] += get_random_number() * pow(2.0, 32);
142  Tp->CurrentShiftVector[j] <<= 32;
143  Tp->CurrentShiftVector[j] += get_random_number() * pow(2.0, 32);
144  Tp->CurrentShiftVector[j] <<= 32;
145  Tp->CurrentShiftVector[j] += get_random_number() * pow(2.0, 32);
146 #endif
147 
148 #if defined(RANDOMIZE_DOMAINCENTER_TYPES) || defined(PLACEHIGHRESREGION)
149  MyIntPosType boxoff = (Tp->CurrentShiftVector[j] & Tp->PlacingMask);
150  MyIntPosType inboxoff = (Tp->CurrentShiftVector[j] - boxoff) % (Tp->PlacingBlocksize - domainInnersize);
151 
152  MyIntPosType off = domainXmintot[j] + domainReferenceIntPos[j] + Tp->CurrentShiftVector[j];
153  Tp->CurrentShiftVector[j] -= off; // now we have the high-res region aligned with the left box size
154  Tp->CurrentShiftVector[j] += boxoff + inboxoff;
155 
156  if(domain_type_extension_overlap(j))
157  {
158  domain_printf("(Tp->PlacingBlocksize - domainInnersize)=%g %g\n",
159  (Tp->PlacingBlocksize - domainInnersize) * Tp->FacIntToCoord, inboxoff * Tp->FacIntToCoord);
160  domain_printf("DOMAIN: Need to draw shift vector again for j=%d\n", j);
161  Terminate("we should not get here anymore\n");
162  j--; // causes a repeat of the loop for the same index
163  count++;
164  if(count > 1000)
165  Terminate("too many repeats");
166  continue;
167  }
168 #endif
169  }
170  }
171 
172 #ifdef GRAVITY_TALLBOX
173  Tp->CurrentShiftVector[GRAVITY_TALLBOX] = 0;
174 #endif
175 
176  MPI_Bcast(Tp->CurrentShiftVector, 3 * sizeof(MyIntPosType), MPI_BYTE, 0, Communicator);
177 
178  for(int i = 0; i < Tp->NumPart; i++)
179  {
180  for(int j = 0; j < 3; j++)
181  Tp->P[i].IntPos[j] += Tp->CurrentShiftVector[j];
182 
183  Tp->constrain_intpos(Tp->P[i].IntPos);
184  }
185 
186  domain_printf("DOMAIN: New shift vector determined (%g %g %g)\n",
187  ((MySignedIntPosType)Tp->CurrentShiftVector[0]) * Tp->FacIntToCoord,
188  ((MySignedIntPosType)Tp->CurrentShiftVector[1]) * Tp->FacIntToCoord,
189  ((MySignedIntPosType)Tp->CurrentShiftVector[2]) * Tp->FacIntToCoord);
190 #endif
191 }
192 
193 #if defined(RANDOMIZE_DOMAINCENTER_TYPES) || defined(PLACEHIGHRESREGION)
194 
195 template <typename partset>
197 {
198  MyIntPosType *xmintot = (MyIntPosType *)domainXmintot;
199  MyIntPosType *xmaxtot = (MyIntPosType *)domainXmaxtot;
200 
201  MyIntPosType xmin = xmintot[j] + domainReferenceIntPos[j] + Tp->CurrentShiftVector[j];
202  MyIntPosType xmax = xmaxtot[j] + domainReferenceIntPos[j] + Tp->CurrentShiftVector[j];
203 
204  if((xmin & Tp->PlacingMask) != (xmax & Tp->PlacingMask))
205  return 1;
206  else
207  return 0;
208 }
209 
210 template <typename partset>
212 {
213  /* first, find a reference coordinate by selecting an arbitrary particle in the respective region. For definiteness, we choose the
214  * first particle */
215 
216  int have_high_mesh = NTask; /* default is we don't have a particle */
217 
218  for(int i = 0; i < Tp->NumPart; i++)
219  {
220  if(((1 << Tp->P[i].getType()) & (RANDOMIZE_DOMAINCENTER_TYPES)))
221  {
222  for(int j = 0; j < 3; j++)
223  domainReferenceIntPos[j] = Tp->P[i].IntPos[j];
224 
225  have_high_mesh = ThisTask;
226  break;
227  }
228  }
229 
230  int have_global[2] = {have_high_mesh, ThisTask};
231 
232  MPI_Allreduce(MPI_IN_PLACE, have_global, 1, MPI_2INT, MPI_MINLOC, Communicator);
233 
234  if(have_global[0] >= NTask)
235  Terminate("have_global[0]=%d >= NTask=%d: Don't we have any particle? Note: RANDOMIZE_DOMAINCENTER_TYPES=%d is a bitmask",
236  have_global[0], NTask, RANDOMIZE_DOMAINCENTER_TYPES);
237 
238  MPI_Bcast(domainReferenceIntPos, 3 * sizeof(MyIntPosType), MPI_BYTE, have_global[1], Communicator);
239 
240  /* find enclosing rectangle */
241 
242  MySignedIntPosType xmin[3], xmax[3];
243 
244  for(int j = 0; j < 3; j++)
245  {
246  xmin[j] = 0;
247  xmax[j] = 0;
248  }
249 
250  for(int i = 0; i < Tp->NumPart; i++)
251  {
252  if(((1 << Tp->P[i].getType()) & (RANDOMIZE_DOMAINCENTER_TYPES)))
253  {
254  MyIntPosType diff[3] = {Tp->P[i].IntPos[0] - domainReferenceIntPos[0], Tp->P[i].IntPos[1] - domainReferenceIntPos[1],
255  Tp->P[i].IntPos[2] - domainReferenceIntPos[2]};
256 
257  MySignedIntPosType *delta = (MySignedIntPosType *)diff;
258 
259  for(int j = 0; j < 3; j++)
260  {
261  if(delta[j] > xmax[j])
262  xmax[j] = delta[j];
263  if(delta[j] < xmin[j])
264  xmin[j] = delta[j];
265  }
266  }
267  }
268 
269  MPI_Allreduce(xmin, domainXmintot, 3, MPI_MyIntPosType, MPI_MIN_MySignedIntPosType, Communicator);
270  MPI_Allreduce(xmax, domainXmaxtot, 3, MPI_MyIntPosType, MPI_MAX_MySignedIntPosType, Communicator);
271 
272  for(int j = 0; j < 3; j++)
273  domainXmaxtot[j] += 1; /* so that all particles fulfill xmin <= pos < xmax instead of xmin <= pos <= xmax*/
274 
275  domainInnersize = domainXmaxtot[0] - domainXmintot[0];
276 
277  if((MyIntPosType)(domainXmaxtot[1] - domainXmintot[1]) > domainInnersize)
278  domainInnersize = domainXmaxtot[1] - domainXmintot[1];
279 
280  if((MyIntPosType)(domainXmaxtot[2] - domainXmintot[2]) > domainInnersize)
281  domainInnersize = domainXmaxtot[2] - domainXmintot[2];
282 
283  domain_printf("DOMAIN: Shrink-wrap region size for RANDOMIZE_DOMAINCENTER_TYPES is %g\n", domainInnersize * Tp->FacIntToCoord);
284 
285  if(domainInnersize * Tp->FacIntToCoord >= 0.125 * All.BoxSize)
286  Terminate("inappropriately big region selection for RANDOMIZE_DOMAINCENTER_TYPES");
287 
288  /* increase the region by at least 1/8 of its size to still allow some randomness in placing the particles within the high-res node
289  */
290  MyIntPosType ref_size = domainInnersize + (domainInnersize >> 3);
291 
292  Tp->PlacingBlocksize = 1;
293  Tp->PlacingMask = ~((MyIntPosType)0);
294 
295  for(int i = 0; i < BITS_FOR_POSITIONS; i++)
296  {
297  if(Tp->PlacingBlocksize >= ref_size)
298  break;
299 
300  Tp->PlacingBlocksize <<= 1;
301  Tp->PlacingMask <<= 1;
302  }
303 
304  domain_printf("DOMAIN: We enlarge this to %g (%g times smaller than boxsize)\n", Tp->PlacingBlocksize * Tp->FacIntToCoord,
305  All.BoxSize / (Tp->PlacingBlocksize * Tp->FacIntToCoord));
306 }
307 #endif
308 
309 #ifdef LIGHTCONE_PARTICLES
310 template <>
312 {
313 }
314 #endif
315 
316 #include "../data/simparticles.h"
317 template class domain<simparticles>;
318 
319 #ifdef LIGHTCONE_PARTICLES
320 #include "../data/lcparticles.h"
321 template class domain<lcparticles>;
322 #endif
global_data_all_processes All
Definition: main.cc:40
Definition: domain.h:31
@ STANDARD
Definition: domain.h:23
uint32_t MyIntPosType
Definition: dtypes.h:35
int32_t MySignedIntPosType
Definition: dtypes.h:36
#define BITS_FOR_POSITIONS
Definition: dtypes.h:37
#define Terminate(...)
Definition: macros.h:19
MPI_Datatype MPI_MyIntPosType
Definition: mpi_vars.cc:24
MPI_Op MPI_MAX_MySignedIntPosType
Definition: mpi_vars.cc:29
MPI_Op MPI_MIN_MySignedIntPosType
Definition: mpi_vars.cc:28
expr pow(half base, half exp)
Definition: half.hpp:2803
double get_random_number(void)
Definition: system.cc:49