MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
Classes | Macros | Functions | Variables
winds.c File Reference
#include <math.h>
#include <string.h>
#include <omp.h>
#include "winds.h"
#include "physconst.h"
#include "treewalk.h"
#include "slotsmanager.h"
#include "timebinmgr.h"
#include "walltime.h"
#include "density.h"
#include "hydra.h"
Include dependency graph for winds.c:

Go to the source code of this file.

Classes

struct  WindParams
 
struct  TreeWalkQueryWind
 
struct  TreeWalkResultWind
 
struct  TreeWalkNgbIterWind
 
struct  winddata
 
struct  StarKick
 
struct  WindPriv
 

Macros

#define NWINDHSML   5 /* Number of densities to evaluate for wind weight ngbiter*/
 
#define NUMDMNGB   40 /*Number of DM ngb to evaluate vel dispersion */
 
#define MAXDMDEVIATION   2
 
#define WIND_GET_PRIV(tw)   ((struct WindPriv *) (tw->priv))
 
#define WINDP(i, wind)   wind[P[i].PI]
 

Functions

void set_winds_params (ParameterSet *ps)
 
void init_winds (double FactorSN, double EgySpecSN, double PhysDensThresh, double UnitTime_in_s)
 
int winds_are_subgrid (void)
 
int winds_is_particle_decoupled (int i)
 
void winds_decoupled_hydro (int i, double atime)
 
static void wind_do_kick (int other, double vel, double therm, double atime)
 
static int get_wind_dir (int i, double dir[3])
 
static void get_wind_params (double *vel, double *windeff, double *utherm, const double vdisp, const double time)
 
static void sfr_wind_reduce_weight (int place, TreeWalkResultWind *remote, enum TreeWalkReduceMode mode, TreeWalk *tw)
 
static void sfr_wind_copy (int place, TreeWalkQueryWind *input, TreeWalk *tw)
 
static void sfr_wind_weight_postprocess (const int i, TreeWalk *tw)
 
static void sfr_wind_weight_ngbiter (TreeWalkQueryWind *I, TreeWalkResultWind *O, TreeWalkNgbIterWind *iter, LocalTreeWalk *lv)
 
static void sfr_wind_feedback_ngbiter (TreeWalkQueryWind *I, TreeWalkResultWind *O, TreeWalkNgbIterWind *iter, LocalTreeWalk *lv)
 
int winds_ever_decouple (void)
 
int cmp_by_part_id (const void *a, const void *b)
 
static void winds_find_weights (TreeWalk *tw, struct WindPriv *priv, int *NewStars, int NumNewStars, const double Time, const double hubble, ForceTree *tree)
 
void winds_subgrid (int *MaybeWind, int NumMaybeWind, const double Time, const double hubble, ForceTree *tree, MyFloat *StellarMasses)
 
void winds_and_feedback (int *NewStars, int NumNewStars, const double Time, const double hubble, ForceTree *tree)
 
void winds_evolve (int i, double a3inv, double hubble)
 
static double effdmradius (int place, int i, TreeWalk *tw)
 
int winds_make_after_sf (int i, double sm, double vdisp, double atime)
 

Variables

static struct WindParams wind_params
 

Macro Definition Documentation

◆ MAXDMDEVIATION

#define MAXDMDEVIATION   2

Definition at line 40 of file winds.c.

◆ NUMDMNGB

#define NUMDMNGB   40 /*Number of DM ngb to evaluate vel dispersion */

Definition at line 39 of file winds.c.

◆ NWINDHSML

#define NWINDHSML   5 /* Number of densities to evaluate for wind weight ngbiter*/

Definition at line 38 of file winds.c.

◆ WIND_GET_PRIV

#define WIND_GET_PRIV (   tw)    ((struct WindPriv *) (tw->priv))

Definition at line 250 of file winds.c.

◆ WINDP

#define WINDP (   i,
  wind 
)    wind[P[i].PI]

Definition at line 251 of file winds.c.

Function Documentation

◆ cmp_by_part_id()

int cmp_by_part_id ( const void *  a,
const void *  b 
)

Definition at line 231 of file winds.c.

232 {
233  const struct StarKick * stara = (const struct StarKick * ) a;
234  const struct StarKick * starb = (const struct StarKick *) b;
235  if(stara->part_index > starb->part_index)
236  return 1;
237  if(stara->part_index < starb->part_index)
238  return -1;
239  if(stara->StarDistance > starb->StarDistance)
240  return 1;
241  if(stara->StarDistance < starb->StarDistance)
242  return -1;
243  if(stara->StarID > starb->StarID)
244  return 1;
245  if(stara->StarID < starb->StarID)
246  return -1;
247  return 0;
248 }
int part_index
Definition: winds.c:208
MyIDType StarID
Definition: winds.c:212
double StarDistance
Definition: winds.c:210

References StarKick::part_index, StarKick::StarDistance, and StarKick::StarID.

Referenced by winds_and_feedback().

Here is the caller graph for this function:

◆ effdmradius()

static double effdmradius ( int  place,
int  i,
TreeWalk tw 
)
inlinestatic

Definition at line 422 of file winds.c.

423 {
424  struct winddata * Windd = WIND_GET_PRIV(tw)->Winddata;
425  double left = WINDP(place, Windd).Left;
426  double right = WINDP(place, Windd).Right;
427  /*The asymmetry is because it is free to compute extra densities for h < Hsml, but not for h > Hsml*/
428  if (right > 0.99*tw->tree->BoxSize){
429  right = WINDP(place, Windd).DMRadius;
430  }
431  if(left == 0)
432  left = 0.1 * WINDP(place, Windd).DMRadius;
433  /*Evenly split in volume*/
434  double rvol = pow(right, 3);
435  double lvol = pow(left, 3);
436  return pow((1.0*i+1)/(1.0*NWINDHSML+1) * (rvol - lvol) + lvol, 1./3);
437 }
double BoxSize
Definition: forcetree.h:106
const ForceTree * tree
Definition: treewalk.h:88
#define NWINDHSML
Definition: winds.c:38
#define WIND_GET_PRIV(tw)
Definition: winds.c:250
#define WINDP(i, wind)
Definition: winds.c:251

