Logo Search packages:      
Sourcecode: ecs version File versions  Download package

ecs_vec_def_perio.c

/*============================================================================
 *  Définitions des fonctions
 *   associées aux structures `ecs_vec_int_t' et `ecs_vec_real_t' décrivant
 *   les vecteurs indexés entier et réel
 *   et propres aux vecteurs indexés
 *      liés aux champs principaux de type "définition"
 *  Ces fonctions participent à la fonctionnalité de "périodicité"
 *============================================================================*/

/*
  This file is part of the Code_Saturne Preprocessor, element of the
  Code_Saturne CFD tool.

  Copyright (C) 1999-2007 EDF S.A., France

  contact: saturne-support@edf.fr

  The Code_Saturne Preprocessor is free software; you can redistribute it
  and/or modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2 of
  the License, or (at your option) any later version.

  The Code_Saturne Preprocessor is distributed in the hope that it will be
  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with the Code_Saturne Preprocessor; if not, write to the
  Free Software Foundation, Inc.,
  51 Franklin St, Fifth Floor,
  Boston, MA  02110-1301  USA
*/


/*----------------------------------------------------------------------------
 *  Fichiers `include' librairie standard C
 *----------------------------------------------------------------------------*/

#include <assert.h>
#include <math.h>


/*----------------------------------------------------------------------------
 *  Fichiers `include' systeme ou BFT
 *----------------------------------------------------------------------------*/

#include <bft_error.h>
#include <bft_mem.h>
#include <bft_printf.h>


/*----------------------------------------------------------------------------
 *  Fichiers `include' visibles du  paquetage global "Utilitaire"
 *----------------------------------------------------------------------------*/

#include "ecs_param_perio_glob.h"
#include "ecs_def.h"
#include "ecs_tab.h"

#include "ecs_fic.h"


/*----------------------------------------------------------------------------
 *  Fichiers `include' visibles des paquetages visibles
 *----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------
 *  Fichiers `include' visibles du  paquetage courant
 *----------------------------------------------------------------------------*/

#include "ecs_vec.h"
#include "ecs_vec_int.h"
#include "ecs_vec_real.h"


/*----------------------------------------------------------------------------
 *  Fichier  `include' du  paquetage courant associe au fichier courant
 *----------------------------------------------------------------------------*/

#include "ecs_vec_def_perio.h"


/*----------------------------------------------------------------------------
 *  Fichiers `include' prives   du  paquetage courant
 *----------------------------------------------------------------------------*/

#include "ecs_vec_int_priv.h"
#include "ecs_vec_real_priv.h"



/*============================================================================
 *                       Prototypes de fonctions privées
 *============================================================================*/

/*----------------------------------------------------------------------------
 *  Fonction qui calcule les nouvelles coordonnees d'un vecteur ou d'un point
 *  dans le cas d'une periodicite.
 *----------------------------------------------------------------------------*/

static ecs_vec_real_t * ecs_loc_vec_def_perio__new_coor
(
 const ecs_vec_real_t    * vec_def,
 const ecs_real_t          translation[3],
 const ecs_real_t          point_inv[3],
 const ecs_real_t          matrice[3][3],
 const ecs_bool_t          periodicite_inverse
) ;


/*----------------------------------------------------------------------------
 *  Fonction qui met à jour la renumérotation
 *  "éléments initiaux -> éléments périodiques" en fonction d'un champ
 *  "éléments précédents -> nouveaux éléments".
 *
 *  Cette fonction est appelée après le pré-nettoyage des éléments,
 *  pour les vecteurs de correspondance des arêtes et des faces.
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__maj_apres_prenet
(
       ecs_vec_int_t      *const vec_elt_perio,
       ecs_vec_int_t      *const vec_elt_old_new,
 const ecs_param_perio_t         param_perio,
       size_t                    nbr_elt_new
) ;


/*----------------------------------------------------------------------------
 *  Fonction renvoyant un booléen selon que la rotation considéré est
 *  symétrie ou non.
 *----------------------------------------------------------------------------*/

static ecs_bool_t ecs_loc_vec_def_perio__rot_est_sym
(
 const ecs_real_t  angle,
 const ecs_real_t  matrice[3][3]
) ;


/*----------------------------------------------------------------------------
 *  Fonction qui ajoute des sommets périodiques
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__ajoute_som
(
       ecs_vec_int_t      *      vec_som_perio,
 const ecs_vec_real_t     *const vec_def_som,
 const ecs_tab_int_t             liste_som_new,
 const ecs_param_perio_t         param_perio
) ;


/*----------------------------------------------------------------------------
 *  Fonction qui vérifie qu'il n'y a pas de faces périodiques se
 *  définissant l'une par l'autre (i.e i->j et j->i).
 *  Si c'est le cas on ne garde que l'un des deux couples.
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__verif
(
 ecs_vec_int_t   * vec_elt_perio
) ;


/*----------------------------------------------------------------------------
 *  Fonction qui définit la correspondance inverse des éléments pour
 *  la périodicité (il faut qu'à un élément lui corresponde un unique
 *  élément)
 *----------------------------------------------------------------------------*/

static ecs_vec_int_t * ecs_loc_vec_def_perio__inv_corresp
(
 const ecs_vec_int_t *const vec_elt_perio
) ;


/*----------------------------------------------------------------------------
 *  Fonction qui décale un vec_elt_perio en fonction d'une renumérotation
 *  des indices de départ (vect_renum).
 *  Il s'agit donc necessairement d'un décalage vers le "bas".
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__decale
(
       ecs_vec_int_t *const vec_elt_perio,
 const ecs_vec_int_t *const vect_renum
) ;


/*----------------------------------------------------------------------------
 *  Fonction renvoyant la "position" du nouvel élément
 *----------------------------------------------------------------------------*/

static ecs_tab_int_t  ecs_loc_vec_def_perio__ret_tab_pos
(
 const ecs_tab_int_t        masque_elt_select,
       size_t        *const nbr_elt_new,
       size_t        *const nbr_elt_perio
) ;



/*============================================================================
 *                             Fonctions publiques
 *============================================================================*/

/*----------------------------------------------------------------------------*
 *  Calcul de la matrice d'une rotation définie par un angle theta (en
 *   radians) et un vecteur unitaire direction.
 *----------------------------------------------------------------------------*/

