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
31using namespace std;
32
42template <>
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
195template <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
210template <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
310template <>
312{
313}
314#endif
315
316#include "../data/simparticles.h"
317template class domain<simparticles>;
318
319#ifdef LIGHTCONE_PARTICLES
320#include "../data/lcparticles.h"
321template 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:15
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
STL namespace.
double get_random_number(void)
Definition: system.cc:49