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

« back to all changes in this revision

Viewing changes to preprocessor/base/ecs_table_def.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*============================================================================
 
2
 *  Definitions des fonctions
 
3
 *   associees a la structure `ecs_table_t' decrivant un table
 
4
 *   et propres aux tables principaux de type "definition"
 
5
 *============================================================================*/
 
6
 
 
7
/*
 
8
  This file is part of Code_Saturne, a general-purpose CFD tool.
 
9
 
 
10
  Copyright (C) 1998-2011 EDF S.A.
 
11
 
 
12
  This program is free software; you can redistribute it and/or modify it under
 
13
  the terms of the GNU General Public License as published by the Free Software
 
14
  Foundation; either version 2 of the License, or (at your option) any later
 
15
  version.
 
16
 
 
17
  This program is distributed in the hope that it will be useful, but WITHOUT
 
18
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
19
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 
20
  details.
 
21
 
 
22
  You should have received a copy of the GNU General Public License along with
 
23
  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
24
  Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
25
*/
 
26
 
 
27
/*----------------------------------------------------------------------------*/
 
28
 
 
29
 
 
30
/*============================================================================
 
31
 *                                 Visibilite
 
32
 *============================================================================*/
 
33
 
 
34
/*----------------------------------------------------------------------------
 
35
 *  Fichiers `include' librairie standard C
 
36
 *----------------------------------------------------------------------------*/
 
37
 
 
38
#include <assert.h>
 
39
#include <stdlib.h>
 
40
#include <string.h>
 
41
 
 
42
 
 
43
/*----------------------------------------------------------------------------
 
44
 *  Fichiers `include' visibles du  paquetage global "Utilitaire"
 
45
 *----------------------------------------------------------------------------*/
 
46
 
 
47
#include "ecs_elt_typ_liste.h"
 
48
#include "ecs_def.h"
 
49
#include "ecs_mem.h"
 
50
#include "ecs_tab.h"
 
51
 
 
52
 
 
53
/*----------------------------------------------------------------------------
 
54
 *  Fichiers `include' visibles des paquetages visibles
 
55
 *----------------------------------------------------------------------------*/
 
56
 
 
57
 
 
58
/*----------------------------------------------------------------------------
 
59
 *  Fichiers `include' visibles du  paquetage courant
 
60
 *----------------------------------------------------------------------------*/
 
61
 
 
62
#include "ecs_table.h"
 
63
 
 
64
 
 
65
/*----------------------------------------------------------------------------
 
66
 *  Fichier  `include' du  paquetage courant associe au fichier courant
 
67
 *----------------------------------------------------------------------------*/
 
68
 
 
69
#include "ecs_table_def.h"
 
70
 
 
71
 
 
72
/*----------------------------------------------------------------------------
 
73
 *  Fichiers `include' prives   du  paquetage courant
 
74
 *----------------------------------------------------------------------------*/
 
75
 
 
76
#include "ecs_table_priv.h"
 
77
 
 
78
 
 
79
/*============================================================================
 
80
 *                       Macros globales au fichier
 
81
 *============================================================================*/
 
82
 
 
83
/* Longueur maximale du nom d'un type d'élément (+1 pour le `\0' !) */
 
84
#define ECS_LOC_LNG_MAX_NOM_TYP    11
 
85
 
 
86
#if !defined(FLT_MAX)
 
87
#define FLT_MAX HUGE_VAL
 
88
#endif
 
89
 
 
90
#define ECS_LOC_PRODUIT_VECTORIEL(prod_vect, vect1, vect2) ( \
 
91
prod_vect[0] = vect1[1] * vect2[2] - vect2[1] * vect1[2],   \
 
92
prod_vect[1] = vect2[0] * vect1[2] - vect1[0] * vect2[2],   \
 
93
prod_vect[2] = vect1[0] * vect2[1] - vect2[0] * vect1[1]   )
 
94
 
 
95
#define ECS_LOC_PRODUIT_SCALAIRE(vect1, vect2)                        ( \
 
96
  vect1[0] * vect2[0] + vect1[1] * vect2[1] + vect1[2] * vect2[2] )
 
97
 
 
98
#define ECS_LOC_MODULE(vect) \
 
99
     sqrt(vect[0] * vect[0] + vect[1] * vect[1] + vect[2] * vect[2])
 
100
 
 
101
#define ECS_LOC_DETERMINANT(vect1, vect2, vect3) ( \
 
102
   ((vect1[1] * vect2[2] - vect2[1] * vect1[2]) * vect3[0]) \
 
103
 + ((vect2[0] * vect1[2] - vect1[0] * vect2[2]) * vect3[1]) \
 
104
 + ((vect1[0] * vect2[1] - vect2[0] * vect1[1]) * vect3[2]) )
 
105
 
 
106
/*============================================================================
 
107
 *                              Fonctions privees
 
108
 *============================================================================*/
 
109
 
 
110
/*----------------------------------------------------------------------------
 
111
 *  Fonction qui met à jour la définition faces -> sommets en cas
 
112
 *  de fusion de sommets.
 
113
 *----------------------------------------------------------------------------*/
 
114
 
 
115
static void
 
116
_table_def__maj_fac_som(ecs_table_t          *table_def_fac,
 
117
                        const ecs_tab_int_t  *tab_som_old_new)
 
118
{
 
119
  size_t     cpt_val;
 
120
  size_t     nbr_fac;
 
121
  size_t     nbr_fac_mod;
 
122
  size_t     nbr_val_ini, nbr_val_fin;
 
123
  size_t     nbr_som_fac;
 
124
 
 
125
  size_t     num_som, num_som_prev;
 
126
 
 
127
  size_t     ind_fac;
 
128
  size_t     ind_fac_mod;
 
129
  size_t     ind_som;
 
130
 
 
131
  size_t     ipos_deb, ipos_fin;
 
132
 
 
133
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
134
 
 
135
  /* Initialisations */
 
136
  /* --------------- */
 
137
 
 
138
  nbr_fac = table_def_fac->nbr;
 
139
 
 
140
  nbr_val_ini = table_def_fac->pos[nbr_fac];
 
141
 
 
142
  /* Mise à jour de la définition des faces */
 
143
  /*----------------------------------------*/
 
144
 
 
145
  for (ind_som = 0;
 
146
       ind_som < table_def_fac->pos[table_def_fac->nbr] - 1;
 
147
       ind_som++)
 
148
 
 
149
    table_def_fac->val[ind_som]
 
150
      = tab_som_old_new->val[table_def_fac->val[ind_som] - 1];
 
151
 
 
152
  /* Suppression de sommets confondus de la définition des faces */
 
153
  /*-------------------------------------------------------------*/
 
154
 
 
155
  nbr_fac_mod = 0;
 
156
 
 
157
  cpt_val = 0;
 
158
  ipos_deb = 1;
 
159
 
 
160
  for (ind_fac = 0; ind_fac < nbr_fac; ind_fac++) {
 
161
 
 
162
    ind_fac_mod = 0;
 
163
 
 
164
    ipos_fin = table_def_fac->pos[ind_fac + 1] - 1;
 
165
 
 
166
    nbr_som_fac = ipos_fin - ipos_deb;
 
167
 
 
168
    num_som_prev = table_def_fac->val[ipos_deb + nbr_som_fac - 1];
 
169
 
 
170
    for (ind_som = 0; ind_som < nbr_som_fac; ind_som++) {
 
171
 
 
172
      num_som = table_def_fac->val[ipos_deb + ind_som];
 
173
 
 
174
      if (num_som != num_som_prev) {
 
175
        num_som_prev = num_som;
 
176
        table_def_fac->val[cpt_val++] = num_som;
 
177
      }
 
178
      else
 
179
        ind_fac_mod = 1;
 
180
    }
 
181
 
 
182
    table_def_fac->pos[ind_fac + 1] = cpt_val + 1;
 
183
 
 
184
    ipos_deb = ipos_fin;
 
185
 
 
186
    nbr_fac_mod += ind_fac_mod;
 
187
  }
 
188
 
 
189
  nbr_val_fin = table_def_fac->pos[nbr_fac];
 
190
 
 
191
  assert(nbr_val_fin <= nbr_val_ini);
 
192
 
 
193
  if (nbr_val_fin != nbr_val_ini) {
 
194
 
 
195
    ECS_REALLOC(table_def_fac->val, nbr_val_fin, ecs_int_t);
 
196
    printf(_("\nMesh verification:\n\n"
 
197
             "  %d faces modified due to merged vertices.\n"),
 
198
           (int)nbr_fac_mod);
 
199
  }
 
200
}
 
201
 
 
202
/*----------------------------------------------------------------------------
 
203
 *  Fonction qui transforme un tableau d'équivalence en liste chaînée simple
 
204
 *----------------------------------------------------------------------------*/
 
205
 
 
206
static void
 
207
_table_def__transf_equiv(size_t          nbr_som,
 
208
                         ecs_tab_int_t  *tab_equiv_som)
 
209
{
 
210
  size_t     ind_som;
 
211
  ecs_int_t  ind_som_min;
 
212
  ecs_int_t  ind_som_max;
 
213
  ecs_int_t  ind_som_tmp;
 
214
 
 
215
  ecs_tab_int_t    tab_equiv_prec;
 
216
 
 
217
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
218
 
 
219
  tab_equiv_prec.nbr = nbr_som;
 
220
  ECS_MALLOC(tab_equiv_prec.val, tab_equiv_prec.nbr, ecs_int_t);
 
221
 
 
222
  for (ind_som = 0; ind_som < nbr_som; ind_som++)
 
223
    tab_equiv_prec.val[ind_som] = -1;
 
224
 
 
225
  for (ind_som = 0; ind_som < nbr_som; ind_som++) {
 
226
 
 
227
    if (tab_equiv_som->val[ind_som] != -1) {
 
228
 
 
229
      ind_som_min = ind_som;
 
230
      ind_som_max = tab_equiv_som->val[ind_som];
 
231
 
 
232
      assert (ind_som_min < ind_som_max);
 
233
 
 
234
      while (   ind_som_min != ind_som_max
 
235
             && tab_equiv_prec.val[ind_som_max] != ind_som_min) {
 
236
 
 
237
        /*
 
238
          On parcourt la liste inverse correspondant à ind_som_max jusqu'au
 
239
          point d'insertion (si pas de point precedent dans la chaine,
 
240
          tab_equiv_prec.val[ind_som_max] = -1).
 
241
        */
 
242
 
 
243
        while (tab_equiv_prec.val[ind_som_max] > ind_som_min)
 
244
          ind_som_max = tab_equiv_prec.val[ind_som_max];
 
245
 
 
246
        ind_som_tmp = tab_equiv_prec.val[ind_som_max];
 
247
 
 
248
        /*
 
249
          Si l'on est en début de chaîne, on branche la liste inverse
 
250
          correspondant à ind_som_min au début de celle correspondant
 
251
          à ind_som_max. Sinon, on doit reboucler.
 
252
        */
 
253
 
 
254
        tab_equiv_prec.val[ind_som_max] = ind_som_min;
 
255
 
 
256
        if (ind_som_tmp != -1) {
 
257
          ind_som_max = ind_som_min;
 
258
          ind_som_min = ind_som_tmp;
 
259
        }
 
260
 
 
261
      }
 
262
    }
 
263
  }
 
264
 
 
265
  for (ind_som = 0; ind_som < nbr_som; ind_som++) {
 
266
 
 
267
    if (tab_equiv_prec.val[ind_som] != -1)
 
268
      tab_equiv_som->val[tab_equiv_prec.val[ind_som]] = ind_som;
 
269
 
 
270
  }
 
271
 
 
272
  tab_equiv_prec.nbr = 0;
 
273
  ECS_FREE(tab_equiv_prec.val);
 
274
}
 
275
 
 
276
/*----------------------------------------------------------------------------
 
277
 *  Fonction qui fusionne des sommets équivalents
 
278
 *
 
279
 *  Remarque : le tableau d'équivalence (fusion) des sommets est construit de
 
280
 *             manière à ce qu'à un sommet ne comportant pas d'équivalent
 
281
 *             où de plus petit indice parmi ses équivalents corresponde la
 
282
 *             valeur -1, alors qu'un un sommet possédant des équivalents de
 
283
 *             plus petit indice corresponde le plus grand indice parmi ces
 
284
 *             équivalents (ce qui constitue une sorte de liste chaînée).
 
285
 *----------------------------------------------------------------------------*/
 
286
 
 
287
static ecs_tab_int_t
 
288
_table_def__fusion_som(size_t          *n_vertices,
 
289
                       ecs_coord_t    **coords,
 
290
                       ecs_tab_int_t   *tab_equiv_som)
 
291
{
 
292
  size_t  ind_som, nbr_som_old, nbr_som_new, nbr_som_fus;
 
293
  ecs_int_t  ind_som_loc, ind_som_tmp, icoo;
 
294
  ecs_coord_t  som_poids;
 
295
  double  som_coord[3];
 
296
 
 
297
  ecs_tab_int_t  tab_som_old_new;
 
298
 
 
299
  /* Initialization */
 
300
  /* -------------- */
 
301
 
 
302
  nbr_som_old = *n_vertices;
 
303
 
 
304
  printf(_("\n  Merging vertices:\n"));
 
305
 
 
306
  /* Transform vertex equivalences array into simple linked list. */
 
307
 
 
308
  _table_def__transf_equiv(nbr_som_old, tab_equiv_som);
 
309
 
 
310
  printf(_("    Initial number of vertices        : %10d\n"), (int)nbr_som_old);
 
311
 
 
312
  tab_som_old_new.nbr = nbr_som_old;
 
313
  ECS_MALLOC(tab_som_old_new.val, tab_som_old_new.nbr, ecs_int_t);
 
314
 
 
315
  /* Initialize vertex renumbering array */
 
316
 
 
317
  for (ind_som = 0; ind_som < nbr_som_old; ind_som++)
 
318
    tab_som_old_new.val[ind_som] = 0;
 
319
 
 
320
  /* Main loop on vertices */
 
321
  /*-----------------------*/
 
322
 
 
323
  nbr_som_new = 0;
 
324
 
 
325
  for (ind_som = 0; ind_som < nbr_som_old; ind_som++) {
 
326
 
 
327
    /* If the vertex has not been handled yet */
 
328
 
 
329
    if (tab_som_old_new.val[ind_som] == 0) {
 
330
 
 
331
      /* Initialize vertex */
 
332
 
 
333
      som_poids = 0.0;
 
334
 
 
335
      for (icoo = 0; icoo < 3; icoo++)
 
336
        som_coord[icoo] = 0.0;
 
337
 
 
338
      ind_som_loc = ind_som;
 
339
 
 
340
      /* Mark equivalent vertices and compute their contribution */
 
341
 
 
342
      do {
 
343
 
 
344
        tab_som_old_new.val[ind_som_loc] = nbr_som_new + 1;
 
345
 
 
346
        som_poids += 1.0;
 
347
 
 
348
        for (icoo = 0; icoo < 3; icoo++)
 
349
          som_coord[icoo] += (* coords)[3*ind_som_loc + icoo];
 
350
 
 
351
        ind_som_loc = tab_equiv_som->val[ind_som_loc];
 
352
 
 
353
      } while (ind_som_loc != -1);
 
354
 
 
355
      /* Final coordinates */
 
356
 
 
357
      for (icoo = 0; icoo < 3; icoo++)
 
358
        (*coords)[3*nbr_som_new + icoo] = som_coord[icoo] / som_poids;
 
359
 
 
360
      /* Do not forget to increment the number of vertices after merge */
 
361
 
 
362
      nbr_som_new += 1;
 
363
    }
 
364
 
 
365
  }
 
366
 
 
367
  /* End of main loop */
 
368
  /* ---------------- */
 
369
 
 
370
  /* We now know the number of vertices after merging */
 
371
 
 
372
  *n_vertices = nbr_som_new;
 
373
  ECS_REALLOC(*coords, nbr_som_new*3, ecs_coord_t);
 
374
 
 
375
  printf(_("    Number of vertices after merging  : %10d\n"), (int)nbr_som_new);
 
376
 
 
377
  /* Mark vertices originating from a merge */
 
378
  /*----------------------------------------*/
 
379
 
 
380
  nbr_som_fus = 0;
 
381
 
 
382
  /*
 
383
    We will not need the vertex equivalence array any more; we thus modify
 
384
    it so that only the first vertex of a linked equivalence list points
 
385
    to its first equivalent, to use it as a marker.
 
386
  */
 
387
 
 
388
  for (ind_som = 0; ind_som < tab_equiv_som->nbr; ind_som++) {
 
389
 
 
390
    if (tab_equiv_som->val[ind_som] != -1) {
 
391
 
 
392
      nbr_som_fus += 1;
 
393
 
 
394
      ind_som_loc = tab_equiv_som->val[ind_som];
 
395
 
 
396
      while (ind_som_loc != -1) {
 
397
 
 
398
        ind_som_tmp = ind_som_loc;
 
399
        ind_som_loc = tab_equiv_som->val[ind_som_loc];
 
400
 
 
401
        tab_equiv_som->val[ind_som_tmp] = -1;
 
402
 
 
403
      }
 
404
    }
 
405
  }
 
406
 
 
407
  printf(_("    Number of modified vertices       : %10d\n"), (int)nbr_som_fus);
 
408
 
 
409
  /* Return */
 
410
 
 
411
  return tab_som_old_new;
 
412
}
 