void ecs_vec_def_perio__mat_rot_3d
(
 ecs_real_t  angle,              /* --> Angle de rotation en degres           */
 ecs_real_t  direction[3],       /* --> Vecteur directeur (unitaire) de l'axe */
 ecs_real_t  matrice[3][3]       /* <-- Matrice definissant la rotation       */
)
{

  /* initialisations */

  ecs_int_t        icoo ;
  ecs_real_t       norme_dir ;

  const ecs_real_t pi = 4 * atan(1) ;
  const ecs_real_t theta = pi * angle/180 ;
  const ecs_real_t cost = cos(theta) ;
  const ecs_real_t sint = sin(theta) ;
  const ecs_real_t unmcost = (1.0 - cost) ;


  /*
   *   La matrice est calculée via la formule suivante :
   *
   *  R = (1-cos(theta))direction.transp(direction) + cos(theta)I + sin(theta)V
   *
   *           [ 0            -direction(3)  direction(2)]
   *  avec V = [ direction(3)       0       -direction(1)]
   *           [-direction(2)  direction(1)       0      ]
   *
   */

  if (ECS_ABS(angle) < 1.e-12)
    return ;


  norme_dir = sqrt(  direction[0]*direction[0]
                   + direction[1]*direction[1]
                   + direction[2]*direction[2]) ;

  assert(norme_dir > 1.e-12) ;

  for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
    direction[icoo] /= norme_dir ;


  /* première ligne de la matrice de rotation */

  matrice[0][0] = (unmcost) * direction[0]*direction[0] + cost                ;
  matrice[0][1] = (unmcost) * direction[0]*direction[1] - sint * direction[2] ;
  matrice[0][2] = (unmcost) * direction[0]*direction[2] + sint * direction[1] ;

  /* deuxième ligne de la matrice de rotation */

  matrice[1][0] = (unmcost) * direction[1]*direction[0] + sint * direction[2] ;
  matrice[1][1] = (unmcost) * direction[1]*direction[1] + cost                ;
  matrice[1][2] = (unmcost) * direction[1]*direction[2] - sint * direction[0] ;

  /* troisième ligne de la matrice de rotation */

  matrice[2][0] = (unmcost) * direction[2]*direction[0] - sint * direction[1] ;
  matrice[2][1] = (unmcost) * direction[2]*direction[1] + sint * direction[0] ;
  matrice[2][2] = (unmcost) * direction[2]*direction[2] + cost                ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui duplique les faces selectionnées pour la périodicité
 *  ainsi que les arêtes et sommets associés. Les distances maximales
 *  associées aux sommets sont aussi dupliquées.
 *----------------------------------------------------------------------------*/

void ecs_vec_def_perio__duplique_def
(
       ecs_vec_int_t      *const  vec_def_fac,
       ecs_vec_int_t      *const  vec_def_are,
       ecs_vec_real_t     *const  vec_def_som,
       ecs_vec_int_t    * *const  vec_fac_perio,
       ecs_vec_int_t    * *const  vec_are_perio,
       ecs_vec_int_t    * *const  vec_som_perio,
 const ecs_tab_int_t           *  tab_fac_select,
       ecs_tab_real_t          *  dist_max_som,
 const ecs_param_perio_t          param_perio
)
{

  size_t           ifac ;
  size_t           ifac_select ;
  size_t           iare ;
  size_t           isom ;
  size_t           icoo ;

  ecs_int_t        ind_fac ;
  ecs_int_t        ind_are ;
  ecs_int_t        ind_som ;

  ecs_int_t        num_are ;
  ecs_int_t        num_som ;

  size_t           nbr_are_fac ;
  size_t           pos_are_fac ;

  size_t           nbr_fac_select ;
  size_t           nbr_are_select ;
  size_t           nbr_som_select ;

  size_t           nbr_fac_new ;
  size_t           nbr_are_new ;
  size_t           nbr_som_new ;

  size_t           nbr_val_fac     ;
  size_t           nbr_val_fac_new ;

  ecs_bool_t       inverse_perio ;

  ecs_tab_int_t    liste_are_select ;
  ecs_tab_int_t    profil_are_sel   ;
  ecs_tab_int_t    profil_som_sel   ;

  ecs_vec_real_t  * vec_def_som_aux ;


  /* Initialisation */

  const size_t  nbr_fac_ini = ecs_vec_int__ret_pos_nbr(vec_def_fac) - 1 ;
  const size_t  nbr_are_ini = ecs_vec_int__ret_pos_nbr(vec_def_are) - 1 ;
  const size_t  nbr_som_ini = ecs_vec_real__ret_pos_nbr(vec_def_som) - 1 ;

  nbr_val_fac     = ecs_vec_int__ret_val_nbr(vec_def_fac) ;
  nbr_val_fac_new = nbr_val_fac ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  /*---------------------------------------------*/
  /* Sélection des arêtes et sommets à dupliquer */
  /*---------------------------------------------*/


  /* Arêtes */
  /*--------*/

  nbr_are_select = 0 ;

  profil_are_sel.nbr = nbr_are_ini ;
  BFT_MALLOC(profil_are_sel.val, profil_are_sel.nbr, ecs_int_t) ;

  liste_are_select.nbr = nbr_are_ini ;
  BFT_MALLOC(liste_are_select.val, liste_are_select.nbr, ecs_int_t) ;

  /* On a besoin d'une liste des numéros des arêtes
     car ils peuvent être négatifs */


  for (iare = 0 ; iare < nbr_are_ini ; iare++) {
    profil_are_sel.val[iare] = 0 ;
    liste_are_select.val[iare] = 0 ;
  }


  for (ifac_select = 0 ;
       ifac_select < tab_fac_select->nbr ; ifac_select++) {

    ind_fac = tab_fac_select->val[ifac_select] ;
    pos_are_fac = vec_def_fac->pos_tab[ind_fac] - 1 ;
    nbr_are_fac = vec_def_fac->pos_tab[ind_fac + 1] - 1 - pos_are_fac ;

    nbr_val_fac_new += nbr_are_fac ;

    for (iare = 0 ; iare < nbr_are_fac ; iare++) {

      num_are = vec_def_fac->val_tab[pos_are_fac + iare] ;
      ind_are = ECS_ABS(num_are) - 1 ;

      if (profil_are_sel.val[ind_are] == 0) {

        profil_are_sel.val[ind_are] = 1 ;
        liste_are_select.val[ind_are] = num_are ;

        nbr_are_select++ ;

      }

    }

  }



  /* Sommets */
  /*---------*/

  nbr_som_select = 0 ;

  profil_som_sel.nbr = nbr_som_ini ;
  BFT_MALLOC(profil_som_sel.val, profil_som_sel.nbr, ecs_int_t) ;


  for (isom = 0 ; isom <  profil_som_sel.nbr; isom++)
    profil_som_sel.val[isom] = 0 ;


  for (iare = 0 ; iare < profil_are_sel.nbr ; iare++) {

    if (profil_are_sel.val[iare] == 1)

      for (isom = 0 ; isom < 2 ; isom++) {

        ind_som =
          vec_def_are->val_tab[vec_def_are->pos_tab[iare] - 1 + isom] - 1 ;

        if (profil_som_sel.val[ind_som] == 0) {

          profil_som_sel.val[ind_som] = 1 ;
          nbr_som_select++ ;

        }

      }

  }


  /* Allocation des vec_elt_perio et redimensionnement des vec_def_elt */

  *vec_fac_perio = ecs_vec_int__alloue(vec_def_fac->pos_nbr,
                                       tab_fac_select->nbr) ;
  *vec_are_perio = ecs_vec_int__alloue(vec_def_are->pos_nbr, nbr_are_select) ;
  *vec_som_perio = ecs_vec_int__alloue(vec_def_som->pos_nbr, nbr_som_select) ;


  nbr_fac_new = nbr_fac_ini + tab_fac_select->nbr ;
  nbr_are_new = nbr_are_ini + nbr_are_select ;
  nbr_som_new = nbr_som_ini + nbr_som_select ;

  ecs_vec_int__redimensionne(vec_def_fac, nbr_fac_new + 1, nbr_val_fac_new) ;
  ecs_vec_int__redimensionne(vec_def_are, nbr_are_new + 1, nbr_are_new * 2) ;


  /*--------------------------------------------------------------------------*/
  /* Duplication des sommets, arêtes et faces dans cet ordre afin de pouvoir  */
  /* référencer les arêtes dupliquer avec les NOUVEAUX numéros des sommets,   */
  /*    ex: avt duplication => arête 5 : sommets 2 4                          */
  /*        apres  "   "    => arête 12 : sommets 8 9 (anciennement 2 et 4)   */
  /*--------------------------------------------------------------------------*/


  /* Sommets */
  /*---------*/


  /* Calcul des nouvelles coordonnées des sommets et on redimensionne
     maintenant vec_def_som au nouveau nombre de sommets              */

  inverse_perio = ECS_FALSE ;

  vec_def_som_aux = ecs_loc_vec_def_perio__new_coor(vec_def_som,
                                                    param_perio.translation,
                                                    param_perio.point_inv,
                                                    param_perio.matrice,
                                                    inverse_perio) ;

  ecs_vec_real__redimensionne(vec_def_som, nbr_som_new + 1, nbr_som_new * 3) ;


  /* On rajoute les sommets périodiques à la fin de vec_def_som */

  nbr_som_select = 0 ;
  (*vec_som_perio)->pos_tab[0] = 1 ;


  for (isom = 0 ; isom < nbr_som_ini ; isom++) {

    if (profil_som_sel.val[isom] == 1) {

      (*vec_som_perio)->val_tab[(*vec_som_perio)->pos_tab[isom] - 1]
        = nbr_som_ini + 1 + nbr_som_select ;

      (*vec_som_perio)->pos_tab[isom + 1]
        = (*vec_som_perio)->pos_tab[isom] + 1 ;


      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)

        vec_def_som->val_tab[vec_def_som->pos_pas * (nbr_som_ini+nbr_som_select)
                             + icoo]
          = vec_def_som_aux->val_tab[vec_def_som_aux->pos_pas * isom + icoo] ;

      nbr_som_select++ ;

    }

    else
      (*vec_som_perio)->pos_tab[isom + 1] = (*vec_som_perio)->pos_tab[isom] ;

  }

  /* On libère les tableaux auxiliaires */

  ecs_vec_real__detruit(vec_def_som_aux) ;

  profil_som_sel.nbr = 0 ;
  BFT_FREE(profil_som_sel.val) ;


  /* Arêtes */
  /*--------*/


  nbr_are_select = 0 ;
  (*vec_are_perio)->pos_tab[0] = 1 ;


  for (iare = 0 ; iare < nbr_are_ini ; iare++) {

    if (profil_are_sel.val[iare] == 1) {

      num_are = liste_are_select.val[iare] ;

      vec_def_are->pos_tab[nbr_are_ini + nbr_are_select + 1] =
        vec_def_are->pos_tab[nbr_are_ini] + 2*(nbr_are_select+1) ;

      (*vec_are_perio)->val_tab[(*vec_are_perio)->pos_tab[iare] - 1] =
        nbr_are_ini + 1 + nbr_are_select ;

      (*vec_are_perio)->pos_tab[iare + 1] =
        (*vec_are_perio)->pos_tab[iare] + 1 ;


      for (isom = 0 ; isom < 2 ; isom++) {

        num_som = vec_def_are->val_tab[(ECS_ABS(num_are)-1) * 2 + isom] ;

        /* Les arêtes dupliquées sont définies dans le même sens que les
           arêtes initiales */

        vec_def_are->val_tab[(nbr_are_ini + nbr_are_select) * 2 + isom]
          = (*vec_som_perio)->val_tab[(*vec_som_perio)->pos_tab[num_som - 1]
                                      - 1] ;

      }

      nbr_are_select++ ;

    }
    else
      (*vec_are_perio)->pos_tab[iare + 1] = (*vec_are_perio)->pos_tab[iare] ;

  }


  /* On libère des tableaux auxiliaires */

  profil_are_sel.nbr = 0 ;
  BFT_FREE(profil_are_sel.val) ;

  liste_are_select.nbr = 0 ;
  BFT_FREE(liste_are_select.val) ;


  /* Faces */
  /*-------*/


  nbr_fac_select = 0 ;
  (*vec_fac_perio)->pos_tab[0] = 1 ;


  /*
    Initialisation du comptage des faces (on marque les positions
    suivant celles des faces périodiques dans vec_fac_perio pour
    pouvoir l'utiliser comme indicateur de sélection
    avant de le remplir avec ses valeurs définitives).
  */

  (*vec_fac_perio)->pos_tab[0] = 1 ;

  for (ifac = 0 ; ifac < nbr_fac_ini ; ifac++)
    (*vec_fac_perio)->pos_tab[ifac + 1] = 0 ;

  for (ifac_select = 0 ; ifac_select < tab_fac_select->nbr ; ifac_select++)
    (*vec_fac_perio)->pos_tab[tab_fac_select->val[ifac_select] + 1] = 1 ;


  for (ifac = 0 ; ifac < nbr_fac_ini ; ifac++) {

    /* Face sélectionnée */

    if ((*vec_fac_perio)->pos_tab[ifac + 1] > 0) {

      pos_are_fac = vec_def_fac->pos_tab[ifac] - 1 ;
      nbr_are_fac = vec_def_fac->pos_tab[ifac + 1] - 1 - pos_are_fac ;

      vec_def_fac->pos_tab[nbr_fac_ini + 1 + nbr_fac_select]
        = vec_def_fac->pos_tab[nbr_fac_ini + nbr_fac_select] + nbr_are_fac ;

      (*vec_fac_perio)->val_tab[(*vec_fac_perio)->pos_tab[ifac] - 1]
        = nbr_fac_ini + 1 + nbr_fac_select ;

      (*vec_fac_perio)->pos_tab[ifac + 1]
        = (*vec_fac_perio)->pos_tab[ifac] + 1 ;


      for (iare = 0 ; iare < nbr_are_fac ; iare++) {

        num_are = vec_def_fac->val_tab[pos_are_fac + iare] ;

        /* Les faces dupliquées sont définies dans le même sens que les
           faces initiales */

        if (num_are > 0)
          num_are =   (*vec_are_perio)->val_tab[
                        (*vec_are_perio)->pos_tab[ECS_ABS(num_are) - 1] - 1] ;
        else
          num_are = - (*vec_are_perio)->val_tab[
                        (*vec_are_perio)->pos_tab[ECS_ABS(num_are) - 1] - 1] ;

        vec_def_fac->val_tab[nbr_val_fac + iare] = num_are ;

      }

      nbr_val_fac += nbr_are_fac ;

      nbr_fac_select++ ;

    }

    /* Face non sélectionnée */

    else

      (*vec_fac_perio)->pos_tab[ifac + 1] = (*vec_fac_perio)->pos_tab[ifac] ;

  }


  /* Duplication des distances maximales associées aux sommets */
  /*-----------------------------------------------------------*/

  dist_max_som->nbr += nbr_som_select ;
  BFT_REALLOC(dist_max_som->val, dist_max_som->nbr, ecs_real_t) ;

  nbr_som_select = 0 ;

  for (isom = 0 ; isom < (*vec_som_perio)->pos_nbr - 1 ; isom++)
    if ((*vec_som_perio)->pos_tab[isom + 1] != (*vec_som_perio)->pos_tab[isom])
      dist_max_som->val[nbr_som_ini + (nbr_som_select++)] =
        dist_max_som->val[isom] ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui duplique les normales aux faces périodiques dupliquées.
 *
 *  La taille du tableau normale_fac est doublée (elle doit initialement
 *  correspondre au nombre de faces sélectionnées, donc au nombre de valeurs
 *  non nulles de vec_fac_perio).
 *----------------------------------------------------------------------------*/

void ecs_vec_def_perio__duplique_norm
(
 const ecs_vec_int_t        *const  vec_fac_perio,
 const ecs_param_perio_t            param_perio,
       float              * *       normale_fac
)
{

  size_t        ifac ;
  size_t        icoo, irot ;

  size_t        nbr_norm_ini ;
  size_t        cpt_norm ;

  float        *normale_ini, *normale_new ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  /* Comptage */

  nbr_norm_ini = ecs_vec_int__ret_val_nbr(vec_fac_perio) ;

  BFT_REALLOC(*normale_fac, nbr_norm_ini*6, float) ;


  /*
     On calcule les nouvelles coordonnées des normales par la transformation
     de périodicité. Les faces sont définies au départ dans le même sens que
     leur correspondant périodique donc si la face a été translatée, la
     normale est identique, et si elle a subi une rotation), la normale
     est tournée du même angle mais n'est PAS translatée (c'est un vecteur).
  */


  if (param_perio.type_perio == ECS_PERIO_TYPE_ROTA) {

    cpt_norm = 0;

    for (ifac = 0 ; ifac < vec_fac_perio->pos_nbr - 1 ; ifac++) {

      if (vec_fac_perio->pos_tab[ifac + 1] != vec_fac_perio->pos_tab[ifac]) {

        normale_ini = *normale_fac + cpt_norm*3;
        normale_new = *normale_fac + (nbr_norm_ini + cpt_norm)*3;

        for (icoo = 0 ; icoo < 3 ; icoo++)
          normale_new[icoo] = 0;

        for (icoo = 0 ; icoo < 3 ; icoo++) {
          for (irot = 0 ; irot < 3 ; irot++)
            normale_new[icoo]
              += param_perio.matrice[icoo][irot]*normale_ini[irot];
        }

        cpt_norm++;

      }

    }

  }

  else {

    /* Cas de la translation : les normales dupliquées sont identiques
       car les faces dupliquées ont été définies dans le même sens */

    normale_ini = *normale_fac ;
    normale_new = *normale_fac + nbr_norm_ini*3 ;

    for (ifac = 0; ifac < nbr_norm_ini; ifac++) {
      normale_new[ifac*3    ] = normale_ini[ifac*3];
      normale_new[ifac*3 + 1] = normale_ini[ifac*3 + 1];
      normale_new[ifac*3 + 2] = normale_ini[ifac*3 + 2];
    }

  }

}


/*----------------------------------------------------------------------------
 *  Traitement spécifique pour la périodicité de rotation de 180 degrés
 *----------------------------------------------------------------------------*/

void ecs_vec_def_perio__trait_spec_sym
(
       ecs_vec_real_t     * *const  vec_def_som,
       ecs_vec_int_t      * *const  vec_fac_perio,
       ecs_vec_int_t      * *const  vec_are_perio,
       ecs_vec_int_t      * *const  vec_som_perio,
 const ecs_tab_int_t                liste_som_new,
 const ecs_param_perio_t            param_perio
)
{

  ecs_bool_t       bool_sym ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  if (param_perio.type_perio == ECS_PERIO_TYPE_ROTA) {


    bool_sym = ecs_loc_vec_def_perio__rot_est_sym(param_perio.angle,
                                                  param_perio.matrice) ;


    if (bool_sym == ECS_TRUE) {

      /* Certains sommets issus d'intersections d'arêtes peuvent être
         périodiques entre eux. On les rajoute donc dans vec_som_perio. */

      ecs_loc_vec_def_perio__ajoute_som(*vec_som_perio,
                                        *vec_def_som,
                                        liste_som_new,
                                        param_perio) ;


      /* Vérification si l'on a un cas périodique du type :
         "elt i -> elt j" et "elt j -> elt i". */

      ecs_loc_vec_def_perio__verif(*vec_fac_perio) ;
      ecs_loc_vec_def_perio__verif(*vec_are_perio) ;
      ecs_loc_vec_def_perio__verif(*vec_som_perio) ;

    }

  }


}


/*----------------------------------------------------------------------------
 *  Fonction qui hérite le recollement dans le cas d'une périodicité
 *----------------------------------------------------------------------------*/

void ecs_vec_def_perio__herite
(
       ecs_vec_int_t      * *const  vec_def_fac,
       ecs_vec_int_t      * *const  vec_def_are,
       ecs_vec_real_t     * *const  vec_def_som,
       ecs_vec_int_t        *const  vec_fac_old_new,
       ecs_vec_int_t        *const  vec_are_old_new,
       ecs_vec_int_t        *const  vec_som_old_new,
       ecs_vec_int_t      * *const  vec_fac_perio,
       ecs_vec_int_t      * *const  vec_are_perio,
       ecs_vec_int_t      * *const  vec_som_perio,
       ecs_tab_int_t        *const  liste_fac_err,
       ecs_tab_int_t        *const  liste_som_new,
 const ecs_param_perio_t            param_perio
)
{
  size_t            ifac     ;
  size_t            issfac   ;
  size_t            iare     ;
  size_t            issare   ;
  size_t            isom     ;
  size_t            isssom   ;
  size_t            icoo     ;
  size_t            ipos     ;
  size_t            ipos_new ;

  ecs_int_t         num_fac   ;
  ecs_int_t         ind_fac   ;
  ecs_int_t         num_are   ;
  ecs_int_t         ind_are   ;
  ecs_int_t         ind_som   ;

  size_t            pos_ssfac_fac ;
  size_t            nbr_ssfac_fac ;

  size_t            pos_are_fac     ;
  size_t            nbr_are_fac     ;

  size_t            pos_ssare_are ;
  size_t            nbr_ssare_are ;

  size_t            pos_sssom_som ;
  size_t            nbr_sssom_som ;

  size_t            pos_som_are ;

  size_t            nbr_val_fac ;
  size_t            nbr_val_are ;
  ecs_int_t         nbr_val_som ;

  size_t            nbr_fac_new ;
  size_t            nbr_are_new ;
  size_t            nbr_som_new ;

  size_t            nbr_fac_perio ;
  size_t            nbr_are_perio ;
  size_t            nbr_som_perio ;

  ecs_bool_t        inverse_perio ;

  ecs_tab_int_t     masque_fac_select ;
  ecs_tab_int_t     masque_are_select ;
  ecs_tab_int_t     masque_som_select ;

  ecs_tab_int_t     tab_pos_elt ;

  ecs_vec_int_t   * vec_def_fac_new   ;
  ecs_vec_int_t   * vec_def_are_new   ;
  ecs_vec_real_t  * vec_def_som_new   ;

  ecs_vec_int_t   * vec_fac_old_new_tmp ;
  ecs_vec_int_t   * vec_are_old_new_tmp ;
  ecs_vec_int_t   * vec_som_old_new_tmp ;

  ecs_vec_int_t   * vec_fac_perio_new ;
  ecs_vec_int_t   * vec_are_perio_new ;
  ecs_vec_int_t   * vec_som_perio_new ;

  ecs_vec_int_t   * vec_are_perio_inv ;
  ecs_vec_int_t   * vec_som_perio_inv ;

  ecs_vec_real_t  * vec_def_som_aux   ;


  const size_t  nbr_fac_ini = ecs_vec_int__ret_pos_nbr(*vec_def_fac) - 1 ;
  const size_t  nbr_are_ini = ecs_vec_int__ret_pos_nbr(*vec_def_are) - 1 ;
  const size_t  nbr_som_ini = ecs_vec_real__ret_pos_nbr(*vec_def_som) - 1 ;

  /* Initialisations */

  masque_fac_select.nbr = nbr_fac_ini ;
  masque_are_select.nbr = nbr_are_ini ;
  masque_som_select.nbr = nbr_som_ini ;

  BFT_MALLOC(masque_fac_select.val, masque_fac_select.nbr, ecs_int_t) ;
  BFT_MALLOC(masque_are_select.val, masque_are_select.nbr, ecs_int_t) ;
  BFT_MALLOC(masque_som_select.val, masque_som_select.nbr, ecs_int_t) ;

  for (ifac = 0 ; ifac < masque_fac_select.nbr ; ifac++)
    masque_fac_select.val[ifac] = 0 ;

  for (iare = 0 ; iare < masque_are_select.nbr ; iare++)
    masque_are_select.val[iare] = 0 ;

  for (isom = 0 ; isom < masque_som_select.nbr ; isom++)
    masque_som_select.val[isom] = 0 ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  /*------------------------------------------------------------------------*/
  /* Sélection des éléments auxquels on va appliquer la périodicité inverse */
  /*------------------------------------------------------------------------*/


  /* Liste des faces */
  /*-----------------*/

  /*
    Distinction entre les "types" de faces :
      - type -1 : face     périodique initiale (supprimée)
      - type  0 : face non périodique (simplement recopiée)
      - type  1 : face     périodique recollée (devant etre héritée)
      - type  2 : face     périodique se voyant elle-même (recopiée une fois)
  */

  for (ifac = 0 ; ifac < (*vec_fac_perio)->pos_nbr - 1 ; ifac++) {

    pos_ssfac_fac = (*vec_fac_perio)->pos_tab[ifac] - 1 ;
    nbr_ssfac_fac = (*vec_fac_perio)->pos_tab[ifac + 1] - 1 - pos_ssfac_fac ;


    if (nbr_ssfac_fac > 0)
      masque_fac_select.val[ifac] = -1 ;


    for (issfac = 0 ; issfac < nbr_ssfac_fac ; issfac++) {

      ind_fac
        = ECS_ABS((*vec_fac_perio)->val_tab[pos_ssfac_fac + issfac]) - 1 ;

      masque_fac_select.val[ind_fac] = 1 ;

    }


    if (   nbr_ssfac_fac == 1
        && (   ECS_ABS((*vec_fac_perio)->val_tab[pos_ssfac_fac])
            == (ecs_int_t)(ifac + 1)))
      masque_fac_select.val[ifac] = 2 ;


  }


  /* Liste des arêtes */
  /*------------------*/

  /* Distinction entre les différents "types" d'arêtes (idem faces) */

  for (iare = 0 ; iare < (*vec_are_perio)->pos_nbr - 1 ; iare++) {

    pos_ssare_are = (*vec_are_perio)->pos_tab[iare] - 1 ;
    nbr_ssare_are = (*vec_are_perio)->pos_tab[iare + 1] - 1 - pos_ssare_are ;


    if (nbr_ssare_are > 0)
      masque_are_select.val[iare] = -1 ;


    for (issare = 0 ; issare < nbr_ssare_are ; issare++) {

      ind_are =
        ECS_ABS((*vec_are_perio)->val_tab[pos_ssare_are + issare]) - 1 ;

      masque_are_select.val[ind_are] = 1 ;

    }


    if (   nbr_ssare_are == 1
        && (   ECS_ABS((*vec_are_perio)->val_tab[pos_ssare_are])
            == (ecs_int_t)(iare + 1)))
      masque_are_select.val[iare] = 2 ;


  }


  /* Liste des sommets */
  /*-------------------*/

  /* Distinction entre les différents "types" de sommets (idem faces) */

  for (isom = 0 ; isom < (*vec_som_perio)->pos_nbr - 1 ; isom++) {

    pos_sssom_som = (*vec_som_perio)->pos_tab[isom] - 1 ;
    nbr_sssom_som = (*vec_som_perio)->pos_tab[isom + 1] - 1 - pos_sssom_som ;


    if (nbr_sssom_som > 0)
      masque_som_select.val[isom] = -1 ;


    for (isssom = 0 ; isssom < nbr_sssom_som ; isssom++) {

      ind_som =
        ECS_ABS((*vec_som_perio)->val_tab[pos_sssom_som + isssom]) - 1 ;

      masque_som_select.val[ind_som] = 1 ;

    }


    if (   nbr_sssom_som == 1
        && (   ECS_ABS((*vec_som_perio)->val_tab[pos_sssom_som])
            == (ecs_int_t)(isom + 1)))
      masque_som_select.val[isom] = 2 ;


  }


  /* Éléments supplémentaires à hériter */
  /*------------------------------------*/

  for (ifac = 0 ; ifac < masque_fac_select.nbr ; ifac++) {

    if (masque_fac_select.val[ifac] == 1) {

      pos_are_fac = (*vec_def_fac)->pos_tab[ifac] - 1 ;
      nbr_are_fac = (*vec_def_fac)->pos_tab[ifac + 1] - 1 - pos_are_fac ;

      for (iare = 0 ; iare < nbr_are_fac ; iare++) {

        ind_are = ECS_ABS((*vec_def_fac)->val_tab[pos_are_fac + iare]) - 1 ;

        if (masque_are_select.val[ind_are] == 0)
          masque_are_select.val[ind_are] = 1 ;


        if (masque_are_select.val[ind_are] == 1) {

          pos_som_are = (*vec_def_are)->pos_tab[ind_are] - 1 ;

          for (isom = 0 ; isom < 2 ; isom++) {

            ind_som = (*vec_def_are)->val_tab[pos_som_are + isom] - 1 ;

            if (masque_som_select.val[ind_som] == 0)
              masque_som_select.val[ind_som] = 1 ;

          } /* fin parcours sommets */

        }

      } /* fin parcours arêtes */

    }

  } /* fin parcours faces */





  /*----------------------*/
  /* Héritage des sommets */
  /*----------------------*/


  /* Calcul des coordonnées inverses des sommets */

  inverse_perio = ECS_TRUE ;

  vec_def_som_aux = ecs_loc_vec_def_perio__new_coor(*vec_def_som,
                                                    param_perio.translation,
                                                    param_perio.point_inv,
                                                    param_perio.matrice,
                                                    inverse_perio) ;


  /* On construit un tableau de position des éléments */

  tab_pos_elt = ecs_loc_vec_def_perio__ret_tab_pos(masque_som_select,
                                                   &nbr_som_new,
                                                   &nbr_som_perio) ;


  /* Allocation de nouvelles structures pour vec_def_som et vec_som_perio */

  vec_som_perio_new = ecs_vec_int__alloue(nbr_som_new + 1, nbr_som_perio) ;
  vec_som_perio_new->pos_tab[0] = 1 ;


  nbr_val_som = ecs_vec_int__ret_val_nbr(*vec_som_perio) ;

  vec_som_old_new_tmp =
    ecs_vec_int__alloue((*vec_def_som)->pos_nbr,
                        (*vec_def_som)->pos_nbr + nbr_val_som) ;
  vec_som_old_new_tmp->pos_tab[0] = 1 ;

  vec_def_som_new =
    ecs_vec_real__alloue(nbr_som_new + 1,
                         nbr_som_new * (*vec_def_som)->pos_pas) ;


  /* Définition des nouveaux sommmets */
  /*----------------------------------*/

  nbr_som_new = 0 ;


  for (isom = 0 ; isom < masque_som_select.nbr ; isom++)

    switch (masque_som_select.val[isom]) {

    case -1:

      /* Sommet périodique initial */

      assert(   (*vec_som_perio)->pos_tab[isom+ 1]
             == (*vec_som_perio)->pos_tab[isom] + 1) ;

      ind_som =
        (*vec_som_perio)->val_tab[(*vec_som_perio)->pos_tab[isom] - 1] - 1 ;

      vec_som_old_new_tmp->val_tab[vec_som_old_new_tmp->pos_tab[isom] - 1] =
        tab_pos_elt.val[ind_som] - 1 ;


      vec_som_old_new_tmp->pos_tab[isom + 1] =
        vec_som_old_new_tmp->pos_tab[isom] + 1 ;

      break ;


    case 0:

      /* Ce n'est pas un sommet périodique, on ne fait rien de spécial */

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vec_def_som_new->val_tab[vec_def_som_new->pos_pas*nbr_som_new + icoo] =
          (*vec_def_som)->val_tab[(*vec_def_som)->pos_pas*isom + icoo] ;


      vec_som_old_new_tmp->val_tab[vec_som_old_new_tmp->pos_tab[isom] - 1] =
        nbr_som_new + 1 ;

      vec_som_old_new_tmp->pos_tab[isom + 1] =
        vec_som_old_new_tmp->pos_tab[isom] + 1 ;


      vec_som_perio_new->pos_tab[nbr_som_new  + 1] =
        vec_som_perio_new->pos_tab[nbr_som_new] ;


      nbr_som_new++ ;

      break ;


    case 1:

      /* Sommet périodique + antécédent ("héritage") */

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vec_def_som_new->val_tab[vec_def_som_new->pos_pas*nbr_som_new + icoo] =
          vec_def_som_aux->val_tab[vec_def_som_aux->pos_pas*isom + icoo] ;


      vec_som_perio_new->val_tab[vec_som_perio_new->pos_tab[nbr_som_new] - 1] =
        nbr_som_new + 2 ;

      vec_som_perio_new->pos_tab[nbr_som_new + 1] =
        vec_som_perio_new->pos_tab[nbr_som_new] + 1 ;


      nbr_som_new++ ;


      /* Sommet périodique */

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vec_def_som_new->val_tab[vec_def_som_new->pos_pas*nbr_som_new + icoo] =
          (*vec_def_som)->val_tab[(*vec_def_som)->pos_pas*isom + icoo] ;


      vec_som_old_new_tmp->val_tab[vec_som_old_new_tmp->pos_tab[isom] - 1] =
        nbr_som_new + 1 ;

      vec_som_old_new_tmp->pos_tab[isom + 1] =
        vec_som_old_new_tmp->pos_tab[isom] + 1 ;


      vec_som_perio_new->pos_tab[nbr_som_new  + 1] =
        vec_som_perio_new->pos_tab[nbr_som_new] ;


      nbr_som_new++ ;

      break ;


    case 2:

      /* Sommet périodique se voyant lui-même */

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vec_def_som_new->val_tab[vec_def_som_new->pos_pas*nbr_som_new + icoo] =
          vec_def_som_aux->val_tab[vec_def_som_aux->pos_pas*isom + icoo] ;


      vec_som_old_new_tmp->val_tab[vec_som_old_new_tmp->pos_tab[isom] - 1] =
        nbr_som_new + 1 ;

      vec_som_old_new_tmp->pos_tab[isom + 1] =
        vec_som_old_new_tmp->pos_tab[isom] + 1 ;


      vec_som_perio_new->val_tab[vec_som_perio_new->pos_tab[nbr_som_new] - 1] =
        nbr_som_new + 1 ;

      vec_som_perio_new->pos_tab[nbr_som_new + 1] =
        vec_som_perio_new->pos_tab[nbr_som_new] + 1 ;


      nbr_som_new++ ;

      break ;


    }


  /* Construction du nouveau vec_som_perio */

  ecs_vec_int__detruit(*vec_som_perio) ;
  *vec_som_perio = vec_som_perio_new ;


  /* Réallocation du nouveau vec_def_som */

  ecs_vec_real__detruit(*vec_def_som) ;
  *vec_def_som = vec_def_som_new ;


  /* Redéfinition des arêtes en fonction de la nouvelle numérotation
     des sommets, et renumérotation de vec_som_old_new */

  ecs_vec_int__remplace_ref(*vec_def_are, vec_som_old_new_tmp) ;
  ecs_vec_int__remplace_ref(vec_som_old_new, vec_som_old_new_tmp) ;


  /* Renumérotation des sommets dans liste_som_new */

  for (isom = 0 ; isom < liste_som_new->nbr ; isom++) {

    ipos = vec_som_old_new_tmp->pos_tab[liste_som_new->val[isom]] - 1 ;
    liste_som_new->val[isom] = vec_som_old_new_tmp->val_tab[ipos] - 1 ;

  }


  /* Libération de structures allouées plus tôt dans la routine */

  masque_som_select.nbr = 0 ;
  BFT_FREE(masque_som_select.val) ;

  tab_pos_elt.nbr = 0 ;
  BFT_FREE(tab_pos_elt.val) ;

  ecs_vec_real__detruit(vec_def_som_aux) ;
  ecs_vec_int__detruit(vec_som_old_new_tmp) ;




  /*----------------------*/
  /* Héritage des aretes */
  /*----------------------*/

  /*
     Découpage des arêtes des faces 'initiales' de la périodicité.
     On a déjà duplique les sommets qui vont définir ces nouvelles
     arêtes et vec_are_perio va nous permettre de connaître la
     correspondance de ces arêtes. On 'duplique' les arêtes des faces
     à dupliquer.
  */


  /* On a besoin du vecteur de correspondance inverse des sommets
     et on construit un tableau de position des éléments */

  vec_som_perio_inv = ecs_loc_vec_def_perio__inv_corresp(*vec_som_perio) ;

  tab_pos_elt = ecs_loc_vec_def_perio__ret_tab_pos(masque_are_select,
                                                   &nbr_are_new,
                                                   &nbr_are_perio) ;


  /* Allocation de nouvelles structures pour vec_def_are et vec_are_perio */

  vec_are_perio_new = ecs_vec_int__alloue(nbr_are_new + 1, nbr_are_perio) ;
  vec_are_perio_new->pos_tab[0] = 1 ;


  nbr_val_are = ecs_vec_int__ret_val_nbr(*vec_are_perio) ;

  vec_are_old_new_tmp =
    ecs_vec_int__alloue((*vec_def_are)->pos_nbr,
                        (*vec_def_are)->pos_nbr + nbr_val_are) ;
  vec_are_old_new_tmp->pos_tab[0] = 1 ;

  vec_def_are_new = ecs_vec_int__alloue(nbr_are_new + 1, nbr_are_new * 2) ;
  vec_def_are_new->pos_tab[0] = 1 ;



  /* Définition des nouvelles arêtes */
  /*---------------------------------*/

  nbr_are_new = 0 ;


  for (iare = 0 ; iare < masque_are_select.nbr ; iare++)

    switch (masque_are_select.val[iare]) {

    case -1:

      /* Arête périodique initiale */

      pos_ssare_are = (*vec_are_perio)->pos_tab[iare] - 1 ;
      nbr_ssare_are = (*vec_are_perio)->pos_tab[iare + 1] - 1 - pos_ssare_are ;

      assert(nbr_ssare_are != 0) ;


      ipos = vec_are_old_new_tmp->pos_tab[iare] - 1 ;


      for (issare = 0 ; issare < nbr_ssare_are ; issare++) {

        num_are = (*vec_are_perio)->val_tab[pos_ssare_are + issare] ;
        ind_are = ECS_ABS(num_are) - 1 ;

        if (num_are > 0)
          vec_are_old_new_tmp->val_tab[ipos + issare] =
             (tab_pos_elt.val[ind_are] - 1) ;
        else
          vec_are_old_new_tmp->val_tab[ipos + issare] =
            -(tab_pos_elt.val[ind_are] - 1) ;

      }


      vec_are_old_new_tmp->pos_tab[iare + 1] =
        vec_are_old_new_tmp->pos_tab[iare] + nbr_ssare_are ;


      break ;


    case 0:

      /* Ce n'est pas une arête périodique, on ne fait rien de spécial */

      ipos     = (*vec_def_are)->pos_tab[iare] - 1 ;
      ipos_new = vec_def_are_new->pos_tab[nbr_are_new] - 1 ;

      for (isom = 0 ; isom < 2 ; isom++) {

        vec_def_are_new->val_tab[ipos_new + isom] =
          (*vec_def_are)->val_tab[ipos + isom] ;

      }

      vec_def_are_new->pos_tab[nbr_are_new + 1] =
        vec_def_are_new->pos_tab[nbr_are_new] + 2 ;


      vec_are_old_new_tmp->val_tab[vec_are_old_new_tmp->pos_tab[iare] - 1] =
        nbr_are_new + 1 ;

      vec_are_old_new_tmp->pos_tab[iare + 1] =
        vec_are_old_new_tmp->pos_tab[iare] + 1 ;


      vec_are_perio_new->pos_tab[nbr_are_new  + 1] =
        vec_are_perio_new->pos_tab[nbr_are_new] ;


      nbr_are_new++ ;

      break ;


    case 1:

      /* Arête périodique + antécédent ("héritage") */

      ipos     = (*vec_def_are)->pos_tab[iare] - 1 ;
      ipos_new = vec_def_are_new->pos_tab[nbr_are_new] - 1 ;


      for (isom = 0 ; isom < 2 ; isom++) {

        ind_som = (*vec_def_are)->val_tab[ipos + isom] - 1 ;

        /* On teste le "sens" de la périodicité car, pour une périodicité
           de rotation de 180 degrés, on ne sait pas à l'avance quel doublon
           à été supprimé */

        if (   vec_som_perio_inv->pos_tab[ind_som]
            != vec_som_perio_inv->pos_tab[ind_som + 1])

          vec_def_are_new->val_tab[ipos_new + isom] =
            vec_som_perio_inv->val_tab[vec_som_perio_inv->pos_tab[ind_som] - 1] ;

        else if (   (*vec_som_perio)->pos_tab[ind_som]
                 != (*vec_som_perio)->pos_tab[ind_som + 1])

          vec_def_are_new->val_tab[ipos_new + isom] =
            (*vec_som_perio)->val_tab[(*vec_som_perio)->pos_tab[ind_som] - 1] ;

        else

          assert(   (   vec_som_perio_inv->pos_tab[ind_som]
                     != vec_som_perio_inv->pos_tab[ind_som + 1])
                 || (   (*vec_som_perio)->pos_tab[ind_som]
                     != (*vec_som_perio)->pos_tab[ind_som + 1])) ;

      }


      vec_def_are_new->pos_tab[nbr_are_new + 1] =
        vec_def_are_new->pos_tab[nbr_are_new] + 2 ;


      vec_are_perio_new->val_tab[vec_are_perio_new->pos_tab[nbr_are_new] - 1] =
        nbr_are_new + 2 ;

      vec_are_perio_new->pos_tab[nbr_are_new + 1] =
        vec_are_perio_new->pos_tab[nbr_are_new] + 1 ;


      nbr_are_new++ ;


      /* Arête périodique */

      ipos     = (*vec_def_are)->pos_tab[iare] - 1 ;
      ipos_new = vec_def_are_new->pos_tab[nbr_are_new] - 1 ;

      for (isom = 0 ; isom < 2 ; isom++) {

        vec_def_are_new->val_tab[ipos_new + isom] =
          (*vec_def_are)->val_tab[ipos + isom] ;

      }

      vec_def_are_new->pos_tab[nbr_are_new + 1] =
        vec_def_are_new->pos_tab[nbr_are_new] + 2 ;


      vec_are_old_new_tmp->val_tab[vec_are_old_new_tmp->pos_tab[iare] - 1] =
        nbr_are_new + 1 ;

      vec_are_old_new_tmp->pos_tab[iare + 1] =
        vec_are_old_new_tmp->pos_tab[iare] + 1 ;


      vec_are_perio_new->pos_tab[nbr_are_new  + 1] =
        vec_are_perio_new->pos_tab[nbr_are_new] ;


      nbr_are_new++ ;

      break ;


    case 2:

      /* Arête périodique se voyant elle-même */

      ipos     = (*vec_def_are)->pos_tab[iare] - 1 ;
      ipos_new = vec_def_are_new->pos_tab[nbr_are_new] - 1 ;

      for (isom = 0 ; isom < 2 ; isom++) {

        vec_def_are_new->val_tab[ipos_new + isom] =
          (*vec_def_are)->val_tab[ipos + isom] ;

      }

      vec_def_are_new->pos_tab[nbr_are_new + 1] =
        vec_def_are_new->pos_tab[nbr_are_new] + 2 ;


      vec_are_old_new_tmp->val_tab[vec_are_old_new_tmp->pos_tab[iare] - 1] =
        nbr_are_new + 1 ;

      vec_are_old_new_tmp->pos_tab[iare + 1] =
        vec_are_old_new_tmp->pos_tab[iare] + 1 ;


      ind_som = vec_def_are_new->val_tab[ipos_new] - 1 ;
      ipos = (*vec_som_perio)->pos_tab[ind_som] - 1 ;

      if (   (((*vec_som_perio)->pos_tab[ind_som + 1] - 1) != ipos)
          && ((*vec_som_perio)->val_tab[ipos] == ind_som + 1))
        vec_are_perio_new->val_tab[vec_are_perio_new->pos_tab[nbr_are_new] - 1]
          =   nbr_are_new + 1 ;
      else
        vec_are_perio_new->val_tab[vec_are_perio_new->pos_tab[nbr_are_new] - 1]

          = -(nbr_are_new + 1) ;

      vec_are_perio_new->pos_tab[nbr_are_new + 1] =
        vec_are_perio_new->pos_tab[nbr_are_new] + 1 ;


      nbr_are_new++ ;

      break ;


    }


  /* Construction du nouveau vec_are_perio */

  ecs_vec_int__detruit(*vec_are_perio) ;
  *vec_are_perio = vec_are_perio_new ;


  /* Réallocation du nouveau vec_def_are */

  ecs_vec_int__detruit(*vec_def_are) ;
  *vec_def_are = vec_def_are_new ;


  /* Redéfinition des faces en fonction de la nouvelle numérotation
     des arêtes, et rénumerotation de vec_are_old_new */

  ecs_vec_int__remplace_ref(*vec_def_fac, vec_are_old_new_tmp) ;
  ecs_vec_int__remplace_ref(vec_are_old_new, vec_are_old_new_tmp) ;


  /* Libération de structures allouées plus tôt dans la routine */

  masque_are_select.nbr = 0 ;
  BFT_FREE(masque_are_select.val) ;

  tab_pos_elt.nbr = 0 ;
  BFT_FREE(tab_pos_elt.val) ;

  ecs_vec_int__detruit(vec_som_perio_inv) ;
  ecs_vec_int__detruit(vec_are_old_new_tmp) ;





  /*--------------------*/
  /* Héritage des faces */
  /*--------------------*/


  /*
     Découpage des faces 'initiales' de la périodicité.
     On a déjà duplique les sommets et les arêtes qui vont définir ces
     nouvelles faces et vec_fac_perio va nous permettre de connaître la
     correspondance de ces faces.
  */

  /* On a besoin du vecteur de correspondance inverse des arêtes
     et on construit un tableau de position des éléments */

  vec_are_perio_inv = ecs_loc_vec_def_perio__inv_corresp(*vec_are_perio) ;

  tab_pos_elt = ecs_loc_vec_def_perio__ret_tab_pos(masque_fac_select,
                                                   &nbr_fac_new,
                                                   &nbr_fac_perio) ;


  /* Allocation de nouvelles structures pour vec_def_fac et vec_fac_perio */

  vec_fac_perio_new = ecs_vec_int__alloue(nbr_fac_new + 1, nbr_fac_perio) ;
  vec_fac_perio_new->pos_tab[0] = 1 ;


  nbr_val_fac = ecs_vec_int__ret_val_nbr(*vec_fac_perio) ;

  vec_fac_old_new_tmp =
    ecs_vec_int__alloue((*vec_def_fac)->pos_nbr,
                        (*vec_def_fac)->pos_nbr + nbr_val_fac) ;
  vec_fac_old_new_tmp->pos_tab[0] = 1 ;


  nbr_val_fac = ecs_vec_int__ret_val_nbr(*vec_def_fac) ;

  vec_def_fac_new = ecs_vec_int__alloue(nbr_fac_new + 1, 2 * nbr_val_fac) ;
  vec_def_fac_new->pos_tab[0] = 1 ;



  /* Définition des nouvelles faces */
  /*--------------------------------*/

  nbr_fac_new = 0 ;


  for (ifac = 0 ; ifac < masque_fac_select.nbr ; ifac++)

    switch (masque_fac_select.val[ifac]) {

    case -1:

      /* Face périodique initiale */

      pos_ssfac_fac = (*vec_fac_perio)->pos_tab[ifac] - 1 ;
      nbr_ssfac_fac = (*vec_fac_perio)->pos_tab[ifac + 1] - 1 - pos_ssfac_fac ;

      assert(nbr_ssfac_fac != 0) ;


      ipos = vec_fac_old_new_tmp->pos_tab[ifac] - 1 ;


      for (issfac = 0 ; issfac < nbr_ssfac_fac ; issfac++) {

        num_fac = (*vec_fac_perio)->val_tab[pos_ssfac_fac + issfac] ;
        ind_fac = ECS_ABS(num_fac) - 1 ;

        if (num_fac > 0)
          vec_fac_old_new_tmp->val_tab[ipos + issfac] =
             (tab_pos_elt.val[ind_fac] - 1) ;
        else
          vec_fac_old_new_tmp->val_tab[ipos + issfac] =
            -(tab_pos_elt.val[ind_fac] - 1) ;

      }


      vec_fac_old_new_tmp->pos_tab[ifac + 1] =
        vec_fac_old_new_tmp->pos_tab[ifac] + nbr_ssfac_fac ;


      break ;


    case 0:

      /* Ce n'est pas une face périodique, on ne fait rien de spécial */

      ipos     = (*vec_def_fac)->pos_tab[ifac] - 1 ;
      ipos_new = vec_def_fac_new->pos_tab[nbr_fac_new] - 1 ;
      nbr_are_fac = (*vec_def_fac)->pos_tab[ifac + 1] - 1 - ipos ;

      for (iare = 0 ; iare < nbr_are_fac ; iare++) {

        vec_def_fac_new->val_tab[ipos_new + iare] =
          (*vec_def_fac)->val_tab[ipos + iare] ;

      }

      vec_def_fac_new->pos_tab[nbr_fac_new + 1] =
        vec_def_fac_new->pos_tab[nbr_fac_new] + nbr_are_fac ;


      vec_fac_old_new_tmp->val_tab[vec_fac_old_new_tmp->pos_tab[ifac] - 1] =
        nbr_fac_new + 1 ;

      vec_fac_old_new_tmp->pos_tab[ifac + 1] =
        vec_fac_old_new_tmp->pos_tab[ifac] + 1 ;


      vec_fac_perio_new->pos_tab[nbr_fac_new  + 1] =
        vec_fac_perio_new->pos_tab[nbr_fac_new] ;


      nbr_fac_new++ ;

      break ;


    case 1:

      /* Face périodique + antécédent ("héritage") */

      ipos     = (*vec_def_fac)->pos_tab[ifac] - 1 ;
      ipos_new = vec_def_fac_new->pos_tab[nbr_fac_new] - 1 ;
      nbr_are_fac = (*vec_def_fac)->pos_tab[ifac + 1] - 1 - ipos ;


      for (iare = 0 ; iare < nbr_are_fac ; iare++) {

        num_are = (*vec_def_fac)->val_tab[ipos + iare] ;
        ind_are = ECS_ABS(num_are) - 1 ;


        /* On teste le "sens" de la périodicité car, pour une périodicité
           de rotation de 180 degrés, on ne sait pas à l'avance quel doublon
           à été supprimé */

         if(   vec_are_perio_inv->pos_tab[ind_are]
           != vec_are_perio_inv->pos_tab[ind_are + 1]) {

          if (num_are > 0)
            vec_def_fac_new->val_tab[ipos_new + iare] =
               vec_are_perio_inv->val_tab[vec_are_perio_inv->pos_tab[ind_are]
                                          - 1] ;
          else
            vec_def_fac_new->val_tab[ipos_new + iare] =
              -vec_are_perio_inv->val_tab[vec_are_perio_inv->pos_tab[ind_are]
                                          - 1] ;

        }
         else if(   (*vec_are_perio)->pos_tab[ind_are]
                != (*vec_are_perio)->pos_tab[ind_are + 1]) {

          if (num_are > 0)
            vec_def_fac_new->val_tab[ipos_new + iare] =
               (*vec_are_perio)->val_tab[(*vec_are_perio)->pos_tab[ind_are]
                                         - 1] ;
          else
            vec_def_fac_new->val_tab[ipos_new + iare] =
              -(*vec_are_perio)->val_tab[(*vec_are_perio)->pos_tab[ind_are]
                                         - 1] ;

        }
        else

          assert(   (   vec_are_perio_inv->pos_tab[ind_are]
                     != vec_are_perio_inv->pos_tab[ind_are + 1])
                 || (   (*vec_are_perio)->pos_tab[ind_are]
                     != (*vec_are_perio)->pos_tab[ind_are + 1])) ;


      }


      vec_def_fac_new->pos_tab[nbr_fac_new + 1] =
        vec_def_fac_new->pos_tab[nbr_fac_new] + nbr_are_fac ;


      vec_fac_perio_new->val_tab[vec_fac_perio_new->pos_tab[nbr_fac_new] - 1] =
        nbr_fac_new + 2 ;

      vec_fac_perio_new->pos_tab[nbr_fac_new + 1] =
        vec_fac_perio_new->pos_tab[nbr_fac_new] + 1 ;


      nbr_fac_new++ ;


      /* Face périodique */

      ipos     = (*vec_def_fac)->pos_tab[ifac] - 1 ;
      ipos_new = vec_def_fac_new->pos_tab[nbr_fac_new] - 1 ;
      nbr_are_fac = (*vec_def_fac)->pos_tab[ifac + 1] - 1 - ipos ;

      for (iare = 0 ; iare < nbr_are_fac ; iare++) {

        vec_def_fac_new->val_tab[ipos_new + iare] =
          (*vec_def_fac)->val_tab[ipos + iare] ;

      }

      vec_def_fac_new->pos_tab[nbr_fac_new + 1] =
        vec_def_fac_new->pos_tab[nbr_fac_new] + nbr_are_fac ;


      vec_fac_old_new_tmp->val_tab[vec_fac_old_new_tmp->pos_tab[ifac] - 1] =
        nbr_fac_new + 1 ;

      vec_fac_old_new_tmp->pos_tab[ifac + 1] =
        vec_fac_old_new_tmp->pos_tab[ifac] + 1 ;


      vec_fac_perio_new->pos_tab[nbr_fac_new  + 1] =
        vec_fac_perio_new->pos_tab[nbr_fac_new] ;


      nbr_fac_new++ ;

      break ;


    case 2:

      /* Face périodique se voyant elle-même */

      ipos     = (*vec_def_fac)->pos_tab[ifac] - 1 ;
      ipos_new = vec_def_fac_new->pos_tab[nbr_fac_new] - 1 ;
      nbr_are_fac = (*vec_def_fac)->pos_tab[ifac + 1] - 1 - ipos ;

      for (iare = 0 ; iare < nbr_are_fac ; iare++) {

        vec_def_fac_new->val_tab[ipos_new + iare] =
          (*vec_def_fac)->val_tab[ipos + iare] ;

      }

      vec_def_fac_new->pos_tab[nbr_fac_new + 1] =
        vec_def_fac_new->pos_tab[nbr_fac_new] + nbr_are_fac ;


      vec_fac_old_new_tmp->val_tab[vec_fac_old_new_tmp->pos_tab[ifac] - 1] =
        nbr_fac_new + 1 ;

      vec_fac_old_new_tmp->pos_tab[ifac + 1] =
        vec_fac_old_new_tmp->pos_tab[ifac] + 1 ;


      vec_fac_perio_new->val_tab[vec_fac_perio_new->pos_tab[nbr_fac_new] - 1] =
        -(nbr_fac_new + 1) ;

      vec_fac_perio_new->pos_tab[nbr_fac_new + 1] =
        vec_fac_perio_new->pos_tab[nbr_fac_new] + 1 ;


      nbr_fac_new++ ;

      break ;


    }


  /* Construction du nouveau vec_fac_perio */

  ecs_vec_int__detruit(*vec_fac_perio) ;
  *vec_fac_perio = vec_fac_perio_new ;


  /* Réallocation du nouveau vec_def_fac */

  ecs_vec_int__detruit(*vec_def_fac) ;
  *vec_def_fac = vec_def_fac_new ;


  /* Renumérotation de vec_fac_old_new */

  ecs_vec_int__remplace_ref(vec_fac_old_new, vec_fac_old_new_tmp) ;


  /* Renumérotation éventuelle de liste_fac_err */

  if (liste_fac_err != NULL)

    for (ifac = 0 ; ifac < liste_fac_err->nbr ; ifac++) {

      ipos = vec_fac_old_new_tmp->pos_tab[liste_fac_err->val[ifac]] - 1 ;

      liste_fac_err->val[ifac] =
        ECS_ABS(vec_fac_old_new_tmp->val_tab[ipos]) - 1 ;

    }


  /* Libération de structures allouées plus tôt dans la routine */

  masque_fac_select.nbr = 0 ;
  BFT_FREE(masque_fac_select.val) ;

  tab_pos_elt.nbr = 0 ;
  BFT_FREE(tab_pos_elt.val) ;

  ecs_vec_int__detruit(vec_are_perio_inv) ;
  ecs_vec_int__detruit(vec_fac_old_new_tmp) ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui nettoie les éléments dupliqués n'ayant pas participé au
 *  recollement périodique
 *
 *  Attention : cette fonction doit être appellée un nombre pair de fois
 *              (deux fois par périodicité) et contient un compteur statique
 *              égal au nombre d'appels modulo 2 + 1 à cet effet.
 *----------------------------------------------------------------------------*/

void ecs_vec_def_perio__nettoie
(
       ecs_vec_int_t    * *const  vec_def_fac,
       ecs_vec_int_t    * *const  vec_def_are,
       ecs_vec_real_t   * *const  vec_def_som,
       ecs_vec_int_t      *const  vec_fac_old_new,
       ecs_vec_int_t      *const  vec_are_old_new,
       ecs_vec_int_t      *const  vec_fac_perio,
       ecs_vec_int_t      *const  vec_are_perio,
       ecs_vec_int_t      *const  vec_som_perio,
       ecs_tab_int_t      *const  liste_fac_err,
       ecs_tab_int_t      *const  liste_som_new,
 const ecs_param_perio_t          param_perio
)
{

  size_t            ifac ;
  size_t            iare ;
  size_t            isom ;
  size_t            iloc ;

  size_t            ind_fac ;
  size_t            ind_are ;
  size_t            ind_som ;

  size_t            nbr_fac_new ;
  size_t            nbr_som_new ;

  size_t            nbr_val_fac ;
  size_t            nbr_val_are ;
  size_t            nbr_val_som ;

  size_t            pos_ssfac_fac ;
  size_t            nbr_ssfac_fac ;

  size_t            pos_are_fac ;
  size_t            nbr_are_fac ;

  size_t            pos_som_are ;
  size_t            nbr_som_are ;

  size_t            cpt_err ;

  ecs_bool_t        bool_err ;

  ecs_tab_bool_t    profil_fac  ;
  ecs_tab_bool_t    profil_are  ;
  ecs_tab_bool_t    profil_som  ;

  ecs_tab_int_t     tab_cpt_fac ;
  ecs_tab_int_t     liste_fac_dupl_err ;

  ecs_vec_int_t   * vec_def_fac_new ;
  ecs_vec_int_t   * vec_def_are_new ;
  ecs_vec_real_t  * vec_def_som_new ;

  ecs_vec_int_t   * vect_renum     ;
  ecs_vec_int_t   * vect_renum_err ;

  static int  ipass = 0 ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  /* Incrémentation de l'indice de passage dans la routine */

  ipass = (ipass % 2) + 1 ;


  /*-------------------------------------*/
  /* Traitement spécifique pré-nettoyage */
  /*-------------------------------------*/

  if (ipass == 1) {

  /* Mise à jour des références aux éléments dans le cas d'un "pré-nettoyage".
     On ne s'occupe pour l'instant pas de renuméroter les éléments eux-mêmes,
     i.e pas de décalage du tableau des positions. */

    ecs_vec_int__remplace_ref(vec_fac_perio, vec_fac_old_new) ;
    ecs_vec_int__remplace_ref(vec_are_perio, vec_are_old_new) ;

  }


  /*------------------------------------*/
  /* Sélection et suppression des faces */
  /*------------------------------------*/


  /* Sélection des faces */
  /*---------------------*/

  /*
     On choisit de garder parmi les faces dupliquées (et éventuellement
     découpées après recollement), celles qui sont issues de 2 faces :
     une du maillage initial et une dupliquée. Celles-ci apparaissent 2
     fois dans le tableau des valeurs de vec_fac_old_new.
  */


  tab_cpt_fac.nbr = ecs_vec_int__ret_pos_nbr((*vec_def_fac)) - 1 ;
  BFT_MALLOC(tab_cpt_fac.val, tab_cpt_fac.nbr, ecs_int_t) ;

  for (ifac = 0 ; ifac < tab_cpt_fac.nbr ; ifac++)
    tab_cpt_fac.val[ifac] = 0 ;


  profil_fac.nbr = ecs_vec_int__ret_pos_nbr((*vec_def_fac)) - 1 ;
  BFT_MALLOC(profil_fac.val, profil_fac.nbr, ecs_bool_t) ;

  for (ifac = 0 ; ifac < profil_fac.nbr ; ifac++)
    profil_fac.val[ifac] = ECS_TRUE ;


  nbr_val_fac = ecs_vec_int__ret_val_nbr(vec_fac_old_new) ;


  for (ifac = 0 ; ifac < nbr_val_fac ; ifac++)
    tab_cpt_fac.val[ECS_ABS(vec_fac_old_new->val_tab[ifac]) - 1] += 1 ;


  /* On crée le profil des faces à supprimer */

  if (ipass == 1) {

    /* Premier passage : suppression des faces n'ayant pas participé au
       recollement et ne servant pas à l'héritage */

    for (ifac = 0 ; ifac < vec_fac_perio->pos_nbr - 1 ; ifac++) {

      pos_ssfac_fac = vec_fac_perio->pos_tab[ifac    ] - 1 ;
      nbr_ssfac_fac = vec_fac_perio->pos_tab[ifac + 1] - 1 - pos_ssfac_fac ;

      if (nbr_ssfac_fac == 1) {

        ind_fac = ECS_ABS(vec_fac_perio->val_tab[pos_ssfac_fac]) - 1 ;

        if (tab_cpt_fac.val[ind_fac] == 1)
          profil_fac.val[ind_fac] = ECS_FALSE ;

      }

    }


  }
  else if (ipass == 2) {

    /* Deuxième passage : suppression des dernières faces inutiles */

    for (ifac = 0 ;
         ifac < vec_fac_perio->pos_tab[vec_fac_perio->pos_nbr - 1] - 1 ;
         ifac++) {

      ind_fac = ECS_ABS(vec_fac_perio->val_tab[ifac]) - 1 ;

      if (tab_cpt_fac.val[ind_fac] == 1)
        profil_fac.val[ind_fac] = ECS_FALSE ;

    }

  }
  else {

    assert(ipass == 1 || ipass == 2) ;

  }


  tab_cpt_fac.nbr = 0 ;
  BFT_FREE(tab_cpt_fac.val) ;


  /*
    On conserve les faces avec erreur (car sinon on pourrait ne pas avoir
    de part Ensight, si cela concernait des faces dupliquées).

    Attention ! On supprime ces faces du vecteur de correspondance des faces
    périodiques MAIS pas de ceux concernant les arêtes et les sommets.
    Il faudrait en tenir compte s'il on désirait conserver ces vecteurs.
  */

  cpt_err = 0 ;

  if (liste_fac_err != NULL) {

    /* On compte d'abord les candidats potentiels */

    for (ifac = 0 ; ifac < liste_fac_err->nbr ; ifac++)
      if (profil_fac.val[liste_fac_err->val[ifac]] == ECS_FALSE)
        cpt_err += 1 ;

    /* On les stocke ensuite dans une liste */

    if (cpt_err > 0) {

      liste_fac_dupl_err.nbr = cpt_err ;
      BFT_MALLOC(liste_fac_dupl_err.val, cpt_err, ecs_int_t) ;

      cpt_err = 0 ;


      for (ifac = 0 ; ifac < liste_fac_err->nbr ; ifac++) {

        ind_fac = liste_fac_err->val[ifac] ;

        if (profil_fac.val[ind_fac] == ECS_FALSE){

          profil_fac.val[ind_fac] = ECS_TRUE ;
          liste_fac_dupl_err.val[cpt_err++] = ind_fac ;

        }

      }

    }

  }




  /* Nettoyage des faces */
  /*---------------------*/


  nbr_val_fac = ecs_vec_int__ret_val_nbr(*vec_def_fac) ;
  vec_def_fac_new = ecs_vec_int__alloue((*vec_def_fac)->pos_nbr, nbr_val_fac) ;

  vect_renum = ecs_vec_int__extrait(vec_def_fac_new,
                                    *vec_def_fac,
                                    profil_fac) ;


  ecs_vec_int__detruit(*vec_def_fac) ;
  *vec_def_fac = vec_def_fac_new ;


  profil_fac.nbr = 0 ;
  BFT_FREE(profil_fac.val) ;


  /* Renumérotation de vec_fac_old_new */

  ecs_vec_int__remplace_ref(vec_fac_old_new, vect_renum) ;


  /* Renumérotation éventuelle de liste_fac_err */

  if (liste_fac_err != NULL) {

    size_t  nbr_fac_err = 0 ;


    for (ifac = 0 ; ifac < liste_fac_err->nbr ; ifac++) {

      ind_fac = liste_fac_err->val[ifac] ;

      if (vect_renum->pos_tab[ind_fac + 1] != vect_renum->pos_tab[ind_fac])
        liste_fac_err->val[nbr_fac_err++] =
          ECS_ABS(vect_renum->val_tab[vect_renum->pos_tab[ind_fac] - 1]) - 1 ;

    }

    liste_fac_err->nbr = nbr_fac_err ;
    BFT_REALLOC(liste_fac_err->val, liste_fac_err->nbr, ecs_int_t) ;


    /* On s'occupe ici de nettoyer le vecteur de correspondance des faces
       périodiques d'éventuelles faces dupliquées de liste_fac_err. */

    if (cpt_err > 0) {

      nbr_val_are = ecs_vec_int__ret_val_nbr(vect_renum) ;
      vect_renum_err = ecs_vec_int__alloue(vect_renum->pos_nbr, nbr_val_are) ;

      vect_renum_err->pos_tab[0] = 1 ;

      for (ifac = 0 ; ifac < vect_renum->pos_nbr - 1 ; ifac++) {

        bool_err = ECS_FALSE ;

        for (iloc = 0 ;
             bool_err != ECS_TRUE && iloc < liste_fac_dupl_err.nbr ;
             iloc++) {

          if (liste_fac_dupl_err.val[iloc] == (ecs_int_t)ifac)
            bool_err = ECS_TRUE ;

        }

        if (bool_err == ECS_FALSE) {

          if (vect_renum->pos_tab[ifac + 1] != vect_renum->pos_tab[ifac]) {

            vect_renum_err->val_tab[vect_renum_err->pos_tab[ifac] - 1] =
              vect_renum->val_tab[vect_renum->pos_tab[ifac] - 1] ;

            vect_renum_err->pos_tab[ifac + 1] =
              vect_renum_err->pos_tab[ifac] + 1 ;

          }
          else
            vect_renum_err->pos_tab[ifac + 1] = vect_renum_err->pos_tab[ifac] ;

        }
        else
          vect_renum_err->pos_tab[ifac + 1] = vect_renum_err->pos_tab[ifac] ;

      }


      liste_fac_dupl_err.nbr = 0 ;
      BFT_FREE(liste_fac_dupl_err.val) ;

      ecs_vec_int__detruit(vect_renum) ;

    } /* Fin si (cpt_err > 0) */

  } /* Fin si (liste_fac_err != NULL) */


  /* Renumérotation et redimensionnement de vec_fac_perio.
     On utilise l'un ou l'autre des 'vect_renum' selon les cas. */

  if (cpt_err > 0) {

    ecs_vec_int__remplace_ref(vec_fac_perio, vect_renum_err) ;
    ecs_loc_vec_def_perio__decale(vec_fac_perio, vect_renum_err) ;

    ecs_vec_int__detruit(vect_renum_err) ;

  }
  else {

    ecs_vec_int__remplace_ref(vec_fac_perio, vect_renum) ;
    ecs_loc_vec_def_perio__decale(vec_fac_perio, vect_renum) ;

    ecs_vec_int__detruit(vect_renum) ;

  }




  /*-------------------------------------*/
  /* Sélection et suppression des arêtes */
  /*-------------------------------------*/


  /* Sélection des arêtes */
  /*----------------------*/

  /* On choisit les arêtes à garder parmi les faces que l'on a conservé */

  profil_are.nbr = ecs_vec_int__ret_pos_nbr((*vec_def_are)) - 1 ;
  BFT_MALLOC(profil_are.val, profil_are.nbr, ecs_bool_t) ;

  for (iare = 0 ; iare < profil_are.nbr ; iare++)
    profil_are.val[iare] = ECS_FALSE ;


  for (ifac = 0 ; ifac < (*vec_def_fac)->pos_nbr - 1 ; ifac++) {

    pos_are_fac = (*vec_def_fac)->pos_tab[ifac    ] - 1 ;
    nbr_are_fac = (*vec_def_fac)->pos_tab[ifac + 1] - 1 -pos_are_fac ;

    for (iare = 0 ; iare < nbr_are_fac ; iare++) {

      ind_are = ECS_ABS((*vec_def_fac)->val_tab[pos_are_fac + iare]) - 1 ;

      if (profil_are.val[ind_are] == ECS_FALSE)
        profil_are.val[ind_are] = ECS_TRUE ;

    }

  }



  /* Nettoyage des arêtes */
  /*----------------------*/


  nbr_val_are = ecs_vec_int__ret_val_nbr(*vec_def_are) ;
  vec_def_are_new = ecs_vec_int__alloue((*vec_def_are)->pos_nbr, nbr_val_are) ;

  vect_renum = ecs_vec_int__extrait(vec_def_are_new,
                                    *vec_def_are,
                                    profil_are) ;


  ecs_vec_int__detruit(*vec_def_are) ;
  *vec_def_are = vec_def_are_new ;


  profil_are.nbr = 0 ;
  BFT_FREE(profil_are.val) ;


  /* Renumérotation des arêtes dans la définition des faces */

  ecs_vec_int__remplace_ref(*vec_def_fac, vect_renum) ;


  /* Renumérotation de vec_are_old_new */

  ecs_vec_int__remplace_ref(vec_are_old_new, vect_renum) ;


  /* Renumérotation et redimensionnement de vec_are_perio */

  ecs_vec_int__remplace_ref(vec_are_perio, vect_renum) ;
  ecs_loc_vec_def_perio__decale(vec_are_perio,vect_renum) ;

  ecs_vec_int__detruit(vect_renum) ;




  /*--------------------------------------*/
  /* Sélection et suppression des sommets */
  /*--------------------------------------*/


  /* Sélection des sommets */
  /*-----------------------*/

  /* On choisit les sommets à garder parmi les arêtes que l'on a conservé */

  profil_som.nbr = ecs_vec_real__ret_pos_nbr((*vec_def_som)) - 1 ;
  BFT_MALLOC(profil_som.val, profil_som.nbr, ecs_bool_t) ;

  for (isom = 0 ; isom < profil_som.nbr ; isom++)
    profil_som.val[isom] = ECS_FALSE ;


  for (iare = 0 ; iare < (*vec_def_are)->pos_nbr - 1 ; iare++) {

    pos_som_are = (*vec_def_are)->pos_tab[iare    ] - 1 ;
    nbr_som_are = (*vec_def_are)->pos_tab[iare + 1] - 1 - pos_som_are ;

    for (isom = 0 ; isom < nbr_som_are ; isom++) {

      ind_som = (*vec_def_are)->val_tab[pos_som_are + isom] - 1 ;

      if (profil_som.val[ind_som] == ECS_FALSE)
        profil_som.val[ind_som] = ECS_TRUE ;

    }

  }



  /* Nettoyage des sommets */
  /*-----------------------*/


  nbr_val_som = ecs_vec_real__ret_val_nbr(*vec_def_som) ;
  vec_def_som_new = ecs_vec_real__alloue((*vec_def_som)->pos_nbr, nbr_val_som) ;

  vect_renum = ecs_vec_real__extrait(vec_def_som_new,
                                     *vec_def_som,
                                     profil_som) ;


  ecs_vec_real__detruit(*vec_def_som) ;
  *vec_def_som = vec_def_som_new ;


  profil_som.nbr = 0 ;
  BFT_FREE(profil_som.val) ;


  /* Renumérotation des sommets dans la définition des arêtes */

  ecs_vec_int__remplace_ref(*vec_def_are, vect_renum) ;


  /* Renumérotation des sommets dans liste_som_new */

  nbr_som_new = 0 ;

  for (isom = 0 ; isom < liste_som_new->nbr ; isom++) {

    ind_som = liste_som_new->val[isom] ;

    if (vect_renum->pos_tab[ind_som + 1] != vect_renum->pos_tab[ind_som])
      liste_som_new->val[nbr_som_new++] =
        vect_renum->val_tab[vect_renum->pos_tab[ind_som] - 1] - 1 ;

  }

  liste_som_new->nbr = nbr_som_new ;
  BFT_REALLOC(liste_som_new->val, liste_som_new->nbr, ecs_int_t) ;


  /* Renumérotation et redimensionnement de vec_som_perio */

  ecs_vec_int__remplace_ref(vec_som_perio, vect_renum) ;
  ecs_loc_vec_def_perio__decale(vec_som_perio, vect_renum) ;

  ecs_vec_int__detruit(vect_renum) ;



  /*-------------------------------------*/
  /* Traitement spécifique pré-nettoyage */
  /*-------------------------------------*/

  if (ipass == 1) {

    /* On met à jour les vecteurs de correspondances périodiques */

    const size_t  nbr_fac = ecs_vec_int__ret_pos_nbr(*vec_def_fac) - 1 ;
    const size_t  nbr_are = ecs_vec_int__ret_pos_nbr(*vec_def_are) - 1 ;

    ecs_loc_vec_def_perio__maj_apres_prenet(vec_fac_perio,
                                            vec_fac_old_new,
                                            param_perio,
                                            nbr_fac) ;

    ecs_loc_vec_def_perio__maj_apres_prenet(vec_are_perio,
                                            vec_are_old_new,
                                            param_perio,
                                            nbr_are) ;

  }



  /*---------------------------------------*/
  /* Traitement spécifique nettoyage final */
  /*---------------------------------------*/

  /* On rajoute à la liste des sommets nouveaux les sommets correspondants
     des faces périodiques 'initiales' à l'aide de vec_som_perio           */

  if (ipass == 2) {

    size_t           ipos ;
    size_t           isom_new ;

    ecs_bool_t       bool_sortie ;

    ecs_vec_int_t  * vec_som_perio_inv ;


    vec_som_perio_inv = ecs_loc_vec_def_perio__inv_corresp(vec_som_perio) ;

    ipos = 0 ;
    nbr_som_new = liste_som_new->nbr ;

    liste_som_new->nbr = 2*nbr_som_new ;
    BFT_REALLOC(liste_som_new->val, liste_som_new->nbr, ecs_int_t) ;


    for (isom = 0 ; isom < nbr_som_new ; isom++) {

      ind_som = liste_som_new->val[isom] ;

      /* Test pour une périodicite de rotation de 180 degrés */

      if (   vec_som_perio_inv->pos_tab[ind_som + 1]
          != vec_som_perio_inv->pos_tab[ind_som]) {

        ind_som =
          vec_som_perio_inv->val_tab[vec_som_perio_inv->pos_tab[ind_som] - 1]
          - 1 ;

        bool_sortie = ECS_FALSE ;

        for (isom_new = 0 ; !bool_sortie && isom_new < nbr_som_new ; isom_new++)
          if (ind_som == (size_t)(liste_som_new->val[isom_new]))
            bool_sortie = ECS_TRUE ;

        if (bool_sortie == ECS_FALSE)
          liste_som_new->val[nbr_som_new + ipos++] = ind_som ;

      }

    }


    liste_som_new->nbr = nbr_som_new + ipos ;
    BFT_REALLOC(liste_som_new->val, liste_som_new->nbr, ecs_int_t) ;

    ecs_vec_int__detruit(vec_som_perio_inv) ;

  }


  /*
    Pour pouvoir faire la différence entre les faces nouvelles et les faces
    modifiées, il faut redimensionner vec_fac_old_new en lui ajoutant le
    nombre de faces correspondant au cas où l'on aurait fait la périodicité
    dans l'autre sens. En effet, on repère les faces nouvelles dans un
    recollement par le fait qu'elles sont issues de deux faces et donc
    qu'elles apparaissent deux fois dans vec_fac_old_new.
    On obtient le nombre de faces de la manière suivante :
    -> nbr_fac = tab_fac_select.nbr - 2*nbr_fac_perio
    De manière plus simple, on redimensionne à la fin de la routine,
    mais en n'utilisant qu'une seule face ; comme si elle avait généré
    toutes les faces périodiques (dans le sens inverse).
  */


  if (ipass == 2) {

    nbr_val_fac = ecs_vec_int__ret_val_nbr(vec_fac_old_new) ;

    ecs_vec_int__redimensionne(vec_fac_old_new,
                               vec_fac_old_new->pos_nbr + 1,
                               2*nbr_val_fac) ;


    nbr_fac_new = 0 ;

    for (ifac = 0 ; ifac < vec_fac_perio->pos_nbr - 1 ; ifac++)
      if (vec_fac_perio->pos_tab[ifac + 1] != vec_fac_perio->pos_tab[ifac])
        vec_fac_old_new->val_tab[nbr_val_fac + nbr_fac_new++] = ifac + 1;


    vec_fac_old_new->pos_tab[vec_fac_old_new->pos_nbr - 1] =
      vec_fac_old_new->pos_tab[vec_fac_old_new->pos_nbr - 2] + nbr_fac_new ;


    ecs_vec_int__redimensionne(vec_fac_old_new,
                               vec_fac_old_new->pos_nbr,
                               nbr_val_fac + nbr_fac_new) ;

  }


}


/*----------------------------------------------------------------------------
 *  Fonction qui liste parmi les faces périodiques celles qui se "voient"
 *  elles-mêmes (i.e  "i -> i").
 *----------------------------------------------------------------------------*/

void ecs_vec_def_perio__lis_fac_err
(
 const ecs_vec_int_t   *const vec_fac_perio,
       ecs_tab_int_t   *const liste_fac_err
)
{

  size_t   ifac ;
  size_t   ind_fac ;

  size_t   nbr_fac_err ;
  size_t   nbr_fac_err_old ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  nbr_fac_err = 0 ;

  for (ifac = 0 ; ifac < vec_fac_perio->pos_nbr - 1 ; ifac++)

    if (vec_fac_perio->pos_tab[ifac + 1] != vec_fac_perio->pos_tab[ifac]) {

      ind_fac =
        ECS_ABS(vec_fac_perio->val_tab[vec_fac_perio->pos_tab[ifac] - 1]) - 1 ;

      if (ifac == ind_fac)
        nbr_fac_err += 1 ;

    }



  /* S'il y a un problème pour une ou plusieurs faces */

  if (nbr_fac_err > 0) {

    ecs_warn() ;
    bft_printf(_("Problem for %d periodic face(s). These faces are their own "
                 "periodic\ncorrespondants. The computation with Code_Saturne "
                 "will not be possible.\n-> The rotation axis must not "
                 "bisect a face."), nbr_fac_err) ;


    if (liste_fac_err != NULL)
      nbr_fac_err_old = liste_fac_err->nbr ;
    else
      nbr_fac_err_old = 0 ;

    liste_fac_err->nbr = nbr_fac_err_old + nbr_fac_err ;
    BFT_REALLOC(liste_fac_err->val, liste_fac_err->nbr, ecs_int_t) ;


    nbr_fac_err = 0 ;

    for (ifac = 0 ; ifac < vec_fac_perio->pos_nbr - 1 ; ifac++)

      if (vec_fac_perio->pos_tab[ifac + 1] != vec_fac_perio->pos_tab[ifac]) {

        ind_fac =
          ECS_ABS(vec_fac_perio->val_tab[vec_fac_perio->pos_tab[ifac] - 1])
          - 1 ;

        if (ifac == ind_fac)
          liste_fac_err->val[nbr_fac_err_old + nbr_fac_err++] = ifac ;

      }


  }



}


/*----------------------------------------------------------------------------
 *  Fonction qui met à jour la renumérotation
 *  "éléments initiaux -> éléments périodiques" en fonction d'un champ
 *  "éléments précédents -> nouveaux éléments" en cas de modifications
 *  successives de la définition des éléments.
 *  On actualise 'val_tab' et on décale 'pos_tab'.
 *
 *  On suppose que 'pos_tab[ielt + 1] = pos_tab[ielt] + 1'
 *
 *  Cette fonction est appelée pour chaque vec_fac_perio, s'il y a de
 *  nouvelles périodicités.
 *----------------------------------------------------------------------------*/

void ecs_vec_def__maj_elt_perio
(
 ecs_vec_int_t  *const vec_elt_perio,
 ecs_vec_int_t  *const vec_elt_old_new,
 size_t                nbr_elt_new
)
{

  size_t         ielt ;
  ecs_int_t      num_elt ;
  size_t         nbr_elt_old ;
  size_t         nbr_val_elt ;

  ecs_int_t    * liste_val_elt_new ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  /* Renumérotation de vec_elt_perio */
  /*---------------------------------*/

  nbr_elt_old = ecs_vec_int__ret_pos_nbr(vec_elt_perio) - 1 ;
  nbr_val_elt = ecs_vec_int__ret_val_nbr(vec_elt_perio) ;

  ecs_vec_int__redimensionne(vec_elt_perio, nbr_elt_new + 1, nbr_val_elt) ;


  for (ielt = nbr_elt_old ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++)
    vec_elt_perio->pos_tab[ielt + 1] = vec_elt_perio->pos_tab[ielt] ;


  /* Les positions des éléments d'origine ont pu changées */

  BFT_MALLOC(liste_val_elt_new, nbr_elt_new, ecs_int_t) ;

  for (ielt = 0 ; ielt < nbr_elt_new ; ielt++)
    liste_val_elt_new[ielt] = 0 ;


  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++)

    if (vec_elt_perio->pos_tab[ielt + 1] != vec_elt_perio->pos_tab[ielt]) {

      num_elt = vec_elt_old_new->val_tab[vec_elt_old_new->pos_tab[ielt] - 1] ;

      if (num_elt > 0)
        liste_val_elt_new[ num_elt - 1]
          =   vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt] - 1] ;
      else
        liste_val_elt_new[-num_elt - 1]
          = - vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt] - 1] ;

    }


  /* On modifie en conséquence vec_elt_perio (= décalage des indices) */

  vec_elt_perio->pos_tab[0] = 1 ;

  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++)

    if (liste_val_elt_new[ielt] != 0) {

      vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt] - 1] =
        liste_val_elt_new[ielt] ;
      vec_elt_perio->pos_tab[ielt + 1] = vec_elt_perio->pos_tab[ielt] + 1 ;

    }
    else
      vec_elt_perio->pos_tab[ielt + 1] = vec_elt_perio->pos_tab[ielt] ;


  /* On remplace les références des éléments par les nouvelles */

  ecs_vec_int__remplace_ref(vec_elt_perio,
                            vec_elt_old_new) ;


  /* On n'a plus besoin du tableau auxiliaire */

  BFT_FREE(liste_val_elt_new) ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui met à jour le tableau renvoyé par
 * ecs_vec_def__typ_fac_cel() en fonction d'une connectivité ajoutée par
 * une périodicité.
 *----------------------------------------------------------------------------*/

