MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
Classes | Macros | Functions | Variables
density.c File Reference

SPH density computation and smoothing length determination. More...

#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <gsl/gsl_math.h>
#include <omp.h>
#include "physconst.h"
#include "walltime.h"
#include "cooling.h"
#include "density.h"
#include "treewalk.h"
#include "timefac.h"
#include "slotsmanager.h"
#include "timestep.h"
#include "utils.h"
#include "gravity.h"
#include "winds.h"
Include dependency graph for density.c:

Go to the source code of this file.

Classes

struct  TreeWalkNgbIterDensity
 
struct  TreeWalkQueryDensity
 
struct  TreeWalkResultDensity
 
struct  DensityPriv
 

Macros

#define DENSITY_GET_PRIV(tw)   ((struct DensityPriv*) ((tw)->priv))
 

Functions

void set_densitypar (struct density_params dp)
 
void set_density_params (ParameterSet *ps)
 
double GetNumNgb (enum DensityKernelType KernelType)
 
enum DensityKernelType GetDensityKernelType (void)
 
MyFloat SPH_EntVarPred (int PI, double MinEgySpec, double a3inv, double dloga)
 
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)
 
static int density_haswork (int n, TreeWalk *tw)
 
static void density_postprocess (int i, TreeWalk *tw)
 
static void density_check_neighbours (int i, TreeWalk *tw)
 
static void density_reduce (int place, TreeWalkResultDensity *remote, enum TreeWalkReduceMode mode, TreeWalk *tw)
 
static void density_copy (int place, TreeWalkQueryDensity *I, TreeWalk *tw)
 
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)
 
struct sph_pred_data slots_allocate_sph_pred_data (int nsph)
 
void slots_free_sph_pred_data (struct sph_pred_data *sph_scratch)
 

Variables

static struct density_params DensityParams
 

Detailed Description

SPH density computation and smoothing length determination.

This file contains the "first SPH loop", where the SPH densities and some auxiliary quantities are computed. There is also functionality that corrects the smoothing length if needed.

Definition in file density.c.

Macro Definition Documentation

◆ DENSITY_GET_PRIV

#define DENSITY_GET_PRIV (   tw)    ((struct DensityPriv*) ((tw)->priv))

Definition at line 166 of file density.c.

Function Documentation

◆ density()

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 
)

This function computes the local density for each active SPH particle, the number of neighbours in the current smoothing radius, and the divergence and rotation of the velocity field. The pressure is updated as well. If a particle with its smoothing region is fully inside the local domain, it is not exported to the other processors. The function also detects particles that have a number of neighbours outside the allowed tolerance range. For these particles, the smoothing length is adjusted accordingly, and the density() computation is called again. Note that the smoothing length is not allowed to fall below the lower bound set by MinGasHsml (this may mean that one has to deal with substantially more than normal number of neighbours.)

Definition at line 203 of file density.c.