413
 
 
414
/*----------------------------------------------------------------------------
 
415
 *  Fonction qui met à jour le tableau des fusions de sommets
 
416
 *
 
417
 *  Remarque : le tableau d'équivalence (fusion) des sommets est construit de
 
418
 *             manière à ce qu'à un sommet ne comportant pas d'équivalent
 
419
 *             où de plus grand indice parmi ses équivalents corresponde la
 
420
 *             valeur -1, alors qu'un un sommet possédant des équivalents de
 
421
 *             plus grand indice corresponde le plus petit indice parmi ces
 
422
 *             équivalents (ce qui constitue une sorte de liste chaînée).
 
423
 *----------------------------------------------------------------------------*/
 
424
 
 
425
static void
 
426
_table_def__maj_equiv_som(size_t          ind_som_0,
 
427
                          size_t          ind_som_1,
 
428
                          ecs_tab_int_t  *tab_equiv_som)
 
429
{
 
430
  ecs_int_t  ind_som_max;
 
431
  ecs_int_t  ind_som_min;
 
432
  ecs_int_t  ind_som_tmp;
 
433
 
 
434
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
435
 
 
436
  ind_som_min = ECS_MIN(ind_som_0, ind_som_1);
 
437
  ind_som_max = ECS_MAX(ind_som_0, ind_som_1);
 
438
 
 
439
  /* On fusionne deux listes chaînées */
 
440
  /*----------------------------------*/
 
441
 
 
442
  while (   ind_som_max != ind_som_min
 
443
         && tab_equiv_som->val[ind_som_min] != ind_som_max) {
 
444
 
 
445
    /*
 
446
      On parcourt la liste chaînée correspondant à ind_som_min jusqu'au
 
447
      point d'insertion (si pas de point suivant dans la chaine,
 
448
      tab_equiv_som->val[ind_som_min] = -1).
 
449
    */
 
450
 
 
451
    while (   tab_equiv_som->val[ind_som_min] != -1
 
452
           && tab_equiv_som->val[ind_som_min] < ind_som_max)
 
453
      ind_som_min = tab_equiv_som->val[ind_som_min];
 
454
 
 
455
    ind_som_tmp = tab_equiv_som->val[ind_som_min];
 
456
 
 
457
    /*
 
458
      Si l'on est en fin de chaîne, on branche la liste chaînée correspondant
 
459
      à ind_som_max à la suite de celle correspondant à ind_som_min.
 
460
      Sinon, on doit reboucler
 
461
    */
 
462
 
 
463
    tab_equiv_som->val[ind_som_min] = ind_som_max;
 
464
 
 
465
    if (ind_som_tmp != -1) {
 
466
      ind_som_min = ind_som_max;
 
467
      ind_som_max = ind_som_tmp;
 
468
    }
 
469
  }
 
470
}
 
471
 
 
472
/*----------------------------------------------------------------------------
 
473
 *  Correction si nécessaire de l'orientation d'un quadrangle en connectivité
 
474
 *   nodale ; renvoie -1 si l'on ne parvient pas à corriger l'orientation
 
475
 *   ou que l'on demande une simple vérification (i.e. correc = false),
 
476
 *   0 si l'orientation initiale est bonne, et 1 en cas de correction de
 
477
 *   l'orientation par une permutation de la connectivité locale.
 
478
 *----------------------------------------------------------------------------*/
 
479
 
 
480
static ecs_int_t
 
481
_orient_quad(const ecs_coord_t  coord[],
 
482
             ecs_int_t          connect[],
 
483
             const bool         correc)
 
484
{
 
485
  ecs_int_t   isom_tmp;
 
486
  ecs_int_t   itri;
 
487
  ecs_int_t   nb_angle_obtus;
 
488
  ecs_coord_t  sgn;
 
489
  ecs_coord_t  normale[3];
 
490
  ecs_coord_t  vect1[3];
 
491
  ecs_coord_t  vect2[3];
 
492
  ecs_coord_t  prod_vect[3];
 
493
 
 
494
  ecs_int_t   passage = -1;
 
495
 
 
496
#define ECS_LOC_INIT_VECT(vect, i, j) ( \
 
497
  vect[0] =   coord[((connect[j-1] - 1) * 3)    ]  \
 
498
            - coord[((connect[i-1] - 1) * 3)    ], \
 
499
  vect[1] =   coord[((connect[j-1] - 1) * 3) + 1]  \
 
500
            - coord[((connect[i-1] - 1) * 3) + 1], \
 
501
  vect[2] =   coord[((connect[j-1] - 1) * 3) + 2]  \
 
502
            - coord[((connect[i-1] - 1) * 3) + 2] )
 
503
 
 
504
  /* Calcul d'une direction normale approchée de la face
 
505
     (peut être entrante ou sortante si la face est "croisée") */
 
506
 
 
507
  ECS_LOC_INIT_VECT(vect1, 1, 2);
 
508
  ECS_LOC_INIT_VECT(vect2, 1, 4);
 
509
 
 
510
  ECS_LOC_PRODUIT_VECTORIEL(normale, vect1, vect2);
 
511
 
 
512
  /* Boucle sur les renumérotations possibles */
 
513
 
 
514
  do {
 
515
 
 
516
    passage += 1;
 
517
 
 
518
    nb_angle_obtus = 0;
 
519
 
 
520
    /* Initialisation */
 
521
 
 
522
    switch(passage) {
 
523
 
 
524
    case 0:
 
525
      break;
 
526
 
 
527
    case 1:
 
528
      if (correc == false)
 
529
        return -1;
 
530
      isom_tmp = connect[2];
 
531
      connect[2] = connect[3];
 
532
      connect[3] = isom_tmp;
 
533
      break;
 
534
 
 
535
    default:
 
536
      return -1;
 
537
 
 
538
    }
 
539
 
 
540
    /* Boucle sur les coins */
 
541
 
 
542
    /* On compte les angles obtus, qui devraient être au nombre de 2 sur
 
543
       une face "croisée" (et 0 sur une face bien définie et convexe
 
544
       1 sur une face bien définie non convexe, soit 3 en apparaence
 
545
       sur une face bien définie convexe si la non-convexité se trouve
 
546
       au niveau du sommet 1 et que l'on a donc calculé une normale
 
547
       "à l'envers"). */
 
548
 
 
549
    for (itri = 0; itri < 4; itri++) {
 
550
 
 
551
      ECS_LOC_INIT_VECT(vect1, ((itri+2) % 4) + 1, ((itri+1) % 4) + 1);
 
552
      ECS_LOC_INIT_VECT(vect2, ( itri    % 4) + 1, ((itri+1) % 4) + 1);
 
553
 
 
554
      ECS_LOC_PRODUIT_VECTORIEL(prod_vect, vect1, vect2);
 
555
 
 
556
      /* Angle obtus si produit mixte < 0, aigu sinon. */
 
557
 
 
558
      sgn = ECS_LOC_PRODUIT_SCALAIRE(prod_vect, normale);
 
559
 
 
560
      if (sgn < 0.0)
 
561
        nb_angle_obtus += 1;
 
562
 
 
563
    }
 
564
 
 
565
  } while (nb_angle_obtus == 2);
 
566
 
 
567
  return (ECS_MIN(passage, 1));
 
568
 
 
569
#undef ECS_LOC_INIT_VECT
 
570
}
 
571
 
 
572
/*----------------------------------------------------------------------------
 
573
 *  Correction si nécessaire de l'orientation d'un tétraèdre en connectivité
 
574
 *   nodale ; renvoie -1 si l'on ne parvient pas à corriger l'orientation,
 
575
 *   0 si l'orientation initiale est bonne, et 1 en cas de correction de
 
576
 *   l'orientation par une permutation de la connectivité locale.
 
577
 *----------------------------------------------------------------------------*/
 
578
 
 
579
static ecs_int_t
 
580
_orient_tetra(const ecs_coord_t  coord[],
 
581
              ecs_int_t          connect[])
 
582
{
 
583
  ecs_int_t   isom_tmp;
 
584
  ecs_coord_t  det;
 
585
  ecs_coord_t  vect12[3];
 
586
  ecs_coord_t  vect13[3];
 
587
  ecs_coord_t  vect14[3];
 
588
 
 
589
  ecs_int_t   passage = -1;
 
590
 
 
591
#define ECS_LOC_INIT_VECT(vect, i, j) ( \
 
592
  vect[0] =   coord[((connect[j-1] - 1) * 3)    ]  \
 
593
            - coord[((connect[i-1] - 1) * 3)    ], \
 
594
  vect[1] =   coord[((connect[j-1] - 1) * 3) + 1]  \
 
595
            - coord[((connect[i-1] - 1) * 3) + 1], \
 
596
  vect[2] =   coord[((connect[j-1] - 1) * 3) + 2]  \
 
597
            - coord[((connect[i-1] - 1) * 3) + 2] )
 
598
 
 
599
#define ECS_LOC_PERMUTE(i, j) ( \
 
600
  isom_tmp = connect[i-1],     \
 
601
  connect[i-1] = connect[j-1], \
 
602
  connect[j-1] = isom_tmp      )
 
603
 
 
604
  /* Boucle sur les renumérotations possibles */
 
605
 
 
606
  do {
 
607
 
 
608
    passage += 1;
 
609
 
 
610
    /* Initialisation */
 
611
 
 
612
    switch(passage) {
 
613
 
 
614
    case 0:
 
615
      break;
 
616
 
 
617
    case 1:
 
618
      ECS_LOC_PERMUTE(2, 3);
 
619
      break;
 
620
 
 
621
    default: /* Retour connectivité d'origine et sortie */
 
622
      ECS_LOC_PERMUTE(2, 3);
 
623
      return -1;
 
624
 
 
625
    }
 
626
 
 
627
    ECS_LOC_INIT_VECT(vect12, 1, 2);
 
628
    ECS_LOC_INIT_VECT(vect13, 1, 3);
 
629
    ECS_LOC_INIT_VECT(vect14, 1, 4);
 
630
 
 
631
    det = ECS_LOC_DETERMINANT(vect12, vect13, vect14);
 
632
 
 
633
  } while (det < 0.0);
 
634
 
 
635
  return (ECS_MIN(passage, 1));
 
636
 
 
637
#undef ECS_LOC_INIT_VECT
 
638
#undef ECS_LOC_PERMUTE
 
639
}
 
640
 
 
641
/*----------------------------------------------------------------------------
 
642
 *  Correction si nécessaire de l'orientation d'une pyramide en connectivité
 
643
 *   nodale ; renvoie -1 si l'on ne parvient pas à corriger l'orientation
 
644
 *   ou que l'on demande une simple vérification (i.e. correc = false),
 
645
 *   0 si l'orientation initiale est bonne, et 1 en cas de correction de
 
646
 *   l'orientation par une permutation de la connectivité locale.
 
647
 *
 
648
 *  Tous les cas ne sont pas détectés ou traités : on suppose que le
 
649
 *   sommet est toujours en position 5, mais que la base peut être
 
650
 *   parcourue dans l'ordre 1 4 3 2, 1 2 4 3, ou 1 3 4 2 au lieu de 1 2 3 4,
 
651
 *   dans quel cas on la réordonne.
 
652
 *----------------------------------------------------------------------------*/
 
653
 
 
654
static ecs_int_t
 
655
_orient_pyram(const ecs_coord_t  coord[],
 
656
              ecs_int_t          connect[],
 
657
              const bool         correc)
 
658
{
 
659
  ecs_int_t   isom;
 
660
  ecs_int_t   isom_tmp;
 
661
  ecs_int_t   connect_tmp[8];
 
662
  ecs_int_t   ret_base;
 
663
  ecs_coord_t  det;
 
664
  ecs_coord_t  vect1[3];
 
665
  ecs_coord_t  vect2[3];
 
666
  ecs_coord_t  vect3[3];
 
667
 
 
668
  ecs_int_t   retval = 0;
 
669
  ecs_int_t   passage = -1;
 
670
 
 
671
#define ECS_LOC_INIT_VECT(vect, i, j) ( \
 
672
  vect[0] =   coord[((connect_tmp[j-1] - 1) * 3)    ]  \
 
673
            - coord[((connect_tmp[i-1] - 1) * 3)    ], \
 
674
  vect[1] =   coord[((connect_tmp[j-1] - 1) * 3) + 1]  \
 
675
            - coord[((connect_tmp[i-1] - 1) * 3) + 1], \
 
676
  vect[2] =   coord[((connect_tmp[j-1] - 1) * 3) + 2]  \
 
677
            - coord[((connect_tmp[i-1] - 1) * 3) + 2] )
 
678
 
 
679
#define ECS_LOC_PERMUTE(i, j) ( \
 
680
  isom_tmp = connect[i-1],             \
 
681
  connect_tmp[i-1] = connect_tmp[j-1], \
 
682
  connect_tmp[j-1] = isom_tmp         )
 
683
 
 
684
 
 
685
  for (isom = 0; isom < 5; isom++)
 
686
    connect_tmp[isom] = connect[isom];
 
687
 
 
688
  /* Vérification et correction éventuelle de l'orientation de la base */
 
689
 
 
690
  ret_base = _orient_quad(coord,
 
691
                          connect_tmp,
 
692
                          correc);
 
693
 
 
694
  retval = ECS_MAX(ret_base, retval);
 
695
 
 
696
  if ((correc == false && ret_base != 0) || ret_base < 0)
 
697
    return - 1;
 
698
 
 
699
 
 
700
  /* Boucle sur les renumérotations possibles */
 
701
 
 
702
  do {
 
703
 
 
704
    passage += 1;
 
705
 
 
706
    /* Initialisation */
 
707
 
 
708
    switch(passage) {
 
709
 
 
710
    case 0:
 
711
      break;
 
712
 
 
713
    case 1:
 
714
      if (correc == false)
 
715
        return -1;
 
716
      else
 
717
        retval = 1;
 
718
      ECS_LOC_PERMUTE(2, 4);
 
719
      break;
 
720
 
 
721
    default: /* Retour connectivité d'origine et sortie */
 
722
      ECS_LOC_PERMUTE(2, 4);
 
723
      return -1;
 
724
 
 
725
    }
 
726
 
 
727
    ECS_LOC_INIT_VECT(vect1, 1, 2);
 
728
    ECS_LOC_INIT_VECT(vect2, 1, 4);
 
729
    ECS_LOC_INIT_VECT(vect3, 1, 5);
 
730
 
 
731
    det = ECS_LOC_DETERMINANT(vect1, vect2, vect3);
 
732
 
 
733
  } while (det < 0.0);
 
734
 
 
735
  if (retval > 0) {
 
736
    for (isom = 0; isom < 5; isom++)
 
737
      connect[isom] = connect_tmp[isom];
 
738
  }
 
739
 
 
740
  return retval;
 
741
 
 
742
#undef ECS_LOC_INIT_VECT
 
743
#undef ECS_LOC_PERMUTE
 
744
}
 
745
 
 
746
/*----------------------------------------------------------------------------
 
747
 *  Correction si nécessaire de l'orientation d'un prisme en connectivité
 
748
 *   nodale ; renvoie -1 si l'on ne parvient pas à corriger l'orientation
 
749
 *   ou que l'on demande une simple vérification (i.e. correc = false),
 
750
 *   0 si l'orientation initiale est bonne, et 1 en cas de correction de
 
751
 *   l'orientation par une permutation de la connectivité locale.
 
752
 *
 
753
 *  Tous les cas ne sont pas détectés ou traités : on suppose que les
 
754
 *   bases peuvent être parcourues dans l'ordre 1 3 2 et 4 6 5 au lieu
 
755
 *   de 1 2 3 et 4 5 6, dans quel cas on les réordonne.
 
756
 *----------------------------------------------------------------------------*/
 
757
 
 
758
static ecs_int_t
 
759
_orient_prism(const ecs_coord_t  coord[],
 
760
              ecs_int_t          connect[],
 
761
              const bool         correc)
 
762
{
 
763
  ecs_int_t   idim;
 
764
  ecs_int_t   isom_tmp;
 
765
  ecs_coord_t  pscal;
 
766
  ecs_coord_t  vect1[3];
 
767
  ecs_coord_t  vect2[3];
 
768
  ecs_coord_t  vect3[3];
 
769
 
 
770
  ecs_int_t   passage    = -1;
 
771
 
 
772
#define ECS_LOC_INIT_VECT(vect, i, j) ( \
 
773
  vect[0] =   coord[((connect[j-1] - 1) * 3)    ]  \
 
774
            - coord[((connect[i-1] - 1) * 3)    ], \
 
775
  vect[1] =   coord[((connect[j-1] - 1) * 3) + 1]  \
 
776
            - coord[((connect[i-1] - 1) * 3) + 1], \
 
777
  vect[2] =   coord[((connect[j-1] - 1) * 3) + 2]  \
 
778
            - coord[((connect[i-1] - 1) * 3) + 2] )
 
779
 
 
780
#define ECS_LOC_PERMUTE(i, j) ( \
 
781
  isom_tmp = connect[i-1],     \
 
782
  connect[i-1] = connect[j-1], \
 
783
  connect[j-1] = isom_tmp      )
 
