src/ include/ test/ fig/ objs/
[sddekit.git] / src / sk_hist.c
blobe335b6b6a4bc7876a05e8d7d06b7fb65d6760a80
1 /* Apache 2.0 INS-AMU 2015 */
3 #include "stdlib.h"
4 #include "string.h"
5 #include "math.h"
7 #include "sk_util.h"
8 #include "sk_hist.h"
11 static void setup_buffer_structure(sk_hist *h)
13 int i, j, ui;
14 double maxd;
16 SK_MALLOCHECK(h->maxd = malloc (sizeof(double) * h->nu));
17 SK_MALLOCHECK(h->lim = malloc (sizeof(double) * (h->nu + 1)));
18 SK_MALLOCHECK(h->len = malloc (sizeof(double) * h->nu));
19 SK_MALLOCHECK(h->pos = malloc (sizeof(double) * h->nu));
21 /* vi2i requires max(uvi) then filling in vi2i[ui]=i */
22 h->maxvi = 0;
23 for (i=0; i<h->nu; i++)
24 if (h->uvi[i] > h->maxvi)
25 h->maxvi = h->uvi[i];
27 SK_MALLOCHECK(h->vi2i = malloc (sizeof(int) * (h->maxvi + 1)));
29 for (i=0; i<h->nu; i++)
31 ui = h->uvi[i];
32 h->vi2i[ui] = i;
33 maxd = 0.0;
34 /* TODO double check */
35 for (j=0; j<h->nd; j++)
36 if (h->vi[j]==ui && h->del[j]>maxd)
37 maxd = h->del[j];
38 h->maxd[i] = maxd;
39 h->len[i] = ceil(maxd / h->dt) + 2;
40 h->pos[i] = 0;
41 if (i==0)
42 h->lim[i] = 0;
43 else
44 h->lim[i] = h->pos[i-1] + h->len[i-1];
46 h->lim[h->nu] = h->lim[h->nu-1] + h->len[h->nu-1];
49 void sk_hist_init(sk_hist *h, int nd, int *vi, double *vd, double t0, double dt)
51 h->dt = dt;
52 h->t = t0;
53 h->nd = nd;
55 /* identify unique delayed variable indices
56 * NB: this allocates h->uci
58 sk_util_uniqi(nd, vi, &(h->nu), &(h->uvi));
60 /* alloc & copy the delay values */
61 SK_MALLOCHECK(h->del = malloc (sizeof(double) * nd));
62 memcpy(h->del, vd, nd * sizeof(double));
64 /* and indices */
65 SK_MALLOCHECK(h->vi = malloc (sizeof(int) * nd));
66 memcpy(h->vi, vi, nd * sizeof(int));
68 /* setup maxd, off, len, pos */
69 setup_buffer_structure(h);
71 /* alloc buf */
72 SK_MALLOCHECK(h->buf = malloc (sizeof(double) * h->lim[h->nu]));
75 void sk_hist_free(sk_hist *h)
77 free(h->uvi);
78 free(h->del);
79 free(h->vi);
80 free(h->maxd);
81 free(h->lim);
82 free(h->len);
83 free(h->pos);
84 free(h->vi2i);
85 free(h->buf);
88 void sk_hist_fill(sk_hist *h, sk_hist_filler filler, void *fill_data)
90 int i, j, ui, o, n, *vi;
91 double *t;
93 n = h->lim[h->nu];
94 SK_MALLOCHECK(t = malloc (sizeof(double) * n));
95 SK_MALLOCHECK(vi = malloc (sizeof(int) * n));
97 /* expand indices per buffer element */
98 for (i=0; i<h->nu; i++)
100 ui = h->uvi[i];
101 for (j=h->lim[i]; j<h->lim[i+1]; j++)
102 vi[j] = ui;
105 /* evaluate time per buffer element */
106 for (i=0; i<h->nu; i++)
108 for (j=0; j<(h->len[i]-1); j++)
110 o = h->pos[i]; /* current position in buffer */
111 o += j; /* time step through buffer */
112 o %= h->len[i]; /* wrap around on section length */
113 o += h->lim[i]; /* offset to start of section */
114 t[o] = h->t - j * h->dt;
116 j = h->len[i] - 1;
117 o = h->pos[i]; /* current position in buffer */
118 o += j; /* time step through buffer */
119 o %= h->len[i]; /* wrap around on section length */
120 o += h->lim[i]; /* offset to start of section */
121 t[o] = h->t + h->dt; /* last point is next grid point */
124 filler(fill_data, n, t, vi, h->buf);
126 free(t);
127 free(vi);
130 void sk_hist_get(sk_hist *h, double t, double *c)
132 int i, i0, i1, ui;
134 for (i=0; i<h->nd; i++)
136 ui = h->vi2i[h->vi[i]];
137 i0 = h->pos[ui] - floor((t - h->del[i] - h->t) / h->dt);
138 i0 %= h->len[ui];
139 i1 = i0 ? i0 - 1 : h->len[ui]-1;
140 i0 += h->lim[ui];
141 i1 += h->lim[ui];
143 #ifdef SKDEBUG
144 if ((i0 < 0) || (i0 > h->lim[h->nu]))
145 fprintf(stderr, "[sk_hist] oob i0=%d %s:%d\n", i0, __FILE__, __LINE__);
146 if ((i1 < 0) || (i1 > h->lim[h->nu]))
147 fprintf(stderr, "[sk_hist] oob i1=%d %s:%d\n", i1, __FILE__, __LINE__);
148 #endif
149 c[i] = (h->buf[i1] - h->buf[i0]) / h->dt
150 * fmod((t + h->del[i]), h->dt) + h->buf[i0];
154 static void update_time(sk_hist *h, double new_t)
156 int i, n_steps;
158 /* the current time must always be contained between
159 * pos and pos-1 in the buffer
161 n_steps = 0;
162 while ((h->t + h->dt) < new_t)
164 h->t += h->dt;
165 n_steps++;
168 /* if no steps to take, return early */
169 if (n_steps==0)
170 return;
172 /* update positions */
173 for (i=0; i<h->nu; i++)
175 h->pos[i] -= n_steps;
176 if (h->pos[i] < 0)
177 h->pos[i] += h->len[i];
181 void sk_hist_set(sk_hist *h, double t, double *x)
183 int i, i0, i1;
184 double x0, dx, dt;
186 update_time(h, t);
188 /* extrapolate from (x(h->t), x(t)) to next grid point*/
189 for (i=0; i<h->nu; i++)
191 i0 = h->pos[i];
192 i1 = i0 ? i0 - 1 : h->len[i] - 1;
193 i0 += h->lim[i];
194 i1 += h->lim[i];
195 x0 = h->buf[i0];
196 dt = t - h->t;
197 dx = x[h->uvi[i]] - h->buf[i0];
198 h->buf[i1] = (dx / dt) * h->dt + x0;
202 int sk_hist_nbytes(sk_hist *h)
204 int nb;
205 nb = sizeof(sk_hist);
206 nb += sizeof(int) * ((h->nu+1) + 3*h->nu + h->nd + h->maxvi);
207 nb += sizeof(double) * (h->lim[h->nu] + h->nu + h->nd);
208 return nb;
211 void sk_hist_zero_filler(void *data, int n, double *t, int *indices, double *buf)
213 int i;
214 /* suppress unused parameter warnings */
215 (void) data; (void) n; (void) t; (void) indices;
216 for (i=0; i<n; i++)
217 buf[i] = 0.0;