void ecs_vec_def__typ_fac_perio
(
 ecs_vec_int_t  * vec_fac_perio,
 ecs_tab_int_t  * typ_fac
)
{

  size_t            ifac ;

  ecs_int_t         ind_fac_0 ;
  ecs_int_t         ind_fac_1 ;

  ecs_int_t         num_fac ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  for (ifac = 0 ; ifac < vec_fac_perio->pos_nbr - 1 ; ifac++) {

    if (vec_fac_perio->pos_tab[ifac + 1] != vec_fac_perio->pos_tab[ifac]) {

      num_fac = vec_fac_perio->val_tab[vec_fac_perio->pos_tab[ifac] - 1] ;

      ind_fac_0 = ifac ;
      ind_fac_1 = ECS_ABS(num_fac) - 1 ;

      if (    (   typ_fac->val[ind_fac_0] == 1
               && typ_fac->val[ind_fac_1] == 2)
           || (   typ_fac->val[ind_fac_0] == 2
               && typ_fac->val[ind_fac_1] == 1)) {

        typ_fac->val[ind_fac_0] = 3 ;
        typ_fac->val[ind_fac_1] = 3 ;

      }

      else if (   typ_fac->val[ind_fac_0] > 0
               && typ_fac->val[ind_fac_1] > 0) {

        if ((   typ_fac->val[ind_fac_0] & 1)
             && typ_fac->val[ind_fac_1] & 1) {
          typ_fac->val[ind_fac_0] = typ_fac->val[ind_fac_0] | 4 ;
          typ_fac->val[ind_fac_1] = typ_fac->val[ind_fac_1] | 4 ;
        }

        if ((   typ_fac->val[ind_fac_0] & 2)
             && typ_fac->val[ind_fac_1] & 2) {
          typ_fac->val[ind_fac_0] = typ_fac->val[ind_fac_0] | 8 ;
          typ_fac->val[ind_fac_1] = typ_fac->val[ind_fac_1] | 8 ;
        }

      }

    }

  }

}