204 {
205  TreeWalk tw[1] = {{0}};
206  struct DensityPriv priv[1];
207 
208  tw->ev_label = "DENSITY";
210  tw->NoNgblist = 1;
213  tw->haswork = density_haswork;
219  tw->priv = priv;
220  tw->tree = tree;
221 
222  int i;
223 
224  double timeall = 0;
225  double timecomp, timecomm, timewait;
226  const double atime = exp(loga_from_ti(times.Ti_Current));
227 
228  walltime_measure("/Misc");
229 
230  DENSITY_GET_PRIV(tw)->Left = (MyFloat *) mymalloc("DENS_PRIV->Left", PartManager->NumPart * sizeof(MyFloat));
231  DENSITY_GET_PRIV(tw)->Right = (MyFloat *) mymalloc("DENS_PRIV->Right", PartManager->NumPart * sizeof(MyFloat));
232  DENSITY_GET_PRIV(tw)->NumNgb = (MyFloat *) mymalloc("DENS_PRIV->NumNgb", PartManager->NumPart * sizeof(MyFloat));
233  DENSITY_GET_PRIV(tw)->Rot = (MyFloat (*) [3]) mymalloc("DENS_PRIV->Rot", SlotsManager->info[0].size * sizeof(priv->Rot[0]));
234  /* This one stores the gradient for h finding. The factor stored in SPHP->DhsmlEgyDensityFactor depends on whether PE SPH is enabled.*/
235  DENSITY_GET_PRIV(tw)->DhsmlDensityFactor = (MyFloat *) mymalloc("DENSITY_GET_PRIV(tw)->DhsmlDensity", PartManager->NumPart * sizeof(MyFloat));
236 
237  DENSITY_GET_PRIV(tw)->update_hsml = update_hsml;
238  DENSITY_GET_PRIV(tw)->DoEgyDensity = DoEgyDensity;
239 
241  DENSITY_GET_PRIV(tw)->MinGasHsml = DensityParams.MinGasHsmlFractional * (FORCE_SOFTENING(1, 1)/2.8);
242 
243  DENSITY_GET_PRIV(tw)->BlackHoleOn = BlackHoleOn;
244  DENSITY_GET_PRIV(tw)->SPH_predicted = SPH_predicted;
245  DENSITY_GET_PRIV(tw)->GradRho = GradRho;
246 
247  /* Init Left and Right: this has to be done before treewalk */
248  #pragma omp parallel for
249  for(i = 0; i < act->NumActiveParticle; i++) {
250  int p_i = act->ActiveParticle ? act->ActiveParticle[i] : i;
251  /* We only really need active particles with work
252  * but I don't want to read the particle table here*/
253  DENSITY_GET_PRIV(tw)->Right[p_i] = tree->BoxSize;
254  DENSITY_GET_PRIV(tw)->NumNgb[p_i] = 0;
255  DENSITY_GET_PRIV(tw)->Left[p_i] = 0;
256  }
257 
258  priv->a3inv = pow(atime, -3);
259  priv->MinEgySpec = MinEgySpec;
260  /* Factor this out since all particles have the same drift time*/
262  memset(priv->gravkicks, 0, sizeof(priv->gravkicks[0])*(TIMEBINS+1));
263  memset(priv->hydrokicks, 0, sizeof(priv->hydrokicks[0])*(TIMEBINS+1));
264  /* Compute the factors to move a current kick times velocity to the drift time velocity.
265  * We need to do the computation for all timebins up to the maximum because even inactive
266  * particles may have interactions. */
267  #pragma omp parallel for
268  for(i = times.mintimebin; i <= TIMEBINS; i++)
269  {
270  priv->gravkicks[i] = get_exact_gravkick_factor(CP, times.Ti_kick[i], times.Ti_Current);
271  priv->hydrokicks[i] = get_exact_hydrokick_factor(CP, times.Ti_kick[i], times.Ti_Current);
272  }
273  priv->times = &times;
274 
275  #pragma omp parallel for
276  for(i = 0; i < act->NumActiveParticle; i++)
277  {
278  int p_i = act->ActiveParticle ? act->ActiveParticle[i] : i;
279  if(P[p_i].Type == 0 && !P[p_i].IsGarbage) {
280  int bin = P[p_i].TimeBin;
281  double dloga = dloga_from_dti(priv->times->Ti_Current - priv->times->Ti_kick[bin], priv->times->Ti_Current);
282  priv->SPH_predicted->EntVarPred[P[p_i].PI] = SPH_EntVarPred(P[p_i].PI, priv->MinEgySpec, priv->a3inv, dloga);
283  SPH_VelPred(p_i, priv->SPH_predicted->VelPred + 3 * P[p_i].PI, priv->FgravkickB, priv->gravkicks[bin], priv->hydrokicks[bin]);
284  }
285  }
286 
287  /* allocate buffers to arrange communication */
288 
289  walltime_measure("/SPH/Density/Init");
290 
291  /* Do the treewalk with looping for hsml*/
293 
299 
300 
301  /* collect some timing information */
302 
304 
305  timecomp = tw->timecomp3 + tw->timecomp1 + tw->timecomp2;
306  timewait = tw->timewait1 + tw->timewait2;
307  timecomm = tw->timecommsumm1 + tw->timecommsumm2;
308 
309  walltime_add("/SPH/Density/Compute", timecomp);
310  walltime_add("/SPH/Density/Wait", timewait);
311  walltime_add("/SPH/Density/Comm", timecomm);
312  walltime_add("/SPH/Density/Misc", timeall - (timecomp + timewait + timecomm));
313 }
void SPH_VelPred(int i, MyFloat *VelPred, const double FgravkickB, double gravkick, double hydrokick)
Definition: density.c:89
static void density_ngbiter(TreeWalkQueryDensity *I, TreeWalkResultDensity *O, TreeWalkNgbIterDensity *iter, LocalTreeWalk *lv)
Definition: density.c:388
double GetNumNgb(enum DensityKernelType KernelType)
Definition: density.c:55
MyFloat SPH_EntVarPred(int PI, double MinEgySpec, double a3inv, double dloga)
Definition: density.c:71
static void density_copy(int place, TreeWalkQueryDensity *I, TreeWalk *tw)
Definition: density.c:316
static struct density_params DensityParams
Definition: density.c:21
static void density_reduce(int place, TreeWalkResultDensity *remote, enum TreeWalkReduceMode mode, TreeWalk *tw)
Definition: density.c:339
static void density_postprocess(int i, TreeWalk *tw)
Definition: density.c:512
static int density_haswork(int n, TreeWalk *tw)
Definition: density.c:501
#define DENSITY_GET_PRIV(tw)
Definition: density.c:166
double FORCE_SOFTENING(int i, int type)
static double dloga
Definition: lightcone.c:21
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define myfree(x)
Definition: mymalloc.h:19
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define P
Definition: partmanager.h:88
static Cosmology * CP
Definition: power.c:27
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
int * ActiveParticle
Definition: timestep.h:13
int64_t NumActiveParticle
Definition: timestep.h:12
int update_hsml
Definition: density.c:148
int DoEgyDensity
Definition: density.c:149
struct sph_pred_data * SPH_predicted
Definition: density.c:133
MyFloat * Left
Definition: density.c:140
DriftKickTimes const * times
Definition: density.c:160
MyFloat * GradRho
Definition: density.c:136
MyFloat(* Rot)[3]
Definition: density.c:141
MyFloat * NumNgb
Definition: density.c:138
int BlackHoleOn
Definition: density.c:155
double MinEgySpec
Definition: density.c:159
MyFloat * Right
Definition: density.c:140
MyFloat * DhsmlDensityFactor
Definition: density.c:147
inttime_t PM_kick
Definition: timestep.h:31
inttime_t Ti_Current
Definition: timestep.h:27
inttime_t Ti_kick[TIMEBINS+1]
Definition: timestep.h:23
int mintimebin
Definition: timestep.h:20
double BoxSize
Definition: forcetree.h:106
void * priv
Definition: treewalk.h:85
TreeWalkHasWorkFunction haswork
Definition: treewalk.h:100
size_t ngbiter_type_elsize
Definition: treewalk.h:97
double timecomp2
Definition: treewalk.h:124
double timecomp3
Definition: treewalk.h:125
double timecommsumm1
Definition: treewalk.h:126
const ForceTree * tree
Definition: treewalk.h:88
TreeWalkProcessFunction postprocess
Definition: treewalk.h:104
TreeWalkNgbIterFunction ngbiter
Definition: treewalk.h:103
TreeWalkReduceResultFunction reduce
Definition: treewalk.h:102
const char * ev_label
Definition: treewalk.h:91
double timewait2
Definition: treewalk.h:122
int NoNgblist
Definition: treewalk.h:156
TreeWalkVisitFunction visit
Definition: treewalk.h:99
size_t result_type_elsize
Definition: treewalk.h:96
TreeWalkFillQueryFunction fill
Definition: treewalk.h:101
double timecomp1
Definition: treewalk.h:123
double timewait1
Definition: treewalk.h:121
double timecommsumm2
Definition: treewalk.h:127
size_t query_type_elsize
Definition: treewalk.h:95
double MinGasHsmlFractional
Definition: density.h:22
enum DensityKernelType DensityKernelType
Definition: density.h:18
int64_t size
Definition: slotsmanager.h:12
struct slot_info info[6]
Definition: slotsmanager.h:112
double loga_from_ti(int ti)
Definition: test_timefac.c:51
double dloga_from_dti(inttime_t dti, const inttime_t Ti_Current)
Definition: timebinmgr.c:256
#define TIMEBINS
Definition: timebinmgr.h:13
double get_exact_hydrokick_factor(Cosmology *CP, inttime_t ti0, inttime_t ti1)
Definition: timefac.c:75
double get_exact_gravkick_factor(Cosmology *CP, inttime_t ti0, inttime_t ti1)
Definition: timefac.c:70
int treewalk_visit_nolist_ngbiter(TreeWalkQueryBase *I, TreeWalkResultBase *O, LocalTreeWalk *lv)
Definition: treewalk.c:1143
void treewalk_do_hsml_loop(TreeWalk *tw, int *queue, int64_t queuesize, int update_hsml)
Definition: treewalk.c:1254
int(* TreeWalkVisitFunction)(TreeWalkQueryBase *input, TreeWalkResultBase *output, LocalTreeWalk *lv)
Definition: treewalk.h:68
void(* TreeWalkReduceResultFunction)(const int j, TreeWalkResultBase *result, const enum TreeWalkReduceMode mode, TreeWalk *tw)
Definition: treewalk.h:76
void(* TreeWalkProcessFunction)(const int i, TreeWalk *tw)
Definition: treewalk.h:73
void(* TreeWalkNgbIterFunction)(TreeWalkQueryBase *input, TreeWalkResultBase *output, TreeWalkNgbIterBase *iter, LocalTreeWalk *lv)
Definition: treewalk.h:70
void(* TreeWalkFillQueryFunction)(const int j, TreeWalkQueryBase *query, TreeWalk *tw)
Definition: treewalk.h:75
LOW_PRECISION MyFloat
Definition: types.h:19
#define walltime_measure(name)
Definition: walltime.h:8
#define WALLTIME_IGNORE
Definition: walltime.h:6
#define walltime_add(name, dt)
Definition: walltime.h:9

