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

routines for 'kicking' particles in momentum space and assigning new timesteps More...

#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <omp.h>
#include "utils.h"
#include "physconst.h"
#include "timebinmgr.h"
#include "domain.h"
#include "timefac.h"
#include "cosmology.h"
#include "checkpoint.h"
#include "slotsmanager.h"
#include "partmanager.h"
#include "hydra.h"
#include "walltime.h"
#include "timestep.h"
#include "gravity.h"
Include dependency graph for timestep.c:

Go to the source code of this file.

Classes

struct  timestep_params
 

Enumerations

enum  TimeStepType {
  TI_ACCEL = 0 , TI_COURANT = 1 , TI_ACCRETE = 2 , TI_NEIGH = 3 ,
  TI_HSML = 4
}
 

Functions

void set_timestep_params (ParameterSet *ps)
 
static int get_active_particle (const ActiveParticles *act, int pa)
 
static int timestep_eh_slots_fork (EIBase *event, void *userdata)
 
static inttime_t get_timestep_ti (const int p, const inttime_t dti_max, const inttime_t Ti_Current, const double atime, const double hubble, enum TimeStepType *titype)
 
static int get_timestep_bin (inttime_t dti)
 
static void do_the_short_range_kick (int i, double dt_entr, double Fgravkick, double Fhydrokick, const double atime, const double MinEgySpec)
 
static inttime_t get_PM_timestep_ti (const DriftKickTimes *const times, const double atime, const Cosmology *CP, const int FastParticleType, const double asmth)
 
inttime_t init_timebins (double TimeInit)
 
DriftKickTimes init_driftkicktime (inttime_t Ti_Current)
 
int is_timebin_active (int i, inttime_t current)
 
int is_PM_timestep (const DriftKickTimes *const times)
 
double get_atime (const inttime_t Ti_Current)
 
int find_timesteps (const ActiveParticles *act, DriftKickTimes *times, const double atime, int FastParticleType, const Cosmology *CP, const double asmth, const int isFirstTimeStep)
 
void update_lastactive_drift (DriftKickTimes *times)
 
void apply_half_kick (const ActiveParticles *act, Cosmology *CP, DriftKickTimes *times, const double atime, const double MinEgySpec)
 
void apply_PM_half_kick (Cosmology *CP, DriftKickTimes *times)
 
static double get_timestep_dloga (const int p, const inttime_t Ti_Current, const double atime, const double hubble, enum TimeStepType *titype)
 
double get_long_range_timestep_dloga (const double atime, const Cosmology *CP, const int FastParticleType, const double asmth)
 
inttime_t find_next_kick (inttime_t Ti_Current, int minTimeBin)
 
static void print_timebin_statistics (const DriftKickTimes *const times, const int NumCurrentTiStep, int *TimeBinCountType, const double Time)
 
int rebuild_activelist (ActiveParticles *act, const DriftKickTimes *const times, int NumCurrentTiStep, const double Time)
 
void free_activelist (ActiveParticles *act)
 

Variables

static struct timestep_params TimestepParams
 

Detailed Description

routines for 'kicking' particles in momentum space and assigning new timesteps

Definition in file timestep.c.

Enumeration Type Documentation

◆ TimeStepType

Enumerator
TI_ACCEL 
TI_COURANT 
TI_ACCRETE 
TI_NEIGH 
TI_HSML 

Definition at line 106 of file timestep.c.

107 {
108  TI_ACCEL = 0,
109  TI_COURANT = 1,
110  TI_ACCRETE = 2,
111  TI_NEIGH = 3,
112  TI_HSML = 4,
113 };
@ TI_NEIGH
Definition: timestep.c:111
@ TI_COURANT
Definition: timestep.c:109
@ TI_ACCEL
Definition: timestep.c:108
@ TI_ACCRETE
Definition: timestep.c:110
@ TI_HSML
Definition: timestep.c:112

Function Documentation

◆ apply_half_kick()

void apply_half_kick ( const ActiveParticles act,
Cosmology CP,
DriftKickTimes times,
const double  atime,
const double  MinEgySpec 
)

Definition at line 323 of file timestep.c.

324 {
325  int pa, bin;
326  walltime_measure("/Misc");
327  double gravkick[TIMEBINS+1] = {0}, hydrokick[TIMEBINS+1] = {0};
328  /* Do nothing for the first timestep when the kicks are always zero*/
329  if(times->mintimebin == 0 && times->maxtimebin == 0)
330  return;
331  #pragma omp parallel for
332  for(bin = times->mintimebin; bin <= TIMEBINS; bin++)
333  {
334  /* Kick the active timebins*/
335  if(is_timebin_active(bin, times->Ti_Current)) {
336  /* do the kick for half a step*/
337  inttime_t dti = dti_from_timebin(bin);
338  inttime_t newkick = times->Ti_kick[bin] + dti/2;
339  /* Compute kick factors for occupied bins*/
340  gravkick[bin] = get_exact_gravkick_factor(CP, times->Ti_kick[bin], newkick);
341  hydrokick[bin] = get_exact_hydrokick_factor(CP, times->Ti_kick[bin], newkick);
342  // message(0, "drift %d bin %d kick: %d->%d\n", times->Ti_Current, bin, times->Ti_kick[bin], newkick);
343  times->Ti_kick[bin] = newkick;
344  }
345  }
346  /* Advance the shorter bins without particles by the minimum occupied timestep.*/
347  for(bin=1; bin < times->mintimebin; bin++)
348  times->Ti_kick[bin] += dti_from_timebin(times->mintimebin)/2;
349  // message(0, "drift %d bin %d kick: %d\n", times->Ti_Current, bin, times->Ti_kick[bin]);
350  /* Now assign new timesteps and kick */
351  #pragma omp parallel for
352  for(pa = 0; pa < act->NumActiveParticle; pa++)
353  {
354  const int i = get_active_particle(act, pa);
355  if(P[i].Swallowed || P[i].IsGarbage)
356  continue;
357  int bin = P[i].TimeBin;
358  if(bin > TIMEBINS)
359  endrun(4, "Particle %d (type %d, id %ld) had unexpected timebin %d\n", i, P[i].Type, P[i].ID, P[i].TimeBin);
360 #ifdef DEBUG
361  if(isnan(gravkick[bin]) || gravkick[bin] == 0.)
362  endrun(5, "Bad kicks %lg bin %d tik %d\n", gravkick[bin], bin, times->Ti_kick[bin]);
363 #endif
364  inttime_t dti = dti_from_timebin(bin);
365  const double dt_entr = dloga_from_dti(dti/2, times->Ti_Current);
366  /*This only changes particle i, so is thread-safe.*/
367  do_the_short_range_kick(i, dt_entr, gravkick[bin], hydrokick[bin], atime, MinEgySpec);
368  }
369  walltime_measure("/Timeline/HalfKick/Short");
370 }
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
#define P
Definition: partmanager.h:88
static Cosmology * CP
Definition: power.c:27
int64_t NumActiveParticle
Definition: timestep.h:12
int maxtimebin
Definition: timestep.h:21
inttime_t Ti_Current
Definition: timestep.h:27
inttime_t Ti_kick[TIMEBINS+1]
Definition: timestep.h:23
int mintimebin
Definition: timestep.h:20
double dloga_from_dti(inttime_t dti, const inttime_t Ti_Current)
Definition: timebinmgr.c:256
#define TIMEBINS
Definition: timebinmgr.h:13
static inttime_t dti_from_timebin(int bin)
Definition: timebinmgr.h:44
double get_exact_hydrokick_factor(Cosmology *CP, inttime_t ti0, inttime_t ti1)
Definition: timefac.c:75
double get_exact_gravkick_factor(Cosmology *CP, inttime_t ti0, inttime_t ti1)
Definition: timefac.c:70
static void do_the_short_range_kick(int i, double dt_entr, double Fgravkick, double Fhydrokick, const double atime, const double MinEgySpec)
Definition: timestep.c:396
static int get_active_particle(const ActiveParticles *act, int pa)
Definition: timestep.c:68
int is_timebin_active(int i, inttime_t current)
Definition: timestep.c:149
int32_t inttime_t
Definition: types.h:8
#define walltime_measure(name)
Definition: walltime.h:8