References ForceTree::BoxSize, NWINDHSML, TreeWalk::tree, WIND_GET_PRIV, and WINDP.

Referenced by sfr_wind_copy(), and sfr_wind_weight_postprocess().

Here is the caller graph for this function:

◆ get_wind_dir()

static int get_wind_dir ( int  i,
double  dir[3] 
)
static

Definition at line 614 of file winds.c.

614  {
615  /* v and vmean are in internal units (km/s *a ), not km/s !*/
616  /* returns 0 if particle i is converted to wind. */
617  // message(1, "%ld Making ID=%ld (%g %g %g) to wind with v= %g\n", ID, P[i].ID, P[i].Pos[0], P[i].Pos[1], P[i].Pos[2], v);
618  /* ok, make the particle go into the wind */
619  double theta = acos(2 * get_random_number(P[i].ID + 3) - 1);
620  double phi = 2 * M_PI * get_random_number(P[i].ID + 4);
621 
622  dir[0] = sin(theta) * cos(phi);
623  dir[1] = sin(theta) * sin(phi);
624  dir[2] = cos(theta);
625  return 0;
626 }
#define P
Definition: partmanager.h:88
double get_random_number(uint64_t id)
Definition: system.c:60

References get_random_number(), and P.

Referenced by wind_do_kick().

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

◆ get_wind_params()

static void get_wind_params ( double *  vel,
double *  windeff,
double *  utherm,
const double  vdisp,
const double  time 
)
static

Definition at line 630 of file winds.c.

631 {
632  /* Physical velocity*/
633  double vphys = vdisp / time;
634  *utherm = wind_params.WindThermalFactor * 1.5 * vphys * vphys;
636  *windeff = wind_params.WindEfficiency;
637  *vel = wind_params.WindSpeed * time;
638  } else if(HAS(wind_params.WindModel, WIND_USE_HALO)) {
639  *windeff = pow(wind_params.WindSigma0, 2) / (vphys * vphys + 2 * (*utherm));
640  *vel = wind_params.WindSpeedFactor * vdisp;
641  } else {
642  endrun(1, "WindModel = 0x%X is strange. This shall not happen.\n", wind_params.WindModel);
643  }
644  /* Minimum wind velocity. This ensures particles do not remain in the wind forever*/
645  if(*vel < wind_params.MinWindVelocity * time)
646  *vel = wind_params.MinWindVelocity * time;
647 }
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
double WindEfficiency
Definition: winds.c:26
double WindSpeedFactor
Definition: winds.c:31
double WindThermalFactor
Definition: winds.c:35
enum WindModel WindModel
Definition: winds.c:18
double WindSpeed
Definition: winds.c:27
double WindSigma0
Definition: winds.c:30
double MinWindVelocity
Definition: winds.c:33
#define HAS(val, flag)
Definition: types.h:22
static struct WindParams wind_params
@ WIND_FIXED_EFFICIENCY
Definition: winds.h:17
@ WIND_USE_HALO
Definition: winds.h:16

References endrun(), HAS, WindParams::MinWindVelocity, WIND_FIXED_EFFICIENCY, wind_params, WIND_USE_HALO, WindParams::WindEfficiency, WindParams::WindModel, WindParams::WindSigma0, WindParams::WindSpeed, WindParams::WindSpeedFactor, and WindParams::WindThermalFactor.

Referenced by sfr_wind_feedback_ngbiter().

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

◆ init_winds()

void init_winds ( double  FactorSN,
double  EgySpecSN,
double  PhysDensThresh,
double  UnitTime_in_s 
)

Definition at line 97 of file winds.c.

98 {
99  wind_params.WindSpeed = sqrt(2 * wind_params.WindEnergyFraction * FactorSN * EgySpecSN / (1 - FactorSN));
100  /* Convert wind free travel time from Myr to internal units*/
105  message(0, "Windspeed: %g MaxDelay %g\n", wind_params.WindSpeed, wind_params.MaxWindFreeTravelTime);
106  } else if(HAS(wind_params.WindModel, WIND_USE_HALO)) {
107  message(0, "Reference Windspeed: %g, MaxDelay %g\n", wind_params.WindSigma0 * wind_params.WindSpeedFactor, wind_params.MaxWindFreeTravelTime);
108  } else {
109  /* Check for undefined wind models*/
110  endrun(1, "WindModel = 0x%X is strange. This shall not happen.\n", wind_params.WindModel);
111  }
112 }
void message(int where, const char *fmt,...)
Definition: endrun.c:175
#define SEC_PER_MEGAYEAR
Definition: physconst.h:31
double WindFreeTravelDensThresh
Definition: winds.c:22
double WindEnergyFraction
Definition: winds.c:28
double WindFreeTravelDensFac
Definition: winds.c:20
double MaxWindFreeTravelTime
Definition: winds.c:24

References endrun(), HAS, WindParams::MaxWindFreeTravelTime, message(), SEC_PER_MEGAYEAR, WIND_FIXED_EFFICIENCY, wind_params, WIND_USE_HALO, WindParams::WindEfficiency, WindParams::WindEnergyFraction, WindParams::WindFreeTravelDensFac, WindParams::WindFreeTravelDensThresh, WindParams::WindModel, WindParams::WindSigma0, WindParams::WindSpeed, and WindParams::WindSpeedFactor.

Referenced by init_cooling_and_star_formation().

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

◆ set_winds_params()

void set_winds_params ( ParameterSet ps)

Definition at line 72 of file winds.c.

