~ubuntu-branches/ubuntu/precise/code-saturne/precise

« back to all changes in this revision

Viewing changes to src/fvm/fvm_nodal.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2011-11-24 00:00:08 UTC
  • mfrom: (6.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20111124000008-2vo99e38267942q5
Tags: 2.1.0-3
Install a missing file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*============================================================================
 
2
 * Main structure for a nodal representation associated with a mesh
 
3
 *============================================================================*/
 
4
 
 
5
/*
 
6
  This file is part of Code_Saturne, a general-purpose CFD tool.
 
7
 
 
8
  Copyright (C) 1998-2011 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
#if defined(HAVE_CONFIG_H)
 
28
#include "cs_config.h"
 
29
#endif
 
30
 
 
31
/*----------------------------------------------------------------------------
 
32
 * Standard C library headers
 
33
 *----------------------------------------------------------------------------*/
 
34
 
 
35
#include <assert.h>
 
36
#include <stdio.h>
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
39
 
 
40
/*----------------------------------------------------------------------------
 
41
 * BFT library headers
 
42
 *----------------------------------------------------------------------------*/
 
43
 
 
44
#include <bft_mem.h>
 
45
#include <bft_printf.h>
 
46
 
 
47
/*----------------------------------------------------------------------------
 
48
 *  Local headers
 
49
 *----------------------------------------------------------------------------*/
 
50
 
 
51
#include "fvm_config_defs.h"
 
52
#include "fvm_defs.h"
 
53
#include "fvm_io_num.h"
 
54
#include "fvm_parall.h"
 
55
#include "fvm_tesselation.h"
 
56
 
 
57
/*----------------------------------------------------------------------------
 
58
 *  Header for the current file
 
59
 *----------------------------------------------------------------------------*/
 
60
 
 
61
#include "fvm_nodal.h"
 
62
#include "fvm_nodal_priv.h"
 
63
 
 
64
/*----------------------------------------------------------------------------*/
 
65
 
 
66
#ifdef __cplusplus
 
67
extern "C" {
 
68
#if 0
 
69
} /* Fake brace to force back Emacs auto-indentation back to column 0 */
 
70
#endif
 
71
#endif /* __cplusplus */
 
72
 
 
73
/*============================================================================
 
74
 * Static global variables
 
75
 *============================================================================*/
 
76
 
 
77
/* Number of vertices associated with each "nodal" element type */
 
78
 
 
79
const int  fvm_nodal_n_vertices_element[] = {2,   /* Edge */
 
80
                                             3,   /* Triangle */
 
81
                                             4,   /* Quadrangle */
 
82
                                             0,   /* Simple polygon */
 
83
                                             4,   /* Tetrahedron */
 
84
                                             5,   /* Pyramid */
 
85
                                             6,   /* Prism */
 
86
                                             8,   /* Hexahedron */
 
87
                                             0};  /* Simple polyhedron */
 
88
 
 
89
/* Number of vertices associated with each "nodal" element type */
 
90
 
 
91
static int  fvm_nodal_n_edges_element[] = {1,   /* Edge */
 
92
                                           3,   /* Triangle */
 
93
                                           4,   /* Quadrangle */
 
94
                                           0,   /* Simple polygon */
 
95
                                           6,   /* Tetrahedron */
 
96
                                           8,   /* Pyramid */
 
97
                                           9,   /* Prism */
 
98
                                           12,  /* Hexahedron */
 
99
                                           0};  /* Simple polyhedron */
 
100
 
 
101
/*============================================================================
 
102
 * Private function definitions
 
103
 *============================================================================*/
 
104
 
 
105
/*----------------------------------------------------------------------------
 
106
 * Compare edges (qsort function).
 
107
 *
 
108
 * parameters:
 
109
 *   x <-> pointer to first edge definition
 
110
 *   y <-> pointer to second edge definition
 
111
 *
 
112
 * returns:
 
113
 *   result of strcmp() on group names
 
114
 *----------------------------------------------------------------------------*/
 
115
 
 
116
static int _compare_edges(const void *x, const void *y)
 
117
{
 
118
  int retval = 1;
 
119
 
 
120
  const fvm_lnum_t *e0 = x;
 
121
  const fvm_lnum_t *e1 = y;
 
122
 
 
123
  if (e0[0] < e1[0])
 
124
    retval = -1;
 
125
 
 
126
  else if (e0[0] == e1[0]) {
 
127
    if (e0[1] < e1[1])
 
128
      retval = -1;
 
129
    else if (e0[1] == e1[1])
 
130
      retval = 0;
 
131
  }
 
132
 
 
133
  return retval;
 
134
}
 
135
 
 
136
/*----------------------------------------------------------------------------
 
137
 * Copy a nodal mesh section representation structure, sharing arrays
 
138
 * with the original structure.
 
139
 *
 
140
 * parameters:
 
141
 *   this_section <-> pointer to structure that should be copied
 
142
 *
 
143
 * returns:
 
144
 *   pointer to created nodal mesh section representation structure
 
145
 *----------------------------------------------------------------------------*/
 
146
 
 
147
static fvm_nodal_section_t *
 
148
_fvm_nodal_section_copy(const fvm_nodal_section_t *this_section)
 
149
{
 
150
  fvm_nodal_section_t  *new_section;
 
151
 
 
152
  BFT_MALLOC(new_section, 1, fvm_nodal_section_t);
 
153
 
 
154
  /* Global information */
 
155
 
 
156
  new_section->entity_dim = this_section->entity_dim;
 
157
 
 
158
  new_section->n_elements = this_section->n_elements;
 
159
  new_section->type = this_section->type;
 
160
 
 
161
  /* Connectivity */
 
162
 
 
163
  new_section->connectivity_size = this_section->connectivity_size;
 
164
  new_section->stride = this_section->stride;
 
165
 
 
166
  new_section->n_faces = this_section->n_faces;
 
167
 
 
168
  new_section->face_index = this_section->face_index;
 
169
  new_section->face_num = this_section->face_num;
 
170
  new_section->vertex_index = this_section->vertex_index;
 
171
  new_section->vertex_num = this_section->vertex_num;
 
172
 
 
173
  new_section->_face_index = NULL;
 
174
  new_section->_face_num   = NULL;
 
175
  new_section->_vertex_index = NULL;
 
176
  new_section->_vertex_num = NULL;
 
177
 
 
178
  new_section->gc_id = NULL;
 
179
 
 
180
  new_section->tesselation = NULL;  /* TODO: copy tesselation */
 
181
 
 
182
  /* Numbering */
 
183
  /*-----------*/
 
184
 
 
185
  new_section->parent_element_num = this_section->parent_element_num;
 
186
  new_section->_parent_element_num = NULL;
 
187
 
 
188
  if (this_section->global_element_num != NULL) {
 
189
    fvm_lnum_t n_ent
 
190
      = fvm_io_num_get_local_count(this_section->global_element_num);
 
191
    fvm_gnum_t global_count
 
192
      = fvm_io_num_get_global_count(this_section->global_element_num);
 
193
    const fvm_gnum_t *global_num
 
194
      = fvm_io_num_get_global_num(this_section->global_element_num);
 
195
 
 
196
    new_section->global_element_num
 
197
      = fvm_io_num_create_shared(global_num, global_count, n_ent);
 
198
  }
 
199
  else
 
200
    new_section->global_element_num = NULL;
 
201
 
 
202
  return (new_section);
 
203
}
 
204
 
 
205
/*----------------------------------------------------------------------------
 
206
 * Reduction of a nodal mesh representation section: only the associations
 
207
 * (numberings) necessary to redistribution of fields for output are
 
208
 * conserved, the full connectivity being no longer useful once it has been
 
209
 * output.
 
210
 *
 
211
 * parameters:
 
212
 *   this_section      <-> pointer to structure that should be reduced
 
213
 *
 
214
 * returns:
 
215
 *   true if connectivity has been reduced
 
216
 *----------------------------------------------------------------------------*/
 
217
 
 
218
static _Bool
 
219
_fvm_nodal_section_reduce(fvm_nodal_section_t  * this_section)
 
220
{
 
221
  _Bool retval = false;
 
222
 
 
223
  /* If we have a tesselation of polyhedra (face index != NULL),
 
224
     we may need to keep the connectivity information, to
 
225
     interpolate nodal values to added vertices */
 
226
 
 
227
  if (   this_section->tesselation == NULL
 
228
      || this_section->_face_index == NULL) {
 
229
 
 
230
      /* Connectivity */
 
231
 
 
232
    this_section->connectivity_size = 0;
 
233
 
 
234
    if (this_section->_face_index != NULL)
 
235
      BFT_FREE(this_section->_face_index);
 
236
    this_section->face_index = NULL;
 
237
 
 
238
    if (this_section->_face_num != NULL)
 
239
      BFT_FREE(this_section->_face_num);
 
240
    this_section->face_num = NULL;
 
241
 
 
242
    if (this_section->_vertex_index != NULL)
 
243
      BFT_FREE(this_section->_vertex_index);
 
244
    this_section->vertex_index = NULL;
 
245
 
 
246
    if (this_section->_vertex_num != NULL)
 
247
      BFT_FREE(this_section->_vertex_num);
 
248
    this_section->vertex_num = NULL;
 
249
 
 
250
    retval = true;
 
251
  }
 
252
 
 
253
  if (this_section->gc_id != NULL)
 
254
    BFT_FREE(this_section->gc_id);
 
255
 
 
256
  if (this_section->tesselation != NULL)
 
257
    fvm_tesselation_reduce(this_section->tesselation);
 
258
 
 
259
  return retval;
 
260
}
 
261
 
 
262
/*----------------------------------------------------------------------------
 
263
 * Change entity parent numbering; this is useful when entities of the
 
264
 * parent mesh have been renumbered after a nodal mesh representation
 
265
 * structure's creation. As the parent_num[] array is defined only when
 
266
 * non trivial (i.e. not 1, 2, ..., n), it may be allocated or freed
 
267
 * by this function. The return argument corresponds to the new
 
268
 * pointer which should replace the parent_num input argument.
 
269
 *
 
270
 * parameters:
 
271
 *   parent_num_size     <-- size of local parent numbering array
 
272
 *   new_parent_num      <-- pointer to local parent renumbering array
 
273
 *                           ({1, ..., n} <-- {1, ..., n})
 
274
 *   parent_num          <-> pointer to local parent numbering array
 
275
 *   _parent_num         <-> pointer to local parent numbering array if
 
276
 *                           owner, NULL otherwise
 
277
 *
 
278
 * returns:
 
279
 *   pointer to resulting parent_num[] array
 
280
 *----------------------------------------------------------------------------*/
 
281
 
 
282
static fvm_lnum_t *
 
283
_renumber_parent_num(fvm_lnum_t         parent_num_size,
 
284
                     const fvm_lnum_t   new_parent_num[],
 
285
                     const fvm_lnum_t   parent_num[],
 
286
                     fvm_lnum_t         _parent_num[])
 
287
{
 
288
  int  i;
 
289
  fvm_lnum_t  old_num_id;
 
290
  fvm_lnum_t *parent_num_p = _parent_num;
 
291
  _Bool trivial = true;
 
292
 
 
293
  if (parent_num_size > 0 && new_parent_num != NULL) {
 
294
 
 
295
    if (parent_num_p != NULL) {
 
296
      for (i = 0; i < parent_num_size; i++) {
 
297
        old_num_id = parent_num_p[i] - 1;
 
298
        parent_num_p[i] = new_parent_num[old_num_id];
 
299
        if (parent_num_p[i] != i+1)
 
300
          trivial = false;
 
301
      }
 
302
    }
 
303
    else {
 
304
      BFT_MALLOC(parent_num_p, parent_num_size, fvm_lnum_t);
 
305
      if (parent_num != NULL) {
 
306
        for (i = 0; i < parent_num_size; i++) {
 
307
          old_num_id = parent_num[i] - 1;
 
308
          parent_num_p[i] = new_parent_num[old_num_id];
 
309
          if (parent_num_p[i] != i+1)
 
310
            trivial = false;
 
311
        }
 
312
      }
 
313
      else {
 
314
        for (i = 0; i < parent_num_size; i++) {
 
315
          parent_num_p[i] = new_parent_num[i];
 
316
          if (parent_num_p[i] != i+1)
 
317
            trivial = false;
 
318
        }
 
319
      }
 
320
    }
 
321
  }
 
322
 
 
323
  if (trivial == true)
 
324
    BFT_FREE(parent_num_p);
 
325
 
 
326
  return parent_num_p;
 
327
}
 
328
 
 
329
/*----------------------------------------------------------------------------
 
330
 * Renumber vertices based on those actually referenced, and update
 
331
 * connectivity arrays and parent numbering in accordance.
 
332
 *
 
333
 * The number of vertices assigned to the nodal mesh (this_nodal->n_vertices)
 
334
 * is computed and set by this function. If this number was previously
 
335
 * non-zero (i.e. vertices have already been assigned to the structure),
 
336
 * those vertices are considered as referenced. This is useful if we want
 
337
 * to avoid discarding a given set of vertices, such as when building a
 
338
 * nodal mesh representation containing only vertices.
 
339
 *
 
340
 * parameters:
 
341
 *   this_nodal <-> nodal mesh structure
 
342
 *----------------------------------------------------------------------------*/
 
343
 
 
344
static void
 
345
_renumber_vertices(fvm_nodal_t  *this_nodal)
 
346
{
 
347
  size_t      i;
 
348
  int         section_id;
 
349
  fvm_lnum_t  j;
 
350
  fvm_lnum_t  vertex_id;
 
351
  fvm_lnum_t  n_vertices;
 
352
  fvm_nodal_section_t  *section;
 
353
 
 
354
  fvm_lnum_t  *loc_vertex_num = NULL;
 
355
  fvm_lnum_t   max_vertex_num = 0;
 
356
 
 
357
  /* Find maximum vertex reference */
 
358
  /*-------------------------------*/
 
359
 
 
360
  /* The mesh may already contain direct vertex references
 
361
     (as in the case of a "mesh" only containing vertices) */
 
362
 
 
363
  if (this_nodal->n_vertices > 0) {
 
364
    if (this_nodal->parent_vertex_num != NULL) {
 
365
      for (j = 0; j < this_nodal->n_vertices; j++) {
 
366
        if (this_nodal->parent_vertex_num[j] > max_vertex_num)
 
367
          max_vertex_num = this_nodal->parent_vertex_num[j];
 
368
      }
 
369
    }
 
370
    else
 
371
      max_vertex_num = this_nodal->n_vertices;
 
372
  }
 
373
 
 
374
  /* In most cases, the mesh will reference vertices through elements */
 
375
 
 
376
  for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
377
    section = this_nodal->sections[section_id];
 
378
    if (this_nodal->parent_vertex_num != NULL) {
 
379
      for (i = 0; i < section->connectivity_size; i++) {
 
380
        fvm_lnum_t vertex_num
 
381
          = this_nodal->parent_vertex_num[section->vertex_num[i] - 1];
 
382
        if (vertex_num > max_vertex_num)
 
383
          max_vertex_num = vertex_num;
 
384
      }
 
385
    }
 
386
    else {
 
387
      for (i = 0; i < section->connectivity_size; i++) {
 
388
        if (section->vertex_num[i] > max_vertex_num)
 
389
          max_vertex_num = section->vertex_num[i];
 
390
      }
 
391
    }
 
392
  }
 
393
 
 
394
  /* Flag referenced vertices and compute size */
 
395
  /*-------------------------------------------*/
 
396
 
 
397
  BFT_MALLOC(loc_vertex_num, max_vertex_num, fvm_lnum_t);
 
398
 
 
399
  for (vertex_id = 0; vertex_id < max_vertex_num; vertex_id++)
 
400
    loc_vertex_num[vertex_id] = 0;
 
401
 
 
402
  if (this_nodal->n_vertices > 0) {
 
403
    if (this_nodal->parent_vertex_num != NULL) {
 
404
      for (j = 0; j < this_nodal->n_vertices; j++) {
 
405
        vertex_id = this_nodal->parent_vertex_num[j] - 1;
 
406
        if (loc_vertex_num[vertex_id] == 0)
 
407
          loc_vertex_num[vertex_id] = 1;
 
408
      }
 
409
    }
 
410
    else {
 
411
      for (j = 0; j < this_nodal->n_vertices; j++) {
 
412
        if (loc_vertex_num[j] == 0)
 
413
          loc_vertex_num[j] = 1;
 
414
      }
 
415
    }
 
416
  }
 
417
 
 
418
  for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
419
    section = this_nodal->sections[section_id];
 
420
    if (this_nodal->parent_vertex_num != NULL) {
 
421
      for (i = 0; i < section->connectivity_size; i++) {
 
422
        vertex_id
 
423
          = this_nodal->parent_vertex_num[section->vertex_num[i] - 1] - 1;
 
424
        if (loc_vertex_num[vertex_id] == 0)
 
425
          loc_vertex_num[vertex_id] = 1;
 
426
      }
 
427
    }
 
428
    else {
 
429
      for (i = 0; i < section->connectivity_size; i++) {
 
430
        vertex_id = section->vertex_num[i] - 1;
 
431
        if (loc_vertex_num[vertex_id] == 0)
 
432
          loc_vertex_num[vertex_id] = 1;
 
433
      }
 
434
    }
 
435
  }
 
