// 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) .
//
// 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 .
//
// For more information, please consult: .
#include "Charge.h"
#include "ConstMath.h"
#include "MathUtil.h"
#include "ReferenceNE.h"
#include "ReferenceAF.h"
#include "CourbePolyLineaire1D.h"
// --------------- méthodes particulière pour les conteneurs de chargement ----------
// == cas de la classe PHydro
// certaines fonctions sont redéfinies en suivant le caneva de Bloc.h
Charge::PHydro::PHydro()
:BlocGeneEtVecMultType(2,1),N(),M(),normer(false)
{};
Charge::PHydro::PHydro(const Charge::PHydro & a) : // constructeur par defaut
BlocGeneEtVecMultType(a),N(a.N),M(a.M),normer(a.normer)
{};
Charge::PHydro::~PHydro () // destructeur
{}; // les courbes éventuelles existent par ailleurs, elles n'ont pas à être supprimées
// mise en place de l'association des courbes
// en retour indique si l'association est ok
bool Charge::PHydro::Mise_en_place_des_courbes(LesCourbes1D& lesCourbes1D)
{ // on passe en revue la liste de nom pour associer éventuellement avec les courbes
int dim = ParaGlob::Dimension();
// cas du vecteur N
for (int i=1;i<=dim;i++)
{ const string& nom = Nom_vect(1,i);
if (nom != "NULL")
{ // cas d'une coordonnée gérée par une courbe
if (N.Taille() == 0) N.Change_taille(dim,NULL);
if (lesCourbes1D.Existe(nom))
{ N(i) = lesCourbes1D.Trouve(nom);}
else
{ cout << "\n erreur, on ne trouve pas la courbe coefficient " << i << "pour la direction normale N !!! "
<< " de nom: " << nom
<< "\n Charge::PHydro::Mise_en_place_des_courbes(...";
return false;
};
};
};
// cas du vecteur M
for (int i=1;i<=dim;i++)
{ const string& nom = Nom_vect(2,i);
if (nom != "NULL")
{ // cas d'une coordonnée gérée par une courbe
if (M.Taille() == 0) M.Change_taille(dim,NULL);
if (lesCourbes1D.Existe(nom))
{ M(i) = lesCourbes1D.Trouve(nom);}
else
{ cout << "\n erreur, on ne trouve pas la courbe coefficient " << i << "pour le point A de la surface libre !!! "
<< " de nom: " << nom
<< "\n Charge::PHydro::Mise_en_place_des_courbes(...";
return false;
};
};
};
// si on arrive là c'est que tous c'est bien passé
return true;
};
// récup de la direction N normée
const Coordonnee& Charge::PHydro::Direction_N()
{ // on regarde s'il y a des courbes de charges
Coordonnee N_vect = Vect_de_coordonnee(1); // init
if (N.Taille() == 0)
// pas de courbe, on norme la première fois
{ if (!normer)
{ double norme = N_vect.Norme();
if (norme != 1.)
{ N_vect.Normer(); Change_vect_de_coordonnee(1,N_vect);}
normer = true;
};
}
else // sinon il faut voir avec le temps
{int dim = N.Taille();
// récup des valeurs
for (int i=1;i <= dim; i++)
{if (N(i) != NULL)
N_vect(i) = (N(i)->Valeur(ParaGlob::Variables_de_temps().TempsCourant()));
};
// on norme le vecteur
double norme = N_vect.Norme();
if (norme != 1.)
{ N_vect.Normer();};
// on met à jour le vecteur
Change_vect_de_coordonnee(1,N_vect);
};
// retour du vecteur qui continue à exister
return Vect_de_coordonnee(1);
};
// récup du point de la surface libre
const Coordonnee& Charge::PHydro::Point_M()
{ // on regarde s'il y a des courbes de charges
Coordonnee M_vect = Vect_de_coordonnee(2); // init
if (M.Taille() != 0)
// il faut voir avec le temps
{int dim = M.Taille();
// récup des valeurs
for (int i=1;i <= dim; i++)
{if (M(i) != NULL)
M_vect(i) = (M(i)->Valeur(ParaGlob::Variables_de_temps().TempsCourant()));
};
// on met à jour le vecteur
Change_vect_de_coordonnee(2,M_vect);
};
// retour du vecteur qui continue à exister
return Vect_de_coordonnee(2);
};
// == cas de la classe PHydrodyna
// --- mise en place de l'association des courbes pour PHydrodyna
// en retour indique si l'association est ok
bool Charge::PHydrodyna::Mise_en_place_des_courbes(LesCourbes1D& lesCourbes1D)
{ // on passe en revue la liste de nom pour associer avec les courbes
// cas du frottement fluid
const string& nom = Nom(3);
if (nom != "NULL")
{ // cas où le frottement fluide est actif
if (lesCourbes1D.Existe(nom))
{ frot_fluid = lesCourbes1D.Trouve(nom);}
else
{ cout << "\n erreur, on ne trouve pas la courbe coefficient pour le frottement fluide !!! "
<< " de nom: " << nom
<< "\n Charge::PHydrodyna::Mise_en_place_des_courbes(...";
return false;
};
};
// cas de l'effort de traînée
const string& nom1 = Nom(4);
if (nom1 != "NULL")
{ // cas où l'effort de traînée est actif
if (lesCourbes1D.Existe(nom1))
{ coef_aero_n = lesCourbes1D.Trouve(nom1);}
else
{ cout << "\n erreur, on ne trouve pas la courbe coefficient pour l'effort de trainee !!! "
<< " de nom: " << nom1
<< "\n Charge::PHydrodyna::Mise_en_place_des_courbes(...";
return false;
};
};
// cas de l'effort de portance
const string& nom2 = Nom(5);
if (nom2 != "NULL")
{ // cas où l'effort de portance est actif
if (lesCourbes1D.Existe(nom2))
{ coef_aero_t = lesCourbes1D.Trouve(nom2);}
else
{ cout << "\n erreur, on ne trouve pas la courbe coefficient pour l'effort de portance !!! "
<< " de nom: " << nom2
<< "\n Charge::PHydrodyna::Mise_en_place_des_courbes(...";
return false;
};
};
// si on arrive là c'est que tous c'est bien passé
return true;
};
// cas des torseurs de charges ponctuelles
// --------------- fin méthodes particulière pour les conteneurs de chargement ----------
// ------------- fin des variables static -----------------
Charge::Charge () : // constructeur par defaut
tabFsurfac(),tabPresUnif(),tabPonctuel(),PresUniDir(),PresHydro(),coefHydroDyna(),tabFlineique()
,tabFlineiqueSuiv(),tabFvol(),f_charge(NULL),interne_f_charge(false)
,tabTorseurPonct(),tab_P(),t_force()
,multi(0.),coeff(0.),temps_sauve(0.),multi_sauve(0.),coeff_sauve(0.)
,temps_fin_non_stricte(0)
,nomtypeCharge(),ancien_num_pt_type5(0),num_pt_courant_type5(0)
,temps_cpu_chargement()
#ifdef UTILISATION_MPI
,temps_transfert_court(),temps_transfert_long(),temps_attente()
,tab_reqs1(),tab_reqs2(),tab_reqs3()
,tabV_transfert(),tabMat_transfert(),tab_six_faux_entiers()
#endif
{// mise à jour de la valeur par défaut du chargement au cas où aucun chargement
// n'est définit
nomtypeCharge ="TYPE1";
tabType.Change_taille(1);
tabType(1) = 1.;
#ifdef UTILISATION_MPI
// on définit les conteneurs de passage d'info
int taille_passage = 8;
tab_reqs1.Change_taille(taille_passage);
tab_reqs2.Change_taille(taille_passage);
tab_reqs3.Change_taille(taille_passage);
tabV_transfert.Change_taille(taille_passage);
tabMat_transfert.Change_taille(taille_passage);
tab_six_faux_entiers.Change_taille(taille_passage);
for (int i=1;i<=taille_passage;i++)tab_six_faux_entiers(i).Change_taille(6);
#endif
}
Charge::~Charge ()
{ if (f_charge != NULL)
{ // on utilise un deuxième indicateur, car si la courbe est globale, et quelle est déjà supprimée
// on ne peut plus la tester
if (interne_f_charge)
delete f_charge;
};
};
// affichage des differents chargements
void Charge::Affiche() const // affiche la totalite
{ Affiche1();
Affiche2();
};
void Charge::Affiche1() const // affiche que la premiere lecture
{ cout << "\n ******** Charges ******** \n";
if (tabFvol.Taille() != 0)
{cout << tabFvol.Taille() << " reference de force volumique lue \n";
for (int i=1; i<=tabFvol.Taille(); i++)
tabFvol(i).Affiche();
cout << "\n\n";
}
if (tabFsurfac.Taille() != 0)
{cout << tabFsurfac.Taille() << " reference de densite de force surfacique lue \n";
for (int i=1; i<=tabFsurfac.Taille(); i++)
tabFsurfac(i).Affiche();
cout << "\n\n";
}
if (tabPresUnif.Taille() != 0)
{cout << tabPresUnif.Taille() << " reference de pression uniformement reparti lue \n";
for (int i=1; i<=tabPresUnif.Taille(); i++)
tabPresUnif(i).Affiche();
cout << "\n\n";
}
if (tabPonctuel.Taille() != 0)
{cout << tabPonctuel.Taille() << " reference de force ponctuelle lue \n";
for (int i=1; i<=tabPonctuel.Taille(); i++)
tabPonctuel(i).Affiche();
cout << "\n\n";
}
if (PresUniDir.Taille() != 0)
{cout << PresUniDir.Taille() << " reference de pression unidirectionnelle"
<< " type pression dynamique des fluides lue \n";
for (int i=1; i<=PresUniDir.Taille(); i++)
PresUniDir(i).Affiche();
cout << "\n\n";
}
if (PresHydro.Taille() != 0)
{cout << PresHydro.Taille() << " reference de pression hydrostatique lue \n";
for (int i=1; i<=PresHydro.Taille(); i++)
PresHydro(i).Affiche();
cout << "\n\n";
}
if (coefHydroDyna.Taille() != 0)
{cout << coefHydroDyna.Taille() << " reference de pression hydrodynamique lue \n";
for (int i=1; i<=coefHydroDyna.Taille(); i++)
coefHydroDyna(i).Affiche();
cout << "\n\n";
}
if (tabFlineique.Taille() != 0)
{cout << tabFlineique.Taille() << " reference de densite de force lineique lue \n";
for (int i=1; i<=tabFlineique.Taille(); i++)
tabFlineique(i).Affiche();
cout << "\n\n";
};
if (tabFlineiqueSuiv.Taille() != 0)
{cout << tabFlineiqueSuiv.Taille() << " reference de densite de force lineique suiveuse lue \n";
for (int i=1; i<=tabFlineiqueSuiv.Taille(); i++)
tabFlineiqueSuiv(i).Affiche();
cout << "\n\n";
};
if (tabTorseurPonct.Taille() != 0)
{cout << tabTorseurPonct.Taille() << " reference de torseur de forces ponctuelles lue \n";
for (int i=1; i<=tabTorseurPonct.Taille(); i++)
tabTorseurPonct(i).Affiche();
cout << "\n\n";
};
cout << endl;
};
void Charge::Affiche2() const // affiche que la seconde lecture
{ cout << "\n ******** Type de Chargement ******** \n";
if ((nomtypeCharge == "TYPE1") || (nomtypeCharge == "TYPE2") )
{ cout << " type de chargement : " << nomtypeCharge << ", parametre : ";
for (int i=1; i<=tabType.Taille(); i++)
cout << tabType(i) << " " ;
cout << endl;
}
else if (nomtypeCharge == "TYPE3")
{ cout << " type de chargement : " << nomtypeCharge << ", pas de parametre " << endl ;}
else if ((nomtypeCharge == "TYPE4") || (nomtypeCharge == "TYPE5"))
{ cout << " type de chargement : " << nomtypeCharge << ", fonction de charge: ";
if (interne_f_charge)
{f_charge->Affiche();}
else { cout << " courbe1D " << f_charge->NomCourbe() << " ";};
}
else
{ cout << " **** type de chargement non défini !! **** " << endl ;}
// cas de l'application du contrôle de temps fin
if (temps_fin_non_stricte)
cout << "\n la limite de temps est non stricte ";
else
cout << "\n la limite de temps est stricte ";
};
// lecture des actions exterieurs imposees
void Charge::Lecture1(UtilLecture & entreePrinc,LesReferences& lesRef,LesCourbes1D& lesCourbes1D
,LesFonctions_nD& lesFonctionsnD)
{ if (ParaGlob::NiveauImpression() >= 4)
cout << " debut de la lecture du chargement " << endl;
MotCle motCle; // ref aux mots cle
{ // on se positionne sur un mot cle
while ( !motCle.SimotCle(entreePrinc.tablcar))
entreePrinc.NouvelleDonnee();
// definition de la liste de sous mot cle specifique
Tableau tsousMotref(10);
tsousMotref(1) = "UNIFORME";tsousMotref(2) = "PRESSION";
tsousMotref(3) = "PONCTUELLE";tsousMotref(4) = "PRESSDIR";
tsousMotref(5) = "PHYDRO"; tsousMotref(6) = "LINEIQUE";
tsousMotref(7) = "VOLUMIQUE"; tsousMotref(8) = "LINEIC_SUIVEUSE";
tsousMotref(9) = "P_HYDRODYNA"; tsousMotref(10) = "TORSEUR_PONCT";
Tableau tsousMot(tsousMotref); // copie qui varie selon l'utilisation
// lecture pour se positionner sur un premier sous mot cle
entreePrinc.NouvelleDonnee();
// def d'une classe de lecture de bloc BlocCharge
LectBloc < BlocCharge< BlocDdlLim > > lecVecType;
// def d'une classe de lecture de bloc BlocScalType
LectBloc < BlocCharge< BlocDdlLim > > lecScalType;
// def d'une classe de lecture de bloc PHydro
LectBloc < BlocCharge< BlocDdlLim > > lecPHydro;
// def d'une classe de lecture de bloc PHydrodyna
LectBloc < BlocCharge< BlocDdlLim > > lecPHydrodyna;
// def d'une classe de lecture de bloc PTorseurPonct
LectBloc < BlocCharge< BlocDdlLim > > lecPTorseurPonct;
bool avance = true;
while ( !motCle.SimotCle(entreePrinc.tablcar) && avance)
// lecture jusqu'au prochain mot cle
{ string inter(entreePrinc.tablcar); // pour eviter la boucle infini qui n'avance pas
// lecture eventuelle des densite de force surfacique
tsousMot = tsousMotref;
tsousMot.Enleve (1); // on enleve "UNIFORME"
lecVecType.Lecture(entreePrinc,lesRef,"UNIFORME",
"lecture des densite de force surfacique",tabFsurfac,tsousMot,false);
// lecture eventuelle des pressions uniformement reparti
tsousMot = tsousMotref;
tsousMot.Enleve (2); // on enleve "PRESSION"
lecScalType.Lecture(entreePrinc,lesRef,"PRESSION",
"lecture des pressions uniformement reparti",tabPresUnif,tsousMot,false);
// lecture eventuelle des forces ponctuelles
tsousMot = tsousMotref;
tsousMot.Enleve (3); // on enleve "PONCTUELLE"
lecVecType.Lecture(entreePrinc,lesRef,"PONCTUELLE",
"lecture des forces ponctuelles",tabPonctuel,tsousMot,false);
// lecture eventuelle des pression unidirectionnelle
tsousMot = tsousMotref;
tsousMot.Enleve (4); // on enleve "PRESSDIR"
lecVecType.Lecture(entreePrinc,lesRef,"PRESSDIR",
"lecture des pressions unidirectionnelles",PresUniDir,tsousMot,false);
// lecture eventuelle des pressions hydrostatiques
tsousMot = tsousMotref;
tsousMot.Enleve (5); // on enleve "PHYDRO"
lecPHydro.Lecture(entreePrinc,lesRef,"PHYDRO",
"lecture des pressions hydrostatiques",PresHydro,tsousMot,false);
// initialisation éventuelle
int taj= PresHydro.Taille(); for (int i=1;i<=taj;i++)
{ if (!(PresHydro(i).Mise_en_place_des_courbes(lesCourbes1D))) // mise en place et test
{ entreePrinc.MessageBuffer("** lecture des pressions hydrostatiques **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
};
};
// lecture eventuelle des coeffs pour les efforts hydrodynamiques
tsousMot = tsousMotref;
tsousMot.Enleve (9); // on enleve "P_HYDRODYNA"
lecPHydrodyna.Lecture(entreePrinc,lesRef,"P_HYDRODYNA",
"lecture des pressions hydrodynamique",coefHydroDyna,tsousMot,false);
// initialisation éventuelle
int tai= coefHydroDyna.Taille(); for (int i=1;i<=tai;i++)
{ if (!(coefHydroDyna(i).Mise_en_place_des_courbes(lesCourbes1D))) // mise en place et test
{ entreePrinc.MessageBuffer("** lecture des pressions hydrodynamiques **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
};
};
// lecture eventuelle des forces linéique uniformement reparti
tsousMot = tsousMotref;
tsousMot.Enleve (6); // on enleve "LINEIQUE"
lecVecType.Lecture(entreePrinc,lesRef,"LINEIQUE",
"lecture des forces lineique uniformement reparti",tabFlineique,tsousMot,false);
// lecture eventuelle des forces linéique uniformement reparti suiveuses
tsousMot = tsousMotref;
tsousMot.Enleve (8); // on enleve "LINEIC_SUIVEUSE"
lecVecType.Lecture(entreePrinc,lesRef,"LINEIC_SUIVEUSE",
"lecture des forces lineique suiveuses uniformement reparti",tabFlineiqueSuiv,tsousMot,false);
// lecture eventuelle des forces volumiques
tsousMot = tsousMotref;
tsousMot.Enleve (7); // on enleve "VOLUMIQUE"
lecVecType.Lecture(entreePrinc,lesRef,"VOLUMIQUE",
"lecture des forces volumique",tabFvol,tsousMot,false);
// lecture eventuelle des torseurs de forces ponctuelles
tsousMot = tsousMotref;
tsousMot.Enleve (10); // on enleve "TORSEUR_PONCT"
lecPTorseurPonct.Lecture(entreePrinc,lesRef,"TORSEUR_PONCT",
"lecture des torseurs de forces ponctuelles ",tabTorseurPonct,tsousMot,false);
string sortie(entreePrinc.tablcar); // pour eviter la boucle infini
if (inter == sortie)
{avance = false;
cout << " erreur dans la lecture des chargements, on ne trouve pas"
<< " de sous mot cle";
entreePrinc.MessageBuffer("** lecture des divers chargements **");
Affiche1();
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
}
}
}
if (ParaGlob::NiveauImpression() >= 4)
cout << " fin de la lecture du chargement " << endl;
// on dimensionne certains tableaux de travail
int taille_tors = tabTorseurPonct.Taille();
tab_P.Change_taille(taille_tors);
t_force.Change_taille(taille_tors);
};
// lecture du type d'application du chargement
void Charge::Lecture2(UtilLecture & entreePrinc,LesCourbes1D& lesCourbes1D
,LesFonctions_nD& lesFonctionsnD)
{ if (ParaGlob::NiveauImpression() >= 4)
cout << " debut de la lecture du type d'application du chargement " << endl;
MotCle motCle; // ref aux mots cle
while ( !motCle.SimotCle(entreePrinc.tablcar))
entreePrinc.NouvelleDonnee();
if (strstr(entreePrinc.tablcar,"typecharge")!=NULL)
{ entreePrinc.NouvelleDonnee();
*(entreePrinc.entree) >> nomtypeCharge;
if (nomtypeCharge == "TYPE1")
{ tabType.Change_taille(1);
*(entreePrinc.entree) >> tabType(1);
// verif de la coherence des donnees
if ( (Dabs(tabType(1)) <= ConstMath::trespetit) )
{ cout << " \n erreur : type de chargement 1, le temps final lu "
<< tabType(1) << " est trop petit " ;
entreePrinc.MessageBuffer("** lecture du type d\'application du chargement **");
Affiche2();
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
}
}
else if (nomtypeCharge == "TYPE2")
{ tabType.Change_taille(2);
for (int i=1; i<=2; i++)
*(entreePrinc.entree) >> tabType(i);
// verif de la coherence des donnees
if ( (Dabs(tabType(1)) <= ConstMath::trespetit) )
{ cout << " \n erreur : type de chargement 2, le temps t1 lu "
<< tabType(1) << " est trop petit " ;
entreePrinc.MessageBuffer("** lecture du type d\'application du chargement **");
Affiche2();
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
}
if ( (Dabs(tabType(2)) <= ConstMath::trespetit) )
{ cout << " \n erreur : type de chargement 2, le temps t2 lu "
<< tabType(2) << " est trop petit " ;
entreePrinc.MessageBuffer("** lecture du type d\'application du chargement **");
Affiche2();
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
}
}
else if (nomtypeCharge == "TYPE3")
{ // rien à faire
}
else if ((nomtypeCharge == "TYPE4") || (nomtypeCharge == "TYPE5"))
{ // cas d'une courbe de charge donnée par une courbe1D
string nom;
*(entreePrinc.entree) >> nom; // lecture du nom de la courbe
// on regarde si la courbe existe, si oui on récupère la référence
if (lesCourbes1D.Existe(nom))
{ f_charge = lesCourbes1D.Trouve(nom);
interne_f_charge = false;
}
else
{ // sinon il faut la lire maintenant
string non_courbe("_");
f_charge = Courbe1D::New_Courbe1D(non_courbe,Id_Nom_Courbe1D (nom.c_str()));
// lecture de la courbe
f_charge->LectDonnParticulieres_courbes (non_courbe,&entreePrinc);
interne_f_charge = true;
};
// dans le cas ou le type est 5, on vérifie que la courbe est de type de liste de points
if (nomtypeCharge == "TYPE5")
{ if ( (f_charge->Type_courbe() != COURBEPOLYLINEAIRE_1_D)
&& (f_charge->Type_courbe() != CPL1D))
{cout << "\n **** erreur en lecture de la courbe de charge associee au type TYPE5"
<< "\n la courbe doit etre de type poly-lineaire classique ou simplifie (cf. doc) ";
entreePrinc.MessageBuffer("** erreur en lecture du type de chargement **");
throw (UtilLecture::ErrNouvelleDonnee(-1));
Sortie (1);
};
};
}
else if (nomtypeCharge == "TYPE6")
{ entreePrinc.NouvelleDonnee();
typedef double inter ;
list lili;
inter t1,t2;
while ( !motCle.SimotCle(entreePrinc.tablcar))
{ *(entreePrinc.entree) >> t1 >> t2;
lili.push_back(t1);
lili.push_back(t2);
entreePrinc.NouvelleDonnee();
}
// enregistrement des infos
tabType.Change_taille((int) lili.size());
list ::iterator i;
int j;
for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++)
tabType(j) = (*i);
}
else if (nomtypeCharge == "TYPE7")
{ entreePrinc.NouvelleDonnee();
typedef double inter ;
list lili;
inter t1,t2;
while ( !motCle.SimotCle(entreePrinc.tablcar))
{ *(entreePrinc.entree) >> t1 >> t2;
lili.push_back(t1);
lili.push_back(t2);
entreePrinc.NouvelleDonnee();
}
// enregistrement des infos
tabType.Change_taille((int) lili.size());
list ::iterator i;
int j;
for (i=lili.begin(),j=1 ; i != lili.end(); i++,j++)
tabType(j) = (*i);
}
}
else
{ if (ParaGlob::NiveauImpression() >= 4)
{ cout << " \n warning : pas de mot cle typecharge, utilisation des valeurs par defaut ";
Affiche2();}
}
if (ParaGlob::NiveauImpression() >= 4)
cout << " fin de la lecture du du type d'application du chargement " << endl;
};
// initialisation du chargement
// on verifie egalement la bonne adequation des references
void Charge::Initialise(LesMaillages * lesmail,LesReferences* lesRef,ParaAlgoControle& pa
,const LesCourbes1D& lesCourbes1D,const LesFonctions_nD& lesFonctionsnD)
{ // initialisation des parametres temps
paAlgo = & pa; // paAlgo->Multiplicateur()
//-// deltatmaxi = pa.Deltatmaxi() ; // increment de temps maxi
//-// prectemps = pa.Prectemps(); // precision sur le temps final
//-// deltat = pa.Deltat(); // increment de temps
//-// tempsfin = pa.Tempsfin(); // temps de fin de calcul
//-// maxincre = pa.Maxincre(); // maximum d'increments de temps
//-// max_essai_incre = pa.Max_essai_incre(); // maximum de tentatives d'increments de temps
//-// multiplicateur = pa.Multiplicateur(); // multiplicateur de la charge
// initialisation des pointeurs de fonction
if (nomtypeCharge == "TYPE1")
{ PtDebut = &Charge::Debut1;
PtAvance = &Charge::Avance1;
PtPrecedent = &Charge::Precedent1;
PtFin = &Charge::Fin1;
}
else if (nomtypeCharge == "TYPE2")
{ PtDebut = &Charge::Debut2;
PtAvance = &Charge::Avance2;
PtPrecedent = &Charge::Precedent2;
PtFin = &Charge::Fin2;
}
else if (nomtypeCharge == "TYPE3")
{ PtDebut = &Charge::Debut3;
PtAvance = &Charge::Avance3;
PtPrecedent = &Charge::Precedent3;
PtFin = &Charge::Fin3;
}
else if (nomtypeCharge == "TYPE4")
{ PtDebut = &Charge::Debut4;
PtAvance = &Charge::Avance4;
PtPrecedent = &Charge::Precedent4;
PtFin = &Charge::Fin4;
}
else if (nomtypeCharge == "TYPE5")
{ PtDebut = &Charge::Debut5;
PtAvance = &Charge::Avance5;
PtPrecedent = &Charge::Precedent5;
PtFin = &Charge::Fin5;
}
else if (nomtypeCharge == "TYPE6")
{ PtDebut = &Charge::Debut6;
PtAvance = &Charge::Avance6;
PtPrecedent = &Charge::Precedent6;
PtFin = &Charge::Fin6;
}
else if (nomtypeCharge == "TYPE7")
{ PtDebut = &Charge::Debut7;
PtAvance = &Charge::Avance7;
PtPrecedent = &Charge::Precedent7;
PtFin = &Charge::Fin7;
}
else
{ cout << "\n cas non prevu, ne devrait pas arriver, nomtypeCharge = ";
cout << nomtypeCharge << ", void Charge::Initialise(ParaAlgoControle& pa) " << endl;
Sortie (1);
}
// appel de la fonction ad hoc
coeff = 0.; // charge courante a priori, en fait si type3 elle vaut 1 tout le temps, même au début
(this->*PtDebut)();
// ==== verification des references ===
// --- cas des forces ponctuelles
// on parcours le tableau tabPonctuel
for (int i=1;i<= tabPonctuel.Taille();i++)
{ // recup de la reference correspondant au mot cle
const Reference& ref = lesRef->Trouve(tabPonctuel(i).NomRef(),tabPonctuel(i).NomMaillage());
const ReferenceNE & refN = ((ReferenceNE &) ref);
if (ref.Indic() != 1)
// cas où la référence ne correspond pas à des noeuds
{ cout << "\n ERREUR la reference: " << ref.Nom()
<< " ne correspond pas a des noeuds !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... "
<< "\n cas des forces ponctuelles " << endl;
Sortie (1);
}
// dans le cas où il s'agit d'une ref relative à un champ, on vérifie que le nombre
// de valeurs enregistrées correspond bien au nombre de noeuds
if (tabPonctuel(i).Champ() != 0)
{ if (tabPonctuel(i).DimVect() != refN.Taille())
{ cout << "\n ERREUR la reference: " << ref.Nom()
<< " contiens "<Trouve(tabFsurfac(i).NomRef(),tabFsurfac(i).NomMaillage());
if ( ((refi.Indic() != 3)&& (ParaGlob::Dimension() == 3))
|| ((refi.Indic() != 3)&&(refi.Indic() != 4)&&(ParaGlob::Dimension() == 2))
|| (ParaGlob::Dimension() == 1))
// cas d'element
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des frontieres d'element,"
<< " ce qui est necessaire pour les chargements surfacique !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
}
const ReferenceAF & ref = ((ReferenceAF &) refi);
// Maintenant il faut vérifier que les surfaces en question sont possible pour l'élément
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
{ // on regarde si l'on est en 2D ou en 3D
bool surface_existe = false;
if (ParaGlob::Dimension() == 3)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).SurfExiste(ref.NumeroFA(ns));
else if (ParaGlob::Dimension() == 2)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).AreteExiste(ref.NumeroFA(ns));
if (!surface_existe)
{ cout << "\n ERREUR l'enregistrement " <Trouve(tabPresUnif(i).NomRef(),tabPresUnif(i).NomMaillage());
if ( ( ((refi.Indic() != 3)&& (ParaGlob::Dimension() == 3)) // ce n'est pas une surface et on est en dim 3
// et ce n'est pas : une arête + dim 3 + axisymétrie
&& !((refi.Indic() == 4)&&((ParaGlob::Dimension() == 3)&&(ParaGlob::AxiSymetrie())))
)
|| ((refi.Indic() != 3)&&(refi.Indic() != 4)&&(ParaGlob::Dimension() == 2))
|| (ParaGlob::Dimension() == 1))
// cas d'element
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des frontieres surfaciques d'element,"
<< " ce qui est necessaire pour les chargements de pression !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
}
const ReferenceAF & ref = ((ReferenceAF &) refi);
// Maintenant il faut vérifier que les surfaces en question sont possible pour l'élément
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
{ // on regarde si l'on est en 2D ou 2D axisymétrique ou en 3D,
bool surface_existe = false;
if ( (ParaGlob::Dimension() == 2)
|| ((ParaGlob::Dimension() == 3)&&(ParaGlob::AxiSymetrie())))
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).AreteExiste(ref.NumeroFA(ns));
else if (ParaGlob::Dimension() == 3)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).SurfExiste(ref.NumeroFA(ns));
if (!surface_existe)
{ cout << "\n ERREUR l'enregistrement " <Trouve(PresUniDir(i).NomRef(),PresUniDir(i).NomMaillage());
if ( ((refi.Indic() != 3)&& (ParaGlob::Dimension() == 3))
|| ((refi.Indic() != 3)&&(refi.Indic() != 4)&&(ParaGlob::Dimension() == 2))
|| (ParaGlob::Dimension() == 1))
// cas d'element
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des frontieres surfaciques d'element,"
<< " ce qui est necessaire pour les chargements de pression unidirectionnelle!!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
}
const ReferenceAF & ref = ((ReferenceAF &) refi);
// a priori pour l'instant ce type de chargement n'est valide que pour la 3D, et plus
// non axisymétrique. On laisse cependant les tests pour les autres dimensions, au cas où
// plus-tard on change d'avis
if (ParaGlob::Dimension() !=3)
{ cout << "\n ERREUR: a priori le type de chargement suiveur en surfacique ne s'utilise que dans "
<< " un espace de travail 3D (classique), pour les autres dimensions il existe des chargements"
<< " equivalents specifiques : cf. la documentation ! ";
cout << "\n ==== reference du chargement: " << ref.Nom();
Sortie (1);
}
else if (ParaGlob::AxiSymetrie())
{ cout << "\n ERREUR: le type de chargement suiveur en surfacique ne s'utilise que dans "
<< " un espace de travail 3D (classique), en axisymetrique il existe des chargements"
<< " equivalents specifiques : cf. la documentation ! ";
cout << "\n ==== reference du chargement: " << ref.Nom();
Sortie (1);
};
// Maintenant il faut vérifier que les surfaces en question sont possible pour l'élément
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
{ // on regarde si l'on est en 2D ou en 3D
bool surface_existe = false;
if (ParaGlob::Dimension() == 3)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).SurfExiste(ref.NumeroFA(ns));
else if (ParaGlob::Dimension() == 2)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).AreteExiste(ref.NumeroFA(ns));
if (!surface_existe)
{ cout << "\n ERREUR l'enregistrement " <Trouve(PresHydro(i).NomRef(),PresHydro(i).NomMaillage());
if ( ( ((refi.Indic() != 3)&& (ParaGlob::Dimension() == 3)) // ce n'est pas une surface et on est en dim 3
// et ce n'est pas : une arête + dim 3 + axisymétrie
&& !((refi.Indic() == 4)&&((ParaGlob::Dimension() == 3)&&(ParaGlob::AxiSymetrie())))
)
|| ((refi.Indic() != 3)&&(refi.Indic() != 4)&&(ParaGlob::Dimension() == 2))
|| (ParaGlob::Dimension() == 1))
// cas d'element
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des frontieres surfaciques d'element,"
<< " ce qui est necessaire pour les chargements surfacique hydrostatique!!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
};
const ReferenceAF & ref = ((ReferenceAF &) refi);
// Maintenant il faut vérifier que les surfaces en question sont possible pour l'élément
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
{ // on regarde si l'on est en 2D ou en 3D
bool surface_existe = false;
if ( (ParaGlob::Dimension() == 2)
|| ((ParaGlob::Dimension() == 3)&&(ParaGlob::AxiSymetrie())))
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).AreteExiste(ref.NumeroFA(ns));
else if (ParaGlob::Dimension() == 3)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).SurfExiste(ref.NumeroFA(ns));
if (!surface_existe)
{ cout << "\n ERREUR l'enregistrement " <Trouve(coefHydroDyna(i).NomRef(),coefHydroDyna(i).NomMaillage());
if ( ((refi.Indic() != 3)&& (ParaGlob::Dimension() == 3))
|| ((refi.Indic() != 3)&&(refi.Indic() != 4)&&(ParaGlob::Dimension() == 2))
|| (ParaGlob::Dimension() == 1))
// cas d'element
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des frontieres surfaciques d'element,"
<< " ce qui est necessaire pour les chargements hydrosdynamiques !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
}
const ReferenceAF & ref = ((ReferenceAF &) refi);
// Maintenant il faut vérifier que les surfaces en question sont possible pour l'élément
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
{ // on regarde si l'on est en 2D ou en 3D
bool surface_existe = false;
if (ParaGlob::Dimension() == 3)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).SurfExiste(ref.NumeroFA(ns));
else if (ParaGlob::Dimension() == 2)
surface_existe =
(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).AreteExiste(ref.NumeroFA(ns));
if (!surface_existe)
{ cout << "\n ERREUR l'enregistrement " <Trouve(tabFlineique(i).NomRef(),tabFlineique(i).NomMaillage());
if (refi.Indic() != 4)
// cas d'arrêtes
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des frontieres d'arête d'element,"
<< " ce qui est necessaire pour les chargements lineique !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
};
const ReferenceAF & ref = ((ReferenceAF &) refi);
// Maintenant il faut vérifier que les aretes en question sont possible pour l'élément
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
if (!(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).AreteExiste(ref.NumeroFA(ns)))
{ cout << "\n ERREUR l'enregistrement " < 0)&&(ParaGlob::Dimension() != 2)&&(!ParaGlob::AxiSymetrie()))
{ cout << "\n ERREUR la dimension est différente de 2 et il y a des forces linéiques suiveuses défini"
<< " \n ceci n'est pas possible !! (indétermination de direction)"
<< " \n Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
}
// on parcours le tableau tabFlineiqueSuiv dans le repère global
for (int i=1;i<= tabFlineiqueSuiv.Taille();i++)
{ // recup de la reference correspondant au mot cle
const Reference& refi = lesRef->Trouve(tabFlineiqueSuiv(i).NomRef(),tabFlineiqueSuiv(i).NomMaillage());
if (refi.Indic() != 4)
// cas d'arrêtes
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des frontieres d'arête d'element,"
<< " ce qui est necessaire pour les chargements lineique !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... " << endl;
Sortie (1);
}
const ReferenceAF & ref = ((ReferenceAF &) refi);
// Maintenant il faut vérifier que les aretes en question sont possible pour l'élément
int nbref = ref.Taille();
for (int ns=1;ns<= nbref;ns++)
if (!(lesmail->Element_LesMaille(ref.Nbmaille(), ref.NumeroElem(ns))).AreteExiste(ref.NumeroFA(ns)))
{ cout << "\n ERREUR l'enregistrement " <Trouve(tabFvol(i).NomRef(),tabFvol(i).NomMaillage());
if (refi.Indic() != 2)
// cas d'elements
{ cout << "\n ERREUR la reference: " << refi.Nom()
<< " ne correspond pas a des element,"
<< " ce qui est necessaire pour les chargements volumique !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... "
<< "\n cas des forces volumiques uniformes " << endl;
Sortie (1);
};
// dans le cas où il s'agit d'une ref relative à un champ, on vérifie que le nombre
// de valeurs enregistrées correspond bien au nombre d'éléments
const ReferenceNE & refE = ((ReferenceNE &) refi);
if (tabFvol(i).Champ() != 0)
{ if (tabFvol(i).DimVect() != refE.Taille())
{ cout << "\n ERREUR la reference: " << refE.Nom()
<< " contiens "<Trouve(tabTorseurPonct(i).NomRef(),tabTorseurPonct(i).NomMaillage());
//const ReferenceNE & refN = ((ReferenceNE &) ref);
if (ref.Indic() != 1)
// cas où la référence ne correspond pas à des noeuds
{ cout << "\n ERREUR la reference: " << ref.Nom()
<< " ne correspond pas a des noeuds !!";
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... "
<< "\n cas des torseurs de forces ponctuelles " << endl;
Sortie (1);
};
}
// on met à jour les fonctions nD internes si nécessaire
if (!tabTorseurPonct(i).Mise_en_place_des_fonction_nD(lesFonctionsnD))
{ cout << "\n ERREUR d'association de fonction nD: pour la condition " << tabTorseurPonct(i)
<< " revoir la mise en donnees !!";
if (ParaGlob::param->NiveauImpression() > 3)
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... "
<< "\n cas des torseurs de forces ponctuelles " << endl;
Sortie (1);
};
{ //On s'occupe maintenant des noeuds éventuellement à rattacher
// récup du nom de la ref éventuelle de noeuds pour le centre du moment
Deux_String nom_ref = tabTorseurPonct(i).Nom_Ref_pour_Ce();
if ( nom_ref.nom2.length())
{// cas du centre de gravité d'une référence de noeuds
int num_mail = 1; // init par défaut
if ( nom_ref.nom1.length()) // s'il y a un nom de maillage
lesmail->NumMaillage(nom_ref.nom2); // on en récupère le numéro
const Reference& ref =
((Reference &) lesRef->Trouve(nom_ref.nom2,num_mail));
if (ref.Indic() != 1)
// cas où la référence ne correspond pas à des noeuds
{ cout << "\n ERREUR la reference: " << ref.Nom()
<< " prevu pour un centre de gravite pour le calcul de torseur d'action, "
<< " ne correspond pas a des noeuds !!";
if (ParaGlob::param->NiveauImpression() > 3)
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... "
<< "\n cas des torseurs de forces ponctuelles " << endl;
Sortie (1);
};
const ReferenceNE & refN = ((ReferenceNE &) ref);
// on va constituer une liste de noeuds que l'on va transmettre au torseur
list < const Noeud * > liNoe;
int reftaille = refN.Taille();
for (int nn =1; nn<= reftaille;nn++) // nn = position des num de noeud
liNoe.push_back(&(lesmail->Noeud_LesMaille(refN.Nbmaille(),refN.Numero(nn))));
// mise en place des infos pour le centre si celui-ci dépend des noeuds
if (!tabTorseurPonct(i).Def_tab_noeud_pour_centre(liNoe))
{ cout << "\n ERREUR dans la definition du centre de ref du momemt pour la condition " << tabTorseurPonct(i)
<< " revoir la mise en donnees !!";
if (ParaGlob::param->NiveauImpression() > 3)
cout << " Charge::Initialise(LesMaillages * lesMail,etc ... "
<< "\n cas des torseurs de forces ponctuelles " << endl;
Sortie (1);
};
}
};
{//On définit des places de stockage intermédiaire pour optimiser les temps de calcul
BlocCharge< BlocDdlLim >& tabTorseurPonct_i = tabTorseurPonct(i);
const ReferenceNE & ref =
((ReferenceNE &) lesRef->Trouve(tabTorseurPonct_i.NomRef(),tabTorseurPonct_i.NomMaillage()));
int reftaille = ref.Taille();
tab_P(i).Change_taille(reftaille);
t_force(i).Change_taille(reftaille);
};
};
};
//----- lecture écriture de base info -----
// lecture base info
// = 1 : on récupère tout
// = 2 : on récupère uniquement les données variables (supposées comme telles)
void Charge::Lecture_base_info(ifstream& entr,const int cas,LesReferences& ,LesCourbes1D& lesCourbes1D
,LesFonctions_nD& lesFonctionsnD)
{switch (cas)
{ case 1 : // ------- on récupère tout -------------------------
{ cout << "== lecture du chargement \n";
string toto;entr >> toto ; // lecture en tête
string type; entr >> type; // lecture du premier type
while (type != "type_de_charge")
{ if (type == "force_volumique")
// cas des densites de force volumique dans le repère absolu
entr >> tabFvol;
if (type == "force_surfacique")
// cas des densites de force surfacique dans le repère absolu
entr >> tabFsurfac;
if (type == "force_pression_uniforme")
// cas des pressions uniformement repartis, appliquee normalement a la surface
entr >> tabPresUnif;
if (type == "forces_ponctuelles")
// cas des forces ponctuelles sur un noeud
entr >> tabPonctuel;
if (type == "pression_unidirectionnelle")
// pression unidirectionnelle type pression dynamique des fluides
entr >> PresUniDir;
if (type == "pression_hydrostatique")
// pression hydrostatique
entr >> PresHydro;
if (type == "pression_hydrodynamique")
// pression hydrodynamique
entr >> coefHydroDyna;
if (type == "forces_lineiques")
// densite de force lineique dans le repère absolu
entr >> tabFlineique;
if (type == "forces_lineiques_suiveuses")
// densite de force lineique suiveuse
entr >> tabFlineiqueSuiv;
if (type == "torseurs_forces_ponctuelles" )
// densite de torseurs de forces ponctuelles
entr >> tabTorseurPonct;
entr >> type;
}
// type d'application du chargement
entr >> nomtypeCharge;
int tabType_taille;
entr >> toto >> tabType_taille;
tabType.Change_taille(tabType_taille);
for (int i=1;i<= tabType_taille;i++)
entr >> tabType(i);
// cas particulier d'une fonction de charge
if ((nomtypeCharge == "TYPE4") || (nomtypeCharge == "TYPE5"))
{ string nom; entr >> nom;
if (nom != " fonction_de_charge: ")
{ cout << "\n erreur en lecture de la fonction de charge, "
<< " on attendait fonction_de_charge: et on a lue " << nom
<< "\n Charge::Lecture_base_info(...";
Sortie(1);
};
f_charge = lesCourbes1D.Lecture_pour_base_info(entr,cas,f_charge);
{if (f_charge->NomCourbe() == "_") interne_f_charge=true; else interne_f_charge=false;};
};
// on lit éventuellement les paramètres particuliers de gestion des types de chargement
if (nomtypeCharge == "TYPE5")
entr >> toto >> num_pt_courant_type5;
// on écrit le type de gestion du temps fin
entr >> toto >> temps_fin_non_stricte;
break;
}
case 2 : // ----------- lecture uniquement de se qui varie --------------------
{
// le parametre global d'avancement de la charge
string toto;
entr >> toto; // lecture de l'entête
// compteur_essai_increment d'increment
entr >> toto >> compteur_essai_increment;
// multi = l'increment courant de multiplication de la charge
// coeff = niveau actuel de la charge
entr >> toto >> multi >> coeff;
// on lit également le numéro du type pour la gestion éventuelle de reprise
// avec des types différents
short int numtype; entr >> numtype;
if ((numtype != 5) && (nomtypeCharge == "TYPE5"))
{ // cas d'une reprise avec le type 5, à la suite d'un autre type -> a priori impossible
cout << "\n erreur en restart !! on ne peut pas redemarrer avec le type 5 de chargement "
<< " a la suite d'un autre type !! ";
if (ParaGlob::NiveauImpression() >= 4){ cout << "\n Charge::Lecture_base_info(.... ";};
Sortie(1);
};
// on lit éventuellement les paramètres particuliers de gestion des types de chargement
if (nomtypeCharge == "TYPE5")
entr >> toto >> num_pt_courant_type5;
// temps cpu
entr >> toto >> temps_cpu_chargement;
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
cout << "Charge::Lecture_base_info(ifstream& entr,const int cas)"
<< " cas= " << cas << endl;
Sortie(1);
}
};
};
// écriture base info
// = 1 : on sauvegarde tout
// = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
void Charge::Ecriture_base_info(ofstream& sort,const int cas)
{switch (cas)
{ case 1 : // ------- on sauvegarde tout -------------------------
{ sort << "\n ****chargement \n" ;
// cas des densites de force volumique dans le repère absolu
if (tabFvol.Taille() != 0)
sort << " force_volumique " << tabFvol;
// cas des densites de force surfacique dans le repère absolu
if (tabFsurfac.Taille() != 0)
sort << " force_surfacique " << tabFsurfac;
// cas des pressions uniformement repartis, appliquee normalement a la surface
if (tabPresUnif.Taille() != 0)
sort << " force_pression_uniforme " << tabPresUnif;
// cas des forces ponctuelles sur un noeud
if (tabPonctuel.Taille() != 0)
sort << " forces_ponctuelles " << tabPonctuel;
// pression unidirectionnelle type pression dynamique des fluides
if (PresUniDir.Taille() != 0)
sort << " pression_unidirectionnelle " << PresUniDir;
// pression hydrostatique
if (PresHydro.Taille() != 0)
sort << " pression_hydrostatique " << PresHydro;
// pression hydrodynamique
if (coefHydroDyna.Taille() != 0)
sort << " pression_hydrodynamique " << coefHydroDyna;
// densite de force lineique dans le repère absolu
if (tabFlineique.Taille() != 0)
sort << " forces_lineiques " << tabFlineique;
// densite de force lineique suiveuses
if (tabFlineiqueSuiv.Taille() != 0)
sort << " forces_lineiques_suiveuses " << tabFlineiqueSuiv;
// densite de torseurs de forces ponctuelles
if (tabTorseurPonct.Taille() != 0)
sort << " torseurs_forces_ponctuelles " << tabTorseurPonct;
// type d'application du chargement
sort << " type_de_charge " << nomtypeCharge;
int tabType_taille = tabType.Taille();
sort << " parametres " << tabType_taille;
for (int i=1;i<= tabType_taille;i++)
sort << " " << tabType(i);
// cas particulier d'une fonction de charge
if ((nomtypeCharge == "TYPE4") || (nomtypeCharge == "TYPE5"))
{ sort << " fonction_de_charge: " ;
LesCourbes1D::Ecriture_pour_base_info(sort,cas,f_charge);
}
// on écrit également les paramètres particuliers de gestion des types de chargement
if (nomtypeCharge == "TYPE5")
sort << " para_type5 " << num_pt_courant_type5 << " ";
// on écrit le type de gestion du temps fin
sort << "\n gestion_temps_fin " << temps_fin_non_stricte;
break;
}
case 2 : // ----------- sauvegarde uniquement de se qui varie --------------------
{
// le parametre global d'avancement de la charge
// sort << "\n temps " << temps << " ";
// compteur_essai_increment d'increment
sort << "\n ****chargement " ;
sort <<"\n compteur_essai_increment " << compteur_essai_increment << " ";
// multi = l'increment courant de multiplication de la charge
// coeff = niveau actuel de la charge
sort << "\n multi_et_coeff " << multi << " " << coeff << " ";
// on sort également le numéro du type pour la gestion éventuelle de reprise
// avec des types différents
sort << nomtypeCharge.substr(4,nomtypeCharge.length()-4) << " ";
if (nomtypeCharge == "TYPE5")
{sort << " para_type5 " << num_pt_courant_type5 << " ";};
// else { sort << "---" << 0 ; }; // de manière à ne pas avoir de pb si on change
// temps cpu
sort << "\n temps_cpu_charge: "<< temps_cpu_chargement;
break;
}
default :
{ cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
cout << "Charge::Ecriture_base_info(ofstream& sort,const int cas)"
<< " cas= " << cas << endl;
Sortie(1);
}
};
};
#ifdef UTILISATION_MPI
// transfert du second membre "SM_transfert" et mise à jour
// de l'index des tableaux "index_transfert" par rotation cyclique
// NB: tous les tableaux doivent avoir la même taille
void Charge::Transfert_SM(bool& premier_passage,
const int& tyfront,
const int& num_front,
Vecteur & SM_transfert,
int& index_transfert,
const int & numail,
const int & numelem
)
{
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier
mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier
int taille_tableau = tab_six_faux_entiers.Taille();
// on récupère un signal du process 0
if (premier_passage) {premier_passage = false;}
else // on regarde l'activité , car au début avant le balayage de tous les éléments des tableaux
{if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés
if (reqs2.active()) reqs2.wait(); // car aucun transfert n'a encore été effectué
};
temps_attente.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier
six_faux_entiers(1) = (double) numelem;
six_faux_entiers(2) = (double) numail;
six_faux_entiers(3) = (double) tyfront;
six_faux_entiers(4) = (double) num_front;
six_faux_entiers(5) = (double) SM_transfert.Taille();
six_faux_entiers(6) = (double) index_transfert;
// on transmet les numéros d'élément et de maillage etc.
reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34);
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
// puis on transmets le vecteur résidu sauf si tyfront est négatif
if (tyfront > 0)
{temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM_transfert.Ienvoi_MPI(0,35);
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
// // debug
// cout << "\n debug Charge::Transfert_SM( proc= "<< ParaGlob::Monde()->rank()
// << " six_faux_entiers= " << six_faux_entiers
// << " SM_transfert= " << SM_transfert << flush;
// // fin debug
};
// ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore
// en transfert vers le proc 0
index_transfert++;
if (index_transfert > taille_tableau) // on fait une permutation circulaire
index_transfert = 1;// on revient au premier élément des tableaux de transfert
};
// transfert du second membre "SM_transfert" et de la matrice "MAT_transfert" et mise à jour
// de l'index des tableaux "index_transfert" par rotation cyclique
// NB: tous les tableaux doivent avoir la même taille
void Charge::Transfert_MatSm(bool& premier_passage,
const int& tyfront,
const int& num_front,
Vecteur & SM_transfert,
Mat_pleine * MAT_transfert,
int& index_transfert,
const int & numail,
const int & numelem
)
{
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
mpi::request & reqs1 = tab_reqs1(index_transfert); // pour simplifier
mpi::request & reqs2 = tab_reqs2(index_transfert); // pour simplifier
mpi::request & reqs3 = tab_reqs3(index_transfert); // pour simplifier
int taille_tableau = tab_six_faux_entiers.Taille();
// on récupère un signal du process 0
if (premier_passage) {premier_passage = false;}
else // on regarde l'activité , car au début avant le balayage de tous les éléments des tableaux
{if (reqs1.active()) reqs1.wait(); // les requests ne sont pas alimentés
if (reqs2.active()) reqs2.wait(); // car aucun transfert n'a encore été effectué
if (reqs3.active()) reqs3.wait(); // car aucun transfert n'a encore été effectué
};
temps_attente.Arret_du_comptage(); // fin comptage cpu
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
Vecteur& six_faux_entiers = tab_six_faux_entiers(index_transfert); // pour simplifier
six_faux_entiers(1) = (double) numelem;
six_faux_entiers(2) = (double) numail;
six_faux_entiers(3) = (double) tyfront;
six_faux_entiers(4) = (double) num_front;
six_faux_entiers(5) = (double) SM_transfert.Taille();
six_faux_entiers(6) = (double) index_transfert;
// on transmet les numéros d'élément et de maillage etc.
reqs1 = six_faux_entiers.Ienvoi_MPI(0, 34);
// // debug
// cout << "\n debug Charge::Transfert_SM( proc= "<< ParaGlob::Monde()->rank()
// << " six_faux_entiers= " << six_faux_entiers
// << " SM_transfert= " << SM_transfert << flush;
// // fin debug
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
// puis on transmets le vecteur résidu
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
reqs2 = SM_transfert.Ienvoi_MPI(0,35);
// puis on transmets éventuellementla matrice de raideur
if (MAT_transfert != NULL)
reqs3 = MAT_transfert->Ienvoi_MPI(0,36);
// ici on utilise un nouveau élément de tableau pour éviter d'écraser la précédente version qui peut être encore
// en transfert vers le proc 0
index_transfert++;
if (index_transfert > taille_tableau) // on fait une permutation circulaire
index_transfert = 1;// on revient au premier élément des tableaux de transfert
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
};
#endif