/*============================================================================ * * 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 * *============================================================================*/ /*============================================================================ * Structure principale associée à un maillage *============================================================================*/ /* includes système */ #include #include #include #include #include /*---------------------------------------------------------------------------- * Fichiers `include' librairie standard C, BFT, ou FVM *----------------------------------------------------------------------------*/ #include #include #include #include #include /*---------------------------------------------------------------------------- * Fichiers `include' locaux *----------------------------------------------------------------------------*/ #include "cs_base.h" #include "cs_perio.h" /*---------------------------------------------------------------------------- * Fichiers `include' associés au fichier courant *----------------------------------------------------------------------------*/ #include "cs_maillage.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /*============================================================================ * Variables globales statiques *============================================================================*/ /* Pointeur sur le maillage principal */ cs_maillage_t *cs_glob_maillage = NULL; #if defined(_CS_HAVE_MPI) /* Pointeur sur la structure de tampons associée au maillage principal */ cs_maillage_tmp_t *cs_glob_maillage_tmp = NULL; #endif /*============================================================================ * Prototypes de fonctions privées *============================================================================*/ /*---------------------------------------------------------------------------- * Recherche des coordonnées minimales et maximales *----------------------------------------------------------------------------*/ static void _cs_maillage_extents ( const cs_maillage_t *maillage ); #if defined(_CS_HAVE_MPI) /*---------------------------------------------------------------------------- * Mise à jour d'un tableau des familles de cellules en cas de parallélisme * * Le rôle de cette fonction consiste à recopier les valeurs sur les * cellules principales en frontière parallèle d'autres domaines * (indices entre 1 et ncel) vers les cellules halo du domaine en * cours (indices ncel+1 à ncelet) *----------------------------------------------------------------------------*/ static void _cs_maillage_sync_fam_cel ( cs_maillage_t *const maillage, /* <-> Structure maillage associée */ cs_maillage_tmp_t *const maillage_tmp /* <-> Structure tampon maillage */ ); #endif /* _CS_HAVE_MPI */ /*============================================================================ * Fonctions publiques pour API Fortran *============================================================================*/ /*---------------------------------------------------------------------------- * Recherche du numéro de groupe correspondant à un nom donné. Si le groupe * existe, le numéro renvoyé correspond au rang du groupe (commençant à 1) * dans la liste des groupes du maillage, et multiplié par -1. Cette * numérotation est celle utilisée dans le tableau IPRFML(NFML, NPRFML) * de description des familles. * * Si le groupe de nom indiqué n'existe pas, on renvoie 9999. * * Interface Fortran : * * FUNCTION NUMGRP (NOMGRP, LNGNOM) * *************** * * CHARACTER* NOMGRP : --> : Nom du groupe recherché * INTEGER LNGNOM : --> : Longueur du nom du groupe *----------------------------------------------------------------------------*/ cs_int_t CS_PROCF (numgrp, NUMGRP) ( const char *const nomgrp, /* --> Nom du groupe */ const cs_int_t *const lngnom /* --> Longueur du nom */ CS_ARGF_SUPP_CHAINE /* (arguments 'longueur' éventuels F77, */ /* inutilisés lors de l'appel mais */ /* placés par de nombreux compilateurs) */ ) { int ind, lngcmp ; char *nomcmp ; cs_maillage_t *maillage = cs_glob_maillage; for (ind = 0 ; ind < maillage->nbr_grp ; ind++) { nomcmp = maillage->nom_grp + (maillage->pos_grp[ind] - 1) ; lngcmp = strlen(nomcmp) ; if (lngcmp == *lngnom && strncmp(nomcmp, nomgrp, lngcmp) == 0) return (-(ind + 1)) ; } return -9999 ; } /*---------------------------------------------------------------------------- * Sauvegarde des numérotations initiales des faces * * Remarque : lorsque des faces sont renumérotées, les connectivités et * variables basées sur les faces sont toutes mises à jour, sauf * les numéros globaux associés à ces faces (en cas de parallélisme) * et conservés dans la structure maillage ('num_fac'et num_fbr') ; * en effet, cette numérotation est destinée à se ramener à la * numérotation initiale, notamment pour l'écriture et la lecture de * fichiers suite indépendants du nombre de domaines en parallélisme * ou d'une renumérotation vectorielle, et il est plus aisé de la * manipuler si elle n'est pas modifiée. * * Interface Fortran : * * SUBROUTINE SAVNUM (IVECTV, IVECTB, INUMFI, INUMFB) * ***************** * * INTEGER IVECTV : --> : Indicateur renum. faces internes * INTEGER IVECTB : --> : Indicateur renum. faces de bord * INTEGER INUMFI : --> : Table de renum. des faces internes * INTEGER INUMFB : --> : Table de renum. des faces de bord *----------------------------------------------------------------------------*/ void CS_PROCF (savnum, SAVNUM) ( const cs_int_t *const ivectv, /* --> Indicateur renum. faces internes */ const cs_int_t *const ivectb, /* --> Indicateur renum. faces de bord */ const cs_int_t *const inumfi, /* --> Table de renum. des faces internes */ const cs_int_t *const inumfb /* --> Table de renum. des faces de bord */ ) { cs_int_t ind; cs_maillage_t *maillage = cs_glob_maillage; /* Sauvegarde correspondance des faces internes -> faces internes initiales */ if (*ivectv != 0) { BFT_MALLOC (maillage->num_fac_ini, maillage->nbr_fac, cs_int_t); for (ind = 0 ; ind < maillage->nbr_fac ; ind++) maillage->num_fac_ini[ind] = inumfi[ind]; } /* Sauvegarde correspondance des faces de bord -> faces de bord initiales */ if (*ivectb != 0) { BFT_MALLOC (maillage->num_fbr_ini, maillage->nbr_fbr, cs_int_t); for (ind = 0 ; ind < maillage->nbr_fbr ; ind++) maillage->num_fbr_ini[ind] = inumfb[ind]; } } /*============================================================================ * Fonctions publiques *============================================================================*/ /*---------------------------------------------------------------------------- * Création d'une structure maillage *----------------------------------------------------------------------------*/ cs_maillage_t * cs_maillage_cree ( void ) { cs_maillage_t * maillage; BFT_MALLOC (maillage, 1, cs_maillage_t); maillage->dim = 3; maillage->num_dom = cs_glob_base_rang + 1; maillage->nbr_dom = 0; maillage->nbr_per = 0; maillage->ind_type_voiset = CS_MAILLAGE_TYPE_VOISET_SANS ; maillage->nbr_cel = 0; maillage->nbr_fac = 0; maillage->nbr_fbr = 0; maillage->nbr_som = 0; maillage->lng_fac_som = 0; maillage->lng_fbr_som = 0; maillage->nbr_cel_fac_par = 0; maillage->nbr_dom_fac_par = 0; maillage->nbr_cel_etendu = 0; maillage->nbr_cel_fac_par_voiset = 0; maillage->nbr_dom_fac_par_voiset = 0; maillage->nbr_val_connect_voiset_cel_cel_dom = 0; maillage->nbr_cel_glob = 0; maillage->nbr_fac_glob = 0; maillage->nbr_fbr_glob = 0; maillage->nbr_som_glob = 0; maillage->coo_som = NULL; maillage->fac_cel = NULL; maillage->fbr_cel = NULL; maillage->pos_fac_som = NULL; maillage->pos_fbr_som = NULL; maillage->val_fac_som = NULL; maillage->val_fbr_som = NULL; maillage->num_cel = NULL; maillage->num_fac = NULL; maillage->num_fbr = NULL; maillage->num_som = NULL; maillage->pos_dom_fac_par = NULL; maillage->pos_per_fac_par = NULL; maillage->num_cel_fac_par = NULL; maillage->num_dom_fac_par = NULL; maillage->liste_param_per = NULL; maillage->pos_dom_fac_par_voiset = NULL; maillage->pos_per_fac_par_voiset = NULL; maillage->num_cel_fac_par_voiset = NULL; maillage->num_dom_fac_par_voiset = NULL; maillage->coord_cel_avec_voiset = NULL; maillage->pos_connect_voiset_cel_cel_dom = NULL; maillage->val_connect_voiset_cel_cel_dom = NULL; maillage->num_fac_ini = NULL; maillage->num_fbr_ini = NULL; maillage->nbr_grp = 0; maillage->pos_grp = NULL; maillage->nom_grp = NULL; maillage->nbr_prop_fam_max = 0; maillage->nbr_fam = 0; maillage->prop_fam = NULL; maillage->fam_cel = NULL; maillage->fam_fbr = NULL; return (maillage); } /*---------------------------------------------------------------------------- * Destruction d'une structure maillage *----------------------------------------------------------------------------*/ cs_maillage_t * cs_maillage_detruit ( cs_maillage_t * maillage ) { BFT_FREE(maillage->coo_som); BFT_FREE(maillage->fac_cel); BFT_FREE(maillage->fbr_cel); BFT_FREE(maillage->pos_fac_som); BFT_FREE(maillage->pos_fbr_som); BFT_FREE(maillage->val_fac_som); BFT_FREE(maillage->val_fbr_som); BFT_FREE (maillage->num_cel); BFT_FREE (maillage->num_fac); BFT_FREE (maillage->num_fbr); BFT_FREE (maillage->num_som); BFT_FREE (maillage->num_cel_fac_par); BFT_FREE (maillage->pos_dom_fac_par); BFT_FREE (maillage->pos_per_fac_par); BFT_FREE (maillage->num_dom_fac_par); BFT_FREE (maillage->liste_param_per); BFT_FREE (maillage->num_cel_fac_par_voiset); BFT_FREE (maillage->pos_dom_fac_par_voiset); BFT_FREE (maillage->pos_per_fac_par_voiset); BFT_FREE (maillage->num_dom_fac_par_voiset); BFT_FREE (maillage->coord_cel_avec_voiset); BFT_FREE (maillage->pos_connect_voiset_cel_cel_dom); BFT_FREE (maillage->val_connect_voiset_cel_cel_dom); BFT_FREE (maillage->num_fac_ini); BFT_FREE (maillage->num_fbr_ini); BFT_FREE(maillage->pos_grp); BFT_FREE(maillage->nom_grp); BFT_FREE(maillage->prop_fam); BFT_FREE(maillage->fam_cel); BFT_FREE(maillage->fam_fbr); BFT_FREE (maillage); return (maillage); } /*---------------------------------------------------------------------------- * Renumérotation des sommets de manière à assurer que : * si i < j, maillage->num_som[i] < maillage->num_som[j] * (ce qui n'est pas assuré par la numérotation initialement * fournie par l'Enveloppe). *----------------------------------------------------------------------------*/ void cs_maillage_ordonne_sommets ( cs_maillage_t *const maillage /* <-> Structure maillage associée */ ) { /* Variables locales */ cs_int_t ind, ind_dim; cs_int_t taille; cs_int_t dim = 3; cs_int_t nbr_som = 0; cs_int_t *num_tmp = NULL; cs_real_t *coord_tmp = NULL; fvm_lnum_t *ordre_som = NULL; fvm_lnum_t *renum_som = NULL; fvm_gnum_t *num_g_som = NULL; assert(maillage != NULL); /* Aucun traitement en mode séquentiel */ if (maillage->num_som == NULL) return; dim = maillage->dim; nbr_som = maillage->nbr_som; /* Calcul de la renumérotation des sommets */ BFT_MALLOC(num_g_som, nbr_som, fvm_gnum_t); for (ind = 0 ; ind < nbr_som ; ind++) num_g_som[ind] = maillage->num_som[ind]; ordre_som = fvm_order_local(NULL, num_g_som, (size_t)nbr_som); BFT_FREE(num_g_som); renum_som = fvm_order_local_renumbering(ordre_som, (size_t)nbr_som); BFT_FREE(ordre_som); /* Application de la renumérotation des sommets à la connectivité faces -> sommets */ if (maillage->nbr_fac > 0) { for (ind = 0, taille = maillage->pos_fac_som[maillage->nbr_fac] - 1 ; ind < taille ; ind++) maillage->val_fac_som[ind] = renum_som[maillage->val_fac_som[ind] - 1] + 1; } if (maillage->nbr_fbr > 0) { for (ind = 0, taille = maillage->pos_fbr_som[maillage->nbr_fbr] - 1 ; ind < taille ; ind++) maillage->val_fbr_som[ind] = renum_som[maillage->val_fbr_som[ind] - 1] + 1; } /* Mise à jour des coordonnées */ BFT_MALLOC(coord_tmp, nbr_som * dim, cs_real_t); for (ind = 0 ; ind < nbr_som ; ind++) { for (ind_dim = 0 ; ind_dim < dim ; ind_dim++) { coord_tmp[renum_som[ind]*dim + ind_dim] = maillage->coo_som[ind*dim + ind_dim]; } } memcpy(maillage->coo_som, coord_tmp, (nbr_som * dim * sizeof(cs_real_t))); BFT_FREE(coord_tmp); /* Mise à jour de la numérotation globale */ BFT_MALLOC(num_tmp, nbr_som, cs_int_t); for (ind = 0 ; ind < nbr_som ; ind++) { num_tmp[renum_som[ind]] = maillage->num_som[ind]; } memcpy(maillage->num_som, num_tmp, (nbr_som * sizeof(cs_int_t))); BFT_FREE(num_tmp); /* Libération mémoire */ BFT_FREE(renum_som); } /*---------------------------------------------------------------------------- * Affichage d'informations relatives à un maillage *----------------------------------------------------------------------------*/ void cs_maillage_info ( const cs_maillage_t *maillage ) { _cs_maillage_extents(maillage); } #if defined(_CS_HAVE_MPI) /*---------------------------------------------------------------------------- * Création d'une structure de tampons associée à un maillage *----------------------------------------------------------------------------*/ cs_maillage_tmp_t * cs_maillage_tmp_cree ( cs_maillage_t * maillage ) { cs_int_t nbr_val_var_assembl ; cs_int_t nbr_val_var_assembl_voiset ; cs_int_t ind_dom ; cs_int_t ind_dom_fac_par ; cs_int_t icpt ; cs_int_t *nbr_cel_attendu; cs_int_t *nbr_cel_a_envoyer; cs_maillage_tmp_t * maillage_tmp = NULL; if (cs_glob_base_nbr <= 1) return NULL; BFT_MALLOC (maillage_tmp, 1, cs_maillage_tmp_t); /* Requetes et status surdimensionnés, mais pas grave */ BFT_MALLOC (maillage_tmp->mpi_request, maillage->nbr_dom * 2, MPI_Request); BFT_MALLOC (maillage_tmp->mpi_status, maillage->nbr_dom * 2, MPI_Status); /* ATTENTION Les halos entrant et sortant n'ont pas forcément la meme taille : pour un voisinage étendu basé sur les sommets (dans le halo standard ou séparé), il est nécessaire de prévoir des tableaux distincts pour les données entrantes et sortantes du processeur courant. La modification pourrait être limitée à ce cas, mais elle conduirait en pratique à dupliquer les fonctions de communication, ce qui rendrait les tests moins faciles. La principale difficulté consiste à dimensionner les tableaux relatifs aux données sortantes (pour les données entrantes, les informations sont lues dans le fichier de communication avec l'enveloppe). On alloue ci-dessous : pos_dom_var_assembl num_dom_var_assembl var_assembl num_cel_loc_par On calcule nbr_dom_var_assembl pos_dom_var_assembl num_dom_var_assembl On procède de même pour le voisinage étendu, s'il est traité séparément. En outre, on réserve une variable maillage_tmp->var_cel_avec_voiset qui permettra de stocker une variable ncelet+voinage étendu séparé */ BFT_MALLOC(nbr_cel_attendu, maillage->nbr_dom, cs_int_t); BFT_MALLOC(nbr_cel_a_envoyer, maillage->nbr_dom, cs_int_t); /* Pour allouer var_assembl, on calcule sa taille en demandant aux processeurs voisins la quantité de données qu'ils attendent du processeur courant. */ for (ind_dom = 0 ; ind_dom < maillage->nbr_dom ; ind_dom++) nbr_cel_attendu[ind_dom] = 0 ; for (ind_dom_fac_par = 0 ; ind_dom_fac_par < maillage->nbr_dom_fac_par ; ind_dom_fac_par++) { ind_dom = maillage->num_dom_fac_par[ind_dom_fac_par] - 1; nbr_cel_attendu[ind_dom] = maillage->pos_dom_fac_par[ind_dom_fac_par + 1] - maillage->pos_dom_fac_par[ind_dom_fac_par]; } /* Envoi au processeur j de nbr_cel_attendu[j], et réception en nbr_cel_a_envoyer[i] la valeur correspondante fournie par le processeur i */ MPI_Alltoall(nbr_cel_attendu, 1, CS_MPI_INT, nbr_cel_a_envoyer, 1, CS_MPI_INT, cs_glob_base_mpi_comm); /* MPI_Alltoall(nbr_cel_attendu, maillage->nbr_dom, CS_MPI_INT, nbr_cel_a_envoyer, maillage->nbr_dom, CS_MPI_INT, cs_glob_base_mpi_comm); */ /* Calcul du nombre de domaines auxquels on envoie effectivement des voisins */ for (ind_dom = 0, icpt = 0 ; ind_dom < maillage->nbr_dom ; ind_dom++) { if (nbr_cel_a_envoyer[ind_dom] > 0) icpt++; } maillage_tmp->nbr_dom_var_assembl = icpt; /* Tableau des numéro des voisins auquel le processeur courant envoie des informations. */ BFT_MALLOC (maillage_tmp->num_dom_var_assembl, maillage_tmp->nbr_dom_var_assembl, cs_int_t); /* Tableau de position des cases de var_assembl associées à un voisin donné auquel le processeur courant envoie des informations. */ BFT_MALLOC (maillage_tmp->pos_dom_var_assembl, maillage_tmp->nbr_dom_var_assembl + 1, cs_int_t); /* Construction de num_dom_var_assembl et de pos_dom_var_assembl */ maillage_tmp->pos_dom_var_assembl[0] = 1; for (ind_dom = 0, icpt = 0 ; ind_dom < maillage->nbr_dom ; ind_dom++) { if (nbr_cel_a_envoyer[ind_dom] > 0) { maillage_tmp->num_dom_var_assembl[icpt] = ind_dom + 1; maillage_tmp->pos_dom_var_assembl[icpt+1] = maillage_tmp->pos_dom_var_assembl[icpt] + nbr_cel_a_envoyer[ind_dom]; icpt++; } } assert(icpt == maillage_tmp->nbr_dom_var_assembl); /* Allocation du halo sortant (variable d'assemblage et tableau destiné à contenir le numéro local des cellules à y verser) */ nbr_val_var_assembl = maillage_tmp->pos_dom_var_assembl[maillage_tmp->nbr_dom_var_assembl] - 1; BFT_MALLOC (maillage_tmp->var_assembl, nbr_val_var_assembl, cs_real_t); BFT_MALLOC (maillage_tmp->num_cel_loc_par, nbr_val_var_assembl, cs_int_t); /* Même chose pour le voisinage étendu s'il est traité séparément du halo classique */ if(maillage->ind_type_voiset == CS_MAILLAGE_TYPE_VOISET_SEPARE) { /* Pour allouer var_assembl_voiset, on calcule sa taille en demandant aux processeurs voisins la quantité de données qu'ils attendent du processeur courant. */ for (ind_dom = 0 ; ind_dom < maillage->nbr_dom ; ind_dom++) nbr_cel_attendu[ind_dom] = 0 ; for (ind_dom_fac_par = 0 ; ind_dom_fac_par < maillage->nbr_dom_fac_par_voiset ; ind_dom_fac_par++) { ind_dom = maillage->num_dom_fac_par_voiset[ind_dom_fac_par] - 1; nbr_cel_attendu[ind_dom] = maillage->pos_dom_fac_par_voiset[ind_dom_fac_par + 1] - maillage->pos_dom_fac_par_voiset[ind_dom_fac_par]; } /* Envoi au processeur j de nbr_cel_attendu[j], et réception en nbr_cel_a_envoyer[i] la valeur correspondante fournie par le processeur i */ MPI_Alltoall(nbr_cel_attendu, 1, CS_MPI_INT, nbr_cel_a_envoyer, 1, CS_MPI_INT, cs_glob_base_mpi_comm); /* Calcul du nombre de domaines auxquels on envoie effectivement des voisins */ for (ind_dom = 0, icpt = 0 ; ind_dom < maillage->nbr_dom ; ind_dom++) { if (nbr_cel_a_envoyer[ind_dom] > 0) icpt++; } maillage_tmp->nbr_dom_var_assembl_voiset = icpt ; /* Tableau des numéro des voisins étendus auquel le processeur courant envoie des informations. */ BFT_MALLOC (maillage_tmp->num_dom_var_assembl_voiset, maillage_tmp->nbr_dom_var_assembl_voiset, cs_int_t); /* Tableau de position des cases de var_assembl_voiset associées à un voisin donné auquel le processeur courant envoie des informations. */ BFT_MALLOC (maillage_tmp->pos_dom_var_assembl_voiset, maillage_tmp->nbr_dom_var_assembl_voiset + 1, cs_int_t); /* Construction de num_dom_var_assembl_voiset et de pos_dom_var_assembl_voiset */ maillage_tmp->pos_dom_var_assembl_voiset[0] = 1; for (ind_dom = 0, icpt = 0 ; ind_dom < maillage->nbr_dom ; ind_dom++) { if (nbr_cel_a_envoyer[ind_dom] > 0) { maillage_tmp->num_dom_var_assembl_voiset[icpt] = ind_dom + 1; maillage_tmp->pos_dom_var_assembl_voiset[icpt+1] = maillage_tmp->pos_dom_var_assembl_voiset[icpt] + nbr_cel_a_envoyer[ind_dom]; icpt++; } } assert(icpt == maillage_tmp->nbr_dom_var_assembl_voiset); /* Allocation du halo sortant (variable d'assemblage et tableau destiné à contenir le numéro local des cellules à y verser) */ nbr_val_var_assembl_voiset = maillage_tmp->pos_dom_var_assembl_voiset [maillage_tmp->nbr_dom_var_assembl_voiset] - 1; BFT_MALLOC (maillage_tmp->var_assembl_voiset, nbr_val_var_assembl_voiset, cs_real_t); BFT_MALLOC (maillage_tmp->num_cel_loc_par_voiset, nbr_val_var_assembl_voiset, cs_int_t); /* Allocation d'une variable allongée pour le halo entrant (voisinage étendu séparé) */ if(maillage->nbr_cel_fac_par_voiset > 0) BFT_MALLOC (maillage_tmp->var_cel_avec_voiset, maillage->nbr_cel + maillage->nbr_cel_fac_par + maillage->nbr_cel_fac_par_voiset, cs_real_t); else maillage_tmp->var_cel_avec_voiset = NULL ; } /* Si voisinage étendu n'est pas traité séparément du halo classique (ou s'il n'existe pas) : tout nul */ else { maillage_tmp->nbr_dom_var_assembl_voiset = 0 ; maillage_tmp->pos_dom_var_assembl_voiset = NULL ; maillage_tmp->num_dom_var_assembl_voiset = NULL ; maillage_tmp->num_cel_loc_par_voiset = NULL ; maillage_tmp->var_assembl_voiset = NULL ; maillage_tmp->var_cel_avec_voiset = NULL ; } BFT_FREE (nbr_cel_attendu); BFT_FREE (nbr_cel_a_envoyer); return (maillage_tmp); } /*---------------------------------------------------------------------------- * Destruction d'une structure de tampons associée à un maillage *----------------------------------------------------------------------------*/ cs_maillage_tmp_t * cs_maillage_tmp_detruit ( cs_maillage_tmp_t * maillage_tmp ) { if (maillage_tmp == NULL) return NULL; /* Libération posant problème avec lam-mpi */ BFT_FREE (maillage_tmp->mpi_request); BFT_FREE (maillage_tmp->mpi_status); BFT_FREE (maillage_tmp->num_cel_loc_par); BFT_FREE (maillage_tmp->pos_dom_var_assembl); BFT_FREE (maillage_tmp->num_dom_var_assembl); BFT_FREE (maillage_tmp->var_assembl); BFT_FREE (maillage_tmp->num_cel_loc_par_voiset); BFT_FREE (maillage_tmp->pos_dom_var_assembl_voiset); BFT_FREE (maillage_tmp->num_dom_var_assembl_voiset); BFT_FREE (maillage_tmp->var_assembl_voiset); BFT_FREE (maillage_tmp->var_cel_avec_voiset); BFT_FREE (maillage_tmp); return (maillage_tmp); } /*---------------------------------------------------------------------------- * Tableaux supplémentaires d'un maillage pour le parallélisme *----------------------------------------------------------------------------*/ void cs_maillage_init_parallel ( cs_maillage_t *maillage, cs_maillage_tmp_t *maillage_tmp ) { cs_int_t lbloc, ind, ind_dom; cs_int_t *buf; fvm_gnum_t nbr_ent_glob[4], num_ent_max[4]; int cpt_request ; if (cs_glob_base_nbr <= 1) return; /* Dimensions globales du maillage */ num_ent_max[0] = maillage->nbr_cel; MPI_Allreduce (num_ent_max, nbr_ent_glob, 1, FVM_MPI_GNUM, MPI_SUM, cs_glob_base_mpi_comm); num_ent_max[1] = 0; for (ind = 0 ; ind < maillage->nbr_fac ; ind++) { if (maillage->num_fac[ind] > num_ent_max[1]) num_ent_max[1] = maillage->num_fac[ind]; } num_ent_max[2] = 0; for (ind = 0 ; ind < maillage->nbr_fbr ; ind++) { if (maillage->num_fbr[ind] > num_ent_max[2]) num_ent_max[2] = maillage->num_fbr[ind]; } num_ent_max[3] = 0; for (ind = 0 ; ind < maillage->nbr_som ; ind++) { if (maillage->num_som[ind] > num_ent_max[3]) num_ent_max[3] = maillage->num_som[ind]; } MPI_Allreduce (num_ent_max + 1, nbr_ent_glob + 1, 3, FVM_MPI_GNUM, MPI_MAX, cs_glob_base_mpi_comm); maillage->nbr_cel_glob = nbr_ent_glob[0]; maillage->nbr_fac_glob = nbr_ent_glob[1]; maillage->nbr_fbr_glob = nbr_ent_glob[2]; maillage->nbr_som_glob = nbr_ent_glob[3]; /* On souhaite disposer du numéro local des cellules à envoyer aux voisins */ /* Émission et réception de messages des autres domaines (avec des communications non bloquantes) */ cpt_request = 0 ; /* On envoie aux voisins le numéro (dans leur numérotation locale) des cellules que l'on souhaite recevoir de leur part */ for (ind_dom = 0 ; ind_dom < maillage->nbr_dom_fac_par ; ind_dom++) { lbloc = maillage->pos_dom_fac_par[ind_dom + 1] - maillage->pos_dom_fac_par[ind_dom] ; buf = maillage->num_cel_fac_par + maillage->pos_dom_fac_par[ind_dom] - 1; MPI_Isend (buf, lbloc, CS_MPI_INT, maillage->num_dom_fac_par[ind_dom] - 1, maillage->num_dom - 1, cs_glob_base_mpi_comm, &(maillage_tmp->mpi_request[cpt_request++])); } /* On recoit des voisins le numéro (dans la numérotation locale courante) des cellules qu'il faudra leur envoyer, dans l'ordre */ for (ind_dom = 0 ; ind_dom < maillage_tmp->nbr_dom_var_assembl ; ind_dom++) { lbloc = maillage_tmp->pos_dom_var_assembl[ind_dom + 1] - maillage_tmp->pos_dom_var_assembl[ind_dom] ; buf = maillage_tmp->num_cel_loc_par + maillage_tmp->pos_dom_var_assembl[ind_dom] - 1; MPI_Irecv (buf, lbloc, CS_MPI_INT, maillage_tmp->num_dom_var_assembl[ind_dom] - 1, maillage_tmp->num_dom_var_assembl[ind_dom] - 1, cs_glob_base_mpi_comm, &(maillage_tmp->mpi_request[cpt_request++])); } MPI_Waitall (cpt_request, maillage_tmp->mpi_request, maillage_tmp->mpi_status); /* Synchronisation du tableau des familles des cellules */ _cs_maillage_sync_fam_cel (maillage, maillage_tmp) ; /* Pour le voisinage étendu, s'il est traité séparément : de même. */ if(maillage->ind_type_voiset == CS_MAILLAGE_TYPE_VOISET_SEPARE) { /* Émission et réception de messages des autres domaines pour disposer du numéro local des cellules à envoyer (avec des communications non bloquantes) */ cpt_request = 0 ; /* On envoie aux voisins le numéro (dans leur numérotation locale) des cellules que l'on souhaite recevoir de leur part */ for (ind_dom = 0 ; ind_dom < maillage->nbr_dom_fac_par_voiset ; ind_dom++) { lbloc = maillage->pos_dom_fac_par_voiset[ind_dom + 1] - maillage->pos_dom_fac_par_voiset[ind_dom] ; buf = maillage->num_cel_fac_par_voiset + maillage->pos_dom_fac_par_voiset[ind_dom] - 1; MPI_Isend (buf, lbloc, CS_MPI_INT, maillage->num_dom_fac_par_voiset[ind_dom] - 1, maillage->num_dom - 1, cs_glob_base_mpi_comm, &(maillage_tmp->mpi_request[cpt_request++])); } /* On recoit des voisins le numéro (dans la numérotation locale courante) des cellules qu'il faudra leur envoyer, dans l'ordre */ for (ind_dom = 0 ; ind_dom < maillage_tmp->nbr_dom_var_assembl_voiset ; ind_dom++) { lbloc = maillage_tmp->pos_dom_var_assembl_voiset[ind_dom + 1] - maillage_tmp->pos_dom_var_assembl_voiset[ind_dom] ; buf = maillage_tmp->num_cel_loc_par_voiset + maillage_tmp->pos_dom_var_assembl_voiset[ind_dom] - 1; MPI_Irecv (buf, lbloc, CS_MPI_INT, maillage_tmp->num_dom_var_assembl_voiset[ind_dom] - 1, maillage_tmp->num_dom_var_assembl_voiset[ind_dom] - 1, cs_glob_base_mpi_comm, &(maillage_tmp->mpi_request[cpt_request++])); } MPI_Waitall (cpt_request, maillage_tmp->mpi_request, maillage_tmp->mpi_status); } } #endif /* _CS_HAVE_MPI */ /*============================================================================ * Fonctions privées *============================================================================*/ /*---------------------------------------------------------------------------- * Recherche des coordonnées minimales et maximales *----------------------------------------------------------------------------*/ static void _cs_maillage_extents ( const cs_maillage_t *maillage ) { cs_int_t isom, iloc; cs_int_t dim = maillage->dim; /* Allocation des structures s'il ne s'agit pas d'une mise à jour */ if (maillage->nbr_som_glob > 0) { cs_real_t xyz_min[3] = { 1.e127, 1.e127, 1.e127}; cs_real_t xyz_max[3] = {-1.e127, -1.e127, -1.e127}; for (isom = 0 ; isom < maillage->nbr_som ; isom++) { for (iloc = 0 ; iloc < dim ; iloc++) { if (maillage->coo_som[isom*dim + iloc] < xyz_min[iloc]) xyz_min[iloc] = maillage->coo_som[isom*dim + iloc]; if (maillage->coo_som[isom*dim + iloc] > xyz_max[iloc]) xyz_max[iloc] = maillage->coo_som[isom*dim + iloc]; } } #if defined(_CS_HAVE_MPI) if (cs_glob_base_nbr > 1) { cs_real_t xyz_min_g[3]; cs_real_t xyz_max_g[3]; MPI_Allreduce (xyz_min, xyz_min_g, dim, CS_MPI_REAL, MPI_MIN, cs_glob_base_mpi_comm); MPI_Allreduce (xyz_max, xyz_max_g, dim, CS_MPI_REAL, MPI_MAX, cs_glob_base_mpi_comm); for (iloc = 0 ; iloc < dim ; iloc++) { xyz_min[iloc] = xyz_min_g[iloc]; xyz_max[iloc] = xyz_max_g[iloc]; } } #endif /* _CS_HAVE_MPI */ bft_printf(_("\n" " ** COORDONNEES DU MAILLAGE MINIMALE ET MAXIMALE\n" " X : %14.7e %14.7e\n" " Y : %14.7e %14.7e\n" " Z : %14.7e %14.7e\n"), xyz_min[0], xyz_max[0], xyz_min[1], xyz_max[1], xyz_min[2], xyz_max[2]); } } #if defined(_CS_HAVE_MPI) /*---------------------------------------------------------------------------- * Mise à jour d'un tableau des familles de cellules en cas de parallélisme * * Le rôle de cette fonction consiste à recopier les valeurs sur les * cellules principales en frontière parallèle d'autres domaines * (indices entre 1 et ncel) vers les cellules halo du domaine en * cours (indices ncel+1 à ncelet) *----------------------------------------------------------------------------*/ static void _cs_maillage_sync_fam_cel ( cs_maillage_t *const maillage, /* <-> Structure maillage associée */ cs_maillage_tmp_t *const maillage_tmp /* <-> Structure tampon maillage */ ) { /* Variables locales */ cs_int_t dbloc, lbloc; cs_int_t ind, ind_dom; cs_int_t *tab_assembl = NULL; cs_int_t *buf = NULL; int cpt_request = 0; /* Aucun traitement en mode séquentiel */ if (cs_glob_base_nbr < 2) return; /* On utilise ici le tampon var_assembl de maillage_tmp (normalement prévu pour contenir des réels) pour des entiers */ assert(sizeof(cs_int_t) <= sizeof(cs_real_t)); tab_assembl = (cs_int_t *)maillage_tmp->var_assembl; /* Émission vers les autres domaines (communications non bloquantes) */ /*-------------------------------------------------------------------*/ for (ind_dom = 0 ; ind_dom < maillage_tmp->nbr_dom_var_assembl ; ind_dom++) { /* Test sur le numéro de maillage utile en périodicité */ if (maillage_tmp->num_dom_var_assembl[ind_dom] != maillage->num_dom) { /* On envoie aux voisins, dans une variable d'assemblage */ dbloc = maillage_tmp->pos_dom_var_assembl[ind_dom] - 1; lbloc = maillage_tmp->pos_dom_var_assembl[ind_dom + 1] - maillage_tmp->pos_dom_var_assembl[ind_dom] ; for (ind = 0 ; ind < lbloc ; ind++) tab_assembl[dbloc + ind] = maillage->fam_cel[maillage_tmp->num_cel_loc_par[dbloc + ind] - 1]; buf = tab_assembl + dbloc ; MPI_Isend (buf, lbloc, CS_MPI_INT, maillage_tmp->num_dom_var_assembl[ind_dom] - 1, maillage->num_dom - 1, cs_glob_base_mpi_comm, &(maillage_tmp->mpi_request[cpt_request++])); } } /* Émission depuis les autres domaines (communications non bloquantes) */ /*---------------------------------------------------------------------*/ for (ind_dom = 0 ; ind_dom < maillage->nbr_dom_fac_par ; ind_dom++) { /* Test sur le numéro de maillage utile en périodicité */ /* On le laisse par cohérence avec parcom, mais on pourrait s'en affranchir, car en périodicité, on ne fera rien de plus */ if (maillage->num_dom_fac_par[ind_dom] != maillage->num_dom) { /* On réceptionne des voisins directement dans le halo */ dbloc = maillage->pos_dom_fac_par[ind_dom] - 1; lbloc = maillage->pos_dom_fac_par[ind_dom + 1] - maillage->pos_dom_fac_par[ind_dom] ; buf = maillage->fam_cel + maillage->nbr_cel + dbloc ; MPI_Irecv (buf, lbloc, CS_MPI_INT, maillage->num_dom_fac_par[ind_dom] - 1, maillage->num_dom_fac_par[ind_dom] - 1, cs_glob_base_mpi_comm, &(maillage_tmp->mpi_request[cpt_request++])); } } /* On synchronise après que tout le monde ait recu tous les messages */ MPI_Waitall (cpt_request, maillage_tmp->mpi_request, maillage_tmp->mpi_status); } #endif #ifdef __cplusplus } #endif /* __cplusplus */