References CP, dloga_from_dti(), do_the_short_range_kick(), dti_from_timebin(), endrun(), get_active_particle(), get_exact_gravkick_factor(), get_exact_hydrokick_factor(), is_timebin_active(), DriftKickTimes::maxtimebin, DriftKickTimes::mintimebin, ActiveParticles::NumActiveParticle, P, DriftKickTimes::Ti_Current, DriftKickTimes::Ti_kick, TIMEBINS, and walltime_measure.

Referenced by run().

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

◆ apply_PM_half_kick()

void apply_PM_half_kick ( Cosmology CP,
DriftKickTimes times 
)

Definition at line 373 of file timestep.c.

374 {
375  /*Always do a PM half-kick, because this should be called just after a PM step*/
376  const inttime_t tistart = times->PM_kick;
377  const inttime_t tiend = tistart + times->PM_length / 2;
378  /* Do long-range kick */
379  int i;
380  const double Fgravkick = get_exact_gravkick_factor(CP, tistart, tiend);
381 
382  #pragma omp parallel for
383  for(i = 0; i < PartManager->NumPart; i++)
384  {
385  int j;
386  if(P[i].Swallowed || P[i].IsGarbage)
387  continue;
388  for(j = 0; j < 3; j++) /* do the kick */
389  P[i].Vel[j] += P[i].GravPM[j] * Fgravkick;
390  }
391  times->PM_kick = tiend;
392  walltime_measure("/Timeline/HalfKick/Long");
393 }
static struct gravpm_params GravPM
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
inttime_t PM_kick
Definition: timestep.h:31
inttime_t PM_length
Definition: timestep.h:29

References CP, get_exact_gravkick_factor(), GravPM, part_manager_type::NumPart, P, PartManager, DriftKickTimes::PM_kick, DriftKickTimes::PM_length, and walltime_measure.

Referenced by run().

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

◆ do_the_short_range_kick()

void do_the_short_range_kick ( int  i,
double  dt_entr,
double  Fgravkick,
double  Fhydrokick,
const double  atime,
const double  MinEgySpec 
)
static

Definition at line 396 of file timestep.c.

397 {
398  int j;
399  for(j = 0; j < 3; j++)
400  P[i].Vel[j] += P[i].GravAccel[j] * Fgravkick;
401 
402  /* Add kick from dynamic friction and hydro drag for BHs. */
403  if(P[i].Type == 5) {
404  for(j = 0; j < 3; j++){
405  P[i].Vel[j] += BHP(i).DFAccel[j] * Fgravkick;
406  P[i].Vel[j] += BHP(i).DragAccel[j] * Fgravkick;
407  }
408  }
409 
410  if(P[i].Type == 0) {
411  /* Add kick from hydro and SPH stuff */
412  for(j = 0; j < 3; j++) {
413  P[i].Vel[j] += SPHP(i).HydroAccel[j] * Fhydrokick;
414  }
415  /* Code here imposes a hard limit (default to speed of light)
416  * on the gas velocity. This should rarely be hit.*/
417  double vv=0;
418  for(j=0; j < 3; j++)
419  vv += P[i].Vel[j] * P[i].Vel[j];
420  vv = sqrt(vv);
421 
422  if(vv > 0 && vv/atime > TimestepParams.MaxGasVel) {
423  message(1,"Gas Particle ID %ld exceeded the gas velocity limit: %g > %g\n",P[i].ID, vv / atime, TimestepParams.MaxGasVel);
424  for(j=0;j < 3; j++)
425  {
426  P[i].Vel[j] *= TimestepParams.MaxGasVel * atime / vv;
427  }
428  }
429 
430  /* Update entropy for adiabatic change*/
431  SPHP(i).Entropy += SPHP(i).DtEntropy * dt_entr;
432 
433  /* Limit entropy in simulations with cooling disabled*/
434  double a3inv = 1/(atime * atime * atime);
435  const double enttou = pow(SPHP(i).Density * a3inv, GAMMA_MINUS1) / GAMMA_MINUS1;
436  if(SPHP(i).Entropy < MinEgySpec/enttou)
437  SPHP(i).Entropy = MinEgySpec / enttou;
438  }
439 #ifdef DEBUG
440  /* Check we have reasonable velocities. If we do not, try to explain why*/
441  if(isnan(P[i].Vel[0]) || isnan(P[i].Vel[1]) || isnan(P[i].Vel[2])) {
442  message(1, "Vel = %g %g %g Type = %d gk = %g a_g = %g %g %g\n",
443  P[i].Vel[0], P[i].Vel[1], P[i].Vel[2], P[i].Type,
444  Fgravkick, P[i].GravAccel[0], P[i].GravAccel[1], P[i].GravAccel[2]);
445  }
446 #endif
447 }
void message(int where, const char *fmt,...)
Definition: endrun.c:175
#define GAMMA_MINUS1
Definition: physconst.h:35
#define BHP(i)
Definition: slotsmanager.h:125
#define SPHP(i)
Definition: slotsmanager.h:124
double MaxGasVel
Definition: timestep.c:45
static struct timestep_params TimestepParams

References BHP, GAMMA_MINUS1, timestep_params::MaxGasVel, message(), P, SPHP, and TimestepParams.

Referenced by apply_half_kick().

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

◆ find_next_kick()

inttime_t find_next_kick ( inttime_t  Ti_Current,
int  minTimeBin 
)

