1 /*============================================================================
2  * \file Define cs_mesh_t fields from cs_mesh_builder_t fields.
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 #include <limits.h>
38 #include <math.h>
39 #include <assert.h>
40 
41 /*----------------------------------------------------------------------------
42  *  Local headers
43  *----------------------------------------------------------------------------*/
44 
45 #include "bft_mem.h"
46 #include "bft_printf.h"
47 
48 #include "fvm_io_num.h"
49 #include "fvm_periodicity.h"
50 
51 #include "cs_base.h"
52 #include "cs_all_to_all.h"
53 #include "cs_block_dist.h"
54 #include "cs_block_to_part.h"
55 #include "cs_mesh.h"
56 #include "cs_mesh_builder.h"
57 #include "cs_order.h"
58 #include "cs_partition.h"
59 
60 /*----------------------------------------------------------------------------
61  *  Header for the current file
62  *----------------------------------------------------------------------------*/
63 
64 #include "cs_mesh_from_builder.h"
65 
66 /*----------------------------------------------------------------------------*/
67 
68 BEGIN_C_DECLS
69 
70 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
71 
72 /*=============================================================================
73  * Local Macro Definitions
74  *============================================================================*/
75 
76 /*============================================================================
77  * Local Type definitions
78  *============================================================================*/
79 
80 typedef double  _vtx_coords_t[3];
81 
82 /*=============================================================================
83  * Local Macro definitions
84  *============================================================================*/
85 
86 /*============================================================================
87  * Static global variables
88  *============================================================================*/
89 
90 /*=============================================================================
91  * Private function definitions
92  *============================================================================*/
93 
94 #if defined(HAVE_MPI)
95 
96 /*----------------------------------------------------------------------------
97  * Mark faces by type (0 for interior, 1 for exterior faces with outwards
98  * pointing normal, 2 for exterior faces with inwards pointing normal,
99  * 3 for isolated faces) in parallel mode.
100  *
101  * The mesh structure is also updated with face counts and connectivity sizes.
102  *
103  * parameters:
104  *   mesh              <-> pointer to mesh structure
105  *   n_faces           <-- number of local faces
106  *   face_ifs          <-- parallel and periodic faces interfaces set
107  *   face_cell         <-- local face -> cell connectivity
108  *   face_vertices_idx <-- local face -> vertices index
109  *   face_type         --> face type marker
110  *----------------------------------------------------------------------------*/
111 
112 static void
_face_type_g(cs_mesh_t * mesh,cs_lnum_t n_faces,const cs_interface_set_t * face_ifs,const cs_lnum_2_t face_cell[],const cs_lnum_t face_vertices_idx[],char face_type[])113 _face_type_g(cs_mesh_t                 *mesh,
114              cs_lnum_t                  n_faces,
115              const cs_interface_set_t  *face_ifs,
116              const cs_lnum_2_t          face_cell[],
117              const cs_lnum_t            face_vertices_idx[],
118              char                       face_type[])
119 {
120   cs_lnum_t i;
121   int j;
122 
123   const int n_interfaces = cs_interface_set_size(face_ifs);
124 
125   /* Mark base interior faces */
126 
127   for (i = 0; i < n_faces; i++) {
128     if (face_cell[i][0] > -1 && face_cell[i][1] > -1)
129       face_type[i] = '\0';
130     else if (face_cell[i][0] > -1)
131       face_type[i] = '\1';
132     else if (face_cell[i][1] > -1)
133       face_type[i] = '\2';
134     else {
135       face_type[i] = '\3';
136     }
137   }
138 
139   /* Also mark parallel and periodic faces as interior */
140 
141   for (j = 0; j < n_interfaces; j++) {
142 
143     const cs_interface_t *face_if = cs_interface_set_get(face_ifs, j);
144     cs_lnum_t face_if_size = cs_interface_size(face_if);
145     const cs_lnum_t *loc_id = cs_interface_get_elt_ids(face_if);
146 
147     for (i = 0; i < face_if_size; i++)
148       face_type[loc_id[i]] = '\0';
149 
150   }
151 
152   /* Now count faces of each type */
153 
154   mesh->n_i_faces = 0;
155   mesh->n_b_faces = 0;
156   mesh->i_face_vtx_connect_size = 0;
157   mesh->b_face_vtx_connect_size = 0;
158 
159   for (i = 0; i < n_faces; i++) {
160     cs_lnum_t n_f_vertices = face_vertices_idx[i+1] - face_vertices_idx[i];
161     if (face_type[i] == '\0') {
162       mesh->n_i_faces += 1;
163       mesh->i_face_vtx_connect_size += n_f_vertices;
164     }
165     else {
166       mesh->n_b_faces += 1;
167       mesh->b_face_vtx_connect_size += n_f_vertices;
168     }
169   }
170 }
171 
172 #endif /* defined(HAVE_MPI) */
173 
174 /*----------------------------------------------------------------------------
175  * Mark faces by type (0 for interior, 1 for exterior faces with outwards
176  * pointing normal, 2 for exterior faces with inwards pointing normal,
177  * 3 for isolated faces) in serial mode.
178  *
179  * The mesh structure is also updated with face counts and connectivity sizes.
180  *
181  * parameters:
182  *   mesh               <-> pointer to mesh structure
183  *   n_faces            <-- number of local faces
184  *   n_periodic_couples <-- number of periodic couples associated with
185  *                          each periodic list
186  *   periodic_couples   <-- array indicating periodic couples (using
187  *                          global numberings) for each list
188  *   face_cell          <-- local face -> cell connectivity
189  *   face_vertices_idx  <-- local face -> vertices index
190  *   face_type          --> face type marker
191  *----------------------------------------------------------------------------*/
192 
193 static void
_face_type_l(cs_mesh_t * mesh,cs_lnum_t n_faces,const cs_lnum_t n_periodic_couples[],const cs_gnum_t * const periodic_couples[],const cs_lnum_2_t face_cell[],const cs_lnum_t face_vertices_idx[],char face_type[])194 _face_type_l(cs_mesh_t                  *mesh,
195              cs_lnum_t                   n_faces,
196              const cs_lnum_t             n_periodic_couples[],
197              const cs_gnum_t      *const periodic_couples[],
198              const cs_lnum_2_t           face_cell[],
199              const cs_lnum_t             face_vertices_idx[],
200              char                        face_type[])
201 {
202   cs_lnum_t i;
203   int j;
204 
205   /* Mark base interior faces */
206 
207   for (i = 0; i < n_faces; i++) {
208     if (face_cell[i][0] > -1 && face_cell[i][1] > -1)
209       face_type[i] = '\0';
210     else if (face_cell[i][0] > -1)
211       face_type[i] = '\1';
212     else if (face_cell[i][1] > -1)
213       face_type[i] = '\2';
214     else
215       face_type[i] = '\3';
216   }
217 
218   /* Also mark parallel and periodic faces as interior */
219 
220   for (i = 0; i < mesh->n_init_perio; i++) {
221 
222     const cs_gnum_t *p_couples = periodic_couples[i];
223 
224     for (j = 0; j < n_periodic_couples[i]; j++) {
225       face_type[p_couples[j*2] - 1] = '\0';
226       face_type[p_couples[j*2 + 1] - 1] = '\0';
227     }
228 
229   }
230 
231   /* Now count faces of each type */
232 
233   mesh->n_i_faces = 0;
234   mesh->n_b_faces = 0;
235   mesh->i_face_vtx_connect_size = 0;
236   mesh->b_face_vtx_connect_size = 0;
237 
238   for (i = 0; i < n_faces; i++) {
239     cs_lnum_t n_f_vertices = face_vertices_idx[i+1] - face_vertices_idx[i];
240     if (face_type[i] == '\0') {
241       mesh->n_i_faces += 1;
242       mesh->i_face_vtx_connect_size += n_f_vertices;
243     }
244     else {
245       mesh->n_b_faces += 1;
246       mesh->b_face_vtx_connect_size += n_f_vertices;
247     }
248   }
249 
250   mesh->n_g_i_faces = mesh->n_i_faces;
251   mesh->n_g_b_faces = mesh->n_b_faces;
252 }
253 
254 /*----------------------------------------------------------------------------
255  * Build internal and boundary face -> cell connectivity using a common
256  * face -> cell connectivity and a face type marker.
257  *
258  * At this stage, isolated faces, if present, are considered to be
259  * boundary faces, as they may participate in future mesh joining
260  * operations. Their matching cell number will be set to -1.
261  * Remaining isolated faces should be removed before completing
262  * the mesh structure.
263  *
264  * The corresponding arrays in the mesh structure are allocated and
265  * defined by this function, and should have been previously empty.
266  *
267  * parameters:
268  *   mesh      <-> pointer to mesh structure
269  *   n_faces   <-- number of local faces
270  *   face_cell <-- local face -> cell connectivity
271  *   face_type <-- face type marker
272  *----------------------------------------------------------------------------*/
273 
274 static void
_extract_face_cell(cs_mesh_t * mesh,cs_lnum_t n_faces,const cs_lnum_2_t face_cell[],const char face_type[])275 _extract_face_cell(cs_mesh_t         *mesh,
276                    cs_lnum_t          n_faces,
277                    const cs_lnum_2_t  face_cell[],
278                    const char         face_type[])
279 {
280   cs_lnum_t i;
281 
282   size_t n_i_faces = 0;
283   size_t n_b_faces = 0;
284 
285   /* Allocate arrays */
286 
287   BFT_MALLOC(mesh->i_face_cells, mesh->n_i_faces, cs_lnum_2_t);
288   BFT_MALLOC(mesh->b_face_cells, mesh->n_b_faces, cs_lnum_t);
289 
290   /* Now copy face -> cell connectivity */
291 
292   for (i = 0; i < n_faces; i++) {
293 
294     if (face_type[i] == '\0') {
295       mesh->i_face_cells[n_i_faces][0] = face_cell[i][0];
296       mesh->i_face_cells[n_i_faces][1] = face_cell[i][1];
297       n_i_faces++;
298     }
299 
300     else if (face_type[i] == '\1') {
301       mesh->b_face_cells[n_b_faces] = face_cell[i][0];
302       n_b_faces++;
303     }
304 
305     else if (face_type[i] == '\2') {
306       mesh->b_face_cells[n_b_faces] = face_cell[i][1];
307       n_b_faces++;
308     }
309 
310     else if (face_type[i] == '\3') {
311       mesh->b_face_cells[n_b_faces] = -1;
312       mesh->n_g_free_faces += 1;
313       n_b_faces++;
314     }
315   }
316 }
317 
318 /*----------------------------------------------------------------------------
319  * Build internal and boundary face -> vertices connectivity using a common
320  * face -> vertices connectivity and a face type marker.
321  *
322  * The corresponding arrays in the mesh structure are allocated and
323  * defined by this function, and should have been previously empty.
324  *
325  * parameters:
326  *   mesh              <-> pointer to mesh structure
327  *   n_faces           <-- number of local faces
328  *   face_vertices_idx <-- local face -> vertices index
329  *   face_vertices     <-- local face -> vertices connectivity
330  *   face_type         <-- face type marker
331  *----------------------------------------------------------------------------*/
332 
333 static void
_extract_face_vertices(cs_mesh_t * mesh,cs_lnum_t n_faces,const cs_lnum_t face_vertices_idx[],const cs_lnum_t face_vertices[],const char face_type[])334 _extract_face_vertices(cs_mesh_t         *mesh,
335                        cs_lnum_t          n_faces,
336                        const cs_lnum_t    face_vertices_idx[],
337                        const cs_lnum_t    face_vertices[],
338                        const char         face_type[])
339 {
340   cs_lnum_t i;
341   size_t j;
342 
343   size_t n_i_faces = 0;
344   size_t n_b_faces = 0;
345 
346   /* Allocate and initialize */
347 
348   BFT_MALLOC(mesh->i_face_vtx_idx, mesh->n_i_faces+1, cs_lnum_t);
349   BFT_MALLOC(mesh->i_face_vtx_lst, mesh->i_face_vtx_connect_size, cs_lnum_t);
350 
351   mesh->i_face_vtx_idx[0] = 0;
352 
353   BFT_MALLOC(mesh->b_face_vtx_idx, mesh->n_b_faces+1, cs_lnum_t);
354   mesh->b_face_vtx_idx[0] = 0;
355 
356   if (mesh->n_b_faces > 0)
357     BFT_MALLOC(mesh->b_face_vtx_lst, mesh->b_face_vtx_connect_size, cs_lnum_t);
358 
359   /* Now copy face -> vertices connectivity */
360 
361   for (i = 0; i < n_faces; i++) {
362 
363     size_t n_f_vertices = face_vertices_idx[i+1] - face_vertices_idx[i];
364     const cs_lnum_t *_face_vtx = face_vertices + face_vertices_idx[i];
365 
366     if (face_type[i] == '\0') {
367       cs_lnum_t *_i_face_vtx =   mesh->i_face_vtx_lst
368                                + mesh->i_face_vtx_idx[n_i_faces];
369       for (j = 0; j < n_f_vertices; j++)
370         _i_face_vtx[j] = _face_vtx[j] - 1;
371       mesh->i_face_vtx_idx[n_i_faces + 1] =   mesh->i_face_vtx_idx[n_i_faces]
372                                             + n_f_vertices;
373       n_i_faces++;
374     }
375 
376     else if (face_type[i] == '\1' || face_type[i] == '\3') {
377       cs_lnum_t *_b_face_vtx =   mesh->b_face_vtx_lst
378                                + mesh->b_face_vtx_idx[n_b_faces];
379       for (j = 0; j < n_f_vertices; j++)
380         _b_face_vtx[j] = _face_vtx[j] - 1;
381       mesh->b_face_vtx_idx[n_b_faces + 1] =   mesh->b_face_vtx_idx[n_b_faces]
382                                             + n_f_vertices;
383       n_b_faces++;
384     }
385 
386     else if (face_type[i] == '\2') {
387       cs_lnum_t *_b_face_vtx =   mesh->b_face_vtx_lst
388                                + mesh->b_face_vtx_idx[n_b_faces];
389       for (j = 0; j < n_f_vertices; j++)
390         _b_face_vtx[j] = _face_vtx[n_f_vertices - j - 1] - 1;
391       mesh->b_face_vtx_idx[n_b_faces + 1] =   mesh->b_face_vtx_idx[n_b_faces]
392                                             + n_f_vertices;
393       n_b_faces++;
394     }
395 
396   }
397 }
398 
399 #if defined(HAVE_MPI)
400 
401 /*----------------------------------------------------------------------------
402  * Build internal and boundary face -> global numberings using a common
403  * face group class id and a face type marker.
404  *
405  * The corresponding arrays in the mesh structure are allocated and
406  * defined by this function, and should have been previously empty.
407  *
408  * parameters:
409  *   mesh            <-> pointer to mesh structure
410  *   n_faces         <-- number of local faces
411  *   global_face_num <-- global face numbers
412  *   face_type       <-- face type marker
413  *----------------------------------------------------------------------------*/
414 
415 static void
_extract_face_gnum(cs_mesh_t * mesh,cs_lnum_t n_faces,const cs_gnum_t global_face_num[],const char face_type[])416 _extract_face_gnum(cs_mesh_t         *mesh,
417                    cs_lnum_t          n_faces,
418                    const cs_gnum_t    global_face_num[],
419                    const char         face_type[])
420 {
421   cs_lnum_t i;
422 
423   size_t n_i_faces = 0;
424   size_t n_b_faces = 0;
425 
426   cs_lnum_t *global_i_face = NULL;
427   cs_lnum_t *global_b_face = NULL;
428 
429   fvm_io_num_t *tmp_face_num = NULL;
430 
431   /* Allocate arrays (including temporary arrays) */
432 
433   BFT_MALLOC(mesh->global_i_face_num, mesh->n_i_faces, cs_gnum_t);
434   BFT_MALLOC(mesh->global_b_face_num, mesh->n_b_faces, cs_gnum_t);
435 
436   BFT_MALLOC(global_i_face, mesh->n_i_faces, cs_lnum_t);
437   BFT_MALLOC(global_b_face, mesh->n_b_faces, cs_lnum_t);
438 
439   /* Now build internal and boundary face lists */
440 
441   for (i = 0; i < n_faces; i++) {
442 
443     if (face_type[i] == '\0')
444       global_i_face[n_i_faces++] = i+1;
445 
446     else
447       global_b_face[n_b_faces++] = i+1;
448 
449   }
450 
451   /* Build an I/O numbering on internal faces to compact the global numbering */
452 
453   tmp_face_num = fvm_io_num_create(global_i_face,
454                                    global_face_num,
455                                    n_i_faces,
456                                    0);
457 
458   memcpy(mesh->global_i_face_num,
459          fvm_io_num_get_global_num(tmp_face_num),
460          n_i_faces*sizeof(cs_gnum_t));
461 
462   mesh->n_g_i_faces = fvm_io_num_get_global_count(tmp_face_num);
463 
464   assert(fvm_io_num_get_local_count(tmp_face_num) == (cs_lnum_t)n_i_faces);
465 
466   tmp_face_num = fvm_io_num_destroy(tmp_face_num);
467 
468   /* Build an I/O numbering on boundary faces to compact the global numbering */
469 
470   tmp_face_num = fvm_io_num_create(global_b_face,
471                                    global_face_num,
472                                    n_b_faces,
473                                    0);
474 
475   if (n_b_faces > 0)
476     memcpy(mesh->global_b_face_num,
477            fvm_io_num_get_global_num(tmp_face_num),
478            n_b_faces*sizeof(cs_gnum_t));
479 
480   mesh->n_g_b_faces = fvm_io_num_get_global_count(tmp_face_num);
481 
482   assert(fvm_io_num_get_local_count(tmp_face_num) == (cs_lnum_t)n_b_faces);
483 
484   tmp_face_num = fvm_io_num_destroy(tmp_face_num);
485 
486   /* Free remaining temporary arrays */
487 
488   BFT_FREE(global_i_face);
489   BFT_FREE(global_b_face);
490 }
491 
492 #endif /* defined(HAVE_MPI) */
493 
494 /*----------------------------------------------------------------------------
495  * Build internal and boundary face -> group class id using a common
496  * face group class id and a face type marker.
497  *
498  * The corresponding arrays in the mesh structure are allocated and
499  * defined by this function, and should have been previously empty.
500  *
501  * parameters:
502  *   mesh       <-> pointer to mesh structure
503  *   n_faces    <-- number of local faces
504  *   face_gc_id <-- local face group class id
505  *   face_type  <-- face type marker
506  *----------------------------------------------------------------------------*/
507 
508 static void
_extract_face_gc_id(cs_mesh_t * mesh,cs_lnum_t n_faces,const int face_gc_id[],const char face_type[])509 _extract_face_gc_id(cs_mesh_t  *mesh,
510                     cs_lnum_t   n_faces,
511                     const int   face_gc_id[],
512                     const char  face_type[])
513 {
514   cs_lnum_t i;
515 
516   size_t n_i_faces = 0;
517   size_t n_b_faces = 0;
518 
519   /* Allocate arrays */
520 
521   BFT_MALLOC(mesh->i_face_family, mesh->n_i_faces, int);
522   BFT_MALLOC(mesh->b_face_family, mesh->n_b_faces, int);
523 
524   /* Now copy face group class (family) id */
525 
526   for (i = 0; i < n_faces; i++) {
527 
528     assert(face_gc_id[i] > -1 && face_gc_id[i] <= mesh->n_families);
529 
530     if (face_type[i] == '\0')
531       mesh->i_face_family[n_i_faces++] = face_gc_id[i];
532 
533     else
534       mesh->b_face_family[n_b_faces++] = face_gc_id[i];
535 
536   }
537 }
538 
539 /*----------------------------------------------------------------------------
540  * Build internal and boundary face -> refinement generation using a common
541  * face level and a face type marker.
542  *
543  * The corresponding arrays in the mesh structure are allocated and
544  * defined by this function, and should have been previously empty.
545  *
546  * parameters:
547  *   mesh       <-> pointer to mesh structure
548  *   n_faces    <-- number of local faces
549  *   face_r_gen <-- local face level
550  *   face_type  <-- face type marker
551  *----------------------------------------------------------------------------*/
552 
553 static void
_extract_face_r_gen(cs_mesh_t * mesh,cs_lnum_t n_faces,const char face_r_gen[],const char face_type[])554 _extract_face_r_gen(cs_mesh_t        *mesh,
555                     cs_lnum_t         n_faces,
556                     const char        face_r_gen[],
557                     const char        face_type[])
558 {
559   size_t n_i_faces = 0;
560 
561   /* Allocate arrays */
562 
563   BFT_MALLOC(mesh->i_face_r_gen, mesh->n_i_faces, char);
564 
565   /* Now copy face group class (family) id */
566 
567   for (cs_lnum_t i = 0; i < n_faces; i++) {
568     if (face_type[i] == '\0')
569       mesh->i_face_r_gen[n_i_faces++] = face_r_gen[i];
570   }
571 }
572 
573 #if defined(HAVE_MPI)
574 
575 /*----------------------------------------------------------------------------
576  * Renumber face interface references from mixed faces to interior faces.
577  *
578  * parameters:
579  *   face_ifs          <-> parallel and periodic faces interfaces set
580  *   n_faces           <-- number of local faces
581  *   face_type         <-- face type marker
582  *----------------------------------------------------------------------------*/
583 
584 static void
_face_ifs_to_interior(cs_interface_set_t * face_ifs,cs_lnum_t n_faces,const char face_type[])585 _face_ifs_to_interior(cs_interface_set_t  *face_ifs,
586                       cs_lnum_t            n_faces,
587                       const char           face_type[])
588 {
589   cs_lnum_t i;
590 
591   cs_lnum_t   i_face_count = 0;
592   cs_lnum_t  *i_face_id = NULL;
593 
594   /* Build face renumbering */
595 
596   BFT_MALLOC(i_face_id, n_faces, cs_lnum_t);
597 
598   for (i = 0; i < n_faces; i++) {
599     if (face_type[i] == '\0')
600       i_face_id[i] = i_face_count++;
601     else
602       i_face_id[i] = -1;
603   }
604 
605   cs_interface_set_renumber(face_ifs, i_face_id);
606 
607   BFT_FREE(i_face_id);
608 }
609 
610 #endif /* defined(HAVE_MPI) */
611 
612 /*----------------------------------------------------------------------------
613  * Extract periodic face connectivity information for mesh builder when
614  * running in serial mode.
615  *
616  * Arrays are simply transferred from the mesh reader to the builder and
617  * renumbered
618  *
619  * parameters:
620  *   mb            <-> pointer to mesh builder structure
621  *   n_init_perio  <-- number of initial periodicities
622  *   n_faces       <-- number of local faces
623  *   face_type     <-- face type marker
624  *----------------------------------------------------------------------------*/
625 
626 static void
_extract_periodic_faces_l(cs_mesh_builder_t * mb,int n_init_perio,cs_lnum_t n_faces,const char face_type[])627 _extract_periodic_faces_l(cs_mesh_builder_t  *mb,
628                           int                 n_init_perio,
629                           cs_lnum_t           n_faces,
630                           const char          face_type[])
631 {
632   int i;
633 
634   cs_gnum_t   next_face_num = 1;
635   cs_gnum_t  *i_face_num = NULL;
636 
637   /* Transfer arrays from reader to builder, then renumber couples */
638 
639   assert(mb != NULL);
640 
641   mb->n_perio = n_init_perio;
642 
643   /* Build face renumbering */
644 
645   BFT_MALLOC(i_face_num, n_faces, cs_gnum_t);
646 
647   for (i = 0; i < n_faces; i++) {
648     if (face_type[i] == '\0')
649       i_face_num[i] = next_face_num++;
650     else
651       i_face_num[i] = 0;
652   }
653 
654   /* Apply new numbering */
655 
656   for (i = 0; i < n_init_perio; i++) {
657 
658     size_t j;
659     cs_gnum_t *p_couples = mb->per_face_couples[i];
660     const size_t n_vals = mb->n_per_face_couples[i] * 2;
661 
662     for (j = 0; j < n_vals; j++) {
663       p_couples[j] = i_face_num[p_couples[j] - 1];
664       assert(p_couples[j] > 0);
665     }
666   }
667 
668   BFT_FREE(i_face_num);
669 }
670 
671 #if defined(HAVE_MPI)
672 
673 /*----------------------------------------------------------------------------
674  * Compute free (isolated) face centers using minimal local data.
675  *
676  * parameters:
677  *   n_f_faces     <-- number of faces
678  *   f_face_ids    <-- list of free faces
679  *   face_vtx_idx  <-- face -> vertices connectivity index
680  *   face_vtx      <-- face -> vertices connectivity
681  *   vtx_coord     <-- vertex coordinates
682  *   f_face_center --> free face centers
683  *----------------------------------------------------------------------------*/
684 
685 static void
_f_face_center(cs_lnum_t n_f_faces,cs_lnum_t f_face_ids[],const cs_lnum_t face_vtx_idx[],const cs_lnum_t face_vtx[],const cs_real_t vtx_coord[],cs_coord_t f_face_center[])686 _f_face_center(cs_lnum_t         n_f_faces,
687                cs_lnum_t         f_face_ids[],
688                const cs_lnum_t   face_vtx_idx[],
689                const cs_lnum_t   face_vtx[],
690                const cs_real_t   vtx_coord[],
691                cs_coord_t        f_face_center[])
692 {
693   cs_lnum_t i, j, k;
694   cs_lnum_t vtx_id, start_id, end_id;
695   cs_lnum_t n_face_vertices;
696   cs_coord_t ref_normal[3], vtx_cog[3];
697 
698   cs_lnum_t n_max_face_vertices = 0;
699 
700   _vtx_coords_t *face_vtx_coord = NULL;
701 
702   const double surf_epsilon = 1e-24;
703 
704   assert(face_vtx_idx[0] == 0);
705 
706   for (i = 0; i < n_f_faces; i++) {
707     for (j = 0; j < 3; j++)
708       f_face_center[i*3 + j] = 0.0;
709   }
710 
711   /* Counting and allocation */
712 
713   n_max_face_vertices = 0;
714 
715   for (k = 0; k < n_f_faces; k++) {
716     cs_lnum_t face_id = f_face_ids[k];
717     n_face_vertices = face_vtx_idx[face_id + 1] - face_vtx_idx[face_id];
718     if (n_max_face_vertices <= n_face_vertices)
719       n_max_face_vertices = n_face_vertices;
720   }
721 
722   BFT_MALLOC(face_vtx_coord, n_max_face_vertices, _vtx_coords_t);
723 
724   /* Loop on each face */
725 
726   for (k = 0; k < n_f_faces; k++) {
727 
728     cs_lnum_t tri_id;
729 
730     /* Initialization */
731 
732     cs_lnum_t face_id = f_face_ids[k];
733     cs_coord_t unweighted_center[3] = {0.0, 0.0, 0.0};
734     cs_coord_t face_surface = 0.0;
735     cs_coord_t *face_center = f_face_center + (k*3);
736 
737     n_face_vertices = 0;
738 
739     start_id = face_vtx_idx[face_id];
740     end_id = face_vtx_idx[face_id + 1];
741 
742     /* Define the polygon (P) according to the vertices (Pi) of the face */
743 
744     for (vtx_id = start_id; vtx_id < end_id; vtx_id++) {
745 
746       cs_lnum_t shift = 3 * (face_vtx[vtx_id]);
747       for (i = 0; i < 3; i++)
748         face_vtx_coord[n_face_vertices][i] = vtx_coord[shift + i];
749       n_face_vertices++;
750 
751     }
752 
753     /* Compute the barycenter of the face vertices */
754 
755     for (i = 0; i < 3; i++) {
756       vtx_cog[i] = 0.0;
757       for (vtx_id = 0; vtx_id < n_face_vertices; vtx_id++)
758         vtx_cog[i] += face_vtx_coord[vtx_id][i];
759       vtx_cog[i] /= n_face_vertices;
760     }
761 
762     /* Loop on the triangles of the face (defined by an edge of the face
763        and its barycenter) */
764 
765     for (i = 0; i < 3; i++) {
766       ref_normal[i] = 0.;
767       face_center[i] = 0.0;
768     }
769 
770     for (tri_id = 0 ; tri_id < n_face_vertices ; tri_id++) {
771 
772       cs_coord_t tri_surface;
773       cs_coord_t vect1[3], vect2[3], tri_normal[3], tri_center[3];
774 
775       cs_lnum_t id0 = tri_id;
776       cs_lnum_t id1 = (tri_id + 1)%n_face_vertices;
777 
778       /* Normal for each triangle */
779 
780       for (i = 0; i < 3; i++) {
781         vect1[i] = face_vtx_coord[id0][i] - vtx_cog[i];
782         vect2[i] = face_vtx_coord[id1][i] - vtx_cog[i];
783       }
784 
785       tri_normal[0] = vect1[1] * vect2[2] - vect2[1] * vect1[2];
786       tri_normal[1] = vect2[0] * vect1[2] - vect1[0] * vect2[2];
787       tri_normal[2] = vect1[0] * vect2[1] - vect2[0] * vect1[1];
788 
789       if (tri_id == 0) {
790         for (i = 0; i < 3; i++)
791           ref_normal[i] = tri_normal[i];
792       }
793 
794       /* Center of gravity for a triangle */
795 
796       for (i = 0; i < 3; i++) {
797         tri_center[i] = (  vtx_cog[i]
798                          + face_vtx_coord[id0][i]
799                          + face_vtx_coord[id1][i]) / 3.0;
800       }
801 
802       tri_surface = sqrt(  tri_normal[0]*tri_normal[0]
803                          + tri_normal[1]*tri_normal[1]
804                          + tri_normal[2]*tri_normal[2]) * 0.5;
805 
806       if ((  tri_normal[0]*ref_normal[0]
807            + tri_normal[1]*ref_normal[1]
808            + tri_normal[2]*ref_normal[2]) < 0.0)
809         tri_surface *= -1.0;
810 
811       /* Now compute contribution to face center and surface */
812 
813       face_surface += tri_surface;
814 
815       for (i = 0; i < 3; i++) {
816         face_center[i] += tri_surface * tri_center[i];
817         unweighted_center[i] = tri_center[i];
818       }
819 
820     } /* End of loop  on triangles of the face */
821 
822     if (face_surface > surf_epsilon) {
823       for (i = 0; i < 3; i++)
824         face_center[i] /= face_surface;
825     }
826     else {
827       face_surface = surf_epsilon;
828       for (i = 0; i < 3; i++)
829         face_center[i] = unweighted_center[i] * face_surface / n_face_vertices;
830     }
831   } /* End of loop on faces */
832 
833   BFT_FREE(face_vtx_coord);
834 }
835 
836 /*----------------------------------------------------------------------------
837  * Compute face centers using block data.
838  *
839  * parameters:
840  *   mb          <-- pointer to mesh builder helper structure
841  *   n_f_faces   <-- local number of free faces
842  *   f_face_ids  <-- free face ids
843  *   face_center --> cell centers array
844  *   comm        <-- associated MPI communicator
845  *----------------------------------------------------------------------------*/
846 
847 static void
_precompute_free_face_center(const cs_mesh_builder_t * mb,cs_lnum_t n_f_faces,cs_lnum_t f_face_ids[],cs_coord_t f_face_center[],MPI_Comm comm)848 _precompute_free_face_center(const cs_mesh_builder_t  *mb,
849                              cs_lnum_t                 n_f_faces,
850                              cs_lnum_t                 f_face_ids[],
851                              cs_coord_t                f_face_center[],
852                              MPI_Comm                  comm)
853 {
854   int n_ranks = 0;
855 
856   cs_datatype_t real_type = (sizeof(cs_real_t) == 8) ? CS_DOUBLE : CS_FLOAT;
857 
858   cs_lnum_t _n_faces = 0;
859 
860   cs_lnum_t *_face_vertices = NULL;
861 
862   /* Initialization */
863 
864   MPI_Comm_size(comm, &n_ranks);
865 
866   assert((sizeof(cs_lnum_t) == 4) || (sizeof(cs_lnum_t) == 8));
867 
868   _n_faces = mb->face_bi.gnum_range[1] - mb->face_bi.gnum_range[0];
869 
870   /* Distribute vertices */
871   /*---------------------*/
872 
873   size_t _n_vertices = 0;
874   cs_gnum_t *_vtx_num = NULL;
875 
876   cs_order_single_gnum(mb->face_vertices_idx[_n_faces],
877                        1, /* base */
878                        mb->face_vertices,
879                        &_n_vertices,
880                        &_vtx_num);
881 
882   cs_all_to_all_t *d
883     = cs_all_to_all_create_from_block(_n_vertices,
884                                       CS_ALL_TO_ALL_USE_DEST_ID,
885                                       _vtx_num,
886                                       mb->vertex_bi,
887                                       comm);
888 
889   cs_real_t *_vtx_coord
890     = cs_all_to_all_copy_array(d,
891                                real_type,
892                                3,
893                                true, /* reverse */
894                                mb->vertex_coords,
895                                NULL);
896 
897   cs_all_to_all_destroy(&d);
898 
899   /* Now convert face -> vertex connectivity to local vertex numbers */
900 
901   BFT_MALLOC(_face_vertices, mb->face_vertices_idx[_n_faces], cs_lnum_t);
902 
903   cs_block_to_part_global_to_local(mb->face_vertices_idx[_n_faces],
904                                    1,
905                                    _n_vertices,
906                                    true,
907                                    _vtx_num,
908                                    mb->face_vertices,
909                                    _face_vertices);
910 
911   _f_face_center(n_f_faces,
912                  f_face_ids,
913                  mb->face_vertices_idx,
914                  _face_vertices,
915                  _vtx_coord,
916                  f_face_center);
917 
918   BFT_FREE(_vtx_coord);
919   BFT_FREE(_vtx_num);
920   BFT_FREE(_face_vertices);
921 }
922 
923 /*----------------------------------------------------------------------------
924  * Compute default face destination rank array in case of isolated faces.
925  *
926  * parameters:
927  *   mb           <-- pointer to mesh builder helper structure
928  *   comm         <-- associated MPI communicator
929  *
930  * returns:
931  *  default rank array for faces (>= for isolated faces)
932  *----------------------------------------------------------------------------*/
933 
934 static int *
_default_face_rank(const cs_mesh_builder_t * mb,MPI_Comm comm)935 _default_face_rank(const cs_mesh_builder_t  *mb,
936                    MPI_Comm                  comm)
937 {
938   cs_lnum_t i;
939   cs_block_dist_info_t free_face_bi;
940 
941   int n_ranks = 0, rank_id = -1;
942 
943   cs_lnum_t _n_faces = 0, n_free_faces = 0;
944   cs_gnum_t _n_g_free_faces = 0, n_g_free_faces = 0;
945 
946   cs_lnum_t *free_face_ids = NULL;
947   cs_coord_t *free_face_centers = NULL;
948 
949   fvm_io_num_t *free_face_io_num = NULL;
950   const cs_gnum_t *free_face_num = NULL;
951 
952   int *default_rank = NULL;
953 
954   /* Initialization */
955 
956   assert((sizeof(cs_lnum_t) == 4) || (sizeof(cs_lnum_t) == 8));
957 
958   /* Count number of isolated faces */
959 
960   _n_faces = mb->face_bi.gnum_range[1] - mb->face_bi.gnum_range[0];
961   n_free_faces = 0;
962 
963   for (i = 0; i < _n_faces; i++) {
964     if (mb->face_cells[2*i] == 0 && mb->face_cells[2*i+1] == 0)
965       n_free_faces += 1;
966   }
967 
968   _n_g_free_faces = n_free_faces;
969   MPI_Allreduce(&_n_g_free_faces, &n_g_free_faces, 1,
970                 CS_MPI_GNUM, MPI_SUM, comm);
971 
972   /* Return if we do not have isolated faces */
973 
974   if (n_g_free_faces == 0)
975     return NULL;
976 
977   /* Initialize rank info */
978 
979   MPI_Comm_size(comm, &n_ranks);
980   MPI_Comm_size(comm, &rank_id);
981   free_face_bi = cs_block_dist_compute_sizes(rank_id,
982                                              n_ranks,
983                                              0,
984                                              0,
985                                              n_g_free_faces);
986 
987   /* Define distribution of isolated faces based on sfc;
988    *
989    *  As those faces are not connected, the main objective of this function
990    *  is to ensure some measure of load balancing. */
991 
992   BFT_MALLOC(default_rank, _n_faces, int);
993   for (i = 0; i < _n_faces; i++)
994     default_rank[i] = -1;
995 
996   BFT_MALLOC(free_face_ids, n_free_faces, cs_lnum_t);
997   BFT_MALLOC(free_face_centers, n_free_faces*3, cs_coord_t);
998 
999   n_free_faces = 0;
1000   for (i = 0; i < _n_faces; i++) {
1001     if (mb->face_cells[2*i] == 0 && mb->face_cells[2*i+1] == 0)
1002       free_face_ids[n_free_faces++] = i;
1003   }
1004 
1005   _precompute_free_face_center(mb,
1006                                n_free_faces,
1007                                free_face_ids,
1008                                free_face_centers,
1009                                comm);
1010 
1011   free_face_io_num = fvm_io_num_create_from_sfc(free_face_centers,
1012                                                 3,
1013                                                 n_free_faces,
1014                                                 FVM_IO_NUM_SFC_MORTON_BOX);
1015 
1016   BFT_FREE(free_face_centers);
1017 
1018   free_face_num = fvm_io_num_get_global_num(free_face_io_num);
1019 
1020   /* Determine rank based on global numbering with SFC ordering */
1021   for (i = 0; i < n_free_faces; i++) {
1022     default_rank[free_face_ids[i]]
1023       =    ((free_face_num[i] - 1) / free_face_bi.block_size)
1024          * free_face_bi.rank_step;
1025   }
1026 
1027   free_face_io_num = fvm_io_num_destroy(free_face_io_num);
1028   BFT_FREE(free_face_ids);
1029 
1030   return default_rank;
1031 }
1032 
1033 /*----------------------------------------------------------------------------
1034  * Organize data read by blocks in parallel and build most mesh structures.
1035  *
1036  * parameters:
1037  *   mesh    <-> pointer to mesh structure
1038  *   mb      <-> pointer to mesh builder structure
1039  *   comm    <-- associated MPI communicator
1040  *----------------------------------------------------------------------------*/
1041 
1042 static void
_decompose_data_g(cs_mesh_t * mesh,cs_mesh_builder_t * mb,MPI_Comm comm)1043 _decompose_data_g(cs_mesh_t          *mesh,
1044                   cs_mesh_builder_t  *mb,
1045                   MPI_Comm            comm)
1046 {
1047   int n_ranks = 0;
1048 
1049   cs_datatype_t real_type = (sizeof(cs_real_t) == 8) ? CS_DOUBLE : CS_FLOAT;
1050 
1051   cs_lnum_t _n_faces = 0;
1052   cs_gnum_t *_face_num = NULL;
1053   cs_gnum_t *_face_gcells = NULL;
1054   cs_gnum_t *_face_gvertices = NULL;
1055 
1056   cs_lnum_2_t *_face_cells = NULL;
1057   int  *_face_gc_id = NULL;
1058   char *_face_r_gen = NULL;
1059   cs_lnum_t *_face_vertices_idx = NULL;
1060   cs_lnum_t *_face_vertices = NULL;
1061 
1062   int *_periodicity_num = NULL;
1063 
1064   int  *default_face_rank = NULL;
1065   char *face_type = NULL;
1066   cs_interface_set_t *face_ifs = NULL;
1067 
1068   /* Initialization */
1069 
1070   MPI_Comm_size(comm, &n_ranks);
1071 
1072   assert((sizeof(cs_lnum_t) == 4) || (sizeof(cs_lnum_t) == 8));
1073 
1074   /* Different handling of cells depending on whether decomposition
1075      data is available or not. */
1076 
1077   if (mb->have_cell_rank == true) {
1078 
1079     cs_lnum_t n_block_ents = 0;
1080     if (mb->cell_bi.gnum_range[1] > mb->cell_bi.gnum_range[0])
1081       n_block_ents = (mb->cell_bi.gnum_range[1] - mb->cell_bi.gnum_range[0]);
1082 
1083     cs_all_to_all_t *d
1084       = cs_all_to_all_create(n_block_ents,
1085                              CS_ALL_TO_ALL_ORDER_BY_SRC_RANK,   /* flags */
1086                              NULL,
1087                              mb->cell_rank,
1088                              comm);
1089 
1090     mesh->n_cells = cs_all_to_all_n_elts_dest(d);
1091 
1092     cs_gnum_t *b_global_num;
1093     BFT_MALLOC(b_global_num, n_block_ents, cs_gnum_t);
1094 
1095     mesh->cell_family = cs_all_to_all_copy_array(d,
1096                                                  CS_INT_TYPE,
1097                                                  1,
1098                                                  false, /* reverse */
1099                                                  mb->cell_gc_id,
1100                                                  NULL);
1101 
1102     BFT_FREE(mb->cell_gc_id);
1103 
1104     cs_gnum_t  gnum_shift = mb->cell_bi.gnum_range[0];
1105     for (cs_lnum_t i = 0; i < n_block_ents; i++)
1106       b_global_num[i] = (cs_gnum_t)i + gnum_shift;
1107 
1108     mesh->global_cell_num = cs_all_to_all_copy_array(d,
1109                                                      CS_GNUM_TYPE,
1110                                                      1,
1111                                                      false, /* reverse */
1112                                                      b_global_num,
1113                                                      NULL);
1114 
1115     BFT_FREE(b_global_num);
1116 
1117     cs_all_to_all_destroy(&d);
1118 
1119   }
1120   else {
1121 
1122     mesh->n_cells = mb->cell_bi.gnum_range[1] - mb->cell_bi.gnum_range[0];
1123 
1124     BFT_MALLOC(mesh->global_cell_num, mesh->n_cells, cs_gnum_t);
1125 
1126     for (cs_lnum_t i = 0; i < mesh->n_cells; i++)
1127       mesh->global_cell_num[i] = mb->cell_bi.gnum_range[0] + i;
1128 
1129     mesh->cell_family = mb->cell_gc_id;
1130     mb->cell_gc_id = NULL;
1131   }
1132 
1133   if (mesh->n_cells == 0)
1134     bft_error(__FILE__, __LINE__, 0,
1135               _("Number of cells on rank %d is zero.\n"
1136                 "(number of cells / number of processes ratio too low)."),
1137               (int)cs_glob_rank_id);
1138 
1139   mesh->n_cells_with_ghosts = mesh->n_cells; /* will be increased later */
1140 
1141   /* Distribute faces */
1142   /*------------------*/
1143 
1144   default_face_rank = _default_face_rank(mb, comm);
1145 
1146   cs_all_to_all_t *d
1147     = cs_block_to_part_create_by_adj_s(comm,
1148                                        mb->face_bi,
1149                                        mb->cell_bi,
1150                                        2,
1151                                        mb->face_cells,
1152                                        mb->cell_rank,
1153                                        default_face_rank,
1154                                        &_n_faces,
1155                                        &_face_num);
1156 
1157   if (default_face_rank != NULL)
1158     BFT_FREE(default_face_rank);
1159 
1160   BFT_FREE(mb->cell_rank); /* Not needed anymore */
1161 
1162   BFT_MALLOC(_face_gcells, _n_faces*2, cs_gnum_t);
1163 
1164   /* Face -> cell connectivity */
1165 
1166   cs_all_to_all_copy_array(d,
1167                            CS_GNUM_TYPE,
1168                            2,
1169                            true,  /* reverse */
1170                            mb->face_cells,
1171                            _face_gcells);
1172 
1173   BFT_FREE(mb->face_cells);
1174 
1175   /* Now convert face -> cell connectivity to local cell numbers */
1176 
1177   BFT_MALLOC(_face_cells, _n_faces, cs_lnum_2_t);
1178 
1179   cs_block_to_part_global_to_local(_n_faces*2,
1180                                    0,
1181                                    mesh->n_cells,
1182                                    true,  /* reverse */
1183                                    mesh->global_cell_num,
1184                                    _face_gcells,
1185                                    (cs_lnum_t *)_face_cells);
1186 
1187   BFT_FREE(_face_gcells);
1188 
1189   /* Face family */
1190 
1191   BFT_MALLOC(_face_gc_id, _n_faces, int);
1192 
1193   cs_all_to_all_copy_array(d,
1194                            CS_INT_TYPE,
1195                            1,
1196                            true,  /* reverse */
1197                            mb->face_gc_id,
1198                            _face_gc_id);
1199 
1200   BFT_FREE(mb->face_gc_id);
1201 
1202   /* Face level */
1203 
1204   BFT_MALLOC(_face_r_gen, _n_faces, char);
1205 
1206   if (mb->have_face_r_gen)
1207     cs_all_to_all_copy_array(d,
1208                              CS_CHAR,
1209                              1,
1210                              true,  /* reverse */
1211                              mb->face_r_gen,
1212                              _face_r_gen);
1213   else {
1214     for (cs_lnum_t i = 0; i < _n_faces; i++)
1215       _face_r_gen[i] = 0;
1216   }
1217 
1218   BFT_FREE(mb->face_r_gen);
1219 
1220   /* Face connectivity */
1221 
1222   BFT_MALLOC(_face_vertices_idx, _n_faces + 1, cs_lnum_t);
1223 
1224   cs_all_to_all_copy_index(d,
1225                            true,  /* reverse */
1226                            mb->face_vertices_idx,
1227                            _face_vertices_idx);
1228 
1229   BFT_MALLOC(_face_gvertices, _face_vertices_idx[_n_faces], cs_gnum_t);
1230 
1231   cs_all_to_all_copy_indexed(d,
1232                              CS_GNUM_TYPE,
1233                              true,  /* reverse */
1234                              mb->face_vertices_idx,
1235                              mb->face_vertices,
1236                              _face_vertices_idx,
1237                              _face_gvertices);
1238 
1239   BFT_FREE(mb->face_vertices_idx);
1240   BFT_FREE(mb->face_vertices);
1241 
1242   cs_all_to_all_destroy(&d);
1243 
1244   /* Vertices */
1245 
1246   size_t _n_vertices = 0;
1247 
1248   cs_order_single_gnum(_face_vertices_idx[_n_faces],
1249                        1, /* base */
1250                        _face_gvertices,
1251                        &_n_vertices,
1252                        &(mesh->global_vtx_num));
1253 
1254   mesh->n_vertices = _n_vertices;
1255 
1256   cs_all_to_all_t *dv
1257     = cs_all_to_all_create_from_block(mesh->n_vertices,
1258                                       CS_ALL_TO_ALL_USE_DEST_ID,
1259                                       mesh->global_vtx_num,
1260                                       mb->vertex_bi,
1261                                       comm);
1262 
1263   mesh->vtx_coord = cs_all_to_all_copy_array(dv,
1264                                              real_type,
1265                                              3,
1266                                              true, /* reverse */
1267                                              mb->vertex_coords,
1268                                              NULL);
1269 
1270   BFT_FREE(mb->vertex_coords);
1271 
1272   cs_all_to_all_destroy(&dv);
1273 
1274   /* Now convert face -> vertex connectivity to local vertex numbers */
1275 
1276   BFT_MALLOC(_face_vertices, _face_vertices_idx[_n_faces], cs_lnum_t);
1277 
1278   cs_block_to_part_global_to_local(_face_vertices_idx[_n_faces],
1279                                    1,
1280                                    mesh->n_vertices,
1281                                    true,
1282                                    mesh->global_vtx_num,
1283                                    _face_gvertices,
1284                                    _face_vertices);
1285 
1286   BFT_FREE(_face_gvertices);
1287 
1288   /* In case of periodicity, build a cs_interface so as to obtain
1289      periodic face correspondants in local numbering (periodic couples
1290      need not be defined by the ranks owning one of the 2 members
1291      for the interface to be built correctly). */
1292 
1293   BFT_MALLOC(_periodicity_num, mb->n_perio, int);
1294 
1295   for (int i = 0; i < mb->n_perio; i++)
1296     _periodicity_num[i] = i+1;
1297 
1298   face_ifs
1299     = cs_interface_set_create(_n_faces,
1300                               NULL,
1301                               _face_num,
1302                               mesh->periodicity,
1303                               mb->n_perio,
1304                               _periodicity_num,
1305                               mb->n_per_face_couples,
1306                               (const cs_gnum_t *const *)mb->per_face_couples);
1307 
1308 
1309   if (mb->n_perio > 0) {
1310     BFT_FREE(_periodicity_num);
1311     for (int i = 0; i < mb->n_perio; i++)
1312       BFT_FREE(mb->per_face_couples[i]);
1313     BFT_FREE(mb->per_face_couples);
1314     BFT_FREE(mb->n_g_per_face_couples);
1315     BFT_FREE(mb->n_per_face_couples);
1316     BFT_FREE(mb->per_face_bi);
1317   }
1318 
1319   /* We may now separate interior from boundary faces */
1320 
1321   BFT_MALLOC(face_type, _n_faces, char);
1322 
1323   _face_type_g(mesh,
1324                _n_faces,
1325                face_ifs,
1326                (const cs_lnum_2_t *)_face_cells,
1327                (const cs_lnum_t *)_face_vertices_idx,
1328                face_type);
1329 
1330   _extract_face_cell(mesh,
1331                      _n_faces,
1332                      (const cs_lnum_2_t *)_face_cells,
1333                      face_type);
1334 
1335   {
1336     cs_gnum_t _n_g_free_faces = mesh->n_g_free_faces;
1337     MPI_Allreduce(&_n_g_free_faces, &(mesh->n_g_free_faces), 1,
1338                   CS_MPI_GNUM, MPI_SUM, comm);
1339   }
1340 
1341   BFT_FREE(_face_cells);
1342 
1343   if (mb->n_perio == 0)
1344     cs_interface_set_destroy(&face_ifs);
1345 
1346   _extract_face_vertices(mesh,
1347                          _n_faces,
1348                          _face_vertices_idx,
1349                          _face_vertices,
1350                          face_type);
1351 
1352   BFT_FREE(_face_vertices_idx);
1353   BFT_FREE(_face_vertices);
1354 
1355   _extract_face_gnum(mesh,
1356                      _n_faces,
1357                      _face_num,
1358                      face_type);
1359 
1360   BFT_FREE(_face_num);
1361 
1362   if (mb->n_perio > 0) {
1363     _face_ifs_to_interior(face_ifs, _n_faces, face_type);
1364     cs_mesh_builder_extract_periodic_faces_g(mesh->n_init_perio,
1365                                              mb,
1366                                              mesh->periodicity,
1367                                              mesh->global_i_face_num,
1368                                              face_ifs);
1369     cs_interface_set_destroy(&face_ifs);
1370   }
1371 
1372   _extract_face_gc_id(mesh,
1373                       _n_faces,
1374                       _face_gc_id,
1375                       face_type);
1376 
1377   BFT_FREE(_face_gc_id);
1378 
1379   _extract_face_r_gen(mesh,
1380                       _n_faces,
1381                       _face_r_gen,
1382                       face_type);
1383   BFT_FREE(_face_r_gen);
1384 
1385   BFT_FREE(face_type);
1386 }
1387 
1388 #endif /* defined(HAVE_MPI) */
1389 
1390 /*----------------------------------------------------------------------------
1391  * Organize data read locally and build most mesh structures
1392  *
1393  * parameters:
1394  *   mesh         <-- pointer to mesh structure
1395  *   mesh_builder <-- pointer to mesh builder structure
1396  *----------------------------------------------------------------------------*/
1397 
1398 static void
_decompose_data_l(cs_mesh_t * mesh,cs_mesh_builder_t * mb)1399 _decompose_data_l(cs_mesh_t          *mesh,
1400                   cs_mesh_builder_t  *mb)
1401 {
1402   cs_lnum_t _n_faces = 0;
1403 
1404   cs_lnum_2_t *_face_cells = NULL;
1405   cs_lnum_t *_face_vertices_idx = NULL;
1406   cs_lnum_t *_face_vertices = NULL;
1407 
1408   char *face_type = NULL;
1409 
1410   /* Initialization */
1411 
1412   assert((sizeof(cs_lnum_t) == 4) || (sizeof(cs_lnum_t) == 8));
1413 
1414   mesh->n_cells = mb->cell_bi.gnum_range[1] - 1;
1415   mesh->n_cells_with_ghosts = mesh->n_cells; /* may be increased later */
1416 
1417   /* Cell families are already of the correct type,
1418      so they can simply be moved */
1419 
1420   mesh->cell_family = mb->cell_gc_id;
1421   mb->cell_gc_id = NULL;
1422 
1423   /* Build faces */
1424   /*-------------*/
1425 
1426   _n_faces = mb->face_bi.gnum_range[1] - 1;
1427 
1428   /* Now copy face -> cell connectivity to local cell numbers */
1429 
1430   BFT_MALLOC(_face_cells, _n_faces, cs_lnum_2_t);
1431 
1432   for (cs_lnum_t i = 0; i < _n_faces; i++) {
1433     _face_cells[i][0] = mb->face_cells[i*2] - 1;
1434     _face_cells[i][1] = mb->face_cells[i*2+1] - 1;
1435   }
1436 
1437   BFT_FREE(mb->face_cells);
1438 
1439   /* Face connectivity */
1440 
1441   BFT_MALLOC(_face_vertices_idx, _n_faces + 1, cs_lnum_t);
1442 
1443   for (cs_lnum_t i = 0; i < _n_faces+1; i++)
1444     _face_vertices_idx[i] = mb->face_vertices_idx[i];
1445 
1446   BFT_FREE(mb->face_vertices_idx);
1447 
1448   BFT_MALLOC(_face_vertices, _face_vertices_idx[_n_faces], cs_lnum_t);
1449 
1450   for (cs_lnum_t i = 0; i < _face_vertices_idx[_n_faces]; i++)
1451     _face_vertices[i] = mb->face_vertices[i];
1452 
1453   BFT_FREE(mb->face_vertices);
1454 
1455   /* Vertices */
1456 
1457   mesh->n_vertices = mb->vertex_bi.gnum_range[1] - 1;
1458 
1459   mesh->vtx_coord = mb->vertex_coords;
1460   mb->vertex_coords = NULL;
1461 
1462   /* We may now separate interior from boundary faces */
1463 
1464   BFT_MALLOC(face_type, _n_faces, char);
1465 
1466   _face_type_l(mesh,
1467                _n_faces,
1468                mb->n_per_face_couples,
1469                (const cs_gnum_t *const *)mb->per_face_couples,
1470                (const cs_lnum_2_t *)_face_cells,
1471                _face_vertices_idx,
1472                face_type);
1473 
1474   _extract_face_cell(mesh,
1475                      _n_faces,
1476                      (const cs_lnum_2_t *)_face_cells,
1477                      face_type);
1478 
1479   BFT_FREE(_face_cells);
1480 
1481   if (mb->n_perio > 0) {
1482 
1483     /* Transfer arrays from reader to builder, then renumber couples */
1484 
1485     _extract_periodic_faces_l(mb,
1486                               mesh->n_init_perio,
1487                               _n_faces,
1488                               face_type);
1489 
1490     BFT_FREE(mb->n_g_per_face_couples);
1491     BFT_FREE(mb->per_face_bi);
1492 
1493   }
1494 
1495   _extract_face_vertices(mesh,
1496                          _n_faces,
1497                          _face_vertices_idx,
1498                          _face_vertices,
1499                          face_type);
1500 
1501   BFT_FREE(_face_vertices_idx);
1502   BFT_FREE(_face_vertices);
1503 
1504   _extract_face_gc_id(mesh,
1505                       _n_faces,
1506                       mb->face_gc_id,
1507                       face_type);
1508 
1509   BFT_FREE(mb->face_gc_id);
1510 
1511   if (mb->have_face_r_gen) {
1512     _extract_face_r_gen(mesh,
1513                         _n_faces,
1514                         mb->face_r_gen,
1515                         face_type);
1516     BFT_FREE(mb->face_r_gen);
1517   }
1518   else {
1519     BFT_MALLOC(mesh->i_face_r_gen, mesh->n_i_faces, char);
1520     for (cs_lnum_t i = 0; i < mesh->n_i_faces; i++)
1521       mesh->i_face_r_gen[i] = 0;
1522   }
1523 
1524   BFT_FREE(face_type);
1525 }
1526 
1527 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
1528 
1529 /*=============================================================================
1530  * Public function definitions
1531  *============================================================================*/
1532 
1533 /*----------------------------------------------------------------------------*/
1534 /*!
1535  * \brief Transfer mesh builder to mesh structure.
1536  *
1537  * \param[in, out]  mesh          pointer to mesh structure
1538  * \param[in, out]  mesh_builder  pointer to mesh builder structure
1539  */
1540 /*----------------------------------------------------------------------------*/
1541 
1542 void
cs_mesh_from_builder(cs_mesh_t * mesh,cs_mesh_builder_t * mesh_builder)1543 cs_mesh_from_builder(cs_mesh_t             *mesh,
1544                      cs_mesh_builder_t     *mesh_builder)
1545 {
1546   /* Clear previous builder data if present (periodicity done separately) */
1547 
1548   cs_mesh_free_rebuildable(mesh, true);
1549 
1550 #if defined(HAVE_MPI)
1551 
1552   if (cs_glob_n_ranks > 1)
1553     _decompose_data_g(mesh,
1554                       mesh_builder,
1555                       cs_glob_mpi_comm);
1556 
1557 #endif
1558 
1559   if (cs_glob_n_ranks == 1)
1560     _decompose_data_l(mesh, mesh_builder);
1561 
1562 }
1563 
1564 /*----------------------------------------------------------------------------*/
1565 
1566 END_C_DECLS
1567