/*============================================================================ * * Code_Saturne version 1.3 * ------------------------ * * * This file is part of the Code_Saturne Kernel, element of the * Code_Saturne CFD tool. * * Copyright (C) 1998-2007 EDF S.A., France * * contact: saturne-support@edf.fr * * The Code_Saturne Kernel 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 Kernel 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 Kernel; if not, write to the * Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA * *============================================================================*/ /*============================================================================ * Gestion des fichiers suite *============================================================================*/ /*---------------------------------------------------------------------------- * Fichiers `include' librairie standard C *----------------------------------------------------------------------------*/ #include #include #include #if defined(_CS_HAVE_MPI) #include #endif /*---------------------------------------------------------------------------- * Fichiers `include' librairie BFT *----------------------------------------------------------------------------*/ #include #include #include #include /*---------------------------------------------------------------------------- * Fichiers `include' locaux *----------------------------------------------------------------------------*/ #include "cs_base.h" #include "cs_maillage.h" /*---------------------------------------------------------------------------- * Fichiers `include' associés au fichier courant *----------------------------------------------------------------------------*/ #include "cs_suite.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /*============================================================================ * Structures locales *============================================================================*/ typedef struct _cs_suite_rec_t { char *nom; /* Nom de l'enregistrement */ cs_int_t ind_support; /* Indice du support (code cs_suite_support_t ou utilisateur dans version ultérieure) */ cs_int_t nbr_val_ent; /* Nombre de valeurs/entité support */ cs_type_t typ_val; /* Type de variable */ cs_int_t ind_fic; /* Indice du fichier correspondant */ bft_file_off_t pos_fic; /* Position du début dans le fichier */ } cs_suite_rec_t; struct _cs_suite_t { char *nom; /* Nom du fichier suite */ cs_int_t nbr_cel; /* Nombre de cellules du support en lecture */ cs_int_t nbr_fac; /* Nb. faces internes du support en lecture */ cs_int_t nbr_fbr; /* Nb. faces de bord du support en lecture */ cs_int_t nbr_som; /* Nombre de sommets du support en lecture */ cs_int_t nbr_rec; /* Nombre d'enregistrements courant */ cs_int_t nbr_rec_max; /* Nombre d'enregistrements maximal avant redimensionnement de tab_rec */ cs_suite_rec_t *tab_rec; /* Index des enregistrements */ cs_int_t nbr_fic; /* Nombre de fichiers associés (un seul en écriture, plusieurs possibles en lecture) */ bft_file_t **fic; /* Pointeurs sur fichiers associés ; tableau de taille 1 en écriture (un fichier ouvert réutilise la position 0), et de taille nbr_fic en lecture (plusieurs fichiers peuvent être ouverts si données trop volumineuses pour un seul */ cs_suite_type_t type; /* Type de codage des données */ cs_suite_mode_t mode; /* Lecture ou écriture */ }; /*============================================================================ * Constantes et Macros *============================================================================*/ /* Taille maximale d'un fichier : 0.95 * entier 32 bits max (2147483647) */ #define CS_SUITE_TAILLE_FIC_MAX 2040109464 #define CS_SUITE_LNG_NOM_TYPE_ELT 2 /* Longueur du nom de type */ #define CS_SUITE_LNG_BUF_ASCII 120 /* Longueur tampon ligne ASCII */ /* * Label MPI (pour distinguer messages associés aux suites des autres, * sans passer par un communicateur distinct) */ #define CS_SUITE_MPI_TAG 'C'+'S'+'_'+'S'+'U'+'I'+'T'+'E' /* Formats pour mode texte (voire chaînes globales plus bas) */ #define CS_SUITE_FMT_ASCII_DIM_COL_INT 11 /* %10d + 1 col */ #define CS_SUITE_FMT_ASCII_DIM_COL_REAL 24 /* %23.15E + 1 col */ #define CS_SUITE_FMT_ASCII_NBR_COL_INT 7 #define CS_SUITE_FMT_ASCII_NBR_COL_REAL 3 /* API Fortran */ /* ----------- */ /* * (longueur max 'usuelle' de nom ; un nom plus long est possible * mais provoquera une allocation de mémoire dynamique). */ #define CS_SUITE_LNG_NOM 64 /*============================================================================ * Variables globales statiques *============================================================================*/ /* Taille minimale d'un buffer sur le rang 0 (pour limiter le nombre de blocs lorsqu'on a un grand nombre de processeurs) */ static int cs_suite_taille_buf_def = 1024*1024*8; /* Chaîne indiquant que la suite continue sur un autre fichier */ static char const cs_suite_nom_fin_fic[] = "reprise : fin"; static char const cs_suite_nom_decoup_fic[] = "reprise : fic suivant"; static char const cs_suite_nom_partie_fic[] = "reprise : partie num "; /* Type de valeur (dans l'ordre de définition de cs_type_t dans cs_base.h, seuls les types "principaux étant" traités ici) */ static char const cs_suite_nom_typ_elt[3][4] = {"c ", "i32", "r64"}; /* Nom de support (dans l'ordre de définition de cs_suite_support_t) */ static char const *cs_suite_nom_support[5] = {"---", "cel", "fac", "fbr", "som"}; /* Formats d'écriture de valeurs */ static char cs_suite_fmt_ascii_tab_int[] = " %10d"; static char cs_suite_fmt_ascii_tab_real[] = " %23.15E"; /* Tableau pour API Fortran */ static cs_int_t cs_glob_suite_ptr_nbr = 0; static cs_suite_t **cs_glob_suite_ptr_tab = NULL; #if defined(_CS_HAVE_MPI) /* Mode de rapatriement sûr (légèrement plus lent) */ #if defined(__blrts__) /* Blue Gene/L */ static cs_bool_t cs_glob_suite_sync_gather = CS_TRUE; #else static cs_bool_t cs_glob_suite_sync_gather = CS_FALSE; #endif #endif /* defined(_CS_HAVE_MPI) */ /*============================================================================ * Prototypes de fonctions privées *============================================================================*/ /*---------------------------------------------------------------------------- * Calcul du nombre de valeurs d'un enregistrement *----------------------------------------------------------------------------*/ static cs_int_t cs_loc_suite_calc_nbr_ent ( const cs_suite_t *const suite, /* --> Suite associée */ const cs_suite_support_t support, /* --> Support de la variable */ const cs_int_t nbr_val_ent /* --> Nb. val/point support */ ); /*---------------------------------------------------------------------------- * Calcul du déplacement dans un fichier correspondant aux valeurs * d'une rubrique. *----------------------------------------------------------------------------*/ static bft_file_off_t cs_loc_suite_calc_avance ( const cs_suite_t *const suite, /* --> Suite associée */ const cs_suite_support_t support, /* --> Support de la variable */ const cs_int_t nbr_val_ent, /* --> Nb. val/point support */ const cs_type_t typ_val /* --> Type de valeurs */ ); /*---------------------------------------------------------------------------- * Fonction qui initialise une structure fichier àssociée à une suite ; * Le nom de fichier associé correspond au nom de la suite pour le * premier fichier, prolongé éventuellement par '_pxx' pour les fichiers * successifs en cas de découpage du fichier en plusieurs morceaux pour * des gros volumes de données. * On indique en retour si les données se poursuivent sur un autre fichier. *----------------------------------------------------------------------------*/ static cs_bool_t cs_loc_suite_fic_ajoute ( cs_suite_t *const suite /* --> Structure suite */ ); /*---------------------------------------------------------------------------- * Fonction qui lit une liste de valeurs sur un fichier ; on suppose que * l'on est déjà à la bonne position de départ dans le fichier. *----------------------------------------------------------------------------*/ static void cs_loc_suite_lit_val ( const cs_suite_type_t type, /* --> Structure suite */ const bft_file_t *const fic, /* --> Fichier associé */ const cs_int_t nbr_val, /* --> Nb. valeurs à lire */ const cs_type_t typ_val, /* --> Type de valeurs */ void *const val, /* <-- Valeurs à lire */ char asc_buffer[] /* <-> Buffer texte */ ); /*---------------------------------------------------------------------------- * Fonction qui écrit une liste de valeurs sur un fichier *----------------------------------------------------------------------------*/ static void cs_loc_suite_ecr_val ( const cs_suite_t *const suite, /* --> Ptr. fichier suite */ const cs_int_t nbr_val, /* --> Nb. valeurs à écrire */ const cs_type_t typ_val, /* --> Type de valeurs */ const void *const val, /* --> Valeurs à écrire */ cs_int_t *const ind_col /* <-> Colonne départ/fin */ ); /*---------------------------------------------------------------------------- * Fonction qui termine l'écriture d'une liste de valeurs sur un fichier *----------------------------------------------------------------------------*/ static void cs_loc_suite_ecr_val_fin ( const cs_suite_t *const suite, /* --> Ptr. fichier suite */ cs_int_t *const ind_col /* <-> Colonne départ/fin */ ); /*---------------------------------------------------------------------------- * Fonction qui analyse le contenu d'un fichier suite en mode texte * On démare en haut de deuxième ligne, ayant lu l'en-tête, et on * indique en retour si la suite continue sur un autre fichier *----------------------------------------------------------------------------*/ static cs_bool_t cs_loc_suite_analyse_txt ( cs_suite_t *const suite /* --> Structure suite */ ); /*---------------------------------------------------------------------------- * Fonction qui analyse le contenu d'un fichier suite en mode binaire * On démarre à la position suivantl'en-tête, et on indique en retour * si la suite continue sur un autre fichier *----------------------------------------------------------------------------*/ static cs_bool_t cs_loc_suite_analyse_bin ( cs_suite_t *const suite /* --> Structure suite */ ); /*---------------------------------------------------------------------------- * Fonction qui prépare l'index généré lors de l'analyse du fichier à * l'utilisation par les fonctions de lecture d'enregistrements *----------------------------------------------------------------------------*/ static void cs_loc_suite_prepare_index ( cs_suite_t *const suite /* --> Structure suite */ ); /*---------------------------------------------------------------------------- * Conversion d'arguments de lecture/écriture de l'API Fortran vers l'API C *----------------------------------------------------------------------------*/ static void cs_loc_suite_rub_f77_vers_C ( const cs_int_t *const numsui, /* --> Numéro du fichier suite */ const cs_int_t *const itysup, /* --> Code type de support */ const cs_int_t *const irtype, /* --> Entiers ou réels ? */ cs_suite_t **const suite, /* <-- Pointeur structure suite */ cs_suite_support_t *const support, /* <-- Type de support */ cs_type_t *const typ_val, /* <-- Entiers ou réels */ cs_int_t *const ierror /* <-- 0 = succès, < 0 = erreur */ ); #if defined(_CS_HAVE_MPI) /*---------------------------------------------------------------------------- * Fonction qui créé des listes locales->globales associées à chaque bloc. * * Pour le processus "maître E/S", le tableau "nbr_ent_bloc" indiquant le * nombre d'entités appartenant à chaque bloc, et ceci pour chaque domaine : * nbr_ent(bloc, domaine) = nbr_ent_bloc[nbr_bloc * ind_dom + ind_bloc] ; * Pour les autres processus, le tableau "nbr_ent_loc" indique le nombre * d'entités locales appartenant à chaque bloc. * Les tableaux "lst_ent_loc" et "lst_ent_glob" donnent les indices locaux * et globaux des entités locales appartenant à chaque bloc (nbr_ent_loc[0] * premières valeurs pour le bloc 0, nbr_ent_loc[1] suivantes pour le * second, etc.). * * Ces tableaux sont alloués ici et devront être libérés par la suite. * * On renvoie la plus grande valeur (globale) de nbr_ent_loc. *----------------------------------------------------------------------------*/ static cs_int_t cs_loc_suite_cree_listes_ent ( const cs_int_t nbr_bloc, /* --> Nombre de blocs */ const cs_int_t nbr_ent_glob, /* --> Nombre global d'entités */ const cs_int_t nbr_ent_loc, /* --> Nombre local d'entités */ const fvm_gnum_t *const num_glob_ent, /* --> Numéros globaux des entités */ cs_int_t *const pas_bloc, /* <-- Taille blocs (sauf dernier) */ cs_int_t * *const nbr_ent_bloc, /* <-- Nombre d'entités par bloc */ cs_int_t * *const lst_ent_loc, /* <-- Liste des entités par bloc */ cs_int_t * *const lst_ent_glob /* <-- Liste des entités par bloc */ ); /*---------------------------------------------------------------------------- * Fonction qui lit les valeurs associées à une variable définie sur * une entité de maillage. *----------------------------------------------------------------------------*/ static void cs_loc_suite_lit_val_ent ( const cs_suite_t *const suite, /* --> Structure suite */ const bft_file_t *const fic, /* --> Fichier associé aux valeurs */ const cs_int_t nbr_bloc, /* --> Nombre de blocs */ const cs_int_t nbr_ent_glob, /* --> Nombre global d'entités */ const cs_int_t nbr_ent_loc, /* --> Nombre local d'entités */ const fvm_gnum_t *const num_glob_ent, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ cs_byte_t *const tab_val /* --> Tableau des valeurs */ ); /*---------------------------------------------------------------------------- * Fonction qui écrit les valeurs associées à une variable définie sur * une entité de maillage. *----------------------------------------------------------------------------*/ static void cs_loc_suite_ecr_val_ent ( const cs_suite_t *const suite, /* --> Structure suite */ const cs_int_t nbr_bloc, /* --> Nombre de blocs */ const cs_int_t nbr_ent_glob, /* --> Nombre global d'entités */ const cs_int_t nbr_ent_loc, /* --> Nombre local d'entités */ const fvm_gnum_t *const num_glob_ent, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ const cs_byte_t *const tab_val /* --> Tableau des valeurs */ ); /*---------------------------------------------------------------------------- * Fonction qui distribue une liste de variables *----------------------------------------------------------------------------*/ static void cs_loc_suite_distr_val ( const cs_int_t nbr_val, /* --> Nb. valeurs */ const cs_type_t typ_val, /* --> Type de valeurs */ void *const val /* <-> Valeurs à lire */ ) ; #endif /* #if defined(_CS_HAVE_MPI) */ /*---------------------------------------------------------------------------- * Permutation des valeurs d'un tableau renuméroté en lecture *----------------------------------------------------------------------------*/ static void cs_loc_suite_permute_lec ( const cs_int_t nbr_ent, /* --> Nombre d'entités */ const cs_int_t *const num_ent_ini, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ cs_byte_t *const tab_val /* --> Tableau des valeurs */ ); /*---------------------------------------------------------------------------- * Permutation des valeurs d'un tableau renuméroté en écriture *----------------------------------------------------------------------------*/ static cs_byte_t * cs_loc_suite_permute_ecr ( const cs_int_t nbr_ent, /* --> Nombre d'entités */ const cs_int_t *const num_ent_ini, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ const cs_byte_t *const tab_val /* --> Tableau des valeurs */ ); /*============================================================================ * Fonctions publiques pour API Fortran *============================================================================*/ /*---------------------------------------------------------------------------- * Ouverture d'un fichier suite * * Interface Fortran : * * SUBROUTINE OPNSUI (NOMSUI, LNGNOM, IREAWR, IFORMA, NUMSUI) * ***************** * * CHARACTER* NOMSUI : --> : Nom du fichier suite * INTEGER LNGNOM : --> : Longueur du nom du fichier suite * INTEGER IREAWR : --> : 1 pour lecture, 2 pour écriture * INTEGER IFORMA : --> : 0 pour binaire, 1 pour formaté * INTEGER NUMSUI : <-- : Numéro du fichier suite ouvert * INTEGER IERROR : <-- : 0 pour succès, < 0 pour erreur *----------------------------------------------------------------------------*/ void CS_PROCF (opnsui, OPNSUI) ( const char *const nomsui, /* --> Nom du fichier */ const cs_int_t *const lngnom, /* --> Longueur du nom */ const cs_int_t *const ireawr, /* --> 1 pour lecture, 2 pour écriture */ const cs_int_t *const iforma, /* --> 0 pour binaire, 1 pour formaté */ cs_int_t *const numsui, /* <-- Numéro du ficher suite ouvert */ cs_int_t *const ierror /* <-- 0 pour succès, < 0 pour erreur */ CS_ARGF_SUPP_CHAINE /* (arguments 'longueur' éventuels F77, */ /* inutilisés lors de l'appel mais */ /* placés par de nombreux compilateurs) */ ) { char *nombuf; cs_int_t ind; cs_suite_mode_t suite_mode; cs_suite_type_t suite_type; /* Initialisation */ *ierror = CS_SUITE_SUCCES; /* Traitement du nom pour l'API C */ nombuf = cs_base_chaine_f_vers_c_cree(nomsui, *lngnom); /* Options de création du fichier */ { switch(*ireawr) { case 1: suite_mode = CS_SUITE_MODE_LECTURE; break; case 2: suite_mode = CS_SUITE_MODE_ECRITURE; break; default: cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le mode d'ouverture du fichier suite <%s>\n" "doit être égal à 1 (lecture) ou 2 (écriture) " "et non <%d>"), nombuf, (int)(*ireawr)); *ierror = CS_SUITE_ERR_MODE; } } if (*ierror == CS_SUITE_SUCCES) { if (suite_mode == CS_SUITE_MODE_ECRITURE) { switch (*iforma) { case 0: suite_type = CS_SUITE_TYPE_BINAIRE; break; case 1: suite_type = CS_SUITE_TYPE_ASCII; break; default: cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le type du fichier suite <%s>\n" "doit être égal à 0 (binaire) ou 1 (formaté) " "et non <%d>\n(binaire par défaut)"), nombuf, (int)(*iforma)); *ierror = CS_SUITE_ERR_TYPE_FIC; } } else suite_type = CS_SUITE_TYPE_BINAIRE; /* Inutile, mais évite warning sous Purify */ } /* Recherche d'un emplacement disponible */ if (*ierror == CS_SUITE_SUCCES) { for (ind = 0 ; ind < cs_glob_suite_ptr_nbr && cs_glob_suite_ptr_tab[ind] != NULL ; ind++); /* Si aucun emplacement disponible, on autorise plus de fichiers suite */ if (ind == cs_glob_suite_ptr_nbr) { BFT_REALLOC(cs_glob_suite_ptr_tab, cs_glob_suite_ptr_nbr * 2, cs_suite_t *); for (ind = cs_glob_suite_ptr_nbr ; ind < cs_glob_suite_ptr_nbr * 2 ; ind++) cs_glob_suite_ptr_tab[ind] = NULL; cs_glob_suite_ptr_nbr *= 2; } } /* Création du fichier suite */ if (*ierror == CS_SUITE_SUCCES) cs_glob_suite_ptr_tab[ind] = cs_suite_cree(nombuf, suite_mode, suite_type); /* Libération de mémoire si nécessaire */ nombuf = cs_base_chaine_f_vers_c_detruit(nombuf); /* * On renvoie le numéro de position du pointeur dans le tableau * (indice + 1 pour avoir un numéro de 1 à n, plus classique en F77) */ if (*ierror == CS_SUITE_SUCCES) *numsui = ind + 1; else *numsui = -1; } /*---------------------------------------------------------------------------- * Fermeture d'un fichier suite * * Interface Fortran : * * SUBROUTINE CLSSUI (NUMSUI) * ***************** * * INTEGER NUMSUI : --> : numéro du fichier suite à fermer * INTEGER IERROR : <-- : 0 pour succès, < 0 pour erreur *----------------------------------------------------------------------------*/ void CS_PROCF (clssui, CLSSUI) ( const cs_int_t *const numsui, /* --> Numéro du ficher suite à fermer */ cs_int_t *const ierror /* <-- Numéro du ficher suite ouvert */ ) { cs_int_t indsui = *numsui - 1; *ierror = CS_SUITE_SUCCES; /* Vérification que le fichier est valide */ if ( indsui < 0 || indsui > cs_glob_suite_ptr_nbr || cs_glob_suite_ptr_tab[indsui] == NULL) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le fichier suite numéro <%d> ne peut être fermé\n" "(fichier déjà fermé ou numéro invalide)"), (int)(*numsui)); *ierror = CS_SUITE_ERR_NUM_FIC; return; } /* Fermeture du fichier */ cs_suite_detruit(cs_glob_suite_ptr_tab[indsui]); cs_glob_suite_ptr_tab[indsui] = NULL; } /*---------------------------------------------------------------------------- * Vérification du support associé à un fichier suite ; * On renvoie pour chaque type d'entité 1 si le nombre d'entités associées * au fichier suite correspond au nombre d'entités en cours (et donc que * l'on considère que le support est bien le même), 0 sinon. * * Interface Fortran : * * SUBROUTINE TSTSUI (NUMSUI, INDCEL, INDFAC, INDFBR, INDSOM) * ***************** * * INTEGER NUMSUI : --> : Numéro du fichier suite * INTEGER INDCEL : <-- : Indicateur corresp. cellules * INTEGER INDFAC : <-- : Indicateur corresp. faces internes * INTEGER INDFBR : <-- : Indicateur corresp. faces de bord * INTEGER INDSOM : <-- : Indicateur corresp. sommets *----------------------------------------------------------------------------*/ void CS_PROCF (tstsui, TSTSUI) ( const cs_int_t *const numsui, /* --> Numéro du fichier suite */ cs_int_t *const indcel, /* <-- Indicateur corresp. cellules */ cs_int_t *const indfac, /* <-- Indicateur corresp. faces internes */ cs_int_t *const indfbr, /* <-- Indicateur corresp. faces de bord */ cs_int_t *const indsom /* <-- Indicateur corresp. sommets */ ) { cs_bool_t corresp_cel, corresp_fac, corresp_fbr, corresp_som; cs_int_t indsui = *numsui - 1; /* Pointeur de structure suite associé */ if ( indsui < 0 || indsui > cs_glob_suite_ptr_nbr || cs_glob_suite_ptr_tab[indsui] == NULL) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Infomation sur le fichier suite numéro <%d> indisponible\n" "(fichier déjà fermé ou numéro invalide)"), (int)(*numsui)); *indcel = 0; *indfac = 0; *indfbr = 0; *indsom = 0; return; } else { cs_suite_verif_support(cs_glob_suite_ptr_tab[indsui], &corresp_cel, &corresp_fac, &corresp_fbr, &corresp_som); *indcel = (corresp_cel == CS_TRUE ? 1 : 0); *indfac = (corresp_fac == CS_TRUE ? 1 : 0); *indfbr = (corresp_fbr == CS_TRUE ? 1 : 0); *indsom = (corresp_som == CS_TRUE ? 1 : 0); } } /*---------------------------------------------------------------------------- * Affichage de l'index associé à un fichier suite * * Interface Fortran : * * SUBROUTINE INFSUI (NUMSUI) * ***************** * * INTEGER NUMSUI : --> : Numéro du fichier suite *----------------------------------------------------------------------------*/ void CS_PROCF (infsui, INFSUI) ( const cs_int_t *const numsui /* --> Numéro du fichier suite */ ) { cs_int_t indsui = *numsui - 1; /* Pointeur de structure suite associé */ if ( indsui < 0 || indsui > cs_glob_suite_ptr_nbr || cs_glob_suite_ptr_tab[indsui] == NULL) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Infomation sur le fichier suite numéro <%d> indisponible\n" "(fichier déjà fermé ou numéro invalide)"), (int)(*numsui)); } else { cs_suite_affiche_index(cs_glob_suite_ptr_tab[indsui]); } } /*---------------------------------------------------------------------------- * Lecture d'une rubrique sur fichier suite * * Interface Fortran : * * SUBROUTINE LECSUI (NUMSUI, NOMRUB, LNGNOM, ITYSUP, NBVENT, IRTYPE, TABVAR) * ***************** * * INTEGER NUMSUI : --> : Numéro du fichier suite * CHARACTER* NOMRUB : --> : Nom de la rubrique * INTEGER LNGNOM : --> : Longueur du nom de la rubrique * INTEGER ITYSUP : --> : Type de support : * : : 0 : scalaire (pas de support) * : : 1 : cellules * : : 2 : faces internes * : : 3 : faces de bord * : : 4 : sommets (si disponibles) * INTEGER NBVENT : --> : Nb. valeurs par entité de support * INTEGER IRTYPE : --> : 1 pour entiers, 2 pour double précision * (?) TABVAR : <-> : Tableau des valeurs à lire * INTEGER IERROR : <-- : 0 pour succès, < 0 pour erreur *----------------------------------------------------------------------------*/ void CS_PROCF (lecsui, LECSUI) ( const cs_int_t *const numsui, /* --> Numéro du fichier suite */ const char *const nomrub, /* --> Nom de la rubrique */ const cs_int_t *const lngnom, /* --> Longueur du nom de la rubrique */ const cs_int_t *const itysup, /* --> Type de support (voir ci-dessus) */ const cs_int_t *const nbvent, /* --> Nb. valeurs par entité du support */ const cs_int_t *const irtype, /* --> 1 pour entiers, 2 pour double préc. */ void *const tabvar, /* <-- Tableur des valeurs à lire */ cs_int_t *const ierror /* <-- 0 pour succès, < 0 pour erreur */ CS_ARGF_SUPP_CHAINE /* (arguments 'longueur' éventuels F77, */ /* inutilisés lors de l'appel mais */ /* placés par de nombreux compilateurs) */ ) { char *nombuf; cs_type_t typ_val; cs_suite_t *suite; cs_suite_support_t support; *ierror = CS_SUITE_SUCCES; /* Traitement du nom pour l'API C */ nombuf = cs_base_chaine_f_vers_c_cree(nomrub, *lngnom); /* Traitement des autres arguments pour l'API C */ cs_loc_suite_rub_f77_vers_C(numsui, itysup, irtype, &suite, &support, &typ_val, ierror); if (*ierror < CS_SUITE_SUCCES) return; /* Lecture de la rubrique */ *ierror = cs_suite_lit_rub(suite, nombuf, support, *nbvent, typ_val, tabvar); /* Libération de mémoire si nécessaire */ nombuf = cs_base_chaine_f_vers_c_detruit(nombuf); } /*---------------------------------------------------------------------------- * Écriture d'une rubrique sur fichier suite * * Interface Fortran : * * SUBROUTINE ECRSUI (NUMSUI, NOMRUB, LNGNOM, ITYSUP, NBVENT, IRTYPE, TABVAR) * ***************** * * INTEGER NUMSUI : --> : Numéro du fichier suite * CHARACTER* NOMRUB : --> : Nom de la rubrique * INTEGER LNGNOM : --> : Longueur du nom de la rubrique * INTEGER ITYSUP : --> : Type de support : * : : 0 : scalaire (pas de support) * : : 1 : cellules * : : 2 : faces internes * : : 3 : faces de bord * : : 4 : sommets (si disponibles) * INTEGER NBVENT : --> : Nb. valeurs par entité de support * INTEGER IRTYPE : --> : 1 pour entiers, 2 pour double précision * (?) TABVAR : --> : Tableau des valeurs fournies * INTEGER IERROR : <-- : 0 pour succès, < 0 pour erreur *----------------------------------------------------------------------------*/ void CS_PROCF (ecrsui, ECRSUI) ( const cs_int_t *const numsui, /* --> Numéro du fichier suite */ const char *const nomrub, /* --> Nom de la rubrique */ const cs_int_t *const lngnom, /* --> Longueur du nom de la rubrique */ const cs_int_t *const itysup, /* --> Type de support (voir ci-dessus) */ const cs_int_t *const nbvent, /* --> Nb. valeurs par entité du support */ const cs_int_t *const irtype, /* --> 1 pour entiers, 2 pour double préc. */ const void *const tabvar, /* --> Tableur des valeurs fournies */ cs_int_t *const ierror /* <-- 0 pour succès, < 0 pour erreur */ CS_ARGF_SUPP_CHAINE /* (arguments 'longueur' éventuels F77, */ /* inutilisés lors de l'appel mais */ /* placés par de nombreux compilateurs) */ ) { char *nombuf; cs_type_t typ_val; cs_suite_t *suite; cs_suite_support_t support; *ierror = CS_SUITE_SUCCES; /* Traitement du nom pour l'API C */ nombuf = cs_base_chaine_f_vers_c_cree(nomrub, *lngnom); /* Traitement des autres arguments pour l'API C */ cs_loc_suite_rub_f77_vers_C(numsui, itysup, irtype, &suite, &support, &typ_val, ierror); if (*ierror < CS_SUITE_SUCCES) return; /* Écriture de la rubrique */ cs_suite_ecr_rub(suite, nombuf, support, *nbvent, typ_val, tabvar); /* Libération de mémoire si nécessaire */ nombuf = cs_base_chaine_f_vers_c_detruit(nombuf); } /*============================================================================ * Définitions de fonctions publiques *============================================================================*/ /*---------------------------------------------------------------------------- * Fonction qui initialise un fichier suite *----------------------------------------------------------------------------*/ cs_suite_t * cs_suite_cree ( const char *const nom, /* --> nom de base du fichier */ const cs_suite_mode_t mode, /* --> Lecture ou écriture */ const cs_suite_type_t type /* --> ASCII ou binaire */ ) { cs_bool_t lit_fichier; cs_suite_t * suite; cs_maillage_t *maillage = cs_glob_maillage; /* Instructions */ BFT_MALLOC(suite, 1, cs_suite_t); /* Construction du nom du fichier suite */ BFT_MALLOC(suite->nom, strlen(nom) + 1, char); strcpy(suite->nom, nom); /* Initialisation des autres champs */ suite->mode = mode; suite->type = (mode == CS_SUITE_MODE_LECTURE) ? CS_SUITE_TYPE_BINAIRE : type ; suite->nbr_fic = 0; suite->fic = NULL; /* Initialisation des données du support */ if (suite->mode == CS_SUITE_MODE_LECTURE) { suite->nbr_cel = 0; suite->nbr_fac = 0; suite->nbr_fbr = 0; suite->nbr_som = 0; } else { suite->nbr_cel = maillage->nbr_cel_glob; suite->nbr_fac = maillage->nbr_fac_glob; suite->nbr_fbr = maillage->nbr_fbr_glob; suite->nbr_som = maillage->nbr_som_glob; } /* Initialisation de l'index (pour lecture) */ suite->nbr_rec = 0; suite->tab_rec = NULL; suite->nbr_rec_max = 0; if (suite->mode == CS_SUITE_MODE_LECTURE && cs_glob_base_rang <= 0) { suite->nbr_rec_max = 1; BFT_MALLOC(suite->tab_rec, suite->nbr_rec_max, cs_suite_rec_t); } /* Ouverture du ou des fichier(s) associé(s) et analyse du contenu en lecture ou écriture de l'en-tête en écriture. */ if (cs_glob_base_rang <= 0) { lit_fichier = CS_TRUE; while (lit_fichier == CS_TRUE) lit_fichier = cs_loc_suite_fic_ajoute(suite); } /* En lecture, nettoyage et distribution de l'index */ if (suite->mode == CS_SUITE_MODE_LECTURE) cs_loc_suite_prepare_index(suite); return suite; } /*---------------------------------------------------------------------------- * Fonction qui détruit la structure associée à un fichier suite (et ferme * le fichier associé) ; elle renvoie un pointeur NULL. *----------------------------------------------------------------------------*/ cs_suite_t * cs_suite_detruit ( cs_suite_t * suite /* --> Fichier suite */ ) { assert(suite != NULL); if (suite->fic != NULL) { cs_int_t ind, nbr_fic; if (suite->mode == CS_SUITE_MODE_ECRITURE) { nbr_fic = 1; /* Marquage numéro de suite sur fichier suivant */ switch(suite->type) { case CS_SUITE_TYPE_ASCII: bft_file_printf(suite->fic[0], "[%s]\n", cs_suite_nom_fin_fic); break; case CS_SUITE_TYPE_BINAIRE: { cs_int_t buf[4] = {0, 0, 0, 0}; buf[0] = strlen(cs_suite_nom_fin_fic) + 1; bft_file_write(buf, sizeof(cs_int_t), 4, suite->fic[0]); bft_file_write(cs_suite_nom_fin_fic, 1, buf[0], suite->fic[0]); } break; } } else /* if (suite->mode == CS_SUITE_MODE_LECTURE) */ nbr_fic = suite->nbr_fic; /* Fermeture des fichiers et libération structures associées */ for (ind = 0 ; ind < nbr_fic ; ind++) bft_file_free(suite->fic[ind]); BFT_FREE(suite->fic); } /* Libérations de l'index */ if (suite->nbr_rec > 0) { cs_int_t ind; for (ind = 0 ; ind < suite->nbr_rec ; ind++) BFT_FREE((suite->tab_rec[ind]).nom); } if (suite->tab_rec != NULL) BFT_FREE(suite->tab_rec); /* Dernières libérations mémoire */ BFT_FREE(suite->nom); BFT_FREE(suite); return NULL; } /*---------------------------------------------------------------------------- * Fonction qui vérifie le support associé à un fichier suite ; * On renvoie pour chaque type d'entité CS_TRUE si le nombre d'entités * associées au fichier suite correspond au nombre d'entités en cours (et * donc que l'on considère que le support est bien le même), CS_FALSE sinon. *----------------------------------------------------------------------------*/ void cs_suite_verif_support ( const cs_suite_t *const suite, /* --> Fichier suite */ cs_bool_t *const corresp_cel, /* <-- Corresp. cellules */ cs_bool_t *const corresp_fac, /* <-- Corresp. faces internes */ cs_bool_t *const corresp_fbr, /* <-- Corresp. faces de bord */ cs_bool_t *const corresp_som /* <-- Corresp. sommets */ ) { cs_maillage_t *maillage = cs_glob_maillage; assert(suite != NULL); *corresp_cel = (maillage->nbr_cel_glob == suite->nbr_cel ? CS_TRUE : CS_FALSE); *corresp_fac = (maillage->nbr_fac_glob == suite->nbr_fac ? CS_TRUE : CS_FALSE); *corresp_fbr = (maillage->nbr_fbr_glob == suite->nbr_fbr ? CS_TRUE : CS_FALSE); *corresp_som = (maillage->nbr_som_glob == suite->nbr_som ? CS_TRUE : CS_FALSE); /* Messages d'avertissement pour listing "maître E/S" */ if (cs_glob_base_rang <= 0) { /* * Dimensions du support */ if (suite->nbr_cel != maillage->nbr_cel_glob) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le nombre de cellules associées au fichier suite\n" "<%s> vaut %d et ne correspond pas au maillage en cours\n"), suite->nom, (int)suite->nbr_cel); } if (suite->nbr_fac != maillage->nbr_fac_glob) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le nombre de faces internes associées au fichier suite\n" "<%s> vaut %d et ne correspond pas au maillage en cours\n"), suite->nom, (int)suite->nbr_fac); } if (suite->nbr_fbr != maillage->nbr_fbr_glob) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le nombre de faces de bord associées au fichier suite\n" "<%s> vaut %d et ne correspond pas au maillage en cours\n"), suite->nom, (int)suite->nbr_fbr); } if (suite->nbr_som != maillage->nbr_som_glob) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le nombre de sommets associés au fichier suite\n" "<%s> vaut %d et ne correspond pas au maillage en cours\n"), suite->nom, (int)suite->nbr_som); } } } /*---------------------------------------------------------------------------- * Fonction qui affiche l'index généré lors de l'analyse du fichier *----------------------------------------------------------------------------*/ void cs_suite_affiche_index ( const cs_suite_t *const suite /* --> Structure suite */ ) { cs_int_t ind_rec; assert(suite != NULL); bft_printf(_(" Index associé à la suite : %s\n" " (support, nbr_val/ent, type_val, [ind_fic, pos_fic], " "nom) : \n"), suite->nom); for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) bft_printf(" %s %d %s [%2d %10d] %s\n", cs_suite_nom_support[(suite->tab_rec[ind_rec]).ind_support], (suite->tab_rec[ind_rec]).nbr_val_ent, cs_suite_nom_typ_elt[(suite->tab_rec[ind_rec]).typ_val], (suite->tab_rec[ind_rec]).ind_fic, (int)(suite->tab_rec[ind_rec]).pos_fic, (suite->tab_rec[ind_rec]).nom); bft_printf("\n"); } /*---------------------------------------------------------------------------- * Fonction qui lit un enregistrement sur fichier suite ; On renvoie 0 * (CS_SUITE_SUCCES) en cas de succès, une valeur négative (de type * CS_SUITE_ERR_xxx) en cas d'échec. *----------------------------------------------------------------------------*/ cs_int_t cs_suite_lit_rub ( const cs_suite_t *const suite, /* --> Ptr. structure suite */ const char *const nom_rub, /* --> Nom de la rubrique */ const cs_suite_support_t support, /* --> Support de la variable */ const cs_int_t nbr_val_ent, /* --> Nb. val/point support */ const cs_type_t typ_val, /* --> Type de valeurs */ void *const val /* <-- Valeurs à lire */ ) { char buffer_ascii[CS_SUITE_LNG_BUF_ASCII + 1]; cs_int_t nbr_val_tot, nbr_ent_glob, nbr_ent_loc; fvm_gnum_t *num_glob_ent; cs_int_t ind_rec; bft_file_t *fic; cs_maillage_t *maillage = cs_glob_maillage; assert(suite != NULL); buffer_ascii[0] = '\0'; /* Vérification du support associé */ switch (support) { case CS_SUITE_SUPPORT_SCAL: break; case CS_SUITE_SUPPORT_CEL: if (maillage->nbr_cel_glob != suite->nbr_cel) return CS_SUITE_ERR_SUPPORT; break; case CS_SUITE_SUPPORT_FAC_INT: if (maillage->nbr_fac_glob != suite->nbr_fac) return CS_SUITE_ERR_SUPPORT; break; case CS_SUITE_SUPPORT_FAC_BRD: if (maillage->nbr_fbr_glob != suite->nbr_fbr) return CS_SUITE_ERR_SUPPORT; break; case CS_SUITE_SUPPORT_SOM: if (maillage->nbr_som_glob != suite->nbr_som) return CS_SUITE_ERR_SUPPORT; break; default: assert(support <= CS_SUITE_SUPPORT_SOM); } /* On recherche l'enregistrement correspondant dans l'index */ for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) { if (strcmp((suite->tab_rec[ind_rec]).nom, nom_rub) == 0) break; } /* Si on n'a pas trouvé l'enregistrement */ if (ind_rec >= suite->nbr_rec) return CS_SUITE_ERR_EXISTE; /* Si le support ne correspond pas ; on recherche un enregistrement de même nom mais de support approprié. */ if ( (cs_suite_support_t)((suite->tab_rec[ind_rec]).ind_support) != support) { for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) { if ( (strncmp((suite->tab_rec[ind_rec]).nom, nom_rub, strlen((suite->tab_rec[ind_rec]).nom)) == 0) && ((cs_suite_support_t)((suite->tab_rec[ind_rec]).ind_support) == support)) break; } if (ind_rec >= suite->nbr_rec) return CS_SUITE_ERR_SUPPORT; } /* Si le nombre de valeurs par entité ne correspond pas */ if ((suite->tab_rec[ind_rec]).nbr_val_ent != nbr_val_ent) return CS_SUITE_ERR_NBR_VAL; /* Si le type de valeurs ne correspond pas */ if ((cs_type_t)((suite->tab_rec[ind_rec]).typ_val) != typ_val) return CS_SUITE_ERR_TYPE_VAL; /* Sinon, on se positionne pour effectuer la lecture */ if (cs_glob_base_rang <= 0) { fic = suite->fic[(suite->tab_rec[ind_rec]).ind_fic]; bft_file_seek(fic, (suite->tab_rec[ind_rec]).pos_fic, BFT_FILE_SEEK_SET); } /* Contenu de la rubrique */ /*------------------------*/ nbr_val_tot = cs_loc_suite_calc_nbr_ent(suite, support, nbr_val_ent); /* En mode non-parallèle */ if (cs_glob_base_rang < 0) cs_loc_suite_lit_val(suite->type, fic, nbr_val_tot, typ_val, val, buffer_ascii); #if defined(_CS_HAVE_MPI) /* Variable indépendante du support et commune aux processus */ else if (support == CS_SUITE_SUPPORT_SCAL) { if (cs_glob_base_rang == 0) cs_loc_suite_lit_val(suite->type, fic, nbr_val_tot, typ_val, val, buffer_ascii); cs_loc_suite_distr_val(nbr_val_tot, typ_val, val); } /* En mode parallèle sur une entité de maillage */ else { cs_int_t nbr_bloc; switch(support) { case CS_SUITE_SUPPORT_CEL: nbr_ent_glob = maillage->nbr_cel_glob; nbr_ent_loc = maillage->nbr_cel; num_glob_ent = maillage->num_cel; break; case CS_SUITE_SUPPORT_FAC_INT: nbr_ent_glob = maillage->nbr_fac_glob; nbr_ent_loc = maillage->nbr_fac; num_glob_ent = maillage->num_fac; break; case CS_SUITE_SUPPORT_FAC_BRD: nbr_ent_glob = maillage->nbr_fbr_glob; nbr_ent_loc = maillage->nbr_fbr; num_glob_ent = maillage->num_fbr; break; case CS_SUITE_SUPPORT_SOM: nbr_ent_glob = maillage->nbr_som_glob; nbr_ent_loc = maillage->nbr_som; num_glob_ent = maillage->num_som; break; default: assert( support > CS_SUITE_SUPPORT_SCAL && support <= CS_SUITE_SUPPORT_SOM); } nbr_bloc = ( ((sizeof(cs_real_t) * nbr_ent_glob * nbr_val_ent) - 1) / cs_suite_taille_buf_def) + 1; if (nbr_bloc > cs_glob_base_nbr) nbr_bloc = cs_glob_base_nbr; cs_loc_suite_lit_val_ent(suite, fic, nbr_bloc, nbr_ent_glob, nbr_ent_loc, num_glob_ent, nbr_val_ent, typ_val, (cs_byte_t *)val); } #endif /* #if defined(_CS_HAVE_MPI) */ /* Traitement des renumérotations éventuelles */ switch (support) { case CS_SUITE_SUPPORT_FAC_INT: cs_loc_suite_permute_lec(maillage->nbr_fac, maillage->num_fac_ini, nbr_val_ent, typ_val, val); break; case CS_SUITE_SUPPORT_FAC_BRD: cs_loc_suite_permute_lec(maillage->nbr_fbr, maillage->num_fbr_ini, nbr_val_ent, typ_val, val); break; default: break; } /* Retour */ return CS_SUITE_SUCCES; } /*---------------------------------------------------------------------------- * Fonction qui écrit un enregistrement sur fichier suite *----------------------------------------------------------------------------*/ void cs_suite_ecr_rub ( cs_suite_t *const suite, /* --> Ptr. structure suite */ const char *const nom_rub, /* --> Nom de la rubrique */ const cs_suite_support_t support, /* --> Support de la variable */ const cs_int_t nbr_val_ent, /* --> Nb. val/point support */ const cs_type_t typ_val, /* --> Type de valeurs */ const void *const val /* --> Valeurs à écrire */ ) { cs_int_t nbr_val_tot, nbr_ent_glob, nbr_ent_loc; fvm_gnum_t *num_glob_ent; bft_file_off_t taille_rub, pos_fic_cur; cs_byte_t *val_tmp; cs_int_t ind_col_0 = 0; cs_maillage_t *maillage = cs_glob_maillage; assert(suite != NULL); assert( suite->type == CS_SUITE_TYPE_ASCII || suite->type == CS_SUITE_TYPE_BINAIRE); /* En fonction de la taille max, on bascule ou non sur un nouveau fichier. */ /* ----------------------------------------------------------------------- */ if (cs_glob_base_rang <= 0) { /* Taille données */ taille_rub = cs_loc_suite_calc_avance(suite, support, nbr_val_ent, typ_val); /* * Taille en-tête (surestimée : on doit pouvoir contenir l'entête, * et il doit rester assez de place après l'enregistrement pour * écrire un indicateur de poursuite sur fichier suivant, sans * dépasser la taille indiquée) */ taille_rub += strlen(nom_rub); taille_rub += 200; /* Traitement */ pos_fic_cur = bft_file_tell(suite->fic[0]); if (CS_SUITE_TAILLE_FIC_MAX - taille_rub <= pos_fic_cur) { switch(suite->type) { case CS_SUITE_TYPE_ASCII: bft_file_printf(suite->fic[0], "[%s]\n", cs_suite_nom_decoup_fic); break; case CS_SUITE_TYPE_BINAIRE: { cs_int_t buf[4] = {0, 0, 0, 0}; buf[0] = strlen(cs_suite_nom_decoup_fic) + 1; bft_file_write(buf, sizeof(cs_int_t), 4, suite->fic[0]); bft_file_write(cs_suite_nom_decoup_fic, 1, buf[0], suite->fic[0]); } break; } /* Bascule effective sur fichier suivant */ cs_loc_suite_fic_ajoute(suite); /* Marquage numéro de suite sur fichier suivant */ switch(suite->type) { case CS_SUITE_TYPE_ASCII: bft_file_printf(suite->fic[0], "[%s%2d]\n", cs_suite_nom_partie_fic, (int)suite->nbr_fic); break; case CS_SUITE_TYPE_BINAIRE: { cs_int_t buf[4] = {0, 0, 0, 0}; buf[0] = strlen(cs_suite_nom_partie_fic) + 1; buf[1] = suite->nbr_fic; bft_file_write(buf, sizeof(cs_int_t), 4, suite->fic[0]); bft_file_write(cs_suite_nom_partie_fic, 1, buf[0], suite->fic[0]); } break; } } } /* Entête de la rubrique */ /* --------------------- */ if (cs_glob_base_rang <= 0) { switch(suite->type) { case CS_SUITE_TYPE_ASCII: bft_file_printf(suite->fic[0], "[%s\n", nom_rub); bft_file_printf(suite->fic[0], " support = %3s, nbr_val_ent = %3d, typ_val = %3s]\n", cs_suite_nom_support[(int)support], (int)nbr_val_ent, cs_suite_nom_typ_elt[(int)typ_val]); break; case CS_SUITE_TYPE_BINAIRE: { cs_int_t buf[4]; buf[0] = strlen(nom_rub) + 1; buf[1] = (int)support; buf[2] = (int)nbr_val_ent; buf[3] = (int)typ_val; bft_file_write(buf, sizeof(cs_int_t), 4, suite->fic[0]); bft_file_write(nom_rub, 1, buf[0], suite->fic[0]); } break; } } /* Traitement des renumérotations éventuelles */ switch (support) { case CS_SUITE_SUPPORT_FAC_INT: val_tmp = cs_loc_suite_permute_ecr(maillage->nbr_fac, maillage->num_fac_ini, nbr_val_ent, typ_val, val); break; case CS_SUITE_SUPPORT_FAC_BRD: val_tmp = cs_loc_suite_permute_ecr(maillage->nbr_fbr, maillage->num_fbr_ini, nbr_val_ent, typ_val, val); break; default: val_tmp = NULL; } /* Contenu de la rubrique */ /*------------------------*/ nbr_val_tot = cs_loc_suite_calc_nbr_ent(suite, support, nbr_val_ent); /* En mode non-parallèle */ if (cs_glob_base_rang < 0) { cs_loc_suite_ecr_val(suite, nbr_val_tot, typ_val, (val_tmp != NULL) ? val_tmp : val, &ind_col_0); cs_loc_suite_ecr_val_fin(suite, &ind_col_0); } #if defined(_CS_HAVE_MPI) /* Variable indépendante du support et commune aux processus */ else if (support == CS_SUITE_SUPPORT_SCAL) { if (cs_glob_base_rang == 0) { cs_loc_suite_ecr_val(suite, nbr_val_tot, typ_val, (val_tmp != NULL) ? val_tmp : val, &ind_col_0); cs_loc_suite_ecr_val_fin(suite, &ind_col_0); } } /* En mode parallèle sur une entité de maillage */ else { cs_int_t nbr_bloc; switch(support) { case CS_SUITE_SUPPORT_CEL: nbr_ent_glob = maillage->nbr_cel_glob; nbr_ent_loc = maillage->nbr_cel; num_glob_ent = maillage->num_cel; break; case CS_SUITE_SUPPORT_FAC_INT: nbr_ent_glob = maillage->nbr_fac_glob; nbr_ent_loc = maillage->nbr_fac; num_glob_ent = maillage->num_fac; break; case CS_SUITE_SUPPORT_FAC_BRD: nbr_ent_glob = maillage->nbr_fbr_glob; nbr_ent_loc = maillage->nbr_fbr; num_glob_ent = maillage->num_fbr; break; case CS_SUITE_SUPPORT_SOM: nbr_ent_glob = maillage->nbr_som_glob; nbr_ent_loc = maillage->nbr_som; num_glob_ent = maillage->num_som; break; default: assert( support > CS_SUITE_SUPPORT_SCAL && support <= CS_SUITE_SUPPORT_SOM); } nbr_bloc = ( ((sizeof(cs_real_t) * nbr_ent_glob * nbr_val_ent) - 1) / cs_suite_taille_buf_def) + 1; if (nbr_bloc > cs_glob_base_nbr) nbr_bloc = cs_glob_base_nbr; cs_loc_suite_ecr_val_ent (suite, nbr_bloc, nbr_ent_glob, nbr_ent_loc, num_glob_ent, nbr_val_ent, typ_val, (val_tmp != NULL) ? val_tmp : (const cs_byte_t *)val); } #endif /* #if defined(_CS_HAVE_MPI) */ if (val_tmp != NULL) BFT_FREE (val_tmp); } /*---------------------------------------------------------------------------- * Fonction qui initialise l'API Fortran *----------------------------------------------------------------------------*/ void cs_suite_f77_api_init ( void ) { cs_int_t ind; /* Allocation du tableau des pointeurs */ cs_glob_suite_ptr_nbr = 10; BFT_MALLOC(cs_glob_suite_ptr_tab, cs_glob_suite_ptr_nbr, cs_suite_t *); /* Mise à zéro du tableau des pointeurs */ for (ind = 0 ; ind < cs_glob_suite_ptr_nbr ; ind++) cs_glob_suite_ptr_tab[ind] = NULL; } /*---------------------------------------------------------------------------- * Fonction qui termine l'API Fortran *----------------------------------------------------------------------------*/ void cs_suite_f77_api_finalize ( void ) { cs_int_t ind; /* Fermeture des fichiers qui ne le seraient pas */ for (ind = 0 ; ind < cs_glob_suite_ptr_nbr ; ind++) { if (cs_glob_suite_ptr_tab[ind] != NULL) cs_suite_detruit (cs_glob_suite_ptr_tab[ind]); } /* Libération du tableau des pointeurs */ cs_glob_suite_ptr_nbr = 0; BFT_FREE(cs_glob_suite_ptr_tab); } /*============================================================================ * Définitions de fonctions privées *============================================================================*/ /*---------------------------------------------------------------------------- * Calcul du nombre de valeurs d'un enregistrement *----------------------------------------------------------------------------*/ static cs_int_t cs_loc_suite_calc_nbr_ent ( const cs_suite_t *const suite, /* --> Suite associée */ const cs_suite_support_t support, /* --> Support de la variable */ const cs_int_t nbr_val_ent /* --> Nb. val/point support */ ) { switch(support) { case CS_SUITE_SUPPORT_SCAL: return (nbr_val_ent); case CS_SUITE_SUPPORT_CEL: return (suite->nbr_cel * nbr_val_ent); case CS_SUITE_SUPPORT_FAC_INT: return (suite->nbr_fac * nbr_val_ent); case CS_SUITE_SUPPORT_FAC_BRD: return (suite->nbr_fbr * nbr_val_ent); case CS_SUITE_SUPPORT_SOM: return (suite->nbr_som * nbr_val_ent); default: assert(support <= CS_SUITE_SUPPORT_SOM); } return 0; } /*---------------------------------------------------------------------------- * Calcul du déplacement dans un fichier correspondant aux valeurs * d'une rubrique. *----------------------------------------------------------------------------*/ static bft_file_off_t cs_loc_suite_calc_avance ( const cs_suite_t *const suite, /* --> Suite associée */ const cs_suite_support_t support, /* --> Support de la variable */ const cs_int_t nbr_val_ent, /* --> Nb. val/point support */ const cs_type_t typ_val /* --> Type de valeurs */ ) { cs_int_t nbr_val; bft_file_off_t taille; assert( suite->type == CS_SUITE_TYPE_ASCII || suite->type == CS_SUITE_TYPE_BINAIRE); assert(typ_val == CS_TYPE_cs_int_t || typ_val == CS_TYPE_cs_real_t); nbr_val = cs_loc_suite_calc_nbr_ent(suite, support, nbr_val_ent); if (suite->type == CS_SUITE_TYPE_ASCII) { cs_int_t nbr_val_par_ligne, largeur_col; cs_int_t nbr_ligne_complet, nbr_val_reste; switch (typ_val) { case CS_TYPE_cs_int_t: nbr_val_par_ligne = CS_SUITE_FMT_ASCII_NBR_COL_INT; largeur_col = CS_SUITE_FMT_ASCII_DIM_COL_INT; break; case CS_TYPE_cs_real_t: nbr_val_par_ligne = CS_SUITE_FMT_ASCII_NBR_COL_REAL; largeur_col = CS_SUITE_FMT_ASCII_DIM_COL_REAL; break; default: return 0; } nbr_ligne_complet = nbr_val / nbr_val_par_ligne; nbr_val_reste = nbr_val % nbr_val_par_ligne; /* Nombre valeurs * largeur associée + fins des lignes entières */ taille = (nbr_val * largeur_col) + nbr_ligne_complet; if (nbr_val_reste > 0) taille += 1; /* dernière fin de ligne */ } else if (suite->type == CS_SUITE_TYPE_BINAIRE) { switch (typ_val) { case CS_TYPE_cs_int_t: taille = nbr_val * sizeof(cs_int_t); break; case CS_TYPE_cs_real_t: taille = nbr_val * sizeof(cs_real_t); break; default: return 0; } } return (taille); } /*---------------------------------------------------------------------------- * Fonction qui initialise une structure fichier associée à une suite ; * Le nom de fichier associé correspond au nom de la suite pour le * premier fichier, prolongé éventuellement par '_pxx' pour les fichiers * successifs en cas de découpage du fichier en plusieurs morceaux pour * des gros volumes de données. * On indique en retour si les données se poursuivent sur un autre fichier. *----------------------------------------------------------------------------*/ static cs_bool_t cs_loc_suite_fic_ajoute ( cs_suite_t *const suite /* --> Structure suite */ ) { /* On ne change le numero que si les fichiers suite des * versions precedentes ne sont plus compatibles. Ce numero est en * fait deconnecte du numero de version */ char entete_txt[] = "Code_Saturne 1.1 (reprise)\n"; char entete_bin[] = "Code_Saturne_1.1_bin_reprise\n"; char buffer[CS_SUITE_LNG_BUF_ASCII + 1]; char *nom_fic = NULL; cs_int_t ind_fic = 0; bft_file_mode_t fic_mode; bft_file_type_t fic_type; cs_bool_t autre_partie = CS_FALSE; /* Instructions */ if (cs_glob_base_rang > 0) return CS_FALSE; /* Incrémentation du compteur */ suite->nbr_fic += 1; /* Construction du nom du fichier suite */ if (suite->nbr_fic == 1) nom_fic = suite->nom; else { BFT_MALLOC(nom_fic, strlen(suite->nom) + strlen("_pxx") + 1, char); sprintf(nom_fic, "%s_p%02d", suite->nom, suite->nbr_fic); } /* Création du descripteur de fichier d'interface */ /*------------------------------------------------*/ /* En lecture, on détecte le type binaire/texte automatiquement (en commencant par une tentative en mode binaire) ; en cas de découpage en plusieurs fichiers pour gros volumes de données, tous les fichiers doivent être de même type. En écriture, on choisit le type. */ if (suite->mode == CS_SUITE_MODE_LECTURE) { fic_mode = BFT_FILE_MODE_READ; fic_type = BFT_FILE_TYPE_BINARY; } else { fic_mode = BFT_FILE_MODE_WRITE; if (suite->type == BFT_FILE_TYPE_TEXT) fic_type = BFT_FILE_TYPE_TEXT; else fic_type = BFT_FILE_TYPE_BINARY; } /* Création du fichier */ if (suite->mode == CS_SUITE_MODE_LECTURE) { ind_fic = suite->nbr_fic - 1; BFT_REALLOC(suite->fic, suite->nbr_fic, bft_file_t *); } else if (suite->mode == CS_SUITE_MODE_ECRITURE) { ind_fic = 0; if (suite->fic == NULL) BFT_MALLOC(suite->fic, 1, bft_file_t *); else if (suite->fic[0] != NULL) bft_file_free(suite->fic[0]); } suite->fic[ind_fic] = bft_file_open(nom_fic, fic_mode, fic_type); if (fic_type == BFT_FILE_TYPE_BINARY) bft_file_set_big_endian(suite->fic[ind_fic]); /* Gestion des en-têtes selon le mode d'ouverture */ /*------------------------------------------------*/ /* Lecture de l'en-tête */ if (suite->mode == CS_SUITE_MODE_LECTURE) { cs_int_t nbr_rec, nbr_lus; cs_int_t num_ligne = 1; char *str; cs_suite_type_t suite_type_detect = CS_SUITE_TYPE_BINAIRE; /* Détection automatique de type de fichier */ nbr_rec = strlen(entete_bin); nbr_lus = bft_file_read_try(buffer, 1, nbr_rec, suite->fic[ind_fic]); if (strncmp(entete_bin, buffer, nbr_rec) != 0) { assert( CS_SUITE_LNG_BUF_ASCII > strlen(entete_txt) && CS_SUITE_LNG_BUF_ASCII > strlen(entete_bin)); bft_file_free(suite->fic[ind_fic]); fic_type = BFT_FILE_TYPE_TEXT; suite->fic[ind_fic] = bft_file_open(nom_fic, fic_mode, fic_type); nbr_rec = strlen(entete_txt); str = bft_file_gets_try(buffer, CS_SUITE_LNG_BUF_ASCII, suite->fic[ind_fic], &num_ligne); if (str != NULL) { nbr_rec = strlen(entete_txt); if (strncmp(entete_txt, buffer, nbr_rec) == 0) suite_type_detect = CS_SUITE_TYPE_ASCII; } if (suite_type_detect != CS_SUITE_TYPE_ASCII) bft_error(__FILE__, __LINE__, 0, _("Le fichier <%s> n'est pas un fichier suite valide\n"), nom_fic); } if (suite->type != suite_type_detect) { if (suite->nbr_fic > 1) bft_error(__FILE__, __LINE__, 0, _("Le fichier suite <%s> et son prolongement\n" "<%s> ne sont du même type (texte/binaire) ;\n" "ils ne correspondent pas au même jeu de données\n"), suite->nom, nom_fic); else suite->type = suite_type_detect; } if (suite->type == CS_SUITE_TYPE_ASCII) autre_partie = cs_loc_suite_analyse_txt(suite); else if (suite->type == CS_SUITE_TYPE_BINAIRE) autre_partie = cs_loc_suite_analyse_bin(suite); } /* Écriture de l'en-tête */ else if (suite->mode == CS_SUITE_MODE_ECRITURE) { switch(suite->type) { case CS_SUITE_TYPE_ASCII: bft_file_printf(suite->fic[0], entete_txt); bft_file_printf(suite->fic[0], "[nbr_cel = %d]\n", (int)cs_glob_maillage->nbr_cel_glob); bft_file_printf(suite->fic[0], "[nbr_fac_int = %d]\n", (int)cs_glob_maillage->nbr_fac_glob); bft_file_printf(suite->fic[0], "[nbr_fac_brd = %d]\n", (int)cs_glob_maillage->nbr_fbr_glob); bft_file_printf(suite->fic[0], "[nbr_som = %d]\n", (int)cs_glob_maillage->nbr_som_glob); break; case CS_SUITE_TYPE_BINAIRE: { cs_int_t buf[4]; buf[0] = cs_glob_maillage->nbr_cel_glob; buf[1] = cs_glob_maillage->nbr_fac_glob; buf[2] = cs_glob_maillage->nbr_fbr_glob; buf[3] = cs_glob_maillage->nbr_som_glob; bft_file_write(entete_bin, 1, strlen(entete_bin),suite->fic[0]); bft_file_write(buf, sizeof(cs_int_t), 4, suite->fic[0]); } break; default: assert ( suite->type == CS_SUITE_TYPE_ASCII || suite->type == CS_SUITE_TYPE_BINAIRE); } } /* Libération mémoire */ if (nom_fic != suite->nom) BFT_FREE(nom_fic); /* On indique en retour si le fichier continue */ return autre_partie; } /*---------------------------------------------------------------------------- * Fonction qui lit une liste de valeurs sur un fichier ; on suppose que * l'on est déjà à la bonne position de départ dans le fichier. *----------------------------------------------------------------------------*/ static void cs_loc_suite_lit_val ( const cs_suite_type_t type, /* --> Structure suite */ const bft_file_t *const fic, /* --> Fichier associé */ const cs_int_t nbr_val, /* --> Nb. valeurs à lire */ const cs_type_t typ_val, /* --> Type de valeurs */ void *const val, /* <-- Valeurs à lire */ char asc_buffer[] /* <-> Buffer texte */ ) { /* Traitement des fichiers binaires (simple) */ if (type == CS_SUITE_TYPE_BINAIRE) { cs_int_t typ_taille = 1; switch (typ_val) { case CS_TYPE_cs_int_t: typ_taille = sizeof(cs_int_t); break; case CS_TYPE_cs_real_t: typ_taille = sizeof(cs_real_t); break; default: assert ( typ_val != CS_TYPE_cs_int_t || typ_val != CS_TYPE_cs_real_t); } bft_file_read(val, typ_taille, nbr_val, fic); } /* Traitement des fichiers formatés (plus complexe) */ else if (type == CS_SUITE_TYPE_ASCII) { char fmt_lec[4]; cs_int_t ind_val; char *str = asc_buffer; cs_int_t num_ligne = 1; fmt_lec[0] = '%'; switch (typ_val) { case CS_TYPE_cs_int_t: { const cs_int_t *const tab_val_int = (const cs_int_t *)val; /* Attention au format de lecture (longueur des types) ! */ if (sizeof(cs_int_t) == sizeof(int)) fmt_lec[1] = 'd', fmt_lec[2] = '\0'; else if(sizeof(cs_int_t) == sizeof(long)) fmt_lec[1] = 'l', fmt_lec[2] = 'd', fmt_lec[3] = '\0'; else fmt_lec[1] = 'L', fmt_lec[2] = 'd', fmt_lec[3] = '\0'; /* Lecture effective */ for (ind_val = 0 ; ind_val < nbr_val ; ind_val++) { char col_deb = *str; if (col_deb == '\n' || col_deb == '\0') str = bft_file_gets(asc_buffer, CS_SUITE_LNG_BUF_ASCII, fic, &num_ligne); else { if (col_deb != ' ' && col_deb != '\t') bft_error(__FILE__, __LINE__, 0, _("Erreur à la lecture d'un tableau d'entiers dans un " "fichier suite :\n" "champs de largeur différente de %d"), CS_SUITE_FMT_ASCII_DIM_COL_INT); } if (str == NULL) break; if (sscanf(str, fmt_lec, &(tab_val_int[ind_val])) != 1) bft_error(__FILE__, __LINE__, 0, _("Erreur à la lecture d'un tableau d'entiers dans un " "fichier suite :\n" "%ul sur %ul valeurs lues"), (unsigned long)ind_val, (unsigned long)nbr_val); str += CS_SUITE_FMT_ASCII_DIM_COL_INT; } if (ind_val < nbr_val) bft_error(__FILE__, __LINE__, 0, _("Erreur à la lecture d'un tableau d'entiers dans un " "fichier suite :\n" "%ul sur %ul valeurs lues"), (unsigned long)ind_val, (unsigned long)nbr_val); } break; case CS_TYPE_cs_real_t: { const cs_real_t *const tab_val_real = (const cs_real_t *)val; /* Attention au format de lecture (longueur des types) ! */ if (sizeof(cs_real_t) == sizeof(float)) fmt_lec[1] = 'g', fmt_lec[2] = '\0'; else if (sizeof(cs_real_t) == sizeof(double)) fmt_lec[1] = 'l', fmt_lec[2] = 'g', fmt_lec[3] = '\0'; else fmt_lec[1] = 'L', fmt_lec[2] = 'g', fmt_lec[3] = '\0'; /* Lecture effective */ for (ind_val = 0 ; ind_val < nbr_val ; ind_val++) { char col_deb = *str; if (col_deb == '\n' || col_deb == '\0') str = bft_file_gets(asc_buffer, CS_SUITE_LNG_BUF_ASCII, fic, &num_ligne); else { if (col_deb != ' ' && col_deb != '\t') bft_error(__FILE__, __LINE__, 0, _("Erreur à la lecture d'un tableau de réels dans un " "fichier suite :\n" "champs de largeur différente de %d"), CS_SUITE_FMT_ASCII_DIM_COL_REAL); } if (str == NULL) break; if (sscanf(str, fmt_lec, &(tab_val_real[ind_val])) != 1) bft_error(__FILE__, __LINE__, 0, _("Erreur à la lecture d'un tableau de réels dans un " "fichier suite :\n" "%ul sur %ul valeurs lues"), (unsigned long)ind_val, (unsigned long)nbr_val); str += CS_SUITE_FMT_ASCII_DIM_COL_REAL; } if (ind_val < nbr_val) bft_error(__FILE__, __LINE__, 0, _("Erreur à la lecture d'un tableau de réels dans un " "fichier suite :\n" "%ul sur %ul valeurs lues"), (unsigned long)ind_val, (unsigned long)nbr_val); } break; default: assert( typ_val != CS_TYPE_cs_int_t || typ_val != CS_TYPE_cs_real_t); } /* Fin : switch (typ_val) */ } } /*---------------------------------------------------------------------------- * Fonction qui écrit une liste de valeurs sur un fichier *----------------------------------------------------------------------------*/ static void cs_loc_suite_ecr_val ( const cs_suite_t *const suite, /* --> Ptr. fichier suite */ const cs_int_t nbr_val, /* --> Nb. valeurs à écrire */ const cs_type_t typ_val, /* --> Type de valeurs */ const void *const val, /* --> Valeurs à écrire */ cs_int_t *const ind_col /* <-> Colonne départ/fin */ ) { /* Traitement des fichiers binaires (simple) */ if (suite->type == CS_SUITE_TYPE_BINAIRE) { cs_int_t typ_taille = 1; switch (typ_val) { case CS_TYPE_cs_int_t: typ_taille = sizeof(cs_int_t); break; case CS_TYPE_cs_real_t: typ_taille = sizeof(cs_real_t); break; default: assert( typ_val != CS_TYPE_cs_int_t || typ_val != CS_TYPE_cs_real_t); } bft_file_write(val, typ_taille, nbr_val, suite->fic[0]); } /* Traitement des fichiers formatés (plus complexe) */ else if (suite->type == CS_SUITE_TYPE_ASCII) { cs_int_t ind_val; switch (typ_val) { case CS_TYPE_cs_int_t: { const cs_int_t *const tab_val_int = (const cs_int_t *)val; for (ind_val = 0 ; ind_val < nbr_val ; ind_val++) { if (*ind_col == CS_SUITE_FMT_ASCII_NBR_COL_INT) { *ind_col = 0; bft_file_printf(suite->fic[0], "\n"); } *ind_col += 1; bft_file_printf(suite->fic[0], cs_suite_fmt_ascii_tab_int, tab_val_int[ind_val]); } } break; case CS_TYPE_cs_real_t: { const cs_real_t *const tab_val_real = (const cs_real_t *)val; for (ind_val = 0 ; ind_val < nbr_val ; ind_val++) { if (*ind_col == CS_SUITE_FMT_ASCII_NBR_COL_REAL) { *ind_col = 0; bft_file_printf(suite->fic[0], "\n"); } *ind_col += 1; bft_file_printf(suite->fic[0], cs_suite_fmt_ascii_tab_real, tab_val_real[ind_val]); } } break; default: assert( typ_val != CS_TYPE_cs_int_t || typ_val != CS_TYPE_cs_real_t); } /* Fin : switch (typ_val) */ } } /*---------------------------------------------------------------------------- * Fonction qui termine l'écriture d'une liste de valeurs sur un fichier *----------------------------------------------------------------------------*/ static void cs_loc_suite_ecr_val_fin ( const cs_suite_t *const suite, /* --> Ptr. fichier suite */ cs_int_t *const ind_col /* <-> Colonne départ/fin */ ) { /* Rien à faire pour les fichiers binaires */ /* Traitement des fichiers formatés */ if (suite->type == CS_SUITE_TYPE_ASCII) { bft_file_printf(suite->fic[0], "\n"); *ind_col = 0; } } #if defined(_CS_HAVE_MPI) /*---------------------------------------------------------------------------- * Fonction qui créé des listes locales->globales associées à chaque bloc. * * Pour le processus "maître E/S", le tableau "nbr_ent_bloc" indiquant le * nombre d'entités appartenant à chaque bloc, et ceci pour chaque domaine : * nbr_ent(bloc, domaine) = nbr_ent_bloc[nbr_bloc * ind_dom + ind_bloc] ; * Pour les autres processus, le tableau "nbr_ent_loc" indique le nombre * d'entités locales appartenant à chaque bloc. * Les tableaux "lst_ent_loc" et "lst_ent_glob" donnent les indices locaux * et globaux des entités locales appartenant à chaque bloc (nbr_ent_loc[0] * premières valeurs pour le bloc 0, nbr_ent_loc[1] suivantes pour le * second, etc.) * * Ces tableaux sont alloués ici et devront être libérés par la suite. * * On renvoie la plus grande valeur (globale) de nbr_ent_loc. *----------------------------------------------------------------------------*/ static cs_int_t cs_loc_suite_cree_listes_ent ( const cs_int_t nbr_bloc, /* --> Nombre de blocs */ const cs_int_t nbr_ent_glob, /* --> Nombre global d'entités */ const cs_int_t nbr_ent_loc, /* --> Nombre local d'entités */ const fvm_gnum_t *const num_glob_ent, /* --> Numéros globaux des entités */ cs_int_t *const pas_bloc, /* <-- Taille blocs (sauf dernier) */ cs_int_t * *const nbr_ent_bloc, /* <-- Nombre d'entités par bloc */ cs_int_t * *const lst_ent_loc, /* <-- Liste des entités par bloc */ cs_int_t * *const lst_ent_glob /* <-- Liste des entités par bloc */ ) { cs_int_t ind, ind_bloc, ind_glob_ent; cs_int_t taille_max_loc, taille_max_glob; cs_int_t *pos_ent_bloc; cs_int_t *nbr_ent_bloc_loc; /* pas_bloc = ceil(nbr_ent_glob/nbr_bloc) */ *pas_bloc = nbr_ent_glob / nbr_bloc; if (nbr_ent_glob % nbr_bloc > 0) *pas_bloc += 1; /* Allocation */ BFT_MALLOC(*lst_ent_loc, nbr_ent_loc, cs_int_t); BFT_MALLOC(*lst_ent_glob, nbr_ent_loc, cs_int_t); if (cs_glob_base_rang == 0) { BFT_MALLOC(*nbr_ent_bloc, nbr_bloc * cs_glob_base_nbr, cs_int_t); BFT_MALLOC(nbr_ent_bloc_loc, nbr_bloc, cs_int_t); } else { BFT_MALLOC(*nbr_ent_bloc, nbr_bloc, cs_int_t); nbr_ent_bloc_loc = *nbr_ent_bloc; } BFT_MALLOC(pos_ent_bloc, nbr_bloc, cs_int_t); /* Comptage */ for (ind_bloc = 0 ; ind_bloc < nbr_bloc ; ind_bloc++) nbr_ent_bloc_loc[ind_bloc] = 0; for (ind = 0 ; ind < nbr_ent_loc ; ind++) { ind_bloc = (num_glob_ent[ind] - 1) / *pas_bloc; nbr_ent_bloc_loc[ind_bloc] += 1; } /* Affectation */ pos_ent_bloc[0] = 0; for (ind_bloc = 1 ; ind_bloc < nbr_bloc ; ind_bloc++) pos_ent_bloc[ind_bloc] = pos_ent_bloc[ind_bloc - 1] + nbr_ent_bloc_loc[ind_bloc - 1]; for (ind = 0 ; ind < nbr_ent_loc ; ind++) { ind_glob_ent = num_glob_ent[ind] - 1; ind_bloc = ind_glob_ent / *pas_bloc; (*lst_ent_loc) [pos_ent_bloc[ind_bloc]] = ind; (*lst_ent_glob)[pos_ent_bloc[ind_bloc]] = ind_glob_ent % (*pas_bloc); pos_ent_bloc[ind_bloc] += 1; } BFT_FREE(pos_ent_bloc); /* * Dimensionnement des messages ; le processus "maître E/S" stocke * le nombre d'entités par bloc et par domaine externe : * nbr_ent_bloc[ind_dom][ind_bloc] */ MPI_Gather(nbr_ent_bloc_loc, nbr_bloc, CS_MPI_INT, *nbr_ent_bloc, nbr_bloc, CS_MPI_INT, 0, cs_glob_base_mpi_comm); if (cs_glob_base_rang == 0) BFT_FREE(nbr_ent_bloc_loc); else nbr_ent_bloc_loc = NULL; /* Tailles des divers messages */ taille_max_loc = (*nbr_ent_bloc)[0]; for (ind_bloc = 1 ; ind_bloc < nbr_bloc ; ind_bloc++) taille_max_loc = CS_MAX(taille_max_loc, (*nbr_ent_bloc)[ind_bloc]); MPI_Allreduce(&taille_max_loc, &taille_max_glob, 1, CS_MPI_INT, MPI_MAX, cs_glob_base_mpi_comm); return taille_max_glob; } /*---------------------------------------------------------------------------- * Fonction qui lit les valeurs associées à une variable définie sur * une entité de maillage. *----------------------------------------------------------------------------*/ static void cs_loc_suite_lit_val_ent ( const cs_suite_t *const suite, /* --> Structure suite */ const bft_file_t *const fic, /* --> Fichier associé aux valeurs */ const cs_int_t nbr_bloc, /* --> Nombre de blocs */ const cs_int_t nbr_ent_glob, /* --> Nombre global d'entités */ const cs_int_t nbr_ent_loc, /* --> Nombre local d'entités */ const fvm_gnum_t *const num_glob_ent, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ cs_byte_t *const tab_val /* --> Tableau des valeurs */ ) { char buffer_ascii[CS_SUITE_LNG_BUF_ASCII + 1]; cs_int_t pas_bloc, ind, ind_dom, ind_bloc, ind_loc; cs_int_t ind_deb_glob_bloc, ind_fin_glob_bloc, nbr_ent_glob_bloc; cs_int_t ind_deb_loc_bloc, nbr_ent_bloc_cur; cs_int_t nbr_bloc_max; cs_int_t *nbr_ent_bloc; cs_int_t *lst_ent_loc; cs_int_t *lst_ent_glob; cs_int_t *ind_ent_bloc; cs_int_t *buffer_ent_bloc = NULL; cs_byte_t *buffer_fic = NULL, *buffer_msg = NULL; size_t ind_byte, nbr_byte_ent; MPI_Datatype mpi_typ; MPI_Status status; /* Initialisations */ buffer_ascii[0] = '\0'; switch (typ_val) { case CS_TYPE_cs_int_t: mpi_typ = CS_MPI_INT; nbr_byte_ent = nbr_val_ent * sizeof(cs_int_t); break; case CS_TYPE_cs_real_t: mpi_typ = CS_MPI_REAL; nbr_byte_ent = nbr_val_ent * sizeof(cs_real_t); break; break; default: assert(typ_val == CS_TYPE_cs_int_t || typ_val == CS_TYPE_cs_real_t); } /* Création des listes d'entités associées à la redistribution */ /*-------------------------------------------------------------*/ nbr_bloc_max = cs_loc_suite_cree_listes_ent(nbr_bloc, nbr_ent_glob, nbr_ent_loc, num_glob_ent, &pas_bloc, &nbr_ent_bloc, &lst_ent_loc, &lst_ent_glob); /* Allocation des tableaux de travail */ if (cs_glob_base_rang == 0) BFT_MALLOC(buffer_ent_bloc, nbr_bloc_max, cs_int_t); BFT_MALLOC(buffer_fic, pas_bloc * nbr_byte_ent, cs_byte_t); BFT_MALLOC(buffer_msg, nbr_bloc_max * nbr_byte_ent, cs_byte_t); /* Boucle sur les blocs */ /*----------------------*/ ind_deb_glob_bloc = 0; ind_deb_loc_bloc = 0; for (ind_bloc = 0 ; ind_bloc < nbr_bloc ; ind_bloc++) { ind_fin_glob_bloc = CS_MIN(ind_deb_glob_bloc + pas_bloc, nbr_ent_glob); /* Traitement processus "maître E/S" */ if (cs_glob_base_rang == 0) { nbr_ent_glob_bloc = ind_fin_glob_bloc - ind_deb_glob_bloc; /* Lecture sur fichier */ cs_loc_suite_lit_val(suite->type, fic, nbr_ent_glob_bloc * nbr_val_ent, typ_val, (void *)buffer_fic, buffer_ascii); for (ind_dom = 0 ; ind_dom < cs_glob_base_nbr ; ind_dom++) { /* Index des valeurs */ nbr_ent_bloc_cur = nbr_ent_bloc[ind_dom * nbr_bloc + ind_bloc]; if (ind_dom > 0) { if (nbr_ent_bloc_cur > 0) { MPI_Recv((void *)buffer_ent_bloc, nbr_ent_bloc_cur, CS_MPI_INT, ind_dom, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm, &status); ind_ent_bloc = buffer_ent_bloc; } } else /* if (ind_dom == 0) */ ind_ent_bloc = lst_ent_glob + ind_deb_loc_bloc; /* Envoi des valeurs indexées */ if (ind_dom > 0) { if (nbr_ent_bloc_cur > 0) { ind = 0; for (ind_loc = 0 ; ind_loc < nbr_ent_bloc_cur ; ind_loc++) { for (ind_byte = 0 ; ind_byte < nbr_byte_ent ; ind_byte++) buffer_msg[ind++] = buffer_fic[ind_ent_bloc[ind_loc] * nbr_byte_ent + ind_byte]; } MPI_Send((void *)buffer_msg, nbr_ent_bloc_cur * nbr_val_ent, mpi_typ, ind_dom, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm); } } else { /* if (ind_dom == 0) */ for (ind_loc = 0 ; ind_loc < nbr_ent_bloc_cur ; ind_loc++) { for (ind_byte = 0 ; ind_byte < nbr_byte_ent ; ind_byte++) tab_val[((lst_ent_loc + ind_deb_loc_bloc)[ind_loc]) * nbr_byte_ent + ind_byte] = buffer_fic[ind_ent_bloc[ind_loc] * nbr_byte_ent + ind_byte]; } } } } /* Traitement autres processus */ else if (nbr_ent_bloc[ind_bloc] > 0) { /* Index des valeurs */ ind_ent_bloc = lst_ent_glob + ind_deb_loc_bloc; MPI_Send((void *)ind_ent_bloc, nbr_ent_bloc[ind_bloc], CS_MPI_INT, 0, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm); /* Remplissage et envoi des valeurs indexées */ ind_ent_bloc = lst_ent_loc + ind_deb_loc_bloc; MPI_Recv((void *)buffer_msg, nbr_ent_bloc[ind_bloc] * nbr_val_ent, mpi_typ, 0, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm, &status); ind = 0; for (ind_loc = 0 ; ind_loc < nbr_ent_bloc[ind_bloc] ; ind_loc++) { for (ind_byte = 0 ; ind_byte < nbr_byte_ent ; ind_byte++) tab_val[ind_ent_bloc[ind_loc] * nbr_byte_ent + ind_byte] = buffer_msg[ind++]; } } ind_deb_glob_bloc = ind_fin_glob_bloc; ind_deb_loc_bloc += nbr_ent_bloc[ind_bloc]; } /* Libération des tableaux de travail */ BFT_FREE(buffer_fic); BFT_FREE(buffer_msg); if (cs_glob_base_rang == 0) BFT_FREE(buffer_ent_bloc); BFT_FREE(nbr_ent_bloc); BFT_FREE(lst_ent_loc); BFT_FREE(lst_ent_glob); } /*---------------------------------------------------------------------------- * Fonction qui écrit les valeurs associées à une variable définie sur * une entité de maillage. *----------------------------------------------------------------------------*/ static void cs_loc_suite_ecr_val_ent ( const cs_suite_t *const suite, /* --> Structure suite */ const cs_int_t nbr_bloc, /* --> Nombre de blocs */ const cs_int_t nbr_ent_glob, /* --> Nombre global d'entités */ const cs_int_t nbr_ent_loc, /* --> Nombre local d'entités */ const fvm_gnum_t *const num_glob_ent, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ const cs_byte_t *const tab_val /* --> Tableau des valeurs */ ) { cs_int_t pas_bloc, ind, ind_dom, ind_bloc, ind_loc; cs_int_t ind_deb_glob_bloc, ind_fin_glob_bloc, nbr_ent_glob_bloc; cs_int_t ind_deb_loc_bloc, nbr_ent_bloc_cur; cs_int_t nbr_bloc_max; cs_int_t *nbr_ent_bloc; cs_int_t *lst_ent_loc; cs_int_t *lst_ent_glob; cs_int_t *ind_ent_bloc; cs_int_t ind_col = 0; cs_int_t *buffer_ent_bloc = NULL; cs_byte_t *buffer_fic = NULL, *buffer_msg = NULL; size_t ind_byte, nbr_byte_ent; MPI_Datatype mpi_typ; MPI_Status status; /* Initialisations */ switch (typ_val) { case CS_TYPE_cs_int_t: mpi_typ = CS_MPI_INT; nbr_byte_ent = nbr_val_ent * sizeof(cs_int_t); break; case CS_TYPE_cs_real_t: mpi_typ = CS_MPI_REAL; nbr_byte_ent = nbr_val_ent * sizeof(cs_real_t); break; default: assert(typ_val == CS_TYPE_cs_int_t || typ_val == CS_TYPE_cs_real_t); } /* Création des listes d'entités associées à la redistribution */ /*-------------------------------------------------------------*/ nbr_bloc_max = cs_loc_suite_cree_listes_ent(nbr_bloc, nbr_ent_glob, nbr_ent_loc, num_glob_ent, &pas_bloc, &nbr_ent_bloc, &lst_ent_loc, &lst_ent_glob); /* Allocation des tableaux de travail */ if (cs_glob_base_rang == 0) BFT_MALLOC(buffer_ent_bloc, nbr_bloc_max, cs_int_t); BFT_MALLOC(buffer_fic, pas_bloc * nbr_byte_ent, cs_byte_t); BFT_MALLOC(buffer_msg, nbr_bloc_max * nbr_byte_ent, cs_byte_t); /* Boucle sur les blocs */ /*----------------------*/ ind_deb_glob_bloc = 0; ind_deb_loc_bloc = 0; for (ind_bloc = 0 ; ind_bloc < nbr_bloc ; ind_bloc++) { ind_fin_glob_bloc = CS_MIN(ind_deb_glob_bloc + pas_bloc, nbr_ent_glob); /* Traitement processus "maître E/S" */ if (cs_glob_base_rang == 0) { nbr_ent_glob_bloc = ind_fin_glob_bloc - ind_deb_glob_bloc; for (ind_dom = 0 ; ind_dom < cs_glob_base_nbr ; ind_dom++) { nbr_ent_bloc_cur = nbr_ent_bloc[ind_dom * nbr_bloc + ind_bloc]; /* Synchronisation forcée pour éviter que tous les autres rangs ne postent des envois en même temps (pouvant mener à un problème d'allocation de buffers) */ if ( cs_glob_suite_sync_gather == CS_TRUE && ind_dom > 0 && nbr_ent_bloc_cur > 0) { int _ind_dom = ind_dom; MPI_Send(&_ind_dom, 1, MPI_INT, ind_dom, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm); } /* Index des valeurs */ if (ind_dom > 0) { if (nbr_ent_bloc_cur > 0) { MPI_Recv((void *)buffer_ent_bloc, nbr_ent_bloc_cur, CS_MPI_INT, ind_dom, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm, &status); ind_ent_bloc = buffer_ent_bloc; } } else /* if (ind_dom == 0) */ ind_ent_bloc = lst_ent_glob + ind_deb_loc_bloc; /* Récupération des valeurs indexées et préparation écriture */ if (ind_dom > 0) { if (nbr_ent_bloc_cur > 0) { MPI_Recv((void *)buffer_msg, nbr_ent_bloc_cur * nbr_val_ent, mpi_typ, ind_dom, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm, &status); ind = 0; for (ind_loc = 0 ; ind_loc < nbr_ent_bloc_cur ; ind_loc++) { for (ind_byte = 0 ; ind_byte < nbr_byte_ent ; ind_byte++) buffer_fic[ind_ent_bloc[ind_loc] * nbr_byte_ent + ind_byte] = buffer_msg[ind++]; } } } else { /* if (ind_dom == 0) */ for (ind_loc = 0 ; ind_loc < nbr_ent_bloc_cur ; ind_loc++) { for (ind_byte = 0 ; ind_byte < nbr_byte_ent ; ind_byte++) buffer_fic[ind_ent_bloc[ind_loc] * nbr_byte_ent + ind_byte] = tab_val[((lst_ent_loc + ind_deb_loc_bloc)[ind_loc]) * nbr_byte_ent + ind_byte]; } } } /* Écriture sur fichier */ cs_loc_suite_ecr_val(suite, nbr_ent_glob_bloc * nbr_val_ent, typ_val, (void *)buffer_fic, &ind_col); } /* Traitement autres processus */ else if (nbr_ent_bloc[ind_bloc] > 0) { /* Remplissage des valeurs indexées */ ind_ent_bloc = lst_ent_loc + ind_deb_loc_bloc; ind = 0; for (ind_loc = 0 ; ind_loc < nbr_ent_bloc[ind_bloc] ; ind_loc++) { for (ind_byte = 0 ; ind_byte < nbr_byte_ent ; ind_byte++) buffer_msg[ind++] = tab_val[ind_ent_bloc[ind_loc] * nbr_byte_ent + ind_byte]; } /* Synchronisation forcée pour éviter que tous les autres rangs ne postent des envois en même temps (pouvant mener à un problème d'allocation de buffers) */ if (cs_glob_suite_sync_gather == CS_TRUE) { int _ind_sync; MPI_Recv(&_ind_sync, 1, MPI_INT, 0, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm, &status); } /* Index des valeurs */ ind_ent_bloc = lst_ent_glob + ind_deb_loc_bloc; MPI_Send((void *)ind_ent_bloc, nbr_ent_bloc[ind_bloc], CS_MPI_INT, 0, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm); /* Envoi des valeurs indexées */ MPI_Send((void *)buffer_msg, nbr_ent_bloc[ind_bloc] * nbr_val_ent, mpi_typ, 0, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm); } ind_deb_glob_bloc = ind_fin_glob_bloc; ind_deb_loc_bloc += nbr_ent_bloc[ind_bloc]; } /* Retour à la ligne pour fichier ASCII */ if (cs_glob_base_rang == 0) cs_loc_suite_ecr_val_fin(suite, &ind_col); /* Libération des tableaux de travail */ BFT_FREE(buffer_fic); BFT_FREE(buffer_msg); if (cs_glob_base_rang == 0) BFT_FREE(buffer_ent_bloc); BFT_FREE(nbr_ent_bloc); BFT_FREE(lst_ent_loc); BFT_FREE(lst_ent_glob); } /*---------------------------------------------------------------------------- * Fonction qui distribue une liste de variables *----------------------------------------------------------------------------*/ static void cs_loc_suite_distr_val ( const cs_int_t nbr_val, /* --> Nb. valeurs */ const cs_type_t typ_val, /* --> Type de valeurs */ void *const val /* <-> Valeurs à lire */ ) { cs_int_t ind_dom; MPI_Datatype mpi_typ; MPI_Status status; /* Initialisations */ switch (typ_val) { case CS_TYPE_cs_int_t: mpi_typ = CS_MPI_INT; break; case CS_TYPE_cs_real_t: mpi_typ = CS_MPI_REAL; break; default: assert(typ_val == CS_TYPE_cs_int_t || typ_val == CS_TYPE_cs_real_t); } if (cs_glob_base_rang == 0) { for (ind_dom = 1 ; ind_dom < cs_glob_base_nbr ; ind_dom++) MPI_Send((void *)val, nbr_val, mpi_typ, ind_dom, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm); } else if (cs_glob_base_rang > 0) { MPI_Recv((void *)val, nbr_val, mpi_typ, 0, CS_SUITE_MPI_TAG, cs_glob_base_mpi_comm, &status); } } #endif /* #if defined(_CS_HAVE_MPI) */ /*---------------------------------------------------------------------------- * Fonction qui analyse le contenu d'un fichier suite en mode texte * On démare en haut de deuxième ligne, ayant lu l'en-tête, et on * indique en retour si la suite continue sur un autre fichier *----------------------------------------------------------------------------*/ static cs_bool_t cs_loc_suite_analyse_txt ( cs_suite_t *const suite /* --> Structure suite */ ) { char buffer [CS_SUITE_LNG_BUF_ASCII + 1]; char sub [CS_SUITE_LNG_BUF_ASCII + 1]; char str_typ[CS_SUITE_LNG_BUF_ASCII + 1]; char *str; cs_int_t ind, ind_rec, ind_rub, ind_fin, lng, etape; cs_int_t nbr_cel, nbr_fac, nbr_fbr, nbr_som; int nbr_ent, nbr_val_ent; cs_int_t num_ligne = 1; cs_int_t ind_fic = suite->nbr_fic - 1; cs_bool_t err_fmt = CS_FALSE; cs_bool_t fin_fic = CS_FALSE; /* Initialisations */ for (ind = CS_SUITE_SUPPORT_CEL ; ind <= CS_SUITE_SUPPORT_SOM ; ind++) { str = bft_file_gets_try(buffer, CS_SUITE_LNG_BUF_ASCII, suite->fic[ind_fic], &num_ligne); if (str != NULL) { /* Décodage en-tête globale */ if (sscanf(buffer, "[%s = %d]", sub, &nbr_ent) == 2) { if (strncmp("nbr_cel", sub, strlen("nbr_cel")) == 0) nbr_cel = nbr_ent; else if (strncmp ("nbr_fac_int", sub, strlen("nbr_fac_int")) == 0) nbr_fac = nbr_ent; else if (strncmp("nbr_fac_brd", sub, strlen("nbr_fac_brd")) == 0) nbr_fbr = nbr_ent; else if (strncmp("nbr_som", sub, strlen("nbr_som")) == 0) nbr_som = nbr_ent; else { err_fmt = CS_TRUE; break; } } else { err_fmt = CS_TRUE; break; } } else { /* if (str != NULL) */ err_fmt = CS_TRUE; /* break; */ } } if (err_fmt == CS_TRUE) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le fichier suite <%s> numéro <%d> n'est pas conforme\n"), suite->nom, suite->nbr_fic); return CS_FALSE; } /* Dimensions du support */ if (ind_fic == 0) { suite->nbr_cel = nbr_cel; suite->nbr_fac = nbr_fac; suite->nbr_fbr = nbr_fbr; suite->nbr_som = nbr_som; } else if (ind_fic > 0 && ( nbr_cel != suite->nbr_cel || nbr_fac != suite->nbr_fac || nbr_fbr != suite->nbr_fbr || nbr_som != suite->nbr_som)) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Les dimensions du support associé au fichier suite <%s>\n" "numéro <%d> ne correspondent pas au fichier numéro <1>\n"), suite->nom, suite->nbr_fic); return CS_FALSE; } /* Tableaux et champs contenus dans le fichier */ while (fin_fic == CS_FALSE) { str = bft_file_gets_try(buffer, CS_SUITE_LNG_BUF_ASCII, suite->fic[ind_fic], &num_ligne); if (str == NULL) { fin_fic = CS_TRUE; break; } /* Traitement d'une rubrique */ else if (buffer[0] == '[') { lng = strlen(buffer); while ( buffer[lng - 1] == '\n' || buffer[lng - 1] == '\r' || buffer[lng - 1] == '\t' || buffer[lng - 1] == ' ') { buffer[lng - 1] = '\0'; lng --; } strcpy (sub, buffer + 1); /* Indicateur de fin de fichier */ if (strncmp(sub, cs_suite_nom_fin_fic, strlen(cs_suite_nom_fin_fic)) == 0) return CS_FALSE; /* Indicateur de découpage de fichier */ else if (strncmp(sub, cs_suite_nom_decoup_fic, strlen(cs_suite_nom_decoup_fic)) == 0) return CS_TRUE; /* Numéro de partie de fichier (en cas de découpage) */ else if (strncmp(sub, cs_suite_nom_partie_fic, strlen(cs_suite_nom_partie_fic)) == 0) { int num_part; ind = strlen(cs_suite_nom_partie_fic); for (ind_fin = lng - 1 ; ind_fin >= ind && sub[ind_fin] != ']' ; ind_fin--); sub[ind_fin] = '\0'; if ( sscanf(sub + ind, "%d", &num_part) !=1 || num_part != suite->nbr_fic) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le fichier suite <%s_p%02d> ne correspond pas\n" "à la partie <%d> du fichier suite d'origine\n"), suite->nom, (int)suite->nbr_fic, (int)suite->nbr_fic); return CS_FALSE; } continue; } /* Traitement d'un enregistrement standard */ if (suite->nbr_rec == suite->nbr_rec_max) { suite->nbr_rec_max *= 2; BFT_REALLOC(suite->tab_rec, suite->nbr_rec_max, cs_suite_rec_t); } ind_rec = suite->nbr_rec; BFT_MALLOC((suite->tab_rec[ind_rec]).nom, strlen(sub) + 1, char); strcpy((suite->tab_rec[ind_rec]).nom, sub); str = bft_file_gets_try(buffer, CS_SUITE_LNG_BUF_ASCII, suite->fic[ind_fic], &num_ligne); if (str == NULL) { fin_fic = CS_TRUE; break; } /* Décodage de la deuxième ligne d'entête (avec vérification de la syntaxe) ; on part de la fin, qui doit être caractérisée par le caractère ']', et on progresse vers le début */ ind_fin = strlen(buffer); for (ind = ind_fin - 1 ; ind > 0 && buffer[ind] != ']' ; ind--); buffer[ind] = '\0'; ind_fin = ind - 1; for (etape = 0 ; etape < 3 ;etape++) { if (ind_fin > 0 && err_fmt == CS_FALSE) { for ( ; ind > 0 && buffer[ind] != '=' ; ind--); for (ind_rub = ind ; ind_rub > 0 && buffer[ind_rub] != ',' ; ind_rub--); ind++; for ( ; ind < ind_fin && buffer[ind] == ' ' ; ind++); switch(etape) { case 0: if (strncmp(", typ_val = ", buffer+ind_rub, strlen(", typ_val = ")) == 0) strcpy(str_typ, buffer+ind); else err_fmt = CS_TRUE; break; case 1: if (strncmp(", nbr_val_ent = ", buffer+ind_rub, strlen(", nbr_val_ent = ")) == 0) { if (sscanf(buffer+ind, "%d", &nbr_val_ent) != 1) err_fmt = CS_TRUE; } else err_fmt = CS_TRUE; break; case 2: if (strncmp(" support = ", buffer+ind_rub, strlen(" support = ")) == 0) strcpy(sub, buffer+ind); else err_fmt = CS_TRUE; break; } ind = ind_rub; buffer[ind_rub] = '\0'; ind_fin = ind_rub - 1; } else err_fmt = CS_TRUE; } /* Remplissage de la structure */ for (ind = CS_SUITE_SUPPORT_SCAL ; ind <= CS_SUITE_SUPPORT_SOM ; ind++) { if (strcmp(sub, cs_suite_nom_support[ind]) == 0) { (suite->tab_rec[ind_rec]).ind_support = (cs_suite_support_t)ind; break; } } if (ind > CS_SUITE_SUPPORT_SOM) err_fmt = CS_TRUE; (suite->tab_rec[ind_rec]).nbr_val_ent = (cs_int_t) nbr_val_ent; for (ind = 0 ; ind < 3 ; ind++) { if (strcmp(str_typ, cs_suite_nom_typ_elt[ind]) == 0) { (suite->tab_rec[ind_rec]).typ_val = (cs_type_t)ind; break; } } if (ind == 3) err_fmt = CS_TRUE; /* Position dans le fichier */ (suite->tab_rec[ind_rec]).ind_fic = ind_fic; (suite->tab_rec[ind_rec]).pos_fic = bft_file_tell(suite->fic[ind_fic]); /* Libération du nom si erreur de format */ if ( (fin_fic == CS_TRUE || err_fmt == CS_TRUE) && (suite->tab_rec[ind_rec]).nom != NULL) BFT_FREE((suite->tab_rec[ind_rec]).nom); else { /* Incrémentation compteur */ suite->nbr_rec += 1; /* Passage rapide à la suite */ bft_file_seek (suite->fic[ind_fic], ( (suite->tab_rec[ind_rec]).pos_fic + cs_loc_suite_calc_avance (suite, (cs_suite_support_t)((suite->tab_rec[ind_rec]).ind_support), (suite->tab_rec[ind_rec]).nbr_val_ent, (suite->tab_rec[ind_rec]).typ_val)), BFT_FILE_SEEK_SET); } } } return CS_FALSE; } /*---------------------------------------------------------------------------- * Fonction qui analyse le contenu d'un fichier suite en mode binaire * On démarre à la position suivant l'en-tête, et on indique en retour * si la suite continue sur un autre fichier *----------------------------------------------------------------------------*/ static cs_bool_t cs_loc_suite_analyse_bin ( cs_suite_t *const suite /* --> Structure suite */ ) { char buf_nom[CS_SUITE_LNG_NOM + 1]; char *nom = buf_nom; cs_int_t lng_nom_max = CS_SUITE_LNG_NOM; cs_int_t buf[4], nbr_lus, ind_rec; cs_int_t ind_fic = suite->nbr_fic - 1; cs_bool_t fic_suiv = CS_FALSE; cs_bool_t fin_fic = CS_FALSE; /* Initialisations */ nbr_lus = bft_file_read_try(buf, sizeof(cs_int_t), 4, suite->fic[ind_fic]); if (nbr_lus == 4) { /* Dimensions du support */ if (ind_fic == 0) { suite->nbr_cel = buf[0]; suite->nbr_fac = buf[1]; suite->nbr_fbr = buf[2]; suite->nbr_som = buf[3]; } else if (ind_fic > 0 && ( buf[0] != suite->nbr_cel || buf[1] != suite->nbr_fac || buf[2] != suite->nbr_fbr || buf[3] != suite->nbr_som)) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Les dimensions du support associé au fichier suite <%s>\n" "numéro <%d> ne correspondent pas au fichier numéro <1>\n"), suite->nom, suite->nbr_fic); return CS_FALSE; } } else { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le fichier suite <%s> numéro <%d> n'est pas conforme\n"), suite->nom, suite->nbr_fic); return CS_FALSE; } /* Tableaux et champs contenus dans le fichier */ while (fin_fic == CS_FALSE) { nbr_lus = bft_file_read_try(buf, sizeof(cs_int_t), 4, suite->fic[ind_fic]); if (nbr_lus < 4) { fin_fic = CS_TRUE; break; } if (buf[0] > lng_nom_max) { lng_nom_max = buf[0]; if (nom == buf_nom) BFT_MALLOC(nom, lng_nom_max, char); else BFT_REALLOC(nom, lng_nom_max, char); } bft_file_read(nom, 1, buf[0], suite->fic[ind_fic]); /* Traitement d'une rubrique */ /* Indicateur de fin de fichier */ if (strncmp(nom, cs_suite_nom_fin_fic, strlen(cs_suite_nom_fin_fic)) == 0) { fin_fic = CS_TRUE; break; } /* Indicateur de découpage de fichier */ else if (strncmp(nom, cs_suite_nom_decoup_fic, strlen(cs_suite_nom_decoup_fic)) == 0) { fin_fic = CS_TRUE; fic_suiv = CS_TRUE; break; } /* Numéro de partie de fichier (en cas de découpage) */ else if (strncmp(nom, cs_suite_nom_partie_fic, strlen(cs_suite_nom_partie_fic)) == 0) { if (buf[1] != suite->nbr_fic) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le fichier suite <%s_p%02d> ne correspond pas\n" "à la partie <%d> du fichier suite d'origine\n"), suite->nom, (int)suite->nbr_fic, (int)suite->nbr_fic); fin_fic = CS_TRUE; break; } continue; } /* Traitement d'un enregistrement standard */ if (suite->nbr_rec == suite->nbr_rec_max) { suite->nbr_rec_max *= 2; BFT_REALLOC(suite->tab_rec, suite->nbr_rec_max, cs_suite_rec_t); } ind_rec = suite->nbr_rec; BFT_MALLOC((suite->tab_rec[ind_rec]).nom, strlen(nom) + 1, char); strcpy((suite->tab_rec[ind_rec]).nom, nom); (suite->tab_rec[ind_rec]).ind_support = buf[1]; (suite->tab_rec[ind_rec]).nbr_val_ent = buf[2]; (suite->tab_rec[ind_rec]).typ_val = (cs_type_t)buf[3]; /* Position dans le fichier */ (suite->tab_rec[ind_rec]).ind_fic = ind_fic; (suite->tab_rec[ind_rec]).pos_fic = bft_file_tell(suite->fic[ind_fic]); /* Incrémentation compteur */ suite->nbr_rec += 1; /* Passage rapide à la suite */ bft_file_seek (suite->fic[ind_fic], ( (suite->tab_rec[ind_rec]).pos_fic + cs_loc_suite_calc_avance (suite, (cs_suite_support_t)((suite->tab_rec[ind_rec]).ind_support), (suite->tab_rec[ind_rec]).nbr_val_ent, (suite->tab_rec[ind_rec]).typ_val)), BFT_FILE_SEEK_SET); } if (nom != buf_nom) BFT_FREE(nom); return fic_suiv; } /*---------------------------------------------------------------------------- * Fonction qui prépare l'index généré lors de l'analyse du fichier à * l'utilisation par les fonctions de lecture d'enregistrements *----------------------------------------------------------------------------*/ static void cs_loc_suite_prepare_index ( cs_suite_t *const suite /* --> Structure suite */ ) { cs_int_t ind_rec; /* Traitement pour le parallélisme */ #if defined(_CS_HAVE_MPI) if (cs_glob_base_rang >= 0) { cs_int_t buf[5]; cs_int_t lng_nom; cs_int_t *pos_nom = NULL, *buf_idx = NULL; char *buf_nom = NULL; /* Distribution dimensions et index */ buf[0] = suite->nbr_cel; buf[1] = suite->nbr_fac; buf[2] = suite->nbr_fbr; buf[3] = suite->nbr_som; buf[4] = suite->nbr_rec; MPI_Bcast((void *)buf, 5, CS_MPI_INT, 0, cs_glob_base_mpi_comm); if (cs_glob_base_rang > 0) { suite->nbr_cel = buf[0]; suite->nbr_fac = buf[1]; suite->nbr_fbr = buf[2]; suite->nbr_som = buf[3]; suite->nbr_rec = buf[4]; suite->nbr_rec_max = suite->nbr_rec; BFT_MALLOC(suite->tab_rec, suite->nbr_rec, cs_suite_rec_t); } /* Noms des enregistrements */ BFT_MALLOC(pos_nom, suite->nbr_rec + 1, cs_int_t); if (cs_glob_base_rang == 0) { pos_nom[0] = 0; for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) pos_nom[ind_rec + 1] = pos_nom[ind_rec] + strlen((suite->tab_rec[ind_rec]).nom); } MPI_Bcast((void *)pos_nom, suite->nbr_rec + 1, CS_MPI_INT, 0, cs_glob_base_mpi_comm); BFT_MALLOC(buf_nom, pos_nom[suite->nbr_rec], char); if (cs_glob_base_rang == 0) { for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) { lng_nom = pos_nom[ind_rec + 1] - pos_nom[ind_rec]; strncpy(buf_nom + pos_nom[ind_rec], (suite->tab_rec[ind_rec]).nom, lng_nom); } } MPI_Bcast((void *)buf_nom, pos_nom[suite->nbr_rec], MPI_CHAR, 0, cs_glob_base_mpi_comm); if (cs_glob_base_rang > 0) { for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) { lng_nom = pos_nom[ind_rec + 1] - pos_nom[ind_rec]; BFT_MALLOC ((suite->tab_rec[ind_rec]).nom, lng_nom + 1, char); strncpy((suite->tab_rec[ind_rec]).nom, buf_nom + pos_nom[ind_rec], lng_nom); (suite->tab_rec[ind_rec]).nom[lng_nom] = '\0'; } } BFT_FREE(buf_nom); BFT_FREE(pos_nom); /* Autres parties de l'index */ BFT_MALLOC(buf_idx, suite->nbr_rec * 3, cs_int_t); if (cs_glob_base_rang == 0) { for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) { buf_idx[ind_rec * 3] = (suite->tab_rec[ind_rec]).ind_support; buf_idx[ind_rec * 3 + 1] = (suite->tab_rec[ind_rec]).nbr_val_ent; buf_idx[ind_rec * 3 + 2] = (cs_int_t)(suite->tab_rec[ind_rec]).typ_val; } } MPI_Bcast((void *)buf_idx, suite->nbr_rec * 3, CS_MPI_INT, 0, cs_glob_base_mpi_comm); if (cs_glob_base_rang > 0) { for (ind_rec = 0 ; ind_rec < suite->nbr_rec ; ind_rec++) { (suite->tab_rec[ind_rec]).ind_support = buf_idx[ind_rec * 3]; (suite->tab_rec[ind_rec]).nbr_val_ent = buf_idx[ind_rec * 3 + 1]; (suite->tab_rec[ind_rec]).typ_val = (cs_type_t)(buf_idx[ind_rec * 3 + 2]); (suite->tab_rec[ind_rec]).ind_fic = -1; (suite->tab_rec[ind_rec]).pos_fic = -1; } } BFT_FREE(buf_idx); } #endif /* defined(_CS_HAVE_MPI) */ } /*---------------------------------------------------------------------------- * Conversion d'arguments de lecture/écriture de l'API Fortran vers l'API C *----------------------------------------------------------------------------*/ static void cs_loc_suite_rub_f77_vers_C ( const cs_int_t *const numsui, /* --> Numéro du fichier suite */ const cs_int_t *const itysup, /* --> Code type de support */ const cs_int_t *const irtype, /* --> Entiers ou réels ? */ cs_suite_t **const suite, /* <-- Pointeur structure suite */ cs_suite_support_t *const support, /* <-- Type de support */ cs_type_t *const typ_val, /* <-- Entiers ou réels */ cs_int_t *const ierror /* <-- 0 = succès, < 0 = erreur */ ) { cs_int_t indsui = *numsui - 1; *ierror = CS_SUITE_SUCCES; /* Pointeur de structure suite associé */ if ( indsui < 0 || indsui > cs_glob_suite_ptr_nbr || cs_glob_suite_ptr_tab[indsui] == NULL) { cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le fichier suite numéro <%d> ne peut être fermé\n" "(fichier déjà fermé ou numéro invalide)"), (int)(*numsui)); *ierror = CS_SUITE_ERR_NUM_FIC; return; } else *suite = cs_glob_suite_ptr_tab[indsui]; /* Support associé à la rubrique */ switch (*itysup) { case 0: *support = CS_SUITE_SUPPORT_SCAL; break; case 1: *support = CS_SUITE_SUPPORT_CEL; break; case 2: *support = CS_SUITE_SUPPORT_FAC_INT; break; case 3: *support = CS_SUITE_SUPPORT_FAC_BRD; break; case 4: *support = CS_SUITE_SUPPORT_SOM; break; default: cs_base_warn(__FILE__, __LINE__); bft_printf(_("Le type de support <%d> indiqué pour une rubrique de\n" "fichier suite est invalide"), (int)(*itysup)); *ierror = CS_SUITE_ERR_SUPPORT; return; } /* Type associé à la rubrique */ switch (*irtype) { case 1: *typ_val = CS_TYPE_cs_int_t; break; case 2: *typ_val = CS_TYPE_cs_real_t; break; default: bft_error(__FILE__, __LINE__, 0, _("Le type de valeur <%d> indiqué pour une rubrique de\n" "fichier suite est invalide"), (int)(*irtype)); *ierror = CS_SUITE_ERR_TYPE_VAL; return; } } /*---------------------------------------------------------------------------- * Permutation des valeurs d'un tableau renuméroté en lecture *----------------------------------------------------------------------------*/ static void cs_loc_suite_permute_lec ( const cs_int_t nbr_ent, /* --> Nombre d'entités */ const cs_int_t *const num_ent_ini, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ cs_byte_t *const tab_val /* --> Tableau des valeurs */ ) { cs_int_t ind_ent, ind_loc; cs_int_t ind = 0; /* Instructions */ if (num_ent_ini == NULL) return; switch (typ_val) { case CS_TYPE_cs_int_t: { cs_int_t *val_ord; cs_int_t *val_cur = (cs_int_t *)tab_val; BFT_MALLOC(val_ord, nbr_ent * nbr_val_ent, cs_int_t); for (ind_ent = 0 ; ind_ent < nbr_ent ; ind_ent++) { for (ind_loc = 0 ; ind_loc < nbr_val_ent ; ind_loc++) val_ord[ind++] = val_cur[(num_ent_ini[ind_ent] - 1) * nbr_val_ent + ind_loc]; } for (ind = 0 ; ind < nbr_ent * nbr_val_ent ; ind++) val_cur[ind] = val_ord[ind]; BFT_FREE(val_ord); } break; case CS_TYPE_cs_real_t: { cs_real_t *val_ord; cs_real_t *val_cur = (cs_real_t *)tab_val; BFT_MALLOC (val_ord, nbr_ent * nbr_val_ent, cs_real_t); for (ind_ent = 0 ; ind_ent < nbr_ent ; ind_ent++) { for (ind_loc = 0 ; ind_loc < nbr_val_ent ; ind_loc++) val_ord[ind++] = val_cur[(num_ent_ini[ind_ent] - 1) * nbr_val_ent + ind_loc]; } for (ind = 0 ; ind < nbr_ent * nbr_val_ent ; ind++) val_cur[ind] = val_ord[ind]; BFT_FREE(val_ord); } break; default: assert(typ_val == CS_TYPE_cs_int_t || typ_val == CS_TYPE_cs_real_t); } } /*---------------------------------------------------------------------------- * Permutation des valeurs d'un tableau renuméroté en écriture *----------------------------------------------------------------------------*/ static cs_byte_t * cs_loc_suite_permute_ecr ( const cs_int_t nbr_ent, /* --> Nombre d'entités */ const cs_int_t *const num_ent_ini, /* --> Numéros globaux des entités */ const cs_int_t nbr_val_ent, /* --> Nombre de valeurs/entité */ const cs_type_t typ_val, /* --> Type de valeur */ const cs_byte_t *const tab_val /* --> Tableau des valeurs */ ) { cs_int_t ind_ent, ind_loc; cs_int_t ind = 0; /* Instructions */ if (num_ent_ini == NULL) return NULL; switch (typ_val) { case CS_TYPE_cs_int_t: { cs_int_t *val_ord; const cs_int_t *val_cur = (const cs_int_t *)tab_val; BFT_MALLOC(val_ord, nbr_ent * nbr_val_ent, cs_int_t); for (ind_ent = 0 ; ind_ent < nbr_ent ; ind_ent++) { for (ind_loc = 0 ; ind_loc < nbr_val_ent ; ind_loc++) val_ord[(num_ent_ini[ind_ent] - 1) * nbr_val_ent + ind_loc] = val_cur[ind++]; } return (cs_byte_t *)val_ord; } break; case CS_TYPE_cs_real_t: { cs_real_t *val_ord; const cs_real_t *val_cur = (const cs_real_t *)tab_val; BFT_MALLOC(val_ord, nbr_ent * nbr_val_ent, cs_real_t); for (ind_ent = 0 ; ind_ent < nbr_ent ; ind_ent++) { for (ind_loc = 0 ; ind_loc < nbr_val_ent ; ind_loc++) val_ord[(num_ent_ini[ind_ent] - 1) * nbr_val_ent + ind_loc] = val_cur[ind++]; } return (cs_byte_t *)val_ord; } break; default: assert(typ_val == CS_TYPE_cs_int_t || typ_val == CS_TYPE_cs_real_t); return NULL; } } #ifdef __cplusplus } #endif /* __cplusplus */