436
 
 
437
  /* Build vertices renumbering */
 
438
  /*----------------------------*/
 
439
 
 
440
  n_vertices = 0;
 
441
 
 
442
  for (vertex_id = 0; vertex_id < max_vertex_num; vertex_id++) {
 
443
    if (loc_vertex_num[vertex_id] == 1) {
 
444
      n_vertices += 1;
 
445
      loc_vertex_num[vertex_id] = n_vertices;
 
446
    }
 
447
  }
 
448
  this_nodal->n_vertices = n_vertices;
 
449
 
 
450
  /* Update connectivity and vertex parent numbering */
 
451
  /*-------------------------------------------------*/
 
452
 
 
453
  /* If all vertices are flagged, no need to renumber */
 
454
 
 
455
  if (n_vertices == max_vertex_num)
 
456
    BFT_FREE(loc_vertex_num);
 
457
 
 
458
  else {
 
459
 
 
460
    /* Update connectivity */
 
461
 
 
462
    for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
463
      section = this_nodal->sections[section_id];
 
464
      if (section->_vertex_num == NULL)
 
465
        fvm_nodal_section_copy_on_write(section, false, false, false, true);
 
466
      if (this_nodal->parent_vertex_num != NULL) {
 
467
        for (i = 0; i < section->connectivity_size; i++) {
 
468
          vertex_id
 
469
            = this_nodal->parent_vertex_num[section->vertex_num[i] - 1] - 1;
 
470
          section->_vertex_num[i] = loc_vertex_num[vertex_id];
 
471
        }
 
472
      }
 
473
      else {
 
474
        for (i = 0; i < section->connectivity_size; i++) {
 
475
          vertex_id = section->vertex_num[i] - 1;
 
476
          section->_vertex_num[i] = loc_vertex_num[vertex_id];
 
477
        }
 
478
      }
 
479
    }
 
480
 
 
481
    /* Build or update vertex parent numbering */
 
482
 
 
483
    this_nodal->parent_vertex_num = NULL;
 
484
    if (this_nodal->_parent_vertex_num != NULL)
 
485
      BFT_FREE(this_nodal->_parent_vertex_num);
 
486
 
 
487
    if (loc_vertex_num != NULL) {
 
488
      BFT_MALLOC(this_nodal->_parent_vertex_num, n_vertices, fvm_lnum_t);
 
489
      for (vertex_id = 0; vertex_id < max_vertex_num; vertex_id++) {
 
490
        if (loc_vertex_num[vertex_id] > 0)
 
491
          this_nodal->_parent_vertex_num[loc_vertex_num[vertex_id] - 1]
 
492
            = vertex_id + 1;
 
493
      }
 
494
      this_nodal->parent_vertex_num = this_nodal->_parent_vertex_num;
 
495
    }
 
496
  }
 
497
 
 
498
  /* Free renumbering array */
 
499
 
 
500
  BFT_FREE(loc_vertex_num);
 
501
}
 
502
 
 
503
/*----------------------------------------------------------------------------
 
504
 * Dump printout of a nodal representation structure section.
 
505
 *
 
506
 * parameters:
 
507
 *   this_section <-- pointer to structure that should be dumped
 
508
 *----------------------------------------------------------------------------*/
 
509
 
 
510
static void
 
511
_fvm_nodal_section_dump(const fvm_nodal_section_t  *this_section)
 
512
{
 
513
  fvm_lnum_t  n_elements, i, j;
 
514
  const fvm_lnum_t  *idx, *num;
 
515
 
 
516
  /* Global indicators */
 
517
  /*--------------------*/
 
518
 
 
519
  bft_printf("\n"
 
520
             "Entity dimension:     %d\n"
 
521
             "Number of elements:   %ld\n"
 
522
             "Element type:         %s\n",
 
523
             this_section->entity_dim, (long)this_section->n_elements,
 
524
             fvm_elements_type_name[this_section->type]);
 
525
 
 
526
  bft_printf("\n"
 
527
             "Connectivity_size:     %llu\n"
 
528
             "Stride:                %d\n"
 
529
             "Number of faces:       %d\n",
 
530
             (unsigned long long)(this_section->connectivity_size),
 
531
             this_section->stride,
 
532
             (long)(this_section->n_faces));
 
533
 
 
534
  bft_printf("\n"
 
535
             "Pointers to shareable arrays:\n"
 
536
             "  face_index:           %p\n"
 
537
             "  face_num:             %p\n"
 
538
             "  vertex_index:         %p\n"
 
539
             "  vertex_num:           %p\n"
 
540
             "  parent_element_num:   %p\n",
 
541
             this_section->face_index, this_section->face_num,
 
542
             this_section->vertex_index, this_section->vertex_num,
 
543
             this_section->parent_element_num);
 
544
 
 
545
  bft_printf("\n"
 
546
             "Pointers to local arrays:\n"
 
547
             "  _face_index:          %p\n"
 
548
             "  _face_num:            %p\n"
 
549
             "  _vertex_index:        %p\n"
 
550
             "  _vertex_num:          %p\n"
 
551
             "  _parent_element_num:  %p\n",
 
552
             "  gc_id:                %p\n",
 
553
             this_section->_face_index, this_section->_face_num,
 
554
             this_section->_vertex_index, this_section->_vertex_num,
 
555
             this_section->_parent_element_num, this_section->gc_id);
 
556
 
 
557
  if (this_section->face_index != NULL) {
 
558
    bft_printf("\nPolyhedra -> faces (polygons) connectivity:\n\n");
 
559
    n_elements = this_section->n_elements;
 
560
    idx = this_section->face_index;
 
561
    num = this_section->face_num;
 
562
    for (i = 0; i < n_elements; i++) {
 
563
      bft_printf("%10d (idx = %10d) %10d\n",
 
564
                 i+1, idx[i], num[idx[i]]);
 
565
      for (j = idx[i] + 1; j < idx[i + 1]; j++)
 
566
        bft_printf("                              %10d\n", num[j]);
 
567
    }
 
568
    bft_printf("      end  (idx = %10d)\n", idx[n_elements]);
 
569
  }
 
570
 
 
571
  if (this_section->vertex_index != NULL) {
 
572
    fvm_lnum_t  n_faces = (this_section->n_faces > 0) ?
 
573
                          this_section->n_faces : this_section->n_elements;
 
574
    bft_printf("\nPolygons -> vertices connectivity:\n\n");
 
575
    idx = this_section->vertex_index;
 
576
    num = this_section->vertex_num;
 
577
    for (i = 0; i < n_faces; i++) {
 
578
      bft_printf("%10d (idx = %10d) %10d\n",
 
579
                i + 1, idx[i], num[idx[i]]);
 
580
      for (j = idx[i] + 1; j < idx[i + 1]; j++)
 
581
        bft_printf("                              %10d\n", num[j]);
 
582
    }
 
583
    bft_printf("      end  (idx = %10d)\n", idx[n_faces]);
 
584
  }
 
585
 
 
586
  else {
 
587
    bft_printf("\nElements -> vertices connectivity:\n\n");
 
588
    n_elements = this_section->n_elements;
 
589
    num = this_section->vertex_num;
 
590
    switch(this_section->stride) {
 
591
    case 2:
 
592
      for (i = 0; i < n_elements; i++)
 
593
        bft_printf("%10d : %10d %10d\n",
 
594
                   i+1, num[i*2], num[i*2+1]);
 
595
      break;
 
596
    case 3:
 
597
      for (i = 0; i < n_elements; i++)
 
598
        bft_printf("%10d : %10d %10d %10d\n",
 
599
                   i+1, num[i*3], num[i*3+1], num[i*3+2]);
 
600
      break;
 
601
    case 4:
 
602
      for (i = 0; i < n_elements; i++)
 
603
        bft_printf("%10d : %10d %10d %10d %10d\n",
 
604
                   i+1, num[i*4], num[i*4+1], num[i*4+2],
 
605
                   num[i*4+3]);
 
606
      break;
 
607
    case 5:
 
608
      for (i = 0; i < n_elements; i++)
 
609
        bft_printf("%10d : %10d %10d %10d %10d %10d\n",
 
610
                   i+1, num[i*5], num[i*5+1], num[i*5+2],
 
611
                   num[i*5+3], num[i*5+4]);
 
612
      break;
 
613
    case 6:
 
614
      for (i = 0; i < n_elements; i++)
 
615
        bft_printf("%10d : %10d %10d %10d %10d %10d %10d\n",
 
616
                   i+1, num[i*6], num[i*6+1], num[i*6+2],
 
617
                   num[i*6+3], num[i*6+4], num[i*6+5]);
 
618
      break;
 
619
    case 8:
 
620
      for (i = 0; i < n_elements; i++)
 
621
        bft_printf("%10d : %10d %10d %10d %10d %10d %10d %10d %10d\n",
 
622
                   i+1, num[i*8], num[i*8+1], num[i*8+2], num[i*8+3],
 
623
                   num[i*8+4], num[i*8+5], num[i*8+6], num[i*8+7]);
 
624
      break;
 
625
    default:
 
626
      for (i = 0; i < n_elements; i++) {
 
627
        bft_printf("%10d :", i+1);
 
628
        for (j = 0; j < this_section->stride; j++)
 
629
          bft_printf(" %10d", num[i*this_section->stride + j]);
 
630
        bft_printf("\n");
 
631
      }
 
632
    }
 
633
  }
 
634
 
 
635
  if (this_section->gc_id != NULL) {
 
636
    bft_printf("\nGroup class ids:\n\n");
 
637
    for (i = 0; i < this_section->n_elements; i++)
 
638
      bft_printf("%10d : %10d\n", i + 1, this_section->gc_id[i]);
 
639
    bft_printf("\n");
 
640
  }
 
641
 
 
642
  /* Faces tesselation */
 
643
 
 
644
  if (this_section->tesselation != NULL)
 
645
    fvm_tesselation_dump(this_section->tesselation);
 
646
 
 
647
  /* Numbers of associated elements in the parent mesh */
 
648
 
 
649
  bft_printf("\nLocal element numbers in parent mesh:\n");
 
650
  if (this_section->parent_element_num == NULL)
 
651
    bft_printf("\n  Nil\n\n");
 
652
  else {
 
653
    for (i = 0; i < this_section->n_elements; i++)
 
654
      bft_printf("  %10d %10d\n", i+1, this_section->parent_element_num[i]);
 
655
  }
 
656
 
 
657
  /* Global element numbers (only for parallel execution) */
 
658
 
 
659
  if (this_section->global_element_num != NULL) {
 
660
    bft_printf("\nGlobal element numbers:\n");
 
661
    fvm_io_num_dump(this_section->global_element_num);
 
662
  }
 
663
}
 
