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

/*============================================================================
 * Programme principal
 *============================================================================*/

/* Includes système */

#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Includes BFT */

#include <bft_config.h>
#include <bft_mem.h>
#include <bft_printf.h>
#include <bft_fp_trap.h>
#include <bft_timer.h>

/* Includes librairie */

#include "cs_base.h"
#include "cs_comm.h"
#include "cs_couplage.h"
#include "cs_maillage.h"
#include "cs_maillage_connect.h"
#include "cs_maillage_grd.h"
#include "cs_maillage_solcom.h"
#include "cs_mesh_quality.h"
#include "cs_messages_ecs.h"
#include "cs_opts.h"
#include "cs_suite.h"
#include "cs_syr_coupling.h"
#include "cs_post.h"

#if defined(_CS_HAVE_XML)
#include "cs_gui.h"
#endif

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

/*----------------------------------------------------------------------------
 * SUBROUTINE CSINIT : sous-programme d'initialisation Fortran listing
 *----------------------------------------------------------------------------*/

extern void CS_PROCF(csinit, CSINIT)
(
 cs_int_t  *ifoenv,    /* Format de communication avec l'enveloppe            */
 cs_int_t  *iparal,    /* Rang du noyau en cas de parallelisme                */
 cs_int_t  *nparal,    /* Nombre de processus (=1 en sequentiel)              */
 cs_int_t  *ilisr0,    /* Option de sortie du listing principal (rang 0) :    */
                       /*   0 : non redirigé ; 1 : sur fichier 'listing'      */
 cs_int_t  *ilisrp     /* Option de sortie des listings de rang > 0 :         */
                       /*   0 : non redirigé ; 1 : sur fichier 'listing_n*' ; */
                       /*   2 : sur fichier '/dev/null' (suppression)         */
);

/*----------------------------------------------------------------------------
 * SUBROUTINE INITI1 : sous-programme d'initialisation Fortran
 *----------------------------------------------------------------------------*/

extern void CS_PROCF(initi1, INITI1)
(
 cs_int_t  *longia,    /* Longueur du tableau d'entiers IA                    */
 cs_int_t  *longra,    /* Longueur du tableau d'entiers IA                    */
 cs_int_t  *idebia,    /* Premiere position libre dans IA                     */
 cs_int_t  *idebra,    /* Premiere position libre dans RA                     */
 cs_int_t  *iverif     /* Activation des tests élémentaires                   */
);


/*----------------------------------------------------------------------------
 * SUBROUTINE CALTRI : sous-programme principal Fortran
 *----------------------------------------------------------------------------*/

extern void CS_PROCF(caltri, CALTRI)
(
 cs_int_t   *longia,   /* Longueur du tableau d'entiers IA                    */
 cs_int_t   *longra,   /* Longueur du tableau d'entiers IA                    */
 cs_int_t   *idebia,   /* Premiere position libre dans IA                     */
 cs_int_t   *idebra,   /* Premiere position libre dans RA                     */
 cs_int_t   *iverif,   /* Activation des tests elementaires                   */
 cs_int_t   *ifacel,   /* Éléments voisins d'une face interne                 */
 cs_int_t   *ifabor,   /* Élément  voisin  d'une face de bord                 */
 cs_int_t   *ifmfbr,   /* Numéro de famille d'une face de bord                */
 cs_int_t   *ifmcel,   /* Numéro de famille d'une cellule                     */
 cs_int_t   *iprfml,   /* Propriétés d'une famille                            */
 cs_int_t   *ipnfac,   /* Pointeur par sommet dans NODFAC (optionnel)         */
 cs_int_t   *nodfac,   /* Connectivité faces internes/sommets (optionnelle)   */
 cs_int_t   *ipnfbr,   /* Pointeur par sommet dans NODFBR (optionnel)         */
 cs_int_t   *nodfbr,   /* Connectivité faces de bord/sommets (optionnelle)    */
 cs_int_t   *ia,       /* Pointeur sur le tableau d'entiers IA                */
 cs_real_t  *xyzcen,   /* Points associés aux centres des volumes de contrôle */
 cs_real_t  *surfac,   /* Vecteurs surfaces des faces internes                */
 cs_real_t  *surfbo,   /* Vecteurs surfaces des faces de bord                 */
 cs_real_t  *cdgfac,   /* Centres de gravité des faces internes               */
 cs_real_t  *cdgfbr,   /* Centres de gravité des faces de bord                */
 cs_real_t  *xyznod,   /* Coordonnées des sommets (optionnelle)               */
 cs_real_t  *volume,   /* Volumes des cellules                                */
 cs_real_t  *ra        /* Pointeur sur le tableau de reels RA                 */
);


/*----------------------------------------------------------------------------
 * Fonction utilisateur pour la modification de la géométrie
 *----------------------------------------------------------------------------*/

