/*============================================================================
*
*                    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 associée à la sélection d'entités liées à cs_maillage_t
 *============================================================================*/

/* includes système */

#include <assert.h>
#include <string.h>

#if defined(_CS_HAVE_MPI)
#include <mpi.h>
#endif

/* Includes BFT */

#include <bft_mem.h>
#include <bft_error.h>
#include <bft_printf.h>

/* Includes librairie */

#include "cs_base.h"
#include "cs_maillage.h"
#include "cs_maillage_select.h"


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


/*============================================================================
 *                       Définition des structures
 *============================================================================*/

/* Structure associée à la sélection d'entités */

struct _cs_maillage_select_t {

  cs_int_t     nbr_couleur;      /* nombre de couleurs associées au couplage  */
  cs_int_t    *lst_couleur_fac;  /* liste des couleurs associées              */

  cs_int_t     nbr_groupe;       /* nombre de groupes associés au couplage    */
  char       **lst_groupe_fac;   /* liste des groupes associés                */

  cs_bool_t    inv_selection;

};


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



/*============================================================================
 * Fonctions publiques
 *============================================================================*/

/*----------------------------------------------------------------------------
 * Fonction qui alloue et initialise une structure _cs_maillage_select_t
 *----------------------------------------------------------------------------*/

cs_maillage_select_t * cs_maillage_select_cree
(
 cs_int_t     nbr_couleur,
 cs_int_t     nbr_groupe,
 cs_int_t    *couleurs,
 char       **groupes,
 cs_bool_t    invsel
)
{
  cs_int_t i_coul, i_group, lng;

  cs_maillage_select_t *selection = NULL;

  BFT_MALLOC(selection, 1, cs_maillage_select_t);

  selection->inv_selection = invsel;

  /* Initialisation des couleurs */

  selection->nbr_couleur = nbr_couleur;
  BFT_MALLOC(selection->lst_couleur_fac, nbr_couleur, cs_int_t);

  for (i_coul = 0; i_coul < nbr_couleur; i_coul++)
    selection->lst_couleur_fac[i_coul] = couleurs[i_coul];

  /* Initialisation des groupes */

  selection->nbr_groupe = nbr_groupe;
  BFT_MALLOC(selection->lst_groupe_fac, nbr_groupe, char *);

  for (i_group = 0; i_group < nbr_groupe; i_group++) {

    lng = strlen(groupes[i_group]);
    BFT_MALLOC(selection->lst_groupe_fac[i_group], lng + 1, char);
    strncpy(selection->lst_groupe_fac[i_group], groupes[i_group], lng);
    (selection->lst_groupe_fac[i_group])[lng + 1] = '\0';

  }

  return selection;
}

/*----------------------------------------------------------------------------
 * Fonction qui détruit une structure _cs_maillage_select_t
 *----------------------------------------------------------------------------*/

cs_maillage_select_t * cs_maillage_select_detruit
(
 cs_maillage_select_t *selection
)
{
  cs_int_t igroup;

  BFT_FREE(selection->lst_couleur_fac);

  for (igroup = 0; igroup < selection->nbr_groupe; igroup++)
    BFT_FREE(selection->lst_groupe_fac[igroup]);
  BFT_FREE(selection->lst_groupe_fac);

  BFT_FREE(selection);

  return NULL;
}

/*----------------------------------------------------------------------------
 * Fonction qui renvoie le nombre de couleurs dans la sélection
 *----------------------------------------------------------------------------*/

cs_int_t cs_maillage_select_ret_nbr_coul
(
 const cs_maillage_select_t *selection
)
{
  return selection->nbr_couleur;
}

/*----------------------------------------------------------------------------
 * Fonction qui renvoie le nombre de groupes dans la sélection
 *----------------------------------------------------------------------------*/

cs_int_t cs_maillage_select_ret_nbr_grp
(
 const cs_maillage_select_t *selection
)
{
  return selection->nbr_groupe;
}

/*----------------------------------------------------------------------------
 * Fonction qui extrait une liste de faces de bord suivant les critères de
 * sélection passés dans la structure cs_maillage_select_t
 *----------------------------------------------------------------------------*/

