GADGET-4
ngbtree_build.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 <math.h>
15#include <mpi.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "../data/allvars.h"
21#include "../data/dtypes.h"
22#include "../data/mymalloc.h"
23#include "../domain/domain.h"
24#include "../gravtree/gravtree.h"
25#include "../io/io.h"
26#include "../logs/logs.h"
27#include "../logs/timer.h"
28#include "../main/simulation.h"
29#include "../ngbtree/ngbtree.h"
30#include "../sort/peano.h"
31#include "../system/system.h"
32#include "../time_integration/driftfac.h"
33#include "../time_integration/timestep.h"
34
36{
37 double numnodes = NumNodes, tot_numnodes;
38 MPI_Reduce(&numnodes, &tot_numnodes, 1, MPI_DOUBLE, MPI_SUM, 0, D->Communicator);
39
40 D->mpi_printf("NGBTREE: Ngb-tree construction done. took %g sec <numnodes>=%g NTopnodes=%d NTopleaves=%d\n", Buildtime,
41 tot_numnodes / D->NTask, D->NTopnodes, D->NTopleaves);
42}
43
44void ngbtree::fill_in_export_points(ngbpoint_data *exp_point, int i, int no) { Terminate("we don't expect to get here"); }
45
47{
48 struct leafnode_data
49 {
50 MySignedIntPosType center_offset_min[3];
51 MySignedIntPosType center_offset_max[3];
52 MyNgbTreeFloat vmin[3];
53 MyNgbTreeFloat vmax[3];
54 MyNgbTreeFloat MaxCsnd;
55 MyNgbTreeFloat MaxHsml;
56 MyNgbTreeFloat MaxDtHsml;
57 unsigned char not_empty;
58 };
59 leafnode_data *glob_leaf_node_data, *loc_leaf_node_data;
60
61 glob_leaf_node_data = (leafnode_data *)Mem.mymalloc("glob_leaf_node_data", D->NTopleaves * sizeof(leafnode_data));
62
63 /* share the pseudo-particle data accross CPUs */
64 int *recvcounts = (int *)Mem.mymalloc("recvcounts", sizeof(int) * D->NTask);
65 int *recvoffset = (int *)Mem.mymalloc("recvoffset", sizeof(int) * D->NTask);
66 int *bytecounts = (int *)Mem.mymalloc("bytecounts", sizeof(int) * D->NTask);
67 int *byteoffset = (int *)Mem.mymalloc("byteoffset", sizeof(int) * D->NTask);
68
69 for(int task = 0; task < D->NTask; task++)
70 recvcounts[task] = 0;
71
72 for(int n = 0; n < D->NTopleaves; n++)
73 recvcounts[D->TaskOfLeaf[n]]++;
74
75 for(int task = 0; task < D->NTask; task++)
76 bytecounts[task] = recvcounts[task] * sizeof(leafnode_data);
77
78 recvoffset[0] = 0;
79 byteoffset[0] = 0;
80
81 for(int task = 1; task < D->NTask; task++)
82 {
83 recvoffset[task] = recvoffset[task - 1] + recvcounts[task - 1];
84 byteoffset[task] = byteoffset[task - 1] + bytecounts[task - 1];
85 }
86
87 loc_leaf_node_data = (leafnode_data *)Mem.mymalloc("loc_leaf_node_data", recvcounts[D->ThisTask] * sizeof(leafnode_data));
88
89 int idx = 0;
90
91 for(int n = 0; n < D->NTopleaves; n++)
92 {
93 if(D->TaskOfLeaf[n] == D->ThisTask)
94 {
95 int no = NodeIndex[n];
96 ngbnode *nop = &TopNodes[no];
97
98 leafnode_data *locp = &loc_leaf_node_data[idx];
99
100 locp->MaxCsnd = nop->MaxCsnd;
101 locp->MaxHsml = nop->MaxHsml;
102 locp->MaxDtHsml = nop->MaxDtHsml;
103 locp->not_empty = nop->not_empty;
104
105 for(int k = 0; k < 3; k++)
106 {
107 locp->center_offset_min[k] = nop->center_offset_min[k];
108 locp->center_offset_max[k] = nop->center_offset_max[k];
109 locp->vmin[k] = nop->vmin[k];
110 locp->vmax[k] = nop->vmax[k];
111 }
112
113 idx++;
114 }
115 }
116
117 myMPI_Allgatherv(loc_leaf_node_data, bytecounts[D->ThisTask], MPI_BYTE, glob_leaf_node_data, bytecounts, byteoffset, MPI_BYTE,
118 D->Communicator);
119
120 for(int task = 0; task < D->NTask; task++)
121 recvcounts[task] = 0;
122
123 for(int n = 0; n < D->NTopleaves; n++)
124 {
125 int task = D->TaskOfLeaf[n];
126 if(task != D->ThisTask)
127 {
128 int no = NodeIndex[n];
129 ngbnode *nop = &TopNodes[no];
130
131 int idx = recvoffset[task] + recvcounts[task]++;
132 leafnode_data *globp = &glob_leaf_node_data[idx];
133
134 nop->MaxCsnd = globp->MaxCsnd;
135 nop->MaxHsml = globp->MaxHsml;
136 nop->MaxDtHsml = globp->MaxDtHsml;
138 nop->not_empty = globp->not_empty;
139
140 for(int k = 0; k < 3; k++)
141 {
142 nop->center_offset_min[k] = globp->center_offset_min[k];
143 nop->center_offset_max[k] = globp->center_offset_max[k];
144 nop->vmin[k] = globp->vmin[k];
145 nop->vmax[k] = globp->vmax[k];
146 }
147
149 }
150 }
151
152 Mem.myfree(loc_leaf_node_data);
153 Mem.myfree(byteoffset);
154 Mem.myfree(bytecounts);
155 Mem.myfree(recvoffset);
156 Mem.myfree(recvcounts);
157 Mem.myfree(glob_leaf_node_data);
158}
159
161{
162 for(int i = 0; i < Ninsert; i++)
163 {
164 if(Tp->P[i].get_Ti_Current() != All.Ti_Current)
165 Tp->drift_particle(&Tp->P[i], &Tp->SphP[i], All.Ti_Current); // this function avoids race conditions
166
167 int no = Father[i];
168
169 while(no >= 0)
170 {
171 ngbnode *nop = get_nodep(no);
172
173 if(nop->level <= LEVEL_ALWAYS_OPEN) // don't test the root node
174 break;
175
176 if(nop->Ti_Current != All.Ti_Current)
178
179 int errflag = 0;
180
181 MyIntPosType left[3], right[3];
182
183 left[0] = Tp->nearest_image_intpos_to_intpos_X(nop->center_offset_min[0] + nop->center[0], Tp->P[i].IntPos[0]);
184 right[0] = Tp->nearest_image_intpos_to_intpos_X(nop->center_offset_max[0] + nop->center[0], Tp->P[i].IntPos[0]);
185
186 /* check whether we can stop walking along this branch */
187 if(left[0] > 0 && right[0] > left[0])
188 errflag |= 1;
189
190 left[1] = Tp->nearest_image_intpos_to_intpos_Y(nop->center_offset_min[1] + nop->center[1], Tp->P[i].IntPos[1]);
191 right[1] = Tp->nearest_image_intpos_to_intpos_Y(nop->center_offset_max[1] + nop->center[1], Tp->P[i].IntPos[1]);
192
193 /* check whether we can stop walking along this branch */
194 if(left[1] > 0 && right[1] > left[1])
195 errflag |= 2;
196
197 left[2] = Tp->nearest_image_intpos_to_intpos_Z(nop->center_offset_min[2] + nop->center[2], Tp->P[i].IntPos[2]);
198 right[2] = Tp->nearest_image_intpos_to_intpos_Z(nop->center_offset_max[2] + nop->center[2], Tp->P[i].IntPos[2]);
199
200 /* check whether we can stop walking along this branch */
201 if(left[2] > 0 && right[2] > left[2])
202 errflag |= 4;
203
204 if(errflag)
205 {
206 MyIntPosType range_min[3], range_max[3];
207 for(int k = 0; k < 3; k++)
208 {
209 range_min[k] = nop->center_offset_min[k] + nop->center[k];
210 range_max[k] = nop->center_offset_max[k] + nop->center[k];
211 }
212
213 double pos[3], min[3], max[3];
214
215 Tp->intpos_to_pos(Tp->P[i].IntPos, pos);
216 Tp->intpos_to_pos(range_min, min);
217 Tp->intpos_to_pos(range_max, max);
218
219 Terminate(
220 "level=%d errflag=%d pos=%g %g %g vel=%g %g %g min=%g %g %g max=%g %g %g vmin=%g %g %g vmax=%g %g %g "
221 "\n",
222 nop->level, errflag, pos[0], pos[1], pos[2], Tp->P[i].Vel[0], Tp->P[i].Vel[1], Tp->P[i].Vel[2], min[0], min[1],
223 min[2], max[0], max[1], max[2], nop->vmin[0], nop->vmin[1], nop->vmin[2], nop->vmax[0], nop->vmax[1], nop->vmax[2]);
224 }
225
226 errflag = 0;
227
228 for(int k = 0; k < 3; k++)
229 {
230 if(nop->vmin[k] > Tp->P[i].Vel[k])
231 errflag = 1;
232
233 if(nop->vmax[k] < Tp->P[i].Vel[k])
234 errflag = 1;
235 }
236
237 if(errflag)
238 {
239 Terminate("vel=%g %g %g min=%g %g %g max=%g %g %g\n", Tp->P[i].Vel[0], Tp->P[i].Vel[1], Tp->P[i].Vel[2],
240 nop->vmin[0], nop->vmin[1], nop->vmin[2], nop->vmax[0], nop->vmax[1], nop->vmax[2]);
241 }
242
243 no = nop->father;
244 }
245 }
246}
247
254void ngbtree::update_node_recursive(int no, int sib, int mode)
255{
256 if(!(no >= MaxPart && no < MaxPart + MaxNodes)) /* are we an internal node? */
257 Terminate("no internal node\n");
258
259 ngbnode *nop = get_nodep(no);
260
261 if(mode == TREE_MODE_TOPLEVEL)
262 {
263 int p = nop->nextnode;
264
265 /* if the next node is not a top-level node, we have reached a leaf node, and we need to do nothing */
266 if(p < MaxPart || p >= FirstNonTopLevelNode)
267 return;
268 }
269
270 MyNgbTreeFloat maxcsnd = 0;
271 MyNgbTreeFloat maxhsml = 0;
272 MyNgbTreeFloat maxDtHsml = 0;
273
274 MySignedIntPosType center_offset_min[3];
275 MySignedIntPosType center_offset_max[3];
276 MyNgbTreeFloat vmin[3], vmax[3];
277
278 unsigned char not_empty = 0;
279
280 MyIntPosType halflen = ((MyIntPosType)1) << ((BITS_FOR_POSITIONS - 1) - nop->level);
281
282 for(int k = 0; k < 3; k++)
283 {
284 center_offset_min[k] = (halflen - 1);
285 center_offset_max[k] = -halflen;
286
287 vmin[k] = MAX_FLOAT_NUMBER;
288 vmax[k] = -MAX_FLOAT_NUMBER;
289 }
290
291 int p = nop->nextnode;
292
293 while(p != nop->sibling)
294 {
295 if(p >= 0)
296 {
297 if(p >= MaxPart && p < MaxPart + MaxNodes) /* we have an internal node */
298 {
299 int nextsib = get_nodep(p)->sibling;
300
301 update_node_recursive(p, nextsib, mode);
302 }
303
304 if(p < MaxPart) /* a particle */
305 {
306 if(maxcsnd < Tp->get_Csnd(p))
307 maxcsnd = Tp->get_Csnd(p);
308
309 if(maxhsml < Tp->SphP[p].get_Hsml())
310 maxhsml = Tp->SphP[p].get_Hsml();
311
312 if(maxDtHsml < Tp->get_DtHsml(p))
313 maxDtHsml = Tp->get_DtHsml(p);
314
315 MySignedIntPosType offset[3];
316
317 for(int k = 0; k < 3; k++)
318 {
319 offset[k] = Tp->P[p].IntPos[k] - nop->center[k];
320
321 if(offset[k] < center_offset_min[k])
322 center_offset_min[k] = offset[k];
323
324 if(offset[k] > center_offset_max[k])
325 center_offset_max[k] = offset[k];
326
327 if(vmin[k] > Tp->P[p].Vel[k])
328 vmin[k] = Tp->P[p].Vel[k];
329
330 if(vmax[k] < Tp->P[p].Vel[k])
331 vmax[k] = Tp->P[p].Vel[k];
332 }
333
334 not_empty = 1;
335
336 p = Nextnode[p];
337 }
338 else if(p < MaxPart + MaxNodes) /* an internal node */
339 {
340 ngbnode *noptr = get_nodep(p);
341
342 if(maxcsnd < noptr->MaxCsnd)
343 maxcsnd = noptr->MaxCsnd;
344
345 if(maxhsml < noptr->MaxHsml)
346 maxhsml = noptr->MaxHsml;
347
348 if(maxDtHsml < noptr->MaxDtHsml)
349 maxDtHsml = noptr->MaxDtHsml;
350
351 MySignedIntPosType offset_min[3], offset_max[3];
352
353 for(int k = 0; k < 3; k++)
354 {
355 offset_min[k] = noptr->center_offset_min[k] + (MySignedIntPosType)(noptr->center[k] - nop->center[k]);
356 offset_max[k] = noptr->center_offset_max[k] + (MySignedIntPosType)(noptr->center[k] - nop->center[k]);
357
358 if(offset_min[k] < center_offset_min[k])
359 center_offset_min[k] = offset_min[k];
360
361 if(offset_max[k] > center_offset_max[k])
362 center_offset_max[k] = offset_max[k];
363
364 if(vmin[k] > noptr->vmin[k])
365 vmin[k] = noptr->vmin[k];
366
367 if(vmax[k] < noptr->vmax[k])
368 vmax[k] = noptr->vmax[k];
369 }
370
371 not_empty |= noptr->not_empty;
372
373 p = noptr->sibling;
374 }
375 else if(p < MaxPart + MaxNodes + D->NTopleaves) /* a pseudo particle */
376 {
377 /* we are processing a local leaf-node which does not have any particles.
378 * can continue to the next element, which should end the work.
379 */
380 p = Nextnode[p - MaxNodes];
381 }
382 else
383 {
384 /* an imported point */
385
386 Terminate("Ups!");
387 p = Nextnode[p - MaxNodes];
388 }
389 }
390 }
391
392 nop->MaxCsnd = maxcsnd;
393 nop->MaxHsml = maxhsml;
394 nop->MaxDtHsml = maxDtHsml;
395
397 nop->not_empty = not_empty;
398
399 for(int k = 0; k < 3; k++)
400 {
401 nop->center_offset_min[k] = center_offset_min[k];
402 nop->center_offset_max[k] = center_offset_max[k];
403 nop->vmin[k] = vmin[k];
404 nop->vmax[k] = vmax[k];
405 }
406
408}
409
410void ngbtree::update_vbounds(int i, int *nchanged, int *nodelist, char *flag_changed)
411{
412 int no = Father[i];
413
414 while(no >= 0)
415 {
416 ngbnode *nop = get_nodep(no);
417
418 if(nop->Ti_Current != All.Ti_Current)
420
421 int has_changed = 0;
422
423 for(int j = 0; j < 3; j++)
424 {
425 if(nop->vmin[j] > Tp->P[i].Vel[j])
426 {
427 nop->vmin[j] = Tp->P[i].Vel[j];
428 has_changed = 1;
429 }
430
431 if(nop->vmax[j] < Tp->P[i].Vel[j])
432 {
433 nop->vmax[j] = Tp->P[i].Vel[j];
434 has_changed = 1;
435 }
436 }
437
438 if(has_changed == 0)
439 break;
440
441 if(no < FirstNonTopLevelNode) /* top-level tree-node reached */
442 {
443 int top_no = no - MaxPart;
444
445 if(flag_changed[top_no] == 0)
446 {
447 flag_changed[top_no] = 1;
448
449 nodelist[*nchanged] = no;
450 *nchanged = *nchanged + 1;
451 }
452 break;
453 }
454
455 no = nop->father;
456 }
457}
458
459void ngbtree::finish_vounds_update(int nchanged, int *nodelist)
460{
461 int i, j, no, task, tot_nchanged;
462 int *recvcounts, *recvoffset, *bytecounts, *byteoffset;
463 int *tot_nodelist;
464 struct leafnode_data
465 {
466 MyNgbTreeFloat vmin[3];
467 MyNgbTreeFloat vmax[3];
468 };
469 leafnode_data *glob_leaf_node_data, *loc_leaf_node_data;
470
471 /* share the pseudo-particle data accross CPUs */
472 recvcounts = (int *)Mem.mymalloc("recvcounts", sizeof(int) * D->NTask);
473 recvoffset = (int *)Mem.mymalloc("recvoffset", sizeof(int) * D->NTask);
474 bytecounts = (int *)Mem.mymalloc("bytecounts", sizeof(int) * D->NTask);
475 byteoffset = (int *)Mem.mymalloc("byteoffset", sizeof(int) * D->NTask);
476
477 MPI_Allgather(&nchanged, 1, MPI_INT, recvcounts, 1, MPI_INT, D->Communicator);
478
479 for(task = 0; task < D->NTask; task++)
480 bytecounts[task] = recvcounts[task] * sizeof(leafnode_data);
481
482 for(task = 1, recvoffset[0] = 0, byteoffset[0] = 0; task < D->NTask; task++)
483 {
484 recvoffset[task] = recvoffset[task - 1] + recvcounts[task - 1];
485 byteoffset[task] = byteoffset[task - 1] + bytecounts[task - 1];
486 }
487
488 loc_leaf_node_data = (leafnode_data *)Mem.mymalloc("loc_leaf_node_data", recvcounts[D->ThisTask] * sizeof(leafnode_data));
489
490 for(i = 0; i < nchanged; i++)
491 {
492 for(j = 0; j < 3; j++)
493 {
494 loc_leaf_node_data[i].vmin[j] = get_nodep(nodelist[i])->vmin[j];
495 loc_leaf_node_data[i].vmax[j] = get_nodep(nodelist[i])->vmax[j];
496 }
497 }
498
499 for(task = 0, tot_nchanged = 0; task < D->NTask; task++)
500 tot_nchanged += recvcounts[task];
501
502 tot_nodelist = (int *)Mem.mymalloc("tot_nodelist", tot_nchanged * sizeof(int));
503 glob_leaf_node_data = (leafnode_data *)Mem.mymalloc("glob_leaf_node_data", tot_nchanged * sizeof(leafnode_data));
504
505 myMPI_Allgatherv(nodelist, nchanged, MPI_INT, tot_nodelist, recvcounts, recvoffset, MPI_INT, D->Communicator);
506 myMPI_Allgatherv(loc_leaf_node_data, bytecounts[D->ThisTask], MPI_BYTE, glob_leaf_node_data, bytecounts, byteoffset, MPI_BYTE,
507 D->Communicator);
508
509 if(TreeSharedMem_ThisTask == 0) /* only one of the shared memory threads needs to update the toplevel tree */
510 {
511 for(i = 0; i < tot_nchanged; i++)
512 {
513 no = tot_nodelist[i];
514
515 ngbnode *nop = get_nodep(no);
516
517 if(nop->Ti_Current != All.Ti_Current)
519
520 for(j = 0; j < 3; j++)
521 {
522 nop->vmin[j] = glob_leaf_node_data[i].vmin[j];
523 nop->vmax[j] = glob_leaf_node_data[i].vmax[j];
524 }
525
526 no = nop->father;
527
528 while(no >= 0)
529 {
530 ngbnode *nop = get_nodep(no);
531
532 if(nop->Ti_Current != All.Ti_Current)
534
535 int flag_changed = 0;
536
537 for(j = 0; j < 3; j++)
538 {
539 if(nop->vmin[j] > glob_leaf_node_data[i].vmin[j])
540 {
541 nop->vmin[j] = glob_leaf_node_data[i].vmin[j];
542 flag_changed = 1;
543 }
544
545 if(nop->vmax[j] < glob_leaf_node_data[i].vmax[j])
546 {
547 nop->vmax[j] = glob_leaf_node_data[i].vmax[j];
548 flag_changed = 1;
549 }
550 }
551
552 if(flag_changed == 0)
553 break;
554
555 no = nop->father;
556 }
557 }
558 }
559
560 Mem.myfree(glob_leaf_node_data);
561 Mem.myfree(tot_nodelist);
562 Mem.myfree(loc_leaf_node_data);
563 Mem.myfree(byteoffset);
564 Mem.myfree(bytecounts);
565 Mem.myfree(recvoffset);
566 Mem.myfree(recvcounts);
567}
568
569void ngbtree::finish_maxhsml_update(int nchanged, int *nodelist)
570{
571 int i, no, task, tot_nchanged;
572 int *recvcounts, *recvoffset, *bytecounts, *byteoffset;
573 int *tot_nodelist;
574 struct leafnode_data
575 {
576 MyNgbTreeFloat MaxHsml;
577 MyNgbTreeFloat MaxDtHsml;
578 };
579 leafnode_data *glob_leaf_node_data, *loc_leaf_node_data;
580
581 /* share the pseudo-particle data accross CPUs */
582 recvcounts = (int *)Mem.mymalloc("recvcounts", sizeof(int) * D->NTask);
583 recvoffset = (int *)Mem.mymalloc("recvoffset", sizeof(int) * D->NTask);
584 bytecounts = (int *)Mem.mymalloc("bytecounts", sizeof(int) * D->NTask);
585 byteoffset = (int *)Mem.mymalloc("byteoffset", sizeof(int) * D->NTask);
586
587 MPI_Allgather(&nchanged, 1, MPI_INT, recvcounts, 1, MPI_INT, D->Communicator);
588
589 for(task = 0; task < D->NTask; task++)
590 bytecounts[task] = recvcounts[task] * sizeof(leafnode_data);
591
592 for(task = 1, recvoffset[0] = 0, byteoffset[0] = 0; task < D->NTask; task++)
593 {
594 recvoffset[task] = recvoffset[task - 1] + recvcounts[task - 1];
595 byteoffset[task] = byteoffset[task - 1] + bytecounts[task - 1];
596 }
597
598 loc_leaf_node_data = (leafnode_data *)Mem.mymalloc("loc_leaf_node_data", recvcounts[D->ThisTask] * sizeof(leafnode_data));
599
600 for(i = 0; i < nchanged; i++)
601 {
602 loc_leaf_node_data[i].MaxHsml = get_nodep(nodelist[i])->MaxHsml;
603 loc_leaf_node_data[i].MaxDtHsml = get_nodep(nodelist[i])->MaxDtHsml;
604 }
605
606 for(task = 0, tot_nchanged = 0; task < D->NTask; task++)
607 tot_nchanged += recvcounts[task];
608
609 tot_nodelist = (int *)Mem.mymalloc("tot_nodelist", tot_nchanged * sizeof(int));
610 glob_leaf_node_data = (leafnode_data *)Mem.mymalloc("glob_leaf_node_data", tot_nchanged * sizeof(leafnode_data));
611
612 myMPI_Allgatherv(nodelist, nchanged, MPI_INT, tot_nodelist, recvcounts, recvoffset, MPI_INT, D->Communicator);
613 myMPI_Allgatherv(loc_leaf_node_data, bytecounts[D->ThisTask], MPI_BYTE, glob_leaf_node_data, bytecounts, byteoffset, MPI_BYTE,
614 D->Communicator);
615
616 if(TreeSharedMem_ThisTask == 0) /* only one of the shared memory threads needs to update the toplevel tree */
617 {
618 for(i = 0; i < tot_nchanged; i++)
619 {
620 no = tot_nodelist[i];
621
622 ngbnode *nop = get_nodep(no);
623
624 if(nop->Ti_Current != All.Ti_Current)
626
627 nop->MaxHsml = glob_leaf_node_data[i].MaxHsml;
628 nop->MaxDtHsml = glob_leaf_node_data[i].MaxDtHsml;
629
630 no = nop->father;
631
632 while(no >= 0)
633 {
634 ngbnode *nop = get_nodep(no);
635
636 if(nop->Ti_Current != All.Ti_Current)
638
639 if(glob_leaf_node_data[i].MaxHsml <= nop->MaxHsml && glob_leaf_node_data[i].MaxDtHsml <= nop->MaxDtHsml)
640 break;
641 else
642 {
643 if(glob_leaf_node_data[i].MaxHsml > nop->MaxHsml)
644 nop->MaxHsml = glob_leaf_node_data[i].MaxHsml;
645
646 if(glob_leaf_node_data[i].MaxDtHsml > nop->MaxDtHsml)
647 nop->MaxDtHsml = glob_leaf_node_data[i].MaxDtHsml;
648 }
649
650 no = nop->father;
651 }
652 }
653 }
654
655 Mem.myfree(glob_leaf_node_data);
656 Mem.myfree(tot_nodelist);
657 Mem.myfree(loc_leaf_node_data);
658 Mem.myfree(byteoffset);
659 Mem.myfree(bytecounts);
660 Mem.myfree(recvoffset);
661 Mem.myfree(recvcounts);
662}
663
665{
666 TIMER_START(CPU_NGBTREEUPDATEVEL);
667
668 int nchanged = 0;
669 int *nodelist = (int *)Mem.mymalloc("nodelist", D->NTopleaves * sizeof(int));
670 char *flag_changed = (char *)Mem.mymalloc_clear("flag_changed", D->NTopnodes * sizeof(char));
671
672 for(int i = 0; i < Tp->TimeBinsHydro.NActiveParticles; i++)
673 {
674 int target = Tp->TimeBinsHydro.ActiveParticleList[i];
675
676 if(Tp->P[target].getType() == 0)
677 update_vbounds(target, &nchanged, nodelist, flag_changed);
678 }
679
680 for(int timebin = All.HighestSynchronizedTimeBin; timebin >= 0; timebin--)
681 {
682 for(int target = Tp->TimeBinsHydro.FirstInTimeBin[timebin]; target >= 0; target = Tp->TimeBinsHydro.NextInTimeBin[target])
683 if(Tp->P[target].getType() == 0)
684 {
685 update_vbounds(target, &nchanged, nodelist, flag_changed);
686 }
687 }
688
689 finish_vounds_update(nchanged, nodelist);
690
691 Mem.myfree(flag_changed);
692 Mem.myfree(nodelist);
693
694 TIMER_STOP(CPU_NGBTREEUPDATEVEL);
695}
696
698{
699 TIMER_START(CPU_NGBTREEUPDATEMAXHSML);
700
701 int nchanged = 0;
702 int *nodelist = (int *)Mem.mymalloc("nodelist", D->NTopleaves * sizeof(int));
703 char *flag_changed = (char *)Mem.mymalloc_clear("flag_changed", D->NTopnodes * sizeof(char));
704
705 for(int i = 0; i < Tp->TimeBinsHydro.NActiveParticles; i++)
706 {
707 int target = Tp->TimeBinsHydro.ActiveParticleList[i];
708 if(Tp->P[target].getType() == 0)
709 {
710 int no = Father[target];
711
712 while(no >= 0)
713 {
714 ngbnode *nop = get_nodep(no);
715
716 if(nop->Ti_Current != All.Ti_Current)
718
719 if(Tp->SphP[target].Hsml <= nop->MaxHsml && Tp->SphP[target].DtHsml <= nop->MaxDtHsml)
720 break;
721 else
722 {
723 if(Tp->SphP[target].Hsml > nop->MaxHsml)
724 nop->MaxHsml = Tp->SphP[target].Hsml;
725
726 if(Tp->SphP[target].DtHsml > nop->MaxDtHsml)
727 nop->MaxDtHsml = Tp->SphP[target].DtHsml;
728 }
729
730 if(no < FirstNonTopLevelNode) /* top-level tree-node reached */
731 {
732 int top_no = no - MaxPart;
733
734 if(top_no < 0 || top_no >= D->NTopnodes)
735 Terminate("top_no=%d D->NTopleaves=%d\n", top_no, D->NTopnodes);
736
737 if(flag_changed[top_no] == 0)
738 {
739 flag_changed[top_no] = 1;
740
741 nodelist[nchanged++] = no;
742 }
743 break;
744 }
745
746 no = nop->father;
747 }
748 }
749 }
750
751 finish_maxhsml_update(nchanged, nodelist);
752
753 Mem.myfree(flag_changed);
754 Mem.myfree(nodelist);
755
756 TIMER_STOP(CPU_NGBTREEUPDATEMAXHSML);
757}
global_data_all_processes All
Definition: main.cc:40
MyIntPosType nearest_image_intpos_to_intpos_Y(const MyIntPosType a, const MyIntPosType b)
MyIntPosType nearest_image_intpos_to_intpos_Z(const MyIntPosType a, const MyIntPosType b)
void intpos_to_pos(MyIntPosType *intpos, T *posdiff)
MyIntPosType nearest_image_intpos_to_intpos_X(const MyIntPosType a, const MyIntPosType b)
void exchange_topleafdata(void) override
void update_vbounds(int i, int *nchanged, int *nodelist, char *flag_changed)
void update_node_recursive(int no, int sib, int mode) override
void update_maxhsml(void)
void update_velocities(void)
void fill_in_export_points(ngbpoint_data *exp_point, int i, int no) override
void report_log_message(void) override
void check_bounds(void)
MyFloat get_DtHsml(int i)
Definition: simparticles.h:231
int drift_particle(particle_data *P, sph_particle_data *SphP, integertime time1, bool ignore_light_cone=false)
This function drifts a particle i to time1.
Definition: predict.cc:313
MyFloat get_Csnd(int i)
Definition: simparticles.h:233
particle_data * P
Definition: simparticles.h:54
sph_particle_data * SphP
Definition: simparticles.h:59
TimeBinData TimeBinsHydro
Definition: simparticles.h:204
#define MAX_FLOAT_NUMBER
Definition: constants.h:79
uint32_t MyIntPosType
Definition: dtypes.h:35
#define LEVEL_ALWAYS_OPEN
Definition: dtypes.h:383
float MyNgbTreeFloat
Definition: dtypes.h:88
int32_t MySignedIntPosType
Definition: dtypes.h:36
#define BITS_FOR_POSITIONS
Definition: dtypes.h:37
int myMPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcount, int *displs, MPI_Datatype recvtype, MPI_Comm comm)
#define TIMER_START(counter)
Starts the timer counter.
Definition: logs.h:197
#define TIMER_STOP(counter)
Stops the timer counter.
Definition: logs.h:220
#define Terminate(...)
Definition: macros.h:15
memory Mem
Definition: main.cc:44
int NActiveParticles
Definition: timestep.h:18
int * ActiveParticleList
Definition: timestep.h:20
int FirstInTimeBin[TIMEBINS]
Definition: timestep.h:23
int * NextInTimeBin
Definition: timestep.h:25
unsigned char level
Definition: tree.h:64
std::atomic< unsigned char > cannot_be_opened_locally
Definition: tree.h:70
int father
Definition: tree.h:59
unsigned char not_empty
Definition: tree.h:73
int nextnode
Definition: tree.h:57
vector< MyIntPosType > center
Definition: tree.h:51
int sibling
Definition: tree.h:53
integertime Ti_Current
Definition: allvars.h:188
std::atomic< integertime > Ti_Current
Definition: ngbtree.h:56
MyNgbTreeFloat vmax[3]
Definition: ngbtree.h:51
MyNgbTreeFloat MaxHsml
Definition: ngbtree.h:52
MySignedIntPosType center_offset_max[3]
Definition: ngbtree.h:48
MyNgbTreeFloat MaxDtHsml
Definition: ngbtree.h:53
MySignedIntPosType center_offset_min[3]
Definition: ngbtree.h:47
void drift_node(integertime time1, simparticles *Sp)
Definition: ngbtree.h:58
MyNgbTreeFloat vmin[3]
Definition: ngbtree.h:50
MyNgbTreeFloat MaxCsnd
Definition: ngbtree.h:54
integertime get_Ti_Current(void)
MyFloat Vel[3]
Definition: particle_data.h:54
unsigned char getType(void)
MyIntPosType IntPos[3]
Definition: particle_data.h:53
#define TREE_MODE_TOPLEVEL
Definition: tree.h:20