/*----------------------------------------------------------------------------
 *  Fonction qui compte le nombre d'éléments périodiques.
 *  On vérifie qu'un élément périodique ne se voit pas lui-même (cela
 *  peut arriver dans le cas d'une périodicite de rotation de 180 degrés)
 *----------------------------------------------------------------------------*/

ecs_int_t ecs_vec_def__compte_elt_perio
(
 const ecs_vec_int_t  * vec_elt_perio
)
{

  size_t    ielt ;
  size_t    ind_elt ;

  size_t    nbr_elt_perio ;
  size_t    nbr_elt_ident ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  nbr_elt_ident = 0 ;


  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++)

    if (vec_elt_perio->pos_tab[ielt + 1] != vec_elt_perio->pos_tab[ielt]) {

      ind_elt =
        ECS_ABS(vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt] - 1]) - 1 ;

      if (ind_elt == ielt)
        nbr_elt_ident +=1 ;

    }


  nbr_elt_perio = 2 * ecs_vec_int__ret_val_nbr(vec_elt_perio) - nbr_elt_ident ;

  return nbr_elt_perio ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui construit la des faces périodiques associées à une
 *  périodicité num_per de la manière suivante :
 *  =>  [i,j; ...] avec i->j
 *----------------------------------------------------------------------------*/

