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

« back to all changes in this revision

Viewing changes to src/fvm/fvm_tesselation.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2011-11-01 17:43:32 UTC
  • mto: (6.1.7 sid)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: package-import@ubuntu.com-20111101174332-tl4vk45no0x3emc3
Tags: upstream-2.1.0
ImportĀ upstreamĀ versionĀ 2.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*============================================================================
 
2
 * Structure describing a mesh section's subdivision into simpler elements
 
3
 *
 
4
 * This is mostly useful to replace polygons or polyhedra by simpler
 
5
 * elements such as triangles, tetrahedra, and prisms upon data export.
 
6
 *============================================================================*/
 
7
 
 
8
/*
 
9
  This file is part of Code_Saturne, a general-purpose CFD tool.
 
10
 
 
11
  Copyright (C) 1998-2011 EDF S.A.
 
12
 
 
13
  This program is free software; you can redistribute it and/or modify it under
 
14
  the terms of the GNU General Public License as published by the Free Software
 
15
  Foundation; either version 2 of the License, or (at your option) any later
 
16
  version.
 
17
 
 
18
  This program is distributed in the hope that it will be useful, but WITHOUT
 
19
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
20
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 
21
  details.
 
22
 
 
23
  You should have received a copy of the GNU General Public License along with
 
24
  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
25
  Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
26
*/
 
27
 
 
28
/*----------------------------------------------------------------------------*/
 
29
 
 
30
/*
 
31
 * Notes:
 
32
 *
 
33
 * For a polygon with n vertices (and thus n edges), a compact way of
 
34
 * storing a tesselation is described here:
 
35
 *   The vertices of each of the polygon's triangles are defined in
 
36
 *   terms of the polgon's local vertex numbers. As the local number
 
37
 *   of resulting triangles should remain small, these numbers may
 
38
 *   be represented by bit fields. for example, with 32 bit integers,
 
39
 *   we may use bits 1-10, 11-20, and 21-30 for each of a triangle's
 
40
 *   vertices (allowing for polygons with up to 1024 vertices, which
 
41
 *   vastly exceeds the number of vertices we expect for polygons
 
42
 *   (usually in the range of 5-10).
 
43
 *   This requires n-2 values per polygon, while the expanded
 
44
 *   connectivity requires (n - 2) * 3 values.
 
45
 *
 
46
 * As polyhedra are defined by their polygonal faces, this encoding
 
47
 * is also used.
 
48
 *
 
49
 * For a quadrangle, a better way is to use a single diagonal_flag, equal to
 
50
 *   O if the quadrangle is split along its diagonal (1, 3), or
 
51
 *   1 if the quadrangle is split along its diagonal (2, 4).
 
52
 *
 
53
 * In the fvm_tesselation_t structure, the encoding[] array corresponds
 
54
 * to the opposite_vertex_num[] array (of the same size as vertex_num[])
 
55
 * for polygons and polyhedra, and to a diagonal_flag[] array of size
 
56
 * n_elements for quadrangles.
 
57
 *
 
58
 * If FVM model were ever extended to elements with more than 2 vertices
 
59
 * per edge, we would need to replace n_vertices by n_edges in some of
 
60
 * this file's function's logic, but the biggest difficulty would
 
61
 * be in adding extra vertices along new edges without duplicating them:
 
62
 * this would only require some extra processing for a given section,
 
63
 * (including some communication between processors), but would
 
64
 * involve difficulties mainly when using multiple tesselation structures
 
65
 * for multiple mesh sections, as extra vertices along section boundaries
 
66
 * would need to be shared, involving extra book-keeping (and not sharing
 
67
 * those vertices would make the corresponding elements non-conforming,
 
68
 * so it would not be an option). As in most known data models, general
 
69
 * simple polygons or polyhedra only have two vertices per edge,
 
70
 * restricting tesselation to linear element types would not be a problem
 
71
 * as regards its main intended use, which is to allow replacement of
 
72
 * polygons and/or polyhedra upon export to some formats or for use with
 
73
 * some tools which do not support these types of elements.
 
74
 */
 
75
 
 
76
/*----------------------------------------------------------------------------*/
 
77
 
 
78
#if defined(HAVE_CONFIG_H)
 
79
#include "cs_config.h"
 
80
#endif
 
81
 
 
82
/*----------------------------------------------------------------------------
 
83
 * Standard C library headers
 
84
 *----------------------------------------------------------------------------*/
 
85
 
 
86
#include <assert.h>
 
87
#include <math.h>
 
88
#include <stdio.h>
 
89
#include <stdlib.h>
 
90
#include <string.h>
 
91
 
 
92
/*----------------------------------------------------------------------------
 
93
 * BFT library headers
 
94
 *----------------------------------------------------------------------------*/
 
95
 
 
96
#include <bft_error.h>
 
97
#include <bft_mem.h>
 
98
#include <bft_printf.h>
 
99
 
 
100
/*----------------------------------------------------------------------------
 
101
 *  Local headers
 
102
 *----------------------------------------------------------------------------*/
 
103
 
 
104
#include "fvm_config_defs.h"
 
105
#include "fvm_defs.h"
 
106
#include "fvm_io_num.h"
 
107
#include "fvm_parall.h"
 
108
#include "fvm_triangulate.h"
 
109
 
 
110
/*----------------------------------------------------------------------------
 
111
 *  Header for the current file
 
112
 *----------------------------------------------------------------------------*/
 
113
 
 
114
#include "fvm_tesselation.h"
 
115
 
 
116
/*----------------------------------------------------------------------------*/
 
117
 
 
118
#ifdef __cplusplus
 
119
extern "C" {
 
120
#if 0
 
121
} /* Fake brace to force Emacs auto-indentation back to column 0 */
 
122
#endif
 
123
#endif /* __cplusplus */
 
124
 
 
125
/*=============================================================================
 
126
 * Macro definitions
 
127
 *============================================================================*/
 
128
 
 
129
/* Geometric primitives */
 
130
 
 
131
#undef _CROSS_PRODUCT_3D
 
132
#undef _DOT_PRODUCT_3D
 
133
#undef _MODULE_3D
 
134
 
 
135
#define _CROSS_PRODUCT_3D(cross_v1_v2, v1, v2) ( \
 
136
 cross_v1_v2[0] = v1[1]*v2[2] - v1[2]*v2[1],   \
 
137
 cross_v1_v2[1] = v1[2]*v2[0] - v1[0]*v2[2],   \
 
138
 cross_v1_v2[2] = v1[0]*v2[1] - v1[1]*v2[0]  )
 
139
 
 
140
#define _DOT_PRODUCT_3D(v1, v2) ( \
 
141
 v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2])
 
142
 
 
143
#define _MODULE_3D(v) \
 
144
 sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
 
145
 
 
146
/* Tesselation encoding */
 
147
 
 
148
#undef _ENCODING_BITS
 
149
#undef _DECODE_TRIANGLE_VERTICES
 
150
 
 
151
#define _ENCODING_BITS (sizeof(fvm_tesselation_encoding_t)*8/3)
 
152
#define _DECODE_TRIANGLE_VERTICES(vertex_list, encoding, decoding_mask) (\
 
153
  vertex_list[0] = encoding & decoding_mask[0], \
 
154
  vertex_list[1] = (encoding & decoding_mask[1]) >> _ENCODING_BITS, \
 
155
  vertex_list[2] = (encoding & decoding_mask[2]) >> (_ENCODING_BITS*2) )
 
156
 
 
157
/*============================================================================
 
158
 * Type definitions
 
159
 *============================================================================*/
 
160
 
 
161
typedef unsigned fvm_tesselation_encoding_t;
 
162
 
 
163
/*----------------------------------------------------------------------------
 
164
 * Structure defining a tesselation of a mesh section.
 
165
 *----------------------------------------------------------------------------*/
 
166
 
 
167
struct _fvm_tesselation_t {
 
168
 
 
169
  /* Parent section information */
 
170
  /*----------------------------*/
 
171
 
 
172
  fvm_element_t  type;             /* Element types */
 
173
 
 
174
  fvm_lnum_t  n_elements;          /* Number of elements */
 
175
 
 
176
  int         dim;                 /* Spatial dimension */
 
177
 
 
178
  int         entity_dim;          /* Entity dimension */
 
179
 
 
180
  int         stride;              /* Element size for regular elements
 
181
                                      (0 for polygons and polyhedra) */
 
182
 
 
183
  fvm_lnum_t  n_faces;             /* Number of faces defining polyhedra */
 
184
 
 
185
  /* Pointers to shared vertex coordinates */
 
186
 
 
187
  const fvm_coord_t  *vertex_coords;    /* pointer to  vertex coordinates
 
188
                                           (always interlaced:
 
189
                                           x1, y1, z1, x2, y2, z2, ...) */
 
190
 
 
191
  const fvm_lnum_t   *parent_vertex_num; /* Local numbers (1 to n) of local
 
192
                                            vertices in the parent mesh.
 
193
                                            This array is present only when non
 
194
                                            "trivial" (i.e. not 1, 2, ..., n). */
 
195
 
 
196
  /* Pointers to shared connectivity arrays */
 
197
 
 
198
  const fvm_lnum_t  *face_index;   /* polyhedron -> faces index (O to n-1);
 
199
                                      dimension [n_elements + 1] */
 
200
  const fvm_lnum_t  *face_num;     /* polyhedron -> face numbers (1 to n, signed,
 
201
                                      > 0 for outwards pointing face normal
 
202
                                      < 0 for inwards pointing face normal);
 
203
                                      dimension: [face_index[n_elements]] */
 
204
 
 
205
  const fvm_lnum_t  *vertex_index; /* polygon face -> vertices index (O to n-1);
 
206
                                      dimension: [n_cell_faces + 1] */
 
207
 
 
208
  const fvm_lnum_t  *vertex_num;   /* vertex numbers (1 to n);
 
209
                                      dimension: connectivity_size */
 
210
 
 
211
  /* Pointer to shared global element numbers */
 
212
 
 
213
  const fvm_io_num_t  *global_element_num;
 
214
 
 
215
  /* Basic information */
 
216
  /*-------------------*/
 
217
 
 
218
  int               n_sub_types;         /* Number of sub-element types
 
219
                                            (currently max 2) */
 
220
  fvm_element_t     sub_type[2];         /* Sub-element types */
 
221
 
 
222
  fvm_lnum_t        n_sub_max[2];        /* Maximum number of sub-elements of
 
223
                                            each type per element */
 
224
  fvm_lnum_t        n_sub_max_glob[2];   /* Global maximum number of
 
225
                                            sub-elements of each type
 
226
                                            per element */
 
227
  fvm_lnum_t        n_sub[2];            /* Number of sub-elements of
 
228
                                            each type */
 
229
  fvm_gnum_t        n_sub_glob[2];       /* Global number of sub-elements
 
230
                                            of each type */
 
231
 
 
232
  const fvm_tesselation_encoding_t  *encoding;    /* Compact tesselation
 
233
                                                     encoding array
 
234
                                                     (see notes above) */
 
235
 
 
236
  fvm_tesselation_encoding_t        *_encoding;   /* encoding if owner,
 
237
                                                     NULL if shared */
 
238
 
 
239
  const fvm_lnum_t  *sub_elt_index[2];   /* index of sub-elements of each
 
240
                                            given type associated with
 
241
                                            each element (0 to n-1); */
 
242
  fvm_lnum_t        *_sub_elt_index[2];  /* sub_elt_index if owner,
 
243
                                            NULL if shared */
 
244
 
 
245
};
 
246
 
 
247
/*============================================================================
 
248
 * Static global variables
 
249
 *============================================================================*/
 
250
 
 
251
/*============================================================================
 
252
 * Private function definitions
 
253
 *============================================================================*/
 
254
 
 
255
/*----------------------------------------------------------------------------
 
256
 * Compute coordinates of added vertices for a tesselation of a polyhedron.
 
257
 *
 
258
 * parameters:
 
259
 *   ts             <-- tesselation structure
 
260
 *   vertex_coords  --> coordinates of added vertices
 
261
 *   n_vertices_tot --> total number of vertex references (or NULL)
 
262
 *   element_id     <-- element index
 
263
 *----------------------------------------------------------------------------*/
 
264
 
 
265
static inline void
 
266
_added_vertex_coords(const fvm_tesselation_t  *ts,
 
267
                     fvm_coord_t               vertex_coords[3],
 
268
                     int                      *n_vertices_tot,
 
269
                     fvm_lnum_t                element_id)
 
270
{
 
271
  fvm_lnum_t n_vertices;
 
272
  fvm_lnum_t i, j, k, face_id, vertex_id;
 
273
 
 
274
  fvm_lnum_t _n_vertices_tot = 0;
 
275
  fvm_coord_t cell_center[3] = {0., 0., 0.};
 
276
  fvm_coord_t cell_center_divisor = 0.;
 
277
 
 
278
  /* Loop on polyhedron's faces */
 
279
  /*----------------------------*/
 
280
 
 
281
  for (i = ts->face_index[element_id];
 
282
       i < ts->face_index[element_id + 1];
 
283
       i++) {
 
284
 
 
285
    fvm_coord_t sign, v1[3], v2[3];
 
286
 
 
287
    fvm_coord_t vertices_center[3] = {0., 0., 0.};
 
288
    fvm_coord_t face_center[3] = {0., 0., 0.};
 
289
    fvm_coord_t face_normal[3] = {0., 0., 0.};
 
290
    fvm_coord_t triangle_center[3] = {0., 0., 0.};
 
291
    fvm_coord_t triangle_normal[3] = {0., 0., 0.};
 
292
    fvm_coord_t face_surface = 0.;
 
293
    fvm_coord_t triangle_surface = 0.;
 
294
    const fvm_coord_t *current_coords = NULL;
 
295
 
 
296
    face_id = FVM_ABS(ts->face_num[i]) - 1;
 
297
 
 
298
    n_vertices = ts->vertex_index[face_id+1] - ts->vertex_index[face_id];
 
299
 
 
300
    _n_vertices_tot += n_vertices;
 
301
 
 
302
    /* First loop on face vertices to estimate face center location */
 
303
 
 
304
    for (j = 0; j < n_vertices; j++) {
 
305
 
 
306
      vertex_id = ts->vertex_num[ts->vertex_index[face_id] + j] - 1;
 
307
 
 
308
      if (ts->parent_vertex_num != NULL)
 
309
        current_coords
 
310
          = ts->vertex_coords + ((ts->parent_vertex_num[vertex_id] - 1) * 3);
 
311
      else
 
312
        current_coords = ts->vertex_coords + (vertex_id * 3);
 
313
 
 
314
      for (k = 0; k < 3; k++)
 
315
        vertices_center[k] += current_coords[k];
 
316
 
 
317
    }
 
318
 
 
319
    for (k = 0; k < 3; k++)
 
320
      vertices_center[k] /= (fvm_coord_t)n_vertices;
 
321
 
 
322
    /* At this stage, current_coords points
 
323
       to the last face vertice's coords */
 
324
 
 
325
    for (k = 0; k < 3; k++) {
 
326
      v1[k] = current_coords[k] - vertices_center[k];
 
327
      triangle_center[k] = current_coords[k] + vertices_center[k];
 
328
    }
 
329
 
 
330
    /* Second loop on face vertices to estimate face normal */
 
331
 
 
332
    for (j = 0; j < n_vertices; j++) {
 
333
 
 
334
      vertex_id = ts->vertex_num[ts->vertex_index[face_id] + j] - 1;
 
335
 
 
336
      if (ts->parent_vertex_num != NULL)
 
337
        current_coords
 
338
          = ts->vertex_coords + ((ts->parent_vertex_num[vertex_id] - 1) * 3);
 
339
      else
 
340
        current_coords = ts->vertex_coords + (vertex_id * 3);
 
341
 
 
342
      for (k = 0; k < 3; k++) {
 
343
        v2[k] = current_coords[k] - vertices_center[k];
 
344
        triangle_center[k] =   (triangle_center[k] + current_coords[k])
 
345
                             * (1./3.);
 
346
      }
 
347
 
 
348
      _CROSS_PRODUCT_3D(triangle_normal, v1, v2);
 
349
 
 
350
      for (k = 0; k < 3; k++)
 
351
        face_normal[k] += triangle_normal[k];
 
352
 
 
353
      triangle_surface = _MODULE_3D(triangle_normal) * 0.5;
 
354
 
 
355
      if (_DOT_PRODUCT_3D(triangle_normal, face_normal) > 0)
 
356
        sign = 1.;
 
357
      else
 
358
        sign = -1.;
 
359
 
 
360
      /* Add triangle contributions to face center and normal */
 
361
 
 
362
      face_surface += triangle_surface * sign;
 
363
      for (k = 0; k < 3; k++)
 
364
        face_center[k] += triangle_center[k] * triangle_surface * sign;
 
365
 
 
366
      /* Prepare for next face vertex */
 
367
 
 
368
      for (k = 0; k < 3; k++) {
 
369
        v1[k] = v2[k];
 
370
        triangle_center[k] = current_coords[k] + vertices_center[k];
 
371
      }
 
372
 
 
373
    } /* End of second loop on face vertices */
 
374
 
 
375
    /* If first normal was not oriented like the face normal, correct sign */
 
376
 
 
377
    if (face_surface < 0) {
 
378
      face_surface = - face_surface;
 
379
      for (k = 0; k < 3; k++)
 
380
        face_center[k] = -face_center[k];
 
381
    }
 
382
 
 
383
    /* We should now divide the face_center[] values by face_surface to
 
384
       finish, but the contribution of face center to element center is:
 
385
       face_center[] * face_surface;
 
386
       which the face_center[] array contains, so we use those directly */
 
387
 
 
388
    cell_center_divisor += face_surface;
 
389
    for (k = 0; k < 3; k++)
 
390
      cell_center[k] += face_center[k];
 
391
 
 
392
  } /* End of loop on polyhedron's faces */
 
393
 
 
394
  for (k = 0; k < 3; k++)
 
395
    vertex_coords[k] = cell_center[k] / cell_center_divisor;
 
396
 
 
397
  if (n_vertices_tot != NULL)
 
398
    *n_vertices_tot = _n_vertices_tot;
 
399
}
 