784
 
 
785
  /* Boucle sur les renumérotations possibles */
 
786
 
 
787
  do {
 
788
 
 
789
    passage += 1;
 
790
 
 
791
    /* Initialisation */
 
792
 
 
793
    switch(passage) {
 
794
 
 
795
    case 0:
 
796
      break;
 
797
 
 
798
    case 1:
 
799
      if (correc == false)
 
800
        return -1;
 
801
      ECS_LOC_PERMUTE(2, 3);
 
802
      ECS_LOC_PERMUTE(5, 6);
 
803
      break;
 
804
 
 
805
    default: /* Retour connectivité d'origine et sortie */
 
806
      ECS_LOC_PERMUTE(2, 3);
 
807
      ECS_LOC_PERMUTE(5, 6);
 
808
      return -1;
 
809
 
 
810
    }
 
811
 
 
812
    ECS_LOC_INIT_VECT(vect2, 1, 2);
 
813
    ECS_LOC_INIT_VECT(vect3, 1, 3);
 
814
 
 
815
    ECS_LOC_PRODUIT_VECTORIEL(vect1, vect2, vect3);
 
816
 
 
817
    for (idim = 0; idim < 3; idim++)
 
818
      vect2[idim] = (  coord[((connect[4-1] - 1) * 3) + idim]
 
819
                     + coord[((connect[5-1] - 1) * 3) + idim]
 
820
                     + coord[((connect[6-1] - 1) * 3) + idim]
 
821
                     - coord[((connect[1-1] - 1) * 3) + idim]
 
822
                     - coord[((connect[2-1] - 1) * 3) + idim]
 
823
                     - coord[((connect[3-1] - 1) * 3) + idim]);
 
824
 
 
825
    pscal = ECS_LOC_PRODUIT_SCALAIRE(vect1, vect2);
 
826
 
 
827
  } while (pscal < 0.0);
 
828
 
 
829
  return (ECS_MIN(passage, 1));
 
830
 
 
831
#undef ECS_LOC_INIT_VECT
 
832
#undef ECS_LOC_PERMUTE
 
833
}
 
834
 
 
835
/*----------------------------------------------------------------------------
 
836
 *  Correction si nécessaire de l'orientation d'un hexaèdre en connectivité
 
837
 *   nodale ; renvoie -1 si l'on ne parvient pas à corriger l'orientation
 
838
 *   ou que l'on demande une simple vérification (i.e. correc = false),
 
839
 *   0 si l'orientation initiale est bonne, et 1 en cas de correction de
 
840
 *   l'orientation par une permutation de la connectivité locale.
 
841
 *
 
842
 *  Tous les cas ne sont pas détectés ou traités : on suppose que les
 
843
 *   bases peuvent être parcourues dans l'ordre soit 1 4 3 2 et 5 8 7 6,
 
844
 *   soit 1 2 4 3 et 5 6 8 7, soit 1 3 4 2 et 5 7 8 6 au lieu
 
845
 *   de 1 2 3 4 et 5 6 7 8, dans quel cas on les réordonne.
 
846
 *----------------------------------------------------------------------------*/
 
847
 
 
848
static ecs_int_t
 
849
_orient_hexa(const ecs_coord_t  coord[],
 
850
             ecs_int_t          connect[],
 
851
             const bool         correc)
 
852
{
 
853
  ecs_int_t   idim;
 
854
  ecs_int_t   isom;
 
855
  ecs_int_t   isom_tmp;
 
856
  ecs_int_t   connect_tmp[8];
 
857
  ecs_int_t   ret_base_1;
 
858
  ecs_int_t   ret_base_2;
 
859
  ecs_coord_t  pscal;
 
860
  ecs_coord_t  vect1[3];
 
861
  ecs_coord_t  vect2[3];
 
862
  ecs_coord_t  vect3[3];
 
863
 
 
864
  ecs_int_t   retval = 0;
 
865
  ecs_int_t   passage = -1;
 
866
 
 
867
#define ECS_LOC_INIT_VECT(vect, i, j) ( \
 
868
  vect[0] =   coord[((connect_tmp[j-1] - 1) * 3)    ]  \
 
869
            - coord[((connect_tmp[i-1] - 1) * 3)    ], \
 
870
  vect[1] =   coord[((connect_tmp[j-1] - 1) * 3) + 1]  \
 
871
            - coord[((connect_tmp[i-1] - 1) * 3) + 1], \
 
872
  vect[2] =   coord[((connect_tmp[j-1] - 1) * 3) + 2]  \
 
873
            - coord[((connect_tmp[i-1] - 1) * 3) + 2] )
 
874
 
 
875
#define ECS_LOC_PERMUTE(i, j) ( \
 
876
  isom_tmp = connect[i-1],             \
 
877
  connect_tmp[i-1] = connect_tmp[j-1], \
 
878
  connect_tmp[j-1] = isom_tmp         )
 
879
 
 
880
 
 
881
  for (isom = 0; isom < 8; isom++)
 
882
    connect_tmp[isom] = connect[isom];
 
883
 
 
884
  /* Vérification et correction éventuelle de l'orientation des bases */
 
885
 
 
886
  ret_base_1 = _orient_quad(coord,
 
887
                            connect_tmp,
 
888
                            correc);
 
889
 
 
890
  if ((correc == false && ret_base_1 != 0) || ret_base_1 < 0)
 
891
    return - 1;
 
892
 
 
893
  else if (ret_base_1 > 0) {
 
894
    ret_base_2 = _orient_quad(coord,
 
895
                              connect_tmp + 4,
 
896
                              correc);
 
897
    if (ret_base_2 != ret_base_1)
 
898
      return - 1;
 
899
    else
 
900
      retval = 1;
 
901
  }
 
902
 
 
903
  /* Boucle sur les renumérotations possibles */
 
904
 
 
905
  do {
 
906
 
 
907
    passage += 1;
 
908
 
 
909
    /* Initialisation */
 
910
 
 
911
    switch(passage) {
 
912
 
 
913
    case 0:
 
914
      break;
 
915
 
 
916
    case 1:
 
917
      if (correc == false)
 
918
        return -1;
 
919
      else
 
920
        retval = 1;
 
921
      ECS_LOC_PERMUTE(2, 4);
 
922
      ECS_LOC_PERMUTE(6, 8);
 
923
      break;
 
924
 
 
925
    default:
 
926
      return -1;
 
927
      break;
 
928
 
 
929
    }
 
930
 
 
931
    ECS_LOC_INIT_VECT(vect2, 1, 2);
 
932
    ECS_LOC_INIT_VECT(vect3, 1, 4);
 
933
 
 
934
    ECS_LOC_PRODUIT_VECTORIEL(vect1, vect2, vect3);
 
935
 
 
936
    for (idim = 0; idim < 3; idim++)
 
937
      vect2[idim] = (  coord[((connect_tmp[5-1] - 1) * 3) + idim]
 
938
                     + coord[((connect_tmp[6-1] - 1) * 3) + idim]
 
939
                     + coord[((connect_tmp[7-1] - 1) * 3) + idim]
 
940
                     + coord[((connect_tmp[8-1] - 1) * 3) + idim]
 
941
                     - coord[((connect_tmp[1-1] - 1) * 3) + idim]
 
942
                     - coord[((connect_tmp[2-1] - 1) * 3) + idim]
 
943
                     - coord[((connect_tmp[3-1] - 1) * 3) + idim]
 
944
                     - coord[((connect_tmp[4-1] - 1) * 3) + idim]) * 0.25;
 
945
 
 
946
    pscal = ECS_LOC_PRODUIT_SCALAIRE(vect1, vect2);
 
947
 
 
948
  } while (pscal < 0.0);
 
949
 
 
950
  if (retval > 0) {
 
951
    for (isom = 0; isom < 8; isom++)
 
952
      connect[isom] = connect_tmp[isom];
 
953
  }
 
954
 
 
955
  /* Vérification et correction éventuelle de l'orientation des cotés */
 
956
 
 
957
  connect_tmp[1-1] = connect[2-1];
 
958
  connect_tmp[2-1] = connect[3-1];
 
959
  connect_tmp[3-1] = connect[7-1];
 
960
  connect_tmp[4-1] = connect[6-1];
 
961
 
 
962
  ret_base_1 = _orient_quad(coord,
 
963
                            connect_tmp,
 
964
                            correc);
 
965
 
 
966
  if (ret_base_1 != 0)
 
967
    return - 1;
 
968
 
 
969
  connect_tmp[1-1] = connect[1-1];
 
970
  connect_tmp[2-1] = connect[2-1];
 
971
  connect_tmp[3-1] = connect[6-1];
 
972
  connect_tmp[4-1] = connect[5-1];
 
973
 
 
974
  ret_base_1 = _orient_quad(coord,
 
975
                            connect_tmp,
 
976
                            correc);
 
977
 
 
978
  if (ret_base_1 != 0)
 
979
    return - 1;
 
980
 
 
981
  return retval;
 
982
 
 
983
#undef ECS_LOC_INIT_VECT
 
984
#undef ECS_LOC_PERMUTE
 
985
}
 
986
 
 
987
/*----------------------------------------------------------------------------
 
988
 * Compute contribution of a polygonal face to a cell's volume,
 
989
 *  using Stoke's theorem
 
990
 *
 
991
 *                          Pi+1
 
992
 *              *---------*                   B  : barycentre of the polygon
 
993
 *             / .       . \
 
994
 *            /   .     .   \                 Pi : vertices of the polygon
 
995
 *           /     .   .     \
 
996
 *          /       . .  Ti   \               Ti : triangle
 
997
 *         *.........B.........* Pi
 
998
 *     Pn-1 \       . .       /
 
999
 *           \     .   .     /
 
1000
 *            \   .     .   /
 
1001
 *             \ .   T0  . /
 
1002
 *              *---------*
 
1003
 *            P0
 
1004
 *----------------------------------------------------------------------------*/
 
1005
 
 
1006
static double
 
1007
_compute_face_vol_contrib(ecs_int_t          n_face_vertices,
 
1008
                          const ecs_coord_t  vtx_coord[],
 
1009
                          const ecs_int_t    face_vtx_lst[])
 
1010
{
 
1011
  ecs_int_t   i, tri_id, vtx_id;
 
1012
  ecs_coord_t  tri_center[3], tri_norm[3];
 
1013
  ecs_coord_t  vect1[3], vect2[3];
 
1014
 
 
1015
  ecs_coord_t  face_barycentre[3] = {0., 0., 0.};
 
1016
 
 
1017
  double inv3 = 1./3.;
 
1018
 
 
1019
  double vol_contrib = 0.;
 
1020
 
 
1021
  /* Compute barycentre (B) coordinates for the polygon (P) */
 
1022
 
 
1023
  for (vtx_id = 0; vtx_id < n_face_vertices; vtx_id++) {
 
1024
    size_t coord_id = face_vtx_lst[vtx_id] - 1;
 
1025
    for (i = 0; i < 3; i++)
 
1026
      face_barycentre[i] += vtx_coord[coord_id*3 + i];
 
1027
  }
 
1028
 
 
1029
  for (i = 0; i < 3; i++)
 
1030
    face_barycentre[i] /= n_face_vertices;
 
1031
 
 
1032
  /* Loop on triangles of the face */
 
1033
 
 
1034
  for (tri_id = 0; tri_id < n_face_vertices; tri_id++) {
 
1035
 
 
1036
    size_t coord_id_1 = face_vtx_lst[tri_id % n_face_vertices] - 1;
 
1037
    size_t coord_id_2 = face_vtx_lst[(tri_id + 1)% n_face_vertices] - 1;
 
1038
 
 
1039
    for (i = 0; i < 3; i++) {
 
1040
      vect1[i] = vtx_coord[coord_id_1*3 + i] - face_barycentre[i];
 
1041
      vect2[i] = vtx_coord[coord_id_2*3 + i] - face_barycentre[i];
 
1042
    }
 
1043
 
 
1044
    ECS_LOC_PRODUIT_VECTORIEL(tri_norm, vect1, vect2);
 
1045
 
 
1046
    for (i = 0; i < 3; i++)
 
1047
      tri_norm[i] *= 0.5;
 
1048
 
 
1049
    /* Computation of the center of the triangle Ti */
 
1050
 
 
1051
    for (i = 0; i < 3; i++)
 
1052
      tri_center[i] = (  face_barycentre[i]
 
1053
                       + vtx_coord[coord_id_1*3 + i]
 
1054
                       + vtx_coord[coord_id_2*3 + i]) * inv3;
 
1055
 
 
1056
    /* Contribution to cell volume using Stoke's formula */
 
1057
 
 
1058
    for (i = 0; i < 3; i++)
 
1059
      vol_contrib += (tri_norm[i] * tri_center[i]);
 
1060
 
 
1061
  } /* End of loop on triangles of the face */
 
1062
 
 
1063
  return vol_contrib;
 
1064
}
 
1065
 
 
1066
/*----------------------------------------------------------------------------
 
1067
 *  Correction si nécessaire de l'orientation d'un polyedre en connectivité
 
1068
 *   nodale ; renvoie -1 si l'on ne parvient pas à corriger l'orientation
 
1069
 *   ou que l'on demande une simple vérification (i.e. correc = false),
 
1070
 *   0 si l'orientation initiale est bonne, et 1 en cas de correction de
 
1071
 *   l'orientation par une permutation de la connectivité locale.
 
1072
 *
 
1073
 *  On suppose que toutes les faces polygonales sont bien définies, mais
 
1074
 *   que certaines faces peuvent être définies avec une normale intérieure
 
1075
 *   à la cellule et non pas extérieure. On suppose que la non-convexité
 
1076
 *   du polyèdre est limitée.
 
1077
 *----------------------------------------------------------------------------*/
 
1078
 
 
1079
static ecs_int_t
 
1080
_orient_polyhedron(const ecs_coord_t   coord[],
 
1081
                   ecs_int_t           connect[],
 
1082
                   ecs_int_t           size,
 
1083
                   bool                correc,
 
1084
                   ecs_tab_int_t      *face_index,
 
1085
                   ecs_tab_int_t      *face_marker,
 
1086
                   ecs_tab_int_t      *edges)
 
