717 lines
41 KiB
C++
717 lines
41 KiB
C++
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
|
|
#include "ImpliNonDynaCont.h"
|
|
#include "MathUtil.h"
|
|
/*#ifdef ENLINUX_STREAM
|
|
#include "Profiler.h"
|
|
#endif
|
|
#define USE_PROFILE*/
|
|
|
|
|
|
// CONSTRUCTEURS :
|
|
ImpliNonDynaCont::ImpliNonDynaCont () : // par defaut
|
|
Algori()
|
|
,vglobin(),vglobex(),vglobaal(),vcontact(),forces_vis_num()
|
|
{ };
|
|
|
|
// constructeur en fonction du type de calcul
|
|
// il y a ici lecture des parametres attaches au type
|
|
ImpliNonDynaCont::ImpliNonDynaCont (const bool avec_typeDeCal
|
|
,const list <EnumSousTypeCalcul>& soustype
|
|
,const list <bool>& avec_soustypeDeCal
|
|
,UtilLecture& entreePrinc) :
|
|
Algori(NON_DYNA_CONT,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
|
|
,vglobin(),vglobex(),vglobaal(),vcontact(),forces_vis_num()
|
|
{ // lecture des paramètres attachés au type de calcul (ici aucun)
|
|
switch (entreePrinc.Lec_ent_info())
|
|
{ case 0 :
|
|
{// pour signaler à Algori qu'il n'y a pas eu de lecture de paramètre
|
|
deja_lue_entete_parametre=0;
|
|
// puis appel de la méthode de la classe mère
|
|
Algori::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);
|
|
}
|
|
};
|
|
|
|
// constructeur de copie
|
|
ImpliNonDynaCont::ImpliNonDynaCont (const ImpliNonDynaCont& algo):
|
|
Algori(algo)
|
|
,vglobin(),vglobex(),vglobaal(),vcontact(),forces_vis_num()
|
|
|
|
{};
|
|
|
|
// destructeur
|
|
ImpliNonDynaCont::~ImpliNonDynaCont ()
|
|
{
|
|
};
|
|
// execution de l'algorithme dans le cas non dynamique, implicit, sans contact
|
|
void ImpliNonDynaCont::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)
|
|
{ // 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
|
|
{ // on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
|
|
if (! (charge->Fin(icharge,true) ) )
|
|
Calcul_Equilibre(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
|
|
{ // 1- on fait le calcul d'équilibre
|
|
// on ne continue que si on n'a pas dépasser le nombre d'incréments maxi ou le temps maxi
|
|
if (! (charge->Fin(icharge,true) ) )
|
|
Calcul_Equilibre(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);
|
|
};
|
|
};
|
|
}
|
|
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);
|
|
};
|
|
};
|
|
}
|
|
}
|
|
};
|
|
|
|
// execution de l'algorithme dans le cas non dynamique avec prise en
|
|
// compte du contact
|
|
void ImpliNonDynaCont::Calcul_Equilibre(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(NON_DYNA_CONT); // transfert info
|
|
// on défini globalement que l'on a pas de combinaison des ddl c'est à dire que le seul ddl est X
|
|
int cas_combi_ddl=0;
|
|
// 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 le temps fin stricte, vrai par défaut en implicite
|
|
charge->Change_temps_fin_non_stricte(0);
|
|
// dans le cas où l'on calcul des contraintes et/ou déformation et/ou un estimateur d'erreur
|
|
// à chaque incrément, initialisation
|
|
bool 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);};
|
|
// on définit un nouveau cas d'assemblage
|
|
// à travers la définition d'une instance de la classe assemblage
|
|
Nb_assemb cas_a = lesMail->InitNouveauCasAssemblage(1); // récup du numéro
|
|
Assemblage Ass(cas_a); // stockage numéro
|
|
// 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());
|
|
// mise a zero de tous les ddl actifs et creation des tableaux a t+dt
|
|
// les ddl de position ne sont pas mis a zero ! ils sont initialises
|
|
// 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 actifs avec les conditions initiales
|
|
lesCondLim->Initial(lesMail,lesRef,lesCourbes1D,lesFonctionsnD,true,cas_combi_ddl);
|
|
// activation des ddl de position
|
|
lesMail->Active_un_type_ddl_particulier(X1);
|
|
lesMail->MiseAJourPointeurAssemblage(Ass.Nb_cas_assemb());// mise a jour des pointeurs d'assemblage
|
|
int nbddl = lesMail->NbTotalDdlActifs(); // nb total de ddl
|
|
// choix initial de la matrice de raideur du système linéaire
|
|
Tableau < Mat_abstraite*> tab_mato(1);tab_mato(1)=NULL;
|
|
tab_mato = Choix_matriciel(nbddl,tab_mato,lesMail,lesRef,Ass.Nb_cas_assemb(),lesCondLim,lescontacts);
|
|
Mat_abstraite* mato=tab_mato(1);
|
|
Mat_abstraite& matglob = *mato;
|
|
// choix de la résolution
|
|
matglob.Change_Choix_resolution(pa.Type_resolution(),pa.Type_preconditionnement());
|
|
// vérification d'une singularité éventuelle de la matrice de raideur
|
|
VerifSingulariteRaideurMeca(nbddl,*lesMail);
|
|
// def vecteurs globaux
|
|
vglobin.Change_taille(nbddl); // puissance interne
|
|
vglobex.Change_taille(nbddl); // puissance externe
|
|
vglobaal.Change_taille(nbddl,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); // puissance de contact
|
|
|
|
// 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_tdt.Change_taille(nbddl); delta_X.Change_taille(nbddl);
|
|
var_delta_X.Change_taille(nbddl);
|
|
// vecteur qui globalise toutes les vitesses de l'ensemble des noeuds
|
|
vitesse_t.Change_taille(nbddl);vitesse_tdt.Change_taille(nbddl);
|
|
// vecteur qui globalise toutes les accélérations
|
|
acceleration_t.Change_taille(nbddl);acceleration_tdt.Change_taille(nbddl) ;
|
|
|
|
|
|
// calcul des énergies
|
|
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); F_ext_t.Change_taille(nbddl); // forces généralisées int et ext au pas précédent
|
|
F_int_tdt.Change_taille(nbddl); F_ext_tdt.Change_taille(nbddl); // forces généralisées int et ext au pas actuel
|
|
residu_final.Change_taille(nbddl); // pour la sauvegarde du résidu pour le post-traitement
|
|
|
|
// définition d'un pointeur de fonction d'assemblage en fonction du type voulu
|
|
// définition d'un pointeur de fonction d'assemblage (symétrique ou non)
|
|
// utilisé dans la prise en compte des efforts extérieurs
|
|
void (Assemblage::* assembMat) // le pointeur
|
|
(Mat_abstraite & matglob,const Mat_abstraite & matloc,
|
|
const DdlElement& tab_ddl,const Tableau<Noeud *>&tab_noeud)
|
|
= & Assemblage::AssembMatSym;
|
|
if (pa.Symetrie_matrice())
|
|
// cas d'un assemblage symétrique
|
|
assembMat = & Assemblage::AssembMatSym;
|
|
else // cas d'un assemblage non symétrique
|
|
assembMat = & Assemblage::AssembMatnonSym;
|
|
|
|
// calcul de la largeur de bande relative aux maillages individuellement
|
|
int demi,total;
|
|
lesMail->Largeur_Bande(demi,total,Ass.Nb_cas_assemb());
|
|
total = std::min(total,nbddl);
|
|
|
|
// boucle sur les increments de charge
|
|
icharge = 1;
|
|
//--** // un premier increment pour demmarer le processus
|
|
//--** charge->Avance(); // premier increment de charge ????????? différent des autres algos
|
|
|
|
// 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
|
|
// --- 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
|
|
};
|
|
//--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
|
|
bool 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;
|
|
brestart = true;
|
|
// 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());
|
|
// 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())
|
|
{ // 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);
|
|
};
|
|
|
|
OrdreVisu::EnumTypeIncre type_incre = OrdreVisu::PREMIER_INCRE; // pour la visualisation au fil du calcul
|
|
// Tableau <Tableau <Noeud*> *> tesc;
|
|
/* #ifdef USE_PROFILE
|
|
// préparation du profiler
|
|
if (!ProfilerInit(collectDetailed, bestTimeBase,4000, 50))
|
|
{
|
|
#endif*/
|
|
/* #ifdef USE_PROFILE
|
|
int erro;
|
|
// sortie des infos pour le profiler
|
|
erro= ProfilerDump("\pHerezh.prof");
|
|
ProfilerTerm();
|
|
}
|
|
#endif*/
|
|
// Sortie(1);
|
|
// def d'un indicateur pour le premier contact de chaque increment
|
|
bool premiercontact = true;
|
|
int niveau_substitution = 1; // par défaut on utilise la matrice de raideur mato = tab_mato(1)
|
|
// mise à jour au cas où
|
|
Algori::MiseAJourAlgoMere(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp,diversStockage
|
|
,charge,lesCondLim,lescontacts,resultats);
|
|
|
|
tempsInitialisation.Arret_du_comptage(); // temps cpu
|
|
tempsCalEquilibre.Mise_en_route_du_comptage(); // temps cpu
|
|
|
|
// 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
|
|
bool arret=false; // pour arrêt du calcul au niveau du pilotage
|
|
double max_delta_X=0.; // le maxi du delta X
|
|
double max_var_delta_X=0.; // idem d'une itération à l'autre
|
|
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é
|
|
)
|
|
{ // def de variables
|
|
double maxPuissExt; // maxi de la puissance des efforts externes
|
|
double maxPuissInt; // maxi de la puissance des efforts internes
|
|
double maxReaction; // maxi des reactions
|
|
int inReaction = 0; // pointeur d'assemblage pour le maxi de reaction
|
|
int inSol =0 ; // pointeur d'assemblage du maxi de variation de ddl
|
|
double maxDeltaDdl=0; // // maxi de variation de ddl
|
|
double last_var_ddl_max=0; // maxi var ddl juste après résolutuion, que l'on sauvegarde d'une it à l'autre
|
|
// initialisation de la variable puissance_précédente d'une itération à l'autre
|
|
double puis_precedente = 0.;
|
|
|
|
// 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,Ass.Nb_cas_assemb(),*lesRef);
|
|
varExpor->RenseigneVarUtilisateur(*lesMail,*lesRef);
|
|
lesMail->CalStatistique(); // calcul éventuel de statistiques
|
|
Transfert_ParaGlob_NORME_CONVERGENCE(ConstMath::grand);// on met une norme grande par défaut au début
|
|
if (premiercontact) // modification de la charge et du pas de temps qu'au premier passage
|
|
// mais pas après un changement de statut
|
|
{ Pilotage_du_temps(charge,arret); // appel du Pilotage
|
|
if (arret) break; }// pilotage -> arret du calcul
|
|
|
|
// **** pour l'instant on ne met pas à jour les boites d'encombrement des différenents élément, de frontières
|
|
// **** mais il faudra y penser surtout lorsque les déformations et déplacement deviendront important !!!!!
|
|
|
|
bool aff_incr=pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde); // pour simplifier
|
|
if (premiercontact)
|
|
{
|
|
// affichage de l'increment de charge
|
|
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
|
|
// initialisation des coordonnees et des ddl a tdt en fonctions des
|
|
// ddl imposes et de l'increment du chargement et des conditions linéaires imposées
|
|
bool change_statut = false; // init des changements de statut, ne sert pas ici
|
|
lesCondLim->MiseAJour_tdt
|
|
(pa.Multiplicateur(),lesMail,charge->Increment_de_Temps(),lesRef,charge->Temps_courant()
|
|
,lesCourbes1D,lesFonctionsnD,charge->MultCharge(),change_statut,cas_combi_ddl);
|
|
// definition des elements de contact eventuels
|
|
// - imposition des conditions de non penetration
|
|
lescontacts->DefElemCont(lesMail->Max_var_dep_t_a_tdt());
|
|
}
|
|
else
|
|
cout << "\n============================================================================="
|
|
<< "\n ....... re-analyse du contact ........ "
|
|
<< "\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
|
|
// mise à jour éventuelle de la matrice de raideur en fonction du contact
|
|
Mise_a_jour_Choix_matriciel_contact(tab_mato,Ass.Nb_cas_assemb(),lescontacts,niveau_substitution);
|
|
mato=tab_mato(1);
|
|
|
|
// boucle de convergence sur un increment
|
|
Vecteur * sol; // pointeur du vecteur solution
|
|
// boucle d'equilibre sur un pas
|
|
// on ne réexamine pas le decollement ou de nouveaux contact a chaque iteration,
|
|
// car il peut y avoir beaucoup d'oscillation, du au comportement matériel
|
|
int compteur; // déclaré à l'extérieur de la boucle car utilisé après la boucle
|
|
for (compteur = 0; compteur<= pa.Iterations();compteur++)
|
|
//---//\\//\\// début de la boucle sur les itérations d'équilibres //\\//\\//
|
|
{// initialisation de la matrice et du second membre
|
|
matglob.Initialise (0.);
|
|
vglobin.Zero();
|
|
vglobex.Zero();
|
|
// 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,Ass.Nb_cas_assemb(),*lesRef);
|
|
varExpor->RenseigneVarUtilisateur(*lesMail,*lesRef);
|
|
lesMail->CalStatistique(); // calcul éventuel de statistiques
|
|
Transfert_ParaGlob_COMPTEUR_ITERATION_ALGO_GLOBAL(compteur);
|
|
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
|
|
// mise en place des conditions linéaires sur les ddl
|
|
// les 3 lignes qui suivent ont été rajouté à la suite de la modification de la prise en compte
|
|
// des conditions linéaires (version >= 6.425) maintenant il faudra tester, en particulier
|
|
// peut-être faut-il prendre en compte le change_statut dans la matrice ???
|
|
// dans un premier temps se reporter à AlgoriNonDyna::CalEquilibre
|
|
bool change_statut = false;
|
|
lesCondLim->MiseAJour_condilineaire_tdt
|
|
(pa.Multiplicateur(),lesMail,charge->Increment_de_Temps(),lesRef,charge->Temps_courant()
|
|
,lesCourbes1D,lesFonctionsnD,charge->MultCharge(),change_statut,cas_combi_ddl);
|
|
|
|
// affichage ou non de l'itération
|
|
bool aff_iteration = (pa.freq_affich_iter() > 0) ?
|
|
(aff_incr && (compteur % pa.freq_affich_iter()==0) &&(compteur!=0)) : false ;
|
|
// utilisation d'un comportement tangent simplifié si nécessaire
|
|
if (compteur <= pa.Init_comp_tangent_simple() )
|
|
lesLoisDeComp->Loi_simplifie(true);
|
|
else
|
|
lesLoisDeComp->Loi_simplifie(false);
|
|
lesLoisDeComp->MiseAJour_umat_nbiter(compteur); // init pour les lois Umat éventuelles
|
|
// actualisation des conditions de contact qui peuvent changer
|
|
// la largeur de bande, quand un noeud glisse d'une facette sur une voisine
|
|
if (compteur != 0)
|
|
{ lescontacts->Actualisation(1);
|
|
// mise à jour éventuelle de la matrice de raideur en fonction du contact
|
|
Mise_a_jour_Choix_matriciel_contact(tab_mato,Ass.Nb_cas_assemb(),lescontacts,niveau_substitution);
|
|
mato=tab_mato(1);
|
|
}
|
|
// mise en place du chargement impose sur le second membre
|
|
// et éventuellement sur la raideur en fonction de sur_raideur
|
|
|
|
// mise en place du chargement impose, c-a-d calcul de la puissance externe
|
|
// si pb on sort de la boucle
|
|
if (!(charge->ChargeSMembreRaideur_Im_mecaSolid
|
|
(Ass,lesMail,lesRef,vglobex,matglob,assembMat,pa,lesCourbes1D,lesFonctionsnD)))
|
|
{ Change_PhaseDeConvergence(-10);break;};
|
|
|
|
maxPuissExt = vglobex.Max_val_abs();
|
|
F_ext_tdt = vglobex; // sauvegarde des forces généralisées extérieures
|
|
// - definition des conditions limites de contact
|
|
list <Condilineaire>& listCondLine = lescontacts->ConditionLin(Ass.Nb_cas_assemb());
|
|
// -- appel du calcul de la raideur et du second membre, énergies
|
|
// dans le cas d'un calcul inexploitable arrêt de la boucle
|
|
if (!RaidSmEner(lesMail,Ass,vglobin,matglob)) break;
|
|
// calcul des maxi des puissances internes
|
|
maxPuissInt = vglobin.Max_val_abs();
|
|
F_int_tdt = vglobin; // sauvegarde des forces généralisées intérieures
|
|
// second membre total ( vglobal est identique a vglobin)
|
|
vglobaal = vglobex ; vglobaal += vglobin;
|
|
// calcul des reactions de contact pour les noeuds esclaves
|
|
// dans le repere absolu ( pour la sortie des infos sur le contact)
|
|
// et test s'il y a decollement de noeud en contact
|
|
bool decol;
|
|
lescontacts->CalculReaction(vglobin,decol,Ass.Nb_cas_assemb(),aff_iteration);
|
|
// initialisation des sauvegardes sur matrice et second membre
|
|
lesCondLim->InitSauve(Ass.Nb_cas_assemb());
|
|
// on récupère les réactions avant changement de repère et calcul des torseurs de réaction
|
|
lesCondLim->ReacAvantCHrepere(vglobaal,lesMail,lesRef,Ass.Nb_cas_assemb(),cas_combi_ddl);
|
|
|
|
|
|
// mise en place de condition externe lineaires
|
|
/* string toti;
|
|
cout << "\n matrice et second membre avant mise en place du contact";
|
|
matglob.Affiche1(1,4,1,1,4,1);
|
|
vglobal.Affiche();*/
|
|
// cout <<" \n une valeur continuer ? "; cin >> toti;
|
|
// expression de la raideur et du second membre dans un nouveau repere
|
|
lesCondLim->CoLinCHrepere_ext(matglob,vglobaal,listCondLine,Ass.Nb_cas_assemb(),vglob_stat);
|
|
/* cout << "\n matrice et second membre dans le nouveau repere";
|
|
matglob.Affiche1(1,4,1,1,4,1);
|
|
vglobal.Affiche(); */
|
|
// cout <<" \n une valeur continuer ? "; cin >> toti;
|
|
// sauvegarde des reactions aux ddl bloque
|
|
// en fait ne sert à rien, car les réactions maxi sont calculées dans condlin, mais comme c'est peut-être un peu spécial ici on laisse
|
|
// mais dans les autres algos c'est supprimé !!!!!
|
|
lesCondLim->ReacApresCHrepere(vglobin,lesMail,lesRef,Ass.Nb_cas_assemb(),cas_combi_ddl);
|
|
|
|
// blocage des conditions limites autres que le contact
|
|
lesCondLim->ImposeConLimtdt(lesMail,lesRef,matglob,vglobaal
|
|
,Ass.Nb_cas_assemb(),cas_combi_ddl,vglob_stat);
|
|
/* cout << "\n matrice et second membre apres blocage des CL autres que ceux du contact";
|
|
matglob.Affiche1(1,4,1,1,4,1);
|
|
vglobal.Affiche();*/
|
|
// cout <<" \n une valeur continuer ? "; cin >> toti;
|
|
// blocage des conditions lineaires de contact
|
|
lesCondLim->CoLinBlocage(matglob,vglobaal,Ass.Nb_cas_assemb(),vglob_stat);
|
|
/* cout << "\n matrice et second membre apres blocage des CL de contact";
|
|
matglob.Affiche1(1,4,1,1,4,1);
|
|
vglobal.Affiche();
|
|
cout <<" \n une valeur continuer ? "; cin >> toti;*/
|
|
// calcul du maxi des reactions
|
|
maxReaction = lesCondLim->MaxEffort(inReaction,Ass.Nb_cas_assemb());
|
|
|
|
// --- resolution
|
|
/// matglob.Affiche(1,8,1,1,6,1); // -- pour le debug
|
|
/// vglobal.Affiche(); // -- pour le debug
|
|
// sortie d'info sur l'increment concernant les réactions
|
|
if (compteur != 0)
|
|
if (aff_iteration) InfoIncrementReac(lesMail,compteur,inReaction,maxReaction,Ass.Nb_cas_assemb());
|
|
// calcul des énergies et affichage des balances
|
|
// récupération (initialisation) des ddl position à t et t+dt
|
|
lesMail->Vect_loc_vers_glob(TEMPS_t,X1,X_t,X1);
|
|
lesMail->Vect_loc_vers_glob(TEMPS_tdt,X1,X_tdt,X1);
|
|
// calcul de la variation de ddl / delta t
|
|
// 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);
|
|
Vecteur forces_vis_num; // ne sert pas
|
|
CalEnergieAffichage(delta_X,icharge,brestart,forces_vis_num);
|
|
// test de convergence sur un increment
|
|
// en tenant compte du contact (non decollement)
|
|
if (Convergence(aff_iteration,last_var_ddl_max,vglobaal,maxPuissExt,maxPuissInt,maxReaction,compteur,arret)
|
|
&& !decol)
|
|
{ // sortie des itérations sauf si l'on est en loi simplifiée
|
|
if (lesLoisDeComp->Test_loi_simplife() )
|
|
// cas d'une loi simplifié on remet normal
|
|
lesLoisDeComp->Loi_simplifie(false);
|
|
else
|
|
// cas normal,
|
|
break;
|
|
}
|
|
else if (arret) {break;} // cas ou la méthode Convergence() demande l'arret
|
|
// sinon on continue
|
|
// ici sol en fait = vecglob qui est ecrase par la resolution
|
|
|
|
// ---- resolution ----
|
|
residu_final = vglobaal; // sauvegarde pour le post-traitement
|
|
tempsResolSystemLineaire.Mise_en_route_du_comptage(); // temps cpu
|
|
bool erreur_resolution_syst_lineaire = false; // init
|
|
try
|
|
{// ici sol en fait = vecglob qui est ecrase par la resolution
|
|
sol = &(matglob.Resol_systID
|
|
(vglobaal,pa.Tolerance(),pa.Nb_iter_nondirecte(),pa.Nb_vect_restart()));
|
|
// affichage éventuelle du vecteur solution : deltat_ddl
|
|
if (ParaGlob::NiveauImpression() >= 10)
|
|
{ string entete = " affichage du vecteur solution (delta_ddl) ";
|
|
sol->Affichage_ecran(entete); };
|
|
// retour des ddl dans les reperes generaux, dans le cas où ils ont ete modifie
|
|
// par des conditions linéaires
|
|
lesCondLim->RepInitiaux( *sol,Ass.Nb_cas_assemb());
|
|
//---debug
|
|
//cout << "\ndelta ddl "; for(int i=1;i<=3;i++) { cout << "\nnoe:"<<i<< " ";for (int j=1;j<=3;j++) cout << (*sol)((i-1)*3+j)<<" ";};
|
|
////--fin-debug
|
|
// cout << "\n résolution "; sol->Affiche(); // --- pour le debug
|
|
}
|
|
catch (ErrResolve_system_lineaire excep)
|
|
// cas d'une d'une erreur survenue pendant la résolution
|
|
{ erreur_resolution_syst_lineaire = true; // on prépare l'arrêt
|
|
} // car il faut néanmoins effacer les marques avant l'arrêt
|
|
catch (ErrSortieFinale)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortieFinale toto;
|
|
throw (toto);
|
|
}
|
|
catch ( ... )
|
|
{ erreur_resolution_syst_lineaire = true; // on prépare l'arrêt
|
|
}
|
|
tempsResolSystemLineaire.Arret_du_comptage(); // temps cpu
|
|
|
|
// effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée
|
|
lesCondLim->EffMarque();
|
|
if (pa.ContactType()) lescontacts->EffMarque();
|
|
|
|
if (erreur_resolution_syst_lineaire)
|
|
{Change_PhaseDeConvergence(-9); // on signale une divergence due à la résolution
|
|
break; // arrêt si on avait détecté une erreur à la résolution
|
|
};
|
|
|
|
// affichage éventuelle du vecteur solution : deltat_ddl
|
|
if (ParaGlob::NiveauImpression() >= 10)
|
|
{ string entete = " affichage du vecteur solution (delta_ddl) apres retour dans le repere principal";
|
|
sol->Affichage_ecran(entete);
|
|
};
|
|
// calcul du maxi de variation de ddl
|
|
maxDeltaDdl = sol->Max_val_abs(inSol); last_var_ddl_max=maxDeltaDdl;
|
|
double maxDeltatDdl_signe=(*sol)(inSol); // récupération de la grandeur signée
|
|
// pilotage à chaque itération: ramène: maxDeltaDdl,sol modifiés éventuellement et insol
|
|
Pilotage_chaque_iteration(sol,maxDeltaDdl,compteur,lesMail);
|
|
// sortie d'info sur l'increment concernant les variations de ddl
|
|
if (aff_iteration&&(ParaGlob::NiveauImpression() > 1))
|
|
InfoIncrementDdl(lesMail,inSol,maxDeltatDdl_signe,Ass.Nb_cas_assemb());
|
|
|
|
// sol->Affiche(); // -- pour le debug
|
|
// actualisation des ddl actifs a t+dt
|
|
lesMail->PlusDelta_tdt(*sol,Ass.Nb_cas_assemb());
|
|
//---//\\//\\// fin de la boucle sur les itérations d'équilibres //\\//\\//
|
|
}
|
|
// effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée
|
|
// car ici on n'est pas passé par cette endroit si l'on a convergé
|
|
if (compteur<= pa.Iterations())
|
|
{lescontacts->EffMarque(); lesCondLim->EffMarque();};
|
|
// gestion de la fin des itérations
|
|
if (!Pilotage_fin_iteration_implicite(compteur))
|
|
{ // cas d'une non convergence
|
|
// comme on incrémente pas les ddl on remet cependant les ddl
|
|
// et les grandeurs actives de tdt aux valeurs de ceux de t
|
|
lesMail->TversTdt();
|
|
}
|
|
else
|
|
{ // réexamen du contact pour voir s'il n'y a pas de nouveau element de contact
|
|
if (lescontacts->Nouveau(lesMail->Max_var_dep_t_a_tdt()))
|
|
// !!! il faudra prevoir un compteur sur le reexamen du contact
|
|
premiercontact = false; // retour sur l'increment pour un re examen
|
|
// avec les nouveaux elements de contact
|
|
else
|
|
{ premiercontact = true; //pour le prochain increment
|
|
// actualisation des ddl et des grandeurs actives de t+dt vers t
|
|
lesMail->TdtversT();
|
|
lesMail->Mise_a_jour_boite_encombrement_elem_front(TEMPS_tdt);
|
|
// 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(X1);};
|
|
// 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);
|
|
}
|
|
}
|
|
// effacement du marquage de ddl bloque du au conditions lineaire de contact
|
|
// déjà fait ??????????? sans doute à supprimer
|
|
lescontacts->EffMarque();
|
|
} //-- fin du while ((charge->Fin())||(icharge == 1))
|
|
// exploitation des resultats en fonctions de l'instance de Resultats
|
|
// on remet à jour le nombre d'incréments qui ont convergés:
|
|
icharge--;
|
|
Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL(icharge);
|
|
|
|
// fin des calculs
|
|
tempsCalEquilibre.Arret_du_comptage(); // temps cpu
|
|
// passage finale dans le cas d'une visualisation au fil du calcul
|
|
type_incre = OrdreVisu::DERNIER_INCRE;
|
|
VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge
|
|
,lesCondLim,lescontacts,resultats,type_incre,icharge);
|
|
// sauvegarde de l'état finale 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()));
|
|
};
|