References DensityPriv::a3inv, ActiveParticles::ActiveParticle, DensityPriv::BlackHoleOn, ForceTree::BoxSize, CP, density_copy(), DENSITY_GET_PRIV, density_haswork(), density_ngbiter(), density_postprocess(), density_reduce(), density_params::DensityKernelType, DensityParams, DensityPriv::DhsmlDensityFactor, dloga, dloga_from_dti(), DensityPriv::DoEgyDensity, sph_pred_data::EntVarPred, TreeWalk::ev_label, DensityPriv::FgravkickB, TreeWalk::fill, FORCE_SOFTENING(), get_exact_gravkick_factor(), get_exact_hydrokick_factor(), GetNumNgb(), DensityPriv::GradRho, DensityPriv::gravkicks, TreeWalk::haswork, DensityPriv::hydrokicks, slots_manager_type::info, DensityPriv::Left, loga_from_ti(), DensityPriv::MinEgySpec, density_params::MinGasHsmlFractional, DriftKickTimes::mintimebin, myfree, mymalloc, TreeWalk::ngbiter, TreeWalk::ngbiter_type_elsize, TreeWalk::NoNgblist, ActiveParticles::NumActiveParticle, DensityPriv::NumNgb, part_manager_type::NumPart, P, PartManager, DriftKickTimes::PM_kick, TreeWalk::postprocess, TreeWalk::priv, TreeWalk::query_type_elsize, TreeWalk::reduce, TreeWalk::result_type_elsize, DensityPriv::Right, DensityPriv::Rot, slot_info::size, SlotsManager, SPH_EntVarPred(), DensityPriv::SPH_predicted, SPH_VelPred(), DriftKickTimes::Ti_Current, DriftKickTimes::Ti_kick, TIMEBINS, TreeWalk::timecommsumm1, TreeWalk::timecommsumm2, TreeWalk::timecomp1, TreeWalk::timecomp2, TreeWalk::timecomp3, DensityPriv::times, TreeWalk::timewait1, TreeWalk::timewait2, TreeWalk::tree, treewalk_do_hsml_loop(), treewalk_visit_nolist_ngbiter(), DensityPriv::update_hsml, sph_pred_data::VelPred, TreeWalk::visit, walltime_add, WALLTIME_IGNORE, and walltime_measure.