1087
{
 
1088
  size_t      i, j, face_id, edge_id;
 
1089
  ecs_int_t   ind_premier, ind_dernier;
 
1090
 
 
1091
  double      cell_vol = 0.;
 
1092
  size_t      n_unmarked_faces = 0;
 
1093
  size_t      n_faces = 0;
 
1094
  size_t      n_edges = 0;
 
1095
  ecs_int_t   retval = 0;
 
1096
 
 
1097
  /* Ensure working arrays are large enough */
 
1098
 
 
1099
  /* Mark faces */
 
1100
 
 
1101
  {
 
1102
    ecs_int_t   premier_som  = -1;
 
1103
 
 
1104
    for (i = 0; i < (size_t)size; i++) {
 
1105
 
 
1106
      if (face_index->nbr < n_faces + 1) {
 
1107
        face_index->nbr = ECS_MAX(n_faces + 1, face_index->nbr*2);
 
1108
        ECS_REALLOC(face_index->val, face_index->nbr, ecs_int_t);
 
1109
      }
 
1110
 
 
1111
      if (premier_som == -1) {
 
1112
        face_index->val[n_faces] = i;
 
1113
        premier_som = connect[i];
 
1114
        ind_premier = i;
 
1115
      }
 
1116
      else if (connect[i] == premier_som) {
 
1117
        n_faces += 1;
 
1118
        premier_som = -1;
 
1119
        ind_dernier = i;
 
1120
      }
 
1121
    }
 
1122
 
 
1123
    if (face_index->nbr < n_faces + 1) {
 
1124
      face_index->nbr = ECS_MAX(n_faces + 1, face_index->nbr*2);
 
1125
      ECS_REALLOC(face_index->val, face_index->nbr, ecs_int_t);
 
1126
    }
 
1127
 
 
1128
    face_index->val[n_faces] = size;
 
1129
 
 
1130
    /* face_marker: 0 initially, 1 if oriented, -1 if inverted */
 
1131
 
 
1132
    if (face_marker->nbr < n_faces) {
 
1133
      face_marker->nbr = ECS_MAX(n_faces, face_marker->nbr*2);
 
1134
      ECS_REALLOC(face_marker->val, face_marker->nbr, ecs_int_t);
 
1135
    }
 
1136
 
 
1137
    for (face_id = 0; face_id < n_faces; face_id++)
 
1138
      face_marker->val[face_id] = 0;
 
1139
  }
 
1140
 
 
1141
  if (n_faces == 0)
 
1142
    return 0;
 
1143
 
 
1144
  /* Extract edges and build edge-face connectivity */
 
1145
  /*------------------------------------------------*/
 
1146
 
 
1147
  for (face_id = 0; face_id < n_faces; face_id++) {
 
1148
 
 
1149
    size_t start_id = face_index->val[face_id];
 
1150
    size_t end_id = face_index->val[face_id + 1] - 1;
 
1151
 
 
1152
    /* Loop on unassociated edges */
 
1153
 
 
1154
    for (i = start_id; i < end_id; i++) {
 
1155
 
 
1156
      ecs_int_t v_id_1 = connect[i], v_id_2 = connect[i + 1];
 
1157
      ecs_int_t is_match = 0;
 
1158
 
 
1159
      /* Compare with other edges */
 
1160
 
 
1161
      for (edge_id = 0; edge_id < n_edges; edge_id++) {
 
1162
 
 
1163
        ecs_int_t v_id_1_cmp = edges->val[edge_id*4];
 
1164
        ecs_int_t v_id_2_cmp = edges->val[edge_id*4 + 1];
 
1165
 
 
1166
        if ((v_id_1 == v_id_2_cmp) && (v_id_2 == v_id_1_cmp))
 
1167
          is_match = 1;
 
1168
 
 
1169
        else if ((v_id_1 == v_id_1_cmp) && (v_id_2 == v_id_2_cmp))
 
1170
          is_match = -1;
 
1171
 
 
1172
        /* Each edge should be shared by exactly 2 faces */
 
1173
 
 
1174
        if (is_match != 0) {
 
1175
          if (edges->val[edge_id*4 + 3] == 0) {
 
1176
            edges->val[edge_id*4 + 3] = is_match * (face_id + 1);
 
1177
            break;
 
1178
          }
 
1179
          else
 
1180
            return -1;
 
1181
        }
 
1182
      }
 
1183
 
 
1184
      /* If edge is unmatched, add it */
 
1185
 
 
1186
      if (is_match == 0) {
 
1187
 
 
1188
        if (edges->nbr < (n_edges + 1)*4) {
 
1189
          edges->nbr = ECS_MAX(edges->nbr*2, (n_edges + 1)*4);
 
1190
          ECS_REALLOC(edges->val, edges->nbr, ecs_int_t);
 
1191
        }
 
1192
 
 
1193
        edges->val[n_edges*4] = v_id_1;
 
1194
        edges->val[n_edges*4 + 1] = v_id_2;
 
1195
        edges->val[n_edges*4 + 2] = face_id + 1;
 
1196
        edges->val[n_edges*4 + 3] = 0;
 
1197
 
 
1198
        n_edges += 1;
 
1199
      }
 
1200
 
 
1201
    }
 
1202
 
 
1203
  }
 
1204
 
 
1205
  /* Check if each edge is associated with 2 faces
 
1206
     (i.e., that cell is closed) */
 
1207
 
 
1208
  for (edge_id = 0; edge_id < n_edges; edge_id++) {
 
1209
    if (edges->val[edge_id*4 + 3] == 0)
 
1210
      return -1;
 
1211
  }
 
1212
 
 
1213
  /* Now check if face orientations are compatible */
 
1214
  /*-----------------------------------------------*/
 
1215
 
 
1216
  face_marker->val[0] = 1; /* First face defines reference */
 
1217
  n_unmarked_faces = n_faces - 1;
 
1218
 
 
1219
  while (n_unmarked_faces > 0) {
 
1220
 
 
1221
    for (edge_id = 0; edge_id < n_edges; edge_id++) {
 
1222
 
 
1223
      ecs_int_t face_num_2 = edges->val[edge_id*4 + 3];
 
1224
      ecs_int_t face_id_1 = edges->val[edge_id*4 + 2] - 1;
 
1225
      ecs_int_t face_id_2 = ECS_ABS(face_num_2) - 1;
 
1226
 
 
1227
      if (   face_marker->val[face_id_1] == 0
 
1228
          && face_marker->val[face_id_2] != 0) {
 
1229
        if (face_num_2 > 0)
 
1230
          face_marker->val[face_id_1] = face_marker->val[face_id_2];
 
1231
        else
 
1232
          face_marker->val[face_id_1] = - face_marker->val[face_id_2];
 
1233
        n_unmarked_faces -= 1;
 
1234
      }
 
1235
 
 
1236
      else if (   face_marker->val[face_id_1] != 0
 
1237
               && face_marker->val[face_id_2] == 0) {
 
1238
        if (face_num_2 > 0)
 
1239
          face_marker->val[face_id_2] = face_marker->val[face_id_1];
 
1240
        else
 
1241
          face_marker->val[face_id_2] = - face_marker->val[face_id_1];
 
1242
        n_unmarked_faces -= 1;
 
1243
      }
 
1244
    }
 
1245
 
 
1246
  }
 
1247
 
 
1248
  for (edge_id = 0; edge_id < n_edges; edge_id++) {
 
1249
 
 
1250
    ecs_int_t face_num_2 = edges->val[edge_id*4 + 3];
 
1251
    ecs_int_t face_id_1 = edges->val[edge_id*4 + 2] - 1;
 
1252
    ecs_int_t face_id_2 = ECS_ABS(face_num_2) - 1;
 
1253
 
 
1254
    ecs_int_t marker_product
 
1255
      = face_marker->val[face_id_1]*face_marker->val[face_id_2];
 
1256
 
 
1257
    if (   (face_num_2 < 0 && marker_product > 0)
 
1258
        || (face_num_2 > 0 && marker_product < 0))
 
1259
      return -1;
 
1260
 
 
1261
  }
 
1262
 
 
1263
  /* At this stage, topology is correct; check for inside-out cell */
 
1264
  /*---------------------------------------------------------------*/
 
1265
 
 
1266
  for (face_id = 0; face_id < n_faces; face_id++) {
 
1267
 
 
1268
    size_t start_id = face_index->val[face_id];
 
1269
    size_t end_id = face_index->val[face_id + 1] - 1;
 
1270
 
 
1271
    double vol_contrib
 
1272
      = _compute_face_vol_contrib(end_id - start_id,
 
1273
                                  coord,
 
1274
                                  connect + start_id);
 
1275
    cell_vol += vol_contrib * (double)(face_marker->val[face_id]);
 
1276
  }
 
1277
 
 
1278
  /* Invert orientation if cell is inside_out */
 
1279
 
 
1280
  if (cell_vol < 0.) {
 
1281
    for (face_id = 0; face_id < n_faces; face_id++)
 
1282
      face_marker->val[face_id] *= -1;
 
1283
  }
 
1284
 
 
1285
  /* Now correct connectivity if required */
 
1286
  /*--------------------------------------*/
 
1287
 
 
1288
  if (correc == true) {
 
1289
 
 
1290
    for (face_id = 0; face_id < n_faces; face_id++) {
 
1291
 
 
1292
      if (face_marker->val[face_id] == -1) {
 
1293
 
 
1294
        for (i = face_index->val[face_id] + 1,
 
1295
               j = face_index->val[face_id + 1] - 2;
 
1296
             i < j;
 
1297
             i++, j--) {
 
1298
          ecs_int_t connect_tmp = connect[i];
 
1299
          connect[i] = connect[j];
 
1300
          connect[j] = connect_tmp;
 
1301
        }
 
1302
 
 
1303
        retval = 1;
 
1304
 
 
1305
      }
 
1306
    }
 
1307
  }
 
1308
 
 
1309
  else {
 
1310
 
 
1311
    for (face_id = 0; face_id < n_faces; face_id++) {
 
1312
      if (face_marker->val[face_id] == -1)
 
1313
        retval = -1;
 
1314
    }
 
1315
  }
 
1316
 
 
1317
  return retval;
 
1318
}
 
1319
 
 
1320
/*============================================================================
 
1321
 *                             Fonctions publiques
 
1322
 *============================================================================*/
 
1323
 
 
1324
/*----------------------------------------------------------------------------
 
1325
 *  Fonction qui réalise le tri des types géométriques
 
1326
 *  La fonction affiche le nombre d'éléments par type géométrique
 
1327
 *----------------------------------------------------------------------------*/
 
1328
 
 
1329
ecs_tab_int_t
 
1330
ecs_table_def__trie_typ(ecs_table_t  *this_table_def,
 
1331
                        int           dim_elt)
 
1332
{
 
1333
  size_t       ielt;
 
1334
  size_t       nbr_elt;
 
1335
  size_t       nbr_som;
 
1336
 
 
1337
  ecs_tab_int_t   tab_typ_geo_ord;
 
1338
  ecs_tab_int_t   tab_typ_geo;
 
1339
  ecs_tab_int_t   vect_renum;
 
1340
 
 
1341
  ecs_elt_typ_t   typ_geo;
 
1342
 
 
1343
  const ecs_elt_typ_t  *typ_geo_base;
 
1344
 
 
1345
  const int lng_imp = ECS_LNG_AFF_STR - ECS_LOC_LNG_MAX_NOM_TYP;
 
1346
 
 
1347
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
1348
 
 
1349
  assert(this_table_def != NULL);
 
1350
 
 
1351
  vect_renum.nbr = 0   ;
 
1352
  vect_renum.val = NULL;
 
1353
 
 
1354
  nbr_elt = this_table_def->nbr;
 
1355
 
 
1356
  if (nbr_elt == 0)
 
1357
    return vect_renum;
 
1358
 
 
1359
  /* Détermination de base du type d'élément "classique" */
 
1360
 
 
1361
  assert(dim_elt >=2 && dim_elt <= 3);
 
1362
 
 
1363
  typ_geo_base = ecs_glob_typ_elt[dim_elt - 2];
 
1364
 
 
1365
  /* Si tous les éléments sont de même type, rien à faire */
 
1366
  /*------------------------------------------------------*/
 
1367
 
 
1368
  if (this_table_def->pos == NULL) {
 
1369
 
 
1370
    if (this_table_def->pas < 9)
 
1371
      typ_geo = typ_geo_base[this_table_def->pas];
 
1372
    else if (dim_elt == 2)
 
1373
      typ_geo = ECS_ELT_TYP_FAC_POLY;
 
1374
    else if (dim_elt == 3)
 
1375
      typ_geo = ECS_ELT_TYP_CEL_POLY;
 
1376
    else
 
1377
      typ_geo = ECS_ELT_TYP_NUL;
 
1378
 
 
1379
    printf("  %-*s%*.*s : %*lu\n",
 
1380
           lng_imp, _("Number of elements"),
 
1381
           ECS_LOC_LNG_MAX_NOM_TYP, ECS_LOC_LNG_MAX_NOM_TYP,
 
1382
           ecs_fic_elt_typ_liste_c[typ_geo].nom,
 
1383
           ECS_LNG_AFF_ENT, (unsigned long)nbr_elt);
 
1384
 
 
1385
  }
 
1386
 
 
1387
  /* Si tous les éléments ne sont pas de même type */
 
1388
  /*-----------------------------------------------*/
 
1389
 
 
1390
  else {
 
1391
 
 
1392
    /* Construction d'un tableau temporaire de type géométrique */
 
1393
 
 
1394
    tab_typ_geo.nbr = nbr_elt;
 
1395
    ECS_MALLOC(tab_typ_geo.val, tab_typ_geo.nbr, ecs_int_t);
 
1396
 
 
1397
    for (ielt = 0; ielt < nbr_elt; ielt++) {
 
1398
 
 
1399
      nbr_som =   this_table_def->pos[ielt + 1]
 
1400
                - this_table_def->pos[ielt];
 
1401
 
 
1402
      if (nbr_som < 9)
 
1403
        tab_typ_geo.val[ielt] = typ_geo_base[nbr_som];
 
1404
 
 
1405
      else if (dim_elt == 2)
 
1406
        tab_typ_geo.val[ielt] = ECS_ELT_TYP_FAC_POLY;
 
1407
 
 
1408
      else if (dim_elt == 3)
 
1409
        tab_typ_geo.val[ielt] = ECS_ELT_TYP_CEL_POLY;
 
1410
 
 
1411
      else
 
1412
        tab_typ_geo.val[ielt] = ECS_ELT_TYP_NUL;
 
1413
 
 
1414
    }
 
1415
 
 
1416
    /* On regarde si les types géométriques ne sont pas deja ordonnés */
 
1417
 
 
1418
    ielt = 1;
 
1419
    while (ielt < nbr_elt                                     &&
 
1420
           tab_typ_geo.val[ielt] >= tab_typ_geo.val[ielt - 1]   )
 
1421
      ielt++;
 
1422
 
 
1423
    if (ielt < nbr_elt) {
 
1424
 
 
1425
      /* Les types géométriques ne sont pas ordonnés */
 
1426
      /* On ordonne les types géométriques */
 
1427
 
 
1428
      vect_renum.nbr = nbr_elt;
 
1429
      ECS_MALLOC(vect_renum.val, nbr_elt, ecs_int_t);
 
1430
 
 
1431
 
 
1432
      tab_typ_geo_ord = ecs_tab_int__trie_et_renvoie(tab_typ_geo,
 
1433
                                                     vect_renum);
 
1434
 
 
1435
      /*
 
1436
        `vect_renum' prend pour indice les indices nouveaux, et ses valeurs
 
1437
        contiennent les indices anciens correspondants
 
1438
        On inverse le contenu de `vect_renum' :
 
1439
        à chaque indice ancien, `vect_renum' donne la valeur du nouvel indice
 
1440
      */
 
1441
 
 
1442
      ecs_tab_int__inverse(&vect_renum);
 
1443
 
 
1444
      ECS_FREE(tab_typ_geo.val);
 
1445
 
 
1446
      tab_typ_geo.val = tab_typ_geo_ord.val;
 
1447
 
 
1448
      tab_typ_geo_ord.nbr = 0;
 
1449
      tab_typ_geo_ord.val = NULL;
 
1450
 
 
1451
    }
 
1452
 
 
1453
    /* Message d'information sur la composition des éléments du maillage */
 
1454
 
 
1455
    {
 
1456
      ecs_int_t val_typ_ref;
 
1457
      size_t    nbr_val_typ_geo;
 
1458
 
 
1459
      size_t    cpt_ielt = 0;
 
1460
 
 
1461
      while (cpt_ielt < nbr_elt) {
 
1462
 
 
1463
        val_typ_ref = tab_typ_geo.val[cpt_ielt];
 
1464
 
 
1465
        /* On compte le nombre d'éléments ayant le même type géométrique */
 
1466
 
 
1467
        nbr_val_typ_geo = 0;
 
1468
 
 
1469
        for (ielt = cpt_ielt;
 
1470
             ielt < nbr_elt && tab_typ_geo.val[ielt] == val_typ_ref; ielt++)
 
1471
          nbr_val_typ_geo++;
 
1472
 
 
1473
        printf("  %-*s%*.*s : %*lu\n",
 
1474
               lng_imp, _("Number of elements"),
 
1475
               ECS_LOC_LNG_MAX_NOM_TYP, ECS_LOC_LNG_MAX_NOM_TYP,
 
1476
               ecs_fic_elt_typ_liste_c[val_typ_ref].nom,
 
1477
               ECS_LNG_AFF_ENT, (unsigned long)nbr_val_typ_geo);
 
1478
 
 
1479
        cpt_ielt += nbr_val_typ_geo;
 
1480
 
 
1481
      }
 
1482
    }
 
1483
 
 
1484
    /* Le tableau de type géométrique n'est plus nécessaire */
 
1485
 
 
1486
    tab_typ_geo.nbr = 0;
 
1487
    ECS_FREE(tab_typ_geo.val);
 
1488
 
 
1489
  }
 
1490
 
 
1491
  /* Renvoi du vecteur de renumérotation */
 
1492
  /*-------------------------------------*/
 
1493
 
 
1494
  return vect_renum;
 
1495
}
 
1496
 
 
1497
/*----------------------------------------------------------------------------
 
1498
 *  Fonction qui construit
 
1499
 *   les définitions des faces par décomposition des tables des cellules
 
1500
 *----------------------------------------------------------------------------*/
 
1501
 
 
1502
void
 
1503
ecs_table_def__decompose_cel(ecs_table_t  **table_def_fac,
 
1504
                             ecs_table_t   *table_def_cel)
 