ecs_tab_int_t ecs_vec_def__liste_fac_perio
(
 const ecs_vec_int_t  * vec_elt_perio
)
{

  size_t    ielt ;
  size_t    ind_elt ;

  size_t    cpt_val ;

  ecs_tab_int_t   liste_fac_perio ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  /* Initialisation */

  liste_fac_perio.nbr = ecs_vec_def__compte_elt_perio(vec_elt_perio) ;

  BFT_MALLOC(liste_fac_perio.val, liste_fac_perio.nbr, ecs_int_t) ;


  /* Remplissage du tableau */

  cpt_val = 0 ;

  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++) {

    if (vec_elt_perio->pos_tab[ielt + 1] != vec_elt_perio->pos_tab[ielt]) {

      ind_elt =
        ECS_ABS(vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt] - 1]) - 1 ;

      liste_fac_perio.val[cpt_val++] = ielt + 1 ;
      liste_fac_perio.val[cpt_val++] = ind_elt + 1 ;

    }

  }

  assert(cpt_val == liste_fac_perio.nbr) ;

  return liste_fac_perio ;

}


/*============================================================================
 *                              Fonctions privées
 *============================================================================*/

/*----------------------------------------------------------------------------
 *  Fonction qui calcule les nouvelles coordonnees d'un vecteur ou d'un point
 *  dans le cas d'une periodicite.
 *----------------------------------------------------------------------------*/

