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