void CS_PROCF (usmodg, USMODG)
(
 const cs_int_t  *ndim,      /* --> dimension de l'espace                     */
 const cs_int_t  *ncelet,    /* --> nombre de cellules étendu                 */
 const cs_int_t  *ncel,      /* --> nombre de cellules                        */
 const cs_int_t  *nfac,      /* --> nombre de faces internes                  */
 const cs_int_t  *nfabor,    /* --> nombre de faces de bord                   */
 const cs_int_t  *nfml,      /* --> nombre de familles                        */
 const cs_int_t  *nprfml,    /* --> nombre de proprietes des familles         */
 const cs_int_t  *nnod,      /* --> nombre de sommets                         */
 const cs_int_t  *lndfac,    /* --> longueur de nodfac                        */
 const cs_int_t  *lndfbr,    /* --> longueur de nodfbr                        */
 const cs_int_t   ifacel[],  /* --> connectivité faces internes / cellules    */
 const cs_int_t   ifabor[],  /* --> connectivité faces de bord / cellules     */
 const cs_int_t   ifmfbr[],  /* --> liste des familles des faces de bord      */
 const cs_int_t   ifmcel[],  /* --> liste des familles des cellules           */
 const cs_int_t   iprfml[],  /* --> liste des propriétés des familles         */
 const cs_int_t   ipnfac[],  /* --> rang dans nodfac 1er sommet faces int.    */
 const cs_int_t   nodfac[],  /* --> numéro des sommets des faces intérieures  */
 const cs_int_t   ipnfbr[],  /* --> rang dans nodfbr 1er sommet faces bord    */
 const cs_int_t   nodfbr[],  /* --> numéro des sommets des faces de bord      */
       cs_real_t  xyznod[]   /* --> coordonnées des sommets                   */
);


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

/*============================================================================
 * Programme principal
 *============================================================================*/

/*----------------------------------------------------------------------------
 * Point d'entrée du programme principal
 *----------------------------------------------------------------------------*/

