/*============================================================================
*
*                    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
*
*============================================================================*/

/*============================================================================
 * Interfaces Fortran pour la parallélisation du code
 *============================================================================*/

/* includes système */


/* Includes BFT et FVM */

#include <fvm_interface.h>


/* Includes librairie */

#include "cs_base.h"


#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */


/*============================================================================
 * Prototypes de fonctions publiques
 *============================================================================*/

/*----------------------------------------------------------------------------
 * Initialisations après lecture du maillage en cas de parallélisme
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARGEO
 * *****************
 *
 * INTEGER          NCELGB      : <-  : Nombre de cellules global
 * INTEGER          NFACGB      : <-  : Nombre de faces internes global
 * INTEGER          NFBRGB      : <-  : Nombre de faces internes global
 * INTEGER          NSOMGB      : <-  : Nombre de sommets global
 *----------------------------------------------------------------------------*/

void CS_PROCF (pargeo, PARGEO)
(
 cs_int_t  *ncelgb,             /* <-  Nombre de cellules global */
 cs_int_t  *nfacgb,             /* <-  Nombre de faces internes global */
 cs_int_t  *nfbrgb,             /* <-  Nombre de faces internes global */
 cs_int_t  *nsomgb              /* <-  Nombre de sommets global */
);


/*----------------------------------------------------------------------------
 * Mise à jour du voisinage étendu des coordonnées du centre des cellules
 *   dans le voisinage étendu s'il est traité séparément du reste du halo
 *
 * 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 et a les placer dans la structure maillage
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARGVE (NDIM, XYZCEN)
 * *****************
 *
 * INTEGER          NDIM             : --> : dimension de l'espace
 * DOUBLE PRECISION XYZCEN(3,NCELET) : --> : coordonnées du centre des cellules
 *----------------------------------------------------------------------------*/

void CS_PROCF (pargve, PARGVE)
(
 const cs_int_t  * const ndim      ,/* --> dimension de l'espace              */
 const cs_real_t * const xyzcen     /* --> coordonnées du centre des cellules */
);


/*----------------------------------------------------------------------------
 * Mise à jour d'un tableau sur les 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)
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARCOM (VAR)
 * *****************
 *
 * DOUBLE PRECISION VAR(NCELET) : <-> : variable sur les cellules, mise à
 *                                      jour de VAR(NCEL+1..NCELET) en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parcom, PARCOM)
(
 cs_real_t  var[]               /* <-> variable définie sur les cellules
                                 *     (mise à jour sur les cellules halo) */
);


/*----------------------------------------------------------------------------
 * Mise à jour du voisinage étendu d'une variable au centre des cellules
 *   dans le voisinage étendu s'il est traité séparément du reste du halo
 *
 * Fonction calquée sur PARCOM
 *
 * 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 et a les placer dans la structure maillage
 *
 *----------------------------------------------------------------------------*/

void cs_parallel_parcve
(
 const cs_real_t * const var       ,/* --> variable au centre des cellules */
       cs_real_t *       var_voiset /* --> variable au centre des cellules
                                           dans le voisinage étendu        */
);


/*----------------------------------------------------------------------------
 * Interface FORTRAN pour les echanges sur le voisinage étendu lorsqu'il est
 *   traité séparément du halo classique. Le tableau traité est supposé
 *   correctement dimensionné (ncelet + nombre de cellules halo étendu).
 *
 * Appelée en parallèle uniquement.
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARCVE
 * *****************
 *
 *    & ( PVAR )
 *
 *----------------------------------------------------------------------------*/

void CS_PROCF (parcve, PARCVE)
(
       cs_real_t         pvar[]       /* <-> tab. echangé                     */
 CS_ARGF_SUPP_CHAINE                  /*     (arguments 'longueur' éventuels,
                                             Fortran, inutilisés lors de
                                             l'appel mais placés par de
                                             nombreux compilateurs)           */
);


/*----------------------------------------------------------------------------
 * Maximum d'un compteur entier sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à mettre l'indicateur ind à la valeur
 * maximale obtenue sur les différents domaines de calcul
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARCMX (IND)
 * *****************
 *
 * INTEGER          IND         : <-> : indicateur local en entrée,
 *                                      maximum en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parcmx, PARCMX)
(
 cs_int_t  *ind                 /* <-> indicateur */
);