73 {
74  int ThisTask;
75  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
76  if(ThisTask == 0) {
77  /*Wind model parameters*/
78  wind_params.WindModel = (enum WindModel) param_get_enum(ps, "WindModel");
79  /* The following two are for VS08 and SH03*/
80  wind_params.WindEfficiency = param_get_double(ps, "WindEfficiency");
81  wind_params.WindEnergyFraction = param_get_double(ps, "WindEnergyFraction");
82 
83  /* The following two are for OFJT10*/
84  wind_params.WindSigma0 = param_get_double(ps, "WindSigma0");
85  wind_params.WindSpeedFactor = param_get_double(ps, "WindSpeedFactor");
86 
87  wind_params.WindThermalFactor = param_get_double(ps, "WindThermalFactor");
88  wind_params.MinWindVelocity = param_get_double(ps, "MinWindVelocity");
89  wind_params.MaxWindFreeTravelTime = param_get_double(ps, "MaxWindFreeTravelTime");
90  wind_params.WindFreeTravelLength = param_get_double(ps, "WindFreeTravelLength");
91  wind_params.WindFreeTravelDensFac = param_get_double(ps, "WindFreeTravelDensFac");
92  }
93  MPI_Bcast(&wind_params, sizeof(struct WindParams), MPI_BYTE, 0, MPI_COMM_WORLD);
94 }
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
double WindFreeTravelLength
Definition: winds.c:19
int ThisTask
Definition: test_exchange.c:23
WindModel
Definition: winds.h:12

References WindParams::MaxWindFreeTravelTime, WindParams::MinWindVelocity, param_get_double(), param_get_enum(), ThisTask, wind_params, WindParams::WindEfficiency, WindParams::WindEnergyFraction, WindParams::WindFreeTravelDensFac, WindParams::WindFreeTravelLength, WindParams::WindModel, WindParams::WindSigma0, WindParams::WindSpeedFactor, and WindParams::WindThermalFactor.

Referenced by read_parameter_file().

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

◆ sfr_wind_copy()

static void sfr_wind_copy ( int  place,
TreeWalkQueryWind input,
TreeWalk tw 
)
static

Definition at line 501 of file winds.c.

502 {
503  double dtime = get_dloga_for_bin(P[place].TimeBin, P[place].Ti_drift) / WIND_GET_PRIV(tw)->hubble;
504  struct winddata * Windd = WIND_GET_PRIV(tw)->Winddata;
505 
506  input->ID = P[place].ID;
507  input->Dt = dtime;
508  input->Mass = P[place].Mass;
509  input->Hsml = P[place].Hsml;
510  input->TotalWeight = WINDP(place, Windd).TotalWeight;
511  input->Vdisp = WINDP(place, Windd).Vdisp;
512  int i;
513  for(i=0; i<3; i++)
514  input->Vel[i] = P[place].Vel[i];
515  for(i = 0; i<NWINDHSML; i++){
516  input->DMRadius[i]=effdmradius(place,i,tw);
517  }
518 }
double Mass
Definition: winds.c:46
MyIDType ID
Definition: winds.c:44
double Vdisp
Definition: winds.c:50
double Dt
Definition: winds.c:45
double DMRadius[NWINDHSML]
Definition: winds.c:49
double Hsml
Definition: winds.c:47
double Vel[3]
Definition: winds.c:51
double TotalWeight
Definition: winds.c:48
double get_dloga_for_bin(int timebin, const inttime_t Ti_Current)
Definition: timebinmgr.c:279
static double effdmradius(int place, int i, TreeWalk *tw)
Definition: winds.c:422

References TreeWalkQueryWind::DMRadius, TreeWalkQueryWind::Dt, effdmradius(), get_dloga_for_bin(), TreeWalkQueryWind::Hsml, TreeWalkQueryWind::ID, TreeWalkQueryWind::Mass, NWINDHSML, P, TreeWalkQueryWind::TotalWeight, TreeWalkQueryWind::Vdisp, TreeWalkQueryWind::Vel, WIND_GET_PRIV, and WINDP.

Referenced by winds_find_weights().

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

◆ sfr_wind_feedback_ngbiter()

static void sfr_wind_feedback_ngbiter ( TreeWalkQueryWind I,
TreeWalkResultWind O,
TreeWalkNgbIterWind iter,
LocalTreeWalk lv 
)
static

Definition at line 650 of file winds.c.

654 {
655 
656  /* this evaluator walks the tree and blows wind. */
657 
658  if(iter->base.other == -1) {
659  iter->base.mask = 1;
661  iter->base.Hsml = I->Hsml;
662  return;
663  }
664  int other = iter->base.other;
665  double r = iter->base.r;
666 
667  /* this is radius cut is redundant because the tree walk is asymmetric
668  * we may want to use fancier weighting that requires symmetric in the future. */
669  if(r > I->Hsml) return;
670 
671  /* skip earlier wind particles */
672  if(SPHP(other).DelayTime > 0) return;
673 
674  /* No eligible gas particles not in wind*/
675  if(I->TotalWeight == 0 || I->Vdisp <= 0) return;
676 
677  /* Paranoia*/
678  if(P[other].Type != 0 || P[other].IsGarbage || P[other].Swallowed)
679  return;
680 
681  /* Get the velocity, thermal energy and efficiency of the kick*/
682  double utherm = 0, v=0, windeff = 0;
683  get_wind_params(&v, &windeff, &utherm, I->Vdisp, WIND_GET_PRIV(lv->tw)->Time);
684 
685  double p = windeff * I->Mass / I->TotalWeight;
686  double random = get_random_number(I->ID + P[other].ID);
687 
688  if (random < p && v > 0) {
689  /* Store a potential kick. This might not be the kick actually used,
690  * because another star particle may be closer, but we can resolve
691  * that after the treewalk*/
692  int64_t * nkicks = &WIND_GET_PRIV(lv->tw)->nkicks;
693  /* Use a single global kick list.*/
694  int64_t ikick = atomic_fetch_and_add_64(nkicks, 1);
695  if(ikick >= WIND_GET_PRIV(lv->tw)->maxkicks)
696  endrun(5, "Not enough room in kick queue: %ld > %ld for particle %d starid %ld distance %g\n",
697  ikick, WIND_GET_PRIV(lv->tw)->maxkicks, other, I->ID, r);
698  struct StarKick * kick = &WIND_GET_PRIV(lv->tw)->kicks[ikick];
699  kick->StarDistance = r;
700  kick->StarID = I->ID;
701  kick->StarKickVelocity = v;
702  kick->StarTherm = utherm;
703  kick->part_index = other;
704  }
705 }
#define SPHP(i)
Definition: slotsmanager.h:124
TreeWalk * tw
Definition: treewalk.h:47
double StarKickVelocity
Definition: winds.c:214
double StarTherm
Definition: winds.c:216
enum NgbTreeFindSymmetric symmetric
Definition: treewalk.h:37
TreeWalkNgbIterBase base
Definition: winds.c:65
static int64_t atomic_fetch_and_add_64(int64_t *ptr, int64_t value)
Definition: system.h:68
@ NGB_TREEFIND_ASYMMETRIC
Definition: treewalk.h:12
static void get_wind_params(double *vel, double *windeff, double *utherm, const double vdisp, const double time)
Definition: winds.c:630

