MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
Classes | Functions | Variables
sfr_eff.c File Reference
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <omp.h>
#include "physconst.h"
#include "sfr_eff.h"
#include "cooling.h"
#include "slotsmanager.h"
#include "walltime.h"
#include "winds.h"
#include "hydra.h"
#include "forcetree.h"
#include "domain.h"
Include dependency graph for sfr_eff.c:

Go to the source code of this file.

Classes

struct  SFRParams
 
struct  sfr_eeqos_data
 

Functions

int get_generations (void)
 
static struct sfr_eeqos_data get_sfr_eeqos (struct particle_data *part, struct sph_particle_data *sph, double dtime, struct UVBG *local_uvbg, const double redshift, const double a3inv)
 
static void cooling_direct (int i, const double redshift, const double a3inv, const double hubble, const struct UVBG *const GlobalUVBG)
 
static void cooling_relaxed (int i, double dtime, struct UVBG *local_uvbg, const double redshift, const double a3inv, struct sfr_eeqos_data sfr_data, const struct UVBG *const GlobalUVBG)
 
static int make_particle_star (int child, int parent, int placement, double Time)
 
static int starformation (int i, double *localsfr, MyFloat *sm_out, MyFloat *GradRho, const double redshift, const double a3inv, const double hubble, const double GravInternal, const struct UVBG *const GlobalUVBG)
 
static int quicklyastarformation (int i, const double a3inv)
 
static double get_sfr_factor_due_to_selfgravity (int i, const double atime, const double a3inv, const double hubble, const double GravInternal)
 
static double get_sfr_factor_due_to_h2 (int i, MyFloat *GradRho, const double atime)
 
static double get_starformation_rate_full (int i, MyFloat *GradRho, struct sfr_eeqos_data sfr_data, const double atime, const double a3inv, const double hubble, const double GravInternal)
 
static double get_egyeff (double redshift, double dens, struct UVBG *uvbg)
 
static double find_star_mass (int i, const double avg_baryon_mass)
 
static int * sfr_reserve_slots (ActiveParticles *act, int *NewStars, int NumNewStar, ForceTree *tt)
 
void set_sfr_params (ParameterSet *ps)
 
void cooling_and_starformation (ActiveParticles *act, double Time, double dloga, ForceTree *tree, const Cosmology *CP, MyFloat *GradRho, FILE *FdSfr)
 
int sfreff_on_eeqos (const struct sph_particle_data *sph, const double a3inv)
 
double get_neutral_fraction_sfreff (double redshift, double hubble, struct particle_data *partdata, struct sph_particle_data *sphdata)
 
double get_helium_neutral_fraction_sfreff (int ion, double redshift, double hubble, struct particle_data *partdata, struct sph_particle_data *sphdata)
 
double get_MinEgySpec (void)
 
void init_cooling_and_star_formation (int CoolingOn, int StarformationOn, Cosmology *CP, const double avg_baryon_mass, const double BoxSize, const struct UnitSystem units)
 
int sfr_need_to_compute_sph_grad_rho (void)
 
static double ev_NH_from_GradRho (MyFloat gradrho_mag, double hsml, double rho, double include_h)
 

Variables

static struct SFRParams sfr_params
 

Function Documentation

◆ cooling_and_starformation()

void cooling_and_starformation ( ActiveParticles act,
double  Time,
double  dloga,
ForceTree tree,
const Cosmology CP,
MyFloat GradRho,
FILE *  FdSfr 
)

Definition at line 167 of file sfr_eff.c.