void cs_maillage_select_extrait_fbr
(
 const cs_maillage_t  *const maillage,        /* maillage d'origine           */
 const cs_maillage_select_t *selection,       /* critères de sélection        */
       cs_int_t             *nbr_fbr_select,  /* nb de fbr sélectionnées      */
       cs_int_t            **lst_fbr_select   /* liste des fbr sélectionnées  */
)
{
  cs_int_t i_fam, i_prop, idx, i_coul, i_grp, i_fac, num_grp ;
  cs_bool_t  fin;
  char *grp = NULL;
  cs_bool_t *select_fam = NULL;
  cs_int_t  *_lst_fbr_select = NULL;

  /* Données issues du maille d'origine */
  cs_int_t *prop_fam = maillage->prop_fam;
  cs_int_t *pos_grp = maillage->pos_grp;
  char     *nom_grp = maillage->nom_grp;

  BFT_MALLOC(select_fam, maillage->nbr_fam, cs_bool_t);

  for (i_fam = 0; i_fam < maillage->nbr_fam; i_fam++)
    select_fam[i_fam] = CS_FALSE;

  /* Recherche des familles repondant aux critères de sélection */

  idx = 0;
  for (i_prop = 0; i_prop < maillage->nbr_prop_fam_max; i_prop++) {

    for (i_fam = 0; i_fam < maillage->nbr_fam; i_fam++) {

      if (prop_fam[idx] > 0) { /* Sélection par la couleur */

        i_coul = 0;
        fin = CS_FALSE;
        while (fin == CS_FALSE && i_coul < selection->nbr_couleur) {

          if (prop_fam[idx] == selection->lst_couleur_fac[i_coul]) {
            /* la famille est sélectionnée */
            select_fam[i_fam] = CS_TRUE;
            fin = CS_TRUE;
            bft_printf(_("Famille n°%d sélectionnée pour le couplage syrthes\n"),
              i_fam + 1);
          }
          i_coul++;

        }

      } /* Fin du traitement des couleurs */

      else if (prop_fam[idx] < 0) { /* Sélection par les groupes */

        i_grp = 0;
        fin = CS_FALSE;
        num_grp = CS_ABS(prop_fam[idx]);
        grp = &(nom_grp[pos_grp[num_grp - 1] - 1]);

        while (fin == CS_FALSE && i_grp < selection->nbr_groupe) {

          if (!strcmp(selection->lst_groupe_fac[i_grp], grp)) {
            /* la famille est sélectionnée */
            select_fam[i_fam] = CS_TRUE;
            fin = CS_TRUE;
            bft_printf(_("Famille n°%d sélectionnée pour le couplage syrthes\n"),
              i_fam + 1);
          }
          i_grp++;

        }

      } /* Fin du traitement des groupes */

      else { /* Famille par défaut */

        assert(prop_fam[idx] == 0);

      }

      idx++;

    } /* Fin de la boucle sur les familles */

  } /* Fin de la boucle sur les propriétés des familles */

  /* Si inversion de la selection demandée */

  if (selection->inv_selection == CS_TRUE) {
    for (i_fam = 0;  i_fam < maillage->nbr_fam; i_fam++) {

      if (select_fam[i_fam] == CS_FALSE)
        select_fam[i_fam] = CS_TRUE;
      else if (select_fam[i_fam] == CS_TRUE)
        select_fam[i_fam] = CS_FALSE;
      else
        assert(select_fam[i_fam] == CS_TRUE ||
               select_fam[i_fam] == CS_FALSE);

    }
  }

  /* Sélection des faces appartenant aux familles retenues */

  *nbr_fbr_select = 0;

  /* Surdimensionne certainement la liste mais évite une boucle sur les
     faces de bord pour déterminer exactement la dimension */

  BFT_MALLOC(_lst_fbr_select, maillage->nbr_fbr, cs_int_t);

  for (i_fac = 0; i_fac < maillage->nbr_fbr; i_fac++) {
    if (select_fam[maillage->fam_fbr[i_fac] - 1] == CS_TRUE) {

      _lst_fbr_select[*nbr_fbr_select] = i_fac + 1;
      *nbr_fbr_select += 1;

    }
  }

  /* Redimensionne la liste si nécessaire */

  if (*nbr_fbr_select != maillage->nbr_fbr)
    BFT_REALLOC(_lst_fbr_select, *nbr_fbr_select, cs_int_t);

  *lst_fbr_select = _lst_fbr_select;

  /* Libération des buffers temporaires */

  BFT_FREE(select_fam);
}

/*----------------------------------------------------------------------------
 * Fonction qui affiche le contenu de la structure _cs_maillage_select_t
 *----------------------------------------------------------------------------*/

void cs_maillage_select_dump
(
 cs_maillage_select_t  *selection
)
{
  cs_int_t i;

  assert(selection != NULL);

  if (selection->inv_selection == CS_TRUE)
    bft_printf("Inversion de la sélection demandé\n");

  bft_printf("\nCouleur(s) des faces couplées:\n");
  bft_printf("Nombre de couleur(s): %i\n",selection->nbr_couleur);
  for (i = 0; i < selection->nbr_couleur; i++)
    bft_printf("Couleur numéro: %i\n", selection->lst_couleur_fac[i]);

  bft_printf("\nGroupes(s) des faces couplées:\n");
  bft_printf("Nombre de groupe(s): %i\n",selection->nbr_groupe);
  for (i = 0; i < selection->nbr_groupe; i++)
    bft_printf("Groupe: %s\n", selection->lst_groupe_fac[i]);

  bft_printf_flush();
}

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




#ifdef __cplusplus
}
#endif /* __cplusplus */