1505
{
 
1506
  size_t      nbr_cel;
 
1507
  size_t      nbr_def;
 
1508
  size_t      nbr_fac;
 
1509
  size_t      nbr_fac_old;
 
1510
  size_t      nbr_val_cel;
 
1511
  size_t      nbr_val_fac;
 
1512
  size_t      nbr_val_fac_old;
 
1513
  size_t      ind_pos_cel;
 
1514
  size_t      ind_pos_loc;
 
1515
  size_t      ind_pos_sui;
 
1516
  size_t      nbr_pos_loc;
 
1517
  ecs_int_t   num_def;
 
1518
  ecs_int_t   marqueur_fin;
 
1519
 
 
1520
  size_t      isom;
 
1521
  size_t      icel;
 
1522
  int         idef;
 
1523
  size_t      cpt_fac;
 
1524
  int         ifac;
 
1525
 
 
1526
  ecs_int_t   typ_geo_cel;        /* Type géométrique élément en cours */
 
1527
 
 
1528
  ecs_int_t typ_geo_base[9] = {ECS_ELT_TYP_NUL,
 
1529
                               ECS_ELT_TYP_NUL,
 
1530
                               ECS_ELT_TYP_NUL,
 
1531
                               ECS_ELT_TYP_NUL,
 
1532
                               ECS_ELT_TYP_CEL_TETRA,
 
1533
                               ECS_ELT_TYP_CEL_PYRAM,
 
1534
                               ECS_ELT_TYP_CEL_PRISM,
 
1535
                               ECS_ELT_TYP_NUL,
 
1536
                               ECS_ELT_TYP_CEL_HEXA};
 
1537
 
 
1538
  ecs_size_t   *def_cel_fac_pos = NULL;
 
1539
  ecs_int_t    *def_cel_fac_val = NULL;
 
1540
 
 
1541
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
1542
 
 
1543
  /*=================*/
 
1544
  /* Initialisations */
 
1545
  /*=================*/
 
1546
 
 
1547
  nbr_cel  = table_def_cel->nbr;
 
1548
 
 
1549
  ecs_table__regle_en_pos(table_def_cel);
 
1550
 
 
1551
  /* Construction, pour les cellules, des tables principaux */
 
1552
  /*--------------------------------------------------------*/
 
1553
 
 
1554
  /* Boucle de comptage pour l'allocation des sous-éléments */
 
1555
  /*--------------------------------------------------------*/
 
1556
 
 
1557
  if (*table_def_fac != NULL) {
 
1558
    nbr_fac_old = (*table_def_fac)->nbr;
 
1559
    nbr_val_fac_old = ecs_table__ret_val_nbr(*table_def_fac);
 
1560
  }
 
1561
  else {
 
1562
    nbr_fac_old = 0;
 
1563
    nbr_val_fac_old = 0;
 
1564
  }
 
1565
 
 
1566
  nbr_fac     = 0;
 
1567
  nbr_val_fac = 0;
 
1568
  nbr_def     = 0;
 
1569
 
 
1570
  for (icel = 0; icel < nbr_cel; icel++ ) {
 
1571
 
 
1572
    ind_pos_cel = table_def_cel->pos[icel] - 1;
 
1573
 
 
1574
    nbr_val_cel = table_def_cel->pos[icel + 1] - 1 - ind_pos_cel;
 
1575
 
 
1576
    /* Traitement des cellules "classiques" */
 
1577
    /*--------------------------------------*/
 
1578
 
 
1579
    if (nbr_val_cel < 9) {
 
1580
 
 
1581
      typ_geo_cel = typ_geo_base[nbr_val_cel];
 
1582
 
 
1583
      /* Boucle sur les sous-éléments définissant la cellulle */
 
1584
 
 
1585
      for (ifac = 0;
 
1586
           ifac < ecs_fic_elt_typ_liste_c[typ_geo_cel].nbr_sous_elt;
 
1587
           ifac++ ) {
 
1588
 
 
1589
        const ecs_sous_elt_t  * sous_elt
 
1590
          = &(ecs_fic_elt_typ_liste_c[typ_geo_cel].sous_elt[ifac]);
 
1591
 
 
1592
        nbr_fac++;
 
1593
 
 
1594
        for (idef = 0;
 
1595
             idef < (ecs_fic_elt_typ_liste_c[sous_elt->elt_typ]).nbr_som;
 
1596
             idef++);
 
1597
 
 
1598
        nbr_val_fac += idef;
 
1599
 
 
1600
      }
 
1601
 
 
1602
    }
 
1603
 
 
1604
    /* Traitement des éléments de type "polyèdre" */
 
1605
    /*--------------------------------------------*/
 
1606
 
 
1607
    else {
 
1608
 
 
1609
      ind_pos_sui = table_def_cel->pos[icel + 1] - 1;
 
1610
      nbr_pos_loc = ind_pos_sui - ind_pos_cel;
 
1611
 
 
1612
      /* Convention : définition nodale cellule->sommets avec numéros de
 
1613
         premiers sommets répétés en fin de liste pour marquer la fin
 
1614
         de chaque face */
 
1615
 
 
1616
      marqueur_fin = -1;
 
1617
 
 
1618
      for (isom = ind_pos_cel; isom < ind_pos_sui; isom++) {
 
1619
 
 
1620
        if (table_def_cel->val[isom] != marqueur_fin) {
 
1621
          nbr_val_fac += 1;
 
1622
          if (marqueur_fin == -1)
 
1623
            marqueur_fin = table_def_cel->val[isom];
 
1624
        }
 
1625
        else {
 
1626
          marqueur_fin = -1;
 
1627
          nbr_fac += 1;
 
1628
        }
 
1629
 
 
1630
      }
 
1631
 
 
1632
    }
 
1633
 
 
1634
  } /* Fin de la boucle de comptage sur les cellules */
 
1635
 
 
1636
  /* Allocation et initialisation pour les faces  */
 
1637
  /*  des tableaux associés aux définitions       */
 
1638
  /*----------------------------------------------*/
 
1639
 
 
1640
  nbr_fac += nbr_fac_old;
 
1641
  nbr_val_fac += nbr_val_fac_old;
 
1642
 
 
1643
  if (*table_def_fac != NULL) {
 
1644
    ecs_table__regle_en_pos(*table_def_fac);
 
1645
    (*table_def_fac)->nbr = nbr_fac;
 
1646
    ECS_REALLOC((*table_def_fac)->pos, nbr_fac + 1, ecs_size_t);
 
1647
    ECS_REALLOC((*table_def_fac)->val, nbr_val_fac, ecs_int_t);
 
1648
  }
 
1649
  else {
 
1650
    *table_def_fac = ecs_table__alloue(nbr_fac,
 
1651
                                       nbr_val_fac);
 
1652
    (*table_def_fac)->pos[0] = 1;
 
1653
  }
 
1654
 
 
1655
  ECS_MALLOC(def_cel_fac_pos, nbr_cel + 1, ecs_size_t);
 
1656
  ECS_MALLOC(def_cel_fac_val, nbr_fac - nbr_fac_old, ecs_int_t);
 
1657
 
 
1658
  def_cel_fac_pos[0] = 1;
 
1659
 
 
1660
  /*=======================================*/
 
1661
  /* Boucle sur les cellules à transformer */
 
1662
  /*=======================================*/
 
1663
 
 
1664
  cpt_fac = nbr_fac_old;
 
1665
  nbr_def = nbr_val_fac_old;
 
1666
 
 
1667
  for (icel = 0; icel < nbr_cel; icel++ ) {
 
1668
 
 
1669
    ind_pos_cel = table_def_cel->pos[icel] - 1;
 
1670
 
 
1671
    nbr_val_cel = table_def_cel->pos[icel + 1] - 1 - ind_pos_cel;
 
1672
 
 
1673
    /*--------------------------------------*/
 
1674
    /* Traitement des éléments "classiques" */
 
1675
    /*--------------------------------------*/
 
1676
 
 
1677
    if (nbr_val_cel < 9) {
 
1678
 
 
1679
      typ_geo_cel = typ_geo_base[nbr_val_cel];
 
1680
 
 
1681
      /* Boucle sur les faces définissant la cellulle */
 
1682
      /*==============================================*/
 
1683
 
 
1684
      for (ifac = 0;
 
1685
           ifac < ecs_fic_elt_typ_liste_c[typ_geo_cel].nbr_sous_elt;
 
1686
           ifac++ ) {
 
1687
 
 
1688
        const ecs_sous_elt_t  * sous_elt
 
1689
          = &(ecs_fic_elt_typ_liste_c[typ_geo_cel].sous_elt[ifac]);
 
1690
 
 
1691
        /* Boucle sur les sommets définissant la face */
 
1692
        /*--------------------------------------------*/
 
1693
 
 
1694
        for (idef = 0;
 
1695
             idef < (ecs_fic_elt_typ_liste_c[sous_elt->elt_typ]).nbr_som;
 
1696
             idef++) {
 
1697
 
 
1698
          /* Définition de la face en fonction des sommets */
 
1699
 
 
1700
          num_def = sous_elt->som[idef];
 
1701
 
 
1702
          (*table_def_fac)->val[nbr_def++]
 
1703
            = table_def_cel->val[ind_pos_cel + num_def - 1];
 
1704
 
 
1705
        }
 
1706
 
 
1707
        /* Position de la face dans sa définition en fonction des sommets */
 
1708
        /*----------------------------------------------------------------*/
 
1709
 
 
1710
        (*table_def_fac)->pos[cpt_fac + 1]
 
1711
          = (*table_def_fac)->pos[cpt_fac] + idef;
 
1712
 
 
1713
        /* Détermination de la cellule en fonction des faces */
 
1714
        /*---------------------------------------------------*/
 
1715
 
 
1716
        def_cel_fac_val[cpt_fac - nbr_fac_old] = cpt_fac + 1;
 
1717
 
 
1718
        cpt_fac++;
 
1719
 
 
1720
      } /* Fin de la boucle sur les faces d'une cellule */
 
1721
 
 
1722
    }
 
1723
 
 
1724
 
 
1725
    /*--------------------------------------------*/
 
1726
    /* Traitement des éléments de type "polyèdre" */
 
1727
    /*--------------------------------------------*/
 
1728
 
 
1729
    else {
 
1730
 
 
1731
      /* Boucle sur les faces définissant le polyèdre */
 
1732
      /*==============================================*/
 
1733
 
 
1734
      ifac = 0;
 
1735
      marqueur_fin = -1;
 
1736
 
 
1737
      nbr_pos_loc = table_def_cel->pos[icel + 1] - 1 - ind_pos_cel;
 
1738
 
 
1739
      for (ind_pos_loc = 0; ind_pos_loc < nbr_pos_loc; ind_pos_loc++) {
 
1740
 
 
1741
        /* Définition de la face en fonction des sommets */
 
1742
 
 
1743
        if (table_def_cel->val[ind_pos_cel + ind_pos_loc] != marqueur_fin) {
 
1744
 
 
1745
          (*table_def_fac)->val[nbr_def++]
 
1746
            = table_def_cel->val[ind_pos_cel + ind_pos_loc];
 
1747
 
 
1748
          if (marqueur_fin == -1)
 
1749
            marqueur_fin = table_def_cel->val[ind_pos_cel + ind_pos_loc];
 
1750
 
 
1751
        }
 
1752
 
 
1753
        /* Position de la face dans sa définition en fonction des sommets */
 
1754
 
 
1755
        else {
 
1756
 
 
1757
          (*table_def_fac)->pos[cpt_fac + 1] = nbr_def + 1;
 
1758
 
 
1759
          marqueur_fin = -1;
 
1760
 
 
1761
          def_cel_fac_val[cpt_fac - nbr_fac_old] = cpt_fac + 1;
 
1762
 
 
1763
          /* Incrémentation du nombre de faces */
 
1764
 
 
1765
          ifac++;
 
1766
          cpt_fac++;
 
1767
 
 
1768
        }
 
1769
 
 
1770
      } /* Fin de la boucle sur les faces du polyèdre */
 
1771
 
 
1772
    }
 
1773
 
 
1774
    /* A ce point, on a : ifac
 
1775
       = ecs_fic_elt_typ_liste_c[table_typ_geo_cel->val[icel]].nbr_sous_elt
 
1776
       pour des éléments classiques, et ifac est égal au nombre de faces pour
 
1777
       des éléments polyédriques. */
 
1778
 
 
1779
    def_cel_fac_pos[icel + 1] = def_cel_fac_pos[icel] + ifac;
 
1780
 
 
1781
  } /* Fin de la boucle sur les éléments */
 
1782
 
 
1783
  /* Mise à jour de la table */
 
1784
  /*-------------------------*/
 
1785
 
 
1786
  ECS_FREE(table_def_cel->pos);
 
1787
  ECS_FREE(table_def_cel->val);
 
1788
 
 
1789
  table_def_cel->pos = def_cel_fac_pos;
 
1790
  table_def_cel->val = def_cel_fac_val;
 
1791
 
 
1792
  /* ecs_table__pos_en_regle(*table_def_fac); */
 
1793
  ecs_table__pos_en_regle(table_def_cel);
 
1794
}
 
1795
 
 
1796
/*----------------------------------------------------------------------------
 
1797
 *  Fonction qui realise la fusion des definitions des elements
 
1798
 *----------------------------------------------------------------------------*/
 
1799
 
 
1800
ecs_tab_int_t
 
1801
ecs_table_def__fusionne(ecs_table_t    *table_def,
 
1802
                        size_t         *nbr_elt_cpct,
 
1803
                        ecs_tab_int_t  *signe_elt)
 