static ecs_vec_real_t * ecs_loc_vec_def_perio__new_coor
(
 const ecs_vec_real_t    * vec_def,
 const ecs_real_t          translation[3],
 const ecs_real_t          point_inv[3],
 const ecs_real_t          matrice[3][3],
 const ecs_bool_t          periodicite_inverse
)
{

  size_t            ielt ;
  size_t            icoo ;
  size_t            irot ;
  size_t            ipos ;

  ecs_real_t        vect[3] ;

  ecs_vec_real_t  * vec_def_new ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  assert(vec_def->pos_nbr != 0) ;

  vec_def_new = ecs_vec_real__alloue(vec_def->pos_nbr,
                                     (vec_def->pos_nbr - 1) * ECS_DIM_3) ;


  if (periodicite_inverse == ECS_FALSE)


    for (ielt = 0 ; ielt < vec_def->pos_nbr - 1 ; ielt++) {

      ipos = vec_def->pos_pas * ielt ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vect[icoo] = 0. ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        for (irot = 0 ; irot < ECS_DIM_3 ; irot++)
          vect[icoo] = vect[icoo] + matrice[icoo][irot] *
            (vec_def->val_tab[ipos+irot]-point_inv[irot] + translation[irot]) ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vec_def_new->val_tab[ipos+icoo] =  vect[icoo] + point_inv[icoo] ;

    }


  else


    for (ielt = 0 ; ielt < vec_def->pos_nbr - 1 ; ielt++) {

      ipos = vec_def->pos_pas * ielt ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vect[icoo] = 0. ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        for (irot = 0 ; irot < ECS_DIM_3 ; irot++)
          vect[icoo] = vect[icoo] + matrice[irot][icoo] *
            (vec_def->val_tab[ipos+irot]-point_inv[irot]) ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        vec_def_new->val_tab[ipos+icoo] =  vect[icoo] + point_inv[icoo]
                                           - translation[icoo] ;

    }



  return vec_def_new ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui met à jour la renumérotation
 *  "éléments initiaux -> éléments périodiques" en fonction d'un champ
 *  "éléments précédents -> nouveaux éléments".
 *
 *  Cette fonction est appelée après le pré-nettoyage des éléments,
 *  pour les vecteurs de correspondance des arêtes et des faces.
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__maj_apres_prenet
(
       ecs_vec_int_t     *const vec_elt_perio,
       ecs_vec_int_t     *const vec_elt_old_new,
 const ecs_param_perio_t        param_perio,
       size_t                   nbr_elt_new
)
{

  size_t            ielt   ;
  size_t            isselt ;

  size_t            ind_elt ;
  ecs_int_t         num_elt ;

  size_t            pos_sselt_elt ;
  size_t            nbr_sselt_elt ;

  size_t            nbr_val_elt ;

  size_t            nbr_elt_perio ;

  ecs_bool_t        bool_symetrie     ;
  ecs_bool_t        bool_non_conforme ;

  ecs_int_t       * liste_pos_elt_new ;

  ecs_vec_int_t   * vec_elt_perio_new ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  /* Renumérotation de vec_elt_perio */
  /*---------------------------------*/

  bool_non_conforme = ECS_FALSE ;
  bool_symetrie     = ecs_loc_vec_def_perio__rot_est_sym(param_perio.angle,
                                                         param_perio.matrice) ;


  nbr_val_elt = ecs_vec_int__ret_val_nbr(vec_elt_perio) ;
  vec_elt_perio_new = ecs_vec_int__alloue(nbr_elt_new + 1, nbr_val_elt) ;


  /* Les positions des éléments d'origine ont pu changées */

  BFT_MALLOC(liste_pos_elt_new, nbr_elt_new, ecs_int_t) ;

  for (ielt = 0 ; ielt < nbr_elt_new ; ielt++)
    liste_pos_elt_new[ielt] = 0 ;


  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++)

    if (vec_elt_perio->pos_tab[ielt + 1] != vec_elt_perio->pos_tab[ielt]) {

      pos_sselt_elt = vec_elt_old_new->pos_tab[ielt] - 1 ;
      nbr_sselt_elt = vec_elt_old_new->pos_tab[ielt + 1] - 1 - pos_sselt_elt ;


      /* Test en cas de recollement non conforme survenant pour
         une périodicité de rotation de 180 degrés. */

      if (nbr_sselt_elt > 1 && bool_non_conforme == ECS_FALSE)
        bool_non_conforme = ECS_TRUE ;


      num_elt = vec_elt_old_new->val_tab[pos_sselt_elt] ;

      if (num_elt > 0)
        liste_pos_elt_new[ num_elt - 1] =  (ielt + 1) ;
      else
        liste_pos_elt_new[-num_elt - 1] = -(ielt + 1) ;


    }



  /* On modifie en conséquence vec_elt_perio (= décalage des indices) */

  vec_elt_perio_new->pos_tab[0] = 1 ;


  /* Cas "habituel" */

  if ((bool_symetrie == ECS_FALSE) || (bool_non_conforme == ECS_FALSE)) {

    for (ielt = 0 ; ielt < nbr_elt_new ; ielt++)

      if (liste_pos_elt_new[ielt] != 0) {


        num_elt = liste_pos_elt_new[ielt] ;
        ind_elt = ECS_ABS(num_elt) - 1 ;

        pos_sselt_elt = vec_elt_perio->pos_tab[ind_elt] - 1 ;
        nbr_sselt_elt = vec_elt_perio->pos_tab[ind_elt + 1] - 1
          - pos_sselt_elt ;

        assert(nbr_sselt_elt > 0) ;


        if (num_elt > 0)

          for (isselt = 0 ; isselt < nbr_sselt_elt ; isselt++) {

            vec_elt_perio_new->val_tab[vec_elt_perio_new->pos_tab[ielt] - 1
                                       + isselt] =
              vec_elt_perio->val_tab[pos_sselt_elt + isselt] ;

          }

        else

          for (isselt = 0 ; isselt < nbr_sselt_elt ; isselt++) {

            vec_elt_perio_new->val_tab[vec_elt_perio_new->pos_tab[ielt] - 1
                                       + isselt] =
              - vec_elt_perio->val_tab[pos_sselt_elt + isselt] ;

          }


        vec_elt_perio_new->pos_tab[ielt + 1] =
          vec_elt_perio_new->pos_tab[ielt] + nbr_sselt_elt ;

      }
      else
        vec_elt_perio_new->pos_tab[ielt + 1] =
          vec_elt_perio_new->pos_tab[ielt] ;

  }

  /* Symétrie non-conforme (rotation de 180 degrés entraînant un découpage
     des faces périodiques) */

  else {

    for (ielt = 0 ; ielt < nbr_elt_new ; ielt++)
      liste_pos_elt_new[ielt] = 0 ;


    for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++) {

      nbr_elt_perio =   vec_elt_perio->pos_tab[ielt + 1]
                      - vec_elt_perio->pos_tab[ielt] ;

      if (nbr_elt_perio > 0) {

        pos_sselt_elt = vec_elt_old_new->pos_tab[ielt] - 1 ;
        nbr_sselt_elt = vec_elt_old_new->pos_tab[ielt + 1] - 1 - pos_sselt_elt ;

        if (nbr_sselt_elt != nbr_elt_perio)

          bft_error(__FILE__, __LINE__, 0,
                    _("180 degrees rotation periodicity leading to unhandled\n"
                      "non-conforming faces situation.\n"
                      "Algorithm not adapted yet.")) ;

        for (isselt = 0 ; isselt < nbr_sselt_elt ; isselt++) {

          num_elt = vec_elt_old_new->val_tab[pos_sselt_elt + isselt] ;

          if (num_elt > 0)
            liste_pos_elt_new[ num_elt - 1] =
               vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt]-1 + isselt] ;
          else
            liste_pos_elt_new[-num_elt - 1] =
              -vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt]-1 + isselt] ;

        }

      }

    }


    for (ielt = 0 ; ielt < nbr_elt_new ; ielt++) {

      if (liste_pos_elt_new[ielt] != 0) {

        vec_elt_perio_new->val_tab[vec_elt_perio_new->pos_tab[ielt] - 1] =
          liste_pos_elt_new[ielt] ;

        vec_elt_perio_new->pos_tab[ielt + 1] =
          vec_elt_perio_new->pos_tab[ielt] + 1;

      }
      else

        vec_elt_perio_new->pos_tab[ielt + 1] =
          vec_elt_perio_new->pos_tab[ielt] ;

    }


  }


  /* On n'a plus besoin du tableau auxiliaire */

  BFT_FREE(liste_pos_elt_new) ;


  /* On affecte le nouveau vec_elt_perio */

  ecs_vec_int__redimensionne(vec_elt_perio,
                             nbr_elt_new + 1,
                             nbr_val_elt) ;


  BFT_FREE(vec_elt_perio->pos_tab) ;
  BFT_FREE(vec_elt_perio->val_tab) ;

  vec_elt_perio->pos_tab = vec_elt_perio_new->pos_tab ;
  vec_elt_perio->val_tab = vec_elt_perio_new->val_tab ;

  ecs_vec_int__libere(vec_elt_perio_new) ;


}


