1 /*============================================================================
2 * Time dependency control for variables or properties.
3 *============================================================================*/
4
5 /*
6 This file is part of Code_Saturne, a general-purpose CFD tool.
7
8 Copyright (C) 1998-2021 EDF S.A.
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
13 version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22 Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25 /*----------------------------------------------------------------------------*/
26
27 #include "cs_defs.h"
28
29 /*----------------------------------------------------------------------------*/
30
31 /*----------------------------------------------------------------------------
32 * Standard C library headers
33 *----------------------------------------------------------------------------*/
34
35 #include <assert.h>
36 #include <math.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 /*----------------------------------------------------------------------------
43 * Local headers
44 *----------------------------------------------------------------------------*/
45
46 #include "bft_mem.h"
47 #include "bft_error.h"
48 #include "bft_printf.h"
49
50 #include "cs_log.h"
51 #include "cs_map.h"
52
53 /*----------------------------------------------------------------------------
54 * Header for the current file
55 *----------------------------------------------------------------------------*/
56
57 #include "cs_time_control.h"
58
59 /*----------------------------------------------------------------------------*/
60
61 BEGIN_C_DECLS
62
63 /*=============================================================================
64 * Additional doxygen documentation
65 *============================================================================*/
66
67 /*!
68 \file cs_time_control.c
69 Time dependency control for variables or properties.
70 */
71
72 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
73
74 /*=============================================================================
75 * Macro definitions
76 *============================================================================*/
77
78 /*============================================================================
79 * Type definitions
80 *============================================================================*/
81
82 /*============================================================================
83 * Static global variables
84 *============================================================================*/
85
86 /*============================================================================
87 * Global variables
88 *============================================================================*/
89
90 static const cs_time_control_t cs_time_control_default
91 = {
92 .type = CS_TIME_CONTROL_TIME_STEP,
93 .at_start = false,
94 .at_end = false,
95 .start_nt = -1,
96 .end_nt = -1,
97 .interval_nt = 1,
98 .control_func = NULL,
99 .control_input = NULL,
100 .current_state = false,
101 .current_time_step = -1,
102 .last_nt = -2,
103 .last_t = -HUGE_VAL
104 };
105
106 /*============================================================================
107 * Private function definitions
108 *============================================================================*/
109
110 /*----------------------------------------------------------------------------
111 *!
112 * \brief Base initialization for time control.
113 *
114 * \param[in] tc pointer to time control structure.
115 * \param[in] at_start always active at start ?
116 * \param[in] at_start always active at end ?
117 */
118 /*----------------------------------------------------------------------------*/
119
120 static void
_time_control_init_base(cs_time_control_t * tc,bool at_start,bool at_end)121 _time_control_init_base(cs_time_control_t *tc,
122 bool at_start,
123 bool at_end)
124 {
125 memset(tc, 0, sizeof(cs_time_control_t));
126
127 *tc = cs_time_control_default;
128
129 tc->at_start = at_start;
130 tc->at_end = at_end;
131 }
132
133 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
134
135 /*=============================================================================
136 * Public function definitions
137 *============================================================================*/
138
139 /*----------------------------------------------------------------------------
140 *!
141 * \brief Indicate if a time control is active or not at the given time.
142 *
143 * If the time control or time step argument is NULL, true is returned.
144 *
145 * \param[in] tc time control structure
146 * \param[in] ts time step structure
147 *
148 * \return true if active, false if inactive
149 */
150 /*----------------------------------------------------------------------------*/
151
152 bool
cs_time_control_is_active(cs_time_control_t * tc,const cs_time_step_t * ts)153 cs_time_control_is_active(cs_time_control_t *tc,
154 const cs_time_step_t *ts)
155 {
156 bool retval = false;
157
158 if (tc == NULL || ts == NULL)
159 retval = true;
160
161 else {
162 if (tc->current_time_step == ts->nt_cur)
163 retval = tc->current_state;
164
165 else {
166 switch (tc->type) {
167 case CS_TIME_CONTROL_TIME_STEP:
168 if ( tc->interval_nt > 0
169 && ts->nt_cur > ts->nt_prev
170 && ts->nt_cur % (tc->interval_nt) == 0)
171 retval = true;
172 if (tc->start_nt > ts->nt_cur)
173 retval = false;
174 if (tc->end_nt >= 0 && tc->end_nt < ts->nt_cur)
175 retval = false;
176 break;
177
178 case CS_TIME_CONTROL_TIME:
179 {
180 double delta_t = ts->t_cur - tc->last_t;
181 if ( delta_t >= tc->interval_t*(1-1e-6)
182 && tc->interval_t > 0)
183 retval = true;
184 if (tc->start_t > ts->t_cur)
185 retval = false;
186 if (tc->end_t >= 0 && tc->end_t < ts->nt_cur)
187 retval = false;
188 }
189 break;
190
191 case CS_TIME_CONTROL_FUNCTION:
192 retval = tc->control_func(ts, tc->control_input);
193 }
194
195 }
196
197 if (ts->nt_cur == ts->nt_prev && tc->at_start)
198 retval = true;
199 if (ts->nt_cur == ts->nt_max && tc->at_end)
200 retval = true;
201
202 }
203
204 if (tc->current_time_step < ts->nt_cur) {
205 tc->current_time_step = ts->nt_cur;
206 tc->current_state = retval;
207 if (retval) {
208 tc->last_nt = ts->nt_cur;
209 tc->last_t = ts->t_cur;
210 }
211 }
212
213 return retval;
214 }
215
216 /*----------------------------------------------------------------------------
217 *!
218 * \brief Simple time control initialization based on time step options.
219 *
220 * \param[in] tc pointer to time control structure.
221 * \param[in] nt_start start time step (or < 0 for unlimited)
222 * \param[in] nt_end end time step (or < 0 for unlimited)
223 * \param[in] at_start always active at start ?
224 * \param[in] at_start always active at end ?
225 */
226 /*----------------------------------------------------------------------------*/
227
228 void
cs_time_control_init_by_time_step(cs_time_control_t * tc,int nt_start,int nt_end,int nt_interval,bool at_start,bool at_end)229 cs_time_control_init_by_time_step(cs_time_control_t *tc,
230 int nt_start,
231 int nt_end,
232 int nt_interval,
233 bool at_start,
234 bool at_end)
235 {
236 _time_control_init_base(tc, at_start, at_end);
237
238 tc->type = CS_TIME_CONTROL_TIME_STEP;
239
240 if (nt_start < 0)
241 nt_start = -1;
242 if (nt_end < 0)
243 nt_end = -1;
244 if (nt_interval < 1)
245 nt_interval = -1;
246
247 tc->start_nt = nt_start;
248 tc->end_nt = nt_end;
249 tc->interval_nt = nt_interval;
250 }
251
252 /*----------------------------------------------------------------------------
253 *!
254 * \brief Simple time control initialization based on physical time options.
255 *
256 * \param[in] tc pointer to time control structure.
257 * \param[in] t_start start time (or < 0 for unlimited)
258 * \param[in] t_end end time (or < 0 for unlimited)
259 * \param[in] at_start always active at start ?
260 * \param[in] at_start always active at end ?
261 */
262 /*----------------------------------------------------------------------------*/
263
264 void
cs_time_control_init_by_time(cs_time_control_t * tc,double t_start,double t_end,double t_interval,bool at_start,bool at_end)265 cs_time_control_init_by_time(cs_time_control_t *tc,
266 double t_start,
267 double t_end,
268 double t_interval,
269 bool at_start,
270 bool at_end)
271 {
272 _time_control_init_base(tc, at_start, at_end);
273
274 tc->type = CS_TIME_CONTROL_TIME;
275
276 if (t_start < 0)
277 t_start = -1;
278 if (t_end < 0)
279 t_end = -1;
280 if (t_interval <= 0)
281 t_interval = 0;
282
283 tc->start_t = t_start;
284 tc->end_t = t_end;
285 tc->interval_t = t_interval;
286 }
287
288 /*----------------------------------------------------------------------------
289 *!
290 * \brief Simple time control initialization based on external function.
291 *
292 * \remark: if the input pointer is non-NULL, it must point to valid data
293 * when the control function is called, so that value or structure
294 * should not be temporary (i.e. local);
295 *
296 * \param[in] tc pointer to time control structure.
297 * \param[in] control_func pointer to time control funcction.
298 * \param[in] control_input pointer to optional (untyped) value or structure,
299 * or NULL.
300 * \param[in] at_start always active at start ?
301 * \param[in] at_start always active at end ?
302 */
303 /*----------------------------------------------------------------------------*/
304
305 void
cs_time_control_init_by_func(cs_time_control_t * tc,cs_time_control_func_t * control_func,void * control_input,bool at_start,bool at_end)306 cs_time_control_init_by_func(cs_time_control_t *tc,
307 cs_time_control_func_t *control_func,
308 void *control_input,
309 bool at_start,
310 bool at_end)
311 {
312 _time_control_init_base(tc, at_start, at_end);
313
314 tc->type = CS_TIME_CONTROL_FUNCTION;
315
316 tc->control_func = control_func;
317 tc->control_input = control_input;
318 }
319
320 /*----------------------------------------------------------------------------
321 *!
322 * \brief Get text description of time control configuration.
323 *
324 * If the time control or time step argument is NULL, true is returned.
325 *
326 * \param[in] tc time control structure
327 * \param[out] desc description string
328 * \param[in] desc_size description string maximum size
329 *
330 * \return true if active, false if inactive
331 */
332 /*----------------------------------------------------------------------------*/
333
334 void
cs_time_control_get_description(const cs_time_control_t * tc,char * desc,size_t desc_size)335 cs_time_control_get_description(const cs_time_control_t *tc,
336 char *desc,
337 size_t desc_size)
338 {
339 char b[256] = ""; /* should be more than enough */
340 char *s = b;
341
342 if (tc == NULL) {
343 snprintf(s, 256, "always active");
344 }
345
346 else {
347
348 switch (tc->type) {
349 case CS_TIME_CONTROL_TIME_STEP:
350 if (tc->interval_nt == 1)
351 s += sprintf(s, _(", every time step"));
352 else if (tc->interval_nt > 1)
353 s += sprintf(s, _(", every %d time steps"), tc->interval_nt);
354 if (tc->start_nt > 0)
355 s += sprintf(s, _(", start %d"), tc->start_nt);
356 if (tc->end_nt > 0)
357 s += sprintf(s, _(", end %d"), tc->end_nt);
358 break;
359
360 case CS_TIME_CONTROL_TIME:
361 if (tc->interval_t >= 0) {
362 if (tc->interval_t <= 0)
363 s += sprintf(s, _(", every time step"));
364 else
365 s += sprintf(s, _(", every %g s"), tc->interval_t);
366 }
367 if (tc->start_t > 0)
368 s += sprintf(s, _(", start %g s"), tc->start_t);
369 if (tc->end_nt > 0)
370 s += sprintf(s, _(", end %g s"), tc->end_t);
371 break;
372
373 case CS_TIME_CONTROL_FUNCTION:
374 s += sprintf(s, _(", function-based"));
375 }
376
377 if (tc->at_start)
378 s += sprintf(s, _(", at start"));
379 if (tc->at_end)
380 s += sprintf(s, _(", at end"));
381 }
382
383 int shift = 0;
384 while (b[shift] == ' ' || b[shift] == ',')
385 shift++;
386
387 strncpy(desc, b+shift, desc_size);
388 if (desc_size > 0)
389 desc[desc_size-1] = '\0';
390 }
391
392 /*----------------------------------------------------------------------------*/
393
394 END_C_DECLS
395