6 #include <gsl/gsl_math.h>
35 MPI_Comm_rank(MPI_COMM_WORLD, &
ThisTask);
45 message(1,
"The Density resolution is %g * mean separation, or %g neighbours\n",
73 double EntVarPred =
SphP[PI].Entropy +
SphP[PI].DtEntropy *
dloga;
75 if(
dloga > 0 && EntVarPred < 0.5*
SphP[PI].Entropy)
76 EntVarPred = 0.5 *
SphP[PI].Entropy;
78 if(EntVarPred < MinEgySpec / enttou)
79 EntVarPred = MinEgySpec / enttou;
80 EntVarPred = pow(EntVarPred, 1/
GAMMA);
89 SPH_VelPred(
int i,
MyFloat * VelPred,
const double FgravkickB,
double gravkick,
double hydrokick)
92 for(j = 0; j < 3; j++) {
93 VelPred[j] =
P[i].Vel[j] + gravkick *
P[i].GravAccel[j]
94 +
P[i].GravPM[j] * FgravkickB + hydrokick *
SPHP(i).HydroAccel[j];
166 #define DENSITY_GET_PRIV(tw) ((struct DensityPriv*) ((tw)->priv))
225 double timecomp, timecomm, timewait;
248 #pragma omp parallel for
258 priv->
a3inv = pow(atime, -3);
267 #pragma omp parallel for
275 #pragma omp parallel for
279 if(
P[p_i].Type == 0 && !
P[p_i].IsGarbage) {
280 int bin =
P[p_i].TimeBin;
312 walltime_add(
"/SPH/Density/Misc", timeall - (timecomp + timewait + timecomm));
318 I->
Hsml =
P[place].Hsml;
320 I->
Type =
P[place].Type;
322 if(
P[place].Type != 0)
324 I->
Vel[0] =
P[place].Vel[0];
325 I->
Vel[1] =
P[place].Vel[1];
326 I->
Vel[2] =
P[place].Vel[2];
331 I->
Vel[0] = velpred[3 *
P[place].PI];
332 I->
Vel[1] = velpred[3 *
P[place].PI + 1];
333 I->
Vel[2] = velpred[3 *
P[place].PI + 2];
344 if(
P[place].Type == 0)
349 int pi =
P[place].PI;
368 else if(
P[place].Type == 5)
395 const double h = I->
Hsml;
405 const double r = iter->
base.
r;
406 const double r2 = iter->
base.
r2;
407 const double * dist = iter->
base.
dist;
409 if(
P[other].Mass == 0) {
410 endrun(12,
"Density found zero mass particle %d type %d id %ld pos %g %g %g\n",
411 other,
P[other].Type,
P[other].ID,
P[other].Pos[0],
P[other].Pos[1],
P[other].Pos[2]);
427 const double mass_j =
P[other].Mass;
429 O->
Rho += (mass_j *
wk);
444 #pragma omp atomic read
451 int bin =
P[other].TimeBin;
458 for(i = 0; i < 3; i++) {
459 #pragma omp atomic write
460 SphP_scratch->
VelPred[3 *
P[other].PI + i] = VelPred[i];
462 #pragma omp atomic write
463 SphP_scratch->
EntVarPred[
P[other].PI] = EntVarPred;
467 for(i = 0; i < 3; i++) {
468 #pragma omp atomic read
469 VelPred[i] = SphP_scratch->
VelPred[3 *
P[other].PI + i];
473 O->
EgyRho += mass_j * EntVarPred *
wk;
479 double fac = mass_j *
dwk / r;
483 for(d = 0; d < 3; d ++) {
484 dv[d] = I->
Vel[d] - VelPred[d];
489 for(d = 0; d < 3; d ++) {
490 O->
Rot[d] += fac * rot[d];
493 for (d = 0; d < 3; d ++)
494 O->
GradRho[d] += fac * dist[d];
506 if(
P[n].Type == 0 ||
P[n].Type == 5)
518 else if(
P[i].Type == 5)
521 endrun(12,
"Particle %d type %d has bad density: %g\n", i,
P[i].Type,
density);
524 *DhsmlDens = 1 / (1 + *DhsmlDens);
536 const double EntPred = SphP_scratch->
EntVarPred[
P[i].PI];
537 if(EntPred <= 0 ||
SPHP(i).EgyWtDensity <=0)
538 endrun(12,
"Particle %d has bad predicted entropy: %g or EgyWtDensity: %g\n", i, EntPred,
SPHP(i).EgyWtDensity);
539 SPHP(i).DhsmlEgyDensityFactor *=
P[i].Hsml/ (
NUMDIMS *
SPHP(i).EgyWtDensity);
540 SPHP(i).DhsmlEgyDensityFactor *= - (*DhsmlDens);
541 SPHP(i).EgyWtDensity /= EntPred;
544 SPHP(i).DhsmlEgyDensityFactor = *DhsmlDens;
547 SPHP(i).CurlVel = sqrt(Rot[0] * Rot[0] + Rot[1] * Rot[1] + Rot[2] * Rot[2]) /
SPHP(i).Density;
557 int tid = omp_get_thread_num();
573 if((Right[i] - Left[i]) < 1.0e-3 * Left[i])
576 message(1,
"Very tight Hsml bounds for i=%d ID=%lu Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g pos=(%g|%g|%g)\n",
577 i,
P[i].ID,
P[i].Hsml, Left[i], Right[i], NumNgb[i], Right[i] - Left[i],
P[i].Pos[0],
P[i].Pos[1],
P[i].Pos[2]);
578 P[i].Hsml = Right[i];
583 if(NumNgb[i] < desnumngb) {
586 Right[i] =
P[i].Hsml;
591 P[i].Hsml = pow(0.5 * (pow(Left[i], 3) + pow(Right[i], 3)), 1.0 / 3);
594 if(!(Right[i] < tw->
tree->
BoxSize) && Left[i] == 0)
595 endrun(8188,
"Cannot occur. Check for memory corruption: i=%d L = %g R = %g N=%g. Type %d, Pos %g %g %g hsml %g Box %g\n", i, Left[i], Right[i], NumNgb[i],
P[i].Type,
P[i].Pos[0],
P[i].Pos[1],
P[i].Pos[2],
P[i].Hsml, tw->
tree->
BoxSize);
600 fac = 1 - (NumNgb[i] - desnumngb) / (
NUMDIMS * NumNgb[i]) * DensFac;
603 if(Right[i] > 0.99 * tw->
tree->
BoxSize && Left[i] > 0)
604 if(DensFac <= 0 || fabs(NumNgb[i] - desnumngb) >= 0.5 * desnumngb || fac > 1.26)
607 if(Right[i] < 0.99*tw->
tree->
BoxSize && Left[i] == 0)
608 if(DensFac <=0 || fac < 1./3)
646 message(1,
"i=%d ID=%lu Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g\n pos=(%g|%g|%g)\n",
647 i,
P[i].ID,
P[i].Hsml, Left[i], Right[i],
648 NumNgb[i], Right[i] - Left[i],
P[i].Pos[0],
P[i].Pos[1],
P[i].Pos[2]);
659 memset(sph_scratch.EntVarPred, 0,
sizeof(sph_scratch.EntVarPred[0]) * nsph);
void SPH_VelPred(int i, MyFloat *VelPred, const double FgravkickB, double gravkick, double hydrokick)
static void density_ngbiter(TreeWalkQueryDensity *I, TreeWalkResultDensity *O, TreeWalkNgbIterDensity *iter, LocalTreeWalk *lv)
double GetNumNgb(enum DensityKernelType KernelType)
MyFloat SPH_EntVarPred(int PI, double MinEgySpec, double a3inv, double dloga)
static void density_copy(int place, TreeWalkQueryDensity *I, TreeWalk *tw)
void set_densitypar(struct density_params dp)
struct sph_pred_data slots_allocate_sph_pred_data(int nsph)
void set_density_params(ParameterSet *ps)
static struct density_params DensityParams
void slots_free_sph_pred_data(struct sph_pred_data *sph_scratch)
static void density_check_neighbours(int i, TreeWalk *tw)
enum DensityKernelType GetDensityKernelType(void)
void density(const ActiveParticles *act, int update_hsml, int DoEgyDensity, int BlackHoleOn, double MinEgySpec, const DriftKickTimes times, Cosmology *CP, struct sph_pred_data *SPH_predicted, MyFloat *GradRho, const ForceTree *const tree)
static void density_reduce(int place, TreeWalkResultDensity *remote, enum TreeWalkReduceMode mode, TreeWalk *tw)
static void density_postprocess(int i, TreeWalk *tw)
static int density_haswork(int n, TreeWalk *tw)
#define DENSITY_GET_PRIV(tw)
double density_kernel_dwk(DensityKernel *kernel, double u)
double(* wk)(DensityKernel *kernel, double q)
double(* dwk)(DensityKernel *kernel, double q)
double density_kernel_volume(DensityKernel *kernel)
void density_kernel_init(DensityKernel *kernel, double H, enum DensityKernelType type)
double density_kernel_desnumngb(DensityKernel *kernel, double eta)
double density_kernel_wk(DensityKernel *kernel, double u)
static double dotproduct(const double v1[3], const double v2[3])
static void crossproduct(const double v1[3], const double v2[3], double out[3])
static double density_kernel_dW(DensityKernel *kernel, double u, double wk, double dwk)
void message(int where, const char *fmt,...)
void endrun(int where, const char *fmt,...)
double FORCE_SOFTENING(int i, int type)
static double kernel(double loga, void *params)
#define mymalloc(name, size)
#define mymalloc2(name, size)
double param_get_double(ParameterSet *ps, const char *name)
int param_get_enum(ParameterSet *ps, const char *name)
struct part_manager_type PartManager[1]
struct slots_manager_type SlotsManager[1]
int64_t NumActiveParticle
struct sph_pred_data * SPH_predicted
double gravkicks[TIMEBINS+1]
DriftKickTimes const * times
double hydrokicks[TIMEBINS+1]
MyFloat * DhsmlDensityFactor
inttime_t Ti_kick[TIMEBINS+1]
enum NgbTreeFindSymmetric symmetric
TreeWalkHasWorkFunction haswork
size_t ngbiter_type_elsize
TreeWalkProcessFunction postprocess
TreeWalkNgbIterFunction ngbiter
TreeWalkReduceResultFunction reduce
TreeWalkVisitFunction visit
size_t result_type_elsize
TreeWalkFillQueryFunction fill
double MaxNumNgbDeviation
double DensityResolutionEta
double MinGasHsmlFractional
double BlackHoleNgbFactor
enum DensityKernelType DensityKernelType
double BlackHoleMaxAccretionRadius
double loga_from_ti(int ti)
double dloga_from_dti(inttime_t dti, const inttime_t Ti_Current)
double get_exact_hydrokick_factor(Cosmology *CP, inttime_t ti0, inttime_t ti1)
double get_exact_gravkick_factor(Cosmology *CP, inttime_t ti0, inttime_t ti1)
int treewalk_visit_nolist_ngbiter(TreeWalkQueryBase *I, TreeWalkResultBase *O, LocalTreeWalk *lv)
void treewalk_do_hsml_loop(TreeWalk *tw, int *queue, int64_t queuesize, int update_hsml)
int(* TreeWalkVisitFunction)(TreeWalkQueryBase *input, TreeWalkResultBase *output, LocalTreeWalk *lv)
void(* TreeWalkReduceResultFunction)(const int j, TreeWalkResultBase *result, const enum TreeWalkReduceMode mode, TreeWalk *tw)
void(* TreeWalkProcessFunction)(const int i, TreeWalk *tw)
void(* TreeWalkNgbIterFunction)(TreeWalkQueryBase *input, TreeWalkResultBase *output, TreeWalkNgbIterBase *iter, LocalTreeWalk *lv)
void(* TreeWalkFillQueryFunction)(const int j, TreeWalkQueryBase *query, TreeWalk *tw)
#define TREEWALK_REDUCE(A, B)
@ NGB_TREEFIND_ASYMMETRIC
#define walltime_measure(name)
#define walltime_add(name, dt)
int winds_is_particle_decoupled(int i)