168 {
169  const int nthreads = omp_get_max_threads();
170  /*This is a queue for the new stars and their parents, so we can reallocate the slots after the main cooling loop.*/
171  int * NewStars = NULL;
172  int * NewParents = NULL;
173  int64_t NumNewStar = 0, NumMaybeWind = 0;
174  int * MaybeWind = NULL;
175  MyFloat * StellarMass = NULL;
176 
177  size_t *nqthrsfr = ta_malloc("nqthrsfr", size_t, nthreads);
178  int **thrqueuesfr = ta_malloc("thrqueuesfr", int *, nthreads);
179  int **thrqueueparent = ta_malloc("thrqueueparent", int *, nthreads);
180  size_t *nqthrwind = NULL;
181  int **thrqueuewind = NULL;
182 
183  /*Need to capture this so that when NumActiveParticle increases during the loop
184  * we don't add extra loop iterations on particles with invalid slots.*/
185  const int nactive = act->NumActiveParticle;
186  const double a3inv = 1./(Time * Time * Time);
187  const double hubble = hubble_function(CP, Time);
188 
190  NewStars = (int *) mymalloc("NewStars", nactive * sizeof(int) * nthreads);
191  gadget_setup_thread_arrays(NewStars, thrqueuesfr, nqthrsfr, nactive, nthreads);
192  NewParents = (int *) mymalloc2("NewParents", nactive * sizeof(int) * nthreads);
193  gadget_setup_thread_arrays(NewParents, thrqueueparent, nqthrsfr, nactive, nthreads);
194  }
195 
197  nqthrwind = ta_malloc("nqthrwind", size_t, nthreads);
198  thrqueuewind = ta_malloc("thrqueuewind", int *, nthreads);
199  StellarMass = (MyFloat *) mymalloc("StellarMass", SlotsManager->info[0].size * sizeof(MyFloat));
200  MaybeWind = (int *) mymalloc("MaybeWind", nactive * sizeof(int) * nthreads);
201  gadget_setup_thread_arrays(MaybeWind, thrqueuewind, nqthrwind, nactive, nthreads);
202  }
203 
204 
205  /* Get the global UVBG for this redshift. */
206  const double redshift = 1./Time - 1;
207  struct UVBG GlobalUVBG = get_global_UVBG(redshift);
208  double sum_sm = 0, sum_mass_stars = 0, localsfr = 0;
209 
210  /* First decide which stars are cooling and which starforming. If star forming we add them to a list.
211  * Note the dynamic scheduling: individual particles may have very different loop iteration lengths.
212  * Cooling is much slower than sfr. I tried splitting it into a separate loop instead, but this was faster.*/
213  #pragma omp parallel reduction(+:localsfr) reduction(+: sum_sm) reduction(+:sum_mass_stars)
214  {
215  int i;
216  const int tid = omp_get_thread_num();
217  #pragma omp for schedule(static)
218  for(i=0; i < nactive; i++)
219  {
220  /*Use raw particle number if active_set is null, otherwise use active_set*/
221  const int p_i = act->ActiveParticle ? act->ActiveParticle[i] : i;
222  /* Skip non-gas or garbage particles */
223  if(P[p_i].Type != 0 || P[p_i].IsGarbage || P[p_i].Mass <= 0)
224  continue;
225 
226  int shall_we_star_form = 0;
228  /*Reduce delaytime for wind particles.*/
229  winds_evolve(p_i, a3inv, hubble);
230  /* check whether we are star forming gas.*/
232  shall_we_star_form = quicklyastarformation(p_i, a3inv);
233  else
234  shall_we_star_form = sfreff_on_eeqos(&SPHP(p_i), a3inv);
235  }
236 
237  if(shall_we_star_form) {
238  int newstar = -1;
239  MyFloat sm = 0;
241  /*New star is always the same particle as the parent for quicklya*/
242  newstar = p_i;
243  sum_sm += P[p_i].Mass;
244  sm = P[p_i].Mass;
245  } else {
246  newstar = starformation(p_i, &localsfr, &sm, GradRho, redshift, a3inv, hubble, CP->GravInternal, &GlobalUVBG);
247  sum_sm += P[p_i].Mass * (1 - exp(-sm/P[p_i].Mass));
248  }
249  /*Add this particle to the stellar conversion queue if necessary.*/
250  if(newstar >= 0) {
251  thrqueuesfr[tid][nqthrsfr[tid]] = newstar;
252  thrqueueparent[tid][nqthrsfr[tid]] = p_i;
253  nqthrsfr[tid]++;
254  }
255  /* Add this particle to the queue for consideration to spawn a wind.
256  * Only for subgrid winds. */
257  if(nqthrwind && newstar < 0) {
258  thrqueuewind[tid][nqthrwind[tid]] = p_i;
259  StellarMass[P[p_i].PI] = sm;
260  nqthrwind[tid]++;
261  }
262  }
263  else
264  cooling_direct(p_i, redshift, a3inv, hubble, &GlobalUVBG);
265  }
266  }
267 
268  report_memory_usage("SFR");
269 
270  walltime_measure("/Cooling/Cooling");
271 
272  /* Do subgrid winds*/
274  NumMaybeWind = gadget_compact_thread_arrays(MaybeWind, thrqueuewind, nqthrwind, nthreads);
275  winds_subgrid(MaybeWind, NumMaybeWind, Time, hubble, tree, StellarMass);
276  myfree(MaybeWind);
277  myfree(StellarMass);
278  ta_free(thrqueuewind);
279  ta_free(nqthrwind);
280  }
281 
282  /*Merge step for the queue.*/
283  if(NewStars) {
284  NumNewStar = gadget_compact_thread_arrays(NewStars, thrqueuesfr, nqthrsfr, nthreads);
285  int64_t NumNewParent = gadget_compact_thread_arrays(NewParents, thrqueueparent, nqthrsfr, nthreads);
286  if(NumNewStar != NumNewParent)
287  endrun(3,"%lu new stars, but %lu new parents!\n",NumNewStar, NumNewParent);
288  /*Shrink star memory as we keep it for the wind model*/
289  NewStars = (int *) myrealloc(NewStars, sizeof(int) * NumNewStar);
290  }
291 
292  ta_free(thrqueueparent);
293  ta_free(thrqueuesfr);
294  ta_free(nqthrsfr);
295 
296 
298  return;
299 
300  /*Get some empty slots for the stars*/
301  int firststarslot = SlotsManager->info[4].size;
302  /* We ran out of slots! We must be forming a lot of stars.
303  * There are things in the way of extending the slot list, so we have to move them.
304  * The code in sfr_reserve_slots is not elegant, but I cannot think of a better way.*/
305  if(sfr_params.StarformationOn && (SlotsManager->info[4].size + NumNewStar >= SlotsManager->info[4].maxsize)) {
306  if(NewParents)
307  NewParents = (int *) myrealloc(NewParents, sizeof(int) * NumNewStar);
308  NewStars = sfr_reserve_slots(act, NewStars, NumNewStar, tree);
309  }
310  SlotsManager->info[4].size += NumNewStar;
311 
312  int stars_converted=0, stars_spawned=0;
313  int i;
314 
315  /*Now we turn the particles into stars*/
316  #pragma omp parallel for schedule(static) reduction(+:stars_converted) reduction(+:stars_spawned) reduction(+:sum_mass_stars)
317  for(i=0; i < NumNewStar; i++)
318  {
319  int child = NewStars[i];
320  int parent = NewParents[i];
321  make_particle_star(child, parent, firststarslot+i, Time);
322  sum_mass_stars += P[child].Mass;
323  if(child == parent)
324  stars_converted++;
325  else
326  stars_spawned++;
327  }
328 
329  /*Done with the parents*/
330  myfree(NewParents);
331 
332  int64_t tot_spawned=0, tot_converted=0;
333  sumup_large_ints(1, &stars_spawned, &tot_spawned);
334  sumup_large_ints(1, &stars_converted, &tot_converted);
335 
336  double total_sum_mass_stars, total_sm, totsfrrate;
337 
338  MPI_Reduce(&localsfr, &totsfrrate, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
339  MPI_Reduce(&sum_sm, &total_sm, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
340  MPI_Reduce(&sum_mass_stars, &total_sum_mass_stars, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
341  if(FdSfr)
342  {
343  double rate = 0;
344 
345  if(dloga > 0)
346  rate = total_sm / (dloga / hubble);
347 
348  /* convert to solar masses per yr */
349 
350  double rate_in_msunperyear = rate * sfr_params.UnitSfr_in_solar_per_year;
351 
352  /* Format:
353  * Time = current scale factor,
354  * total_sm = expected change in stellar mass this timestep,
355  * totsfrrate = current star formation rate in active particles in Msun/year,
356  * rate_in_msunperyear = expected stellar mass formation rate in Msun/year from total_sm,
357  * total_sum_mass_stars = actual mass of stars formed this timestep (discretized total_sm) */
358  fprintf(FdSfr, "%g %g %g %g %g\n", Time, total_sm, totsfrrate, rate_in_msunperyear,
359  total_sum_mass_stars);
360  fflush(FdSfr);
361  }
362 
363  MPIU_Barrier(MPI_COMM_WORLD);
364  if(tot_spawned || tot_converted)
365  message(0, "SFR: spawned %ld stars, converted %ld gas particles into stars\n", tot_spawned, tot_converted);
366 
367  walltime_measure("/Cooling/StarFormation");
368 
369  /* Now apply the wind model using the list of new stars.*/
371  winds_and_feedback(NewStars, NumNewStar, Time, hubble, tree);
372 
373  myfree(NewStars);
374 }
struct UVBG get_global_UVBG(double redshift)
double hubble_function(const Cosmology *CP, double a)
Definition: cosmology.c:58
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
static double dloga
Definition: lightcone.c:21
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define ta_malloc(name, type, nele)
Definition: mymalloc.h:25
#define myrealloc(ptr, size)
Definition: mymalloc.h:18
#define ta_free(p)
Definition: mymalloc.h:28
#define mymalloc2(name, size)
Definition: mymalloc.h:16
#define myfree(x)
Definition: mymalloc.h:19
#define report_memory_usage(x)
Definition: mymalloc.h:30
#define P
Definition: partmanager.h:88
static Cosmology * CP
Definition: power.c:27
static struct SFRParams sfr_params
static int starformation(int i, double *localsfr, MyFloat *sm_out, MyFloat *GradRho, const double redshift, const double a3inv, const double hubble, const double GravInternal, const struct UVBG *const GlobalUVBG)
Definition: sfr_eff.c:666
int sfreff_on_eeqos(const struct sph_particle_data *sph, const double a3inv)
Definition: sfr_eff.c:486
static int make_particle_star(int child, int parent, int placement, double Time)
Definition: sfr_eff.c:578
static int * sfr_reserve_slots(ActiveParticles *act, int *NewStars, int NumNewStar, ForceTree *tt)
Definition: sfr_eff.c:380
static void cooling_direct(int i, const double redshift, const double a3inv, const double hubble, const struct UVBG *const GlobalUVBG)
Definition: sfr_eff.c:444
static int quicklyastarformation(int i, const double a3inv)
Definition: sfr_eff.c:641
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
#define SPHP(i)
Definition: slotsmanager.h:124
int * ActiveParticle
Definition: timestep.h:13
int64_t NumActiveParticle
Definition: timestep.h:12
double GravInternal
Definition: cosmology.h:32
int StarformationOn
Definition: sfr_eff.c:39
double UnitSfr_in_solar_per_year
Definition: sfr_eff.c:72
double QuickLymanAlphaProbability
Definition: sfr_eff.c:62
int WindOn
Definition: sfr_eff.c:41
Definition: cooling.h:8
int64_t maxsize
Definition: slotsmanager.h:11
int64_t size
Definition: slotsmanager.h:12
struct slot_info info[6]
Definition: slotsmanager.h:112
void gadget_setup_thread_arrays(int *dest, int *srcs[], size_t sizes[], size_t total_size, int narrays)
Definition: system.c:600
void sumup_large_ints(int n, int *src, int64_t *res)
Definition: system.c:192
size_t gadget_compact_thread_arrays(int *dest, int *srcs[], size_t sizes[], int narrays)
Definition: system.c:587
#define MPIU_Barrier(comm)
Definition: system.h:103
LOW_PRECISION MyFloat
Definition: types.h:19
#define walltime_measure(name)
Definition: walltime.h:8
void winds_evolve(int i, double a3inv, double hubble)
Definition: winds.c:403
void winds_subgrid(int *MaybeWind, int NumMaybeWind, const double Time, const double hubble, ForceTree *tree, MyFloat *StellarMasses)
Definition: winds.c:306
int winds_are_subgrid(void)
Definition: winds.c:115
void winds_and_feedback(int *NewStars, int NumNewStars, const double Time, const double hubble, ForceTree *tree)
Definition: winds.c:333

References ActiveParticles::ActiveParticle, cooling_direct(), CP, dloga, endrun(), gadget_compact_thread_arrays(), gadget_setup_thread_arrays(), get_global_UVBG(), Cosmology::GravInternal, hubble_function(), slots_manager_type::info, make_particle_star(), slot_info::maxsize, message(), MPIU_Barrier, myfree, mymalloc, mymalloc2, myrealloc, ActiveParticles::NumActiveParticle, P, quicklyastarformation(), SFRParams::QuickLymanAlphaProbability, report_memory_usage, sfr_params, sfr_reserve_slots(), sfreff_on_eeqos(), slot_info::size, SlotsManager, SPHP, starformation(), SFRParams::StarformationOn, sumup_large_ints(), ta_free, ta_malloc, SFRParams::UnitSfr_in_solar_per_year, walltime_measure, SFRParams::WindOn, winds_and_feedback(), winds_are_subgrid(), winds_evolve(), and winds_subgrid().

Referenced by run(), and runfof().

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

◆ cooling_direct()

static void cooling_direct ( int  i,
const double  redshift,
const double  a3inv,
const double  hubble,
const struct UVBG *const  GlobalUVBG 
)
static

Definition at line 444 of file sfr_eff.c.

445 {
446  /* the actual time-step */
447  double dloga = get_dloga_for_bin(P[i].TimeBin, P[i].Ti_drift);
448  double dtime = dloga / hubble;
449 
450  double ne = SPHP(i).Ne; /* electron abundance (gives ionization state and mean molecular weight) */
451 
452  const double enttou = pow(SPHP(i).Density * a3inv, GAMMA_MINUS1) / GAMMA_MINUS1;
453 
454  /* Current internal energy including adiabatic change*/
455  double uold = SPHP(i).Entropy * enttou;
456 
457  struct UVBG uvbg = get_local_UVBG(redshift, GlobalUVBG, P[i].Pos, PartManager->CurrentParticleOffset);
458  double lasttime = exp(loga_from_ti(P[i].Ti_drift - dti_from_timebin(P[i].TimeBin)));
459  double lastred = 1/lasttime - 1;
460  double unew;
461  /* The particle reionized this timestep, bump the temperature to the HI reionization temperature.
462  * We only do this for non-star-forming gas.*/
463  if(sfr_params.HIReionTemp > 0 && uvbg.zreion > redshift && uvbg.zreion < lastred) {
464  /* We assume it is fully ionized*/
465  const double meanweight = 4 / (8 - 5 * (1 - HYDROGEN_MASSFRAC));
466  unew = sfr_params.temp_to_u / meanweight * sfr_params.HIReionTemp;
467  }
468  else {
469  /* mean molecular weight assuming ZERO ionization NEUTRAL GAS*/
470  const double meanweight = 4.0 / (1 + 3 * HYDROGEN_MASSFRAC);
471  const double MinEgySpec = sfr_params.temp_to_u/meanweight * sfr_params.MinGasTemp;
472  unew = DoCooling(redshift, uold, SPHP(i).Density * a3inv, dtime, &uvbg, &ne, SPHP(i).Metallicity, MinEgySpec, P[i].HeIIIionized);
473  }
474 
475  SPHP(i).Ne = ne;
476  /* Update the entropy. This is done after synchronizing kicks and drifts, as per run.c.*/
477  SPHP(i).Entropy = unew / enttou;
478  /* Cooling gas is not forming stars*/
479  SPHP(i).Sfr = 0;
480 }
double DoCooling(double redshift, double u_old, double rho, double dt, struct UVBG *uvbg, double *ne_guess, double Z, double MinEgySpec, int isHeIIIionized)
Definition: cooling.c:71
struct UVBG get_local_UVBG(double redshift, const struct UVBG *const GlobalUVBG, const double *const Pos, const double *const PosOffset)
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define HYDROGEN_MASSFRAC
Definition: physconst.h:37
#define GAMMA_MINUS1
Definition: physconst.h:35
double temp_to_u
Definition: sfr_eff.c:70
double MinGasTemp
Definition: sfr_eff.c:57
double HIReionTemp
Definition: sfr_eff.c:78
double zreion
Definition: cooling.h:16
double CurrentParticleOffset[3]
Definition: partmanager.h:82
double loga_from_ti(int ti)
Definition: test_timefac.c:51
double get_dloga_for_bin(int timebin, const inttime_t Ti_Current)
Definition: timebinmgr.c:279
static inttime_t dti_from_timebin(int bin)
Definition: timebinmgr.h:44

References part_manager_type::CurrentParticleOffset, dloga, DoCooling(), dti_from_timebin(), GAMMA_MINUS1, get_dloga_for_bin(), get_local_UVBG(), SFRParams::HIReionTemp, HYDROGEN_MASSFRAC, loga_from_ti(), SFRParams::MinGasTemp, P, PartManager, sfr_params, SPHP, SFRParams::temp_to_u, and UVBG::zreion.

Referenced by cooling_and_starformation().

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

◆ cooling_relaxed()

static void cooling_relaxed ( int  i,
double  dtime,
struct UVBG local_uvbg,
const double  redshift,
const double  a3inv,
struct sfr_eeqos_data  sfr_data,
const struct UVBG *const  GlobalUVBG 
)
static

Definition at line 606 of file sfr_eff.c.

607 {
608  const double egyeff = sfr_params.EgySpecCold * sfr_data.cloudfrac + (1 - sfr_data.cloudfrac) * sfr_data.egyhot;
609  const double Density = SPHP(i).Density;
610  const double densityfac = pow(Density * a3inv, GAMMA_MINUS1) / GAMMA_MINUS1;
611  double egycurrent = SPHP(i).Entropy * densityfac;
612  double trelax = sfr_data.trelax;
613  if(sfr_params.BHFeedbackUseTcool == 1 && P[i].BHHeated)
614  {
615  if(egycurrent > egyeff)
616  {
617  double ne = SPHP(i).Ne;
618  /* In practice tcool << trelax*/
619  double tcool = GetCoolingTime(redshift, egycurrent, SPHP(i).Density * a3inv, local_uvbg, &ne, SPHP(i).Metallicity);
620 
621  /* The point of the star-forming equation of state is to pressurize the gas. However,
622  * when the gas has been heated above the equation of state it is pressurized and does not cool successfully.
623  * This code uses the cooling time rather than the relaxation time.
624  * This reduces the effect of black hole feedback marginally (a 5% reduction in star formation)
625  * and dates from the earliest versions of this code available.
626  * The main impact is on the high end of the black hole mass function: turning this off
627  * removes most massive black holes. */
628  if(tcool < trelax && tcool > 0)
629  trelax = tcool;
630  }
631  P[i].BHHeated = 0;
632  }
633 
634  SPHP(i).Entropy = (egyeff + (egycurrent - egyeff) * exp(-dtime / trelax)) /densityfac;
635 }
double GetCoolingTime(double redshift, double u_old, double rho, struct UVBG *uvbg, double *ne_guess, double Z)
Definition: cooling.c:157
double EgySpecCold
Definition: sfr_eff.c:49
int BHFeedbackUseTcool
Definition: sfr_eff.c:55
double cloudfrac
Definition: sfr_eff.c:104
double trelax
Definition: sfr_eff.c:96
double egyhot
Definition: sfr_eff.c:100

References SFRParams::BHFeedbackUseTcool, sfr_eeqos_data::cloudfrac, sph_particle_data::Density, sfr_eeqos_data::egyhot, SFRParams::EgySpecCold, GAMMA_MINUS1, GetCoolingTime(), sph_particle_data::Metallicity, P, sfr_params, SPHP, and sfr_eeqos_data::trelax.

Referenced by get_sfr_eeqos().

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

◆ ev_NH_from_GradRho()

static double ev_NH_from_GradRho ( MyFloat  gradrho_mag,
double  hsml,
double  rho,
double  include_h 
)
static

Definition at line 959 of file sfr_eff.c.

960 {
961  /* column density from GradRho, copied from gadget-p; what is it
962  * calculating? */
963  if(rho<=0)
964  return 0;
965  double ev_NH = 0;
966  if(gradrho_mag > 0)
967  ev_NH = rho*rho/gradrho_mag;
968  if(include_h > 0)
969  ev_NH += rho*hsml;
970  return ev_NH; // *(Z/Zsolar) add metallicity dependence
971 }

Referenced by get_sfr_factor_due_to_h2().

Here is the caller graph for this function:

◆ find_star_mass()

static double find_star_mass ( int  i,
const double  avg_baryon_mass 
)
static

Definition at line 921 of file sfr_eff.c.

922 {
923  /*Quick Lyman Alpha always turns all of a particle into stars*/
925  return P[i].Mass;
926 
927  double mass_of_star = avg_baryon_mass / sfr_params.Generations;
928  if(mass_of_star > P[i].Mass) {
929  /* if some mass has been stolen by BH, e.g */
930  mass_of_star = P[i].Mass;
931  }
932  /* Conditions to turn the gas into a star. .
933  * The mass check makes sure we never get a gas particle which is lighter
934  * than the smallest star particle.
935  * The Generations check (which can happen because of mass return)
936  * ensures we never instantaneously enrich stars above solar. */
937  if(P[i].Mass < 2 * mass_of_star || P[i].Generation > sfr_params.Generations) {
938  mass_of_star = P[i].Mass;
939  }
940  return mass_of_star;
941 }
int Generations
Definition: sfr_eff.c:65

References SFRParams::Generations, P, SFRParams::QuickLymanAlphaProbability, and sfr_params.

Referenced by get_sfr_eeqos().

Here is the caller graph for this function:

◆ get_egyeff()

static double get_egyeff ( double  redshift,
double  dens,
struct UVBG uvbg 
)
static

Definition at line 782 of file sfr_eff.c.

783 {
784  double tsfr = sqrt(sfr_params.PhysDensThresh / (dens)) * sfr_params.MaxSfrTimescale;
785  double factorEVP = pow(dens / sfr_params.PhysDensThresh, -0.8) * sfr_params.FactorEVP;
786  double egyhot = sfr_params.EgySpecSN / (1 + factorEVP) + sfr_params.EgySpecCold;
787 
788  double ne = 0.5;
789  double tcool = GetCoolingTime(redshift, egyhot, dens, uvbg, &ne, 0.0);
790 
791  double y = tsfr / tcool * egyhot / (sfr_params.FactorSN * sfr_params.EgySpecSN - (1 - sfr_params.FactorSN) * sfr_params.EgySpecCold);
792  double x = 1 + 1 / (2 * y) - sqrt(1 / y + 1 / (4 * y * y));
793  return egyhot * (1 - x) + sfr_params.EgySpecCold * x;
794 }
double MaxSfrTimescale
Definition: sfr_eff.c:54
double PhysDensThresh
Definition: sfr_eff.c:46
double FactorEVP
Definition: sfr_eff.c:50
double EgySpecSN
Definition: sfr_eff.c:47
double FactorSN
Definition: sfr_eff.c:48

References sfr_eeqos_data::egyhot, SFRParams::EgySpecCold, SFRParams::EgySpecSN, SFRParams::FactorEVP, SFRParams::FactorSN, GetCoolingTime(), SFRParams::MaxSfrTimescale, sfr_eeqos_data::ne, SFRParams::PhysDensThresh, sfr_params, and sfr_eeqos_data::tsfr.

Referenced by init_cooling_and_star_formation(), and sfreff_on_eeqos().

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

◆ get_generations()

int get_generations ( void  )

Definition at line 87 of file sfr_eff.c.

88 {
89  return sfr_params.Generations;
90 }

References SFRParams::Generations, and sfr_params.

Referenced by init(), and petaio_read_header_internal().

Here is the caller graph for this function:

◆ get_helium_neutral_fraction_sfreff()

double get_helium_neutral_fraction_sfreff ( int  ion,
double  redshift,
double  hubble,
struct particle_data partdata,
struct sph_particle_data sphdata 
)

Definition at line 548 of file sfr_eff.c.

549 {
550  const double a3inv = pow(1+redshift,3);
551  double helium;
552  struct UVBG GlobalUVBG = get_global_UVBG(redshift);
553  struct UVBG uvbg = get_local_UVBG(redshift, &GlobalUVBG, partdata->Pos, PartManager->CurrentParticleOffset);
554  double physdens = sphdata->Density * a3inv;
555 
556  if(sfr_params.QuickLymanAlphaProbability > 0 || !sfreff_on_eeqos(sphdata, a3inv)) {
557  /*This gets the neutral fraction for standard gas*/
558  double eomdensity = sphdata->Density;
559  double InternalEnergy = sphdata->Entropy / GAMMA_MINUS1 * pow(eomdensity * a3inv, GAMMA_MINUS1);
560  helium = GetHeliumIonFraction(ion, InternalEnergy, physdens, &uvbg, sphdata->Ne);
561  }
562  else {
563  /* This gets the neutral fraction for gas on the star-forming equation of state.
564  * This needs special handling because the cold clouds have a different neutral
565  * fraction than the hot gas*/
566  double dloga = get_dloga_for_bin(partdata->TimeBin, partdata->Ti_drift);
567  double dtime = dloga / hubble;
568  struct sfr_eeqos_data sfr_data = get_sfr_eeqos(partdata, sphdata, dtime, &uvbg, redshift, a3inv);
569  double nh0cold = GetHeliumIonFraction(ion, sfr_params.EgySpecCold, physdens, &uvbg, sfr_data.ne);
570  double nh0hot = GetHeliumIonFraction(ion, sfr_data.egyhot, physdens, &uvbg, sfr_data.ne);
571  helium = nh0cold * sfr_data.cloudfrac + (1-sfr_data.cloudfrac) * nh0hot;
572  }
573  return helium;
574 }
double GetHeliumIonFraction(int ion, double u_old, double rho, const struct UVBG *uvbg, double ne_init)
Definition: cooling.c:192
static struct sfr_eeqos_data get_sfr_eeqos(struct particle_data *part, struct sph_particle_data *sph, double dtime, struct UVBG *local_uvbg, const double redshift, const double a3inv)
Definition: sfr_eff.c:722
unsigned char TimeBin
Definition: partmanager.h:26
double Pos[3]
Definition: partmanager.h:12
inttime_t Ti_drift
Definition: partmanager.h:36
double ne
Definition: sfr_eff.c:106

References sfr_eeqos_data::cloudfrac, part_manager_type::CurrentParticleOffset, sph_particle_data::Density, dloga, sfr_eeqos_data::egyhot, SFRParams::EgySpecCold, sph_particle_data::Entropy, GAMMA_MINUS1, get_dloga_for_bin(), get_global_UVBG(), get_local_UVBG(), get_sfr_eeqos(), GetHeliumIonFraction(), sfr_eeqos_data::ne, sph_particle_data::Ne, PartManager, particle_data::Pos, SFRParams::QuickLymanAlphaProbability, sfr_params, sfreff_on_eeqos(), particle_data::Ti_drift, and particle_data::TimeBin.

Referenced by GTHeliumIFraction(), GTHeliumIIFraction(), and GTHeliumIIIFraction().

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

◆ get_MinEgySpec()

double get_MinEgySpec ( void  )

Definition at line 797 of file sfr_eff.c.

798 {
799  /* mean molecular weight assuming ZERO ionization NEUTRAL GAS*/
800  const double meanweight = 4.0 / (1 + 3 * HYDROGEN_MASSFRAC);
801  /*Enforces a minimum internal energy in cooling. */
802  return sfr_params.temp_to_u / meanweight * sfr_params.MinGasTemp;
803 }

References HYDROGEN_MASSFRAC, SFRParams::MinGasTemp, sfr_params, and SFRParams::temp_to_u.

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

Here is the caller graph for this function:

◆ get_neutral_fraction_sfreff()

double get_neutral_fraction_sfreff ( double  redshift,
double  hubble,
struct particle_data partdata,
struct sph_particle_data sphdata 
)

Definition at line 520 of file sfr_eff.c.

521 {
522  double nh0;
523  const double a3inv = pow(1+redshift,3);
524  struct UVBG GlobalUVBG = get_global_UVBG(redshift);
525  struct UVBG uvbg = get_local_UVBG(redshift, &GlobalUVBG, partdata->Pos, PartManager->CurrentParticleOffset);
526  double physdens = sphdata->Density * a3inv;
527 
528  if(sfr_params.QuickLymanAlphaProbability > 0 || !sfreff_on_eeqos(sphdata, a3inv)) {
529  /*This gets the neutral fraction for standard gas*/
530  double eomdensity = sphdata->Density;
531  double InternalEnergy = sphdata->Entropy / GAMMA_MINUS1 * pow(eomdensity * a3inv, GAMMA_MINUS1);
532  nh0 = GetNeutralFraction(InternalEnergy, physdens, &uvbg, sphdata->Ne);
533  }
534  else {
535  /* This gets the neutral fraction for gas on the star-forming equation of state.
536  * This needs special handling because the cold clouds have a different neutral
537  * fraction than the hot gas*/
538  double dloga = get_dloga_for_bin(partdata->TimeBin, partdata->Ti_drift);
539  double dtime = dloga / hubble;
540  struct sfr_eeqos_data sfr_data = get_sfr_eeqos(partdata, sphdata, dtime, &uvbg, redshift, a3inv);
541  double nh0cold = GetNeutralFraction(sfr_params.EgySpecCold, physdens, &uvbg, sfr_data.ne);
542  double nh0hot = GetNeutralFraction(sfr_data.egyhot, physdens, &uvbg, sfr_data.ne);
543  nh0 = nh0cold * sfr_data.cloudfrac + (1-sfr_data.cloudfrac) * nh0hot;
544  }
545  return nh0;
546 }
double GetNeutralFraction(double u_old, double rho, const struct UVBG *uvbg, double ne_init)
Definition: cooling.c:181

References sfr_eeqos_data::cloudfrac, part_manager_type::CurrentParticleOffset, sph_particle_data::Density, dloga, sfr_eeqos_data::egyhot, SFRParams::EgySpecCold, sph_particle_data::Entropy, GAMMA_MINUS1, get_dloga_for_bin(), get_global_UVBG(), get_local_UVBG(), get_sfr_eeqos(), GetNeutralFraction(), sfr_eeqos_data::ne, sph_particle_data::Ne, PartManager, particle_data::Pos, SFRParams::QuickLymanAlphaProbability, sfr_params, sfreff_on_eeqos(), particle_data::Ti_drift, and particle_data::TimeBin.

Referenced by blackhole_accretion_ngbiter(), and GTNeutralHydrogenFraction().

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

◆ get_sfr_eeqos()

struct sfr_eeqos_data get_sfr_eeqos ( struct particle_data part,
struct sph_particle_data sph,
double  dtime,
struct UVBG local_uvbg,
const double  redshift,
const double  a3inv 
)
static

Definition at line 666 of file sfr_eff.c.

723 {
724  struct sfr_eeqos_data data;
725  /* Initialise data to something, just in case.*/
727  data.tsfr = sfr_params.MaxSfrTimescale;
728  data.egyhot = sfr_params.EgySpecCold;
729  data.cloudfrac = 0;
730  data.ne = 0;
731 
732  /* This shall never happen, but just in case*/
733  if(!sfreff_on_eeqos(sph, a3inv))
734  return data;
735 
736  data.ne = sph->Ne;
737  data.tsfr = sqrt(sfr_params.PhysDensThresh / (sph->Density * a3inv)) * sfr_params.MaxSfrTimescale;
738  /*
739  * gadget-p doesn't have this cap.
740  * without the cap sm can be bigger than cloudmass.
741  */
742  if(data.tsfr < dtime && dtime > 0)
743  data.tsfr = dtime;
744 
745  double factorEVP = pow(sph->Density * a3inv / sfr_params.PhysDensThresh, -0.8) * sfr_params.FactorEVP;
746 
747  data.egyhot = sfr_params.EgySpecSN / (1 + factorEVP) + sfr_params.EgySpecCold;
748  data.egycold = sfr_params.EgySpecCold;
749 
750  double tcool = GetCoolingTime(redshift, data.egyhot, sph->Density * a3inv, local_uvbg, &data.ne, sph->Metallicity);
751  double y = data.tsfr / tcool * data.egyhot / (sfr_params.FactorSN * sfr_params.EgySpecSN - (1 - sfr_params.FactorSN) * sfr_params.EgySpecCold);
752 
753  data.cloudfrac = 1 + 1 / (2 * y) - sqrt(1 / y + 1 / (4 * y * y));
754 
755  data.trelax = data.tsfr * (1 - data.cloudfrac) / data.cloudfrac / (sfr_params.FactorSN * (1 + factorEVP));
756  return data;
757 }

References SFRParams::avg_baryon_mass, cooling_relaxed(), part_manager_type::CurrentParticleOffset, dloga, find_star_mass(), SFRParams::Generations, get_dloga_for_bin(), get_local_UVBG(), get_random_number(), get_starformation_rate_full(), METAL_YIELD, sfr_eeqos_data::ne, P, PartManager, sfr_params, slots_split_particle(), SPHP, and SFRParams::UnitSfr_in_solar_per_year.

Referenced by get_helium_neutral_fraction_sfreff(), and get_neutral_fraction_sfreff().

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

◆ get_sfr_factor_due_to_h2()

static double get_sfr_factor_due_to_h2 ( int  i,
MyFloat GradRho,
const double  atime 
)
static

Definition at line 973 of file sfr_eff.c.

973  {
974  /* Krumholz & Gnedin fitting function for f_H2 as a function of local
975  * properties, from gadget-p; we return the enhancement on SFR in this
976  * function */
977  double tau_fmol;
978  const double a2 = atime * atime;
979  double zoverzsun = SPHP(i).Metallicity/METAL_YIELD;
980  double gradrho_mag = sqrt(GradRho[3*P[i].PI]*GradRho[3*P[i].PI]+GradRho[3*P[i].PI+1]*GradRho[3*P[i].PI+1]+GradRho[3*P[i].PI+2]*GradRho[3*P[i].PI+2]);
981  //message(4, "GradRho %g rho %g hsml %g i %d\n", gradrho_mag, SPHP(i).Density, P[i].Hsml, i);
982  tau_fmol = ev_NH_from_GradRho(gradrho_mag,P[i].Hsml,SPHP(i).Density,1) /a2;
983  tau_fmol *= (0.1 + zoverzsun);
984  if(tau_fmol>0) {
985  tau_fmol *= 434.78*sfr_params.tau_fmol_unit;
986  double y = 0.756*(1+3.1*pow(zoverzsun,0.365));
987  y = log(1+0.6*y+0.01*y*y)/(0.6*tau_fmol);
988  y = 1-0.75*y/(1+0.25*y);
989  if(y<0) y=0;
990  if(y>1) y=1;
991  return y;
992 
993  } // if(tau_fmol>0)
994  return 1.0;
995 }
static double ev_NH_from_GradRho(MyFloat gradrho_mag, double hsml, double rho, double include_h)
Definition: sfr_eff.c:959
#define METAL_YIELD
Definition: sfr_eff.h:11
double tau_fmol_unit
Definition: sfr_eff.c:60

References ev_NH_from_GradRho(), METAL_YIELD, P, sfr_params, SPHP, and SFRParams::tau_fmol_unit.

Referenced by get_starformation_rate_full().

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

◆ get_sfr_factor_due_to_selfgravity()

static double get_sfr_factor_due_to_selfgravity ( int  i,
const double  atime,
const double  a3inv,
const double  hubble,
const double  GravInternal 
)
static

Definition at line 997 of file sfr_eff.c.

997  {
998  const double a2 = atime * atime;
999  double divv = SPHP(i).DivVel / a2;
1000 
1001  divv += 3.0*hubble * a2; // hubble-flow correction
1002 
1004  if( divv>=0 ) return 0; // restrict to convergent flows (optional) //
1005  }
1006 
1007  double dv2abs = (divv*divv
1008  + (SPHP(i).CurlVel/a2)
1009  * (SPHP(i).CurlVel/a2)
1010  ); // all in physical units
1011  double alpha_vir = 0.2387 * dv2abs/(GravInternal * SPHP(i).Density * a3inv);
1012 
1013  double y = 1.0;
1014 
1015  if((alpha_vir < 1.0)
1016  || (SPHP(i).Density * a3inv > 100. * sfr_params.PhysDensThresh)
1017  ) {
1018  y = 66.7;
1019  } else {
1020  y = 0.1;
1021  }
1022  // PFH: note the latter flag is an arbitrary choice currently set
1023  // -by hand- to prevent runaway densities from this prescription! //
1024 
1026  // continuous cutoff w alpha_vir instead of sharp (optional) //
1027  y *= 1.0/(1.0 + alpha_vir);
1028  }
1029  return y;
1030 }
@ SFR_CRITERION_CONVERGENT_FLOW
Definition: sfr_eff.h:21
@ SFR_CRITERION_CONTINUOUS_CUTOFF
Definition: sfr_eff.h:22
enum StarformationCriterion StarformationCriterion
Definition: sfr_eff.c:40
#define HAS(val, flag)
Definition: types.h:22