664
 
 
665
/*============================================================================
 
666
 * Semi-private function definitions (prototypes in fvm_nodal_priv.h)
 
667
 *============================================================================*/
 
668
 
 
669
/*----------------------------------------------------------------------------
 
670
 * Creation of a nodal mesh section representation structure.
 
671
 *
 
672
 * parameters:
 
673
 *   type <-- type of element defined by this section
 
674
 *
 
675
 * returns:
 
676
 *   pointer to created nodal mesh section representation structure
 
677
 *----------------------------------------------------------------------------*/
 
678
 
 
679
fvm_nodal_section_t *
 
680
fvm_nodal_section_create(const fvm_element_t  type)
 
681
{
 
682
  fvm_nodal_section_t  *this_section;
 
683
 
 
684
  BFT_MALLOC(this_section, 1, fvm_nodal_section_t);
 
685
 
 
686
  /* Global information */
 
687
 
 
688
  if (type == FVM_EDGE)
 
689
    this_section->entity_dim = 1;
 
690
  else if (type >= FVM_FACE_TRIA && type <= FVM_FACE_POLY)
 
691
    this_section->entity_dim = 2;
 
692
  else
 
693
    this_section->entity_dim = 3;
 
694
 
 
695
  this_section->n_elements = 0;
 
696
  this_section->type = type;
 
697
 
 
698
  /* Connectivity */
 
699
 
 
700
  this_section->connectivity_size = 0;
 
701
 
 
702
  if (type != FVM_FACE_POLY && type != FVM_CELL_POLY)
 
703
    this_section->stride = fvm_nodal_n_vertices_element[type];
 
704
  else
 
705
    this_section->stride = 0;
 
706
 
 
707
  this_section->n_faces = 0;
 
708
  this_section->face_index = NULL;
 
709
  this_section->face_num   = NULL;
 
710
  this_section->vertex_index = NULL;
 
711
  this_section->vertex_num = NULL;
 
712
 
 
713
  this_section->_face_index = NULL;
 
714
  this_section->_face_num   = NULL;
 
715
  this_section->_vertex_index = NULL;
 
716
  this_section->_vertex_num = NULL;
 
717
 
 
718
  this_section->gc_id = NULL;
 
719
 
 
720
  this_section->tesselation = NULL;
 
721
 
 
722
  /* Numbering */
 
723
  /*-----------*/
 
724
 
 
725
  this_section->parent_element_num = NULL;
 
726
  this_section->_parent_element_num = NULL;
 
727
 
 
728
  this_section->global_element_num = NULL;
 
729
 
 
730
  return (this_section);
 
731
}
 
732
 
 
733
/*----------------------------------------------------------------------------
 
734
 * Destruction of a nodal mesh section representation structure.
 
735
 *
 
736
 * parameters:
 
737
 *   this_section <-> pointer to structure that should be destroyed
 
738
 *
 
739
 * returns:
 
740
 *   NULL pointer
 
741
 *----------------------------------------------------------------------------*/
 
742
 
 
743
fvm_nodal_section_t *
 
744
fvm_nodal_section_destroy(fvm_nodal_section_t  * this_section)
 
745
{
 
746
  /* Connectivity */
 
747
 
 
748
  if (this_section->_face_index != NULL)
 
749
    BFT_FREE(this_section->_face_index);
 
750
  if (this_section->_face_num != NULL)
 
751
    BFT_FREE(this_section->_face_num);
 
752
 
 
753
  if (this_section->_vertex_index != NULL)
 
754
    BFT_FREE(this_section->_vertex_index);
 
755
  if (this_section->_vertex_num != NULL)
 
756
    BFT_FREE(this_section->_vertex_num);
 
757
 
 
758
  if (this_section->gc_id != NULL)
 
759
    BFT_FREE(this_section->gc_id);
 
760
 
 
761
  if (this_section->tesselation != NULL)
 
762
    fvm_tesselation_destroy(this_section->tesselation);
 
763
 
 
764
  /* Numbering */
 
765
  /*-----------*/
 
766
 
 
767
  if (this_section->parent_element_num != NULL) {
 
768
    this_section->parent_element_num = NULL;
 
769
    BFT_FREE(this_section->_parent_element_num);
 
770
  }
 
771
 
 
772
  if (this_section->global_element_num != NULL)
 
773
    fvm_io_num_destroy(this_section->global_element_num);
 
774
 
 
775
  /* Main structure destroyed and NULL returned */
 
776
 
 
777
  BFT_FREE(this_section);
 
778
 
 
779
  return (this_section);
 
780
}
 
781
 
 
782
/*----------------------------------------------------------------------------
 
783
 * Copy selected shared connectivity information to private connectivity
 
784
 * for a nodal mesh section.
 
785
 *
 
786
 * parameters:
 
787
 *   this_section      <-> pointer to section structure
 
788
 *   copy_face_index   <-- copy face index (polyhedra only) ?
 
789
 *   copy_face_num     <-- copy face numbers (polyhedra only) ?
 
790
 *   copy_vertex_index <-- copy vertex index (polyhedra/polygons only) ?
 
791
 *   copy_vertex_num   <-- copy vertex numbers ?
 
792
 *----------------------------------------------------------------------------*/
 
793
 
 
794
void
 
795
fvm_nodal_section_copy_on_write(fvm_nodal_section_t  *this_section,
 
796
                                _Bool                 copy_face_index,
 
797
                                _Bool                 copy_face_num,
 
798
                                _Bool                 copy_vertex_index,
 
799
                                _Bool                 copy_vertex_num)
 
800
{
 
801
  fvm_lnum_t  n_faces;
 
802
  size_t  i;
 
803
 
 
804
  if (copy_face_index == true
 
805
      && this_section->face_index != NULL && this_section->_face_index == NULL) {
 
806
    BFT_MALLOC(this_section->_face_index, this_section->n_elements + 1, fvm_lnum_t);
 
807
    for (i = 0; i < (size_t)(this_section->n_elements + 1); i++) {
 
808
      this_section->_face_index[i] = this_section->face_index[i];
 
809
    }
 
810
    this_section->face_index = this_section->_face_index;
 
811
  }
 
812
 
 
813
  if (copy_face_num == true
 
814
      && this_section->face_num != NULL && this_section->_face_num == NULL) {
 
815
    n_faces = this_section->face_index[this_section->n_elements];
 
816
    BFT_MALLOC(this_section->_face_num, n_faces, fvm_lnum_t);
 
817
    for (i = 0; i < (size_t)n_faces; i++) {
 
818
      this_section->_face_num[i] = this_section->face_num[i];
 
819
    }
 
820
    this_section->face_num = this_section->_face_num;
 
821
  }
 
822
 
 
823
  if (   copy_vertex_index == true
 
824
      && this_section->vertex_index != NULL
 
825
      && this_section->_vertex_index == NULL) {
 
826
    if (this_section->n_faces != 0)
 
827
      n_faces = this_section->n_faces;
 
828
    else
 
829
      n_faces = this_section->n_elements;
 
830
    BFT_MALLOC(this_section->_vertex_index, n_faces + 1, fvm_lnum_t);
 
831
    for (i = 0; i < (size_t)n_faces + 1; i++) {
 
832
      this_section->_vertex_index[i] = this_section->vertex_index[i];
 
833
    }
 
834
    this_section->vertex_index = this_section->_vertex_index;
 
835
  }
 
836
 
 
837
  if (copy_vertex_num == true && this_section->_vertex_num == NULL) {
 
838
    BFT_MALLOC(this_section->_vertex_num,
 
839
               this_section->connectivity_size, fvm_lnum_t);
 
840
    for (i = 0; i < this_section->connectivity_size; i++) {
 
841
      this_section->_vertex_num[i] = this_section->vertex_num[i];
 
842
    }
 
843
    this_section->vertex_num = this_section->_vertex_num;
 
844
  }
 
845
 
 
846
}
 
847
 
 
848
/*----------------------------------------------------------------------------
 
849
 * Return global number of elements associated with section.
 
850
 *
 
851
 * parameters:
 
852
 *   this_section      <-- pointer to section structure
 
853
 *
 
854
 * returns:
 
855
 *   global number of elements associated with section
 
856
 *----------------------------------------------------------------------------*/
 
857
 
 
858
fvm_gnum_t
 
859
fvm_nodal_section_n_g_elements(const fvm_nodal_section_t  *this_section)
 
860
{
 
861
  if (this_section->global_element_num != NULL)
 
862
    return fvm_io_num_get_global_count(this_section->global_element_num);
 
863
  else
 
864
    return this_section->n_elements;
 
865
}
 
866
 
 
867
/*----------------------------------------------------------------------------
 
868
 * Return global number of vertices associated with nodal mesh.
 
869
 *
 
870
 * parameters:
 
871
 *   this_nodal           <-- pointer to nodal mesh structure
 
872
 *
 
873
 * returns:
 
874
 *   global number of vertices associated with nodal mesh
 
875
 *----------------------------------------------------------------------------*/
 
876
 
 
877
fvm_gnum_t
 
878
fvm_nodal_n_g_vertices(const fvm_nodal_t  *this_nodal)
 
879
{
 
880
  fvm_gnum_t  n_g_vertices;
 
881
 
 
882
  if (this_nodal->global_vertex_num != NULL)
 
883
    n_g_vertices = fvm_io_num_get_global_count(this_nodal->global_vertex_num);
 
884
  else
 
885
    n_g_vertices = this_nodal->n_vertices;
 
886
 
 
887
  return n_g_vertices;
 
888
}
 
889
 
 
890
/*----------------------------------------------------------------------------
 
891
 * Define cell->face connectivity for strided cell types.
 
892
 *
 
893
 * parameters:
 
894
 *   element_type     <-- type of strided element
 
895
 *   n_faces          --> number of element faces
 
896
 *   n_face_vertices  --> number of vertices of each face
 
897
 *   face_vertices    --> face -> vertex base connectivity (0 to n-1)
 
898
 *----------------------------------------------------------------------------*/
 
899
 
 
900
void
 
901
fvm_nodal_cell_face_connect(fvm_element_t   element_type,
 
902
                            int            *n_faces,
 
903
                            int             n_face_vertices[6],
 
904
                            int             face_vertices[6][4])
 
