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