int main
(
 int    argc,       /* Nombre d'arguments dans la ligne de commandes */
 char  *argv[]      /* Tableau des arguments de la ligne de commandes */
)
{
  /* variables locales */

  int     rang_deb = -1;

  cs_opts_t   opts;
  cs_int_t    idebia, idebra;
  cs_int_t   *ia = NULL;
  cs_real_t  *ra = NULL;

  /* Première analyse de la ligne de commande pour savoir si l'on a besoin
     de MPI ou non, et initialisation de MPI le cas échéant */

#if defined(_CS_HAVE_MPI)
  rang_deb = cs_opts_mpi_rank(&argc, &argv);
  if (rang_deb > -1)
    cs_base_mpi_init(&argc, &argv, rang_deb);
#endif

  /* initialisation par défaut */

#if defined(_CS_ARCH_Linux)
  setlocale(LC_ALL,"");
  setlocale(LC_NUMERIC, "C");
#endif

  (void)bft_timer_wtime();

  bft_fp_trap_set();

  /* Initialisation de la gestion mémoire et des signaux */

  cs_base_mem_init();
  cs_base_erreur_init();

  /* interprétation des arguments de la ligne de commande */

  cs_opts_define(argc, argv, &opts);

  /* Ouverture des fichiers 'listing' pour les noeuds de rang > 0 */
  CS_PROCF(csinit, CSINIT)(&(opts.ifoenv),
                           &cs_glob_base_rang,
                           &cs_glob_base_nbr,
                           &(opts.ilisr0),
                           &(opts.ilisrp));
  cs_base_bft_printf_set();

  /* Entête et rappel des options de la ligne de commande */
  cs_opts_logfile_head(argc, argv);

  /* Infos système */
  cs_base_info_systeme();

  /* Initialisation du maillage principal */
  cs_glob_maillage     = cs_maillage_cree();
  cs_glob_maillage_grd = cs_maillage_grd_cree();

  /* Initialisation de la communication avec l'Enveloppe */

  if (opts.ifoenv != 0) {

    cs_glob_comm_ecs_vers_cs = cs_comm_initialise("enveloppe",
                                                  "solveur",
                                                  "ESC_0.1",
                                                  0,
#if defined(_CS_HAVE_MPI)
                                                  -1,
#endif
                                                  CS_COMM_MODE_RECEPTION,
                                                  opts.comm_type,
                                                  opts.echo_comm);

    /* Initialisation des communications avec Syrthes */

    if (cs_syr_coupling_n_couplings() != 0) {

      cs_int_t i_coupl;
      cs_int_t n_coupl = cs_syr_coupling_n_couplings();

      for (i_coupl = 0; i_coupl < n_coupl; i_coupl++)
        cs_syr_coupling_init_comm(cs_syr_coupling_by_id(i_coupl),
                                  i_coupl + 1,
                                  opts.echo_comm);

    } /* Couplage Syrthes */

  } /* Si ifoenv != 0 */

  /* Allocation de structures internes de l'API F77 pour fichiers suite */
  cs_suite_f77_api_init();

  /* Appel du sous-programme d'initalisation ou de l'aide */

  CS_PROCF(initi1, INITI1)(&(opts.longia),
                           &(opts.longra),
                           &idebia,
                           &idebra,
                           &(opts.iverif));

  if (opts.ifoenv == 0) {

    /* Lecture du fichier au format "SolCom" */
    cs_maillage_solcom_lit(cs_glob_maillage,
                           cs_glob_maillage_grd);

  }
  else {

    /* Lecture des données issues de l'enveloppe */
    cs_messages_ecs_lit_data(cs_glob_maillage);

    /* Initialisations liées au parallélisme */
#if defined(_CS_HAVE_MPI)
    cs_glob_maillage_tmp = cs_maillage_tmp_cree(cs_glob_maillage);
    cs_maillage_init_parallel(cs_glob_maillage,
                              cs_glob_maillage_tmp);
#endif
  }

  /* Modification éventuelle de la géométrie */

  CS_PROCF (usmodg, USMODG)(&(cs_glob_maillage->dim),
                            &(cs_glob_maillage->nbr_cel_etendu),
                            &(cs_glob_maillage->nbr_cel),
                            &(cs_glob_maillage->nbr_fac),
                            &(cs_glob_maillage->nbr_fbr),
                            &(cs_glob_maillage->nbr_fam),
                            &(cs_glob_maillage->nbr_prop_fam_max),
                            &(cs_glob_maillage->nbr_som),
                            &(cs_glob_maillage->lng_fac_som),
                            &(cs_glob_maillage->lng_fbr_som),
                            cs_glob_maillage->fac_cel,
                            cs_glob_maillage->fbr_cel,
                            cs_glob_maillage->fam_fbr,
                            cs_glob_maillage->fam_cel,
                            cs_glob_maillage->prop_fam,
                            cs_glob_maillage->pos_fac_som,
                            cs_glob_maillage->val_fac_som,
                            cs_glob_maillage->pos_fbr_som,
                            cs_glob_maillage->val_fbr_som,
                            cs_glob_maillage->coo_som);

  /* Calcul des grandeurs géométriques associées au maillage */
  cs_maillage_grd_calc(cs_glob_maillage,
                       cs_glob_maillage_grd);

  cs_maillage_info(cs_glob_maillage);

  /* Initialisation du post-traitement principal */
  cs_post_init_pcp();

  /* Boucle en temps ou critères de qualité selon options de vérification */

  if (opts.iverif == 0) {
    cs_mesh_quality(cs_glob_maillage,
                    cs_glob_maillage_grd);
  }

  else {

    /* Allocation des tableaux de travail */
    BFT_MALLOC(ia, opts.longia, cs_int_t);
    BFT_MALLOC(ra, opts.longra, cs_real_t);

    /*------------------------------------------------------------------------
     *  appel du sous-programme de gestion de calcul (noyau du code)
     *------------------------------------------------------------------------*/

    CS_PROCF(caltri, CALTRI)(&(opts.longia),
                             &(opts.longra),
                             &idebia,
                             &idebra,
                             &(opts.iverif),
                             cs_glob_maillage->fac_cel,
                             cs_glob_maillage->fbr_cel,
                             cs_glob_maillage->fam_fbr,
                             cs_glob_maillage->fam_cel,
                             cs_glob_maillage->prop_fam,
                             cs_glob_maillage->pos_fac_som,
                             cs_glob_maillage->val_fac_som,
                             cs_glob_maillage->pos_fbr_som,
                             cs_glob_maillage->val_fbr_som,
                             ia,
                             cs_glob_maillage_grd->cen_cel,
                             cs_glob_maillage_grd->surf_fac,
                             cs_glob_maillage_grd->surf_fbr,
                             cs_glob_maillage_grd->cdg_fac,
                             cs_glob_maillage_grd->cdg_fbr,
                             cs_glob_maillage->coo_som,
                             cs_glob_maillage_grd->vol_cel,
                             ra);

    /* les fichiers listing de noeuds > 0 sont fermés dans caltri. */

    /* Libération des tableaux de travail */
    BFT_FREE(ia);
    BFT_FREE(ra);

  }


#if defined(_CS_HAVE_XML)
  /* Libération des structures liées à la lecture du fichier xml */
  cs_gui_clean_memory();
#endif

  /* Libération de structures internes de l'API F77 pour fichiers suite */

  cs_suite_f77_api_finalize();

  /* Libération de la mémoire éventuellement affectée aux couplages */

  cs_syr_coupling_all_destroy();
#if defined(_CS_HAVE_MPI)
  cs_couplage_detruit_tout();
#endif

  /* Libération de la mémoire associée aux post-traitements */

  cs_post_detruit();

  /* Libération du maillage principal */
#if defined(_CS_HAVE_MPI)
  cs_maillage_tmp_detruit(cs_glob_maillage_tmp);
#endif
  cs_maillage_grd_detruit(cs_glob_maillage_grd);
  cs_maillage_detruit(cs_glob_maillage);

  /* Temps CPU et finalisation de la gestion mémoire */
  cs_base_bilan_temps();
  cs_base_mem_fin();

  /* retour */
  cs_exit(EXIT_SUCCESS);

  /* jamais appelé normalement, mais pour éviter un warning de compilation */
  return 0;

}


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

