Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
events.h
Go to the documentation of this file.
1/** @file events.h
2 */
3typedef struct _Event Event;
4typedef int (* Expr) (int *, double *, Event *);
5
6struct _Event {
7 int last, nexpr;
8 int (* action) (const int, const double, Event *);
10 int * arrayi;
11 double * arrayt;
12 char * file;
13 int line;
14 char * name;
15 double t;
16 int i, a;
17 void * data;
19};
20
21static Event * Events = NULL; // all events
22
23int iter = 0, inext = 0; // current step and step of next event
24double t = 0, tnext = 0; // current time and time of next event
25void init_events (void);
27static void _init_solver (void);
28
29#define INIT ev->expr[0]
30#define COND ev->expr[1]
31#define INC ev->expr[2]
32
33static int END_EVENT = 1234567890;
34static double TEND_EVENT = 1234567890;
35static double TEPS = 1e-9;
36
37static void event_error (Event * ev, const char * s)
38{
39 fprintf (stderr, "%s:%d: error: %s\n", ev->file, ev->line, s);
40 exit (1);
41}
42
43static void init_event (Event * ev)
44{
45 if (ev->arrayi || ev->arrayt) {
46 ev->i = -1; ev->t = - TEND_EVENT;
47 if (ev->arrayi)
48 ev->i = ev->arrayi[0];
49 else
50 ev->t = ev->arrayt[0];
51 ev->a = 1;
52 ev->expr[1] = NULL;
53 }
54 else {
55 if (ev->nexpr > 0) {
56 Expr init = NULL, cond = NULL, inc = NULL;
57 for (int j = 0; j < ev->nexpr; j++) {
58 int i = -123456; double t = - TEND_EVENT;
59 (* ev->expr[j]) (&i, &t, ev);
60 if (i == -123456 && t == - TEND_EVENT) {
61 /* nothing done to i and t: this must be the condition */
62 if (cond)
63 event_error (ev, "events can only use a single condition");
64 cond = ev->expr[j];
65 }
66 else {
67 /* this is either an initialisation or an increment */
68 int i1 = i; double t1 = t;
69 (* ev->expr[j]) (&i1, &t1, ev);
70 if (i1 == i && t1 == t) {
71 /* applying twice does not change anything: this is an
72 initialisation */
73 if (init)
74 event_error (ev, "events can only use a single initialisation");
75 init = ev->expr[j];
76 }
77 else {
78 /* this is the increment */
79 if (inc)
80 event_error (ev, "events can only use a single increment");
81 inc = ev->expr[j];
82 }
83 }
84 }
85 INIT = init;
86 COND = cond;
87 INC = inc;
88 ev->nexpr = 0;
89 }
90 ev->i = -1; ev->t = - TEND_EVENT;
91 if (INIT) {
92 (* INIT) (&ev->i, &ev->t, ev);
93 if (ev->i == END_EVENT || ev->t == TEND_EVENT) {
94 ev->i = END_EVENT; ev->t = - TEND_EVENT;
95 }
96 }
97 else if (INC) {
98 (* INC) (&ev->i, &ev->t, ev);
99 if (ev->i != -1)
100 ev->i = 0;
101 if (ev->t != - TEND_EVENT)
102 ev->t = 0;
103 }
104 }
105}
106
108
109static int event_finished (Event * ev)
110{
111 ev->i = -1; ev->t = - TEND_EVENT;
112 return event_done;
113}
114
116 assert (Events);
117 assert (!event.last);
118 int n = 0, parent = -1;
119 for (Event * ev = Events; !ev->last; ev++) {
120 if (!strcmp (event.name, ev->name)) {
121 assert (parent < 0);
122 parent = n;
123 }
124 n++;
125 }
126 if (parent < 0) {
127 Events = (Event *)realloc(Events, (n + 2)*sizeof(Event));
128 Events[n] = event;
129 Events[n].next = NULL;
130 Events[n + 1].last = true;
131 init_event (&Events[n]);
132 }
133 else {
134 Event * ev = qcalloc (1, Event);
135 *ev = Events[parent];
136 Events[parent] = event;
137 Events[parent].next = ev;
138 init_event (&Events[parent]);
139 }
140}
141
142static int event_cond (Event * ev, int i, double t)
143{
144 if (!COND)
145 return true;
146 return (* COND) (&i, &t, ev);
147}
148
149#if DEBUG_EVENTS
150static void event_print (Event * ev, FILE * fp)
151{
152 char * root = strstr (ev->file, BASILISK);
153 fprintf (fp, " %-25s %s%s:%d\n", ev->name,
154 root ? "src" : "",
155 root ? &ev->file[strlen(BASILISK)] : ev->file,
156 ev->line);
157}
158#endif
159
160/**
161The interpreter [overloads](/ast/interpreter/overload.h) the function
162below to control (i.e. shorten) the events loop. */
163
164static bool overload_event() { return true; }
165
166static int event_do (Event * ev, bool action)
167{
168 if ((iter > ev->i && t > ev->t) || !event_cond (ev, iter, t))
169 return event_finished (ev);
170 if (!overload_event() || iter == ev->i || fabs (t - ev->t) <= TEPS*t) {
171 if (action) {
172 bool finished = false;
173 for (Event * e = ev; e; e = e->next) {
174#if DEBUG_EVENTS
176#endif
177 if ((* e->action) (iter, t, e))
178 finished = true;
179 }
180 if (finished) {
182 return event_stop;
183 }
184 }
185 if (ev->arrayi) { /* i = {...} */
186 ev->i = ev->arrayi[ev->a++];
187 if (ev->i < 0)
188 return event_finished (ev);
189 }
190 if (ev->arrayt) { /* t = {...} */
191 ev->t = ev->arrayt[ev->a++];
192 if (ev->t < 0)
193 return event_finished (ev);
194 }
195 else if (INC) {
196 int i0 = ev->i;
197 (* INC) (&ev->i, &ev->t, ev);
198 if (i0 == -1 && ev->i != i0)
199 ev->i += iter + 1;
200 if (!event_cond (ev, iter + 1, ev->t))
201 return event_finished (ev);
202 }
203 else if (INIT && !COND)
204 return event_finished (ev);
205 }
206 return event_alive;
207}
208
209static void end_event_do (bool action)
210{
211#if DEBUG_EVENTS
212 if (action)
213 fprintf (stderr, "\nend events (i = %d, t = %g)\n", iter, t);
214#endif
215 for (Event * ev = Events; !ev->last; ev++)
216 if (ev->i == END_EVENT && action)
217 for (Event * e = ev; e; e = e->next) {
218#if DEBUG_EVENTS
220#endif
221 e->action (iter, t, e);
222 }
223}
224
225int events (bool action)
226{
227#if DEBUG_EVENTS
228 if (action)
229 fprintf (stderr, "\nevents (i = %d, t = %g)\n", iter, t);
230#endif
231
232 if (iter == 0)
233 for (Event * ev = Events; !ev->last; ev++)
234 init_event (ev);
235
236 int cond = 0, cond1 = 0;
238 for (Event * ev = Events; !ev->last && !cond; ev++)
239 if (ev->i != END_EVENT &&
240 (COND || (INIT && !COND && !INC) || ev->arrayi || ev->arrayt))
241 cond = 1;
242 for (Event * ev = Events; !ev->last; ev++) {
243 int status = event_do (ev, action);
244 if (status == event_stop) {
245 end_event_do (action);
246 return 0;
247 }
248 if (status == event_alive && ev->i != END_EVENT &&
249 (COND || (INIT && !COND && !INC) || ev->arrayi || ev->arrayt))
250 cond1 = 1;
251 if (ev->t > t && ev->t < tnext)
252 tnext = ev->t;
253 if (ev->i > iter && ev->i < inext)
254 inext = ev->i;
255 }
256 if (overload_event() && (!cond || cond1) && (tnext != HUGE || inext != END_EVENT)) {
257 inext = iter + 1;
258 return 1;
259 }
260 end_event_do (action);
261 return 0;
262}
263
264void event (const char * name)
265{
266 for (Event * ev = Events; !ev->last; ev++)
267 if (!strcmp (ev->name, name))
268 for (Event * e = ev; e; e = e->next) {
269#if DEBUG_EVENTS
271#endif
272 (* e->action) (0, 0, e);
273 }
274}
275
276double dtnext (double dt)
277{
278 if (tnext != HUGE && tnext > t) {
279 assert (dt > 0.);
280 unsigned int n = (tnext - t)/dt;
281 assert (n < INT_MAX); // check that dt is not too small
282 if (n == 0)
283 dt = tnext - t;
284 else {
285 double dt1 = (tnext - t)/n;
286 if (dt1 > dt*(1. + TEPS))
287 dt = (tnext - t)/(n + 1);
288 else if (dt1 < dt)
289 dt = dt1;
290 tnext = t + dt;
291 }
292 }
293 else
294 tnext = t + dt;
295 return dt;
296}
297
299{
300 Events = malloc (sizeof (Event));
301 Events[0].last = 1;
302 _attribute = calloc (datasize/sizeof(real), sizeof (_Attributes));
303 int n = datasize/sizeof(real);
304 all = (scalar *) malloc (sizeof (scalar)*(n + 1));
305 baseblock = (scalar *) malloc (sizeof (scalar)*(n + 1));
306 for (int i = 0; i < n; i++)
307 baseblock[i].i = all[i].i = i;
308 baseblock[n].i = all[n].i = -1;
309#if _CADNA
310 cadna_init (-1);
311#endif
312#if _MPI
313 mpi_init();
314#elif MTRACE == 1
315 char * etrace = getenv ("MTRACE");
316 pmtrace.fp = fopen (etrace ? etrace : "mtrace", "w");
317 pmtrace.fname = systrdup (etrace ? etrace : "mtrace");
318#endif
319}
event init(i=0)
User initialisation happens here.
double real
Definition cartesian.h:6
int x
Definition common.h:76
scalar * all
Definition common.h:342
static _Attributes * _attribute
Definition common.h:165
#define HUGE
Definition common.h:6
scalar * baseblock
Definition common.h:343
size_t datasize
Definition common.h:132
#define qcalloc(size, type)
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line calloc(n, s) @ define prealloc(p
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define file
Definition config.h:120
#define assert(a)
Definition config.h:107
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line line realloc(p, s) @ define pfree(p
else return n
Definition curvature.h:101
double dt
scalar s
Definition embed-tree.h:56
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
scalar int i
Definition embed.h:74
static int line
Definition errors.c:754
static double TEND_EVENT
Definition events.h:34
double dtnext(double dt)
Definition events.h:276
static int END_EVENT
Definition events.h:33
void init_solver()
Definition events.h:298
static void event_error(Event *ev, const char *s)
Definition events.h:37
void init_events(void)
@ event_alive
Definition events.h:107
@ event_stop
Definition events.h:107
@ event_done
Definition events.h:107
#define COND
Definition events.h:30
static void end_event_do(bool action)
Definition events.h:209
double t
Definition events.h:24
struct _Event Event
Definition events.h:3
static Event * Events
Definition events.h:21
static bool overload_event()
The interpreter overloads the function below to control (i.e.
Definition events.h:164
int inext
Definition events.h:23
int iter
Definition events.h:23
#define INIT
Definition events.h:29
double tnext
Definition events.h:24
static double TEPS
Definition events.h:35
static int event_cond(Event *ev, int i, double t)
Definition events.h:142
int(* Expr)(int *, double *, Event *)
Definition events.h:4
static int event_finished(Event *ev)
Definition events.h:109
static void init_event(Event *ev)
Definition events.h:43
static void _init_solver(void)
static int event_do(Event *ev, bool action)
Definition events.h:166
#define INC
Definition events.h:31
void event(const char *name)
Definition events.h:264
void event_register(Event event)
Definition events.h:115
static int
Definition include.c:978
FILE * fp
Definition mtrace.h:7
struct @9 pmtrace
int events
Definition qcc.c:60
Definition events.h:6
Event * next
Definition events.h:18
int last
Definition events.h:7
double t
Definition events.h:15
Expr expr[3]
Definition events.h:9
int nexpr
Definition events.h:7
double * arrayt
Definition events.h:11
int * arrayi
Definition events.h:10
int i
Definition events.h:16
int line
Definition events.h:13
char * name
Definition events.h:14
int a
Definition events.h:16
char * file
Definition events.h:12
int(* action)(const int, const double, Event *)
Definition events.h:8
void * data
Definition events.h:17
int i
Definition common.h:44