1 /*============================================================================
2 * Lagrangian module postprocessing
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 * Standard C library headers
31 *----------------------------------------------------------------------------*/
32
33 #include <stddef.h>
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <math.h>
38 #include <assert.h>
39
40 /*----------------------------------------------------------------------------
41 * Local headers
42 *----------------------------------------------------------------------------*/
43
44 #include "bft_mem.h"
45 #include "bft_printf.h"
46
47 #include "cs_base.h"
48 #include "cs_mesh_location.h"
49
50 #include "cs_parameters.h"
51 #include "cs_time_step.h"
52 #include "cs_parall.h"
53 #include "cs_post.h"
54
55 #include "cs_lagr.h"
56 #include "cs_lagr_particle.h"
57 #include "cs_lagr_stat.h"
58
59 /*----------------------------------------------------------------------------
60 * Header for the current file
61 *----------------------------------------------------------------------------*/
62
63 #include "cs_lagr_post.h"
64
65 /*----------------------------------------------------------------------------*/
66
67 BEGIN_C_DECLS
68
69 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
70
71 /*============================================================================
72 * Local types and structures
73 *============================================================================*/
74
75 /* Structure associated with postprocessing options */
76 /*--------------------------------------------------*/
77
78 typedef struct {
79
80 /*! \anchor particle_attr
81 flag for activation of output for each possible particle attribute:
82 0: not active
83 1: active
84 > 1: for atributes with multiple components, number of components
85 postprocessed as separate scalars */
86 int attr_output[CS_LAGR_N_ATTRIBUTES];
87
88 } cs_lagr_post_options_t;
89
90 /*============================================================================
91 * Static global variables
92 *============================================================================*/
93
94 static bool _lagr_post_options_is_set = false;
95
96 /* Postprocessing options structure and associated pointer */
97
98 static cs_lagr_post_options_t _lagr_post_options
99 = {.attr_output[0] = -1};
100
101 const cs_lagr_post_options_t *cs_glob_lagr_post_options = &_lagr_post_options;
102
103 /*=============================================================================
104 * Private function definitions
105 *============================================================================*/
106
107 /*----------------------------------------------------------------------------
108 * Define which Lagragian variables should be postprocessed
109 *----------------------------------------------------------------------------*/
110
111 static void
_activate_particle_output(void)112 _activate_particle_output(void)
113 {
114 /* No output if nothing initialized by now */
115
116 if (_lagr_post_options.attr_output[0] == -1) {
117 for (cs_lagr_attribute_t i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
118 _lagr_post_options.attr_output[i] = 0;
119 }
120 }
121
122 else {
123 for (cs_lagr_attribute_t i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
124 if (_lagr_post_options.attr_output[i]) {
125 int count = 0;
126 cs_lagr_get_attr_info(cs_glob_lagr_particle_set,
127 0,
128 i,
129 NULL,
130 NULL,
131 NULL,
132 NULL,
133 &count);
134
135 if (count == 3) {
136 switch(i) {
137 case CS_LAGR_COORDS:
138 case CS_LAGR_VELOCITY:
139 case CS_LAGR_VELOCITY_SEEN:
140 case CS_LAGR_PRED_VELOCITY:
141 case CS_LAGR_PRED_VELOCITY_SEEN:
142 case CS_LAGR_ORIENTATION:
143 case CS_LAGR_RADII:
144 case CS_LAGR_ANGULAR_VEL:
145 count = 1;
146 break;
147 default:
148 break;
149 }
150 }
151
152 _lagr_post_options.attr_output[i] = count;
153 }
154 }
155 }
156 }
157
158 /*----------------------------------------------------------------------------
159 * Default additional particle output of mesh and time-dependent variables
160 * for the call to pstvar / cs_post_write_vars.
161 *
162 * Note: if the input pointer is non-NULL, it must point to valid data
163 * when the output function is called, so either:
164 * - that value or structure should not be temporary (i.e. local);
165 * - post-processing output must be ensured using cs_post_write_var()
166 * or similar before the data pointed to goes out of scope.
167 *
168 * parameters:
169 * input <-> pointer to optional (untyped) value or structure;
170 * here, we should point to _lagr_post_options.
171 * mesh_id <-- id of the output mesh for the current call
172 * cat_id <-- category id of the output mesh for the current call
173 * ts <-- time step status structure
174 *----------------------------------------------------------------------------*/
175
176 static void
_write_particle_vars(cs_lagr_post_options_t * options,int mesh_id,const cs_time_step_t * ts)177 _write_particle_vars(cs_lagr_post_options_t *options,
178 int mesh_id,
179 const cs_time_step_t *ts)
180 {
181 cs_lagr_attribute_t attr_id;
182
183 char var_name[64];
184 int component_id;
185 char var_name_component[96];
186
187 for (attr_id = 0; attr_id < CS_LAGR_N_ATTRIBUTES; attr_id++) {
188
189 if (options->attr_output[attr_id] > 0) {
190
191 /* build name */
192
193 snprintf(var_name,
194 63,
195 "particle_%s",
196 cs_lagr_attribute_name[attr_id]);
197 var_name[63] = '\0';
198
199 /* Output values */
200
201 if (options->attr_output[attr_id] == 1)
202 cs_post_write_particle_values(mesh_id,
203 CS_POST_WRITER_ALL_ASSOCIATED,
204 attr_id,
205 var_name,
206 -1,
207 ts);
208 else {
209 /* Create one output per component */
210 for (component_id = 0;
211 component_id < options->attr_output[attr_id];
212 component_id++) {
213 snprintf(var_name_component,
214 95,
215 "%s_layer_%2.2i",
216 var_name,
217 component_id+1);
218 var_name_component[95] = '\0';
219 cs_post_write_particle_values(mesh_id,
220 CS_POST_WRITER_ALL_ASSOCIATED,
221 attr_id,
222 var_name_component,
223 component_id,
224 ts);
225 }
226 }
227 }
228
229 }
230 }
231
232 /*----------------------------------------------------------------------------
233 * Function for additional postprocessing of Lagrangian data.
234 *
235 * This function should match the prototype of a
236 * (cs_post_time_mesh_dep_output_t) function, and be registered using
237 * cs_post_add_time_mesh_dep_output().
238 *
239 * parameters:
240 * input <-> pointer to optional (untyped) value or structure.
241 * mesh_id <-- id of the output mesh for the current call
242 * cat_id <-- category id of the output mesh for the current call
243 * ent_flag <-- indicate global presence of cells (ent_flag[0]), interior
244 * faces (ent_flag[1]), boundary faces (ent_flag[2]),
245 * particles (ent_flag[3]) or probes (ent_flag[4])
246 * n_cells <-- local number of cells of post_mesh
247 * n_i_faces <-- local number of interior faces of post_mesh
248 * n_b_faces <-- local number of boundary faces of post_mesh
249 * cell_ids <-- list of cells (0 to n-1) of post-processing mesh
250 * i_face_ids <-- list of interior faces (0 to n-1) of post-processing mesh
251 * b_face_ids <-- list of boundary faces (0 to n-1) of post-processing mesh
252 * ts <-- time step status structure, or NULL
253 *----------------------------------------------------------------------------*/
254
255 static void
_cs_lagr_post(void * input,int mesh_id,int cat_id,int ent_flag[5],cs_lnum_t n_cells,cs_lnum_t n_i_faces,cs_lnum_t n_b_faces,const cs_lnum_t cell_ids[],const cs_lnum_t i_face_ids[],const cs_lnum_t b_face_ids[],const cs_time_step_t * ts)256 _cs_lagr_post(void *input,
257 int mesh_id,
258 int cat_id,
259 int ent_flag[5],
260 cs_lnum_t n_cells,
261 cs_lnum_t n_i_faces,
262 cs_lnum_t n_b_faces,
263 const cs_lnum_t cell_ids[],
264 const cs_lnum_t i_face_ids[],
265 const cs_lnum_t b_face_ids[],
266 const cs_time_step_t *ts)
267 {
268 CS_UNUSED(ent_flag);
269 CS_UNUSED(n_cells);
270 CS_UNUSED(n_i_faces);
271 CS_UNUSED(cell_ids);
272 CS_UNUSED(i_face_ids);
273
274 /* Specific handling for particle meshes */
275
276 if (cat_id == -3) {
277 _write_particle_vars(input, mesh_id, ts);
278 return;
279 }
280
281 /* Boundary statistics */
282 /*---------------------*/
283
284 else if (cat_id == -2 && cs_glob_lagr_time_scheme->iilagr > 0) {
285
286 cs_lnum_t nfabor = cs_glob_mesh->n_b_faces;
287
288 const cs_lagr_boundary_interactions_t
289 *lagr_b = cs_glob_lagr_boundary_interactions;
290
291 cs_real_t threshold = cs_glob_lagr_stat_options->threshold;
292
293 cs_real_t *val;
294 BFT_MALLOC(val, nfabor, cs_real_t);
295
296 for (int irf = 0; irf < cs_glob_lagr_dim->n_boundary_stats; irf++) {
297
298 const char *var_name = lagr_b->nombrd[irf];
299
300 const cs_real_t *_b_stats = bound_stat + nfabor*irf;
301
302 const cs_real_t *_f_count = bound_stat + nfabor*lagr_b->inbr;
303
304 for (cs_lnum_t i = 0; i < n_b_faces; i++) {
305 cs_lnum_t f_id = b_face_ids[i];
306 if (_f_count[f_id] > threshold)
307 val[i] = _b_stats[f_id];
308 else
309 val[i] = 0.;
310 }
311
312 cs_post_write_var(mesh_id,
313 CS_POST_WRITER_ALL_ASSOCIATED,
314 var_name,
315 1, /* var_dim */
316 true, /* interlace */
317 false, /* use_parent */
318 CS_POST_TYPE_cs_real_t,
319 NULL,
320 NULL,
321 val,
322 cs_glob_time_step);
323
324 }
325
326 BFT_FREE(val);
327
328 }
329 }
330
331 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
332
333 /*============================================================================
334 * Public function definitions
335 *============================================================================*/
336
337 /*----------------------------------------------------------------------------*/
338 /*!
339 * \brief Initialize Lagrangian postprocessing.
340 */
341 /*----------------------------------------------------------------------------*/
342
343 void
cs_lagr_post_init(void)344 cs_lagr_post_init(void)
345 {
346 _activate_particle_output();
347
348 cs_post_add_time_mesh_dep_output(_cs_lagr_post, &_lagr_post_options);
349 _lagr_post_options_is_set = true;
350 }
351
352 /*----------------------------------------------------------------------------*/
353 /*!
354 * \brief Activate or deactive postprocessing for a given particle attribute.
355 *
356 * \param[in] attr_id associated attribute id
357 *
358 * \return true if output of given attribute is active, false otherwise
359 */
360 /*----------------------------------------------------------------------------*/
361
362 bool
cs_lagr_post_get_attr(cs_lagr_attribute_t attr_id)363 cs_lagr_post_get_attr(cs_lagr_attribute_t attr_id)
364 {
365 /* Initialize if not done yet */
366
367 if (_lagr_post_options.attr_output[0] == -1) {
368 for (cs_lagr_attribute_t i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
369 _lagr_post_options.attr_output[i] = 0;
370 }
371 }
372
373 bool retval = false;
374 if (_lagr_post_options.attr_output[attr_id] > 0)
375 retval = true;
376
377 return retval;
378 }
379
380 /*----------------------------------------------------------------------------*/
381 /*!
382 * \brief Activate or deactive postprocessing for a given particle attribute.
383 *
384 * \param[in] attr_id associated attribute id
385 * \param[in] active true if postprocessing is required, false otherwise
386 */
387 /*----------------------------------------------------------------------------*/
388
389 void
cs_lagr_post_set_attr(cs_lagr_attribute_t attr_id,bool active)390 cs_lagr_post_set_attr(cs_lagr_attribute_t attr_id,
391 bool active)
392 {
393 if (_lagr_post_options_is_set)
394 bft_error(__FILE__, __LINE__, 0,
395 _("%s should not be called after %s."),
396 __func__, "cs_lagr_post_init");
397
398 /* Initialize if not done yet */
399
400 if (_lagr_post_options.attr_output[0] == -1) {
401 for (cs_lagr_attribute_t i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
402 _lagr_post_options.attr_output[i] = 0;
403 }
404 }
405
406 cs_lagr_particle_attr_in_range(attr_id);
407
408 if (active == false)
409 _lagr_post_options.attr_output[attr_id] = 0;
410 else
411 _lagr_post_options.attr_output[attr_id] = 1;
412 }
413
414 /*----------------------------------------------------------------------------*/
415
416 END_C_DECLS
417