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