400
 
 
401
/*----------------------------------------------------------------------------
 
402
 * Solve Ax = B for a 4x4 system.
 
403
 *
 
404
 * parameters:
 
405
 *   a                  <-- matrix
 
406
 *   b                  <-- right hand side
 
407
 *   x                  --> solution of Ax = b
 
408
 *
 
409
 * returns: 0 if solution was found, 1 in case of error (zero pivot)
 
410
 *----------------------------------------------------------------------------*/
 
411
 
 
412
static int
 
413
_solve_ax_b_4(double            a[4][4],
 
414
              double  *restrict b,
 
415
              double  *restrict x)
 
416
{
 
417
  int i, j, k, k_pivot;
 
418
 
 
419
  double abs_pivot, abs_a_ki, factor;
 
420
  double _a[4][4], _b[4];
 
421
  double _a_swap[4], _b_swap;
 
422
 
 
423
  const double _epsilon = 1.0e-15;
 
424
 
 
425
  /* Copy array and RHS (avoid modifying a and b) */
 
426
 
 
427
  for (i = 0; i < 4; i++) {
 
428
    for (j = 0; j < 4; j++) {
 
429
      _a[i][j] = a[i][j];
 
430
    }
 
431
    _b[i] = b[i];
 
432
  }
 
433
 
 
434
  /* Forward elimination */
 
435
 
 
436
  for (i = 0; i < 4-1; i++) {
 
437
 
 
438
    /* Seek best pivot */
 
439
 
 
440
    k_pivot = i;
 
441
    abs_pivot = FVM_ABS(_a[i][i]);
 
442
 
 
443
    for (k = i+1; k < 4; k++) {
 
444
      abs_a_ki = FVM_ABS(_a[k][i]);
 
445
      if (abs_a_ki > abs_pivot) {
 
446
        abs_pivot = abs_a_ki;
 
447
        k_pivot = k;
 
448
      }
 
449
    }
 
450
 
 
451
    /* Swap if necessary */
 
452
 
 
453
    if (k_pivot != i) {
 
454
 
 
455
      for (j = 0; j < 4; j++) {
 
456
        _a_swap[j] = _a[i][j];
 
457
        _a[i][j] = _a[k_pivot][j];
 
458
        _a[k_pivot][j] = _a_swap[j];
 
459
      }
 
460
 
 
461
      _b_swap = _b[i];
 
462
      _b[i] = _b[k_pivot];
 
463
      _b[k_pivot] = _b_swap;
 
464
 
 
465
    }
 
466
 
 
467
    if (abs_pivot < _epsilon)
 
468
      return 1;
 
469
 
 
470
    /* Eliminate values */
 
471
 
 
472
    for (k = i+1; k < 4; k++) {
 
473
 
 
474
      factor = _a[k][i] / _a[i][i];
 
475
 
 
476
      _a[k][i] = 0.0;
 
477
      for (j = i+1; j < 4; j++) {
 
478
        _a[k][j] -= _a[i][j]*factor;
 
479
      }
 
480
      _b[k] -= _b[i]*factor;
 
481
 
 
482
    }
 
483
 
 
484
  }
 
485
 
 
486
  /* Solve system */
 
487
 
 
488
  x[3] =  _b[3]                                                   / _a[3][3];
 
489
  x[2] = (_b[2] - _a[2][3]*x[3])                                  / _a[2][2];
 
490
  x[1] = (_b[1] - _a[1][3]*x[3]  - _a[1][2]*x[2])                 / _a[1][1];
 
491
  x[0] = (_b[0] - _a[0][3]*x[3]  - _a[0][2]*x[2] - _a[0][1]*x[1]) / _a[0][0];
 
492
 
 
493
  return 0;
 
494
}
 
495
 
 
496
/*----------------------------------------------------------------------------
 
497
 * Compute coordinates of added vertices for a tesselation of a polyhedron.
 
498
 *
 
499
 * The heap and vertex_list arrays should be large enough to contain
 
500
 * all vertex references of all the polyhedron's faces.
 
501
 *
 
502
 * parameters:
 
503
 *   ts               <-- tesselation structure
 
504
 *   heap             --- working array
 
505
 *   vertex_list      --> list of polyhedron's vertices
 
506
 *   vertex_list_size --> list size
 
507
 *   element_id       <-- element index
 
508
 *----------------------------------------------------------------------------*/
 
509
 
 
510
static inline void
 
511
_polyhedron_vertices(const fvm_tesselation_t   *ts,
 
512
                     fvm_lnum_t                 heap[],
 
513
                     fvm_lnum_t                 vertex_list[],
 
514
                     int                       *vertex_list_size,
 
515
                     fvm_lnum_t                 element_id)
 
516
{
 
517
  fvm_lnum_t n_vertices;
 
518
  fvm_lnum_t i, j, face_id, vertex_id;
 
519
 
 
520
  int heap_size = 0;
 
521
 
 
522
  /* Loop on polyhedron's faces */
 
523
  /*----------------------------*/
 
524
 
 
525
  for (i = ts->face_index[element_id];
 
526
       i < ts->face_index[element_id + 1];
 
527
       i++) {
 
528
 
 
529
    /* Loop on face vertices */
 
530
    /*-----------------------*/
 
531
 
 
532
    face_id = FVM_ABS(ts->face_num[i]) - 1;
 
533
 
 
534
    n_vertices = ts->vertex_index[face_id+1] - ts->vertex_index[face_id];
 
535
 
 
536
    for (j = 0; j < n_vertices; j++) {
 
537
 
 
538
      /* Add to heap */
 
539
 
 
540
      int hole = heap_size;
 
541
      int parent = (hole - 1) / 2;
 
542
 
 
543
      vertex_id = ts->vertex_num[ts->vertex_index[face_id] + j] - 1;
 
544
 
 
545
      while (hole > 0 && heap[parent] > vertex_id) {
 
546
        heap[hole] = heap[parent];
 
547
        hole = parent;
 
548
        parent = (parent - 1) / 2;
 
549
      }
 
550
 
 
551
      heap[hole] = vertex_id;
 
552
      heap_size++;
 
553
 
 
554
    }
 
555
 
 
556
  }
 
557
 
 
558
  /* Now remove entries from heap */
 
559
 
 
560
  i = 0;
 
561
 
 
562
  if (heap_size > 0)
 
563
    vertex_list[i++] = heap[0];
 
564
 
 
565
  while (heap_size > 0) {
 
566
 
 
567
    if (heap[0] != vertex_list[i-1])
 
568
      vertex_list[i++] = heap[0];
 
569
 
 
570
    heap_size--;
 
571
 
 
572
    /* Insert the last item in the heap whose root is empty */
 
573
 
 
574
    {
 
575
      int start = 0;
 
576
      int child = 1; /* left child of 0 */
 
577
 
 
578
      vertex_id = heap[heap_size];
 
579
 
 
580
      while (child < heap_size) {
 
581
 
 
582
        if (child < (heap_size - 1) && heap[child] > heap[child+1])
 
583
          child++;  /* child is the smaller child of start */
 
584
 
 
585
        if (vertex_id < heap[child])
 
586
          break;    /* item stays in start */
 
587
 
 
588
        else {
 
589
          heap[start] = heap[child];
 
590
          start = child;
 
591
          child = 2*start + 1;
 
592
        }
 
593
 
 
594
      }
 
595
 
 
596
      heap[start] = vertex_id;
 
597
 
 
598
    }
 
599
 
 
600
  }
 
601
 
 
602
  *vertex_list_size = i;
 
603
}
 
604
 
 
605
/*----------------------------------------------------------------------------
 
606
 * Compute field values at added vertices for a tesselation of polyhedra.
 
607
 *
 
608
 * One additional vertex is added near the center of each polyhedra.
 
609
 * For element types other than polyhedra, there is no need for added
 
610
 * vertices, so this function returns immediately.
 
611
 *
 
612
 * parameters:
 
613
 *   this_tesselation <-- tesselation structure
 
614
 *   vertex_coords    <-- coordinates of added vertices
 
615
 *   src_dim          <-- dimension of source data
 
616
 *   src_dim_shift    <-- source data dimension shift (start index)
 
617
 *   dest_dim         <-- destination data dimension (1 if non interlaced)
 
618
 *   start_id         <-- added vertices start index
 
619
 *   end_id           <-- added vertices past the end index
 
620
 *   src_interlace    <-- indicates if source data is interlaced
 
621
 *   src_datatype     <-- source data type (float, double, or int)
 
622
 *   dest_datatype    <-- destination data type (float, double, or int)
 
623
 *   n_parent_lists   <-- number of parent lists (if parent_num != NULL)
 
624
 *   parent_num_shift <-- parent number to value array index shifts;
 
625
 *                        size: n_parent_lists
 
626
 *   parent_num       <-- if n_parent_lists > 0, parent entity numbers
 
627
 *   src_data         <-- array of source arrays (at least one, with one per
 
628
 *                        source dimension if non interlaced, times one per
 
629
 *                        parent list if multiple parent lists, with
 
630
 *                        x_parent_1, y_parent_1, ..., x_parent_2, ...) order
 
631
 *   dest_data        --> destination buffer
 
632
 *----------------------------------------------------------------------------*/
 
633
 
 
634
static void
 
635
_vertex_field_of_real_values(const fvm_tesselation_t  *this_tesselation,
 
636
                             int                       src_dim,
 
637
                             int                       src_dim_shift,
 
638
                             int                       dest_dim,
 
639
                             fvm_lnum_t                start_id,
 
640
                             fvm_lnum_t                end_id,
 
641
                             fvm_interlace_t           src_interlace,
 
642
                             fvm_datatype_t            src_datatype,
 
643
                             fvm_datatype_t            dest_datatype,
 
644
                             int                       n_parent_lists,
 
645
                             const fvm_lnum_t          parent_num_shift[],
 
646
                             const fvm_lnum_t          parent_num[],
 
647
                             const void         *const src_data[],
 
648
                             void               *const dest_data)
 
649
{
 
650
  int n_vertices_tot, pl, vertex_list_size;
 
651
  fvm_lnum_t i, j, parent_id, src_id, vertex_id;
 
652
 
 
653
  int _src_dim_shift = src_dim_shift;
 
654
  int max_list_size = 128;
 
655
 
 
656
  fvm_lnum_t _heap[128];
 
657
  fvm_lnum_t _vertex_list[128];
 
658
  fvm_lnum_t *heap = _heap;
 
659
  fvm_lnum_t *vertex_list = _vertex_list;
 
660
 
 
661
  const fvm_tesselation_t *ts = this_tesselation;
 
662
  const fvm_coord_t *current_coords = NULL;
 
663
 
 
664
  if (ts->type != FVM_CELL_POLY)
 
665
    return;
 
666
 
 
667
  /* Main loop on polyhedra */
 
668
  /*------------------------*/
 
669
 
 
670
  for (i = start_id; i < end_id; i++) {
 
671
 
 
672
    for (j = 0; j < dest_dim; j++) { /* Loop on destination dimension */
 
673
 
 
674
      fvm_coord_t vertex_coords[3];
 
675
      double coeff[4];
 
676
      double interpolated_value, v_x, v_y, v_z;
 
677
      double v_f = 0.;
 
678
 
 
679
      double a[4][4] = {{0., 0., 0., 0.},
 
680
                        {0., 0., 0., 0.},
 
681
                        {0., 0., 0., 0.},
 
682
                        {0., 0., 0., 0.}};
 
683
      double b[4] = {0., 0., 0., 0.};
 
684
 
 
685
      _added_vertex_coords(ts,
 
686
                           vertex_coords,
 
687
                           &n_vertices_tot,
 
688
                           i);
 
689
 
 
690
      /* Allocate or resize working arrays if too small */
 
691
 
 
692
      if (n_vertices_tot > max_list_size) {
 
693
        max_list_size *= 2;
 
694
        if (heap == _heap) {
 
695
          heap = NULL;
 
696
          vertex_list = NULL;
 
697
        }
 
698
        BFT_REALLOC(heap, max_list_size, fvm_lnum_t);
 
699
        BFT_REALLOC(vertex_list, max_list_size, fvm_lnum_t);
 
700
      }
 
701
 
 
702
      /* Obtain list of polyhedron's vertices */
 
703
 
 
704
      _polyhedron_vertices(ts,
 
705
                           heap,
 
706
                           vertex_list,
 
707
                           &vertex_list_size,
 
708
                           i);
 
709
 
 
710
      /* Build matrix for least squares */
 
711
 
 
712
      for (j = 0; j < vertex_list_size; j++) {
 
713
 
 
714
        vertex_id = vertex_list[j];
 
715
 
 
716
        if (ts->parent_vertex_num != NULL)
 
717
          current_coords
 
718
            = ts->vertex_coords + ((ts->parent_vertex_num[vertex_id] - 1) * 3);
 
719
        else
 
720
          current_coords = ts->vertex_coords + (vertex_id * 3);
 
721
 
 
722
        v_x = current_coords[0];
 
723
        v_y = current_coords[1];
 
724
        v_z = current_coords[2];
 
725
 
 
726
        /* Position in source data for current vertex value */
 
727
 
 
728
        if (n_parent_lists == 0) {
 
729
          pl = 0;
 
730
          parent_id = vertex_id;
 
731
        }
 
732
        else if (parent_num != NULL) {
 
733
          for (parent_id = parent_num[vertex_id] - 1, pl = n_parent_lists - 1;
 
734
               parent_id < parent_num_shift[pl];
 
735
               pl--);
 
736
          assert(pl > -1);
 
737
          parent_id -= parent_num_shift[pl];
 
738
        }
 
739
        else {
 
740
          for (parent_id = vertex_id, pl = n_parent_lists - 1 ;
 
741
               parent_id < parent_num_shift[pl] ;
 
742
               pl--);
 
743
          assert(pl > -1);
 
744
          parent_id -= parent_num_shift[pl];
 
745
        }
 
746
 
 
747
        if (src_interlace == FVM_INTERLACE) {
 
748
          src_id = parent_id * src_dim + _src_dim_shift;
 
749
        }
 
750
        else {
 
751
          pl = src_dim*pl + _src_dim_shift;
 
752
          src_id = parent_id;
 
753
        }
 
754
 
 
755
        /* Now convert based on source datatype */
 
756
 
 
757
        switch(src_datatype) {
 
758
        case FVM_FLOAT:
 
759
          v_f = ((const float *const *const)src_data)[pl][src_id];
 
760
          break;
 
761
        case FVM_DOUBLE:
 
762
          v_f = ((const double *const *const)src_data)[pl][src_id];
 
763
          break;
 
764
        default:
 
765
          assert(0);
 
766
        }
 
767
 
 
768
        a[0][0] += v_x * v_x;
 
769
        a[0][1] += v_x * v_y;
 
770
        a[0][2] += v_x * v_z;
 
771
        a[0][3] += v_x;
 
772
 
 
773
        a[1][1] += v_y * v_y;
 
774
        a[1][2] += v_y * v_z;
 
775
        a[1][3] += v_y;
 
776
 
 
777
        a[2][2] += v_z * v_z;
 
778
        a[2][3] += v_z;
 
779
 
 
780
        a[3][3] += 1.;
 
781
 
 
782
        b[0] += v_x * v_f;
 
783
        b[1] += v_y * v_f;
 
784
        b[2] += v_z * v_f;
 
785
        b[3] += v_f;
 
786
 
 
787
      } /* End of loop on element vertices */
 
788
 
 
789
      /* Matrix is symmetric */
 
790
 
 
791
      a[1][0] = a[0][1];
 
792
      a[2][0] = a[0][2];
 
793
      a[3][0] = a[0][3];
 
794
 
 
795
      a[2][1] = a[1][2];
 
796
      a[3][1] = a[1][3];
 
797
 
 
798
      a[3][2] = a[2][3];
 
799
 
 
800
      /* Find hyperplane coefficients and compute added value */
 
801
 
 
802
      if (_solve_ax_b_4(a, b, coeff) == 0) {
 
803
        interpolated_value = (  coeff[0] * vertex_coords[0]
 
804
                              + coeff[1] * vertex_coords[1]
 
805
                              + coeff[2] * vertex_coords[2]
 
806
                              + coeff[3]);
 
807
      }
 
808
      else {
 
809
        interpolated_value = v_f; /* last encountered value */
 
810
      }
 
811
 
 
812
      /* Now convert based on destination datatype */
 
813
 
 
814
      switch(dest_datatype) {
 
815
      case FVM_FLOAT:
 
816
        ((float *const)dest_data)[i] = interpolated_value;
 
817
        break;
 
818
      case FVM_DOUBLE:
 
819
        ((double *const)dest_data)[i] = interpolated_value;
 
820
        break;
 
821
      default:
 
822
        assert(0);
 
823
      }
 
824
 
 
825
    } /* End of loop on destination dimension */
 
826
 
 
827
  } /* End of main loop on polyhedra */
 
828
 
 
829
  if (heap != _heap) {
 
830
    BFT_FREE(heap);
 
831
    BFT_FREE(vertex_list);
 
832
  }
 
833
}
 
