1 /*============================================================================
2  * Mesh locations management.
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 <assert.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 /*----------------------------------------------------------------------------
39  * Local headers
40  *----------------------------------------------------------------------------*/
41 
42 #include "bft_mem.h"
43 #include "bft_error.h"
44 #include "bft_printf.h"
45 
46 #include "fvm_selector.h"
47 
48 #include "cs_halo.h"
49 #include "cs_parall.h"
50 
51 #include "cs_mesh.h"
52 #include "cs_sort.h"
53 
54 /*----------------------------------------------------------------------------
55  * Header for the current file
56  *----------------------------------------------------------------------------*/
57 
58 #include "cs_mesh_location.h"
59 
60 /*----------------------------------------------------------------------------*/
61 
62 BEGIN_C_DECLS
63 
64 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
65 
66 /*=============================================================================
67  * Macro definitions
68  *============================================================================*/
69 
70 /*============================================================================
71  * Type definitions
72  *============================================================================*/
73 
74 /*-----------------------------------------------------------------------------
75  * Local type definitions
76  *----------------------------------------------------------------------------*/
77 
78 /* Associated typedef documentation (for cs_mesh_location.h) */
79 
80 /*!
81  * \typedef cs_mesh_location_select_t
82  *
83  * \brief Function pointer to mesh location elements selection definition.
84  *
85  * If non-empty and not containing all elements, a list of elements
86  * of the parent mesh belonging to the location should be allocated
87  * (using BFT_MALLOC) and defined by this function when called.
88  * This list's lifecycle is then managed by the mesh location object.
89  *
90  * \param [in]   m            pointer to associated mesh structure.
91  * \param [in]   location_id  id of associated location.
92  * \param [out]  n_elts       number of selected elements
93  * \param [out]  elt_list     list of selected elements.
94  */
95 
96 struct _cs_mesh_location_t {
97 
98   char                        name[32];     /* Name */
99 
100   const cs_mesh_t            *mesh;         /* Pointer to associated mesh */
101 
102   cs_mesh_location_type_t     type;         /* Location type */
103 
104   char                       *select_str;   /* String */
105   cs_mesh_location_select_t  *select_fp;    /* Function pointer */
106   void                       *select_input; /* Optional input for the function
107                                                pointer */
108   int                         n_sub_ids;    /* Number of mesh location ids
109                                                used to build this location */
110   int                        *sub_ids;      /* List of mesh location ids */
111   bool                        complement;   /* Take the complement ? */
112   bool                        explicit_ids; /* Need explicit ids ? */
113 
114   cs_lnum_t                   n_elts[3];    /* Number of associated elements:
115                                                0: local,
116                                                1: with standard ghost elements,
117                                                2: with extended ghost elements
118                                             */
119 
120   cs_lnum_t                  *elt_list;     /* List of associated elements,
121                                                (0 to n-1 numbering) if non
122                                                trivial (i.e. a subset) */
123 };
124 
125 /*============================================================================
126  * Static global variables
127  *============================================================================*/
128 
129 /*============================================================================
130  * Global variables
131  *============================================================================*/
132 
133 /* Names associated with location types */
134 
135 const char  *cs_mesh_location_type_name[] = {N_("none"),
136                                              N_("cells"),
137                                              N_("interior faces"),
138                                              N_("boundary faces"),
139                                              N_("vertices"),
140                                              N_("faces"),
141                                              N_("edges"),
142                                              N_("particles"),
143                                              N_("other")};
144 
145 /* Location definitions */
146 
147 static int                  _n_mesh_locations_max = 0;
148 static int                  _n_mesh_locations = 0;
149 static cs_mesh_location_t  *_mesh_location = NULL;
150 
151 /* Shared explicit ids */
152 
153 static cs_lnum_t            _explicit_ids_size = 0;
154 static cs_lnum_t           *_explicit_ids = NULL;
155 
156 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
157 
158 /*============================================================================
159  * Private function definitions
160  *============================================================================*/
161 
162 /*----------------------------------------------------------------------------
163  * \brief Get a pointer to a mesh location by its id.
164  *
165  * \param[in]  id         id of mesh location
166  *
167  * \return  a pointer to the associated mesh location
168  */
169 /*----------------------------------------------------------------------------*/
170 
171 static cs_mesh_location_t *
_mesh_location_by_id(int id)172 _mesh_location_by_id(int  id)
173 {
174   cs_mesh_location_t  *retval = NULL;
175 
176   if (id < 0 || id > _n_mesh_locations)
177     bft_error(__FILE__, __LINE__, 0,
178               _("The requested mesh location\n"
179                 "%d is not defined.\n"), id);
180   else
181     retval = _mesh_location + id;
182 
183   return retval;
184 }
185 
186 /*----------------------------------------------------------------------------
187  * \brief Get a const pointer to a mesh location by its id.
188  *
189  * \param[in]  id         id of mesh location
190  *
191  * \return  a pointer to the associated mesh location
192  */
193 /*----------------------------------------------------------------------------*/
194 
195 static const cs_mesh_location_t *
_const_mesh_location_by_id(int id)196 _const_mesh_location_by_id(int  id)
197 {
198   const cs_mesh_location_t  *retval = NULL;
199 
200   if (id < 0 || id > _n_mesh_locations)
201     bft_error(__FILE__, __LINE__, 0,
202               _("The requested mesh location\n"
203                 "%d is not defined.\n"), id);
204   else
205     retval = _mesh_location + id;
206 
207   return retval;
208 }
209 
210 /*----------------------------------------------------------------------------*/
211 /*!
212  * \brief Find the related location id from the location name
213  *
214  * \param[in]  ref_name    name of the location to find
215  *
216  * \return -1 if not found otherwise the associated id
217  */
218 /*----------------------------------------------------------------------------*/
219 
220 static int
_find_id_by_name(const char * ref_name)221 _find_id_by_name(const char  *ref_name)
222 {
223   int  ml_id = -1, reflen = strlen(ref_name);
224 
225   for (int i = 0; i < _n_mesh_locations; i++) {
226 
227     cs_mesh_location_t  *ml = _mesh_location + i;
228     int len = strlen(ml->name);
229 
230     if (reflen == len) {
231       if (strcmp(ref_name, ml->name) == 0) {
232         ml_id = i;
233         break;
234       }
235     }
236 
237   } /* Loops on mesh locations */
238 
239   return ml_id;
240 }
241 
242 /*----------------------------------------------------------------------------
243  * \brief Define a new mesh location.
244  *
245  * If a list of associated elements is given (defining a subset of a main
246  * location), its ownership is transferred to the mesh location.
247  *
248  * \param[in]  name      name of location to define
249  * \param[in]  type      type of location to define
250  *
251  * \return   id of the newly defined mesh location
252  */
253 /*----------------------------------------------------------------------------*/
254 
255 static int
_mesh_location_define(const char * name,cs_mesh_location_type_t type)256 _mesh_location_define(const char               *name,
257                       cs_mesh_location_type_t   type)
258 {
259   int  i;
260 
261   cs_mesh_location_t  *ml = NULL;
262 
263   /* Check if there is already a mesh location with the same name */
264   int id = _find_id_by_name(name);
265 
266   if (id == -1) /* Not found in the current list */
267     id = _n_mesh_locations;
268 
269   else { /* A mesh location shares the same name */
270     ml = _mesh_location + id;
271     if (ml->type != type)
272       bft_error(__FILE__, __LINE__, 0,
273                 _(" The mesh location %s is already defined as a mesh location"
274                   " but with a different type.\n"
275                   " Please check your settings."), name);
276     return id;
277   }
278 
279   /* Allocate new locations if necessary */
280   if (_n_mesh_locations >= _n_mesh_locations_max) {
281     if (_n_mesh_locations_max == 0)
282       _n_mesh_locations_max = 4;
283     else
284       _n_mesh_locations_max *= 2;
285     BFT_REALLOC(_mesh_location,
286                 _n_mesh_locations_max,
287                 cs_mesh_location_t);
288   }
289   _n_mesh_locations++;
290 
291   /* Define mesh location */
292   ml = _mesh_location + id;
293 
294   ml->mesh = NULL;
295 
296   strncpy(ml->name, name, 31);
297   ml->name[31] = '\0';
298 
299   ml->type = type;
300 
301   ml->select_str = NULL;
302   ml->select_fp = NULL;
303   ml->select_input = NULL;
304   ml->n_sub_ids = 0;
305   ml->sub_ids = NULL;
306   ml->complement = false;
307   ml->explicit_ids = false;
308 
309   for (i = 0; i < 3; i++)
310     ml->n_elts[i] = 0;
311   ml->elt_list = NULL;
312 
313   return id;
314 }
315 
316 /*----------------------------------------------------------------------------
317  * \brief Build a list of element ids from a list of existing mesh location
318  *        ids
319  *
320  * \param[in]  name      name of location to define
321  * \param[in]  type      type of location to define
322  */
323 /*----------------------------------------------------------------------------*/
324 
325 static void
_build_by_ml_ids(cs_mesh_location_t * ml)326 _build_by_ml_ids(cs_mesh_location_t  *ml)
327 {
328   int  i, count;
329 
330   cs_lnum_t  n_elts_max = 0;
331 
332   switch(ml->type) {
333   case CS_MESH_LOCATION_CELLS:
334     n_elts_max = ml->mesh->n_cells;
335     break;
336   case CS_MESH_LOCATION_FACES:
337     n_elts_max = ml->mesh->n_b_faces + ml->mesh->n_i_faces;
338     break;
339   case CS_MESH_LOCATION_INTERIOR_FACES:
340     n_elts_max = ml->mesh->n_i_faces;
341     break;
342   case CS_MESH_LOCATION_BOUNDARY_FACES:
343     n_elts_max = ml->mesh->n_b_faces;
344     break;
345   case CS_MESH_LOCATION_VERTICES:
346     n_elts_max = ml->mesh->n_vertices;
347     break;
348   default:
349     assert(0);
350     break;
351   }
352 
353   if (ml->n_sub_ids == 1 && ml->complement == false) {
354 
355     int  sub_id = ml->sub_ids[0];
356     assert(sub_id < _n_mesh_locations);
357     cs_mesh_location_t  *sub_ml = _mesh_location + sub_id;
358     assert(sub_ml->type == ml->type);
359 
360     ml->n_elts[0] = sub_ml->n_elts[0];
361     if (sub_ml->elt_list != NULL) { /* Copy */
362       BFT_MALLOC(ml->elt_list, ml->n_elts[0], cs_lnum_t);
363       memcpy(ml->elt_list, sub_ml->elt_list, ml->n_elts[0]*sizeof(cs_lnum_t));
364     }
365 
366   }
367   else {
368 
369     bool  *flag = NULL;
370 
371     /* Initialize flag */
372     BFT_MALLOC(flag, n_elts_max, bool);
373     for (i = 0; i < n_elts_max; i++)
374       flag[i] = false;
375 
376     /* Build flag */
377     for (int ii = 0; ii < ml->n_sub_ids; ii++) {
378 
379       int  sub_id = ml->sub_ids[ii];
380       assert(sub_id < _n_mesh_locations);
381       cs_mesh_location_t  *sub_ml = _mesh_location + sub_id;
382       assert(sub_ml->type == ml->type);
383 
384       if (sub_ml->elt_list == NULL)
385         for (i = 0; i < n_elts_max; i++)
386           flag[i] = true;
387       else
388         for (i = 0; i < sub_ml->n_elts[0]; i++)
389           flag[sub_ml->elt_list[i]] = true;
390 
391     } /* Loop on (sub) mesh locations */
392 
393     if (ml->complement) {
394       for (i = 0; i < n_elts_max; i++) {
395         if (flag[i])
396           flag[i] = false;
397         else
398           flag[i] = true;
399       }
400     }
401 
402     /* Compute n_elts[0] */
403     count = 0;
404     for (i = 0; i < n_elts_max; i++)
405       if (flag[i]) count++;
406     ml->n_elts[0] = count;
407 
408     /* Build elt_list */
409     if (ml->n_elts[0] != 0 && ml->n_elts[0] != n_elts_max) {
410       BFT_MALLOC(ml->elt_list, ml->n_elts[0], cs_lnum_t);
411       count = 0;
412       for (i = 0; i < n_elts_max; i++)
413         if (flag[i]) ml->elt_list[count++] = i;
414     }
415 
416     BFT_FREE(flag);
417 
418   } /* If simple case (n_sub_ids = 1 and no complement) or not */
419 
420 }
421 
422 /*=============================================================================
423  * Public function definitions
424  *============================================================================*/
425 
426 /*----------------------------------------------------------------------------*/
427 /*!
428  * \brief Return number of mesh locations defined.
429  *
430  * \return  number of mesh locations defined
431  */
432 /*----------------------------------------------------------------------------*/
433 
434 int
cs_mesh_location_n_locations(void)435 cs_mesh_location_n_locations(void)
436 {
437   return _n_mesh_locations;
438 }
439 
440 /*----------------------------------------------------------------------------*/
441 /*!
442  * \brief Initialize mesh location API.
443  *
444  * By default, 7 mesh locations are built, matching the 7 first values of
445  * the cs_mesh_location_type_t enum: CS_MESH_LOCATION_NONE for global
446  * values, CS_MESH_LOCATION_CELLS for the cells of the (default) global mesh,
447  * CS_MESH_LOCATION_INTERIOR_FACES and CS_MESH_LOCATION_BOUNDARY_FACES for
448  * its faces, and CS_MESH_LOCATION_VERTICES for its vertices.
449  * CS_MESH_LOCATION_FACES and a placeholder for CS_MESH_LOCATION_EDGES are
450  * also added for CDO discretizations.
451  *
452  * Locations should then be built once the global mesh is complete, and
453  * its halo structures completed.
454  */
455 /*----------------------------------------------------------------------------*/
456 
457 void
cs_mesh_location_initialize(void)458 cs_mesh_location_initialize(void)
459 {
460   cs_mesh_location_add(N_("global"),
461                        CS_MESH_LOCATION_NONE,
462                        NULL);
463   cs_mesh_location_add(N_("cells"),
464                        CS_MESH_LOCATION_CELLS,
465                        NULL);
466   cs_mesh_location_add(N_("interior_faces"),
467                        CS_MESH_LOCATION_INTERIOR_FACES,
468                        NULL);
469   cs_mesh_location_add(N_("boundary_faces"),
470                        CS_MESH_LOCATION_BOUNDARY_FACES,
471                        NULL);
472   cs_mesh_location_add(N_("vertices"),
473                        CS_MESH_LOCATION_VERTICES,
474                        NULL);
475   cs_mesh_location_add(N_("faces"),
476                        CS_MESH_LOCATION_FACES,
477                        NULL);
478   cs_mesh_location_add(N_("edges (type)"),
479                        CS_MESH_LOCATION_EDGES,
480                        NULL);
481 }
482 
483 /*----------------------------------------------------------------------------*/
484 /*!
485  * \brief Finalize mesh location API.
486  */
487 /*----------------------------------------------------------------------------*/
488 
489 void
cs_mesh_location_finalize(void)490 cs_mesh_location_finalize(void)
491 {
492   int  i;
493 
494   BFT_FREE(_explicit_ids);
495 
496   for (i = 0; i < _n_mesh_locations; i++) {
497     cs_mesh_location_t  *ml = _mesh_location + i;
498     BFT_FREE(ml->elt_list);
499     BFT_FREE(ml->select_str);
500     BFT_FREE(ml->sub_ids);
501   }
502 
503   _explicit_ids_size = 0;
504   _n_mesh_locations = 0;
505   _n_mesh_locations_max = 0;
506 
507   BFT_FREE(_mesh_location);
508 }
509 
510 /*----------------------------------------------------------------------------*/
511 /*!
512  * \brief Associate mesh locations with a mesh.
513  *
514  * If mesh_id is negative, all defined mesh locations are associated
515  * (which is useful for the common case where only one mesh is present).
516  * If mesh_id is non-negative, only the location with the matching
517  * id is associated (which may be useful when multiple meshes are defined).
518  *
519  * The number of elements are computed based on the underlying mesh,
520  * and element lists are built for mesh subset locations.
521  *
522  * \param[in]  mesh  pointer to associated mesh structure
523  * \param[in]  id    id of mesh location
524  */
525 /*----------------------------------------------------------------------------*/
526 
527 void
cs_mesh_location_build(cs_mesh_t * mesh,int id)528 cs_mesh_location_build(cs_mesh_t  *mesh,
529                        int         id)
530 {
531   int  ml_id;
532   int id_start = 0, id_end = _n_mesh_locations;
533 
534   cs_lnum_t  explicit_ids_size = 0;
535 
536   assert(mesh != NULL);
537   assert(   mesh->halo != NULL
538          || (cs_glob_n_ranks == 1 && mesh->periodicity == NULL));
539 
540   if (id >= 0) {
541     id_start = id;
542     if (id < _n_mesh_locations)
543       id_end = id + 1;
544   }
545 
546   for (ml_id = id_start; ml_id < id_end; ml_id++) {
547 
548     int n_elts_max = 0;
549     fvm_selector_t *selector = NULL;
550     cs_mesh_location_t  *ml = _mesh_location + ml_id;
551 
552     ml->mesh = mesh;
553 
554     if (ml->elt_list != NULL)
555       BFT_FREE(ml->elt_list);
556 
557     switch(ml->type) {
558     case CS_MESH_LOCATION_CELLS:
559       selector = mesh->select_cells;
560       n_elts_max = ml->mesh->n_cells;
561       break;
562     case CS_MESH_LOCATION_FACES:
563       n_elts_max = ml->mesh->n_b_faces + ml->mesh->n_i_faces;
564       break;
565     case CS_MESH_LOCATION_INTERIOR_FACES:
566       selector = mesh->select_i_faces;
567       n_elts_max = ml->mesh->n_i_faces;
568       break;
569     case CS_MESH_LOCATION_BOUNDARY_FACES:
570       selector = mesh->select_b_faces;
571       n_elts_max = ml->mesh->n_b_faces;
572       break;
573     case CS_MESH_LOCATION_VERTICES:
574       n_elts_max = mesh->n_vertices;
575       break;
576     default:
577       break;
578     }
579 
580     if (ml->select_str != NULL) {
581       if (selector != NULL) {
582         BFT_MALLOC(ml->elt_list, n_elts_max, cs_lnum_t);
583         int c_id = fvm_selector_get_list(selector,
584                                          ml->select_str,
585                                          0,
586                                          ml->n_elts,
587                                          ml->elt_list);
588         if (ml->n_elts[0] == n_elts_max && ml->elt_list != NULL)
589           BFT_FREE(ml->elt_list);
590         else
591           BFT_REALLOC(ml->elt_list, ml->n_elts[0], cs_lnum_t);
592         if (fvm_selector_n_missing(selector, c_id) > 0) {
593           const char *missing
594             = fvm_selector_get_missing(selector, c_id, 0);
595           cs_base_warn(__FILE__, __LINE__);
596           bft_printf(_("The group \"%s\" in the selection criteria:\n"
597                        "\"%s\"\n"
598                        " does not correspond to any boundary face.\n"),
599                      missing, ml->select_str);
600         }
601       }
602       else
603         bft_error(__FILE__, __LINE__, 0,
604                   _("A selection criteria is given but no associated selector\n"
605                     "is available for mesh location %d of type %d."),
606                   ml_id, (int)ml->type);
607     }
608     else if (ml->select_fp != NULL) {
609       ml->select_fp(ml->select_input,
610                     ml->mesh,
611                     ml_id,
612                     ml->n_elts,
613                     &(ml->elt_list));
614       if (ml->elt_list != NULL)
615         cs_sort_lnum(ml->elt_list, ml->n_elts[0]);
616     }
617     else if (ml->n_sub_ids > 0 && ml->sub_ids != NULL)
618       _build_by_ml_ids(ml);
619     else
620       ml->n_elts[0] = n_elts_max;
621 
622     ml->n_elts[1] = ml->n_elts[0];
623     ml->n_elts[2] = ml->n_elts[0];
624 
625     if (ml->type == CS_MESH_LOCATION_CELLS && ml->n_elts[0] == mesh->n_cells) {
626       if (mesh->halo != NULL) {
627         assert(mesh->halo->n_local_elts == ml->n_elts[0]);
628         ml->n_elts[1] += mesh->halo->n_elts[0];
629         ml->n_elts[2] += mesh->halo->n_elts[1];
630       }
631     }
632 
633     if (ml->explicit_ids && explicit_ids_size < ml->n_elts[0])
634       explicit_ids_size = ml->n_elts[0];
635 
636   } /* Loop on mesh locations */
637 
638   if (explicit_ids_size != _explicit_ids_size) {
639     if (id == 0 || explicit_ids_size > _explicit_ids_size) {
640       cs_lnum_t s_id = (id == 0) ? 0 : _explicit_ids_size;
641       _explicit_ids_size = explicit_ids_size;
642       BFT_REALLOC(_explicit_ids, _explicit_ids_size, cs_lnum_t);
643       for (cs_lnum_t i = s_id; i < _explicit_ids_size; i++)
644         _explicit_ids[i] = i;
645     }
646   }
647 }
648 
649 /*----------------------------------------------------------------------------*/
650 /*!
651  * \brief Define a new mesh location.
652  *
653  * So as to define a subset of mesh entities of a given type, an optional
654  * selection criteria may be given.
655  *
656  * \param[in]  name      name of location to define
657  * \param[in]  type      type of location to define
658  * \param[in]  criteria  selection criteria for associated elements,
659  *                       or NULL
660  *
661  * \return  id of newly defined created mesh location
662  */
663 /*----------------------------------------------------------------------------*/
664 
665 int
cs_mesh_location_add(const char * name,cs_mesh_location_type_t type,const char * criteria)666 cs_mesh_location_add(const char                *name,
667                      cs_mesh_location_type_t    type,
668                      const char                *criteria)
669 {
670   int  ml_id = _mesh_location_define(name, type);
671   cs_mesh_location_t  *ml = _mesh_location + ml_id;
672 
673   if (criteria != NULL) {
674     BFT_MALLOC(ml->select_str, strlen(criteria) + 1, char);
675     strcpy(ml->select_str, criteria);
676   }
677 
678   return ml_id;
679 }
680 
681 /*----------------------------------------------------------------------------*/
682 /*!
683  * \brief Define a new mesh location with an associated selection function.
684  *
685  * So as to define a subset of mesh entities of a given type, a pointer
686  * to a selection function may be given.
687  *
688  * This requires more programming but allows finer control than selection
689  * criteria, as the function has access to the complete mesh structure.
690  *
691  * \param[in]  name        name of location to define
692  * \param[in]  type        type of location to define
693  * \param[in]  func        pointer to selection function for associated
694  *                         elements, or NULL
695  * \param[in, out]  input  pointer to optional (untyped) value
696  *                         or structure.
697  *
698  * \return  id of newly defined created mesh location
699  */
700 /*----------------------------------------------------------------------------*/
701 
702 int
cs_mesh_location_add_by_func(const char * name,cs_mesh_location_type_t type,cs_mesh_location_select_t * func,void * input)703 cs_mesh_location_add_by_func(const char                 *name,
704                              cs_mesh_location_type_t     type,
705                              cs_mesh_location_select_t  *func,
706                              void                       *input)
707 {
708   int  ml_id = _mesh_location_define(name, type);
709   cs_mesh_location_t  *ml = _mesh_location + ml_id;
710 
711   ml->select_fp = func;
712   ml->select_input = input;
713 
714   return ml_id;
715 }
716 
717 /*----------------------------------------------------------------------------*/
718 /*!
719  * \brief Define a new mesh location.
720  *
721  * So as to define a subset of mesh entities of a given type, a list of ids
722  * related to existing mesh locations may be given
723  *
724  * \param[in]  name        name of location to define
725  * \param[in]  type        type of location to define
726  * \param[in]  n_ml_ids    number of mesh location ids
727  * \param[in]  ml_ids      list of mesh location ids
728  * \param[in]  complement  take the complement of the selected entities if true
729  *
730  * \return  id of newly created mesh location
731  */
732 /*----------------------------------------------------------------------------*/
733 
734 int
cs_mesh_location_add_by_union(const char * name,cs_mesh_location_type_t type,int n_ml_ids,const int * ml_ids,bool complement)735 cs_mesh_location_add_by_union(const char               *name,
736                               cs_mesh_location_type_t   type,
737                               int                       n_ml_ids,
738                               const int                *ml_ids,
739                               bool                      complement)
740 {
741   int  ml_id = _mesh_location_define(name, type);
742   cs_mesh_location_t  *ml = _mesh_location + ml_id;
743 
744   ml->complement = complement;
745   ml->n_sub_ids = n_ml_ids;
746   if (ml->n_sub_ids > 0) {
747     BFT_MALLOC(ml->sub_ids, ml->n_sub_ids, int);
748     for (int i = 0; i < ml->n_sub_ids; i++)
749       ml->sub_ids[i] = ml_ids[i];
750   }
751 
752   return ml_id;
753 }
754 
755 /*----------------------------------------------------------------------------*/
756 /*!
757  * \brief Find the related location id from the location name
758  *
759  * \param[in]  ref_name    name of the location to find
760  *
761  * \return -1 if not found otherwise the associated id
762  */
763 /*----------------------------------------------------------------------------*/
764 
765 int
cs_mesh_location_get_id_by_name(const char * ref_name)766 cs_mesh_location_get_id_by_name(const char  *ref_name)
767 {
768   return _find_id_by_name(ref_name);
769 }
770 
771 /*----------------------------------------------------------------------------*/
772 /*!
773  * \brief  Get a mesh location's name.
774  *
775  * \param[in]  id  id of mesh location
776  *
777  * \return  pointer to mesh location name
778  */
779 /*----------------------------------------------------------------------------*/
780 
781 const char *
cs_mesh_location_get_name(int id)782 cs_mesh_location_get_name(int  id)
783 {
784   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
785 
786   return ml->name;
787 }
788 
789 /*----------------------------------------------------------------------------*/
790 /*!
791  * \brief  Get a mesh location's type.
792  *
793  * \param[in]  id  id of mesh location
794  *
795  * \return  mesh location type
796  */
797 /*----------------------------------------------------------------------------*/
798 
799 cs_mesh_location_type_t
cs_mesh_location_get_type(int id)800 cs_mesh_location_get_type(int  id)
801 {
802   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
803 
804   return ml->type;
805 }
806 
807 /*----------------------------------------------------------------------------*/
808 /*!
809  * \brief  Get a mesh location's number of elements.
810  *
811  * A pointer to a array of 3 values is returned:
812  *   0: local number of elements
813  *   1: with standard ghost elements (if applicable)
814  *   2: with extended ghost elements (if applicable)
815  *
816  * \param[in]  id  id of mesh location
817  *
818  * \return  array of numbers of elements.
819  */
820 /*----------------------------------------------------------------------------*/
821 
822 const cs_lnum_t *
cs_mesh_location_get_n_elts(int id)823 cs_mesh_location_get_n_elts(int id)
824 {
825   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
826 
827   return ml->n_elts;
828 }
829 
830 /*----------------------------------------------------------------------------*/
831 /*!
832  * \brief  Get a mesh location's elements list, if present.
833  *
834  * A list of elements is defined if the location is a subset of a main
835  * location type.
836  *
837  * \deprecated  Use \ref cs_mesh_location_get_elt_ids_try or
838  * \ref cs_mesh_location_get_elt_ids instead.
839  *
840  * \param[in]  id  id of mesh location
841  *
842  * \return  pointer to elements array (0 to n-1 numbering).
843  */
844 /*----------------------------------------------------------------------------*/
845 
846 const cs_lnum_t *
cs_mesh_location_get_elt_list(int id)847 cs_mesh_location_get_elt_list(int id)
848 {
849   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
850 
851   return ml->elt_list;
852 }
853 
854 /*----------------------------------------------------------------------------*/
855 /*!
856  * \brief  Get a mesh location's element ids, if present.
857  *
858  * An array of element ids is returned if the location is a subset of a main
859  * main location type, and NULL is returned when the id array would map to
860  * the identity function (i.e. {0, 1, 2, ..., n_elts-1}).
861  *
862  * \param[in]  id  id of mesh location
863  *
864  * \return  pointer to elements array (0 to n-1 numbering).
865  */
866 /*----------------------------------------------------------------------------*/
867 
868 const cs_lnum_t *
cs_mesh_location_get_elt_ids_try(int id)869 cs_mesh_location_get_elt_ids_try(int id)
870 {
871   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
872 
873   return ml->elt_list;
874 }
875 
876 /*----------------------------------------------------------------------------*/
877 /*!
878  * \brief  Get a mesh location's element ids.
879  *
880  * This function may only be used with a given location if
881  * \ref cs_mesh_location_set_explicit_ids has been used to indicate
882  * explicit ids are needed for this location type.
883  *
884  * \param[in]  id  id of mesh location
885  *
886  * \return  pointer to elements array (0 to n-1 numbering).
887  */
888 /*----------------------------------------------------------------------------*/
889 
890 const cs_lnum_t *
cs_mesh_location_get_elt_ids(int id)891 cs_mesh_location_get_elt_ids(int id)
892 {
893   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
894 
895   if (! (   ml->explicit_ids
896          || (_mesh_location + ml->type)->explicit_ids))
897     bft_error(__FILE__, __LINE__, 0,
898               _("Explicit ids have not been built for mesh location %d\n"
899                 "or its base type.\n"
900                 "Use cs_mesh_location_set_explicit_ids."), id);
901 
902   const cs_lnum_t *retval = ml->elt_list;
903   if (retval == NULL && ml->n_elts[0] != 0)
904     retval = _explicit_ids;
905 
906   return retval;
907 }
908 
909 /*----------------------------------------------------------------------------*/
910 /*!
911  * \brief Get a mesh location's definition method.
912  *
913  * \param[in]  id  id of mesh location
914  *
915  * \return  enum value corresponding to the definition method
916  */
917 /*----------------------------------------------------------------------------*/
918 
919 cs_mesh_location_def_t
cs_mesh_location_get_definition_method(int id)920 cs_mesh_location_get_definition_method(int id)
921 {
922 
923   cs_mesh_location_def_t ml_def = CS_MESH_LOCATION_DEF_NONE;
924 
925   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
926 
927   if (ml->select_str != NULL)
928     ml_def = CS_MESH_LOCATION_DEF_SELECTION_STR;
929   else if (ml->select_fp != NULL)
930     ml_def = CS_MESH_LOCATION_DEF_SELECTION_FUNC;
931   else if (ml->sub_ids != NULL && ml->n_sub_ids > 0)
932     ml_def = CS_MESH_LOCATION_DEF_UNION;
933 
934   return ml_def;
935 }
936 
937 /*----------------------------------------------------------------------------*/
938 /*!
939  * \brief  Get a mesh location's selection criteria string
940  *
941  * \param[in]  id  id of mesh location
942  *
943  * \return  pointer to mesh location selection criteria, or NULL
944  */
945 /*----------------------------------------------------------------------------*/
946 
947 const char *
cs_mesh_location_get_selection_string(int id)948 cs_mesh_location_get_selection_string(int  id)
949 {
950   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
951 
952   return ml->select_str;
953 }
954 
955 /*----------------------------------------------------------------------------*/
956 /*!
957  * \brief  Get a mesh location's selection function pointer
958  *
959  * \param[in]  id  id of mesh location
960  *
961  * \return  pointer to mesh location selection function pointer, or NULL
962  */
963 /*----------------------------------------------------------------------------*/
964 
965 cs_mesh_location_select_t *
cs_mesh_location_get_selection_function(int id)966 cs_mesh_location_get_selection_function(int  id)
967 {
968   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
969 
970   return ml->select_fp;
971 }
972 
973 /*----------------------------------------------------------------------------*/
974 /*!
975  * \brief Get a mesh location's number of sub ids
976  *
977  * \param[in]  id  id of mesh location
978  *
979  * \return integer value equal to the number of sub ids
980  */
981 /*----------------------------------------------------------------------------*/
982 
983 int
cs_mesh_location_get_n_sub_ids(int id)984 cs_mesh_location_get_n_sub_ids(int id)
985 {
986 
987   const cs_mesh_location_t *ml = _const_mesh_location_by_id(id);
988 
989   return ml->n_sub_ids;
990 }
991 
992 /*----------------------------------------------------------------------------*/
993 /*!
994  * \brief Get a mesh location's list of sub ids.
995  *
996  * \param[in]  id  id of mesh location
997  *
998  * \return pointer to the list of sub ids.
999  */
1000 /*----------------------------------------------------------------------------*/
1001 
1002 int *
cs_mesh_location_get_sub_ids(int id)1003 cs_mesh_location_get_sub_ids(int id)
1004 {
1005 
1006   const cs_mesh_location_t *ml = _const_mesh_location_by_id(id);
1007 
1008   return ml->sub_ids;
1009 }
1010 
1011 /*----------------------------------------------------------------------------*/
1012 /*!
1013  * \brief Check if a mesh location is built as a complement of other mesh
1014  * locations.
1015  *
1016  * \param[in]  id  id of mesh location
1017  *
1018  * \return true if build method is a complement, false otherwise.
1019  */
1020 /*----------------------------------------------------------------------------*/
1021 
1022 bool
cs_mesh_location_is_complement(int id)1023 cs_mesh_location_is_complement(int id)
1024 {
1025 
1026   const cs_mesh_location_t *ml = _const_mesh_location_by_id(id);
1027 
1028   return ml->complement;
1029 }
1030 
1031 /*----------------------------------------------------------------------------*/
1032 /*!
1033  * \brief  Check if \ref cs_mesh_location_get_elt_ids always returns
1034  *         explicit element ids for a given mesh location type.
1035  *
1036  * \param[in]  id  id or type of location
1037  *
1038  * \return true if explicit element ids are needed, false otherwise
1039  */
1040 /*----------------------------------------------------------------------------*/
1041 
1042 bool
cs_mesh_location_get_explicit_ids(int id)1043 cs_mesh_location_get_explicit_ids(int id)
1044 {
1045   const cs_mesh_location_t  *ml = _const_mesh_location_by_id(id);
1046   return ml->explicit_ids;
1047 }
1048 
1049 /*----------------------------------------------------------------------------*/
1050 /*!
1051  * \brief  Set behavior of \ref cs_mesh_location_get_elt_ids for mesh
1052  *         mesh location type.
1053  *
1054  * \param[in]  id                id or type of location
1055  * \param[in]  explicit_elt_ids  indicate if explicit element ids are needed
1056  */
1057 /*----------------------------------------------------------------------------*/
1058 
1059 void
cs_mesh_location_set_explicit_ids(int id,bool explicit_elt_ids)1060 cs_mesh_location_set_explicit_ids(int   id,
1061                                   bool  explicit_elt_ids)
1062 {
1063   cs_mesh_location_t  *ml = _mesh_location_by_id(id);
1064   ml->explicit_ids = explicit_elt_ids;
1065 }
1066 
1067 /*----------------------------------------------------------------------------*/
1068 
1069 END_C_DECLS
1070