/*----------------------------------------------------------------------------
 *  Fonction renvoyant un booléen selon que la rotation considérée est une
 *  symétrie ou non.
 *----------------------------------------------------------------------------*/

static ecs_bool_t ecs_loc_vec_def_perio__rot_est_sym
(
 const ecs_real_t  angle,
 const ecs_real_t  matrice[3][3]
)
{

  ecs_real_t   cost  ;
  ecs_real_t   trace ;

  ecs_bool_t   bool_sym ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  trace = 0. ;
  bool_sym = ECS_FALSE ;


  /* Si une rotation est définie par sa matrice R,
     alors on a la relation suivante : " trace(R) = 1 + 2*cosinus(angle) "
     (Que se passe-t-il si la matrice représente la composée de 2 rotations ?
     Peut-on toujours conserver ce test ?) */

  if (ECS_ABS(angle) < 1.e-6) {

    trace = matrice[0][0] + matrice[1][1] + matrice[2][2] ;
    cost  = (trace - 1.)/2. ;

    if (ECS_ABS(cost + 1.) < 1.e-6)
      bool_sym = ECS_TRUE ;

  }

  /* Sinon elle est définie par son angle. */

  else if (ECS_ABS(ECS_ABS(angle) - 180.0) < 1.e-6) {

     bool_sym = ECS_TRUE ;

  }


  return bool_sym ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui ajoute des sommets périodiques
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__ajoute_som
(
       ecs_vec_int_t      *      vec_som_perio,
 const ecs_vec_real_t     *const vec_def_som,
 const ecs_tab_int_t             liste_som_new,
 const ecs_param_perio_t         param_perio
)
{

  size_t            isom ;
  size_t            icoo ;
  size_t            iloc ;
  size_t            irot ;

  size_t            ind_som ;

  size_t            cpt_per ;

  size_t            nbr_val_new ;

  ecs_bool_t        bool_per ;

  ecs_point_t       taille_boite    ;
  ecs_point_t       coord_som       ;
  ecs_point_t       coord_som_perio ;
  ecs_point_t       delta_coord ;

  ecs_int_t       * liste_per ;

  ecs_vec_int_t   * vec_som_perio_new ;

  const size_t   nbr_som = ecs_vec_real__ret_pos_nbr(vec_def_som) - 1 ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  BFT_MALLOC(liste_per, nbr_som, ecs_int_t) ;

  for (isom = 0 ; isom < nbr_som ; isom++)
    liste_per[isom] = 0 ;


  for (icoo =  0 ; icoo < ECS_DIM_3 ; icoo++)
    taille_boite[icoo] = 2.e-4 ;

  cpt_per = 0 ;


  for (isom = 0 ; isom < liste_som_new.nbr ; isom++) {

    ind_som = liste_som_new.val[isom] ;

    if (   vec_som_perio->pos_tab[ind_som + 1]
        == vec_som_perio->pos_tab[ind_som]) {

      /* Calcul des coordonnées du nouveau sommet */

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        coord_som[icoo] =
          vec_def_som->val_tab[vec_def_som->pos_pas * ind_som + icoo] ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        coord_som_perio[icoo] = 0. ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        for (irot = 0 ; irot < ECS_DIM_3 ; irot++)
          coord_som_perio[icoo]
            +=    param_perio.matrice[icoo][irot]
               * (  coord_som[irot] - param_perio.point_inv[irot]
                  + param_perio.translation[irot]) ;

      for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
        coord_som_perio[icoo] += param_perio.point_inv[icoo] ;


      /* Recherche de correspondant périodique ;
         TODO : paramètre de tolérance relatif à la taille des arêtes
         connectées, boucle non quadratique */

      bool_per = ECS_FALSE ;


      for (iloc = 0 ; iloc < nbr_som && bool_per == ECS_FALSE ; iloc++) {

        for (icoo = 0 ; icoo < ECS_DIM_3 ; icoo++)
          delta_coord[icoo] =
            ECS_ABS(coord_som_perio[icoo] -
                    vec_def_som->val_tab[vec_def_som->pos_pas * iloc + icoo]) ;

        if (   delta_coord[0] < taille_boite[0]
            && delta_coord[1] < taille_boite[1]
            && delta_coord[2] < taille_boite[2]) {

          cpt_per += 1 ;
          bool_per = ECS_TRUE ;
          liste_per[ind_som] = iloc + 1 ;

        }

      }

    }

  }


  nbr_val_new = ecs_vec_int__ret_val_nbr(vec_som_perio) + cpt_per ;
  vec_som_perio_new = ecs_vec_int__alloue(nbr_som + 1,
                                          nbr_val_new) ;

  vec_som_perio_new->pos_tab[0] = 1 ;

  cpt_per = 0 ;


  for (isom = 0 ; isom < nbr_som ; isom++) {

    if (vec_som_perio->pos_tab[isom] != vec_som_perio->pos_tab[isom + 1]) {

      assert(liste_per[isom] == 0) ;

      vec_som_perio_new->val_tab[vec_som_perio_new->pos_tab[isom] - 1] =
        vec_som_perio->val_tab[vec_som_perio->pos_tab[isom] - 1] ;

      vec_som_perio_new->pos_tab[isom + 1] =
        vec_som_perio_new->pos_tab[isom] + 1 ;

    }
    else if (liste_per[isom] != 0) {

      ind_som = liste_per[isom] - 1 ;

      if (   vec_som_perio->pos_tab[ind_som]
          == vec_som_perio->pos_tab[ind_som + 1]) {

        vec_som_perio_new->val_tab[vec_som_perio_new->pos_tab[isom] - 1] =
          liste_per[isom] ;

        vec_som_perio_new->pos_tab[isom + 1] =
          vec_som_perio_new->pos_tab[isom] + 1 ;

        cpt_per += 1 ;

      }
      else
        vec_som_perio_new->pos_tab[isom + 1] =
          vec_som_perio_new->pos_tab[isom] ;

    }
    else
      vec_som_perio_new->pos_tab[isom + 1] = vec_som_perio_new->pos_tab[isom] ;

  }


  BFT_FREE(liste_per) ;


  /* Réallocation du vecteur de correspondance des sommets périodiques */

  nbr_val_new = ecs_vec_int__ret_val_nbr(vec_som_perio) + cpt_per ;

  ecs_vec_int__redimensionne(vec_som_perio_new,
                             nbr_som + 1,
                             nbr_val_new) ;


  BFT_FREE(vec_som_perio->pos_tab) ;
  BFT_FREE(vec_som_perio->val_tab) ;

  vec_som_perio->pos_tab = vec_som_perio_new->pos_tab ;
  vec_som_perio->val_tab = vec_som_perio_new->val_tab ;

  ecs_vec_int__libere(vec_som_perio_new) ;



}


/*----------------------------------------------------------------------------
 *  Fonction qui vérifie qu'il n'y a pas de d'éléments périodiques se
 *  définissant l'un par l'autre (i.e i->j et j->i).
 *  Si c'est le cas on ne garde que l'un des deux couples.
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__verif
(
 ecs_vec_int_t   * vec_elt_perio
)
{

  size_t              ielt     ;
  size_t              isselt   ;
  size_t              isselt_0 ;
  size_t              ipos     ;

  size_t              ind_elt_0 ;
  size_t              ind_elt_1 ;

  size_t              cpt_max ;
  size_t              cpt_pos ;
  size_t              cpt_val ;

  size_t              nbr_val_elt ;

  size_t              pos_sselt_elt ;
  size_t              nbr_sselt_elt ;
  size_t              pos_sselt_elt_0 ;
  size_t              nbr_sselt_elt_0 ;

  ecs_bool_t          bool_sortie ;

  ecs_size_t        * liste_pos_sup ;
  ecs_int_t         * liste_val_sup ;

  ecs_vec_int_t     * vec_elt_perio_new ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  cpt_pos = 0 ;
  cpt_val = 0 ;

  nbr_val_elt = ecs_vec_int__ret_val_nbr(vec_elt_perio) ;

  BFT_MALLOC(liste_pos_sup, nbr_val_elt, ecs_size_t) ;
  BFT_MALLOC(liste_val_sup, nbr_val_elt, ecs_int_t) ;


  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++) {

    pos_sselt_elt = vec_elt_perio->pos_tab[ielt] - 1 ;
    nbr_sselt_elt = vec_elt_perio->pos_tab[ielt + 1] - 1 - pos_sselt_elt ;

    if (nbr_sselt_elt > 0) {

      for (isselt = 0 ; isselt < nbr_sselt_elt ; isselt++) {

        ind_elt_0
          = ECS_ABS(vec_elt_perio->val_tab[pos_sselt_elt + isselt]) - 1 ;

        bool_sortie = ECS_FALSE ;

        pos_sselt_elt_0 = vec_elt_perio->pos_tab[ind_elt_0] - 1 ;
        nbr_sselt_elt_0 = vec_elt_perio->pos_tab[ind_elt_0 + 1] - 1
          -pos_sselt_elt_0 ;

        for (isselt_0 = 0 ;
             bool_sortie == ECS_FALSE && isselt_0 < nbr_sselt_elt_0 ;
             isselt_0++) {

          ind_elt_1 = ECS_ABS(vec_elt_perio->val_tab[pos_sselt_elt_0
                                                     + isselt_0]) - 1 ;


          /* On marque les valeurs et leur position associée à ne pas garder
             dans vec_elt_perio. La liste des positions à supprimer est
             croissante et celles des valeurs rangée dans l'ordre du val_tab. */

          if (ielt == ind_elt_1 && ielt < ind_elt_0) {
              liste_pos_sup[cpt_pos++] = ielt ;
              liste_val_sup[cpt_val++] = ind_elt_0 ;
          }

        }

      }

    }

  }


  if (cpt_pos == 0) { /* Pas de difficultés pour l'héritage périodique */

    BFT_FREE(liste_pos_sup) ;
    BFT_FREE(liste_val_sup) ;

    return ;

  }


  BFT_REALLOC(liste_pos_sup, cpt_pos, ecs_size_t) ;
  BFT_REALLOC(liste_val_sup, cpt_val, ecs_int_t) ;


  cpt_max = cpt_pos ; /* = cpt_val */
  cpt_pos = 0 ;
  cpt_val = 0 ;

  vec_elt_perio_new = ecs_vec_int__alloue(vec_elt_perio->pos_nbr,
                                          nbr_val_elt) ;
  vec_elt_perio_new->pos_tab[0] = 1 ;


  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++) {

    pos_sselt_elt = vec_elt_perio->pos_tab[ielt] - 1 ;
    nbr_sselt_elt = vec_elt_perio->pos_tab[ielt + 1] - 1 - pos_sselt_elt ;

    if (cpt_max < cpt_pos + 1 || ielt != liste_pos_sup[cpt_pos]) {

      for (isselt = 0 ; isselt < nbr_sselt_elt ; isselt++)
        vec_elt_perio_new->val_tab[vec_elt_perio_new->pos_tab[ielt] - 1
                                   + isselt] =
          vec_elt_perio->val_tab[pos_sselt_elt + isselt] ;

      vec_elt_perio_new->pos_tab[ielt + 1] = vec_elt_perio_new->pos_tab[ielt] +
        nbr_sselt_elt ;

    }
    else {

      ipos = 0 ;
      vec_elt_perio_new->pos_tab[ielt + 1] = vec_elt_perio_new->pos_tab[ielt] ;


      while(cpt_pos < cpt_max && ielt == liste_pos_sup[cpt_pos])

        if (ECS_ABS(vec_elt_perio->val_tab[pos_sselt_elt + ipos]) !=
            liste_val_sup[cpt_val] + 1) {

          vec_elt_perio_new->val_tab[vec_elt_perio_new->pos_tab[ielt] - 1
                                     + ipos] =
            vec_elt_perio_new->val_tab[pos_sselt_elt + ipos] ;

          vec_elt_perio_new->pos_tab[ielt + 1] += 1 ;
          ipos++ ;

        }
        else {
          ipos++ ;
          cpt_val++ ;
          cpt_pos++ ;
        }


      while(ipos < nbr_sselt_elt) {

        vec_elt_perio_new->val_tab[vec_elt_perio_new->pos_tab[ielt] - 1
                                   + ipos++] =
          vec_elt_perio_new->val_tab[pos_sselt_elt + isselt] ;

      }

    }

  }


  BFT_FREE(liste_pos_sup) ;
  BFT_FREE(liste_val_sup) ;


  nbr_val_elt = ecs_vec_int__ret_val_nbr(vec_elt_perio_new) ;
  ecs_vec_int__redimensionne(vec_elt_perio_new,
                             vec_elt_perio->pos_nbr,
                             nbr_val_elt) ;

  ecs_vec_int__redimensionne(vec_elt_perio,
                             vec_elt_perio->pos_nbr,
                             nbr_val_elt) ;

  BFT_FREE(vec_elt_perio->pos_tab) ;
  BFT_FREE(vec_elt_perio->val_tab) ;

  vec_elt_perio->pos_tab = vec_elt_perio_new->pos_tab ;
  vec_elt_perio->val_tab = vec_elt_perio_new->val_tab ;

  ecs_vec_int__libere(vec_elt_perio_new) ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui définit la correspondance inverse des éléments pour
 *  la périodicité.
 *  Attention ! Il faut qu'à un élément lui corresponde au plus un unique
 *  élément
 *----------------------------------------------------------------------------*/