834
 
 
835
/*----------------------------------------------------------------------------
 
836
 * Initialize decoding mask for polygon triangulations.
 
837
 *
 
838
 * parameters:
 
839
 *   decoding_mask         <-- decoding mask for triangle
 
840
 *----------------------------------------------------------------------------*/
 
841
 
 
842
static void
 
843
_init_decoding_mask(fvm_tesselation_encoding_t decoding_mask[3])
 
844
{
 
845
  unsigned i;
 
846
 
 
847
  for (i = 0; i < _ENCODING_BITS; i++)
 
848
    decoding_mask[0] = (decoding_mask[0] << 1) + 1;
 
849
  decoding_mask[1] = decoding_mask[0] << _ENCODING_BITS;
 
850
  decoding_mask[2] = decoding_mask[1] << _ENCODING_BITS;
 
851
}
 
852
 
 
853
/*----------------------------------------------------------------------------
 
854
 * Tesselate polygons (2D elements or 3D element faces) of a mesh section
 
855
 * referred to by an fvm_tesselation_t structure. Quadrangles are not
 
856
 * tesselated.
 
857
 *
 
858
 * parameters:
 
859
 *   this_tesselation   <-> partially initialized tesselation structure
 
860
 *   dim                <-- spatial dimension
 
861
 *   vertex_coords      <-- associated vertex coordinates array
 
862
 *   parent_vertex_num  <-- optional indirection to vertex coordinates
 
863
 *   error_count        --> number of triangulation errors counter (optional)
 
864
 *----------------------------------------------------------------------------*/
 
865
 
 
866
static void
 
867
_tesselate_polygons(fvm_tesselation_t  *this_tesselation,
 
868
                    int                 dim,
 
869
                    const fvm_coord_t   vertex_coords[],
 
870
                    const fvm_lnum_t    parent_vertex_num[],
 
871
                    fvm_lnum_t         *error_count)
 
872
{
 
873
  int type_id;
 
874
  fvm_lnum_t n_vertices, n_triangles, n_quads, n_elements;
 
875
  fvm_lnum_t n_vertices_max, n_triangles_max;
 
876
  fvm_lnum_t i, j, k, vertex_id, encoding_id;
 
877
  fvm_tesselation_encoding_t encoding_sub[3];
 
878
 
 
879
  fvm_gnum_t n_g_elements_tot[2] = {0, 0}; /* Global new elements count */
 
880
  fvm_lnum_t n_elements_tot[2] = {0, 0}; /* New triangles/quadrangles */
 
881
  fvm_lnum_t n_g_elements_max[2] = {0, 0}; /* Global max triangles/quadrangles */
 
882
  fvm_lnum_t n_elements_max[2] = {0, 0}; /* Max triangles/quadrangles */
 
883
  fvm_lnum_t *triangle_vertices = NULL;
 
884
  fvm_triangulate_state_t *state = NULL;
 
885
 
 
886
  fvm_tesselation_t *ts = this_tesselation;
 
887
 
 
888
  /* Initialization */
 
889
 
 
890
  if (error_count != NULL)
 
891
    *error_count = 0;
 
892
 
 
893
  if (ts->type != FVM_CELL_POLY)
 
894
    n_elements = ts->n_elements;
 
895
  else
 
896
    n_elements = ts->n_faces;
 
897
 
 
898
  /* Count expected local numbers of triangles and quadrangles */
 
899
 
 
900
  n_vertices_max = 0;
 
901
  n_triangles_max = 0;
 
902
 
 
903
  if (ts->vertex_index != NULL) {
 
904
    for (i = 0 ; i < n_elements ; i++) {
 
905
      n_vertices = ts->vertex_index[i+1] - ts->vertex_index[i];
 
906
      if (n_vertices == 4)
 
907
        n_elements_tot[1] += 1;
 
908
      else
 
909
        n_elements_tot[0] += n_vertices - 2;
 
910
      if (n_vertices > n_vertices_max)
 
911
        n_vertices_max = n_vertices;
 
912
    }
 
913
  }
 
914
  else
 
915
    return;
 
916
 
 
917
  n_triangles_max = n_vertices_max - 2;
 
918
 
 
919
  if (n_vertices_max > 2<<_ENCODING_BITS)
 
920
    bft_error(__FILE__, __LINE__, 0,
 
921
              _("Encoding of tesselation impossible:\n"
 
922
                "maximum number of vertices per polygon: %u\n"
 
923
                "maximum integer encoded on %d/3 = %d bits: %ld\n"),
 
924
              (unsigned)n_triangles_max,
 
925
              sizeof(fvm_tesselation_encoding_t)*8,
 
926
              _ENCODING_BITS, (long)(2<<_ENCODING_BITS));
 
927
 
 
928
  /* Destroy previous tesselation description if present */
 
929
 
 
930
  ts->encoding = NULL;
 
931
  if (ts->_encoding != NULL)
 
932
    BFT_FREE(ts->_encoding);
 
933
 
 
934
  /* Allocate memory and state variables */
 
935
  /*-------------------------------------*/
 
936
 
 
937
  if (n_vertices_max > 4) {
 
938
    BFT_MALLOC(ts->_encoding,
 
939
               ts->vertex_index[n_elements] - n_elements*2,
 
940
               fvm_tesselation_encoding_t);
 
941
    ts->encoding = ts->_encoding;
 
942
    BFT_MALLOC(triangle_vertices, (n_vertices_max - 2) * 3, fvm_lnum_t);
 
943
    state = fvm_triangulate_state_create(n_vertices_max);
 
944
  }
 
945
 
 
946
  n_elements_tot[0] = 0; n_elements_tot[1] = 0; /* reset */
 
947
 
 
948
  /* Main loop on section face elements */
 
949
  /*------------------------------------*/
 
950
 
 
951
  for (i = 0 ; i < n_elements ; i++) {
 
952
 
 
953
    n_triangles = 0;
 
954
    n_quads = 0;
 
955
    n_vertices = ts->vertex_index[i+1] - ts->vertex_index[i];
 
956
    vertex_id = ts->vertex_index[i];
 
957
 
 
958
    /* We calculate the encoding index base from the polygon's
 
959
       connectivity index base, knowing that for a polygon
 
960
       with n vertices, we have at most n-2 triangles
 
961
       (exactly n-2 when no error occurs) */
 
962
 
 
963
    encoding_id = ts->vertex_index[i] - (i*2);
 
964
 
 
965
    if (n_vertices == 4)
 
966
      type_id = 1;
 
967
    else
 
968
      type_id = 0;
 
969
 
 
970
    /* If face must be subdivided */
 
971
 
 
972
    if (n_vertices > 4) {
 
973
 
 
974
      n_triangles = fvm_triangulate_polygon(dim,
 
975
                                            n_vertices,
 
976
                                            vertex_coords,
 
977
                                            parent_vertex_num,
 
978
                                            (  ts->vertex_num
 
979
                                             + vertex_id),
 
980
                                            FVM_TRIANGULATE_ELT_DEF,
 
981
                                            triangle_vertices,
 
982
                                            state);
 
983
 
 
984
      if (n_triangles != (n_vertices - 2) && error_count != NULL)
 
985
        *error_count += 1;
 
986
 
 
987
      /* Encode local triangle connectivity */
 
988
 
 
989
      for (j = 0; j < n_triangles; j++) {
 
990
 
 
991
        for (k = 0; k < 3; k++)
 
992
          encoding_sub[k]
 
993
            = (   ((fvm_tesselation_encoding_t)(triangle_vertices[j*3 + k] - 1))
 
994
               << (_ENCODING_BITS * k));
 
995
 
 
996
        ts->_encoding[encoding_id + j]
 
997
          = encoding_sub[0] | encoding_sub[1] | encoding_sub[2];
 
998
 
 
999
      }
 
1000
 
 
1001
      /* In case of incomplete tesselation due to errors,
 
1002
         blank unused encoding values */
 
1003
 
 
1004
      for (j = n_triangles; j < (n_vertices - 2); j++)
 
1005
        ts->_encoding[encoding_id + j] = 0;
 
1006
 
 
1007
      n_elements_tot[0] += n_triangles;
 
1008
 
 
1009
    }
 
1010
 
 
1011
    /* Otherwise, tesselation trivial or not necessary for this face */
 
1012
 
 
1013
    else {
 
1014
 
 
1015
      if (ts->_encoding != NULL) {
 
1016
        for (j = 0; j < (n_vertices - 2); j++)
 
1017
          ts->_encoding[encoding_id + j] = 0;
 
1018
      }
 
1019
 
 
1020
      if (n_vertices == 4) {
 
1021
        n_elements_tot[1] += 1;
 
1022
        n_quads = 1;
 
1023
      }
 
1024
 
 
1025
      else if (n_vertices == 3) {
 
1026
        n_elements_tot[0] += 1;
 
1027
        n_triangles = 1;
 
1028
      }
 
1029
 
 
1030
    }
 
1031
 
 
1032
    if (n_triangles > n_elements_max[0])
 
1033
      n_elements_max[0] = n_triangles;
 
1034
 
 
1035
    if (n_quads > n_elements_max[1])
 
1036
      n_elements_max[1] = n_triangles;
 
1037
 
 
1038
  } /* End of loop on elements */
 
1039
 
 
1040
  /* Free memory and state variables */
 
1041
 
 
1042
  if (n_vertices_max > 4) {
 
1043
    BFT_FREE(triangle_vertices);
 
1044
    state = fvm_triangulate_state_destroy(state);
 
1045
  }
 
1046
 
 
1047
  /* Update tesselation structure info */
 
1048
 
 
1049
  for (type_id = 0; type_id < 2; type_id++) {
 
1050
    n_g_elements_tot[type_id] = n_elements_tot[type_id];
 
1051
    n_g_elements_max[type_id] = n_elements_max[type_id];
 
1052
  }
 
1053
 
 
1054
  fvm_parall_counter(n_g_elements_tot, 2);
 
1055
  fvm_parall_counter_max(n_g_elements_max, 2);
 
1056
 
 
1057
  for (type_id = 0; type_id < 2; type_id++) {
 
1058
    if (n_g_elements_tot[type_id] > 0) {
 
1059
      if (type_id == 0)
 
1060
        ts->sub_type[ts->n_sub_types] = FVM_FACE_TRIA;
 
1061
      else
 
1062
        ts->sub_type[ts->n_sub_types] = FVM_FACE_QUAD;
 
1063
      ts->n_sub_max[ts->n_sub_types] = n_elements_max[type_id];
 
1064
      ts->n_sub_max_glob[ts->n_sub_types] = n_g_elements_max[type_id];
 
1065
      ts->n_sub[ts->n_sub_types] = n_elements_tot[type_id];
 
1066
      ts->n_sub_glob[ts->n_sub_types] = n_elements_tot[type_id];
 
1067
      ts->n_sub_types += 1;
 
1068
    }
 
1069
  }
 
1070
 
 
1071
}
 
1072
 
 
1073
/*----------------------------------------------------------------------------
 
1074
 * Build indexes and global counts for polygons of a mesh section referred
 
1075
 * to by an fvm_tesselation_t structure.
 
1076
 *
 
1077
 * parameters:
 
1078
 *   this_tesselation   <-> partially initialized tesselation structure
 
1079
 *   global_count       <-- indicates if global counts should be built
 
1080
 *----------------------------------------------------------------------------*/
 
1081
 
 
1082
static void
 
1083
_count_and_index_sub_polygons(fvm_tesselation_t  *this_tesselation,
 
1084
                              _Bool               global_count)
 
1085
{
 
1086
  int sub_type_id, type_id;
 
1087
  fvm_lnum_t n_vertices, n_triangles, n_elements;
 
1088
  fvm_lnum_t i, j, encoding_id;
 
1089
 
 
1090
  fvm_lnum_t *n_sub_elements[2] = {NULL, NULL};
 
1091
 
 
1092
  fvm_tesselation_t *ts = this_tesselation;
 
1093
 
 
1094
  /* Initial checks */
 
1095
 
 
1096
  if (ts->vertex_index == NULL)
 
1097
    return;
 
1098
 
 
1099
  /* Initialization */
 
1100
 
 
1101
  n_elements = ts->n_elements;
 
1102
 
 
1103
  /* Count expected local numbers of triangles and quadrangles */
 
1104
 
 
1105
  for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++) {
 
1106
 
 
1107
    type_id = -1;
 
1108
    switch(ts->sub_type[sub_type_id]) {
 
1109
    case FVM_FACE_TRIA:
 
1110
      type_id = 0;
 
1111
      break;
 
1112
    case FVM_FACE_QUAD:
 
1113
      type_id = 1;
 
1114
      break;
 
1115
    default:
 
1116
      assert(0);
 
1117
    }
 
1118
 
 
1119
    BFT_MALLOC(ts->_sub_elt_index[sub_type_id], n_elements + 1, fvm_lnum_t);
 
1120
 
 
1121
    for (i = 0 ; i < n_elements + 1 ; i++)
 
1122
      ts->_sub_elt_index[sub_type_id][i] = 0;
 
1123
 
 
1124
    /* The index array will first be used to hold n_sub_elements[],
 
1125
       of size n_elements. To simplify future conversion to index,
 
1126
       we shift shuch that n_sub_elements[i] corresponds to index[i+1]. */
 
1127
 
 
1128
    n_sub_elements[type_id] = ts->_sub_elt_index[sub_type_id] + 1;
 
1129
 
 
1130
  }
 
1131
 
 
1132
  /* Loop on elements to populate n_sub_elements[].
 
1133
     Note that each n_sub_elements[] array has been initialized with zeroes,
 
1134
     as it is mapped to a ts->sub_elt_index[] thus initialized. */
 
1135
 
 
1136
  for (i = 0 ; i < n_elements ; i++) {
 
1137
 
 
1138
    n_vertices = ts->vertex_index[i+1] - ts->vertex_index[i];
 
1139
    n_triangles = 0;
 
1140
 
 
1141
    if (n_vertices == 3) {
 
1142
      n_sub_elements[0][i] = 1;
 
1143
      n_triangles += 1;
 
1144
    }
 
1145
 
 
1146
    else { /* if (n_vertices > 3) */
 
1147
 
 
1148
      encoding_id = ts->vertex_index[i] - (i*2);
 
1149
 
 
1150
      for (j = 0; j < (n_vertices - 2); j++) {
 
1151
        if (ts->encoding != NULL) {
 
1152
          if (ts->encoding[encoding_id + j] != 0)
 
1153
            n_triangles += 1;
 
1154
        }
 
1155
      }
 
1156
      if (n_triangles > 0)
 
1157
        n_sub_elements[0][i] = n_triangles;
 
1158
      else if (n_vertices == 4)
 
1159
        n_sub_elements[1][i] = 1;
 
1160
      assert(n_triangles > 0 || n_vertices == 4);
 
1161
    }
 
1162
 
 
1163
  }
 
1164
 
 
1165
  /* Now compute max global number if necessary */
 
1166
 
 
1167
  for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++)
 
1168
    ts->n_sub_glob[sub_type_id] = ts->n_sub[sub_type_id];
 
1169
 
 
1170
  if (global_count == true && ts->global_element_num != NULL) {
 
1171
 
 
1172
    for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++) {
 
1173
      if (ts->_sub_elt_index[sub_type_id] != NULL) {
 
1174
        fvm_lnum_t * _n_sub_elements = ts->_sub_elt_index[sub_type_id] + 1;
 
1175
        if (n_elements == 0) _n_sub_elements = NULL;
 
1176
        ts->n_sub_glob[sub_type_id]
 
1177
          = fvm_io_num_global_sub_size(ts->global_element_num,
 
1178
                                       _n_sub_elements);
 
1179
      }
 
1180
      else
 
1181
        ts->n_sub_glob[sub_type_id] = 0;
 
1182
    }
 
1183
 
 
1184
  }
 
1185
 
 
1186
  /* Finally, build index from n_sub_elements_glob */
 
1187
 
 
1188
  for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++) {
 
1189
 
 
1190
    fvm_lnum_t *sub_elt_index = ts->_sub_elt_index[sub_type_id];
 
1191
    for (i = 0 ; i < n_elements ; i++)
 
1192
      sub_elt_index[i+1] = sub_elt_index[i] + sub_elt_index[i+1];
 
1193
    ts->sub_elt_index[sub_type_id] = ts->_sub_elt_index[sub_type_id];
 
1194
 
 
1195
  }
 
1196
 
 
1197
}
 
1198
 
 
1199
/*----------------------------------------------------------------------------
 
1200
 * Count resulting number of tetrahedra and pyramids when tesselating
 
1201
 * polyhedra of a mesh section referred to by an fvm_tesselation_t
 
1202
 * structure. This requires that the mesh section's polygonal faces have
 
1203
 * already been tesselated (i.e. _tesselate_polygons has been called).
 
1204
 *
 
1205
 * parameters:
 
1206
 *   this_tesselation   <-> partially initialized tesselation structure
 
1207
 *   error_count        --> number of tesselation errors counter (optional)
 
1208
 *   global_count       <-- indicates if global counts should be built
 
1209
 *----------------------------------------------------------------------------*/
 
1210
 
 
1211
static void
 
1212
_count_and_index_sub_polyhedra(fvm_tesselation_t  *this_tesselation,
 
1213
                               fvm_lnum_t         *error_count,
 
1214
                               _Bool               global_count)
 