/*----------------------------------------------------------------------------
 * Somme d'un compteur entier sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à ajouter au compteur cpt les
 * valeurs correspondantes sur les autre domaines de calcul
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARCPT (CPT)
 * *****************
 *
 * INTEGER          CPT         : <-> : compteur à sommer en entrée,
 *                                      somme en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parcpt, PARCPT)
(
 cs_int_t  *cpt                 /* <-> compteur à sommer */
);


/*----------------------------------------------------------------------------
 * Somme d'un réel sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à ajouter au réel var les
 * valeurs correspondantes sur les autre domaines de calcul
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARSOM (VAR)
 * *****************
 *
 * DOUBLE PRECISION VAR         : <-> : valeur à sommer en entrée,
 *                                      somme en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parsom, PARSOM)
(
 cs_real_t  *var                /* <-> variable à sommer */
);


/*----------------------------------------------------------------------------
 * Maximum d'un réel sur plusieurs domaines en cas de parallélisme
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARMAX (VAR)
 * *****************
 *
 * DOUBLE PRECISION VAR         : <-> : maximum local en entrée,
 *                                      maximum global en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parmax, PARMAX)
(
 cs_real_t  *var
);


/*----------------------------------------------------------------------------
 * Minimum d'un réel sur plusieurs domaines en cas de parallélisme
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARMIN (VAR)
 * *****************
 *
 * DOUBLE PRECISION VAR         : <-> : minimum local en entrée,
 *                                      minimum global en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parmin, PARMIN)
(
 cs_real_t  *var
);


/*----------------------------------------------------------------------------
 * Maximum d'un réel et valeurs associées sur plusieurs domaines
 * en cas de parallélisme
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARMXL (NBR, VAR, XYZVAR)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs associees
 * DOUBLE PRECISION VAR         : <-> : maximum local en entrée,
 *                                      maximum global en sortie
 * DOUBLE PRECISION XYZVAR(NBR) : <-> : val. associees au max loc.   en entrée,
 *                                      val. associees au max. glob. en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parmxl, PARMXL)
(
 cs_int_t   *nbr,
 cs_real_t  *var,
 cs_real_t   xyzvar[]
);


/*----------------------------------------------------------------------------
 * Minimum d'un réel et valeurs associées sur plusieurs domaines
 * en cas de parallélisme
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARMNL (NBR, VAR, XYZVAR)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs associees
 * DOUBLE PRECISION VAR         : <-> : minimum local en entrée,
 *                                      minimum global en sortie
 * DOUBLE PRECISION XYZVAR(NBR) : <-> : valeurs associées min local en entrée,
 *                                      valeurs associées min global en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parmnl, PARMNL)
(
 cs_int_t   *nbr,
 cs_real_t  *var,
 cs_real_t   xyzvar[]
);


/*----------------------------------------------------------------------------
 * Somme d'un tableau entier sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à mettre le tableau itab a la valeur
 * somme des valeurs correspondantes sur les autre domaines de calcul
 * (terme par terme)
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARISM (NBR,ITAB)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * INTEGER          ITAB(*)     : <-> : tableau local en entrée,
 *                                      somme en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parism, PARISM)
(
 cs_int_t  *nbr,                 /* <-> dimension */
 cs_int_t   itab[]
);


/*----------------------------------------------------------------------------
 * Maximum d'un tableau entier sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à mettre le tableau ind à la valeur
 * maximale obtenue sur les différents domaines de calcul
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARIMX (NBR,ITAB)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * INTEGER          ITAB(*)     : <-> : tableau local en entrée,
 *                                      maximum en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parimx, PARIMX)
(
 cs_int_t  *nbr,                 /* <-> dimension */
 cs_int_t   itab[]
);


/*----------------------------------------------------------------------------
 * Minimum d'un tableau entier sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à mettre le tableau itab à la valeur
 * minimale obtenue sur les différents domaines de calcul
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARIMN (NBR,ITAB)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * INTEGER          ITAB(*)     : <-> : tableau local en entrée,
 *                                      minimum en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parimn, PARIMN)
(
 cs_int_t  *nbr,                 /* <-> dimension */
 cs_int_t   itab[]
);


  /*----------------------------------------------------------------------------
 * Somme d'un tableau reel sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à mettre le tableau rtab a la valeur
 * somme des valeurs correspondantes sur les autre domaines de calcul
 * (terme par terme)
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARRSM (NBR,RTAB)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * DOUBLE PRECISION RTAB(*)     : <-> : tableau local en entrée,
 *                                      somme en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parrsm, PARRSM)
(
 cs_int_t  *nbr,                 /* <-> dimension */
 cs_real_t   rtab[]
);