1804
{
 
1805
  size_t           cpt_sup_fin;
 
1806
  size_t           ind_cmp;
 
1807
  size_t           ind_inf;
 
1808
  size_t           ind_loc_sup;
 
1809
  size_t           ind_loc_cmp;
 
1810
  size_t           ind_pos;
 
1811
  size_t           ind_pos_loc;
 
1812
  size_t           ind_sup;
 
1813
  size_t           nbr_sup_ini;
 
1814
  size_t           nbr_inf;
 
1815
  ecs_int_t        num_inf;
 
1816
  ecs_int_t        num_inf_loc;
 
1817
  ecs_int_t        num_inf_min;
 
1818
  ecs_int_t        num_inf_min_cmp;
 
1819
  size_t           pos_cmp;
 
1820
  size_t           pos_cpt;
 
1821
  size_t           pos_sup;
 
1822
  int              sgn;
 
1823
 
 
1824
  size_t           ind_pos_sup[3];
 
1825
  size_t           ind_pos_cmp[3];
 
1826
 
 
1827
  ecs_tab_int_t    cpt_ref_inf;
 
1828
 
 
1829
  ecs_size_t      *pos_recherche = NULL;
 
1830
  ecs_int_t       *val_recherche = NULL;
 
1831
 
 
1832
  ecs_tab_int_t    tab_transf;    /* Tableau de transformation */
 
1833
 
 
1834
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
1835
 
 
1836
  ecs_table__regle_en_pos(table_def);
 
1837
 
 
1838
  /* Fusion des definitions des elements sur la liste initiale  */
 
1839
  /*------------------------------------------------------------*/
 
1840
 
 
1841
  /* Initialisations avec précautions pour cas vide */
 
1842
 
 
1843
  tab_transf.nbr = 0;
 
1844
  tab_transf.val = NULL;
 
1845
 
 
1846
  if (table_def == NULL)
 
1847
    return tab_transf;
 
1848
 
 
1849
  if (table_def == NULL)
 
1850
    return tab_transf;
 
1851
 
 
1852
  nbr_sup_ini = table_def->nbr;
 
1853
  cpt_sup_fin = 0;
 
1854
 
 
1855
  if (nbr_sup_ini < 1)
 
1856
    return tab_transf;
 
1857
 
 
1858
  if (signe_elt != NULL) {
 
1859
    signe_elt->nbr = nbr_sup_ini;
 
1860
    ECS_MALLOC(signe_elt->val, nbr_sup_ini, ecs_int_t);
 
1861
  }
 
1862
 
 
1863
  /* Comptage du nombre de sous-entités */
 
1864
 
 
1865
  nbr_inf = 0;
 
1866
 
 
1867
  for (ind_sup = 0;
 
1868
       ind_sup < table_def->pos[nbr_sup_ini] - 1;
 
1869
       ind_sup++) {
 
1870
    num_inf = table_def->val[ind_sup];
 
1871
    if ((size_t)(ECS_ABS(num_inf)) > nbr_inf)
 
1872
      nbr_inf = ECS_ABS(num_inf);
 
1873
  }
 
1874
 
 
1875
  /* Construction du tableau de recherche des sous-entités */
 
1876
  /*-------------------------------------------------------*/
 
1877
 
 
1878
  ECS_MALLOC(pos_recherche, nbr_inf + 1, ecs_size_t);
 
1879
  ECS_MALLOC(val_recherche, table_def->nbr, ecs_int_t);
 
1880
 
 
1881
  /*
 
1882
    Comptage pour chaque élément de l'entité inférieure du nombre de fois où il
 
1883
    apparaît comme élement d'indice minimal d'un élément de l'entité supérieure
 
1884
  */
 
1885
 
 
1886
  cpt_ref_inf = ecs_tab_int__cree_init(nbr_inf, 0);
 
1887
 
 
1888
  for (ind_sup = 0; ind_sup < table_def->nbr; ind_sup++) {
 
1889
 
 
1890
    ind_pos_loc = table_def->pos[ind_sup] - 1;
 
1891
 
 
1892
    num_inf_min = ECS_ABS(table_def->val[ind_pos_loc]);
 
1893
    while (++ind_pos_loc < table_def->pos[ind_sup + 1] -1) {
 
1894
      num_inf_loc = ECS_ABS(table_def->val[ind_pos_loc]);
 
1895
      if (num_inf_loc < num_inf_min)
 
1896
        num_inf_min = num_inf_loc;
 
1897
    }
 
1898
 
 
1899
    assert(num_inf_min > 0 && (size_t)num_inf_min <= nbr_inf);
 
1900
 
 
1901
    cpt_ref_inf.val[num_inf_min - 1] += 1;
 
1902
  }
 
1903
 
 
1904
 
 
1905
  /* Construction du vecteur */
 
1906
 
 
1907
  pos_recherche[0] = 1;
 
1908
 
 
1909
  for (ind_inf = 0; ind_inf < nbr_inf; ind_inf++) {
 
1910
 
 
1911
    pos_recherche[ind_inf + 1]
 
1912
      = pos_recherche[ind_inf] + cpt_ref_inf.val[ind_inf];
 
1913
 
 
1914
    cpt_ref_inf.val[ind_inf] = 0;
 
1915
 
 
1916
  }
 
1917
 
 
1918
 
 
1919
  for (ind_sup = 0; ind_sup < table_def->nbr; ind_sup++) {
 
1920
 
 
1921
    ind_pos_loc = table_def->pos[ind_sup] - 1;
 
1922
 
 
1923
    num_inf_min = ECS_ABS(table_def->val[ind_pos_loc]);
 
1924
    while (ind_pos_loc < table_def->pos[ind_sup + 1] -1) {
 
1925
      num_inf_loc = ECS_ABS(table_def->val[ind_pos_loc]);
 
1926
      ind_pos_loc++;
 
1927
      if (num_inf_loc < num_inf_min)
 
1928
        num_inf_min = num_inf_loc;
 
1929
    }
 
1930
 
 
1931
    ind_inf = num_inf_min - 1;
 
1932
 
 
1933
    ind_pos =   pos_recherche[ind_inf] - 1
 
1934
              + cpt_ref_inf.val[ind_inf];
 
1935
 
 
1936
    cpt_ref_inf.val[ind_inf] += 1;
 
1937
 
 
1938
    val_recherche[ind_pos] = ind_sup + 1;
 
1939
 
 
1940
  }
 
1941
 
 
1942
 
 
1943
  /* Libération du tableau auxiliaire */
 
1944
 
 
1945
  cpt_ref_inf.nbr = 0;
 
1946
  ECS_FREE(cpt_ref_inf.val);
 
1947
 
 
1948
  /* Allocation du tableau de transformation */
 
1949
 
 
1950
  tab_transf = ecs_tab_int__cree(nbr_sup_ini);
 
1951
 
 
1952
  for (ind_sup = 0; ind_sup < nbr_sup_ini; ind_sup++)
 
1953
    tab_transf.val[ind_sup] = ind_sup;
 
1954
 
 
1955
 
 
1956
  /* Boucle principale de recherche sur les éléments supérieurs */
 
1957
  /*------------------------------------------------------------*/
 
1958
 
 
1959
  /*
 
1960
    Le premier élément ne peut pas être fusionné avec un élément précédent,
 
1961
    la boucle commence donc au deuxième
 
1962
  */
 
1963
 
 
1964
  tab_transf.val[0] = 0;
 
1965
 
 
1966
  if (signe_elt != NULL)
 
1967
    signe_elt->val[0] = 1;
 
1968
 
 
1969
  cpt_sup_fin       = 1;
 
1970
 
 
1971
  for (ind_sup = 1; ind_sup < table_def->nbr; ind_sup++) {
 
1972
 
 
1973
    /* Recherche élement entité inférieure de plus petit numéro référencé */
 
1974
 
 
1975
    ind_pos_sup[0] = table_def->pos[ind_sup    ] - 1; /* début */
 
1976
    ind_pos_sup[1] = table_def->pos[ind_sup + 1] - 1; /* fin */
 
1977
    ind_pos_sup[2] = table_def->pos[ind_sup    ] - 1; /* plus petit */
 
1978
 
 
1979
    ind_pos_loc = ind_pos_sup[0];
 
1980
 
 
1981
    num_inf_min = ECS_ABS(table_def->val[ind_pos_loc]);
 
1982
    while (++ind_pos_loc < ind_pos_sup[1]) {
 
1983
      num_inf_loc = ECS_ABS(table_def->val[ind_pos_loc]);
 
1984
      if (num_inf_loc < num_inf_min) {
 
1985
        num_inf_min    = num_inf_loc;
 
1986
        ind_pos_sup[2] = ind_pos_loc;
 
1987
      }
 
1988
    }
 
1989
 
 
1990
    /*
 
1991
      On cherche des éléments de l'entité courante de plus petit numéro que
 
1992
      l'entité courante ayant même plus petit élément de l'entité inférieure
 
1993
      (recherche de candidats pour la fusion)
 
1994
    */
 
1995
 
 
1996
    ind_inf = num_inf_min - 1;
 
1997
    sgn     = 0;
 
1998
 
 
1999
    for (pos_cmp = pos_recherche[ind_inf]     - 1;
 
2000
         pos_cmp < pos_recherche[ind_inf + 1] - 1;
 
2001
         pos_cmp++) {
 
2002
 
 
2003
      ind_cmp = val_recherche[pos_cmp] - 1;
 
2004
 
 
2005
      /* Repérage point de départ pour comparaison */
 
2006
 
 
2007
      if (ind_cmp < ind_sup) {
 
2008
 
 
2009
        ind_pos_cmp[0] = table_def->pos[ind_cmp    ] - 1; /* début */
 
2010
        ind_pos_cmp[1] = table_def->pos[ind_cmp + 1] - 1; /* fin */
 
2011
        ind_pos_cmp[2] = table_def->pos[ind_cmp    ] - 1; /* plus petit */
 
2012
 
 
2013
        assert(ind_pos_cmp[1] > ind_pos_cmp[0]);
 
2014
 
 
2015
        ind_pos_cmp[1] = table_def->pos[ind_cmp + 1] - 1;  /* fin */
 
2016
 
 
2017
        ind_pos_loc = ind_pos_cmp[0];
 
2018
 
 
2019
        num_inf_min_cmp = ECS_ABS(table_def->val[ind_pos_loc]);
 
2020
        while ((++ind_pos_loc) < ind_pos_cmp[1]) {
 
2021
          num_inf_loc = ECS_ABS(table_def->val[ind_pos_loc]);
 
2022
          if (num_inf_loc < num_inf_min_cmp) {
 
2023
            num_inf_min_cmp = num_inf_loc;
 
2024
            ind_pos_cmp[2]  = ind_pos_loc;
 
2025
          }
 
2026
        }
 
2027
 
 
2028
        /* Comparaison des définitions */
 
2029
 
 
2030
        for (sgn = 1; sgn > -2; sgn -= 2) {
 
2031
 
 
2032
          ind_loc_sup = ind_pos_sup[2];
 
2033
          ind_loc_cmp = ind_pos_cmp[2];
 
2034
 
 
2035
          do {
 
2036
 
 
2037
            ind_loc_sup++;
 
2038
            if (ind_loc_sup == ind_pos_sup[1])
 
2039
              ind_loc_sup = ind_pos_sup[0];
 
2040
 
 
2041
            ind_loc_cmp += sgn;
 
2042
            if (ind_loc_cmp == ind_pos_cmp[1])
 
2043
              ind_loc_cmp = ind_pos_cmp[0];
 
2044
            else if (   ind_loc_cmp < ind_pos_cmp[0]
 
2045
                     || ind_loc_cmp > ind_pos_cmp[1])
 
2046
              ind_loc_cmp = ind_pos_cmp[1] - 1;
 
2047
 
 
2048
          } while (   (   ECS_ABS(table_def->val[ind_loc_sup])
 
2049
                       == ECS_ABS(table_def->val[ind_loc_cmp]))
 
2050
                   && ind_loc_sup != ind_pos_sup[2]
 
2051
                   && ind_loc_cmp != ind_pos_cmp[2]);
 
2052
 
 
2053
          if (   ind_loc_sup == ind_pos_sup[2]
 
2054
              && ind_loc_cmp == ind_pos_cmp[2])
 
2055
            break; /* Sortie boucle sur signe parcours (1, -1, -3) */
 
2056
 
 
2057
        }
 
2058
 
 
2059
        /*
 
2060
          Si sgn =  1, les entités sont confondues, de même sens;
 
2061
          Si sgn = -1, elles sont confondues, de sens inverse;
 
2062
          Sinon, elles ne sont pas confondues
 
2063
        */
 
2064
 
 
2065
        if (sgn == 1 || sgn == -1)
 
2066
          break; /* Sortie boucle sur pos_cmp pour recherche de candidats */
 
2067
 
 
2068
      } /* Fin de la comparaison référence/candidat (if ind_cmp < ind_sup) */
 
2069
 
 
2070
    } /* Fin boucle sur pos_cmp recherche de candidats */
 
2071
 
 
2072
 
 
2073
    /* Si on a trouvé une entité à fusionner */
 
2074
 
 
2075
    if (sgn == 1 || sgn == -1) {
 
2076
 
 
2077
      assert(pos_cmp < pos_recherche[ind_inf + 1] - 1);
 
2078
 
 
2079
      if (sgn == 1 && (ind_pos_cmp[1] - ind_pos_cmp[0] == 2)) {
 
2080
 
 
2081
        /*
 
2082
          Si l'on a deux entités inférieures par entité supérieure,
 
2083
          la permutation cyclique peut trouver une égalité quel
 
2084
          que soit le signe; on le corrige si nécessaire
 
2085
        */
 
2086
 
 
2087
        if (   ECS_ABS(table_def->val[ind_pos_sup[0]])
 
2088
            != ECS_ABS(table_def->val[ind_pos_cmp[0]]))
 
2089
          sgn = -1;
 
2090
 
 
2091
      }
 
2092
 
 
2093
      tab_transf.val[ind_sup] = tab_transf.val[ind_cmp];
 
2094
 
 
2095
      if (signe_elt != NULL)
 
2096
        signe_elt->val[ind_sup] = sgn;
 
2097
 
 
2098
    }
 
2099
    else {
 
2100
 
 
2101
      tab_transf.val[ind_sup] = cpt_sup_fin++;
 
2102
 
 
2103
      if (signe_elt != NULL)
 
2104
        signe_elt->val[ind_sup] = 1;
 
2105
 
 
2106
    }
 
2107
 
 
2108
 
 
2109
  } /* Fin boucle sur les éléments de l'entité supérieure (que l'on fusionne) */
 
2110
 
 
2111
  /* Libération du tableau de recherche */
 
2112
 
 
2113
  ECS_FREE(pos_recherche);
 
2114
  ECS_FREE(val_recherche);
 
2115
 
 
2116
  /* Compactage de la définition */
 
2117
  /*-----------------------------*/
 
2118
 
 
2119
  /*
 
2120
    Le premier élément ne peut pas être fusionné avec un élément précédent,
 
2121
    la boucle commence donc au deuxième
 
2122
  */
 
2123
 
 
2124
  cpt_sup_fin       = 1;
 
2125
 
 
2126
  for (ind_sup = 1; ind_sup < table_def->nbr; ind_sup++) {
 
2127
 
 
2128
    if (tab_transf.val[ind_sup] > (ecs_int_t)(cpt_sup_fin - 1)) {
 
2129
 
 
2130
      /* Recopie définition sur partie compactée du tableau */
 
2131
 
 
2132
      for (pos_cpt = table_def->pos[cpt_sup_fin],
 
2133
             pos_sup = table_def->pos[ind_sup];
 
2134
           pos_sup < table_def->pos[ind_sup + 1];
 
2135
           pos_cpt++, pos_sup++)
 
2136
        table_def->val[pos_cpt - 1] = table_def->val[pos_sup - 1];
 
2137
 
 
2138
      cpt_sup_fin += 1;
 
2139
 
 
2140
      table_def->pos[cpt_sup_fin] = pos_cpt;
 
2141
 
 
2142
    }
 
2143
  }
 
2144
 
 
2145
  /* Redimensionnement de l'entité compactée */
 
2146
 
 
2147
  table_def->nbr = cpt_sup_fin;
 
2148
  ECS_REALLOC(table_def->pos, cpt_sup_fin + 1, ecs_size_t);
 
2149
  ECS_REALLOC(table_def->val,
 
2150
              table_def->pos[cpt_sup_fin] - 1,
 
2151
              ecs_int_t);
 
2152
 
 
2153
  ecs_table__pos_en_regle(table_def);
 
2154
 
 
2155
  /* Affectation de la nouvelle liste compactee */
 
2156
  /*--------------------------------------------*/
 
2157
 
 
2158
  *nbr_elt_cpct = table_def->nbr;
 
2159
 
 
2160
  /* Renvoi du tableau de transformation */
 
2161
  /*-------------------------------------*/
 
2162
 
 
2163
  return tab_transf;
 
2164
}
 
2165
 
 
2166
/*----------------------------------------------------------------------------
 
2167
 *  Fonction qui construit la liste des cellules attachées à une liste
 
2168
 *  de faces fournie en argument.
 
2169
 *----------------------------------------------------------------------------*/
 
2170
 
 
2171
ecs_tab_int_t
 
2172
ecs_table_def__liste_cel_fac(const size_t          nbr_fac,
 
2173
                             ecs_table_t          *table_def_cel,
 
2174
                             const ecs_tab_int_t   liste_fac)
 
2175
{
 
2176
  size_t      cpt_cel;
 
2177
  size_t      icel;
 
2178
  size_t      ifac;
 
2179
  size_t      iloc;
 
2180
  size_t      ipos;
 
2181
  size_t      nbr_cel;
 
2182
  size_t      nbr_fac_cel;
 
2183
  ecs_int_t  *indic_cel;
 
2184
  ecs_int_t  *indic_fac;
 
2185
 
 
2186
  ecs_tab_int_t   liste_cel;
 
2187
 
 
2188
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2189
 
 
2190
  assert(table_def_cel != NULL);
 
2191
 
 
2192
  ecs_table__regle_en_pos(table_def_cel);
 
2193
 
 
2194
  /* Initialisations */
 
2195
 
 
2196
  cpt_cel = 0;
 
2197
 
 
2198
  nbr_cel = table_def_cel->nbr;
 
2199
 
 
2200
  /* Indicateurs */
 
2201
 
 
2202
  ECS_MALLOC(indic_cel, nbr_cel, ecs_int_t);
 
2203
  ECS_MALLOC(indic_fac, nbr_fac, ecs_int_t);
 
2204
 
 
2205
  for (icel = 0; icel < nbr_cel; icel++)
 
2206
    indic_cel[icel] = 0;
 
2207
 
 
2208
  for (ifac = 0; ifac < nbr_fac; ifac++)
 
2209
    indic_fac[ifac] = 0;
 
2210
 
 
2211
  for (ifac = 0; ifac < liste_fac.nbr; ifac++)
 
2212
    indic_fac[liste_fac.val[ifac]] = 1;
 
2213
 
 
2214
  /* Première boucle sur les cellules : marquage */
 
2215
 
 
2216
  for (icel = 0; icel < nbr_cel; icel++) {
 
2217
 
 
2218
    nbr_fac_cel
 
2219
      = table_def_cel->pos[icel + 1]
 
2220
      - table_def_cel->pos[icel];
 
2221
 
 
2222
    ipos = table_def_cel->pos[icel] - 1;
 
2223
 
 
2224
    for (iloc = 0; iloc < nbr_fac_cel; iloc++) {
 
2225
 
 
2226
      ifac = ECS_ABS(table_def_cel->val[ipos]) - 1;
 
2227
 
 
2228
      ipos++;
 
2229
 
 
2230
      if (indic_fac[ifac] == 1 && indic_cel[icel] == 0) {
 
2231
        indic_cel[icel] = 1;
 
2232
        cpt_cel++;
 
2233
      }
 
2234
 
 
2235
    }
 
2236
  }
 
2237
 
 
2238
  ECS_FREE(indic_fac);
 
2239
 
 
2240
  /* Seconde boucle sur les cellules : remplissage */
 
2241
 
 
2242
  liste_cel.nbr = cpt_cel;
 
2243
  ECS_MALLOC(liste_cel.val, liste_cel.nbr, ecs_int_t);
 
2244
 
 
2245
  cpt_cel = 0;
 
2246
 
 
2247
  for (icel = 0; icel < nbr_cel; icel++) {
 
2248
 
 
2249
    if (indic_cel[icel] == 1)
 
2250
      liste_cel.val[cpt_cel++] = icel;
 
2251
 
 
2252
  }
 
2253
 
 
2254
  ECS_FREE(indic_cel);
 
2255
 
 
2256
  ecs_table__libere_pos(table_def_cel);
 
2257
 
 
2258
  return liste_cel;
 
2259
}
 
2260
 
 
2261
/*----------------------------------------------------------------------------
 
2262
 *  Fonction qui remplace les références à des éléments
 
2263
 *  en des références à d'autres éléments liés aux premiers
 
2264
 *  par un tableau de renumérotation qui peut être signé.
 
2265
 *----------------------------------------------------------------------------*/
 
2266
 
 
2267
void
 
2268
ecs_table_def__remplace_ref(ecs_table_t    *table_def,
 
2269
                            ecs_tab_int_t  *tab_old_new)
 
2270
{
 
2271
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2272
 
 
2273
  if (table_def != NULL && tab_old_new != NULL) {
 
2274
 
 
2275
    ecs_int_t  num_old, num_new;
 
2276
    ecs_size_t ielt;
 
2277
    ecs_size_t ival, ival_deb, ival_fin;
 
2278
    ecs_size_t cpt_val = 0;
 
2279
    size_t nbr_elt = table_def->nbr;
 
2280
 
 
2281
    ecs_table__regle_en_pos(table_def);
 
2282
 
 
2283
    ival_deb = 0;
 
2284
 
 
2285
    for (ielt = 0; ielt < nbr_elt; ielt++) {
 
2286
 
 
2287
      ival_fin = table_def->pos[ielt+1] - 1;
 
2288
 
 
2289
      for (ival = ival_deb; ival < ival_fin; ival++) {
 
2290
        num_new = 0;
 
2291
        num_old = table_def->val[ival];
 
2292
        if (num_old > 0)
 
2293
          num_new = tab_old_new->val[num_old -1];
 
2294
        else
 
2295
          num_new = -tab_old_new->val[-num_old -1];
 
2296
        if (num_new != 0)
 
2297
          table_def->val[cpt_val++] = num_new;
 
2298
      }
 
2299
 
 
2300
      ival_deb = table_def->pos[ielt+1] - 1;
 
2301
      table_def->pos[ielt+1] = cpt_val + 1;
 
2302
    }
 
2303
 
 
2304
    ECS_REALLOC(table_def->val, cpt_val, ecs_int_t);
 
2305
 
 
2306
    ecs_table__pos_en_regle(table_def);
 
2307
  }
 
2308
}
 