References atomic_fetch_and_add_64(), TreeWalkNgbIterWind::base, endrun(), get_random_number(), get_wind_params(), TreeWalkNgbIterBase::Hsml, TreeWalkQueryWind::Hsml, TreeWalkQueryWind::ID, TreeWalkNgbIterBase::mask, TreeWalkQueryWind::Mass, NGB_TREEFIND_ASYMMETRIC, TreeWalkNgbIterBase::other, P, StarKick::part_index, TreeWalkNgbIterBase::r, SPHP, StarKick::StarDistance, StarKick::StarID, StarKick::StarKickVelocity, StarKick::StarTherm, TreeWalkNgbIterBase::symmetric, TreeWalkQueryWind::TotalWeight, LocalTreeWalk::tw, TreeWalkQueryWind::Vdisp, and WIND_GET_PRIV.

Referenced by winds_and_feedback().

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

◆ sfr_wind_reduce_weight()

static void sfr_wind_reduce_weight ( int  place,
TreeWalkResultWind remote,
enum TreeWalkReduceMode  mode,
TreeWalk tw 
)
static

Definition at line 480 of file winds.c.

481 {
482  struct winddata * Windd = WIND_GET_PRIV(tw)->Winddata;
483  TREEWALK_REDUCE(WINDP(place, Windd).TotalWeight, O->TotalWeight);
484 
485  int i;
486  if(mode == 0 || WINDP(place, Windd).maxcmpte > O->maxcmpte)
487  WINDP(place, Windd).maxcmpte = O->maxcmpte;
488  int k;
489  for (i = 0; i < O->maxcmpte; i++){
490  TREEWALK_REDUCE(WINDP(place, Windd).Ngb[i], O->Ngb[i]);
491  TREEWALK_REDUCE(WINDP(place, Windd).V2sum[i], O->V2sum[i]);
492  for(k = 0; k < 3; k ++) {
493  TREEWALK_REDUCE(WINDP(place, Windd).V1sum[i][k], O->V1sum[i][k]);
494  }
495  }
496 // message(1, "Reduce ID=%ld, NGB_first=%d NGB_last=%d maxcmpte = %d, left = %g, right = %g\n",
497 // P[place].ID, O->Ngb[0],O->Ngb[O->maxcmpte-1],WINDP(place, Windd).maxcmpte,WINDP(place, Windd).Left,WINDP(place, Windd).Right);
498 }
double TotalWeight
Definition: winds.c:182
int maxcmpte
Definition: winds.c:188
double V2sum[NWINDHSML]
Definition: winds.c:185
double Ngb[NWINDHSML]
Definition: winds.c:187
double V1sum[NWINDHSML][3]
Definition: winds.c:186
#define TREEWALK_REDUCE(A, B)
Definition: treewalk.h:189

References TreeWalkResultWind::maxcmpte, winddata::maxcmpte, TreeWalkResultWind::Ngb, winddata::Ngb, TreeWalkResultWind::TotalWeight, winddata::TotalWeight, TREEWALK_REDUCE, TreeWalkResultWind::V1sum, winddata::V1sum, TreeWalkResultWind::V2sum, winddata::V2sum, WIND_GET_PRIV, and WINDP.

Referenced by winds_find_weights().

Here is the caller graph for this function:

◆ sfr_wind_weight_ngbiter()

static void sfr_wind_weight_ngbiter ( TreeWalkQueryWind I,
TreeWalkResultWind O,
TreeWalkNgbIterWind iter,
LocalTreeWalk lv 
)
static

Definition at line 521 of file winds.c.

525 {
526  /* this evaluator walks the tree and sums the total mass of surrounding gas
527  * particles as described in VS08. */
528  /* it also calculates the DM dispersion of the nearest 40 DM particles */
529  if(iter->base.other == -1) {
530  double hsearch = DMAX(I->Hsml, I->DMRadius[NWINDHSML-1]);
531  iter->base.Hsml = hsearch;
532  iter->base.mask = 1 + 2; /* gas and dm */
534  O->maxcmpte = NWINDHSML;
535  return;
536  }
537 
538  int other = iter->base.other;
539  double r = iter->base.r;
540  double * dist = iter->base.dist;
541 
542  if(P[other].Type == 0) {
543  if(r > I->Hsml) return;
544  /* skip earlier wind particles, which receive
545  * no feedback energy */
546  if(SPHP(other).DelayTime > 0) return;
547 
548  /* NOTE: think twice if we want a symmetric tree walk when wk is used. */
549  //double wk = density_kernel_wk(&kernel, r);
550  double wk = 1.0;
551  O->TotalWeight += wk * P[other].Mass;
552  /* Sum up all particles visited on this processor*/
553  WIND_GET_PRIV(lv->tw)->nvisited[omp_get_thread_num()]++;
554  }
555 
556  int i;
557  if(P[other].Type == 1) {
558  const double atime = WIND_GET_PRIV(lv->tw)->Time;
559  for(i = 0; i < O->maxcmpte; i++){
560  if(r < I->DMRadius[i]){
561  O->Ngb[i] += 1;
562  int d;
563  for(d = 0; d < 3; d ++) {
564  /* Add hubble flow to relative velocity. */
565  double vel = P[other].Vel[d] - I->Vel[d] + WIND_GET_PRIV(lv->tw)->hubble * atime * atime * dist[d];
566  O->V1sum[i][d] += vel;
567  O->V2sum[i] += vel * vel;
568  }
569  }
570  }
571  }
572 
573  for(i = 0; i<NWINDHSML; i++){
574  if(O->Ngb[i] > NUMDMNGB){
575  O->maxcmpte = i+1;
576  iter->base.Hsml = I->DMRadius[i];
577  break;
578  }
579  }
580 
581  /*
582  message(1, "ThisTask = %d %ld ngb=%d NGB=%d TotalWeight=%g V2sum=%g V1sum=%g %g %g\n",
583  ThisTask, I->ID, numngb, O->Ngb, O->TotalWeight, O->V2sum,
584  O->V1sum[0], O->V1sum[1], O->V1sum[2]);
585  */
586 }
double(* wk)(DensityKernel *kernel, double q)
Definition: densitykernel.c:94
double dist[3]
Definition: treewalk.h:40
double TotalWeight
Definition: winds.c:56
double Ngb[NWINDHSML]
Definition: winds.c:59
double V2sum[NWINDHSML]
Definition: winds.c:58
double V1sum[NWINDHSML][3]
Definition: winds.c:57
#define DMAX(x, y)
Definition: test_interp.c:11
#define NUMDMNGB
Definition: winds.c:39

