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

code for initialisation of a simulation from initial conditions More...

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <mpi.h>
#include <gsl/gsl_sf_gamma.h>
#include "init.h"
#include "utils.h"
#include "cooling.h"
#include "forcetree.h"
#include "density.h"
#include "timefac.h"
#include "petaio.h"
#include "domain.h"
#include "walltime.h"
#include "slotsmanager.h"
#include "hydra.h"
#include "sfr_eff.h"
#include "exchange.h"
#include "fof.h"
#include "timestep.h"
#include "timebinmgr.h"
#include "cosmology.h"
#include "gravity.h"
#include "physconst.h"
Include dependency graph for init.c:

Go to the source code of this file.

Classes

struct  init_params
 

Functions

void set_init_params (ParameterSet *ps)
 
void init_timeline (int RestartSnapNum, double TimeMax, const struct header_data *header, const int SnapshotWithFOF)
 
static void get_mean_separation (double *MeanSeparation, const double BoxSize, const int64_t *NTotalInit)
 
static void check_omega (struct part_manager_type *PartManager, Cosmology *CP, int generations, double G, double *MassTable)
 
static void check_positions (struct part_manager_type *PartManager)
 
static void check_smoothing_length (struct part_manager_type *PartManager, double *MeanSpacing)
 
static void init_alloc_particle_slot_memory (struct part_manager_type *PartManager, struct slots_manager_type *SlotsManager, const double PartAllocFactor, struct header_data *header, MPI_Comm Comm)
 
inttime_t init (int RestartSnapNum, const char *OutputDir, struct header_data *header, Cosmology *CP)
 
void check_density_entropy (Cosmology *CP, const double MinEgySpec, const double atime)
 
static void setup_density_indep_entropy (const ActiveParticles *act, ForceTree *Tree, Cosmology *CP, struct sph_pred_data *sph_pred, double u_init, double a3, int BlackHoleOn, const inttime_t Ti_Current)
 
void setup_smoothinglengths (int RestartSnapNum, DomainDecomp *ddecomp, Cosmology *CP, int BlackHoleOn, double MinEgySpec, double uu_in_cgs, const inttime_t Ti_Current, const double atime, const int64_t NTotGasInit)
 

Variables

static struct init_params InitParams
 

Detailed Description

code for initialisation of a simulation from initial conditions

Definition in file init.c.

Function Documentation

◆ check_density_entropy()

void check_density_entropy ( Cosmology CP,
const double  MinEgySpec,
const double  atime 
)

Definition at line 344 of file init.c.