Referenced by density_postprocess(), do_density_test(), get_compton_cooling(), get_equilib_ne(), get_heatingcooling_rate(), get_helium_ion_phys_cgs(), get_individual_cooling(), get_ne_by_nh(), get_neutral_fraction_phys_cgs(), get_temp(), run(), runfof(), setup_density_indep_entropy(), and setup_smoothinglengths().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ density_check_neighbours()

void density_check_neighbours ( int  i,
TreeWalk tw 
)
static

Definition at line 554 of file density.c.

555 {
556  /* now check whether we had enough neighbours */
557  int tid = omp_get_thread_num();
558  double desnumngb = DENSITY_GET_PRIV(tw)->DesNumNgb;
559 
560  if(DENSITY_GET_PRIV(tw)->BlackHoleOn && P[i].Type == 5)
561  desnumngb = desnumngb * DensityParams.BlackHoleNgbFactor;
562 
563  MyFloat * Left = DENSITY_GET_PRIV(tw)->Left;
564  MyFloat * Right = DENSITY_GET_PRIV(tw)->Right;
565  MyFloat * NumNgb = DENSITY_GET_PRIV(tw)->NumNgb;
566 
567  if(NumNgb[i] < (desnumngb - DensityParams.MaxNumNgbDeviation) ||
568  (NumNgb[i] > (desnumngb + DensityParams.MaxNumNgbDeviation)))
569  {
570  /* This condition is here to prevent the density code looping forever if it encounters
571  * multiple particles at the same position. If this happens you likely have worse
572  * problems anyway, so warn also. */
573  if((Right[i] - Left[i]) < 1.0e-3 * Left[i])
574  {
575  /* If this happens probably the exchange is screwed up and all your particles have moved to (0,0,0)*/
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];
579  return;
580  }
581 
582  /* If we need more neighbours, move the lower bound up. If we need fewer, move the upper bound down.*/
583  if(NumNgb[i] < desnumngb) {
584  Left[i] = P[i].Hsml;
585  } else {
586  Right[i] = P[i].Hsml;
587  }
588 
589  /* Next step is geometric mean of previous. */
590  if((Right[i] < tw->tree->BoxSize && Left[i] > 0) || (P[i].Hsml * 1.26 > 0.99 * tw->tree->BoxSize))
591  P[i].Hsml = pow(0.5 * (pow(Left[i], 3) + pow(Right[i], 3)), 1.0 / 3);
592  else
593  {
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);
596 
597  MyFloat DensFac = DENSITY_GET_PRIV(tw)->DhsmlDensityFactor[i];
598  double fac = 1.26;
599  if(NumNgb[i] > 0)
600  fac = 1 - (NumNgb[i] - desnumngb) / (NUMDIMS * NumNgb[i]) * DensFac;
601 
602  /* Find the initial bracket using the kernel gradients*/
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)
605  fac = 1.26;
606 
607  if(Right[i] < 0.99*tw->tree->BoxSize && Left[i] == 0)
608  if(DensFac <=0 || fac < 1./3)
609  fac = 1./3;
610 
611  P[i].Hsml *= fac;
612  }
613 
614  if(DENSITY_GET_PRIV(tw)->BlackHoleOn && P[i].Type == 5)
616  {
618  return;
619  }
620 
621  if(Right[i] < DENSITY_GET_PRIV(tw)->MinGasHsml) {
622  P[i].Hsml = DENSITY_GET_PRIV(tw)->MinGasHsml;
623  return;
624  }
625  /* More work needed: add this particle to the redo queue*/
626  tw->NPRedo[tid][tw->NPLeft[tid]] = i;
627  tw->NPLeft[tid] ++;
628  if(tw->NPLeft[tid] > tw->Redo_thread_alloc)
629  endrun(5, "Particle %d on thread %d exceeded allocated size of redo queue %ld\n", tw->NPLeft[tid], tid, tw->Redo_thread_alloc);
630  }
631  else {
632  /* We might have got here by serendipity, without bounding.*/
633  if(DENSITY_GET_PRIV(tw)->BlackHoleOn && P[i].Type == 5)
636  if(P[i].Hsml < DENSITY_GET_PRIV(tw)->MinGasHsml)
637  P[i].Hsml = DENSITY_GET_PRIV(tw)->MinGasHsml;
638  }
639  if(tw->maxnumngb[tid] < NumNgb[i])
640  tw->maxnumngb[tid] = NumNgb[i];
641  if(tw->minnumngb[tid] > NumNgb[i])
642  tw->minnumngb[tid] = NumNgb[i];
643 
644  if(tw->Niteration >= MAXITER - 10)
645  {
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]);
649  }
650 }
#define MAXITER
Definition: cooling.c:46
#define NUMDIMS
Definition: densitykernel.h:5
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
int64_t Niteration
Definition: treewalk.h:142
double * minnumngb
Definition: treewalk.h:172
double * maxnumngb
Definition: treewalk.h:171
int ** NPRedo
Definition: treewalk.h:168
size_t Redo_thread_alloc
Definition: treewalk.h:169
size_t * NPLeft
Definition: treewalk.h:167
double MaxNumNgbDeviation
Definition: density.h:12
double BlackHoleNgbFactor
Definition: density.h:15
double BlackHoleMaxAccretionRadius
Definition: density.h:16