2309
 
 
2310
/*----------------------------------------------------------------------------
 
2311
 *  Fonction qui construit un tableau de booleens conforme a une liste
 
2312
 *   de sous-elements
 
2313
 *  Un sous-element est a `true'
 
2314
 *   s'il intervient dans la definition des elements
 
2315
 *----------------------------------------------------------------------------*/
 
2316
 
 
2317
void
 
2318
ecs_table_def__cree_masque(ecs_tab_bool_t   bool_sselt_select,
 
2319
                           ecs_table_t     *table_def_elt)
 
2320
{
 
2321
  size_t  nbr_elt;
 
2322
  size_t  num_sselt;
 
2323
  size_t  pos_inf;
 
2324
  size_t  pos_sup;
 
2325
 
 
2326
  size_t  ielt;
 
2327
  size_t  ipos;
 
2328
 
 
2329
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2330
 
 
2331
  ecs_table__regle_en_pos(table_def_elt);
 
2332
 
 
2333
  nbr_elt = table_def_elt->nbr;
 
2334
 
 
2335
  for (ielt = 0; ielt < nbr_elt; ielt++) {
 
2336
 
 
2337
    pos_inf = table_def_elt->pos[ielt    ] - 1;
 
2338
    pos_sup = table_def_elt->pos[ielt + 1] - 1;
 
2339
 
 
2340
    for (ipos = pos_inf; ipos < pos_sup; ipos++) {
 
2341
 
 
2342
      num_sselt = ECS_ABS(table_def_elt->val[ipos]) - 1;
 
2343
 
 
2344
      /* If the sub-element has not yet been accounted for, mark it */
 
2345
 
 
2346
      if (bool_sselt_select.val[num_sselt] == false)
 
2347
        bool_sselt_select.val[num_sselt] = true;
 
2348
 
 
2349
    }
 
2350
  }
 
2351
 
 
2352
  ecs_table__libere_pos(table_def_elt);
 
2353
}
 
2354
 
 
2355
/*----------------------------------------------------------------------------
 
2356
 * Suppression des sommets ne participant pas à la connectivité
 
2357
 *  et mise à jour de la connectivité.
 
2358
 *----------------------------------------------------------------------------*/
 
2359
 
 
2360
void
 
2361
ecs_table_def__nettoie_nodal(size_t        *n_vertices,
 
2362
                             ecs_coord_t  **vtx_coords,
 
2363
                             ecs_table_t   *table_def_fac,
 
2364
                             ecs_table_t   *table_def_cel)
 
2365
{
 
2366
  size_t  cpt_som;
 
2367
  size_t  iloc;
 
2368
  size_t  ipos_new;
 
2369
  size_t  ipos_old;
 
2370
  size_t  isom;
 
2371
  size_t  ival;
 
2372
  size_t  nbr_som;
 
2373
  size_t  nbr_val;
 
2374
 
 
2375
  ecs_tab_int_t   tab_som_old_new;
 
2376
 
 
2377
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2378
 
 
2379
  tab_som_old_new.nbr = 0;
 
2380
  tab_som_old_new.val = NULL;
 
2381
 
 
2382
  if (vtx_coords == NULL)
 
2383
    return;
 
2384
 
 
2385
  /* Initialisation du vecteur de renumérotation comme marqueur */
 
2386
 
 
2387
  nbr_som = *n_vertices;
 
2388
 
 
2389
  tab_som_old_new = ecs_tab_int__cree_init(nbr_som, 0);
 
2390
 
 
2391
  /* faces */
 
2392
 
 
2393
  if (table_def_fac != NULL) {
 
2394
 
 
2395
    nbr_val = ecs_table__ret_val_nbr(table_def_fac);
 
2396
 
 
2397
    for (ival = 0; ival < nbr_val; ival++)
 
2398
      tab_som_old_new.val[table_def_fac->val[ival] - 1] = 1;
 
2399
  }
 
2400
 
 
2401
  /* cellules */
 
2402
 
 
2403
  if (table_def_cel != NULL) {
 
2404
 
 
2405
    nbr_val = ecs_table__ret_val_nbr(table_def_cel);
 
2406
 
 
2407
    for (ival = 0; ival < nbr_val; ival++)
 
2408
      tab_som_old_new.val[table_def_cel->val[ival] - 1] = 1;
 
2409
  }
 
2410
 
 
2411
  /* Préparation de la renumérotation */
 
2412
 
 
2413
  cpt_som = 0;
 
2414
 
 
2415
  for (isom = 0; isom < nbr_som; isom++) {
 
2416
    if (tab_som_old_new.val[isom] != 0)
 
2417
      cpt_som++;
 
2418
  }
 
2419
 
 
2420
  /* Si tous les sommets sont référencés, rien à faire */
 
2421
 
 
2422
  if (cpt_som == nbr_som) {
 
2423
    tab_som_old_new.nbr = 0;
 
2424
    ECS_FREE(tab_som_old_new.val);
 
2425
    return;
 
2426
  }
 
2427
 
 
2428
  /* Compactage du tableau des sommets
 
2429
     et transformation du marquer en renumérotation */
 
2430
 
 
2431
  cpt_som = 0;
 
2432
 
 
2433
  for (isom = 0; isom < nbr_som; isom++) {
 
2434
 
 
2435
    if (tab_som_old_new.val[isom] != 0) {
 
2436
 
 
2437
      ipos_new = 3 * (cpt_som);
 
2438
      ipos_old = 3 * isom;
 
2439
 
 
2440
      for (iloc = 0; iloc < 3; iloc++)
 
2441
        (*vtx_coords)[ipos_new++] = (*vtx_coords)[ipos_old++];
 
2442
 
 
2443
      tab_som_old_new.val[isom] = cpt_som + 1;
 
2444
 
 
2445
      cpt_som++;
 
2446
 
 
2447
    }
 
2448
  }
 
2449
 
 
2450
  *n_vertices = cpt_som;
 
2451
  ECS_REALLOC(*vtx_coords, cpt_som*3, ecs_coord_t);
 
2452
 
 
2453
  /* Mise à jour de la connectivité nodale */
 
2454
 
 
2455
  if (table_def_fac != NULL)
 
2456
    ecs_table_def__remplace_ref(table_def_fac,
 
2457
                                &tab_som_old_new);
 
2458
 
 
2459
  if (table_def_cel != NULL)
 
2460
    ecs_table_def__remplace_ref(table_def_cel,
 
2461
                                &tab_som_old_new);
 
2462
 
 
2463
  tab_som_old_new.nbr = 0;
 
2464
  ECS_FREE(tab_som_old_new.val);
 
2465
}
 
2466
 
 
2467
/*----------------------------------------------------------------------------
 
2468
 *  Correction si nécessaire de l'orientation des éléments en connectivité
 
2469
 *   nodale. L'argument liste_cel_err est optionnel.
 
2470
 *----------------------------------------------------------------------------*/
 
2471
 
 
2472
void
 
2473
ecs_table_def__orient_nodal(ecs_coord_t     *vtx_coords,
 
2474
                            ecs_table_t     *table_def_fac,
 
2475
                            ecs_table_t     *table_def_cel,
 
2476
                            ecs_tab_int_t   *liste_cel_err,
 
2477
                            bool             correc_orient)
 
2478
{
 
2479
  size_t      ipos_cel;
 
2480
  size_t      ipos_fac;
 
2481
  size_t      icel;
 
2482
  size_t      ifac;
 
2483
  size_t      nbr_som_loc;
 
2484
  size_t      nbr_fac;
 
2485
  size_t      nbr_cel;
 
2486
  ecs_int_t   typ_elt;
 
2487
  ecs_int_t   ret_orient;
 
2488
 
 
2489
  ecs_int_t   cpt_orient_correc[ECS_ELT_TYP_FIN];
 
2490
  ecs_int_t   cpt_orient_erreur[ECS_ELT_TYP_FIN];
 
2491
 
 
2492
  ecs_int_t   typ_cel_base[9] = {ECS_ELT_TYP_NUL,
 
2493
                                 ECS_ELT_TYP_NUL,
 
2494
                                 ECS_ELT_TYP_NUL,
 
2495
                                 ECS_ELT_TYP_NUL,
 
2496
                                 ECS_ELT_TYP_CEL_TETRA,
 
2497
                                 ECS_ELT_TYP_CEL_PYRAM,
 
2498
                                 ECS_ELT_TYP_CEL_PRISM,
 
2499
                                 ECS_ELT_TYP_NUL,
 
2500
                                 ECS_ELT_TYP_CEL_HEXA};
 
2501
 
 
2502
  ecs_int_t   cpt_cel_erreur = 0;
 
2503
  ecs_int_t   cpt_cel_correc = 0;
 
2504
 
 
2505
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2506
 
 
2507
  if (vtx_coords == NULL)
 
2508
    return;
 
2509
 
 
2510
  if (table_def_fac != NULL)
 
2511
    ecs_table__regle_en_pos(table_def_fac);
 
2512
 
 
2513
  if (table_def_cel != NULL)
 
2514
    ecs_table__regle_en_pos(table_def_cel);
 
2515
 
 
2516
  assert(vtx_coords != NULL);
 
2517
 
 
2518
  for (typ_elt = 0; typ_elt < ECS_ELT_TYP_FIN; typ_elt++) {
 
2519
    cpt_orient_correc[typ_elt] = 0;
 
2520
    cpt_orient_erreur[typ_elt] = 0;
 
2521
  }
 
2522
 
 
2523
  printf(_("\n  Element orientation check.\n\n"));
 
2524
 
 
2525
  /* faces */
 
2526
 
 
2527
  if (table_def_fac != NULL) {
 
2528
 
 
2529
    nbr_fac = table_def_fac->nbr;
 
2530
 
 
2531
    for (ifac = 0; ifac < nbr_fac; ifac++) {
 
2532
 
 
2533
      ipos_fac    = table_def_fac->pos[ifac    ] - 1;
 
2534
      nbr_som_loc = table_def_fac->pos[ifac + 1] - 1 - ipos_fac;
 
2535
 
 
2536
      if (nbr_som_loc == 4) {
 
2537
 
 
2538
        ret_orient
 
2539
          = _orient_quad(vtx_coords,
 
2540
                         &(table_def_fac->val[ipos_fac]),
 
2541
                         correc_orient);
 
2542
 
 
2543
        if (ret_orient < 0)
 
2544
          cpt_orient_erreur[ECS_ELT_TYP_FAC_QUAD] += 1;
 
2545
        else if (ret_orient > 0)
 
2546
          cpt_orient_correc[ECS_ELT_TYP_FAC_QUAD] += 1;
 
2547
 
 
2548
      }
 
2549
    }
 
2550
  }
 
2551
 
 
2552
  /* cellules */
 
2553
 
 
2554
  if (table_def_cel != NULL) {
 
2555
 
 
2556
    ecs_tab_int_t face_index, face_marker, edges;
 
2557
 
 
2558
    face_index.nbr = 0;
 
2559
    face_index.val = NULL;
 
2560
 
 
2561
    face_marker.nbr = 0;
 
2562
    face_marker.val = NULL;
 
2563
 
 
2564
    edges.nbr = 0;
 
2565
    edges.val = NULL;
 
2566
 
 
2567
    nbr_cel = table_def_cel->nbr;
 
2568
 
 
2569
    for (icel = 0; icel < nbr_cel; icel++) {
 
2570
 
 
2571
      ipos_cel = table_def_cel->pos[icel] - 1;
 
2572
 
 
2573
      nbr_som_loc = table_def_cel->pos[icel + 1] - 1 - ipos_cel;
 
2574
 
 
2575
      if (nbr_som_loc < 9)
 
2576
        typ_elt = typ_cel_base[nbr_som_loc];
 
2577
      else
 
2578
        typ_elt = ECS_ELT_TYP_CEL_POLY;
 
2579
 
 
2580
      switch (typ_elt) {
 
2581
 
 
2582
      case ECS_ELT_TYP_CEL_TETRA:
 
2583
 
 
2584
        ret_orient = _orient_tetra(vtx_coords,
 
2585
                                   &(table_def_cel->val[ipos_cel]));
 
2586
        break;
 
2587
 
 
2588
      case ECS_ELT_TYP_CEL_PYRAM:
 
2589
 
 
2590
        ret_orient
 
2591
          = _orient_pyram(vtx_coords,
 
2592
                          &(table_def_cel->val[ipos_cel]),
 
2593
                          correc_orient);
 
2594
        break;
 
2595
 
 
2596
      case ECS_ELT_TYP_CEL_PRISM:
 
2597
 
 
2598
        ret_orient
 
2599
          = _orient_prism(vtx_coords,
 
2600
                          &(table_def_cel->val[ipos_cel]),
 
2601
                          correc_orient);
 
2602
 
 
2603
        break;
 
2604
 
 
2605
      case ECS_ELT_TYP_CEL_HEXA:
 
2606
 
 
2607
        ret_orient
 
2608
          = _orient_hexa(vtx_coords,
 
2609
                         &(table_def_cel->val[ipos_cel]),
 
2610
                         correc_orient);
 
2611
 
 
2612
        break;
 
2613
 
 
2614
      default: /* ECS_ELT_TYP_CEL_POLY */
 
2615
 
 
2616
        ret_orient = _orient_polyhedron(vtx_coords,
 
2617
                                        &(table_def_cel->val[ipos_cel]),
 
2618
                                        (  table_def_cel->pos[icel + 1]
 
2619
                                         - table_def_cel->pos[icel]),
 
2620
                                        correc_orient,
 
2621
                                        &face_index,
 
2622
                                        &face_marker,
 
2623
                                        &edges);
 
2624
 
 
2625
      };
 
2626
 
 
2627
      if (ret_orient < 0) {
 
2628
        cpt_orient_erreur[typ_elt] += 1;
 
2629
        if (liste_cel_err != NULL) {
 
2630
          if (liste_cel_err->nbr == 0) {
 
2631
            liste_cel_err->nbr = nbr_cel;
 
2632
            ECS_MALLOC(liste_cel_err->val, liste_cel_err->nbr, ecs_int_t);
 
2633
          }
 
2634
          liste_cel_err->val[cpt_cel_erreur] = icel;
 
2635
        }
 
2636
        cpt_cel_erreur += 1;
 
2637
      }
 
2638
 
 
2639
      else if (ret_orient > 0) {
 
2640
        cpt_orient_correc[typ_elt] += 1;
 
2641
        cpt_cel_correc += 1;
 
2642
      }
 
2643
    }
 
2644
 
 
2645
    if (face_index.nbr > 0)
 
2646
      ECS_FREE(face_index.val);
 
2647
 
 
2648
    if (face_marker.nbr > 0)
 
2649
      ECS_FREE(face_marker.val);
 
2650
 
 
2651
    if (edges.nbr > 0)
 
2652
      ECS_FREE(edges.val);
 
2653
  }
 
2654
 
 
2655
  /* Impression de messages d'avertissement */
 
2656
 
 
2657
  for (typ_elt = 0; typ_elt < ECS_ELT_TYP_FIN; typ_elt++) {
 
2658
    if (cpt_orient_correc[typ_elt] > 0) {
 
2659
      ecs_warn();
 
2660
      printf(_("%d elements of type %s had to be re-oriented\n"),
 
2661
             (int)(cpt_orient_correc[typ_elt]),
 
2662
             _(ecs_fic_elt_typ_liste_c[typ_elt].nom));
 
2663
    }
 
2664
    if (cpt_orient_erreur[typ_elt] > 0) {
 
2665
      if (correc_orient == true) {
 
2666
        ecs_warn();
 
2667
        printf(_("%d elements of type %s were impossible to re-orient\n"),
 
2668
               (int)(cpt_orient_erreur[typ_elt]),
 
2669
               _(ecs_fic_elt_typ_liste_c[typ_elt].nom));
 
2670
      }
 
2671
      else {
 
2672
        ecs_warn();
 
2673
        printf(_("%d elements of type %s are mis-oriented or highly warped\n"),
 
2674
               (int)(cpt_orient_erreur[typ_elt]),
 
2675
               _(ecs_fic_elt_typ_liste_c[typ_elt].nom));
 
2676
      }
 
2677
    }
 
2678
  }
 
2679
 
 
2680
  /* Redimensionnement de la liste des cellules toujours mal orientées */
 
2681
 
 
2682
  if (liste_cel_err != NULL) {
 
2683
    if (liste_cel_err->nbr > 0) {
 
2684
      liste_cel_err->nbr = cpt_cel_erreur;
 
2685
      ECS_REALLOC(liste_cel_err->val, liste_cel_err->nbr, ecs_int_t);
 
2686
    }
 
2687
  }
 
2688
 
 
2689
  if (table_def_fac != NULL)
 
2690
    ecs_table__libere_pos(table_def_fac);
 
2691
 
 
2692
  if (table_def_cel != NULL)
 
2693
    ecs_table__libere_pos(table_def_cel);
 
2694
}
 