/*----------------------------------------------------------------------------
 * Maximum d'un tableau reel   sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à mettre le tableau rtab à la valeur
 * maximale obtenue sur les différents domaines de calcul
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARRMX (NBR,RTAB)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * DOUBLE PRECISION RTAB(*)     : <-> : tableau local en entrée,
 *                                      maximum en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parrmx, PARRMX)
(
 cs_int_t  *nbr,                 /* <-> dimension */
 cs_real_t   rtab[]
);


/*----------------------------------------------------------------------------
 * Minimum d'un tableau reel   sur plusieurs domaines en cas de parallélisme
 *
 * Le rôle de cette fonction consiste à mettre le tableau rtab à la valeur
 * minimale obtenue sur les différents domaines de calcul
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARRMN (NBR,RTAB)
 * *****************
 *
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * INTEGER          RTAB(*)     : <-> : tableau local en entrée,
 *                                      minimum en sortie
 *----------------------------------------------------------------------------*/

void CS_PROCF (parrmn, PARRMN)
(
 cs_int_t  *nbr,                 /* <-> dimension */
 cs_real_t   rtab[]
);


/*----------------------------------------------------------------------------
 * Envoi de valeurs entières d'un processus à ses voisins
 * (encapsulation de MPI_Bcast())
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARBCI (IRANGV, NBR, ITAB)
 * *****************
 *
 * INTEGER          IRANGV      :  -> : rang du processus associé aux valeurs
 *                                      à envoyer
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * DOUBLE PRECISION ITAB(*)     : <-> : valeurs entières
 *----------------------------------------------------------------------------*/

void CS_PROCF (parbci, PARBCI)
(
 cs_int_t   *irangv,
 cs_int_t   *nbr,
 cs_int_t    itab[]
);


/*----------------------------------------------------------------------------
 * Envoi de valeurs réelles d'un processus à ses voisins
 * (encapsulation de MPI_Bcast())
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARBCR (IRANGV, NBR, RTAB)
 * *****************
 *
 * INTEGER          IRANGV      :  -> : rang du processus associé aux valeurs
 *                                      à envoyer
 * INTEGER          NBR         :  -> : nombre de valeurs à envoyer/recevoir
 * DOUBLE PRECISION RTAB(*)     : <-> : valeurs réelles
 *----------------------------------------------------------------------------*/

void CS_PROCF (parbcr, PARBCR)
(
 cs_int_t   *irangv,
 cs_int_t   *nbr,
 cs_real_t   rtab[]
);

/*----------------------------------------------------------------------------
 * Méthode "AllGather" pour récupérer les données sur tous les processeurs
 * dans le cas où le nombre de variables locales est différent suivant
 * les domaines
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARAGV (NVAR, NVARGB, VAR, VARGB)
 * *****************
 *
 * INTEGER          NVAR        :  -> : nombre de variables locales
 * INTEGER          NVARGB      :  -> : nombre de variables globales
 * DOUBLE PRECISION VAR(*)      :  -> : variables locales
 * DOUBLE PRECISION VARGB(*)    : <-  : variables globales
 *----------------------------------------------------------------------------*/

void CS_PROCF (paragv, PARAGV)
(
 cs_int_t   *nvar,
 cs_int_t   *nvargb,
 cs_real_t   var[],
 cs_real_t  *vargb
);


/*----------------------------------------------------------------------------
 * Recherche du point minimisant une distance donnée et du rang associé au
 * processus contenant ce point (pour localiser un point parmi plusieurs
 * domaines)
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARFPT (NODE, NDRANG, DIS2MN, XYZSND)
 * *****************
 *
 * INTEGER          NODE        : <-> : numéro local du point le plus proche
 *                                      du point recherché
 * INTEGER          NDRANG      : <-  : rang du processus pour lequel la
 *                                      distance est la plus faible
 * DOUBLE PRECISION DIS2MN      :  -> : distance au carré du point en entrée
 *                                      au point recherché
 *----------------------------------------------------------------------------*/

void CS_PROCF (parfpt, PARFPT)
(
 cs_int_t   *node,
 cs_int_t   *ndrang,
 cs_real_t  *dis2mn
);


