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 
44 void 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  MPI_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;
137  nop->Ti_Current = All.Ti_Current;
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 
148  nop->Ti_Current = All.Ti_Current;
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)
177  nop->drift_node(All.Ti_Current, Tp);
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 
254 void 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 
396  nop->cannot_be_opened_locally = 0;
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 
407  nop->Ti_Current = All.Ti_Current;
408 }
409 
410 void 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)
419  nop->drift_node(All.Ti_Current, Tp);
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 
459 void 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  MPI_Allgatherv(nodelist, nchanged, MPI_INT, tot_nodelist, recvcounts, recvoffset, MPI_INT, D->Communicator);
506  MPI_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)
518  nop->drift_node(All.Ti_Current, Tp);
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)
533  nop->drift_node(All.Ti_Current, Tp);
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 
569 void 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  MPI_Allgatherv(nodelist, nchanged, MPI_INT, tot_nodelist, recvcounts, recvoffset, MPI_INT, D->Communicator);
613  MPI_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)
625  nop->drift_node(All.Ti_Current, Tp);
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)
637  nop->drift_node(All.Ti_Current, Tp);
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)
717  nop->drift_node(All.Ti_Current, Tp);
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
int NTopnodes
Definition: domain.h:52
int * TaskOfLeaf
Definition: domain.h:63
int NTopleaves
Definition: domain.h:53
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)
void mpi_printf(const char *fmt,...)
Definition: setcomm.h:55
int ThisTask
Definition: setcomm.h:33
int NTask
Definition: setcomm.h:32
MPI_Comm Communicator
Definition: setcomm.h:31
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
#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:19
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