1215
{
 
1216
  int sub_type_id, type_id;
 
1217
  fvm_lnum_t n_vertices, n_triangles, n_elements;
 
1218
  fvm_lnum_t n_tetras, n_pyrams;
 
1219
  fvm_lnum_t i, j, k, face_id, encoding_id;
 
1220
 
 
1221
  fvm_gnum_t n_g_elements_tot[2] = {0, 0}; /* Global new elements count */
 
1222
  fvm_lnum_t n_elements_tot[2] = {0, 0}; /* New tetrahedra/pyramids */
 
1223
  fvm_lnum_t *n_sub_elements[2] = {NULL, NULL};
 
1224
  fvm_lnum_t n_g_elements_max[2] = {0, 0}; /* Global max tetrahedra/pyramids */
 
1225
  fvm_lnum_t n_elements_max[2] = {0, 0}; /* Max tetrahedra/pyramids */
 
1226
 
 
1227
  fvm_tesselation_t *ts = this_tesselation;
 
1228
 
 
1229
  /* Initial checks */
 
1230
 
 
1231
  assert(ts->vertex_index != NULL);
 
1232
 
 
1233
  /* Initialization */
 
1234
 
 
1235
  if (error_count != NULL)
 
1236
    *error_count = 0;
 
1237
 
 
1238
  n_elements = ts->n_elements;
 
1239
 
 
1240
  /* Count expected total and local numbers of tetrahedra and pyramids;
 
1241
     at this stage, the tesselation has been initialized as a
 
1242
     polygon tesselation; adding a "center" vertex, triangle faces
 
1243
     lead to tetrahedra, and quadrangles to pyramids */
 
1244
 
 
1245
  for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++) {
 
1246
 
 
1247
    type_id = -1;
 
1248
    switch(ts->sub_type[sub_type_id]) {
 
1249
    case FVM_FACE_TRIA:
 
1250
      type_id = 0;
 
1251
      break;
 
1252
    case FVM_FACE_QUAD:
 
1253
      type_id = 1;
 
1254
      break;
 
1255
    default:
 
1256
      assert(0);
 
1257
    }
 
1258
 
 
1259
    BFT_MALLOC(ts->_sub_elt_index[sub_type_id], n_elements + 1, fvm_lnum_t);
 
1260
 
 
1261
    for (i = 0 ; i < n_elements + 1 ; i++)
 
1262
      ts->_sub_elt_index[sub_type_id][i] = 0;
 
1263
 
 
1264
    /* The index array will first be used to hold n_sub_elements[],
 
1265
       of size n_elements. To simplify future conversion to index,
 
1266
       we shift shuch that n_sub_elements[i] corresponds to index[i+1]. */
 
1267
 
 
1268
    n_sub_elements[type_id] = ts->_sub_elt_index[sub_type_id] + 1;
 
1269
 
 
1270
  }
 
1271
 
 
1272
  /* Counting loop on polyhedra elements */
 
1273
  /*-------------------------------------*/
 
1274
 
 
1275
  for (i = 0 ; i < n_elements ; i++) {
 
1276
 
 
1277
    n_tetras = 0;
 
1278
    n_pyrams = 0;
 
1279
 
 
1280
    for (j = ts->face_index[i];     /* Loop on element faces */
 
1281
         j < ts->face_index[i+1];
 
1282
         j++) {
 
1283
 
 
1284
      face_id = FVM_ABS(ts->face_num[j]) - 1;
 
1285
 
 
1286
      n_vertices = ts->vertex_index[face_id+1] - ts->vertex_index[face_id];
 
1287
 
 
1288
      if (n_vertices == 3)
 
1289
        n_tetras += 1;
 
1290
 
 
1291
      else { /* if (n_vertices > 3) */
 
1292
 
 
1293
        n_triangles = 0;
 
1294
 
 
1295
        encoding_id = ts->vertex_index[face_id] - (face_id*2);
 
1296
 
 
1297
        for (k = encoding_id; k < (encoding_id + n_vertices - 2); k++) {
 
1298
          if (ts->encoding != NULL) {
 
1299
            if (ts->encoding[k] != 0)
 
1300
              n_triangles += 1;
 
1301
          }
 
1302
        }
 
1303
 
 
1304
        if (error_count != NULL && n_triangles < n_vertices - 2)
 
1305
          *error_count += 1;
 
1306
 
 
1307
        if (n_triangles > 0)
 
1308
          n_tetras += n_triangles;
 
1309
        else if (n_vertices == 4)
 
1310
          n_pyrams += 1;
 
1311
 
 
1312
      }
 
1313
 
 
1314
    } /* End of loop on element faces */
 
1315
 
 
1316
    n_elements_tot[0] += n_tetras;
 
1317
    n_elements_tot[1] += n_pyrams;
 
1318
 
 
1319
    if (n_tetras > n_elements_max[0])
 
1320
      n_elements_max[0] = n_tetras;
 
1321
 
 
1322
    if (n_pyrams > n_elements_max[1])
 
1323
      n_elements_max[1] = n_pyrams;
 
1324
 
 
1325
    if (n_sub_elements[0] != NULL)
 
1326
      n_sub_elements[0][i] = n_tetras;
 
1327
 
 
1328
    if (n_sub_elements[1] != NULL)
 
1329
      n_sub_elements[1][i] = n_pyrams;
 
1330
 
 
1331
  }  /* End of loop on elements */
 
1332
 
 
1333
  /* Update tesselation structure info */
 
1334
 
 
1335
  for (type_id = 0; type_id < 2; type_id++) {
 
1336
    n_g_elements_tot[type_id] = n_elements_tot[type_id];
 
1337
    n_g_elements_max[type_id] = n_elements_max[type_id];
 
1338
  }
 
1339
 
 
1340
  fvm_parall_counter(n_g_elements_tot, 2);
 
1341
  fvm_parall_counter_max(n_g_elements_max, 2);
 
1342
 
 
1343
  ts->n_sub_types = 0;
 
1344
 
 
1345
  for (type_id = 0; type_id < 2; type_id++) {
 
1346
    if (n_g_elements_tot[type_id] > 0) {
 
1347
      if (type_id == 0)
 
1348
        ts->sub_type[ts->n_sub_types] = FVM_CELL_TETRA;
 
1349
      else
 
1350
        ts->sub_type[ts->n_sub_types] = FVM_CELL_PYRAM;
 
1351
      ts->n_sub_max[ts->n_sub_types] = n_elements_max[type_id];
 
1352
      ts->n_sub_max_glob[ts->n_sub_types] = n_g_elements_max[type_id];
 
1353
      ts->n_sub[ts->n_sub_types] = n_elements_tot[type_id];
 
1354
      ts->n_sub_glob[ts->n_sub_types] = n_elements_tot[type_id];
 
1355
      ts->n_sub_types += 1;
 
1356
    }
 
1357
  }
 
1358
 
 
1359
  /* Now compute max global number if necessary */
 
1360
 
 
1361
  for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++)
 
1362
    ts->n_sub_glob[sub_type_id] = ts->n_sub[sub_type_id];
 
1363
 
 
1364
  if (global_count == true && ts->global_element_num != NULL) {
 
1365
 
 
1366
    for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++) {
 
1367
      if (ts->_sub_elt_index[sub_type_id] != NULL) {
 
1368
        fvm_lnum_t * _n_sub_elements = ts->_sub_elt_index[sub_type_id] + 1;
 
1369
        if (n_elements == 0) _n_sub_elements = NULL;
 
1370
        ts->n_sub_glob[sub_type_id]
 
1371
          = fvm_io_num_global_sub_size(ts->global_element_num,
 
1372
                                       _n_sub_elements);
 
1373
      }
 
1374
      else
 
1375
        ts->n_sub_glob[sub_type_id] = 0;
 
1376
    }
 
1377
 
 
1378
  }
 
1379
 
 
1380
  /* Finally, build index from n_sub_elements_glob */
 
1381
 
 
1382
  for (sub_type_id = 0; sub_type_id < ts->n_sub_types; sub_type_id++) {
 
1383
 
 
1384
    fvm_lnum_t *sub_elt_index = ts->_sub_elt_index[sub_type_id];
 
1385
    for (i = 0 ; i < n_elements ; i++)
 
1386
      sub_elt_index[i+1] = sub_elt_index[i] + sub_elt_index[i+1];
 
1387
    ts->sub_elt_index[sub_type_id] = ts->_sub_elt_index[sub_type_id];
 
1388
 
 
1389
  }
 
1390
 
 
1391
}
 
1392
 
 
1393
#if defined(HAVE_MPI)
 
1394
 
 
1395
/*----------------------------------------------------------------------------
 
1396
 * Update global_num_end when limiting partial connectivity range end index.
 
1397
 *
 
1398
 * parameters:
 
1399
 *   this_tesselation   <-- tesselation structure
 
1400
 *   end_id             <-- initial end of subset in parent section
 
1401
 *   global_num_end     <-> past the end (maximum + 1) parent element
 
1402
 *                          global number (reduced on return if required
 
1403
 *                          by buffer_size)
 
1404
 *   comm               <-- associated MPI communicator
 
1405
 *
 
1406
 * returns:
 
1407
 *   index corresponding to end of decoded range
 
1408
 *----------------------------------------------------------------------------*/
 
1409
 
 
1410
static void
 
1411
_expand_limit_g(const fvm_tesselation_t  *this_tesselation,
 
1412
                fvm_lnum_t                end_id,
 
1413
                fvm_gnum_t               *global_num_end,
 
1414
                MPI_Comm                  comm)
 
1415
{
 
1416
  fvm_gnum_t local_max, global_max;
 
1417
 
 
1418
  const fvm_gnum_t *global_element_num
 
1419
    = fvm_io_num_get_global_num(this_tesselation->global_element_num);
 
1420
 
 
1421
  /* Check if the maximum id returned on some ranks leads to
 
1422
     a lower global_num_end than initially required
 
1423
     (due to local buffer being full) */
 
1424
 
 
1425
  if (end_id < this_tesselation->n_elements) {
 
1426
    if (global_element_num != NULL)
 
1427
      local_max = global_element_num[end_id];
 
1428
    else
 
1429
      local_max = end_id + 1;
 
1430
  }
 
1431
  else
 
1432
    local_max = *global_num_end;
 
1433
 
 
1434
  MPI_Allreduce(&local_max, &global_max, 1, FVM_MPI_GNUM, MPI_MIN, comm);
 
1435
 
 
1436
  if (global_max < *global_num_end)
 
1437
    *global_num_end = global_max;
 
1438
}
 
1439
 
 
1440
#endif /* defined(HAVE_MPI) */
 
1441
 
 
1442
#if defined(HAVE_MPI)
 
1443
 
 
1444
/*----------------------------------------------------------------------------
 
1445
 * Decode polygons tesselation to a connectivity buffer.
 
1446
 *
 
1447
 * To avoid requiring huge buffers and computing unneeded element
 
1448
 * connectivities when exporting data in slices, this function may decode
 
1449
 * a partial connectivity range, starting at polygon index start_id and ending
 
1450
 * either when the indicated buffer size is attained, or the global element
 
1451
 * number corresponding to a given polygon exceeds a given value.
 
1452
 * It returns the effective polygon index end.
 
1453
 *
 
1454
 * parameters:
 
1455
 *   this_tesselation   <-- tesselation structure
 
1456
 *   connect_type       <-- destination element type
 
1457
 *   start_id           <-- start index of polygons subset in parent section
 
1458
 *   buffer_limit       <-- maximum number of sub-elements of destination
 
1459
 *                          element type allowable for sub_element_idx[]
 
1460
 *                          and vertex_num[] buffers
 
1461
 *   global_num_end     <-- past the end (maximum + 1) parent element
 
1462
 *                          global number
 
1463
 *   global_vertex_num  <-- global vertex numbering
 
1464
 *   vertex_num         --> sub-element (global) vertex connectivity
 
1465
 *
 
1466
 * returns:
 
1467
 *   polygon index end corresponding to decoded range
 
1468
 *----------------------------------------------------------------------------*/
 
1469
 
 
1470
static fvm_lnum_t
 
1471
_decode_polygons_tesselation_g(const fvm_tesselation_t  *this_tesselation,
 
1472
                               fvm_element_t             connect_type,
 
1473
                               fvm_lnum_t                start_id,
 
1474
                               fvm_lnum_t                buffer_limit,
 
1475
                               fvm_gnum_t                global_num_end,
 
1476
                               const fvm_io_num_t       *global_vertex_num,
 
1477
                               fvm_gnum_t                vertex_num[])
 
1478
{
 
1479
  fvm_lnum_t n_vertices;
 
1480
  fvm_lnum_t i, j, k, l, vertex_id, encoding_id;
 
1481
  fvm_lnum_t tv[3];
 
1482
  fvm_tesselation_encoding_t decoding_mask[3] = {0, 0, 0};
 
1483
 
 
1484
  fvm_lnum_t n_sub_tot = 0;
 
1485
  const fvm_tesselation_t *ts = this_tesselation;
 
1486
  fvm_lnum_t retval = start_id;
 
1487
 
 
1488
  const fvm_gnum_t *_global_vertex_num
 
1489
                      = fvm_io_num_get_global_num(global_vertex_num);
 
1490
  const fvm_gnum_t *global_element_num
 
1491
    = fvm_io_num_get_global_num(ts->global_element_num);
 
1492
 
 
1493
  _init_decoding_mask(decoding_mask);
 
1494
 
 
1495
  /* Main loop on polygons */
 
1496
  /*-----------------------*/
 
1497
 
 
1498
  for (i = 0, j = start_id ;
 
1499
       j < this_tesselation->n_elements;
 
1500
       i++, j++) {
 
1501
 
 
1502
    if (   global_element_num != NULL
 
1503
        && global_element_num[j] >= global_num_end)
 
1504
      break;
 
1505
 
 
1506
    n_vertices = ts->vertex_index[j+1] - ts->vertex_index[j];
 
1507
    vertex_id = ts->vertex_index[j];
 
1508
    encoding_id = ts->vertex_index[j] - (j*2);
 
1509
 
 
1510
    /* Sub-elements (triangles) connectivity */
 
1511
    /*---------------------------------------*/
 
1512
 
 
1513
    if (   connect_type == FVM_FACE_TRIA
 
1514
        && n_vertices > 3 && ts->encoding != NULL) {
 
1515
 
 
1516
      /* Loop on triangles */
 
1517
 
 
1518
      for (k = 0; k < (n_vertices - 2); k++) {
 
1519
 
 
1520
        if (ts->encoding[encoding_id + k] != 0) {
 
1521
 
 
1522
          /* Fill connectivity array */
 
1523
          /* Return previous element's end index if buffer size reached */
 
1524
 
 
1525
          if (n_sub_tot >= buffer_limit)
 
1526
            return j;
 
1527
 
 
1528
          /* Fill connectivity array */
 
1529
 
 
1530
          _DECODE_TRIANGLE_VERTICES(tv,
 
1531
                                    ts->encoding[encoding_id + k],
 
1532
                                    decoding_mask);
 
1533
 
 
1534
          if (_global_vertex_num != NULL) {
 
1535
            for (l = 0; l < 3; l++)
 
1536
              vertex_num[n_sub_tot*3 + l]
 
1537
                = _global_vertex_num[ts->vertex_num[vertex_id + tv[l]] - 1];
 
1538
          }
 
1539
          else {
 
1540
            for (l = 0; l < 3; l++)
 
1541
              vertex_num[n_sub_tot*3 + l]
 
1542
                = ts->vertex_num[vertex_id + tv[l]];
 
1543
          }
 
1544
 
 
1545
          n_sub_tot += 1;
 
1546
 
 
1547
        }
 
1548
 
 
1549
      } /* End of loop on polygon vertices */
 
1550
 
 
1551
    }
 
1552
 
 
1553
    /* Non-tesselated elements connectivity */
 
1554
    /*--------------------------------------*/
 
1555
 
 
1556
    else if (   (connect_type == FVM_FACE_TRIA && n_vertices == 3)
 
1557
             || (connect_type == FVM_FACE_QUAD && n_vertices == 4)) {
 
1558
 
 
1559
      /* Check that polygon is not subdivided */
 
1560
 
 
1561
      k = n_vertices;
 
1562
      if (ts->encoding != NULL) {
 
1563
        for (k = 0; k < (n_vertices - 2); k++)
 
1564
          if (ts->encoding[encoding_id + k] > 0)
 
1565
            break;
 
1566
      }
 
1567
 
 
1568
      if (k == n_vertices - 2 || ts->encoding == NULL) {
 
1569
 
 
1570
        /* Return previous element's end index if buffer size reached */
 
1571
 
 
1572
        if (n_sub_tot >= buffer_limit)
 
1573
          return j;
 
1574
 
 
1575
        /* Fill connectivity array */
 
1576
 
 
1577
        if (_global_vertex_num != NULL) {
 
1578
          for (k = 0; k < n_vertices; k++)
 
1579
            vertex_num[n_sub_tot*n_vertices +k]
 
1580
              = _global_vertex_num[ts->vertex_num[vertex_id + k] - 1];
 
1581
        }
 
1582
        else {
 
1583
          for (k = 0; k < n_vertices; k++)
 
1584
            vertex_num[n_sub_tot*n_vertices +k]
 
1585
              = ts->vertex_num[vertex_id + k];
 
1586
        }
 
1587
 
 
1588
        n_sub_tot += 1;
 
1589
 
 
1590
      }
 
1591
 
 
1592
    } /* End of case where polygon is not tesselated */
 
1593
 
 
1594
    retval = j+1; /* If end of buffer has not already been reached */
 
1595
 
 
1596
  } /* End of loop on polygons */
 
1597
 
 
1598
  return retval;
 
1599
}
 
1600
 
 
1601
#endif /* defined(HAVE_MPI) */
 