905
{
 
906
  int i, j;
 
907
 
 
908
  /* Initialization */
 
909
 
 
910
  *n_faces = 0;
 
911
 
 
912
  for (i = 0; i < 6; i++) {
 
913
    n_face_vertices[i] = 0;
 
914
    for (j = 0; j < 4; j++)
 
915
      face_vertices[i][j] = 0;
 
916
  }
 
917
 
 
918
  /* Define connectivity based on element type */
 
919
 
 
920
  switch(element_type) {
 
921
 
 
922
  case FVM_CELL_TETRA:
 
923
    {
 
924
      fvm_lnum_t _face_vertices[4][3] = {{1, 3, 2},     /*       x 4     */
 
925
                                         {1, 2, 4},     /*      /|\      */
 
926
                                         {1, 4, 3},     /*     / | \     */
 
927
                                         {2, 3, 4}};    /*    /  |  \    */
 
928
                                                        /* 1 x- -|- -x 3 */
 
929
      for (i = 0; i < 4; i++) {                         /*    \  |  /    */
 
930
        n_face_vertices[i] = 3;                         /*     \ | /     */
 
931
        for (j = 0; j < 3; j++)                         /*      \|/      */
 
932
          face_vertices[i][j] = _face_vertices[i][j];   /*       x 2     */
 
933
      }
 
934
      *n_faces = 4;
 
935
    }
 
936
    break;
 
937
 
 
938
  case FVM_CELL_PYRAM:
 
939
    {
 
940
      fvm_lnum_t _n_face_vertices[5] = {3, 3, 3, 3, 4};
 
941
      fvm_lnum_t _face_vertices[5][4] = {{1, 2, 5, 0},  /*        5 x       */
 
942
                                         {1, 5, 4, 0},  /*         /|\      */
 
943
                                         {2, 3, 5, 0},  /*        //| \     */
 
944
                                         {3, 4, 5, 0},  /*       // |  \    */
 
945
                                         {1, 4, 3, 2}}; /*    4 x/--|---x 3 */
 
946
                                                        /*     //   |  /    */
 
947
      for (i = 0; i < 5; i++) {                         /*    //    | /     */
 
948
        n_face_vertices[i] = _n_face_vertices[i];       /* 1 x-------x 2    */
 
949
        for (j = 0; j < 4; j++)
 
950
          face_vertices[i][j] = _face_vertices[i][j];
 
951
      }
 
952
      *n_faces = 5;
 
953
    }
 
954
    break;
 
955
 
 
956
  case FVM_CELL_PRISM:
 
957
    {
 
958
      fvm_lnum_t _n_face_vertices[5] = {3, 3, 4, 4, 4};
 
959
      fvm_lnum_t _face_vertices[5][4] = {{1, 3, 2, 0},  /* 4 x-------x 6 */
 
960
                                         {4, 5, 6, 0},  /*   |\     /|   */
 
961
                                         {1, 2, 5, 4},  /*   | \   / |   */
 
962
                                         {1, 4, 6, 3},  /* 1 x- \-/ -x 3 */
 
963
                                         {2, 3, 6, 5}}; /*    \ 5x  /    */
 
964
                                                        /*     \ | /     */
 
965
      for (i = 0; i < 5; i++) {                         /*      \|/      */
 
966
        n_face_vertices[i] = _n_face_vertices[i];       /*       x 2     */
 
967
        for (j = 0; j < 4; j++)
 
968
          face_vertices[i][j] = _face_vertices[i][j];
 
969
      }
 
970
      *n_faces = 5;
 
971
    }
 
972
    break;
 
973
 
 
974
  case FVM_CELL_HEXA:
 
975
    {
 
976
      fvm_lnum_t _n_face_vertices[6] = {4, 4, 4, 4, 4, 4};
 
977
      fvm_lnum_t _face_vertices[6][4] = {{1, 4, 3, 2},  /*    8 x-------x 7 */
 
978
                                         {1, 2, 6, 5},  /*     /|      /|   */
 
979
                                         {1, 5, 8, 4},  /*    / |     / |   */
 
980
                                         {2, 3, 7, 6},  /* 5 x-------x6 |   */
 
981
                                         {3, 4, 8, 7},  /*   | 4x----|--x 3 */
 
982
                                         {5, 6, 7, 8}}; /*   | /     | /    */
 
983
      for (i = 0; i < 6; i++) {                         /*   |/      |/     */
 
984
        n_face_vertices[i] = _n_face_vertices[i];       /* 1 x-------x 2    */
 
985
        for (j = 0; j < 4; j++)
 
986
          face_vertices[i][j] = _face_vertices[i][j];
 
987
      }
 
988
      *n_faces = 6;
 
989
    }
 
990
    break;
 
991
 
 
992
  default:
 
993
    assert(0);
 
994
  }
 
995
 
 
996
  /* Switch from (1, n) to (0, n-1) numbering */
 
997
 
 
998
  for (i = 0; i < 6; i++) {
 
999
    for (j = 0; j < 4; j++)
 
1000
      face_vertices[i][j] -= 1;
 
1001
  }
 
1002
}
 
1003
 
 
1004
/*============================================================================
 
1005
 * Public function definitions
 
1006
 *============================================================================*/
 
1007
 
 
1008
/*----------------------------------------------------------------------------
 
1009
 * Creation of a nodal mesh representation structure.
 
1010
 *
 
1011
 * parameters:
 
1012
 *   name <-- name that should be assigned to the nodal mesh
 
1013
 *   dim  <-- spatial dimension
 
1014
 *
 
1015
 * returns:
 
1016
 *  pointer to created nodal mesh representation structure
 
1017
 *----------------------------------------------------------------------------*/
 
1018
 
 
1019
fvm_nodal_t *
 
1020
fvm_nodal_create(const char  *name,
 
1021
                 int          dim)
 
1022
{
 
1023
  fvm_nodal_t  *this_nodal;
 
1024
 
 
1025
  BFT_MALLOC(this_nodal, 1, fvm_nodal_t);
 
1026
 
 
1027
  /* Global indicators */
 
1028
 
 
1029
  if (name != NULL) {
 
1030
    BFT_MALLOC(this_nodal->name, strlen(name) + 1, char);
 
1031
    strcpy(this_nodal->name, name);
 
1032
  }
 
1033
  else
 
1034
    this_nodal->name = NULL;
 
1035
 
 
1036
  this_nodal->dim     = dim;
 
1037
  this_nodal->num_dom = fvm_parall_get_rank() + 1;
 
1038
  this_nodal->n_doms  = fvm_parall_get_size();
 
1039
  this_nodal->n_sections = 0;
 
1040
 
 
1041
  /* Local dimensions */
 
1042
 
 
1043
  this_nodal->n_cells = 0;
 
1044
  this_nodal->n_faces = 0;
 
1045
  this_nodal->n_edges = 0;
 
1046
  this_nodal->n_vertices = 0;
 
1047
 
 
1048
  /* Local structures */
 
1049
 
 
1050
  this_nodal->vertex_coords = NULL;
 
1051
  this_nodal->_vertex_coords = NULL;
 
1052
 
 
1053
  this_nodal->parent_vertex_num = NULL;
 
1054
  this_nodal->_parent_vertex_num = NULL;
 
1055
 
 
1056
  this_nodal->global_vertex_num = NULL;
 
1057
 
 
1058
  this_nodal->sections = NULL;
 
1059
 
 
1060
  this_nodal->gc_set = NULL;
 
1061
 
 
1062
  return (this_nodal);
 
1063
}
 
1064
 
 
1065
/*----------------------------------------------------------------------------
 
1066
 * Destruction of a nodal mesh representation structure.
 
1067
 *
 
1068
 * parameters:
 
1069
 *   this_nodal  <-> pointer to structure that should be destroyed
 
1070
 *
 
1071
 * returns:
 
1072
 *  NULL pointer
 
1073
 *----------------------------------------------------------------------------*/
 
1074
 
 
1075
fvm_nodal_t *
 
1076
fvm_nodal_destroy(fvm_nodal_t  * this_nodal)
 
1077
{
 
1078
  int           i;
 
1079
 
 
1080
  /* Local structures */
 
1081
 
 
1082
  if (this_nodal->name != NULL)
 
1083
    BFT_FREE(this_nodal->name);
 
1084
 
 
1085
  if (this_nodal->_vertex_coords != NULL)
 
1086
    BFT_FREE(this_nodal->_vertex_coords);
 
1087
 
 
1088
  if (this_nodal->parent_vertex_num != NULL) {
 
1089
    this_nodal->parent_vertex_num = NULL;
 
1090
    BFT_FREE(this_nodal->_parent_vertex_num);
 
1091
  }
 
1092
 
 
1093
  if (this_nodal->global_vertex_num != NULL)
 
1094
    fvm_io_num_destroy(this_nodal->global_vertex_num);
 
1095
 
 
1096
  for (i = 0; i < this_nodal->n_sections; i++)
 
1097
    fvm_nodal_section_destroy(this_nodal->sections[i]);
 
1098
 
 
1099
  if (this_nodal->sections != NULL)
 
1100
    BFT_FREE(this_nodal->sections);
 
1101
 
 
1102
  if (this_nodal->gc_set != NULL)
 
1103
    this_nodal->gc_set = fvm_group_class_set_destroy(this_nodal->gc_set);
 
1104
 
 
1105
  /* Main structure destroyed and NULL returned */
 
1106
 
 
1107
  BFT_FREE(this_nodal);
 
1108
 
 
1109
  return (this_nodal);
 
1110
}
 
1111
 
 
1112
/*----------------------------------------------------------------------------
 
1113
 * Copy a nodal mesh representation structure, sharing arrays with the
 
1114
 * original structure.
 
1115
 *
 
1116
 * Element group classes and mesh group class descriptions are not currently
 
1117
 * copied.
 
1118
 *
 
1119
 * parameters:
 
1120
 *   this_nodal  <-> pointer to structure that should be copied
 
1121
 *
 
1122
 * returns:
 
1123
 *   pointer to created nodal mesh representation structure
 
1124
 *----------------------------------------------------------------------------*/
 
1125
 
 
1126
fvm_nodal_t *
 
1127
fvm_nodal_copy(const fvm_nodal_t *this_nodal)
 
1128
{
 
1129
  int i;
 
1130
  fvm_nodal_t  *new_nodal;
 
1131
 
 
1132
  BFT_MALLOC(new_nodal, 1, fvm_nodal_t);
 
1133
 
 
1134
  /* Global indicators */
 
1135
 
 
1136
  if (this_nodal->name != NULL) {
 
1137
    BFT_MALLOC(new_nodal->name, strlen(this_nodal->name) + 1, char);
 
1138
    strcpy(new_nodal->name, this_nodal->name);
 
1139
  }
 
1140
  else
 
1141
    new_nodal->name = NULL;
 
1142
 
 
1143
  new_nodal->dim     = this_nodal->dim;
 
1144
  new_nodal->num_dom = this_nodal->num_dom;
 
1145
  new_nodal->n_doms  = this_nodal->n_doms;
 
1146
  new_nodal->n_sections = this_nodal->n_sections;
 
1147
 
 
1148
  /* Local dimensions */
 
1149
 
 
1150
  new_nodal->n_cells = this_nodal->n_cells;
 
1151
  new_nodal->n_faces = this_nodal->n_faces;
 
1152
  new_nodal->n_edges = this_nodal->n_edges;
 
1153
  new_nodal->n_vertices = this_nodal->n_vertices;
 
1154
 
 
1155
  /* Local structures */
 
1156
 
 
1157
  new_nodal->vertex_coords = this_nodal->vertex_coords;
 
1158
  new_nodal->_vertex_coords = NULL;
 
1159
 
 
1160
  new_nodal->parent_vertex_num = this_nodal->parent_vertex_num;
 
1161
  new_nodal->_parent_vertex_num = NULL;
 
1162
 
 
1163
  if (this_nodal->global_vertex_num != NULL) {
 
1164
    fvm_lnum_t n_ent
 
1165
      = fvm_io_num_get_local_count(this_nodal->global_vertex_num);
 
1166
    fvm_gnum_t global_count
 
1167
      = fvm_io_num_get_global_count(this_nodal->global_vertex_num);
 
1168
    const fvm_gnum_t *global_num
 
1169
      = fvm_io_num_get_global_num(this_nodal->global_vertex_num);
 
1170
 
 
1171
    new_nodal->global_vertex_num
 
1172
      = fvm_io_num_create_shared(global_num, global_count, n_ent);
 
1173
  }
 
1174
  else
 
1175
    new_nodal->global_vertex_num = NULL;
 
1176
 
 
1177
  BFT_MALLOC(new_nodal->sections,
 
1178
             new_nodal->n_sections,
 
1179
             fvm_nodal_section_t *);
 
1180
  for (i = 0; i < new_nodal->n_sections; i++)
 
1181
    new_nodal->sections[i] = _fvm_nodal_section_copy(this_nodal->sections[i]);
 
1182
 
 
1183
  new_nodal->gc_set = NULL;
 
1184
 
 
1185
  return (new_nodal);
 
1186
}
 
1187
 
 
1188
/*----------------------------------------------------------------------------
 
1189
 * Reduction of a nodal mesh representation structure: only the associations
 
1190
 * (numberings) necessary to redistribution of fields for output are
 
1191
 * conserved, the full connectivity being in many cases no longer useful
 
1192
 * once it has been output. If the del_vertex_num value is set
 
1193
 * to true, vertex-based values may not be output in parallel mode
 
1194
 * after this function is called.
 
1195
 *
 
1196
 * parameters:
 
1197
 *   this_nodal        <-> pointer to structure that should be reduced
 
1198
 *   del_vertex_num    <-- indicates if vertex parent indirection and
 
1199
 *                         I/O numbering are destroyed (1) or not (0)
 
1200
 *----------------------------------------------------------------------------*/
 
1201
 
 
1202
void
 
1203
fvm_nodal_reduce(fvm_nodal_t  *this_nodal,
 
1204
                 int           del_vertex_num)
 
1205
{
 
1206
  int  i;
 
1207
  _Bool reduce_vertices = true;
 
1208
 
 
1209
  /* Connectivity */
 
1210
 
 
1211
  for (i = 0; i < this_nodal->n_sections; i++) {
 
1212
    if (_fvm_nodal_section_reduce(this_nodal->sections[i]) == false)
 
1213
      reduce_vertices = false;
 
1214
  }
 
1215
 
 
1216
  /* Vertices */
 
1217
 
 
1218
  if (reduce_vertices == true) {
 
1219
 
 
1220
    if (this_nodal->_vertex_coords != NULL)
 
1221
      BFT_FREE(this_nodal->_vertex_coords);
 
1222
    this_nodal->vertex_coords = NULL;
 
1223
 
 
1224
  }
 
1225
 
 
1226
  /* Depending on this option, output on vertices may not remain possible */
 
1227
 
 
1228
  if (del_vertex_num > 0) {
 
1229
 
 
1230
    if (this_nodal->parent_vertex_num != NULL) {
 
1231
      this_nodal->parent_vertex_num = NULL;
 
1232
      BFT_FREE(this_nodal->_parent_vertex_num);
 
1233
    }
 
1234
 
 
1235
    if (this_nodal->global_vertex_num != NULL)
 
1236
      this_nodal->global_vertex_num
 
1237
        = fvm_io_num_destroy(this_nodal->global_vertex_num);
 
1238
 
 
1239
  }
 
1240
 
 
1241
  if (this_nodal->gc_set != NULL)
 
1242
    this_nodal->gc_set = fvm_group_class_set_destroy(this_nodal->gc_set);
 
1243
}
 
