12#include "gadgetconfig.h"
22#include "../data/allvars.h"
23#include "../data/dtypes.h"
24#include "../data/intposconvert.h"
25#include "../data/mymalloc.h"
26#include "../domain/domain.h"
27#include "../fmm/fmm.h"
28#include "../gravity/ewald.h"
29#include "../gravtree/gravtree.h"
30#include "../logs/logs.h"
31#include "../logs/timer.h"
32#include "../main/simulation.h"
33#include "../mpi_utils/mpi_utils.h"
34#include "../mpi_utils/shared_mem_handler.h"
36#include "../sort/cxxsort.h"
37#include "../system/system.h"
38#include "../time_integration/timestep.h"
40void fmm::fmm_force_passdown(
int no,
unsigned char no_shmrank, taylor_data taylor_current)
42 if(no >= MaxPart && no < MaxPart + MaxNodes)
46 taylor_current.coeff.phi += TaylorCoeff[no].coeff.phi;
48 taylor_current.coeff.dphi += TaylorCoeff[no].coeff.dphi;
49#if(MULTIPOLE_ORDER >= 2)
50 taylor_current.coeff.d2phi += TaylorCoeff[no].coeff.d2phi;
52#if(MULTIPOLE_ORDER >= 3)
53 taylor_current.coeff.d3phi += TaylorCoeff[no].coeff.d3phi;
55#if(MULTIPOLE_ORDER >= 4)
56 taylor_current.coeff.d4phi += TaylorCoeff[no].coeff.d4phi;
58#if(MULTIPOLE_ORDER >= 5)
59 taylor_current.coeff.d5phi += TaylorCoeff[no].coeff.d5phi;
62 taylor_current.coeff.interactions += TaylorCoeff[no].coeff.interactions;
65 Terminate(
"this is not an internal node, which should not happen\n");
67 gravnode *node_no = get_nodep(no, no_shmrank);
75 if(p < MaxPart || (p >= ImportedNodeOffset && p < EndOfTreePoints))
83 if(p >= ImportedNodeOffset)
85 m = p - ImportedNodeOffset;
86 intpos = Points[m].IntPos;
88 p = get_nextnodep(shmrank)[p - MaxNodes];
93 intpos = Tp->P[p].IntPos;
95 p = get_nextnodep(shmrank)[p];
101 Tp->nearest_image_intpos_to_pos(intpos, node_no->
s.da, dxyz.
da);
104 MyReal pot = taylor_current.coeff.phi + taylor_current.coeff.dphi * dxyz;
108#if(MULTIPOLE_ORDER >= 2)
112 pot += 0.5f * (d2phidxyz * dxyz);
115#if(MULTIPOLE_ORDER >= 3)
117 dphi += 0.5f * d3phidxyz2;
119 pot +=
static_cast<MyReal>(1.0 / 6) * (dxyz * d3phidxyz2);
122#if(MULTIPOLE_ORDER >= 4)
124 dphi +=
static_cast<MyReal>(1.0 / 6) * d4phidxyz3;
126 pot +=
static_cast<MyReal>(1.0 / 24) * (dxyz * d4phidxyz3);
129#if(MULTIPOLE_ORDER >= 5)
131 dphi +=
static_cast<MyReal>(1.0 / 24) * d5phidxyz4;
133 pot +=
static_cast<MyReal>(1.0 / 120) * (dxyz * d5phidxyz4);
139#ifndef HIERARCHICAL_GRAVITY
140 if(Tp->TimeBinSynchronized[Tp->P[mp].TimeBinGrav])
143 Tp->P[mp].GravAccel -= dphi;
145 Tp->P[mp].Potential += pot;
149 Tp->P[mp].GravCost += taylor_current.coeff.interactions;
151 interactioncountEffective += taylor_current.coeff.interactions;
156#ifndef HIERARCHICAL_GRAVITY
157 if(Points[m].ActiveFlag)
160 int idx = ResultIndexList[m];
161 ResultsActiveImported[idx].GravAccel -= dphi;
163 ResultsActiveImported[idx].Potential += pot;
166 ResultsActiveImported[idx].GravCost += taylor_current.coeff.interactions;
168 interactioncountEffective += taylor_current.coeff.interactions;
172 else if(p < MaxPart + MaxNodes)
174 gravnode *node_p = get_nodep(p, shmrank);
176 if(fmm_depends_on_local_mass(p, shmrank))
178 taylor_data taylor_sub = taylor_current;
181 Tp->nearest_image_intpos_to_pos(node_p->
s.da, node_no->
s.da, dxyz.
da);
186 taylor_sub.coeff.phi += taylor_current.coeff.dphi * dxyz;
189#if(MULTIPOLE_ORDER >= 2)
191 taylor_sub.coeff.dphi += delta_dphi;
193 taylor_sub.coeff.phi += 0.5f * (delta_dphi * dxyz);
196#if(MULTIPOLE_ORDER >= 3)
199 taylor_sub.coeff.d2phi += delta_d2phi;
201 delta_dphi = delta_d2phi * dxyz;
203 taylor_sub.coeff.dphi += 0.5f * delta_dphi;
205 taylor_sub.coeff.phi +=
static_cast<MyReal>(1.0 / 6) * (delta_dphi * dxyz);
208#if(MULTIPOLE_ORDER >= 4)
210 taylor_sub.coeff.d3phi += delta_d3phi;
212 delta_d2phi = delta_d3phi * dxyz;
213 taylor_sub.coeff.d2phi += 0.5f * delta_d2phi;
215 delta_dphi = delta_d2phi * dxyz;
216 taylor_sub.coeff.dphi +=
static_cast<MyReal>(1.0 / 6) * delta_dphi;
218 taylor_sub.coeff.phi +=
static_cast<MyReal>(1.0 / 24) * (delta_dphi * dxyz);
221#if(MULTIPOLE_ORDER >= 5)
223 taylor_sub.coeff.d4phi += delta_d4phi;
225 delta_d3phi = delta_d4phi * dxyz;
226 taylor_sub.coeff.d3phi += 0.5f * delta_d3phi;
228 delta_d2phi = delta_d3phi * dxyz;
229 taylor_sub.coeff.d2phi +=
static_cast<MyReal>(1.0 / 6) * delta_d2phi;
231 delta_dphi = delta_d2phi * dxyz;
232 taylor_sub.coeff.dphi +=
static_cast<MyReal>(1.0 / 24) * delta_dphi;
234 taylor_sub.coeff.phi +=
static_cast<MyReal>(1.0 / 120) * (delta_dphi * dxyz);
237 fmm_force_passdown(p, shmrank, taylor_sub);
243 else if(p >= EndOfTreePoints && p < EndOfForeignNodes)
246 gravnode *nop = get_nodep(p, shmrank);
250 else if(p >= EndOfForeignNodes)
261 "should not happen: p=%d MaxPart=%d MaxNodes=%d ImportedNodeOffset=%d EndOfTreePoints=%d EndOfForeignNodes=%d "
263 p, MaxPart, MaxNodes, ImportedNodeOffset, EndOfTreePoints, EndOfForeignNodes, shmrank);
268inline void fmm::fmm_open_both(
gravnode *noptr_sink,
gravnode *noptr_source,
int mintopleafnode,
int committed)
271 if(noptr_sink == noptr_source)
278 while(p_sink != noptr_sink->
sibling ||
282 unsigned char next_shmrank_sink;
288 next_sink = get_nextnodep(shmrank_sink)[p_sink];
289 next_shmrank_sink = shmrank_sink;
292 else if(p_sink < MaxPart + MaxNodes)
294 gravnode *nop = get_nodep(p_sink, shmrank_sink);
299 else if(p_sink >= ImportedNodeOffset && p_sink < EndOfTreePoints)
302 next_sink = get_nextnodep(shmrank_sink)[p_sink - MaxNodes];
303 next_shmrank_sink = shmrank_sink;
306 else if(p_sink >= EndOfTreePoints && p_sink < EndOfForeignNodes)
308 gravnode *nop = get_nodep(p_sink, shmrank_sink);
313 else if(p_sink >= EndOfForeignNodes)
325 Terminate(
"pseudo particle - should not happen");
328 int p_source = noptr_source->
nextnode;
331 while(p_source != noptr_source->
sibling ||
335 unsigned char next_shmrank_source;
338 if(p_source < MaxPart)
341 next_source = get_nextnodep(shmrank_source)[p_source];
342 next_shmrank_source = shmrank_source;
345 else if(p_source < MaxPart + MaxNodes)
347 gravnode *nop = get_nodep(p_source, shmrank_source);
352 else if(p_source >= ImportedNodeOffset && p_source < EndOfTreePoints)
355 next_source = get_nextnodep(shmrank_source)[p_source - MaxNodes];
356 next_shmrank_source = shmrank_source;
359 else if(p_source >= EndOfTreePoints && p_source < EndOfForeignNodes)
361 gravnode *nop = get_nodep(p_source, shmrank_source);
366 else if(p_source >= EndOfForeignNodes)
369 next_source = foreignpoint->
Nextnode;
378 Terminate(
"pseudo particle - should not happen");
381 if(self_flag == 0 || p_source >= p_sink)
386 fmm_force_interact(p_source, p_sink, type_source, type_sink, shmrank_source, shmrank_sink, mintopleafnode,
391 fmm_force_interact(p_sink, p_source, type_sink, type_source, shmrank_sink, shmrank_source, mintopleafnode,
396 p_source = next_source;
397 shmrank_source = next_shmrank_source;
401 shmrank_sink = next_shmrank_sink;
405inline void fmm::fmm_open_node(
int no_particle,
gravnode *nop,
char type_particle,
unsigned char shmrank_particle,
int mintopleafnode,
417 unsigned char next_shmrank;
423 next = get_nextnodep(shmrank)[p];
424 next_shmrank = shmrank;
427 else if(p < MaxPart + MaxNodes)
429 gravnode *nop = get_nodep(p, shmrank);
434 else if(p >= ImportedNodeOffset && p < EndOfTreePoints)
437 next = get_nextnodep(shmrank)[p - MaxNodes];
438 next_shmrank = shmrank;
441 else if(p >= EndOfTreePoints && p < EndOfForeignNodes)
443 gravnode *nop = get_nodep(p, shmrank);
448 else if(p >= EndOfForeignNodes)
460 "should not happen: p=%d MaxPart=%d MaxNodes=%d ImportedNodeOffset=%d EndOfTreePoints=%d EndOfForeignNodes=%d "
462 p, MaxPart, MaxNodes, ImportedNodeOffset, EndOfTreePoints, EndOfForeignNodes, shmrank);
465 fmm_force_interact(no_particle, p, type_particle, type, shmrank_particle, shmrank, mintopleafnode, committed);
468 shmrank = next_shmrank;
472inline void fmm::fmm_particle_particle_interaction(
int no_sink,
int no_source,
int type_sink,
int type_source,
473 unsigned char shmrank_sink,
unsigned char shmrank_source)
475#ifdef PRESERVE_SHMEM_BINARY_INVARIANCE
476 if(skip_actual_force_computation)
483#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
495#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
496 test_n = P->InsideOutsideFlag;
501 gravpoint_data *Pointp = get_pointsp(no_sink - ImportedNodeOffset, shmrank_sink);
503 intpos_n = Pointp->
IntPos;
504 mass_n = Pointp->
Mass;
506#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
507 test_n = Pointp->InsideOutsideFlag;
514 intpos_n = foreignpoint->
IntPos;
515 mass_n = foreignpoint->
Mass;
517#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
518 test_n = foreignpoint->InsideOutsideFlag;
530#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
531 test_m = P->InsideOutsideFlag;
536 gravpoint_data *Pointp = get_pointsp(no_source - ImportedNodeOffset, shmrank_source);
538 intpos_m = Pointp->
IntPos;
539 mass_m = Pointp->
Mass;
541#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
542 test_m = Pointp->InsideOutsideFlag;
549 intpos_m = foreignpoint->
IntPos;
550 mass_m = foreignpoint->
Mass;
552#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
553 test_m = foreignpoint->InsideOutsideFlag;
557 MyReal h_max = (h_m > h_n) ? h_m : h_n;
560 Tp->nearest_image_intpos_to_pos(intpos_m, intpos_n, dxyz.
da);
564 MyReal rinv = (r > 0) ? 1 / r : 0;
573#ifdef PLACEHIGHRESREGION
580 if(modify_gfactors_pm_monopole(gfac, r, rinv, mfp))
585 get_gfactors_monopole(gfac, r, h_max, rinv);
608#ifndef HIERARCHICAL_GRAVITY
609 if(Tp->TimeBinSynchronized[Tp->P[no_sink].TimeBinGrav])
612 Tp->P[no_sink].GravAccel -= mass_m * D1;
614 Tp->P[no_sink].Potential -= mass_m * D0;
617 Tp->P[no_sink].GravCost++;
619 interactioncountPP += 1;
624#ifndef HIERARCHICAL_GRAVITY
625 if(Points[no_sink - ImportedNodeOffset].ActiveFlag)
628 int idx = ResultIndexList[no_sink - ImportedNodeOffset];
629 ResultsActiveImported[idx].GravAccel -= mass_m * D1;
631 ResultsActiveImported[idx].Potential -= mass_m * D0;
634 ResultsActiveImported[idx].GravCost++;
636 interactioncountPP += 1;
645#ifndef HIERARCHICAL_GRAVITY
646 if(Tp->TimeBinSynchronized[Tp->P[no_source].TimeBinGrav])
649 Tp->P[no_source].GravAccel += mass_n * D1;
651 Tp->P[no_source].Potential -= mass_n * D0;
655 Tp->P[no_source].GravCost++;
657 interactioncountPP += 1;
662#ifndef HIERARCHICAL_GRAVITY
663 if(Points[no_source - ImportedNodeOffset].ActiveFlag)
666 int idx = ResultIndexList[no_source - ImportedNodeOffset];
667 ResultsActiveImported[idx].GravAccel += mass_n * D1;
669 ResultsActiveImported[idx].Potential -= mass_n * D0;
672 ResultsActiveImported[idx].GravCost++;
674 interactioncountPP += 1;
680inline void fmm::fmm_particle_node_interaction(
int no_sink,
int no_source,
int type_sink,
int type_source,
unsigned char shmrank_sink,
683#ifdef PRESERVE_SHMEM_BINARY_INVARIANCE
684 if(skip_actual_force_computation)
694#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
707#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
708 test_point = P->InsideOutsideFlag;
713 gravpoint_data *Pointp = get_pointsp(no_sink - ImportedNodeOffset, shmrank_sink);
715 intpos_i = Pointp->
IntPos;
716 mass_i = Pointp->
Mass;
718#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
719 test_point = Pointp->InsideOutsideFlag;
726 intpos_i = foreignpoint->
IntPos;
727 mass_i = foreignpoint->
Mass;
729#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
730 test_point = foreignpoint->InsideOutsideFlag;
735 MyReal h_max = (h_j > h_i) ? h_j : h_i;
740 MyReal rinv = (r > 0) ? 1 / r : 0;
749#ifdef PLACEHIGHRESREGION
752 int test_node = noptr_source->overlap_flag;
758 if(modify_gfactors_pm_multipole(gfac, r, rinv, mfp))
763 get_gfactors_multipole(gfac, r, h_max, rinv);
770 MyReal g1 = gfac.fac1 * rinv;
773#if(MULTIPOLE_ORDER >= 2)
774 MyReal g2 = gfac.fac2 * gfac.rinv2;
781#if(MULTIPOLE_ORDER >= 3)
782 MyReal g3 = gfac.fac3 * gfac.rinv3;
788#if(MULTIPOLE_ORDER >= 4)
789 MyReal g4 = gfac.fac4 * gfac.rinv2 * gfac.rinv2;
795#if(MULTIPOLE_ORDER >= 5)
796 MyReal g5 = gfac.fac5 * gfac.rinv3 * gfac.rinv2;
811#if(MULTIPOLE_ORDER >= 2)
814#if(MULTIPOLE_ORDER >= 3)
817#if(MULTIPOLE_ORDER >= 4)
820#if(MULTIPOLE_ORDER >= 5)
831#if(MULTIPOLE_ORDER >= 3) || ((MULTIPOLE_ORDER >= 2) && defined(EXTRAPOTTERM))
834#if(MULTIPOLE_ORDER >= 4) || ((MULTIPOLE_ORDER >= 3) && defined(EXTRAPOTTERM))
837#if(MULTIPOLE_ORDER >= 5) || ((MULTIPOLE_ORDER >= 4) && defined(EXTRAPOTTERM))
840#if(MULTIPOLE_ORDER >= 5) && defined(EXTRAPOTTERM)
845 MyReal pot = -mass_j * D0;
846#if(MULTIPOLE_ORDER >= 3) || ((MULTIPOLE_ORDER >= 2) && defined(EXTRAPOTTERM))
847 pot -= 0.5f * (D2 * Q2_j);
849#if(MULTIPOLE_ORDER >= 4) || ((MULTIPOLE_ORDER >= 3) && defined(EXTRAPOTTERM))
850 pot -=
static_cast<MyReal>(1.0 / 6) * (D3 * Q3_j);
852#if(MULTIPOLE_ORDER >= 5) || ((MULTIPOLE_ORDER >= 4) && defined(EXTRAPOTTERM))
853 pot -=
static_cast<MyReal>(1.0 / 24) * (D4 * Q4_j);
855#if(MULTIPOLE_ORDER >= 5) && defined(EXTRAPOTTERM)
857 pot -=
static_cast<MyReal>(1.0 / 120) * (D5 * Q5_j);
863#if(MULTIPOLE_ORDER >= 3)
864 dphi +=
static_cast<MyReal>(0.5) * (D3 * Q2_j);
866#if(MULTIPOLE_ORDER >= 4)
867 dphi +=
static_cast<MyReal>(1.0 / 6) * (D4 * Q3_j);
869#if(MULTIPOLE_ORDER >= 5)
870 dphi +=
static_cast<MyReal>(1.0 / 24) * (D5 * Q4_j);
875#ifndef HIERARCHICAL_GRAVITY
876 if(Tp->TimeBinSynchronized[Tp->P[no_sink].TimeBinGrav])
879 Tp->P[no_sink].GravAccel -= dphi;
881 Tp->P[no_sink].Potential += pot;
884 Tp->P[no_sink].GravCost++;
886 interactioncountPN += 1;
887 interactioncountEffective += 1;
892#ifndef HIERARCHICAL_GRAVITY
893 if(Points[no_sink - ImportedNodeOffset].ActiveFlag)
896 int idx = ResultIndexList[no_sink - ImportedNodeOffset];
897 ResultsActiveImported[idx].GravAccel -= dphi;
899 ResultsActiveImported[idx].Potential += pot;
902 ResultsActiveImported[idx].GravCost++;
904 interactioncountPN += 1;
905 interactioncountEffective += 1;
910 if(fmm_depends_on_local_mass(no_source, shmrank_source))
915 TaylorCoeff[no_source].coeff.phi += (-mass_i) * D0;
917 TaylorCoeff[no_source].coeff.dphi += (-mass_i) * D1;
918#if(MULTIPOLE_ORDER >= 2)
919 TaylorCoeff[no_source].coeff.d2phi += (-mass_i) * D2;
921#if(MULTIPOLE_ORDER >= 3)
922 TaylorCoeff[no_source].coeff.d3phi += (-mass_i) * D3;
924#if(MULTIPOLE_ORDER >= 4)
925 TaylorCoeff[no_source].coeff.d4phi += (-mass_i) * D4;
927#if(MULTIPOLE_ORDER >= 5)
928 TaylorCoeff[no_source].coeff.d5phi += (-mass_i) * D5;
930 TaylorCoeff[no_source].coeff.interactions += 1;
932 interactioncountPN += 1;
936inline void fmm::fmm_node_node_interaction(
int no_sink,
int no_source,
int type_sink,
int type_source,
unsigned char shmrank_sink,
940#ifdef PRESERVE_SHMEM_BINARY_INVARIANCE
941 if(skip_actual_force_computation)
953#if(MULTIPOLE_ORDER >= 3) || ((MULTIPOLE_ORDER >= 2) && defined(EXTRAPOTTERM))
957#if(MULTIPOLE_ORDER >= 4) || ((MULTIPOLE_ORDER >= 3) && defined(EXTRAPOTTERM))
961#if(MULTIPOLE_ORDER >= 5) || ((MULTIPOLE_ORDER >= 4) && defined(EXTRAPOTTERM))
965#if(MULTIPOLE_ORDER >= 5) && defined(EXTRAPOTTERM) && defined(EVALPOTENTIAL)
973 MyReal rinv = (r > 0) ? 1 / r : 0;
977 MyReal h_max = (h_m > h_n) ? h_m : h_n;
986#ifdef PLACEHIGHRESREGION
994 if(modify_gfactors_pm_multipole(gfac, r, rinv, mfp))
999 get_gfactors_multipole(gfac, r, h_max, rinv);
1006 MyReal g1 = gfac.fac1 * rinv;
1009#if(MULTIPOLE_ORDER >= 2)
1010 MyReal g2 = gfac.fac2 * gfac.rinv2;
1018#if(MULTIPOLE_ORDER >= 3)
1019 MyReal g3 = gfac.fac3 * gfac.rinv3;
1025#if(MULTIPOLE_ORDER >= 4)
1026 MyReal g4 = gfac.fac4 * gfac.rinv2 * gfac.rinv2;
1029 setup_D4(
INIT, D4, dxyz, aux2, aux3, aux4, g2, g3, g4);
1032#if(MULTIPOLE_ORDER >= 5)
1033 MyReal g5 = gfac.fac5 * gfac.rinv3 * gfac.rinv2;
1036 setup_D5(
INIT, D5, dxyz, aux3, aux4, aux5, g3, g4, g5);
1048#if(MULTIPOLE_ORDER >= 2)
1051#if(MULTIPOLE_ORDER >= 3)
1054#if(MULTIPOLE_ORDER >= 4)
1057#if(MULTIPOLE_ORDER >= 5)
1062 if(fmm_depends_on_local_mass(no_sink, shmrank_sink))
1066 TaylorCoeff[no_sink].coeff.phi += (-mass_m) * D0;
1067#if(MULTIPOLE_ORDER >= 3) || ((MULTIPOLE_ORDER >= 2) && defined(EXTRAPOTTERM))
1068 TaylorCoeff[no_sink].coeff.phi +=
static_cast<MyReal>(-0.5) * (D2 * Q2_m);
1070#if(MULTIPOLE_ORDER >= 4) || ((MULTIPOLE_ORDER >= 3) && defined(EXTRAPOTTERM))
1071 TaylorCoeff[no_sink].coeff.phi +=
static_cast<MyReal>(-1.0 / 6) * (D3 * Q3_m);
1073#if(MULTIPOLE_ORDER >= 5) || ((MULTIPOLE_ORDER >= 4) && defined(EXTRAPOTTERM))
1074 TaylorCoeff[no_sink].coeff.phi +=
static_cast<MyReal>(-1.0 / 24) * (D4 * Q4_m);
1076#if(MULTIPOLE_ORDER >= 5) && defined(EXTRAPOTTERM)
1077 TaylorCoeff[no_sink].coeff.phi +=
static_cast<MyReal>(-1.0 / 120) * (D5 * Q5_m);
1081 TaylorCoeff[no_sink].coeff.dphi += mass_m * D1;
1082#if(MULTIPOLE_ORDER >= 2)
1083 TaylorCoeff[no_sink].coeff.d2phi += (-mass_m) * D2;
1085#if(MULTIPOLE_ORDER >= 3)
1086 TaylorCoeff[no_sink].coeff.dphi +=
static_cast<MyReal>(0.5) * (D3 * Q2_m);
1087 TaylorCoeff[no_sink].coeff.d3phi += mass_m * D3;
1089#if(MULTIPOLE_ORDER >= 4)
1090 TaylorCoeff[no_sink].coeff.dphi +=
static_cast<MyReal>(1.0 / 6) * (D4 * Q3_m);
1091 TaylorCoeff[no_sink].coeff.d2phi +=
static_cast<MyReal>(-0.5) * (D4 * Q2_m);
1092 TaylorCoeff[no_sink].coeff.d4phi += (-mass_m) * D4;
1094#if(MULTIPOLE_ORDER >= 5)
1095 TaylorCoeff[no_sink].coeff.dphi +=
static_cast<MyReal>(1.0 / 24) * (D5 * Q4_m);
1096 TaylorCoeff[no_sink].coeff.d2phi +=
static_cast<MyReal>(-1.0 / 6) * (D5 * Q3_m);
1097 TaylorCoeff[no_sink].coeff.d3phi +=
static_cast<MyReal>(0.5) * (D5 * Q2_m);
1098 TaylorCoeff[no_sink].coeff.d5phi += mass_m * D5;
1101 TaylorCoeff[no_sink].coeff.interactions += 1;
1102 interactioncountNN += 1;
1105 if(fmm_depends_on_local_mass(no_source, shmrank_source))
1109 TaylorCoeff[no_source].coeff.phi += (-mass_n) * D0;
1110#if(MULTIPOLE_ORDER >= 3) || ((MULTIPOLE_ORDER >= 2) && defined(EXTRAPOTTERM))
1111 TaylorCoeff[no_source].coeff.phi +=
static_cast<MyReal>(-0.5) * (D2 * Q2_n);
1113#if(MULTIPOLE_ORDER >= 4) || ((MULTIPOLE_ORDER >= 3) && defined(EXTRAPOTTERM))
1114 TaylorCoeff[no_source].coeff.phi +=
static_cast<MyReal>(1.0 / 6) * (D3 * Q3_n);
1116#if(MULTIPOLE_ORDER >= 5) || ((MULTIPOLE_ORDER >= 4) && defined(EXTRAPOTTERM))
1117 TaylorCoeff[no_source].coeff.phi +=
static_cast<MyReal>(-1.0 / 24) * (D4 * Q4_n);
1119#if(MULTIPOLE_ORDER >= 5) && defined(EXTRAPOTTERM)
1120 TaylorCoeff[no_source].coeff.phi +=
static_cast<MyReal>(1.0 / 120) * (D5 * Q5_n);
1124 TaylorCoeff[no_source].coeff.dphi += (-mass_n) * D1;
1125#if(MULTIPOLE_ORDER >= 2)
1126 TaylorCoeff[no_source].coeff.d2phi += (-mass_n) * D2;
1128#if(MULTIPOLE_ORDER >= 3)
1129 TaylorCoeff[no_source].coeff.dphi +=
static_cast<MyReal>(-0.5) * (D3 * Q2_n);
1130 TaylorCoeff[no_source].coeff.d3phi += (-mass_n) * D3;
1132#if(MULTIPOLE_ORDER >= 4)
1133 TaylorCoeff[no_source].coeff.dphi +=
static_cast<MyReal>(1.0 / 6) * (D4 * Q3_n);
1134 TaylorCoeff[no_source].coeff.d2phi +=
static_cast<MyReal>(-0.5) * (D4 * Q2_n);
1135 TaylorCoeff[no_source].coeff.d4phi += (-mass_n) * D4;
1137#if(MULTIPOLE_ORDER >= 5)
1138 TaylorCoeff[no_source].coeff.dphi +=
static_cast<MyReal>(-1.0 / 24) * (D5 * Q4_n);
1139 TaylorCoeff[no_source].coeff.d2phi +=
static_cast<MyReal>(1.0 / 6) * (D5 * Q3_n);
1140 TaylorCoeff[no_source].coeff.d3phi +=
static_cast<MyReal>(-0.5) * (D5 * Q2_n);
1141 TaylorCoeff[no_source].coeff.d5phi += (-mass_n) * D5;
1144 TaylorCoeff[no_source].coeff.interactions += 1;
1145 interactioncountNN += 1;
1153 Terminate(
"This shouldn't happen: noptr_level=%d noptr_sink->level=%d ", noptr_source->
level, noptr_sink->
level);
1155 if(noptr_source->
level <=
1164#ifndef TREE_NO_SAFETY_BOX
1168 Tp->nearest_image_intpos_to_absolute_intdist(noptr_source->
center.da, noptr_sink->
center.da, dist);
1170 if(dist[0] < twolens && dist[1] < twolens && dist[2] < twolens)
1175 Tp->nearest_image_intpos_to_pos(noptr_source->
s.da, noptr_sink->
s.da, dxyz.
da);
1182#ifdef PLACEHIGHRESREGION
1185 int test_source = noptr_source->overlap_flag;
1186 int test_sink = noptr_sink->overlap_flag;
1191 Terminate(
"this shouldn't happen any more");
1202 if(DoPM && r2 > mfp->rcut2 && noptr_sink->
level > 1)
1207 if(dist_x > mfp->intrcut[0] + intlen)
1212 if(dist_y > mfp->intrcut[1] + intlen)
1217 if(dist_z > mfp->intrcut[2] + intlen)
1224 MyReal len = intlen * Tp->FacIntToCoord;
1229 if(4 * len2 > r2 * errTolTheta2)
1234 if(4 * len2 > r2 * errTolThetaMax2)
1239 errTolForceAcc * ((noptr_sink->MinOldAcc < noptr_source->MinOldAcc) ? noptr_sink->MinOldAcc : noptr_source->MinOldAcc);
1240#if(MULTIPOLE_ORDER == 1)
1241 if(mmax > r2 * amin)
1243#elif(MULTIPOLE_ORDER == 2)
1246#elif(MULTIPOLE_ORDER == 3)
1247 if(mmax * len2 > r2 * r2 * amin)
1249#elif(MULTIPOLE_ORDER == 4)
1250 if(
square(mmax * len * len2) > r2 *
square(r2 * r2 * amin))
1252#elif(MULTIPOLE_ORDER == 5)
1253 if(mmax * len2 * len2 > r2 * r2 * r2 * amin)
1261 MyReal h_max = (h_m > h_n) ? h_m : h_n;
1263 if(r2 < h_max * h_max)
1277inline int fmm::fmm_evaluate_particle_node_opening_criterion(
int no_sink,
char type_sink,
unsigned char shmrank_sink,
1286#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
1300#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
1301 test_point = P->InsideOutsideFlag;
1306 gravpoint_data *Pointp = get_pointsp(no_sink - ImportedNodeOffset, shmrank_sink);
1308 intpos_n = Pointp->
IntPos;
1309 mass_n = Pointp->
Mass;
1314#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
1315 test_point = Pointp->InsideOutsideFlag;
1322 intpos_n = foreignpoint->
IntPos;
1323 mass_n = foreignpoint->
Mass;
1324 aold = foreignpoint->
OldAcc;
1328#if defined(PMGRID) && defined(PLACEHIGHRESREGION)
1329 test_point = foreignpoint->InsideOutsideFlag;
1339#ifndef TREE_NO_SAFETY_BOX
1341 Tp->nearest_image_intpos_to_absolute_intdist(nop_source->
center.da, intpos_n, dist);
1343 if(dist[0] < intlen && dist[1] < intlen && dist[2] < intlen)
1348 Tp->nearest_image_intpos_to_pos(nop_source->
s.da, intpos_n, dxyz.
da);
1355#ifdef PLACEHIGHRESREGION
1358 int test_node = nop_source->overlap_flag;
1362 Terminate(
"this shouldn't happen any more");
1373 if(DoPM && r2 > mfp->rcut2)
1378 if(dist_x > mfp->intrcut[0] + halflen)
1383 if(dist_y > mfp->intrcut[1] + halflen)
1388 if(dist_z > mfp->intrcut[2] + halflen)
1393 MyReal len = intlen * Tp->FacIntToCoord;
1398 if(4 * len2 > r2 * errTolTheta2)
1403 if(4 * len2 > r2 * errTolThetaMax2)
1406 MyReal mmax = (nop_source->
mass < mass_n) ? mass_n : nop_source->
mass;
1407 MyReal amin = errTolForceAcc * ((aold < nop_source->MinOldAcc) ? aold : nop_source->MinOldAcc);
1409#if(MULTIPOLE_ORDER == 1)
1410 if(mmax > r2 * amin)
1412#elif(MULTIPOLE_ORDER == 2)
1415#elif(MULTIPOLE_ORDER == 3)
1416 if(mmax * len2 > r2 * r2 * amin)
1418#elif(MULTIPOLE_ORDER == 4)
1419 if(
square(mmax * len * len2) > r2 *
square(r2 * r2 * amin))
1421#elif(MULTIPOLE_ORDER == 5)
1422 if(mmax * len2 * len2 > r2 * r2 * r2 * amin)
1444void fmm::fmm_force_interact(
int no_sink,
int no_source,
char type_sink,
char type_source,
unsigned char shmrank_sink,
1445 unsigned char shmrank_source,
int mintopleafnode,
int committed)
1453 if(no_sink != no_source || shmrank_source != shmrank_sink)
1454 fmm_particle_particle_interaction(no_sink, no_source, type_sink, type_source, shmrank_sink, shmrank_source);
1460 gravnode *noptr_source = get_nodep(no_source, shmrank_source);
1463 if(fmm_depends_on_local_mass(no_source, shmrank_source) ==
false &&
1471 if(no_source < MaxPart + MaxNodes)
1472 if(noptr_source->
nextnode >= MaxPart + MaxNodes)
1473 mintopleafnode = no_source;
1478 int openflag = fmm_evaluate_particle_node_opening_criterion(no_sink, type_sink, shmrank_sink, noptr_source, dxyz, r2);
1482 fmm_particle_node_interaction(no_sink, no_source, type_sink, type_source, shmrank_sink, shmrank_source, noptr_source, dxyz,
1492 Terminate(
"this should not happen any more");
1496 tree_add_to_fetch_stack(noptr_source, no_source, shmrank_source);
1498 fmm_add_to_work_stack(no_sink, no_source, shmrank_sink, shmrank_source, mintopleafnode);
1503 int min_buffer_space =
1504 std::min<int>(MaxOnWorkStack - (NumOnWorkStack + NewOnWorkStack), MaxOnFetchStack - NumOnFetchStack);
1507 fmm_open_node(no_sink, noptr_source, type_sink, shmrank_sink, mintopleafnode,
1510 fmm_add_to_work_stack(no_sink, no_source, shmrank_sink, shmrank_source, mintopleafnode);
1516 gravnode *noptr_sink = get_nodep(no_sink, shmrank_sink);
1517 gravnode *noptr_source = get_nodep(no_source, shmrank_source);
1520 if(fmm_depends_on_local_mass(no_sink, shmrank_sink) || fmm_depends_on_local_mass(no_source, shmrank_source))
1525 if(noptr_sink == noptr_source)
1527 if(no_source < MaxPart + MaxNodes)
1528 if(noptr_source->
nextnode >= MaxPart + MaxNodes)
1529 mintopleafnode = no_source;
1533 Terminate(
"should not happen because we have a self-interaction of a supposedly local node");
1537 int min_buffer_space =
1538 std::min<int>(MaxOnWorkStack - (NumOnWorkStack + NewOnWorkStack), MaxOnFetchStack - NumOnFetchStack);
1541 fmm_open_both(noptr_sink, noptr_sink, mintopleafnode,
1544 fmm_add_to_work_stack(no_source, no_sink, shmrank_source, shmrank_sink, mintopleafnode);
1552 int openflag = fmm_evaluate_node_node_opening_criterion(noptr_sink, noptr_source, dxyz, r2);
1557 fmm_node_node_interaction(no_sink, no_source, type_sink, type_source, shmrank_sink, shmrank_source, noptr_sink,
1558 noptr_source, dxyz, r2);
1564 if(no_source < MaxPart + MaxNodes)
1565 if(noptr_source->
nextnode >= MaxPart + MaxNodes)
1566 mintopleafnode = std::min<int>(mintopleafnode, no_source);
1568 if(no_sink < MaxPart + MaxNodes)
1569 if(noptr_sink->
nextnode >= MaxPart + MaxNodes)
1570 mintopleafnode = std::min<int>(mintopleafnode, no_sink);
1575 Terminate(
"this should not happen, because then both nodes would be foreign");
1578 tree_add_to_fetch_stack(noptr_source, no_source, shmrank_source);
1581 tree_add_to_fetch_stack(noptr_sink, no_sink, shmrank_sink);
1583 fmm_add_to_work_stack(no_source, no_sink, shmrank_source, shmrank_sink, mintopleafnode);
1587 int min_buffer_space =
1588 std::min<int>(MaxOnWorkStack - (NumOnWorkStack + NewOnWorkStack), MaxOnFetchStack - NumOnFetchStack);
1591 fmm_open_both(noptr_sink, noptr_source, mintopleafnode,
1594 fmm_add_to_work_stack(no_source, no_sink, shmrank_source, shmrank_sink, mintopleafnode);
1603void fmm::fmm_determine_nodes_with_local_mass(
int no,
int sib)
1610 if(p < MaxPart || p >= FirstNonTopLevelNode)
1613 unsigned char depends_on_local_mass = 0;
1619 if(p >= MaxPart && p < MaxPart + MaxNodes)
1623 fmm_determine_nodes_with_local_mass(p, nextsib);
1630 else if(p < MaxPart + MaxNodes)
1632 depends_on_local_mass |= Topnode_depends_on_local_mass[p];
1636 else if(p < MaxPart + MaxNodes + D->NTopleaves)
1650 Topnode_depends_on_local_mass[no] = depends_on_local_mass;
1653void fmm::gravity_fmm(
int timebin)
1655 interactioncountPP = 0;
1656 interactioncountPN = 0;
1657 interactioncountNN = 0;
1658 interactioncountEffective = 0;
1663 D->mpi_printf(
"FMM: Begin tree force. timebin=%d (presently allocated=%g MB)\n", timebin,
All.
ErrTolTheta,
1670 Topnode_depends_on_local_mass = (
char *)
Mem.mymalloc_clear(
"Topnode_depends_on_local_mass", D->NTopnodes *
sizeof(
char));
1671 Topnode_depends_on_local_mass -= MaxPart;
1673 for(
int n = 0; n < D->NTopleaves; n++)
1675 if(D->TaskOfLeaf[n] == D->ThisTask)
1677 int no = NodeIndex[n];
1679 if(TopNodes[no].not_empty)
1680 Topnode_depends_on_local_mass[no] = 1;
1684 fmm_determine_nodes_with_local_mass(MaxPart, -1);
1693 FMM_WorkStack = (fmm_workstack_data *)
Mem.mymalloc(
"FMM_WorkStack", AllocWorkStackBaseHigh *
sizeof(fmm_workstack_data));
1694 ResultIndexList = (
int *)
Mem.mymalloc(
"ResultIndexList", NumPartImported *
sizeof(
int));
1696 for(
int i = 0; i < Tp->TimeBinsGravity.NActiveParticles; i++)
1698 int target = Tp->TimeBinsGravity.ActiveParticleList[i];
1701 int softtype = Tp->P[target].getSofteningClass();
1703 Terminate(
"Particle with ID=%lld of type=%d and softening type=%d was assigned zero softening\n",
1704 (
long long)Tp->P[target].ID.get(), Tp->P[target].getType(), softtype);
1709 for(
int i = 0; i < NumPartImported; i++)
1711#ifndef HIERARCHICAL_GRAVITY
1712 if(Points[i].ActiveFlag)
1715 ResultIndexList[i] = ncount++;
1725 NumOnWorkStack = NewOnWorkStack;
1727 ResultsActiveImported =
1728 (resultsactiveimported_data *)
Mem.mymalloc_clear(
"ResultsActiveImported", ncount *
sizeof(resultsactiveimported_data));
1730 TaylorCoeff = (taylor_data *)
Mem.mymalloc_clear(
"TaylorCoeff", NumNodes *
sizeof(taylor_data));
1731 TaylorCoeff -= MaxPart;
1741 sum_NumForeignNodes = 0;
1742 sum_NumForeignPoints = 0;
1747 StackToFetch = (fetch_data *)
Mem.mymalloc_movable(&StackToFetch,
"StackToFetch", MaxOnFetchStack *
sizeof(fetch_data));
1752 MaxForeignNodes = nspace;
1753 MaxForeignPoints = 8 * nspace;
1754 NumForeignNodes = 0;
1755 NumForeignPoints = 0;
1758 Foreign_Nodes = (
gravnode *)
Mem.mymalloc_movable(&Foreign_Nodes,
"Foreign_Nodes", MaxForeignNodes *
sizeof(
gravnode));
1762 tree_initialize_leaf_node_access_info();
1767 int max_ncycles = 0;
1769 prepare_shared_memory_access();
1771#ifdef PRESERVE_SHMEM_BINARY_INVARIANCE
1772 for(
int rep = 0; rep < 2; rep++)
1776 skip_actual_force_computation =
true;
1780 skip_actual_force_computation =
false;
1788 NumOnWorkStack = NewOnWorkStack;
1792 while(NumOnWorkStack > 0)
1795 NumOnFetchStack = 0;
1796 MaxOnWorkStack = std::min<int>(AllocWorkStackBaseLow + max_ncycles *
TREE_MIN_WORKSTACK_SIZE, AllocWorkStackBaseHigh);
1803 while(item < NumOnWorkStack)
1805 int min_buffer_space =
1806 std::min<int>(MaxOnWorkStack - (NumOnWorkStack + NewOnWorkStack), MaxOnFetchStack - NumOnFetchStack);
1810 if(min_buffer_space >= committed)
1812 int no1 = FMM_WorkStack[item].Node1;
1813 int no2 = FMM_WorkStack[item].Node2;
1814 unsigned char shmrank1 = FMM_WorkStack[item].ShmRank1;
1815 unsigned char shmrank2 = FMM_WorkStack[item].ShmRank2;
1816 int mintopleaf = FMM_WorkStack[item].MinTopLeafNode;
1819 char type1 = 0, type2 = 0;
1823 else if(no1 < MaxPart + MaxNodes)
1825 else if(no1 >= ImportedNodeOffset && no1 < EndOfTreePoints)
1827 else if(no1 >= EndOfTreePoints && no1 < EndOfForeignNodes)
1829 else if(no1 >= EndOfForeignNodes)
1834 else if(no2 < MaxPart + MaxNodes)
1836 else if(no2 >= ImportedNodeOffset && no2 < EndOfTreePoints)
1838 else if(no2 >= EndOfTreePoints && no2 < EndOfForeignNodes)
1840 else if(no2 >= EndOfForeignNodes)
1843 if(no1 == MaxPart && no2 == MaxPart)
1846 fmm_force_interact(no1, no2, type1, type2, shmrank1, shmrank2, mintopleaf, committed);
1854 gravnode *nop1 = get_nodep(no1, shmrank1);
1855 gravnode *nop2 = get_nodep(no2, shmrank2);
1860 fmm_open_both(nop1, nop2, mintopleaf, committed);
1867 gravnode *nop2 = get_nodep(no2, shmrank2);
1870 Terminate(
"now we should be able to open it!");
1872 fmm_open_node(no1, nop2, type1, shmrank1, mintopleaf, committed);
1880 if(item == 0 && NumOnWorkStack > 0)
1881 Terminate(
"Can't even process a single particle");
1887 tree_fetch_foreign_nodes(FETCH_GRAVTREE);
1895 NumOnWorkStack = NumOnWorkStack - item + NewOnWorkStack;
1896 memmove(FMM_WorkStack, FMM_WorkStack + item, NumOnWorkStack *
sizeof(fmm_workstack_data));
1899 mycxxsort(FMM_WorkStack, FMM_WorkStack + NumOnWorkStack, compare_fmm_workstack);
1906#ifdef PRESERVE_SHMEM_BINARY_INVARIANCE
1912 MPI_Allreduce(MPI_IN_PLACE, &max_ncycles, 1, MPI_INT, MPI_MAX, D->Communicator);
1916 cleanup_shared_memory_access();
1920 Mem.myfree(Foreign_Points);
1921 Mem.myfree(Foreign_Nodes);
1922 Mem.myfree(StackToFetch);
1926 taylor_data taylor_current{};
1934 Mem.myfree(TaylorCoeff + MaxPart);
1938 D->mpi_printf(
"FMM: Forces calculated, with %d cycles took %g sec\n", max_ncycles,
Logs.
timediff(t0, t1));
1941 gravity_exchange_forces();
1943 Mem.myfree(ResultsActiveImported);
1944 Mem.myfree(ResultIndexList);
1945 Mem.myfree(FMM_WorkStack);
1949 D->mpi_printf(
"FMM: tree-force is done.\n");
1955 struct detailed_timings
1957 double all,
tree, wait, fetch, stack, lastpm;
1958 double costtotal, numnodes;
1959 double interactioncountEffective;
1960 double interactioncountPP, interactioncountPN, interactioncountNN;
1961 double NumForeignNodes, NumForeignPoints;
1962 double fillfacFgnNodes, fillfacFgnPoints;
1965 detailed_timings timer, tisum, timax;
1967 memset(&timer, 0,
sizeof(detailed_timings));
1972 for(
int i = 0; i < Tp->NumPart; i++)
1973 if(Tp->TimeBinSynchronized[Tp->P[i].TimeBinGrav])
1974 sum += Tp->P[i].GravCost;
1976 timer.sumcost = sum;
1983 timer.all = timer.tree + timer.wait + timer.fetch + timer.stack +
TIMER_DIFF(CPU_TREE);
1985 timer.costtotal = interactioncountPP + interactioncountEffective;
1986 timer.interactioncountPP = interactioncountPP;
1987 timer.interactioncountPN = interactioncountPN;
1988 timer.interactioncountNN = interactioncountNN;
1989 timer.interactioncountEffective = interactioncountEffective;
1990 timer.NumForeignNodes = NumForeignNodes;
1991 timer.NumForeignPoints = NumForeignPoints;
1992 timer.fillfacFgnNodes = NumForeignNodes / ((double)MaxForeignNodes);
1993 timer.fillfacFgnPoints = NumForeignPoints / ((double)MaxForeignPoints);
1994 timer.numnodes = NumNodes;
1996 MPI_Reduce((
double *)&timer, (
double *)&tisum, (
int)(
sizeof(detailed_timings) /
sizeof(
double)), MPI_DOUBLE, MPI_SUM, 0,
1998 MPI_Reduce((
double *)&timer, (
double *)&timax, (
int)(
sizeof(detailed_timings) /
sizeof(
double)), MPI_DOUBLE, MPI_MAX, 0,
2003 if(D->ThisTask == 0)
2005 fprintf(
Logs.
FdTimings,
"Nf=%9lld FMM timebin=%d total-Nf=%lld\n", Tp->TimeBinsGravity.GlobalNActiveParticles, timebin,
2007 fprintf(
Logs.
FdTimings,
" work-load balance: %g part/sec: raw=%g, effective=%g ia/part: avg=%g (%g|%g|%g)\n",
2008 timax.tree / ((tisum.tree + 1e-20) / D->NTask), Tp->TimeBinsGravity.GlobalNActiveParticles / (tisum.tree + 1.0e-20),
2009 Tp->TimeBinsGravity.GlobalNActiveParticles / ((timax.tree + 1.0e-20) * D->NTask),
2010 tisum.costtotal / (Tp->TimeBinsGravity.GlobalNActiveParticles + 1.0e-20),
2011 tisum.interactioncountPP / (Tp->TimeBinsGravity.GlobalNActiveParticles + 1.0e-20),
2012 tisum.interactioncountPN / (Tp->TimeBinsGravity.GlobalNActiveParticles + 1.0e-20),
2013 tisum.interactioncountNN / (Tp->TimeBinsGravity.GlobalNActiveParticles + 1.0e-20));
2015 " maximum number of nodes: %g, filled: %g NumForeignNodes: max=%g avg=%g fill=%g NumForeignPoints: max=%g avg=%g "
2016 "fill=%g cycles=%d\n",
2017 timax.numnodes, timax.numnodes / MaxNodes, timax.NumForeignNodes, tisum.NumForeignNodes / D->NTask,
2018 timax.fillfacFgnNodes, timax.NumForeignPoints, tisum.NumForeignPoints / D->NTask, timax.fillfacFgnPoints, max_ncycles);
2020 " avg times: <all>=%g <tree>=%g <wait>=%g <fetch>=%g <stack>=%g "
2021 "(lastpm=%g) sec\n",
2022 tisum.all / D->NTask, tisum.tree / D->NTask, tisum.wait / D->NTask, tisum.fetch / D->NTask, tisum.stack / D->NTask,
2023 tisum.lastpm / D->NTask);
2024 fprintf(
Logs.
FdTimings,
" total interaction cost: %g (imbalance=%g) total cost measure: %g %g\n", tisum.costtotal,
2025 timax.costtotal / (tisum.costtotal / D->NTask), tisum.sumcost,
2026 tisum.interactioncountPP + tisum.interactioncountEffective);
2030 Mem.myfree(Topnode_depends_on_local_mass + MaxPart);
global_data_all_processes All
void ewald_gridlookup(const MyIntPosType *p_intpos, const MyIntPosType *target_intpos, enum interpolate_options flag, ewald_data &fper)
double timediff(double t0, double t1)
double getAllocatedBytesInMB(void)
int * GetNodeIDForSimulCommRank
#define FLAG_BOUNDARYOVERLAP
double mycxxsort(T *begin, T *end, Tcomp comp)
#define LEVEL_ALWAYS_OPEN
int32_t MySignedIntPosType
#define BITS_FOR_POSITIONS
#define TREE_ACTIVE_CUTTOFF_HIGHRES_PM
#define TREE_MIN_WORKSTACK_SIZE
#define NODE_TYPE_FETCHED_NODE
#define NODE_TYPE_TREEPOINT_PARTICLE
#define TREE_EXPECTED_CYCLES
#define NODE_TYPE_FETCHED_PARTICLE
#define NODE_TYPE_LOCAL_NODE
#define NODE_TYPE_LOCAL_PARTICLE
#define TIMER_START(counter)
Starts the timer counter.
#define TIMER_STOP(counter)
Stops the timer counter.
#define TIMER_STORE
Copies the current value of CPU times to a stored variable, such that differences with respect to thi...
#define TIMER_DIFF(counter)
Returns amount elapsed for the timer since last save with TIMER_STORE.
unsigned char nextnode_shmrank
std::atomic< unsigned char > cannot_be_opened_locally
vector< MyIntPosType > center
unsigned char sibling_shmrank
symtensor3< MyReal > D3phi
symtensor2< MyReal > D2phi
unsigned char getSofteningClass(void)
unsigned char Nextnode_shmrank
double CPUForLastPMExecution
double ForceSoftening[NSOFTCLASSES+NSOFTCLASSES_HYDRO+2]
char RelOpeningCriterionInUse
int getSofteningClass(void)
unsigned char maxsofttype
unsigned char minsofttype
unsigned char getSofteningClass(void)
unsigned char getSofteningClass(void)
vector< typename which_return< T1, T2 >::type > contract_fourtimes(const symtensor5< T1 > &D, const vector< T2 > &v)
vector< typename which_return< T1, T2 >::type > contract_twice(const symtensor3< T1 > &D, const vector< T2 > &v)
void setup_D5(enum setup_options opt, symtensor5< T > &D5, vector< T > &dxyz, symtensor3< T > &aux3, symtensor4< T > &aux4, symtensor5< T > &aux5, TypeGfac g3, TypeGfac g4, TypeGfac g5)
void setup_D3(enum setup_options opt, symtensor3< T > &D3, vector< T > &dxyz, symtensor2< T > &aux2, symtensor3< T > &aux3, TypeGfac g2, TypeGfac g3)
vector< typename which_return< T1, T2 >::type > contract_thrice(const symtensor4< T1 > &D, const vector< T2 > &v)
void setup_D4(enum setup_options opt, symtensor4< T > &D4, vector< T > &dxyz, symtensor2< T > &aux2, symtensor3< T > &aux3, symtensor4< T > &aux4, TypeGfac g2, TypeGfac g3, TypeGfac g4)
void myflush(FILE *fstream)
#define TREE_NUM_BEFORE_NODESPLIT