/*----------------------------------------------------------------------------
 * Renvoi d'une valeur associée à une sonde
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARHIS (NODE, NDRANG, VAR, VARCAP)
 * *****************
 *
 * INTEGER          NODE        :  -> : numéro local de l'élément associé
 *                                      à la sonde
 * INTEGER          NDRANG      :  -> : rang du processus associé à la sonde
 *                                      distance est la plus faible
 * DOUBLE PRECISION VAR(*)      :  -> : variable discrétisée
 * DOUBLE PRECISION VARCAP      : <-  : valeur de la variable au point associé
 *                                      à la sonde
 *----------------------------------------------------------------------------*/

void CS_PROCF (parhis, PARHIS)
(
 cs_int_t   *node,
 cs_int_t   *ndrang,
 cs_real_t   var[],
 cs_real_t  *varcap
);


/*----------------------------------------------------------------------------
 * Numéro de cellule global associé à un numéro de cellule local
 *   (envoi a tous les processeurs)
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARCEL (NUMLOC,INDDOM,NUMGLO)
 * *****************
 *
 * INTEGER          NUMLOC      :  -> : numéro de cellule local
 * INTEGER          INDDOM      :  -> : rang du domaine associé (0 à N-1)
 * INTEGER          NUMGLO      :  -> : numéro de cellule global
 *----------------------------------------------------------------------------*/

void CS_PROCF (parcel, PARCEL)
(
 cs_int_t   *numloc,
 cs_int_t   *inddom,
 cs_int_t   *numglo
);


/*----------------------------------------------------------------------------
 * Numéro de cellule global associé à un numéro de cellule local
 *   du processeur courant, sans communication avec les autres
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARCLG (NUMLOC,INDDOM,NUMGLO)
 * *****************
 *
 * INTEGER          NUMLOC      :  -> : numéro de cellule local
 * INTEGER          INDDOM      :  -> : rang du domaine associé (0 à N-1)
 * INTEGER          NUMGLO      :  -> : numéro de cellule global
 *----------------------------------------------------------------------------*/

void CS_PROCF (parclg, PARCLG)
(
 cs_int_t   *numloc,
 cs_int_t   *inddom,
 cs_int_t   *numglo
);


/*----------------------------------------------------------------------------
 * Numéro de face interne global associé à un numéro de face interne local
 *   du processeur courant, sans communication avec les autres
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARFIG (NUMLOC,INDDOM,NUMGLO)
 * *****************
 *
 * INTEGER          NUMLOC      :  -> : numéro de face interne local
 * INTEGER          INDDOM      :  -> : rang du domaine associé (0 à N-1)
 * INTEGER          NUMGLO      :  -> : numéro de face interne global
 *----------------------------------------------------------------------------*/

void CS_PROCF (parfig, PARFIG)
(
 cs_int_t   *numloc,
 cs_int_t   *inddom,
 cs_int_t   *numglo
);


/*----------------------------------------------------------------------------
 * Numéro de face de bord global associé à un numéro de face de bord local
 *   du processeur courant, sans communication avec les autres
 *
 * Interface Fortran :
 *
 * SUBROUTINE PARFBG (NUMLOC,INDDOM,NUMGLO)
 * *****************
 *
 * INTEGER          NUMLOC      :  -> : numéro de face de bord local
 * INTEGER          INDDOM      :  -> : rang du domaine associé (0 à N-1)
 * INTEGER          NUMGLO      :  -> : numéro de face de bord global
 *----------------------------------------------------------------------------*/

void CS_PROCF (parfbg, PARFBG)
(
 cs_int_t   *numloc,
 cs_int_t   *inddom,
 cs_int_t   *numglo
);


/*----------------------------------------------------------------------------
 * Somme aux entités correspondant à une interface interdomaines
 * des valeurs d'une variable réelle.
 *
 * Les valeurs aux entités ne correspondant pas à l'interface sont inchangées,
 * celles aux entités correspondant à l'interface sont sommées avec les
 * valeurs distantes associées.
 *----------------------------------------------------------------------------*/

void cs_parallel_interface_sr
(
 fvm_interface_set_t  *interfaces,     /* --> jeu d'interfaces interdomaines  */
 cs_int_t              nbr_ent,        /* --> nombre d'entités associées      */
 cs_int_t              pas,            /* --> nombre de valeurs (non
                                        *     entrelacées)  par entité        */
 cs_real_t            *var             /* <-> variable                        */
);


/*----------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif /* __cplusplus */