1244
 
 
1245
/*----------------------------------------------------------------------------
 
1246
 * Change entity parent numbering; this is useful when entities of the
 
1247
 * parent mesh have been renumbered after a nodal mesh representation
 
1248
 * structure's creation.
 
1249
 *
 
1250
 * parameters:
 
1251
 *   this_nodal          <-- nodal mesh structure
 
1252
 *   new_parent_num      <-- pointer to local parent renumbering array
 
1253
 *                           ({1, ..., n} <-- {1, ..., n})
 
1254
 *   entity_dim          <-- 3 for cells, 2 for faces, 1 for edges,
 
1255
 *                           and 0 for vertices
 
1256
 *----------------------------------------------------------------------------*/
 
1257
 
 
1258
void
 
1259
fvm_nodal_change_parent_num(fvm_nodal_t       *this_nodal,
 
1260
                            const fvm_lnum_t   new_parent_num[],
 
1261
                            int                entity_dim)
 
1262
{
 
1263
  /* Vertices */
 
1264
 
 
1265
  if (entity_dim == 0) {
 
1266
 
 
1267
    this_nodal->_parent_vertex_num
 
1268
      = _renumber_parent_num(this_nodal->n_vertices,
 
1269
                             new_parent_num,
 
1270
                             this_nodal->parent_vertex_num,
 
1271
                             this_nodal->_parent_vertex_num);
 
1272
    this_nodal->parent_vertex_num = this_nodal->_parent_vertex_num;
 
1273
 
 
1274
  }
 
1275
 
 
1276
  /* Other elements */
 
1277
 
 
1278
  else {
 
1279
 
 
1280
    int  i = 0;
 
1281
    fvm_nodal_section_t  *section = NULL;
 
1282
 
 
1283
    for (i = 0; i < this_nodal->n_sections; i++) {
 
1284
      section = this_nodal->sections[i];
 
1285
      if (section->entity_dim == entity_dim) {
 
1286
        section->_parent_element_num
 
1287
          = _renumber_parent_num(section->n_elements,
 
1288
                                 new_parent_num,
 
1289
                                 section->parent_element_num,
 
1290
                                 section->_parent_element_num);
 
1291
        section->parent_element_num = section->_parent_element_num;
 
1292
      }
 
1293
    }
 
1294
 
 
1295
  }
 
1296
 
 
1297
}
 
1298
 
 
1299
/*----------------------------------------------------------------------------
 
1300
 * Remove entity parent numbering; this is useful for example when we
 
1301
 * want to assign coordinates or fields to an extracted mesh using
 
1302
 * arrays relative to the mesh, and not to its parent.
 
1303
 *
 
1304
 * This is equivalent to calling fvm_nodal_change_parent_num(), with
 
1305
 * 'trivial' (1 o n) new_parent_num[] values.
 
1306
 *
 
1307
 * parameters:
 
1308
 *   this_nodal          <-- nodal mesh structure
 
1309
 *   entity_dim          <-- 3 for cells, 2 for faces, 1 for edges,
 
1310
 *                           and 0 for vertices
 
1311
 *----------------------------------------------------------------------------*/
 
1312
 
 
1313
void
 
1314
fvm_nodal_remove_parent_num(fvm_nodal_t  *this_nodal,
 
1315
                            int           entity_dim)
 
1316
{
 
1317
  /* Vertices */
 
1318
 
 
1319
  if (entity_dim == 0) {
 
1320
    this_nodal->parent_vertex_num = NULL;
 
1321
    if (this_nodal->_parent_vertex_num != NULL)
 
1322
      BFT_FREE(this_nodal->_parent_vertex_num);
 
1323
  }
 
1324
 
 
1325
  /* Other elements */
 
1326
 
 
1327
  else {
 
1328
 
 
1329
    int  i = 0;
 
1330
    fvm_nodal_section_t  *section = NULL;
 
1331
 
 
1332
    for (i = 0; i < this_nodal->n_sections; i++) {
 
1333
      section = this_nodal->sections[i];
 
1334
      if (section->entity_dim == entity_dim) {
 
1335
        section->parent_element_num = NULL;
 
1336
        if (section->_parent_element_num != NULL)
 
1337
          BFT_FREE(section->_parent_element_num);
 
1338
      }
 
1339
    }
 
1340
 
 
1341
  }
 
1342
 
 
1343
}
 
1344
 
 
1345
/*----------------------------------------------------------------------------
 
1346
 * Build external numbering for entities based on global numbers.
 
1347
 *
 
1348
 * parameters:
 
1349
 *   this_nodal           <-- nodal mesh structure
 
1350
 *   parent_global_number <-- pointer to list of global (i.e. domain splitting
 
1351
 *                            independent) parent entity numbers
 
1352
 *   entity_dim           <-- 3 for cells, 2 for faces, 1 for edges,
 
1353
 *                            and 0 for vertices
 
1354
 *----------------------------------------------------------------------------*/
 
1355
 
 
1356
void
 
1357
fvm_nodal_init_io_num(fvm_nodal_t       *this_nodal,
 
1358
                      const fvm_gnum_t   parent_global_numbers[],
 
1359
                      int                entity_dim)
 
1360
{
 
1361
  int  i;
 
1362
  fvm_nodal_section_t  *section;
 
1363
 
 
1364
  if (entity_dim == 0)
 
1365
    this_nodal->global_vertex_num
 
1366
      = fvm_io_num_create(this_nodal->parent_vertex_num,
 
1367
                          parent_global_numbers,
 
1368
                          this_nodal->n_vertices,
 
1369
                          0);
 
1370
 
 
1371
  else {
 
1372
    for (i = 0; i < this_nodal->n_sections; i++) {
 
1373
      section = this_nodal->sections[i];
 
1374
      if (section->entity_dim == entity_dim) {
 
1375
        section->global_element_num
 
1376
          = fvm_io_num_create(section->parent_element_num,
 
1377
                              parent_global_numbers,
 
1378
                              section->n_elements,
 
1379
                              0);
 
1380
      }
 
1381
    }
 
1382
  }
 
1383
 
 
1384
}
 
1385
 
 
1386
/*----------------------------------------------------------------------------
 
1387
 * Preset number and list of vertices to assign to a nodal mesh.
 
1388
 *
 
1389
 * If the parent_vertex_num argument is NULL, the list is assumed to
 
1390
 * be {1, 2, ..., n}. If parent_vertex_num is given, it specifies a
 
1391
 * list of n vertices from a larger set (1 to n numbering).
 
1392
 *
 
1393
 * Ownership of the given parent vertex numbering array is
 
1394
 * transferred to the nodal mesh representation structure.
 
1395
 *
 
1396
 * This function should be called before fvm_nodal_set_shared_vertices()
 
1397
 * or fvm_nodal_transfer_vertices() if we want to force certain
 
1398
 * vertices to appear in the mesh (especially if we want to define
 
1399
 * a mesh containing only vertices).
 
1400
 *
 
1401
 * parameters:
 
1402
 *   this_nodal        <-> nodal mesh structure
 
1403
 *   n_vertices        <-- number of vertices to assign
 
1404
 *   parent_vertex_num <-- parent numbers of vertices to assign
 
1405
 *----------------------------------------------------------------------------*/
 
1406
 
 
1407
void
 
1408
fvm_nodal_define_vertex_list(fvm_nodal_t  *this_nodal,
 
1409
                             fvm_lnum_t    n_vertices,
 
1410
                             fvm_lnum_t    parent_vertex_num[])
 
1411
{
 
1412
  assert(this_nodal != NULL);
 
1413
 
 
1414
  this_nodal->n_vertices = n_vertices;
 
1415
 
 
1416
  this_nodal->parent_vertex_num = NULL;
 
1417
  if (this_nodal->_parent_vertex_num != NULL)
 
1418
    BFT_FREE(this_nodal->_parent_vertex_num);
 
1419
 
 
1420
  if (parent_vertex_num != NULL) {
 
1421
    this_nodal->_parent_vertex_num = parent_vertex_num;
 
1422
    this_nodal->parent_vertex_num = parent_vertex_num;
 
1423
  }
 
1424
}
 
1425
 
 
1426
/*----------------------------------------------------------------------------
 
1427
 * Assign shared vertex coordinates to an extracted nodal mesh,
 
1428
 * renumbering vertex numbers based on those really referenced,
 
1429
 * and updating connectivity arrays in accordance.
 
1430
 *
 
1431
 * This function should only be called once all element sections
 
1432
 * have been added to a nodal mesh representation.
 
1433
 *
 
1434
 * parameters:
 
1435
 *   this_nodal      <-> nodal mesh structure
 
1436
 *   vertex_coords   <-- coordinates of parent vertices (interlaced)
 
1437
 *----------------------------------------------------------------------------*/
 
1438
 
 
1439
void
 
1440
fvm_nodal_set_shared_vertices(fvm_nodal_t        *this_nodal,
 
1441
                              const fvm_coord_t   vertex_coords[])
 
1442
{
 
1443
  assert(this_nodal != NULL);
 
1444
 
 
1445
  /* Map vertex coordinates to array passed as argument
 
1446
     (this_nodal->_vertex_coords remains NULL, so only
 
1447
     the const pointer may be used for a shared array) */
 
1448
 
 
1449
  this_nodal->vertex_coords = vertex_coords;
 
1450
 
 
1451
  /* If the mesh contains only vertices, its n_vertices and
 
1452
     parent_vertex_num must already have been set, and do not
 
1453
     require updating */
 
1454
 
 
1455
  if (this_nodal->n_sections == 0)
 
1456
    return;
 
1457
 
 
1458
  /* Renumber vertices based on those really referenced */
 
1459
 
 
1460
  _renumber_vertices(this_nodal);
 
1461
 
 
1462
}
 
1463
 
 
1464
/*----------------------------------------------------------------------------
 
1465
 * Assign private vertex coordinates to a nodal mesh,
 
1466
 * renumbering vertex numbers based on those really referenced,
 
1467
 * and updating connectivity arrays in accordance.
 
1468
 *
 
1469
 * Ownership of the given coordinates array is transferred to
 
1470
 * the nodal mesh representation structure.
 
1471
 *
 
1472
 * This function should only be called once all element sections
 
1473
 * have been added to a nodal mesh representation.
 
1474
 *
 
1475
 * parameters:
 
1476
 *   this_nodal      <-> nodal mesh structure
 
1477
 *   vertex_coords   <-- coordinates of parent vertices (interlaced)
 
1478
 *
 
1479
 * returns:
 
1480
 *   updated pointer to vertex_coords (may be different from initial
 
1481
 *   argument if vertices were renumbered).
 
1482
 *----------------------------------------------------------------------------*/
 
1483
 
 
1484
fvm_coord_t *
 
1485
fvm_nodal_transfer_vertices(fvm_nodal_t  *this_nodal,
 
1486
                            fvm_coord_t   vertex_coords[])
 
1487
{
 
1488
  fvm_lnum_t  i;
 
1489
  int         j;
 
1490
 
 
1491
  fvm_coord_t  *_vertex_coords = vertex_coords;
 
1492
 
 
1493
  assert(this_nodal != NULL);
 
1494
 
 
1495
  /* Renumber vertices based on those really referenced, and
 
1496
     update connectivity arrays in accordance. */
 
1497
 
 
1498
  _renumber_vertices(this_nodal);
 
1499
 
 
1500
  /* If renumbering is necessary, update connectivity */
 
1501
 
 
1502
  if (this_nodal->parent_vertex_num != NULL) {
 
1503
 
 
1504
    int dim = this_nodal->dim;
 
1505
    const fvm_lnum_t *parent_vertex_num = this_nodal->parent_vertex_num;
 
1506
 
 
1507
    BFT_MALLOC(_vertex_coords, this_nodal->n_vertices * dim, fvm_coord_t);
 
1508
 
 
1509
    for (i = 0; i < this_nodal->n_vertices; i++) {
 
1510
      for (j = 0; j < dim; j++)
 
1511
        _vertex_coords[i*dim + j]
 
1512
          = vertex_coords[(parent_vertex_num[i]-1)*dim + j];
 
1513
    }
 
1514
 
 
1515
    BFT_FREE(vertex_coords);
 
1516
 
 
1517
    this_nodal->parent_vertex_num = NULL;
 
1518
    if (this_nodal->_parent_vertex_num != NULL)
 
1519
      BFT_FREE(this_nodal->_parent_vertex_num);
 
1520
  }
 
1521
 
 
1522
  this_nodal->_vertex_coords = _vertex_coords;
 
1523
  this_nodal->vertex_coords = _vertex_coords;
 
1524
 
 
1525
  return _vertex_coords;
 
1526
}
 
1527
 
 
1528
/*----------------------------------------------------------------------------
 
1529
 * Make vertex coordinates of a nodal mesh private.
 
1530
 *
 
1531
 * If vertex coordinates were previously shared, those coordinates that
 
1532
 * are actually refernces are copied, and the relation to parent vertices
 
1533
 * is discarded.
 
1534
 *
 
1535
 * If vertices were already private, the mesh is not modified.
 
1536
 *
 
1537
 * parameters:
 
1538
 *   this_nodal <-> nodal mesh structure
 
1539
 *----------------------------------------------------------------------------*/
 