References HAS, SFRParams::PhysDensThresh, SFR_CRITERION_CONTINUOUS_CUTOFF, SFR_CRITERION_CONVERGENT_FLOW, sfr_params, SPHP, and SFRParams::StarformationCriterion.

Referenced by get_starformation_rate_full().

Here is the caller graph for this function:

◆ get_starformation_rate_full()

static double get_starformation_rate_full ( int  i,
MyFloat GradRho,
struct sfr_eeqos_data  sfr_data,
const double  atime,
const double  a3inv,
const double  hubble,
const double  GravInternal 
)
static

Definition at line 759 of file sfr_eff.c.

760 {
761  if(!sfreff_on_eeqos(&SPHP(i), a3inv)) {
762  return 0;
763  }
764 
765  double cloudmass = sfr_data.cloudfrac * P[i].Mass;
766 
767  double rateOfSF = (1 - sfr_params.FactorSN) * cloudmass / sfr_data.tsfr;
768 
770  if(!GradRho)
771  endrun(1, "GradRho not allocated but has SFR_CRITERION_MOLECULAR_H2. Should never happen!\n");
772  rateOfSF *= get_sfr_factor_due_to_h2(i, GradRho, atime);
773  }
775  rateOfSF *= get_sfr_factor_due_to_selfgravity(i, atime, a3inv, hubble, GravInternal);
776  }
777  return rateOfSF;
778 }
static double get_sfr_factor_due_to_selfgravity(int i, const double atime, const double a3inv, const double hubble, const double GravInternal)
Definition: sfr_eff.c:997
static double get_sfr_factor_due_to_h2(int i, MyFloat *GradRho, const double atime)
Definition: sfr_eff.c:973
@ SFR_CRITERION_MOLECULAR_H2
Definition: sfr_eff.h:18
@ SFR_CRITERION_SELFGRAVITY
Definition: sfr_eff.h:19
double tsfr
Definition: sfr_eff.c:98