345 {
346  const double a3 = pow(atime, 3);
347  int i;
348  int bad = 0;
349  double meanbar = CP->OmegaBaryon * 3 * HUBBLE * CP->HubbleParam * HUBBLE * CP->HubbleParam/ (8 * M_PI * GRAVITY);
350  #pragma omp parallel for reduction(+: bad)
351  for(i = 0; i < SlotsManager->info[0].size; i++) {
352  /* This allows us to continue gracefully if
353  * there was some kind of bug in the run that output the snapshot.
354  * density() below will fix this up.*/
355  if(SphP[i].Density <= 0 || !isfinite(SphP[i].Density)) {
356  SphP[i].Density = meanbar;
357  bad++;
358  }
359  if(SphP[i].EgyWtDensity <= 0 || !isfinite(SphP[i].EgyWtDensity)) {
360  SphP[i].EgyWtDensity = SphP[i].Density;
361  }
362  double minent = GAMMA_MINUS1 * MinEgySpec / pow(SphP[i].Density / a3 , GAMMA_MINUS1);
363  if(SphP[i].Entropy < minent)
364  SphP[i].Entropy = minent;
365  }
366  MPI_Allreduce(MPI_IN_PLACE, &bad, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
367  if(bad > 0)
368  message(0, "Detected bad densities in %d particles on disc\n",bad);
369 }
void message(int where, const char *fmt,...)
Definition: endrun.c:175
#define HUBBLE
Definition: physconst.h:25
#define GRAVITY
Definition: physconst.h:5
#define GAMMA_MINUS1
Definition: physconst.h:35
static Cosmology * CP
Definition: power.c:27
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
#define SphP
Definition: slotsmanager.h:119
double HubbleParam
Definition: cosmology.h:20
double OmegaBaryon
Definition: cosmology.h:19
int64_t size
Definition: slotsmanager.h:12
struct slot_info info[6]
Definition: slotsmanager.h:112

References CP, GAMMA_MINUS1, GRAVITY, HUBBLE, Cosmology::HubbleParam, slots_manager_type::info, message(), Cosmology::OmegaBaryon, slot_info::size, SlotsManager, and SphP.

Referenced by begrun().

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

◆ check_omega()

void check_omega ( struct part_manager_type PartManager,
Cosmology CP,
int  generations,
double  G,
double *  MassTable 
)
static

This routine computes the mass content of the box and compares it to the specified value of Omega-matter. If discrepant, the run is terminated.

Definition at line 184 of file init.c.

185 {
186  double mass = 0, masstot, omega;
187  int i, badmass = 0;
188  int64_t totbad;
189 
190  #pragma omp parallel for reduction(+: mass) reduction(+: badmass)
191  for(i = 0; i < PartManager->NumPart; i++) {
192  /* In case zeros have been written to the saved mass array,
193  * recover the true masses*/
194  if(P[i].Mass == 0) {
195  P[i].Mass = MassTable[P[i].Type] * ( 1. - (double)P[i].Generation/generations);
196  badmass++;
197  }
198  mass += P[i].Mass;
199  }
200 
201  MPI_Allreduce(&mass, &masstot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
202 
203  sumup_large_ints(1, &badmass, &totbad);
204  if(totbad)
205  message(0, "Warning: recovering from %ld Mass entries corrupted on disc\n",totbad);
206 
207  omega =
208  masstot / (PartManager->BoxSize * PartManager->BoxSize * PartManager->BoxSize) / (3 * CP->Hubble * CP->Hubble / (8 * M_PI * G));
209 
210  /*Add the density for analytically follows massive neutrinos*/
212  omega += get_omega_nu_nopart(&CP->ONu, 1);
213  if(fabs(omega - CP->Omega0) > 1.0e-3)
214  {
215  endrun(0, "The mass content accounts only for Omega=%g,\nbut you specified Omega=%g in the parameterfile.\n",
216  omega, CP->Omega0);
217  }
218 }
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
double get_omega_nu_nopart(const _omega_nu *const omnu, const double a)
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define P
Definition: partmanager.h:88
double Omega0
Definition: cosmology.h:10
int MassiveNuLinRespOn
Definition: cosmology.h:26
_omega_nu ONu
Definition: cosmology.h:24
double Hubble
Definition: cosmology.h:21
void sumup_large_ints(int n, int *src, int64_t *res)
Definition: system.c:192
static const double G
Definition: test_gravity.c:35

References part_manager_type::BoxSize, CP, endrun(), G, get_omega_nu_nopart(), Cosmology::Hubble, Cosmology::MassiveNuLinRespOn, message(), part_manager_type::NumPart, Cosmology::Omega0, Cosmology::ONu, P, PartManager, and sumup_large_ints().

Referenced by init().

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

◆ check_positions()

void check_positions ( struct part_manager_type PartManager)
static

This routine checks that the initial positions of the particles are within the box. If not, there is likely a bug in the IC generator and we abort. It also checks for multiple zeros in the positions, guarding against a common fs bug.

Definition at line 294 of file init.c.

295 {
296  int i;
297  int numzero = 0;
298  int lastzero = -1;
299 
300  #pragma omp parallel for reduction(+: numzero) reduction(max:lastzero)
301  for(i=0; i< PartManager->NumPart; i++){
302  int j;
303  double * Pos = PartManager->Base[i].Pos;
304  for(j=0; j<3; j++) {
305  if(Pos[j] < 0 || Pos[j] > PartManager->BoxSize || !isfinite(Pos[j]))
306  endrun(0,"Particle %d is outside the box (L=%g) at (%g %g %g)\n",i, PartManager->BoxSize, Pos[0], Pos[1], Pos[2]);
307  }
308  if((Pos[0] < 1e-35) && (Pos[1] < 1e-35) && (Pos[2] < 1e-35)) {
309  numzero++;
310  lastzero = i;
311  }
312  }
313  if(numzero > 1)
314  endrun(5, "Particle positions contain %d zeros at particle %d. Pos %g %g %g. Likely write corruption!\n",
315  numzero, lastzero, PartManager->Base[lastzero].Pos[0], PartManager->Base[lastzero].Pos[1], PartManager->Base[lastzero].Pos[2]);
316 }
struct particle_data * Base
Definition: partmanager.h:74
double Pos[3]
Definition: partmanager.h:12

References part_manager_type::Base, part_manager_type::BoxSize, endrun(), part_manager_type::NumPart, PartManager, and particle_data::Pos.

Referenced by init().

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

◆ check_smoothing_length()

void check_smoothing_length ( struct part_manager_type PartManager,
double *  MeanSpacing 
)
static

This routine checks that the initial smoothing lengths of the particles are sensible and resets them to mean interparticle spacing if not. Guards against a problem writing the snapshot. Matters because a very large initial smoothing length will cause density() to go crazy.

Definition at line 323 of file init.c.

324 {
325  int i;
326  int numprob = 0;
327  int lastprob = -1;
328  #pragma omp parallel for reduction(+: numprob) reduction(max:lastprob)
329  for(i=0; i< PartManager->NumPart; i++){
330  if(P[i].Type != 5 && P[i].Type != 0)
331  continue;
332  if(P[i].Hsml > PartManager->BoxSize || P[i].Hsml <= 0) {
333  P[i].Hsml = MeanSpacing[P[i].Type];
334  numprob++;
335  lastprob = i;
336  }
337  }
338  if(numprob > 0)
339  message(5, "Bad smoothing lengths %d last bad %d hsml %g id %ld\n", numprob, lastprob, P[lastprob].Hsml, P[lastprob].ID);
340 }

References part_manager_type::BoxSize, message(), part_manager_type::NumPart, P, and PartManager.

Referenced by init().

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

◆ get_mean_separation()

void get_mean_separation ( double *  MeanSeparation,
const double  BoxSize,
const int64_t *  NTotalInit 
)
static

Definition at line 371 of file init.c.

372 {
373  int i;
374  for(i = 0; i < 6; i++) {
375  if(NTotalInit[i] > 0)
376  MeanSeparation[i] = BoxSize / pow(NTotalInit[i], 1.0 / 3);
377  }
378 }

Referenced by init().

Here is the caller graph for this function:

◆ init()

inttime_t init ( int  RestartSnapNum,
const char *  OutputDir,
struct header_data header,
Cosmology CP 
)

This function reads the initial conditions, allocates storage for the particle data, validates and initialises the particle data.

Definition at line 86 of file init.c.

87 {
88  int i;
89 
91 
92  /*Read the snapshot*/
93  petaio_read_snapshot(RestartSnapNum, OutputDir, CP, header, PartManager, SlotsManager, MPI_COMM_WORLD);
94 
96 
98 
100 
101  double MeanSeparation[6] = {0};
102 
103  get_mean_separation(MeanSeparation, PartManager->BoxSize, header->NTotalInit);
104 
105  if(RestartSnapNum == -1)
106  check_smoothing_length(PartManager, MeanSeparation);
107 
108  /* As the above will mostly take place
109  * on Task 0, there will be a lot of imbalance*/
110  MPIU_Barrier(MPI_COMM_WORLD);
111 
112  gravshort_set_softenings(MeanSeparation[1]);
113  fof_init(MeanSeparation[1]);
114 
115  inttime_t Ti_Current = init_timebins(header->TimeSnapshot);
116 
117  #pragma omp parallel for
118  for(i = 0; i < PartManager->NumPart; i++) /* initialize sph_properties */
119  {
120  int j;
121  P[i].Ti_drift = Ti_Current;
122 
123  if(RestartSnapNum == -1 && P[i].Type == 5 )
124  {
125  /* Note: Gadget-3 sets this to the seed black hole mass.*/
126  BHP(i).Mass = P[i].Mass;
127  }
128 
129  if(P[i].Type == 4 )
130  {
131  /* Touch up zero star smoothing lengths, not saved in the snapshots.*/
132  if(P[i].Hsml == 0)
133  P[i].Hsml = 0.1 * MeanSeparation[0];
134  }
135 
136  if(P[i].Type == 5)
137  {
138  for(j = 0; j < 3; j++) {
139  BHP(i).DFAccel[j] = 0;
140  BHP(i).DragAccel[j] = 0;
141  }
142  }
143 
144  P[i].Key = PEANO(P[i].Pos, PartManager->BoxSize);
145 
146  if(P[i].Type != 0) continue;
147 
148  for(j = 0; j < 3; j++)
149  {
150  SPHP(i).HydroAccel[j] = 0;
151  }
152 
153  if(!isfinite(SPHP(i).DelayTime ))
154  endrun(6, "Bad DelayTime %g for part %d id %ld\n", SPHP(i).DelayTime, i, P[i].ID);
155  SPHP(i).DtEntropy = 0;
156 
157  if(RestartSnapNum == -1)
158  {
159  SPHP(i).Density = -1;
160  SPHP(i).EgyWtDensity = -1;
161  SPHP(i).DhsmlEgyDensityFactor = -1;
162  SPHP(i).Entropy = -1;
163  SPHP(i).Ne = 1.0;
164  SPHP(i).DivVel = 0;
165  SPHP(i).CurlVel = 0;
166  SPHP(i).DelayTime = 0;
167  SPHP(i).Metallicity = 0;
168  memset(SPHP(i).Metals, 0, NMETALS*sizeof(float));
169  /* Initialise to primordial abundances for H and He*/
170  SPHP(i).Metals[0] = HYDROGEN_MASSFRAC;
171  SPHP(i).Metals[1] = 1- HYDROGEN_MASSFRAC;
172  SPHP(i).Sfr = 0;
173  SPHP(i).MaxSignalVel = 0;
174  }
175  }
176  walltime_measure("/Init");
177  return Ti_Current;
178 }
void domain_test_id_uniqueness(struct part_manager_type *pman)
Definition: exchange.c:570
void fof_init(double DMMeanSeparation)
Definition: fof.c:66
void gravshort_set_softenings(double MeanDMSeparation)
static void check_omega(struct part_manager_type *PartManager, Cosmology *CP, int generations, double G, double *MassTable)
Definition: init.c:184
static struct init_params InitParams
static void check_smoothing_length(struct part_manager_type *PartManager, double *MeanSpacing)
Definition: init.c:323
static void check_positions(struct part_manager_type *PartManager)
Definition: init.c:294
static void init_alloc_particle_slot_memory(struct part_manager_type *PartManager, struct slots_manager_type *SlotsManager, const double PartAllocFactor, struct header_data *header, MPI_Comm Comm)
Definition: init.c:222
static void get_mean_separation(double *MeanSeparation, const double BoxSize, const int64_t *NTotalInit)
Definition: init.c:371
static peano_t PEANO(double *Pos, double BoxSize)
Definition: peano.h:14
void petaio_read_snapshot(int num, const char *OutputDir, Cosmology *CP, struct header_data *header, struct part_manager_type *PartManager, struct slots_manager_type *SlotsManager, MPI_Comm Comm)
Definition: petaio.c:255
#define HYDROGEN_MASSFRAC
Definition: physconst.h:37
int get_generations(void)
Definition: sfr_eff.c:87
#define BHP(i)
Definition: slotsmanager.h:125
#define SPHP(i)
Definition: slotsmanager.h:124
#define NMETALS
Definition: slotsmanager.h:60
double GravInternal
Definition: cosmology.h:32
int64_t NTotalInit[6]
Definition: petaio.h:20
double TimeSnapshot
Definition: petaio.h:26
double MassTable[6]
Definition: petaio.h:22
double PartAllocFactor
Definition: init.c:40
#define MPIU_Barrier(comm)
Definition: system.h:103
inttime_t init_timebins(double TimeInit)
Definition: timestep.c:123
int32_t inttime_t
Definition: types.h:8
#define walltime_measure(name)
Definition: walltime.h:8

References BHP, part_manager_type::BoxSize, check_omega(), check_positions(), check_smoothing_length(), CP, domain_test_id_uniqueness(), endrun(), fof_init(), get_generations(), get_mean_separation(), Cosmology::GravInternal, gravshort_set_softenings(), HYDROGEN_MASSFRAC, init_alloc_particle_slot_memory(), init_timebins(), InitParams, header_data::MassTable, MPIU_Barrier, NMETALS, header_data::NTotalInit, part_manager_type::NumPart, P, init_params::PartAllocFactor, PartManager, PEANO(), petaio_read_snapshot(), SlotsManager, SPHP, header_data::TimeSnapshot, and walltime_measure.

Referenced by begrun().

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

◆ init_alloc_particle_slot_memory()

static void init_alloc_particle_slot_memory ( struct part_manager_type PartManager,
struct slots_manager_type SlotsManager,
const double  PartAllocFactor,
struct header_data header,
MPI_Comm  Comm 
)
static

Definition at line 222 of file init.c.

223 {
224  int NTask, ThisTask;
225  MPI_Comm_size(Comm, &NTask);
226  MPI_Comm_rank(Comm, &ThisTask);
227 
228  int ptype;
229 
230  int64_t TotNumPart = 0;
231  int64_t TotNumPartInit= 0;
232  for(ptype = 0; ptype < 6; ptype ++) {
233  TotNumPart += header->NTotal[ptype];
234  TotNumPartInit += header->NTotalInit[ptype];
235  }
236 
237  message(0, "Total number of particles: %018ld\n", TotNumPart);
238 
239  const char * PARTICLE_TYPE_NAMES [] = {"Gas", "DarkMatter", "Neutrino", "Unknown", "Star", "BlackHole"};
240 
241  for(ptype = 0; ptype < 6; ptype ++) {
242  double MeanSeparation = header->BoxSize / pow(header->NTotalInit[ptype], 1.0 / 3);
243  message(0, "% 11s: Total: %018ld Init: %018ld Mean-Sep %g \n",
244  PARTICLE_TYPE_NAMES[ptype], header->NTotal[ptype], header->NTotalInit[ptype], MeanSeparation);
245  }
246 
247  /* sets the maximum number of particles that may reside on a processor */
248  int MaxPart = (int) (PartAllocFactor * TotNumPartInit / NTask);
249 
250  /*Allocate the particle memory*/
251  particle_alloc_memory(PartManager, header->BoxSize, MaxPart);
252 
253  for(ptype = 0; ptype < 6; ptype ++) {
254  int64_t start = ThisTask * header->NTotal[ptype] / NTask;
255  int64_t end = (ThisTask + 1) * header->NTotal[ptype] / NTask;
256  header->NLocal[ptype] = end - start;
257  PartManager->NumPart += header->NLocal[ptype];
258  }
259 
260  /* Allocate enough memory for stars and black holes.
261  * This will be dynamically increased as needed.*/
262 
264  endrun(1, "Overwhelmed by part: %ld > %ld\n", PartManager->NumPart, PartManager->MaxPart);
265  }
266 
267  /* Now allocate memory for the secondary particle data arrays.
268  * This may be dynamically resized later!*/
269 
270  /*Ensure all processors have initially the same number of particle slots*/
271  int64_t newSlots[6] = {0};
272 
273  /* Can't use MPI_IN_PLACE, which is broken for arrays and MPI_MAX at least on intel mpi 19.0.5*/
274  MPI_Allreduce(header->NLocal, newSlots, 6, MPI_INT64, MPI_MAX, Comm);
275 
276  for(ptype = 0; ptype < 6; ptype ++) {
277  newSlots[ptype] *= PartAllocFactor;
278  }
279  /* Boost initial amount of stars allocated, as it is often uneven.
280  * The total number of stars is usually small so this doesn't
281  * waste that much memory*/
282  newSlots[4] *= 2;
283 
284  slots_reserve(0, newSlots, SlotsManager);
285 
286  /* so we can set up the memory topology of secondary slots */
288 }
void particle_alloc_memory(struct part_manager_type *PartManager, double BoxSize, int64_t MaxPart)
Definition: partmanager.c:14
size_t slots_reserve(int where, int64_t atleast[6], struct slots_manager_type *sman)
Definition: slotsmanager.c:475
void slots_setup_topology(struct part_manager_type *pman, int64_t *NLocal, struct slots_manager_type *sman)
Definition: slotsmanager.c:624
int64_t NLocal[6]
Definition: petaio.h:16
double BoxSize
Definition: petaio.h:28
int64_t NTotal[6]
Definition: petaio.h:18
#define MPI_INT64
Definition: system.h:12
int ThisTask
Definition: test_exchange.c:23
int NTask
Definition: test_exchange.c:23
int TotNumPart
Definition: test_exchange.c:24
static enum TransferType ptype
Definition: zeldovich.c:146

References header_data::BoxSize, endrun(), part_manager_type::MaxPart, message(), MPI_INT64, header_data::NLocal, NTask, header_data::NTotal, header_data::NTotalInit, part_manager_type::NumPart, particle_alloc_memory(), PartManager, ptype, slots_reserve(), slots_setup_topology(), SlotsManager, ThisTask, and TotNumPart.

Referenced by init().

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

◆ init_timeline()

void init_timeline ( int  RestartSnapNum,
double  TimeMax,
const struct header_data header,
const int  SnapshotWithFOF 
)

Definition at line 56 of file init.c.

57 {
58  /*Add TimeInit and TimeMax to the output list*/
59  if (RestartSnapNum < 0) {
60  /* allow a first snapshot at IC time; */
61  setup_sync_points(header->TimeIC, TimeMax, 0.0, SnapshotWithFOF);
62  } else {
63  /* skip dumping the exactly same snapshot */
64  setup_sync_points(header->TimeIC, TimeMax, header->TimeSnapshot, SnapshotWithFOF);
65  /* If TimeInit is not in a sensible place on the integer timeline
66  * (can happen if the outputs changed since it was written)
67  * start the integer timeline anew from TimeInit */
68  inttime_t ti_init = ti_from_loga(log(header->TimeSnapshot)) % TIMEBASE;
69  if(round_down_power_of_two(ti_init) != ti_init) {
70  message(0,"Resetting integer timeline (as %x != %x) to current snapshot\n",ti_init, round_down_power_of_two(ti_init));
71  setup_sync_points(header->TimeSnapshot, TimeMax, header->TimeSnapshot, SnapshotWithFOF);
72  }
73  }
74 }
double TimeIC
Definition: petaio.h:24
inttime_t ti_from_loga(double loga)
Definition: timebinmgr.c:236
inttime_t round_down_power_of_two(inttime_t dti)
Definition: timebinmgr.c:286
void setup_sync_points(double TimeIC, double TimeMax, double no_snapshot_until_time, int SnapshotWithFOF)
Definition: timebinmgr.c:97
#define TIMEBASE
Definition: timebinmgr.h:14

References message(), round_down_power_of_two(), setup_sync_points(), ti_from_loga(), TIMEBASE, header_data::TimeIC, and header_data::TimeSnapshot.

Referenced by begrun().

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

◆ set_init_params()

void set_init_params ( ParameterSet ps)

Definition at line 45 of file init.c.

46 {
47  int ThisTask;
48  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
49  if(ThisTask == 0) {
50  InitParams.InitGasTemp = param_get_double(ps, "InitGasTemp");
51  InitParams.PartAllocFactor = param_get_double(ps, "PartAllocFactor");
52  }
53  MPI_Bcast(&InitParams, sizeof(InitParams), MPI_BYTE, 0, MPI_COMM_WORLD);
54 }
double param_get_double(ParameterSet *ps, const char *name)
Definition: paramset.c:336
double InitGasTemp
Definition: init.c:36

References init_params::InitGasTemp, InitParams, param_get_double(), init_params::PartAllocFactor, and ThisTask.

Referenced by read_parameter_file().

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

◆ setup_density_indep_entropy()

static void setup_density_indep_entropy ( const ActiveParticles act,
ForceTree Tree,
Cosmology CP,
struct sph_pred_data sph_pred,
double  u_init,
double  a3,
int  BlackHoleOn,
const inttime_t  Ti_Current 
)
static

Definition at line 384 of file init.c.

385 {
386  int j;
387  int stop = 0;
388 
389  message(0, "Converting u -> entropy, with density split sph\n");
390 
391  /* This gives better convergence than initializing EgyWtDensity before Density is known*/
392  #pragma omp parallel for
393  for(j = 0; j < SlotsManager->info[0].size; j++)
394  SphP[j].EgyWtDensity = SphP[j].Density;
395 
396  MyFloat * olddensity = (MyFloat *)mymalloc("olddensity ", SlotsManager->info[0].size * sizeof(MyFloat));
397  for(j = 0; j < 100; j++)
398  {
399  int i;
400  /* since ICs give energies, not entropies, need to iterate get this initialized correctly */
401  #pragma omp parallel for
402  for(i = 0; i < SlotsManager->info[0].size; i++) {
403  SphP[i].Entropy = GAMMA_MINUS1 * u_init / pow(SphP[i].EgyWtDensity / a3 , GAMMA_MINUS1);
404  olddensity[i] = SphP[i].EgyWtDensity;
405  }
406  /* Empty kick factors as we do not move*/
407  DriftKickTimes times = init_driftkicktime(Ti_Current);
408  /* Update the EgyWtDensity*/
409  density(act, 0, DensityIndependentSphOn(), BlackHoleOn, 0, times, CP, sph_pred, NULL, Tree);
410  if(stop)
411  break;
412 
413  double maxdiff = 0;
414  #pragma omp parallel for reduction(max: maxdiff)
415  for(i = 0; i < SlotsManager->info[0].size; i++) {
416  double value = fabs(SphP[i].EgyWtDensity - olddensity[i]) / SphP[i].EgyWtDensity;
417  maxdiff = DMAX(maxdiff,value);
418  }
419  MPI_Allreduce(MPI_IN_PLACE, &maxdiff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
420 
421  message(0, "iteration %d, max relative change in EgyWtDensity = %g \n", j, maxdiff);
422 
423  /* If maxdiff is small, do one more iteration and stop*/
424  if(maxdiff < 1e-3)
425  stop = 1;
426 
427  }
428  myfree(olddensity);
429 }
void density(const ActiveParticles *act, int update_hsml, int DoEgyDensity, int BlackHoleOn, double MinEgySpec, const DriftKickTimes times, Cosmology *CP, struct sph_pred_data *SPH_predicted, MyFloat *GradRho, const ForceTree *const tree)
Definition: density.c:203
int DensityIndependentSphOn(void)
Definition: hydra.c:49
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define myfree(x)
Definition: mymalloc.h:19
#define DMAX(x, y)
Definition: test_interp.c:11
DriftKickTimes init_driftkicktime(inttime_t Ti_Current)
Definition: timestep.c:133
LOW_PRECISION MyFloat
Definition: types.h:19

References CP, density(), DensityIndependentSphOn(), DMAX, GAMMA_MINUS1, slots_manager_type::info, init_driftkicktime(), message(), myfree, mymalloc, slot_info::size, SlotsManager, and SphP.

Referenced by setup_smoothinglengths().

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

◆ setup_smoothinglengths()

void setup_smoothinglengths ( int  RestartSnapNum,
DomainDecomp ddecomp,
Cosmology CP,
int  BlackHoleOn,
double  MinEgySpec,
double  uu_in_cgs,
const inttime_t  Ti_Current,
const double  atime,
const int64_t  NTotGasInit 
)

This function is used to find an initial smoothing length and initial entropy for each SPH particle. Entropies are set using the initial gas temperature. It guarantees that the number of neighbours will be between desired_ngb-MAXDEV and desired_ngb+MAXDEV. For simplicity, a first guess of the smoothing length is provided to the function density(), which will then iterate if needed to find the right smoothing length.

Definition at line 439 of file init.c.

440 {
441  int i;
442  const double a3 = pow(atime, 3);
443 
444  if(RestartSnapNum >= 0)
445  return;
446 
447  if(InitParams.InitGasTemp < 0)
449 
450  const double MeanGasSeparation = PartManager->BoxSize / pow(NTotGasInit, 1.0 / 3);
451 
452  int64_t tot_sph, tot_bh;
453  MPI_Allreduce(&SlotsManager->info[0].size, &tot_sph, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
454  MPI_Allreduce(&SlotsManager->info[5].size, &tot_bh, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
455 
456  /* Do nothing if we are a pure DM run*/
457  if(tot_sph + tot_bh == 0)
458  return;
459 //
460 
461  ForceTree Tree = {0};
462  /* Need moments because we use them to set Hsml*/
463  force_tree_rebuild(&Tree, ddecomp, 0, 1, NULL);
464 
465  /* quick hack to adjust for the baryon fraction
466  * only this fraction of mass is of that type.
467  * this won't work for non-dm non baryon;
468  * ideally each node shall have separate count of
469  * ptypes of each type.
470  *
471  * Eventually the iteration will fix this. */
472  const double massfactor = CP->OmegaBaryon / CP->Omega0;
473  const double DesNumNgb = GetNumNgb(GetDensityKernelType());
474 
475  #pragma omp parallel for
476  for(i = 0; i < PartManager->NumPart; i++)
477  {
478  /* These initial smoothing lengths are only used for SPH-like particles.*/
479  if(P[i].Type != 0 && P[i].Type != 5)
480  continue;
481 
482  int no = force_get_father(i, &Tree);
483 
484  while(10 * DesNumNgb * P[i].Mass > massfactor * Tree.Nodes[no].mom.mass)
485  {
486  int p = force_get_father(no, &Tree);
487 
488  if(p < 0)
489  break;
490 
491  no = p;
492  }
493 
494  P[i].Hsml =
495  pow(3.0 / (4 * M_PI) * DesNumNgb * P[i].Mass / (massfactor * Tree.Nodes[no].mom.mass),
496  1.0 / 3) * Tree.Nodes[no].len;
497 
498  /* recover from a poor initial guess */
499  if(P[i].Hsml > 500.0 * MeanGasSeparation)
500  P[i].Hsml = MeanGasSeparation;
501 
502  if(P[i].Hsml <= 0)
503  endrun(5, "Bad hsml guess: i=%d, mass = %g type %d hsml %g no %d len %d treemass %g\n",
504  i, P[i].Mass, P[i].Type, P[i].Hsml, no, Tree.Nodes[no].len, Tree.Nodes[no].mom.mass);
505  }
506 
507  /* for clean IC with U input only, we need to iterate to find entropy */
508  double u_init = (1.0 / GAMMA_MINUS1) * (BOLTZMANN / PROTONMASS) * InitParams.InitGasTemp;
509  u_init /= uu_in_cgs; /* unit conversion */
510 
511  double molecular_weight;
512  if(InitParams.InitGasTemp > 1.0e4) /* assuming FULL ionization */
513  molecular_weight = 4 / (8 - 5 * (1 - HYDROGEN_MASSFRAC));
514  else /* assuming NEUTRAL GAS */
515  molecular_weight = 4 / (1 + 3 * HYDROGEN_MASSFRAC);
516  u_init /= molecular_weight;
517 
518  if(u_init < MinEgySpec)
519  u_init = MinEgySpec;
520  /* snapshot already has EgyWtDensity; hope it is read in correctly.
521  * (need a test on this!) */
522  /*Allocate the extra SPH data for transient SPH particle properties.*/
524 
525  /*At the first time step all particles should be active*/
526  ActiveParticles act = {0};
527  act.ActiveParticle = NULL;
529 
530  /* Empty kick factors as we do not move*/
531  DriftKickTimes times = init_driftkicktime(Ti_Current);
532  density(&act, 1, 0, BlackHoleOn, 0, times, CP, &sph_pred, NULL, &Tree);
533 
535  setup_density_indep_entropy(&act, &Tree, CP, &sph_pred, u_init, a3, Ti_Current, BlackHoleOn);
536  }
537  else {
538  /*Initialize to initial energy*/
539  #pragma omp parallel for
540  for(i = 0; i < SlotsManager->info[0].size; i++)
541  SphP[i].Entropy = GAMMA_MINUS1 * u_init / pow(SphP[i].Density / a3 , GAMMA_MINUS1);
542  }
543  slots_free_sph_pred_data(&sph_pred);
544  force_tree_free(&Tree);
545 }
double GetNumNgb(enum DensityKernelType KernelType)
Definition: density.c:55
struct sph_pred_data slots_allocate_sph_pred_data(int nsph)
Definition: density.c:654
void slots_free_sph_pred_data(struct sph_pred_data *sph_scratch)
Definition: density.c:665
enum DensityKernelType GetDensityKernelType(void)
Definition: density.c:63
void force_tree_rebuild(ForceTree *tree, DomainDecomp *ddecomp, const int HybridNuGrav, const int DoMoments, const char *EmergencyOutputDir)
Definition: forcetree.c:140
void force_tree_free(ForceTree *tree)
Definition: forcetree.c:1409
int force_get_father(int no, const ForceTree *tree)
Definition: forcetree.c:905
static void setup_density_indep_entropy(const ActiveParticles *act, ForceTree *Tree, Cosmology *CP, struct sph_pred_data *sph_pred, double u_init, double a3, int BlackHoleOn, const inttime_t Ti_Current)
Definition: init.c:384
#define PROTONMASS
Definition: physconst.h:21
#define BOLTZMANN
Definition: physconst.h:11
int * ActiveParticle
Definition: timestep.h:13
int64_t NumActiveParticle
Definition: timestep.h:12
double CMBTemperature
Definition: cosmology.h:9
struct NODE * Nodes
Definition: forcetree.h:97
struct NODE::@9 mom
MyFloat mass
Definition: forcetree.h:56
MyFloat len
Definition: forcetree.h:42

References ActiveParticles::ActiveParticle, BOLTZMANN, part_manager_type::BoxSize, Cosmology::CMBTemperature, CP, density(), DensityIndependentSphOn(), endrun(), force_get_father(), force_tree_free(), force_tree_rebuild(), GAMMA_MINUS1, GetDensityKernelType(), GetNumNgb(), HYDROGEN_MASSFRAC, slots_manager_type::info, init_driftkicktime(), init_params::InitGasTemp, InitParams, NODE::len, NODE::mass, NODE::mom, MPI_INT64, ForceTree::Nodes, ActiveParticles::NumActiveParticle, part_manager_type::NumPart, Cosmology::Omega0, Cosmology::OmegaBaryon, P, PartManager, PROTONMASS, setup_density_indep_entropy(), slot_info::size, slots_allocate_sph_pred_data(), slots_free_sph_pred_data(), SlotsManager, and SphP.

Referenced by begrun().

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

Variable Documentation

◆ InitParams

struct init_params InitParams
static