1540
 
 
1541
void
 
1542
fvm_nodal_make_vertices_private(fvm_nodal_t  *this_nodal)
 
1543
{
 
1544
  assert(this_nodal != NULL);
 
1545
 
 
1546
  if (this_nodal->_vertex_coords == NULL) {
 
1547
 
 
1548
    fvm_coord_t *_vertex_coords = NULL;
 
1549
    const fvm_coord_t *vertex_coords = this_nodal->vertex_coords;
 
1550
    const fvm_lnum_t n_vertices = this_nodal->n_vertices;
 
1551
    const int dim = this_nodal->dim;
 
1552
 
 
1553
    BFT_MALLOC(vertex_coords, n_vertices * dim, fvm_coord_t);
 
1554
 
 
1555
    /* If renumbering is necessary, update connectivity */
 
1556
 
 
1557
    if (this_nodal->parent_vertex_num != NULL) {
 
1558
 
 
1559
      fvm_lnum_t i;
 
1560
      int j;
 
1561
      const fvm_lnum_t *parent_vertex_num = this_nodal->parent_vertex_num;
 
1562
 
 
1563
      for (i = 0; i < n_vertices; i++) {
 
1564
        for (j = 0; j < dim; j++)
 
1565
          _vertex_coords[i*dim + j]
 
1566
            = vertex_coords[(parent_vertex_num[i]-1)*dim + j];
 
1567
      }
 
1568
 
 
1569
      this_nodal->parent_vertex_num = NULL;
 
1570
      if (this_nodal->_parent_vertex_num != NULL)
 
1571
        BFT_FREE(this_nodal->_parent_vertex_num);
 
1572
    }
 
1573
    else
 
1574
      memcpy(_vertex_coords, vertex_coords, n_vertices*dim*sizeof(fvm_coord_t));
 
1575
 
 
1576
    /* Assign new array to structure */
 
1577
 
 
1578
    this_nodal->_vertex_coords = _vertex_coords;
 
1579
    this_nodal->vertex_coords = _vertex_coords;
 
1580
  }
 
1581
}
 
1582
 
 
1583
/*----------------------------------------------------------------------------
 
1584
 * Assign group class set descriptions to a nodal mesh.
 
1585
 *
 
1586
 * The structure builds its own copy of the group class sets,
 
1587
 * renumbering them so as to discard those not referenced.
 
1588
 * Empty group classes are also renumbered to zero.
 
1589
 *
 
1590
 * This function should only be called once all element sections
 
1591
 * have been added to a nodal mesh representation.
 
1592
 *
 
1593
 * parameters:
 
1594
 *   this_nodal <-> nodal mesh structure
 
1595
 *   gc_set     <-- group class set descriptions
 
1596
 *----------------------------------------------------------------------------*/
 
1597
 
 
1598
void
 
1599
fvm_nodal_set_group_class_set(fvm_nodal_t                  *this_nodal,
 
1600
                              const fvm_group_class_set_t  *gc_set)
 
1601
{
 
1602
  int gc_id, section_id;
 
1603
  int n_gc = fvm_group_class_set_size(gc_set);
 
1604
  int n_gc_new = 0;
 
1605
  fvm_lnum_t *gc_renum = NULL;
 
1606
 
 
1607
  assert(this_nodal != NULL);
 
1608
 
 
1609
  if (this_nodal->gc_set != NULL)
 
1610
    this_nodal->gc_set = fvm_group_class_set_destroy(this_nodal->gc_set);
 
1611
 
 
1612
  if (gc_set == NULL)
 
1613
    return;
 
1614
 
 
1615
  /* Mark referenced group classes */
 
1616
 
 
1617
  BFT_MALLOC(gc_renum, n_gc, fvm_lnum_t);
 
1618
 
 
1619
  for (gc_id = 0; gc_id < n_gc; gc_id++)
 
1620
    gc_renum[gc_id] = 0;
 
1621
 
 
1622
  for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
1623
    fvm_lnum_t i;
 
1624
    const fvm_nodal_section_t  *section = this_nodal->sections[section_id];
 
1625
    if (section->gc_id == NULL)
 
1626
      continue;
 
1627
    for (i = 0; i < section->n_elements; i++) {
 
1628
      if (section->gc_id[i] != 0)
 
1629
        gc_renum[section->gc_id[i] - 1] = 1;
 
1630
    }
 
1631
  }
 
1632
 
 
1633
  fvm_parall_counter_max(gc_renum, n_gc);
 
1634
 
 
1635
  /* Renumber group classes if necessary */
 
1636
 
 
1637
  for (gc_id = 0; gc_id < n_gc; gc_id++) {
 
1638
    if (gc_renum[gc_id] != 0) {
 
1639
      gc_renum[gc_id] = n_gc_new + 1;
 
1640
      n_gc_new++;
 
1641
    }
 
1642
  }
 
1643
 
 
1644
  if (n_gc_new < n_gc) {
 
1645
    for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
1646
      fvm_lnum_t i;
 
1647
      const fvm_nodal_section_t  *section = this_nodal->sections[section_id];
 
1648
      if (section->gc_id == NULL)
 
1649
        continue;
 
1650
      for (i = 0; i < section->n_elements; i++) {
 
1651
        if (section->gc_id[i] != 0)
 
1652
          section->gc_id[i] = gc_renum[section->gc_id[i] - 1];
 
1653
      }
 
1654
    }
 
1655
  }
 
1656
 
 
1657
  /* Transform renumbering array to list */
 
1658
 
 
1659
  n_gc_new = 0;
 
1660
  for (gc_id = 0; gc_id < n_gc; gc_id++) {
 
1661
    if (gc_renum[gc_id] != 0)
 
1662
      gc_renum[n_gc_new++] = gc_id;
 
1663
  }
 
1664
 
 
1665
  if (n_gc_new > 0)
 
1666
    this_nodal->gc_set = fvm_group_class_set_copy(gc_set,
 
1667
                                                  n_gc_new,
 
1668
                                                  gc_renum);
 
1669
 
 
1670
  BFT_FREE(gc_renum);
 
1671
}
 
1672
 
 
1673
/*----------------------------------------------------------------------------
 
1674
 * Obtain the name of a nodal mesh.
 
1675
 *
 
1676
 * parameters:
 
1677
 *   this_nodal           <-- pointer to nodal mesh structure
 
1678
 *
 
1679
 * returns:
 
1680
 *   pointer to constant string containing the mesh name
 
1681
 *----------------------------------------------------------------------------*/
 
1682
 
 
1683
const char *
 
1684
fvm_nodal_get_name(const fvm_nodal_t  *this_nodal)
 
1685
{
 
1686
  assert(this_nodal != NULL);
 
1687
 
 
1688
  return this_nodal->name;
 
1689
}
 
1690
 
 
1691
/*----------------------------------------------------------------------------
 
1692
 * Return spatial dimension of the nodal mesh.
 
1693
 *
 
1694
 * parameters:
 
1695
 *   this_nodal <-- pointer to nodal mesh structure
 
1696
 *
 
1697
 * returns:
 
1698
 *  spatial dimension.
 
1699
 *----------------------------------------------------------------------------*/
 
1700
 
 
1701
int
 
1702
fvm_nodal_get_dim(const fvm_nodal_t  *this_nodal)
 
1703
{
 
1704
  return this_nodal->dim;
 
1705
}
 
1706
 
 
1707
/*----------------------------------------------------------------------------
 
1708
 * Return maximum dimension of entities in a nodal mesh.
 
1709
 *
 
1710
 * parameters:
 
1711
 *   this_nodal <-- pointer to nodal mesh structure
 
1712
 *
 
1713
 * returns:
 
1714
 *  maximum dimension of entities in mesh (0 to 3)
 
1715
 *----------------------------------------------------------------------------*/
 
1716
 
 
1717
int
 
1718
fvm_nodal_get_max_entity_dim(const fvm_nodal_t  *this_nodal)
 
1719
{
 
1720
  int  section_id;
 
1721
  int  max_entity_dim = 0;
 
1722
 
 
1723
  assert(this_nodal != NULL);
 
1724
 
 
1725
  for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
1726
    const fvm_nodal_section_t  *section = this_nodal->sections[section_id];
 
1727
    if (section->entity_dim > max_entity_dim)
 
1728
      max_entity_dim = section->entity_dim;
 
1729
  }
 
1730
 
 
1731
  return max_entity_dim;
 
1732
}
 
1733
 
 
1734
/*----------------------------------------------------------------------------
 
1735
 * Return number of entities of a given dimension in a nodal mesh.
 
1736
 *
 
1737
 * parameters:
 
1738
 *   this_nodal <-- pointer to nodal mesh structure
 
1739
 *   entity_dim <-- dimension of entities we want to count (0 to 3)
 
1740
 *
 
1741
 * returns:
 
1742
 *  number of entities of given dimension in mesh
 
1743
 *----------------------------------------------------------------------------*/
 
1744
 
 
1745
fvm_lnum_t
 
1746
fvm_nodal_get_n_entities(const fvm_nodal_t  *this_nodal,
 
1747
                         int                 entity_dim)
 
1748
{
 
1749
  fvm_lnum_t n_entities;
 
1750
 
 
1751
  assert(this_nodal != NULL);
 
1752
 
 
1753
  switch(entity_dim) {
 
1754
  case 0:
 
1755
    n_entities = this_nodal->n_vertices;
 
1756
    break;
 
1757
  case 1:
 
1758
    n_entities = this_nodal->n_edges;
 
1759
    break;
 
1760
  case 2:
 
1761
    n_entities = this_nodal->n_faces;
 
1762
    break;
 
1763
  case 3:
 
1764
    n_entities = this_nodal->n_cells;
 
1765
    break;
 
1766
  default:
 
1767
    n_entities = 0;
 
1768
  }
 
1769
 
 
1770
  return n_entities;
 
1771
}
 
1772
 
 
1773
/*----------------------------------------------------------------------------
 
1774
 * Return global number of vertices associated with nodal mesh.
 
1775
 *
 
1776
 * parameters:
 
1777
 *   this_nodal           <-- pointer to nodal mesh structure
 
1778
 *
 
1779
 * returns:
 
1780
 *   global number of vertices associated with nodal mesh
 
1781
 *----------------------------------------------------------------------------*/
 
1782
 
 
1783
fvm_gnum_t
 
1784
fvm_nodal_get_n_g_vertices(const fvm_nodal_t  *this_nodal)
 
1785
{
 
1786
  return fvm_nodal_n_g_vertices(this_nodal);
 
1787
}
 
1788
 
 
1789
/*----------------------------------------------------------------------------
 
1790
 * Return global number of elements of a given type associated with nodal mesh.
 
1791
 *
 
1792
 * parameters:
 
1793
 *   this_nodal           <-- pointer to nodal mesh structure
 
1794
 *   element_type         <-- type of elements for query
 
1795
 *
 
1796
 * returns:
 
1797
 *   global number of elements of the given type associated with nodal mesh
 
1798
 *----------------------------------------------------------------------------*/
 
1799
 
 
1800
fvm_gnum_t
 
1801
fvm_nodal_get_n_g_elements(const fvm_nodal_t  *this_nodal,
 
1802
                           fvm_element_t       element_type)
 
1803
{
 
1804
  int  i;
 
1805
  fvm_gnum_t  n_g_elements = 0;
 
1806
 
 
1807
  assert(this_nodal != NULL);
 
1808
 
 
1809
  for (i = 0; i < this_nodal->n_sections; i++) {
 
1810
    fvm_nodal_section_t  *section = this_nodal->sections[i];
 
1811
    if (section->type == element_type)
 
1812
      n_g_elements += fvm_nodal_section_n_g_elements(section);
 
1813
  }
 
1814
 
 
1815
  return n_g_elements;
 
1816
}
 
1817
 
 
1818
/*----------------------------------------------------------------------------
 
1819
 * Return local number of elements of a given type associated with nodal mesh.
 
1820
 *
 
1821
 * parameters:
 
1822
 *   this_nodal           <-- pointer to nodal mesh structure
 
1823
 *   element_type         <-- type of elements for query
 
1824
 *
 
1825
 * returns:
 
1826
 *   local number of elements of the given type associated with nodal mesh
 
1827
 *----------------------------------------------------------------------------*/
 
1828
 
 
1829
fvm_lnum_t
 
1830
fvm_nodal_get_n_elements(const fvm_nodal_t  *this_nodal,
 
1831
                         fvm_element_t       element_type)
 
1832
{
 
1833
  int  i;
 
1834
  fvm_lnum_t  n_elements = 0;
 
1835
 
 
1836
  assert(this_nodal != NULL);
 
1837
 
 
1838
  for (i = 0; i < this_nodal->n_sections; i++) {
 
1839
    fvm_nodal_section_t  *section = this_nodal->sections[i];
 
1840
    if (section->type == element_type)
 
1841
      n_elements += section->n_elements;
 
1842
  }
 
1843
 
 
1844
  return n_elements;
 
1845
}
 
