/*============================================================================
*
* 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 <assert.h>
#include <stdio.h>
#include <string.h>
#if defined(_CS_HAVE_MPI)
#include <mpi.h>
#endif
/*----------------------------------------------------------------------------
* Fichiers `include' librairie BFT
*----------------------------------------------------------------------------*/
#include <bft_file.h>
#include <bft_mem.h>
#include <bft_error.h>
#include <bft_printf.h>
/*----------------------------------------------------------------------------
* 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 */
syntax highlighted by Code2HTML, v. 0.9.1