static ecs_vec_int_t * ecs_loc_vec_def_perio__inv_corresp
(
 const ecs_vec_int_t *const vec_elt_perio
)
{

  size_t           ielt ;
  ecs_int_t        num_elt ;
  size_t           nbr_elt ;
  size_t           nbr_val ;

  ecs_tab_int_t    liste_elt_inv ;

  ecs_vec_int_t  * vec_elt_perio_inv ;


  /* Initialisation */

  nbr_elt = ecs_vec_int__ret_pos_nbr(vec_elt_perio) - 1 ;
  nbr_val = ecs_vec_int__ret_val_nbr(vec_elt_perio) ;

  vec_elt_perio_inv = ecs_vec_int__alloue(nbr_elt + 1,
                                          nbr_val) ;

  vec_elt_perio_inv->pos_tab[0] = 1 ;


  liste_elt_inv.nbr = nbr_elt ;
  BFT_MALLOC(liste_elt_inv.val, liste_elt_inv.nbr, ecs_int_t) ;

  for (ielt = 0 ; ielt < nbr_elt ; ielt++)
    liste_elt_inv.val[ielt] = 0 ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  for (ielt = 0 ; ielt < nbr_elt ; ielt++)

    if (vec_elt_perio->pos_tab[ielt + 1] != vec_elt_perio->pos_tab[ielt]) {

      num_elt = vec_elt_perio->val_tab[vec_elt_perio->pos_tab[ielt] - 1] ;

      if (num_elt > 0)
        liste_elt_inv.val[ num_elt - 1] =   ielt + 1 ;
      else
        liste_elt_inv.val[-num_elt - 1] = -(ielt + 1) ;

    }


  for (ielt = 0 ; ielt < nbr_elt ; ielt++)

    if (liste_elt_inv.val[ielt] != 0) {

      vec_elt_perio_inv->val_tab[vec_elt_perio_inv->pos_tab[ielt] - 1] =
        liste_elt_inv.val[ielt] ;

      vec_elt_perio_inv->pos_tab[ielt + 1] =
        vec_elt_perio_inv->pos_tab[ielt] + 1 ;

    }

    else
      vec_elt_perio_inv->pos_tab[ielt + 1] = vec_elt_perio_inv->pos_tab[ielt] ;


  liste_elt_inv.nbr = 0 ;
  BFT_FREE(liste_elt_inv.val) ;


  return vec_elt_perio_inv ;


}


/*----------------------------------------------------------------------------
 *  Fonction qui décale un vec_elt_perio en fonction d'une renumérotation
 *  des indices de départ (vect_renum).
 *  Il s'agit donc nécessairement d'un décalage vers le "bas".
 *----------------------------------------------------------------------------*/

static void ecs_loc_vec_def_perio__decale
(
       ecs_vec_int_t *const vec_elt_perio,
 const ecs_vec_int_t *const vect_renum
)
{

  size_t           ielt   ;
  size_t           isselt ;

  size_t           ipos_new ;

  size_t           nbr_val_elt ;

  size_t           pos_sselt_elt ;
  size_t           nbr_sselt_elt ;

  ecs_vec_int_t  * vec_elt_perio_new ;



  /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  nbr_val_elt = ecs_vec_int__ret_val_nbr(vec_elt_perio) ;

  vec_elt_perio_new = ecs_vec_int__alloue(vec_elt_perio->pos_nbr, nbr_val_elt) ;
  vec_elt_perio_new->pos_tab[0] = 1 ;


  ipos_new = 0 ;


  for (ielt = 0 ; ielt < vec_elt_perio->pos_nbr - 1 ; ielt++)

    if (vect_renum->pos_tab[ielt + 1] != vect_renum->pos_tab[ielt]) {

      pos_sselt_elt = vec_elt_perio->pos_tab[ielt] - 1 ;
      nbr_sselt_elt = vec_elt_perio->pos_tab[ielt + 1] - 1 - pos_sselt_elt ;

      if (nbr_sselt_elt > 0) {

        for (isselt = 0 ; isselt < nbr_sselt_elt ; isselt++) {

          vec_elt_perio_new->val_tab[vec_elt_perio_new->pos_tab[ipos_new] - 1
                                     + isselt] =
            vec_elt_perio->val_tab[pos_sselt_elt + isselt] ;

          vec_elt_perio_new->pos_tab[ipos_new + 1] =
            vec_elt_perio_new->pos_tab[ipos_new] + nbr_sselt_elt  ;

        }

        ipos_new++ ;

      }
      else {

        vec_elt_perio_new->pos_tab[ipos_new + 1] =
          vec_elt_perio_new->pos_tab[ipos_new] ;

        ipos_new++ ;

      }

    }


  ecs_vec_int__redimensionne(vec_elt_perio_new,
                             ipos_new + 1,
                             nbr_val_elt) ;

  BFT_FREE(vec_elt_perio->pos_tab) ;
  BFT_FREE(vec_elt_perio->val_tab) ;

  vec_elt_perio->pos_tab = vec_elt_perio_new->pos_tab ;
  vec_elt_perio->val_tab = vec_elt_perio_new->val_tab ;

  ecs_vec_int__redimensionne(vec_elt_perio,
                             vec_elt_perio_new->pos_nbr,
                             nbr_val_elt) ;

  ecs_vec_int__libere(vec_elt_perio_new) ;


}


/*----------------------------------------------------------------------------
 *  Fonction renvoyant la "position" du nouvel élément
 *----------------------------------------------------------------------------*/

static ecs_tab_int_t   ecs_loc_vec_def_perio__ret_tab_pos
(
 const ecs_tab_int_t        masque_elt_select,
       size_t        *const nbr_elt_new,
       size_t        *const nbr_elt_perio
)
{

  size_t          ielt ;

  ecs_tab_int_t   tab_pos_elt ;


  /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


  tab_pos_elt.nbr = masque_elt_select.nbr ;
  BFT_MALLOC(tab_pos_elt.val, tab_pos_elt.nbr, ecs_int_t) ;

  *nbr_elt_perio = 0 ;
  *nbr_elt_new   = 0 ;


  for (ielt = 0 ; ielt < masque_elt_select.nbr ; ielt++)

    switch (masque_elt_select.val[ielt]) {

    case -1:

      if (ielt == 0)
        tab_pos_elt.val[0] = 0 ;
      else
        tab_pos_elt.val[ielt] = tab_pos_elt.val[ielt - 1] ;

      break ;

    case 0:

      if (ielt == 0)
        tab_pos_elt.val[0] = 1 ;
      else
        tab_pos_elt.val[ielt] = tab_pos_elt.val[ielt - 1] + 1 ;

      *nbr_elt_new += 1 ;
      break ;

    case 1:

      if (ielt == 0)
        tab_pos_elt.val[0] = 2 ;
      else
        tab_pos_elt.val[ielt] = tab_pos_elt.val[ielt - 1] + 2 ;

      *nbr_elt_new   += 2 ;
      *nbr_elt_perio += 1 ;
      break ;

    case 2:

      if (ielt == 0)
        tab_pos_elt.val[0] = 1 ;
      else
        tab_pos_elt.val[ielt] = tab_pos_elt.val[ielt - 1] + 1 ;

      *nbr_elt_new   += 1 ;
      *nbr_elt_perio += 1 ;
      break ;

    }


  return tab_pos_elt ;


}


Generated by  Doxygen 1.6.0   Back to index