1846
 
 
1847
/*----------------------------------------------------------------------------
 
1848
 * Return local parent numbering array for all entities of a given
 
1849
 * dimension in a nodal mesh.
 
1850
 *
 
1851
 * The number of entities of the given dimension may be obtained
 
1852
 * through fvm_nodal_get_n_entities(), the parent_num[] array is populated
 
1853
 * with the parent entity numbers of those entities, in order (i.e. in
 
1854
 * local section order, section by section).
 
1855
 *
 
1856
 * parameters:
 
1857
 *   this_nodal <-- pointer to nodal mesh structure
 
1858
 *   entity_dim <-- dimension of entities we are interested in (0 to 3)
 
1859
 *   parent_num --> entity parent numbering (array must be pre-allocated)
 
1860
 *----------------------------------------------------------------------------*/
 
1861
 
 
1862
void
 
1863
fvm_nodal_get_parent_num(const fvm_nodal_t  *this_nodal,
 
1864
                         int                 entity_dim,
 
1865
                         fvm_lnum_t          parent_num[])
 
1866
{
 
1867
  int section_id;
 
1868
  fvm_lnum_t i;
 
1869
 
 
1870
  fvm_lnum_t entity_count = 0;
 
1871
 
 
1872
  assert(this_nodal != NULL);
 
1873
 
 
1874
  /* Entity dimension 0: vertices */
 
1875
 
 
1876
  if (entity_dim == 0) {
 
1877
    if (this_nodal->parent_vertex_num != NULL) {
 
1878
      for (i = 0; i < this_nodal->n_vertices; i++)
 
1879
        parent_num[entity_count++] = this_nodal->parent_vertex_num[i];
 
1880
    }
 
1881
    else {
 
1882
      for (i = 0; i < this_nodal->n_vertices; i++)
 
1883
        parent_num[entity_count++] = i + 1;
 
1884
    }
 
1885
  }
 
1886
 
 
1887
  /* Entity dimension > 0: edges, faces, or cells */
 
1888
 
 
1889
  else {
 
1890
 
 
1891
    for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
1892
 
 
1893
      const fvm_nodal_section_t  *section = this_nodal->sections[section_id];
 
1894
 
 
1895
      if (section->entity_dim == entity_dim) {
 
1896
        if (section->parent_element_num != NULL) {
 
1897
          for (i = 0; i < section->n_elements; i++)
 
1898
            parent_num[entity_count++] = section->parent_element_num[i];
 
1899
        }
 
1900
        else {
 
1901
          for (i = 0; i < section->n_elements; i++)
 
1902
            parent_num[entity_count++] = i + 1;
 
1903
        }
 
1904
      }
 
1905
 
 
1906
    } /* end loop on sections */
 
1907
 
 
1908
  }
 
1909
}
 
1910
 
 
1911
/*----------------------------------------------------------------------------
 
1912
 * Compute tesselation a a nodal mesh's sections of a given type, and add the
 
1913
 * corresponding structure to the mesh representation.
 
1914
 *
 
1915
 * If global element numbers are used (i.e. in parallel mode), this function
 
1916
 * should be only be used after calling fvm_nodal_init_io_num().
 
1917
 *
 
1918
 * If some mesh sections have already been tesselated, their tesselation
 
1919
 * is unchanged.
 
1920
 *
 
1921
 * parameters:
 
1922
 *   this_nodal  <-> pointer to nodal mesh structure
 
1923
 *   type        <-> element type that should be tesselated
 
1924
 *   error_count --> number of elements with a tesselation error
 
1925
 *                   counter (optional)
 
1926
 *----------------------------------------------------------------------------*/
 
1927
 
 
1928
void
 
1929
fvm_nodal_tesselate(fvm_nodal_t    *this_nodal,
 
1930
                    fvm_element_t   type,
 
1931
                    fvm_lnum_t     *error_count)
 
1932
{
 
1933
  int section_id;
 
1934
  fvm_lnum_t section_error_count;
 
1935
 
 
1936
  assert(this_nodal != NULL);
 
1937
 
 
1938
  if (error_count != NULL)
 
1939
    *error_count = 0;
 
1940
 
 
1941
  for (section_id = 0; section_id < this_nodal->n_sections; section_id++) {
 
1942
 
 
1943
    fvm_nodal_section_t  *section = this_nodal->sections[section_id];
 
1944
 
 
1945
    if (section->type == type && section->tesselation == NULL) {
 
1946
 
 
1947
      section->tesselation = fvm_tesselation_create(type,
 
1948
                                                    section->n_elements,
 
1949
                                                    section->face_index,
 
1950
                                                    section->face_num,
 
1951
                                                    section->vertex_index,
 
1952
                                                    section->vertex_num,
 
1953
                                                    section->global_element_num);
 
1954
 
 
1955
      fvm_tesselation_init(section->tesselation,
 
1956
                           this_nodal->dim,
 
1957
                           this_nodal->vertex_coords,
 
1958
                           this_nodal->parent_vertex_num,
 
1959
                           &section_error_count);
 
1960
 
 
1961
      if (error_count != NULL)
 
1962
        *error_count += section_error_count;
 
1963
    }
 
1964
 
 
1965
  }
 
1966
}
 
1967
 
 
1968
/*----------------------------------------------------------------------------
 
1969
 * Build a nodal representation structure based on extraction of a
 
1970
 * mesh's edges.
 
1971
 *
 
1972
 * parameters:
 
1973
 *   name        <-- name to assign to extracted mesh
 
1974
 *   this_nodal  <-> pointer to nodal mesh structure
 
1975
 *----------------------------------------------------------------------------*/
 
1976
 
 
1977
fvm_nodal_t *
 
1978
fvm_nodal_copy_edges(const char         *name,
 
1979
                     const fvm_nodal_t  *this_nodal)
 
1980
{
 
1981
  int i;
 
1982
  fvm_lnum_t j, k;
 
1983
  fvm_lnum_t n_edges = 0, n_max_edges = 0;
 
1984
  fvm_nodal_t *new_nodal = NULL;
 
1985
  fvm_nodal_section_t *new_section = NULL;
 
1986
 
 
1987
  BFT_MALLOC(new_nodal, 1, fvm_nodal_t);
 
1988
 
 
1989
  /* Global indicators */
 
1990
 
 
1991
  if (name != NULL) {
 
1992
    BFT_MALLOC(new_nodal->name, strlen(name) + 1, char);
 
1993
    strcpy(new_nodal->name, name);
 
1994
  }
 
1995
  else
 
1996
    new_nodal->name = NULL;
 
1997
 
 
1998
  new_nodal->dim     = this_nodal->dim;
 
1999
  new_nodal->num_dom = this_nodal->num_dom;
 
2000
  new_nodal->n_doms  = this_nodal->n_doms;
 
2001
  new_nodal->n_sections = 1;
 
2002
 
 
2003
  /* Local dimensions */
 
2004
 
 
2005
  new_nodal->n_cells = 0;
 
2006
  new_nodal->n_faces = 0;
 
2007
  new_nodal->n_edges = 0;
 
2008
  new_nodal->n_vertices = this_nodal->n_vertices;
 
2009
 
 
2010
  /* Local structures */
 
2011
 
 
2012
  new_nodal->vertex_coords = this_nodal->vertex_coords;
 
2013
  new_nodal->_vertex_coords = NULL;
 
2014
 
 
2015
  new_nodal->parent_vertex_num = this_nodal->parent_vertex_num;
 
2016
  new_nodal->_parent_vertex_num = NULL;
 
2017
 
 
2018
  if (this_nodal->global_vertex_num != NULL) {
 
2019
    fvm_lnum_t n_ent
 
2020
      = fvm_io_num_get_local_count(this_nodal->global_vertex_num);
 
2021
    fvm_gnum_t global_count
 
2022
      = fvm_io_num_get_global_count(this_nodal->global_vertex_num);
 
2023
    const fvm_gnum_t *global_num
 
2024
      = fvm_io_num_get_global_num(this_nodal->global_vertex_num);
 
2025
 
 
2026
    new_nodal->global_vertex_num
 
2027
      = fvm_io_num_create_shared(global_num, global_count, n_ent);
 
2028
  }
 
2029
  else
 
2030
    new_nodal->global_vertex_num = NULL;
 
2031
 
 
2032
  /* Counting step */
 
2033
 
 
2034
  for (i = 0; i < this_nodal->n_sections; i++) {
 
2035
    const fvm_nodal_section_t *this_section = this_nodal->sections[i];
 
2036
    if (this_section->vertex_index == NULL)
 
2037
      n_max_edges += (  fvm_nodal_n_edges_element[this_section->type]
 
2038
                      * this_section->n_elements);
 
2039
    else if (this_section->type == FVM_FACE_POLY)
 
2040
      n_max_edges += this_section->vertex_index[this_section->n_elements];
 
2041
    else if (this_section->type == FVM_CELL_POLY)
 
2042
      n_max_edges += this_section->vertex_index[this_section->n_faces];
 
2043
  }
 
2044
 
 
2045
  BFT_MALLOC(new_nodal->sections, 1, fvm_nodal_section_t *);
 
2046
 
 
2047
  new_section = fvm_nodal_section_create(FVM_EDGE);
 
2048
  new_nodal->sections[0] = new_section;
 
2049
 
 
2050
  BFT_MALLOC(new_section->_vertex_num, n_max_edges*2, fvm_lnum_t);
 
2051
 
 
2052
  /* Add edges */
 
2053
 
 
2054
  for (i = 0; i < this_nodal->n_sections; i++) {
 
2055
 
 
2056
    const fvm_nodal_section_t *this_section = this_nodal->sections[i];
 
2057
 
 
2058
    if (   this_section->type == FVM_FACE_POLY
 
2059
        || this_section->type == FVM_CELL_POLY) {
 
2060
 
 
2061
      fvm_lnum_t n_faces = this_section->type == FVM_FACE_POLY ?
 
2062
        this_section->n_elements : this_section->n_faces;
 
2063
 
 
2064
      for (j = 0; j < n_faces; j++) {
 
2065
        const fvm_lnum_t face_start_id = this_section->vertex_index[j];
 
2066
        const fvm_lnum_t n_face_edges
 
2067
          = this_section->vertex_index[j+1] - this_section->vertex_index[j];
 
2068
        for (k = 0; k < n_face_edges; k++) {
 
2069
          new_section->_vertex_num[n_edges*2]
 
2070
            = this_section->vertex_num[face_start_id + k];
 
2071
          new_section->_vertex_num[n_edges*2 + 1]
 
2072
            = this_section->vertex_num[face_start_id + (k + 1)%n_face_edges];
 
2073
          n_edges += 1;
 
2074
        }
 
2075
      }
 
2076
 
 
2077
    }
 
2078
    else {
 
2079
 
 
2080
      fvm_lnum_t edges[2][12];
 
2081
 
 
2082
      fvm_lnum_t n_elt_edges = fvm_nodal_n_edges_element[this_section->type];
 
2083
      fvm_lnum_t n_elts = this_section->n_elements;
 
2084
      fvm_lnum_t stride = this_section->stride;
 
2085
 
 
2086
      switch (this_section->type) {
 
2087
 
 
2088
      case FVM_EDGE:
 
2089
      case FVM_FACE_TRIA:
 
2090
      case FVM_FACE_QUAD:
 
2091
        for (j = 0; j < n_elt_edges; j++) {
 
2092
          edges[0][j] = j;
 
2093
          edges[1][j] = (j+1)%n_elt_edges;
 
2094
        }
 
2095
        break;
 
2096
 
 
2097
      case FVM_CELL_TETRA:
 
2098
        edges[0][0] = 0; edges[1][0] = 1;
 
2099
        edges[0][1] = 1; edges[1][1] = 2;
 
2100
        edges[0][2] = 2; edges[1][2] = 0;
 
2101
        edges[0][3] = 0; edges[1][3] = 3;
 
2102
        edges[0][4] = 1; edges[1][4] = 3;
 
2103
        edges[0][5] = 2; edges[1][5] = 3;
 
2104
        break;
 
2105
 
 
2106
      case FVM_CELL_PYRAM:
 
2107
        edges[0][0] = 0; edges[1][0] = 1;
 
2108
        edges[0][1] = 1; edges[1][1] = 2;
 
2109
        edges[0][2] = 2; edges[1][2] = 3;
 
2110
        edges[0][3] = 3; edges[1][3] = 0;
 
2111
        edges[0][4] = 0; edges[1][4] = 4;
 
2112
        edges[0][5] = 1; edges[1][5] = 4;
 
2113
        edges[0][6] = 2; edges[1][6] = 4;
 
2114
        edges[0][7] = 3; edges[1][7] = 4;
 
2115
        break;
 
2116
 
 
2117
      case FVM_CELL_PRISM:
 
2118
        edges[0][0] = 0; edges[1][0] = 1;
 
2119
        edges[0][1] = 1; edges[1][1] = 2;
 
2120
        edges[0][2] = 2; edges[1][2] = 0;
 
2121
        edges[0][3] = 0; edges[1][3] = 3;
 
2122
        edges[0][4] = 1; edges[1][4] = 4;
 
2123
        edges[0][5] = 2; edges[1][5] = 5;
 
2124
        edges[0][6] = 3; edges[1][6] = 4;
 
2125
        edges[0][7] = 4; edges[1][7] = 5;
 
2126
        edges[0][8] = 5; edges[1][8] = 3;
 
2127
        break;
 
2128
 
 
2129
      case FVM_CELL_HEXA:
 
2130
        edges[0][0] = 0; edges[1][0] = 1;
 
2131
        edges[0][1] = 1; edges[1][1] = 2;
 
2132
        edges[0][2] = 2; edges[1][2] = 3;
 
2133
        edges[0][3] = 3; edges[1][3] = 0;
 
2134
        edges[0][4] = 0; edges[1][4] = 4;
 
2135
        edges[0][5] = 1; edges[1][5] = 5;
 
2136
        edges[0][6] = 2; edges[1][6] = 6;
 
2137
        edges[0][7] = 3; edges[1][7] = 7;
 
2138
        edges[0][8] = 4; edges[1][8] = 5;
 
2139
        edges[0][9] = 5; edges[1][9] = 6;
 
2140
        edges[0][10] = 6; edges[1][10] = 7;
 
2141
        edges[0][11] = 7; edges[1][11] = 4;
 
2142
        break;
 
2143
 
 
2144
      default:
 
2145
        assert(0);
 
2146
        edges[0][0] = -1; /* For nonempty default clause */
 
2147
      }
 
2148
 
 
2149
      for (j = 0; j < n_elts; j++) {
 
2150
        const fvm_lnum_t *_vertex_num = this_section->vertex_num + (j*stride);
 
2151
        for (k = 0; k < n_elt_edges; k++) {
 
2152
          new_section->_vertex_num[n_edges*2] = _vertex_num[edges[0][k]];
 
2153
          new_section->_vertex_num[n_edges*2 + 1] = _vertex_num[edges[1][k]];
 
2154
          n_edges += 1;
 
2155
        }
 
2156
      }
 
2157
    }
 
2158
  } /* End of loop on sections */
 
2159
 
 
2160
  assert(n_edges == n_max_edges);
 
2161
 
 
2162
  /* Ensure edges are oriented in the same direction */
 
2163
 
 
2164
  if (this_nodal->global_vertex_num != NULL) {
 
2165
 
 
2166
    const fvm_gnum_t *v_num_g
 
2167
      = fvm_io_num_get_global_num(this_nodal->global_vertex_num);
 
2168
 
 
2169
    for (j = 0; j < n_max_edges; j++) {
 
2170
      fvm_lnum_t vnum_1 = new_section->_vertex_num[j*2];
 
2171
      fvm_lnum_t vnum_2 = new_section->_vertex_num[j*2 + 1];
 
2172
      if (v_num_g[vnum_1 - 1] > v_num_g[vnum_2 - 1]) {
 
2173
        new_section->_vertex_num[j*2] = vnum_2;
 
2174
        new_section->_vertex_num[j*2 + 1] = vnum_1;
 
2175
      }
 
2176
 
 
2177
    }
 
2178
 
 
2179
  }
 
2180
  else {
 
2181
 
 
2182
    for (j = 0; j < n_max_edges; j++) {
 
2183
      fvm_lnum_t vnum_1 = new_section->_vertex_num[j*2];
 
2184
      fvm_lnum_t vnum_2 = new_section->_vertex_num[j*2 + 1];
 
2185
      if (vnum_1 > vnum_2) {
 
2186
        new_section->_vertex_num[j*2] = vnum_2;
 
2187
        new_section->_vertex_num[j*2 + 1] = vnum_1;
 
2188
      }
 
2189
    }
 
2190
 
 
2191
  }
 
2192
 
 
2193
  /* Sort and remove duplicates
 
2194
     (use qsort rather than fvm_order_local_s() so as to sort in place) */
 
2195
 
 
2196
  qsort(new_section->_vertex_num,
 
2197
        n_max_edges,
 
2198
        sizeof(fvm_lnum_t) * 2,
 
2199
        &_compare_edges);
 
2200
 
 
2201
  {
 
2202
    fvm_lnum_t vn_1_p = -1;
 
2203
    fvm_lnum_t vn_2_p = -1;
 
2204
 
 
2205
    n_edges = 0;
 
2206
 
 
2207
    for (j = 0; j < n_max_edges; j++) {
 
2208
 
 
2209
      fvm_lnum_t vn_1 = new_section->_vertex_num[j*2];
 
2210
      fvm_lnum_t vn_2 = new_section->_vertex_num[j*2 + 1];
 
2211
 
 
2212
      if (vn_1 != vn_1_p || vn_2 != vn_2_p) {
 
2213
        new_section->_vertex_num[n_edges*2]     = vn_1;
 
2214
        new_section->_vertex_num[n_edges*2 + 1] = vn_2;
 
2215
        vn_1_p = vn_1;
 
2216
        vn_2_p = vn_2;
 
2217
        n_edges += 1;
 
2218
      }
 
2219
    }
 
2220
  }
 
2221
 
 
2222
  /* Resize edge connectivity to adjust to final size */
 
2223
 
 
2224
  BFT_REALLOC(new_section->_vertex_num, n_edges*2, fvm_lnum_t);
 
2225
  new_section->vertex_num = new_section->_vertex_num;
 
2226
 
 
2227
  new_section->n_elements = n_edges;
 
2228
  new_nodal->n_edges = n_edges;
 
2229
 
 
2230
  /* Build  global edge numbering if necessary */
 
2231
 
 
2232
  if (new_nodal->n_doms > 1) {
 
2233
 
 
2234
    fvm_gnum_t *edge_vertices_g; /* edges -> global vertices */
 
2235
 
 
2236
    BFT_MALLOC(edge_vertices_g, n_edges*2, fvm_gnum_t);
 
2237
 
 
2238
    if (this_nodal->global_vertex_num != NULL) {
 
2239
      const fvm_gnum_t *v_num_g
 
2240
        = fvm_io_num_get_global_num(this_nodal->global_vertex_num);
 
2241
      for (j = 0; j < n_edges; j++) {
 
2242
        edge_vertices_g[j*2]   = v_num_g[new_section->_vertex_num[j*2] - 1];
 
2243
        edge_vertices_g[j*2+1] = v_num_g[new_section->_vertex_num[j*2+1] - 1];
 
2244
      }
 
2245
    }
 
2246
    else {
 
2247
      for (j = 0; j < n_edges; j++) {
 
2248
        edge_vertices_g[j*2]     = new_section->_vertex_num[j*2];
 
2249
        edge_vertices_g[j*2 + 1] = new_section->_vertex_num[j*2 + 1];
 
2250
      }
 
2251
    }
 
2252
 
 
2253
    new_section->global_element_num
 
2254
      = fvm_io_num_create_from_adj_s(NULL, edge_vertices_g, n_edges, 2);
 
2255
 
 
2256
 
 
2257
    BFT_FREE(edge_vertices_g);
 
2258
  };
 
2259
 
 
2260
  new_nodal->gc_set = NULL;
 
2261
 
 
2262
  return (new_nodal);
 
2263
}
 