References TreeWalkNgbIterWind::base, TreeWalkNgbIterBase::dist, DMAX, TreeWalkQueryWind::DMRadius, winddata::DMRadius, TreeWalkNgbIterBase::Hsml, TreeWalkQueryWind::Hsml, TreeWalkNgbIterBase::mask, TreeWalkResultWind::maxcmpte, TreeWalkResultWind::Ngb, NGB_TREEFIND_ASYMMETRIC, NUMDMNGB, NWINDHSML, TreeWalkNgbIterBase::other, P, TreeWalkNgbIterBase::r, SPHP, TreeWalkNgbIterBase::symmetric, TreeWalkResultWind::TotalWeight, LocalTreeWalk::tw, TreeWalkResultWind::V1sum, TreeWalkResultWind::V2sum, TreeWalkQueryWind::Vel, WIND_GET_PRIV, and wk.

Referenced by winds_find_weights().

Here is the caller graph for this function:

◆ sfr_wind_weight_postprocess()

static void sfr_wind_weight_postprocess ( const int  i,
TreeWalk tw 
)
static

Definition at line 441 of file winds.c.

442 {
443  struct winddata * Windd = WIND_GET_PRIV(tw)->Winddata;
444 
445  const int maxcmpt = WINDP(i, Windd).maxcmpte;
446  int j;
447  double evaldmradius[NWINDHSML];
448  for(j = 0; j < maxcmpt; j++){
449  evaldmradius[j] = effdmradius(i,j,tw);
450  }
451  int close = 0;
452  WINDP(i, Windd).DMRadius = ngb_narrow_down(&WINDP(i, Windd).Right, &WINDP(i, Windd).Left, evaldmradius, WINDP(i, Windd).Ngb, maxcmpt, NUMDMNGB, &close, tw->tree->BoxSize);
453  double numngb = WINDP(i, Windd).Ngb[close];
454 
455  int tid = omp_get_thread_num();
456  /* If we have 40 neighbours, or if DMRadius is narrow, set vdisp. Otherwise add to redo queue */
457  if((numngb < (NUMDMNGB - MAXDMDEVIATION) || numngb > (NUMDMNGB + MAXDMDEVIATION)) &&
458  (WINDP(i, Windd).Right - WINDP(i, Windd).Left > 1e-2)) {
459  /* More work needed: add this particle to the redo queue*/
460  tw->NPRedo[tid][tw->NPLeft[tid]] = i;
461  tw->NPLeft[tid] ++;
462  }
463  else{
464  double vdisp = WINDP(i, Windd).V2sum[close] / numngb;
465  int d;
466  for(d = 0; d<3; d++){
467  vdisp -= pow(WINDP(i, Windd).V1sum[close][d] / numngb,2);
468  }
469  if(vdisp > 0)
470  WINDP(i, Windd).Vdisp = sqrt(vdisp / 3);
471  }
472 
473  if(tw->maxnumngb[tid] < numngb)
474  tw->maxnumngb[tid] = numngb;
475  if(tw->minnumngb[tid] > numngb)
476  tw->minnumngb[tid] = numngb;
477 }
double * minnumngb
Definition: treewalk.h:172
double * maxnumngb
Definition: treewalk.h:171
int ** NPRedo
Definition: treewalk.h:168
size_t * NPLeft
Definition: treewalk.h:167
double Right
Definition: winds.c:181
double Left
Definition: winds.c:180
double ngb_narrow_down(double *right, double *left, const double *radius, const double *numNgb, int maxcmpt, int desnumngb, int *closeidx, double BoxSize)
Definition: treewalk.c:1366
#define MAXDMDEVIATION
Definition: winds.c:40

References ForceTree::BoxSize, effdmradius(), winddata::Left, MAXDMDEVIATION, TreeWalk::maxnumngb, TreeWalk::minnumngb, winddata::Ngb, ngb_narrow_down(), TreeWalk::NPLeft, TreeWalk::NPRedo, NUMDMNGB, NWINDHSML, winddata::Right, TreeWalk::tree, winddata::V1sum, WIND_GET_PRIV, and WINDP.

Referenced by winds_find_weights().

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

◆ wind_do_kick()

static void wind_do_kick ( int  other,
double  vel,
double  therm,
double  atime 
)
static

Definition at line 590 of file winds.c.

