// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program 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 3 of the License,
// or (at your option) any later version.
//
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *     DATE:        03/01/2022                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  une classe qui a pour objectif de servir,                  *
 *           d'interface entre un conteneur Element::ResRaid et         *
 *           un conteneur qui est transmis entre CPU via MPI            *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 ************************************************************************/
 
#ifndef RESRAID_MPI_H
#define RESRAID_MPI_H

#include <boost/serialization/split_member.hpp>
#include <boost/mpi/packed_oarchive.hpp>

#include "Vecteur.h"
#include "Mat_pleine.h"
#include "Basiques.h"

/**
*
*     BUT:  une classe qui a pour objectif de servir,
*           d'interface entre un conteneur Element::ResRaid et
*           un conteneur qui est transmis entre CPU via MPI
*
*
* \author    Gérard Rio
* \version   1.0
* \date      03/01/2022
* \brief     classe d'interface entre Element::ResRaid  et un conteneur transmis entre CPU via MPI
*
*/

class ResRaid_MPI
{
  public :
    // CONSTRUCTEURS :
    // par défaut
    ResRaid_MPI();
    
    // fonction d'un resraid et d'un élément particulier
    // avec_recopie : indique si on veut une recopie ou pas
    //                si false: c'est seulement les tailles qui sont utilisées
    ResRaid_MPI(const DeuxEntiers& elem, const Vecteur* res, const Mat_pleine* raid,bool avec_recopie);
           
    // constructeur de copie
    ResRaid_MPI (const ResRaid_MPI& a);

    // DESTRUCTEUR :
    ~ResRaid_MPI() ;
    
    // METHODES PUBLIQUES :

    // affectation à partir d'un élément particulier et d'un resraid
    // opération analogue à la construction, mais dédié à une instance déjà existante
    // correspond à la surcharge d'affectation, mais je préfère une fonction plus explicite !
    // pour éviter des affectations non voulues
    void Affectation(const DeuxEntiers& elem, const Vecteur* res, const Mat_pleine* raid);

    //============= lecture écriture dans base info ==========
    // cas donne le niveau de la récupération
    // = 1 : on récupère tout
    // = 2 : on récupère uniquement les données variables (supposées comme telles)
    void Lecture_base_info(istream& ent,const int cas);
    // cas donne le niveau de sauvegarde
    // = 1 : on sauvegarde tout
    // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
    void Ecriture_base_info(ostream& sort,const int cas);
    
    // récupération des infos
    int  Num_elt() const {return  val_de_base(1);};  // numero d'identification de l'element
    int  Num_mail() const {return  val_de_base(2);};  // numéro de maillage
    
    const Vecteur & Const_res() const {return *res;};       // vecteur résidu
    const Mat_pleine &  Const_raid() const {return *raid ;};     // vecteur raideur

    
  private :
    // VARIABLES PROTEGEES :
    // l'idée c'est d'avoir un seul gros conteneur qui englobe toutes les infos
    // pour pouvoir faire un passage MPI natif: c-a-d un pointeur + un nombre
    
    // --1) le vecteur qui contient tout
    Vecteur val_de_base;
    // val_de_base(1) contient le num de l'element
    // val_de_base(2) contient le num du maillage

    // --2) puis les grandeurs qui sont  une tranche de val_de_base (vecteur et mat_pleine)
    
    Vecteur*     res;       // vecteur résidu
    Mat_pleine*  raid ;     // vecteur raideur

    // méthode interne pour créer les vecteurs tranches
    // ce qui crée une liaison entre les deux stockages
    // avec_recopie : indique si on veut une recopie ou pas
    void Creation_res_raid(bool avec_recopie,const Vecteur* ress, const Mat_pleine* raidd);
    // idem pour modifier éventuellement les tailles  uniquement
    void Change_tailles_res_raid(bool avec_recopie,const Vecteur* ress, const Mat_pleine* raidd);


// on supprime la sérialisation, qui ne devrait plus être utilisée

//    // METHODES PROTEGEES :
//    // -- serialisation ---
//    // NB: pas trouvé comment déclarer l'implantation des méthodes template
//    //     en dehors du .h, donc on décrit le fct ici en inline
//    // déclaration en friend pour l'acces direct de boost
//    friend class boost::serialization::access;
//    // on spécialise la sauvegarde et la restitution
//    // version == 0 pour la première sauvegarde et ensuite > 0
//    // NB: c'est toujours la version en cours au moment de la sauvegarde
//    // ==> dans notre cas, on ne sent sert pas pour l'instant: supposé tjs == 0
//    template<class Archive>
//    void save(Archive & ar,  unsigned int version) const
//      { // on commence par les num mail et élément
//        ar << std::string(" num_maillage ")<< num_maillage
//           << std::string(" num_elem ") << num_elt;
//        // puis le vecteur résidu
//        ar << res;
//        // puis la raideur
//        ar << raid;
//      }
//
//    // en lecture, le num de version permet de ce positionner sur une version particulière
//    template<class Archive>
//    void load(Archive & ar, const unsigned int version)
//     { // opération inverse de save
//       std::string toto;
//       // on commence par les num mail et élément
//       ar >>  toto >> num_maillage
//          >> toto >>  num_elt;
//       // puis le vecteur résidu
//       ar >> res;
//       // puis la raideur
//       ar >> raid;
//    }
//
//    // la macro suivante va définir automatiquement la méthode : "serialize"
//    BOOST_SERIALIZATION_SPLIT_MEMBER()
//    // pour mémoire on indique l'entête de la méthode "serialize"
////    // la méthode serialize fonctionne dans les deux sens: lecture et écriture dans ar
////    // << et >> est remplacé par &
////    // le choix dépend du fait que ar est un flux entrant ou sortant
////    template<class Archive>
////    void serialize(Archive & ar, const unsigned int version);

 };
 
#endif