2264
 
 
2265
/*----------------------------------------------------------------------------
 
2266
 * Dump printout of a nodal representation structure.
 
2267
 *
 
2268
 * parameters:
 
2269
 *   this_nodal <-- pointer to structure that should be dumped
 
2270
 *----------------------------------------------------------------------------*/
 
2271
 
 
2272
void
 
2273
fvm_nodal_dump(const fvm_nodal_t  *this_nodal)
 
2274
{
 
2275
  fvm_lnum_t  i;
 
2276
  fvm_lnum_t  num_vertex = 1;
 
2277
  const fvm_coord_t  *coord = this_nodal->vertex_coords;
 
2278
 
 
2279
  /* Global indicators */
 
2280
  /*--------------------*/
 
2281
 
 
2282
  bft_printf("\n"
 
2283
             "Mesh name:\"%s\"\n",
 
2284
             this_nodal->name);
 
2285
 
 
2286
  bft_printf("\n"
 
2287
             "Mesh dimension:               %d\n"
 
2288
             "Domain number:                %d\n"
 
2289
             "Number of domains:            %d\n"
 
2290
             "Number of sections:           %d\n",
 
2291
             this_nodal->dim, this_nodal->num_dom, this_nodal->n_doms,
 
2292
             this_nodal->n_sections);
 
2293
 
 
2294
  bft_printf("\n"
 
2295
             "Number of cells:               %d\n"
 
2296
             "Number of faces:               %d\n"
 
2297
             "Number of edges:               %d\n"
 
2298
             "Number of vertices:            %d\n",
 
2299
            this_nodal->n_cells,
 
2300
            this_nodal->n_faces,
 
2301
            this_nodal->n_edges,
 
2302
            this_nodal->n_vertices);
 
2303
 
 
2304
  if (this_nodal->n_vertices > 0) {
 
2305
 
 
2306
    bft_printf("\n"
 
2307
               "Pointers to shareable arrays:\n"
 
2308
               "  vertex_coords:        %p\n"
 
2309
               "  parent_vertex_num:    %p\n",
 
2310
               this_nodal->vertex_coords,
 
2311
               this_nodal->parent_vertex_num);
 
2312
 
 
2313
    bft_printf("\n"
 
2314
               "Pointers to local arrays:\n"
 
2315
               "  _vertex_coords:       %p\n"
 
2316
               "  _parent_vertex_num:   %p\n",
 
2317
               this_nodal->_vertex_coords,
 
2318
               this_nodal->_parent_vertex_num);
 
2319
 
 
2320
    /* Output coordinates depending on parent numbering */
 
2321
 
 
2322
    if (this_nodal->parent_vertex_num == NULL) {
 
2323
 
 
2324
      bft_printf("\nVertex coordinates:\n\n");
 
2325
      switch(this_nodal->dim) {
 
2326
      case 1:
 
2327
        for (i = 0; i < this_nodal->n_vertices; i++)
 
2328
          bft_printf("%10d : %12.5f\n",
 
2329
                     num_vertex++, (double)(coord[i]));
 
2330
        break;
 
2331
      case 2:
 
2332
        for (i = 0; i < this_nodal->n_vertices; i++)
 
2333
          bft_printf("%10d : %12.5f %12.5f\n",
 
2334
                     num_vertex++, (double)(coord[i*2]),
 
2335
                     (double)(coord[i*2+1]));
 
2336
        break;
 
2337
      case 3:
 
2338
        for (i = 0; i < this_nodal->n_vertices; i++)
 
2339
          bft_printf("%10d : %12.5f %12.5f %12.5f\n",
 
2340
                     num_vertex++, (double)(coord[i*3]),
 
2341
                     (double)(coord[i*3+1]), (double)(coord[i*3+2]));
 
2342
        break;
 
2343
      default:
 
2344
        bft_printf("coordinates not output\n"
 
2345
                   "dimension = %d unsupported\n", this_nodal->dim);
 
2346
      }
 
2347
 
 
2348
    }
 
2349
    else { /* if (this_nodal->parent_vertex_num != NULL) */
 
2350
 
 
2351
      bft_printf("\nVertex parent and coordinates:\n\n");
 
2352
 
 
2353
      switch(this_nodal->dim) {
 
2354
      case 1:
 
2355
        for (i = 0; i < this_nodal->n_vertices; i++) {
 
2356
          coord =   this_nodal->vertex_coords
 
2357
                  + (this_nodal->parent_vertex_num[i]-1);
 
2358
          bft_printf("%10d : %12.5f\n",
 
2359
                     num_vertex++, (double)(coord[0]));
 
2360
        }
 
2361
        break;
 
2362
      case 2:
 
2363
        for (i = 0; i < this_nodal->n_vertices; i++) {
 
2364
          coord =   this_nodal->vertex_coords
 
2365
                  + ((this_nodal->parent_vertex_num[i]-1)*2);
 
2366
          bft_printf("%10d : %12.5f %12.5f\n",
 
2367
                     num_vertex++, (double)(coord[0]), (double)(coord[1]));
 
2368
        }
 
2369
        break;
 
2370
      case 3:
 
2371
        for (i = 0; i < this_nodal->n_vertices; i++) {
 
2372
          coord =   this_nodal->vertex_coords
 
2373
                  + ((this_nodal->parent_vertex_num[i]-1)*3);
 
2374
          bft_printf("%10d : %12.5f %12.5f %12.5f\n",
 
2375
                     num_vertex++, (double)(coord[0]), (double)(coord[1]),
 
2376
                     (double)(coord[2]));
 
2377
        }
 
2378
        break;
 
2379
      default:
 
2380
        bft_printf("coordinates not output\n"
 
2381
                   "dimension = %d unsupported\n", this_nodal->dim);
 
2382
      }
 
2383
 
 
2384
    }
 
2385
 
 
2386
  }
 
2387
 
 
2388
  /* Global vertex numbers (only for parallel execution) */
 
2389
  if (this_nodal->global_vertex_num != NULL) {
 
2390
    bft_printf("\nGlobal vertex numbers:\n\n");
 
2391
    fvm_io_num_dump(this_nodal->global_vertex_num);
 
2392
  }
 
2393
 
 
2394
  /* Dump element sections */
 
2395
  /*-----------------------*/
 
2396
 
 
2397
  for (i = 0; i < this_nodal->n_sections; i++)
 
2398
    _fvm_nodal_section_dump(this_nodal->sections[i]);
 
2399
 
 
2400
  /* Dump group class set (NULL allowed) */
 
2401
 
 
2402
  fvm_group_class_set_dump(this_nodal->gc_set);
 
2403
}
 
2404
 
 
2405
/*----------------------------------------------------------------------------*/
 
2406
 
 
2407
#ifdef __cplusplus
 
2408
}
 
2409
#endif /* __cplusplus */