MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
timebinmgr.c
Go to the documentation of this file.
1 #include <math.h>
2 #include <string.h>
3 #include <stdlib.h>
4 
5 #include "timebinmgr.h"
6 #include "utils.h"
7 
10 static int NSyncPoints; /* number of times stored in table of desired sync points */
11 static struct sync_params
12 {
14  double OutputListTimes[1024];
15 } Sync;
16 
17 int cmp_double(const void * a, const void * b)
18 {
19  return ( *(double*)a - *(double*)b );
20 }
21 
31 int OutputListAction(ParameterSet* ps, const char* name, void* data)
32 {
33  char * outputlist = param_get_string(ps, name);
34  char * strtmp = fastpm_strdup(outputlist);
35  char * token;
36  int count;
37 
38  /* Note TimeInit and TimeMax not yet initialised here*/
39 
40  /*First parse the string to get the number of outputs*/
41  for(count=0, token=strtok(strtmp,","); token; count++, token=strtok(NULL, ","))
42  {}
43 /* message(1, "Found %d times in output list.\n", count); */
44 
45  /*Allocate enough memory*/
46  Sync.OutputListLength = count;
47  int maxcount = sizeof(Sync.OutputListTimes) / sizeof(Sync.OutputListTimes[0]);
48  if(maxcount > (int) MAXSNAPSHOTS)
49  maxcount = MAXSNAPSHOTS;
50  if(Sync.OutputListLength > maxcount) {
51  message(1, "Too many entries (%d) in the OutputList, can take no more than %d.\n", Sync.OutputListLength, maxcount);
52  return 1;
53  }
54  /*Now read in the values*/
55  for(count=0,token=strtok(outputlist,","); count < Sync.OutputListLength && token; count++, token=strtok(NULL,","))
56  {
57  /* Skip a leading quote if one exists.
58  * Extra characters are ignored by atof, so
59  * no need to skip matching char.*/
60  if(token[0] == '"')
61  token+=1;
62 
63  double a = atof(token);
64 
65  if(a < 0.0) {
66  endrun(1, "Requesting a negative output scaling factor a = %g\n", a);
67  }
68  Sync.OutputListTimes[count] = a;
69 /* message(1, "Output at: %g\n", Sync.OutputListTimes[count]); */
70  }
71  myfree(strtmp);
72  return 0;
73 }
74 
75 /* For the tests*/
76 void set_sync_params(int OutputListLength, double * OutputListTimes)
77 {
78  int i;
80  for(i = 0; i < OutputListLength; i++)
81  Sync.OutputListTimes[i] = OutputListTimes[i];
82 }
83 
84 /* This function compiles
85  *
86  * Sync.OutputListTimes, All.TimeIC, All.TimeMax
87  *
88  * into a list of SyncPoint objects.
89  *
90  * A SyncPoint is a time step where all state variables are at the same time on the
91  * KkdkK timeline.
92  *
93  * TimeIC and TimeMax are used to ensure restarting from snapshot obtains exactly identical
94  * integer stamps.
95  **/
96 void
97 setup_sync_points(double TimeIC, double TimeMax, double no_snapshot_until_time, int SnapshotWithFOF)
98 {
99  int i;
100 
102 
103  if(NSyncPoints > 0)
105  SyncPoints = (SyncPoint *) mymalloc("SyncPoints", sizeof(SyncPoint) * (Sync.OutputListLength+2));
106 
107  /* Set up first and last entry to SyncPoints; TODO we can insert many more! */
108 
109  SyncPoints[0].a = TimeIC;
110  SyncPoints[0].loga = log(TimeIC);
111  SyncPoints[0].write_snapshot = 0; /* by default no output here. */
112  SyncPoints[0].write_fof = 0;
113  SyncPoints[1].a = TimeMax;
114  SyncPoints[1].loga = log(TimeMax);
115  SyncPoints[1].write_snapshot = 1;
116  if(SnapshotWithFOF)
117  SyncPoints[1].write_fof = 1;
118  else
119  SyncPoints[1].write_fof = 0;
120  NSyncPoints = 2;
121 
122  /* we do an insertion sort here. A heap is faster but who cares the speed for this? */
123  for(i = 0; i < Sync.OutputListLength; i ++) {
124  int j = 0;
125  double a = Sync.OutputListTimes[i];
126  double loga = log(a);
127 
128  for(j = 0; j < NSyncPoints; j ++) {
129  if(a <= SyncPoints[j].a) {
130  break;
131  }
132  }
133  if(j == NSyncPoints) {
134  /* beyond TimeMax, skip */
135  continue;
136  }
137  /* found, so loga >= SyncPoints[j].loga */
138  if(a == SyncPoints[j].a) {
139  /* requesting output on an existing entry, e.g. TimeInit or duplicated entry */
140  } else {
141  /* insert the item; */
142  memmove(&SyncPoints[j + 1], &SyncPoints[j],
143  sizeof(SyncPoints[0]) * (NSyncPoints - j));
144  SyncPoints[j].a = a;
145  SyncPoints[j].loga = loga;
146  NSyncPoints ++;
147  }
148  if(SyncPoints[j].a > no_snapshot_until_time) {
149  SyncPoints[j].write_snapshot = 1;
150  if(SnapshotWithFOF) {
151  SyncPoints[j].write_fof = 1;
152  }
153  else
154  SyncPoints[j].write_fof = 0;
155  } else {
156  SyncPoints[j].write_snapshot = 0;
157  SyncPoints[j].write_fof = 0;
158  }
159  }
160 
161  for(i = 0; i < NSyncPoints; i++) {
162  SyncPoints[i].ti = (i * 1L) << (TIMEBINS);
163  }
164 
165 /* for(i = 0; i < NSyncPoints; i++) { */
166 /* message(1,"Out: %g %ld\n", exp(SyncPoints[i].loga), SyncPoints[i].ti); */
167 /* } */
168 }
169 
173 SyncPoint *
175 {
176  int i;
177  for(i = 0; i < NSyncPoints; i ++) {
178  if(SyncPoints[i].ti > ti) {
179  return &SyncPoints[i];
180  }
181  }
182  return NULL;
183 }
184 
185 /* This function finds if ti is a sync point; if so returns the sync point;
186  * otherwise, NULL. We check if we shall write a snapshot with this. */
187 SyncPoint *
189 {
190  int i;
191  for(i = 0; i < NSyncPoints; i ++) {
192  if(SyncPoints[i].ti == ti) {
193  return &SyncPoints[i];
194  }
195  }
196  return NULL;
197 }
198 
199 /* Each integer time stores in the first 10 bits the snapshot number.
200  * Then the rest of the bits are the standard integer timeline,
201  * which should be a power-of-two hierarchy. We use this bit trick to speed up
202  * the dloga look up. But the additional math makes this quite fragile. */
203 
204 /*Gets Dloga / ti for the current integer timeline.
205  * Valid up to the next snapshot, after which it will change*/
206 static double
208 {
209  /* FIXME: This uses the bit tricks because it has to be fast
210  * -- till we clean up the calls to loga_from_ti; then we can avoid bit tricks. */
211 
212  inttime_t lastsnap = ti >> TIMEBINS;
213 
214  if(lastsnap >= NSyncPoints - 1) {
215  /* stop advancing loga after the last sync point. */
216  return 0;
217  }
218  double lastoutput = SyncPoints[lastsnap].loga;
219  return (SyncPoints[lastsnap+1].loga - lastoutput)/TIMEBASE;
220 }
221 
222 double
224 {
225  inttime_t lastsnap = ti >> TIMEBINS;
226  if(lastsnap > NSyncPoints) {
227  endrun(1, "Requesting snap %d, from ti %d, beyond last sync point %d\n", lastsnap, ti, NSyncPoints);
228  }
229  double last = SyncPoints[lastsnap].loga;
230  inttime_t dti = ti & (TIMEBASE - 1);
231  double logDTime = Dloga_interval_ti(ti);
232  return last + dti * logDTime;
233 }
234 
235 inttime_t
236 ti_from_loga(double loga)
237 {
238  int i;
239  int ti;
240  /* First syncpoint is simulation start*/
241  for(i = 1; i < NSyncPoints - 1; i++)
242  {
243  if(SyncPoints[i].loga > loga)
244  break;
245  }
246  /*If loop didn't trigger, i == All.NSyncPointTimes-1*/
247  double logDTime = (SyncPoints[i].loga - SyncPoints[i-1].loga)/TIMEBASE;
248  ti = (i-1) << TIMEBINS;
249  /* Note this means if we overrun the end of the timeline,
250  * we still get something reasonable*/
251  ti += (loga - SyncPoints[i-1].loga)/logDTime;
252  return ti;
253 }
254 
255 double
256 dloga_from_dti(inttime_t dti, const inttime_t Ti_Current)
257 {
258  double Dloga = Dloga_interval_ti(Ti_Current);
259  int sign = 1;
260  if(dti < 0) {
261  dti = -dti;
262  sign = -1;
263  }
264  if((unsigned int) dti > TIMEBASE) {
265  endrun(1, "Requesting dti %d larger than TIMEBASE %u\n", sign*dti, TIMEBASE);
266  }
267  return Dloga * dti * sign;
268 }
269 
270 inttime_t
271 dti_from_dloga(double loga, const inttime_t Ti_Current)
272 {
273  inttime_t ti = ti_from_loga(loga_from_ti(Ti_Current));
274  inttime_t tip = ti_from_loga(loga+loga_from_ti(Ti_Current));
275  return tip - ti;
276 }
277 
278 double
279 get_dloga_for_bin(int timebin, const inttime_t Ti_Current)
280 {
281  double logDTime = Dloga_interval_ti(Ti_Current);
282  return (timebin > 0 ? (1u << (unsigned) timebin) : 0 ) * logDTime;
283 }
284 
285 inttime_t
287 {
288  /* make dti a power 2 subdivision */
289  inttime_t ti_min = TIMEBASE;
290  int sign = 1;
291  if(dti < 0) {
292  dti = -dti;
293  sign = -1;
294  }
295  while(ti_min > dti)
296  ti_min >>= 1;
297  return ti_min * sign;
298 }
299 
const char * name
Definition: densitykernel.c:93
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define myfree(x)
Definition: mymalloc.h:19
char * param_get_string(ParameterSet *ps, const char *name)
Definition: paramset.c:346
char * fastpm_strdup(const char *str)
Definition: string.c:31
inttime_t ti
Definition: timebinmgr.h:28
double a
Definition: timebinmgr.h:24
int write_fof
Definition: timebinmgr.h:27
double loga
Definition: timebinmgr.h:25
int write_snapshot
Definition: timebinmgr.h:26
int OutputListLength
Definition: timebinmgr.c:13
double OutputListTimes[1024]
Definition: timebinmgr.c:14
#define qsort_openmp
Definition: test_exchange.c:14
#define OutputListLength
static double Dloga_interval_ti(inttime_t ti)
Definition: timebinmgr.c:207
inttime_t dti_from_dloga(double loga, const inttime_t Ti_Current)
Definition: timebinmgr.c:271
static int NSyncPoints
Definition: timebinmgr.c:10
inttime_t ti_from_loga(double loga)
Definition: timebinmgr.c:236
SyncPoint * find_next_sync_point(inttime_t ti)
Definition: timebinmgr.c:174
inttime_t round_down_power_of_two(inttime_t dti)
Definition: timebinmgr.c:286
int OutputListAction(ParameterSet *ps, const char *name, void *data)
Definition: timebinmgr.c:31
double dloga_from_dti(inttime_t dti, const inttime_t Ti_Current)
Definition: timebinmgr.c:256
double get_dloga_for_bin(int timebin, const inttime_t Ti_Current)
Definition: timebinmgr.c:279
double loga_from_ti(inttime_t ti)
Definition: timebinmgr.c:223
SyncPoint * find_current_sync_point(inttime_t ti)
Definition: timebinmgr.c:188
int cmp_double(const void *a, const void *b)
Definition: timebinmgr.c:17
void setup_sync_points(double TimeIC, double TimeMax, double no_snapshot_until_time, int SnapshotWithFOF)
Definition: timebinmgr.c:97
static SyncPoint * SyncPoints
Definition: timebinmgr.c:9
static struct sync_params Sync
void set_sync_params(int OutputListLength, double *OutputListTimes)
Definition: timebinmgr.c:76
#define MAXSNAPSHOTS
Definition: timebinmgr.h:15
#define TIMEBINS
Definition: timebinmgr.h:13
#define TIMEBASE
Definition: timebinmgr.h:14
int32_t inttime_t
Definition: types.h:8