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 "AlgoriNonDyna.h"
# include "MatBand.h"
# include <cmath>
//------- 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 AlgoriNonDyna : : 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 ( NON_DYNA ) ; // 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 ) ;
2023-09-03 10:10:17 +02:00
tempsInitialisation . Arret_du_comptage ( ) ; // temps cpu
temps_transfert_court_algo . Mise_en_route_du_comptage ( ) ; // comptage cpu
2023-05-03 17:23:49 +02:00
distribution_CPU_algo . Passage_Equilibrage_aux_CPU ( ) ;
2023-09-03 10:10:17 +02:00
temps_transfert_court_algo . Arret_du_comptage ( ) ; // comptage cpu
tempsInitialisation . Mise_en_route_du_comptage ( ) ; // temps cpu
paraGlob - > Init_tableau ( distribution_CPU_algo . Tableau_element_CPU_en_cours ( )
, distribution_CPU_algo . Tab_indique_CPU_en_cours ( ) ) ;
2023-05-03 17:23:49 +02:00
} ;
# endif
////------- debug
//cout << "\n debug AlgoriNonDyna::InitAlgorithme ";
//lesMail->Noeud_LesMaille(1,120).Affiche(9);
//cout << endl;
////-------- fin debug
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 // dans le cas où il y a de la mécanique, on active X1
{ lesMail - > Active_un_type_ddl_particulier ( X1 ) ;
} ;
} ;
// on défini globalement que l'on a pas de combinaison des ddl c'est à dire que le seul ddl est X
// ou TEMP pour la température ...
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
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
if ( Ass_ = = NULL ) Ass_ = new Assemblage ( lesMail - > InitNouveauCasAssemblage ( 1 ) ) ;
Assemblage & Ass = * Ass_ ;
// 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 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
lesCondLim - > Initial ( lesMail , lesRef , lesCourbes1D , lesFonctionsnD , true , cas_combi_ddl ) ;
// L'algorithme peut s'appliquer à plusieurs types de problème: création des types de ddl du pb en fonction
// des physiques
lesMail - > Active_un_type_ddl_particulier ( lesMail - > Ddl_representatifs_des_physiques ( ) ) ;
// lesMail->Active_un_type_ddl_particulier(X1);
lesMail - > MiseAJourPointeurAssemblage ( Ass . Nb_cas_assemb ( ) ) ; // mise a jour des pointeurs d'assemblage
// mise en place éventuelle du bulk viscosity: pas prévue au départ donc exploratoire !!
lesMail - > Init_bulk_viscosity ( pa . BulkViscosity ( ) , pa . CoefsBulk ( ) ) ;
//---- arrêt intro thermique --- la suite à suivre !!!!!!!!!
int nbddl_X = lesMail - > NbTotalDdlActifs ( ) ; // nb total de ddl
// choix de la matrice de raideur du système linéaire (calcul éventuellement d'une largeur de bande ad oc)
Choix_matriciel ( nbddl_X , tab_mato , lesMail , lesRef , Ass . Nb_cas_assemb ( ) , lesCondLim ) ;
matglob = tab_mato ( 1 ) ; // par défaut c'est la première matrice
// dans le cas où l'on veut également utiliser du Newton modifié, on definit la matrice de sauvegarde
if ( deb_newton_modifie > = 0 )
Choix_matriciel ( nbddl_X , tab_matsauve , lesMail , lesRef , Ass . Nb_cas_assemb ( ) , lesCondLim ) ;
matsauve = tab_matsauve ( 1 ) ; // par défaut c'est la première matrice
// dans le cas où l'on veut utiliser une raideur moyenne on définit les sous-matrices
// pour chaque niveau secondaire
if ( deb_raideur_moyenne > = 0 )
// on boucle sur les groupes de matrices
{
// comme il s'agit du premier dimensionnement on commence par tout supprimer
// au cas où quelque chose existait déjà
{ int taille = tab_tab_matmoysauve . Taille ( ) ;
for ( int i = 1 ; i < = taille ; i + + )
if ( tab_tab_matmoysauve ( i ) ! = NULL )
{ Tableau < Mat_abstraite * > * tab_matmoysauve_i = tab_tab_matmoysauve ( i ) ; // par simplicité
int tail = tab_matmoysauve_i - > Taille ( ) ;
for ( int j = 1 ; j < = tail ; j + + )
if ( ( * tab_matmoysauve_i ) ( j ) ! = NULL )
delete ( * tab_matmoysauve_i ) ( j ) ;
} ;
} ;
// puis on redimensionne le tableau maître de pointeurs
// nb_mat_secondaire = le nb de table secondaire + 1
int nb_mat_secondaire = tab_mato . Taille ( ) ;
tab_tab_matmoysauve . Change_taille ( nb_raideur_moyenne , NULL ) ;
// maintenant on crée les sous tableaux de pointeurs nulles
for ( int i = 1 ; i < = nb_raideur_moyenne ; i + + )
{ tab_tab_matmoysauve ( i ) = new Tableau < Mat_abstraite * > ;
tab_tab_matmoysauve ( i ) - > Change_taille ( nb_mat_secondaire , NULL ) ;
} ;
// maintenant on peu créer les matrices
for ( int i = 1 ; i < = nb_raideur_moyenne ; i + + )
{ Tableau < Mat_abstraite * > & tab_matmoysauve_i = * tab_tab_matmoysauve ( i ) ;
Choix_matriciel ( nbddl_X , tab_matmoysauve_i , lesMail , lesRef , Ass . Nb_cas_assemb ( ) , lesCondLim ) ;
} ;
} ;
// on refait une passe dans le cas où l'utilisateur veut une renumérotation des pointeurs
// d'assemblage, globalement
{ bool premier_calcul = true ; bool nouvelle_situation_CLL = false ;
int niveau_substitution = 0 ; // on intervient sur toutes les matrices
Gestion_stockage_et_renumerotation_sans_contact
( lesContacts , premier_calcul , lesMail , nouvelle_situation_CLL
, lesCondLim , lesRef , tab_mato , Ass . Nb_cas_assemb ( )
, niveau_substitution ) ;
} ;
// choix de la résolution pour la première matrice
matglob - > Change_Choix_resolution ( pa . Type_resolution ( ) , pa . Type_preconditionnement ( ) ) ;
// vérification d'une singularité éventuelle de la matrice de raideur
// à cause d'un trop faible nombre de pti
VerifSingulariteRaideurMeca ( nbddl_X , * lesMail ) ;
2023-05-03 17:23:49 +02:00
// def vecteurs globaux
2021-09-26 14:31:23 +02:00
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
// dans le cas où on initialise les ddl_tdt(n) avec les ddl_t(n)+delta_ddl(n-1), def de grandeurs
X_t . Change_taille ( nbddl_X ) ; X_tdt . Change_taille ( nbddl_X ) ; delta_X . Change_taille ( nbddl_X ) ;
delta_prec_X . Change_taille ( nbddl_X ) ; var_delta_X . 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_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
// définition d'un pointeur de fonction d'assemblage en fonction du type voulu
// (symetrique ou non), utilisé dans la prise en compte des efforts extérieurs
if ( pa . Symetrie_matrice ( ) )
// cas d'un assemblage symétrique
assembMat = & Assemblage : : AssembMatSym ;
else // cas d'un assemblage non symétrique
assembMat = & Assemblage : : AssembMatnonSym ;
// dans le cas où l'on fait du line search on dimensionne des vecteurs
// globaux supplémentaires
if ( pa . Line_search ( ) )
{ sauve_deltadept = new Vecteur ( nbddl_X ) ;
Vres = new Vecteur ( nbddl_X ) ;
sauve_dept_a_tdt = new Vecteur ( nbddl_X ) ;
v_travail = new Vecteur ( nbddl_X ) ;
}
else if ( acceleration_convergence )
// idem pour l'accélération de convergence, pour la sauvegarde du résidu
{ Vres = new Vecteur ( nbddl_X ) ;
for ( int ni = 1 ; ni < = nb_vec_cycle + 2 ; ni + + )
{ if ( cas_acceleration_convergence < 4 )
{ Vi ( ni ) . Change_taille ( nbddl_X ) ; }
else if ( cas_acceleration_convergence = = 4 )
{ Vi ( ni ) . Change_taille ( 1 ) ; } ;
Yi ( ni ) . Change_taille ( nbddl_X ) ;
} ;
} ;
// initi boucle sur les 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 )
2023-05-03 17:23:49 +02:00
{ lesMail - > Mise_a_jour_boite_encombrement_elem_front ( TEMPS_t ) ;
2021-09-26 14:31:23 +02:00
// 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 ( ) ;
2023-05-03 17:23:49 +02:00
// // definition des elements de contact eventuels
// // et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact)
// lesContacts->DefElemCont(0.); // au début le déplacement des noeuds est nul
2021-09-26 14:31:23 +02:00
if ( pa . ContactType ( ) = = 4 ) // cas particulier du type 4 de contact où on utilise les forces internes
{ // def d'un type générique, utilisé pour le transfert des forces internes, vers les conteneurs noeuds
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 pour un vecteur force à chaque noeud
TypeQuelconque typQ_gene_int ( FORCE_GENE_INT , X1 , gt ) ;
lesMail - > AjoutConteneurAuNoeud ( typQ_gene_int ) ;
} ;
// definition des elements de contact eventuels
// et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact)
// double diam_mini = lesMail->Min_dist2Noeud_des_elements(TEMPS_0);
// lesContacts->DefElemCont(2. * diam_mini);
try {
2023-05-03 17:23:49 +02:00
// definition des elements de contact eventuels
// et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact)
2021-09-26 14:31:23 +02:00
bool nevez_contact = lesContacts - > DefElemCont ( 0. ) ; // au début le déplacement des noeuds est nul
int niveau_substitution = 0 ; // on intervient sur toutes les matrices
bool premier_calcul = true ;
// mise à jour éventuelle de la matrice de raideur en fonction du contact
2023-05-03 17:23:49 +02:00
//bool changement_sur_matrice =
G estion_stockage_et_renumerotation_avec_contact
2021-09-26 14:31:23 +02:00
( premier_calcul , lesMail , nevez_contact , lesCondLim
, lesRef , tab_mato , Ass . Nb_cas_assemb ( ) , lesContacts , niveau_substitution ) ;
matglob = tab_mato ( 1 ) ;
}
// sortie anormale de l'initialisation du contact
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 inconnue
{ cout < < " \n **** >>>> ERREUR inconnuee en en initialisant le contact ***** " ;
if ( ParaGlob : : NiveauImpression ( ) > = 4 )
cout < < " \n AlgoriNonDyna::InitAlgorithme(.. " ;
cout < < endl ;
} ;
} ;
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 ;
////---debug
//{cout << "\n debug1: AlgoriNonDyna::InitAlgorithme(...";
// Noeud& noe = lesMail->Noeud_LesMaille(1,4);
// noe.Affiche();
//}
////--fin-debug // 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 ( ) ) ) ;
// on ferme tout de suite le baseinfo en lecture de manière à éviter des pb de switch
// lecture -> écriture, si le fichier est très gros
entreePrinc - > Fermeture_base_info ( ) ;
icharge = this - > Num_restart ( ) ; //+1;
brestart = true ;
////---debug
//{cout << "\n debug2: AlgoriNonDyna::InitAlgorithme(...";
// Noeud& noe = lesMail->Noeud_LesMaille(1,4);
// noe.Affiche();
//}
////--fin-debug // ouverture de base info
// 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 ) ;
////---debug
//{cout << "\n debug3: AlgoriNonDyna::InitAlgorithme(...";
// Noeud& noe = lesMail->Noeud_LesMaille(1,4);
// noe.Affiche();
//}
//--fin-debug // ouverture de base info
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 ( ) ) ;
////---debug
//{cout << "\n debug4: AlgoriNonDyna::InitAlgorithme(...";
// Noeud& noe = lesMail->Noeud_LesMaille(1,4);
// noe.Affiche();
//}
////--fin-debug // ouverture de base info
// on remet à jour les éléments pour le contact s'il y du contact présumé
if ( pa . ContactType ( ) )
{ // mise à jour pour le contact s'il y du contact présumé
if ( 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 ) ;
} ;
// sinon ok, et on met à jour la boite d'encombrement compte tenue des nouvelles coordonnées
lesMail - > Mise_a_jour_boite_encombrement_elem_front ( TEMPS_t ) ;
2023-05-03 17:23:49 +02:00
bool nevez_contact = lesContacts - > Actualisation ( 0 ) ;
// *** test
bool nevez_bis_contact = lesContacts - > Nouveau ( 0. ) ;
nevez_contact = ( nevez_contact | | nevez_bis_contact ) ; //double dep_max)
2021-09-26 14:31:23 +02:00
int niveau_substitution = 0 ; // on intervient sur toutes les matrices
bool premier_calcul = true ;
// mise à jour éventuelle de la matrice de raideur en fonction du contact
2023-05-03 17:23:49 +02:00
//bool changement_sur_matrice =
Gestion_stockage_et_renumerotation_avec_contact
2021-09-26 14:31:23 +02:00
( premier_calcul , lesMail , nevez_contact , lesCondLim
, lesRef , tab_mato , Ass . Nb_cas_assemb ( ) , lesContacts , niveau_substitution ) ;
matglob = tab_mato ( 1 ) ;
if ( deb_newton_modifie > = 0 )
( * matsauve ) = ( * matglob ) ;
// dans le cas où l'on veut utiliser une raideur moyenne on redéfinit les matrices
if ( deb_raideur_moyenne > = 0 )
{ Tableau < Mat_abstraite * > & tab_matmoysauve = * tab_tab_matmoysauve ( 1 ) ;
tab_matmoysauve . Change_taille ( nb_raideur_moyenne ) ;
for ( int i = 1 ; i < = nb_raideur_moyenne ; i + + )
( * tab_matmoysauve ( i ) ) = ( * matglob ) ;
} ;
} ;
} ;
// 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 ) ;
} ;
} ;
// init de var glob
Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL ( icharge ) ;
//--fin cas de restart et/ou de sauvegarde--------
type_incre = OrdreVisu : : PREMIER_INCRE ; // pour la visualisation au fil du calcul
2023-05-03 17:23:49 +02:00
2021-09-26 14:31:23 +02:00
// 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 ) ;
} ;
// 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
} ;
// mise à jour
void AlgoriNonDyna : : 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 ( NON_DYNA ) ; // transfert info
// on regarde le type de calcul: tout n'est pas possible pour l'instant !!
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 ;
case THERMIQUE :
{ cout < < " \n *** cas non operationnel: pour l'instant MiseAjourAlgo "
< < " n'est prevu que pour de la meca ... "
< < " \n AlgoriNonDyna::MiseAJourAlgo(...) " ;
Sortie ( 1 ) ;
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 ( ) ;
// il faut sans doute faire plus de chose, par exemple activer les ddl particuliers
cout < < " \n *** cas non operationnel: pour l'instant MiseAjourAlgo "
< < " n'est prevu que pour de la meca ... "
< < " \n AlgoriNonDyna::MiseAJourAlgo(...) " ;
Sortie ( 1 ) ;
}
else // dans le cas où il y a de la mécanique, et que l'on a récupéré des ddl de vitesse et d'accélération
{ // on les inactives
lesMail - > Inactive_un_type_ddl_particulier ( V1 ) ;
lesMail - > Inactive_un_type_ddl_particulier ( GAMMA1 ) ;
lesMail - > Active_un_type_ddl_particulier ( X1 ) ;
} ;
// mise à jour au cas où
Algori : : MiseAJourAlgoMere ( paraGlob , lesMail , lesRef , lesCourbes1D , lesFonctionsnD , varExpor , lesLoisDeComp
, diversStockage , charge , lesCondLim , lesContacts , resultats ) ;
tempsMiseAjourAlgo . Arret_du_comptage ( ) ; // temps cpu
} ;
// calcul de l'équilibre
// calcul
// 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 AlgoriNonDyna : : 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 ( NON_DYNA ) ; // transfert info
// 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
// on vérifie que le pas de temps est correcte: on propose le deltat actuel qui sera modifié s'il n'est pas bon
double deltat_actuel = pa . Deltat ( ) ;
pa . Modif_Detat_dans_borne ( deltat_actuel ) ;
// def d'un type générique, utilisé pour le transfert des forces internes, vers les conteneurs noeuds
int dim = ParaGlob : : Dimension ( ) ; if ( ParaGlob : : AxiSymetrie ( ) ) dim - - ;
Coordonnee coor ( dim ) ; // un type coordonnee typique
Grandeur_coordonnee gt ( coor ) ; // une grandeur typique de type Grandeur_coordonnee
// def d'un type quelconque représentatif pour un vecteur force à chaque noeud
TypeQuelconque typQ_gene_int ( FORCE_GENE_INT , X1 , gt ) ;
// on définit un type générique qui sert pour passer aux noeuds les positions à l'itération 0
TypeQuelconque typQ_XI_ITER_0 ( XI_ITER_0 , X1 , gt ) ;
// on met à jour des variables de travail
Assemblage & Ass = * Ass_ ;
Vecteur vglobal_sauv ; // vecteur de sauvegarde éventuel, dans le cas de l'utilisation de matrices de raideur secondaire
double max_delta_X = 0. ; // le maxi du delta X
double max_var_delta_X = 0. ; // idem d'une itération à l'autre
// 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_pilotage = false ; // pour arrêt du calcul au niveau du pilotage
bool premier_calcul = true ; // utilisé pour l'initialisation de l'incrément avec le pas précédent
int indicCycleContact = 0 ; // def d'un indicateur donnant la situation dans le cycle de contact
// un booléen pour uniquement gérer le fait que dans la boucle globale on fait le test après le test du while
// d'où pour le temps final, on peut sortir de la boucle globale sans avoir convergé, ce qui n'est pas bon
bool pas_de_convergence_pour_l_instant = 1 ;
icharge + + ; // on incrémente le chargement -> donne le num d'incr du prochain incr chargé
while ( ( ( ! charge - > Fin ( icharge , ! pas_de_convergence_pour_l_instant ) ) // on n'affiche la situation
// que si on a eu convergence
| | pas_de_convergence_pour_l_instant | | ( 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é
& & ( ! pa . EtatSortieEquilibreGlobal ( ) )
)
{ 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. ;
Transfert_ParaGlob_NORME_CONVERGENCE ( ConstMath : : grand ) ; // on met une norme grande par défaut au début
// affichage de l'increment de charge
bool aff_incr = pa . Vrai_commande_sortie ( icharge , temps_derniere_sauvegarde ) ; // pour simplifier
bool change_statut = false ; // init des changements de statut, ne sert pas ici
// 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 ) ;
////--- debug
//if (premier_calcul)
// cout << "\toto "<<flush;
////--- fin debug
// premier contact de l'incrément
if ( ! indicCycleContact ) // 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_pilotage ) ; // appel du Pilotage
if ( arret_pilotage ) break ; // pilotage -> arret du calcul
2023-05-03 17:23:49 +02:00
# ifdef UTILISATION_MPI
2023-07-06 08:42:57 +02:00
// seule le process 0 s'occupe de la sortie
if ( ParaGlob : : Monde ( ) - > rank ( ) = = 0 )
2023-05-03 17:23:49 +02:00
# endif
2021-09-26 14:31:23 +02:00
if ( aff_incr )
{ cout < < " \n ====================================================================== "
< < " \n INCREMENT DE CHARGE : " < < icharge
< < " intensite " < < charge - > IntensiteCharge ( )
< < " t= " < < charge - > Temps_courant ( )
< < " dt= " < < ParaGlob : : Variables_de_temps ( ) . IncreTempsCourant ( )
< < " \n ====================================================================== " ;
} ;
// -- on regarde si l'on doit initialiser l'incrément avec le pas précédent: cas d'un premier calcul
// sinon c'est fait à la fin lors de la préparation pour le prochain incrément
lesMail - > Vect_loc_vers_glob ( TEMPS_t , X1 , X_t , X1 ) ; // sert pour calculer le delta_X après CL (**)
if ( ( ! premier_calcul ) & & ( delta_t_precedent_a_convergence > 0. )
& & pa . IniIncreAvecDeltaDdlPrec ( ) & & Pilotage_init_Xtdt ( ) ) // si oui, calcul
{ // de X_tdt = X_t + deltat(n)/deltat(n-1) *(X_tdt(n-1) - X_t(n-1))
delta_X = delta_prec_X ; // init avec le précédent delta_X qui a convergé
X_tdt = X_t ; delta_X * = pa . Deltat ( ) * pa . IniIncreAvecDeltaDdlPrec ( ) ; X_tdt + = delta_X ;
// passage de ces nouvelles positions aux niveaux des maillages
lesMail - > Vect_glob_vers_local ( TEMPS_tdt , X1 , X_tdt , X1 ) ;
} ;
// -- initialisation des coordonnees et des ddl a tdt en fonctions des
// ddl imposes et de l'increment du chargement: change_statut sera recalculé ensuite
lesCondLim - > MiseAJour_tdt
( pa . Multiplicateur ( ) , lesMail , charge - > Increment_de_Temps ( ) , lesRef , charge - > Temps_courant ( )
, lesCourbes1D , lesFonctionsnD , charge - > MultCharge ( ) , change_statut , cas_combi_ddl ) ;
// on récupère les nouvelles positions globalement de manière à pouvoir calculer le delta_X pour le contact
lesMail - > Vect_loc_vers_glob ( TEMPS_tdt , X1 , X_tdt , X1 ) ;
// 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 ) ;
// --- calcul des éléments de contact: (correspond à la définition de la surface de contact)
// definition ou mise à jour, des elements de contact eventuels
// - imposition (en fonction de l'algorithme de contact) de conditions particulières de penetration (nulle par exemple)
if ( pa . ContactType ( ) ) // traitement différent lors du premier incément calculé (premier passage) puis des passages courants
{ bool a_changer = false ; // init par défaut
if ( premier_calcul )
{ a_changer = lescontacts - > DefElemCont ( max_delta_X ) ; }
else
{ // on supprime les éléments inactifs testés à l'incr prec dans Actualisation()
a_changer = lescontacts - > SuppressionDefinitiveElemInactif ( ) ;
2023-05-03 17:23:49 +02:00
bool a_changer_nouveau = lescontacts - > Nouveau ( max_delta_X ) ;
a_changer = a_changer | | a_changer_nouveau ;
2021-09-26 14:31:23 +02:00
} ;
int niveau_substitution = 0 ; // on intervient sur toutes les matrices
if ( premier_calcul | | a_changer )
2023-05-03 17:23:49 +02:00
{ //bool changement_sur_matrice =
Gestion_stockage_et_renumerotation_avec_contact
2021-09-26 14:31:23 +02:00
( premier_calcul , lesMail , a_changer , lesCondLim , lesRef
, tab_mato , Ass . Nb_cas_assemb ( ) , lescontacts , niveau_substitution ) ;
matglob = tab_mato ( 1 ) ;
} ;
} ;
}
else
{ if ( arret_pilotage ) break ; // pilotage -> arret du calcul
2023-05-03 17:23:49 +02:00
# ifdef UTILISATION_MPI
2023-07-06 08:42:57 +02:00
// seule le process 0 s'occupe de la sortie
if ( ParaGlob : : Monde ( ) - > rank ( ) = = 0 )
2023-05-03 17:23:49 +02:00
# endif
cout < < " \n ============================================================================= "
2021-09-26 14:31:23 +02:00
< < " \n ....... re-analyse du contact ........ "
< < " \n INCREMENT 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
// récupération (initialisation) des ddl position à t
lesMail - > Vect_loc_vers_glob ( TEMPS_t , X1 , X_t , X1 ) ;
// on démarre avec le compteur à 0 et on sauvegarde la position finale à l'itération 0
lesMail - > Quelconque_glob_vers_local ( X1 , X_tdt , typQ_XI_ITER_0 ) ;
// boucle de convergence sur un increment
Vecteur * sol ; // pointeur du vecteur solution
bool arret_convergence = false ;
int tab_matmoysauve_rempli = 0 ; // ne sert que pour les matrices de raideur moyenne
// for (compteur = 0; compteur<= pa.Iterations();compteur++)
for ( compteur = 0 ; ( compteur < = pa . Iterations ( ) ) & & ( ! pa . EtatSortieEquilibreGlobal ( ) ) ; 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 ( ) ;
if ( pa . ContactType ( ) )
vcontact . Zero ( ) ;
vglobaal . Zero ( ) ; // puissance totale
// init de var glob
Transfert_ParaGlob_COMPTEUR_ITERATION_ALGO_GLOBAL ( compteur ) ;
// prise en compte du cas particulier ou l'utilisateur demande
// une mise à jour des conditions limites à chaque itération
if ( cL_a_chaque_iteration )
{ // -- initialisation des coordonnees et des ddl a tdt en fonctions des
// ddl imposes et de l'increment du chargement: change_statut sera recalculé ensuite
lesCondLim - > MiseAJour_tdt
( pa . Multiplicateur ( ) , lesMail , charge - > Increment_de_Temps ( ) , lesRef , charge - > Temps_courant ( )
, lesCourbes1D , lesFonctionsnD , charge - > MultCharge ( ) , change_statut , cas_combi_ddl ) ;
// on récupère les nouvelles positions globalement de manière à pouvoir calculer le delta_X pour le contact
lesMail - > Vect_loc_vers_glob ( TEMPS_tdt , X1 , X_tdt , X1 ) ;
// 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 ) ;
} ;
// renseigne les variables définies par l'utilisateur via les valeurs déjà calculées par Herezh
// if (compteur > 0)
{ 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
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
//---debug
//lesMail->Vect_loc_vers_glob(TEMPS_tdt,X1,X_tdt,X1);
//cout << "\ninitial Xtdt "; for(int i=1;i<=3;i++) { cout << "\nnoe:"<<i<< " ";cout << X_tdt(i)<<" ";}
//for (int j=1;j<=3;j++) cout << X_tdt((i-1)*3+j)<<" ";};
//--fin-debug
// mise en place des conditions linéaires (ne comprend pas les conditions linéaires de contact éventuelles)
lesCondLim - > MiseAJour_condilineaire_tdt
( pa . Multiplicateur ( ) , lesMail , charge - > Increment_de_Temps ( ) , lesRef , charge - > Temps_courant ( )
, lesCourbes1D , lesFonctionsnD , charge - > MultCharge ( ) , change_statut , cas_combi_ddl ) ;
//---debug
//lesMail->Vect_loc_vers_glob(TEMPS_tdt,X1,X_tdt,X1);
//cout << "\naprès condlin Xtdt "; for(int i=1;i<=3;i++) { cout << "\nnoe:"<<i<< " ";cout << X_tdt(i)<<" ";}
//for(int i=1;i<=3;i++) { cout << "\nnoe:"<<i<< " ";for (int j=1;j<=3;j++) cout << X_tdt((i-1)*3+j)<<" ";};
//--fin-debug
// 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, peut changer la position du noeud
// qui est projeté sur la facette dans le cas de l'algorithme cinématique
if ( pa . ContactType ( ) )
{ int niveau_substitution = 0 ; // on intervient sur toutes les matrices
2023-05-03 17:23:49 +02:00
bool a_changer = lescontacts - > Actualisation ( 1 ) ;
2021-09-26 14:31:23 +02:00
// mise à jour éventuelle des matrices de raideur en fonction du contact
if ( a_changer )
2023-05-03 17:23:49 +02:00
{ //bool changement_sur_matrice =
Gestion_stockage_et_renumerotation_avec_contact
2021-09-26 14:31:23 +02:00
( premier_calcul , lesMail , a_changer , lesCondLim , lesRef
, tab_mato , Ass . Nb_cas_assemb ( ) , lescontacts , niveau_substitution ) ;
matglob = tab_mato ( 1 ) ;
} ;
}
else if ( change_statut ) // sinon il faut éventuellement tenir compte du cht du au CLL
// NB: c'est pris en compte directement dans le contact, quand celui-ci est actif
{ bool premier_calcul_inter = false ; // si pas de contact, normalement il n'y a pas à changer
int niveau_substitution = 0 ; // on intervient sur toutes les matrices
Gestion_stockage_et_renumerotation_sans_contact
( lescontacts , premier_calcul_inter , lesMail , change_statut
, lesCondLim , lesRef , tab_mato , Ass . Nb_cas_assemb ( )
, niveau_substitution ) ;
} ;
// -- appel du calcul de la raideur et du second membre, énergies
// dans le cas d'un calcul inexploitable arrêt de la boucle
// avec prise en compte éventuelle d'un newton modifié
if ( ( deb_newton_modifie > = 0 ) & & ( compteur > = deb_newton_modifie ) & & ( compteur < = fin_newton_modifie ) )
{ if ( ( ( compteur - deb_newton_modifie ) % nb_iter_NM ) = = 0 )
// on est au début du cycle -> on récupère la partie effort externes relative aux chargements
{ matsauve - > Initialise ( 0. ) ;
( * matsauve ) - = ( * matglob ) ; // change de signe
// -- 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 ;
// on sauvegade la raideur seule
( * matsauve ) + = ( * matglob ) ; // sans les efforts externes
}
else
// sinon on est en newton modifié, on utilise la matrice modifiée pour la raideur
{ ( * matglob ) + = ( * matsauve ) ;
// on calcul uniquement le second membre
if ( ! SecondMembreEnerg ( lesMail , Ass , vglobin ) ) break ;
} ;
}
else
// sinon on regarde si on utilise de la raideur moyenne
{ if ( deb_raideur_moyenne > = 0 )
{ if ( ( compteur > = ( deb_raideur_moyenne - nb_raideur_moyenne ) )
& & ( compteur < = deb_raideur_moyenne ) & & ( compteur < = fin_raideur_moyenne ) )
// phase de premier remplissage
{ tab_matmoysauve_rempli + + ;
if ( tab_matmoysauve_rempli > nb_raideur_moyenne ) tab_matmoysauve_rempli = 1 ;
( * tab_tab_matmoysauve ( tab_matmoysauve_rempli ) ) ( 1 ) - > Initialise ( 0. ) ;
// -- 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
, ( * ( * tab_tab_matmoysauve ( tab_matmoysauve_rempli ) ) ( 1 ) ) ) )
break ;
// on met à jour la raideur
( * matglob ) + = ( * ( * tab_tab_matmoysauve ( tab_matmoysauve_rempli ) ) ( 1 ) ) ;
( * ( * tab_tab_matmoysauve ( tab_matmoysauve_rempli ) ) ( 1 ) )
* = ( 1. / nb_raideur_moyenne ) ; // on prépare la moyenne
}
else
// phase d'exploitation
{ tab_matmoysauve_rempli + + ;
if ( tab_matmoysauve_rempli > nb_raideur_moyenne ) tab_matmoysauve_rempli = 1 ;
( * tab_tab_matmoysauve ( tab_matmoysauve_rempli ) ) ( 1 ) - > Initialise ( 0. ) ;
// -- 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
, ( * ( * tab_tab_matmoysauve ( tab_matmoysauve_rempli ) ) ( 1 ) ) ) )
break ;
( * ( * tab_tab_matmoysauve ( tab_matmoysauve_rempli ) ) ( 1 ) )
* = ( 1. / nb_raideur_moyenne ) ; // on prépare la moyenne
// on met à jour la raideur utilisée
for ( int ii = 1 ; ii < = nb_raideur_moyenne ; ii + + )
( * matglob ) + = ( * ( * tab_tab_matmoysauve ( ii ) ) ( 1 ) ) ;
} ;
}
else
{ // sinon calcul classique NR
if ( ! RaidSmEner ( lesMail , Ass , vglobin , ( * matglob ) ) ) break ;
} ;
} ;
// calcul des maxi des puissances internes
maxPuissInt = vglobin . Max_val_abs ( ) ;
//cout << "\n debug AlgoNonDyna::CalEquilibre: maxPuissInt => "<<maxPuissInt
// << " compteur= " << compteur <<flush;
// dans le cas où l'on utilise de l'amortissement numérique le second membre
// et la matrice de raideur sont modifiés
if ( pa . Amort_visco_artificielle ( ) )
{ Algori : : Cal_mat_visqueux_num_stat ( * matglob , forces_vis_num ) ;
vglobaal + = forces_vis_num ;
} ;
F_int_tdt = vglobin ; // sauvegarde des forces généralisées intérieures
if ( pa . ContactType ( ) = = 4 ) // si contact on passe les efforts aux noeuds
// on transfert les forces internes aux noeuds
lesMail - > Quelconque_glob_vers_local ( X1 , F_int_tdt , typQ_gene_int ) ;
// 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 ; } ;
//cout << "\n debug AlgoNonDyna::CalEquilibre: vglobex => "; vglobex.Affiche();
// cas des efforts de contact, contribution second membre et matrice,
// suivant le type de contact on utilise ou on recalcule les reactions de contact éventuelles (contact et frottement)
if ( pa . ContactType ( ) ) // et des énergies développées pendant le contact
// dans le cas où le calcul est inexploitable (pb dans le calcul) arrêt de la boucle
if ( ! RaidSmEnerContact ( lescontacts , Ass , vcontact , ( * matglob ) ) ) break ;
//cout << "\n debug AlgoNonDyna::CalEquilibre: vcontact => "; vcontact.Affiche();
// on globalise tout pour les forces externes généralisées
F_ext_tdt_prec = F_ext_tdt ; // sauvegarde des valeurs de l'itération précédente
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 ;
//cout << "\n debug AlgoNonDyna::CalEquilibre: vglobal => "; vglobal.Affiche();
// 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 (pour les contacts actifs)
// mais ici, il n'y a pas de modification des éléments de contact (elles ont été faites dans lescontacts->Actualisation())
bool decol = false ; // création et init de decol
if ( pa . ContactType ( ) )
lescontacts - > CalculReaction ( vglobin , decol , Ass . Nb_cas_assemb ( ) , aff_iteration ) ;
// - definition éventuelle de conditions limites linéaires de contact, en fonction des éléments du contact existant à ce niveau
// (certains contacts (par pénalisation par exemple) ne produise pas de conditions linéaires)
const Tableau < Condilineaire > * tabCondLine = NULL ;
if ( ( pa . ContactType ( ) = = 1 ) | | ( pa . ContactType ( ) = = 3 ) )
tabCondLine = & ( lescontacts - > ConditionLin ( Ass . Nb_cas_assemb ( ) ) ) ;
// - 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 ) ;
// ---exploratoire
// // mise en place des conditions linéaires (ne comprend pas les conditions linéaires de contact éventuelles)
// lesCondLim->MiseAJour_condilineaire_tdt
// (pa.Multiplicateur(),lesMail,charge->Increment_de_Temps(),lesRef,charge->Temps_courant()
// ,lesCourbes1D,lesFonctionsnD,charge->MultCharge(),change_statut,cas_combi_ddl);
// ---exploratoire
// -->> expression de la raideur et du second membre dans un nouveau repere
// mais ici on n'impose pas les conditons, on fait simplement le changement de repère
lesCondLim - > CoLinCHrepere_int ( ( * matglob ) , vglobaal , Ass . Nb_cas_assemb ( ) , vglob_stat ) ;
if ( pa . ContactType ( ) = = 1 )
lesCondLim - > CoLinCHrepere_ext ( ( * matglob ) , vglobaal , * tabCondLine , Ass . Nb_cas_assemb ( ) , vglob_stat ) ;
if ( pa . ContactType ( ) = = 3 ) // *** exploratoire
lesCondLim - > CoLinUneOpe_ext ( ( * matglob ) , vglobaal , * tabCondLine , Ass . Nb_cas_assemb ( ) , vglob_stat ) ;
// sauvegarde des reactions pour les ddl bloques (simplement)
// 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 ) ; // a voir au niveau du nom
// prise en compte des conditions imposée sur la matrice et second membres (donc dans le nouveau repère)
lesCondLim - > ImposeConLimtdt ( lesMail , lesRef , ( * matglob ) , vglobaal , Ass . Nb_cas_assemb ( )
, cas_combi_ddl , vglob_stat ) ;
if ( pa . ContactType ( ) ! = 3 ) // *** exploratoire
// cas des conditions linéaires: répercutions sur matrices et second membre
// (blocage de toutes les conditions lineaires, quelque soit leur origines ext ou int donc contact éventuel)
lesCondLim - > CoLinBlocage ( ( * matglob ) , vglobaal , Ass . Nb_cas_assemb ( ) , vglob_stat ) ;
// calcul du maxi des reactions
maxReaction = lesCondLim - > MaxEffort ( inReaction , Ass . Nb_cas_assemb ( ) ) ;
// 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+dt
lesMail - > Vect_loc_vers_glob ( TEMPS_tdt , X1 , X_tdt , X1 ) ;
// calcul de la variation de ddl / delta t
// 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 ) ;
2023-07-06 08:42:57 +02:00
# ifdef UTILISATION_MPI
// cas d'un calcul //, pour l'instant seul le CPU 0 sont concerné
if ( ( ParaGlob : : Monde ( ) - > rank ( ) = = 0 ) & & ( permet_affichage > 3 ) )
# else
if ( permet_affichage > 3 )
# endif
2021-09-26 14:31:23 +02:00
{ cout < < " \n --- |max_var_DeltaDdl|= " < < max_var_delta_X
< < " , |max_deltaDdl|= " < < max_delta_X < < flush ; } ;
// ---dans le cas du mode debug on sort éventuellement les infos au fil du calcul (un peu bricolé)
if ( ( mode_debug > 0 ) | | ( pa . EtatSortieEtatActuelDansCVisu ( ) ) )
{ bool a_sortir_debug = false ; // pour éviter une division par 0 du test (compteur % mode_debug == 0)
if ( pa . EtatSortieEtatActuelDansCVisu ( ) ) { a_sortir_debug = true ; }
else if ( compteur % mode_debug = = 0 ) { a_sortir_debug = true ; } ;
if ( a_sortir_debug )
{ // on passe les déplacements de tdt à t
tempsCalEquilibre . Arret_du_comptage ( ) ; // on arrête le compteur pour la sortie
lesMail - > Vect_glob_vers_local ( TEMPS_t , X1 , X_tdt , X1 ) ;
// visualisation éventuelle au fil du calcul: essentiellement la déformée
VisuAuFilDuCalcul ( paraGlob , lesMail , lesRef , lesCourbes1D , lesFonctionsnD , lesLoisDeComp , diversStockage , charge
, lesCondLim , lescontacts , resultats , type_incre , ( icharge * 1000000 + compteur ) ) ;
tempsCalEquilibre . Mise_en_route_du_comptage ( ) ; // on remet en route le compteur
// on remet les choses dans l'ordre initial
lesMail - > Vect_glob_vers_local ( TEMPS_t , X1 , X_t , X1 ) ;
} ;
} ;
CalEnergieAffichage ( delta_X , icharge , brestart , forces_vis_num ) ;
// test de convergence sur un increment
// en tenant compte éventuellement du contact (non decollement) decol = false systématiquement si pas de contact
decol = false ; // pour debugger
2023-05-03 17:23:49 +02:00
bool arret_iteration = false ;
# ifdef UTILISATION_MPI
2023-07-06 08:42:57 +02:00
// seule le process 0 s'occupe de la convergence
if ( ParaGlob : : Monde ( ) - > rank ( ) = = 0 )
{
2023-05-03 17:23:49 +02:00
# endif
2021-09-26 14:31:23 +02:00
if ( Convergence ( aff_iteration , last_var_ddl_max , vglobaal , maxPuissExt , maxPuissInt , maxReaction , compteur , arret_convergence )
& & ! decol )
{ // on sort de la boucle 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,
2023-05-03 17:23:49 +02:00
{ arret_iteration = true ; } ; //break;};
2021-09-26 14:31:23 +02:00
}
else if ( arret_convergence )
2023-05-03 17:23:49 +02:00
{ arret_iteration = true ; } ; //break;} // cas ou la méthode Convergence() demande l'arret
# ifdef UTILISATION_MPI
2023-07-06 08:42:57 +02:00
} ;
2023-09-03 10:10:17 +02:00
temps_transfert_court_algo . Mise_en_route_du_comptage ( ) ; // comptage cpu
2023-05-03 17:23:49 +02:00
broadcast ( * ParaGlob : : Monde ( ) , arret_iteration , 0 ) ;
2023-09-03 10:10:17 +02:00
temps_transfert_court_algo . Arret_du_comptage ( ) ; // fin comptage cpu
2023-05-03 17:23:49 +02:00
# endif
if ( arret_iteration )
break ;
2021-09-26 14:31:23 +02:00
// sinon on continue
// pour le pilotage ou pour l'accélération de convergence, sauvegarde du résidu
if ( pa . Line_search ( ) | | ( acceleration_convergence ) )
( * Vres ) = vglobaal ;
// ---- resolution ----
tempsResolSystemLineaire . Mise_en_route_du_comptage ( ) ; // temps cpu
bool erreur_resolution_syst_lineaire = false ; // init
int nb_matrice_secondaire = tab_mato . Taille ( ) ; // = 1 par défaut, mais on peut en avoir d'autre
int niveau_substitution = 1 ; // par défaut on utilise la matrice de raideur matglob = tab_mato(1)
2023-05-03 17:23:49 +02:00
# ifdef UTILISATION_MPI
2023-07-06 08:42:57 +02:00
// seule le process 0 fait la résolution globale
if ( ParaGlob : : Monde ( ) - > rank ( ) = = 0 )
{
2023-05-03 17:23:49 +02:00
# endif
2021-09-26 14:31:23 +02:00
while ( niveau_substitution < = nb_matrice_secondaire )
{ // on sauvegarde éventuellement le second membre
if ( nb_matrice_secondaire > 1 ) // cela veut dire que l'on est suceptible de faire plusieurs boucles
{ if ( niveau_substitution = = 1 )
// init au premier passage
{ vglobal_sauv = vglobaal ;
matglob - > Transfert_vers_mat ( * tab_mato ( niveau_substitution + 1 ) ) ;
}
else
{ vglobaal = vglobal_sauv ; // récup du second membre
// s'il y a une matrice de substitution supplémentaire, on sauvegarde
if ( nb_matrice_secondaire > niveau_substitution )
tab_mato ( niveau_substitution ) - > Transfert_vers_mat
( * tab_mato ( niveau_substitution + 1 ) ) ;
if ( ParaGlob : : NiveauImpression ( ) > = 3 )
{ cout < < " \n nouvelle resolution du systeme avec la matrice " < < niveau_substitution
< < " de substitution " < < endl ;
} ;
} ;
} ;
residu_final = vglobaal ; // sauvegarde pour le post-traitement
try
{ // ici sol en fait = vecglob qui est ecrase par la resolution
sol = & ( tab_mato ( niveau_substitution ) - > 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
if ( pa . ContactType ( ) ! = 3 ) // *** exploratoire
lesCondLim - > RepInitiaux ( * sol , Ass . Nb_cas_assemb ( ) ) ;
erreur_resolution_syst_lineaire = false ;
break ; // on sort du while
}
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
}
// il y a eu un pb de résolution
niveau_substitution + + ;
} ;
tempsResolSystemLineaire . Arret_du_comptage ( ) ; // temps cpu
// cas où on a eu au final une erreur de résolution
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
} ;
// idem si la norme de la solution est infinie
// 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
if ( ( std : : isinf ( maxDeltaDdl ) ) | | ( std : : isnan ( maxDeltaDdl ) ) )
{ if ( ParaGlob : : NiveauImpression ( ) > 2 )
cout < < " \n resolution du systeme lineaire global (equilibre global) norme de delta_ddl infinie "
< < maxDeltaDdl ;
Change_PhaseDeConvergence ( - 9 ) ; // on signale une divergence due à la résolution
break ; // arrêt si on avait détecté une erreur à la résolution
} ;
if ( ( ( ParaGlob : : NiveauImpression ( ) > 6 ) & & ( ParaGlob : : NiveauImpression ( ) < 10 ) )
| | ( permet_affichage > 6 ) )
{ cout < < " \n vecteur solution: " ; sol - > Affiche ( ) ; } ;
// pilotage à chaque itération: ramène: maxDeltaDdl,csol 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 ( ) ) ;
2023-05-03 17:23:49 +02:00
# ifdef UTILISATION_MPI
}
else // s'il s'agit d'un process de calcul élémentaire
{ sol = & vglobaal ; // il faut affecter sol pour récupérer ensuite la solution
} ;
// le process 0 transmet aux autres process le vecteur résultat
2023-09-03 10:10:17 +02:00
temps_transfert_long_algo . Mise_en_route_du_comptage ( ) ; // comptage cpu
2023-05-03 17:23:49 +02:00
//// essai pour remplacer broadcast
// int nb_process = ParaGlob::Monde()->size();
// mpi::request reqs1;
// if (ParaGlob::Monde()->rank() == 0)
// // NB: le process 0 c'est le main
// {for (int i=1;i<nb_process;i++) // < absolu, donc le max c'est nb_process-1
// {reqs1 = sol->Ienvoi_MPI(i, 38);}
// }
// else
// {reqs1 = sol->Irecup_MPI(0,38);};
//// ParaGlob::Monde()->barrier();
// reqs1.wait();
// mpi::request Ienvoi_MPI(int dest, int tag) const
// {return ParaGlob::Monde()->isend(dest,tag,v,taille);};
// mpi::request Irecup_MPI(int source, int tag) const
sol - > Broadcast ( 0 ) ;
// broadcast(*ParaGlob::Monde(), *sol, 0);
// synchronisation ici de tous les process (à supprimer par la suite car n'est
// pas nécessaire pour le déroulementa priori ?? )
// ParaGlob::Monde()->barrier();
2023-09-03 10:10:17 +02:00
temps_transfert_long_algo . Arret_du_comptage ( ) ; // fin comptage cpu
2023-05-03 17:23:49 +02:00
# endif
// effacement du marquage de ddl bloque du au conditions lineaire imposée par l'entrée
lesCondLim - > EffMarque ( ) ;
if ( ( pa . ContactType ( ) = = 1 ) | | ( pa . ContactType ( ) = = 3 ) )
lescontacts - > EffMarque ( ) ;
2021-09-26 14:31:23 +02:00
// suite du pilotage
// ------------------------------------------------------------
// |on regarde s'il faut utiliser l'algorithme de line search |
// ------------------------------------------------------------
bool avec_line_search = false ;
if ( pa . Line_search ( ) )
{ // la méthode de line_search incrémente la solution
// même s'il n'y a pas de mise en oeuvre de la méthode
avec_line_search = Line_search1
( * sauve_deltadept , puis_precedente , * Vres , lesMail , sol
, compteur , * sauve_dept_a_tdt , charge , vglobex , Ass , * v_travail ,
lesCondLim , vglobaal , lesRef , vglobin , Ass . Nb_cas_assemb ( ) , cas_combi_ddl , lesCourbes1D , lesFonctionsnD ) ;
}
else
//cas ou l'on ne fait pas de line seach
{ // on regarde si l'on veut une accélération de convergence, par une méthode d'extrapolation
if ( acceleration_convergence )
{ sauve_sol = * sol ; // on sauvegarde le vecteur solution, car = vglobal qui va être écrasé
if ( ! ( AccelerationConvergence ( aff_iteration , ( * Vres ) , lesMail , compteur , X_t , delta_X , charge , vglobex
, Ass , sauve_sol , lesCondLim , vglobaal , lesRef , vglobin , Ass . Nb_cas_assemb ( ) , cas_combi_ddl , lesCourbes1D , lesFonctionsnD )
= = 4 ) )
// 4 cas ou on a a priori convergé avec l'extrapolation,
// les positions finales des noeuds a été modifiée en conséquence
// donc dans ce cas on ne fait rien, sinon on continue normalement
{ // actualisation des ddl actifs a t+dt à chaque incrément
lesMail - > PlusDelta_tdt ( sauve_sol , Ass . Nb_cas_assemb ( ) ) ;
} ;
}
else
// cas normal, sans accélération
{ // actualisation des ddl actifs a t+dt à chaque incrément
lesMail - > PlusDelta_tdt ( * sol , Ass . Nb_cas_assemb ( ) ) ;
//---debug
//lesMail->Vect_loc_vers_glob(TEMPS_tdt,X1,X_tdt,X1);
//cout << "\nXtdt+deltaddl "; for(int i=1;i<=3;i++) { cout << "\nnoe:"<<i<< " ";for (int j=1;j<=3;j++) cout << X_tdt((i-1)*3+j)<<" ";};
//--fin-debug
} ;
} ;
} ;
//---//\\//\\// 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é
lesCondLim - > EffMarque ( ) ;
// 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 ) ;
} ;
if ( ( pa . ContactType ( ) = = 1 ) | | ( pa . ContactType ( ) = = 3 ) ) lescontacts - > EffMarque ( ) ;
2023-05-03 17:23:49 +02:00
// === gestion de la fin des itérations ===
# ifdef UTILISATION_MPI
// seule le process 0 a fait la résolution globale
// il gère seul également la convergence, mais il doit tenir au courant les autres process
Algori : : Passage_indicConvergenceAuxProcCalcul ( ) ;
// ce qui permet le déroulement correct de la suite pour tous les process
# endif
2021-09-26 14:31:23 +02:00
if ( ( ! Pilotage_fin_iteration_implicite ( compteur ) ) | | ( pa . EtatSortieEquilibreGlobal ( ) ) )
// if ((!Pilotage_fin_iteration_implicite(compteur))
// && (!pa.EtatSortieEtatActuelDansBI()))
{ // cas d'une non convergence
pas_de_convergence_pour_l_instant = 1 ;
// 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 ( ) ;
lescontacts - > TversTdt ( ) ; // idem pour les contacts éventuels
// on remet indicCycleContact à 0 pour que le pilotage sur le temps se refasse
indicCycleContact = 0 ;
// ------ cas particulier où on a une divergence qui demande de remonter sur plus d'un incrément
if ( Algori : : PhaseDeConvergence ( ) = = - 8 )
{ int nb_incr_en_arriere = 3 ; // !!!!! nombre actuellement arbitraire -> par la suite mettre dans les para
if ( Controle_retour_sur_un_increment_enregistre ( nb_incr_en_arriere , icharge ) )
{ // cas ou on a réussi à trouver un incrément sauvegardé adoc = maintenant icharge
int cas = 2 ;
this - > Lecture_base_info ( cas , lesMail , lesRef , lesCourbes1D , lesFonctionsnD , lesLoisDeComp , diversStockage
, charge , lesCondLim , lescontacts , resultats , icharge ) ;
// comme les conditions limites cinématiques peuvent être différentes en restart
// on libére 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 ( ) ) ;
// on remet à jour les éléments pour le contact s'il y du contact présumé
if ( pa . ContactType ( ) )
lesMail - > Mise_a_jour_boite_encombrement_elem_front ( TEMPS_t ) ;
brestart = true ; // on signale que l'on repars avec un restart
} ;
// sinon on ne fait rien, on se contente du pilotage de divergence existant
} ;
// ------ fin cas particulier où on a une divergence qui demande de remonter sur plus d'un incrément
}
else
{ // --- sinon calcul correcte
pas_de_convergence_pour_l_instant = 0 ;
if ( permet_affichage > 0 )
{ cout < < " \n --- |max_var_DeltaDdl|= " < < max_var_delta_X
< < " , |max_deltaDdl|= " < < max_delta_X < < flush ; } ;
if ( pa . ContactType ( ) )
{ // actualisation du contact en fonction du dernier incrément
2023-05-03 17:23:49 +02:00
bool nevez_contact = lescontacts - > Actualisation ( 0 ) ;
2021-09-26 14:31:23 +02:00
// réexamen du contact pour voir s'il n'y a pas de nouveau element de contact
// en fait on fera au plus deux passages supplémentaire, sinon la boucle peut être infini,
// à la fin du second passage, on regarde s'il y a décollement, si oui on relâche et on refait un passage
// sinon on valide
//I)--------------
if ( indicCycleContact = = 0 )
2023-05-03 17:23:49 +02:00
{ bool nouveau_contact = lescontacts - > Nouveau ( lesMail - > Max_var_dep_t_a_tdt ( ) ) ;
nevez_contact = nevez_contact | | nouveau_contact ;
2021-09-26 14:31:23 +02:00
if ( nevez_contact )
{ indicCycleContact = 1 ; } // on a de nouveau contact on refait le deuxième cycle
else
// sinon, on n'a pas de nouveau contact, on regarde s'il y a du relachement
{ indicCycleContact = 2 ; } ;
}
else if ( indicCycleContact = = 1 )
{ indicCycleContact = 2 ; } // pour regarder le relachement
else
{ indicCycleContact = 0 ; } ; // pas de newcontact, ni de relachement donc c'est ok
//II)---------------
bool relachement_contact = false ;
if ( indicCycleContact = = 2 )
{ relachement_contact = lescontacts - > RelachementNoeudcolle ( ) ;
if ( relachement_contact )
{ indicCycleContact = 3 ; } // pour une dernière boucle d'équilibre
else
{ indicCycleContact = 0 ; } ; // pas de relachement donc ok
} ;
if ( ( nevez_contact | | relachement_contact )
)
{ int niveau_substitution = 0 ; // on intervient sur toutes les matrices
bool nouveau = ( nevez_contact | | relachement_contact ) ;
2023-05-03 17:23:49 +02:00
//bool changement_sur_matrice =
Gestion_stockage_et_renumerotation_avec_contact
2021-09-26 14:31:23 +02:00
( premier_calcul , lesMail , nouveau , lesCondLim
, lesRef , tab_mato , Ass . Nb_cas_assemb ( ) , lescontacts , niveau_substitution ) ;
matglob = tab_mato ( 1 ) ;
} ;
}
else
// concerne ici le cas où c'est un problème sans contact (=contact non activé)
{ indicCycleContact = 0 ; } ; //pour le prochain increment
if ( ! ( pa . ContactType ( ) ) | | ( indicCycleContact = = 0 ) )
{
// --- pour l'instant en test, mais normalement on fait la sauvegarde et la sortie d'info éventuelle avant le passage de t à tdt
// ce qui permet de différencier les grandeurs à t et celles à tdt
// non !!! ce n'est pas une bonne chose, car il y a plein de grandeur que l'on ne sauve qu'à t, or t c'est la valeur de départ donc cela fait en pratique
// un décalage de temps d'un incrément !! c'est pas une bonne chose, il faudrait intervenir à plein d'endroit. donc on fait t et tdt = idem
//
// // 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()));
// // visualisation éventuelle au fil du calcul
// VisuAuFilDuCalcul(paraGlob,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,lesLoisDeComp,diversStockage,charge
// ,lesCondLim,lescontacts,resultats,type_incre,icharge);
// --- fin de la partie en test
// on regarde si l'on doit initialiser le prochain incrément avec le pas précédent
if ( pa . IniIncreAvecDeltaDdlPrec ( ) ) // si oui on sauvegarde le delta_X actuel / delta_t
{ // 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 = X_tdt; delta_X -= X_t; delta_X /= pa.Deltat();
// 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 ) ;
// si le pas de temps est trop petit il y aura un pb
if ( pa . Deltat ( ) > ConstMath : : unpeupetit )
{ delta_prec_X = delta_X / pa . Deltat ( ) ; // on sauvegarde le delta_X qui a convergé
delta_t_precedent_a_convergence = pa . Deltat ( ) ;
}
else // sinon on neutralise
{ delta_prec_X . Zero ( ) ; // on neutralise
delta_t_precedent_a_convergence = - 1 ; // pour signaler une valeur non utilisable
}
} ;
// 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 ( ) ;
lescontacts - > 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 ( ) ) ;
tempsCalEquilibre . Arret_du_comptage ( ) ; // pour enregistrer
//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: ici on est après le passage de tdt vers t donc, les grandeurs à t et tdt sont identiques !!
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 ( ) ; // en remet en route pour la suite
} ; // -- fin du test: if (validation_calcul)
premier_calcul = false ; // -- on enregistre le fait que l'on n'est plus au premier passage
brestart = false ; // dans le cas où l'on était en restart, on passe l'indicateur en cas courant
if ( validation_calcul )
{ icharge + + ;
// init de var glob
Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL ( icharge ) ;
} ;
} ; //- fin du cas où l'incrément est validé pour l'équilibre avec le contact
} ; // -- fin du cas ou le calcul converge
// cas particulier où la sortie de la boucle est pilotée
if ( sortie_boucle_controler_par_fctnD & & ( ! pas_de_convergence_pour_l_instant ) )
break ;
} ; // -- fin du while sur les incréments de charge
// on remet à jour le nombre d'incréments qui ont convergés:
if ( validation_calcul )
{ icharge - - ;
Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL ( icharge ) ;
// dans le cas d'une suite de sous algo on signale qu'il y a validation
if ( ( tb_combiner ! = NULL ) & & ( ( * tb_combiner ) ( 1 ) ! = NULL ) )
( * tb_combiner ) ( 3 ) = NULL ;
}
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 ) ;
// dans le cas d'une suite de sous algo on signale qu'il n'y a pas validation
if ( ( tb_combiner ! = NULL ) & & ( ( * tb_combiner ) ( 1 ) ! = NULL ) )
( * tb_combiner ) ( 3 ) = ( * tb_combiner ) ( 1 ) ;
} ;
tempsCalEquilibre . Arret_du_comptage ( ) ; // temps cpu
} ;
// dernière passe
void AlgoriNonDyna : : 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 )
{
// fin des calculs
type_incre = OrdreVisu : : DERNIER_INCRE ;
Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL ( NON_DYNA ) ; // transfert info
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 ( ) ) ) ;
} ;
// accélération de convergence, suivant une méthode MMPE (modified minimal polynomial extrapolation)
// ou une méthode pour essayer de régler les oscillations en dents de scie : n'a pas l'air de marcher
// compteur : compteur d'itération
// retour = 0: l'accélération n'est pas active (aucun résultat, aucune action, aucune sauvegarde)
// = 1: phase de préparation: sauvegarde d'info, mais aucun résultat
// = 2: calcul de l'accélération mais ... pas d'accélération constatée
// = 3: calcul de l'accélération et l'accélération est effective
// dans le cas différent de 0 et 1, le programme a priori, change le stockage des conditions
// limites, en particulier CL linéaire, mais avec des hypothèses, pour les sorties de réactions
// etc, il vaut mieux refaire une boucle normale avec toutes les initialisation ad hoc
// affiche: indique si l'on veut l'affichage ou non des infos
// on travaille avec les deltaX, car les deltaX valent 0 pour les ddl bloqués (imposés)
int AlgoriNonDyna : : AccelerationConvergence ( bool affiche , const Vecteur & vres , LesMaillages * lesMail
, const int & compteur , const Vecteur & X_t , const Vecteur & delta_X , Charge * charge , Vecteur & vglobex
, Assemblage & Ass , const Vecteur & delta_delta_X , LesCondLim * lesCondLim , Vecteur & vglobal
, LesReferences * lesRef , Vecteur & vglobin , const Nb_assemb & nb_casAssemb
, int cas_combi_ddl , LesCourbes1D * lesCourbes1D , LesFonctions_nD * lesFonctionsnD )
{ // ne fonctionne que si le compteur est supérieur à 0
if ( compteur < = 0 ) return 0 ;
int retour = 0 ; // par defaut
if ( cas_acceleration_convergence < 4 )
//--- cas de la méthode MMPE (modified minimal polynomial extrapolation) -----------------
{
// borne maxi du cycle qui varie de 1 à nb_vec_cycle
// indique le nombre de vecteur actif
int N = compteur % ( nb_vec_cycle + 2 ) ;
if ( N = = 0 ) N = ( nb_vec_cycle + 2 ) ;
// --- 1) récupération des informations
// calcul des nouvelles grandeurs des vecteurs d'entrées à l'accélération
// (pour toutes les affectations, on a un dimensionnement automatique)
if ( N = = 1 )
{ S_0 = delta_X ; // affectation et dimensionnement automatique de S_1
Vi ( N ) = delta_delta_X ;
switch ( cas_acceleration_convergence )
{ case 1 : case 10 : Yi ( N ) = delta_X ; break ;
case 2 : Yi ( N ) = vres ; break ;
case 3 : Yi ( N ) = delta_delta_X ; break ;
} ;
return 1 ;
}
else
{ Vi ( N ) = delta_delta_X ; // affectation et dimensionnement automatique de S_1
switch ( cas_acceleration_convergence )
{ case 1 : case 10 : Yi ( N ) = delta_X ; break ;
case 2 : Yi ( N ) = vres ; break ;
case 3 : Yi ( N ) = delta_delta_X ; break ;
} ;
} ;
retour = 2 ; // par défaut
// --- 2) calcul d'une nouvelle position extrapolée
// préparation du calcul des coeff ai:
// calcul de la matrice et du second membre
mat_ai . Initialise ( 0. ) ; Sm_ai . Zero ( ) ; // on initialise l'ensemble des containers
// mais seule la partie de 1 à N est utilisé
for ( int i = 1 ; i < = N - 1 ; i + + )
{ Sm_ai ( i ) = - ( Vi ( 1 ) * Yi ( i ) ) ;
for ( int j = 1 ; j < = N - 1 ; j + + )
// projection des delta_Gi sur les Yi
mat_ai ( i , j ) = Yi ( i ) * ( Vi ( j + 1 ) - Vi ( j ) ) ;
} ;
// pour éviter d'avoir une matrice singulière on met des 1 sur la partie de la diagonale restante
for ( int i = N ; i < = nb_vec_cycle + 1 ; i + + )
mat_ai ( i , i ) = 1. ;
// calcul des coef ai
coef_ai = mat_ai . Resol_systID ( Sm_ai ) ;
// construction du vecteur extrapolé, de position
X_extrapol = S_0 ; // affectation et dimensionnement automatique de X_extrapol
for ( int i = 1 ; i < = N - 1 ; i + + )
X_extrapol + = coef_ai ( i ) * Vi ( i ) ;
X_extrapol + = X_t ;
// cout << "\n coef_ai " << coef_ai ;
// --- 3) l'ancien résidu
double norme_residu_entree = vres . Max_val_abs ( ) ;
// --- 4) calcul du nouveau résidu
// maintenant on va calculer le résidu correspondant aux vecteur extrapolé de position
int re_init = 0 ; // sert dans le cas d'un pb de calcul
// 1) passage de ces nouvelles positions aux niveaux des maillages
lesMail - > Vect_glob_vers_local ( TEMPS_tdt , X1 , X_extrapol , X1 ) ;
// 2 - initialisation de la puissance externe puis on la calcule
vglobex . Zero ( ) ;
// 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
( Ass , lesMail , lesRef , vglobex , pa , lesCourbes1D , lesFonctionsnD ) ) )
{ Change_PhaseDeConvergence ( - 10 ) ; } ;
double maxPuissExt = vglobex . Max_val_abs ( ) ;
// 3 - idem pour la puissance interne
vglobin . 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
// 4 - calcul du second membre et des énergies
// dans le cas d'un calcul inexploitable on ressort en remettant les choses telles qu'elles
// étaient en entrée
if ( ! SecondMembreEnerg ( lesMail , Ass , vglobin ) )
{ cout < < " \n pb dans l'acceleration de convergence, on neutralise l'acceleration " ;
re_init = 1 ;
} ;
double maxPuissInt = vglobin . Max_val_abs ( ) ;
// 5 - second membre total
vglobal + = vglobex ; vglobal + = vglobin ;
// 6 - mise en place des conditions limites, vglobal contiend le nouveau résidu
// sauvegarde des reactions aux ddl bloque
lesCondLim - > ReacApresCHrepere ( vglobal , lesMail , lesRef , Ass . Nb_cas_assemb ( ) , cas_combi_ddl ) ; // a voir au niveau du nom
// mise en place des conditions limites, uniquement sur le second membre
///!!!!! on considère que les conditions limites sont identiques à celle utilisée avec Xtd
///!!!!! au moment de la résolution (qui a précédé l'appel de AccelerationConvergence)
///!!!!! donc on ne s'occupe pas de CoLinCHrepere
lesCondLim - > ImposeConLimtdt ( lesMail , lesRef , vglobal , nb_casAssemb , cas_combi_ddl , vglob_stat ) ;
double nouvelle_norme = vglobal . Max_val_abs ( ) ;
// pour le débug !!!!!!!!!!!!!!!!!!!!!!!!!
/* X_extrapol = X_t;
X_extrapol + = delta_X ;
// --- 4) calcul du nouveau résidu
// maintenant on va calculer le résidu correspondant aux vecteur extrapolé de position
re_init = 0 ; // sert dans le cas d'un pb de calcul
// 1) passage de ces nouvelles positions aux niveaux des maillages
lesMail - > Vect_glob_vers_local ( TEMPS_tdt , X1 , X_extrapol , X1 ) ;
// 2 - initialisation de la puissance externe puis on la calcul
vglobex . Zero ( ) ;
charge - > ChargeSecondMembre_Ex_mecaSolid ( Ass , lesMail , lesRef , vglobex , pa , lesCourbes1D ) ;
maxPuissExt = vglobex . Max_val_abs ( ) ;
// 3 - idem pour la puissance interne
vglobin . Zero ( ) ;
// 4 - calcul du second membre et des énergies
// dans le cas d'un calcul inexploitable on ressort en remettant les choses telles qu'elles
// étaient en entrée
if ( ! SecondMembreEnerg ( lesMail , Ass , vglobin ) )
{ cout < < " \n pb dans l'acceleration de convergence, on neutralise l'acceleration " ;
re_init = 1 ;
} ;
maxPuissInt = vglobin . Max_val_abs ( ) ;
// 5 - second membre total ( vglobal est identique a vglobin)
vglobal + = vglobex ;
// 6 - mise en place des conditions limites, vglobal contiend le nouveau résidu
// sauvegarde des reactions aux ddl bloque
lesCondLim - > ReacApresCHrepere ( vglobal , lesMail , lesRef , Ass . Nb_cas_assemb ( ) , cas_combi_ddl ) ; // a voir au niveau du nom
// mise en place des conditions limites, uniquement sur le second membre
///!!!!! on considère que les conditions limites sont identiques à celle utilisée avec Xtd
///!!!!! au moment de la résolution (qui a précédé l'appel de AccelerationConvergence)
///!!!!! donc on ne s'occupe pas de CoLinCHrepere
lesCondLim - > ImposeConLimtdt ( lesMail , lesRef , vglobal , nb_casAssemb , cas_combi_ddl ) ;
double new_norme = vglobal . Max_val_abs ( ) ;
cout < < " \n new_norme = " < < new_norme ;
*/
// fin pour le débug !!!!!!!!!!!!!!!!!!!!!!
// --- 5) exploitation: comparaison des résidus
if ( norme_residu_entree < nouvelle_norme )
{ // dans le cas où le nouveau résidu est plus grand que l'ancien on ne fait rien, et on affiche éventuellement
if ( affiche & & ( ParaGlob : : NiveauImpression ( ) > 1 ) )
cout < < " \n ..pas d'acceleration....koz_res= " < < norme_residu_entree < < " nevez_res= " < < nouvelle_norme ;
// on remet en place le vecteur position
X_extrapol = X_t ; X_extrapol + = delta_X ; // on se sert de X_extrapol comme contenaire intermédiaire
lesMail - > Vect_glob_vers_local ( TEMPS_tdt , X1 , X_extrapol , X1 ) ;
retour = 2 ;
}
else
{ // cas où on est meilleurs, petit message éventuel
if ( affiche & & ( ParaGlob : : NiveauImpression ( ) > 1 ) )
cout < < " \n ... acceleration positive....koz_res= " < < norme_residu_entree < < " nevez_res= " < < nouvelle_norme ;
// puis on appel de la convergence, pour voir si en plus on aurait convergé
double maxReaction = MaX ( maxPuissExt , maxPuissInt ) ; // on simplifie
bool arret_convergence ; // ne sert pas ici
double last_var_ddl_max = delta_delta_X . Max_val_abs ( ) ; // le dernier accroissement de ddl
if ( Convergence ( affiche , last_var_ddl_max , vglobal , maxPuissExt , maxPuissInt , maxReaction , compteur , arret_convergence ) )
// a priori on a convergé donc on laisse le nouveau vecteur position en conséquence
{ retour = 4 ; }
else
// c'est meilleur mais on n'a pas convergé donc on remet en place le vecteur position
{ X_extrapol = X_t ; X_extrapol + = delta_X ; // on se sert de X_extrapol comme contenaire intermédiaire
lesMail - > Vect_glob_vers_local ( TEMPS_tdt , X1 , X_extrapol , X1 ) ;
retour = 3 ;
} ;
} ;
}
//---- fin du cas de l'accélération avec la méthode MMPE (modified minimal polynomial extrapolation)
else
{
// --- cas simple où l'on essaie de gérer le cas d'une oscillation infinie entre deux positions ---------
// tout d'abord on regarde si effectivement on est dans le cas en question, pour cela il faut que l'on ait au moins 4 iterations enregistrées
// borne maxi du cycle qui varie de 1 à nb_vec_cycle (==2 a priori)
// indique le nombre de vecteur actif
int N = compteur % ( nb_vec_cycle + 2 ) ;
if ( N = = 0 ) N = ( nb_vec_cycle + 2 ) ;
Yi ( N ) = delta_X ; // 1) stockage des delta_X
Vi ( N ) ( 1 ) = vres . Max_val_abs ( ) ; // 2) stockage du maxi du résidu a priori non nul sinon cela veut dire que l'on a convergé
if ( Vi ( N ) ( 1 ) < ConstMath : : trespetit ) return 1 ; // ce n'est pas la pein de continuer
retour = 2 ; // par défaut
if ( compteur < 4 ) return 1 ;
// sinon
// def des 4 indices successifs
int j1 = ( N + 1 ) % ( nb_vec_cycle + 2 ) ; if ( j1 = = 0 ) j1 = ( nb_vec_cycle + 2 ) ;
int j2 = ( N + 2 ) % ( nb_vec_cycle + 2 ) ; if ( j2 = = 0 ) j2 = ( nb_vec_cycle + 2 ) ;
int j3 = ( N + 3 ) % ( nb_vec_cycle + 2 ) ; if ( j3 = = 0 ) j3 = ( nb_vec_cycle + 2 ) ;
int j4 = N ;
// on regarde s'il y a matière à s'inquiéter
// si le j4 > J3, J3 < J2, J2 > J1 : on a une forme de dent de scie ou
// si le j4 < J3, J3 > J2, J2 < J1 : on a une forme de dent de scie
double taux = 0.15 ; // on se met une marge de 15%
if ( ( ( Vi ( j4 ) ( 1 ) > Vi ( j3 ) ( 1 ) ) & & ( Vi ( j3 ) ( 1 ) < Vi ( j2 ) ( 1 ) ) & & ( Vi ( j2 ) ( 1 ) > Vi ( j1 ) ( 1 ) ) )
| | ( ( Vi ( j4 ) ( 1 ) < Vi ( j3 ) ( 1 ) ) & & ( Vi ( j3 ) ( 1 ) > Vi ( j2 ) ( 1 ) ) & & ( Vi ( j2 ) ( 1 ) < Vi ( j1 ) ( 1 ) ) ) )
// si on retombe deux à deux sur les mêmes résidus à taux près
{ if ( ( ! diffpourcent ( Vi ( j4 ) ( 1 ) , Vi ( j2 ) ( 1 ) , Vi ( j4 ) ( 1 ) , taux ) ) & & ( ! diffpourcent ( Vi ( j3 ) ( 1 ) , Vi ( j1 ) ( 1 ) , Vi ( j3 ) ( 1 ) , taux ) ) )
// dans ce cas on est dans une boucle: on choisit un vecteur x = à la moitié des deux précédents delta_delta_X
{ X_extrapol = X_t ;
X_extrapol + = delta_X ; // on se sert de X_extrapol comme contenaire intermédiaire
X_extrapol + = 0.5 * delta_delta_X ;
lesMail - > Vect_glob_vers_local ( TEMPS_tdt , X1 , X_extrapol , X1 ) ;
retour = 4 ;
}
else retour = 1. ;
}
else
{ retour = 1. ;
} ;
// --- fin cas simple où l'on essaie de gérer le cas d'une oscillation infinie entre deux positions ---------
} ;
// retour
return retour ;
} ;
//---- 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 AlgoriNonDyna : : ActionInteractiveAlgo ( )
{ cout < < " \n commande? " ;
return false ;
} ;
// sortie du schemaXML: en fonction de enu
void AlgoriNonDyna : : 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 implicite non dynamique ******************** --> "
< < " \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 ;
}
} ;
} ;
// Calcul de l'équilibre de la pièce avec pilotage de longueur d'arc
void AlgoriNonDyna : : Calcul_Equilibre_longueur_arc
( 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 ) ; // transfert info
// on défini globalement que l'on a pas de combinaison de ddl
int cas_combi_ddl = 0 ; // c'est-à-dire que le seul ddl libre est X
// cas du chargement, on verifie egalement la bonne adequation des references
charge - > Initialise ( lesMail , lesRef , pa , * lesCourbes1D , * lesFonctionsnD ) ;
// 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 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
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
// calcul de la largeur de bande effective
int demi , total ;
lesMail - > Largeur_Bande ( demi , total , Ass . Nb_cas_assemb ( ) ) ;
int nbddl = lesMail - > NbTotalDdlActifs ( ) ; // nb total de ddl
total = std : : min ( total , nbddl ) ;
// def de la matrice bande et d'un second membre globale
// a priori matrice symetrique
// initialisation a zero
MatBand matglob2 ( BANDE_SYMETRIQUE , demi , nbddl , 0 ) ;
// vérification d'une singularité éventuelle de la matrice de raideur
VerifSingulariteRaideurMeca ( nbddl , * lesMail ) ;
// on groupe des vecteurs résidus sous forme de tableau pour des
// raison de facilité de manipulation par la suite
Tableau < Vecteur > tab_residu ( 2 ) ;
tab_residu ( 1 ) . Change_taille ( nbddl ) ;
tab_residu ( 2 ) . Change_taille ( nbddl ) ;
Vecteur & vglobin = tab_residu ( 1 ) ; // puissance interne
Vecteur & vglobex = tab_residu ( 2 ) ; // puissance externe
Vecteur vglobal ( vglobin ) ; // puissance totale
vglobal + = vglobex ;
// définition d'un pointeur de fonction d'assemblage ici symétrique
// utilisé dans la prise en compte des efforts extérieurs
void ( Assemblage : : * assembMat ) // le pointeur
( Mat_abstraite & matglob2 , const Mat_abstraite & matloc ,
const DdlElement & tab_ddl , const Tableau < Noeud * > & tab_noeud )
= & Assemblage : : AssembMatSym ;
// dans le cas où l'on fait du line search on dimensionne des vecteurs
Vecteur * sauve_deltadept , * sauve_dept_a_tdt , * Vres , * v_travail ;
if ( pa . Line_search ( ) )
{ sauve_deltadept = new Vecteur ( nbddl ) ;
Vres = new Vecteur ( nbddl ) ;
sauve_dept_a_tdt = new Vecteur ( nbddl ) ;
v_travail = new Vecteur ( nbddl ) ;
}
// boucle sur les increments de charge
icharge = 1 ;
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
// et imposition éventuel de certaines des conditions de contact (dépend du modèle de contact)
try {
bool nevez_contact = lesContacts - > DefElemCont ( 0. ) ; // au début le déplacement des noeuds est nul
int niveau_substitution = 0 ; // on intervient sur toutes les matrices
bool premier_calcul = true ;
// mise à jour éventuelle de la matrice de raideur en fonction du contact
2023-05-03 17:23:49 +02:00
//bool changement_sur_matrice =
Gestion_stockage_et_renumerotation_avec_contact
2021-09-26 14:31:23 +02:00
( premier_calcul , lesMail , nevez_contact , lesCondLim
, lesRef , tab_mato , Ass . Nb_cas_assemb ( ) , lesContacts , niveau_substitution ) ;
matglob = tab_mato ( 1 ) ;
}
// sortie anormale de l'initialisation du contact
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 inconnue
{ cout < < " \n **** >>>> ERREUR inconnuee en en initialisant le contact ***** " ;
if ( ParaGlob : : NiveauImpression ( ) > = 4 )
cout < < " \n AlgoriNonDyna::InitAlgorithme(.. " ;
cout < < endl ;
} ;
} ;
//--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
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;
// 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 ( ) ) ;
// 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--------
OrdreVisu : : EnumTypeIncre type_incre = OrdreVisu : : PREMIER_INCRE ; // pour la visualisation au fil du calcul
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_pilotage = false ; // pour arrêt du calcul au niveau du pilotage
2023-05-03 17:23:49 +02:00
while ( ( ( ! charge - > Fin ( icharge ) ) | | ( icharge = = 1 ) )
2021-09-26 14:31:23 +02:00
& & ( 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é
)
{ 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 max_delta_X = 0. ; // le maxi du delta X
double max_var_delta_X = 0. ; // idem d'une itération à l'autre
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
// 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 ) ;
// initialisation de la variable puissance_précédente d'une itération à l'autre
double puis_precedente = 0. ;
Transfert_ParaGlob_NORME_CONVERGENCE ( ConstMath : : grand ) ; // on met une norme grande par défaut au début
Pilotage_du_temps ( charge , arret_pilotage ) ; // appel du Pilotage
if ( arret_pilotage ) break ; // pilotage -> arret du calcul
// affichage de l'increment de charge
bool aff_incr = pa . Vrai_commande_sortie ( icharge , temps_derniere_sauvegarde ) ; // pour simplifier
if ( aff_incr )
{ cout < < " \n ====================================================================== "
< < " \n INCREMENT 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 ) ;
/* // mise en place du chargement impose sur le second membre
// et éventuellement sur la raideur en fonction de sur_raideur
vglobex . Zero ( ) ;
// bool sur_raideur = false; // pour l'instant pas de prise en compte sur la raideur
bool sur_raideur = true ; // essai
charge - > ChargeSMembreRaideur_Im_mecaSolid
( Ass , lesMail , lesRef , vglobex , sur_raideur , matglob2 , assembMat , pa , lesCourbes1D ) ;
maxPuissExt = vglobex . Max_val_abs ( ) ; */
// boucle de convergence sur un increment
Vecteur * sol ; // pointeur du vecteur solution delta ddl classique
Vecteur * solF ; // idem pour la solution delta ddl pour uniquement la puissance externe
// bool ifresol = false;// drapeau pour le cas d'une charge sans resolution
int compteur ; // déclaré à l'extérieur de la boucle car utilisé après la boucle
bool arret_convergence = false ;
for ( compteur = 0 ; compteur < = pa . Iterations ( ) ; compteur + + )
{ // initialisation de la matrice et du second membre
matglob2 . Initialise ( 0. ) ;
vglobin . Zero ( ) ;
vglobex . Zero ( ) ;
if ( pa . ContactType ( ) )
vcontact . Zero ( ) ;
vglobaal . Zero ( ) ; // puissance totale
// prise en compte du cas particulier ou l'utilisateur demande
// une mise à jour des conditions limites à chaque itération
if ( cL_a_chaque_iteration )
{ // -- initialisation des coordonnees et des ddl a tdt en fonctions des
// ddl imposes et de l'increment du chargement: change_statut sera recalculé ensuite
lesCondLim - > MiseAJour_tdt
( pa . Multiplicateur ( ) , lesMail , charge - > Increment_de_Temps ( ) , lesRef , charge - > Temps_courant ( )
, lesCourbes1D , lesFonctionsnD , charge - > MultCharge ( ) , change_statut , cas_combi_ddl ) ;
// on récupère les nouvelles positions globalement de manière à pouvoir calculer le delta_X pour le contact
lesMail - > Vect_loc_vers_glob ( TEMPS_tdt , X1 , X_tdt , X1 ) ;
// 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 ) ;
} ;
// 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
// init de var glob
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 du chargement impose sur le second membre
// et éventuellement sur la raideur en fonction de sur_raideur
// mise en place des conditions linéaires
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 ;
lesLoisDeComp - > MiseAJour_umat_nbiter ( compteur ) ; // init pour les lois Umat éventuelles
// bool sur_raideur = false; // pour l'instant pas de prise en compte sur la raideur
2023-05-03 17:23:49 +02:00
// bool sur_raideur = true; // essai
2021-09-26 14:31:23 +02:00
// 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 , matglob2 , assembMat , pa , lesCourbes1D , lesFonctionsnD ) ) )
{ Change_PhaseDeConvergence ( - 10 ) ; break ; } ;
maxPuissExt = vglobex . Max_val_abs ( ) ;
// -- 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 , matglob2 ) ) break ;
// calcul des maxi des puissances internes
maxPuissInt = vglobin . Max_val_abs ( ) ;
// second membre total
vglobal + = vglobex ; vglobal + = vglobin ;
// initialisation des sauvegardes sur matrice et second membre
lesCondLim - > InitSauve ( Ass . Nb_cas_assemb ( ) ) ;
// sauvegarde des reactions aux ddl bloque
lesCondLim - > ReacApresCHrepere ( vglobin , lesMail , lesRef , Ass . Nb_cas_assemb ( ) , cas_combi_ddl ) ; // a voir au niveau du nom
// mise en place des conditions limites
lesCondLim - > ImposeConLimtdt ( lesMail , lesRef , matglob2 , vglobal , Ass . Nb_cas_assemb ( )
, cas_combi_ddl , vglob_stat ) ;
// ************* il faut aussi les conditions limites sur vglobex***********
// calcul du maxi des reactions
maxReaction = lesCondLim - > MaxEffort ( inReaction , Ass . Nb_cas_assemb ( ) ) ;
// resolution
// matglob2.Affiche(1,6,1,1,6,1);
// matglob2.Affiche(1,8,1,7,8,1);
// matglob2.Affiche(1,18,1,13,18,1);
// vglobal.Affiche();
// matglob2.Affiche(1,12,1,1,6,1);
// matglob2.Affiche(1,12,1,7,12,1);
// matglob2.Affiche(1,12,1,9,12,1);
// matglob2.Affiche(1,18,1,13,18,1);
// vglobal.Affiche();
// 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 ( ) ) ;
// test de convergence sur un increment
if ( Convergence ( aff_iteration , last_var_ddl_max , vglobal , maxPuissExt , maxPuissInt , maxReaction , compteur , arret_convergence ) )
{ // 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_convergence ) { break ; } // cas ou la méthode Convergence() demande l'arret
// sinon on continue
// pour le pilotage, sauvegarde du résidu
if ( pa . Line_search ( ) ) ( * Vres ) = vglobal ;
// on résoud deux systèmes, correspondant pour le premier
// aux déplacements classiques stockés en sortie dans tab_résidu(1)
// ce dernier contenant en entrée le résidu interne + externe
// tab_résidu(2) en entrée correspond uniquement aux puissances externes
// en sortie il correspond aux delta ddl relativement uniquement aux puissances
// externes
tempsResolSystemLineaire . Mise_en_route_du_comptage ( ) ; // temps cpu
matglob2 . Resol_systID ( tab_residu ) ;
tempsResolSystemLineaire . Arret_du_comptage ( ) ; // temps cpu
sol = & tab_residu ( 1 ) ; // solution d'incrément de déplacement classique
solF = & tab_residu ( 2 ) ; // delta ddl pour le résidu externe uniquement
// calcul du maxi de variation de ddl
maxDeltaDdl = sol - > Max_val_abs ( inSol ) ;
double maxDeltatDdl_signe = ( * sol ) ( inSol ) ; // récupération de la grandeur signée
// pilotage à chaque itération: ramène: maxDeltaDdl,csol 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 ( ) ) ;
// suite du pilotage
// ------------------------------------------------------------
// |on regarde s'il faut utiliser l'algorithme de line search |
// ------------------------------------------------------------
bool avec_line_search = false ;
if ( pa . Line_search ( ) )
{ // la méthode de line_search incrémente la solution
// même s'il n'y a pas de mise en oeuvre de la méthode
avec_line_search = Line_search1
( * sauve_deltadept , puis_precedente , * Vres , lesMail , sol
, compteur , * sauve_dept_a_tdt , charge , vglobex , Ass , * v_travail ,
lesCondLim , vglobal , lesRef , vglobin , Ass . Nb_cas_assemb ( )
, cas_combi_ddl , lesCourbes1D , lesFonctionsnD ) ;
}
else
//cas ou l'on ne fait pas de line seach
{ // 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 //\\//\\//
}
// 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
{ // sinon calcul correcte
// 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 ( ) ;
// sauvegarde de l'incrément si nécessaire
tempsCalEquilibre . Arret_du_comptage ( ) ; // on arrête le 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
// test de fin de calcul effectue dans charge via : charge->Fin()
icharge + + ;
Transfert_ParaGlob_COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL ( icharge ) ;
}
}
// fin des calculs
tempsCalEquilibre . Arret_du_comptage ( ) ; // temps cpu
// fin des calculs
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 ( ) ) ) ;
} ;