591 {
592  /* Kick the gas particle*/
593  double dir[3];
594  get_wind_dir(other, dir);
595  int j;
596  if(vel > 0 && atime > 0) {
597  for(j = 0; j < 3; j++)
598  {
599  P[other].Vel[j] += vel * dir[j];
600  }
601  /* StarTherm is internal energy per unit mass. Need to convert to entropy*/
602  const double enttou = pow(SPHP(other).Density / pow(atime, 3), GAMMA_MINUS1) / GAMMA_MINUS1;
603  SPHP(other).Entropy += therm/enttou;
604  if(winds_ever_decouple()) {
605  double delay = wind_params.WindFreeTravelLength / (vel / atime);
608  SPHP(other).DelayTime = delay;
609  }
610  }
611 }
#define GAMMA_MINUS1
Definition: physconst.h:35
int winds_ever_decouple(void)
Definition: winds.c:192
static int get_wind_dir(int i, double dir[3])
Definition: winds.c:614

References GAMMA_MINUS1, get_wind_dir(), WindParams::MaxWindFreeTravelTime, P, SPHP, wind_params, WindParams::WindFreeTravelLength, and winds_ever_decouple().

Referenced by winds_and_feedback().

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

◆ winds_and_feedback()

void winds_and_feedback ( int *  NewStars,
int  NumNewStars,
const double  Time,
const double  hubble,
ForceTree tree 
)

Definition at line 333 of file winds.c.

