2021-09-26 14:31:23 +02:00
|
|
|
// This file is part of the Herezh++ application.
|
|
|
|
//
|
|
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
|
|
// of mechanics for large transformations of solid structures.
|
|
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
|
|
//
|
|
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
|
|
//
|
2023-05-03 17:23:49 +02:00
|
|
|
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
|
2021-09-26 14:31:23 +02:00
|
|
|
// AUTHOR : Gérard Rio
|
|
|
|
// E-MAIL : gerardrio56@free.fr
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
|
|
// or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
// See the GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
//
|
|
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
|
|
|
|
|
|
|
|
#include "AlgoRungeKutta.h"
|
|
|
|
|
|
|
|
// CONSTRUCTEURS :
|
|
|
|
AlgoriRungeKutta::AlgoriRungeKutta () : // par defaut
|
|
|
|
Algori()
|
|
|
|
,delta_t(),unsurdeltat(),deltatSurDeux(),deltat2()
|
|
|
|
,maxPuissExt(),maxPuissInt(),maxReaction(),inReaction(),inSol(),maxDeltaDdl()
|
|
|
|
,cas_combi_ddl(),icas(),erreurSecondMembre(false),prepa_avec_remont(false)
|
|
|
|
,brestart(false),type_incre(OrdreVisu::PREMIER_INCRE)
|
|
|
|
,lesMail_(NULL),lesRef_(NULL),lesCourbes1D_(NULL),lesFonctionsnD_(NULL),charge_(NULL)
|
|
|
|
,lesCondLim_(NULL),lesContacts_(NULL),Ass1(NULL),Ass2(NULL),Ass3(NULL)
|
|
|
|
,vglobin(),vglobex(),vglobaal(),vcontact()
|
|
|
|
,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
|
|
|
|
,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_masse_sauve(NULL),mat_C_pt(NULL)
|
|
|
|
,cas_kutta(5),erreurAbsolue(1.e-3),erreurRelative(1.e-5),nbMaxiAppel(2000),erreur_maxi_global(0.)
|
|
|
|
,pilotage_un_step(false),estime_erreur(0)
|
|
|
|
,val_fonc_initiale(0),der_val_fonc_initiale(0),val_fonc(0),der_val_fonc(0)
|
|
|
|
,val_fonc_final(0),der_val_fonc_final(0),scale_fac()
|
|
|
|
{ //vglobal = &vglobin;
|
|
|
|
// message d'erreur
|
|
|
|
cout << "\n constructeur par defaut de AlgoriRungeKutta, ne doit pas etre utilise !!";
|
|
|
|
Sortie(1);};
|
|
|
|
|
|
|
|
// constructeur en fonction du type de calcul et du sous type
|
|
|
|
// il y a ici lecture des parametres attaches au type
|
|
|
|
AlgoriRungeKutta::AlgoriRungeKutta (const bool avec_typeDeCal
|
|
|
|
,const list <EnumSousTypeCalcul>& soustype
|
|
|
|
,const list <bool>& avec_soustypeDeCal
|
|
|
|
,UtilLecture& entreePrinc) :
|
|
|
|
Algori(DYNA_RUNGE_KUTTA,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
|
|
|
|
,delta_t(0.),unsurdeltat(0.),deltatSurDeux(0.),deltat2(0.)
|
|
|
|
,maxPuissExt(0.),maxPuissInt(0.),maxReaction(0.),inReaction(0),inSol(0.),maxDeltaDdl(0.)
|
|
|
|
,cas_combi_ddl(0),icas(),erreurSecondMembre(false),prepa_avec_remont(false)
|
|
|
|
,brestart(false),type_incre(OrdreVisu::PREMIER_INCRE)
|
|
|
|
,lesMail_(NULL),lesRef_(NULL),lesCourbes1D_(NULL),lesFonctionsnD_(NULL),charge_(NULL)
|
|
|
|
,lesCondLim_(NULL),lesContacts_(NULL),Ass1(NULL),Ass2(NULL),Ass3(NULL)
|
|
|
|
,vglobin(),vglobex(),vglobaal(),vcontact()
|
|
|
|
,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
|
|
|
|
,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_masse_sauve(NULL),mat_C_pt(NULL)
|
|
|
|
,cas_kutta(5),erreurAbsolue(1.e-3),erreurRelative(1.e-5),nbMaxiAppel(2000),erreur_maxi_global()
|
|
|
|
,pilotage_un_step(false),estime_erreur(0)
|
|
|
|
,val_fonc_initiale(0),der_val_fonc_initiale(0),val_fonc(0),der_val_fonc(0)
|
|
|
|
,val_fonc_final(0),der_val_fonc_final(0),scale_fac(0.)
|
|
|
|
{ //vglobal = &vglobin;
|
|
|
|
// lecture des paramètres attachés au type de calcul
|
|
|
|
switch (entreePrinc.Lec_ent_info())
|
|
|
|
{ case 0 :
|
|
|
|
{lecture_Parametres(entreePrinc); break;}
|
|
|
|
case -11 : // cas de la création d'un fichier de commande
|
|
|
|
{ Info_commande_parametres(entreePrinc); break;}
|
|
|
|
case -12 : // cas de la création d'un schéma XML, on ne fait rien à ce niveau
|
|
|
|
{ break;}
|
|
|
|
default:
|
|
|
|
Sortie(1);
|
|
|
|
}
|
|
|
|
// paramètre kutta
|
|
|
|
alg_edp.Modif_nbMaxiAppel(nbMaxiAppel);
|
|
|
|
};
|
|
|
|
|
|
|
|
// constructeur de copie
|
|
|
|
AlgoriRungeKutta::AlgoriRungeKutta (const AlgoriRungeKutta& algo):
|
|
|
|
Algori(algo)
|
|
|
|
,delta_t(0.),unsurdeltat(0.),deltatSurDeux(0.),deltat2(0.)
|
|
|
|
,maxPuissExt(0.),maxPuissInt(0.),maxReaction(0.),inReaction(0),inSol(0.),maxDeltaDdl(0.)
|
|
|
|
,cas_combi_ddl(0),icas(0),erreurSecondMembre(false)
|
|
|
|
,prepa_avec_remont(false)
|
|
|
|
,brestart(false),type_incre(OrdreVisu::PREMIER_INCRE)
|
|
|
|
,lesMail_(NULL),lesRef_(NULL),lesCourbes1D_(NULL),lesFonctionsnD_(NULL),charge_(NULL)
|
|
|
|
,lesCondLim_(NULL),lesContacts_(NULL),Ass1(NULL),Ass2(NULL),Ass3(NULL)
|
|
|
|
,vglobin(),vglobex(),vglobaal(),vcontact()
|
|
|
|
,X_Bl(),V_Bl(),G_Bl(),forces_vis_num(0)
|
|
|
|
,li_gene_asso(),t_assemb(),tenuXVG(),mat_masse(NULL),mat_masse_sauve(NULL),mat_C_pt(NULL)
|
|
|
|
,cas_kutta(algo.cas_kutta),erreurAbsolue(algo.erreurAbsolue)
|
|
|
|
,erreurRelative(algo.erreurRelative),nbMaxiAppel(algo.nbMaxiAppel),erreur_maxi_global()
|
|
|
|
,pilotage_un_step(algo.pilotage_un_step),estime_erreur(algo.estime_erreur)
|
|
|
|
,val_fonc_initiale(algo.val_fonc_initiale),der_val_fonc_initiale(algo.der_val_fonc_initiale)
|
|
|
|
,val_fonc(algo.val_fonc),der_val_fonc(algo.der_val_fonc)
|
|
|
|
,val_fonc_final(algo.val_fonc_final),der_val_fonc_final(algo.der_val_fonc_final),scale_fac(0.)
|
|
|
|
{ //vglobal = &vglobin;
|
|
|
|
};
|
|
|
|
|
|
|
|
// destructeur
|
|
|
|
AlgoriRungeKutta::~AlgoriRungeKutta ()
|
|
|
|
{ if (mat_masse != NULL) delete mat_masse;
|
|
|
|
if (mat_masse_sauve != NULL) delete mat_masse_sauve;
|
|
|
|
if (mat_C_pt != NULL) delete mat_C_pt;
|
|
|
|
if (Ass1 != NULL) delete Ass1;
|
|
|
|
if (Ass2 != NULL) delete Ass2;
|
|
|
|
if (Ass3 != NULL) delete Ass3;
|
|
|
|
};
|
|
|
|
|
|
|
|
// execution de l'algorithme dans le cas dynamique explicite, sans contact
|
|
|
|
void AlgoriRungeKutta::Execution(ParaGlob * paraGlob,LesMaillages * lesMail
|
|
|
|
,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
|
|
|
|
,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock
|
|
|
|
,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats)
|
|
|
|
{ Tableau < Fonction_nD* > * tb_combiner = NULL; // ici ne sert pas
|
|
|
|
// on définit le type de calcul a effectuer :
|
|
|
|
if ( soustypeDeCalcul->size()==0 )
|
|
|
|
// cas où il n'y a pas de sous type, on fait le calcul d'équilibre classique
|
|
|
|
// signifie que le type principal est forcément valide
|
|
|
|
{ // initialisation du calcul : deux cas, soit avec une lecture initiale du .info, soit une lecture secondaire
|
|
|
|
if (paraGlob->EtatDeLaLecturePointInfo() == 0)
|
|
|
|
{InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );}
|
|
|
|
else {MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
};
|
|
|
|
// on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
|
|
|
|
// bref que l'on n'a pas fini, sinon on passe
|
|
|
|
if (! (charge->Fin(icharge,true) ) )
|
|
|
|
{ // calcul de l'équilibre
|
|
|
|
CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats
|
|
|
|
,tb_combiner);
|
|
|
|
// fin du calcul, pour l'instant on ne considère pas les autres sous-types
|
|
|
|
FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{if ( avec_typeDeCalcul )
|
|
|
|
// cas où le type principal est valide et qu'il y a des sous_types
|
|
|
|
{ // on regarde si le sous-type "commandeInteractive" existe, si oui on le met en place
|
|
|
|
// détermine si le sous type de calcul existe et s'il est actif
|
|
|
|
if (paraGlob->SousTypeCalcul(commandeInteractive))
|
|
|
|
{// -- cas avec commandes interactives
|
|
|
|
// initialisation du calcul : deux cas, soit avec une lecture initiale du .info, soit une lecture secondaire
|
|
|
|
if (paraGlob->EtatDeLaLecturePointInfo() == 0)
|
|
|
|
{InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
}
|
|
|
|
else {MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
};
|
|
|
|
// calcul de l'équilibre tant qu'il y a des commandes
|
|
|
|
while (ActionInteractiveAlgo())
|
|
|
|
{ // on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
|
|
|
|
// bref que l'on n'a pas fini, sinon on passe
|
|
|
|
if (! (charge->Fin(icharge,true) ) )
|
|
|
|
CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats
|
|
|
|
,tb_combiner);
|
|
|
|
};
|
|
|
|
// fin du calcul, pour l'instant on ne considère pas les autres sous-types
|
|
|
|
FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
}
|
|
|
|
else // cas sans commandes interactives
|
|
|
|
{// on fait le calcul d'équilibre
|
|
|
|
// initialisation du calcul : deux cas, soit avec une lecture initiale du .info, soit une lecture secondaire
|
|
|
|
if (paraGlob->EtatDeLaLecturePointInfo() == 0)
|
|
|
|
{InitAlgorithme(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
}
|
|
|
|
else {MiseAJourAlgo(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
};
|
|
|
|
// on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
|
|
|
|
// bref que l'on n'a pas fini, sinon on passe
|
|
|
|
if (! (charge->Fin(icharge,true) ) )
|
|
|
|
{ // calcul de l'équilibre
|
|
|
|
CalEquilibre(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats
|
|
|
|
,tb_combiner);
|
|
|
|
|
|
|
|
// fin du calcul, pour l'instant on ne considère pas les autres sous-types
|
|
|
|
FinCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,divStock,charge,lesCondLim,lesContacts,resultats );
|
|
|
|
};
|
|
|
|
// ensuite on teste en fonction des calculs complémentaires
|
|
|
|
// dépendant des sous_types. Pour l'instant ici uniquement la remontée
|
|
|
|
list <EnumSousTypeCalcul>::const_iterator ili,ili_fin = soustypeDeCalcul->end();
|
|
|
|
list <bool>::const_iterator ila;
|
|
|
|
for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin();
|
|
|
|
ili!=ili_fin;ili++,ila++)
|
|
|
|
if (*ila) // cas où le sous type est valide
|
|
|
|
{if (Remonte_in(*ili)) // on test la présence du calcul de remonté
|
|
|
|
{ // certaines initialisations sont nécessaires car c'est le premier calcul
|
|
|
|
Algori::InitRemontSigma(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
|
|
|
|
Algori::InitErreur(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
|
|
|
|
Algori::RemontSigma(lesMail);
|
|
|
|
Algori::RemontErreur(lesMail);
|
|
|
|
}
|
|
|
|
else if ( (*ili) == sauveMaillagesEnCours )
|
|
|
|
{ cout << "\n================================================================="
|
|
|
|
<< "\n| ecriture des maillages en cours en .her et .lis |"
|
|
|
|
<< "\n================================================================="
|
|
|
|
<< endl;
|
|
|
|
|
|
|
|
// ----- sort les informations sur fichiers
|
|
|
|
// Affichage des donnees des maillages dans des fichiers dont le nom est construit
|
|
|
|
// à partir du nom de chaque maillage au format ".her" et ".lis"
|
|
|
|
lesMail->Affiche_maillage_dans_her_lis(TEMPS_tdt,*lesRef);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};// fin du cas sans commandes interactives
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// cas ou le type principal n'est pas valide
|
|
|
|
// on ne fait que le calcul complémentaire
|
|
|
|
{ list <EnumSousTypeCalcul>::const_iterator ili,ili_fin = soustypeDeCalcul->end();
|
|
|
|
list <bool>::const_iterator ila;
|
|
|
|
for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin();
|
|
|
|
ili!=ili_fin;ili++,ila++)
|
|
|
|
if (*ila) // cas où le sous type est valide
|
|
|
|
{if (Remonte_in(*ili)) // on test la présence du calcul de remonté
|
|
|
|
{ // certaines initialisations sont nécessaires car c'est le premier calcul
|
|
|
|
Algori::InitRemontSigma(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
|
|
|
|
Algori::InitErreur(lesMail,lesRef,divStock,charge,lesCondLim,lesContacts,resultats);
|
|
|
|
Algori::RemontSigma(lesMail);
|
|
|
|
Algori::RemontErreur(lesMail);
|
|
|
|
}
|
|
|
|
else if ( (*ili) == sauveMaillagesEnCours )
|
|
|
|
{ cout << "\n================================================================="
|
|
|
|
<< "\n| ecriture des maillages en cours en .her et .lis |"
|
|
|
|
<< "\n================================================================="
|
|
|
|
<< endl;
|
|
|
|
|
|
|
|
// ----- sort les informations sur fichiers
|
|
|
|
// Affichage des donnees des maillages dans des fichiers dont le nom est construit
|
|
|
|
// à partir du nom de chaque maillage au format ".her" et ".lis"
|
|
|
|
lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// si on a forcé la sortie des itérations et incréments, il faut réinitialiser l'indicateur
|
|
|
|
if (!(pa.EtatSortieEquilibreGlobal()))
|
|
|
|
pa.ChangeSortieEquilibreGlobal(false);
|
|
|
|
};
|
|
|
|
|
|
|
|
// écriture des paramètres dans la base info
|
|
|
|
// = 1 : on écrit tout
|
|
|
|
// = 2 : on écrot uniquement les données variables (supposées comme telles)
|
|
|
|
void AlgoriRungeKutta::Ecrit_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas)
|
|
|
|
{ // récup du flot
|
|
|
|
ofstream& sort = *entreePrinc.Sort_BI();
|
|
|
|
// sort << "\n parametres_algo_specifiques_ "<< Nom_TypeCalcul(this->TypeDeCalcul());
|
|
|
|
switch (cas)
|
|
|
|
{case 1 : // ------- on sauvegarde tout -------------------------
|
|
|
|
{
|
|
|
|
// ecriture des parametres de réglage du pilotage de RK
|
|
|
|
sort << "\n cas_kutta= " << cas_kutta << " erreurAbsolue= " << erreurAbsolue
|
|
|
|
<< " erreurRelative= " << erreurRelative << " nbMaxiAppel= " << nbMaxiAppel
|
|
|
|
<< " pilotage_un_step= " << pilotage_un_step << " ";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2 : // ----------- on sauvegarde en minimaliste --------------------
|
|
|
|
{ // explication
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default :
|
|
|
|
{ cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
|
|
|
|
cout << "AlgoriRungeKutta::Ecrit_Base_info_Parametre(UtilLecture& ,const int& )"
|
|
|
|
<< " cas= " << cas << endl;
|
|
|
|
Sortie(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// sort << "\n fin_parametres_algo_specifiques_ ";
|
|
|
|
};
|
|
|
|
|
|
|
|
// lecture des paramètres dans la base info
|
|
|
|
// = 1 : on récupère tout
|
|
|
|
// = 2 : on récupère uniquement les données variables (supposées comme telles)
|
|
|
|
// choix = true : fonctionememt normal
|
|
|
|
// choix = false : la méthode ne doit pas lire mais initialiser les données à leurs valeurs par défaut
|
|
|
|
// car la lecture est impossible
|
|
|
|
void AlgoriRungeKutta::Lecture_Base_info_Parametre(UtilLecture& entreePrinc,const int& cas,bool choix)
|
|
|
|
{// récup du flot
|
|
|
|
ifstream& ent = *entreePrinc.Ent_BI();
|
|
|
|
string toto;
|
|
|
|
if (choix)
|
|
|
|
{switch (cas)
|
|
|
|
{case 1 : // ------- on récupère tout -------------------------
|
|
|
|
{
|
|
|
|
// lecture des parametres de réglage du pilotage de RK
|
|
|
|
ent >> toto >> cas_kutta >> toto >> erreurAbsolue
|
|
|
|
>> toto >> erreurRelative >> toto >> nbMaxiAppel >> toto >> pilotage_un_step;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2 : // ----------- on récupère en minimaliste --------------------
|
|
|
|
{ break;
|
|
|
|
}
|
|
|
|
default :
|
|
|
|
{ cout << "\nErreur : valeur incorrecte du type de sauvegarde !\n";
|
|
|
|
cout << "AlgoriRungeKutta::Lecture_Base_info_Parametre(UtilLecture& ,const int& )"
|
|
|
|
<< " cas= " << cas << endl;
|
|
|
|
Sortie(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
// ici on n'initialise pas les paramètre de réglage de l'algo, car ceux sont à initialiser en lecture
|
|
|
|
// uniquement ce qui permet de les modifiers par un restart par exemple
|
|
|
|
};
|
|
|
|
|
|
|
|
// gestion et vérification du pas de temps et modif en conséquence si nécessaire
|
|
|
|
// cas = 0: premier passage à blanc, delta t = 0
|
|
|
|
// cas = 1: initialisation du pas de temps et vérif / au pas de temps critique
|
|
|
|
// ceci pour le temps t=0
|
|
|
|
// cas = 2: initialisation du pas de temps et vérif / au pas de temps critique
|
|
|
|
// ceci pour le temps t. et on divise par nbstep
|
|
|
|
// ceci pour garantir que l'on fait le calcul avec 1 step
|
|
|
|
// en entrée: modif_pas_de_temps: indique qu'il y a eu par ailleurs (via Charge->Avance())
|
|
|
|
// une modification du pas de temps depuis le dernier appel
|
|
|
|
// retourne vrai s'il y a une modification du pas de temps, faux sinon
|
|
|
|
bool AlgoriRungeKutta::Gestion_pas_de_temps
|
|
|
|
(bool modif_pas_de_temps,LesMaillages * lesMail,int cas,int nbstep)
|
|
|
|
{ bool modif_deltat = modif_pas_de_temps; // booleen pour la prise en compte éventuelle de la modif du temps éventuelle
|
|
|
|
if (modif_pas_de_temps) // dans le cas où il y a eu une modification externe du pas de temps on modifie la variable interne
|
|
|
|
delta_t = pa.Deltat(); // sinon elle ne sera pas mise à jour dans l'algo
|
|
|
|
switch (cas)
|
|
|
|
{ case 0 :
|
|
|
|
{ // cas d'un passage à blanc, rien ne bouge et delta t est mis à 0
|
|
|
|
delta_t = 0.;
|
|
|
|
unsurdeltat = ConstMath::unpeugrand;deltatSurDeux = 0.;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1 :
|
|
|
|
{ // --<KUTTA>-- récup du pas de temps, proposé par l'utilisateur
|
|
|
|
// s'il n'y en a pas, c'est pas grave
|
|
|
|
delta_t = pa.Deltat(); double delta_t_old = delta_t;
|
|
|
|
double delta_tSauve = delta_t; // sauvegarde de la situation actuelle
|
|
|
|
// --<DFC>-- on calcul le pas de temps critique DFC pour cela on utilise
|
|
|
|
// les caractéristiques dynamiques d'une biellette de longueur
|
|
|
|
// valant le minimum d'un coté d'arrête
|
|
|
|
double l_sur_c = lesMail->Longueur_arrete_mini_sur_c(TEMPS_0);
|
|
|
|
double delta_t_essai = l_sur_c ;
|
|
|
|
// mise à jour éventuel du pas de temps et du pas de temps maxi et mini s'ils sont définit à partir du temps critique
|
|
|
|
modif_deltat=pa.Modif_Deltat_DeltatMaxi(l_sur_c,l_sur_c); // mais pas de test vis-a-vis des bornes
|
|
|
|
delta_t = pa.Deltat(); // récup du pas de temps
|
|
|
|
// si modif_deltat = false, rien n'a changé pour le delta_t, par contre le temps critique a peut-être bougé
|
|
|
|
// et on doit peut-être appliquer la condition de courant
|
|
|
|
// on vérifie donc la condition, mais que si l'utilisateur veut vérifier la stabilité (pa.Limit_temps_stable()), c'est le cas normal
|
|
|
|
// sinon c'est exploratoire
|
|
|
|
if (pa.Limit_temps_stable() && ( delta_t > delta_t_essai))
|
|
|
|
{ if (ParaGlob::NiveauImpression() > 0)
|
|
|
|
cout << "\n ** ATTENTION ** , l'increment de temps propose : " << delta_t
|
|
|
|
<< ", ne satisfait pas la condition de Courant (C-F-L), "
|
|
|
|
<< "\n on le regle donc pour que cette condition soit satisfaite: nouvel increment: "
|
|
|
|
<< delta_t_essai;
|
|
|
|
delta_t = delta_t_essai;
|
|
|
|
if (delta_tSauve != delta_t)
|
|
|
|
modif_deltat=true;
|
|
|
|
// modification de l'increment de temps dans les paramètres
|
|
|
|
switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1: { cout << "\n initialisation du pas de temps avec la condition de Courant impossible, le nouveau pas"
|
|
|
|
<< "\n de temps calcule est plus petit que le pas de temps mini limite: " << pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal
|
|
|
|
case 1: { pa.Modif_Detat_dans_borne(delta_t);
|
|
|
|
if (ParaGlob::NiveauImpression() > 0)
|
|
|
|
cout << "\n >>>> rectification du pas de temps "<<delta_t_old<<" dans les bornes : nouvel increment:" << delta_t;
|
|
|
|
modif_deltat=true;break;
|
|
|
|
} // cas ou on dépasse la borne maxi
|
|
|
|
default:
|
|
|
|
cout << "\n erreur7 !! cas non pris en compte : AlgoriRungeKutta::Gestion_pas_de_temps( "
|
|
|
|
<< " pa.Modif_Deltat(delta_t)= "<< pa.Modif_Deltat(delta_t) << endl;
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// sinon on regarde simplement si la modification de temps est possible
|
|
|
|
{ switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1: { cout << "\n initialisation du pas de temps impossible, le nouveau pas"
|
|
|
|
<< "\n de temps calcule est plus petit que le pas de temps mini limite: " << pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal
|
|
|
|
case 1: { pa.Modif_Detat_dans_borne(delta_t);
|
|
|
|
if (ParaGlob::NiveauImpression() > 0)
|
|
|
|
cout << "\n >>>> rectification du pas de temps "<<delta_t_old<<" dans les bornes : nouvel increment:" << delta_t;
|
|
|
|
modif_deltat=true;break;
|
|
|
|
} // cas ou on dépasse la borne maxi
|
|
|
|
default:
|
|
|
|
cout << "\n erreur !! cas non pris en compte : AlgoriRungeKutta::Gestion_pas_de_temps( "
|
|
|
|
<< " pa.Modif_Deltat(delta_t)= "<< pa.Modif_Deltat(delta_t) << endl;
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/* // vérification du pas de temps et modification de l'increment de temps dans les paramètres
|
|
|
|
switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1:
|
|
|
|
{ cout << "\n **** modification du pas de temps impossible,"
|
|
|
|
<< " le nouveau pas de temps calcule est plus petit que le pas de temps mini limite: "
|
|
|
|
<< pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal, la modification est accepté
|
|
|
|
case 1:
|
|
|
|
{ // pb de dépassement de la borne maxi
|
|
|
|
if (pa.Limit_temps_stable()) // cas où l'utilisateur impose une limite haute de stabilité
|
|
|
|
{pa.Modif_Detat_dans_borne(delta_t);}
|
|
|
|
else // cas où on est hors borne non contrôlé
|
|
|
|
{ cout << "\n ** AlgoriRungeKutta: initialisation du pas de temps non acceptee, le nouveau pas"
|
|
|
|
<< "\n de temps calcule est plus grand que le pas de temps maxi limite: " << pa.Deltatmaxi();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
modif_deltat=true; */
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
{ // calcul du pas de temps critique DFC
|
|
|
|
double l_sur_c = lesMail->Longueur_arrete_mini_sur_c(TEMPS_t);
|
|
|
|
double ancien_pas=delta_t;
|
|
|
|
double delta_t_essai = l_sur_c ;
|
|
|
|
|
|
|
|
// mise à jour éventuel du pas de temps et du pas de temps maxi s'ils sont définit à partir du temps critique
|
|
|
|
// ici il n'y a qu'un seul pas critique celui de DFC (qui n'est pas d'ailleurs forcément critique mais qui
|
|
|
|
// sert de référence, si l'on veut imposer une valeur qui s'y rattache)
|
|
|
|
bool modif = pa.Modif_Deltat_DeltatMaxi(l_sur_c,l_sur_c); // mais pas de test vis-a-vis des bornes
|
|
|
|
// s'il y a eu modif du pas de temps on met à jour le pas courant, ou plutôt on le récupère
|
|
|
|
if (modif)
|
|
|
|
{ delta_t = pa.Deltat(); modif_deltat=true;}
|
|
|
|
// maintenant on vérifie néanmoins le pas de temps choisit au cas où
|
|
|
|
// en particulier cette vérification n'est en fait pas utile si l'utilisateur
|
|
|
|
// à utilisé un facteur du pas critique < 1
|
|
|
|
if (pa.Limit_temps_stable() && ( delta_t > delta_t_essai))
|
|
|
|
{ if (pa.Coefficient_pas_critique_deltat() <= 1.)
|
|
|
|
{ delta_t = pa.Coefficient_pas_critique_deltat() * delta_t_essai;}
|
|
|
|
else { delta_t = delta_t_essai;};
|
|
|
|
// modification de l'increment de temps dans les paramètres
|
|
|
|
switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1: { cout << "\n **** modification du pas de temps impossible,"
|
|
|
|
<< " le nouveau pas de temps calcule est plus petit que le pas de temps mini limite: "
|
|
|
|
<< pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal
|
|
|
|
case 1: { pa.Modif_Detat_dans_borne(delta_t); break;} // cas ou on dépasse la borne maxi
|
|
|
|
default:
|
|
|
|
cout << "\n erreur2 !! cas non pris en compte : AlgoriRungeKutta::Gestion_pas_de_temps( "
|
|
|
|
<< " pa.Modif_Deltat(delta_t)= "<< pa.Modif_Deltat(delta_t) << endl;
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
modif_deltat=true;
|
|
|
|
}
|
|
|
|
else // sinon on regarde simplement si la modification de temps est possible
|
|
|
|
{ switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1: { cout << "\n **** modification du pas de temps impossible,"
|
|
|
|
<< " le nouveau pas de temps calcule est plus petit que le pas de temps mini limite: "
|
|
|
|
<< pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal
|
|
|
|
case 1: { pa.Modif_Detat_dans_borne(delta_t); break;} // cas ou on dépasse la borne maxi
|
|
|
|
default:
|
|
|
|
cout << "\n erreur6 !! cas non pris en compte : AlgoriRungeKutta::Gestion_pas_de_temps( "
|
|
|
|
<< " pa.Modif_Deltat(delta_t)= "<< pa.Modif_Deltat(delta_t) << endl;
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/* // vérification du pas de temps et modification de l'increment de temps dans les paramètres
|
|
|
|
switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1:
|
|
|
|
{ cout << "\n **** modification du pas de temps impossible,"
|
|
|
|
<< " le nouveau pas de temps calcule est plus petit que le pas de temps mini limite: "
|
|
|
|
<< pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal, la modification est accepté
|
|
|
|
case 1:
|
|
|
|
{ // pb de dépassement de la borne maxi
|
|
|
|
if (pa.Limit_temps_stable()) // cas où l'utilisateur impose une limite haute de stabilité
|
|
|
|
{pa.Modif_Detat_dans_borne(delta_t);}
|
|
|
|
else // cas où on est hors borne non contrôlé
|
|
|
|
{ cout << "\n ** AlgoriRungeKutta: initialisation du pas de temps non acceptee, le nouveau pas"
|
|
|
|
<< "\n de temps calcule est plus grand que le pas de temps maxi limite: " << pa.Deltatmaxi();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};*/
|
|
|
|
|
|
|
|
// --- essai de pilotage en fonction de la précision demandée ---
|
|
|
|
// cela vient en surcharge du cas précédent
|
|
|
|
delta_t_essai = delta_t; // on commence par dire que l'on veut le même pas qu'au pas précédent
|
|
|
|
if (pilotage_un_step) // cas ou l'utilisateur demande d'avoir un pas de temps qui permet d'avoir un step
|
|
|
|
{ delta_t_essai = ancien_pas / nbstep; // différent de l'ancien pas si nbstep diff de 1
|
|
|
|
// si on a un seul step et que l'erreur obtenue est bien inférieure à celle demandée on augmente le pas de temps
|
|
|
|
// au prorata
|
|
|
|
double erreur_admise = erreurAbsolue+val_fonc_final.Max_val_abs()*erreurRelative;
|
|
|
|
double coef_change_pas=0.9;
|
|
|
|
if ((erreur_maxi_global < coef_change_pas*erreur_admise ) && (nbstep==1))
|
|
|
|
delta_t_essai *= Dabs(erreur_admise/(erreur_maxi_global+ConstMath::trespetit));
|
|
|
|
// mise à jour du pas de temps
|
|
|
|
delta_t = delta_t_essai;
|
|
|
|
// vérification du pas de temps et modification de l'increment de temps dans les paramètres
|
|
|
|
switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1:
|
|
|
|
{ cout << "\n **** modification du pas de temps impossible,"
|
|
|
|
<< " le nouveau pas de temps calcule est plus petit que le pas de temps mini limite: "
|
|
|
|
<< pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal, la modification est accepté
|
|
|
|
case 1:
|
|
|
|
{ // pb de dépassement de la borne maxi
|
|
|
|
if (pa.Limit_temps_stable()) // cas où l'utilisateur impose une limite haute de stabilité
|
|
|
|
{pa.Modif_Detat_dans_borne(delta_t);}
|
|
|
|
else // cas où on est hors borne non contrôlé
|
|
|
|
{ cout << "\n ** AlgoriRungeKutta: initialisation du pas de temps non acceptee, le nouveau pas"
|
|
|
|
<< "\n de temps calcule est plus grand que le pas de temps maxi limite: " << pa.Deltatmaxi();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
default:
|
|
|
|
cout << "\n erreur2 !! cas non pris en compte : AlgoriRungeKutta::Gestion_pas_de_temps( "
|
|
|
|
<< " pa.Modif_Deltat(delta_t)= "<< pa.Modif_Deltat(delta_t) << endl;
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
if (delta_t != ancien_pas)
|
|
|
|
modif_deltat=true;
|
|
|
|
};
|
|
|
|
if ((ParaGlob::NiveauImpression() > 0) && (modif_deltat))
|
|
|
|
cout << "\n --->>>> modif increment de temps de " << ancien_pas << " a " << delta_t;
|
|
|
|
|
|
|
|
break;
|
|
|
|
} //-- fin du cas == 2
|
|
|
|
default :
|
|
|
|
{cout << "\nErreur4 : valeur incorrecte du cas = " << cas << "\n";
|
|
|
|
cout << "AlgoriRungeKutta::Gestion_pas_de_temps(... \n";
|
|
|
|
Sortie(1);
|
|
|
|
}
|
|
|
|
}; // fin du switch
|
|
|
|
// --<DFC>-- mise à jour éventuelle des variables simplificatrices pour le temps
|
|
|
|
if ((cas==1) || ( modif_deltat))
|
|
|
|
{unsurdeltat = 1./delta_t;deltatSurDeux = delta_t/2.;
|
|
|
|
};
|
|
|
|
// retour
|
|
|
|
return modif_deltat;
|
|
|
|
};
|
|
|
|
|
|
|
|
// modification transitoire du pas de temps et modif en conséquence si nécessaire
|
|
|
|
// utilisée en continu par RK
|
|
|
|
// delta_tau : nouveau pas de temps transitoire imposé
|
|
|
|
void AlgoriRungeKutta::Modif_transi_pas_de_temps(const double & delta_t)
|
|
|
|
{ // modification de l'increment de temps suivant l'entrée
|
|
|
|
switch (pa.Modif_Deltat(delta_t))
|
|
|
|
{case -1: { cout << "\n ** AlgoriRungeKutta: initialisation du pas de temps non acceptee, le nouveau pas"
|
|
|
|
<< "\n de temps calcule est plus petit que le pas de temps mini limite: " << pa.Deltatmini();
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
case 0: { break;} // cas normal
|
|
|
|
case 1: { cout << "\n ** AlgoriRungeKutta: initialisation du pas de temps non acceptee, le nouveau pas"
|
|
|
|
<< "\n de temps calcule est plus grand que le pas de temps maxi limite: " << pa.Deltatmaxi();
|
|
|
|
pa.Modif_Deltat(delta_t);
|
|
|
|
Sortie(1); break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
cout << "\n erreur5 !! cas non pris en compte : AlgoriRungeKutta::Gestion_pas_de_temps( "
|
|
|
|
<< " pa.Modif_Deltat(delta_t)= "<< pa.Modif_Deltat(delta_t) << endl;
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
// - mise à jour des variables simplificatrices pour le temps
|
|
|
|
unsurdeltat = 1./delta_t;deltatSurDeux = delta_t/2.;
|
|
|
|
deltat2 = delta_t * delta_t;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ------- pour RK : calcul du vecteur dérivée -----------------
|
|
|
|
// calcul de l'expression permettant d'obtenir la dérivée temporelle du problème
|
|
|
|
// utilisée dans la résolution de l'équation d'équilibre dynamique par la méthode RK
|
|
|
|
// en entrée:
|
|
|
|
// tau: temps courant
|
|
|
|
// val_fonc: qui contient à la suite X et X_point à tau
|
|
|
|
// en sortie:
|
|
|
|
// der_val_fonc : qui contient à la suite: X_point et gamma
|
|
|
|
// erreur : =0: le calcul est licite, si diff de 0, indique qu'il y a eu une erreur
|
|
|
|
// =1: erreur de calcul inconnue
|
|
|
|
Vecteur& AlgoriRungeKutta::Dyna_point(const double & tau, const Vecteur & val_fonc
|
|
|
|
,Vecteur & der_val_fonc,int& erreur)
|
|
|
|
{ inReaction = 0; // pointeur d'assemblage pour le maxi de reaction
|
|
|
|
inSol =0 ; // pointeur d'assemblage du maxi de variation de ddl
|
|
|
|
maxDeltaDdl=0; // maxi de variation de ddl
|
|
|
|
erreur = 0; // initialisation
|
|
|
|
|
|
|
|
// modification de l'increment de temps suivant l'entrée
|
|
|
|
double delta_tau = tau - pa.Variables_de_temps().TempsCourant();
|
|
|
|
Modif_transi_pas_de_temps(delta_tau);
|
|
|
|
bool modif_temps = charge_->Avance(); // avancement de la charge et donc du temps courant
|
|
|
|
//-- si le temps a changé il faut de nouveau appeler la gestion du pas de temps
|
|
|
|
// car il y a des grandeurs reliées au pas de temps qui y sont calculé
|
|
|
|
if (modif_temps)
|
|
|
|
{delta_tau = tau - pa.Variables_de_temps().TempsCourant();
|
|
|
|
Modif_transi_pas_de_temps(delta_tau);
|
|
|
|
};
|
|
|
|
// calcul de l'increment
|
|
|
|
// initialisation des deux partie du second membre
|
|
|
|
vglobin.Zero();
|
|
|
|
vglobex.Zero();
|
|
|
|
if (pa.ContactType())
|
|
|
|
vcontact.Zero();
|
|
|
|
vglobaal.Zero(); // puissance totale
|
|
|
|
lesMail_->Force_Ddl_aux_noeuds_a_une_valeur(R_X1,0.0,TEMPS_tdt,true); // mise à 0 des ddl de réactions, qui sont uniquement des sorties
|
|
|
|
lesMail_->Force_Ddl_etendu_aux_noeuds_a_zero(Ddl_enum_etendu::Tab_FN_FT()); // idem pour les composantes normales et tangentielles
|
|
|
|
// 2_3 --<DFC>-- imposition des ddls bloqués
|
|
|
|
// initialisation des coordonnees et des ddl a tdt en fonctions des
|
|
|
|
// ddl imposes et de l'increment du chargement
|
|
|
|
bool change_statut = false; // init des changements de statut
|
|
|
|
lesCondLim_->MiseAJour_tdt
|
|
|
|
(pa.Multiplicateur(),lesMail_,charge_->Increment_de_Temps(),lesRef_,charge_->Temps_courant()
|
|
|
|
,lesCourbes1D_,lesFonctionsnD_,charge_->MultCharge(),change_statut,cas_combi_ddl);
|
|
|
|
// dans le cas ou il y a changement de statut il faut remettre à jour
|
|
|
|
// les conditions limites sur la matrice masse
|
|
|
|
if (change_statut)
|
|
|
|
{li_gene_asso = lesCondLim_->Tableau_indice (lesMail_,t_assemb
|
|
|
|
,lesRef_,charge_->Temps_courant(),icas);
|
|
|
|
int ttsi = li_gene_asso.size();
|
|
|
|
X_Bl.Change_taille(ttsi);V_Bl.Change_taille(ttsi);G_Bl.Change_taille(ttsi);
|
|
|
|
// récupération de la matrice masse sans conditions limites
|
|
|
|
(*mat_masse) = (*mat_masse_sauve);
|
|
|
|
// normalement sur la matrice visqueuse il n'y a rien n'a faire
|
|
|
|
// if (pa.Amort_visco_artificielle()) // initialisation de la matrice visqueuse
|
|
|
|
// { bool initial = false;
|
|
|
|
// Cal_mat_visqueux_num_expli(matrice_mas,mat_C_pt,delta_X,initial,vitesse_tdt);
|
|
|
|
// }
|
|
|
|
// mise en place des conditions limites
|
|
|
|
// ---- initialisation des sauvegardes sur matrice et second membre
|
|
|
|
// ce qui ne correspond à rien ici normalement
|
|
|
|
lesCondLim_->InitSauve(Ass3->Nb_cas_assemb());
|
|
|
|
lesCondLim_->ImposeConLimtdt(lesMail_,lesRef_,*mat_masse,vglobaal
|
|
|
|
,Ass3->Nb_cas_assemb(),cas_combi_ddl,vglob_stat);
|
|
|
|
// puis on prépare (si besoin est en fonction du type de matrice) la résolution
|
|
|
|
mat_masse->Preparation_resol();
|
|
|
|
};
|
|
|
|
// dans le cas d'un amortissement visqueux fonction de l'amortissement critique, C peut évoluer
|
|
|
|
|
|
|
|
// 1_0 ---- récupération (initialisation) des ddl position, vitesse et accélération
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,X1,X_t,X1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,V1,vitesse_t,V1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
|
|
|
|
// récupération au niveau global des ddl locaux à tdt avec conditions limite
|
|
|
|
// pour le vecteur accélération, seules les ddl avec CL sont différents de la précédente
|
|
|
|
// récupération
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_tdt,X1,X_tdt,X1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_tdt,V1,vitesse_tdt,V1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1);
|
|
|
|
|
|
|
|
// maintenant on met les conditions limites sur les ddls bloqués secondaires c-a-d associés
|
|
|
|
// aux ddl bloqués par l'utilisateur, leur calcul dépend de l'algorithme d'où un calcul global
|
|
|
|
// **** actuellement pour simplifier, on utilise l'algo Tchamwa pour imposer les CL en déplacements !!! ****
|
|
|
|
list <LesCondLim::Gene_asso>::iterator ie,iefin=li_gene_asso.end(); // def d'un iterator adoc
|
|
|
|
int ih=1; // indice
|
|
|
|
for(ie=li_gene_asso.begin(),ih=1;ie!=iefin;ie++,ih++)
|
|
|
|
// comme les valeurs des X V Gamma vont être écrasé par le calcul global, on utilise
|
|
|
|
// des conteneurs intermédiaires
|
|
|
|
{//trois cas
|
|
|
|
LesCondLim::Gene_asso & s = (*ie); // pour simplifier
|
|
|
|
int ix=s.pointe(1); // début des Xi
|
|
|
|
int iv=s.pointe(2); // début des Vi
|
|
|
|
int ig=s.pointe(3); // début des gammai
|
|
|
|
// quelquesoit la valeur de phi du schéma de tchamwa, on utilise le schéma des différences finis
|
|
|
|
// centrés pour calculer les valeurs des ddl dans le cas de ddl bloqué
|
|
|
|
if (PremierDdlFamille(s.ty_prin) == X1)
|
|
|
|
// cas ou les Xi sont imposés, on calcul Vi et Gammai
|
|
|
|
{ X_Bl(ih) = X_tdt(ix);
|
|
|
|
V_Bl(ih) = (X_tdt(ix) - X_t(ix))*unsurdeltat ;
|
|
|
|
G_Bl(ih)= (V_Bl(ih)-vitesse_t(iv))*unsurdeltat ;
|
|
|
|
}
|
|
|
|
else if (PremierDdlFamille(s.ty_prin) == V1)
|
|
|
|
// cas ou les Vi sont imposés, calcul des Xi et Gammai
|
|
|
|
{ V_Bl(ih) = vitesse_tdt(iv);
|
|
|
|
G_Bl(ih) = (vitesse_tdt(iv)-vitesse_t(iv))*unsurdeltat ;
|
|
|
|
X_Bl(ih) = X_t(ix) + delta_t * vitesse_tdt(iv);
|
|
|
|
}
|
|
|
|
else if (PremierDdlFamille(s.ty_prin) == GAMMA1)
|
|
|
|
// cas ou les gammai sont imposés, calcul des Vi et Xi
|
|
|
|
{ G_Bl(ih) = acceleration_tdt(ig);
|
|
|
|
V_Bl(ih) = vitesse_t(iv) + delta_t * acceleration_t(iv);
|
|
|
|
X_Bl(ih) = X_t(ix) + delta_t * vitesse_t(iv)
|
|
|
|
+ deltat2 * acceleration_t(ig);
|
|
|
|
}
|
|
|
|
acceleration_t(ig) = G_Bl(ih); // pour le cas ou il y a relachement des conditions limites
|
|
|
|
// au prochain pas de temsp
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
// récupération des vitesses et positions en fonction des données d'entrées
|
|
|
|
X_tdt.Egale_une_partie_de(val_fonc,1);
|
|
|
|
vitesse_tdt.Egale_une_partie_de(val_fonc,X_tdt.Taille()+1);
|
|
|
|
vitesse_tdt /= scale_fac;
|
|
|
|
|
|
|
|
// -- maintenant on met réellement en place les CL a partir de la sauvegarde
|
|
|
|
for(ie=li_gene_asso.begin(),ih=1;ie!=iefin;ie++,ih++)
|
|
|
|
{LesCondLim::Gene_asso & s = (*ie); // pour simplifier
|
|
|
|
int ix=s.pointe(1); // début des Xi
|
|
|
|
int iv=s.pointe(2); // début des Vi
|
|
|
|
int ig=s.pointe(3); // début des gammai
|
|
|
|
X_tdt(ix) = X_Bl(ih);
|
|
|
|
vitesse_tdt(iv) = V_Bl(ih);
|
|
|
|
acceleration_tdt(ig) = G_Bl(ih);
|
|
|
|
};
|
|
|
|
|
|
|
|
// 2_1 ---- passage des valeurs calculées aux niveaux des maillages
|
|
|
|
lesMail_->Vect_glob_vers_local(TEMPS_tdt,X1,X_tdt,X1);
|
|
|
|
lesMail_->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1);
|
|
|
|
// accélération à t : seules celles correspondantes au CL ont variées
|
|
|
|
// lesMail->Vect_glob_vers_local(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
|
|
|
|
// 3 --<DFC>-- calcul des puissances internes et externe
|
|
|
|
// mise en place du chargement impose, c-a-d calcul de la puissance externe
|
|
|
|
// si pb on sort de la boucle
|
|
|
|
if (!(charge_->ChargeSecondMembre_Ex_mecaSolid
|
|
|
|
(*Ass1,lesMail_,lesRef_,vglobex,pa,lesCourbes1D_,lesFonctionsnD_)))
|
|
|
|
{ Change_PhaseDeConvergence(-10);};
|
|
|
|
// appel du calcul de la puissance interne et des énergies
|
|
|
|
// dans le cas d'un calcul inexploitable on enregistre l'erreur
|
|
|
|
if (!SecondMembreEnerg(lesMail_,*Ass1,vglobin))
|
|
|
|
{erreurSecondMembre=true; erreur=1; return der_val_fonc;};
|
|
|
|
// calcul des maxi des puissances internes
|
|
|
|
maxPuissInt = vglobin.Max_val_abs();
|
|
|
|
F_int_tdt = vglobin; // sauvegarde des forces généralisées intérieures
|
|
|
|
|
|
|
|
if (pa.ContactType())
|
|
|
|
vglobex += vcontact;
|
|
|
|
maxPuissExt = vglobex.Max_val_abs();
|
|
|
|
F_ext_tdt = vglobex; // sauvegarde des forces généralisées extérieures
|
|
|
|
// second membre total
|
|
|
|
vglobaal += vglobex ;vglobaal += vglobin ;
|
|
|
|
|
|
|
|
// dans le cas où l'on utilise de l'amortissement numérique le second membre est modifiée
|
|
|
|
if (pa.Amort_visco_artificielle())
|
|
|
|
{ if (Arret_A_Equilibre_Statique()) // si on veut un équilibre statique, on sauvegarde les forces statiques
|
|
|
|
(*vglob_stat) = (vglobaal);
|
|
|
|
Cal_mat_visqueux_num_expli(*mat_masse_sauve,mat_C_pt,delta_X,false,vitesse_tdt); // init de C éventuelle
|
|
|
|
(vglobaal) -= mat_C_pt->Prod_mat_vec(vitesse_t,forces_vis_num);
|
|
|
|
};
|
|
|
|
// initialisation des sauvegardes sur second membre (uniquement pour les gammai)
|
|
|
|
lesCondLim_->InitSauve(Ass3->Nb_cas_assemb());
|
|
|
|
// sauvegarde des reactions aux ddl bloque en fait pour les gammai
|
|
|
|
lesCondLim_->ReacApresCHrepere(vglobin,lesMail_,lesRef_,Ass3->Nb_cas_assemb(),cas_combi_ddl);
|
|
|
|
// sur les Gammai
|
|
|
|
lesCondLim_->ImposeConLimtdt(lesMail_,lesRef_,(vglobaal),Ass3->Nb_cas_assemb()
|
|
|
|
,cas_combi_ddl,vglob_stat);
|
|
|
|
|
|
|
|
// calcul du maxi des reactions (pour les xi)
|
|
|
|
maxReaction = lesCondLim_->MaxEffort(inReaction,Ass3->Nb_cas_assemb());
|
|
|
|
// 4 --<DFC>-- calcul des accélérations
|
|
|
|
// resolution simple (fonction du type de matrice)
|
|
|
|
tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
|
|
|
|
Vecteur vtb(vglobaal);
|
|
|
|
residu_final = vglobaal; // sauvegarde pour le post-traitement
|
|
|
|
mat_masse->Simple_Resol_systID_2 (vglobaal,acceleration_tdt,pa.Tolerance()
|
|
|
|
,pa.Nb_iter_nondirecte(),pa.Nb_vect_restart());
|
|
|
|
|
|
|
|
tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu
|
|
|
|
// on revient aux conditions initiales de début d'incrément concernant le temps
|
|
|
|
charge_->Precedant();
|
|
|
|
// ---- retour des informations----
|
|
|
|
der_val_fonc.Une_partie_egale(1,vitesse_tdt);
|
|
|
|
der_val_fonc.Une_partie_egale(X_tdt.Taille()+1,acceleration_tdt*scale_fac);
|
|
|
|
return der_val_fonc;
|
|
|
|
};
|
|
|
|
|
|
|
|
// vérification de l'intégrité du résultat calculé
|
|
|
|
// erreur : =0: le calcul est licite, si diff de 0, indique qu'il y a eu une erreur
|
|
|
|
// =1: la norme de sigma est supérieure à la valeur limite de saturation
|
|
|
|
void AlgoriRungeKutta::Verif_integrite_Solution(const double & tau, const Vecteur & val_fonc,int & erreur)
|
|
|
|
{ // ici on ne fait pour l'instant pas de vérification de l'intégrité
|
|
|
|
erreur = 0; // initialisation
|
|
|
|
};
|
|
|
|
|
|
|
|
// lecture des paramètres du calcul
|
|
|
|
void AlgoriRungeKutta::lecture_Parametres(UtilLecture& entreePrinc)
|
|
|
|
{ MotCle motCle; // ref aux mots cle
|
|
|
|
Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_RUNGE_KUTTA); // transfert info
|
|
|
|
deja_lue_entete_parametre = 1; // a priori pas de lecture d'entête
|
|
|
|
// on se positionne sur le prochain mot clé
|
|
|
|
do
|
|
|
|
{ entreePrinc.NouvelleDonnee();
|
|
|
|
}
|
|
|
|
while ( !motCle.SimotCle(entreePrinc.tablcar)) ;
|
|
|
|
// si le mot clé est "PARA_TYPE_DE_CALCUL" cela signifie
|
|
|
|
// qu'il y a un paramètre à lire
|
|
|
|
bool lecture_effective = false;
|
|
|
|
if (strstr(entreePrinc.tablcar,"PARA_TYPE_DE_CALCUL")!=NULL)
|
|
|
|
{ //cas de la définition de paramètres
|
|
|
|
// on signale à Algori qu'il y a eu déjà une lecture de paramètre
|
|
|
|
deja_lue_entete_parametre=2;
|
|
|
|
// lecture du premier paramètres de l'algorithme
|
|
|
|
entreePrinc.NouvelleDonnee(); // ligne suivante
|
|
|
|
if (strstr(entreePrinc.tablcar,"algo_kutta_")!=NULL)
|
|
|
|
{ // on lit le type de Runge Kutta
|
|
|
|
string st1;
|
|
|
|
*(entreePrinc.entree) >> st1 >> cas_kutta;
|
|
|
|
if (st1 != "algo_kutta_")
|
|
|
|
{ cout << "\n erreur en lecture du type de Runge Kutta "
|
|
|
|
<< "\n on attendait le mot : algo_kutta_ , au lieu de " << st1
|
|
|
|
<< "\n AlgoriRungeKutta::lecture_Parametres( ... ";
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
// on vérifie la valeur lue
|
|
|
|
if ((cas_kutta < 2) && (cas_kutta > 5))
|
|
|
|
{ cout << "\n erreur en lecture du type de de Runge Kutta "
|
|
|
|
<< "\n on attendait une valeur comprise entre 3 et 5 au lieu de: " << cas_kutta
|
|
|
|
<< "\n AlgoriRungeKutta::lecture_Parametres( ... ";
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
lecture_effective = true;
|
|
|
|
}
|
|
|
|
else // sinon on met une valeur par défaut
|
|
|
|
{ cas_kutta=5;
|
|
|
|
};
|
|
|
|
// lecture de l'erreur absolue pour le pilotage de RK
|
|
|
|
if (strstr(entreePrinc.tablcar,"algoErrAbs_")!=NULL)
|
|
|
|
{ // on lit le type de Runge Kutta
|
|
|
|
string st1;
|
|
|
|
*(entreePrinc.entree) >> st1 >> erreurAbsolue;
|
|
|
|
if (st1 != "algoErrAbs_")
|
|
|
|
{ cout << "\n erreur en lecture de l'erreur absolue "
|
|
|
|
<< "\n on attendait le mot : algoErrAbs_ , au lieu de " << st1
|
|
|
|
<< "\n AlgoriRungeKutta::lecture_Parametres( ... ";
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
lecture_effective = true;
|
|
|
|
}
|
|
|
|
else // sinon on met une valeur par défaut
|
|
|
|
{ erreurAbsolue=1.e-4;
|
|
|
|
};
|
|
|
|
// lecture de l'erreur relative pour le pilotage de RK
|
|
|
|
if (strstr(entreePrinc.tablcar,"algoErrRel_")!=NULL)
|
|
|
|
{ // on lit le type de Runge Kutta
|
|
|
|
string st1;
|
|
|
|
*(entreePrinc.entree) >> st1 >> erreurRelative;
|
|
|
|
if (st1 != "algoErrRel_")
|
|
|
|
{ cout << "\n erreur en lecture de l'erreur relative "
|
|
|
|
<< "\n on attendait le mot : algoErrRel_ , au lieu de " << st1
|
|
|
|
<< "\n AlgoriRungeKutta::lecture_Parametres( ... ";
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
lecture_effective = true;
|
|
|
|
}
|
|
|
|
else // sinon on met une valeur par défaut
|
|
|
|
{ erreurRelative=1.e-4;
|
|
|
|
};
|
|
|
|
// lecture du nombre maxi d'appel de la fonction dérivée pour le pilotage de RK
|
|
|
|
if (strstr(entreePrinc.tablcar,"nbMaxiCall_")!=NULL)
|
|
|
|
{ // on lit le type de Runge Kutta
|
|
|
|
string st1;
|
|
|
|
*(entreePrinc.entree) >> st1 >> nbMaxiAppel;
|
|
|
|
if (st1 != "nbMaxiCall_")
|
|
|
|
{ cout << "\n erreur en lecture du nombre maxi d'appel de la fonction derivee "
|
|
|
|
<< "\n on attendait le mot : nbMaxiCall_ , au lieu de " << st1
|
|
|
|
<< "\n AlgoriRungeKutta::lecture_Parametres( ... ";
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
lecture_effective = true;
|
|
|
|
}
|
|
|
|
else // sinon on met une valeur par défaut
|
|
|
|
{ nbMaxiAppel=2000;
|
|
|
|
};
|
|
|
|
// lecture du pilotage sur un step par pas de temps
|
|
|
|
if (strstr(entreePrinc.tablcar,"pilotage_un_step_")!=NULL)
|
|
|
|
{ // on indique le pilotage
|
|
|
|
pilotage_un_step = true;
|
|
|
|
string st1;
|
|
|
|
*(entreePrinc.entree) >> st1 ; // on passe la chaine de caractère pour vérif
|
|
|
|
if (st1 != "pilotage_un_step_")
|
|
|
|
{ cout << "\n erreur en lecture du pilotage un step = un pas de temps"
|
|
|
|
<< "\n on attendait le mot : pilotage_un_step_ , au lieu de " << st1
|
|
|
|
<< "\n AlgoriRungeKutta::lecture_Parametres( ... ";
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
lecture_effective = true;
|
|
|
|
}
|
|
|
|
else // sinon on met la valeur par défaut
|
|
|
|
{ pilotage_un_step=false;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else // sinon on met les valeurs par défaut
|
|
|
|
{ cas_kutta=5;erreurAbsolue=1.e-4;erreurRelative=1.e-4;nbMaxiAppel=2000;pilotage_un_step=false;
|
|
|
|
};
|
|
|
|
// on prépare la prochaine lecture si la lecture a été effective et que l'on n'est pas
|
|
|
|
// sur un mot clé
|
|
|
|
if ((lecture_effective) && ( !motCle.SimotCle(entreePrinc.tablcar)))
|
|
|
|
entreePrinc.NouvelleDonnee(); // ligne suivante
|
|
|
|
// puis appel de la méthode de la classe mère
|
|
|
|
Algori::lecture_Parametres(entreePrinc);
|
|
|
|
};
|
|
|
|
|
|
|
|
// création d'un fichier de commande: cas des paramètres spécifiques
|
|
|
|
void AlgoriRungeKutta::Info_commande_parametres(UtilLecture& entreePrinc)
|
|
|
|
{ // écriture dans le fichier de commande
|
|
|
|
ofstream & sort = *(entreePrinc.Commande_pointInfo()); // pour simplifier
|
|
|
|
sort << "\n#-----------------------------------------------------------------------------"
|
|
|
|
<< "\n| parametres (falcultatifs ) associes au calcul de dynamique explicite |"
|
|
|
|
<< "\n| definition des parametres de controle pour Runge Kutta |"
|
|
|
|
<< "\n#-----------------------------------------------------------------------------"
|
|
|
|
<< "\n"
|
|
|
|
<< "\n PARA_TYPE_DE_CALCUL"
|
|
|
|
<< "\n # ..................................................................................."
|
|
|
|
<< "\n # / le type de Runge_kutta: 3 pour une methode imbriquee 2-3, 4 pour 3-4, 5 pour 4-5 /"
|
|
|
|
<< "\n # / l'erreur absolue et l'erreur relative finale sur X et V /"
|
|
|
|
<< "\n # / le nombre maxi d'appel de la fonction derivee (gamma et V) /"
|
|
|
|
<< "\n # / pilotage pour avoir un seul step par pas de temps, par defaut pas de pilotage /"
|
|
|
|
<< "\n # / si ce parametre est present donc actif, le pas de temps est calcule automati- /"
|
|
|
|
<< "\n # / quement. Le pas de temps dans le .info sert uniquement au debut. /"
|
|
|
|
<< "\n # / ** parametres tous facultatifs : (mettre les parametres sur une meme ligne et /"
|
|
|
|
<< "\n # / dans l'ordre (meme si certain manque) *** /"
|
|
|
|
<< "\n #....................................................................................."
|
|
|
|
<< "\n algo_kutta_ 5 algoErrAbs_ 1.e-3 algoErrRel_ 1.e-5 nbMaxiCall_ 100 pilotage_un_step_ ";
|
|
|
|
// appel de la classe mère
|
|
|
|
Algori::Info_com_parametres(entreePrinc);
|
|
|
|
sort << "\n" << endl;
|
|
|
|
};
|
|
|
|
|
|
|
|
//------- décomposition en 3 du calcul d'équilibre -------------
|
|
|
|
// a priori : InitAlgorithme et FinCalcul ne s'appellent qu'une fois,
|
|
|
|
// par contre : CalEquilibre peut s'appeler plusieurs fois, le résultat sera différent si entre deux calcul
|
|
|
|
// certaines variables ont-été changés
|
|
|
|
|
|
|
|
// initialisation
|
|
|
|
void AlgoriRungeKutta::InitAlgorithme(ParaGlob * paraGlob,LesMaillages * lesMail,
|
|
|
|
LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
|
|
|
|
,VariablesExporter* varExpor
|
|
|
|
,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,
|
|
|
|
Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts
|
|
|
|
,Resultats* resultats)
|
|
|
|
{ // INITIALISATION globale
|
|
|
|
tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu
|
|
|
|
Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_RUNGE_KUTTA); // transfert info
|
2023-05-03 17:23:49 +02:00
|
|
|
|
|
|
|
#ifdef UTILISATION_MPI
|
|
|
|
// calcul de l'équilibrage initiale par le cpu 0
|
|
|
|
if (distribution_CPU_algo.Tableau_element_CPU_en_cours()->Taille() == 0 )
|
|
|
|
{distribution_CPU_algo.Calcul_Equilibrage_initiale(lesMail);
|
|
|
|
distribution_CPU_algo.Passage_Equilibrage_aux_CPU();
|
2023-12-15 19:17:23 +01:00
|
|
|
paraGlob->Init_tableau(distribution_CPU_algo.Tableau_element_CPU_en_cours()
|
|
|
|
,distribution_CPU_algo.Tab_indique_CPU_en_cours()
|
|
|
|
,distribution_CPU_algo.Tableau_noeud_CPU_en_cours()
|
|
|
|
,distribution_CPU_algo.Tab_indique_noeud_CPU_en_cours());
|
2023-05-03 17:23:49 +02:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2021-09-26 14:31:23 +02:00
|
|
|
// avant toute chose, au cas où l'algo interviendrait après un autre algo
|
|
|
|
// on inactive tous les ddl existants
|
|
|
|
lesMail->Inactive_ddl();
|
|
|
|
// on regarde s'il s'agit d'un pb purement non méca, dans ce cas il faut cependant initialiser les positions
|
|
|
|
// à t et tdt pour le calcul de la métrique associée
|
|
|
|
{ const list <EnumElemTypeProblem >& type_pb = lesMail->Types_de_problemes();
|
|
|
|
bool purement_non_meca = true;
|
|
|
|
list <EnumElemTypeProblem >::const_iterator il,ilfin=type_pb.end();
|
|
|
|
for (il=type_pb.begin();il != ilfin; il++)
|
|
|
|
{switch (*il)
|
|
|
|
{ case MECA_SOLIDE_DEFORMABLE: case MECA_SOLIDE_INDEFORMABLE: case MECA_FLUIDE:
|
|
|
|
purement_non_meca=false; break;
|
|
|
|
default: break; // sinon on ne fait rien
|
|
|
|
};
|
|
|
|
};
|
|
|
|
if (purement_non_meca) // si pas de méca, on initialise les coordonnées à t et tdt avec celles de 0
|
|
|
|
{lesMail->Init_Xi_t_et_tdt_de_0();}
|
|
|
|
else // sinon a minima on active X1
|
|
|
|
{ lesMail->Active_un_type_ddl_particulier(X1);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// -- 1) on met à jour les pointeurs internes de classes
|
|
|
|
lesMail_ =lesMail;
|
|
|
|
lesRef_ =lesRef;
|
|
|
|
lesCourbes1D_ = lesCourbes1D;
|
|
|
|
lesFonctionsnD_ = lesFonctionsnD;
|
|
|
|
charge_ = charge;
|
|
|
|
lesCondLim_ = lesCondLim;
|
|
|
|
lesContacts_ = lesContacts;
|
|
|
|
|
|
|
|
// cas du chargement, on verifie egalement la bonne adequation des references
|
|
|
|
charge->Initialise(lesMail,lesRef,pa,*lesCourbes1D,*lesFonctionsnD);
|
|
|
|
// on indique que l'on ne souhaite pas le temps fin stricte
|
|
|
|
// (sinon erreur non gérée après un changement de delta t), que l'on suppose négligeable
|
|
|
|
// après plusieurs incréments
|
|
|
|
charge->Change_temps_fin_non_stricte(1);
|
|
|
|
// --RK-- on se place dans le cadre de l'algorithme de runge kutta
|
|
|
|
// dans le cas où l'on calcul des contraintes et/ou déformation et/ou un estimateur d'erreur
|
|
|
|
// à chaque incrément, initialisation
|
|
|
|
tenuXVG.Change_taille(3);tenuXVG(1)=X1;tenuXVG(2)=V1;tenuXVG(3)=GAMMA1;
|
|
|
|
prepa_avec_remont = Algori::InitRemont(lesMail,lesRef,diversStockage,charge,lesCondLim,lesContacts,resultats);
|
|
|
|
if ( prepa_avec_remont)// remise enservice des ddl du pab
|
|
|
|
{lesMail->Inactive_ddl(); lesMail->Active_un_type_ddl_particulier(X1);};
|
|
|
|
// 01 --<DFC>-- récup du pas de temps, proposé par l'utilisateur, initialisation et vérif / pas critique
|
|
|
|
this->Gestion_pas_de_temps(true,lesMail,1,1); // 1 signifie qu'il y a initialisation
|
|
|
|
scale_fac=delta_t; // facteur d'homogénéisation des vecteurs _val_fonc_
|
|
|
|
// 00 --<DFC>-- on crée les ddl d'accélération et de vitesse non actif mais libres
|
|
|
|
// car les forces intérieures et extérieures sont les entitées duales
|
|
|
|
// des déplacements, qui sont donc les seules grandeurs actives à ce stade
|
|
|
|
lesMail->Plus_Les_ddl_Vitesse( HSLIBRE);
|
|
|
|
lesMail->Plus_Les_ddl_Acceleration( HSLIBRE);
|
|
|
|
// on défini globalement que l'on a une combinaison des ddl X V GAMMA en même temps
|
|
|
|
cas_combi_ddl=1;
|
|
|
|
// mise en place éventuelle du bulk viscosity
|
|
|
|
lesMail->Init_bulk_viscosity(pa.BulkViscosity(),pa.CoefsBulk());
|
|
|
|
// mise a zero de tous les ddl et creation des tableaux a t+dt
|
|
|
|
// les ddl de position ne sont pas mis a zero ! ils sont initialise
|
|
|
|
// a la position courante
|
|
|
|
lesMail->ZeroDdl(true);
|
|
|
|
// on vérifie que les noeuds sont bien attachés à un élément sinon on met un warning si niveau > 2
|
|
|
|
if (ParaGlob::NiveauImpression() > 2)
|
|
|
|
lesMail->AffichageNoeudNonReferencer();
|
|
|
|
// init des ddl avec les conditions initials
|
|
|
|
// les conditions limites initiales de vitesse et d'accélération sont prise en compte
|
|
|
|
// de manière identiques à des ddl quelconques, ce ne sont pas des ddl fixé !!
|
|
|
|
lesCondLim->Initial(lesMail,lesRef,lesCourbes1D,lesFonctionsnD,true,cas_combi_ddl);
|
|
|
|
// mise à jour des différents pointeur d'assemblage et activation des ddl
|
|
|
|
// a) pour les déplacements qui sont à ce stade les seuls grandeurs actives
|
|
|
|
// on définit un nouveau cas d'assemblage pour les Xi
|
|
|
|
// à travers la définition d'une instance de la classe assemblage
|
|
|
|
Ass1 = new Assemblage(lesMail->InitNouveauCasAssemblage(1));
|
|
|
|
lesMail->MiseAJourPointeurAssemblage(Ass1->Nb_cas_assemb());// mise a jour des pointeurs d'assemblage
|
|
|
|
int nbddl_X = lesMail->NbTotalDdlActifs(X1); // nb total de ddl de déplacement
|
|
|
|
// qui est le même pour les accélérations et les vitesses
|
|
|
|
// b) maintenant le cas des vitesses qui doivent donc être activées
|
|
|
|
// on définit un nouveau cas d'assemblage pour les Vi
|
|
|
|
Ass2= new Assemblage(lesMail->InitNouveauCasAssemblage(1));
|
|
|
|
lesMail->Inactive_un_type_ddl_particulier(X1); // on inactive les Xi
|
|
|
|
lesMail->Active_un_type_ddl_particulier(V1); // on active les Vi
|
|
|
|
lesMail->MiseAJourPointeurAssemblage(Ass2->Nb_cas_assemb()); // mise a jour des pointeurs d'assemblage
|
|
|
|
// c) idem pour les accélérations
|
|
|
|
// on définit le numéro de second membre en cours
|
|
|
|
// on définit un nouveau cas d'assemblage pour les pour GAMMAi
|
|
|
|
Ass3= new Assemblage(lesMail->InitNouveauCasAssemblage(1));
|
|
|
|
lesMail->Inactive_un_type_ddl_particulier(V1); // on inactive les Vi
|
|
|
|
lesMail->Active_un_type_ddl_particulier(GAMMA1); // on active les GAMMAi
|
|
|
|
lesMail->MiseAJourPointeurAssemblage(Ass3->Nb_cas_assemb()); // mise a jour des pointeurs d'assemblage
|
|
|
|
// d) activation de tous les ddl, maintenant ils peuvent être les 3 actifs
|
|
|
|
lesMail->Active_un_type_ddl_particulier(X1);
|
|
|
|
lesMail->Active_un_type_ddl_particulier(V1);
|
|
|
|
// en fait ces trois pointeurs d'assemblage ne sont utils que pour la mise en place des conditions
|
|
|
|
// limites
|
|
|
|
// mise à jour du nombre de cas d'assemblage pour les conditions limites
|
|
|
|
// c-a-d le nombre maxi possible (intégrant les autres pb qui sont résolu en // éventuellement)
|
|
|
|
lesCondLim->InitNombreCasAssemblage(lesMail->Nb_total_en_cours_de_cas_Assemblage());
|
|
|
|
// définition d'un tableau globalisant les numéros d'assemblage de X V gamma
|
|
|
|
t_assemb.Change_taille(3);
|
|
|
|
t_assemb(1)=Ass1->Nb_cas_assemb();t_assemb(2)=Ass2->Nb_cas_assemb();t_assemb(3)=Ass3->Nb_cas_assemb();
|
|
|
|
// récupération des tableaux d'indices généraux des ddl bloqués, y compris les ddls associés
|
|
|
|
icas = 1; // pour indiquer au module Tableau_indice que l'on travaille avec l'association X V GAMMA
|
|
|
|
li_gene_asso = lesCondLim->Tableau_indice (lesMail,t_assemb
|
|
|
|
,lesRef,charge->Temps_courant(),icas);
|
|
|
|
// on définit quatre tableaux qui serviront à stocker transitoirement les X V GAMMA correspondant au ddl imposés
|
|
|
|
int ttsi = li_gene_asso.size();
|
|
|
|
X_Bl.Change_taille(ttsi),V_Bl.Change_taille(ttsi),G_Bl.Change_taille(ttsi);
|
|
|
|
// def vecteurs globaux
|
|
|
|
vglobin.Change_taille(nbddl_X); // puissance interne
|
|
|
|
vglobex.Change_taille(nbddl_X); // puissance externe
|
|
|
|
vglobaal.Change_taille(nbddl_X,0.); // puissance totale
|
|
|
|
// même si le contact n'est pas encore actif, il faut prévoir qu'il le deviendra peut-être !
|
|
|
|
if (lesMail->NbEsclave() != 0)
|
|
|
|
vcontact.Change_taille(nbddl_X); // puissance de contact
|
|
|
|
// 04 --<DFC>-- 6 vecteur pour une manipulation globale des positions vitesses et accélérations
|
|
|
|
// vecteur qui globalise toutes les positions de l'ensemble des noeuds
|
|
|
|
X_t.Change_taille(nbddl_X);X_tdt.Change_taille(nbddl_X); delta_X.Change_taille(nbddl_X);
|
|
|
|
var_delta_X.Change_taille(nbddl_X);
|
|
|
|
// vecteur qui globalise toutes les vitesses de l'ensemble des noeuds
|
|
|
|
vitesse_t.Change_taille(nbddl_X);vitesse_tdt.Change_taille(nbddl_X);
|
|
|
|
// vecteur qui globalise toutes les accélérations
|
|
|
|
acceleration_t.Change_taille(nbddl_X);acceleration_tdt.Change_taille(nbddl_X) ;
|
|
|
|
|
|
|
|
// calcul des énergies
|
|
|
|
if (pa.Amort_visco_artificielle()) // dans le cas d'un amortissement artificiel
|
|
|
|
forces_vis_num.Change_taille(nbddl_X,0.);
|
|
|
|
E_cin_tdt = 0.; E_int_t = 0.; E_int_tdt = 0.; // init des différentes énergies
|
|
|
|
E_ext_t = 0.; E_ext_tdt = 0.; bilan_E = 0.; // " et du bilan
|
|
|
|
F_int_t.Change_taille(nbddl_X); F_ext_t.Change_taille(nbddl_X); // forces généralisées int et ext au pas précédent
|
|
|
|
F_int_tdt.Change_taille(nbddl_X); F_ext_tdt.Change_taille(nbddl_X); // forces généralisées int et ext au pas actuel
|
|
|
|
residu_final.Change_taille(nbddl_X); // pour la sauvegarde du résidu pour le post-traitement
|
|
|
|
|
|
|
|
// initialisation du compteur d'increments de charge
|
|
|
|
icharge = 0;
|
|
|
|
|
2023-05-03 17:23:49 +02:00
|
|
|
// definition des elements de frontiere, ces elements sont utilises pour le contact
|
|
|
|
lesMail->CreeElemFront();
|
|
|
|
// calcul éventuel des normales aux noeuds -> init des normales pour t=0
|
|
|
|
lesMail->InitNormaleAuxNoeuds(); //utilisé pour la stabilisation des membranes par ex
|
2021-09-26 14:31:23 +02:00
|
|
|
// --- init du contact ---
|
|
|
|
// doit-être avant la lecture d'un restart, car il y a une initialisation de conteneurs qui est faites
|
|
|
|
// qui ensuite est utilisée en restart
|
|
|
|
// par exemple il faut initialiser les frontières et la répartition esclave et maître
|
|
|
|
// pour préparer la lecture de restart éventuel
|
|
|
|
if (lesMail->NbEsclave() != 0)
|
|
|
|
{ // definition des elements de frontiere, ces elements sont utilises pour le contact
|
|
|
|
lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_t);
|
|
|
|
// initialisation des zones de contacts éventuelles
|
|
|
|
lesContacts->Init_contact(*lesMail,*lesRef,lesFonctionsnD);
|
|
|
|
// verification qu'il n'y a pas de contact avant le premier increment de charge
|
|
|
|
lesContacts->Verification();
|
|
|
|
// definition des elements de contact eventuels
|
|
|
|
lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul
|
|
|
|
};
|
2023-05-03 17:23:49 +02:00
|
|
|
|
2021-09-26 14:31:23 +02:00
|
|
|
//--cas de restart et/ou de sauvegarde------------
|
|
|
|
// tout d'abord récup du restart si nécessaire
|
|
|
|
// dans le cas ou un incrément différent de 0 est demandé -> seconde lecture à l'incrément
|
|
|
|
brestart=false; // booleen qui indique si l'on est en restart ou pas
|
|
|
|
if (this->Num_restart() != 0)
|
|
|
|
{ int cas = 2;
|
|
|
|
// ouverture de base info
|
|
|
|
entreePrinc->Ouverture_base_info("lecture");
|
|
|
|
this->Lecture_base_info(cas ,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage
|
|
|
|
,charge,lesCondLim,lesContacts,resultats,(this->Num_restart()));
|
|
|
|
icharge = this->Num_restart();//+1;
|
|
|
|
// récup du pas de temps, proposé par l'utilisateur, initialisation et vérif / pas critique
|
|
|
|
this->Gestion_pas_de_temps(true,lesMail,2,1); // 2 signifie cas courant
|
|
|
|
brestart = true;
|
|
|
|
// on oblige les ddls Vi GAMMAi a avoir le même statut que celui des Xi
|
|
|
|
// comme les conditions limites cinématiques peuvent être différentes en restart
|
|
|
|
// par rapport à celles sauvegardées, on commence par libérer toutes les CL imposées éventuelles
|
|
|
|
lesMail->Libere_Ddl_representatifs_des_physiques(LIBRE);
|
|
|
|
lesMail->ChangeStatut(cas_combi_ddl,LIBRE);
|
|
|
|
// dans le cas d'un calcul axisymétrique on bloque le ddl 3
|
|
|
|
if (ParaGlob::AxiSymetrie())
|
2023-05-03 17:23:49 +02:00
|
|
|
lesMail->Inactive_un_ddl_particulier(X3);
|
2021-09-26 14:31:23 +02:00
|
|
|
// on valide l'activité des conditions limites et condition linéaires, pour le temps initial
|
|
|
|
// en conformité avec les conditions lues (qui peuvent éventuellement changé / aux calcul qui a donné le .BI)
|
|
|
|
lesCondLim->Validation_blocage (lesRef,charge->Temps_courant());
|
|
|
|
li_gene_asso = lesCondLim->Tableau_indice (lesMail,t_assemb,lesRef,charge->Temps_courant(),icas);
|
|
|
|
int ttsi = li_gene_asso.size();
|
|
|
|
X_Bl.Change_taille(ttsi);V_Bl.Change_taille(ttsi);G_Bl.Change_taille(ttsi);
|
|
|
|
// mise à jour pour le contact s'il y du contact présumé
|
|
|
|
if (pa.ContactType())
|
|
|
|
lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_t);
|
|
|
|
};
|
|
|
|
// vérif de cohérence pour le contact
|
|
|
|
if ((pa.ContactType()) && (lesMail->NbEsclave() == 0)) // là pb
|
|
|
|
{cout << "\n *** erreur: il n'y a pas de maillage disponible pour le contact "
|
|
|
|
<< " la definition d'un type contact possible est donc incoherente "
|
|
|
|
<< " revoir la mise en donnees !! "<< flush;
|
|
|
|
Sortie(1);
|
|
|
|
};
|
|
|
|
// on regarde s'il y a besoin de sauvegarde
|
|
|
|
if (this->Active_sauvegarde() && (ParaGlob::param->TypeCalcul_maitre() == this->typeCalcul) )
|
|
|
|
{ // si le fichier base_info n'est pas en service on l'ouvre
|
|
|
|
entreePrinc->Ouverture_base_info("ecriture");
|
|
|
|
// dans le cas ou se n'est pas un restart on sauvegarde l'incrément actuel
|
|
|
|
// c'est-à-dire le premier incrément
|
|
|
|
// après s'être positionné au début du fichier
|
|
|
|
if (this->Num_restart() == 0)
|
|
|
|
{ (entreePrinc->Sort_BI())->seekp(0);
|
|
|
|
int cas = 1;
|
|
|
|
paraGlob->Ecriture_base_info(*(entreePrinc->Sort_BI()),cas);
|
|
|
|
this->Ecriture_base_info
|
|
|
|
(cas,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage
|
|
|
|
,charge,lesCondLim,lesContacts,resultats,OrdreVisu::INCRE_0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // sinon on se place dans le fichier à la position du restart
|
|
|
|
// debut_increment a été définit dans algori (classe mère)
|
|
|
|
(entreePrinc->Sort_BI())->seekp(debut_increment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//--fin cas de restart et/ou de sauvegarde--------
|
|
|
|
|
|
|
|
// ajout d'un conteneur pour les coordonnées à l'itération 0
|
|
|
|
{Coordonnee coor(ParaGlob::Dimension()); // un type coordonnee typique
|
|
|
|
Grandeur_coordonnee gt(coor); // une grandeur typique de type Grandeur_coordonnee
|
|
|
|
// def d'un type quelconque représentatif à chaque noeud
|
|
|
|
TypeQuelconque typQ_gene_int(XI_ITER_0,X1,gt);
|
|
|
|
lesMail->AjoutConteneurAuNoeud(typQ_gene_int);
|
|
|
|
};
|
|
|
|
|
|
|
|
// choix de la matrice de masse, qui est en fait celle qui correspond au ddl Xi
|
|
|
|
// ici le numéro d'assemblage est celui de X car on projette bien sur des vitesses virtuelles c-a-d ddl X*.
|
|
|
|
mat_masse = Choix_matrice_masse(nbddl_X,mat_masse,lesMail,lesRef
|
|
|
|
,Ass1->Nb_cas_assemb(),lesContacts,lesCondLim);
|
|
|
|
mat_masse_sauve = Choix_matrice_masse(nbddl_X,mat_masse_sauve,lesMail,lesRef
|
|
|
|
,Ass1->Nb_cas_assemb(),lesContacts,lesCondLim);
|
|
|
|
// choix de la résolution
|
|
|
|
if (mat_masse->Type_matrice() == DIAGONALE)
|
|
|
|
// dans le cas d'une matrice diagonale on force la résolution directe quelque soit l'entrée
|
|
|
|
mat_masse->Change_Choix_resolution(DIRECT_DIAGONAL,pa.Type_preconditionnement());
|
|
|
|
else
|
|
|
|
mat_masse->Change_Choix_resolution(pa.Type_resolution(),pa.Type_preconditionnement());
|
|
|
|
|
|
|
|
// on signale que l'on utilise un comportement matériel normal
|
|
|
|
lesLoisDeComp->Loi_simplifie(false);
|
|
|
|
// on calcul la matrice de masse qui est supposée identique dans le temps
|
|
|
|
// c'est-à-dire que l'on considère que la masse volumique est constante
|
|
|
|
Cal_matrice_masse(lesMail,*Ass1,*mat_masse,diversStockage,lesRef,X1,lesFonctionsnD);
|
|
|
|
// on sauvegarde la matrice masse
|
|
|
|
(*mat_masse_sauve) = (*mat_masse);
|
|
|
|
// dans le cas où l'on utilise de l'amortissement numérique
|
|
|
|
if (pa.Amort_visco_artificielle())
|
|
|
|
{ bool initial = true; // def de la matrice (place et valeurs)
|
|
|
|
mat_C_pt = Cal_mat_visqueux_num_expli(*mat_masse,mat_C_pt,delta_X,initial,vitesse_tdt);
|
|
|
|
forces_vis_num.Change_taille(nbddl_X);
|
|
|
|
if (Arret_A_Equilibre_Statique()) // si on veut un équilibre statique, on sauvegarde les forces statiques
|
|
|
|
{ if (vglob_stat != NULL)
|
|
|
|
{vglob_stat->Change_taille(vglobaal.Taille());}
|
|
|
|
else
|
|
|
|
{vglob_stat = new Vecteur(vglobaal.Taille());}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
// mise en place des conditions limites
|
|
|
|
// ---- initialisation des sauvegardes sur matrice et second membre
|
|
|
|
// ce qui ne correspond à rien ici normalement
|
|
|
|
lesCondLim->InitSauve(Ass3->Nb_cas_assemb());
|
|
|
|
//
|
|
|
|
lesCondLim->ImposeConLimtdt(lesMail,lesRef,*mat_masse,vglobaal,Ass3->Nb_cas_assemb()
|
|
|
|
,cas_combi_ddl,vglob_stat);
|
|
|
|
// puis on prépare (si besoin est en fonction du type de matrice) la résolution
|
|
|
|
mat_masse->Preparation_resol();
|
|
|
|
type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul
|
|
|
|
// --- cas des vecteurs utilisés par la méthode de Runge Kutta ---
|
|
|
|
estime_erreur.Change_taille(nbddl_X);
|
|
|
|
val_fonc.Change_taille(2*nbddl_X);
|
|
|
|
der_val_fonc.Change_taille(2*nbddl_X);
|
|
|
|
val_fonc_initiale.Change_taille(2*nbddl_X);der_val_fonc_initiale.Change_taille(2*nbddl_X);
|
|
|
|
val_fonc_final.Change_taille(2*nbddl_X);der_val_fonc_final.Change_taille(2*nbddl_X);
|
|
|
|
// les différents vecteurs sont initialisés à 0
|
|
|
|
if (amortissement_cinetique)
|
|
|
|
Algori::InitialiseAmortissementCinetique(); // initialisation des compteurs pour l'amortissement au cas ou
|
|
|
|
tempsInitialisation.Arret_du_comptage(); // temps cpu
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// mise à jour
|
|
|
|
void AlgoriRungeKutta::MiseAJourAlgo
|
|
|
|
(ParaGlob * paraGlob,LesMaillages * lesMail
|
|
|
|
,LesReferences* lesRef,LesCourbes1D* lesCourbes1D
|
|
|
|
,LesFonctions_nD* lesFonctionsnD
|
|
|
|
,VariablesExporter* varExpor
|
|
|
|
,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage
|
|
|
|
,Charge* charge,LesCondLim* lesCondLim,LesContacts* lescontacts
|
|
|
|
,Resultats* resultats
|
|
|
|
)
|
|
|
|
{ // INITIALISATION globale
|
|
|
|
tempsMiseAjourAlgo.Mise_en_route_du_comptage(); // temps cpu
|
|
|
|
Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_RUNGE_KUTTA); // transfert info
|
|
|
|
|
|
|
|
scale_fac=delta_t; // facteur d'homogénéisation des vecteurs _val_fonc_
|
|
|
|
// qui est le même pour les accélérations et les vitesses
|
|
|
|
// activation des ddl
|
|
|
|
lesMail->Inactive_ddl(); // on commence par inactiver tous les ddl
|
|
|
|
lesMail->Active_un_type_ddl_particulier(X1); // puis on active les ddl qu'ils faut ici
|
|
|
|
lesMail->Active_un_type_ddl_particulier(V1); // on active les Vi
|
|
|
|
lesMail->Active_un_type_ddl_particulier(GAMMA1); // on active les GAMMAi
|
|
|
|
|
|
|
|
|
|
|
|
// mise à jour au cas où
|
|
|
|
Algori::MiseAJourAlgoMere(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp
|
|
|
|
,diversStockage,charge,lesCondLim,lescontacts,resultats);
|
|
|
|
// init indicateur
|
|
|
|
tempsMiseAjourAlgo.Arret_du_comptage(); // temps cpu
|
|
|
|
};
|
|
|
|
|
|
|
|
// Résolution du problème mécanique en explicite dynamique sans contact
|
|
|
|
// si tb_combiner est non null -> un tableau de 2 fonctions
|
|
|
|
// - la première fct dit si on doit valider ou non le calcul à convergence ok,
|
|
|
|
// - la seconde dit si on doit sortir de la boucle ou non à convergence ok
|
|
|
|
//
|
|
|
|
// si la validation est effectuée, la sauvegarde pour le post-traitement est également effectuée
|
|
|
|
// en fonction de la demande de sauvegard,
|
|
|
|
// sinon pas de sauvegarde pour le post-traitement à moins que l'on a demandé un mode debug
|
|
|
|
// qui lui fonctionne indépendamment
|
|
|
|
void AlgoriRungeKutta::CalEquilibre(ParaGlob * paraGlob,LesMaillages * lesMail
|
|
|
|
,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
|
|
|
|
,VariablesExporter* varExpor
|
|
|
|
,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage
|
|
|
|
,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts
|
|
|
|
,Resultats* resultats,Tableau < Fonction_nD* > * tb_combiner)
|
|
|
|
{
|
|
|
|
tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
|
|
|
|
Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_RUNGE_KUTTA); // transfert info
|
|
|
|
OrdreVisu::EnumTypeIncre type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul
|
|
|
|
|
|
|
|
// préparation pour les aspects validation du calcul et sortie contrôlée des incréments
|
|
|
|
int validation_calcul = 1; // init : par défaut la validation est effective si le calcul converge
|
|
|
|
int sortie_boucle_controler_par_fctnD = 0; // init : par défaut la sortie n'est pas contrôler
|
|
|
|
|
|
|
|
// boucle sur les increments de charge qui sont également les incréments de temps
|
|
|
|
// tant que la fin du chargement n'est pas atteinte
|
|
|
|
// dans le cas du premier chargement on calcul de toute manière, ce qui permet
|
|
|
|
// de calculer meme si l'utilisateur indique un increment de charge supérieur
|
|
|
|
// au temps final
|
|
|
|
//initialisation des variables de calcul dans le Runge
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,X1,X_t,X1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,V1,vitesse_t,V1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
|
|
|
|
val_fonc_initiale.Une_partie_egale(1,X_t);
|
|
|
|
val_fonc_initiale.Une_partie_egale(X_t.Taille()+1,vitesse_t*scale_fac);
|
|
|
|
der_val_fonc_initiale.Une_partie_egale(1,vitesse_t);
|
|
|
|
der_val_fonc_initiale.Une_partie_egale(X_t.Taille()+1,acceleration_t*scale_fac);
|
|
|
|
|
|
|
|
icharge++; // on incrémente le chargement -> donne le num d'incr du prochain incr chargé
|
|
|
|
double max_delta_X=0.; // le maxi du delta X
|
|
|
|
double max_var_delta_X=0.; // idem d'une itération à l'autre
|
|
|
|
int nb_step=1; // a priori
|
|
|
|
bool arret=false; // booleen pour arrêter indépendamment de la charge
|
|
|
|
while (((!charge->Fin(icharge))||(icharge == 1))
|
|
|
|
&& (charge->Fin(icharge,true)!=2) // si on a dépassé le nombre d'incrément permis on s'arrête dans tous les cas
|
|
|
|
&& (charge->Fin(icharge,false)!=3) // idem si on a dépassé le nombre d'essai d'incrément permis
|
|
|
|
// 1er appel avec true: pour affichage et second avec false car c'est déjà affiché
|
|
|
|
&& !arret)
|
|
|
|
{ // mise à jour du calcul éventuel des normales aux noeuds -> mise à jour des normales à t
|
|
|
|
// mais ici, on calcule les normales à tdt, et on transfert à t
|
|
|
|
// comme on est au début de l'incrément, la géométrie à tdt est identique à celle à t
|
|
|
|
// sauf "au premier incrément", si l'algo est un sous algo d'un algo combiné
|
|
|
|
// et que l'on suit un précédent algo sur un même pas de temps
|
|
|
|
// qui a aboutit à une géométrie à tdt différente de celle de t
|
|
|
|
// du coup cela permet d'utiliser la nouvelle géométrie pour ce premier incrément
|
|
|
|
lesMail->MiseAjourNormaleAuxNoeuds_de_tdt_vers_T();
|
|
|
|
// passage aux noeuds des vecteurs globaux: F_INT, F_EXT
|
|
|
|
Algori::Passage_aux_noeuds_F_int_t_et_F_ext_t(lesMail);
|
|
|
|
// renseigne les variables définies par l'utilisateur via les valeurs déjà calculées par Herezh
|
|
|
|
Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(lesMail,varExpor,Ass1->Nb_cas_assemb(),*lesRef);
|
|
|
|
varExpor->RenseigneVarUtilisateur(*lesMail,*lesRef);
|
|
|
|
lesMail->CalStatistique(); // calcul éventuel de statistiques
|
|
|
|
// gestion du pas de temps, vérif du delta_t / pas critique
|
|
|
|
this->Gestion_pas_de_temps(true,lesMail,2,nb_step); // 2 signifie cas courant
|
|
|
|
// init des temps début et fin pour RK
|
|
|
|
double tdeb = pa.Variables_de_temps().TempsCourant();
|
|
|
|
double tfi = tdeb + pa.Deltat();
|
|
|
|
scale_fac=delta_t; // facteur d'homogénéisation des vecteurs _val_fonc_
|
|
|
|
// en fait ici il faut récupérer l'incrément de temps pour commander l'appel à Runge Kutta
|
|
|
|
|
|
|
|
// affichage de l'increment de charge
|
|
|
|
bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier
|
|
|
|
if (aff_incr)
|
|
|
|
{cout << "\n======================================================================"
|
|
|
|
<< "\nINCREMENT DE CHARGE : " << icharge
|
|
|
|
<< " intensite " << charge->IntensiteCharge()
|
|
|
|
<< " t= " << charge->Temps_courant()
|
|
|
|
<< " dt= " << ParaGlob::Variables_de_temps().IncreTempsCourant()
|
|
|
|
<< "\n======================================================================";
|
|
|
|
};
|
|
|
|
lesLoisDeComp->MiseAJour_umat_nbincr(icharge); // init pour les lois Umat éventuelles
|
|
|
|
|
|
|
|
// cas d'une résolution par intégration explicite Runge kutta
|
|
|
|
//initialisation des variables de calcul
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,X1,X_t,X1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,V1,vitesse_t,V1);
|
|
|
|
lesMail_->Vect_loc_vers_glob(TEMPS_t,GAMMA1,acceleration_t,GAMMA1);
|
|
|
|
// la partie accélération est initialisée après le calcul
|
|
|
|
// init de paramètres
|
|
|
|
double dernierTemps=0.,dernierdeltat=0.; // valeurs de retour
|
|
|
|
int nombreAppelF=0; // " "
|
|
|
|
erreur_maxi_global=0.; // "
|
|
|
|
|
|
|
|
// appel de la fonction kutta
|
|
|
|
int conver=alg_edp.Pilotage_kutta
|
|
|
|
(cas_kutta,*this,& AlgoriRungeKutta::Dyna_point,& AlgoriRungeKutta::Verif_integrite_Solution
|
|
|
|
,val_fonc_initiale,der_val_fonc_initiale
|
|
|
|
,tdeb,tfi,erreurAbsolue,erreurRelative
|
|
|
|
,val_fonc_final,der_val_fonc_final,dernierTemps,dernierdeltat
|
|
|
|
,nombreAppelF,nb_step,erreur_maxi_global);
|
|
|
|
if ((nb_step > 1) && (ParaGlob::NiveauImpression() >=6))
|
|
|
|
cout << "\n runge kutta : nb-step = " << nb_step;
|
|
|
|
|
|
|
|
// sortie d'info sur l'increment concernant les réactions
|
|
|
|
if ( aff_incr)
|
|
|
|
InfoIncrementReac(lesMail_,inReaction,maxReaction,Ass3->Nb_cas_assemb());
|
|
|
|
|
|
|
|
|
|
|
|
// gestion de l'erreur de retour
|
|
|
|
if (conver !=2) // cas d'une non convergence
|
|
|
|
{ // on appel du kutta adoc sans gestion d'erreur !!
|
|
|
|
double deltat=tfi-tdeb;
|
|
|
|
switch (cas_kutta)
|
|
|
|
{ case 3:
|
|
|
|
{ alg_edp.Runge_Kutta_step23
|
|
|
|
(*this,& AlgoriRungeKutta::Dyna_point,& AlgoriRungeKutta::Verif_integrite_Solution
|
|
|
|
,val_fonc_initiale,der_val_fonc_initiale,tdeb,deltat,val_fonc_final,estime_erreur);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
|
|
{ alg_edp.Runge_Kutta_step34
|
|
|
|
(*this,& AlgoriRungeKutta::Dyna_point,& AlgoriRungeKutta::Verif_integrite_Solution
|
|
|
|
,val_fonc_initiale,der_val_fonc_initiale,tdeb,deltat,val_fonc_final,estime_erreur);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 5:
|
|
|
|
{ alg_edp.Runge_Kutta_step45
|
|
|
|
(*this,& AlgoriRungeKutta::Dyna_point,& AlgoriRungeKutta::Verif_integrite_Solution
|
|
|
|
,val_fonc_initiale,der_val_fonc_initiale,tdeb,deltat,val_fonc_final,estime_erreur);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
cout << "\n erreur , cas Runge kutta non prevu ! "
|
|
|
|
<< "\n AlgoriRungeKutta::Calcul_Equilibre (..";
|
|
|
|
Sortie(1);
|
|
|
|
}
|
|
|
|
if (ParaGlob::NiveauImpression() >=3)
|
|
|
|
{cout << "\n probleme dans la resolution de l'equation constitutive avec Runge Kutta"
|
|
|
|
<< " indication de retour = " << conver << "appel direct de kutta-> erreur estimee= "
|
|
|
|
<< estime_erreur(1)
|
|
|
|
<< "\n AlgoriRungeKutta::Calcul_Equilibre (...";
|
|
|
|
// *** il faut également calculer la dérivée finale --> correspond à l'accélération !! dans le cas d'un appel simple
|
|
|
|
// c'est à dire def de der_val_fonc_final
|
|
|
|
};
|
|
|
|
};
|
|
|
|
// on valide le pas de temps effectivement fait
|
|
|
|
Modif_transi_pas_de_temps(tfi-tdeb);
|
|
|
|
bool modif_temps = charge_->Avance(); // avancement de la charge et donc du temps courant
|
|
|
|
//-- si le temps a changé il faut de nouveau appeler la gestion du pas de temps
|
|
|
|
// car il y a des grandeurs reliées au pas de temps qui y sont calculé
|
|
|
|
if (modif_temps)
|
|
|
|
{tfi = tdeb + pa.Deltat();
|
|
|
|
Modif_transi_pas_de_temps(tfi-tdeb);
|
|
|
|
};
|
|
|
|
|
|
|
|
// il faut également valider les résultats obtenus
|
|
|
|
// récupération des vitesses et positions en fonction des données d'entrées
|
|
|
|
X_tdt.Egale_une_partie_de(val_fonc_final,1);
|
|
|
|
vitesse_tdt.Egale_une_partie_de(der_val_fonc_final,1);
|
|
|
|
acceleration_tdt.Egale_une_partie_de(der_val_fonc_final,X_tdt.Taille()+1);
|
|
|
|
acceleration_tdt /=scale_fac;
|
|
|
|
// mise à jour des ddl
|
|
|
|
lesMail_->Vect_glob_vers_local(TEMPS_tdt,X1,X_tdt,X1);
|
|
|
|
lesMail_->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1);
|
|
|
|
lesMail_->Vect_glob_vers_local(TEMPS_tdt,GAMMA1,acceleration_tdt,GAMMA1);
|
|
|
|
// on prépare le calcul pour la boucle suivante
|
|
|
|
val_fonc_initiale=val_fonc_final;
|
|
|
|
der_val_fonc_initiale=der_val_fonc_final;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// calcul des énergies et affichage des balances
|
|
|
|
// delta_X.Zero(); delta_X += X_tdt; delta_X -= X_t; // X_tdt - X_t
|
|
|
|
Algori::Cal_Transfert_delta_et_var_X(max_delta_X,max_var_delta_X);
|
|
|
|
CalEnergieAffichage(1.,vitesse_tdt,*mat_masse_sauve,delta_X,icharge,brestart,acceleration_tdt,forces_vis_num);
|
|
|
|
if (icharge==1)// dans le cas du premier incrément on considère que la balance vaut l'énergie
|
|
|
|
// cinétique initiale, car vu que l'on ne met pas de CL à t=0, E_cin_0 est difficile à calculer
|
|
|
|
{E_cin_0 = E_cin_tdt - bilan_E + E_int_tdt - E_ext_tdt; };
|
|
|
|
// calcul éventuelle de l'amortissement cinétique
|
|
|
|
int relax_vit_acce = AmortissementCinetique(delta_X,1.,X_tdt,*mat_masse_sauve,icharge,vitesse_tdt);
|
|
|
|
// s'il y a amortissement cinétique il faut re-updater les vitesses
|
|
|
|
if (Abs(relax_vit_acce) == 1) {lesMail->Vect_glob_vers_local(TEMPS_tdt,V1,vitesse_tdt,V1);};
|
|
|
|
// examen de la convergence éventuelle, utilisant le déplacement et/ou le résidu
|
|
|
|
//!!!!!!! n'est prévu pour l'instant que pour l'arrêt en déplacement, !!!!!
|
|
|
|
int arretResidu = 0; // pour l'instant on n'a pas d'arrêt sur le résidu implanté !! s'il le faut
|
|
|
|
// il faut se référer à tchamwa par exemple
|
|
|
|
Pilotage_fin_relaxation_et_ou_residu(relax_vit_acce,0,icharge,arretResidu,arret);
|
|
|
|
|
|
|
|
|
|
|
|
// mise à jour des indicateurs contrôlés par le tableau: *tb_combiner
|
|
|
|
if (tb_combiner != NULL) // cas d'un contrôle via des fonctions nD
|
|
|
|
{if ((*tb_combiner)(1) != NULL)
|
|
|
|
validation_calcul = (*tb_combiner)(1)->Valeur_pour_variables_globales()(1);
|
|
|
|
if ((*tb_combiner)(2) != NULL)
|
|
|
|
sortie_boucle_controler_par_fctnD = (*tb_combiner)(2)->Valeur_pour_variables_globales()(1);
|
|
|
|
};
|
|
|
|
// si on est sans validation, on ne fait rien, sinon on valide l'incrément
|
|
|
|
// avec sauvegarde éventuelle
|
|
|
|
if (validation_calcul)
|
|
|
|
{// actualisation des ddl et des grandeurs actives de t+dt vers t
|
|
|
|
lesMail->TdtversT();
|
|
|
|
// cas du calcul des énergies, passage des grandeurs de tdt à t
|
|
|
|
Algori::TdtversT();
|
|
|
|
// on valide l'activité des conditions limites et condition linéaires
|
|
|
|
lesCondLim->Validation_blocage (lesRef,charge->Temps_courant());
|
|
|
|
//s'il y a remonté des sigma et/ou def aux noeuds et/ou calcul d'erreur
|
|
|
|
bool change =false; // calcul que s'il y a eu initialisation
|
|
|
|
if(prepa_avec_remont) {change = Algori::CalculRemont(lesMail,type_incre,icharge);};
|
|
|
|
if (change) // dans le cas d'une remonté il faut réactiver les bon ddls
|
|
|
|
{lesMail->Inactive_ddl(); lesMail->Active_un_type_ddl_particulier(tenuXVG);};
|
|
|
|
// sauvegarde de l'incrément si nécessaire
|
|
|
|
tempsCalEquilibre.Arret_du_comptage(); // arrêt du compteur pour la sortie
|
|
|
|
Ecriture_base_info(2,lesMail,lesRef,lesCourbes1D,lesFonctionsnD
|
|
|
|
,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts
|
|
|
|
,resultats,type_incre,icharge);
|
|
|
|
// enregistrement du num d'incrément et du temps correspondant
|
|
|
|
list_incre_temps_calculer.push_front(Entier_et_Double(icharge,pa.Variables_de_temps().TempsCourant()));
|
|
|
|
// visualisation éventuelle au fil du calcul
|
|
|
|
VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge
|
|
|
|
,lesCondLim,lesContacts,resultats,type_incre,icharge);
|
|
|
|
tempsCalEquilibre.Mise_en_route_du_comptage(); // on remet en route le compteur
|
|
|
|
brestart = false; // dans le cas où l'on était en restart, on passe l'indicateur en cas courant
|
|
|
|
// test de fin de calcul effectue dans charge via : charge->Fin()
|
|
|
|
icharge++;
|
|
|
|
Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
|
|
|
|
}; // fin du test: if (validation_calcul)
|
|
|
|
}
|
|
|
|
// on remet à jour le nombre d'incréments qui ont été effectués:
|
|
|
|
if (validation_calcul)
|
|
|
|
{icharge--;
|
|
|
|
Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
|
|
|
|
}
|
|
|
|
else // si on ne valide pas le calcul, on reinitialise la charge
|
|
|
|
// c-a-d l'avancement en temps, incrément et facteur multiplicatif
|
|
|
|
// de manière à avoir les mêmes conditions de départ pour le prochain calcul
|
|
|
|
{ charge->Precedant(true);} ;
|
|
|
|
|
|
|
|
tempsCalEquilibre.Arret_du_comptage(); // temps cpu
|
|
|
|
};
|
|
|
|
|
|
|
|
// dernière passe
|
|
|
|
void AlgoriRungeKutta::FinCalcul(ParaGlob * paraGlob,LesMaillages * lesMail,
|
|
|
|
LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
|
|
|
|
,VariablesExporter* varExpor
|
|
|
|
,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage,
|
|
|
|
Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts
|
|
|
|
,Resultats* resultats)
|
|
|
|
{ // passage finale dans le cas d'une visualisation au fil du calcul
|
|
|
|
Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(DYNA_RUNGE_KUTTA); // transfert info
|
|
|
|
type_incre = OrdreVisu::DERNIER_INCRE;
|
|
|
|
VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge
|
|
|
|
,lesCondLim,lesContacts,resultats,type_incre,icharge);
|
|
|
|
// sauvegarde de l'incrément si nécessaire
|
|
|
|
Ecriture_base_info(2,lesMail,lesRef,lesCourbes1D,lesFonctionsnD
|
|
|
|
,lesLoisDeComp,diversStockage,charge,lesCondLim,lesContacts
|
|
|
|
,resultats,type_incre,icharge);
|
|
|
|
// enregistrement du num d'incrément et du temps correspondant
|
|
|
|
list_incre_temps_calculer.push_front(Entier_et_Double(icharge,pa.Variables_de_temps().TempsCourant()));
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//---- gestion des commndes interactives --------------
|
|
|
|
// écoute et prise en compte d'une commande interactive
|
|
|
|
// ramène true tant qu'il y a des commandes en cours
|
|
|
|
bool AlgoriRungeKutta::ActionInteractiveAlgo()
|
|
|
|
{ cout << "\n commande? ";
|
|
|
|
cout << " *** en chantier !! **** \n" << endl;
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
// sortie du schemaXML: en fonction de enu
|
|
|
|
void AlgoriRungeKutta::SchemaXML_Algori(ofstream& sort,const Enum_IO_XML enu) const
|
|
|
|
{
|
|
|
|
switch (enu)
|
|
|
|
{ case XML_TYPE_GLOBAUX :
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XML_IO_POINT_INFO :
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XML_IO_POINT_BI :
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XML_IO_ELEMENT_FINI :
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XML_ACTION_INTERACTIVE :
|
|
|
|
{sort << "\n <!-- ********** algorithme dynamique explicite dfc ******************** -->"
|
|
|
|
<< "\n<xs:complexType name=\"INIT\" >"
|
|
|
|
<< "\n <xs:annotation>"
|
|
|
|
<< "\n <xs:documentation> initialisation de l'algo "
|
|
|
|
<< "\n </xs:documentation>"
|
|
|
|
<< "\n </xs:annotation>"
|
|
|
|
<< "\n</xs:complexType>";
|
|
|
|
sort << "\n<xs:complexType name=\"EXECUTION\" >"
|
|
|
|
<< "\n <xs:annotation>"
|
|
|
|
<< "\n <xs:documentation> execution de l'ensemble de l'algo, sans l'initialisation et la derniere passe "
|
|
|
|
<< "\n </xs:documentation>"
|
|
|
|
<< "\n </xs:annotation>"
|
|
|
|
<< "\n</xs:complexType>";
|
|
|
|
sort << "\n<xs:complexType name=\"FIN_ALGO_EXPLI\" >"
|
|
|
|
<< "\n <xs:annotation>"
|
|
|
|
<< "\n <xs:documentation> fin de l'algo "
|
|
|
|
<< "\n </xs:documentation>"
|
|
|
|
<< "\n </xs:annotation>"
|
|
|
|
<< "\n</xs:complexType>";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XML_STRUCTURE_DONNEE :
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|