1602
 
 
1603
/*----------------------------------------------------------------------------
 
1604
 * Decode polygons tesselation to a connectivity buffer.
 
1605
 *
 
1606
 * To avoid requiring huge buffers and computing unneeded element
 
1607
 * connectivities this function may decode a partial connectivity range,
 
1608
 * starting at polygon index start_id and ending either when the indicated
 
1609
 * buffer size or the last polygon is attained.
 
1610
 * It returns the effective polygon index end.
 
1611
 *
 
1612
 * parameters:
 
1613
 *   this_tesselation   <-- tesselation structure
 
1614
 *   connect_type       <-- destination element type
 
1615
 *   start_id           <-- start index of polygons subset in parent section
 
1616
 *   buffer_limit       <-- maximum number of sub-elements of destination
 
1617
 *                          element type allowable for vertex_num[] buffer
 
1618
 *   vertex_num         --> sub-element (global) vertex connectivity
 
1619
 *
 
1620
 * returns:
 
1621
 *   polygon index end corresponding to decoded range
 
1622
 *----------------------------------------------------------------------------*/
 
1623
 
 
1624
static fvm_lnum_t
 
1625
_decode_polygons_tesselation_l(const fvm_tesselation_t  *this_tesselation,
 
1626
                               fvm_element_t             connect_type,
 
1627
                               fvm_lnum_t                start_id,
 
1628
                               fvm_lnum_t                buffer_limit,
 
1629
                               fvm_lnum_t                vertex_num[])
 
1630
{
 
1631
  fvm_lnum_t n_vertices;
 
1632
  fvm_lnum_t i, j, k, vertex_id, encoding_id;
 
1633
  fvm_lnum_t tv[3];
 
1634
  fvm_tesselation_encoding_t decoding_mask[3] = {0, 0, 0};
 
1635
 
 
1636
  fvm_lnum_t n_sub_tot = 0;
 
1637
  const fvm_tesselation_t *ts = this_tesselation;
 
1638
  fvm_lnum_t retval = start_id;
 
1639
 
 
1640
  _init_decoding_mask(decoding_mask);
 
1641
 
 
1642
  /* Main loop on polygons */
 
1643
  /*-----------------------*/
 
1644
 
 
1645
  for (i = start_id ; i < this_tesselation->n_elements; i++) {
 
1646
 
 
1647
    n_vertices = ts->vertex_index[i+1] - ts->vertex_index[i];
 
1648
    vertex_id = ts->vertex_index[i];
 
1649
    encoding_id = ts->vertex_index[i] - (i*2);
 
1650
 
 
1651
    /* Sub-elements (triangles) connectivity */
 
1652
    /*---------------------------------------*/
 
1653
 
 
1654
    if (   connect_type == FVM_FACE_TRIA
 
1655
        && n_vertices > 3 && ts->encoding != NULL) {
 
1656
 
 
1657
      /* Loop on polygon vertices */
 
1658
 
 
1659
      for (j = 0; j < (n_vertices - 2); j++) {
 
1660
 
 
1661
        if (ts->encoding[encoding_id + j] != 0) {
 
1662
 
 
1663
          /* Fill connectivity array */
 
1664
          /* Return previous element's end index if buffer size reached */
 
1665
 
 
1666
          if (n_sub_tot >= buffer_limit)
 
1667
            return i;
 
1668
 
 
1669
          /* Fill connectivity array */
 
1670
 
 
1671
          _DECODE_TRIANGLE_VERTICES(tv,
 
1672
                                    ts->encoding[encoding_id + j],
 
1673
                                    decoding_mask);
 
1674
 
 
1675
          for (k = 0; k < 3; k++)
 
1676
            vertex_num[n_sub_tot*3 + k] = ts->vertex_num[vertex_id + tv[k]];
 
1677
 
 
1678
          n_sub_tot += 1;
 
1679
 
 
1680
        }
 
1681
 
 
1682
      } /* End of loop on polygon vertices */
 
1683
 
 
1684
    }
 
1685
 
 
1686
    /* Non-tesselated elements connectivity */
 
1687
    /*--------------------------------------*/
 
1688
 
 
1689
    else if (   (connect_type == FVM_FACE_TRIA && n_vertices == 3)
 
1690
             || (connect_type == FVM_FACE_QUAD && n_vertices == 4)) {
 
1691
 
 
1692
      /* Check that polygon is not subdivided */
 
1693
 
 
1694
      j = n_vertices;
 
1695
      if (ts->encoding != NULL) {
 
1696
        for (j = 0; j < (n_vertices - 2); j++)
 
1697
          if (ts->encoding[encoding_id + j] != 0)
 
1698
            break;
 
1699
      }
 
1700
 
 
1701
      if (j == n_vertices - 2 || ts->encoding == NULL) {
 
1702
 
 
1703
        /* Return previous element's end index if buffer size reached */
 
1704
 
 
1705
        if (n_sub_tot >= buffer_limit)
 
1706
          return i;
 
1707
 
 
1708
        /* Fill connectivity array */
 
1709
 
 
1710
        for (j = 0; j < n_vertices; j++)
 
1711
          vertex_num[n_sub_tot*n_vertices +j] = ts->vertex_num[vertex_id + j];
 
1712
 
 
1713
        n_sub_tot += 1;
 
1714
 
 
1715
      }
 
1716
 
 
1717
    } /* End of case where polygon is not tesselated */
 
1718
 
 
1719
    retval = i+1; /* If end of buffer has not already been reached */
 
1720
 
 
1721
  } /* End of loop on polygons */
 
1722
 
 
1723
  return retval;
 
1724
}
 
1725
 
 
1726
#if defined(HAVE_MPI)
 
1727
 
 
1728
/*----------------------------------------------------------------------------
 
1729
 * Decode polyhedra tesselation to a connectivity buffer.
 
1730
 *
 
1731
 * To avoid requiring huge buffers and computing unneeded element
 
1732
 * connectivities when exporting data in slices, this function may decode a
 
1733
 * partial connectivity range, starting at polyhedron index start_id and ending
 
1734
 * either when the indicated buffer size is attained, or the global element
 
1735
 * number corresponding to a given polyhedron exceeds a given value.
 
1736
 * It returns the effective polyhedron index end.
 
1737
 *
 
1738
 * parameters:
 
1739
 *   this_tesselation      <-- tesselation structure
 
1740
 *   connect_type          <-- destination element type
 
1741
 *   start_id              <-- start index of polyhedra subset in parent section
 
1742
 *   buffer_limit          <-- maximum number of sub-elements of destination
 
1743
 *                             element type allowable for vertex_num[] buffer
 
1744
 *   global_num_end        <-- past the end (maximum + 1) parent element
 
1745
 *                             global number
 
1746
 *   extra_vertex_base     <-- starting number for added vertices
 
1747
 *   global_vertex_num     <-- global vertex numbering
 
1748
 *   vertex_num            --> sub-element (global) vertex connectivity
 
1749
 *
 
1750
 * returns:
 
1751
 *   polyhedron index end corresponding to decoded range
 
1752
 *----------------------------------------------------------------------------*/
 
1753
 
 
1754
static fvm_lnum_t
 
1755
_decode_polyhedra_tesselation_g(const fvm_tesselation_t  *this_tesselation,
 
1756
                                fvm_element_t             connect_type,
 
1757
                                fvm_lnum_t                start_id,
 
1758
                                fvm_lnum_t                buffer_limit,
 
1759
                                fvm_gnum_t                global_num_end,
 
1760
                                fvm_gnum_t                extra_vertex_base_num,
 
1761
                                const fvm_io_num_t       *global_vertex_num,
 
1762
                                fvm_gnum_t                vertex_num[])
 
1763
{
 
1764
  int orient;
 
1765
  fvm_lnum_t n_vertices;
 
1766
  fvm_lnum_t i, j, k, l, m, base_dest_id, face_id, vertex_id, encoding_id;
 
1767
  fvm_lnum_t tv[3];
 
1768
  fvm_tesselation_encoding_t decoding_mask[3] = {0, 0, 0};
 
1769
 
 
1770
  fvm_lnum_t n_sub_tot = 0;
 
1771
  const fvm_tesselation_t *ts = this_tesselation;
 
1772
  fvm_lnum_t retval = start_id;
 
1773
 
 
1774
  const fvm_gnum_t *_global_vertex_num
 
1775
                      = fvm_io_num_get_global_num(global_vertex_num);
 
1776
  const fvm_gnum_t *global_element_num
 
1777
    = fvm_io_num_get_global_num(ts->global_element_num);
 
1778
 
 
1779
  _init_decoding_mask(decoding_mask);
 
1780
 
 
1781
  /* Main loop on polyhedra */
 
1782
  /*------------------------*/
 
1783
 
 
1784
  for (i = 0, j = start_id ;
 
1785
       j < this_tesselation->n_elements;
 
1786
       i++, j++) {
 
1787
 
 
1788
    if (   global_element_num != NULL
 
1789
        && global_element_num[j] >= global_num_end)
 
1790
      break;
 
1791
 
 
1792
    for (k = ts->face_index[j];     /* Loop on element faces */
 
1793
         k < ts->face_index[j+1];
 
1794
         k++) {
 
1795
 
 
1796
      face_id = FVM_ABS(ts->face_num[k]) - 1;
 
1797
 
 
1798
      n_vertices = ts->vertex_index[face_id+1] - ts->vertex_index[face_id];
 
1799
      vertex_id = ts->vertex_index[face_id];
 
1800
      encoding_id = ts->vertex_index[face_id] - (face_id*2);
 
1801
 
 
1802
      /* Invert base orientation as it points outwards in polyhedron
 
1803
         definition, but inwards in tetrahedron and pyramid reference
 
1804
         connectivity */
 
1805
 
 
1806
      if (ts->face_num[k] > 0)
 
1807
        orient = -1;
 
1808
      else
 
1809
        orient = 1;
 
1810
 
 
1811
      /* Sub-elements (tetrahedra) connectivity */
 
1812
      /*----------------------------------------*/
 
1813
 
 
1814
      if (   connect_type == FVM_CELL_TETRA
 
1815
          && n_vertices > 3 && ts->encoding != NULL) {
 
1816
 
 
1817
        /* Loop on face vertices */
 
1818
 
 
1819
        for (l = 0; l < (n_vertices - 2); l++) {
 
1820
 
 
1821
          if (ts->encoding[encoding_id + l] != 0) {
 
1822
 
 
1823
            /* Return previous element's end index if buffer size reached */
 
1824
 
 
1825
            if (n_sub_tot >= buffer_limit)
 
1826
              return j;
 
1827
 
 
1828
            if (orient == 1)
 
1829
              base_dest_id = n_sub_tot*4;
 
1830
            else
 
1831
              base_dest_id = n_sub_tot*4 + 2;
 
1832
 
 
1833
            /* Fill connectivity array */
 
1834
 
 
1835
            _DECODE_TRIANGLE_VERTICES(tv,
 
1836
                                      ts->encoding[encoding_id + l],
 
1837
                                      decoding_mask);
 
1838
 
 
1839
            if (_global_vertex_num != NULL) {
 
1840
              for (m = 0; m < 3; m++)
 
1841
                vertex_num[base_dest_id + orient*m]
 
1842
                  = _global_vertex_num[ts->vertex_num[vertex_id + tv[m]] - 1];
 
1843
            }
 
1844
            else {
 
1845
              for (m = 0; m < 3; m++)
 
1846
                vertex_num[base_dest_id + orient*m]
 
1847
                  = ts->vertex_num[vertex_id + tv[m]];
 
1848
            }
 
1849
 
 
1850
            /* Add extra "top" vertex */
 
1851
 
 
1852
            if (global_element_num != NULL)
 
1853
              vertex_num[n_sub_tot*4 + 3] =   extra_vertex_base_num
 
1854
                                            + global_element_num[j] - 1;
 
1855
            else
 
1856
              vertex_num[n_sub_tot*4 + 3] = extra_vertex_base_num + j;
 
1857
 
 
1858
            n_sub_tot += 1;
 
1859
 
 
1860
          }
 
1861
 
 
1862
        }
 
1863
 
 
1864
      }
 
1865
 
 
1866
      /* Non-tesselated faces connectivity */
 
1867
      /*-----------------------------------*/
 
1868
 
 
1869
      else if (   (connect_type == FVM_CELL_TETRA && n_vertices == 3)
 
1870
               || (connect_type == FVM_CELL_PYRAM && n_vertices == 4)) {
 
1871
 
 
1872
        /* Check that face is not subdivided */
 
1873
 
 
1874
        l = n_vertices;
 
1875
        if (ts->encoding != NULL) {
 
1876
          for (l = 0; l < (n_vertices - 2); l++)
 
1877
            if (ts->encoding[encoding_id + l] != 0)
 
1878
              break;
 
1879
        }
 
1880
 
 
1881
        if (l == n_vertices - 2 || ts->encoding == NULL) {
 
1882
 
 
1883
          fvm_lnum_t stride = n_vertices + 1;
 
1884
 
 
1885
          /* Return previous element's end index if buffer size reached */
 
1886
 
 
1887
          if (n_sub_tot >= buffer_limit)
 
1888
            return j;
 
1889
 
 
1890
          if (orient == 1)
 
1891
            base_dest_id = n_sub_tot*stride;
 
1892
          else
 
1893
            base_dest_id = n_sub_tot*stride + n_vertices-1;
 
1894
 
 
1895
          /* Fill connectivity array */
 
1896
 
 
1897
          if (_global_vertex_num != NULL) {
 
1898
            for (l = 0; l < n_vertices; l++)
 
1899
              vertex_num[base_dest_id + l*orient]
 
1900
                = _global_vertex_num[ts->vertex_num[vertex_id + l] - 1];
 
1901
          }
 
1902
          else {
 
1903
            for (l = 0; l < n_vertices; l++)
 
1904
              vertex_num[base_dest_id + l*orient]
 
1905
                = ts->vertex_num[vertex_id + l];
 
1906
          }
 
1907
 
 
1908
          /* Add extra "top" vertex */
 
1909
 
 
1910
          if (global_element_num != NULL)
 
1911
            vertex_num[n_sub_tot*stride + n_vertices]
 
1912
              =   extra_vertex_base_num + global_element_num[j] - 1;
 
1913
          else
 
1914
            vertex_num[n_sub_tot*stride + n_vertices]
 
1915
              = extra_vertex_base_num + j;
 
1916
 
 
1917
          n_sub_tot += 1;
 
1918
 
 
1919
        }
 
1920
 
 
1921
      } /* End of case where face is not tesselated */
 
1922
 
 
1923
    } /* End of loop on element faces */
 
1924
 
 
1925
    retval = j+1; /* If end of buffer has not already been reached */
 
1926
 
 
1927
  } /* End of main loop on polyhedra */
 
1928
 
 
1929
  return retval;
 
1930
}
 
1931
 
 
1932
#endif /* defined(HAVE_MPI) */
 
1933
 
 
1934
/*----------------------------------------------------------------------------
 
1935
 * Decode polyhedra tesselation to a connectivity buffer.
 
1936
 *
 
1937
 * To avoid requiring huge buffers, this function may decode a partial
 
1938
 * connectivity range, starting at polyhedron index start_id and ending either
 
1939
 * when the indicated buffer size or the last polyhedra is attained.
 
1940
 * It returns the effective polyhedron index end.
 
1941
 *
 
1942
 * parameters:
 
1943
 *   this_tesselation      <-- tesselation structure
 
1944
 *   connect_type          <-- destination element type
 
1945
 *   start_id              <-- start index of polyhedra subset in parent section
 
1946
 *   buffer_limit          <-- maximum number of sub-elements of destination
 
1947
 *                             element type allowable for vertex_num[] buffer
 
1948
 *   extra_vertex_base     <-- starting number for added vertices
 
1949
 *   vertex_num            --> sub-element (global) vertex connectivity
 
1950
 *
 
1951
 * returns:
 
1952
 *   polyhedron index end corresponding to decoded range
 
1953
 *----------------------------------------------------------------------------*/
 
1954
 
 
1955
static fvm_lnum_t
 
1956
_decode_polyhedra_tesselation_l(const fvm_tesselation_t  *this_tesselation,
 
1957
                                fvm_element_t             connect_type,
 
1958
                                fvm_lnum_t                start_id,
 
1959
                                fvm_lnum_t                buffer_limit,
 
1960
                                fvm_lnum_t                extra_vertex_base_num,
 
1961
                                fvm_lnum_t                vertex_num[])
 
