1 /* Apache 2.0 INS-AMU 2015 */
13 /* nu+1 nu nu nu nd, maxvi */
14 int nd
, nu
, *lim
, *len
, *pos
, *uvi
, *vi
, *vi2i
, maxvi
;
16 double *buf
, *maxd
, *del
, dt
, t
;
19 sk_hist
*sk_hist_alloc() {
20 return sk_malloc(sizeof(sk_hist
));
23 int sk_hist_get_maxvi(sk_hist
*h
) {
27 int sk_hist_get_vi2i(sk_hist
*h
, int vi
) {
31 static void setup_buffer_structure(sk_hist
*h
)
36 h
->maxd
= sk_malloc (sizeof(double) * h
->nu
);
37 h
->lim
= sk_malloc (sizeof(double) * (h
->nu
+ 1));
38 h
->len
= sk_malloc (sizeof(double) * h
->nu
);
39 h
->pos
= sk_malloc (sizeof(double) * h
->nu
);
41 /* vi2i requires max(uvi) then filling in vi2i[ui]=i */
43 for (i
=0; i
<h
->nu
; i
++)
44 if (h
->uvi
[i
] > h
->maxvi
)
47 h
->vi2i
= sk_malloc (sizeof(int) * (h
->maxvi
+ 1));
49 for (i
=0; i
<h
->nu
; i
++)
54 for (j
=0; j
<h
->nd
; j
++)
55 if (h
->vi
[j
]==ui
&& h
->del
[j
]>maxd
)
58 h
->len
[i
] = ceil(maxd
/ h
->dt
) + 2;
63 h
->lim
[i
] = h
->lim
[i
-1] + h
->len
[i
-1];
65 h
->lim
[h
->nu
] = h
->lim
[h
->nu
-1] + h
->len
[h
->nu
-1];
68 void sk_hist_init(sk_hist
* restrict h
, int nd
, int * restrict vi
, double * restrict vd
, double t0
, double dt
)
74 /* identify unique delayed variable indices
75 * NB: this allocates h->uci
77 sk_util_uniqi(nd
, vi
, &(h
->nu
), &(h
->uvi
));
79 /* alloc & copy the delay values */
80 h
->del
= sk_malloc (sizeof(double) * nd
);
81 memcpy(h
->del
, vd
, nd
* sizeof(double));
84 h
->vi
= sk_malloc (sizeof(int) * nd
);
85 memcpy(h
->vi
, vi
, nd
* sizeof(int));
87 /* setup maxd, off, len, pos */
88 setup_buffer_structure(h
);
91 h
->buf
= sk_malloc (sizeof(double) * h
->lim
[h
->nu
]);
94 void sk_hist_free(sk_hist
*h
)
108 void sk_hist_fill(sk_hist
* restrict h
, sk_hist_filler filler
, void * restrict fill_data
)
110 int i
, j
, ui
, o
, n
, *vi
;
114 t
= sk_malloc (sizeof(double) * n
);
115 vi
= sk_malloc (sizeof(int) * n
);
117 /* expand indices per buffer element */
118 for (i
=0; i
<h
->nu
; i
++)
121 for (j
=h
->lim
[i
]; j
<h
->lim
[i
+1]; j
++)
125 /* evaluate time per buffer element */
126 for (i
=0; i
<h
->nu
; i
++)
128 for (j
=0; j
<(h
->len
[i
]-1); j
++)
130 o
= h
->pos
[i
]; /* current position in buffer */
131 o
+= j
; /* time step through buffer */
132 o
%= h
->len
[i
]; /* wrap around on section length */
133 o
+= h
->lim
[i
]; /* offset to start of section */
134 t
[o
] = h
->t
- j
* h
->dt
;
137 o
= h
->pos
[i
]; /* current position in buffer */
138 o
+= j
; /* time step through buffer */
139 o
%= h
->len
[i
]; /* wrap around on section length */
140 o
+= h
->lim
[i
]; /* offset to start of section */
141 t
[o
] = h
->t
+ h
->dt
; /* last point is next grid point */
144 filler(fill_data
, n
, t
, vi
, h
->buf
);
150 void sk_hist_get(sk_hist
* restrict h
, double t
, double * restrict aff
)
157 for (i
= 0; i
< h
->nd
; i
++)
159 int ui
, i0
, i1
, i0_
, i1_
, p
, l
, o
;
160 double dt
, y0
, y1
, m
, dx
;
162 ui
= h
->vi2i
[h
->vi
[i
]];
167 dt
= (t
- h
->del
[i
]) - (h
->t
- (l
- 2)*h
->dt
);
169 i0
= (int)ceil((l
- 2) - dt
/ h
->dt
);
172 i1
= i0
? i0
- 1 : l
- 1;
174 i0_
= (p
+ i0
) % l
+ o
;
175 i1_
= (p
+ i1
) % l
+ o
;
178 if ((i0_
< h
->lim
[ui
]) || (i0_
>= h
->lim
[ui
+1]))
179 fprintf(stderr
, "[sk_hist_get] oob: i0_=%d not in [%d, %d) at %s:%d\n", i0_
, h
->lim
[ui
], h
->lim
[ui
+1], __FILE__
, __LINE__
);
180 if ((i1_
< h
->lim
[ui
]) || (i1_
>= h
->lim
[ui
+1]))
181 fprintf(stderr
, "[sk_hist_get] oob: i1_=%d not in [%d, %d) at %s:%d\n", i1_
, h
->lim
[ui
], h
->lim
[ui
+1], __FILE__
, __LINE__
);
188 m
= (y1
- y0
) / h
->dt
;
190 dx
= (t
- h
->del
[i
]) - (h
->t
- i0
*h
->dt
);
192 aff
[i
] = m
* dx
+ y0
;
197 static void update_time(sk_hist
*h
, double new_t
)
201 /* the current time must always be contained between
202 * pos and pos-1 in the buffer
204 * TODO handle case of irregular time step where new_t could
205 * be several h->dt ahead, and we need to fill in the buffer
209 while ((h
->t
+ h
->dt
) <= new_t
)
215 /* if no steps to take, return early */
219 /* update positions */
220 for (i
=0; i
<h
->nu
; i
++)
222 h
->pos
[i
] -= n_steps
;
224 h
->pos
[i
] += h
->len
[i
];
228 void sk_hist_set(sk_hist
* restrict h
, double t
, double * restrict eff
)
238 for (i
=0; i
<h
->nu
; i
++)
241 i1
= i0
? i0
- 1 : h
->len
[i
] - 1;
245 if ((i0
< h
->lim
[i
]) || (i0
> h
->lim
[i
+1]))
246 fprintf(stderr
, "[sk_hist_set] t=%.3f ui=%d, i0=%d not in [%d,%d) %s:%d\n",
247 t
, i
, i0
, h
->lim
[i
], h
->lim
[i
+1], __FILE__
, __LINE__
);
248 if ((i1
< h
->lim
[i
]) || (i1
> h
->lim
[i
+1]))
249 fprintf(stderr
, "[sk_hist_set] t=%.3f ui=%d, i1=%d not in [%d,%d) %s:%d\n",
250 t
, i
, i1
, h
->lim
[i
], h
->lim
[i
+1], __FILE__
, __LINE__
);
257 fprintf(stderr
, "[sk_hist] unhandled dt<0 at %s:%d\n", __FILE__
, __LINE__
);
261 /* extrapolate from (x(h->t), x(t)) to next grid point*/
262 dx
= eff
[h
->vi2i
[h
->uvi
[i
]]] - h
->buf
[i0
];
263 h
->buf
[i1
] = (dx
/ dt
) * h
->dt
+ x0
;
265 /* reset grid point value */
266 h
->buf
[i0
] = eff
[h
->vi2i
[h
->uvi
[i
]]];
271 int sk_hist_nbytes(sk_hist
*h
)
274 nb
= sizeof(sk_hist
);
275 nb
+= sizeof(int) * ((h
->nu
+1) + 3*h
->nu
+ h
->nd
+ h
->maxvi
);
276 nb
+= sizeof(double) * (h
->lim
[h
->nu
] + h
->nu
+ h
->nd
);
280 void sk_hist_zero_filler(void * restrict data
, int n
, double * restrict t
, int * restrict indices
, double * restrict buf
)
283 /* suppress unused parameter warnings */
284 (void) data
; (void) n
; (void) t
; (void) indices
;
289 int sk_hist_get_nu(sk_hist
*h
) {
293 double sk_hist_get_buf_lin(sk_hist
*h
, int index
) {
295 if ((index
< 0) || (index
>= h
->lim
[h
->nu
]))
296 fprintf(stderr
, "[sk_hist_get_buf_lin] oob index=%d not in [0, %d)\n", index
, h
->lim
[h
->nu
]);
298 return h
->buf
[index
];
301 double sk_hist_get_t(sk_hist
*h
) {
305 double sk_hist_get_dt(sk_hist
*h
) {
309 int sk_hist_get_lim(sk_hist
*h
, int i
) {
313 int sk_hist_get_len(sk_hist
*h
, int i
) {
317 int sk_hist_get_nd(sk_hist
*h
) {
321 int sk_hist_get_pos(sk_hist
*h
, int i
) {
325 int sk_hist_get_uvi(sk_hist
*h
, int i
) {
329 int sk_hist_get_vi(sk_hist
*h
, int i
) {
333 double sk_hist_get_maxd(sk_hist
*h
, int i
) {
337 int sk_hist_buf_is_null(sk_hist
*h
) {
338 return h
->buf
== NULL
;
341 double sk_hist_get_vd(sk_hist
*h
, int i
) {