12#include "gadgetconfig.h"
17#include <gsl/gsl_math.h>
27#include "../data/allvars.h"
28#include "../data/dtypes.h"
29#include "../data/intposconvert.h"
30#include "../data/mymalloc.h"
31#include "../domain/domain.h"
32#include "../fof/fof.h"
33#include "../gravtree/gravtree.h"
34#include "../logs/timer.h"
35#include "../main/simulation.h"
36#include "../mpi_utils/generic_comm.h"
37#include "../mpi_utils/mpi_utils.h"
38#include "../subfind/subfind.h"
39#include "../system/system.h"
53#ifdef SUBFIND_STORE_LOCAL_DENSITY
59#ifdef SUBFIND_STORE_LOCAL_DENSITY
63template <
typename T_tree,
typename T_domain,
typename T_partset>
64class subdens_comm :
public generic_comm<subdens_in, subdens_out, T_tree, T_domain, T_partset>
74 subdens_comm(T_domain *dptr, T_tree *tptr, T_partset *pptr) : gcomm(dptr, tptr, pptr) {}
79 in->IntPos[0] = Tp->P[i].IntPos[0];
80 in->IntPos[1] = Tp->P[i].IntPos[1];
81 in->IntPos[2] = Tp->P[i].IntPos[2];
82 in->Hsml = Tp->PS[i].v.DM_Hsml;
86 void out2particle(subdens_out *out,
int i,
int mode)
override
90 DM_NumNgb[i] = out->Ngb;
91 Tp->PS[i].u.s.u.DM_Density = out->Rho;
92#ifdef SUBFIND_STORE_LOCAL_DENSITY
96 Tp->PS[i].SubfindVelDisp = out->VelDisp;
101 DM_NumNgb[i] += out->Ngb;
102 Tp->PS[i].u.s.u.DM_Density += out->Rho;
103#ifdef SUBFIND_STORE_LOCAL_DENSITY
107 Tp->PS[i].SubfindVelDisp += out->VelDisp;
116 int evaluate(
int target,
int mode,
int thread_id,
int action, subdens_in *in,
int numnodes,
node_info *firstnode,
117 subdens_out &out)
override
120 double hsml = in->Hsml;
122 double h2 = hsml * hsml;
123 double hinv = 1.0 / hsml;
124 double hinv3 = hinv * hinv * hinv;
128#ifdef SUBFIND_STORE_LOCAL_DENSITY
135 for(
int k = 0; k < numnodes; k++)
144 no = firstnode[k].
Node;
145 no = Tree->get_nodep(no)->nextnode;
148 unsigned int shmrank = Tree->TreeSharedMem_ThisTask;
154 typename T_partset::pdata *P;
156 if(no < Tree->MaxPart)
159 P = Tree->get_Pp(no, shmrank);
161 no = Tree->get_nextnodep(shmrank)[no];
164 Tp->nearest_image_intpos_to_pos(P->IntPos, intpos, dxyz);
166 r2 = dxyz[0] * dxyz[0];
170 r2 += dxyz[1] * dxyz[1];
174 r2 += dxyz[2] * dxyz[2];
181 else if(no < Tree->MaxPart + Tree->MaxNodes)
185 if(no < Tree->FirstNonTopLevelNode)
190 gravnode *current = Tree->get_nodep(no, shmrank);
196 Tp->nearest_image_intpos_to_pos(current->
center.da, intpos,
201 double dist = hsml + lenhalf;
203 if(
fabs(dxyz[0]) > dist)
205 if(
fabs(dxyz[1]) > dist)
207 if(
fabs(dxyz[2]) > dist)
211 dist +=
FACT1 * 2.0 * lenhalf;
212 if(dxyz[0] * dxyz[0] + dxyz[1] * dxyz[1] + dxyz[2] * dxyz[2] > dist * dist)
220 else if(no >= Tree->ImportedNodeOffset)
222 int n = no - Tree->ImportedNodeOffset;
223 no = Tree->Nextnode[no - Tree->MaxNodes];
227 Tp->nearest_image_intpos_to_pos(Tree->Points[n].IntPos, intpos,
230 r2 = dxyz[0] * dxyz[0];
234 r2 += dxyz[1] * dxyz[1];
238 r2 += dxyz[2] * dxyz[2];
242 mass = Tree->Points[n].Mass;
243 type = Tree->Points[n].Type;
251 Tree->tree_export_node_threads(no, target, &Thread);
253 no = Tree->Nextnode[no - Tree->MaxNodes];
259 if(is_type_primary_link_type(type))
266#ifdef SUBFIND_STORE_LOCAL_DENSITY
270 v2sum += P->Vel[0] * P->Vel[0] + P->Vel[1] * P->Vel[1] + P->Vel[2] * P->Vel[2];
274 if(is_type_primary_link_type(type) || is_type_secondary_link_type(type))
278 double u = r * hinv, wk;
293#ifdef SUBFIND_STORE_LOCAL_DENSITY
303template <
typename partset>
304double fof<partset>::subfind_density(
void)
306 mpi_printf(
"SUBFIND: finding total densities around all particles\n");
310 DM_NumNgb = (
int *)
Mem.mymalloc_movable(&DM_NumNgb,
"DM_NumNgb",
sizeof(
int) * Tp->NumPart);
314 int *targetlist = (
int *)
Mem.mymalloc_movable(&targetlist,
"targetlist",
sizeof(
int) * Tp->NumPart);
316#ifdef SUBFIND_STORE_LOCAL_DENSITY
324 for(
int i = 0; i < Tp->NumPart; i++)
326 Left[i] = Right[i] = 0;
329 Tp->PS[i].u.s.u.DM_Density = 0;
331#ifdef SUBFIND_STORE_LOCAL_DENSITY
332 Tp->PS[i].SubfindHsml = 0;
333 Tp->PS[i].SubfindDensity = 0;
334 Tp->PS[i].SubfindVelDisp = 0;
335 if(is_type_primary_link_type(Tp->P[i].getType()) || is_type_secondary_link_type(Tp->P[i].getType()))
336 targetlist[ntodo++] = i;
339 targetlist[ntodo++] = i;
343 subdens_comm<gravtree<partset>,
domain<partset>, partset> commpattern{FoFDomain, &FoFGravTree, Tp};
356 for(
int n = 0; n < ntodo; n++)
358 int i = targetlist[n];
362 ((Right[i] - Left[i]) > 1.0e-4 * Left[i] || Left[i] == 0 || Right[i] == 0))
365 targetlist[npleft++] = i;
368 Left[i] = (
MyFloat)std::max<double>(Tp->PS[i].v.DM_Hsml, Left[i]);
373 if(Tp->PS[i].v.DM_Hsml < Right[i])
374 Right[i] = Tp->PS[i].v.DM_Hsml;
377 Right[i] = Tp->PS[i].v.DM_Hsml;
383 Tp->intpos_to_pos(Tp->P[i].IntPos, pos);
385 printf(
"SUBFIND: i=%d task=%d ID=%lld Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g\n pos=(%g|%g|%g)\n", i,
386 ThisTask, (
long long)Tp->P[i].ID.get(), Tp->PS[i].v.DM_Hsml, Left[i], Right[i], (
double)DM_NumNgb[i],
387 Right[i] - Left[i], pos[0], pos[1], pos[2]);
391 if(Right[i] > 0 && Left[i] > 0)
392 Tp->PS[i].v.DM_Hsml = (
MyFloat)
pow(0.5 * (
pow(Left[i], 3) +
pow(Right[i], 3)), 1.0 / 3.0);
395 if(Right[i] == 0 && Left[i] == 0)
398 if(Right[i] == 0 && Left[i] > 0)
399 Tp->PS[i].v.DM_Hsml *= 1.26;
401 if(Right[i] > 0 && Left[i] == 0)
402 Tp->PS[i].v.DM_Hsml /= 1.26;
418 mpi_printf(
"SUBFIND: ngb iteration %2d: need to repeat for %15lld particles. (took %g sec)\n", iter, ntot,
422 Terminate(
"failed to converge in neighbour iteration in subfind_density()\n");
427#ifdef SUBFIND_STORE_LOCAL_DENSITY
429 double vel_to_phys = subfind_vel_to_phys_factor();
431 for(
int i = 0; i < Tp->NumPart; i++)
435 Vx[i] /= DM_NumNgb[i];
436 Vy[i] /= DM_NumNgb[i];
437 Vz[i] /= DM_NumNgb[i];
438 Tp->PS[i].SubfindVelDisp /= DM_NumNgb[i];
439 Tp->PS[i].SubfindVelDisp = vel_to_phys *
sqrt(Tp->PS[i].SubfindVelDisp - Vx[i] * Vx[i] - Vy[i] * Vy[i] - Vz[i] * Vz[i]);
442 Tp->PS[i].SubfindVelDisp = 0;
445 Mem.myfree_movable(Vz);
446 Mem.myfree_movable(Vy);
447 Mem.myfree_movable(Vx);
450 Mem.myfree_movable(targetlist);
451 Mem.myfree_movable(Right);
452 Mem.myfree_movable(Left);
453 Mem.myfree_movable(DM_NumNgb);
455#ifdef SUBFIND_STORE_LOCAL_DENSITY
456 for(
int i = 0; i < Tp->NumPart; i++)
458 Tp->PS[i].SubfindHsml = Tp->PS[i].v.DM_Hsml;
459 Tp->PS[i].SubfindDensity = Tp->PS[i].u.s.u.DM_Density;
468double fof<simparticles>::subfind_vel_to_phys_factor(
void)
476#if defined(LIGHTCONE) && defined(LIGHTCONE_PARTICLES_GROUPS)
478double fof<lcparticles>::subfind_vel_to_phys_factor(
void)
484template <
typename partset>
485void fof<partset>::subfind_density_hsml_guess(
void)
487 double hsml_prev = 0;
489 for(
int i = 0; i < Tp->NumPart; i++)
491 if(is_type_primary_link_type(Tp->P[i].getType()))
493 int no = FoFGravTree.Father[i];
495 while(8.0 *
All.
DesNumNgb * Tp->P[i].getMass() > FoFGravTree.get_nodep(no)->mass)
497 int p = FoFGravTree.get_nodep(no)->father;
507 Tp->PS[i].v.DM_Hsml = hsml_prev =
508 (
pow(3.0 / (4.0 *
M_PI) *
All.
DesNumNgb * Tp->P[i].getMass() / FoFGravTree.get_nodep(no)->mass, 1.0 / 3.0) * len);
510 if(Tp->PS[i].v.DM_Hsml == 0)
513 Tp->intpos_to_pos(Tp->P[i].IntPos, pos);
516 "zero hsml guess: Hsml=0 task=%d i=%d no=%d Nodes[no].len=%g Nodes[no].mass=%g P[i].Mass=%g type=%d ID=%llu "
518 ThisTask, i, no, len, FoFGravTree.get_nodep(no)->mass, Tp->P[i].getMass(), Tp->P[i].getType(),
519 (
long long)Tp->P[i].ID.get(), pos[0], pos[1], pos[2]);
525 Tp->PS[i].v.DM_Hsml = hsml_prev;
533#include "../data/simparticles.h"
534template class fof<simparticles>;
536#if defined(LIGHTCONE) && defined(LIGHTCONE_PARTICLES_GROUPS)
537#include "../data/lcparticles.h"
538template class fof<lcparticles>;
global_data_all_processes All
virtual void out2particle(T_out *out, int i, int mode)=0
virtual void particle2in(T_in *in, int i)=0
virtual int evaluate(int target, int mode, int thread_id, int action, T_in *in, int numnodes, node_info *firstnode, T_out &out)=0
double timediff(double t0, double t1)
#define MODE_IMPORTED_PARTICLES
#define MODE_LOCAL_PARTICLES
#define BITS_FOR_POSITIONS
void sumup_large_ints(int n, int *src, long long *res, MPI_Comm comm)
expr pow(half base, half exp)
unsigned char nextnode_shmrank
vector< MyIntPosType > center
unsigned char sibling_shmrank
int SofteningClassOfPartType[NTYPES]
int ComovingIntegrationOn
double MaxNumNgbDeviation
double SofteningTable[NSOFTCLASSES+NSOFTCLASSES_HYDRO]
void myflush(FILE *fstream)