1962
{
 
1963
  int orient;
 
1964
  fvm_lnum_t n_vertices;
 
1965
  fvm_lnum_t i, j, k, l, m, base_dest_id, face_id, vertex_id, encoding_id;
 
1966
  fvm_lnum_t tv[3];
 
1967
  fvm_tesselation_encoding_t decoding_mask[3] = {0, 0, 0};
 
1968
 
 
1969
  fvm_lnum_t n_sub_tot = 0;
 
1970
  const fvm_tesselation_t *ts = this_tesselation;
 
1971
  fvm_lnum_t retval = start_id;
 
1972
 
 
1973
  _init_decoding_mask(decoding_mask);
 
1974
 
 
1975
  /* Main loop on polyhedra */
 
1976
  /*------------------------*/
 
1977
 
 
1978
  for (i = 0, j = start_id ;
 
1979
       j < this_tesselation->n_elements;
 
1980
       i++, j++) {
 
1981
 
 
1982
    for (k = ts->face_index[j];     /* Loop on element faces */
 
1983
         k < ts->face_index[j+1];
 
1984
         k++) {
 
1985
 
 
1986
      face_id = FVM_ABS(ts->face_num[k]) - 1;
 
1987
 
 
1988
      n_vertices = ts->vertex_index[face_id+1] - ts->vertex_index[face_id];
 
1989
      vertex_id = ts->vertex_index[face_id];
 
1990
      encoding_id = ts->vertex_index[face_id] - (face_id*2);
 
1991
 
 
1992
      /* Invert base orientation as it points outwards in polyhedron
 
1993
         definition, but inwards in tetrahedron and pyramid reference
 
1994
         connectivity */
 
1995
 
 
1996
      if (ts->face_num[k] > 0)
 
1997
        orient = -1;
 
1998
      else
 
1999
        orient = 1;
 
2000
 
 
2001
      /* Sub-elements (tetrahedra) connectivity */
 
2002
      /*----------------------------------------*/
 
2003
 
 
2004
      if (   connect_type == FVM_CELL_TETRA
 
2005
          && n_vertices > 3 && ts->encoding != NULL) {
 
2006
 
 
2007
        /* Loop on face vertices */
 
2008
 
 
2009
        for (l = 0; l < (n_vertices - 2); l++) {
 
2010
 
 
2011
          if (ts->encoding[encoding_id + l] != 0) {
 
2012
 
 
2013
            /* Return previous element's end index if buffer size reached */
 
2014
 
 
2015
            if (n_sub_tot >= buffer_limit)
 
2016
              return j;
 
2017
 
 
2018
            if (orient == 1)
 
2019
              base_dest_id = n_sub_tot*4;
 
2020
            else
 
2021
              base_dest_id = n_sub_tot*4 + 2;
 
2022
 
 
2023
            /* Fill connectivity array */
 
2024
 
 
2025
            _DECODE_TRIANGLE_VERTICES(tv,
 
2026
                                      ts->encoding[encoding_id + l],
 
2027
                                      decoding_mask);
 
2028
 
 
2029
            for (m = 0; m < 3; m++)
 
2030
              vertex_num[base_dest_id + orient*m]
 
2031
                = ts->vertex_num[vertex_id + tv[m]];
 
2032
 
 
2033
            /* Add extra "top" vertex */
 
2034
 
 
2035
            vertex_num[n_sub_tot*4 + 3] = extra_vertex_base_num + j;
 
2036
 
 
2037
            n_sub_tot += 1;
 
2038
 
 
2039
          }
 
2040
 
 
2041
        }
 
2042
 
 
2043
      }
 
2044
 
 
2045
      /* Non-tesselated faces connectivity */
 
2046
      /*-----------------------------------*/
 
2047
 
 
2048
      else if (   (connect_type == FVM_CELL_TETRA && n_vertices == 3)
 
2049
               || (connect_type == FVM_CELL_PYRAM && n_vertices == 4)) {
 
2050
 
 
2051
        /* Check that face is not subdivided */
 
2052
 
 
2053
        l = n_vertices;
 
2054
        if (ts->encoding != NULL) {
 
2055
          for (l = 0; l < (n_vertices - 2); l++)
 
2056
            if (ts->encoding[encoding_id + l] != 0)
 
2057
              break;
 
2058
        }
 
2059
 
 
2060
        if (l == n_vertices - 2 || ts->encoding == NULL) {
 
2061
 
 
2062
          fvm_lnum_t stride = n_vertices + 1;
 
2063
 
 
2064
          /* Return previous element's end index if buffer size reached */
 
2065
 
 
2066
          if (n_sub_tot >= buffer_limit)
 
2067
            return j;
 
2068
 
 
2069
          if (orient == 1)
 
2070
            base_dest_id = n_sub_tot*stride;
 
2071
          else
 
2072
            base_dest_id = n_sub_tot*stride + n_vertices-1;
 
2073
 
 
2074
          /* Fill connectivity array */
 
2075
 
 
2076
          for (l = 0; l < n_vertices; l++)
 
2077
            vertex_num[base_dest_id + l*orient]
 
2078
              = ts->vertex_num[vertex_id + l];
 
2079
 
 
2080
          /* Add extra "top" vertex */
 
2081
 
 
2082
          vertex_num[n_sub_tot*stride + n_vertices] = extra_vertex_base_num + j;
 
2083
 
 
2084
          n_sub_tot += 1;
 
2085
 
 
2086
        }
 
2087
 
 
2088
      } /* End of case where face is not tesselated */
 
2089
 
 
2090
    } /* End of loop on element faces */
 
2091
 
 
2092
    retval = j+1; /* If end of buffer has not already been reached */
 
2093
 
 
2094
  } /* End of main loop on polyhedra */
 
2095
 
 
2096
  return retval;
 
2097
}
 
2098
 
 
2099
/*============================================================================
 
2100
 * Public function definitions
 
2101
 *============================================================================*/
 
2102
 
 
2103
/*----------------------------------------------------------------------------
 
2104
 * Creation of a mesh section's subdivision into simpler elements.
 
2105
 *
 
2106
 * The structure contains pointers to the mesh section's connectivity,
 
2107
 * (passed as arguments), which is not copied. This structure should thus
 
2108
 * always be destroyed before the mesh section to which it relates.
 
2109
 *
 
2110
 * Unused connectivity array arguments should be set to NULL (such as
 
2111
 * face_index[] and face_num[] for 2D or regular (strided) elements,
 
2112
 * and vertex_index[] for strided elements.
 
2113
 *
 
2114
 * At this stage, the structure does not yet contain tesselation information.
 
2115
 *
 
2116
 * parameters:
 
2117
 *   element_type       <-- type of elements considered
 
2118
 *   n_elements         <-- number of elements
 
2119
 *   face_index         <-- polyhedron -> faces index (O to n-1)
 
2120
 *                          dimension [n_elements + 1]
 
2121
 *   face_num           <-- element -> face numbers (1 to n, signed,
 
2122
 *                           > 0 for outwards pointing face normal
 
2123
 *                           < 0 for inwards pointing face normal);
 
2124
 *                          dimension: [face_index[n_elements]], or NULL
 
2125
 *   vertex_index       <-- element face -> vertices index (O to n-1);
 
2126
 *                          dimension: [n_cell_faces + 1], [n_elements + 1],
 
2127
 *                          or NULL depending on face_index and vertex_index
 
2128
 *   vertex_num         <-- element -> vertex connectivity (1 to n)
 
2129
 *   global_element_num <-- global element numbers (NULL in serial mode)
 
2130
 *
 
2131
 * returns:
 
2132
 *  pointer to created mesh section tesselation structure
 
2133
 *----------------------------------------------------------------------------*/
 
2134
 
 
2135
fvm_tesselation_t *
 
2136
fvm_tesselation_create(fvm_element_t        element_type,
 
2137
                       fvm_lnum_t           n_elements,
 
2138
                       const fvm_lnum_t     face_index[],
 
2139
                       const fvm_lnum_t     face_num[],
 
2140
                       const fvm_lnum_t     vertex_index[],
 
2141
                       const fvm_lnum_t     vertex_num[],
 
2142
                       const fvm_io_num_t  *global_element_num)
 
2143
 
 
2144
{
 
2145
  int  i;
 
2146
  int  entity_dim = 0, stride = 0;
 
2147
  fvm_tesselation_t  *this_tesselation;
 
2148
 
 
2149
  /* First, check if element type is handled and initialize
 
2150
     additionnal info */
 
2151
 
 
2152
  switch (element_type) {
 
2153
  case FVM_FACE_QUAD:
 
2154
    entity_dim = 2;
 
2155
    stride = 4;
 
2156
    break;
 
2157
  case FVM_FACE_POLY:
 
2158
    entity_dim = 2;
 
2159
    stride = 0;
 
2160
    break;
 
2161
  case FVM_CELL_POLY:
 
2162
    entity_dim = 3;
 
2163
    stride = 0;
 
2164
    break;
 
2165
  default:
 
2166
    return NULL;
 
2167
  }
 
2168
 
 
2169
  /* Now, create structure */
 
2170
 
 
2171
  BFT_MALLOC(this_tesselation, 1, fvm_tesselation_t);
 
2172
 
 
2173
  /* Assign parent mesh section info */
 
2174
 
 
2175
  this_tesselation->type = element_type;
 
2176
  this_tesselation->n_elements = n_elements;
 
2177
  this_tesselation->dim = 0;
 
2178
  this_tesselation->entity_dim = entity_dim;
 
2179
 
 
2180
  this_tesselation->stride = stride;
 
2181
  this_tesselation->n_faces = 0;
 
2182
 
 
2183
  this_tesselation->vertex_coords = NULL;
 
2184
  this_tesselation->parent_vertex_num = NULL;
 
2185
 
 
2186
  this_tesselation->face_index = face_index;
 
2187
  this_tesselation->face_num = face_num;
 
2188
  this_tesselation->vertex_index = vertex_index;
 
2189
  this_tesselation->vertex_num = vertex_num;
 
2190
 
 
2191
  this_tesselation->global_element_num = global_element_num;
 
2192
 
 
2193
  /* Check argument consistency */
 
2194
 
 
2195
  if (face_index != NULL || face_num != NULL) {
 
2196
    if (element_type != FVM_CELL_POLY)
 
2197
      bft_error(__FILE__, __LINE__, 0,
 
2198
                _("Incoherent connectivity for tesselation:\n"
 
2199
                  "Connectivity face_index or face_num non NULL,\n"
 
2200
                  "but element type != FVM_CELL_POLY"));
 
2201
  }
 
2202
 
 
2203
  else if (vertex_index != NULL) {
 
2204
    if (element_type != FVM_FACE_POLY)
 
2205
      bft_error(__FILE__, __LINE__, 0,
 
2206
                _("Incoherent connectivity for tesselation:\n"
 
2207
                  "Connectivy vertex_index non NULL,\n"
 
2208
                  "but element type != FVM_FACE_POLY"));
 
2209
  }
 
2210
 
 
2211
  /* Compute number of polyhedron faces */
 
2212
 
 
2213
  if (n_elements > 0 && face_index != NULL) {
 
2214
    fvm_lnum_t  j, k, face_id;
 
2215
    fvm_lnum_t  max_face_id = 0;
 
2216
    for (j = 0; j < n_elements; j++) {
 
2217
      for (k = face_index[j]; k < face_index[j+1]; k++) {
 
2218
        face_id = FVM_ABS(face_num[k]) - 1;
 
2219
        if (face_id > max_face_id)
 
2220
          max_face_id = face_id;
 
2221
      }
 
2222
    }
 
2223
    this_tesselation->n_faces = max_face_id + 1;
 
2224
  }
 
2225
 
 
2226
  /* Set tesselation structures to zero */
 
2227
 
 
2228
  this_tesselation->n_sub_types = 0;
 
2229
 
 
2230
  for (i = 0; i < FVM_TESSELATION_N_SUB_TYPES_MAX; i++) {
 
2231
    this_tesselation->n_sub_max[i] = 0;
 
2232
    this_tesselation->n_sub_max_glob[i] = 0;
 
2233
    this_tesselation->n_sub[i] = 0;
 
2234
    this_tesselation->n_sub_glob[i] =0;
 
2235
    this_tesselation->sub_type[i] = FVM_N_ELEMENT_TYPES;
 
2236
  }
 
2237
 
 
2238
  this_tesselation->encoding = NULL;
 
2239
  this_tesselation->_encoding = NULL;
 
2240
 
 
2241
  for (i = 0; i < FVM_TESSELATION_N_SUB_TYPES_MAX; i++) {
 
2242
    this_tesselation->sub_elt_index[i] = NULL;
 
2243
    this_tesselation->_sub_elt_index[i] = NULL;
 
2244
  }
 
2245
 
 
2246
  return (this_tesselation);
 
2247
}
 
2248
 
 
2249
/*----------------------------------------------------------------------------
 
2250
 * Destruction of a nodal mesh polygon splitting representation structure.
 
2251
 *
 
2252
 * parameters:
 
2253
 *   this_tesselation <-> pointer to structure that should be destroyed
 
2254
 *
 
2255
 * returns:
 
2256
 *  NULL pointer
 
2257
 *----------------------------------------------------------------------------*/
 
2258
 
 
2259
fvm_tesselation_t *
 
2260
fvm_tesselation_destroy(fvm_tesselation_t  * this_tesselation)
 
2261
{
 
2262
  int i;
 
2263
 
 
2264
  if (this_tesselation->_encoding != NULL)
 
2265
    BFT_FREE(this_tesselation->_encoding);
 
2266
 
 
2267
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
2268
    if (this_tesselation->_sub_elt_index[i] != NULL)
 
2269
      BFT_FREE(this_tesselation->_sub_elt_index[i]);
 
2270
  }
 
2271
  BFT_FREE(this_tesselation);
 
2272
 
 
2273
  return NULL;
 
2274
}
 
2275
 
 
2276
/*----------------------------------------------------------------------------
 
2277
 * Tesselate a mesh section referred to by an fvm_tesselation_t structure.
 
2278
 *
 
2279
 * parameters:
 
2280
 *   this_tesselation   <-> partially initialized tesselation structure
 
2281
 *   dim                <-- spatial dimension
 
2282
 *   vertex_coords      <-- associated vertex coordinates array
 
2283
 *   parent_vertex_num  <-- optional indirection to vertex coordinates
 
2284
 *   error_count        --> number of elements with a tesselation error
 
2285
 *                          counter (optional)
 
2286
 *----------------------------------------------------------------------------*/
 
2287
 
 
2288
void
 
2289
fvm_tesselation_init(fvm_tesselation_t  *this_tesselation,
 
2290
                     int                 dim,
 
2291
                     const fvm_coord_t   vertex_coords[],
 
2292
                     const fvm_lnum_t    parent_vertex_num[],
 
2293
                     fvm_lnum_t         *error_count)
 
2294
{
 
2295
  assert(this_tesselation != NULL);
 
2296
 
 
2297
  this_tesselation->dim = dim;
 
2298
 
 
2299
  this_tesselation->vertex_coords = vertex_coords;
 
2300
  this_tesselation->parent_vertex_num = parent_vertex_num;
 
2301
 
 
2302
  switch(this_tesselation->type) {
 
2303
 
 
2304
  case FVM_CELL_POLY:
 
2305
    _tesselate_polygons(this_tesselation,
 
2306
                        dim,
 
2307
                        vertex_coords,
 
2308
                        parent_vertex_num,
 
2309
                        error_count);
 
2310
    _count_and_index_sub_polyhedra(this_tesselation,
 
2311
                                   error_count,
 
2312
                                   true);
 
2313
    break;
 
2314
 
 
2315
  case FVM_FACE_POLY:
 
2316
    _tesselate_polygons(this_tesselation,
 
2317
                        dim,
 
2318
                        vertex_coords,
 
2319
                        parent_vertex_num,
 
2320
                        error_count);
 
2321
    _count_and_index_sub_polygons(this_tesselation,
 
2322
                                  true);
 
2323
    break;
 
2324
 
 
2325
  default:
 
2326
      bft_error(__FILE__, __LINE__, 0,
 
2327
                _("Tesselation of element type %s not implemented."),
 
2328
                fvm_elements_type_name[this_tesselation->type]);
 
2329
 
 
2330
  }
 
2331
}
 
2332
 
 
2333
/*----------------------------------------------------------------------------
 
2334
 * Reduction of a nodal mesh polygon splitting representation structure;
 
2335
 * only the associations (numberings) necessary to redistribution of fields
 
2336
 * for output are conserved, the full connectivity being no longer useful
 
2337
 * once it has been output.
 
2338
 *
 
2339
 * parameters:
 
2340
 *   this_tesselation <-> pointer to structure that should be reduced
 
2341
 *----------------------------------------------------------------------------*/
 
2342
 
 
2343
void
 
2344
fvm_tesselation_reduce(fvm_tesselation_t  * this_tesselation)
 
2345
{
 
2346
  this_tesselation->stride = 0;
 
2347
  this_tesselation->n_faces = 0;
 
2348
 
 
2349
  if (this_tesselation->face_index == NULL) {
 
2350
    this_tesselation->face_num = NULL;
 
2351
    this_tesselation->vertex_index = NULL;
 
2352
    this_tesselation->vertex_num = NULL;
 
2353
  }
 
2354
 
 
2355
  this_tesselation->encoding = NULL;
 
2356
  if (this_tesselation->_encoding != NULL)
 
2357
    BFT_FREE(this_tesselation->_encoding);
 
2358
}
 
2359
 
 
2360
/*----------------------------------------------------------------------------
 
2361
 * Return number of parent elements of a tesselation.
 
2362
 *
 
2363
 * parameters:
 
2364
 *   this_tesselation <-- tesselation structure
 
2365
 *
 
2366
 * returns:
 
2367
 *   number of parent elements
 
2368
 *----------------------------------------------------------------------------*/
 
2369
 
 
2370
fvm_lnum_t
 
2371
fvm_tesselation_n_elements(const fvm_tesselation_t  *this_tesselation)
 
2372
{
 
2373
  fvm_lnum_t retval = 0;
 
2374
 
 
2375
  if (this_tesselation != NULL)
 
2376
    retval = this_tesselation->n_elements;
 
2377
 
 
2378
  return retval;
 
2379
}
 
2380
 
 
2381
/*----------------------------------------------------------------------------
 
2382
 * Return global number of added vertices associated with a tesselation.
 
2383
 *
 
2384
 * parameters:
 
2385
 *   this_tesselation <-- tesselation structure
 
2386
 *
 
2387
 * returns:
 
2388
 *   global number of added vertices associated with the tesselation
 
2389
 *----------------------------------------------------------------------------*/
 
2390
 
 
2391
fvm_gnum_t
 
2392
fvm_tesselation_n_g_vertices_add(const fvm_tesselation_t  *this_tesselation)
 