References density_params::BlackHoleMaxAccretionRadius, density_params::BlackHoleNgbFactor, ForceTree::BoxSize, DENSITY_GET_PRIV, DensityParams, endrun(), MAXITER, TreeWalk::maxnumngb, density_params::MaxNumNgbDeviation, message(), TreeWalk::minnumngb, TreeWalk::Niteration, TreeWalk::NPLeft, TreeWalk::NPRedo, NUMDIMS, P, TreeWalk::Redo_thread_alloc, and TreeWalk::tree.

Referenced by density_postprocess().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ density_copy()

static void density_copy ( int  place,
TreeWalkQueryDensity I,
TreeWalk tw 
)
static

Definition at line 316 of file density.c.

317 {
318  I->Hsml = P[place].Hsml;
319 
320  I->Type = P[place].Type;
321 
322  if(P[place].Type != 0)
323  {
324  I->Vel[0] = P[place].Vel[0];
325  I->Vel[1] = P[place].Vel[1];
326  I->Vel[2] = P[place].Vel[2];
327  }
328  else
329  {
330  MyFloat * velpred = DENSITY_GET_PRIV(tw)->SPH_predicted->VelPred;
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];
334  }
335 
336 }

References DENSITY_GET_PRIV, TreeWalkQueryDensity::Hsml, P, TreeWalkQueryDensity::Type, and TreeWalkQueryDensity::Vel.

Referenced by density().

Here is the caller graph for this function:

◆ density_haswork()

static int density_haswork ( int  n,
TreeWalk tw 
)
static

Definition at line 501 of file density.c.

502 {
503  /* Don't want a density for swallowed black hole particles*/
504  if(P[n].Swallowed)
505  return 0;
506  if(P[n].Type == 0 || P[n].Type == 5)
507  return 1;
508  return 0;
509 }

References P.

Referenced by density().

Here is the caller graph for this function:

◆ density_ngbiter()

static void density_ngbiter ( TreeWalkQueryDensity I,
TreeWalkResultDensity O,
TreeWalkNgbIterDensity iter,
LocalTreeWalk lv 
)
static

Definition at line 388 of file density.c.

393 {
394  if(iter->base.other == -1) {
395  const double h = I->Hsml;
398 
399  iter->base.Hsml = h;
400  iter->base.mask = 1; /* gas only */
402  return;
403  }
404  const int other = iter->base.other;
405  const double r = iter->base.r;
406  const double r2 = iter->base.r2;
407  const double * dist = iter->base.dist;
408 
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]);
412  }
413 
414  if(r2 < iter->kernel.HH)
415  {
416  /* For the BH we wish to exclude wind particles from the density,
417  * because they are excluded from the accretion treewalk.*/
418  if(I->Type == 5 && winds_is_particle_decoupled(other))
419  return;
420 
421  const double u = r * iter->kernel.Hinv;
422  const double wk = density_kernel_wk(&iter->kernel, u);
423  O->Ngb += wk * iter->kernel_volume;
424 
425  const double dwk = density_kernel_dwk(&iter->kernel, u);
426 
427  const double mass_j = P[other].Mass;
428 
429  O->Rho += (mass_j * wk);
430 
431  /* Hinv is here because O->DhsmlDensity is drho / dH.
432  * nothing to worry here */
433  double density_dW = density_kernel_dW(&iter->kernel, u, wk, dwk);
434  O->DhsmlDensity += mass_j * density_dW;
435 
436  /* For the BH and stars only density and dhsmldensity is used.*/
437  if(I->Type != 0)
438  return;
439 
440  struct sph_pred_data * SphP_scratch = DENSITY_GET_PRIV(lv->tw)->SPH_predicted;
441 
442  double EntVarPred;
443  MyFloat VelPred[3];
444  #pragma omp atomic read
445  EntVarPred = SphP_scratch->EntVarPred[P[other].PI];
446  /* Lazily compute the predicted quantities. We can do this
447  * with minimal locking since nothing happens should we compute them twice.
448  * Zero can be the special value since there should never be zero entropy.*/
449  if(EntVarPred == 0) {
450  struct DensityPriv * priv = DENSITY_GET_PRIV(lv->tw);
451  int bin = P[other].TimeBin;
452  double dloga = dloga_from_dti(priv->times->Ti_Current - priv->times->Ti_kick[bin], priv->times->Ti_Current);
453  EntVarPred = SPH_EntVarPred(P[other].PI, priv->MinEgySpec, priv->a3inv, dloga);
454  SPH_VelPred(other, VelPred, priv->FgravkickB, priv->gravkicks[bin], priv->hydrokicks[bin]);
455  /* Note this goes first to avoid threading issues: EntVarPred will only be set after this is done.
456  * The worst that can happen is that some data points get copied twice.*/
457  int i;
458  for(i = 0; i < 3; i++) {
459  #pragma omp atomic write
460  SphP_scratch->VelPred[3 * P[other].PI + i] = VelPred[i];
461  }
462  #pragma omp atomic write
463  SphP_scratch->EntVarPred[P[other].PI] = EntVarPred;
464  }
465  else {
466  int i;
467  for(i = 0; i < 3; i++) {
468  #pragma omp atomic read
469  VelPred[i] = SphP_scratch->VelPred[3 * P[other].PI + i];
470  }
471  }
472  if(DENSITY_GET_PRIV(lv->tw)->DoEgyDensity) {
473  O->EgyRho += mass_j * EntVarPred * wk;
474  O->DhsmlEgyDensity += mass_j * EntVarPred * density_dW;
475  }
476 
477  if(r > 0)
478  {
479  double fac = mass_j * dwk / r;
480  double dv[3];
481  double rot[3];
482  int d;
483  for(d = 0; d < 3; d ++) {
484  dv[d] = I->Vel[d] - VelPred[d];
485  }
486  O->Div += -fac * dotproduct(dist, dv);
487 
488  crossproduct(dv, dist, rot);
489  for(d = 0; d < 3; d ++) {
490  O->Rot[d] += fac * rot[d];
491  }
492  if(DENSITY_GET_PRIV(lv->tw)->GradRho) {
493  for (d = 0; d < 3; d ++)
494  O->GradRho[d] += fac * dist[d];
495  }
496  }
497  }
498 }
double density_kernel_dwk(DensityKernel *kernel, double u)
double(* wk)(DensityKernel *kernel, double q)
Definition: densitykernel.c:94
double(* dwk)(DensityKernel *kernel, double q)
Definition: densitykernel.c:95
double density_kernel_volume(DensityKernel *kernel)
void density_kernel_init(DensityKernel *kernel, double H, enum DensityKernelType type)
double density_kernel_wk(DensityKernel *kernel, double u)
static double dotproduct(const double v1[3], const double v2[3])
Definition: densitykernel.h:53
static void crossproduct(const double v1[3], const double v2[3], double out[3])
Definition: densitykernel.h:63
static double density_kernel_dW(DensityKernel *kernel, double u, double wk, double dwk)
Definition: densitykernel.h:47
static double kernel(double loga, void *params)
Definition: lightcone.c:59
double a3inv
Definition: density.c:158
double gravkicks[TIMEBINS+1]
Definition: density.c:162
double hydrokicks[TIMEBINS+1]
Definition: density.c:163
double FgravkickB
Definition: density.c:161
TreeWalk * tw
Definition: treewalk.h:47
double dist[3]
Definition: treewalk.h:40
enum NgbTreeFindSymmetric symmetric
Definition: treewalk.h:37
DensityKernel kernel
Definition: density.c:102
TreeWalkNgbIterBase base
Definition: density.c:101
MyFloat Rot[3]
Definition: density.c:126
MyFloat DhsmlDensity
Definition: density.c:123
MyFloat DhsmlEgyDensity
Definition: density.c:120
MyFloat GradRho[3]
Definition: density.c:128
MyFloat * EntVarPred
Definition: density.h:28
MyFloat * VelPred
Definition: density.h:34
@ NGB_TREEFIND_ASYMMETRIC
Definition: treewalk.h:12
int winds_is_particle_decoupled(int i)
Definition: winds.c:124