References sfr_eeqos_data::cloudfrac, endrun(), SFRParams::FactorSN, get_sfr_factor_due_to_h2(), get_sfr_factor_due_to_selfgravity(), HAS, P, SFR_CRITERION_MOLECULAR_H2, SFR_CRITERION_SELFGRAVITY, sfr_params, sfreff_on_eeqos(), SPHP, SFRParams::StarformationCriterion, and sfr_eeqos_data::tsfr.

Referenced by get_sfr_eeqos().

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

◆ init_cooling_and_star_formation()

void init_cooling_and_star_formation ( int  CoolingOn,
int  StarformationOn,
Cosmology CP,
const double  avg_baryon_mass,
const double  BoxSize,
const struct UnitSystem  units 
)

Definition at line 805 of file sfr_eff.c.

806 {
807  struct cooling_units coolunits;
812  /* Get mean cosmic baryon density for photoheating rate from long mean free path photons */
813  coolunits.rho_crit_baryon = 3 * pow(CP->HubbleParam * HUBBLE,2) * CP->OmegaBaryon / (8 * M_PI * GRAVITY);
814 
816 
818 
820 
821  if(!CoolingOn)
822  return;
823 
824  /*Initialize the uv fluctuation table*/
826 
827  sfr_params.StarformationOn = StarformationOn;
828 
829  if(!StarformationOn)
830  return;
831 
832  sfr_params.avg_baryon_mass = avg_baryon_mass;
833 
836  sfr_params.CritOverDensity * CP->OmegaBaryon * 3 * CP->Hubble * CP->Hubble / (8 * M_PI * CP->GravInternal);
837 
839 
840  /* mean molecular weight assuming ZERO ionization NEUTRAL GAS*/
841  double meanweight = 4.0 / (1 + 3 * HYDROGEN_MASSFRAC);
843 
844  /* mean molecular weight assuming FULL ionization */
845  meanweight = 4 / (8 - 5 * (1 - HYDROGEN_MASSFRAC));
847 
848  if(sfr_params.PhysDensThresh == 0)
849  {
850  double egyhot = sfr_params.EgySpecSN / sfr_params.FactorEVP;
851 
852  meanweight = 4 / (8 - 5 * (1 - HYDROGEN_MASSFRAC)); /* note: assuming FULL ionization */
853 
854  double u4 = sfr_params.temp_to_u/meanweight * 1.0e4;
855 
856  double dens = 1.0e6 * 3 * CP->Hubble * CP->Hubble / (8 * M_PI * CP->GravInternal);
857 
858  double ne = 1.0;
859 
860  struct UVBG uvbg = {0};
861  /*XXX: We set the threshold without metal cooling
862  * and with zero ionization at z=0.
863  * It probably make sense to set the parameters with
864  * a metalicity dependence.
865  * */
866  const double tcool = GetCoolingTime(0, egyhot, dens, &uvbg, &ne, 0.0);
867 
868  const double coolrate = egyhot / tcool / dens;
869 
870  const double x = (egyhot - u4) / (egyhot - sfr_params.EgySpecCold);
871 
873  x / pow(1 - x,
874  2) * (sfr_params.FactorSN * sfr_params.EgySpecSN - (1 -
876  (sfr_params.MaxSfrTimescale * coolrate);
877 
878  message(0, "A0= %g \n", sfr_params.FactorEVP);
879  message(0, "Computed: PhysDensThresh= %g (int units) %g h^2 cm^-3\n", sfr_params.PhysDensThresh,
881  message(0, "EXPECTED FRACTION OF COLD GAS AT THRESHOLD = %g\n", x);
882  message(0, "tcool=%g dens=%g egyhot=%g\n", tcool, dens, egyhot);
883 
884  dens = sfr_params.PhysDensThresh * 10;
885 
886  double neff;
887  do
888  {
889  double egyeff = get_egyeff(0, dens, &uvbg);
890 
891  double peff = GAMMA_MINUS1 * dens * egyeff;
892 
893  const double fac = 1 / (log(dens * 1.025) - log(dens));
894  neff = -log(peff) * fac;
895 
896  dens *= 1.025;
897  egyeff = get_egyeff(0, dens, &uvbg);
898  peff = GAMMA_MINUS1 * dens * egyeff;
899 
900  neff += log(peff) * fac;
901  }
902  while(neff > 4.0 / 3);
903 
904  message(0, "Run-away sets in for dens=%g\n", dens);
905  message(0, "Dynamic range for quiescent star formation= %g\n", dens / sfr_params.PhysDensThresh);
906 
907  const double sigma = 10.0 / CP->Hubble * 1.0e-10 / pow(1.0e-3, 2);
908 
909  message(0, "Isotherm sheet central density: %g z0=%g\n",
910  M_PI * CP->GravInternal * sigma * sigma / (2 * GAMMA_MINUS1) / u4,
911  GAMMA_MINUS1 * u4 / (2 * M_PI * CP->GravInternal * sigma));
912  }
913 
914  if(sfr_params.WindOn) {
916  }
917 
918 }
void init_cooling(const char *TreeCoolFile, const char *MetalCoolFile, char *reion_hist_file, struct cooling_units cu, Cosmology *CP)
Definition: cooling.c:36
static struct cooling_units coolunits
Definition: cooling.c:33
void init_uvf_table(const char *UVFluctuationFile, const int UVFlucLen, const double BoxSize, const double UnitLength_in_cm)
double sigma[3]
Definition: densitykernel.c:97
#define HUBBLE
Definition: physconst.h:25
#define SOLAR_MASS
Definition: physconst.h:6
#define GRAVITY
Definition: physconst.h:5
#define PROTONMASS
Definition: physconst.h:21
#define SEC_PER_YEAR
Definition: physconst.h:32
#define BOLTZMANN
Definition: physconst.h:11
static double get_egyeff(double redshift, double dens, struct UVBG *uvbg)
Definition: sfr_eff.c:782
double HubbleParam
Definition: cosmology.h:20
double OmegaBaryon
Definition: cosmology.h:19
double Hubble
Definition: cosmology.h:21
double TempSupernova
Definition: sfr_eff.c:52
double CritOverDensity
Definition: sfr_eff.c:43
char UVFluctuationFile[100]
Definition: sfr_eff.c:82
char MetalCoolFile[100]
Definition: sfr_eff.c:81
char ReionHistFile[100]
Definition: sfr_eff.c:84
double OverDensThresh
Definition: sfr_eff.c:45
double TempClouds
Definition: sfr_eff.c:53
char TreeCoolFile[100]
Definition: sfr_eff.c:80
double avg_baryon_mass
Definition: sfr_eff.c:67
double CritPhysDensity
Definition: sfr_eff.c:44
double UnitMass_in_g
Definition: unitsystem.h:8
double UnitInternalEnergy_in_cgs
Definition: unitsystem.h:14
double UnitTime_in_s
Definition: unitsystem.h:11
double UnitLength_in_cm
Definition: unitsystem.h:10
double UnitDensity_in_cgs
Definition: unitsystem.h:12
double rho_crit_baryon
Definition: cooling.h:31
int CoolingOn
Definition: cooling.h:23
double density_in_phys_cgs
Definition: cooling.h:25
double tt_in_s
Definition: cooling.h:29
double uu_in_cgs
Definition: cooling.h:27
void init_winds(double FactorSN, double EgySpecSN, double PhysDensThresh, double UnitTime_in_s)
Definition: winds.c:97

References SFRParams::avg_baryon_mass, BOLTZMANN, cooling_units::CoolingOn, coolunits, CP, SFRParams::CritOverDensity, SFRParams::CritPhysDensity, cooling_units::density_in_phys_cgs, SFRParams::EgySpecCold, SFRParams::EgySpecSN, SFRParams::FactorEVP, SFRParams::FactorSN, GAMMA_MINUS1, get_egyeff(), GetCoolingTime(), Cosmology::GravInternal, GRAVITY, Cosmology::Hubble, HUBBLE, Cosmology::HubbleParam, HYDROGEN_MASSFRAC, init_cooling(), init_uvf_table(), init_winds(), SFRParams::MaxSfrTimescale, message(), SFRParams::MetalCoolFile, Cosmology::OmegaBaryon, SFRParams::OverDensThresh, SFRParams::PhysDensThresh, PROTONMASS, SFRParams::ReionHistFile, cooling_units::rho_crit_baryon, SEC_PER_YEAR, sfr_params, sigma, SOLAR_MASS, SFRParams::StarformationOn, SFRParams::tau_fmol_unit, SFRParams::temp_to_u, SFRParams::TempClouds, SFRParams::TempSupernova, SFRParams::TreeCoolFile, cooling_units::tt_in_s, UnitSystem::UnitDensity_in_cgs, UnitSystem::UnitInternalEnergy_in_cgs, UnitSystem::UnitLength_in_cm, UnitSystem::UnitMass_in_g, SFRParams::UnitSfr_in_solar_per_year, UnitSystem::UnitTime_in_s, cooling_units::uu_in_cgs, SFRParams::UVFluctuationFile, and SFRParams::WindOn.

Referenced by begrun().

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

◆ make_particle_star()

static int make_particle_star ( int  child,
int  parent,
int  placement,
double  Time 
)
static

Definition at line 578 of file sfr_eff.c.

579 {
580  int retflag = 2;
581  if(P[parent].Type != 0)
582  endrun(7772, "Only gas forms stars, what's wrong?\n");
583 
584  /*Store the SPH particle slot properties, as the PI may be over-written
585  *in slots_convert*/
586  struct sph_particle_data oldslot = SPHP(parent);
587 
588  /*Convert the child slot to the new type.*/
589  child = slots_convert(child, 4, placement, PartManager, SlotsManager);
590 
591  /*Set properties*/
592  STARP(child).FormationTime = Time;
593  STARP(child).LastEnrichmentMyr = 0;
594  STARP(child).TotalMassReturned = 0;
595  STARP(child).BirthDensity = oldslot.Density;
596  /*Copy metallicity*/
597  STARP(child).Metallicity = oldslot.Metallicity;
598  int j;
599  for(j = 0; j < NMETALS; j++)
600  STARP(child).Metals[j] = oldslot.Metals[j];
601  return retflag;
602 }
int slots_convert(int parent, int ptype, int placement, struct part_manager_type *pman, struct slots_manager_type *sman)
Definition: slotsmanager.c:60
#define STARP(i)
Definition: slotsmanager.h:126
#define NMETALS
Definition: slotsmanager.h:60
float Metals[NMETALS]
Definition: slotsmanager.h:108

References sph_particle_data::Density, endrun(), sph_particle_data::Metallicity, sph_particle_data::Metals, NMETALS, P, PartManager, slots_convert(), SlotsManager, SPHP, and STARP.

Referenced by cooling_and_starformation().

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

◆ quicklyastarformation()

static int quicklyastarformation ( int  i,
const double  a3inv 
)
static

Definition at line 641 of file sfr_eff.c.

642 {
643  if(SPHP(i).Density <= sfr_params.OverDensThresh)
644  return 0;
645 
646  const double enttou = pow(SPHP(i).Density * a3inv, GAMMA_MINUS1) / GAMMA_MINUS1;
647  double unew = SPHP(i).Entropy * enttou;
648 
649  const double meanweight = (4 / (8 - 5 * (1 - HYDROGEN_MASSFRAC)));
650  double temp = unew * meanweight / sfr_params.temp_to_u;
651 
653  return 0;
654 
656  return 1;
657 
658  return 0;
659 }
double QuickLymanAlphaTempThresh
Definition: sfr_eff.c:63
double get_random_number(uint64_t id)
Definition: system.c:60

References sph_particle_data::Density, GAMMA_MINUS1, get_random_number(), HYDROGEN_MASSFRAC, SFRParams::OverDensThresh, P, SFRParams::QuickLymanAlphaProbability, SFRParams::QuickLymanAlphaTempThresh, sfr_params, SPHP, and SFRParams::temp_to_u.

Referenced by cooling_and_starformation().

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

◆ set_sfr_params()

void set_sfr_params ( ParameterSet ps)

Definition at line 129 of file sfr_eff.c.

130 {
131  int ThisTask;
132  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
133  if(ThisTask == 0) {
134  /*Star formation parameters*/
135  sfr_params.StarformationCriterion = (enum StarformationCriterion) param_get_enum(ps, "StarformationCriterion");
136  sfr_params.CritOverDensity = param_get_double(ps, "CritOverDensity");
137  sfr_params.CritPhysDensity = param_get_double(ps, "CritPhysDensity");
138  sfr_params.WindOn = param_get_int(ps, "WindOn");
139 
140  sfr_params.FactorSN = param_get_double(ps, "FactorSN");
141  sfr_params.FactorEVP = param_get_double(ps, "FactorEVP");
142  sfr_params.TempSupernova = param_get_double(ps, "TempSupernova");
143  sfr_params.TempClouds = param_get_double(ps, "TempClouds");
144  sfr_params.MaxSfrTimescale = param_get_double(ps, "MaxSfrTimescale");
145  sfr_params.Generations = param_get_int(ps, "Generations");
146  sfr_params.MinGasTemp = param_get_double(ps, "MinGasTemp");
147  sfr_params.BHFeedbackUseTcool = param_get_int(ps, "BHFeedbackUseTcool");
149  endrun(0, "BHFeedbackUseTcool mode %d not supported\n", sfr_params.BHFeedbackUseTcool);
150  /*Lyman-alpha forest parameters*/
151  sfr_params.QuickLymanAlphaProbability = param_get_double(ps, "QuickLymanAlphaProbability");
152  sfr_params.QuickLymanAlphaTempThresh = param_get_double(ps, "QuickLymanAlphaTempThresh");
153  sfr_params.HIReionTemp = param_get_double(ps, "HIReionTemp");
154 
155  /* File names*/
156  param_get_string2(ps, "TreeCoolFile", sfr_params.TreeCoolFile, sizeof(sfr_params.TreeCoolFile));
158  param_get_string2(ps, "MetalCoolFile", sfr_params.MetalCoolFile, sizeof(sfr_params.MetalCoolFile));
159  param_get_string2(ps, "ReionHistFile", sfr_params.ReionHistFile, sizeof(sfr_params.ReionHistFile));
160  }
161  MPI_Bcast(&sfr_params, sizeof(struct SFRParams), MPI_BYTE, 0, MPI_COMM_WORLD);
162 }
double param_get_double(ParameterSet *ps, const char *name)
Definition: paramset.c:336
void param_get_string2(ParameterSet *ps, const char *name, char *dst, size_t len)
Definition: paramset.c:355
int param_get_int(ParameterSet *ps, const char *name)
Definition: paramset.c:368
int param_get_enum(ParameterSet *ps, const char *name)
Definition: paramset.c:378
StarformationCriterion
Definition: sfr_eff.h:16
int ThisTask
Definition: test_exchange.c:23

References SFRParams::BHFeedbackUseTcool, SFRParams::CritOverDensity, SFRParams::CritPhysDensity, endrun(), SFRParams::FactorEVP, SFRParams::FactorSN, SFRParams::Generations, SFRParams::HIReionTemp, SFRParams::MaxSfrTimescale, SFRParams::MetalCoolFile, SFRParams::MinGasTemp, param_get_double(), param_get_enum(), param_get_int(), param_get_string2(), SFRParams::QuickLymanAlphaProbability, SFRParams::QuickLymanAlphaTempThresh, SFRParams::ReionHistFile, sfr_params, SFRParams::StarformationCriterion, SFRParams::TempClouds, SFRParams::TempSupernova, ThisTask, SFRParams::TreeCoolFile, SFRParams::UVFluctuationFile, and SFRParams::WindOn.

Referenced by read_parameter_file().

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

◆ sfr_need_to_compute_sph_grad_rho()

int sfr_need_to_compute_sph_grad_rho ( void  )

Definition at line 952 of file sfr_eff.c.

953 {
955  return 1;
956  }
957  return 0;
958 }

References HAS, SFR_CRITERION_MOLECULAR_H2, sfr_params, and SFRParams::StarformationCriterion.

Referenced by run(), and runfof().

Here is the caller graph for this function:

◆ sfr_reserve_slots()

static int * sfr_reserve_slots ( ActiveParticles act,
int *  NewStars,
int  NumNewStar,
ForceTree tt 
)
static

Definition at line 380 of file sfr_eff.c.

381 {
382  /* SlotsManager is below Nodes and ActiveParticleList,
383  * so we need to move them out of the way before we extend Nodes.
384  * This is quite slow, but need not be collective and is faster than a tree rebuild.
385  * Try not to do this too often.*/
386  message(1, "Need %d star slots, more than %d available. Try increasing SlotsIncreaseFactor on restart.\n", SlotsManager->info[4].size, SlotsManager->info[4].maxsize);
387  /*Move the NewStar array to upper memory*/
388  int * new_star_tmp = NULL;
389  if(NewStars) {
390  new_star_tmp = (int *) mymalloc2("newstartmp", NumNewStar*sizeof(int));
391  memmove(new_star_tmp, NewStars, NumNewStar * sizeof(int));
392  myfree(NewStars);
393  }
394  /*Move the tree to upper memory*/
395  struct NODE * nodes_base_tmp=NULL;
396  int *Father_tmp=NULL;
397  int *ActiveParticle_tmp=NULL;
398  if(force_tree_allocated(tree)) {
399  nodes_base_tmp = (struct NODE *) mymalloc2("nodesbasetmp", tree->numnodes * sizeof(struct NODE));
400  memmove(nodes_base_tmp, tree->Nodes_base, tree->numnodes * sizeof(struct NODE));
401  myfree(tree->Nodes_base);
402  Father_tmp = (int *) mymalloc2("Father_tmp", PartManager->MaxPart * sizeof(int));
403  memmove(Father_tmp, tree->Father, PartManager->MaxPart * sizeof(int));
404  myfree(tree->Father);
405  }
406  if(act->ActiveParticle) {
407  ActiveParticle_tmp = (int *) mymalloc2("ActiveParticle_tmp", act->NumActiveParticle * sizeof(int));
408  memmove(ActiveParticle_tmp, act->ActiveParticle, act->NumActiveParticle * sizeof(int));
409  myfree(act->ActiveParticle);
410  }
411  /*Now we can extend the slots! */
412  int64_t atleast[6];
413  int64_t i;
414  for(i = 0; i < 6; i++)
415  atleast[i] = SlotsManager->info[i].maxsize;
416  atleast[4] += NumNewStar;
417  slots_reserve(1, atleast, SlotsManager);
418 
419  /*And now we need our memory back in the right place*/
420  if(ActiveParticle_tmp) {
421  act->ActiveParticle = (int *) mymalloc("ActiveParticle", sizeof(int)*(act->NumActiveParticle + PartManager->MaxPart - PartManager->NumPart));
422  memmove(act->ActiveParticle, ActiveParticle_tmp, act->NumActiveParticle * sizeof(int));
423  myfree(ActiveParticle_tmp);
424  }
425  if(force_tree_allocated(tree)) {
426  tree->Father = (int *) mymalloc("Father", PartManager->MaxPart * sizeof(int));
427  memmove(tree->Father, Father_tmp, PartManager->MaxPart * sizeof(int));
428  myfree(Father_tmp);
429  tree->Nodes_base = (struct NODE *) mymalloc("Nodes_base", tree->numnodes * sizeof(struct NODE));
430  memmove(tree->Nodes_base, nodes_base_tmp, tree->numnodes * sizeof(struct NODE));
431  myfree(nodes_base_tmp);
432  /*Don't forget to update the Node pointer as well as Node_base!*/
433  tree->Nodes = tree->Nodes_base - tree->firstnode;
434  }
435  if(new_star_tmp) {
436  NewStars = (int *) mymalloc("NewStars", NumNewStar*sizeof(int));
437  memmove(NewStars, new_star_tmp, NumNewStar * sizeof(int));
438  myfree(new_star_tmp);
439  }
440  return NewStars;
441 }
int force_tree_allocated(const ForceTree *tree)
Definition: forcetree.c:134
size_t slots_reserve(int where, int64_t atleast[6], struct slots_manager_type *sman)
Definition: slotsmanager.c:475
Definition: forcetree.h:39

References ActiveParticles::ActiveParticle, ForceTree::Father, ForceTree::firstnode, force_tree_allocated(), slots_manager_type::info, part_manager_type::MaxPart, slot_info::maxsize, message(), myfree, mymalloc, mymalloc2, ForceTree::Nodes, ForceTree::Nodes_base, ActiveParticles::NumActiveParticle, ForceTree::numnodes, part_manager_type::NumPart, PartManager, slot_info::size, slots_reserve(), and SlotsManager.

Referenced by cooling_and_starformation().

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

◆ sfreff_on_eeqos()

int sfreff_on_eeqos ( const struct sph_particle_data sph,
const double  a3inv 
)

Definition at line 486 of file sfr_eff.c.

487 {
488  int flag = 0;
489  /* no sfr: normal cooling*/
491  return 0;
492  }
493 
494  if(sph->Density * a3inv >= sfr_params.PhysDensThresh)
495  flag = 1;
496 
498  flag = 0;
499 
500  if(sph->DelayTime > 0)
501  flag = 0; /* only normal cooling for particles in the wind */
502 
503  /* The model from 0904.2572 makes gas not star forming if more than 0.5 dex above
504  * the effective equation of state (at z=0). This in practice means black hole heated.*/
505  if(flag == 1 && sfr_params.BHFeedbackUseTcool == 2) {
506  //Redshift is the argument
507  double redshift = pow(a3inv, 1./3.)-1;
508  struct UVBG uvbg = get_global_UVBG(redshift);
509  double egyeff = get_egyeff(redshift, sph->Density, &uvbg);
510  const double enttou = pow(sph->Density * a3inv, GAMMA_MINUS1) / GAMMA_MINUS1;
511  double unew = sph->Entropy * enttou;
512  /* 0.5 dex = 10^0.5 = 3.2 */
513  if(unew >= egyeff * 3.2)
514  flag = 0;
515  }
516  return flag;
517 }

References SFRParams::BHFeedbackUseTcool, sph_particle_data::DelayTime, sph_particle_data::Density, sph_particle_data::Entropy, GAMMA_MINUS1, get_egyeff(), get_global_UVBG(), SFRParams::OverDensThresh, SFRParams::PhysDensThresh, sfr_params, and SFRParams::StarformationOn.

Referenced by blackhole_feedback_ngbiter(), cooling_and_starformation(), get_helium_neutral_fraction_sfreff(), get_neutral_fraction_sfreff(), and get_starformation_rate_full().

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

◆ starformation()

static int starformation ( int  i,
double *  localsfr,
MyFloat sm_out,
MyFloat GradRho,
const double  redshift,
const double  a3inv,
const double  hubble,
const double  GravInternal,
const struct UVBG *const  GlobalUVBG 
)
static

Definition at line 666 of file sfr_eff.c.

667 {
668  /* the proper time-step */
669  double dloga = get_dloga_for_bin(P[i].TimeBin, P[i].Ti_drift);
670  double dtime = dloga / hubble;
671  int newstar = -1;
672 
673  struct UVBG uvbg = get_local_UVBG(redshift, GlobalUVBG, P[i].Pos, PartManager->CurrentParticleOffset);
674 
675  struct sfr_eeqos_data sfr_data = get_sfr_eeqos(&P[i], &SPHP(i), dtime, &uvbg, redshift, a3inv);
676 
677  double atime = 1/(1+redshift);
678  double smr = get_starformation_rate_full(i, GradRho, sfr_data, atime, a3inv, hubble, GravInternal);
679 
680  double sm = smr * dtime;
681 
682  *sm_out = sm;
683  double p = sm / P[i].Mass;
684 
685  /* convert to Solar per Year.*/
687  SPHP(i).Ne = sfr_data.ne;
688  *localsfr += SPHP(i).Sfr;
689 
690  const double w = get_random_number(P[i].ID);
691  const double frac = (1 - exp(-p));
692  SPHP(i).Metallicity += w * METAL_YIELD * frac / sfr_params.Generations;
693 
694  /* upon start-up, we need to protect against dloga ==0 */
695  if(dloga > 0 && P[i].TimeBin)
696  cooling_relaxed(i, dtime, &uvbg, redshift, a3inv, sfr_data, GlobalUVBG);
697 
698  double mass_of_star = find_star_mass(i, sfr_params.avg_baryon_mass);
699  double prob = P[i].Mass / mass_of_star * (1 - exp(-p));
700 
701  int form_star = (get_random_number(P[i].ID + 1) < prob);
702  if(form_star) {
703  /* ok, make a star */
704  newstar = i;
705  /* If we get a fraction of the mass we need to create
706  * a new particle for the star and remove mass from i.*/
707  if(P[i].Mass >= 1.1 * mass_of_star)
708  newstar = slots_split_particle(i, mass_of_star, PartManager);
709  }
710 
711  /* Add the rest of the metals if we didn't form a star.
712  * If we did form a star, add winds to the star-forming particle
713  * that formed it if it is still around*/
714  if(!form_star || newstar != i) {
715  SPHP(i).Metallicity += (1-w) * METAL_YIELD * frac / sfr_params.Generations;
716  }
717  return newstar;
718 }
static double get_starformation_rate_full(int i, MyFloat *GradRho, struct sfr_eeqos_data sfr_data, const double atime, const double a3inv, const double hubble, const double GravInternal)
Definition: sfr_eff.c:759
static void cooling_relaxed(int i, double dtime, struct UVBG *local_uvbg, const double redshift, const double a3inv, struct sfr_eeqos_data sfr_data, const struct UVBG *const GlobalUVBG)
Definition: sfr_eff.c:606
static double find_star_mass(int i, const double avg_baryon_mass)
Definition: sfr_eff.c:921
int slots_split_particle(int parent, double childmass, struct part_manager_type *pman)
Definition: slotsmanager.c:103

Referenced by cooling_and_starformation().

Here is the caller graph for this function:

Variable Documentation

◆ sfr_params

struct SFRParams sfr_params
static