2393
{
 
2394
  fvm_gnum_t retval = 0;
 
2395
 
 
2396
  assert(this_tesselation != NULL);
 
2397
 
 
2398
  if (this_tesselation->type == FVM_CELL_POLY) {
 
2399
 
 
2400
    if (this_tesselation->global_element_num != NULL)
 
2401
      retval = fvm_io_num_get_global_count(this_tesselation->global_element_num);
 
2402
    else
 
2403
      retval = this_tesselation->n_elements;
 
2404
 
 
2405
  }
 
2406
 
 
2407
  return retval;
 
2408
}
 
2409
 
 
2410
/*----------------------------------------------------------------------------
 
2411
 * Return (local) number of added vertices associated with a tesselation.
 
2412
 *
 
2413
 * parameters:
 
2414
 *   this_tesselation <-- tesselation structure
 
2415
 *
 
2416
 * returns:
 
2417
 *   global number of added vertices associated with the tesselation
 
2418
 *----------------------------------------------------------------------------*/
 
2419
 
 
2420
fvm_lnum_t
 
2421
fvm_tesselation_n_vertices_add(const fvm_tesselation_t  *this_tesselation)
 
2422
{
 
2423
  fvm_gnum_t retval = 0;
 
2424
 
 
2425
  assert(this_tesselation != NULL);
 
2426
 
 
2427
  if (this_tesselation->type == FVM_CELL_POLY)
 
2428
    retval = this_tesselation->n_elements;
 
2429
 
 
2430
  return retval;
 
2431
}
 
2432
 
 
2433
/*----------------------------------------------------------------------------
 
2434
 * Return number of resulting sub-types of a tesselation.
 
2435
 *
 
2436
 * parameters:
 
2437
 *   this_tesselation <-- tesselation structure
 
2438
 *
 
2439
 * returns:
 
2440
 *   number of resulting sub-types of the tesselation
 
2441
 *----------------------------------------------------------------------------*/
 
2442
 
 
2443
int
 
2444
fvm_tesselation_n_sub_types(const fvm_tesselation_t  *this_tesselation)
 
2445
{
 
2446
  int retval = 0;
 
2447
 
 
2448
  if (this_tesselation != NULL)
 
2449
    retval = this_tesselation->n_sub_types;
 
2450
 
 
2451
  return retval;
 
2452
}
 
2453
 
 
2454
/*----------------------------------------------------------------------------
 
2455
 * Return given sub-types of a tesselation.
 
2456
 *
 
2457
 * parameters:
 
2458
 *   this_tesselation <-- tesselation structure
 
2459
 *   sub_type_id      <-- index of sub-type in tesselation (0 to n-1)
 
2460
 *
 
2461
 * returns:
 
2462
 *   sub-types of the tesselation with the given index
 
2463
 *----------------------------------------------------------------------------*/
 
2464
 
 
2465
fvm_element_t
 
2466
fvm_tesselation_sub_type(const fvm_tesselation_t  *this_tesselation,
 
2467
                         int                       sub_type_id)
 
2468
{
 
2469
  fvm_element_t retval = FVM_N_ELEMENT_TYPES;
 
2470
 
 
2471
  if (this_tesselation == NULL)
 
2472
    retval = FVM_N_ELEMENT_TYPES;
 
2473
  else {
 
2474
    assert(sub_type_id < this_tesselation->n_sub_types);
 
2475
    retval = this_tesselation->sub_type[sub_type_id];
 
2476
  }
 
2477
 
 
2478
  return retval;
 
2479
}
 
2480
 
 
2481
/*----------------------------------------------------------------------------
 
2482
 * Return number of elements of a given sub-type of a tesselation.
 
2483
 *
 
2484
 * parameters:
 
2485
 *   this_tesselation <-- tesselation structure
 
2486
 *   sub_type_id      <-- index of sub-type in tesselation (0 to n-1)
 
2487
 *
 
2488
 * returns:
 
2489
 *   sub-types of the tesselation with the given index
 
2490
 *----------------------------------------------------------------------------*/
 
2491
 
 
2492
fvm_lnum_t
 
2493
fvm_tesselation_n_sub_elements(const fvm_tesselation_t  *this_tesselation,
 
2494
                               fvm_element_t             sub_type)
 
2495
{
 
2496
  int id;
 
2497
 
 
2498
  fvm_lnum_t retval = 0;
 
2499
 
 
2500
  if (this_tesselation != NULL) {
 
2501
    for (id = 0; id < this_tesselation->n_sub_types; id++) {
 
2502
      if (this_tesselation->sub_type[id] == sub_type) {
 
2503
        retval = this_tesselation->n_sub[id];
 
2504
        break;
 
2505
      }
 
2506
    }
 
2507
  }
 
2508
 
 
2509
  return retval;
 
2510
}
 
2511
 
 
2512
/*----------------------------------------------------------------------------
 
2513
 * Obtain the global and maximum number of elements of a given sub-type
 
2514
 * of a tesselation.
 
2515
 *
 
2516
 * parameters:
 
2517
 *   this_tesselation    <-- tesselation structure
 
2518
 *   sub_type_id         <-- index of sub-type in tesselation (0 to n-1)
 
2519
 *   n_sub_elements_glob --> global number of sub-elements of the given type
 
2520
 *   n_sub_elements_max  --> maximum number of sub-elements per element
 
2521
 *                           of the given type (for all ranks)
 
2522
 *----------------------------------------------------------------------------*/
 
2523
 
 
2524
void
 
2525
fvm_tesselation_get_global_size(const fvm_tesselation_t  *this_tesselation,
 
2526
                                fvm_element_t             sub_type,
 
2527
                                fvm_gnum_t               *n_sub_elements_glob,
 
2528
                                fvm_lnum_t               *n_sub_elements_max)
 
2529
{
 
2530
  int id;
 
2531
 
 
2532
  if (n_sub_elements_max != NULL)
 
2533
    *n_sub_elements_max = 0;
 
2534
 
 
2535
  if (n_sub_elements_glob != NULL)
 
2536
    *n_sub_elements_glob = 0;
 
2537
 
 
2538
  if (this_tesselation != NULL) {
 
2539
    for (id = 0; id < this_tesselation->n_sub_types; id++) {
 
2540
      if (this_tesselation->sub_type[id] == sub_type) {
 
2541
        if (n_sub_elements_max != NULL)
 
2542
          *n_sub_elements_max = this_tesselation->n_sub_max_glob[id];
 
2543
        if (n_sub_elements_glob != NULL)
 
2544
          *n_sub_elements_glob = this_tesselation->n_sub_glob[id];
 
2545
        break;
 
2546
      }
 
2547
    }
 
2548
  }
 
2549
}
 
2550
 
 
2551
/*----------------------------------------------------------------------------
 
2552
 * Return global numbering of added vertices associated with a tesselation.
 
2553
 *
 
2554
 * parameters:
 
2555
 *   this_tesselation <-- tesselation structure
 
2556
 *
 
2557
 * returns:
 
2558
 *   pointer to global numbering of added vertices for this tesselation,
 
2559
 *   or NULL if no added vertices are present.
 
2560
 *----------------------------------------------------------------------------*/
 
2561
 
 
2562
const fvm_io_num_t *
 
2563
fvm_tesselation_global_vertex_num(const fvm_tesselation_t  *this_tesselation)
 
2564
{
 
2565
  const fvm_io_num_t *retval = NULL;
 
2566
 
 
2567
  assert(this_tesselation != NULL);
 
2568
 
 
2569
  if (this_tesselation->type == FVM_CELL_POLY)
 
2570
    retval = this_tesselation->global_element_num;
 
2571
 
 
2572
  return retval;
 
2573
}
 
2574
 
 
2575
/*----------------------------------------------------------------------------
 
2576
 * Compute coordinates of added vertices for a tesselation of polyhedra.
 
2577
 *
 
2578
 * One additional vertex is added near the center of each polyhedra.
 
2579
 * For element types other than polyhedra, there is no need for added
 
2580
 * vertices, so this function returns immediately.
 
2581
 *
 
2582
 * parameters:
 
2583
 *   this_tesselation   <-- tesselation structure
 
2584
 *   vertex_coords      --> coordinates of added vertices
 
2585
 *----------------------------------------------------------------------------*/
 
2586
 
 
2587
void
 
2588
fvm_tesselation_vertex_coords(const fvm_tesselation_t  *this_tesselation,
 
2589
                              fvm_coord_t               vertex_coords[])
 
2590
{
 
2591
  fvm_lnum_t i;
 
2592
 
 
2593
  if (this_tesselation->type != FVM_CELL_POLY)
 
2594
    return;
 
2595
 
 
2596
  for (i = 0; i < this_tesselation->n_elements; i++) {
 
2597
 
 
2598
    _added_vertex_coords(this_tesselation, vertex_coords + i*3, NULL, i);
 
2599
 
 
2600
  }
 
2601
 
 
2602
}
 
2603
 
 
2604
/*----------------------------------------------------------------------------
 
2605
 * Return index of sub-elements associated with each element of a given
 
2606
 * sub-type of a tesselation.
 
2607
 *
 
2608
 * parameters:
 
2609
 *   this_tesselation <-- tesselation structure
 
2610
 *   sub_type_id      <-- index of sub-type in tesselation (0 to n-1)
 
2611
 *
 
2612
 * returns:
 
2613
 *   index of sub-elements associated with each element (0 to n-1 numbering)
 
2614
 *----------------------------------------------------------------------------*/
 
2615
 
 
2616
const fvm_lnum_t *
 
2617
fvm_tesselation_sub_elt_index(const fvm_tesselation_t  *this_tesselation,
 
2618
                              fvm_element_t             sub_type)
 
2619
{
 
2620
  int id;
 
2621
  const fvm_lnum_t *retval = NULL;
 
2622
 
 
2623
  if (this_tesselation != NULL) {
 
2624
    for (id = 0; id < this_tesselation->n_sub_types; id++) {
 
2625
      if (this_tesselation->sub_type[id] == sub_type) {
 
2626
        retval = this_tesselation->sub_elt_index[id];
 
2627
        break;
 
2628
      }
 
2629
    }
 
2630
  }
 
2631
 
 
2632
  return retval;
 
2633
}
 
2634
 
 
2635
#if defined(HAVE_MPI)
 
2636
 
 
2637
/*----------------------------------------------------------------------------
 
2638
 * Compute index values corresponding to given range of indices,
 
2639
 * for an element -> sub-element value distribution.
 
2640
 *
 
2641
 * This index is used mainly to gather a decoded tesselation connectivity
 
2642
 * or element -> sub-element data distribution, expanding the corresponding
 
2643
 * data only on the given range.
 
2644
 * Only the index values in the start_id to end_id range are set by
 
2645
 * this function, starting with index[start_id] = 0.
 
2646
 *
 
2647
 * parameters:
 
2648
 *   this_tesselation      <-- tesselation structure
 
2649
 *   connect_type          <-- destination element type
 
2650
 *   stride                <-- number of associated values per sub-element
 
2651
 *   start_id              <-- start index of polyhedra subset in parent section
 
2652
 *   buffer_limit          <-- maximum number of sub-elements of destination
 
2653
 *                             element type allowable for vertex_num[] buffer
 
2654
 *   global_num_end        <-> past the end (maximum + 1) parent element
 
2655
 *                             global number (reduced on return if required
 
2656
 *                             by buffer_size limits)
 
2657
 *   index                 --> sub-element index
 
2658
 *   comm                  <-- associated MPI communicator
 
2659
 *
 
2660
 * returns:
 
2661
 *   polyhedron index end corresponding to decoded range
 
2662
 *----------------------------------------------------------------------------*/
 
2663
 
 
2664
fvm_lnum_t
 
2665
fvm_tesselation_range_index_g(const fvm_tesselation_t  *this_tesselation,
 
2666
                              fvm_element_t             connect_type,
 
2667
                              int                       stride,
 
2668
                              fvm_lnum_t                start_id,
 
2669
                              fvm_lnum_t                buffer_limit,
 
2670
                              fvm_gnum_t               *global_num_end,
 
2671
                              fvm_lnum_t                index[],
 
2672
                              MPI_Comm                  comm)
 
2673
{
 
2674
  fvm_lnum_t i;
 
2675
  fvm_lnum_t buffer_size = buffer_limit * stride;
 
2676
 
 
2677
  const fvm_gnum_t *global_element_num
 
2678
    = fvm_io_num_get_global_num(this_tesselation->global_element_num);
 
2679
 
 
2680
  const fvm_lnum_t *sub_element_idx
 
2681
    = fvm_tesselation_sub_elt_index(this_tesselation, connect_type);
 
2682
 
 
2683
  /* In parallel mode, global_element_num should exist */
 
2684
 
 
2685
  if (index == NULL)
 
2686
    return start_id;
 
2687
 
 
2688
  /* Loop on tesselated elements */
 
2689
  /*-----------------------------*/
 
2690
 
 
2691
  index[start_id] = 0;
 
2692
 
 
2693
  for (i = start_id; i < this_tesselation->n_elements; i++) {
 
2694
 
 
2695
    if (global_element_num[i] >= *global_num_end)
 
2696
      break;
 
2697
 
 
2698
    index[i+1] = index[i] + (  sub_element_idx[i+1]
 
2699
                             - sub_element_idx[i]) * stride;
 
2700
 
 
2701
    if (index[i+1] > buffer_size) {
 
2702
      *global_num_end = global_element_num[i];
 
2703
      break;
 
2704
    }
 
2705
 
 
2706
  }
 
2707
 
 
2708
  /* Check if the maximum id returned on some ranks leads to
 
2709
     a lower global_num_end than initially required
 
2710
     (due to local buffer being full) */
 
2711
 
 
2712
  _expand_limit_g(this_tesselation,
 
2713
                  i,
 
2714
                  global_num_end,
 
2715
                  comm);
 
2716
 
 
2717
  return i;
 
2718
}
 
2719
 
 
2720
/*----------------------------------------------------------------------------
 
2721
 * Decode tesselation to a parent element->sub elements index and
 
2722
 * connectivity buffer.
 
2723
 *
 
2724
 * To avoid requiring huge buffers and computing unneeded element
 
2725
 * connectivities when exporting data in slices, this function may decode
 
2726
 * a partial connectivity range, starting at polygon index start_id and ending
 
2727
 * either when the indicated buffer size is attained, or the global element
 
2728
 * number corresponding to a given polygon exceeds a given value.
 
2729
 * It returns the effective polygon index end.
 
2730
 *
 
2731
 * parameters:
 
2732
 *   this_tesselation   <-- tesselation structure
 
2733
 *   connect_type       <-- destination element type
 
2734
 *   start_id           <-- start index of polygons subset in parent section
 
2735
 *   buffer_limit       <-- maximum number of sub-elements of destination
 
2736
 *                          element type allowable for sub_element_idx[]
 
2737
 *                          and vertex_num[] buffers
 
2738
 *   global_num_end     <-> past the end (maximum + 1) parent element
 
2739
 *                          global number (reduced on return if required
 
2740
 *                          by buffer_limit)
 
2741
 *   extra_vertex_base  <-- starting number for added vertices
 
2742
 *   global_vertex_num  <-- global vertex numbering
 
2743
 *   vertex_num         --> sub-element (global) vertex connectivity
 
2744
 *   comm               <-- associated MPI communicator
 
2745
 *
 
2746
 * returns:
 
2747
 *   polygon index corresponding to end of decoded range
 
2748
 *----------------------------------------------------------------------------*/
 
2749
 
 
2750
fvm_lnum_t
 
2751
fvm_tesselation_decode_g(const fvm_tesselation_t  *this_tesselation,
 
2752
                         fvm_element_t             connect_type,
 
2753
                         fvm_lnum_t                start_id,
 
2754
                         fvm_lnum_t                buffer_limit,
 
2755
                         fvm_gnum_t               *global_num_end,
 
2756
                         const fvm_io_num_t       *global_vertex_num,
 
2757
                         fvm_gnum_t                extra_vertex_base,
 
2758
                         fvm_gnum_t                vertex_num[],
 
2759
                         MPI_Comm                  comm)
 
2760
{
 
2761
  fvm_lnum_t retval = 0;
 
2762
 
 
2763
  switch(this_tesselation->type) {
 
2764
 
 
2765
  case FVM_CELL_POLY:
 
2766
    retval = _decode_polyhedra_tesselation_g(this_tesselation,
 
2767
                                             connect_type,
 
2768
                                             start_id,
 
2769
                                             buffer_limit,
 
2770
                                             *global_num_end,
 
2771
                                             extra_vertex_base,
 
2772
                                             global_vertex_num,
 
2773
                                             vertex_num);
 
2774
    break;
 
2775
 
 
2776
  case FVM_FACE_POLY:
 
2777
    retval = _decode_polygons_tesselation_g(this_tesselation,
 
2778
                                            connect_type,
 
2779
                                            start_id,
 
2780
                                            buffer_limit,
 
2781
                                            *global_num_end,
 
2782
                                            global_vertex_num,
 
2783
                                            vertex_num);
 
2784
    break;
 
2785
 
 
2786
  default:
 
2787
    assert(0);
 
2788
 
 
2789
  }
 
2790
 
 
2791
  /* Check if the maximum id returned on some ranks leads to
 
2792
     a lower global_num_end than initially required
 
2793
     (due to local buffer being full) */
 
2794
 
 
2795
  _expand_limit_g(this_tesselation,
 
2796
                  retval,
 
2797
                  global_num_end,
 
2798
                  comm);
 
2799
 
 
2800
  return retval;
 
2801
}
 
2802
 
 
2803
#endif /* defined(HAVE_MPI) */
 