References DensityPriv::a3inv, TreeWalkNgbIterDensity::base, crossproduct(), DENSITY_GET_PRIV, density_kernel_dW(), density_kernel_dwk(), density_kernel_init(), density_kernel_volume(), density_kernel_wk(), density_params::DensityKernelType, DensityParams, TreeWalkResultDensity::DhsmlDensity, TreeWalkResultDensity::DhsmlEgyDensity, TreeWalkNgbIterBase::dist, TreeWalkResultDensity::Div, dloga, dloga_from_dti(), dotproduct(), dwk, TreeWalkResultDensity::EgyRho, endrun(), sph_pred_data::EntVarPred, DensityPriv::FgravkickB, TreeWalkResultDensity::GradRho, DensityPriv::gravkicks, DensityKernel::Hinv, TreeWalkQueryDensity::Hsml, TreeWalkNgbIterBase::Hsml, DensityPriv::hydrokicks, TreeWalkNgbIterDensity::kernel, kernel(), TreeWalkNgbIterDensity::kernel_volume, TreeWalkNgbIterBase::mask, DensityPriv::MinEgySpec, TreeWalkResultDensity::Ngb, NGB_TREEFIND_ASYMMETRIC, TreeWalkNgbIterBase::other, P, TreeWalkNgbIterBase::r, TreeWalkNgbIterBase::r2, TreeWalkResultDensity::Rho, TreeWalkResultDensity::Rot, SPH_EntVarPred(), SPH_VelPred(), TreeWalkNgbIterBase::symmetric, DriftKickTimes::Ti_Current, DriftKickTimes::Ti_kick, DensityPriv::times, LocalTreeWalk::tw, TreeWalkQueryDensity::Type, TreeWalkQueryDensity::Vel, sph_pred_data::VelPred, winds_is_particle_decoupled(), and wk.

Referenced by density().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ density_postprocess()

static void density_postprocess ( int  i,
TreeWalk tw 
)
static

Definition at line 512 of file density.c.

