1 /*============================================================================
2 * Lagrangian particle model
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 <limits.h>
34 #include <stdio.h>
35 #include <stddef.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39 #include <ctype.h>
40 #include <float.h>
41 #include <assert.h>
42
43 /*----------------------------------------------------------------------------
44 * Local headers
45 *----------------------------------------------------------------------------*/
46
47 #include "bft_printf.h"
48 #include "bft_error.h"
49 #include "bft_mem.h"
50
51 #include "fvm_periodicity.h"
52
53 #include "cs_base.h"
54 #include "cs_math.h"
55 #include "cs_order.h"
56 #include "cs_parall.h"
57 #include "cs_random.h"
58 #include "cs_timer_stats.h"
59
60 #include "cs_lagr.h"
61 #include "cs_lagr_post.h"
62 #include "cs_lagr_clogging.h"
63 #include "cs_lagr_roughness.h"
64 #include "cs_lagr_dlvo.h"
65
66 /*----------------------------------------------------------------------------
67 * Header for the current file
68 *----------------------------------------------------------------------------*/
69
70 #include "cs_lagr_particle.h"
71
72 /*----------------------------------------------------------------------------*/
73
74 BEGIN_C_DECLS
75
76 /*=============================================================================
77 * Additional doxygen documentation
78 *============================================================================*/
79
80 /*!
81 \file cs_lagr_particle.c
82 Particle structure.
83 */
84
85 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
86
87 /*=============================================================================
88 * Local Macro definitions
89 *============================================================================*/
90
91 #define N_GEOL 13
92 #define CS_LAGR_MIN_COMM_BUF_SIZE 8
93
94 /*=============================================================================
95 * Local Enumeration definitions
96 *============================================================================*/
97
98 /* keys to sort attributes by type.
99
100 rvar real values at current and previous time steps
101 ivar integer values at current and previous time steps
102 rprp real properties at current an previous time steps
103 iprp integer properties at current and previous time steps
104 rkid values are for rank ids, useful and valid only for previous
105 time steps */
106
107 typedef enum {
108 CS_LAGR_P_RVAR_TS = 1, /* CS_LAGR_P_RVAR with possible source terms */
109 CS_LAGR_P_RVAR,
110 CS_LAGR_P_IVAR,
111 CS_LAGR_P_RPRP,
112 CS_LAGR_P_IPRP,
113 CS_LAGR_P_RKID,
114 } _array_map_id_t;
115
116 /*============================================================================
117 * Local structure definitions
118 *============================================================================*/
119
120 /* Private tracking data associated to each particle */
121 /* --------------------------------------------------*/
122
123 /* This structure is a copy of the one defined in cs_lagr_tracking.c,
124 which is currently mapped to the beginning of each
125 * particle's data, and contains values which are used during the
126 * tracking algorithm only.
127 * It could be separated in the future, but this would require
128 * keeping track of a particle's local id in most functions. */
129
130 typedef struct {
131
132 cs_real_t start_coords[3]; /* starting coordinates for
133 next displacement */
134
135 cs_lnum_t last_face_num; /* last face number encountered */
136
137 int state; /* current state (actually an enum) */
138
139 } cs_lagr_tracking_info_t;
140
141 /* Particle data value */
142 /*---------------------*/
143
144 union cs_lagr_value_t {
145 cs_lnum_t l; /* v_lnum_t */
146 cs_gnum_t g; /* v_gnum_t */
147 cs_real_t f; /* v_real_t */
148 };
149
150 /*============================================================================
151 * Static global variables
152 *============================================================================*/
153
154 /* Enumerator names */
155
156 const char *cs_lagr_attribute_name[] = {
157 "state_flag",
158 "cell_id",
159 "rank_id",
160 "rebound_id",
161 "random_value",
162 "stat_weight",
163 "residence_time",
164 "mass",
165 "diameter",
166 "taup_aux",
167 "coords",
168 "velocity",
169 "velocity_seen",
170 "tr_truncate",
171 "tr_reposition",
172
173 /* Arrays for 2nd order scheme */
174 "turb_state_1",
175 "pred_velocity",
176 "pred_velocity_seen",
177 "v_gauss",
178 "br_gauss",
179
180 /* Non-spherical particles submodel additoinal parameters */
181 "shape",
182 "orientation",
183 "radii",
184 "angular_vel",
185 "euler",
186 "shape_param",
187
188 /* Deposition submodel additional parameters */
189 "yplus",
190 "interf",
191 "neighbor_face_id",
192 "marko_value",
193 "fouling_index",
194
195 "n_large_asperities",
196 "n_small_asperities",
197 "adhesion_force",
198 "adhesion_torque",
199 "displacement_norm",
200
201 "height",
202 "cluster_nb_part",
203 "depo_time",
204 "consol_height",
205
206 "temperature",
207 "fluid_temperature",
208 "cp",
209
210 "water_mass",
211 "coal_mass",
212 "coke_mass",
213 "shrinking_diameter",
214 "initial_diameter",
215 "coal_id",
216 "coal_density",
217
218 "emissivity",
219
220 "stat_class",
221
222 "agglo_class_id",
223 "agglo_fractal_dim",
224
225 "user",
226 "<none>"};
227
228 /* Global particle attributes map */
229
230 static cs_lagr_attribute_map_t *_p_attr_map = NULL;
231
232 /* Particle set reallocation parameters */
233
234 static double _reallocation_factor = 2.0;
235 static unsigned long long _n_g_max_particles = ULLONG_MAX;
236
237 /*============================================================================
238 * Global variables
239 *============================================================================*/
240
241 /* Pointer to the main particle set */
242
243 cs_lagr_particle_set_t *cs_glob_lagr_particle_set = NULL;
244
245 /*=============================================================================
246 * Private function definitions
247 *============================================================================*/
248
249 /*----------------------------------------------------------------------------*
250 * Compute new extents to ensure alignment of data
251 *
252 * returns:
253 * padded extents ensuring alignement
254 *----------------------------------------------------------------------------*/
255
256 static size_t
_align_extents(size_t size)257 _align_extents(size_t size)
258 {
259 size_t retval = size;
260
261 size_t align_size = sizeof(union cs_lagr_value_t);
262
263 size_t r = size % align_size;
264 if (r > 0)
265 retval += (align_size - r);
266
267 return retval;
268 }
269
270 /*----------------------------------------------------------------------------*
271 * Map particle attributes for a given configuration.
272 *
273 * parameters:
274 * attr_keys <-> keys to sort attributes by Fortran array and index
275 * for each attribute: array, index in array, count
276 *
277 * returns:
278 * pointer to structure mapping particle attributes
279 *----------------------------------------------------------------------------*/
280
281 static cs_lagr_attribute_map_t *
_create_attr_map(cs_lnum_t attr_keys[CS_LAGR_N_ATTRIBUTES][3])282 _create_attr_map(cs_lnum_t attr_keys[CS_LAGR_N_ATTRIBUTES][3])
283 {
284 cs_lagr_attribute_t attr;
285 cs_lnum_t *order;
286
287 cs_lagr_attribute_map_t *p_am;
288
289 BFT_MALLOC(p_am, 1, cs_lagr_attribute_map_t);
290
291 /* Start of buffer is used for private tracking state info */
292
293 p_am->lb = _align_extents(sizeof(cs_lagr_tracking_info_t));
294
295 p_am->extents = p_am->lb;
296
297 /* Currently, current and previous time values are managed */
298
299 p_am->n_time_vals = 2;
300
301 if (true) { /* Allocation requires typedef due to cast */
302
303 typedef ptrdiff_t lagr_attr_ptrdiff_t[CS_LAGR_N_ATTRIBUTES];
304 typedef int lagr_attr_int_t[CS_LAGR_N_ATTRIBUTES];
305
306 BFT_MALLOC(p_am->displ, 2, lagr_attr_ptrdiff_t);
307 BFT_MALLOC(p_am->count, 2, lagr_attr_int_t);
308
309 }
310
311 else { /* Variant:
312 to avoid issue with cast and no typdef, use lower level function */
313
314 p_am->displ = bft_mem_malloc(2, sizeof(p_am->displ[0]),
315 "p_am->displ", __FILE__, __LINE__);
316 p_am->count = bft_mem_malloc(2, sizeof(p_am->count[0]),
317 "p_am->count", __FILE__, __LINE__);
318
319 }
320
321 p_am->source_term_displ = NULL;
322
323 for (attr = 0; attr < CS_LAGR_N_ATTRIBUTES; attr++) {
324 p_am->size[attr] = 0;
325 p_am->datatype[attr] = CS_REAL_TYPE;
326 for (int time_id = 0; time_id < p_am->n_time_vals; time_id++) {
327 p_am->displ[time_id][attr] = -1;
328 p_am->count[time_id][attr] = 1;
329 }
330 }
331
332 BFT_MALLOC(order, CS_LAGR_N_ATTRIBUTES, cs_lnum_t);
333
334 cs_order_lnum_allocated_s(NULL,
335 (const cs_lnum_t *)attr_keys,
336 3,
337 order,
338 CS_LAGR_N_ATTRIBUTES);
339
340 /* Loop on available times */
341
342 for (int time_id = 0; time_id < p_am->n_time_vals; time_id++) {
343
344 int array_prev = 0;
345
346 /* Now loop on ordered attributes */
347
348 for (int i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
349
350 cs_datatype_t datatype = CS_REAL_TYPE;
351 int min_time_id = 0;
352 int max_time_id = 0;
353
354 attr = order[i];
355
356 if (time_id == 0)
357 p_am->datatype[attr] = CS_DATATYPE_NULL;
358 p_am->displ[time_id][attr] =-1;
359 p_am->count[time_id][attr] = 0;
360
361 if (attr_keys[attr][0] < 1) continue;
362
363 /*
364 ieptp/ieptpa integer values at current and previous time steps
365 pepa real values at current time step
366 ipepa integer values at current time step */
367
368 /* Behavior depending on array */
369
370 switch(attr_keys[attr][0]) {
371 case CS_LAGR_P_RVAR_TS:
372 case CS_LAGR_P_RVAR:
373 max_time_id = 1;
374 break;
375 case CS_LAGR_P_IVAR:
376 datatype = CS_LNUM_TYPE;
377 max_time_id = 1;
378 break;
379 case CS_LAGR_P_RPRP:
380 break;
381 case CS_LAGR_P_IPRP:
382 datatype = CS_LNUM_TYPE;
383 break;
384 case CS_LAGR_P_RKID:
385 datatype = CS_LNUM_TYPE;
386 min_time_id = 1;
387 max_time_id = 1;
388 break;
389 default:
390 continue;
391 }
392
393 if (time_id < min_time_id || time_id > max_time_id)
394 continue;
395
396 /* Add padding for alignment when changing array */
397
398 if (attr_keys[attr][0] != array_prev) {
399 p_am->extents = _align_extents(p_am->extents);
400 array_prev = attr_keys[attr][0];
401 }
402
403 /* Add attribute to map */
404
405 p_am->displ[time_id][attr] = p_am->extents;
406 p_am->count[time_id][attr] = attr_keys[attr][2];
407 if (time_id == min_time_id) {
408 p_am->datatype[attr] = datatype;
409 p_am->size[attr] = p_am->count[time_id][attr]
410 * cs_datatype_size[p_am->datatype[attr]];
411 }
412
413 p_am->extents += p_am->size[attr];
414
415 }
416
417 p_am->extents = _align_extents(p_am->extents);
418
419 }
420
421 /* Add source terms for 2nd order */
422
423 if (cs_glob_lagr_time_scheme->t_order > 1) {
424
425 BFT_MALLOC(p_am->source_term_displ, CS_LAGR_N_ATTRIBUTES, ptrdiff_t);
426
427 /* loop again on ordered attributes */
428
429 for (int i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
430
431 attr = order[i];
432
433 /* Add attribute to map if in CS_LAGR_P_RVARS array */
434
435 if ( attr_keys[attr][0] == CS_LAGR_P_RVAR_TS
436 && p_am->count[0][attr] > 0) {
437 p_am->source_term_displ[attr] = p_am->extents;
438 p_am->extents += p_am->size[attr];
439 }
440 else
441 p_am->source_term_displ[attr] = -1;
442
443 }
444
445 p_am->extents = _align_extents(p_am->extents);
446
447 }
448
449 BFT_FREE(order);
450
451 return p_am;
452 }
453
454 /*----------------------------------------------------------------------------*
455 * Free particle attributes for a given configuration.
456 *----------------------------------------------------------------------------*/
457
458 static void
_destroy_attr_map(cs_lagr_attribute_map_t ** p_am)459 _destroy_attr_map(cs_lagr_attribute_map_t **p_am)
460 {
461 if (*p_am != NULL) {
462 cs_lagr_attribute_map_t *_p_am = *p_am;
463
464 BFT_FREE(_p_am->source_term_displ);
465
466 BFT_FREE(_p_am->displ);
467 BFT_FREE(_p_am->count);
468
469 BFT_FREE(*p_am);
470 }
471 }
472
473 /*----------------------------------------------------------------------------
474 * Allocate a cs_lagr_particle_set_t structure.
475 *
476 * parameters:
477 * n_particles_max <-- local max. number of particles
478 * p_am <-- particle attributes map
479 *
480 * returns:
481 * a new allocated cs_lagr_particle_set_t structure
482 *----------------------------------------------------------------------------*/
483
484 static cs_lagr_particle_set_t *
_create_particle_set(cs_lnum_t n_particles_max,const cs_lagr_attribute_map_t * p_am)485 _create_particle_set(cs_lnum_t n_particles_max,
486 const cs_lagr_attribute_map_t *p_am)
487
488 {
489 cs_lagr_particle_set_t *new_set = NULL;
490
491 if (n_particles_max == 0)
492 return NULL;
493
494 BFT_MALLOC(new_set, 1, cs_lagr_particle_set_t);
495
496 BFT_MALLOC(new_set->p_buffer, n_particles_max * p_am->extents, unsigned char);
497
498 new_set->n_particles = 0;
499 new_set->n_part_new = 0;
500 new_set->n_part_merged = 0;
501 new_set->n_part_out = 0;
502 new_set->n_part_dep = 0;
503 new_set->n_part_fou = 0;
504 new_set->n_part_resusp = 0;
505 new_set->n_failed_part = 0;
506
507 new_set->weight = 0.0;
508 new_set->weight_new = 0.0;
509 new_set->weight_merged = 0.0;
510 new_set->weight_out = 0.0;
511 new_set->weight_dep = 0.0;
512 new_set->weight_fou = 0.0;
513 new_set->weight_resusp = 0.0;
514 new_set->weight_failed = 0.0;
515
516 new_set->n_particles_max = n_particles_max;
517
518 assert(n_particles_max >= 1);
519
520 new_set->p_am = p_am;
521
522 return new_set;
523 }
524
525 /*----------------------------------------------------------------------------
526 * Destroy a cs_lagr_particle_set_t structure.
527 *
528 * parameters:
529 * particle_set <-> a cs_lagr_particle_set_t structure
530 *----------------------------------------------------------------------------*/
531
532 static void
_destroy_particle_set(cs_lagr_particle_set_t ** set)533 _destroy_particle_set(cs_lagr_particle_set_t **set)
534 {
535 if (set != NULL) {
536
537 cs_lagr_particle_set_t *_set = *set;
538 BFT_FREE(_set->p_buffer);
539
540 BFT_FREE(*set);
541 }
542 }
543
544 /*----------------------------------------------------------------------------
545 * Dump a particle structure
546 *
547 * parameter
548 * particles <-- cs_lagr_particle_set_t structure to dump
549 * particle_id <-- id of particle to dump
550 *----------------------------------------------------------------------------*/
551
552 static void
_dump_particle(const cs_lagr_particle_set_t * particles,cs_lnum_t particle_id)553 _dump_particle(const cs_lagr_particle_set_t *particles,
554 cs_lnum_t particle_id)
555 {
556 const unsigned char *p = particles->p_buffer
557 + particles->p_am->extents*particle_id;
558 const cs_lagr_attribute_map_t *am = particles->p_am;
559
560 bft_printf(" particle: %lu\n", (unsigned long)particle_id);
561
562 for (int time_id = 0; time_id < particles->p_am->n_time_vals; time_id++) {
563
564 if (time_id == 0)
565 bft_printf(" values at time n:\n");
566 else
567 bft_printf(" values at time: n-%d\n", time_id);
568
569 for (cs_lagr_attribute_t attr = 0;
570 attr < CS_LAGR_N_ATTRIBUTES;
571 attr++) {
572 if (am->count[time_id][attr] > 0) {
573 const char *attr_name = cs_lagr_attribute_name[attr];
574 switch (am->datatype[attr]) {
575 case CS_LNUM_TYPE:
576 {
577 const cs_lnum_t *v
578 = cs_lagr_particle_attr_n_const(p, particles->p_am, time_id, attr);
579 bft_printf(" %24s: %10ld\n", attr_name, (long)v[0]);
580 for (int i = 1; i < am->count[time_id][attr]; i++)
581 bft_printf(" %24s: %10ld\n", " ", (long)v[i]);
582 }
583 break;
584 case CS_GNUM_TYPE:
585 {
586 const cs_gnum_t *v
587 = cs_lagr_particle_attr_n_const(p, particles->p_am, time_id, attr);
588 bft_printf(" %24s: %10lu\n", attr_name, (unsigned long)v[0]);
589 for (int i = 1; i < am->count[time_id][attr]; i++)
590 bft_printf(" %24s: %10lu\n", " ", (unsigned long)v[i]);
591 }
592 break;
593 case CS_REAL_TYPE:
594 {
595 const cs_real_t *v
596 = cs_lagr_particle_attr_n_const(p, particles->p_am, time_id, attr);
597 bft_printf(" %24s: %10.3g\n", attr_name, v[0]);
598 for (int i = 1; i < am->count[time_id][attr]; i++)
599 bft_printf(" %24s: %10.3g\n", " ", v[i]);
600 }
601 break;
602 default:
603 break;
604 }
605 }
606 }
607 }
608 bft_printf("\n");
609 }
610
611 /*----------------------------------------------------------------------------
612 * Resize a cs_lagr_particle_set_t structure.
613 *
614 * parameters:
615 * particle_set <-> pointer to a cs_lagr_particle_set_t structure
616 * n_particles_max_min <-- minimum local max. number of particles
617 *
618 * returns:
619 * 1 if resizing was required, 0 otherwise
620 *----------------------------------------------------------------------------*/
621
622 static int
_particle_set_resize(cs_lagr_particle_set_t * particle_set,const cs_lnum_t n_particles_max_min)623 _particle_set_resize(cs_lagr_particle_set_t *particle_set,
624 const cs_lnum_t n_particles_max_min)
625 {
626 int retval = 0;
627
628 assert(n_particles_max_min >= 0);
629
630 if (particle_set->n_particles_max < n_particles_max_min) {
631
632 if (particle_set->n_particles_max == 0)
633 particle_set->n_particles_max = 1;
634
635 while (particle_set->n_particles_max < n_particles_max_min)
636 particle_set->n_particles_max *= _reallocation_factor;
637
638 BFT_REALLOC(particle_set->p_buffer,
639 particle_set->n_particles_max * particle_set->p_am->extents,
640 unsigned char);
641
642 retval = 1;
643 }
644
645 return retval;
646 }
647
648 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
649
650 /*============================================================================
651 * Public function definitions
652 *============================================================================*/
653
654 /*----------------------------------------------------------------------------*/
655 /*!
656 * \brief Define particle map based on defined options.
657 */
658 /*----------------------------------------------------------------------------*/
659
660 void
cs_lagr_particle_attr_initialize(void)661 cs_lagr_particle_attr_initialize(void)
662 {
663 cs_lagr_model_t *lagr_model = cs_glob_lagr_model;
664 cs_lagr_time_scheme_t *lagr_time_scheme = cs_glob_lagr_time_scheme;
665 const cs_lagr_extra_module_t *extra = cs_glob_lagr_extra_module;
666
667 int i;
668
669 int loc_count = 0;
670
671 int pepa_loc_add = 1000; /* should be abore any j* pointer if used */
672
673 cs_lnum_t attr_keys[CS_LAGR_N_ATTRIBUTES][3];
674
675 /* Initialize global parameter relative to the lagrangian module */
676
677 /* cs_glob_lagr_brownian->lamvbr = *lamvbr; */
678
679 if (lagr_model->physical_model == CS_LAGR_PHYS_COAL)
680 lagr_model->n_temperature_layers = cs_glob_lagr_const_dim->nlayer;
681 else
682 lagr_model->n_temperature_layers = 1;
683
684 /* Set indexes */
685
686 for (i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
687 attr_keys[i][0] = CS_LAGR_P_RVAR; /* default */
688 attr_keys[i][1] = 0;
689 attr_keys[i][2] = 0;
690 }
691
692 /* Special case:
693 cell id is also needed in for previous time step.
694 */
695
696 attr_keys[CS_LAGR_CELL_ID][0] = CS_LAGR_P_IVAR;
697 attr_keys[CS_LAGR_CELL_ID][1] = ++loc_count;
698
699 attr_keys[CS_LAGR_RANK_ID][0] = CS_LAGR_P_RKID;
700 attr_keys[CS_LAGR_RANK_ID][1] = 1;
701
702 /* Other attributes */
703
704 attr_keys[CS_LAGR_P_FLAG][0] = CS_LAGR_P_IPRP;
705 attr_keys[CS_LAGR_P_FLAG][1] = ++loc_count;
706
707 attr_keys[CS_LAGR_REBOUND_ID][0] = CS_LAGR_P_IPRP;
708 attr_keys[CS_LAGR_REBOUND_ID][1] = ++loc_count;
709
710 attr_keys[CS_LAGR_RANDOM_VALUE][0] = CS_LAGR_P_RPRP;
711 attr_keys[CS_LAGR_RANDOM_VALUE][1] = ++loc_count;
712
713 attr_keys[CS_LAGR_STAT_WEIGHT][0] = CS_LAGR_P_RPRP;
714 attr_keys[CS_LAGR_STAT_WEIGHT][1] = ++loc_count;
715
716 attr_keys[CS_LAGR_RESIDENCE_TIME][0] = CS_LAGR_P_RPRP;
717 attr_keys[CS_LAGR_RESIDENCE_TIME][1] = ++loc_count;
718
719 if (lagr_model->clogging == 1)
720 attr_keys[CS_LAGR_HEIGHT][1] = ++loc_count;
721
722 attr_keys[CS_LAGR_MASS][0] = CS_LAGR_P_RVAR_TS;
723 attr_keys[CS_LAGR_MASS][1] = ++loc_count;
724
725 attr_keys[CS_LAGR_DIAMETER][0] = CS_LAGR_P_RVAR_TS;
726 attr_keys[CS_LAGR_DIAMETER][1] = ++loc_count;
727
728 /* Non-sphere model
729 * TODO activate only required arrays */
730 if (lagr_model->shape != CS_LAGR_SHAPE_SPHERE_MODEL) {
731 attr_keys[CS_LAGR_SHAPE][0] = CS_LAGR_P_RPRP;
732 attr_keys[CS_LAGR_SHAPE][1] = ++loc_count;
733
734 attr_keys[CS_LAGR_ORIENTATION][1] = ++loc_count;
735 attr_keys[CS_LAGR_ORIENTATION][2] = 3;
736
737 attr_keys[CS_LAGR_QUATERNION][1] = ++loc_count;
738 attr_keys[CS_LAGR_QUATERNION][2] = 4;
739
740 attr_keys[CS_LAGR_RADII][0] = CS_LAGR_P_RPRP;
741 attr_keys[CS_LAGR_RADII][1] = ++loc_count;
742 attr_keys[CS_LAGR_RADII][2] = 3;
743
744 attr_keys[CS_LAGR_ANGULAR_VEL][1] = ++loc_count;
745 attr_keys[CS_LAGR_ANGULAR_VEL][2] = 3;
746
747 attr_keys[CS_LAGR_EULER][1] = ++loc_count;
748 attr_keys[CS_LAGR_EULER][2] = 4;
749
750 attr_keys[CS_LAGR_SHAPE_PARAM][0] = CS_LAGR_P_RPRP;
751 attr_keys[CS_LAGR_SHAPE_PARAM][1] = ++loc_count;
752 attr_keys[CS_LAGR_SHAPE_PARAM][2] = 4;
753 }
754
755 attr_keys[CS_LAGR_COORDS][1] = ++loc_count;
756 attr_keys[CS_LAGR_COORDS][2] = 3;
757
758 attr_keys[CS_LAGR_VELOCITY][1] = ++loc_count;
759 attr_keys[CS_LAGR_VELOCITY][2] = 3;
760
761 attr_keys[CS_LAGR_VELOCITY_SEEN][1] = ++loc_count;
762 attr_keys[CS_LAGR_VELOCITY_SEEN][2] = 3;
763
764 attr_keys[CS_LAGR_TR_TRUNCATE][0] = CS_LAGR_P_RPRP;
765 attr_keys[CS_LAGR_TR_TRUNCATE][1] = ++loc_count;
766
767 attr_keys[CS_LAGR_TR_REPOSITION][0] = CS_LAGR_P_IPRP;
768 attr_keys[CS_LAGR_TR_REPOSITION][1] = ++loc_count;
769
770 if (lagr_time_scheme->t_order > 1) {
771 attr_keys[CS_LAGR_TAUP_AUX][0] = CS_LAGR_P_RPRP;
772 attr_keys[CS_LAGR_TAUP_AUX][1] = ++pepa_loc_add;
773
774 attr_keys[CS_LAGR_TURB_STATE_1][0] = CS_LAGR_P_RPRP;
775 attr_keys[CS_LAGR_TURB_STATE_1][1] = ++pepa_loc_add;
776 attr_keys[CS_LAGR_TURB_STATE_1][2] = 3;
777
778 attr_keys[CS_LAGR_PRED_VELOCITY][0] = CS_LAGR_P_RPRP;
779 attr_keys[CS_LAGR_PRED_VELOCITY][1] = ++pepa_loc_add;
780 attr_keys[CS_LAGR_PRED_VELOCITY][2] = 3;
781
782 attr_keys[CS_LAGR_PRED_VELOCITY_SEEN][0] = CS_LAGR_P_RPRP;
783 attr_keys[CS_LAGR_PRED_VELOCITY_SEEN][1] = ++pepa_loc_add;
784 attr_keys[CS_LAGR_PRED_VELOCITY_SEEN][2] = 3;
785
786 if (cs_glob_lagr_model->idistu == 1) {
787 attr_keys[CS_LAGR_V_GAUSS][0] = CS_LAGR_P_RPRP;
788 attr_keys[CS_LAGR_V_GAUSS][1] = ++pepa_loc_add;
789 attr_keys[CS_LAGR_V_GAUSS][2] = 9;
790 }
791
792 if (cs_glob_lagr_brownian->lamvbr == 1) {
793 attr_keys[CS_LAGR_BR_GAUSS][0] = CS_LAGR_P_RPRP;
794 attr_keys[CS_LAGR_BR_GAUSS][1] = ++pepa_loc_add;
795 attr_keys[CS_LAGR_BR_GAUSS][2] = 6;
796 }
797 }
798
799 if (lagr_model->deposition == 1) {
800
801 attr_keys[CS_LAGR_YPLUS][0] = CS_LAGR_P_RPRP;
802 attr_keys[CS_LAGR_YPLUS][1] = ++loc_count;
803
804 attr_keys[CS_LAGR_INTERF][0] = CS_LAGR_P_RPRP;
805 attr_keys[CS_LAGR_INTERF][1] = ++loc_count;
806
807 attr_keys[CS_LAGR_NEIGHBOR_FACE_ID][0] = CS_LAGR_P_IPRP;
808 attr_keys[CS_LAGR_NEIGHBOR_FACE_ID][1] = ++loc_count;
809
810 attr_keys[CS_LAGR_MARKO_VALUE][0] = CS_LAGR_P_IPRP;
811 attr_keys[CS_LAGR_MARKO_VALUE][1] = ++loc_count;
812
813 }
814
815 attr_keys[CS_LAGR_FOULING_INDEX][0] = CS_LAGR_P_RPRP;
816 attr_keys[CS_LAGR_FOULING_INDEX][1] = ++loc_count;
817
818 if (lagr_model->resuspension == 1) {
819
820 attr_keys[CS_LAGR_N_LARGE_ASPERITIES][0] = CS_LAGR_P_IPRP;
821 attr_keys[CS_LAGR_N_LARGE_ASPERITIES][1] = ++loc_count;
822
823 attr_keys[CS_LAGR_N_SMALL_ASPERITIES][0] = CS_LAGR_P_IPRP;
824 attr_keys[CS_LAGR_N_SMALL_ASPERITIES][1] = ++loc_count;
825
826 attr_keys[CS_LAGR_ADHESION_FORCE][0] = CS_LAGR_P_RPRP;
827 attr_keys[CS_LAGR_ADHESION_FORCE][1] = ++loc_count;
828
829 attr_keys[CS_LAGR_ADHESION_TORQUE][0] = CS_LAGR_P_RPRP;
830 attr_keys[CS_LAGR_ADHESION_TORQUE][1] = ++loc_count;
831
832 attr_keys[CS_LAGR_DISPLACEMENT_NORM][0] = CS_LAGR_P_RPRP;
833 attr_keys[CS_LAGR_DISPLACEMENT_NORM][1] = ++loc_count;
834
835 }
836
837 if (lagr_model->clogging == 1) {
838
839 attr_keys[CS_LAGR_CLUSTER_NB_PART][0] = CS_LAGR_P_RPRP;
840 attr_keys[CS_LAGR_CLUSTER_NB_PART][1] = ++loc_count;
841
842 attr_keys[CS_LAGR_DEPO_TIME][0] = CS_LAGR_P_RPRP;
843 attr_keys[CS_LAGR_DEPO_TIME][1] = ++loc_count;
844
845 attr_keys[CS_LAGR_CONSOL_HEIGHT][0] = CS_LAGR_P_RPRP;
846 attr_keys[CS_LAGR_CONSOL_HEIGHT][1] = ++loc_count;
847
848 }
849
850 if (lagr_model->physical_model == CS_LAGR_PHYS_HEAT) {
851
852 if (cs_glob_lagr_specific_physics->itpvar == 1) {
853
854 attr_keys[CS_LAGR_CP][1] = ++loc_count;
855
856 attr_keys[CS_LAGR_TEMPERATURE][0] = CS_LAGR_P_RVAR_TS;
857 attr_keys[CS_LAGR_TEMPERATURE][1] = ++loc_count;
858
859 attr_keys[CS_LAGR_FLUID_TEMPERATURE][0] = CS_LAGR_P_RVAR_TS;
860 attr_keys[CS_LAGR_FLUID_TEMPERATURE][1] = ++loc_count;
861
862 if (extra->radiative_model > 0)
863 attr_keys[CS_LAGR_EMISSIVITY][1] = ++loc_count;
864
865 }
866
867 }
868
869 if (lagr_model->physical_model == CS_LAGR_PHYS_COAL) {
870
871 attr_keys[CS_LAGR_CP][1] = ++loc_count;
872
873 attr_keys[CS_LAGR_TEMPERATURE][0] = CS_LAGR_P_RVAR_TS;
874 attr_keys[CS_LAGR_TEMPERATURE][1] = ++loc_count;
875 attr_keys[CS_LAGR_TEMPERATURE][2]
876 = lagr_model->n_temperature_layers;
877
878 attr_keys[CS_LAGR_FLUID_TEMPERATURE][0] = CS_LAGR_P_RVAR_TS;
879 attr_keys[CS_LAGR_FLUID_TEMPERATURE][1] = ++loc_count;
880
881 attr_keys[CS_LAGR_WATER_MASS][1] = ++loc_count;
882
883 attr_keys[CS_LAGR_COAL_MASS][1] = ++loc_count;
884 attr_keys[CS_LAGR_COAL_MASS][2]
885 = lagr_model->n_temperature_layers;
886
887 attr_keys[CS_LAGR_COKE_MASS][1] = ++loc_count;
888 attr_keys[CS_LAGR_COKE_MASS][2]
889 = lagr_model->n_temperature_layers;
890
891 attr_keys[CS_LAGR_SHRINKING_DIAMETER][1] = ++loc_count;
892
893 attr_keys[CS_LAGR_INITIAL_DIAMETER][0] = CS_LAGR_P_RPRP;
894 attr_keys[CS_LAGR_INITIAL_DIAMETER][1] = ++loc_count;
895
896 attr_keys[CS_LAGR_COAL_DENSITY][0] = CS_LAGR_P_RPRP;
897 attr_keys[CS_LAGR_COAL_DENSITY][1] = ++loc_count;
898 attr_keys[CS_LAGR_COAL_DENSITY][2]
899 = lagr_model->n_temperature_layers;
900
901 attr_keys[CS_LAGR_COAL_ID][0] = CS_LAGR_P_IPRP;
902 attr_keys[CS_LAGR_COAL_ID][1] = ++loc_count;
903
904 }
905
906 if (lagr_model->n_stat_classes > 0) {
907 attr_keys[CS_LAGR_STAT_CLASS][0] = CS_LAGR_P_IPRP;
908 attr_keys[CS_LAGR_STAT_CLASS][1] = ++loc_count;
909 }
910
911 if (lagr_model->agglomeration == 1 ||
912 lagr_model->fragmentation == 1 ) {
913 attr_keys[CS_LAGR_AGGLO_CLASS_ID][0] = CS_LAGR_P_IPRP;
914 attr_keys[CS_LAGR_AGGLO_CLASS_ID][1] = ++loc_count;
915
916 attr_keys[CS_LAGR_AGGLO_FRACTAL_DIM][0] = CS_LAGR_P_RPRP;
917 attr_keys[CS_LAGR_AGGLO_FRACTAL_DIM][1] = ++loc_count;
918 }
919
920 if (lagr_model->n_user_variables > 0) {
921 attr_keys[CS_LAGR_USER][1] = ++loc_count;
922 attr_keys[CS_LAGR_USER][2] = lagr_model->n_user_variables;
923 }
924
925 /* Default count of 1 */
926
927 for (i = 0; i < CS_LAGR_N_ATTRIBUTES; i++) {
928 if (attr_keys[i][1] > 0 && attr_keys[i][2] == 0)
929 attr_keys[i][2] = 1;
930 else if (attr_keys[i][1] < 1)
931 attr_keys[i][0] = 0;
932 }
933
934 /* Build mappings
935 (in the future, they should be created first, then marked,
936 then built) */
937
938 _p_attr_map = _create_attr_map(attr_keys);
939 }
940
941 /*----------------------------------------------------------------------------*/
942 /*!
943 * \brief Return const pointer to the main particle attribute map structure.
944 *
945 * \return pointer to current particle attrbute map, or NULL
946 */
947 /*----------------------------------------------------------------------------*/
948
949 const cs_lagr_attribute_map_t *
cs_lagr_particle_get_attr_map(void)950 cs_lagr_particle_get_attr_map(void)
951 {
952 const cs_lagr_attribute_map_t *p_am = _p_attr_map;
953 return p_am;
954 }
955
956 /*----------------------------------------------------------------------------*/
957 /*!
958 * Allocate main cs_lagr_particle_set_t structure.
959 */
960 /*----------------------------------------------------------------------------*/
961
962 void
cs_lagr_particle_set_create(void)963 cs_lagr_particle_set_create(void)
964 {
965 cs_glob_lagr_particle_set = _create_particle_set(128, _p_attr_map);
966
967 #if 0 && defined(DEBUG) && !defined(NDEBUG)
968 bft_printf("\n PARTICLE SET AFTER CREATION\n");
969 cs_lagr_particle_set_dump(cs_glob_lagr_particle_set);
970 #endif
971 }
972
973 /*----------------------------------------------------------------------------*/
974 /*!
975 * \brief Destroy main particle set and map if they exist.
976 */
977 /*----------------------------------------------------------------------------*/
978
979 void
cs_lagr_particle_finalize(void)980 cs_lagr_particle_finalize(void)
981 {
982 _destroy_particle_set(&cs_glob_lagr_particle_set);
983
984 _destroy_attr_map(&_p_attr_map);
985 }
986
987 /*----------------------------------------------------------------------------*/
988 /*!
989 * \brief Copy attributes from one particle to another
990 *
991 * The random value associated with the particle is modified.
992 *
993 * \param dest id (0-based) of destination particle
994 * \param src id (0-based) of source particle
995 */
996 /*----------------------------------------------------------------------------*/
997
998 void
cs_lagr_part_copy(cs_lnum_t dest,cs_lnum_t src)999 cs_lagr_part_copy(cs_lnum_t dest,
1000 cs_lnum_t src)
1001 {
1002 cs_lagr_particle_set_t *particles = cs_glob_lagr_particle_set;
1003 memcpy(particles->p_buffer + particles->p_am->extents*(dest),
1004 particles->p_buffer + particles->p_am->extents*(src),
1005 particles->p_am->extents);
1006 cs_real_t random = -1;
1007 cs_random_uniform(1, &random);
1008 cs_lagr_particles_set_real(particles, (dest-1), CS_LAGR_RANDOM_VALUE,
1009 random);
1010 }
1011
1012 /*----------------------------------------------------------------------------*/
1013 /*!
1014 * \brief Get data extents for a given particle attribute.
1015 *
1016 * For attributes not currently present, the displacement and data
1017 * size should be -1 and 0 respectively.
1018 *
1019 * \param[in] particles associated particle set
1020 * \param[in] time_id associated time id (0: current, 1: previous)
1021 * \param[in] attr particle attribute
1022 * \param[out] extents size (in bytes) of particle structure, or NULL
1023 * \param[out] size size (in bytes) of attribute in particle structure,
1024 * or NULL
1025 * \param[out] displ displacement (in bytes) in particle structure,
1026 * or NULL
1027 * \param[out] datatype datatype of associated attribute, or NULL
1028 * \param[out] count number of type values associated with attribute,
1029 * or NULL
1030 */
1031 /*----------------------------------------------------------------------------*/
1032
1033 void
cs_lagr_get_attr_info(const cs_lagr_particle_set_t * particles,int time_id,cs_lagr_attribute_t attr,size_t * extents,size_t * size,ptrdiff_t * displ,cs_datatype_t * datatype,int * count)1034 cs_lagr_get_attr_info(const cs_lagr_particle_set_t *particles,
1035 int time_id,
1036 cs_lagr_attribute_t attr,
1037 size_t *extents,
1038 size_t *size,
1039 ptrdiff_t *displ,
1040 cs_datatype_t *datatype,
1041 int *count)
1042 {
1043 if (extents)
1044 *extents = particles->p_am->extents;
1045 if (size)
1046 *size = particles->p_am->size[attr];
1047 if (displ)
1048 *displ = particles->p_am->displ[time_id][attr];
1049 if (datatype)
1050 *datatype = particles->p_am->datatype[attr];
1051 if (count)
1052 *count = particles->p_am->count[time_id][attr];
1053 }
1054
1055 /*----------------------------------------------------------------------------*/
1056 /*!
1057 * \brief Check that query for a given particle attribute is valid.
1058 *
1059 * \param[in] particles associated particle set
1060 * \param[in] attr attribute whose values are required
1061 * \param[in] datatype associated value type
1062 * \param[in] stride number of values per particle
1063 * \param[in] component_id if -1 : extract the whole attribute
1064 * if >0 : id of the component to extract
1065 *
1066 * \return 0 in case of success, 1 in case of error
1067 */
1068 /*----------------------------------------------------------------------------*/
1069
1070 int
cs_lagr_check_attr_query(const cs_lagr_particle_set_t * particles,cs_lagr_attribute_t attr,cs_datatype_t datatype,int stride,int component_id)1071 cs_lagr_check_attr_query(const cs_lagr_particle_set_t *particles,
1072 cs_lagr_attribute_t attr,
1073 cs_datatype_t datatype,
1074 int stride,
1075 int component_id)
1076 {
1077 int retval = 0;
1078
1079 assert(particles != NULL);
1080
1081 int _count;
1082 cs_datatype_t _datatype;
1083
1084 cs_lagr_get_attr_info(particles, 0, attr,
1085 NULL, NULL, NULL, &_datatype, &_count);
1086
1087 if ( datatype != _datatype || stride != _count
1088 || component_id < -1 || component_id >= stride) {
1089
1090 char attr_name[128];
1091 attr_name[127] = '\0';
1092 const char *_attr_name = attr_name;
1093 if (attr < CS_LAGR_N_ATTRIBUTES) {
1094 snprintf(attr_name, 127, "CS_LAGR_%s", cs_lagr_attribute_name[attr]);
1095 size_t l = strlen(attr_name);
1096 for (size_t i = 0; i < l; i++)
1097 attr_name[i] = toupper(attr_name[i]);
1098 }
1099 else {
1100 snprintf(attr_name, 127, "%d", (int)attr);
1101 }
1102
1103 if (datatype != _datatype || stride != _count)
1104 bft_error(__FILE__, __LINE__, 0,
1105 _("Attribute %s is of datatype %s and stride %d\n"
1106 "but %s and %d were requested."),
1107 _attr_name,
1108 cs_datatype_name[_datatype], _count,
1109 cs_datatype_name[datatype], stride);
1110
1111 else if (component_id < -1 || component_id >= stride)
1112 bft_error(__FILE__, __LINE__, 0,
1113 _("Attribute %s has a number of components equal to %d\n"
1114 "but component %d is requested."),
1115 _attr_name,
1116 stride,
1117 component_id);
1118
1119 retval = 1;
1120 }
1121
1122 return retval;
1123 }
1124
1125 /*----------------------------------------------------------------------------*/
1126 /*!
1127 * \brief Check if a particle attribute is in a valid range.
1128 *
1129 * If this is not the case, a fatal error is provoked.
1130
1131 * \param[in] attr particle attribute
1132 */
1133 /*----------------------------------------------------------------------------*/
1134
1135 void
cs_lagr_particle_attr_in_range(int attr)1136 cs_lagr_particle_attr_in_range(int attr)
1137 {
1138 if (attr < 0 || attr >= CS_LAGR_N_ATTRIBUTES)
1139 bft_error(__FILE__, __LINE__,0,
1140 _("Out-of range attribute type: %d"),
1141 (int)attr);
1142 }
1143
1144 /*----------------------------------------------------------------------------*/
1145 /*!
1146 * \brief Return pointer to the main cs_lagr_particle_set_t structure.
1147 *
1148 * \return pointer to current particle set, or NULL
1149 */
1150 /*----------------------------------------------------------------------------*/
1151
1152 cs_lagr_particle_set_t *
cs_lagr_get_particle_set(void)1153 cs_lagr_get_particle_set(void)
1154 {
1155 return cs_glob_lagr_particle_set;
1156 }
1157
1158 /*----------------------------------------------------------------------------*/
1159 /*!
1160 * \brief Resize particle set buffers if needed.
1161 *
1162 * By default, the total number of particles is not limited. A global limit
1163 * may be set using \ref cs_lagr_set_n_g_particles_max.
1164 *
1165 * \param[in] n_min_particles minimum number of particles required
1166 *
1167 * \return 1 if resizing was required, -1 if the global minimum number
1168 * of particles would exceed the global limit, 0 otherwise.
1169 */
1170 /*----------------------------------------------------------------------------*/
1171
1172 int
cs_lagr_particle_set_resize(cs_lnum_t n_min_particles)1173 cs_lagr_particle_set_resize(cs_lnum_t n_min_particles)
1174 {
1175 int retval = 0;
1176
1177 /* Do we have a limit ? */
1178
1179 if (_n_g_max_particles < ULLONG_MAX) {
1180 cs_gnum_t _n_g_min_particles = n_min_particles;
1181 cs_parall_counter(&_n_g_min_particles, 1);
1182 if (_n_g_min_particles > _n_g_max_particles)
1183 retval = -1;
1184 }
1185 else
1186 retval = _particle_set_resize(cs_glob_lagr_particle_set, n_min_particles);
1187
1188 return retval;
1189 }
1190
1191 /*----------------------------------------------------------------------------*/
1192 /*!
1193 * \brief Set reallocation factor for particle sets.
1194 *
1195 * This factor determines the multiplier used for reallocations when
1196 * the particle set's buffers are too small to handle the new number of
1197 * particles.
1198 *
1199 * \param[in] f reallocation size multiplier
1200 */
1201 /*----------------------------------------------------------------------------*/
1202
1203 void
cs_lagr_set_reallocation_factor(double f)1204 cs_lagr_set_reallocation_factor(double f)
1205 {
1206 if (f > 1)
1207 _reallocation_factor = f;
1208 }
1209
1210 /*----------------------------------------------------------------------------*/
1211 /*!
1212 * \brief Get global maximum number of particles.
1213 *
1214 * By default, the number is limited only by local \ref cs_lnum_t and global
1215 * \ref cs_gnum_t data representation limits.
1216 *
1217 * \return global maximum number of particles
1218 */
1219 /*----------------------------------------------------------------------------*/
1220
1221 unsigned long long
cs_lagr_get_n_g_particles_max(void)1222 cs_lagr_get_n_g_particles_max(void)
1223 {
1224 return _n_g_max_particles;
1225 }
1226
1227 /*----------------------------------------------------------------------------*/
1228 /*!
1229 * \brief Set global maximum number of particles.
1230 *
1231 * By default, the number is limited only by local \ref cs_lnum_t and global
1232 * \ref cs_gnum_t data representation limits.
1233 *
1234 * \param[in] n_g_particles_max global maximum number of particles
1235 */
1236 /*----------------------------------------------------------------------------*/
1237
1238 void
cs_lagr_set_n_g_particles_max(unsigned long long n_g_particles_max)1239 cs_lagr_set_n_g_particles_max(unsigned long long n_g_particles_max)
1240 {
1241 _n_g_max_particles = n_g_particles_max;
1242 }
1243
1244 /*----------------------------------------------------------------------------*/
1245 /*!
1246 * \brief Copy current attributes to previous attributes.
1247 *
1248 * \param[in, out] particles associated particle set
1249 * \param[in] particle_id id of particle
1250 */
1251 /*----------------------------------------------------------------------------*/
1252
1253 void
cs_lagr_particles_current_to_previous(cs_lagr_particle_set_t * particles,cs_lnum_t particle_id)1254 cs_lagr_particles_current_to_previous(cs_lagr_particle_set_t *particles,
1255 cs_lnum_t particle_id)
1256 {
1257 const cs_lagr_attribute_map_t *p_am = particles->p_am;
1258 unsigned char *p_buf = particles->p_buffer + p_am->extents*(particle_id);
1259
1260 for (cs_lagr_attribute_t attr = 0;
1261 attr < CS_LAGR_N_ATTRIBUTES;
1262 attr++) {
1263 if (p_am->count[1][attr] > 0 && p_am->count[0][attr] > 0) {
1264 memcpy(p_buf + p_am->displ[1][attr],
1265 p_buf + p_am->displ[0][attr],
1266 p_am->size[attr]);
1267 }
1268 }
1269 *((cs_lnum_t *)(p_buf + p_am->displ[1][CS_LAGR_RANK_ID])) = cs_glob_rank_id;
1270 }
1271
1272 /*----------------------------------------------------------------------------*/
1273 /*!
1274 * \brief Dump a cs_lagr_particle_set_t structure
1275 *
1276 * \param[in] particles cs_lagr_particle_t structure to dump
1277 */
1278 /*----------------------------------------------------------------------------*/
1279
1280 void
cs_lagr_particle_set_dump(const cs_lagr_particle_set_t * particles)1281 cs_lagr_particle_set_dump(const cs_lagr_particle_set_t *particles)
1282 {
1283 if (particles != NULL) {
1284
1285 bft_printf("Particle set\n");
1286 bft_printf("------------\n");
1287 bft_printf(" n_particles: %10ld\n", (long)particles->n_particles);
1288 bft_printf(" n_particles_max: %10ld\n", (long)particles->n_particles_max);
1289
1290 bft_printf_flush();
1291
1292 for (cs_lnum_t i = 0; i < particles->n_particles; i++) {
1293 _dump_particle(particles, i);
1294 }
1295
1296 }
1297 bft_printf_flush();
1298 }
1299
1300 /*----------------------------------------------------------------------------*/
1301 /*!
1302 * \brief Set number of user particle variables.
1303 *
1304 * \param[in] n_user_variables number of user variables
1305 */
1306 /*----------------------------------------------------------------------------*/
1307
1308 void
cs_lagr_set_n_user_variables(int n_user_variables)1309 cs_lagr_set_n_user_variables(int n_user_variables)
1310 {
1311 cs_glob_lagr_model->n_user_variables = n_user_variables;
1312 }
1313
1314 /*----------------------------------------------------------------------------*/
1315
1316 END_C_DECLS
1317