2804
 
 
2805
/*----------------------------------------------------------------------------
 
2806
 * Decode tesselation to a connectivity buffer.
 
2807
 *
 
2808
 * To avoid requiring huge buffers and computing unneeded element
 
2809
 * connectivities, this function may decode a partial connectivity range,
 
2810
 * starting at polygon index start_id and ending either when the indicated
 
2811
 * buffer size or the last polygon is attained.
 
2812
 * It returns the effective polygon index end.
 
2813
 *
 
2814
 * parameters:
 
2815
 *   this_tesselation   <-- tesselation structure
 
2816
 *   connect_type       <-- destination element type
 
2817
 *   start_id           <-- start index of polygons subset in parent section
 
2818
 *   buffer_limit       <-- maximum number of sub-elements of destination
 
2819
 *                          element type allowable for sub_element_idx[]
 
2820
 *                          and vertex_num[] buffers
 
2821
 *   extra_vertex_base  <-- starting number for added vertices
 
2822
 *   vertex_num         --> sub-element (global) vertex connectivity
 
2823
 *
 
2824
 * returns:
 
2825
 *   polygon index corresponding to end of decoded range
 
2826
 *----------------------------------------------------------------------------*/
 
2827
 
 
2828
fvm_lnum_t
 
2829
fvm_tesselation_decode(const fvm_tesselation_t  *this_tesselation,
 
2830
                       fvm_element_t             connect_type,
 
2831
                       fvm_lnum_t                start_id,
 
2832
                       fvm_lnum_t                buffer_limit,
 
2833
                       fvm_lnum_t                extra_vertex_base,
 
2834
                       fvm_lnum_t                vertex_num[])
 
2835
{
 
2836
  fvm_lnum_t retval = 0;
 
2837
 
 
2838
  switch(this_tesselation->type) {
 
2839
 
 
2840
  case FVM_CELL_POLY:
 
2841
    retval = _decode_polyhedra_tesselation_l(this_tesselation,
 
2842
                                             connect_type,
 
2843
                                             start_id,
 
2844
                                             buffer_limit,
 
2845
                                             extra_vertex_base,
 
2846
                                             vertex_num);
 
2847
    break;
 
2848
 
 
2849
  case FVM_FACE_POLY:
 
2850
    retval = _decode_polygons_tesselation_l(this_tesselation,
 
2851
                                            connect_type,
 
2852
                                            start_id,
 
2853
                                            buffer_limit,
 
2854
                                            vertex_num);
 
2855
    break;
 
2856
 
 
2857
  default:
 
2858
    assert(0);
 
2859
 
 
2860
  }
 
2861
 
 
2862
  return retval;
 
2863
}
 
2864
 
 
2865
/*----------------------------------------------------------------------------
 
2866
 * Distribute "per element" data from the base elements to their tesselation.
 
2867
 *
 
2868
 * The same data array is used for input and output, so as to avoid requiring
 
2869
 * excess allocation in typical use cases (extracting data from a parent mesh
 
2870
 * to a buffer and distributing it as per its tesselation).
 
2871
 * The data array should be at least of size:
 
2872
 * [sub_elt_index[end_id] - sub_elt_index[start_id] * size
 
2873
 *
 
2874
 * parameters:
 
2875
 *   this_tesselation   <-- tesselation structure
 
2876
 *   connect_type       <-- destination element type
 
2877
 *   start_id           <-- start index of elements subset in parent section
 
2878
 *   end_id             <-- end index of elements subset in parent section
 
2879
 *   size               <-- data size for each element (sizeof(type)*stride)
 
2880
 *   data               <-> undistributed data in, distributed data out
 
2881
 *----------------------------------------------------------------------------*/
 
2882
 
 
2883
void
 
2884
fvm_tesselation_distribute(const fvm_tesselation_t  *this_tesselation,
 
2885
                           fvm_element_t             connect_type,
 
2886
                           fvm_lnum_t                start_id,
 
2887
                           fvm_lnum_t                end_id,
 
2888
                           size_t                    size,
 
2889
                           void                     *data)
 
2890
{
 
2891
  int id;
 
2892
  fvm_lnum_t  i, j, k, n_sub;
 
2893
  size_t  l;
 
2894
  char  *src, *dest;
 
2895
 
 
2896
  const fvm_lnum_t *sub_elt_index = NULL;
 
2897
 
 
2898
  /* Find index, or return */
 
2899
 
 
2900
  if (this_tesselation == NULL)
 
2901
    return;
 
2902
 
 
2903
  for (id = 0; id < this_tesselation->n_sub_types; id++) {
 
2904
    if (this_tesselation->sub_type[id] == connect_type) {
 
2905
      sub_elt_index = this_tesselation->sub_elt_index[id];
 
2906
      break;
 
2907
    }
 
2908
  }
 
2909
  if (id == this_tesselation->n_sub_types)
 
2910
    return;
 
2911
 
 
2912
  /* Distribute data (starting from the end so as not to overwrite
 
2913
     data at the beginning of the array) */
 
2914
 
 
2915
  for (i = end_id, j = end_id - start_id - 1; i > start_id; i--, j--) {
 
2916
 
 
2917
    src = ((char *)data) + j*size;
 
2918
    dest = ((char *)data) + (sub_elt_index[i-1] - sub_elt_index[start_id])*size;
 
2919
    n_sub = sub_elt_index[i] - sub_elt_index[i-1];
 
2920
 
 
2921
    for (k = 0; k < n_sub; k++) {
 
2922
      for (l = 0; l < size; l++)
 
2923
        dest[k*size + l] = src[l];
 
2924
    }
 
2925
  }
 
2926
 
 
2927
}
 
2928
 
 
2929
/*----------------------------------------------------------------------------
 
2930
 * Compute field values at added vertices for a tesselation of polyhedra.
 
2931
 *
 
2932
 * One additional vertex is added near the center of each polyhedra.
 
2933
 * For element types other than polyhedra, there is no need for added
 
2934
 * vertices, so this function returns immediately.
 
2935
 *
 
2936
 * parameters:
 
2937
 *   this_tesselation <-- tesselation structure
 
2938
 *   vertex_coords    <-- coordinates of added vertices
 
2939
 *   src_dim          <-- dimension of source data
 
2940
 *   src_dim_shift    <-- source data dimension shift (start index)
 
2941
 *   dest_dim         <-- destination data dimension (1 if non interlaced)
 
2942
 *   start_id         <-- added vertices start index
 
2943
 *   end_id           <-- added vertices past the end index
 
2944
 *   src_interlace    <-- indicates if source data is interlaced
 
2945
 *   src_datatype     <-- source data type (float, double, or int)
 
2946
 *   dest_datatype    <-- destination data type (float, double, or int)
 
2947
 *   n_parent_lists   <-- number of parent lists (if parent_num != NULL)
 
2948
 *   parent_num_shift <-- parent number to value array index shifts;
 
2949
 *                        size: n_parent_lists
 
2950
 *   parent_num       <-- if n_parent_lists > 0, parent entity numbers
 
2951
 *   src_data         <-- array of source arrays (at least one, with one per
 
2952
 *                        source dimension if non interlaced, times one per
 
2953
 *                        parent list if multiple parent lists, with
 
2954
 *                        x_parent_1, y_parent_1, ..., x_parent_2, ...) order
 
2955
 *   dest_data        --> destination buffer
 
2956
 *----------------------------------------------------------------------------*/
 
2957
 
 
2958
void
 
2959
fvm_tesselation_vertex_values(const fvm_tesselation_t  *this_tesselation,
 
2960
                              int                       src_dim,
 
2961
                              int                       src_dim_shift,
 
2962
                              int                       dest_dim,
 
2963
                              fvm_lnum_t                start_id,
 
2964
                              fvm_lnum_t                end_id,
 
2965
                              fvm_interlace_t           src_interlace,
 
2966
                              fvm_datatype_t            src_datatype,
 
2967
                              fvm_datatype_t            dest_datatype,
 
2968
                              int                       n_parent_lists,
 
2969
                              const fvm_lnum_t          parent_num_shift[],
 
2970
                              const fvm_lnum_t          parent_num[],
 
2971
                              const void         *const src_data[],
 
2972
                              void               *const dest_data)
 
2973
{
 
2974
  /* If source or destination datatype is not floating-point,
 
2975
     set all return values to zero */
 
2976
 
 
2977
  if (   (src_datatype != FVM_DOUBLE && src_datatype != FVM_FLOAT)
 
2978
      || (dest_datatype != FVM_DOUBLE && dest_datatype != FVM_FLOAT)) {
 
2979
 
 
2980
    unsigned char *_dest_data = dest_data;
 
2981
 
 
2982
    size_t data_shift =     start_id
 
2983
                          * (dest_dim * fvm_datatype_size[dest_datatype]);
 
2984
    size_t data_size_c =    (end_id - start_id)
 
2985
                          * (dest_dim * fvm_datatype_size[dest_datatype]);
 
2986
 
 
2987
    memset(_dest_data + data_shift, 0, data_size_c);
 
2988
 
 
2989
  }
 
2990
 
 
2991
  /* Otherwise, interpolate values */
 
2992
 
 
2993
  else {
 
2994
 
 
2995
    _vertex_field_of_real_values(this_tesselation,
 
2996
                                 src_dim,
 
2997
                                 src_dim_shift,
 
2998
                                 dest_dim,
 
2999
                                 start_id,
 
3000
                                 end_id,
 
3001
                                 src_interlace,
 
3002
                                 src_datatype,
 
3003
                                 dest_datatype,
 
3004
                                 n_parent_lists,
 
3005
                                 parent_num_shift,
 
3006
                                 parent_num,
 
3007
                                 src_data,
 
3008
                                 dest_data);
 
3009
  }
 
3010
 
 
3011
}
 
3012
 
 
3013
/*----------------------------------------------------------------------------
 
3014
 * Dump printout of a mesh section tesselation structure.
 
3015
 *
 
3016
 * parameters:
 
3017
 *   this_tesselation  <-- pointer to structure that should be dumped
 
3018
 *----------------------------------------------------------------------------*/
 
3019
 
 
3020
void
 
3021
fvm_tesselation_dump(const fvm_tesselation_t  *this_tesselation)
 
3022
{
 
3023
  int  i;
 
3024
  fvm_lnum_t  n_elements, j, k;
 
3025
  const fvm_lnum_t  *idx;
 
3026
 
 
3027
  if (this_tesselation == NULL)
 
3028
    return;
 
3029
 
 
3030
  /* Global indicators */
 
3031
  /*--------------------*/
 
3032
 
 
3033
  bft_printf("\n"
 
3034
             "Tesselation:\n\n"
 
3035
             "Element type:         %s\n"
 
3036
             "Number of elements:   %ld\n"
 
3037
             "Spatial dimension:    %d\n"
 
3038
             "Entity dimension:     %d\n",
 
3039
             fvm_elements_type_name[this_tesselation->type],
 
3040
             (long)this_tesselation->n_elements,
 
3041
             this_tesselation->dim, this_tesselation->entity_dim);
 
3042
 
 
3043
  bft_printf("\n"
 
3044
             "Stride:                %d\n"
 
3045
             "Number of faces:       %d\n",
 
3046
             this_tesselation->stride,
 
3047
             (long)(this_tesselation->n_faces));
 
3048
 
 
3049
  bft_printf("\n"
 
3050
             "Pointers to shared arrays:\n"
 
3051
             "  vertex_coords         %p\n"
 
3052
             "  parent_vertex_num     %p\n"
 
3053
             "  face_num:             %p\n"
 
3054
             "  vertex_index:         %p\n"
 
3055
             "  vertex_num:           %p\n",
 
3056
             this_tesselation->vertex_coords,
 
3057
             this_tesselation->parent_vertex_num,
 
3058
             this_tesselation->face_index, this_tesselation->face_num,
 
3059
             this_tesselation->vertex_index, this_tesselation->vertex_num);
 
3060
 
 
3061
  bft_printf("\n"
 
3062
             "Pointers to shared global numbering:\n"
 
3063
             "  global_element_num    %p\n",
 
3064
             this_tesselation->global_element_num);
 
3065
 
 
3066
 
 
3067
  /* Basic information */
 
3068
  /*-------------------*/
 
3069
 
 
3070
  bft_printf("\n"
 
3071
             "Number of sub-entity types:     %d\n\n",
 
3072
             this_tesselation->n_sub_types);
 
3073
 
 
3074
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
3075
    bft_printf("Maximum local number of resulting %s per element: %ld\n",
 
3076
               fvm_elements_type_name[this_tesselation->sub_type[i]],
 
3077
               (long)(this_tesselation->n_sub_max[i]));
 
3078
  }
 
3079
 
 
3080
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
3081
    bft_printf("Maximum global number of resulting %s per element: %ld\n",
 
3082
               fvm_elements_type_name[this_tesselation->sub_type[i]],
 
3083
               (long)(this_tesselation->n_sub_max_glob[i]));
 
3084
  }
 
3085
 
 
3086
  bft_printf("\n");
 
3087
 
 
3088
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
3089
    bft_printf("Local number of resulting %s: %ld\n",
 
3090
               fvm_elements_type_name[this_tesselation->sub_type[i]],
 
3091
               (long)(this_tesselation->n_sub[i]));
 
3092
  }
 
3093
 
 
3094
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
3095
    bft_printf("Global number of resulting %s: %llu\n",
 
3096
               fvm_elements_type_name[this_tesselation->sub_type[i]],
 
3097
               (unsigned long long)(this_tesselation->n_sub_glob[i]));
 
3098
  }
 
3099
 
 
3100
  bft_printf("\n"
 
3101
             "Pointers to shareable arrays:\n"
 
3102
             "  encoding:  %p\n",
 
3103
             this_tesselation->encoding);
 
3104
 
 
3105
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
3106
    if (this_tesselation->sub_elt_index[i] != NULL)
 
3107
      bft_printf("  sub_elt_index[%s]: %p\n",
 
3108
                 fvm_elements_type_name[this_tesselation->sub_type[i]],
 
3109
                 this_tesselation->sub_elt_index[i]);
 
3110
  }
 
3111
 
 
3112
  bft_printf("\n"
 
3113
             "Pointers to local arrays:\n"
 
3114
             "  _encoding: %p\n",
 
3115
             this_tesselation->_encoding);
 
3116
 
 
3117
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
3118
    if (this_tesselation->sub_elt_index[i] != NULL)
 
3119
      bft_printf("  _sub_elt_index[%s]: %p\n",
 
3120
                 fvm_elements_type_name[this_tesselation->sub_type[i]],
 
3121
                 this_tesselation->_sub_elt_index[i]);
 
3122
  }
 
3123
 
 
3124
  if (this_tesselation->encoding != NULL) {
 
3125
 
 
3126
    fvm_tesselation_encoding_t decoding_mask[3] = {0, 0, 0};
 
3127
    fvm_lnum_t tv[3];
 
3128
 
 
3129
    _init_decoding_mask(decoding_mask);
 
3130
 
 
3131
    if (this_tesselation->type != FVM_FACE_QUAD) {
 
3132
      bft_printf("\nEncoding (local vertex numbers):\n\n");
 
3133
      if (this_tesselation->n_faces > 0)
 
3134
        n_elements = this_tesselation->n_faces;
 
3135
      else
 
3136
        n_elements = this_tesselation->n_elements;
 
3137
      idx = this_tesselation->vertex_index;
 
3138
      for (j = 0; j < n_elements; j++) {
 
3139
        _DECODE_TRIANGLE_VERTICES(tv,
 
3140
                                  this_tesselation->encoding[idx[j] - 2*j],
 
3141
                                  decoding_mask);
 
3142
        bft_printf("%10d (idx = %10d) %10d %10d %10d\n",
 
3143
                   j+1, idx[j], (int)tv[0], (int)tv[1], (int)tv[2]);
 
3144
        for (k = idx[j] -2*j + 1; k < idx[j+1] - 2*j; k++) {
 
3145
          _DECODE_TRIANGLE_VERTICES(tv,
 
3146
                                    this_tesselation->encoding[k],
 
3147
                                    decoding_mask);
 
3148
          bft_printf("                              %10d %10d %10d\n",
 
3149
                     (int)tv[0], (int)tv[1], (int)tv[2]);
 
3150
        }
 
3151
      }
 
3152
      bft_printf("      end  (idx = %10d)\n", idx[n_elements]);
 
3153
    }
 
3154
    else { /* if (this_tesselation->type != FVM_FACE_QUAD) */
 
3155
      bft_printf("\nEncoding (diagonal flag):\n\n");
 
3156
      n_elements = this_tesselation->n_elements;
 
3157
      for (j = 0; j < n_elements; j++)
 
3158
        bft_printf("%10d: %10d\n", j+1, (int)this_tesselation->encoding[j]);
 
3159
    }
 
3160
 
 
3161
  }
 
3162
 
 
3163
  for (i = 0; i < this_tesselation->n_sub_types; i++) {
 
3164
    if (this_tesselation->sub_elt_index[i] != NULL) {
 
3165
      bft_printf("\nSub-element index [%s]:\n\n",
 
3166
                 fvm_elements_type_name[this_tesselation->sub_type[i]]);
 
3167
      n_elements = this_tesselation->n_elements;
 
3168
      idx = this_tesselation->sub_elt_index[i];
 
3169
      for (j = 0; j < n_elements; j++)
 
3170
        bft_printf("%10d: idx = %10d\n", j+1, idx[j]);
 
3171
      bft_printf("      end: idx = %10d\n", idx[n_elements]);
 
3172
    }
 
3173
  }
 
3174
 
 
3175
}
 
3176
 
 
3177
/*----------------------------------------------------------------------------*/
 
3178
 
 
3179
#ifdef __cplusplus
 
3180
}
 
3181
#endif /* __cplusplus */