513 {
514  MyFloat * DhsmlDens = &(DENSITY_GET_PRIV(tw)->DhsmlDensityFactor[i]);
515  double density = -1;
516  if(P[i].Type == 0)
517  density = SPHP(i).Density;
518  else if(P[i].Type == 5)
519  density = BHP(i).Density;
520  if(density <= 0 && DENSITY_GET_PRIV(tw)->NumNgb[i] > 0) {
521  endrun(12, "Particle %d type %d has bad density: %g\n", i, P[i].Type, density);
522  }
523  *DhsmlDens *= P[i].Hsml / (NUMDIMS * density);
524  *DhsmlDens = 1 / (1 + *DhsmlDens);
525 
526  /* Uses DhsmlDensityFactor and changes Hsml, hence the location.*/
527  if(DENSITY_GET_PRIV(tw)->update_hsml)
529 
530  if(P[i].Type == 0)
531  {
532  int PI = P[i].PI;
533  /*Compute the EgyWeight factors, which are only useful for density independent SPH */
534  if(DENSITY_GET_PRIV(tw)->DoEgyDensity) {
535  struct sph_pred_data * SphP_scratch = DENSITY_GET_PRIV(tw)->SPH_predicted;
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;
542  }
543  else
544  SPHP(i).DhsmlEgyDensityFactor = *DhsmlDens;
545 
546  MyFloat * Rot = DENSITY_GET_PRIV(tw)->Rot[PI];
547  SPHP(i).CurlVel = sqrt(Rot[0] * Rot[0] + Rot[1] * Rot[1] + Rot[2] * Rot[2]) / SPHP(i).Density;
548 
549  SPHP(i).DivVel /= SPHP(i).Density;
550  P[i].DtHsml = (1.0 / NUMDIMS) * SPHP(i).DivVel * P[i].Hsml;
551  }
552 }
static void density_check_neighbours(int i, TreeWalk *tw)
Definition: density.c:554
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)
Definition: density.c:203
#define BHP(i)
Definition: slotsmanager.h:125
#define SPHP(i)
Definition: slotsmanager.h:124

References BHP, density(), density_check_neighbours(), DENSITY_GET_PRIV, endrun(), sph_pred_data::EntVarPred, NUMDIMS, DensityPriv::NumNgb, P, and SPHP.

Referenced by density().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ density_reduce()

static void density_reduce ( int  place,
TreeWalkResultDensity remote,
enum TreeWalkReduceMode  mode,
TreeWalk tw 
)
static

Definition at line 339 of file density.c.

340 {
341  TREEWALK_REDUCE(DENSITY_GET_PRIV(tw)->NumNgb[place], remote->Ngb);
342  TREEWALK_REDUCE(DENSITY_GET_PRIV(tw)->DhsmlDensityFactor[place], remote->DhsmlDensity);
343 
344  if(P[place].Type == 0)
345  {
346  TREEWALK_REDUCE(SPHP(place).Density, remote->Rho);
347 
348  TREEWALK_REDUCE(SPHP(place).DivVel, remote->Div);
349  int pi = P[place].PI;
350  TREEWALK_REDUCE(DENSITY_GET_PRIV(tw)->Rot[pi][0], remote->Rot[0]);
351  TREEWALK_REDUCE(DENSITY_GET_PRIV(tw)->Rot[pi][1], remote->Rot[1]);
352  TREEWALK_REDUCE(DENSITY_GET_PRIV(tw)->Rot[pi][2], remote->Rot[2]);
353 
354  MyFloat * gradrho = DENSITY_GET_PRIV(tw)->GradRho;
355 
356  if(gradrho) {
357  TREEWALK_REDUCE(gradrho[3*pi], remote->GradRho[0]);
358  TREEWALK_REDUCE(gradrho[3*pi+1], remote->GradRho[1]);
359  TREEWALK_REDUCE(gradrho[3*pi+2], remote->GradRho[2]);
360  }
361 
362  /*Only used for density independent SPH*/
363  if(DENSITY_GET_PRIV(tw)->DoEgyDensity) {
364  TREEWALK_REDUCE(SPHP(place).EgyWtDensity, remote->EgyRho);
365  TREEWALK_REDUCE(SPHP(place).DhsmlEgyDensityFactor, remote->DhsmlEgyDensity);
366  }
367  }
368  else if(P[place].Type == 5)
369  {
370  TREEWALK_REDUCE(BHP(place).Density, remote->Rho);
371  }
372 }
#define TREEWALK_REDUCE(A, B)
Definition: treewalk.h:189

References BHP, DENSITY_GET_PRIV, TreeWalkResultDensity::DhsmlDensity, DensityPriv::DhsmlDensityFactor, TreeWalkResultDensity::DhsmlEgyDensity, TreeWalkResultDensity::Div, DensityPriv::DoEgyDensity, TreeWalkResultDensity::EgyRho, TreeWalkResultDensity::GradRho, TreeWalkResultDensity::Ngb, DensityPriv::NumNgb, P, TreeWalkResultDensity::Rho, DensityPriv::Rot, TreeWalkResultDensity::Rot, SPHP, and TREEWALK_REDUCE.

Referenced by density().

Here is the caller graph for this function:

◆ GetDensityKernelType()

enum DensityKernelType GetDensityKernelType ( void  )

Definition at line 55 of file density.c.

64 {
66 }

References density_kernel_desnumngb(), density_kernel_init(), DensityParams, density_params::DensityResolutionEta, and kernel().

Referenced by blackhole_accretion_ngbiter(), blackhole_dynfric_ngbiter(), blackhole_feedback_ngbiter(), do_density_test(), hydro_ngbiter(), metal_return_ngbiter(), petaio_write_header(), set_density_params(), set_init_hsml(), setup_smoothinglengths(), stellar_density(), and stellar_density_ngbiter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetNumNgb()

double GetNumNgb ( enum DensityKernelType  KernelType)

Definition at line 55 of file density.c.

56 {
58  density_kernel_init(&kernel, 1.0, KernelType);
60 }
double density_kernel_desnumngb(DensityKernel *kernel, double eta)
double DensityResolutionEta
Definition: density.h:11

Referenced by density(), do_density_test(), set_density_params(), set_init_hsml(), setup_smoothinglengths(), and stellar_density().

Here is the caller graph for this function:

◆ set_density_params()

void set_density_params ( ParameterSet ps)