This function finds the next synchronization point of the system (i.e. the earliest point of time any of the particles needs a force computation), and drifts the system to this point of time. If the system drifts over the desired time of a snapshot file, the function will drift to this moment, generate an output, and then resume the drift.

Definition at line 712 of file timestep.c.

713 {
714  /* Current value plus the increment for the smallest active bin. */
715  return Ti_Current + dti_from_timebin(minTimeBin);
716 }

References dti_from_timebin().

Referenced by run().

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

◆ find_timesteps()

int find_timesteps ( const ActiveParticles act,
DriftKickTimes times,
const double  atime,
int  FastParticleType,
const Cosmology CP,
const double  asmth,
const int  isFirstTimeStep 
)

Definition at line 176 of file timestep.c.

177 {
178  int pa;
179  inttime_t dti_min = TIMEBASE;
180 
181  walltime_measure("/Misc");
182 
183  /*Update the PM timestep size */
184  const int isPM = is_PM_timestep(times);
185  inttime_t dti_max = times->PM_length;
186 
187  if(isPM) {
188  dti_max = get_PM_timestep_ti(times, atime, CP, FastParticleType, asmth);
189  times->PM_length = dti_max;
190  times->PM_start = times->PM_kick;
191  }
192 
193  const double hubble = hubble_function(CP, atime);
194  /* Now assign new timesteps and kick */
196  int i;
197  #pragma omp parallel for reduction(min:dti_min)
198  for(i = 0; i < PartManager->NumPart; i++)
199  {
200  enum TimeStepType titype;
201  /* Because we don't GC on short timesteps, there can be garbage here.
202  * Avoid making it active. */
203  if(P[i].IsGarbage || P[i].Swallowed)
204  continue;
205  inttime_t dti = get_timestep_ti(i, dti_max, times->Ti_Current, atime, hubble, &titype);
206  if(dti < dti_min)
207  dti_min = dti;
208  }
209  MPI_Allreduce(MPI_IN_PLACE, &dti_min, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
210  }
211 
212  int64_t ntiaccel=0, nticourant=0, ntiaccrete=0, ntineighbour=0, ntihsml=0;
213  int badstepsizecount = 0;
214  int mTimeBin = TIMEBINS, maxTimeBin = 0;
215  #pragma omp parallel for reduction(min: mTimeBin) reduction(+: badstepsizecount, ntiaccel, nticourant, ntiaccrete, ntineighbour, ntihsml) reduction(max:maxTimeBin)
216  for(pa = 0; pa < act->NumActiveParticle; pa++)
217  {
218  const int i = get_active_particle(act, pa);
219 
220  if(P[i].IsGarbage || P[i].Swallowed)
221  continue;
222 
223  enum TimeStepType titype;
224  inttime_t dti;
226  dti = dti_min;
227  } else {
228  dti = get_timestep_ti(i, dti_max, times->Ti_Current, atime, hubble, &titype);
229  if(titype == TI_ACCEL)
230  ntiaccel++;
231  else if (titype == TI_COURANT)
232  nticourant++;
233  else if (titype == TI_ACCRETE)
234  ntiaccrete++;
235  else if (titype == TI_NEIGH)
236  ntineighbour++;
237  else if (titype == TI_HSML)
238  ntihsml++;
239  }
240 
241  /* make it a power 2 subdivision */
242  dti = round_down_power_of_two(dti);
243 
244  int bin = get_timestep_bin(dti);
245  if(bin < 1) {
246  message(1, "Time-step of integer size %d not allowed, id = %lu, debugging info follows.\n", dti, P[i].ID);
247  badstepsizecount++;
248  }
249  int binold = P[i].TimeBin;
250 
251  /* timestep wants to increase */
252  if(bin > binold)
253  {
254  /* make sure the new step is currently active,
255  * so that particles do not miss a step */
256  while(!is_timebin_active(bin, times->Ti_Current) && bin > binold && bin > 1)
257  bin--;
258  }
259  /* This moves particles between time bins:
260  * active particles always remain active
261  * until rebuild_activelist is called
262  * (after domain, on new timestep).*/
263  P[i].TimeBin = bin;
264  /*Find max and min*/
265  if(bin < mTimeBin)
266  mTimeBin = bin;
267  if(bin > maxTimeBin)
268  maxTimeBin = bin;
269  }
270 
271  MPI_Allreduce(MPI_IN_PLACE, &badstepsizecount, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
272  MPI_Allreduce(MPI_IN_PLACE, &mTimeBin, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
273  MPI_Allreduce(MPI_IN_PLACE, &maxTimeBin, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
274 
275  MPI_Allreduce(MPI_IN_PLACE, &ntiaccel, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
276  MPI_Allreduce(MPI_IN_PLACE, &nticourant, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
277  MPI_Allreduce(MPI_IN_PLACE, &ntihsml, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
278  MPI_Allreduce(MPI_IN_PLACE, &ntiaccrete, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
279  MPI_Allreduce(MPI_IN_PLACE, &ntineighbour, 1, MPI_INT64, MPI_SUM, MPI_COMM_WORLD);
280 
281  /* Ensure that the PM timestep is not longer than the longest tree timestep;
282  * this prevents particles in the longest timestep being active and moving into a higher bin
283  * between PM timesteps, thus skipping the PM step entirely.*/
284  if(isPM && times->PM_length > dti_from_timebin(maxTimeBin))
285  times->PM_length = dti_from_timebin(maxTimeBin);
286  message(0, "PM timebin: %x (dloga: %g Max: %g). Criteria: Accel: %ld Soundspeed: %ld DivVel: %ld Accrete: %ld Neighbour: %ld\n",
288  ntiaccel, nticourant, ntihsml, ntiaccrete, ntineighbour);
289 
290  /* BH particles have their timesteps set by a timestep limiter.
291  * On the first timestep this is not effective because all the particles have zero timestep.
292  * So on the first timestep only set all BH particles to the smallest allowable timestep*/
293  if(isFirstTimeStep) {
294  #pragma omp parallel for
295  for(pa = 0; pa < PartManager->NumPart; pa++)
296  {
297  if(P[pa].Type == 5)
298  P[pa].TimeBin = mTimeBin;
299  }
300  }
301  walltime_measure("/Timeline");
302  times->mintimebin = mTimeBin;
303  times->maxtimebin = maxTimeBin;
304  return badstepsizecount;
305 }
double hubble_function(const Cosmology *CP, double a)
Definition: cosmology.c:58
inttime_t PM_start
Definition: timestep.h:30
double MaxSizeTimestep
Definition: timestep.c:36
int ForceEqualTimesteps
Definition: timestep.c:33
#define MPI_INT64
Definition: system.h:12
inttime_t round_down_power_of_two(inttime_t dti)
Definition: timebinmgr.c:286
#define TIMEBASE
Definition: timebinmgr.h:14
int is_PM_timestep(const DriftKickTimes *const times)
Definition: timestep.c:160
static inttime_t get_PM_timestep_ti(const DriftKickTimes *const times, const double atime, const Cosmology *CP, const int FastParticleType, const double asmth)
Definition: timestep.c:667
static inttime_t get_timestep_ti(const int p, const inttime_t dti_max, const inttime_t Ti_Current, const double atime, const double hubble, enum TimeStepType *titype)
Definition: timestep.c:537
static int get_timestep_bin(inttime_t dti)
Definition: timestep.c:686
TimeStepType
Definition: timestep.c:107

References CP, dloga_from_dti(), dti_from_timebin(), timestep_params::ForceEqualTimesteps, get_active_particle(), get_PM_timestep_ti(), get_timestep_bin(), get_timestep_ti(), hubble_function(), is_PM_timestep(), is_timebin_active(), timestep_params::MaxSizeTimestep, DriftKickTimes::maxtimebin, message(), DriftKickTimes::mintimebin, MPI_INT64, ActiveParticles::NumActiveParticle, part_manager_type::NumPart, P, PartManager, DriftKickTimes::PM_kick, DriftKickTimes::PM_length, DriftKickTimes::PM_start, round_down_power_of_two(), TI_ACCEL, TI_ACCRETE, TI_COURANT, DriftKickTimes::Ti_Current, TI_HSML, TI_NEIGH, TIMEBASE, TIMEBINS, TimestepParams, and walltime_measure.

Referenced by run().

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

◆ free_activelist()

void free_activelist ( ActiveParticles act)

Definition at line 795 of file timestep.c.

796 {
797  if(act->ActiveParticle) {
798  myfree(act->ActiveParticle);
799  }
801 }
int event_unlisten(EventSpec *eh, eventfunc func, void *userdata)
Definition: event.c:26
EventSpec EventSlotsFork
Definition: event.c:54
#define myfree(x)
Definition: mymalloc.h:19
int * ActiveParticle
Definition: timestep.h:13
static int timestep_eh_slots_fork(EIBase *event, void *userdata)
Definition: timestep.c:77

References ActiveParticles::ActiveParticle, event_unlisten(), EventSlotsFork, myfree, and timestep_eh_slots_fork().

Referenced by run().

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

◆ get_active_particle()

static int get_active_particle ( const ActiveParticles act,
int  pa 
)
inlinestatic

Definition at line 68 of file timestep.c.

69 {
70  if(act->ActiveParticle)
71  return act->ActiveParticle[pa];
72  else
73  return pa;
74 }

References ActiveParticles::ActiveParticle.

Referenced by apply_half_kick(), and find_timesteps().

Here is the caller graph for this function:

◆ get_atime()

double get_atime ( const inttime_t  Ti_Current)

Definition at line 168 of file timestep.c.

168  {
169  return exp(loga_from_ti(Ti_Current));
170 }
double loga_from_ti(int ti)
Definition: test_timefac.c:51

References loga_from_ti().

Referenced by run().

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

◆ get_long_range_timestep_dloga()

double get_long_range_timestep_dloga ( const double  atime,
const Cosmology CP,
const int  FastParticleType,
const double  asmth 
)

This function computes the PM timestep of the system based on the rms velocities of particles. For cosmological simulations, the criterion used is that the rms displacement should be at most a fraction MaxRMSDisplacementFac of the mean particle separation. Note that the latter is estimated using the assigned particle masses, separately for each particle type.

Definition at line 584 of file timestep.c.

585 {
586  int i, type;
587  int count[6];
588  int64_t count_sum[6];
589  double v[6], v_sum[6], mim[6], min_mass[6];
591 
592  for(type = 0; type < 6; type++)
593  {
594  count[type] = 0;
595  v[type] = 0;
596  mim[type] = 1.0e30;
597  }
598 
599  for(i = 0; i < PartManager->NumPart; i++)
600  {
601  v[P[i].Type] += P[i].Vel[0] * P[i].Vel[0] + P[i].Vel[1] * P[i].Vel[1] + P[i].Vel[2] * P[i].Vel[2];
602  if(P[i].Mass > 0)
603  {
604  if(mim[P[i].Type] > P[i].Mass)
605  mim[P[i].Type] = P[i].Mass;
606  }
607  count[P[i].Type]++;
608  }
609 
610  MPI_Allreduce(v, v_sum, 6, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
611  MPI_Allreduce(mim, min_mass, 6, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
612 
613  sumup_large_ints(6, count, count_sum);
614 
615  /* add star, gas and black hole particles together to treat them on equal footing,
616  * using the original gas particle spacing. */
617  v_sum[0] += v_sum[4];
618  count_sum[0] += count_sum[4];
619  v_sum[4] = v_sum[0];
620  count_sum[4] = count_sum[0];
621  v_sum[0] += v_sum[5];
622  count_sum[0] += count_sum[5];
623  v_sum[5] = v_sum[0];
624  count_sum[5] = count_sum[0];
625 
626  min_mass[5] = min_mass[0];
627 
628  const double hubble = hubble_function(CP, atime);
629  for(type = 0; type < 6; type++)
630  {
631  if(count_sum[type] > 0)
632  {
633  double omega, dmean, dloga1;
634  /* Type 4 is stars, type 5 is BHs, both baryons*/
635  if(type == 0 || type == 4 || type == 5) {
636  omega = CP->OmegaBaryon;
637  }
638  /* In practice usually FastParticleType == 2
639  * so this doesn't matter. */
640  else if (type == 2) {
641  omega = get_omega_nu(&CP->ONu, 1);
642  } else {
643  omega = CP->OmegaCDM;
644  }
645  /* "Avg. radius" of smallest particle: (min_mass/total_mass)^1/3 */
646  dmean = pow(min_mass[type] / (omega * 3 * CP->Hubble * CP->Hubble / (8 * M_PI * CP->GravInternal)), 1.0 / 3);
647 
648  dloga1 = TimestepParams.MaxRMSDisplacementFac * hubble * atime * atime * DMIN(asmth, dmean) / sqrt(v_sum[type] / count_sum[type]);
649  message(0, "type=%d dmean=%g asmth=%g minmass=%g a=%g sqrt(<p^2>)=%g dloga=%g\n",
650  type, dmean, asmth, min_mass[type], atime, sqrt(v_sum[type] / count_sum[type]), dloga1);
651 
652  /* don't constrain the step to the neutrinos */
653  if(type != FastParticleType && dloga1 < dloga)
654  dloga = dloga1;
655  }
656  }
657 
660  }
661 
662  return dloga;
663 }
static double dloga
Definition: lightcone.c:21
double get_omega_nu(const _omega_nu *const omnu, const double a)
double GravInternal
Definition: cosmology.h:32
double OmegaCDM
Definition: cosmology.h:11
double OmegaBaryon
Definition: cosmology.h:19
_omega_nu ONu
Definition: cosmology.h:24
double Hubble
Definition: cosmology.h:21
double MinSizeTimestep
Definition: timestep.c:35
double MaxRMSDisplacementFac
Definition: timestep.c:38
int64_t count_sum(int64_t countLocal)
Definition: system.c:264
void sumup_large_ints(int n, int *src, int64_t *res)
Definition: system.c:192
#define DMIN(x, y)
Definition: test_interp.c:12

References count_sum(), CP, dloga, DMIN, get_omega_nu(), Cosmology::GravInternal, Cosmology::Hubble, hubble_function(), timestep_params::MaxRMSDisplacementFac, timestep_params::MaxSizeTimestep, message(), timestep_params::MinSizeTimestep, part_manager_type::NumPart, Cosmology::OmegaBaryon, Cosmology::OmegaCDM, Cosmology::ONu, P, PartManager, sumup_large_ints(), and TimestepParams.

Referenced by get_PM_timestep_ti().

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

◆ get_PM_timestep_ti()

inttime_t get_PM_timestep_ti ( const DriftKickTimes *const  times,
const double  atime,
const Cosmology CP,
const int  FastParticleType,
const double  asmth 
)
static

Definition at line 667 of file timestep.c.

668 {
669  double dloga = get_long_range_timestep_dloga(atime, CP, FastParticleType, asmth);
670 
671  inttime_t dti = dti_from_dloga(dloga, times->Ti_Current);
672  dti = round_down_power_of_two(dti);
673 
674  SyncPoint * next = find_next_sync_point(times->Ti_Current);
675  if(next == NULL)
676  endrun(0, "Trying to go beyond the last sync point. This happens only at TimeMax \n");
677 
678  /* go no more than the next sync point */
679  inttime_t dti_max = next->ti - times->PM_kick;
680 
681  if(dti > dti_max)
682  dti = dti_max;
683  return dti;
684 }
inttime_t ti
Definition: timebinmgr.h:28
inttime_t dti_from_dloga(double loga, const inttime_t Ti_Current)
Definition: timebinmgr.c:271
SyncPoint * find_next_sync_point(inttime_t ti)
Definition: timebinmgr.c:174
double get_long_range_timestep_dloga(const double atime, const Cosmology *CP, const int FastParticleType, const double asmth)
Definition: timestep.c:584

References CP, dloga, dti_from_dloga(), endrun(), find_next_sync_point(), get_long_range_timestep_dloga(), DriftKickTimes::PM_kick, round_down_power_of_two(), SyncPoint::ti, and DriftKickTimes::Ti_Current.

Referenced by find_timesteps().

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

◆ get_timestep_bin()

int get_timestep_bin ( inttime_t  dti)
static

Definition at line 686 of file timestep.c.

687 {
688  int bin = -1;
689 
690  if(dti <= 0)
691  return 0;
692 
693  if(dti == 1)
694  return -1;
695 
696  while(dti)
697  {
698  bin++;
699  dti >>= 1;
700  }
701 
702  return bin;
703 }

Referenced by find_timesteps().

Here is the caller graph for this function:

◆ get_timestep_dloga()

static double get_timestep_dloga ( const int  p,
const inttime_t  Ti_Current,
const double  atime,
const double  hubble,
enum TimeStepType titype 
)
static

Definition at line 450 of file timestep.c.

451 {
452  double ac = 0;
453  double dt = 0, dt_courant = 0, dt_hsml = 0;
454 
455  /*Compute physical acceleration*/
456  {
457  const double a2inv = 1/(atime * atime);
458 
459  double ax = a2inv * P[p].GravAccel[0];
460  double ay = a2inv * P[p].GravAccel[1];
461  double az = a2inv * P[p].GravAccel[2];
462 
463  ay += a2inv * P[p].GravPM[1];
464  ax += a2inv * P[p].GravPM[0];
465  az += a2inv * P[p].GravPM[2];
466 
467  if(P[p].Type == 0)
468  {
469  const double fac2 = 1 / pow(atime, 3 * GAMMA - 2);
470  ax += fac2 * SPHP(p).HydroAccel[0];
471  ay += fac2 * SPHP(p).HydroAccel[1];
472  az += fac2 * SPHP(p).HydroAccel[2];
473  }
474 
475  ac = sqrt(ax * ax + ay * ay + az * az); /* this is now the physical acceleration */
476  }
477 
478  if(ac == 0)
479  ac = 1.0e-30;
480 
481  /* mind the factor 2.8 difference between gravity and softening used here. */
482  dt = sqrt(2 * TimestepParams.ErrTolIntAccuracy * atime * (FORCE_SOFTENING(p, P[p].Type) / 2.8) / ac);
483  *titype = TI_ACCEL;
484 
485  if(P[p].Type == 0)
486  {
487  const double fac3 = pow(atime, 3 * (1 - GAMMA) / 2.0);
488  dt_courant = 2 * TimestepParams.CourantFac * atime * P[p].Hsml / (fac3 * SPHP(p).MaxSignalVel);
489  if(dt_courant < dt) {
490  dt = dt_courant;
491  *titype = TI_COURANT;
492  }
493  /* This timestep criterion is from Gadget-4, eq. 0 of 2010.03567 and stops
494  * particles having too large a density change.*/
495  dt_hsml = TimestepParams.CourantFac * atime * atime * fabs(P[p].Hsml / (P[p].DtHsml + 1e-20));
496  if(dt_hsml < dt) {
497  dt = dt_hsml;
498  *titype = TI_HSML;
499  }
500  }
501 
502  if(P[p].Type == 5)
503  {
504  if(BHP(p).Mdot > 0 && BHP(p).Mass > 0)
505  {
506  double dt_accr = 0.25 * BHP(p).Mass / BHP(p).Mdot;
507  if(dt_accr < dt) {
508  dt = dt_accr;
509  *titype = TI_ACCRETE;
510  }
511  }
512  if(BHP(p).minTimeBin > 0 && BHP(p).minTimeBin+1 < TIMEBINS) {
513  double dt_limiter = get_dloga_for_bin(BHP(p).minTimeBin+1, Ti_Current) / hubble;
514  /* Set the black hole timestep to the minimum timesteps of neighbouring gas particles.
515  * It should be at least this for accretion accuracy, and it does not make sense to
516  * make it less than this. We go one timestep up because often the smallest
517  * timebin particle is cooling, and so increases its timestep. Then the smallest timebin
518  * contains only the BH which doesn't make much numerical sense. Accretion accuracy is not much changed
519  * by one timestep difference.*/
520  dt = dt_limiter;
521  *titype = TI_NEIGH;
522  }
523  }
524 
525  /* d a / a = dt * H */
526  double dloga = dt * hubble;
527 
528  return dloga;
529 }
double FORCE_SOFTENING(int i, int type)
#define GAMMA
Definition: physconst.h:34
double ErrTolIntAccuracy
Definition: timestep.c:30
double CourantFac
Definition: timestep.c:46
double get_dloga_for_bin(int timebin, const inttime_t Ti_Current)
Definition: timebinmgr.c:279

References BHP, timestep_params::CourantFac, dloga, timestep_params::ErrTolIntAccuracy, FORCE_SOFTENING(), GAMMA, get_dloga_for_bin(), P, SPHP, TI_ACCEL, TI_ACCRETE, TI_COURANT, TI_HSML, TI_NEIGH, TIMEBINS, and TimestepParams.

Referenced by get_timestep_ti().

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

◆ get_timestep_ti()

static inttime_t get_timestep_ti ( const int  p,
const inttime_t  dti_max,
const inttime_t  Ti_Current,
const double  atime,
const double  hubble,
enum TimeStepType titype 
)
static

This function returns the maximum allowed timestep of a particle, expressed in terms of the integer mapping that is used to represent the total simulated timespan. Arguments: p -> particle index dti_max -> maximal timestep.

Definition at line 537 of file timestep.c.

538 {
539  inttime_t dti;
540  /*Give a useful message if we are broken*/
541  if(dti_max == 0)
542  return 0;
543 
544  double dloga = get_timestep_dloga(p, Ti_Current, atime, hubble, titype);
545 
548 
549  dti = dti_from_dloga(dloga, Ti_Current);
550 
551  /* Check for overflow*/
552  if(dti > dti_max || dti < 0)
553  dti = dti_max;
554 
555  if(dti <= 1 || dti > (inttime_t) TIMEBASE)
556  {
557  if(P[p].Type == 0)
558  message(1, "Bad timestep (%x)! titype %d. ID=%lu Type=%d dloga=%g dtmax=%x xyz=(%g|%g|%g) tree=(%g|%g|%g) PM=(%g|%g|%g) hydro-frc=(%g|%g|%g) dens=%g hsml=%g dh = %g Entropy=%g, dtEntropy=%g maxsignal=%g\n",
559  dti, *titype, P[p].ID, P[p].Type, dloga, dti_max,
560  P[p].Pos[0], P[p].Pos[1], P[p].Pos[2],
561  P[p].GravAccel[0], P[p].GravAccel[1], P[p].GravAccel[2],
562  P[p].GravPM[0], P[p].GravPM[1], P[p].GravPM[2],
563  SPHP(p).HydroAccel[0], SPHP(p).HydroAccel[1], SPHP(p).HydroAccel[2],
564  SPHP(p).Density, P[p].Hsml, P[p].DtHsml, SPHP(p).Entropy, SPHP(p).DtEntropy, SPHP(p).MaxSignalVel);
565  else
566  message(1, "Bad timestep (%x)! titype %d. ID=%lu Type=%d dloga=%g dtmax=%x xyz=(%g|%g|%g) tree=(%g|%g|%g) PM=(%g|%g|%g)\n",
567  dti, *titype, P[p].ID, P[p].Type, dloga, dti_max,
568  P[p].Pos[0], P[p].Pos[1], P[p].Pos[2],
569  P[p].GravAccel[0], P[p].GravAccel[1], P[p].GravAccel[2],
570  P[p].GravPM[0], P[p].GravPM[1], P[p].GravPM[2]
571  );
572  }
573 
574  return dti;
575 }
static double get_timestep_dloga(const int p, const inttime_t Ti_Current, const double atime, const double hubble, enum TimeStepType *titype)
Definition: timestep.c:450

References dloga, dti_from_dloga(), get_timestep_dloga(), GravPM, message(), timestep_params::MinSizeTimestep, P, SPHP, TIMEBASE, and TimestepParams.

Referenced by find_timesteps().

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

◆ init_driftkicktime()

DriftKickTimes init_driftkicktime ( inttime_t  Ti_Current)

Definition at line 133 of file timestep.c.

134 {
135  DriftKickTimes times = {0};
136  times.Ti_Current = Ti_Current;
137  int i;
138  for(i = 0; i <= TIMEBINS; i++) {
139  times.Ti_kick[i] = times.Ti_Current;
140  times.Ti_lastactivedrift[i] = times.Ti_Current;
141  }
142  /* this makes sure the first step is a PM step. */
143  times.PM_length = 0;
144  times.PM_kick = times.Ti_Current;
145  times.PM_start = times.Ti_Current;
146  return times;
147 }
inttime_t Ti_lastactivedrift[TIMEBINS+1]
Definition: timestep.h:25

References DriftKickTimes::PM_kick, DriftKickTimes::PM_length, DriftKickTimes::PM_start, DriftKickTimes::Ti_Current, DriftKickTimes::Ti_kick, DriftKickTimes::Ti_lastactivedrift, and TIMEBINS.

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

Here is the caller graph for this function:

◆ init_timebins()

inttime_t init_timebins ( double  TimeInit)

Definition at line 123 of file timestep.c.

124 {
125  inttime_t Ti_Current = ti_from_loga(log(TimeInit));
126  /*Enforce Ti_Current is initially even*/
127  if(Ti_Current % 2 == 1)
128  Ti_Current++;
129  message(0, "Initial TimeStep at TimeInit %g Ti_Current = %d \n", TimeInit, Ti_Current);
130  return Ti_Current;
131 }
inttime_t ti_from_loga(double loga)
Definition: timebinmgr.c:236

References message(), and ti_from_loga().

Referenced by init().

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

◆ is_PM_timestep()

int is_PM_timestep ( const DriftKickTimes *const  times)

Definition at line 160 of file timestep.c.

161 {
162  if(times->Ti_Current > times->PM_start + times->PM_length)
163  endrun(12, "Passed end of PM step! ti=%d, PM = %d + %d\n",times->Ti_Current, times->PM_start, times->PM_length);
164  return times->Ti_Current == times->PM_start + times->PM_length;
165 }

References endrun(), DriftKickTimes::PM_length, DriftKickTimes::PM_start, and DriftKickTimes::Ti_Current.

Referenced by find_timesteps(), print_timebin_statistics(), rebuild_activelist(), and run().

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

◆ is_timebin_active()

int is_timebin_active ( int  i,
inttime_t  current 
)

Definition at line 149 of file timestep.c.

149  {
150  /*Bin 0 is always active and at time 0 all bins are active*/
151  if(i <= 0 || current <= 0)
152  return 1;
153  if(current % dti_from_timebin(i) == 0)
154  return 1;
155  return 0;
156 }

References dti_from_timebin().

Referenced by apply_half_kick(), find_timesteps(), hydro_force(), print_timebin_statistics(), rebuild_activelist(), run(), timestep_eh_slots_fork(), and update_lastactive_drift().

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

◆ print_timebin_statistics()

static void print_timebin_statistics ( const DriftKickTimes *const  times,
const int  NumCurrentTiStep,
int *  TimeBinCountType,
const double  Time 
)
static

This routine writes one line for every timestep. FdCPU the cumulative cpu-time consumption in various parts of the code is stored.

Definition at line 807 of file timestep.c.

808 {
809  int i;
810  int64_t tot = 0, tot_type[6] = {0};
811  int64_t tot_count[TIMEBINS+1] = {0};
812  int64_t tot_count_type[6][TIMEBINS+1] = {{0}};
813  int64_t tot_num_force = 0;
814  int64_t TotNumPart = 0, TotNumType[6] = {0};
815 
816  int NumThreads = omp_get_max_threads();
817  /*Sum the thread-local memory*/
818  for(i = 1; i < NumThreads; i ++) {
819  int j;
820  for(j=0; j < 6 * (TIMEBINS+1); j++)
821  TimeBinCountType[j] += TimeBinCountType[6 * (TIMEBINS+1) * i + j];
822  }
823 
824  for(i = 0; i < 6; i ++) {
825  sumup_large_ints(TIMEBINS+1, &TimeBinCountType[(TIMEBINS+1) * i], tot_count_type[i]);
826  }
827 
828  for(i = 0; i<TIMEBINS+1; i++) {
829  int j;
830  for(j=0; j<6; j++) {
831  tot_count[i] += tot_count_type[j][i];
832  /*Note j*/
833  TotNumType[j] += tot_count_type[j][i];
834  TotNumPart += tot_count_type[j][i];
835  }
836  if(is_timebin_active(i, times->Ti_Current))
837  tot_num_force += tot_count[i];
838  }
839 
840  char extra[20] = {0};
841 
842  if(is_PM_timestep(times))
843  strcat(extra, "PM-Step");
844 
845  const double dloga = get_dloga_for_bin(times->mintimebin, times->Ti_Current);
846  const double z = 1.0 / (Time) - 1;
847  message(0, "Begin Step %d, Time: %g (%x), Redshift: %g, Nf = %014ld, Systemstep: %g, Dloga: %g, status: %s\n",
848  NumCurrentTiStep, Time, times->Ti_Current, z, tot_num_force,
849  dloga * Time, dloga,
850  extra);
851 
852  message(0, "TotNumPart: %013ld SPH %013ld BH %010ld STAR %013ld \n",
853  TotNumPart, TotNumType[0], TotNumType[5], TotNumType[4]);
854  message(0, "Occupied: % 12ld % 12ld % 12ld % 12ld % 12ld % 12ld dt\n", 0L, 1L, 2L, 3L, 4L, 5L);
855 
856  for(i = TIMEBINS; i >= 0; i--) {
857  if(tot_count[i] == 0) continue;
858  message(0, " %c bin=%2d % 12ld % 12ld % 12ld % 12ld % 12ld % 12ld %6g\n",
859  is_timebin_active(i, times->Ti_Current) ? 'X' : ' ',
860  i,
861  tot_count_type[0][i],
862  tot_count_type[1][i],
863  tot_count_type[2][i],
864  tot_count_type[3][i],
865  tot_count_type[4][i],
866  tot_count_type[5][i],
867  get_dloga_for_bin(i, times->Ti_Current));
868 
869  if(is_timebin_active(i, times->Ti_Current))
870  {
871  tot += tot_count[i];
872  int ptype;
873  for(ptype = 0; ptype < 6; ptype ++) {
874  tot_type[ptype] += tot_count_type[ptype][i];
875  }
876  }
877  }
878  message(0, " -----------------------------------\n");
879  message(0, "Total: % 12ld % 12ld % 12ld % 12ld % 12ld % 12ld Sum:% 14ld\n",
880  tot_type[0], tot_type[1], tot_type[2], tot_type[3], tot_type[4], tot_type[5], tot);
881 
882 }
int TotNumPart
Definition: test_exchange.c:24
static enum TransferType ptype
Definition: zeldovich.c:146

References dloga, get_dloga_for_bin(), is_PM_timestep(), is_timebin_active(), message(), DriftKickTimes::mintimebin, ptype, sumup_large_ints(), DriftKickTimes::Ti_Current, TIMEBINS, and TotNumPart.

Referenced by rebuild_activelist().

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

◆ rebuild_activelist()

int rebuild_activelist ( ActiveParticles act,
const DriftKickTimes *const  times,
int  NumCurrentTiStep,
const double  Time 
)

Definition at line 721 of file timestep.c.

722 {
723  int i;
724 
725  int NumThreads = omp_get_max_threads();
726  /*Since we use a static schedule, only need NumPart/NumThreads elements per thread.*/
727  size_t narr = PartManager->NumPart / NumThreads + NumThreads;
728 
729  /*We know all particles are active on a PM timestep*/
730  if(is_PM_timestep(times)) {
731  act->ActiveParticle = NULL;
733  }
734  else {
735  /*Need space for more particles than we have, because of star formation*/
736  act->ActiveParticle = (int *) mymalloc("ActiveParticle", narr * NumThreads * sizeof(int));
737  act->NumActiveParticle = 0;
738  }
739 
740  int * TimeBinCountType = (int *) mymalloc("TimeBinCountType", 6*(TIMEBINS+1)*NumThreads * sizeof(int));
741  memset(TimeBinCountType, 0, 6 * (TIMEBINS+1) * NumThreads * sizeof(int));
742 
743  /*We want a lockless algorithm which preserves the ordering of the particle list.*/
744  size_t *NActiveThread = ta_malloc("NActiveThread", size_t, NumThreads);
745  int **ActivePartSets = ta_malloc("ActivePartSets", int *, NumThreads);
746  gadget_setup_thread_arrays(act->ActiveParticle, ActivePartSets, NActiveThread, narr, NumThreads);
747 
748  /* We enforce schedule static to imply monotonic, ensure that each thread executes on contiguous particles
749  * and ensure no thread gets more than narr particles.*/
750  size_t schedsz = PartManager->NumPart / NumThreads + 1;
751  #pragma omp parallel for schedule(static, schedsz)
752  for(i = 0; i < PartManager->NumPart; i++)
753  {
754  const int bin = P[i].TimeBin;
755  const int tid = omp_get_thread_num();
756  if(P[i].IsGarbage || P[i].Swallowed)
757  continue;
758  /* when we are in PM, all particles must have been synced. */
759  if (P[i].Ti_drift != times->Ti_Current) {
760  endrun(5, "Particle %d type %d has drift time %x not ti_current %x!",i, P[i].Type, P[i].Ti_drift, times->Ti_Current);
761  }
762 
763  if(act->ActiveParticle && is_timebin_active(bin, times->Ti_Current))
764  {
765  /* Store this particle in the ActiveSet for this thread*/
766  ActivePartSets[tid][NActiveThread[tid]] = i;
767  NActiveThread[tid]++;
768  }
769  TimeBinCountType[(TIMEBINS + 1) * (6* tid + P[i].Type) + bin] ++;
770  }
771  if(act->ActiveParticle) {
772  /*Now we want a merge step for the ActiveParticle list.*/
773  act->NumActiveParticle = gadget_compact_thread_arrays(act->ActiveParticle, ActivePartSets, NActiveThread, NumThreads);
774  }
775  ta_free(ActivePartSets);
776  ta_free(NActiveThread);
777 
778  /*Print statistics for this time bin*/
779  print_timebin_statistics(times, NumCurrentTiStep, TimeBinCountType, Time);
780  myfree(TimeBinCountType);
781 
782  /* Shrink the ActiveParticle array. We still need extra space for star formation,
783  * but we do not need space for the known-inactive particles*/
784  if(act->ActiveParticle) {
785  act->ActiveParticle = (int *) myrealloc(act->ActiveParticle, sizeof(int)*(act->NumActiveParticle + PartManager->MaxPart - PartManager->NumPart));
787  /* listen to the slots events such that we can set timebin of new particles */
788  }
790  walltime_measure("/Timeline/Active");
791 
792  return 0;
793 }
int event_listen(EventSpec *eh, eventfunc func, void *userdata)
Definition: event.c:6
#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
int64_t MaxActiveParticle
Definition: timestep.h:11
void gadget_setup_thread_arrays(int *dest, int *srcs[], size_t sizes[], size_t total_size, int narrays)
Definition: system.c:600
size_t gadget_compact_thread_arrays(int *dest, int *srcs[], size_t sizes[], int narrays)
Definition: system.c:587
static void print_timebin_statistics(const DriftKickTimes *const times, const int NumCurrentTiStep, int *TimeBinCountType, const double Time)
Definition: timestep.c:807

References ActiveParticles::ActiveParticle, endrun(), event_listen(), EventSlotsFork, gadget_compact_thread_arrays(), gadget_setup_thread_arrays(), is_PM_timestep(), is_timebin_active(), ActiveParticles::MaxActiveParticle, part_manager_type::MaxPart, myfree, mymalloc, myrealloc, ActiveParticles::NumActiveParticle, part_manager_type::NumPart, P, PartManager, print_timebin_statistics(), ta_free, ta_malloc, DriftKickTimes::Ti_Current, TIMEBINS, timestep_eh_slots_fork(), and walltime_measure.

Referenced by run(), and run_gravity_test().

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

◆ set_timestep_params()

void set_timestep_params ( ParameterSet ps)

Definition at line 51 of file timestep.c.

52 {
53  int ThisTask;
54  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
55  if(ThisTask == 0) {
56  TimestepParams.ErrTolIntAccuracy = param_get_double(ps, "ErrTolIntAccuracy");
57  TimestepParams.MaxGasVel = param_get_double(ps, "MaxGasVel");
58  TimestepParams.MaxSizeTimestep = param_get_double(ps, "MaxSizeTimestep");
59 
60  TimestepParams.MinSizeTimestep = param_get_double(ps, "MinSizeTimestep");
61  TimestepParams.ForceEqualTimesteps = param_get_int(ps, "ForceEqualTimesteps");
62  TimestepParams.MaxRMSDisplacementFac = param_get_double(ps, "MaxRMSDisplacementFac");
63  TimestepParams.CourantFac = param_get_double(ps, "CourantFac");
64  }
65  MPI_Bcast(&TimestepParams, sizeof(struct timestep_params), MPI_BYTE, 0, MPI_COMM_WORLD);
66 }
double param_get_double(ParameterSet *ps, const char *name)
Definition: paramset.c:336
int param_get_int(ParameterSet *ps, const char *name)
Definition: paramset.c:368
int ThisTask
Definition: test_exchange.c:23

References timestep_params::CourantFac, timestep_params::ErrTolIntAccuracy, timestep_params::ForceEqualTimesteps, timestep_params::MaxGasVel, timestep_params::MaxRMSDisplacementFac, timestep_params::MaxSizeTimestep, timestep_params::MinSizeTimestep, param_get_double(), param_get_int(), ThisTask, and TimestepParams.

Referenced by read_parameter_file().

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

◆ timestep_eh_slots_fork()

static int timestep_eh_slots_fork ( EIBase event,
void *  userdata 
)
static

Definition at line 77 of file timestep.c.

78 {
79  /*Update the active particle list:
80  * if the parent is active the child should also be active.
81  * Stars must always be active on formation, but
82  * BHs need not be: a halo can be seeded when the particle in question is inactive.*/
83 
84  EISlotsFork * ev = (EISlotsFork *) event;
85 
86  int parent = ev->parent;
87  int child = ev->child;
88  ActiveParticles * act = (ActiveParticles *) userdata;
89 
90  if(is_timebin_active(P[parent].TimeBin, P[parent].Ti_drift)) {
91  int64_t childactive = atomic_fetch_and_add_64(&act->NumActiveParticle, 1);
92  if(act->ActiveParticle) {
93  /* This should never happen because we allocate as much space for active particles as we have space
94  * for particles, but just in case*/
95  if(childactive >= act->MaxActiveParticle)
96  endrun(5, "Tried to add %ld active particles, more than %ld allowed\n", childactive, act->MaxActiveParticle);
97  act->ActiveParticle[childactive] = child;
98  }
99  }
100  return 0;
101 }
int64_t child
Definition: slotsmanager.h:151
static int64_t atomic_fetch_and_add_64(int64_t *ptr, int64_t value)
Definition: system.h:68

References ActiveParticles::ActiveParticle, atomic_fetch_and_add_64(), EISlotsFork::child, endrun(), is_timebin_active(), ActiveParticles::MaxActiveParticle, ActiveParticles::NumActiveParticle, P, and EISlotsFork::parent.

Referenced by free_activelist(), and rebuild_activelist().

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

◆ update_lastactive_drift()

void update_lastactive_drift ( DriftKickTimes times)

Definition at line 309 of file timestep.c.

310 {
311  int bin;
312  #pragma omp parallel for
313  for(bin = 0; bin <= TIMEBINS; bin++)
314  {
315  /* Update active timestep even if no particles in it*/
316  if(is_timebin_active(bin, times->Ti_Current))
317  times->Ti_lastactivedrift[bin] = times->Ti_Current;
318  }
319 }

References is_timebin_active(), DriftKickTimes::Ti_Current, DriftKickTimes::Ti_lastactivedrift, and TIMEBINS.

Referenced by run().

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

Variable Documentation

◆ TimestepParams

struct timestep_params TimestepParams
static