// 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(istream& 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(istream& 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(ostream& 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(ostream& 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 temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu // puis on transmets le vecteur résidu sauf si tyfront est négatif if (tyfront > 0) {reqs2 = SM_transfert.Ienvoi_MPI(0,35); // // 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 temps_transfert_long.Arret_du_comptage(); // fin comptage cpu }; // 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(); int indique_matrice = (MAT_transfert != NULL); six_faux_entiers(6) = (double) indique_matrice; // 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 temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu // puis on transmets le vecteur résidu sauf si tyfront est négatif if (tyfront > 0) {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