12#include "gadgetconfig.h"
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"
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"
37 double numnodes =
NumNodes, tot_numnodes;
38 MPI_Reduce(&numnodes, &tot_numnodes, 1, MPI_DOUBLE, MPI_SUM, 0,
D->Communicator);
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);
57 unsigned char not_empty;
59 leafnode_data *glob_leaf_node_data, *loc_leaf_node_data;
61 glob_leaf_node_data = (leafnode_data *)
Mem.mymalloc(
"glob_leaf_node_data",
D->NTopleaves *
sizeof(leafnode_data));
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);
69 for(
int task = 0; task <
D->NTask; task++)
72 for(
int n = 0; n <
D->NTopleaves; n++)
73 recvcounts[
D->TaskOfLeaf[n]]++;
75 for(
int task = 0; task < D->NTask; task++)
76 bytecounts[task] = recvcounts[task] *
sizeof(leafnode_data);
81 for(
int task = 1; task <
D->NTask; task++)
83 recvoffset[task] = recvoffset[task - 1] + recvcounts[task - 1];
84 byteoffset[task] = byteoffset[task - 1] + bytecounts[task - 1];
87 loc_leaf_node_data = (leafnode_data *)
Mem.mymalloc(
"loc_leaf_node_data", recvcounts[
D->ThisTask] *
sizeof(leafnode_data));
91 for(
int n = 0; n <
D->NTopleaves; n++)
93 if(
D->TaskOfLeaf[n] ==
D->ThisTask)
98 leafnode_data *locp = &loc_leaf_node_data[idx];
105 for(
int k = 0; k < 3; k++)
109 locp->vmin[k] = nop->
vmin[k];
110 locp->vmax[k] = nop->
vmax[k];
117 myMPI_Allgatherv(loc_leaf_node_data, bytecounts[
D->ThisTask], MPI_BYTE, glob_leaf_node_data, bytecounts, byteoffset, MPI_BYTE,
120 for(
int task = 0; task <
D->NTask; task++)
121 recvcounts[task] = 0;
123 for(
int n = 0; n <
D->NTopleaves; n++)
125 int task =
D->TaskOfLeaf[n];
126 if(task !=
D->ThisTask)
131 int idx = recvoffset[task] + recvcounts[task]++;
132 leafnode_data *globp = &glob_leaf_node_data[idx];
140 for(
int k = 0; k < 3; k++)
144 nop->
vmin[k] = globp->vmin[k];
145 nop->
vmax[k] = globp->vmax[k];
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);
162 for(
int i = 0; i <
Ninsert; i++)
187 if(left[0] > 0 && right[0] > left[0])
194 if(left[1] > 0 && right[1] > left[1])
201 if(left[2] > 0 && right[2] > left[2])
207 for(
int k = 0; k < 3; k++)
213 double pos[3], min[3], max[3];
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 "
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]);
228 for(
int k = 0; k < 3; k++)
278 unsigned char not_empty = 0;
282 for(
int k = 0; k < 3; k++)
284 center_offset_min[k] = (halflen - 1);
285 center_offset_max[k] = -halflen;
306 if(maxcsnd < Tp->get_Csnd(p))
309 if(maxhsml < Tp->SphP[p].get_Hsml())
312 if(maxDtHsml < Tp->get_DtHsml(p))
317 for(
int k = 0; k < 3; k++)
321 if(offset[k] < center_offset_min[k])
322 center_offset_min[k] = offset[k];
324 if(offset[k] > center_offset_max[k])
325 center_offset_max[k] = offset[k];
327 if(vmin[k] >
Tp->
P[p].
Vel[k])
328 vmin[k] =
Tp->
P[p].
Vel[k];
330 if(vmax[k] <
Tp->
P[p].
Vel[k])
331 vmax[k] =
Tp->
P[p].
Vel[k];
342 if(maxcsnd < noptr->MaxCsnd)
345 if(maxhsml < noptr->MaxHsml)
348 if(maxDtHsml < noptr->MaxDtHsml)
353 for(
int k = 0; k < 3; k++)
358 if(offset_min[k] < center_offset_min[k])
359 center_offset_min[k] = offset_min[k];
361 if(offset_max[k] > center_offset_max[k])
362 center_offset_max[k] = offset_max[k];
364 if(vmin[k] > noptr->
vmin[k])
365 vmin[k] = noptr->
vmin[k];
367 if(vmax[k] < noptr->
vmax[k])
368 vmax[k] = noptr->
vmax[k];
375 else if(p < MaxPart + MaxNodes + D->NTopleaves)
399 for(
int k = 0; k < 3; k++)
403 nop->
vmin[k] = vmin[k];
404 nop->
vmax[k] = vmax[k];
423 for(
int j = 0; j < 3; j++)
445 if(flag_changed[top_no] == 0)
447 flag_changed[top_no] = 1;
449 nodelist[*nchanged] = no;
450 *nchanged = *nchanged + 1;
459void ngbtree::finish_vounds_update(
int nchanged,
int *nodelist)
461 int i, j, no, task, tot_nchanged;
462 int *recvcounts, *recvoffset, *bytecounts, *byteoffset;
469 leafnode_data *glob_leaf_node_data, *loc_leaf_node_data;
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);
477 MPI_Allgather(&nchanged, 1, MPI_INT, recvcounts, 1, MPI_INT,
D->Communicator);
479 for(task = 0; task <
D->NTask; task++)
480 bytecounts[task] = recvcounts[task] *
sizeof(leafnode_data);
482 for(task = 1, recvoffset[0] = 0, byteoffset[0] = 0; task <
D->NTask; task++)
484 recvoffset[task] = recvoffset[task - 1] + recvcounts[task - 1];
485 byteoffset[task] = byteoffset[task - 1] + bytecounts[task - 1];
488 loc_leaf_node_data = (leafnode_data *)
Mem.mymalloc(
"loc_leaf_node_data", recvcounts[
D->ThisTask] *
sizeof(leafnode_data));
490 for(i = 0; i < nchanged; i++)
492 for(j = 0; j < 3; j++)
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];
499 for(task = 0, tot_nchanged = 0; task <
D->NTask; task++)
500 tot_nchanged += recvcounts[task];
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));
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,
511 for(i = 0; i < tot_nchanged; i++)
513 no = tot_nodelist[i];
520 for(j = 0; j < 3; j++)
522 nop->
vmin[j] = glob_leaf_node_data[i].vmin[j];
523 nop->
vmax[j] = glob_leaf_node_data[i].vmax[j];
535 int flag_changed = 0;
537 for(j = 0; j < 3; j++)
539 if(nop->
vmin[j] > glob_leaf_node_data[i].vmin[j])
541 nop->
vmin[j] = glob_leaf_node_data[i].vmin[j];
545 if(nop->
vmax[j] < glob_leaf_node_data[i].vmax[j])
547 nop->
vmax[j] = glob_leaf_node_data[i].vmax[j];
552 if(flag_changed == 0)
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);
569void ngbtree::finish_maxhsml_update(
int nchanged,
int *nodelist)
571 int i, no, task, tot_nchanged;
572 int *recvcounts, *recvoffset, *bytecounts, *byteoffset;
579 leafnode_data *glob_leaf_node_data, *loc_leaf_node_data;
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);
587 MPI_Allgather(&nchanged, 1, MPI_INT, recvcounts, 1, MPI_INT,
D->Communicator);
589 for(task = 0; task <
D->NTask; task++)
590 bytecounts[task] = recvcounts[task] *
sizeof(leafnode_data);
592 for(task = 1, recvoffset[0] = 0, byteoffset[0] = 0; task <
D->NTask; task++)
594 recvoffset[task] = recvoffset[task - 1] + recvcounts[task - 1];
595 byteoffset[task] = byteoffset[task - 1] + bytecounts[task - 1];
598 loc_leaf_node_data = (leafnode_data *)
Mem.mymalloc(
"loc_leaf_node_data", recvcounts[
D->ThisTask] *
sizeof(leafnode_data));
600 for(i = 0; i < nchanged; i++)
606 for(task = 0, tot_nchanged = 0; task <
D->NTask; task++)
607 tot_nchanged += recvcounts[task];
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));
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,
618 for(i = 0; i < tot_nchanged; i++)
620 no = tot_nodelist[i];
627 nop->
MaxHsml = glob_leaf_node_data[i].MaxHsml;
628 nop->
MaxDtHsml = glob_leaf_node_data[i].MaxDtHsml;
639 if(glob_leaf_node_data[i].MaxHsml <= nop->MaxHsml && glob_leaf_node_data[i].MaxDtHsml <= nop->MaxDtHsml)
643 if(glob_leaf_node_data[i].MaxHsml > nop->
MaxHsml)
644 nop->
MaxHsml = glob_leaf_node_data[i].MaxHsml;
646 if(glob_leaf_node_data[i].MaxDtHsml > nop->
MaxDtHsml)
647 nop->
MaxDtHsml = glob_leaf_node_data[i].MaxDtHsml;
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);
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));
689 finish_vounds_update(nchanged, nodelist);
691 Mem.myfree(flag_changed);
692 Mem.myfree(nodelist);
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));
734 if(top_no < 0 || top_no >=
D->NTopnodes)
735 Terminate(
"top_no=%d D->NTopleaves=%d\n", top_no,
D->NTopnodes);
737 if(flag_changed[top_no] == 0)
739 flag_changed[top_no] = 1;
741 nodelist[nchanged++] = no;
751 finish_maxhsml_update(nchanged, nodelist);
753 Mem.myfree(flag_changed);
754 Mem.myfree(nodelist);
global_data_all_processes All
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
MyFloat get_DtHsml(int i)
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.
TimeBinData TimeBinsHydro
int TreeSharedMem_ThisTask
domain< simparticles > * D
ngbnode * get_nodep(int no)
#define LEVEL_ALWAYS_OPEN
int32_t MySignedIntPosType
#define BITS_FOR_POSITIONS
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.
#define TIMER_STOP(counter)
Stops the timer counter.
int FirstInTimeBin[TIMEBINS]
std::atomic< unsigned char > cannot_be_opened_locally
vector< MyIntPosType > center
int HighestSynchronizedTimeBin
std::atomic< integertime > Ti_Current
MySignedIntPosType center_offset_max[3]
MySignedIntPosType center_offset_min[3]
void drift_node(integertime time1, simparticles *Sp)
integertime get_Ti_Current(void)
unsigned char getType(void)
#define TREE_MODE_TOPLEVEL