Definition at line 32 of file density.c.

33 {
34  int ThisTask;
35  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
36  if(ThisTask == 0) {
37  DensityParams.DensityKernelType = (enum DensityKernelType) param_get_enum(ps, "DensityKernelType");
38  DensityParams.MaxNumNgbDeviation = param_get_double(ps, "MaxNumNgbDeviation");
39  DensityParams.DensityResolutionEta = param_get_double(ps, "DensityResolutionEta");
40  DensityParams.MinGasHsmlFractional = param_get_double(ps, "MinGasHsmlFractional");
41 
44  message(1, "The Density Kernel type is %s\n", kernel.name);
45  message(1, "The Density resolution is %g * mean separation, or %g neighbours\n",
47  /*These two look like black hole parameters but they are really neighbour finding parameters*/
48  DensityParams.BlackHoleNgbFactor = param_get_double(ps, "BlackHoleNgbFactor");
49  DensityParams.BlackHoleMaxAccretionRadius = param_get_double(ps, "BlackHoleMaxAccretionRadius");
50  }
51  MPI_Bcast(&DensityParams, sizeof(struct density_params), MPI_BYTE, 0, MPI_COMM_WORLD);
52 }
enum DensityKernelType GetDensityKernelType(void)
Definition: density.c:63
DensityKernelType
Definition: densitykernel.h:17
double param_get_double(ParameterSet *ps, const char *name)
Definition: paramset.c:336
int param_get_enum(ParameterSet *ps, const char *name)
Definition: paramset.c:378
int ThisTask
Definition: test_exchange.c:23

References density_params::BlackHoleMaxAccretionRadius, density_params::BlackHoleNgbFactor, density_kernel_init(), density_params::DensityKernelType, DensityParams, density_params::DensityResolutionEta, GetDensityKernelType(), GetNumNgb(), kernel(), density_params::MaxNumNgbDeviation, message(), density_params::MinGasHsmlFractional, param_get_double(), param_get_enum(), and ThisTask.

Referenced by read_parameter_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_densitypar()

void set_densitypar ( struct density_params  dp)

Definition at line 25 of file density.c.

26 {
27  DensityParams = dp;
28 }

References DensityParams.

Referenced by do_density_test(), and setup_density().

Here is the caller graph for this function:

◆ slots_allocate_sph_pred_data()

struct sph_pred_data slots_allocate_sph_pred_data ( int  nsph)

Definition at line 554 of file density.c.

655 {
656  struct sph_pred_data sph_scratch;
657  /*Data is allocated high so that we can free the tree around it*/
658  sph_scratch.EntVarPred = (MyFloat *) mymalloc2("EntVarPred", sizeof(MyFloat) * nsph);
659  memset(sph_scratch.EntVarPred, 0, sizeof(sph_scratch.EntVarPred[0]) * nsph);
660  sph_scratch.VelPred = (MyFloat *) mymalloc2("VelPred", sizeof(MyFloat) * 3 * nsph);
661  return sph_scratch;
662 }
#define mymalloc2(name, size)
Definition: mymalloc.h:16

Referenced by run(), runfof(), setup_density(), and setup_smoothinglengths().

Here is the caller graph for this function:

◆ slots_free_sph_pred_data()

void slots_free_sph_pred_data ( struct sph_pred_data sph_scratch)

Definition at line 665 of file density.c.

666 {
667  myfree(sph_scratch->VelPred);
668  sph_scratch->VelPred = NULL;
669  myfree(sph_scratch->EntVarPred);
670  sph_scratch->EntVarPred = NULL;
671 }

References sph_pred_data::EntVarPred, myfree, and sph_pred_data::VelPred.

Referenced by run(), runfof(), and setup_smoothinglengths().

Here is the caller graph for this function:

◆ SPH_EntVarPred()

MyFloat SPH_EntVarPred ( int  PI,
double  MinEgySpec,
double  a3inv,
double  dloga 
)

Definition at line 71 of file density.c.

72 {
73  double EntVarPred = SphP[PI].Entropy + SphP[PI].DtEntropy * dloga;
74  /*Entropy limiter for the predicted entropy: makes sure entropy stays positive. */
75  if(dloga > 0 && EntVarPred < 0.5*SphP[PI].Entropy)
76  EntVarPred = 0.5 * SphP[PI].Entropy;
77  const double enttou = pow(SphP[PI].Density * a3inv, GAMMA_MINUS1) / GAMMA_MINUS1;
78  if(EntVarPred < MinEgySpec / enttou)
79  EntVarPred = MinEgySpec / enttou;
80  EntVarPred = pow(EntVarPred, 1/GAMMA);
81  return EntVarPred;
82 }
#define GAMMA_MINUS1
Definition: physconst.h:35
#define GAMMA
Definition: physconst.h:34
#define SphP
Definition: slotsmanager.h:119

References dloga, GAMMA, GAMMA_MINUS1, and SphP.

Referenced by density(), density_ngbiter(), and hydro_ngbiter().

Here is the caller graph for this function:

◆ SPH_VelPred()

void SPH_VelPred ( int  i,
MyFloat VelPred,
const double  FgravkickB,
double  gravkick,
double  hydrokick 
)

Definition at line 89 of file density.c.

90 {
91  int j;
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];
95  }
96 }

References P, and SPHP.

Referenced by density(), density_ngbiter(), and hydro_ngbiter().

Here is the caller graph for this function:

Variable Documentation

◆ DensityParams

struct density_params DensityParams
static