MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
density.c
Go to the documentation of this file.
1 #include <mpi.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6 #include <gsl/gsl_math.h>
7 #include <omp.h>
8 
9 #include "physconst.h"
10 #include "walltime.h"
11 #include "cooling.h"
12 #include "density.h"
13 #include "treewalk.h"
14 #include "timefac.h"
15 #include "slotsmanager.h"
16 #include "timestep.h"
17 #include "utils.h"
18 #include "gravity.h"
19 #include "winds.h"
20 
21 static struct density_params DensityParams;
22 
23 /*Set cooling module parameters from a cooling_params struct for the tests*/
24 void
26 {
27  DensityParams = dp;
28 }
29 
30 /*Set the parameters of the density module*/
31 void
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 }
53 
54 double
55 GetNumNgb(enum DensityKernelType KernelType)
56 {
58  density_kernel_init(&kernel, 1.0, KernelType);
60 }
61 
64 {
66 }
67 
68 /* The evolved entropy at drift time: evolved dlog a.
69  * Used to predict pressure and entropy for SPH */
70 MyFloat
71 SPH_EntVarPred(int PI, double MinEgySpec, double a3inv, double dloga)
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 }
83 
84 /* Get the predicted velocity for a particle
85  * at the current Force computation time ti,
86  * which always coincides with the Drift inttime.
87  * For hydro forces.*/
88 void
89 SPH_VelPred(int i, MyFloat * VelPred, const double FgravkickB, double gravkick, double hydrokick)
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 }
97 
100 typedef struct {
105 
106 typedef struct
107 {
109  double Vel[3];
111  int Type;
114 
115 typedef struct {
117 
118  /*These are only used for density independent SPH*/
121 
126  MyFloat Rot[3];
127  /*Only used if sfr_need_to_compute_sph_grad_rho is true*/
128  MyFloat GradRho[3];
130 
131 struct DensityPriv {
132  /* Predicted quantities computed during for density and reused during hydro.*/
134  /* The gradient of the density, used sometimes during star formation.
135  * May be NULL.*/
137  /* Current number of neighbours*/
139  /* Lower and upper bounds on smoothing length*/
141  MyFloat (*Rot)[3];
142  /* This is the DhsmlDensityFactor for the pure density,
143  * not the entropy weighted density.
144  * If DensityIndependentSphOn = 0 then DhsmlEgyDensityFactor and DhsmlDensityFactor
145  * are the same and this is not used.
146  * If DensityIndependentSphOn = 1 then this is used to set DhsmlEgyDensityFactor.*/
151  double DesNumNgb;
153  double MinGasHsml;
154  /* Are there potentially black holes?*/
156 
157  /* For computing the predicted quantities dynamically during the treewalk.*/
158  double a3inv;
159  double MinEgySpec;
161  double FgravkickB;
162  double gravkicks[TIMEBINS+1];
163  double hydrokicks[TIMEBINS+1];
164 };
165 
166 #define DENSITY_GET_PRIV(tw) ((struct DensityPriv*) ((tw)->priv))
167 
168 static void
172  TreeWalkNgbIterDensity * iter,
173  LocalTreeWalk * lv);
174 
175 static int density_haswork(int n, TreeWalk * tw);
176 static void density_postprocess(int i, TreeWalk * tw);
177 static void density_check_neighbours(int i, TreeWalk * tw);
178 
179 static void density_reduce(int place, TreeWalkResultDensity * remote, enum TreeWalkReduceMode mode, TreeWalk * tw);
180 static void density_copy(int place, TreeWalkQueryDensity * I, TreeWalk * tw);
181 
202 void
203 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)
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  {
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 }
314 
315 static void
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 }
337 
338 static void
340 {
341  TREEWALK_REDUCE(DENSITY_GET_PRIV(tw)->NumNgb[place], remote->Ngb);
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 }
373 
374 /******
375  *
376  * This function represents the core of the SPH density computation.
377  *
378  * The neighbours of the particle in the Query are enumerated, and results
379  * are stored into the Result object.
380  *
381  * Upon start-up we initialize the iterator with the density kernels used in
382  * the computation. The assumption is the density kernels are slow to
383  * initialize.
384  *
385  */
386 
387 static void
391  TreeWalkNgbIterDensity * iter,
392  LocalTreeWalk * lv)
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 }
499 
500 static int
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 }
510 
511 static void
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 }
553 
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 }
651 
652 
653 struct sph_pred_data
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 }
663 
664 void
666 {
667  myfree(sph_scratch->VelPred);
668  sph_scratch->VelPred = NULL;
669  myfree(sph_scratch->EntVarPred);
670  sph_scratch->EntVarPred = NULL;
671 }
#define MAXITER
Definition: cooling.c:46
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
void set_densitypar(struct density_params dp)
Definition: density.c:25
struct sph_pred_data slots_allocate_sph_pred_data(int nsph)
Definition: density.c:654
void set_density_params(ParameterSet *ps)
Definition: density.c:32
static struct density_params DensityParams
Definition: density.c:21
void slots_free_sph_pred_data(struct sph_pred_data *sph_scratch)
Definition: density.c:665
static void density_check_neighbours(int i, TreeWalk *tw)
Definition: density.c:554
enum DensityKernelType GetDensityKernelType(void)
Definition: density.c:63
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
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 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_desnumngb(DensityKernel *kernel, double eta)
double density_kernel_wk(DensityKernel *kernel, double u)
DensityKernelType
Definition: densitykernel.h:17
#define NUMDIMS
Definition: densitykernel.h:5
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
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
double FORCE_SOFTENING(int i, int type)
static double kernel(double loga, void *params)
Definition: lightcone.c:59
static double dloga
Definition: lightcone.c:21
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define mymalloc2(name, size)
Definition: mymalloc.h:16
#define myfree(x)
Definition: mymalloc.h:19
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
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define P
Definition: partmanager.h:88
#define GAMMA_MINUS1
Definition: physconst.h:35
#define GAMMA
Definition: physconst.h:34
static Cosmology * CP
Definition: power.c:27
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
#define BHP(i)
Definition: slotsmanager.h:125
#define SPHP(i)
Definition: slotsmanager.h:124
#define SphP
Definition: slotsmanager.h:119
int * ActiveParticle
Definition: timestep.h:13
int64_t NumActiveParticle
Definition: timestep.h:12
double DesNumNgb
Definition: density.c:151
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
double a3inv
Definition: density.c:158
double gravkicks[TIMEBINS+1]
Definition: density.c:162
DriftKickTimes const * times
Definition: density.c:160
MyFloat * GradRho
Definition: density.c:136
double hydrokicks[TIMEBINS+1]
Definition: density.c:163
double MinGasHsml
Definition: density.c:153
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
double FgravkickB
Definition: density.c:161
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
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
TreeWalkQueryBase base
Definition: density.c:108
MyFloat Rot[3]
Definition: density.c:126
MyFloat DhsmlDensity
Definition: density.c:123
MyFloat DhsmlEgyDensity
Definition: density.c:120
TreeWalkResultBase base
Definition: density.c:116
MyFloat GradRho[3]
Definition: density.c:128
int64_t Niteration
Definition: treewalk.h:142
double * minnumngb
Definition: treewalk.h:172
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 * maxnumngb
Definition: treewalk.h:171
double timecomp3
Definition: treewalk.h:125
int ** NPRedo
Definition: treewalk.h:168
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 Redo_thread_alloc
Definition: treewalk.h:169
size_t result_type_elsize
Definition: treewalk.h:96
TreeWalkFillQueryFunction fill
Definition: treewalk.h:101
size_t * NPLeft
Definition: treewalk.h:167
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 MaxNumNgbDeviation
Definition: density.h:12
double DensityResolutionEta
Definition: density.h:11
double MinGasHsmlFractional
Definition: density.h:22
double BlackHoleNgbFactor
Definition: density.h:15
enum DensityKernelType DensityKernelType
Definition: density.h:18
double BlackHoleMaxAccretionRadius
Definition: density.h:16
int64_t size
Definition: slotsmanager.h:12
struct slot_info info[6]
Definition: slotsmanager.h:112
MyFloat * EntVarPred
Definition: density.h:28
MyFloat * VelPred
Definition: density.h:34
int ThisTask
Definition: test_exchange.c:23
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
TreeWalkReduceMode
Definition: treewalk.h:15
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
#define TREEWALK_REDUCE(A, B)
Definition: treewalk.h:189
@ NGB_TREEFIND_ASYMMETRIC
Definition: treewalk.h:12
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
int winds_is_particle_decoupled(int i)
Definition: winds.c:124