2695
 
 
2696
/*----------------------------------------------------------------------------
 
2697
 *  Fusion des sommets confondus d'après la longueur des arêtes des faces.
 
2698
 * La connectivité des faces est mise à jour.
 
2699
 *----------------------------------------------------------------------------*/
 
2700
 
 
2701
void
 
2702
ecs_table_def__nettoie_som_fac(size_t        *n_vertices,
 
2703
                               ecs_coord_t  **vtx_coords,
 
2704
                               ecs_table_t   *table_def_fac)
 
2705
{
 
2706
  size_t     cpt_fusion;
 
2707
 
 
2708
  size_t     icoo;
 
2709
  size_t     ifac;
 
2710
 
 
2711
  size_t     ipos_deb;
 
2712
  size_t     ipos_0;
 
2713
  size_t     ipos_1;
 
2714
  size_t     isom;
 
2715
  size_t     isom_0;
 
2716
  size_t     isom_1;
 
2717
 
 
2718
  size_t     nbr_fac;
 
2719
  size_t     nbr_som;
 
2720
  size_t     nbr_som_fac;
 
2721
 
 
2722
  double      delta_coo;
 
2723
  double      lng_are_min;
 
2724
  double      lng_are_2;
 
2725
  double      lng_min_2;
 
2726
 
 
2727
  ecs_tab_int_t  tab_equiv_som;
 
2728
 
 
2729
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2730
 
 
2731
  if (vtx_coords == NULL || table_def_fac == NULL)
 
2732
    return;
 
2733
 
 
2734
  ecs_table__regle_en_pos(table_def_fac);
 
2735
 
 
2736
  nbr_fac = table_def_fac->nbr;
 
2737
  nbr_som = *n_vertices;
 
2738
 
 
2739
  lng_are_min = 1.0e-15;
 
2740
  if (getenv("CS_PREPROCESS_MIN_EDGE_LEN") != NULL) {
 
2741
    lng_are_min = atof(getenv("CS_PREPROCESS_MIN_EDGE_LEN"));
 
2742
  }
 
2743
  lng_min_2 = lng_are_min * ECS_ABS(lng_are_min);
 
2744
 
 
2745
  /* Marquage des sommets */
 
2746
  /*----------------------*/
 
2747
 
 
2748
  tab_equiv_som = ecs_tab_int__cree_init(nbr_som, -1);
 
2749
 
 
2750
  cpt_fusion = 0;
 
2751
 
 
2752
  /* Boucle sur les faces pour détecter les sommets confondus */
 
2753
  /*----------------------------------------------------------*/
 
2754
 
 
2755
  for (ifac = 0; ifac < nbr_fac; ifac++) {
 
2756
 
 
2757
    ipos_deb = table_def_fac->pos[ifac] - 1;
 
2758
    nbr_som_fac = (table_def_fac->pos[ifac + 1] - 1) - ipos_deb;
 
2759
 
 
2760
    for (isom = 0; isom < nbr_som_fac; isom++) {
 
2761
 
 
2762
      isom_0 = table_def_fac->val[ipos_deb + isom] - 1;
 
2763
      isom_1 = table_def_fac->val[  ipos_deb + ((isom + 1)%nbr_som_fac)] -1;
 
2764
      ipos_0 = isom_0 * 3;
 
2765
      ipos_1 = isom_1 * 3;
 
2766
 
 
2767
      lng_are_2 = 0.0;
 
2768
 
 
2769
      for (icoo = 0; icoo < 3; icoo++) {
 
2770
        delta_coo =   (*vtx_coords)[ipos_1 + icoo]
 
2771
                    - (*vtx_coords)[ipos_0 + icoo];
 
2772
        lng_are_2 += delta_coo * delta_coo;
 
2773
      }
 
2774
 
 
2775
      /* Sommets confondus détectés */
 
2776
 
 
2777
      if (lng_are_2 < lng_min_2) {
 
2778
        _table_def__maj_equiv_som(isom_0, isom_1, &tab_equiv_som);
 
2779
        cpt_fusion += 1;
 
2780
      }
 
2781
 
 
2782
    }
 
2783
  }
 
2784
 
 
2785
  /* Fusion si nécessaire */
 
2786
 
 
2787
  if (cpt_fusion > 0) {
 
2788
 
 
2789
    ecs_tab_int_t  tab_som_old_new;
 
2790
 
 
2791
    printf(_("\nMesh verification:\n\n"
 
2792
             "  %d vertices belong to edges of length less than %g\n"
 
2793
             "  and will be merged; (this tolerance may be modified\n"
 
2794
             "  using the CS_PREPROCESS_MIN_EDGE_LEN environment variable).\n"),
 
2795
           (int)cpt_fusion, lng_are_min);
 
2796
 
 
2797
    tab_som_old_new = _table_def__fusion_som(n_vertices,
 
2798
                                             vtx_coords,
 
2799
                                             &tab_equiv_som);
 
2800
 
 
2801
    _table_def__maj_fac_som(table_def_fac, &tab_som_old_new);
 
2802
 
 
2803
    ECS_FREE(tab_som_old_new.val);
 
2804
 
 
2805
    printf("\n");
 
2806
  }
 
2807
 
 
2808
  /* Libération mémoire et retour */
 
2809
 
 
2810
  ECS_FREE(tab_equiv_som.val);
 
2811
 
 
2812
  ecs_table__pos_en_regle(table_def_fac);
 
2813
}
 
2814
 
 
2815
/*----------------------------------------------------------------------------
 
2816
 *  Fonction qui supprime les éventuelles faces dégénérées
 
2817
 *----------------------------------------------------------------------------*/
 
2818
 
 
2819
ecs_tab_int_t
 
2820
ecs_table_def__nettoie_fac(ecs_table_t  *table_def_fac)
 
2821
{
 
2822
  ecs_int_t  nbr_fac_old;
 
2823
  ecs_int_t  nbr_fac_new;
 
2824
 
 
2825
  ecs_int_t  ind_fac;
 
2826
 
 
2827
  ecs_int_t  cpt_fac;
 
2828
  ecs_int_t  cpt_val;
 
2829
  ecs_int_t  ind_val;
 
2830
  ecs_int_t  ind_val_deb;
 
2831
  ecs_int_t  ind_val_fin;
 
2832
 
 
2833
  ecs_tab_int_t  tab_fac_old_new;
 
2834
 
 
2835
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2836
 
 
2837
  tab_fac_old_new.nbr = 0;
 
2838
  tab_fac_old_new.val = NULL;
 
2839
 
 
2840
  if (table_def_fac == NULL)
 
2841
    return tab_fac_old_new;
 
2842
 
 
2843
  ecs_table__regle_en_pos(table_def_fac);
 
2844
 
 
2845
  /* Initialisations */
 
2846
 
 
2847
  nbr_fac_old = table_def_fac->nbr;
 
2848
 
 
2849
  /* Boucle sur les faces (renumérotation) */
 
2850
  /* ------------------------------------- */
 
2851
 
 
2852
  tab_fac_old_new.nbr = nbr_fac_old;
 
2853
  ECS_MALLOC(tab_fac_old_new.val, tab_fac_old_new.nbr, ecs_int_t);
 
2854
 
 
2855
  cpt_fac = 0;
 
2856
  cpt_val = 0;
 
2857
 
 
2858
  for (ind_fac = 0; ind_fac < nbr_fac_old; ind_fac++) {
 
2859
 
 
2860
    ind_val_deb = table_def_fac->pos[ind_fac    ] - 1;
 
2861
    ind_val_fin = table_def_fac->pos[ind_fac + 1] - 1;
 
2862
 
 
2863
    if (ind_val_fin - ind_val_deb > 2) {
 
2864
 
 
2865
      for (ind_val = ind_val_deb; ind_val < ind_val_fin; ind_val++)
 
2866
        table_def_fac->val[cpt_val++] = table_def_fac->val[ind_val];
 
2867
 
 
2868
      tab_fac_old_new.val[ind_fac] = 1 + cpt_fac++;
 
2869
 
 
2870
      table_def_fac->pos[cpt_fac] = cpt_val + 1;
 
2871
 
 
2872
    }
 
2873
    else
 
2874
      tab_fac_old_new.val[ind_fac] = 0;
 
2875
 
 
2876
  }
 
2877
 
 
2878
  nbr_fac_new = cpt_fac;
 
2879
 
 
2880
  /* Si on n'a pas de faces dégénérées, on peut sortir */
 
2881
 
 
2882
  if (nbr_fac_new == nbr_fac_old) {
 
2883
 
 
2884
    tab_fac_old_new.nbr = 0;
 
2885
    ECS_FREE(tab_fac_old_new.val);
 
2886
 
 
2887
    ecs_table__pos_en_regle(table_def_fac);
 
2888
 
 
2889
    return tab_fac_old_new;
 
2890
  }
 
2891
 
 
2892
  printf(_("\nMesh verification:\n\n"
 
2893
           "  Removal of %d degenerate faces:\n"
 
2894
           "    Initial number of faces           : %10d\n"
 
2895
           "    Number of faces after processing  : %10d\n"),
 
2896
         (int)(nbr_fac_old - nbr_fac_new), (int)nbr_fac_old, (int)nbr_fac_new);
 
2897
 
 
2898
  /* On redimensionne le tableau des faces */
 
2899
 
 
2900
  table_def_fac->nbr = nbr_fac_new;
 
2901
  ECS_REALLOC(table_def_fac->pos, nbr_fac_new + 1, ecs_size_t);
 
2902
  ECS_REALLOC(table_def_fac->val, cpt_val, ecs_int_t);
 
2903
 
 
2904
  ecs_table__pos_en_regle(table_def_fac);
 
2905
 
 
2906
  return tab_fac_old_new;
 
2907
}
 
2908
 
 
2909
/*----------------------------------------------------------------------------
 
2910
 *  Fonction qui renvoie un tableau associant un type à chaque face, sous
 
2911
 * forme de masque : 0 pour face isolée, 1 ou 2 pour face de bord (1 si
 
2912
 * cellule avec cette face normale sortante, 2 si cellule avec cette face
 
2913
 * normale entrante), 1+2 = 3 pour face interne, et 4 ou plus pour tous
 
2914
 * les autres cas, correspondant à une erreur de connectivité (+4 pour faces
 
2915
 * voyant au moins deux cellules avec face normale sortante, +8 pour faces
 
2916
 * voyant au moins deux cellules avec face normale entrante).
 
2917
 *
 
2918
 *  Le type de chaque face pourra être modifié ultérieurement en fonction
 
2919
 * des informations de périodicité.
 
2920
 *----------------------------------------------------------------------------*/
 
2921
 
 
2922
ecs_tab_int_t
 
2923
ecs_table_def__typ_fac_cel(ecs_table_t  *table_def_cel,
 
2924
                           ecs_table_t  *table_def_fac)
 
2925
{
 
2926
  size_t      nbr_cel;
 
2927
  size_t      nbr_fac;
 
2928
  ecs_int_t   num_fac;
 
2929
  size_t      icel;
 
2930
  size_t      ifac;
 
2931
  size_t      ipos;
 
2932
 
 
2933
  ecs_tab_int_t   typ_fac;
 
2934
 
 
2935
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
2936
 
 
2937
  typ_fac.nbr = 0;
 
2938
  typ_fac.val = NULL;
 
2939
 
 
2940
  if (table_def_cel == NULL)
 
2941
    return typ_fac;
 
2942
 
 
2943
  /* Initialisations */
 
2944
 
 
2945
  ecs_table__regle_en_pos(table_def_cel);
 
2946
 
 
2947
  nbr_cel = table_def_cel->nbr;
 
2948
  nbr_fac = table_def_fac->nbr;
 
2949
 
 
2950
  /* Type de face selon le nombre de cellules voisines : 0 pour face isolée,
 
2951
     1 ou 2 pour face de bord, 3 pour faces internes, et 4 pour tous les
 
2952
     autres cas (faces voyant au moins deux cellules sur un même côté) */
 
2953
 
 
2954
  typ_fac.nbr = nbr_fac;
 
2955
 
 
2956
  ECS_MALLOC(typ_fac.val, nbr_fac, ecs_int_t);
 
2957
 
 
2958
  for (ifac = 0; ifac < nbr_fac; ifac++)
 
2959
    typ_fac.val[ifac] = 0;
 
2960
 
 
2961
  /* Boucle sur les cellules : marquage */
 
2962
  /*------------------------------------*/
 
2963
 
 
2964
  for (icel = 0; icel < nbr_cel; icel++ ) {
 
2965
 
 
2966
    for (ipos = table_def_cel->pos[icel] - 1;
 
2967
         ipos < table_def_cel->pos[icel+1] - 1;
 
2968
         ipos++) {
 
2969
 
 
2970
      num_fac = table_def_cel->val[ipos];
 
2971
 
 
2972
      ifac = ECS_ABS(num_fac) - 1;
 
2973
 
 
2974
      if (num_fac > 0 && (typ_fac.val[ifac] & 1) == 0)
 
2975
        typ_fac.val[ifac] += 1;
 
2976
 
 
2977
      else if (num_fac < 0 && (typ_fac.val[ifac] & 2) == 0)
 
2978
        typ_fac.val[ifac] += 2;
 
2979
 
 
2980
      else {
 
2981
        if (num_fac > 0 && (typ_fac.val[ifac] & 1) == 1)
 
2982
          typ_fac.val[ifac] = typ_fac.val[ifac] | 4;
 
2983
        else if (num_fac < 0 && (typ_fac.val[ifac] & 2) == 1)
 
2984
          typ_fac.val[ifac] = typ_fac.val[ifac] | 8;
 
2985
      }
 
2986
 
 
2987
    }
 
2988
 
 
2989
  }
 
2990
 
 
2991
  ecs_table__libere_pos(table_def_cel);
 
2992
 
 
2993
  return typ_fac;
 
2994
}
 
2995
 
 
2996
/*----------------------------------------------------------------------------
 
2997
 *  Fonction qui renvoie un tableau associant un type à chaque face les
 
2998
 * numéros des cellules définies par cette face (normale sortante,
 
2999
 * puis normale entrante). On affecte une valeur 0 lorsqu'il n'y a pas de
 
3000
 * cellule correspondante directe (la périodicité n'est donc pas prise en
 
3001
 * compte à ce niveau).
 
3002
 *
 
3003
 * On suppose que la cohérence du maillage a déjà été véridifiée et
 
3004
 * qu'aucune face n'appartient à plus d'une cellule par côté.
 
3005
 *----------------------------------------------------------------------------*/
 
3006
 
 
3007
ecs_tab_int_t
 
3008
ecs_table_def__fac_cel(ecs_table_t  *table_def_cel,
 
3009
                       ecs_table_t  *table_def_fac)
 
3010
{
 
3011
  size_t      nbr_cel;
 
3012
  size_t      nbr_fac;
 
3013
  ecs_int_t   num_fac;
 
3014
  size_t      icel;
 
3015
  size_t      ifac;
 
3016
  size_t      ipos;
 
3017
 
 
3018
  ecs_tab_int_t   fac_cel;
 
3019
 
 
3020
  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
 
3021
 
 
3022
  fac_cel.nbr = 0;
 
3023
  fac_cel.val = NULL;
 
3024
 
 
3025
  if (table_def_cel == NULL)
 
3026
    return fac_cel;
 
3027
 
 
3028
  /* Initialisations */
 
3029
 
 
3030
  ecs_table__regle_en_pos(table_def_cel);
 
3031
 
 
3032
  nbr_cel = table_def_cel->nbr;
 
3033
  nbr_fac = table_def_fac->nbr;
 
3034
 
 
3035
  /* Allocation et mise à zéro des connectivités */
 
3036
 
 
3037
  fac_cel.nbr = nbr_fac * 2;
 
3038
 
 
3039
  ECS_MALLOC(fac_cel.val, fac_cel.nbr, ecs_int_t);
 
3040
 
 
3041
  for (ipos = 0; ipos < fac_cel.nbr; ipos++)
 
3042
    fac_cel.val[ipos] = 0;
 
3043
 
 
3044
  /* Boucle sur les cellules : marquage */
 
3045
  /*------------------------------------*/
 
3046
 
 
3047
  for (icel = 0; icel < nbr_cel; icel++ ) {
 
3048
 
 
3049
    for (ipos = table_def_cel->pos[icel] - 1;
 
3050
         ipos < table_def_cel->pos[icel+1] - 1;
 
3051
         ipos++) {
 
3052
 
 
3053
      num_fac = table_def_cel->val[ipos];
 
3054
 
 
3055
      ifac = ECS_ABS(num_fac) - 1;
 
3056
 
 
3057
      if (num_fac > 0) {
 
3058
        assert(fac_cel.val[ifac*2] == 0);
 
3059
        fac_cel.val[ifac*2] = icel + 1;
 
3060
      }
 
3061
      else {
 
3062
        assert(fac_cel.val[ifac*2 + 1] == 0);
 
3063
        fac_cel.val[ifac*2 + 1] = icel + 1;
 
3064
      }
 
3065
 
 
3066
    }
 
3067
 
 
3068
  }
 
3069
 
 
3070
  ecs_table__libere_pos(table_def_cel);
 
3071
 
 
3072
  return fac_cel;
 
3073
}
 
3074
 
 
3075
/*----------------------------------------------------------------------------*/
 
3076