334 {
335  /*The subgrid model does nothing here*/
337  return;
338 
339  if(!MPIU_Any(NumNewStars > 0, MPI_COMM_WORLD))
340  return;
341 
342  TreeWalk tw[1] = {{0}};
343  struct WindPriv priv[1];
344  int i;
345  winds_find_weights(tw, priv, NewStars, NumNewStars, Time, hubble, tree);
346 
347  for (i = 1; i < omp_get_max_threads(); i++)
348  priv->nvisited[0] += priv->nvisited[i];
349  priv->maxkicks = priv->nvisited[0]+2;
350 
351  /* Some particles may be kicked by multiple stars on the same timestep.
352  * To ensure this happens only once and does not depend on the order in
353  * which the loops are executed, particles are kicked by the nearest new star.
354  * This struct stores all such possible kicks, and we sort it out after the treewalk.*/
355  priv->kicks = (struct StarKick * ) mymalloc("StarKicks", priv->maxkicks * sizeof(struct StarKick));
356  priv->nkicks = 0;
357  ta_free(priv->nvisited);
358 
359  /* Then run feedback */
360  tw->haswork = NULL;
362  tw->postprocess = NULL;
363  tw->reduce = NULL;
364  tw->ev_label = "WIND_KICK";
365  tw->Niteration = 0;
366 
367  treewalk_run(tw, NewStars, NumNewStars);
368 
369  /* Sort the possible kicks*/
370  qsort_openmp(priv->kicks, priv->nkicks, sizeof(struct StarKick), cmp_by_part_id);
371  /* Not parallel as the number of kicked particles should be pretty small*/
372  int64_t last_part = -1;
373  int64_t nkicked = 0;
374  for(i = 0; i < priv->nkicks; i++) {
375  /* Only do the kick for the first particle, which is the closest*/
376  if(priv->kicks[i].part_index == last_part)
377  continue;
378  int other = priv->kicks[i].part_index;
379  last_part = other;
380  nkicked++;
381  wind_do_kick(other, priv->kicks[i].StarKickVelocity, priv->kicks[i].StarTherm, Time);
382  if(priv->kicks[i].StarKickVelocity <= 0 || !isfinite(priv->kicks[i].StarKickVelocity) || !isfinite(SPHP(other).DelayTime))
383  {
384  endrun(5, "Odd v: other = %d, DT = %g v = %g i = %d, nkicks %d maxkicks %d dist %g id %ld\n",
385  other, SPHP(other).DelayTime, priv->kicks[i].StarKickVelocity, i, priv->nkicks, priv->maxkicks,
386  priv->kicks[i].StarDistance, priv->kicks[i].StarID);
387  }
388  }
389  /* Get total number of potential new stars to allocate memory.*/
390  int64_t tot_newstars, tot_kicks, tot_applied;
391  sumup_large_ints(1, &NumNewStars, &tot_newstars);
392  MPI_Allreduce(&priv->nkicks, &tot_kicks, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
393  MPI_Allreduce(&nkicked, &tot_applied, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
394  message(0, "Made %ld gas wind, discarded %ld kicks from %d stars\n", tot_applied, tot_kicks - tot_applied, tot_newstars);
395 
396  myfree(priv->kicks);
397  myfree(priv->Winddata);
398  walltime_measure("/Cooling/Wind");
399 }
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define ta_free(p)
Definition: mymalloc.h:28
#define myfree(x)
Definition: mymalloc.h:19
int64_t Niteration
Definition: treewalk.h:142
TreeWalkHasWorkFunction haswork
Definition: treewalk.h:100
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 hubble
Definition: winds.c:221
double Time
Definition: winds.c:220
void sumup_large_ints(int n, int *src, int64_t *res)
Definition: system.c:192
int MPIU_Any(int condition, MPI_Comm comm)
Definition: system.c:545
#define MPI_INT64
Definition: system.h:12
#define qsort_openmp
Definition: test_exchange.c:14
void treewalk_run(TreeWalk *tw, int *active_set, size_t size)
Definition: treewalk.c:619
void(* TreeWalkNgbIterFunction)(TreeWalkQueryBase *input, TreeWalkResultBase *output, TreeWalkNgbIterBase *iter, LocalTreeWalk *lv)
Definition: treewalk.h:70
#define walltime_measure(name)
Definition: walltime.h:8
static void wind_do_kick(int other, double vel, double therm, double atime)
Definition: winds.c:590
static void sfr_wind_feedback_ngbiter(TreeWalkQueryWind *I, TreeWalkResultWind *O, TreeWalkNgbIterWind *iter, LocalTreeWalk *lv)
Definition: winds.c:650
int cmp_by_part_id(const void *a, const void *b)
Definition: winds.c:231
static void winds_find_weights(TreeWalk *tw, struct WindPriv *priv, int *NewStars, int NumNewStars, const double Time, const double hubble, ForceTree *tree)
Definition: winds.c:255
@ WIND_SUBGRID
Definition: winds.h:13

References cmp_by_part_id(), endrun(), TreeWalk::ev_label, HAS, TreeWalk::haswork, WindPriv::hubble, WindPriv::kicks, WindPriv::maxkicks, message(), MPI_INT64, MPIU_Any(), myfree, mymalloc, TreeWalk::ngbiter, TreeWalk::Niteration, WindPriv::nkicks, WindPriv::nvisited, StarKick::part_index, TreeWalk::postprocess, qsort_openmp, TreeWalk::reduce, sfr_wind_feedback_ngbiter(), SPHP, StarKick::StarDistance, StarKick::StarID, StarKick::StarKickVelocity, StarKick::StarTherm, sumup_large_ints(), ta_free, WindPriv::Time, treewalk_run(), walltime_measure, wind_do_kick(), wind_params, WIND_SUBGRID, WindPriv::Winddata, WindParams::WindModel, and winds_find_weights().

Referenced by cooling_and_starformation().

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

◆ winds_are_subgrid()

int winds_are_subgrid ( void  )

Definition at line 115 of file winds.c.

116 {
118  return 1;
119  else
120  return 0;
121 }

References HAS, wind_params, WIND_SUBGRID, and WindParams::WindModel.

Referenced by cooling_and_starformation().

Here is the caller graph for this function:

◆ winds_decoupled_hydro()

void winds_decoupled_hydro ( int  i,
double  atime 
)

Definition at line 133 of file winds.c.

134 {
135  int k;
136  for(k = 0; k < 3; k++)
137  SPHP(i).HydroAccel[k] = 0;
138 
139  SPHP(i).DtEntropy = 0;
140 
141  double windspeed = wind_params.WindSpeed * atime;
142  const double fac_mu = pow(atime, 3 * (GAMMA - 1) / 2) / atime;
143  windspeed *= fac_mu;
144  double hsml_c = cbrt(wind_params.WindFreeTravelDensThresh /SPHP(i).Density) * atime;
145  SPHP(i).MaxSignalVel = hsml_c * DMAX((2 * windspeed), SPHP(i).MaxSignalVel);
146 }
#define GAMMA
Definition: physconst.h:34

References DMAX, GAMMA, SPHP, wind_params, WindParams::WindFreeTravelDensThresh, and WindParams::WindSpeed.

Referenced by hydro_postprocess().

Here is the caller graph for this function:

◆ winds_ever_decouple()

int winds_ever_decouple ( void  )

Definition at line 192 of file winds.c.

193 {
195  return 1;
196  else
197  return 0;
198 }

References WindParams::MaxWindFreeTravelTime, and wind_params.

Referenced by wind_do_kick().

Here is the caller graph for this function:

◆ winds_evolve()

void winds_evolve ( int  i,
double  a3inv,
double  hubble 
)

Definition at line 403 of file winds.c.

404 {
405  /*Remove a wind particle from the delay mode if the (physical) density has dropped sufficiently.*/
406  if(SPHP(i).DelayTime > 0 && SPHP(i).Density * a3inv < wind_params.WindFreeTravelDensThresh) {
407  SPHP(i).DelayTime = 0;
408  }
409  /*Reduce the time until the particle can form stars again by the current timestep*/
410  if(SPHP(i).DelayTime > 0) {
411  /* Enforce the maximum in case of restarts*/
412  if(SPHP(i).DelayTime > wind_params.MaxWindFreeTravelTime)
413  SPHP(i).DelayTime = wind_params.MaxWindFreeTravelTime;
414  const double dloga = get_dloga_for_bin(P[i].TimeBin, P[i].Ti_drift);
415  /* the proper time duration of the step */
416  const double dtime = dloga / hubble;
417  SPHP(i).DelayTime = DMAX(SPHP(i).DelayTime - dtime, 0);
418  }
419 }
static double dloga
Definition: lightcone.c:21

References dloga, DMAX, get_dloga_for_bin(), WindPriv::hubble, WindParams::MaxWindFreeTravelTime, P, SPHP, wind_params, and WindParams::WindFreeTravelDensThresh.

Referenced by cooling_and_starformation().

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

◆ winds_find_weights()

static void winds_find_weights ( TreeWalk tw,
struct WindPriv priv,
int *  NewStars,
int  NumNewStars,
const double  Time,
const double  hubble,
ForceTree tree 
)
static

Definition at line 255 of file winds.c.

256 {
257  tw->ev_label = "WIND_WEIGHT";
260  tw->query_type_elsize = sizeof(TreeWalkQueryWind);
262  tw->tree = tree;
263 
264  /* sum the total weight of surrounding gas */
267 
268  tw->haswork = NULL;
271 
272  priv[0].Time = Time;
273  priv[0].hubble = hubble;
274  tw->priv = priv;
275 
276  int64_t totalleft = 0;
277  sumup_large_ints(1, &NumNewStars, &totalleft);
278  /* Subgrid winds come from gas, regular wind from stars: size array accordingly.*/
279  int64_t winddata_sz = SlotsManager->info[4].size;
281  winddata_sz = SlotsManager->info[0].size;
282  priv->Winddata = (struct winddata * ) mymalloc("WindExtraData", winddata_sz * sizeof(struct winddata));
283 
284  /* Note that this will be an over-count because each loop will add more.*/
285  priv->nvisited = ta_malloc("nvisited", int, omp_get_max_threads());
286  memset(WIND_GET_PRIV(tw)->nvisited, 0, omp_get_max_threads()* sizeof(int));
287 
288  int i;
289  /*Initialise the WINDP array*/
290  #pragma omp parallel for
291  for (i = 0; i < NumNewStars; i++) {
292  int n = NewStars ? NewStars[i] : i;
293  WINDP(n, priv->Winddata).DMRadius = 2 * P[n].Hsml;
294  WINDP(n, priv->Winddata).Left = 0;
295  WINDP(n, priv->Winddata).Right = tree->BoxSize;
296  WINDP(n, priv->Winddata).maxcmpte = NUMDMNGB;
297  }
298 
299  /* Find densities*/
300  treewalk_do_hsml_loop(tw, NewStars, NumNewStars, 1);
301 }
#define ta_malloc(name, type, nele)
Definition: mymalloc.h:25
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
void * priv
Definition: treewalk.h:85
size_t ngbiter_type_elsize
Definition: treewalk.h:97
TreeWalkVisitFunction visit
Definition: treewalk.h:99
size_t result_type_elsize
Definition: treewalk.h:96
TreeWalkFillQueryFunction fill
Definition: treewalk.h:101
size_t query_type_elsize
Definition: treewalk.h:95
int * nvisited
Definition: winds.c:226
struct winddata * Winddata
Definition: winds.c:222
int64_t size
Definition: slotsmanager.h:12
struct slot_info info[6]
Definition: slotsmanager.h:112
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(* TreeWalkFillQueryFunction)(const int j, TreeWalkQueryBase *query, TreeWalk *tw)
Definition: treewalk.h:75
static void sfr_wind_reduce_weight(int place, TreeWalkResultWind *remote, enum TreeWalkReduceMode mode, TreeWalk *tw)
Definition: winds.c:480
static void sfr_wind_weight_ngbiter(TreeWalkQueryWind *I, TreeWalkResultWind *O, TreeWalkNgbIterWind *iter, LocalTreeWalk *lv)
Definition: winds.c:521
static void sfr_wind_weight_postprocess(const int i, TreeWalk *tw)
Definition: winds.c:441
static void sfr_wind_copy(int place, TreeWalkQueryWind *input, TreeWalk *tw)
Definition: winds.c:501

References ForceTree::BoxSize, TreeWalk::ev_label, TreeWalk::fill, HAS, TreeWalk::haswork, WindPriv::hubble, slots_manager_type::info, mymalloc, TreeWalk::ngbiter, TreeWalk::ngbiter_type_elsize, NUMDMNGB, WindPriv::nvisited, P, TreeWalk::postprocess, TreeWalk::priv, TreeWalk::query_type_elsize, TreeWalk::reduce, TreeWalk::result_type_elsize, sfr_wind_copy(), sfr_wind_reduce_weight(), sfr_wind_weight_ngbiter(), sfr_wind_weight_postprocess(), slot_info::size, SlotsManager, sumup_large_ints(), ta_malloc, WindPriv::Time, TreeWalk::tree, treewalk_do_hsml_loop(), treewalk_visit_nolist_ngbiter(), TreeWalk::visit, WIND_GET_PRIV, wind_params, WIND_SUBGRID, WindPriv::Winddata, WindParams::WindModel, and WINDP.

Referenced by winds_and_feedback(), and winds_subgrid().

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

◆ winds_is_particle_decoupled()

int winds_is_particle_decoupled ( int  i)

Definition at line 124 of file winds.c.

125 {
127  && P[i].Type == 0 && SPHP(i).DelayTime > 0)
128  return 1;
129  return 0;
130 }
@ WIND_DECOUPLE_SPH
Definition: winds.h:15

References HAS, P, SPHP, WIND_DECOUPLE_SPH, wind_params, and WindParams::WindModel.

Referenced by add_particle_to_group(), blackhole_accretion_ngbiter(), blackhole_feedback_ngbiter(), density_ngbiter(), hydro_ngbiter(), and hydro_postprocess().

Here is the caller graph for this function:

◆ winds_make_after_sf()

int winds_make_after_sf ( int  i,
double  sm,
double  vdisp,
double  atime 
)

Definition at line 708 of file winds.c.

709 {
711  return 0;
712 
713  /* Get the velocity, thermal energy and efficiency of the kick*/
714  double utherm = 0, vel=0, windeff = 0;
715  get_wind_params(&vel, &windeff, &utherm, vdisp, atime);
716 
717  /* Here comes the Springel Hernquist 03 wind model */
718  /* Notice that this is the mass of the gas particle after forking a star, Mass - Mass/GENERATIONS.*/
719  double pw = windeff * sm / P[i].Mass;
720  double prob = 1 - exp(-pw);
721  if(get_random_number(P[i].ID + 2) < prob) {
722  wind_do_kick(i, vel, utherm, atime);
723  }
724  return 0;
725 }

Referenced by winds_subgrid().

Here is the caller graph for this function:

◆ winds_subgrid()

void winds_subgrid ( int *  MaybeWind,
int  NumMaybeWind,
const double  Time,
const double  hubble,
ForceTree tree,
MyFloat StellarMasses 
)

Definition at line 306 of file winds.c.

307 {
308  /*The non-subgrid model does nothing here*/
310  return;
311 
312  if(!MPIU_Any(NumMaybeWind > 0, MPI_COMM_WORLD))
313  return;
314 
315  TreeWalk tw[1] = {{0}};
316  struct WindPriv priv[1];
317  int n;
318  winds_find_weights(tw, priv, MaybeWind, NumMaybeWind, Time, hubble, tree);
319  myfree(priv->nvisited);
320  for(n = 0; n < NumMaybeWind; n++)
321  {
322  int i = MaybeWind ? MaybeWind[n] : n;
323  /* Notice that StellarMasses is indexed like PI, not i!*/
324  MyFloat sm = StellarMasses[P[i].PI];
325  winds_make_after_sf(i, sm, WINDP(i, priv->Winddata).Vdisp, Time);
326  }
327  myfree(priv->Winddata);
328  walltime_measure("/Cooling/Wind");
329 }
LOW_PRECISION MyFloat
Definition: types.h:19
int winds_make_after_sf(int i, double sm, double vdisp, double atime)
Definition: winds.c:708

References HAS, WindPriv::hubble, MPIU_Any(), myfree, WindPriv::nvisited, P, WindPriv::Time, walltime_measure, wind_params, WIND_SUBGRID, WindPriv::Winddata, WindParams::WindModel, WINDP, winds_find_weights(), and winds_make_after_sf().

Referenced by cooling_and_starformation().

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

Variable Documentation

◆ wind_params

struct WindParams wind_params
static