4155 lines
219 KiB
C++
4155 lines
219 KiB
C++
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
|
|
#include "Algori.h"
|
|
#include "string"
|
|
#include "MathUtil.h"
|
|
#include <iostream> // pour utiliser la classe istrstream
|
|
#include <strstream> // nouveau dans CW5.3
|
|
|
|
// les différents types de stockage matriciel
|
|
#include <complex>
|
|
#include "MatLapack.h"
|
|
#include "Mat_pleine.h"
|
|
#include "MatBand.h"
|
|
#include "Mat_creuse_CompCol.h"
|
|
#include "MatDiag.h"
|
|
|
|
#include "ReferenceNE.h"
|
|
#include "ReferenceAF.h"
|
|
#include "ExceptionsElemMeca.h"
|
|
#include "ExceptionsLoiComp.h"
|
|
#include "TypeQuelconqueParticulier.h"
|
|
|
|
|
|
//---------- class DeuxString ---------
|
|
// surcharge de l'operator de lecture /écriture
|
|
istream & operator >> (istream & ent, Algori::DeuxString & a)
|
|
{ //lecture du type et vérification
|
|
string nom_type; ent >> nom_type;
|
|
if (nom_type != "Algori::DeuxString") Sortie(1);
|
|
// les deux strings
|
|
ent >> a.nomFichier >> a.nomMaillage;
|
|
return ent;
|
|
};
|
|
|
|
ostream & operator << (ostream & sort, const Algori::DeuxString & a)
|
|
{ // le type puis les deux strings
|
|
sort << "Algori::DeuxString " << a.nomFichier << " " << a.nomMaillage <<"\n";
|
|
return sort;
|
|
};
|
|
|
|
istream & operator >> (istream & ent , Algori::ListDeuxString & a)
|
|
{ ent >> a.infos; return ent;};
|
|
ostream & operator << (ostream & sort , const Algori::ListDeuxString &a)
|
|
{ sort << a.infos; return sort;};
|
|
|
|
//---------- fin class DeuxString ---------
|
|
|
|
// CONSTRUCTEURS :
|
|
Algori::Algori () : // par defaut
|
|
paraTypeCalcul(),pa(),temps_derniere_sauvegarde(0.),mode_debug(0),permet_affichage(0)
|
|
,list_incre_temps_sauvegarder(),list_incre_temps_calculer()
|
|
,tempsDerniereSortieFilCalcul(0.),noms_fichier(),typeFlotExterne()
|
|
,entreePrinc(NULL),debut_increment(0),visualise(),visualise_maple()
|
|
,visualise_geomview(),visualise_Gid(),visualise_Gmsh(),toto_masse(NULL)
|
|
,icharge(0)
|
|
,phase_de_convergence(0),nombre_de_bonnes_convergences(0),a_converge(false) // variables de travail
|
|
,a_converge_iterMoins1(false)
|
|
,nombre_de_mauvaises_convergences(0)
|
|
,max_var_residu(),nb_cycle_test_max_var_residu(0),v_int() // variables de travail
|
|
,tab_para_stockage() //,pt_icharge(NULL)
|
|
,E_cin_0(0.),E_cin_t(0.),E_cin_tdt(0),E_int_t(0),E_int_tdt(0),E_ext_t(0),E_ext_tdt(0),bilan_E(0) // différentes énergies et bilan
|
|
,q_mov_t(0.),q_mov_tdt(0.)
|
|
,P_acc_tdt(0.),P_int_tdt(0.),P_ext_tdt(0.),bilan_P_tdt(0.),P_acc_t(0.),P_int_t(0.),P_ext_t(0.),bilan_P_t(0.)
|
|
,E_visco_numerique_t(0.),E_visco_numerique_tdt(0.),E_bulk(0.),P_bulk(0.)
|
|
,F_int_t(),F_ext_t(),F_int_tdt(),F_ext_tdt(),F_totale_tdt() // forces généralisées int et ext à t et t+dt
|
|
,residu_final()
|
|
|
|
,E_cin_ind_t(),E_cin_ind_tdt(),E_int_ind_t(),E_int_ind_tdt(),E_ext_ind_t(),E_ext_ind_tdt(),bilan_ind_E()
|
|
,q_mov_ind_t(),q_mov_ind_tdt()
|
|
,P_acc_ind_tdt(),P_int_ind_tdt(),P_ext_ind_tdt(),bilan_P_ind_tdt()
|
|
,P_acc_ind_t(),P_int_ind_t(),P_ext_ind_t(),bilan_P_ind_t()
|
|
,E_visco_numerique_ind_t(),E_visco_numerique_ind_tdt()
|
|
,F_int_ind_t(),F_ext_ind_t(),F_int_ind_tdt(),F_ext_ind_tdt()
|
|
,X_t(),X_tdt(),delta_X(),var_delta_X(),delta_t_precedent_a_convergence(0.)
|
|
,vitesse_t(),vitesse_tdt(),acceleration_t(),acceleration_tdt()
|
|
,E_bulk_ind()
|
|
,P_bulk_ind()
|
|
|
|
,cas_ass_eps(NULL),Ass_eps(NULL),cas_ass_eps11(NULL),Ass_eps11(NULL)
|
|
,cas_ass_sig(NULL),Ass_sig(NULL),cas_ass_sig11(NULL),Ass_sig11(NULL)
|
|
,mat_glob_sigeps(NULL),vglob_sigeps(NULL),vglobal_sigeps(NULL)
|
|
,nbddl_sigeps11(0),nbddl_sigeps(0)
|
|
,cas_ass_err(NULL),Ass_err(NULL),nbddl_err(0)
|
|
,avec_remont_sigma(false),avec_remont_eps(false),avec_erreur(false)
|
|
,energTotal(),energHourglass(0.),energFrottement(),energPenalisation(0.)
|
|
,energStabiliMembBiel(0.)
|
|
,deja_lue_entete_parametre(0)
|
|
//-------- amortissement cinétique
|
|
,amortissement_cinetique(false),max_nb_decroit_pourRelaxDyn(1),compteur_decroit_pourRelaxDyn(0)
|
|
,inter_nb_entre_relax(1),fct_nD_inter_nb_entre_relax(NULL),nom_fct_nD_inter_nb_entre_relax("")
|
|
,nb_depuis_derniere_relax(0)
|
|
,taille_moyenne_glissante(1),moyenne_glissante(ConstMath::tresgrand), moy_gliss_t(0.)
|
|
,sauve_E_cin(),indice_EC1(0),nb_Ecin_stocker(0),test_fraction_energie(0.),X_EcinMax()
|
|
,coef_arret_pourRelaxDyn(0.5),dernier_pic(-1),pic_E_cint_t(-1.)
|
|
,max_pic_E_cin(-1.),coef_redemarrage_pourRelaxDyn(0.05)
|
|
,max_deltaX_pourRelaxDyn(0.1)
|
|
,nb_max_dX_OK_pourRelaxDyn(5),nb_dX_OK_pourRelaxDyn(0)
|
|
,nb_deb_testfin_pourRelaxDyn(100),nb_deb_test_amort_cinetique(1)
|
|
,compteur_test_pourRelaxDyn(0),compteur_pic_energie(0)
|
|
// ...... the same pour l'amortissement local
|
|
,amortissement_cinetique_au_noeud(0),nb_deb_test_amort_cinetique_noe(100)
|
|
,E_cinNoe_tdt(),E_cinNoe_t(),max_nb_decroit_pourRelaxDyn_noe(1),compteur_decroit_pourRelaxDyn_noe()
|
|
,coef_arret_pourRelaxDyn_noe(0.5),dernier_pic_noe()
|
|
,pic_E_cint_t_noe(),max_pic_E_cin_noe(),coef_redemarrage_pourRelaxDyn_noe(0.05)
|
|
,compteur_pic_energie_noe(0)
|
|
//------- amortissement visqueux critique
|
|
,opt_cal_C_critique(-1),f_(0.9),ampli_visco(1.)
|
|
,C_inter(NULL),type_calcul_visqu_critique(0)
|
|
,F_int_tdt_prec(),F_ext_tdt_prec()
|
|
,listeVarGlob(),listeVecGlob()
|
|
|
|
//----- fin des amortissements ---
|
|
,arret_a_equilibre_statique(0),vglob_stat(NULL)
|
|
,volume_total_matiere(0.),vol_total2D_avec_plan_ref(1,Coordonnee(ParaGlob::Dimension()))
|
|
// -- controle précision convergence
|
|
,nom_modulation_precision(""),modulation_precision(NULL),fct_norme(NULL)
|
|
//---- grandeurs de travail privées ------
|
|
,vec_trav()
|
|
//------- temps cpu -----
|
|
,tempsInitialisation(),tempsMiseAjourAlgo(),tempsCalEquilibre()
|
|
,tempsRaidSmEner(),tempsSecondMembreEnerg(),tempsResolSystemLineaire()
|
|
,tempsSauvegarde(),tempsSortieFilCalcul(),tempsRaidSmEnerContact()
|
|
,tempsSecondMembreEnergContact(),temps_CL(),temps_CLL()
|
|
,temps_lois_comportement(),temps_metrique_K_SM(),temps_chargement()
|
|
,temps_rech_contact()
|
|
,ptalgocombi(NULL)
|
|
#ifndef UTILISATION_MPI
|
|
,lesTempsCpu(16)
|
|
#else
|
|
,lesTempsCpu(19),distribution_CPU_algo()
|
|
,temps_transfert_court(),temps_transfert_long(),temps_attente()
|
|
#endif
|
|
//---------- stockage pour la transmission des grandeurs consultables -----
|
|
// ,stock_compteur(GENERIQUE_UNE_GRANDEUR_GLOBALE),val_stock_compteur(NULL)
|
|
// ,stock_icharge(GENERIQUE_UNE_GRANDEUR_GLOBALE),val_stock_icharge(NULL)
|
|
|
|
{ cout << "\n ce constructeur ne doit pas etre utilise !! \n" ;
|
|
cout << " Algo::Algo () // par defaut " << endl;
|
|
Sortie(1);
|
|
};
|
|
|
|
// constructeur en fonction du type de calcul
|
|
// il y a ici lecture des parametres attaches au type
|
|
Algori::Algori (EnumTypeCalcul type,const bool avec_typeDeCal
|
|
,const list <EnumSousTypeCalcul>& soustype
|
|
,const list <bool>& avec_soustypeDeCal
|
|
,UtilLecture& entreePrincipal
|
|
):
|
|
typeCalcul(type),avec_typeDeCalcul(avec_typeDeCal)
|
|
,soustypeDeCalcul(&soustype),avec_soustypeDeCalcul(&avec_soustypeDeCal)
|
|
,paraTypeCalcul()
|
|
,pa(),temps_derniere_sauvegarde(0.),mode_debug(0),permet_affichage(0)
|
|
,list_incre_temps_sauvegarder(),list_incre_temps_calculer()
|
|
,tempsDerniereSortieFilCalcul(0.),noms_fichier(),typeFlotExterne()
|
|
,entreePrinc(&entreePrincipal),debut_increment(0)
|
|
,visualise(&entreePrincipal),visualise_maple(&entreePrincipal)
|
|
,visualise_geomview(&entreePrincipal),visualise_Gid(&entreePrincipal)
|
|
,visualise_Gmsh(&entreePrincipal),toto_masse(NULL)
|
|
,icharge(0)
|
|
,phase_de_convergence(0),nombre_de_bonnes_convergences(0),a_converge(false) // variables de travail
|
|
,a_converge_iterMoins1(false)
|
|
,nombre_de_mauvaises_convergences(0)
|
|
,max_var_residu(),nb_cycle_test_max_var_residu(0),v_int() // variables de travail
|
|
,tab_para_stockage()//,pt_icharge(NULL)
|
|
,E_cin_0(0.),E_cin_t(0),E_cin_tdt(0),E_int_t(0),E_int_tdt(0),E_ext_t(0),E_ext_tdt(0),bilan_E(0) // différentes énergies et bilan
|
|
,q_mov_t(0.),q_mov_tdt(0.)
|
|
,P_acc_tdt(0.),P_int_tdt(0.),P_ext_tdt(0.),bilan_P_tdt(0.),P_acc_t(0.),P_int_t(0.),P_ext_t(0.),bilan_P_t(0.)
|
|
,E_visco_numerique_t(0.),E_visco_numerique_tdt(0.),E_bulk(0.),P_bulk(0.)
|
|
,F_int_t(),F_ext_t(),F_int_tdt(),F_ext_tdt(),F_totale_tdt() // forces généralisées int et ext à t et t+dt
|
|
,residu_final()
|
|
,X_t(),X_tdt(),delta_X(),var_delta_X(),delta_t_precedent_a_convergence(0.)
|
|
,vitesse_t(),vitesse_tdt(),acceleration_t(),acceleration_tdt()
|
|
,cas_ass_eps(NULL),Ass_eps(NULL),cas_ass_eps11(NULL),Ass_eps11(NULL)
|
|
,cas_ass_sig(NULL),Ass_sig(NULL),cas_ass_sig11(NULL),Ass_sig11(NULL)
|
|
,mat_glob_sigeps(NULL),vglob_sigeps(NULL),vglobal_sigeps(NULL)
|
|
,nbddl_sigeps11(0),nbddl_sigeps(0)
|
|
,cas_ass_err(NULL),Ass_err(NULL),nbddl_err(0)
|
|
,avec_remont_sigma(false),avec_remont_eps(false),avec_erreur(false)
|
|
,energTotal(),energHourglass(0.),energFrottement(),energPenalisation(0.),energStabiliMembBiel(0.)
|
|
,deja_lue_entete_parametre(0)
|
|
//-------- amortissement cinétique
|
|
,amortissement_cinetique(false),max_nb_decroit_pourRelaxDyn(1),compteur_decroit_pourRelaxDyn(0)
|
|
,inter_nb_entre_relax(1),fct_nD_inter_nb_entre_relax(NULL),nom_fct_nD_inter_nb_entre_relax("")
|
|
,nb_depuis_derniere_relax(0)
|
|
,taille_moyenne_glissante(1),moyenne_glissante(ConstMath::tresgrand), moy_gliss_t(0.)
|
|
,sauve_E_cin(),indice_EC1(0),nb_Ecin_stocker(0),test_fraction_energie(0.),X_EcinMax()
|
|
,coef_arret_pourRelaxDyn(0.5),dernier_pic(-1.),pic_E_cint_t(-1.),max_pic_E_cin(-1.),coef_redemarrage_pourRelaxDyn(0.05)
|
|
,max_deltaX_pourRelaxDyn(0.1),nb_max_dX_OK_pourRelaxDyn(5),nb_dX_OK_pourRelaxDyn(0)
|
|
,nb_deb_testfin_pourRelaxDyn(100),nb_deb_test_amort_cinetique(1)
|
|
,compteur_test_pourRelaxDyn(0),compteur_pic_energie(0)
|
|
// ...... the same pour l'amortissement local
|
|
,amortissement_cinetique_au_noeud(0),nb_deb_test_amort_cinetique_noe(100)
|
|
,E_cinNoe_tdt(),E_cinNoe_t(),max_nb_decroit_pourRelaxDyn_noe(1),compteur_decroit_pourRelaxDyn_noe()
|
|
,coef_arret_pourRelaxDyn_noe(0.5),dernier_pic_noe()
|
|
,pic_E_cint_t_noe(),max_pic_E_cin_noe(),coef_redemarrage_pourRelaxDyn_noe(0.05)
|
|
,compteur_pic_energie_noe(0)
|
|
//------- amortissement visqueux critique
|
|
,opt_cal_C_critique(-1),f_(0.9),ampli_visco(1.)
|
|
,C_inter(NULL),type_calcul_visqu_critique(0)
|
|
,F_int_tdt_prec(),F_ext_tdt_prec()
|
|
,listeVarGlob(),listeVecGlob()
|
|
|
|
//----- fin des amortissements ---
|
|
,arret_a_equilibre_statique(0),vglob_stat(NULL)
|
|
,volume_total_matiere(0.),vol_total2D_avec_plan_ref(1,Coordonnee(ParaGlob::Dimension()))
|
|
// -- controle précision convergence
|
|
,nom_modulation_precision(""),modulation_precision(NULL),fct_norme(NULL)
|
|
//---- grandeurs de travail privées ------
|
|
,vec_trav()
|
|
//------- temps cpu -----
|
|
,tempsInitialisation(),tempsMiseAjourAlgo(),tempsCalEquilibre()
|
|
,tempsRaidSmEner(),tempsSecondMembreEnerg(),tempsResolSystemLineaire()
|
|
,tempsSauvegarde(),tempsSortieFilCalcul(),tempsRaidSmEnerContact()
|
|
,tempsSecondMembreEnergContact(),temps_CL(),temps_CLL()
|
|
,temps_lois_comportement(),temps_metrique_K_SM(),temps_chargement()
|
|
,temps_rech_contact()
|
|
,ptalgocombi(NULL)
|
|
#ifndef UTILISATION_MPI
|
|
,lesTempsCpu(16)
|
|
#else
|
|
,lesTempsCpu(19),distribution_CPU_algo()
|
|
,temps_transfert_court(),temps_transfert_long(),temps_attente()
|
|
#endif
|
|
|
|
//---------- stockage pour la transmission des grandeurs consultables -----
|
|
// ,stock_compteur(GENERIQUE_UNE_GRANDEUR_GLOBALE),val_stock_compteur(NULL)
|
|
// ,stock_icharge(GENERIQUE_UNE_GRANDEUR_GLOBALE),val_stock_icharge(NULL)
|
|
|
|
{ // on met à jour ParaGlob
|
|
ParaGlob::param->ChangeParaAlgoControleActifs(&pa);
|
|
|
|
// stockage pour la transmission des grandeurs consultables
|
|
// 1) on définie un type quelconque adapté comme conteneur
|
|
{int toto=0;
|
|
Grandeur_scalaire_entier grand_courant(toto);
|
|
TypeQuelconque typQ1(GENERIQUE_UNE_GRANDEUR_GLOBALE,NU_DDL,grand_courant);
|
|
// // 2) on adapte le stockage
|
|
// stock_compteur.ChangeGrandeur(typQ1);
|
|
// val_stock_compteur = (Grandeur_scalaire_entier*) stock_compteur.Grandeur_pointee();
|
|
// stock_icharge.ChangeGrandeur(typQ1);
|
|
// val_stock_icharge = (Grandeur_scalaire_entier*) stock_icharge.Grandeur_pointee();
|
|
// 3) on ajoute en global les grandeurs consultables
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,COMPTEUR_ITERATION_ALGO_GLOBAL);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,COMPTEUR_INCREMENT_CHARGE_ALGO_GLOBAL);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ALGO_GLOBAL_ACTUEL);
|
|
};
|
|
// --- maintenant les énergies
|
|
{double titi=0.; // les énergies sont des doubles
|
|
Grandeur_scalaire_double grand_courant(titi);
|
|
TypeQuelconque typQ1(GENERIQUE_UNE_GRANDEUR_GLOBALE,NU_DDL,grand_courant);
|
|
// et on ajoute
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_CINETIQUE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_EXTERNE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_INTERNE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,PUISSANCE_ACCELERATION);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,PUISSANCE_INTERNE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,PUISSANCE_EXTERNE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,PUISSANCE_BILAN);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_ELASTIQUE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_PLASTIQUE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_VISQUEUSE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_BILAN);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,QUANTITE_MOUVEMENT);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_PENALISATION);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_FROT_ELAST);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_FROT_PLAST);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_FROT_VISQ);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_VISCO_NUMERIQUE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_BULK_VISCOSITY);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_HOURGLASS_);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,ENERGIE_STABILISATION_MEMB_BIEL);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,VOLUME_TOTAL_MATIERE);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,MAXPUISSEXT);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,MAXPUISSINT);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,MAXREACTION);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,MAXRESIDUGLOBAL);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,MAXdeltaX);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,MAXvarDeltaX);
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,MAXvarDdl);
|
|
// //------- debug
|
|
// {void* pt_void = ParaGlob::param->Mise_a_jour_grandeur_consultable(ENERGIE_PENALISATION);
|
|
// TypeQuelconque* pt_quelc = (TypeQuelconque*) pt_void;
|
|
// Grandeur_scalaire_double& gr
|
|
// = *((Grandeur_scalaire_double*) pt_quelc->Grandeur_pointee()); // pour simplifier
|
|
// cout << "\n debug*** Algori::Algori "
|
|
// << "\n pt_void= " << pt_void << " gr.ContDouble()= " << gr.ContDouble()
|
|
// << " (*(gr.ConteneurDouble())) = " << (*(gr.ConteneurDouble()))
|
|
// << flush;
|
|
// }
|
|
// // --- fin debug
|
|
|
|
switch (ParaGlob::Dimension())
|
|
{ case 3: ParaGlob::param->Ajout_grandeur_consultable(&typQ1,VOL_TOTAL2D_AVEC_PLAN_XY);
|
|
case 2: ParaGlob::param->Ajout_grandeur_consultable(&typQ1,VOL_TOTAL2D_AVEC_PLAN_XZ);
|
|
case 1: ParaGlob::param->Ajout_grandeur_consultable(&typQ1,VOL_TOTAL2D_AVEC_PLAN_YZ);
|
|
default: break;
|
|
};
|
|
// au début on met une norme très grande, car a priori on n'a absolument pas convergé !
|
|
Grandeur_scalaire_double& gr
|
|
= *((Grandeur_scalaire_double*) typQ1.Grandeur_pointee()); // pour simplifier
|
|
*(gr.ConteneurDouble()) = ConstMath::grand;
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,NORME_CONVERGENCE);
|
|
|
|
};
|
|
};
|
|
|
|
// constructeur de copie
|
|
Algori::Algori (const Algori& algo) :
|
|
typeCalcul(algo.typeCalcul)
|
|
,avec_typeDeCalcul(algo.avec_typeDeCalcul)
|
|
,soustypeDeCalcul(algo.soustypeDeCalcul)
|
|
,avec_soustypeDeCalcul(algo.avec_soustypeDeCalcul)
|
|
,paraTypeCalcul(algo.paraTypeCalcul),mode_debug(algo.mode_debug)
|
|
,permet_affichage(algo.permet_affichage)
|
|
,pa(algo.pa),temps_derniere_sauvegarde(algo.temps_derniere_sauvegarde)
|
|
,list_incre_temps_sauvegarder(algo.list_incre_temps_sauvegarder)
|
|
,list_incre_temps_calculer(algo.list_incre_temps_calculer)
|
|
,tempsDerniereSortieFilCalcul(algo.tempsDerniereSortieFilCalcul)
|
|
,noms_fichier(algo.noms_fichier)
|
|
,typeFlotExterne(algo.typeFlotExterne)
|
|
,entreePrinc(algo.entreePrinc),debut_increment(algo.debut_increment)
|
|
,visualise(),visualise_maple(),visualise_geomview(),visualise_Gid(),visualise_Gmsh()
|
|
,toto_masse(NULL),icharge(algo.icharge)
|
|
,phase_de_convergence(algo.phase_de_convergence) // variables de travail
|
|
,nombre_de_bonnes_convergences(algo.nombre_de_bonnes_convergences) // "
|
|
,nombre_de_mauvaises_convergences(algo.nombre_de_mauvaises_convergences) // "
|
|
,a_converge(algo.a_converge),a_converge_iterMoins1(algo.a_converge_iterMoins1) // "
|
|
,max_var_residu(algo.max_var_residu) // variables de travail
|
|
,nb_cycle_test_max_var_residu(algo.nb_cycle_test_max_var_residu) // variables de travail
|
|
,v_int(algo.v_int) // "
|
|
,tab_para_stockage(algo.tab_para_stockage) //,pt_icharge(algo.pt_icharge)
|
|
,E_cin_0(algo.E_cin_0),E_cin_t(algo.E_cin_t),E_cin_tdt(algo.E_cin_tdt)
|
|
,E_int_t(algo.E_int_t),E_int_tdt(algo.E_int_tdt) // différentes énergies et bilan
|
|
,E_ext_t(algo.E_ext_t),E_ext_tdt(algo.E_ext_tdt),bilan_E(algo.bilan_E) // "
|
|
,q_mov_t(algo.q_mov_t),q_mov_tdt(algo.q_mov_tdt)
|
|
,P_acc_tdt(algo.P_acc_tdt),P_int_tdt(algo.P_int_tdt),P_ext_tdt(algo.P_ext_tdt),bilan_P_tdt(algo.bilan_P_tdt)
|
|
,P_acc_t(algo.P_acc_t),P_int_t(algo.P_int_t),P_ext_t(algo.P_ext_t),bilan_P_t(algo.bilan_P_t)
|
|
,E_visco_numerique_t(algo.E_visco_numerique_t),E_visco_numerique_tdt(algo.E_visco_numerique_tdt)
|
|
,E_bulk(algo.E_bulk),P_bulk(algo.P_bulk)
|
|
,F_int_t(algo.F_int_t),F_ext_t(algo.F_ext_t) // forces généralisées int et ext à t et t+dt
|
|
,F_int_tdt(algo.F_int_tdt),F_ext_tdt(algo.F_ext_tdt) // "
|
|
,F_totale_tdt(algo.F_totale_tdt),residu_final(algo.residu_final)
|
|
,X_t(algo.X_t),X_tdt(algo.X_tdt),delta_X(algo.delta_X),var_delta_X(algo.var_delta_X)
|
|
,delta_t_precedent_a_convergence(algo.delta_t_precedent_a_convergence)
|
|
,vitesse_t(algo.vitesse_t),vitesse_tdt(algo.vitesse_tdt)
|
|
,acceleration_t(algo.acceleration_t),acceleration_tdt(algo.acceleration_tdt)
|
|
,cas_ass_eps(NULL),Ass_eps(NULL),cas_ass_eps11(NULL),Ass_eps11(NULL)
|
|
,cas_ass_sig(NULL),Ass_sig(NULL),cas_ass_sig11(NULL),Ass_sig11(NULL)
|
|
,mat_glob_sigeps(NULL),vglob_sigeps(NULL),vglobal_sigeps(NULL)
|
|
,nbddl_sigeps11(0),nbddl_sigeps(0)
|
|
,cas_ass_err(NULL),Ass_err(NULL),nbddl_err(0)
|
|
,avec_remont_sigma(false),avec_remont_eps(false),avec_erreur(false)
|
|
,energTotal(algo.energTotal),energHourglass(algo.energHourglass)
|
|
,energFrottement(algo.energFrottement),energPenalisation(algo.energPenalisation)
|
|
,energStabiliMembBiel(algo.energStabiliMembBiel)
|
|
,deja_lue_entete_parametre(algo.deja_lue_entete_parametre)
|
|
//------- amortissement visqueux critique
|
|
,amortissement_cinetique(algo.amortissement_cinetique)
|
|
,taille_moyenne_glissante(algo.taille_moyenne_glissante)
|
|
,moyenne_glissante(algo.moyenne_glissante), moy_gliss_t(algo.moy_gliss_t)
|
|
,sauve_E_cin(algo.sauve_E_cin),indice_EC1(algo.indice_EC1),nb_Ecin_stocker(algo.nb_Ecin_stocker)
|
|
,test_fraction_energie(algo.test_fraction_energie),X_EcinMax(algo.X_EcinMax)
|
|
,max_nb_decroit_pourRelaxDyn(algo.max_nb_decroit_pourRelaxDyn)
|
|
,inter_nb_entre_relax(1),fct_nD_inter_nb_entre_relax(algo.fct_nD_inter_nb_entre_relax)
|
|
,nom_fct_nD_inter_nb_entre_relax(algo.nom_fct_nD_inter_nb_entre_relax)
|
|
,nb_depuis_derniere_relax(0)
|
|
,compteur_decroit_pourRelaxDyn(algo.compteur_decroit_pourRelaxDyn)
|
|
,coef_arret_pourRelaxDyn(algo.coef_arret_pourRelaxDyn),pic_E_cint_t(algo.pic_E_cint_t)
|
|
,dernier_pic(algo.dernier_pic)
|
|
,max_pic_E_cin(algo.max_pic_E_cin),coef_redemarrage_pourRelaxDyn(algo.coef_redemarrage_pourRelaxDyn)
|
|
,max_deltaX_pourRelaxDyn(algo.max_deltaX_pourRelaxDyn),nb_max_dX_OK_pourRelaxDyn(algo.nb_max_dX_OK_pourRelaxDyn)
|
|
,nb_dX_OK_pourRelaxDyn(0),nb_deb_testfin_pourRelaxDyn(algo.nb_deb_testfin_pourRelaxDyn)
|
|
,nb_deb_test_amort_cinetique(algo.nb_deb_test_amort_cinetique)
|
|
,compteur_test_pourRelaxDyn(algo.compteur_test_pourRelaxDyn),compteur_pic_energie(algo.compteur_pic_energie)
|
|
// ...... the same pour l'amortissement local
|
|
,amortissement_cinetique_au_noeud(algo.amortissement_cinetique_au_noeud)
|
|
,nb_deb_test_amort_cinetique_noe(algo.nb_deb_test_amort_cinetique_noe)
|
|
,E_cinNoe_tdt(algo.E_cinNoe_tdt),E_cinNoe_t(algo.E_cinNoe_t)
|
|
,max_nb_decroit_pourRelaxDyn_noe(algo.max_nb_decroit_pourRelaxDyn_noe)
|
|
,compteur_decroit_pourRelaxDyn_noe(algo.compteur_decroit_pourRelaxDyn_noe)
|
|
,coef_arret_pourRelaxDyn_noe(algo.coef_arret_pourRelaxDyn_noe),dernier_pic_noe(algo.dernier_pic_noe)
|
|
,pic_E_cint_t_noe(algo.pic_E_cint_t_noe),max_pic_E_cin_noe(algo.max_pic_E_cin_noe)
|
|
,coef_redemarrage_pourRelaxDyn_noe(algo.coef_redemarrage_pourRelaxDyn_noe)
|
|
,compteur_pic_energie_noe(algo.compteur_pic_energie_noe)
|
|
//------- amortissement visqueux critique
|
|
,opt_cal_C_critique(algo.opt_cal_C_critique),f_(algo.f_)
|
|
,ampli_visco(algo.ampli_visco),C_inter(NULL)
|
|
,type_calcul_visqu_critique(algo.type_calcul_visqu_critique)
|
|
,F_int_tdt_prec(algo.F_int_tdt_prec),F_ext_tdt_prec(algo.F_int_tdt_prec)
|
|
,listeVarGlob(algo.listeVarGlob),listeVecGlob(algo.listeVecGlob)
|
|
|
|
//----- fin des amortissements ---
|
|
,arret_a_equilibre_statique(algo.arret_a_equilibre_statique),vglob_stat(algo.vglob_stat)
|
|
,volume_total_matiere(algo.volume_total_matiere),vol_total2D_avec_plan_ref(algo.vol_total2D_avec_plan_ref)
|
|
// -- controle précision convergence
|
|
,nom_modulation_precision(algo.nom_modulation_precision),modulation_precision(NULL),fct_norme(NULL)
|
|
//---- grandeurs de travail privées ------
|
|
,vec_trav()
|
|
//------- temps cpu -----
|
|
,tempsInitialisation(algo.tempsInitialisation),tempsMiseAjourAlgo(algo.tempsMiseAjourAlgo)
|
|
,tempsCalEquilibre(algo.tempsCalEquilibre),tempsRaidSmEner(algo.tempsRaidSmEner)
|
|
,tempsSecondMembreEnerg(algo.tempsSecondMembreEnerg),tempsResolSystemLineaire(algo.tempsResolSystemLineaire)
|
|
,tempsSauvegarde(algo.tempsSauvegarde),tempsSortieFilCalcul(algo.tempsSortieFilCalcul)
|
|
,tempsRaidSmEnerContact(algo.tempsRaidSmEnerContact)
|
|
,tempsSecondMembreEnergContact(algo.tempsSecondMembreEnergContact)
|
|
,temps_CL(algo.temps_CL),temps_CLL(algo.temps_CLL)
|
|
,temps_lois_comportement(algo.temps_lois_comportement),temps_metrique_K_SM(algo.temps_metrique_K_SM)
|
|
,temps_chargement(algo.temps_chargement),temps_rech_contact(algo.temps_rech_contact)
|
|
,ptalgocombi(NULL)
|
|
#ifndef UTILISATION_MPI
|
|
,lesTempsCpu(16)
|
|
#else
|
|
,lesTempsCpu(18),distribution_CPU_algo(algo.distribution_CPU_algo) // distribution de charge sur les CPU
|
|
,temps_transfert_court(algo.temps_transfert_court),temps_transfert_long(algo.temps_transfert_long)
|
|
,temps_attente(algo.temps_attente)
|
|
#endif
|
|
|
|
//---------- stockage pour la transmission des grandeurs consultables -----
|
|
// ,stock_compteur(algo.stock_compteur),val_stock_compteur(NULL)
|
|
// ,stock_icharge(algo.stock_icharge),val_stock_icharge(NULL)
|
|
|
|
{ // on met à jour ParaGlob
|
|
ParaGlob::param->ChangeParaAlgoControleActifs(&pa);
|
|
|
|
if (vglob_stat != NULL)
|
|
vglob_stat = new Vecteur(*vglob_stat);
|
|
// // 2) on adapte le stockage
|
|
// val_stock_compteur = (Grandeur_scalaire_entier*) stock_compteur.Grandeur_pointee();
|
|
// val_stock_icharge = (Grandeur_scalaire_entier*) stock_icharge.Grandeur_pointee();
|
|
|
|
};
|
|
|
|
// destructeur
|
|
Algori::~Algori ()
|
|
{ if (toto_masse != NULL)
|
|
delete toto_masse;
|
|
if (cas_ass_eps != NULL) {delete cas_ass_eps;cas_ass_eps=NULL;}
|
|
if (Ass_eps != NULL) {delete Ass_eps;Ass_eps=NULL;}
|
|
if (cas_ass_eps11 != NULL) {delete cas_ass_eps11;cas_ass_eps11=NULL;}
|
|
if (Ass_eps11 != NULL) {delete Ass_eps11;Ass_eps11=NULL;}
|
|
if (cas_ass_sig != NULL) {delete cas_ass_sig;cas_ass_sig=NULL;}
|
|
if (Ass_sig != NULL) {delete Ass_sig;Ass_sig=NULL;}
|
|
if (cas_ass_sig11 != NULL) {delete cas_ass_sig11;cas_ass_sig11=NULL;}
|
|
if (Ass_sig11 != NULL) {delete Ass_sig11;Ass_sig11=NULL;}
|
|
if (cas_ass_err != NULL) {delete cas_ass_err;cas_ass_err=NULL;}
|
|
if (Ass_err != NULL) {delete Ass_err;Ass_err=NULL;}
|
|
if (mat_glob_sigeps != NULL) {delete mat_glob_sigeps;mat_glob_sigeps=NULL;}
|
|
if (vglob_sigeps != NULL) {delete vglob_sigeps;vglob_sigeps=NULL;}
|
|
if (vglobal_sigeps != NULL) {delete vglobal_sigeps;vglobal_sigeps=NULL;}
|
|
if (vglob_stat != NULL) delete vglob_stat;
|
|
};
|
|
|
|
//lecture des parametres de controle
|
|
// et préparation de la sortie des paramètres globaux
|
|
void Algori::Lecture(UtilLecture & entreePrinc,ParaGlob & paraglob,LesMaillages& lesMail)
|
|
{ // lecture des paramètres
|
|
pa.Lecture_paraAlgoControle(entreePrinc);
|
|
// mise à jour des paramètres globaux
|
|
paraglob.Change_Nb_diggit_double(1,pa.Nb_diggit_double_calcul());
|
|
paraglob.Change_Nb_diggit_double(2,pa.Nb_diggit_double_graphique());
|
|
paraglob.Change_Nb_diggit_double(3,pa.Nb_diggit_double_ecran());
|
|
if (paraglob.EtatDeLaLecturePointInfo() <= 0) // cas de la première lecture dans le .info
|
|
Preparation_conteneurs_interne(lesMail);
|
|
// // -- modif concernant le stockage global pour volume déplacé: cas d'élément 2D dans un calcul 3D
|
|
// // on met à jour le tableau de volume déplacé en fonction du nombre de maillage effectif
|
|
// int nbMailMax = lesMail.NbMaillage();
|
|
// // normalement ne fait rien si la taille n'est pas changé
|
|
// if (vol_total2D_avec_plan_ref.Taille() != nbMailMax)
|
|
// {vol_total2D_avec_plan_ref.Change_taille(nbMailMax,Coordonnee(ParaGlob::Dimension()));
|
|
// // on remet à jour le stockage des grandeurs globales
|
|
// if ( pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
// { listeVarGlob["vol_total2D_avec_plan_yz"]=&(vol_total2D_avec_plan_ref(1)(1));
|
|
// listeVarGlob["vol_total2D_avec_plan_xz"]=&(vol_total2D_avec_plan_ref(1)(2));
|
|
// listeVarGlob["vol_total2D_avec_plan_xy"]=&(vol_total2D_avec_plan_ref(1)(3));
|
|
// };
|
|
// // s'il y a plus de 1 maillage, on définit de nouvelles variables globales
|
|
// if (pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
// for (int nbMail =2; nbMail<= nbMailMax; nbMail++)
|
|
// { // l'ordre des string est fait pour que le switch ensuite soit ok
|
|
// string nom1("vol_total2D_avec_plan_xy_"+ChangeEntierSTring(nbMail));
|
|
// listeVarGlob[nom1]=&(vol_total2D_avec_plan_ref(nbMail)(3));
|
|
// TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
|
|
// (VOL_ELEM_AVEC_PLAN_REF,nom1,SCALAIRE_DOUBLE);
|
|
// string nom2("vol_total2D_avec_plan_yz_"+ChangeEntierSTring(nbMail));
|
|
// listeVarGlob[nom2]=&(vol_total2D_avec_plan_ref(nbMail)(1));
|
|
// TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
|
|
// (VOL_ELEM_AVEC_PLAN_REF,nom2,SCALAIRE_DOUBLE);
|
|
// string nom3("vol_total2D_avec_plan_xz_"+ChangeEntierSTring(nbMail));
|
|
// listeVarGlob[nom3]=&(vol_total2D_avec_plan_ref(nbMail)(2));
|
|
// TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
|
|
// (VOL_ELEM_AVEC_PLAN_REF,nom3,SCALAIRE_DOUBLE);
|
|
//
|
|
// // --- on ajoute les grandeurs au niveau de paraglob
|
|
// // si elles n'existent pas
|
|
// double titi; // une grandeur de travail
|
|
// Grandeur_scalaire_double grand_courant(titi); // idem
|
|
// TypeQuelconque typQ1(GENERIQUE_UNE_GRANDEUR_GLOBALE,NU_DDL,grand_courant); // idem
|
|
// switch (ParaGlob::Dimension())
|
|
// { case 3: if (ParaGlob::param->GrandeurGlobal(nom1) == NULL)
|
|
// ParaGlob::param->Ajout_grandeur_consultable(&typQ1,nom1);
|
|
// case 2: if (ParaGlob::param->GrandeurGlobal(nom2) == NULL)
|
|
// ParaGlob::param->Ajout_grandeur_consultable(&typQ1,nom2);
|
|
// case 1: if (ParaGlob::param->GrandeurGlobal(nom3) == NULL)
|
|
// ParaGlob::param->Ajout_grandeur_consultable(&typQ1,nom1);
|
|
// default: break;
|
|
// };
|
|
// };
|
|
// };
|
|
};
|
|
// préparation des conteneurs interne, utilisés après la lecture
|
|
// où dans le cas où il n'y a pas de lecture directe
|
|
// (pour un sous algo via un algo combiné par exemple)
|
|
void Algori::Preparation_conteneurs_interne(LesMaillages& lesMail)
|
|
{ // on teste la présence d'un élément , si oui on considère que tous les autres sont présents
|
|
map < string, const double * , std::less <string> >::iterator imap;
|
|
imap = listeVarGlob.find("energie_cinetique");
|
|
if (imap == listeVarGlob.end()) // la map ne contient pas "energie_cinetique"
|
|
{
|
|
// remplissage de la liste des variables scalaires globales
|
|
// tout d'abord pour les énergies globales
|
|
listeVarGlob["energie_cinetique"]=&E_cin_tdt; listeVarGlob["energie_interne"]=&E_int_tdt;
|
|
listeVarGlob["energie_externe"]=&E_ext_tdt; listeVarGlob["energie_bilan"]=&bilan_E;
|
|
// la quantité de mouvement totale
|
|
listeVarGlob["quantite_mouvement"]=&q_mov_tdt;
|
|
// puis pour les puissances
|
|
listeVarGlob["puissance_acceleration"]=&P_acc_tdt; listeVarGlob["puissance_interne"]=&P_int_tdt;
|
|
listeVarGlob["puissance_externe"]=&P_ext_tdt; listeVarGlob["puissance_bilan"]=&bilan_P_tdt;
|
|
// // puis les énergies globales pour chaque maillage
|
|
// listeVarGlob["ener_cin_par_maillage"]=&E_cin_t; listeVarGlob["energie_interne"]=&E_int_t;
|
|
// listeVarGlob["energie_externe"]=&E_ext_t; listeVarGlob["energie_bilan"]=&bilan_E;
|
|
// // la quantité de mouvement totale
|
|
// listeVarGlob["quantite_mouvement"]=&q_mov_t; listeVarGlob["energie_bilan"]=&bilan_E;
|
|
// // puis pour les puissances
|
|
// listeVarGlob["puissance_acceleration"]=&P_acc_t; listeVarGlob["puissance_interne"]=&P_int_t;
|
|
// listeVarGlob["puissance_externe"]=&P_ext_t; listeVarGlob["puissance_bilan"]=&bilan_P_t;
|
|
// pour les énergies internes, elles sont systématiquement calculées
|
|
listeVarGlob["energie_elastique"]=&energTotal.EnergieElastique();
|
|
listeVarGlob["energie_plastique"]=&energTotal.DissipationPlastique();
|
|
listeVarGlob["energie_visqueuse"]=&energTotal.DissipationVisqueuse();
|
|
listeVarGlob["energie_hourglass"]=&energHourglass;
|
|
listeVarGlob["energie_penalisation"]=&energPenalisation;
|
|
listeVarGlob["energie_stabilisation_membrane_biel"]=&energStabiliMembBiel;
|
|
listeVarGlob["energie_frot_elast"]=&energFrottement.EnergieElastique();
|
|
listeVarGlob["energie_frot_plast"]=&energFrottement.DissipationPlastique();
|
|
listeVarGlob["energie_frot_visq"]=&energFrottement.DissipationVisqueuse();
|
|
// cas d'une viscosité numérique on l'a sort systématiquement même si elle est nulle
|
|
// ce qui permet une vérif éventuelle
|
|
listeVarGlob["energie_visco_numerique"]=&E_visco_numerique_tdt;
|
|
// idem pour le bulk viscosity
|
|
listeVarGlob["energie_bulk_viscosity"]=&E_bulk;listeVarGlob["puissance_bulk_viscosity"]=&P_bulk;
|
|
// volume totale de la matière
|
|
listeVarGlob["volume_total_matiere"]=&volume_total_matiere;
|
|
// -- volume déplacé: cas d'élément 2D dans un calcul 3D
|
|
// vol_total2D_avec_plan_ref; // volume total entre la surface et : yz, xz,xy
|
|
// dans une première étape on considère uniquement un seul maillage, ce sera changé éventuellement
|
|
// aprés
|
|
if ( pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
{ listeVarGlob["vol_total2D_avec_plan_yz"]=&(vol_total2D_avec_plan_ref(1)(1));
|
|
listeVarGlob["vol_total2D_avec_plan_xz"]=&(vol_total2D_avec_plan_ref(1)(2));
|
|
listeVarGlob["vol_total2D_avec_plan_xy"]=&(vol_total2D_avec_plan_ref(1)(3));
|
|
};
|
|
// -- cas des temps cpu
|
|
|
|
// //------- temps cpu -----
|
|
// Temps_CPU_HZpp tempsInitialisation; // lesTempsCpu(1)
|
|
// Temps_CPU_HZpp tempsMiseAjourAlgo; // lesTempsCpu(2)
|
|
// Temps_CPU_HZpp tempsCalEquilibre; // lesTempsCpu(3)
|
|
// Temps_CPU_HZpp tempsRaidSmEner; // lesTempsCpu(4)
|
|
// Temps_CPU_HZpp tempsSecondMembreEnerg; // lesTempsCpu(5)
|
|
// Temps_CPU_HZpp tempsResolSystemLineaire; // lesTempsCpu(6)
|
|
// Temps_CPU_HZpp tempsSauvegarde; // lesTempsCpu(7)
|
|
// Temps_CPU_HZpp tempsSortieFilCalcul; // lesTempsCpu(8)
|
|
// Temps_CPU_HZpp tempsRaidSmEnerContact; // lesTempsCpu(9)
|
|
// Temps_CPU_HZpp tempsSecondMembreEnergContact; // lesTempsCpu(10)
|
|
// Temps_CPU_HZpp temps_CL; // lesTempsCpu(11)
|
|
// Temps_CPU_HZpp temps_CLL; // lesTempsCpu(12)
|
|
// Temps_CPU_HZpp temps_lois_comportement; // lesTempsCpu(13)
|
|
// Temps_CPU_HZpp temps_metrique_K_SM; // lesTempsCpu(14)
|
|
// Temps_CPU_HZpp temps_chargement; // lesTempsCpu(15)
|
|
// Temps_CPU_HZpp temps_rech_contact; // lesTempsCpu(16)
|
|
// si calcul //:
|
|
// Temps_CPU_HZpp temps_transfert_court; // lesTempsCpu(17)
|
|
// Temps_CPU_HZpp temps_transfert_long ; // lesTempsCpu(19)
|
|
// Temps_CPU_HZpp temps_attente ; // lesTempsCpu(18)
|
|
|
|
// Tableau <Coordonnee3> lesTempsCpu; // un tableau intermédiaire qui récupère et globalise les temps pour les sorties
|
|
// // via listeVarGlob, mais c'est les variables Temps_CPU_HZpp qui stockent
|
|
// // réellement les temps
|
|
listeVarGlob["tpsU_InitAlgo"]=&lesTempsCpu(1)(1);
|
|
// listeVarGlob["tps_Syst_InitAlgo"]=&lesTempsCpu(1)(2);
|
|
// listeVarGlob["tps_Reel_InitAlgo"]=&lesTempsCpu(1)(3);
|
|
listeVarGlob["tpsU_MiseAJourAlgo"]=&lesTempsCpu(2)(1);
|
|
// listeVarGlob["tps_Syst_MiseAJourAlgo"]=&lesTempsCpu(2)(2);
|
|
// listeVarGlob["tps_Reel_MiseAJourAlgo"]=&lesTempsCpu(2)(3);
|
|
listeVarGlob["tpsU_CalEquilibre"]=&lesTempsCpu(3)(1);
|
|
// listeVarGlob["tps_Syst_CalEquilibre"]=&lesTempsCpu(3)(2);
|
|
// listeVarGlob["tps_Reel_CalEquilibre"]=&lesTempsCpu(3)(3);
|
|
listeVarGlob["tpsU_MatSmLoc"]=&lesTempsCpu(4)(1);
|
|
// listeVarGlob["tps_Syst_MatSmLoc"]=&lesTempsCpu(4)(2);
|
|
// listeVarGlob["tps_Reel_MatSmLoc"]=&lesTempsCpu(4)(3);
|
|
listeVarGlob["tpsU_SmLoc"]=&lesTempsCpu(5)(1);
|
|
// listeVarGlob["tps_Syst_SmLoc"]=&lesTempsCpu(5)(2);
|
|
// listeVarGlob["tps_Reel_SmLoc"]=&lesTempsCpu(5)(3);
|
|
listeVarGlob["tpsU_ResSystLineaire"]=&lesTempsCpu(6)(1);
|
|
// listeVarGlob["tps_Syst_ResSystLineaire"]=&lesTempsCpu(6)(2);
|
|
// listeVarGlob["tps_Reel_ResSystLineaire"]=&lesTempsCpu(6)(3);
|
|
listeVarGlob["tpsU_Sauvegarde"]=&lesTempsCpu(7)(1);
|
|
// listeVarGlob["tps_Syst_Sauvegarde"]=&lesTempsCpu(7)(2);
|
|
// listeVarGlob["tps_Reel_Sauvegarde"]=&lesTempsCpu(7)(3);
|
|
listeVarGlob["tpsU_SortieFilCalcul"]=&lesTempsCpu(8)(1);
|
|
// listeVarGlob["tps_Syst_SortieFilCalcul"]=&lesTempsCpu(8)(2);
|
|
// listeVarGlob["tps_Reel_SortieFilCalcul"]=&lesTempsCpu(8)(3);
|
|
listeVarGlob["tpsU_contactMatSmLoc"]=&lesTempsCpu(9)(1);
|
|
// listeVarGlob["tps_Syst_contactMatSmLoc"]=&lesTempsCpu(9)(2);
|
|
// listeVarGlob["tps_Reel_contactMatSmLoc"]=&lesTempsCpu(9)(3);
|
|
listeVarGlob["tpsU_contactSmLoc"]=&lesTempsCpu(10)(1);
|
|
// listeVarGlob["tps_Syst_contactSmLoc"]=&lesTempsCpu(10)(2);
|
|
// listeVarGlob["tps_Reel_contactSmLoc"]=&lesTempsCpu(10)(3);
|
|
// le tableau sert également aux temps pour la mise en place des CL et CLL
|
|
// car la classe LesCondLim n'a pas vocation a gérer les I/O des tps de cpu
|
|
// par contre les temps sont stocké dans LesCondLim, lesTempsCpu sert d'intermédiaire
|
|
listeVarGlob["tpsU_CL"]=&lesTempsCpu(11)(1);
|
|
// listeVarGlob["tps_Syst_CL"]=&lesTempsCpu(11)(2);
|
|
// listeVarGlob["tps_Reel_CL"]=&lesTempsCpu(11)(3);
|
|
listeVarGlob["tpsU_CLL"]=&lesTempsCpu(12)(1);
|
|
// listeVarGlob["tps_Syst_CLL"]=&lesTempsCpu(12)(2);
|
|
// listeVarGlob["tps_Reel_CLL"]=&lesTempsCpu(12)(3);
|
|
listeVarGlob["tpsU_Lois_comp"]=&lesTempsCpu(13)(1);
|
|
listeVarGlob["tpsU_Metriques"]=&lesTempsCpu(14)(1);
|
|
listeVarGlob["tpsU_chargement"]=&lesTempsCpu(15)(1);
|
|
listeVarGlob["tpsU_rech_contact"]=&lesTempsCpu(16)(1);
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul parallèle
|
|
listeVarGlob["tpsU_transfert_inter_cpu"]=&lesTempsCpu(17)(1);
|
|
listeVarGlob["tpsU_attente_inter_cpu"]=&lesTempsCpu(18)(1);
|
|
#endif
|
|
|
|
// cas des vecteurs globaux
|
|
int dim = ParaGlob::Dimension();
|
|
if (ParaGlob::AxiSymetrie())
|
|
dim--;
|
|
// def des grandeurs courantes de type coordonnee
|
|
Coordonnee coor(dim); // un type coordonnee typique
|
|
// maintenant on définit une grandeur typique de type Grandeur_coordonnee
|
|
Grandeur_coordonnee gt(coor);
|
|
// def d'un type quelconque représentatif pour un vecteur force à chaque noeud
|
|
{ // pour les forces externes
|
|
TypeQuelconque typQ(FORCE_GENE_EXT,X1,gt);
|
|
listeVecGlob.push_back(typQ);
|
|
};
|
|
{ // pour les forces internes
|
|
TypeQuelconque typQ(FORCE_GENE_INT,X1,gt);
|
|
listeVecGlob.push_back(typQ);
|
|
};
|
|
{ // pour les forces totales = internes + externes
|
|
TypeQuelconque typQ(FORCE_GENE_TOT,X1,gt);
|
|
listeVecGlob.push_back(typQ);
|
|
};
|
|
{ // pour les forces résidu d'équilibre
|
|
TypeQuelconque typQ(RESIDU_GLOBAL,X1,gt);
|
|
listeVecGlob.push_back(typQ);
|
|
};
|
|
{ // pour les variations de positions
|
|
TypeQuelconque typQ(DELTA_XI,X1,gt);
|
|
listeVecGlob.push_back(typQ);
|
|
};
|
|
listeVecGlob.sort(); // on ordonne la liste
|
|
listeVecGlob.unique(); // suppression des doublons
|
|
|
|
// -- modif concernant le stockage global pour volume déplacé: cas d'élément 2D dans un calcul 3D
|
|
// on met à jour le tableau de volume déplacé en fonction du nombre de maillage effectif
|
|
int nbMailMax = lesMail.NbMaillage();
|
|
// normalement ne fait rien si la taille n'est pas changé
|
|
if (vol_total2D_avec_plan_ref.Taille() != nbMailMax)
|
|
{vol_total2D_avec_plan_ref.Change_taille(nbMailMax,Coordonnee(ParaGlob::Dimension()));
|
|
// on remet à jour le stockage des grandeurs globales
|
|
if ( pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
{ listeVarGlob["vol_total2D_avec_plan_yz"]=&(vol_total2D_avec_plan_ref(1)(1));
|
|
listeVarGlob["vol_total2D_avec_plan_xz"]=&(vol_total2D_avec_plan_ref(1)(2));
|
|
listeVarGlob["vol_total2D_avec_plan_xy"]=&(vol_total2D_avec_plan_ref(1)(3));
|
|
};
|
|
// s'il y a plus de 1 maillage, on définit de nouvelles variables globales
|
|
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
for (int nbMail =2; nbMail<= nbMailMax; nbMail++)
|
|
{ // l'ordre des string est fait pour que le switch ensuite soit ok
|
|
string nom1("vol_total2D_avec_plan_xy_"+ChangeEntierSTring(nbMail));
|
|
listeVarGlob[nom1]=&(vol_total2D_avec_plan_ref(nbMail)(3));
|
|
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
|
|
(VOL_ELEM_AVEC_PLAN_REF,nom1,SCALAIRE_DOUBLE);
|
|
string nom2("vol_total2D_avec_plan_yz_"+ChangeEntierSTring(nbMail));
|
|
listeVarGlob[nom2]=&(vol_total2D_avec_plan_ref(nbMail)(1));
|
|
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
|
|
(VOL_ELEM_AVEC_PLAN_REF,nom2,SCALAIRE_DOUBLE);
|
|
string nom3("vol_total2D_avec_plan_xz_"+ChangeEntierSTring(nbMail));
|
|
listeVarGlob[nom3]=&(vol_total2D_avec_plan_ref(nbMail)(2));
|
|
TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
|
|
(VOL_ELEM_AVEC_PLAN_REF,nom3,SCALAIRE_DOUBLE);
|
|
|
|
// --- on ajoute les grandeurs au niveau de paraglob
|
|
// si elles n'existent pas
|
|
double titi=0.; // une grandeur de travail
|
|
Grandeur_scalaire_double grand_courant(titi); // idem
|
|
TypeQuelconque typQ1(GENERIQUE_UNE_GRANDEUR_GLOBALE,NU_DDL,grand_courant); // idem
|
|
switch (ParaGlob::Dimension())
|
|
{ case 3: if (ParaGlob::param->GrandeurGlobal(nom1) == NULL)
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,nom1);
|
|
case 2: if (ParaGlob::param->GrandeurGlobal(nom2) == NULL)
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,nom2);
|
|
case 1: if (ParaGlob::param->GrandeurGlobal(nom3) == NULL)
|
|
ParaGlob::param->Ajout_grandeur_consultable(&typQ1,nom1);
|
|
default: break;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
// affichage des parametres
|
|
void Algori::Affiche() const// affichage de tous les parametres
|
|
{ Affiche1();
|
|
Affiche2();
|
|
};
|
|
void Algori::Affiche1() const// affichage du type de calcul
|
|
{ cout << "--> type de calcul = " << Nom_TypeCalcul(typeCalcul) << '\n';
|
|
cout << paraTypeCalcul.Taille() << " parametre(s) = ";
|
|
int nbcar = ParaGlob::NbdigdoEC();
|
|
for (int i=1; i<= paraTypeCalcul.Taille(); i++)
|
|
cout << setw(nbcar) << setprecision(nbcar) << paraTypeCalcul(i) << " , ";
|
|
cout << endl;
|
|
};
|
|
void Algori::Affiche2() const// affichage des parametres de controle
|
|
{ pa.Affiche();
|
|
};
|
|
|
|
|
|
// examine s'il y a convergence ou pas en fonction des parametres
|
|
// de controle et du resultat du systeme lineaire
|
|
// affiche: indique si l'on veut l'affichage ou non des infos
|
|
// itera : correspond au compteur d'itération dans un cas d'équilibre itératif (cal implicite par exemple)
|
|
// arrêt: indique qu'il vaut mieux arrêter le calcul
|
|
bool Algori::Convergence
|
|
(bool affiche,double last_var_ddl_max,Vecteur& residu,double maxPuissExt,double maxPuissInt,double maxReaction
|
|
,int itera,bool& arret)
|
|
{ string type_norme = pa.Norme().nom1; // pour simplifier
|
|
arret = false; // a priori on ne s'arrête pas
|
|
double maxresidu = residu.Max_val_abs();
|
|
// --- on passe les infos au niveau global
|
|
{ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(MAXPUISSEXT,maxPuissExt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(MAXPUISSINT,maxPuissInt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(MAXREACTION,maxReaction);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(MAXRESIDUGLOBAL,maxresidu);
|
|
};
|
|
|
|
////debug ------
|
|
// int iddl=0;
|
|
// maxresidu = residu.Max_val_abs(iddl);
|
|
// cout << "\n iddl= "<<iddl << " residu_total(iddl)= "<<residu(iddl) ;
|
|
////fin debug ------
|
|
|
|
double pa_precision = pa.Precision(); // initialisation de la précision demandé
|
|
if (modulation_precision != NULL) // cas où en plus on fait une modulation de précision
|
|
{pa_precision *= (modulation_precision->Valeur_pour_variables_globales())(1);}
|
|
|
|
double prec_res_mini = 4; // 1 mini
|
|
// dans le cas où on veut un test de convergence uniquement sur la partie statique
|
|
if ( (arret_a_equilibre_statique ) // le dimensionnement se fera à l'affectation (=)
|
|
&& (type_calcul_visqu_critique || pa.Amort_visco_artificielle()))
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (vglob_stat == NULL)
|
|
{ cout << "\n erreur le vecteur vglob_stat n'est pas attribue (=NULL) "
|
|
<< " on ne peut pas effectuer la convergence avec arret en equilibre statique uniquement "
|
|
<< " revoir les parametres (ou se plaindre officiellement !! ) ";
|
|
cout << "\n Algori::Convergence(..";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// if (vglob_stat->Taille() != 0) // si la taille est non nulle
|
|
// // cela veut dire que le vecteur a été affecté, donc on peut l'utiliser
|
|
maxresidu = vglob_stat->Max_val_abs();
|
|
};
|
|
int nbcar = ParaGlob::NbdigdoEC();
|
|
|
|
// 1) --- affichage des maxis de puissances virtuelles
|
|
if (affiche && (ParaGlob::NiveauImpression() > 1))
|
|
{ cout << "\n max puissance exterieure = " << setprecision(nbcar)<< maxPuissExt ;
|
|
cout << "\n max puissance interieurs = " << setprecision(nbcar)<< maxPuissInt ;
|
|
cout << "\n max des reactions = " << setprecision(nbcar)<< maxReaction ;
|
|
cout << "\n max du residu total = " << setprecision(nbcar)<< maxresidu ;
|
|
};
|
|
// 2) --- affichage de la norme
|
|
double laNorme = 0.; // valeur par défaut
|
|
|
|
if (strstr(type_norme.c_str(),"Residu/Reaction_et_Residu"))
|
|
{cout << "\n *** norme exploratoire: ";
|
|
// on initialise le cas "Residu"
|
|
laNorme = maxresidu; //init
|
|
double maxpuissance =MaX(maxReaction,MaX(maxPuissExt,maxPuissInt));
|
|
if (maxpuissance > prec_res_mini)
|
|
// cas de la norme Residu/Reaction
|
|
{if (maxReaction < 1.e-8)
|
|
laNorme = maxresidu;
|
|
else
|
|
laNorme = maxresidu/maxpuissance;
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme Residu/Reaction --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else // cas d'un résidu très faible
|
|
{pa_precision = prec_res_mini/50.;
|
|
if (affiche&&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme Residu --> " << setprecision(nbcar)<< laNorme ;
|
|
cout << "\n: pa_precision est mis au mini de la force admise: "
|
|
<< setprecision(nbcar)<< pa_precision << endl;
|
|
};
|
|
}
|
|
else if (strstr(type_norme.c_str(),"Residu/Reaction"))
|
|
{if (maxReaction < 1.e-8)
|
|
laNorme = maxresidu;
|
|
else
|
|
laNorme = maxresidu/maxReaction;
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme Residu/Reaction --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"Residu/PVExterne"))
|
|
{ if (maxPuissExt < 1.e-8)
|
|
laNorme = maxresidu;
|
|
else
|
|
laNorme = maxresidu/maxPuissExt;
|
|
if (affiche&&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n*** Norme Residu/PVExterne --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"Residu/PVInterne"))
|
|
{ if (maxPuissInt < 1.e-8)
|
|
laNorme = maxresidu;
|
|
else
|
|
laNorme = maxresidu/maxPuissInt;
|
|
if (affiche&&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n*** Norme Residu/PVInterne --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"Residu/maxPVI"))
|
|
{ // détermination du maximum des puissances
|
|
double maxpuissance =MaX(maxReaction,MaX(maxPuissExt,maxPuissInt));
|
|
if (maxpuissance < 1.e-8)
|
|
laNorme = maxresidu;
|
|
else
|
|
laNorme = maxresidu/maxpuissance;
|
|
if (affiche&&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n*** Norme Residu/maxPVI --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"Residu"))
|
|
{laNorme = maxresidu;
|
|
if (affiche&&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme Residu --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"min(Res,Res/Reaction)"))
|
|
{if (maxReaction < 1.e-8)
|
|
laNorme = maxresidu;
|
|
else
|
|
laNorme = MiN(maxresidu,maxresidu/maxReaction);
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme min(Res,Res/Reaction) --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"min(Res,Res/MaX(Reaction_et_PVExterne))"))
|
|
{if (MaX(maxReaction,maxPuissExt) < 1.e-8)
|
|
laNorme = maxresidu;
|
|
else
|
|
laNorme = MiN(maxresidu,maxresidu/MaX(maxReaction,maxPuissExt));
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme min(Res,Res/MaX(Reaction_et_PVExterne)) --> "
|
|
<< setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"E_cinetique/E_statique_ET_ResSurReact"))
|
|
{if (affiche && (ParaGlob::NiveauImpression() > 1))
|
|
{ cout << "\n E_cinetique = " << setprecision(nbcar)<< E_cin_tdt ;
|
|
cout << "\n E_ext = " << setprecision(nbcar)<< -E_ext_tdt ;
|
|
cout << "\n E_int = " << setprecision(nbcar)<< E_int_tdt ;
|
|
};
|
|
double max_abs_eners = MaX(Dabs(E_int_tdt),Dabs(E_ext_tdt));
|
|
if (MaX(max_abs_eners,maxReaction) < 1.e-8)
|
|
laNorme = MaX(E_cin_tdt,maxresidu);
|
|
else if (maxReaction < 1.e-8)
|
|
laNorme = MaX(E_cin_tdt/max_abs_eners,maxresidu);
|
|
else
|
|
laNorme = MaX(E_cin_tdt/max_abs_eners,maxresidu/maxReaction);
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme E_cinetique/E_statique_ET_ResSurReact --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"E_cinetique/E_statique_ET_Res/Reac_et_Fext"))
|
|
{if (affiche && (ParaGlob::NiveauImpression() > 1))
|
|
{ cout << "\n E_cinetique = " << setprecision(nbcar)<< E_cin_tdt ;
|
|
cout << "\n E_ext = " << setprecision(nbcar)<< -E_ext_tdt ;
|
|
cout << "\n E_int = " << setprecision(nbcar)<< E_int_tdt ;
|
|
};
|
|
double max_abs_eners = MaX(Dabs(E_int_tdt),Dabs(E_ext_tdt));
|
|
double maxpuiss_reac =MaX(maxReaction,MaX(maxPuissExt,maxPuissInt));
|
|
if (MaX(max_abs_eners,maxReaction) < 1.e-8)
|
|
laNorme = MaX(E_cin_tdt,maxresidu);
|
|
else if (maxpuiss_reac < 1.e-8)
|
|
laNorme = MaX(E_cin_tdt/max_abs_eners,maxresidu);
|
|
else
|
|
laNorme = MaX(E_cin_tdt/max_abs_eners,maxresidu/maxpuiss_reac);
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** E_cinetique/E_statique_ET_Res/Reac_et_Fext --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"E_cin/E_stat_ET_min(Res,Res/Reac_et_Fext)"))
|
|
{if (affiche && (ParaGlob::NiveauImpression() > 1))
|
|
{ cout << "\n E_cinetique = " << setprecision(nbcar)<< E_cin_tdt ;
|
|
cout << "\n E_ext = " << setprecision(nbcar)<< -E_ext_tdt ;
|
|
cout << "\n E_int = " << setprecision(nbcar)<< E_int_tdt ;
|
|
};
|
|
double max_abs_eners = MaX(Dabs(E_int_tdt),Dabs(E_ext_tdt));
|
|
double maxpuiss_reac =MaX(maxReaction,MaX(maxPuissExt,maxPuissInt));
|
|
if (MaX(max_abs_eners,maxReaction) < 1.e-8)
|
|
laNorme = MaX(E_cin_tdt,maxresidu);
|
|
else if (maxpuiss_reac < 1.e-8)
|
|
laNorme = MaX(E_cin_tdt/max_abs_eners,maxresidu);
|
|
else
|
|
laNorme = MaX(E_cin_tdt/max_abs_eners, MiN(maxresidu,maxresidu/maxpuiss_reac));
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** E_cin/E_stat_ET_min(Res,Res/Reac_et_Fext) --> "
|
|
<< setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"E_cinetique"))
|
|
{if (affiche && (ParaGlob::NiveauImpression() > 1))
|
|
{ cout << "\n E_cinetique = " << setprecision(nbcar)<< E_cin_tdt ;
|
|
cout << "\n E_ext = " << setprecision(nbcar)<< -E_ext_tdt ;
|
|
cout << "\n E_int = " << setprecision(nbcar)<< E_int_tdt ;
|
|
};
|
|
laNorme = E_cin_tdt;
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme E_cinetique --> " << setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"Bilan_puissance/Max(puiss)"))
|
|
{// si on est en statique, la puissance d'accélération = 0. normalement donc n'intervient pas
|
|
if (MaX(MaX(Dabs(P_acc_tdt),Dabs(P_int_tdt)),Dabs(P_ext_tdt)) < 1.e-8)
|
|
laNorme = bilan_P_tdt;
|
|
else
|
|
laNorme = MaX(bilan_P_tdt,bilan_P_tdt/MaX(MaX(Dabs(P_acc_tdt),Dabs(P_int_tdt)),Dabs(P_ext_tdt)));
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme Bilan_puissance/Max(puiss) --> "
|
|
<< setprecision(nbcar)<< laNorme ;
|
|
}
|
|
else if (strstr(type_norme.c_str(),"fonction_nD:"))
|
|
{ // il s'agit ici de l'utilisation d'une fonction nD
|
|
laNorme = (fct_norme->Valeur_pour_variables_globales())(1);
|
|
if (affiche && (ParaGlob::NiveauImpression() > 1))
|
|
{ cout << "\n E_cinetique = " << setprecision(nbcar)<< E_cin_tdt ;
|
|
cout << "\n E_ext = " << setprecision(nbcar)<< -E_ext_tdt ;
|
|
cout << "\n E_int = " << setprecision(nbcar)<< E_int_tdt ;
|
|
};
|
|
if (affiche &&(ParaGlob::NiveauImpression() > 1))
|
|
cout << "\n**** Norme "<< setprecision(nbcar)<<pa.Norme().nom2<<" --> "
|
|
<< setprecision(nbcar)<< laNorme ;
|
|
}
|
|
if (affiche && (modulation_precision != NULL)) // cas où en plus on fait une modulation de précision
|
|
cout << "\n (precision= "<< setprecision(nbcar)<<pa_precision<<" ) ";
|
|
|
|
if (affiche&&(ParaGlob::NiveauImpression() > 1)) cout << endl;
|
|
|
|
//---- debug
|
|
// if (E_cin_tdt == 0)
|
|
// { cout << "\n énergie nulle !! : \n Algori::Convergence(... ";
|
|
// Sortie(1);};
|
|
//---- fin debug
|
|
|
|
|
|
// 3) --- premier test brut de la convergence
|
|
if ((laNorme <= pa_precision) && (itera != 0))
|
|
{a_converge = true;} // cas courant de convergence
|
|
else if ((laNorme <= pa_precision) && (itera == 0))
|
|
// cas particulier de la première itération
|
|
{ if (maxPuissInt == 0.)
|
|
// si la puissance interne est strictement nulle, là il n'y a rien qui bouge, donc cela veut-dire
|
|
// que tout est bloqué, et on peut dire que cela a convergé car rien ne bougera après
|
|
{a_converge = true;}
|
|
else if ((maxPuissInt <= ConstMath::trespetit) && (maxPuissExt > ConstMath::petit))
|
|
// on a théoriquement convergé, mais on a une puissance externe non nulle et une puissance interne nulle
|
|
// donc on est dans des petits nombres, il vaut mieux refaire un passage avec un calcul de delta ddl
|
|
{a_converge = false;}
|
|
else {a_converge = true;};
|
|
}
|
|
else
|
|
{a_converge = false;};
|
|
// une partie exploratoire
|
|
int nbcoup = 1;
|
|
if ((strstr(type_norme.c_str(),"Residu/Reaction_et_Residu")) && (!(laNorme <= pa_precision)) && (itera > nbcoup)
|
|
&& (nombre_de_mauvaises_convergences > nbcoup))
|
|
{ cout << "\n norme transitoire = " << setprecision(nbcar)
|
|
<< pa_precision * PUISSN(10.,nombre_de_mauvaises_convergences-nbcoup )
|
|
<< endl;
|
|
if (laNorme < pa_precision * PUISSN(10.,nombre_de_mauvaises_convergences-nbcoup ))
|
|
{a_converge = true;};
|
|
};
|
|
// fin de la partie exploratoire
|
|
|
|
// on met à jour le tableau de l'historique de l'évolution des résidus
|
|
// au minimum on sauvegarde le résidu actuel et le précédent
|
|
int nb_cycle_controle = MaX(2,pa.NbCycleControleResidu());
|
|
bool cycle_controle = false; // variable de pilotage: a priori le cycle est hors service
|
|
if (itera > 0)
|
|
{if (itera == 1)
|
|
// dimensionnement le premier incrément, puis mise en place pour les autres incréments
|
|
{ max_var_residu.Change_taille(nb_cycle_controle,ConstMath::tresgrand);};
|
|
if (itera <= nb_cycle_controle)
|
|
// cas ou on rempli le tableau max_var_residu sans s'en servir
|
|
{ max_var_residu(itera)=maxresidu;}
|
|
else
|
|
{ // cas où on rempli les tableaux et on fait une rotation
|
|
cycle_controle = true; // le cycle est en service
|
|
for (int i=1;i<nb_cycle_controle;i++)
|
|
{max_var_residu(i)=max_var_residu(i+1);}
|
|
max_var_residu(nb_cycle_controle)= maxresidu;
|
|
};
|
|
};
|
|
|
|
// cas où l'on prend en compte l'évolution des var ddl et/ou des max résidu
|
|
double var_mini_ddl = pa.VarMiniDdl();
|
|
// double var_maxi_ddl = pa.VarMaxiDdl();
|
|
int nbmax_cycle_test_var_residu= pa.PlageControleResidu();
|
|
// traitement initial dans le cas iteratif
|
|
if (itera > 0)
|
|
{ if ((pa.TypeDePilotage() == PILOT_GRADIENT)
|
|
||(strstr(type_norme.c_str(),"et_miniVarDdl")) || (strstr(type_norme.c_str(),"et_maxiVarDdl"))
|
|
|| (strstr(type_norme.c_str(),"et_VarRes")))
|
|
{ // initialisation éventuelle
|
|
if (itera == 1)
|
|
{nb_cycle_test_max_var_residu=0;}
|
|
if (itera > nb_cycle_controle)
|
|
{ //contrôle de la convergence que si ça n'a pas convergé
|
|
if (!a_converge)
|
|
{ // on signale qu'il vaut mieux arrêter car il n'y a pas de décroissance du résidu
|
|
if (((pa.TypeDePilotage() == PILOT_GRADIENT)||(strstr(type_norme.c_str(),"et_VarRes"))) &&
|
|
(max_var_residu(nb_cycle_controle) >= max_var_residu(1)))
|
|
{if(nb_cycle_test_max_var_residu > nbmax_cycle_test_var_residu)
|
|
{arret = true; phase_de_convergence =-2;}
|
|
else nb_cycle_test_max_var_residu++; }
|
|
// on signale qu'il vaut mieux arrêter car la variation de ddl est trop faible
|
|
if (((pa.TypeDePilotage() == PILOT_GRADIENT)||(strstr(type_norme.c_str(),"et_miniVarDdl"))) &&
|
|
(last_var_ddl_max <= var_mini_ddl)) {
|
|
arret = true; phase_de_convergence =-3;}
|
|
// on signale qu'il vaut mieux arrêter car la variation de ddl est trop grande
|
|
if (((pa.TypeDePilotage() == PILOT_GRADIENT)||(strstr(type_norme.c_str(),"et_maxiVarDdl"))) &&
|
|
(last_var_ddl_max <= var_mini_ddl)) {
|
|
arret = true; phase_de_convergence =-4;}
|
|
};
|
|
};
|
|
};
|
|
}; //- fin test sur itera
|
|
|
|
// cas où on demande de vérifier deux fois le résidu
|
|
if (strstr(type_norme.c_str(),"et_verification_ddouble"))
|
|
{// tout d'abord on ne peut pas s'arrêter si le cycle de convergence
|
|
if (itera > 0) // on n'intervient que pour les itérations > 0
|
|
{if (itera == 1) // on ne peut rien contrôler, donc par principe on repasse
|
|
{a_converge_iterMoins1 = a_converge; // on sauvegarde pour l'itération qui suie
|
|
a_converge = false;}
|
|
else // on est sup à 1
|
|
// on applique l'algo
|
|
{if (a_converge_iterMoins1 && a_converge)
|
|
{} // c'est ok on ne fait rien
|
|
else if (a_converge) // mais a_converge_iterMoins1 n'est pas vrai
|
|
{a_converge_iterMoins1 = a_converge; // on le met à vrai
|
|
a_converge = false; // on signal que la convergence n'est pas finie
|
|
};
|
|
};
|
|
}
|
|
else {a_converge = false;} ; // si itera = 0 on refait systématiquement une passe
|
|
};
|
|
|
|
// --- on passe les infos au niveau global
|
|
Transfert_ParaGlob_NORME_CONVERGENCE(laNorme);
|
|
|
|
//en dernier lieu on regarde si les puissances sont infinies ou nan
|
|
// si oui on signale une divergence associée
|
|
// maxPuissExt,double maxPuissInt,double maxReaction
|
|
if ((std::isinf(maxPuissExt))||( std::isnan(maxPuissExt)))
|
|
{if ((ParaGlob::NiveauImpression() > 2) || (permet_affichage> 0))
|
|
cout << "\n *** maxPuissExt inifni ou nan : divergence imposee *** ";
|
|
a_converge = false; phase_de_convergence=-11;arret = true;
|
|
};
|
|
if ((std::isinf(maxPuissInt))||( std::isnan(maxPuissInt)))
|
|
{if ((ParaGlob::NiveauImpression() > 2) || (permet_affichage> 0))
|
|
cout << "\n *** maxPuissInt inifni ou nan : divergence imposee *** ";
|
|
a_converge = false; phase_de_convergence=-11;arret = true;
|
|
};
|
|
if ((std::isinf(maxReaction))||( std::isnan(maxReaction)))
|
|
{if ((ParaGlob::NiveauImpression() > 2) || (permet_affichage> 0))
|
|
cout << "\n *** maxReaction inifni ou nan : divergence imposee *** ";
|
|
a_converge = false; phase_de_convergence=-11;arret = true;
|
|
};
|
|
|
|
// retour
|
|
return a_converge;
|
|
};
|
|
|
|
// sortie d'info sur un increment de calcul pour les ddl
|
|
// nb_casAssemb : donne le numéro du cas d'assemblage
|
|
void Algori::InfoIncrementDdl(LesMaillages * lesMail,
|
|
int inSol,double maxDeltaDdl,const Nb_assemb& nb_casAssemb)
|
|
{ // la variation maxi de ddl
|
|
// recherche des Ddl concernes
|
|
int nbNoeud1,nbMaillage1; double val0;
|
|
Ddl ddl1 = lesMail->NoeudIndice(inSol,nbNoeud1,nbMaillage1,val0,nb_casAssemb.n);
|
|
int nbcar = ParaGlob::NbdigdoEC();
|
|
|
|
// ecriture des infos
|
|
cout << "\n(assemblage " << nb_casAssemb.n << ") "
|
|
<< "delta maxi: " << setprecision(nbcar)<< maxDeltaDdl
|
|
<<", ddl " << ddl1.Nom()
|
|
<<", noeud/mail "<< nbNoeud1 << "/" << nbMaillage1
|
|
<<" , var total:"<< setprecision(nbcar)<< ddl1.Valeur() - val0
|
|
<< ", sur:" << setprecision(nbcar)<< ddl1.Valeur();
|
|
// passage en global
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(MAXvarDdl,maxDeltaDdl);
|
|
// on affiche les autres informations du même noeud si elles existent
|
|
Noeud& noe=lesMail->Noeud_LesMaille(nbMaillage1,nbNoeud1); // récup du noeud
|
|
Enum_ddl enumax=ddl1.Id_nom();
|
|
int inci= enumax - PremierDdlFamille(enumax) ; // incice de composante du ddl -1
|
|
bool absolue = true; // a priori on sort les infos en absolu
|
|
List_io <Enum_ddl> lienu = noe.Les_type_de_ddl(absolue); // récup de tous les types de ddl du noeud
|
|
List_io <Enum_ddl>::iterator il,ilfin=lienu.end(); bool autres_valeurs = false;
|
|
for (il=lienu.begin();il!=ilfin;il++)
|
|
{ Enum_ddl enu = *il;
|
|
if ( (enu!=ddl1.Id_nom()) && (noe.En_service(enu)) && ( (enu-PremierDdlFamille(enu))==inci))
|
|
{ if(!autres_valeurs) {cout << "\n autres ddl ";};
|
|
cout << Nom_ddl(enu) << " " ;
|
|
if (noe.Tdt())
|
|
{cout << setprecision(nbcar)<< noe.Valeur_tdt(enu)
|
|
<< " var " << setprecision(nbcar)<< noe.Valeur_tdt(enu)-noe.Valeur_t(enu);
|
|
}
|
|
else
|
|
{cout << setprecision(nbcar)<< noe.Valeur_t(enu)
|
|
<< " var " << setprecision(nbcar)<< noe.Valeur_t(enu)-noe.Valeur_0(enu);};
|
|
cout << "; ";
|
|
autres_valeurs=true;
|
|
};
|
|
};
|
|
cout << endl;
|
|
};
|
|
|
|
// sortie d'info sur un increment de calcul pour les réaction
|
|
// dans le cas d'un compteur, par exemple dans le cas implicite
|
|
// nb_casAssemb : donne le numéro du cas d'assemblage
|
|
void Algori::InfoIncrementReac(LesMaillages * lesMail,int compteur,
|
|
int inreaction,double maxreaction,const Nb_assemb& nb_casAssemb)
|
|
{ int nbNoeud2,nbMaillage2;
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return ;
|
|
#endif
|
|
|
|
Ddl ddl2 = lesMail->NoeudIndice(inreaction,nbNoeud2,nbMaillage2,nb_casAssemb.n);
|
|
int nbcar = ParaGlob::NbdigdoEC();
|
|
|
|
// ecriture des infos
|
|
cout << "\n ITERATION : " << compteur;
|
|
if (ParaGlob::NiveauImpression() > 1)
|
|
{cout << "\n(assemblage " << nb_casAssemb.n << ") "
|
|
<< " reaction maxi : " << setprecision(nbcar)<< maxreaction <<", du ddl " << ddl2.Nom()
|
|
<<", du noeud/maillage "<< nbNoeud2 << "/" << nbMaillage2 ;
|
|
};
|
|
cout << endl;
|
|
};
|
|
|
|
// sortie d'info sur un increment de calcul pour les réaction
|
|
// dans le cas explicite par exemple (pas de compteur par rapport
|
|
// au cas précédent)
|
|
// nb_casAssemb : donne le numéro du cas d'assemblage
|
|
void Algori::InfoIncrementReac(LesMaillages * lesMail,
|
|
int inreaction,double maxreaction,const Nb_assemb& nb_casAssemb)
|
|
{ int nbNoeud2,nbMaillage2;
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, pour l'instant seule la (ou les) matrices du CPU 0 sont concernées
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return ;
|
|
#endif
|
|
|
|
Ddl ddl2 = lesMail->NoeudIndice(inreaction,nbNoeud2,nbMaillage2,nb_casAssemb.n);
|
|
int nbcar = ParaGlob::NbdigdoEC();
|
|
|
|
// ecriture des infos
|
|
if (ParaGlob::NiveauImpression() > 1)
|
|
{cout << "\n(assemblage " << nb_casAssemb.n << ") "
|
|
<< " reaction maxi : " << setprecision(nbcar)<< maxreaction <<", du ddl " << ddl2.Nom()
|
|
<<", du noeud/maillage "<< nbNoeud2 << "/" << nbMaillage2 ;
|
|
cout << endl;
|
|
};
|
|
};
|
|
|
|
|
|
// calcul une approximation des différences énergie en jeux
|
|
// affichage éventuelle des ces énergies et du bilan
|
|
// V : ddl de vitesse
|
|
// coef_mass : en fait il faut utiliser 1/coef_mass * mat_mass pour la matrice masse, ceci due à la spécificité de l'algo
|
|
// les différentes énergie et efforts généralisées sont des variables internes à l'algo
|
|
// en sortie: énergie cinétique : E_cin_tdt, énergie interne : E_int_tdt, énergie externe = E_ext_tdt, bilan : bilan_E
|
|
// idem avec les puissances
|
|
// énergie visqueuse due aux forces visqueuses numériques
|
|
// icharge : compteur d'increment
|
|
// brestart : booleen qui indique si l'on est en restart ou pas
|
|
void Algori::CalEnergieAffichage(const double& coef_mass,const Vecteur & V,const Mat_abstraite& mat_mass
|
|
,const Vecteur & delta_X,int icharge,bool brestart,const Vecteur & gamma
|
|
,const Vecteur & forces_vis_num)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, pour l'instant seule le CPU 0 est concerné
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return ;
|
|
#endif
|
|
|
|
// -- le calcul est conditionnelle
|
|
if (icharge >= pa.NbIncrCalEnergie())
|
|
{int nbcar = ParaGlob::NbdigdoEC();
|
|
|
|
// --- cas des énergies ------
|
|
// initialisation
|
|
v_int.Change_taille(V.Taille()); v_int.Zero();
|
|
// calcul de l'énergie cinétique et de la quantité de mouvement
|
|
// v_int contient les quantités de mouvement locales à chaque ddl
|
|
E_cin_tdt = (0.5/coef_mass) * (V * (mat_mass.Prod_vec_mat(V,v_int)));
|
|
//---- debug
|
|
// if (E_cin_tdt == 0)
|
|
// { cout << "\n énergie nulle !! : \n Algori::CalEnergieAffichage(... ";
|
|
// Sortie(1);};
|
|
//---- fin debug
|
|
|
|
// calcul de la quantité de mouvement globale
|
|
q_mov_tdt = v_int.Somme();
|
|
// calcul de l'énergie interne dépensée
|
|
v_int.Zero(); // init à 0
|
|
if (!brestart)
|
|
{ // cas normal
|
|
v_int += F_int_t; v_int += F_int_tdt; E_int_tdt = E_int_t - 0.5 * (delta_X * v_int); }
|
|
else // cas d'un restart, F_int_t n'est pas défini, on utilise la formule des rectangles plutôt que des trapèzes
|
|
{ v_int += F_int_tdt; E_int_tdt = E_int_t - delta_X * v_int; }
|
|
// calcul de l'énergie externe dépensée
|
|
v_int.Zero(); // init à 0
|
|
if (!brestart)
|
|
{ // cas normal
|
|
v_int += F_ext_t; v_int += F_ext_tdt; E_ext_tdt = E_ext_t + 0.5 * (delta_X * v_int);}
|
|
else // cas d'un restart, F_int_t n'est pas défini, on utilise la formule des rectangles plutôt que des trapèzes
|
|
{ v_int += F_ext_tdt; E_ext_tdt = E_ext_t + delta_X * v_int;}
|
|
|
|
// bilan des énergies (on retire l'énergie cinétique initiale si elle exite)
|
|
bilan_E = E_cin_tdt - E_cin_0 + E_int_tdt - E_ext_tdt;
|
|
// --- cas des puissances ------
|
|
// calcul de la puissance d'accélération
|
|
v_int.Zero();
|
|
P_acc_tdt = (1./coef_mass) * (V * (mat_mass.Prod_vec_mat(gamma,v_int)));
|
|
// calcul de la puissance interne
|
|
P_int_tdt = V * F_int_tdt;
|
|
// calcul de la puissance externe
|
|
P_ext_tdt = V * F_ext_tdt;
|
|
// bilan des puissances
|
|
bilan_P_tdt = P_acc_tdt - P_int_tdt - P_ext_tdt;
|
|
// cas des forces visqueuses numériques
|
|
double puissance_visco_num = 0.;
|
|
if (pa.Amort_visco_artificielle())
|
|
{E_visco_numerique_tdt = E_visco_numerique_t + delta_X * forces_vis_num;
|
|
puissance_visco_num = V * forces_vis_num;
|
|
bilan_P_tdt += puissance_visco_num;
|
|
bilan_E += E_visco_numerique_tdt;
|
|
};
|
|
// --- affichage ----
|
|
if (( pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde))
|
|
&&(pa.AfficheIncrEnergie()))
|
|
{// cas des énergies
|
|
cout << "\n energies: cin= "<< setprecision(nbcar)<< E_cin_tdt
|
|
<<" int= " << setprecision(nbcar)<< E_int_tdt
|
|
<< " ext= "<< setprecision(nbcar)<< E_ext_tdt
|
|
<< " bilan= " << setprecision(nbcar)<< bilan_E
|
|
<< " qmv= " << setprecision(nbcar)<< q_mov_tdt;
|
|
|
|
// cas des puissances
|
|
cout << "\n puissances: acc= "<< setprecision(nbcar)<< P_acc_tdt
|
|
<<" int= " << setprecision(nbcar)<< P_int_tdt
|
|
<< " ext= " << setprecision(nbcar)<< P_ext_tdt
|
|
<< " bilan= " << setprecision(nbcar)<< bilan_P_tdt;
|
|
|
|
if (pa.Amort_visco_artificielle())
|
|
cout << "\n energie d'amortissement numerique: "
|
|
<< setprecision(nbcar)<< E_visco_numerique_tdt
|
|
<< " puissance d'amortissement numerique: "
|
|
<< setprecision(nbcar)<< puissance_visco_num;
|
|
};
|
|
// --- on passe les infos au niveau global
|
|
{ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_CINETIQUE,E_cin_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_EXTERNE,E_ext_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_INTERNE,E_int_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_VISCO_NUMERIQUE,E_visco_numerique_t);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_BILAN,bilan_E);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(QUANTITE_MOUVEMENT,q_mov_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(PUISSANCE_ACCELERATION,P_acc_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(PUISSANCE_INTERNE,P_int_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(PUISSANCE_EXTERNE,P_ext_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(PUISSANCE_BILAN,bilan_P_tdt);
|
|
}
|
|
};
|
|
};
|
|
|
|
// idem pour un calcul statique, c'est-à-dire sans énergie cinématique
|
|
// affichage éventuelle des ces énergies et du bilan
|
|
// icharge : compteur d'increment
|
|
// brestart : booleen qui indique si l'on est en restart ou pas
|
|
void Algori::CalEnergieAffichage(const Vecteur & delta_X,int icharge,bool brestart,const Vecteur & forces_vis_num)
|
|
{ // le calcul est conditionnelle
|
|
if (icharge >= pa.NbIncrCalEnergie())
|
|
{int nbcar = ParaGlob::NbdigdoEC();
|
|
// initialisation
|
|
v_int.Change_taille(delta_X.Taille()); v_int.Zero();
|
|
// calcul de l'énergie interne dépensée
|
|
if (!brestart)
|
|
{ // cas normal
|
|
v_int += F_int_t; v_int += F_int_tdt; E_int_tdt = E_int_t - 0.5 * (delta_X * v_int); }
|
|
else // cas d'un restart, F_int_t n'est pas défini, on utilise la formule des rectangles plutôt que des trapèzes
|
|
{ v_int += F_int_tdt; E_int_tdt = E_int_t - delta_X * v_int; }
|
|
// calcul de l'énergie externe dépensée
|
|
v_int.Zero(); // init à 0
|
|
if (!brestart)
|
|
{ // cas normal
|
|
v_int += F_ext_t; v_int += F_ext_tdt; E_ext_tdt = E_ext_t + 0.5 * (delta_X * v_int);}
|
|
else // cas d'un restart, F_ext_t n'est pas défini, on utilise la formule des rectangles plutôt que des trapèzes
|
|
{ v_int += F_ext_tdt; E_ext_tdt = E_ext_t + delta_X * v_int;}
|
|
// bilan des énergies (on retire l'énergie cinétique initiale si elle exite)
|
|
bilan_E = E_int_tdt - E_ext_tdt;
|
|
// --- cas des puissances ------
|
|
// recup de l'incrément de temps
|
|
double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
|
|
double unSurDeltat=0;
|
|
if (Abs(deltat) >= ConstMath::trespetit)
|
|
{unSurDeltat = 1./deltat;}
|
|
else
|
|
// si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
|
|
{ // non un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
|
|
if (unSurDeltat < 0)
|
|
{ cout << "\n le pas de temps est négatif !! "; };
|
|
unSurDeltat = ConstMath::tresgrand;
|
|
};
|
|
// calcul de la puissance interne
|
|
P_int_tdt = unSurDeltat * delta_X * F_int_tdt;
|
|
// calcul de la puissance externe
|
|
P_ext_tdt = unSurDeltat * delta_X * F_ext_tdt;
|
|
// bilan des puissances
|
|
bilan_P_tdt = P_int_tdt + P_ext_tdt;
|
|
|
|
// cas des forces visqueuses numériques
|
|
double puissance_visco_num = 0.;
|
|
if (pa.Amort_visco_artificielle())
|
|
{E_visco_numerique_tdt = E_visco_numerique_t + delta_X * forces_vis_num;
|
|
puissance_visco_num = unSurDeltat * delta_X * forces_vis_num;
|
|
bilan_P_tdt += puissance_visco_num;
|
|
bilan_E += E_visco_numerique_tdt;
|
|
};
|
|
|
|
// --- affichage ----
|
|
if (( pa.Vrai_commande_sortie(icharge,temps_derniere_sauvegarde))
|
|
&&(pa.AfficheIncrEnergie()))
|
|
{// cas des énergies
|
|
cout << "\n energies: int= " << setprecision(nbcar)<< E_int_tdt
|
|
<< " ext= " << setprecision(nbcar)<< E_ext_tdt
|
|
<< " bilan= " << setprecision(nbcar)<< bilan_E;
|
|
if (pa.Amort_visco_artificielle())
|
|
cout << " energie numerique: "<< setprecision(nbcar)<< E_visco_numerique_tdt;
|
|
if (pa.BulkViscosity())
|
|
cout << " ener_bulk: " << setprecision(nbcar)<< E_bulk
|
|
<< " P_bulk: "<< setprecision(nbcar)<< P_bulk;
|
|
|
|
// cas des puissances
|
|
cout << "\n puissances(V=delta X): int= " << setprecision(nbcar)<< P_int_tdt
|
|
<< " ext= "<< setprecision(nbcar)<< P_ext_tdt
|
|
<< " bilan= " << setprecision(nbcar)<< bilan_P_tdt;
|
|
};
|
|
|
|
// --- on passe les infos au niveau global
|
|
{ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_EXTERNE,E_ext_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_INTERNE,E_int_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_BILAN,bilan_E);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(PUISSANCE_INTERNE,P_int_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(PUISSANCE_EXTERNE,P_ext_tdt);
|
|
ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(ENERGIE_VISCO_NUMERIQUE,E_visco_numerique_t);
|
|
}
|
|
};
|
|
|
|
};
|
|
|
|
// dans le cas où un grand nombre d'information nécessaire pour l'algorithme
|
|
// est stocké de manière externe sur un fichier
|
|
// exemple : calcul d'erreur a partir
|
|
// d'un champ d'information stocké de manière externe sur un fichier
|
|
// l'acquisition du (ou des) lieu(s) (flot) où sont stocké ces infos est effectuée
|
|
// ce lieu fait parti des paramètres de l'algorithme
|
|
void Algori::DefFlotExterne(UtilLecture* entreePrinc)
|
|
{if (ParaGlob::NiveauImpression() >= 4)
|
|
cout << " debut de la lecture eventuelle de fichiers types flotExterne " << endl;
|
|
// il y a lecture si le mot clé : flotExterne est rencontré
|
|
if (strstr(entreePrinc->tablcar,"flotExterne")!=NULL)
|
|
{ // on passe en revue tous les cas possibles
|
|
// la lecture s'effectue jusqu'à un nouveau mot clé
|
|
MotCle motCle; // ref aux mots cle
|
|
// 1. preparation du flot
|
|
entreePrinc->NouvelleDonnee();
|
|
do
|
|
{
|
|
// 2. lecture du type de données à lire
|
|
int type;
|
|
*(entreePrinc->entree) >> type ;
|
|
|
|
// ------- cas d'un calcul d'erreur sans calcul d'équilibre -------
|
|
// fichier des contraintes
|
|
if (type==1)
|
|
// on balaie la liste des sous_types
|
|
{ list <EnumSousTypeCalcul>::const_iterator ili;
|
|
list <EnumSousTypeCalcul>::const_iterator ili_fin = soustypeDeCalcul->end();
|
|
for (ili = soustypeDeCalcul->begin();ili!= ili_fin;ili++)
|
|
if(!(Avec_in(*ili)) && Remonte_in(*ili))
|
|
LectureUnTypeExterne(entreePrinc,type);
|
|
};
|
|
// ------- cas d'un calcul d'erreur sans calcul d'équilibre -------
|
|
// fichier des déplacements
|
|
if (type==2)
|
|
// on balaie la liste des sous_types
|
|
{ list <EnumSousTypeCalcul>::const_iterator ili;
|
|
list <EnumSousTypeCalcul>::const_iterator ili_fin = soustypeDeCalcul->end();
|
|
for (ili = soustypeDeCalcul->begin();ili!= ili_fin;ili++)
|
|
if(!(Avec_in(*ili)) && Remonte_in(*ili))
|
|
LectureUnTypeExterne(entreePrinc,type);
|
|
}
|
|
// ------ autre cas à rajouter par la suite -------
|
|
|
|
// 3. preparation du flot pour la sortie ou la prochaine lecture
|
|
entreePrinc->NouvelleDonnee();
|
|
}
|
|
while ( !motCle.SimotCle(entreePrinc->tablcar)) ;
|
|
}
|
|
if (ParaGlob::NiveauImpression() >= 4)
|
|
cout << " fin de la lecture eventuelle de fichiers types flotExterne " << endl;
|
|
};
|
|
|
|
// lecture d'un type externe
|
|
void Algori::LectureUnTypeExterne(UtilLecture* entreePrinc,const int type)
|
|
{ // on incrémente la taille des tableaux
|
|
int taille = typeFlotExterne.Taille(); taille++;
|
|
typeFlotExterne.Change_taille(taille);
|
|
noms_fichier.Change_taille(taille);
|
|
// sauvegarde du type
|
|
typeFlotExterne(taille) = type;
|
|
// on crée une liste intermédiaire
|
|
ListDeuxString la_list; list<DeuxString > & lalist = la_list.infos;
|
|
// deux strings
|
|
DeuxString nom;
|
|
// lecture tant qu'il n'y a pas d'erreur
|
|
while (!entreePrinc->entree->rdstate())
|
|
{ // lecture du nom du fichier
|
|
*(entreePrinc->entree) >> nom.nomFichier;
|
|
*(entreePrinc->entree) >> nom.nomMaillage;
|
|
// stockage
|
|
lalist.push_back(nom);
|
|
}
|
|
// stokage de la liste
|
|
noms_fichier(taille) = la_list;
|
|
};
|
|
|
|
// ------------METHODES PROTEGEES ----------------:
|
|
|
|
// calcul de la raideur et du second membre pour tous les maillages
|
|
// ainsi que des énergies
|
|
// si pb retour false: indique que le calcul c'est mal passé, il y a une erreur
|
|
// généré, les résultats: raideur et second membres calculées sont inexploitable
|
|
bool Algori::RaidSmEner(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin
|
|
,Mat_abstraite& matglob )
|
|
{
|
|
tempsRaidSmEner.Mise_en_route_du_comptage(); // comptage cpu
|
|
// on doit initialiser les temps globaux de loi de comp et de métrique car
|
|
// on va ajouter ensuite des temps qui eux mêmes globalisent ce qui se passe à chaque pti
|
|
// Temps_CPU_HZpp tps_zero; // un temps d'initialisation
|
|
// temps_lois_comportement = tps_zero;
|
|
Temps_CPU_HZpp temps_debut_lois_comportement; // temps initial
|
|
// temps_metrique_K_SM = tps_zero;
|
|
Temps_CPU_HZpp temps_debut_metrique_K_SM; // temps initial
|
|
if (permet_affichage >3) cout << "\n -- debut calcul second membre et raideur " << flush;
|
|
|
|
energTotal.Inita(0.); // initialisation des énergies à 0
|
|
energHourglass=0.;energStabiliMembBiel=0.;
|
|
volume_total_matiere = 0.; // init
|
|
E_bulk = 0.; // init
|
|
P_bulk=0.; // init
|
|
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
{vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension()));
|
|
|
|
};
|
|
#ifdef UTILISATION_MPI
|
|
mpi::request reqs1;
|
|
mpi::request reqs2;
|
|
mpi::request reqs3;
|
|
bool premier_passage = true;
|
|
#endif
|
|
// on gère les exceptions éventuelles en mettant le bloc sous surveillance
|
|
try
|
|
{// boucle sur les elements
|
|
int nbMailMax = lesMail->NbMaillage();
|
|
#ifndef UTILISATION_MPI
|
|
// cas d'un calcul mono CPU
|
|
for (int nbMail =1; nbMail<= nbMailMax; nbMail++)
|
|
{int nemax = lesMail->Nombre_element(nbMail);
|
|
for (int ne=1; ne<= nemax;ne++)
|
|
{
|
|
#else
|
|
// cas d'un calcul multi-CPU
|
|
// on va parcourir les éléments associés au cpu
|
|
// on récupère la distribution d'éléments concernant le cpu en cours
|
|
const Tableau < list <int > > tab_list_elem_cpu = distribution_CPU_algo.List_element_CPU_en_cours();
|
|
// la taille est identique à nbMailMax, sauf si c'est le cpu 0, là le tableau est vide et il n'y
|
|
// aura pas de boucle, (ou plutôt on sortira directement de la boucle
|
|
// le cas CPU 0 est traité à part
|
|
int nb_mail_distrib = tab_list_elem_cpu.Taille();
|
|
for (int nbMail =1; nbMail<= nb_mail_distrib; nbMail++)
|
|
{const list <int >& list_elem_cpu= tab_list_elem_cpu(nbMail); // pour simplifier
|
|
// on balaie les éléments nécessaires
|
|
list <int >::const_iterator il,ilfin=list_elem_cpu.end();
|
|
for (il = list_elem_cpu.begin();il != ilfin;il++)
|
|
{ int ne = (*il);
|
|
// on récupère un signal du process 0
|
|
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
|
|
if (premier_passage) {premier_passage = false;}
|
|
else // on attend que les transferts soient finis
|
|
{reqs1.wait();
|
|
reqs2.wait();
|
|
reqs3.wait();
|
|
};
|
|
temps_attente.Arret_du_comptage(); // fin comptage cpu
|
|
|
|
#endif
|
|
//calcul de la raideur local et du residu local
|
|
ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element
|
|
Tableau<Noeud *>& taN = el.Tab_noeud(); // tableau de noeuds de l'el
|
|
temps_debut_lois_comportement=el.Temps_lois_comportement(); // init
|
|
temps_debut_metrique_K_SM = el.Temps_metrique_K_SM(); // init
|
|
Element::ResRaid resu = el.Calcul_implicit(pa);
|
|
|
|
|
|
////---- débug
|
|
//{
|
|
//cout << "\n Algori::RaidSmEner debug : ";
|
|
//string entete = " affichage de la matrice de raideur avant assemblage";
|
|
//matglob.Affichage_ecran(entete);
|
|
//entete = " affichage du second membre (puissance interne) avant assemblage ";
|
|
//vglobin.Affichage_ecran(entete);
|
|
//}
|
|
// cout << "\n affichage des matrices locales : element numéro =" << ne << endl;
|
|
// (resu.res)->Affiche();
|
|
// (resu.raid)->Affiche();
|
|
// on test la symétrie des matrices locales
|
|
//if (!(resu.raid->Symetrie()))
|
|
// resu.raid->AfficheNonSymetries();
|
|
//-- fin débug
|
|
#ifndef UTILISATION_MPI
|
|
// --- assemblage et calcul de grandeur globale, pour mono-CPU
|
|
// assemblage
|
|
Ass.AssemSM (vglobin,*(resu.res),el.TableauDdl(),taN); // du second membre
|
|
////---debug---
|
|
//double maxPuissInt = vglobin.Max_val_abs();
|
|
//if (Dabs(maxPuissInt) > ConstMath::petit)
|
|
// {cout << "\n debug Algori::RaidSmEner maxPuissInt= "<<maxPuissInt<<endl
|
|
// << "\n residu interne= "<<*(resu.res) << endl ;
|
|
// };
|
|
////---fin debug ---
|
|
if (pa.Symetrie_matrice())
|
|
Ass.AssembMatSym (matglob,*(resu.raid),el.TableauDdl(),taN); // de la raideur
|
|
else
|
|
Ass.AssembMatnonSym (matglob,*(resu.raid),el.TableauDdl(),taN); // de la raideur
|
|
// globalisation des énergies
|
|
energTotal += el.EnergieTotaleElement();
|
|
energHourglass += el.Energie_Hourglass();
|
|
energStabiliMembBiel += el.Energie_stab_membBiel();
|
|
E_bulk += el.Energie_Bulk();
|
|
P_bulk += el.Puissance_Bulk();
|
|
// globalisation des volumes
|
|
volume_total_matiere += el.Volume();
|
|
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
{ const Coordonnee& volPlan = el.VolumePlan();
|
|
if (volPlan.Dimension())
|
|
vol_total2D_avec_plan_ref(nbMail) += volPlan;
|
|
//--- debug
|
|
// cout << "\n calcul des volumes balayés";
|
|
// vol_total2D_avec_plan_ref.Affiche();
|
|
// cout << "\n " << *(listeVarGlob["vol_total2D_avec_plan_yz"]) << " " << *(listeVarGlob["vol_total2D_avec_plan_xz"])
|
|
// << " " << *(listeVarGlob["vol_total2D_avec_plan_xy"]) << endl;
|
|
// fin débug
|
|
};
|
|
#else
|
|
// cas d'un calcul parallèle, et CPU != 0
|
|
int num_process = ParaGlob::Monde()->rank();
|
|
if (num_process != 0)
|
|
{tempsRaidSmEner.Arret_du_comptage();
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
DeuxEntiers num_el_et_mail(el.Num_elt(),el.Num_maillage());
|
|
// on transmet les numéros d'élément et de maillage
|
|
reqs1 = ParaGlob::Monde()->isend(0, 24, num_el_et_mail);
|
|
// puis on transmets le vecteur résidu
|
|
reqs2 = resu.res->Ienvoi_MPI(0,25);
|
|
//puis la matrice
|
|
reqs3 = resu.raid->Ienvoi_MPI(0, 26);
|
|
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
|
|
tempsRaidSmEner.Mise_en_route_du_comptage();
|
|
};
|
|
|
|
#endif
|
|
// globalisation des temps cpu loi de comp et métrique
|
|
temps_lois_comportement += el.Temps_lois_comportement();
|
|
temps_lois_comportement -= temps_debut_lois_comportement;
|
|
temps_metrique_K_SM += el.Temps_metrique_K_SM();
|
|
temps_metrique_K_SM -= temps_debut_metrique_K_SM;
|
|
|
|
////--- debug
|
|
//{
|
|
//cout << "\n Algori::RaidSmEner debug : ";
|
|
//string entete = " affichage de la matrice de raideur (puissance interne) après assemblage";
|
|
//matglob.Affichage_ecran(entete);
|
|
//entete = " affichage du second membre (puissance interne) après assemblage ";
|
|
//vglobin.Affichage_ecran(entete);
|
|
//}
|
|
//// fin debug
|
|
|
|
};
|
|
};
|
|
}
|
|
catch (ErrJacobienNegatif_ElemMeca excep)
|
|
// cas d'un jacobien négatif "a prendre en compte"
|
|
{ phase_de_convergence = -5; a_converge = false; return false; }
|
|
catch (ErrVarJacobienMini_ElemMeca excep)
|
|
// cas d'une variation de jacobien trop importante
|
|
{ phase_de_convergence = -6; a_converge = false; return false; }
|
|
catch (ErrNonConvergence_loiDeComportement excep)
|
|
// cas d'une erreur survenue à cause d'une non convergence pour la résolution
|
|
// d'une loi de comportement incrémentale
|
|
{ switch (excep.cas)
|
|
{case 1: phase_de_convergence = -8; break;
|
|
case 0: default : phase_de_convergence = -7; break;
|
|
};
|
|
a_converge = false; return false;
|
|
}
|
|
catch (ErrCalculFct_nD)
|
|
// cas d'une d'une erreur survenue à cause d'une erreur sur le calcul d'une fct nD
|
|
// au niveau du chargement
|
|
{ phase_de_convergence = -10; a_converge = false;
|
|
cout << "\n *** erreur exception genere par une fonction nD utilisee en chargement ";
|
|
return false;
|
|
}
|
|
catch (ErrSortie)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortie toto;
|
|
throw (toto);
|
|
}
|
|
catch (ErrSortieFinale)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortieFinale toto;
|
|
tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu
|
|
throw (toto);
|
|
}
|
|
catch ( ... )
|
|
{ if (ParaGlob::NiveauImpression() >= 1)
|
|
{cout << "\n warning: exception generee par un element mais dont la prise en compte "
|
|
<< " n'est pas prevu !, on ne fait rien et on continue le calcul";
|
|
if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::RaidSmEner(..";
|
|
};
|
|
}
|
|
// affichage éventuelle de la matrice de raideur et du second membre
|
|
if (ParaGlob::NiveauImpression() >= 10)
|
|
{ string entete = " affichage de la matrice de raideur (puissance interne) avant conditions limites";
|
|
matglob.Affichage_ecran(entete);
|
|
entete = " affichage du second membre (puissance interne) avant condition limites ";
|
|
vglobin.Affichage_ecran(entete);
|
|
};
|
|
// -- on transfert en global les énergies internes
|
|
Transfert_ParaGlob_energies_internesLoisComp();
|
|
Transfert_ParaGlob_energies_hourglass_bulk_stab();
|
|
// idem pour les volumes entre plans
|
|
Transfert_ParaGlob_volume_entre_plans();
|
|
// -- calcul des intégrales éventuelles avec transfert en global
|
|
lesMail->Integration();
|
|
// --- debug ------- essai ----
|
|
// cout << "\n *** ener_bulk " << E_bulk;
|
|
// --- fin debug ------- essai ----
|
|
// if ((permet_affichage > 6) || (ParaGlob::NiveauImpression() < 10))
|
|
// {string entete = " affichage du second membre (puissance interne) avant condition limites ";
|
|
// vglobin.Affiche();
|
|
// };
|
|
if (permet_affichage >3) cout << "\n -- fin calcul second membre et raideur " << flush;
|
|
|
|
tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu
|
|
// --- debug ------- essai ----
|
|
// cout << "\temps cpu raid SM energ " << tempsRaidSmEner;
|
|
// --- fin debug ------- essai ----
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
{ tempsRaidSmEner.Mise_en_route_du_comptage(); // comptage cpu
|
|
// récup du nombre total d'éléments, cumul sur tous les maillages
|
|
int total_elem = distribution_CPU_algo.NB_total_element();
|
|
// on va boucler sur les éléments récupérés des différents process
|
|
// jusqu'au nombre maxi d'élément
|
|
int nb_elem_deja_calcule = 0; // init
|
|
while (nb_elem_deja_calcule < total_elem)
|
|
{ // on récupère un résultat de calcul
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
DeuxEntiers num_el_et_mail;
|
|
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 24, num_el_et_mail);
|
|
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
|
|
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
|
|
mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
|
|
temps_attente.Arret_du_comptage(); // fin comptage cpu
|
|
int ne = num_el_et_mail.un; // numero d'identification de l'element
|
|
int nbMail = num_el_et_mail.deux; // numéro de maillage
|
|
// d'où l'élément
|
|
ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne));
|
|
// récupération des conteneurs ad hoc vecteur et raideur
|
|
int source = stat.source(); // récupération du numéro de la source
|
|
Vecteur * residu = el.Conteneur_Residu();
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
mpi::request reqs2 = residu->Irecup_MPI(source, 25);
|
|
Mat_pleine* raideur = el.Conteneur_raideur();
|
|
mpi::request reqs3 = raideur->Irecup_MPI(source, 26);
|
|
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
|
|
|
|
temps_attente.Mise_en_route_du_comptage(); // comptage cpu
|
|
reqs2.wait(); // on attend que le conteneur soit rempli
|
|
reqs3.wait(); // on attend que le conteneur soit rempli
|
|
temps_attente.Arret_du_comptage(); // fin comptage cpu
|
|
|
|
Tableau<Noeud *>& taN = el.Tab_noeud(); // tableau de noeuds de l'el
|
|
// --- assemblage
|
|
Ass.AssemSM (vglobin,*residu,el.TableauDdl(),taN); // du second membre
|
|
if (pa.Symetrie_matrice())
|
|
Ass.AssembMatSym (matglob,*raideur,el.TableauDdl(),taN); // de la raideur
|
|
else
|
|
Ass.AssembMatnonSym (matglob,*raideur,el.TableauDdl(),taN); // de la raideur
|
|
// on incrémente le nombre d'élément traité
|
|
nb_elem_deja_calcule++;
|
|
};
|
|
tempsRaidSmEner.Arret_du_comptage(); // fin comptage cpu
|
|
}
|
|
// else
|
|
// {// on récupère le dernier signal du process 0
|
|
//// std::string msg;
|
|
//// ParaGlob::Monde()->recv(0, 12, msg);
|
|
// // synchronisation ici de tous les process
|
|
// ParaGlob::Monde()->barrier();
|
|
// };
|
|
// synchronisation ici de tous les process
|
|
// ParaGlob::Monde()->barrier();
|
|
|
|
#endif
|
|
// retour indiquant que tout c'est bien passé
|
|
return true ;
|
|
};
|
|
|
|
// calcul du second membre pour tous les maillages ainsi que des énergies totales
|
|
bool Algori::SecondMembreEnerg(LesMaillages * lesMail,Assemblage& Ass,Vecteur & vglobin)
|
|
{tempsSecondMembreEnerg.Mise_en_route_du_comptage(); // comptage cpu
|
|
// on doit initialiser les temps globaux de loi de comp et de métrique car
|
|
// on va ajouter ensuite des temps qui eux mêmes globalisent ce qui se passe à chaque pti
|
|
// Temps_CPU_HZpp tps_zero; // un temps d'initialisation
|
|
// temps_lois_comportement = tps_zero;
|
|
Temps_CPU_HZpp temps_debut_lois_comportement; // temps initial
|
|
// temps_metrique_K_SM = tps_zero;
|
|
Temps_CPU_HZpp temps_debut_metrique_K_SM; // temps initial
|
|
if (permet_affichage >3) cout << "\n -- debut calcul second membre " << flush;
|
|
|
|
energTotal.Inita(0.); // initialisation des énergies à 0
|
|
energHourglass=0.;energStabiliMembBiel=0.;
|
|
E_bulk = 0.; // init
|
|
P_bulk=0.; // init
|
|
volume_total_matiere = 0.; // init
|
|
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
vol_total2D_avec_plan_ref.Inita(Coordonnee(ParaGlob::Dimension()));
|
|
// on gère les exceptions éventuelles en mettant le bloc sous surveillance
|
|
try
|
|
{for (int nbMail =1; nbMail<= lesMail->NbMaillage(); nbMail++)
|
|
for (int ne=1; ne<= lesMail->Nombre_element(nbMail);ne++)
|
|
{ //calcul du residu local
|
|
ElemMeca & el = *((ElemMeca*) &lesMail->Element_LesMaille(nbMail,ne)); // l'element
|
|
Tableau<Noeud *>& taN = el.Tab_noeud(); // tableau de noeuds de l'el
|
|
Temps_CPU_HZpp temps_debut_lois_comportement=el.Temps_lois_comportement(); // init
|
|
Temps_CPU_HZpp temps_debut_metrique_K_SM = el.Temps_metrique_K_SM(); // init
|
|
Vecteur* res = el.CalculResidu_tdt(pa);
|
|
////--- debug
|
|
//if (res->Max_val_abs() > 10)
|
|
// { cout << "\n debug .... Algori::SecondMembreEnerg( "
|
|
// << "\n **** res->Max_val_abs() > 10 ";
|
|
// // on recalcule pour le debug le vecteur résidu
|
|
// res = el.CalculResidu_tdt(pa);
|
|
// };
|
|
//
|
|
////--- fin debug
|
|
|
|
// assemblage
|
|
Ass.AssemSM (vglobin,*res,el.TableauDdl(),taN); // du second membre
|
|
// globalisation des énergies
|
|
energTotal += el.EnergieTotaleElement();
|
|
energHourglass += el.Energie_Hourglass();
|
|
energStabiliMembBiel += el.Energie_stab_membBiel();
|
|
E_bulk += el.Energie_Bulk();
|
|
P_bulk += el.Puissance_Bulk();
|
|
// globalisation des volumes
|
|
volume_total_matiere += el.Volume();
|
|
// globalisation des temps cpu loi de comp et métrique
|
|
temps_lois_comportement += el.Temps_lois_comportement();
|
|
temps_lois_comportement -= temps_debut_lois_comportement;
|
|
temps_metrique_K_SM += el.Temps_metrique_K_SM();
|
|
temps_metrique_K_SM -= temps_debut_metrique_K_SM;
|
|
if (pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
{ const Coordonnee& volPlan = el.VolumePlan();
|
|
if (volPlan.Dimension())
|
|
vol_total2D_avec_plan_ref(nbMail) += volPlan;
|
|
};
|
|
};
|
|
}
|
|
catch (ErrJacobienNegatif_ElemMeca excep)
|
|
// cas d'un jacobien négatif "a prendre en compte"
|
|
{ phase_de_convergence = -5; a_converge = false; return false; }
|
|
catch (ErrVarJacobienMini_ElemMeca excep)
|
|
// cas d'une variation de jacobien trop importante
|
|
{ phase_de_convergence = -6; a_converge = false; return false; }
|
|
catch (ErrNonConvergence_loiDeComportement excep)
|
|
// cas d'une d'une erreur survenue à cause d'une non convergence pour la résolution
|
|
// d'une loi de comportement incrémentale
|
|
{ phase_de_convergence = -7; a_converge = false;
|
|
cout << "\n non convergence sur une loi de comportement ";
|
|
return false;
|
|
}
|
|
catch (ErrCalculFct_nD)
|
|
// cas d'une d'une erreur survenue à cause d'une erreur sur le calcul d'une fct nD
|
|
// au niveau du chargement
|
|
{ phase_de_convergence = -10; a_converge = false;
|
|
cout << "\n *** erreur exception genere par une fonction nD utilisee en chargement ";
|
|
return false;
|
|
}
|
|
catch (ErrSortie)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortie toto;
|
|
throw (toto);
|
|
}
|
|
catch (ErrSortieFinale)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortieFinale toto;
|
|
tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu
|
|
throw (toto);
|
|
}
|
|
catch ( ... )
|
|
{ if (ParaGlob::NiveauImpression() >= 1)
|
|
{cout << "\n warning: exception generee par un element mais dont la prise en compte "
|
|
<< " n'est pas prevu !, on ne fait rien et on continue le calcul";
|
|
if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::SecondMembreEnerg(..";
|
|
};
|
|
}
|
|
// affichage éventuelle du second membre
|
|
if (ParaGlob::NiveauImpression() >= 10)
|
|
{ string entete = " affichage du second membre (puissance interne) avant conditions limites ";
|
|
vglobin.Affichage_ecran(entete);
|
|
};
|
|
if (permet_affichage >3) cout << "\n -- fin calcul second membre " << flush;
|
|
// -- on transfert en global les énergies internes
|
|
Transfert_ParaGlob_energies_internesLoisComp();
|
|
Transfert_ParaGlob_energies_hourglass_bulk_stab();
|
|
// idem pour les volumes entre plans
|
|
//---- debug
|
|
// if (pa.CalVolTotalEntreSurfaceEtPlansRef())
|
|
// { //Tableau <Coordonnee> vol_total2D_avec_plan_ref; // volume total entre la surface et : yz, xz,xy
|
|
// cout << "\n debug Algo::SecondMembreEnerg ";
|
|
// cout << "\n vol_total2D_avec_plan_ref "
|
|
// << vol_total2D_avec_plan_ref(1) << flush;
|
|
// };
|
|
//---- fin debug
|
|
Transfert_ParaGlob_volume_entre_plans();
|
|
|
|
// -- calcul des intégrales éventuelles avec transfert en global
|
|
lesMail->Integration();
|
|
|
|
tempsSecondMembreEnerg.Arret_du_comptage(); // fin comptage cpu
|
|
|
|
// retour indiquant que tout c'est bien passé
|
|
return true ;
|
|
};
|
|
|
|
// Mise à jour de la raideur et du second membre pour le contact
|
|
// calcul des énergies spécifiques au contact
|
|
// si pb retour false: indique que le calcul c'est mal passé, il y a une erreur
|
|
// généré, les résultats: raideur et second membres calculées sont inexploitables
|
|
bool Algori::RaidSmEnerContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & vglobin
|
|
,Mat_abstraite& matglob )
|
|
{
|
|
tempsRaidSmEnerContact.Mise_en_route_du_comptage(); // temps cpu
|
|
energFrottement.Inita(0.); // initialisation des énergies de frottement à 0
|
|
energPenalisation = 0.;
|
|
if (permet_affichage >3) cout << "\n -- debut calcul second membre et raideur pour le contact " << flush;
|
|
|
|
// on récupère la liste des éléments de contact
|
|
LaLIST <ElContact>& listElContact = lesCont->LesElementsDeContact();
|
|
LaLIST <ElContact>::iterator il,ilfin=listElContact.end();
|
|
// on gère les exceptions éventuelles en mettant le bloc sous surveillance
|
|
try
|
|
{// boucle sur les elements de contact
|
|
for (il=listElContact.begin();il != ilfin; il++)
|
|
{
|
|
////------ debug
|
|
// cout << "\n debug Algori::RaidSmEnerContact ";
|
|
//// ------ fin debug
|
|
if ((*il).Actif()) // on n'intervient que si le contact est actif
|
|
{ //calcul de la raideur locale et du residu local
|
|
//------ debug
|
|
// (*il).Affiche();
|
|
// ------ fin debug
|
|
ElContact& elcontact = (*il); // pour simplifier
|
|
Tableau<Noeud *>& taN = elcontact.TabNoeud_pour_assemblage(); // tableau de noeuds
|
|
// calcul effectif de la raideur et résidu locals
|
|
Element::ResRaid resu = elcontact.SM_K_charge_contact();
|
|
// cout << "numéro =" << ne << endl;
|
|
//------ debug
|
|
// (resu.res)->Affiche();
|
|
// (resu.raid)->Affiche(); //1,8,1,1,8,1);
|
|
// (resu.raid)->Affiche1(1,6,1,1,6,1);
|
|
// (int min_i,int max_i,int pas_i,int min_j,int max_j,int pas_j,int nd)
|
|
// ------ fin debug
|
|
// assemblage
|
|
// dans le cas où le retour est un pointeur nul, cela signifie qu'il n'y a pas de second membre et raideur calculés
|
|
if (resu.res != NULL)
|
|
{ Ass.AssemSM (vglobin,*(resu.res),elcontact.TableauDdlCont(),taN); // du second membre
|
|
if (pa.Symetrie_matrice())
|
|
Ass.AssembMatSym (matglob,*(resu.raid),elcontact.TableauDdlCont(),taN); // de la raideur
|
|
else
|
|
Ass.AssembMatnonSym (matglob,*(resu.raid),elcontact.TableauDdlCont(),taN); // de la raideur
|
|
};
|
|
// globalisation des énergies dues aux frottements
|
|
energFrottement += elcontact.EnergieFrottement();
|
|
energPenalisation += elcontact.EnergiePenalisation();
|
|
}; //-- fin du test sur l'activité
|
|
}; //-- fin de la boucle sur les éléments de contact
|
|
} //-- fin du try
|
|
catch (ErrSortie)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortie toto;
|
|
throw (toto);
|
|
}
|
|
catch (ErrSortieFinale)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortieFinale toto;
|
|
tempsRaidSmEnerContact.Arret_du_comptage(); // temps cpu
|
|
throw (toto);
|
|
}
|
|
catch ( ... )
|
|
{ if (ParaGlob::NiveauImpression() >= 1)
|
|
{cout << "\n warning: exception generee par un element de contact mais dont la prise en compte "
|
|
<< " n'est pas prevu !, on ne fait rien et on continue le calcul";
|
|
if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::RaidSmEnerContact(..";
|
|
};
|
|
}
|
|
// affichage éventuelle de la matrice de raideur et du second membre
|
|
//------ debug
|
|
// cout << "\n debug Algori::RaidSmEnerContact ";
|
|
// string entete = " affichage du second membre uniquement du au contact ";
|
|
// vglobin.Affichage_ecran(entete);
|
|
// ------ fin debug
|
|
if (ParaGlob::NiveauImpression() >= 10)
|
|
{ string entete = " affichage de la matrice de raideur (puissance interne) apres le contact ";
|
|
matglob.Affichage_ecran(entete);
|
|
entete = " affichage du second membre uniquement du au contact ";
|
|
vglobin.Affichage_ecran(entete);
|
|
}
|
|
// -- on transfert en global les énergies
|
|
Transfert_ParaGlob_energies_contact();
|
|
if (permet_affichage >3) cout << "\n -- fin calcul second membre et raideur pour le contact " << flush;
|
|
|
|
tempsRaidSmEnerContact.Arret_du_comptage(); // temps cpu
|
|
// retour indiquant que tout c'est bien passé
|
|
return true ;
|
|
};
|
|
|
|
// cas du contact: calcul et mise à jour du second membre ainsi que des énergies spécifiques
|
|
bool Algori::SecondMembreEnergContact(LesContacts * lesCont,Assemblage& Ass,Vecteur & vglobin
|
|
,bool aff_iteration)
|
|
{ tempsSecondMembreEnergContact.Mise_en_route_du_comptage(); // temps cpu
|
|
energFrottement.Inita(0.); // initialisation des énergies de frottement à 0
|
|
energPenalisation = 0.;
|
|
volume_total_matiere = 0.; // init
|
|
if (permet_affichage >3) cout << "\n -- debut calcul second membre pour le contact " << flush;
|
|
|
|
// on récupère la liste des éléments de contact
|
|
LaLIST <ElContact>& listElContact = lesCont->LesElementsDeContact();
|
|
LaLIST <ElContact>::iterator il,ilfin=listElContact.end();
|
|
// on gère les exceptions éventuelles en mettant le bloc sous surveillance
|
|
try
|
|
{// boucle sur les elements de contact
|
|
for (il=listElContact.begin();il != ilfin; il++)
|
|
{ if ((*il).Actif()) // on n'intervient que si le contact est actif
|
|
{ //calcul du residu local
|
|
ElContact& elcontact = (*il); // pour simplifier
|
|
Tableau<Noeud *>& taN = elcontact.TabNoeud_pour_assemblage(); // tableau de noeuds
|
|
//calcul du residu local
|
|
Vecteur* res = elcontact.SM_charge_contact();
|
|
// assemblage
|
|
Ass.AssemSM (vglobin,*res,elcontact.TableauDdlCont(),taN); // du second membre
|
|
// globalisation des énergies dues aux frottements
|
|
energFrottement += elcontact.EnergieFrottement();
|
|
energPenalisation += elcontact.EnergiePenalisation();
|
|
}; //-- fin du test sur l'activité
|
|
}; //-- fin de la boucle sur les éléments de contact
|
|
} //-- fin du try
|
|
catch (ErrSortie)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortie toto;
|
|
throw (toto);
|
|
}
|
|
catch (ErrSortieFinale)
|
|
// cas d'une direction voulue vers la sortie
|
|
// on relance l'interuption pour le niveau supérieur
|
|
{ ErrSortieFinale toto;
|
|
tempsSecondMembreEnergContact.Arret_du_comptage(); // temps cpu
|
|
throw (toto);
|
|
}
|
|
catch ( ... )
|
|
{ if (ParaGlob::NiveauImpression() >= 1)
|
|
{cout << "\n warning: exception generee par un element de contact mais dont la prise en compte "
|
|
<< " n'est pas prevu !, on ne fait rien et on continue le calcul";
|
|
if (ParaGlob::NiveauImpression() >= 4) cout << "\n Algori::SecondMembreEnergContact(..";
|
|
};
|
|
}
|
|
// affichage éventuelle du second membre
|
|
if (ParaGlob::NiveauImpression() >= 10)
|
|
{ string entete = " affichage du second membre uniquement du au contact ";
|
|
vglobin.Affichage_ecran(entete);
|
|
};
|
|
//cout << vglobin << endl;
|
|
// affichage éventuelle de la force maxi de contact
|
|
lesCont->Forces_contact_maxi(aff_iteration);
|
|
// idem pour les gap N et tangentiel
|
|
lesCont->Gap_contact_maxi(aff_iteration);
|
|
if (permet_affichage >3) cout << "\n -- fin calcul second mmembre pour le contact " << flush;
|
|
|
|
|
|
tempsSecondMembreEnergContact.Arret_du_comptage(); // temps cpu
|
|
// retour indiquant que tout c'est bien passé
|
|
return true ;
|
|
};
|
|
|
|
// choix de la matrice de raideur du système linéaire:
|
|
// 1) Si le pointeur est non null, on vérifie les tailles, si c'est différent
|
|
// la matrice est reconstruite
|
|
// 2) Si le pointeur est null, il y a création d'une matrice
|
|
// lesCondLim est utilisé pour modifier la largeur de bande par exemple
|
|
// en fonction des conditions limites linéaire
|
|
// lescontacts: si différent de NULL indique qu'il y a du contact
|
|
// NB: la dimension du tableau dépend du paramétrage lu dans ParaAlgoGlobal
|
|
Tableau <Mat_abstraite* > Algori::Choix_matriciel
|
|
(int nbddl,Tableau <Mat_abstraite* >& tab_matglob,LesMaillages * lesMail
|
|
,LesReferences* lesRef,const Nb_assemb& nb_casAssemb,LesCondLim* lesCondLim
|
|
, LesContacts* lescontacts )
|
|
{ // tout d'abord le choix de la matrice de stockage
|
|
|
|
Tableau<Enum_matrice> tab_enu_matrice_sec; // init
|
|
tab_enu_matrice_sec.Init_from_list(pa.Type_matrice_secondaire());
|
|
Tableau<Enum_type_resolution_matri> tab_enu_type_resolution_matri;
|
|
tab_enu_type_resolution_matri.Init_from_list(pa.Type_resolution_secondaire());
|
|
Tableau<Enum_preconditionnement> tab_enu_preconditionnement;
|
|
tab_enu_preconditionnement.Init_from_list(pa.Type_preconditionnement_secondaire());
|
|
Tableau<int> tab_nb_iter_nondirecte_secondaire;
|
|
tab_nb_iter_nondirecte_secondaire.Init_from_list(pa.Nb_iter_nondirecte_secondaire());
|
|
Tableau<double> tab_tolerance_secondaire;
|
|
tab_tolerance_secondaire.Init_from_list(pa.Tolerance_secondaire());
|
|
|
|
int nb_mat = 1+tab_enu_matrice_sec.Taille(); // nombre de matrices
|
|
|
|
// dans le cas où le tableau serait non nulle on regarde s'il a la bonne dimension
|
|
if (tab_matglob.Taille() > nb_mat)
|
|
// là il faut supprimer les matrices pointées en trop
|
|
{int taille = tab_matglob.Taille();
|
|
for (int i=nb_mat+1;i<=taille;i++)
|
|
if (tab_matglob(i)!= NULL)
|
|
delete tab_matglob(i);
|
|
// maintenant on peut changer la taille, en moins donc normalement
|
|
// on ne modifie pas les pointeurs déjà existants
|
|
tab_matglob.Change_taille(nb_mat);
|
|
}
|
|
else if (tab_matglob.Taille() < nb_mat)
|
|
// s'il est trop petit il faut augmenter la taille: on met les nouveaux pointeurs à NULL
|
|
tab_matglob.Change_taille(nb_mat,NULL);
|
|
// sinon il a la bonne taille et le traitement sera fait en fonction
|
|
// de l'existence ou non d'une matrice associée au pointeur
|
|
|
|
// on va boucler sur le nombre de matrice
|
|
for (int inum_mat = 1; inum_mat <= nb_mat; inum_mat++)
|
|
{ // init des valeurs par défaut de la première matrice
|
|
Enum_matrice enumatrice = pa.Type_Matrice(); // init
|
|
Enum_type_resolution_matri enumResolutionMatri = pa.Type_resolution();
|
|
Enum_preconditionnement enumPreconditionnement = pa.Type_preconditionnement();
|
|
// modif au cas où il y a des matrices secondaire
|
|
if (inum_mat > 1)
|
|
{enumatrice = tab_enu_matrice_sec(inum_mat-1);
|
|
if (tab_enu_type_resolution_matri.Taille() >= (inum_mat-1))
|
|
enumResolutionMatri = tab_enu_type_resolution_matri(inum_mat-1);
|
|
if (tab_enu_preconditionnement.Taille() >= (inum_mat-1))
|
|
enumPreconditionnement = tab_enu_preconditionnement(inum_mat-1);
|
|
};
|
|
int nbddl_MPI = nbddl; // init
|
|
bool cal_parallele_et_rang_non_nul = false;
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la matrice du CPU 0 est initialisée
|
|
// à la taille nécessaire pour une résolution globale
|
|
// pour les autres CPU on définit une matrice de taille unitaire
|
|
// qui ne sera pas utilisée mais qui sera valide
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
{nbddl_MPI = 1;
|
|
cal_parallele_et_rang_non_nul = true;
|
|
};
|
|
#endif
|
|
|
|
switch (enumatrice)
|
|
{ case CARREE : case RECTANGLE : // ici comme les tailles sont identiques rectangle
|
|
// et CARRE -> même traitement
|
|
{// cas s'une matrice carrée
|
|
if (tab_matglob(inum_mat) == NULL)
|
|
{tab_matglob(inum_mat) = new Mat_pleine (nbddl_MPI,nbddl_MPI);}
|
|
// sinon on regarde si la taille est bonne
|
|
else if ((tab_matglob(inum_mat)->Nb_ligne()!= nbddl_MPI) || (tab_matglob(inum_mat)->Nb_colonne()!= nbddl_MPI))
|
|
// dans ce cas on change de matrice
|
|
{ delete tab_matglob(inum_mat);
|
|
tab_matglob(inum_mat) = new Mat_pleine (nbddl_MPI,nbddl_MPI);
|
|
};
|
|
tab_matglob(inum_mat)->Change_Choix_resolution
|
|
(enumResolutionMatri,enumPreconditionnement);
|
|
// sinon il n'y a rien n'a faire au niveau des tailles
|
|
break;
|
|
}
|
|
case CARREE_LAPACK :
|
|
{// cas s'une matrice carrée a priori quelconque
|
|
if (tab_matglob(inum_mat) == NULL)
|
|
{tab_matglob(inum_mat) = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.
|
|
,enumResolutionMatri,enumPreconditionnement);
|
|
}
|
|
// sinon on regarde si la taille est bonne
|
|
else if ((tab_matglob(inum_mat)->Nb_ligne()!= nbddl_MPI) || (tab_matglob(inum_mat)->Nb_colonne()!= nbddl_MPI))
|
|
// dans ce cas on change de matrice
|
|
{ delete tab_matglob(inum_mat);
|
|
tab_matglob(inum_mat) = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.
|
|
,enumResolutionMatri,enumPreconditionnement);
|
|
};
|
|
// sinon il n'y a rien n'a faire au niveau des tailles
|
|
break;
|
|
}
|
|
case CARREE_SYMETRIQUE_LAPACK :
|
|
{// cas s'une matrice carrée symétrique
|
|
bool symetrique = true;
|
|
if (tab_matglob(inum_mat) == NULL)
|
|
{tab_matglob(inum_mat) = new MatLapack (nbddl_MPI,nbddl_MPI,symetrique,0.
|
|
,enumResolutionMatri,enumPreconditionnement);
|
|
}
|
|
// sinon on regarde si la taille est bonne
|
|
else if ((tab_matglob(inum_mat)->Nb_ligne()!= nbddl_MPI) || (tab_matglob(inum_mat)->Nb_colonne()!= nbddl_MPI))
|
|
// dans ce cas on change de matrice
|
|
{ delete tab_matglob(inum_mat);
|
|
tab_matglob(inum_mat) = new MatLapack (nbddl_MPI,nbddl_MPI,symetrique,0.
|
|
,enumResolutionMatri,enumPreconditionnement);
|
|
};
|
|
// sinon il n'y a rien n'a faire au niveau des tailles
|
|
break;
|
|
}
|
|
case RECTANGLE_LAPACK :
|
|
{// cas s'une matrice rectangulaire
|
|
if (tab_matglob(inum_mat) == NULL)
|
|
{tab_matglob(inum_mat) = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.
|
|
,enumResolutionMatri,enumPreconditionnement);
|
|
}
|
|
// sinon on regarde si la taille est bonne
|
|
else if ((tab_matglob(inum_mat)->Nb_ligne()!= nbddl_MPI) || (tab_matglob(inum_mat)->Nb_colonne()!= nbddl_MPI))
|
|
// dans ce cas on change de matrice
|
|
{ delete tab_matglob(inum_mat);
|
|
tab_matglob(inum_mat) = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.
|
|
,enumResolutionMatri,enumPreconditionnement);
|
|
};
|
|
// sinon il n'y a rien n'a faire au niveau des tailles
|
|
break;
|
|
}
|
|
case BANDE_SYMETRIQUE :
|
|
{ // calcul de la largeur de bande effective
|
|
int demi=0,total=0;
|
|
lesMail->Largeur_Bande(demi,total,nb_casAssemb);
|
|
total = std::min(total,nbddl_MPI);
|
|
demi = std::min(demi,nbddl_MPI);
|
|
// --- on stocke les largeurs initiales de ddl
|
|
{ // on redimensionne si nécessaire
|
|
int nombre_cas_assemb = tab_para_stockage.Taille();
|
|
if (nb_casAssemb.n > nombre_cas_assemb)
|
|
tab_para_stockage.Change_taille(nb_casAssemb.n);
|
|
// maintenant on stocke
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = demi;
|
|
parstock.total = total;
|
|
};
|
|
|
|
// dans le cas non // ou // pour le CPU 0, on précise la dim
|
|
// ici on garde nbddl au lien de nbddl_MPI: ils sont identiques
|
|
if (!cal_parallele_et_rang_non_nul)
|
|
{ if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n raideur: largeur de bande initiale pour les elements (en ddl) " << total << " ";
|
|
if (lescontacts!= NULL)
|
|
{// calcul de la largeur de bande effective en tenant compte du contact
|
|
int demic=0,totalc=0,cumule=0;
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule))
|
|
{totalc = std::min(totalc,nbddl);
|
|
demic = std::min(demic,nbddl);
|
|
cumule = std::min(cumule,nbddl);
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation de la largeur de bande pour les conditions de contact (en ddl) " << cumule << " ";
|
|
demi += cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total += 2 * cumule;
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,nbddl);
|
|
demi = std::min(demi,nbddl);
|
|
}
|
|
};
|
|
// cas de l'influence des conditions linéaires d'entrée
|
|
int demic=0,totalc=0,cumule=0;
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
if (lesCondLim->Largeur_Bande(demic,totalc,nb_casAssemb,lesMail,lesRef,cumule))
|
|
{totalc = std::min(totalc,nbddl);
|
|
demic = std::min(demic,nbddl);
|
|
cumule = std::min(cumule,nbddl);
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation de la largeur de bande pour les conditions lineaires (en ddl) " << cumule << " ";
|
|
// ---- les deux lignes qui suivent sont fausses, car dans le cas du produit de deux matrices bandes la largeur de bande du produit
|
|
// = non pas le max, mais la "somme" des deux largeurs de bandes (parties hors diagonales),
|
|
// d'une manière plus précise cf. J Chevalier 1993, soit une matrice bande avec deux bandes de part et autre de la diagonale, différentes
|
|
// A_ij (a,b) telle que A_ij = 0 si j<i-a ou j>i+b, donc a est la bande inf (hors diag) et b est la bande sup (hors diag)
|
|
// soient A(a,b) et B(c,d) alors A*B est de type (a+B,b+d)
|
|
// or pour mettre en place les CL (actuellement)
|
|
// on utilise une matrice de rotation et on fait S^T * K * S , tel S est de type (a,b) et donc S^T est de type (b,a) donc
|
|
// si on suppose que K est de type (l,l) et bien S^T * K * S sera de type (l+a+b,l+a+b) donc c'est a+b qui compte (hors diag)
|
|
|
|
// demi = MaX(demi,demic);
|
|
// total = MaX(total,totalc);
|
|
demi += cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total += 2 * cumule;
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,nbddl);
|
|
demi = std::min(demi,nbddl);
|
|
};
|
|
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n largeur de bande finale (en ddl) " << total << " "
|
|
<< "\n stockage symetrique d'ou utilisation de la demi largeur= " << demi << " ";
|
|
};
|
|
|
|
// création éventuelle et initialisation a zero
|
|
if (tab_matglob(inum_mat) == NULL)
|
|
{tab_matglob(inum_mat) = new MatBand (BANDE_SYMETRIQUE,demi,nbddl_MPI,0);
|
|
}
|
|
// sinon on regarde si la taille est bonne
|
|
else if ((tab_matglob(inum_mat)->Nb_ligne()!= nbddl_MPI) || (tab_matglob(inum_mat)->Nb_colonne()!= nbddl_MPI))
|
|
// dans ce cas on change de matrice
|
|
{ delete tab_matglob(inum_mat);
|
|
tab_matglob(inum_mat) = new MatBand (BANDE_SYMETRIQUE,demi,nbddl_MPI,0);
|
|
}
|
|
else // sinon on se contente d'initialiser à 0.
|
|
tab_matglob(inum_mat)->Initialise(0.);
|
|
// on spécifie le type de résolution
|
|
tab_matglob(inum_mat)->Change_Choix_resolution
|
|
(enumResolutionMatri,enumPreconditionnement);
|
|
// on vérifie que l'assemblage choisit est bien de type symétrique
|
|
if (pa.Symetrie_matrice() != true)
|
|
{ cout << "Erreur de type d'assemblage, le type de matrice choisit est symetrique"
|
|
<< " alors que l'assemblage n'est pas symetrique !! \n";
|
|
cout << " Algori::Choix_matriciel(..)";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
}
|
|
break;
|
|
case BANDE_NON_SYMETRIQUE_LAPACK : case BANDE_SYMETRIQUE_LAPACK: // le choix est fait au moment de l'allocation
|
|
{ // calcul de la largeur de bande effective
|
|
int demi=0,total=0;
|
|
lesMail->Largeur_Bande(demi,total,nb_casAssemb);
|
|
total = std::min(total,2*nbddl_MPI-1);
|
|
demi = std::min(demi,nbddl_MPI);
|
|
// --- on stocke les largeurs initiales de ddl
|
|
{ // on redimensionne si nécessaire
|
|
int nombre_cas_assemb = tab_para_stockage.Taille();
|
|
if (nb_casAssemb.n > nombre_cas_assemb)
|
|
tab_para_stockage.Change_taille(nb_casAssemb.n);
|
|
// maintenant on stocke
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = demi;
|
|
parstock.total = total;
|
|
};
|
|
|
|
// dans le cas non // ou // pour le CPU 0, on précise la dim
|
|
// ici on garde nbddl au lien de nbddl_MPI: ils sont identiques
|
|
if (!cal_parallele_et_rang_non_nul)
|
|
{if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n raideur: largeur de bande initiale pour les elements (en ddl) " << total << " ";
|
|
if (lescontacts!= NULL)
|
|
{// calcul de la largeur de bande effective en tenant compte du contact
|
|
int demic=0,totalc=0,cumule=0;
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule))
|
|
{totalc = std::min(totalc,2*nbddl-1);
|
|
demic = std::min(demic,nbddl);
|
|
cumule = std::min(cumule,nbddl);
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation de la largeur de bande pour les conditions de contact (en ddl) " << cumule << " ";
|
|
demi += cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total += 2 * cumule;
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,2*nbddl-1);
|
|
demi = std::min(demi,nbddl);
|
|
};
|
|
};
|
|
// cas de l'influence des conditions linéaires d'entrée
|
|
int demic=0,totalc=0,cumule=0;
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
if (lesCondLim->Largeur_Bande(demic,totalc,nb_casAssemb,lesMail,lesRef,cumule))
|
|
{totalc = std::min(totalc,2*nbddl-1);
|
|
demic = std::min(demic,nbddl);
|
|
cumule = std::min(cumule,nbddl);
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation de largeur de bande pour les conditions lineaires (en ddl) " << totalc << " ";
|
|
// ---- les deux lignes qui suivent sont faussent, car dans le cas du produit de deux matrices bandes la largeur de bande du produit
|
|
// = non pas le max, mais la "somme" des deux largeurs de bandes (parties hors diagonales),
|
|
// d'une manière plus précise cf. J Chevalier 1993, soit une matrice bande avec deux bandes de part et autre de la diagonale, différentes
|
|
// A_ij (a,b) telle que A_ij = 0 si j<i-a ou j>i+b, donc a est la bande inf (hors diag) et b est la bande sup (hors diag)
|
|
// soient A(a,b) et B(c,d) alors A*B est de type (a+c,b+d)
|
|
// or pour mettre en place les CL (actuellement)
|
|
// on utilise une matrice de rotation et on fait S^T * K * S , tel S est de type (a,b) et donc S^T est de type (b,a) donc
|
|
// si on suppose que K est de type (l,l) et bien S^T * K * S sera de type (l+a+b,l+a+b) donc c'est a+b qui compte (hors diag)
|
|
|
|
// demi = MaX(demi,demic);
|
|
// total = MaX(total,totalc);
|
|
demi += cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total += 2 * cumule;
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,2*nbddl-1);
|
|
demi = std::min(demi,nbddl);
|
|
};
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n largeur de bande finale (en ddl) " << total << " ";
|
|
};
|
|
|
|
// création éventuelle et initialisation a zero
|
|
if (tab_matglob(inum_mat) == NULL)
|
|
{ if (enumatrice == BANDE_SYMETRIQUE_LAPACK)
|
|
{ tab_matglob(inum_mat) = new MatLapack (enumatrice,demi,nbddl_MPI,true,0.0
|
|
,enumResolutionMatri,enumPreconditionnement);}
|
|
else
|
|
{ tab_matglob(inum_mat) = new MatLapack (enumatrice,total,nbddl_MPI,false,0.0
|
|
,enumResolutionMatri,enumPreconditionnement);};
|
|
}
|
|
// sinon on regarde si la taille est bonne
|
|
else if ((tab_matglob(inum_mat)->Nb_ligne()!= nbddl_MPI) || (tab_matglob(inum_mat)->Nb_colonne()!= nbddl_MPI))
|
|
// dans ce cas on change de matrice
|
|
{ delete tab_matglob(inum_mat);
|
|
if (enumatrice == BANDE_SYMETRIQUE_LAPACK)
|
|
{ tab_matglob(inum_mat) = new MatLapack (enumatrice,demi,nbddl_MPI,true,0.0
|
|
,enumResolutionMatri,enumPreconditionnement);}
|
|
else
|
|
{ tab_matglob(inum_mat) = new MatLapack (enumatrice,total,nbddl_MPI,false,0.0
|
|
,enumResolutionMatri,enumPreconditionnement);};
|
|
}
|
|
else // sinon on se contente d'initialiser à 0.
|
|
tab_matglob(inum_mat)->Initialise(0.);
|
|
if (enumatrice == BANDE_SYMETRIQUE_LAPACK) // si on a choisit un stockage symétrique
|
|
// on vérifie que l'assemblage choisit est bien de type symétrique
|
|
if (pa.Symetrie_matrice() != true)
|
|
{ cout << "Erreur de type d'assemblage, le type de matrice choisit est symetrique"
|
|
<< " alors que l'assemblage n'est pas symetrique !! \n";
|
|
cout << " Algori::Choix_matriciel(..)";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
}
|
|
break;
|
|
case CREUSE_COMPRESSEE_COLONNE :
|
|
{ // cas d'une matrice creuse compressée par colonne
|
|
// tout d'abord on demande l'ensemble des tables de connexion
|
|
// pour les éléments
|
|
Tableau < Tableau <int> > petites_matrices;
|
|
lesMail->Table_connexion(petites_matrices,nb_casAssemb);
|
|
// pour l'instant le cas avec contact n'est pas traité
|
|
if (lescontacts!= NULL)
|
|
{ cout << "\n *** cas avec contact non actuellement traite "
|
|
<< "\n Algori::Choix_matriciel(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
// !!! pour l'instant on ne prend pas en compte les conditions linéaires initiales
|
|
// on vérifie
|
|
if (lesCondLim->ExisteCondiLimite())
|
|
{ cout << "\n*** Erreur de choix de matrice de masse, il y a des conditions lineaires intiales, ce qui conduit "
|
|
<< " a intervenir sur le stockage. Or le cas CREUSE_COMPRESSEE_COLONNE ne prend pas en compte pour l'instant "
|
|
<< " la presence de conditions limites !! \n";
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n Algori::Choix_matriciel(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
// puis on définit la matrice en conséquence
|
|
if (tab_matglob(inum_mat) == NULL)
|
|
{tab_matglob(inum_mat) = new Mat_creuse_CompCol(nbddl_MPI,nbddl_MPI, petites_matrices);
|
|
}
|
|
// sinon on regarde si la taille est bonne
|
|
else if ((tab_matglob(inum_mat)->Nb_ligne()!= nbddl_MPI) || (tab_matglob(inum_mat)->Nb_colonne()!= nbddl_MPI))
|
|
// dans ce cas on change de matrice
|
|
{ delete tab_matglob(inum_mat);
|
|
tab_matglob(inum_mat) = new Mat_creuse_CompCol(nbddl_MPI,nbddl_MPI, petites_matrices);
|
|
};
|
|
// on spécifie le type de résolution
|
|
tab_matglob(inum_mat)->Change_Choix_resolution
|
|
(enumResolutionMatri,enumPreconditionnement);
|
|
// sinon il n'y a rien n'a faire au niveau des tailles
|
|
}
|
|
break;
|
|
default :
|
|
cout << "\nErreur : valeur incorrecte ou non implanté du type de matrice retenue, type !\n"
|
|
<< " = " << enumatrice ;
|
|
cout << "\n Algori::Choix_matriciel(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n stockage raideur" << enumatrice << " taille (entiers) :" << tab_matglob(inum_mat)->Place() << endl;
|
|
|
|
};
|
|
return tab_matglob;
|
|
};
|
|
|
|
// Mise à jour éventuelle de la taille de la matrice de raideur ou masse du système linéaire
|
|
// en fonction du contact ou en fonction de "nouvelle_largeur_imposee" dans ce cas, lescontacts
|
|
// n'est pas utilisé ! donc la méthode peut servir dans ce cas sans le contact
|
|
//
|
|
// la matrice *matglob: doit déjà existée
|
|
// en retour le pointeur désigne toujours la même matrice qu'en entrée
|
|
// avec les même caractéristique de fonctionnement que l'ancienne (mêm résolution, stockage ...)
|
|
// NB: la dimension du tableau dépend du paramétrage lu dans ParaAlgoGlobal
|
|
// 1) si niveau_substitution =0 : -> mise à jour de toutes les matrices
|
|
// 2) si niveau_substitution = i : -> uniquement mise à jour de la matrices i
|
|
// par contre la dimension de tab_matglob est toujours mis à jour si c'est nécessaire
|
|
// si nouvelle_largeur_imposee : n'est pas nulle, cela veut-dire qu'il y a eu une nouvelle numérotation
|
|
// et une nouvelle mise en place des pointeurs d'assemblage
|
|
// alors c'est directement cette valeur de ddl (et non de noeud) qui est imposée sur la matrice
|
|
// nouvelle_largeur_imposee.un = la largeur totale
|
|
// nouvelle_largeur_imposee.deux = la demie largeur
|
|
// nouvelles_largeur_en_ddl.trois = la demie largeur maximale pour la partie éléments finis
|
|
// uniquement (sans les CLL)
|
|
void Algori::Mise_a_jour_Choix_matriciel_contact
|
|
(Tableau <Mat_abstraite* >& tab_matglob,const Nb_assemb& nb_casAssemb
|
|
, LesContacts* lescontacts
|
|
,int niveau_substitution ,TroisEntiers* nouvelle_largeur_imposee)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return ;
|
|
#endif
|
|
|
|
// tout d'abord le choix de la matrice de stockage
|
|
Tableau<Enum_matrice> tab_enu_matrice_sec; // init
|
|
tab_enu_matrice_sec.Init_from_list(pa.Type_matrice_secondaire());
|
|
Tableau<Enum_type_resolution_matri> tab_enu_type_resolution_matri;
|
|
tab_enu_type_resolution_matri.Init_from_list(pa.Type_resolution_secondaire());
|
|
Tableau<Enum_preconditionnement> tab_enu_preconditionnement;
|
|
tab_enu_preconditionnement.Init_from_list(pa.Type_preconditionnement_secondaire());
|
|
Tableau<int> tab_nb_iter_nondirecte_secondaire;
|
|
tab_nb_iter_nondirecte_secondaire.Init_from_list(pa.Nb_iter_nondirecte_secondaire());
|
|
Tableau<double> tab_tolerance_secondaire;
|
|
tab_tolerance_secondaire.Init_from_list(pa.Tolerance_secondaire());
|
|
|
|
int nb_mat = 1+tab_enu_matrice_sec.Taille(); // nombre de matrices
|
|
|
|
// dans le cas où le tableau serait non nulle on regarde s'il a la bonne dimension
|
|
if (tab_matglob.Taille() > nb_mat)
|
|
// là il faut supprimer les matrices pointées en trop
|
|
{int taille = tab_matglob.Taille();
|
|
for (int i=nb_mat+1;i<=taille;i++)
|
|
if (tab_matglob(i)!= NULL)
|
|
delete tab_matglob(i);
|
|
// maintenant on peut changer la taille, en moins donc normalement
|
|
// on ne modifie pas les pointeurs déjà existants
|
|
tab_matglob.Change_taille(nb_mat);
|
|
}
|
|
else if (tab_matglob.Taille() < nb_mat)
|
|
// s'il est trop petit il faut augmenter la taille: on met les nouveaux pointeurs à NULL
|
|
tab_matglob.Change_taille(nb_mat,NULL);
|
|
// sinon il a la bonne taille on suppose que les matrices pointées sont de bonnes dimensions
|
|
|
|
int i_deb = 1; int i_fin = nb_mat+1; // initi par défaut des bornes
|
|
if (niveau_substitution != 0)
|
|
{ i_deb = niveau_substitution; i_fin = i_deb+1;};
|
|
|
|
// on va boucler sur le nombre de matrice
|
|
for (int inum_mat = i_deb; inum_mat < i_fin; inum_mat++)
|
|
{ // init des valeurs par défaut de la première matrice
|
|
Mat_abstraite* matglob = tab_matglob(inum_mat);
|
|
Enum_matrice enumatrice = pa.Type_Matrice(); // init
|
|
Enum_type_resolution_matri enumResolutionMatri = pa.Type_resolution();
|
|
Enum_preconditionnement enumPreconditionnement = pa.Type_preconditionnement();
|
|
// modif au cas où il y a des matrices secondaire
|
|
if (inum_mat > 1)
|
|
{enumatrice = tab_enu_matrice_sec(inum_mat-1);
|
|
if (tab_enu_type_resolution_matri.Taille() > (inum_mat-1))
|
|
enumResolutionMatri = tab_enu_type_resolution_matri(inum_mat-1);
|
|
if (tab_enu_preconditionnement.Taille() > (inum_mat-1))
|
|
enumPreconditionnement = tab_enu_preconditionnement(inum_mat-1);
|
|
};
|
|
|
|
switch (enumatrice)
|
|
{ case CARREE : break; // pas de modification
|
|
case RECTANGLE : break; // pas de modification
|
|
case CARREE_LAPACK : break; // pas de modification
|
|
case CARREE_SYMETRIQUE_LAPACK : break; // pas de modification
|
|
case RECTANGLE_LAPACK : break; // pas de modification
|
|
case BANDE_SYMETRIQUE : case BANDE_SYMETRIQUE_LAPACK:
|
|
{ // -- récup des anciennes tailles
|
|
int nbddl = matglob->Nb_ligne();
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
int ancien_demi = matglob->Nb_colonne();
|
|
// calcul de la largeur de bande effective en tenant compte du contact
|
|
int demic=0,totalc=0,cumule=0;
|
|
int demi = parstock.demi; // init
|
|
if (nouvelle_largeur_imposee == NULL) // cas où il faut calculer
|
|
{// on n'intervient que si la largeur en noeud augmente
|
|
if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule))
|
|
{// la mise à jour dépend du type de contact
|
|
if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation
|
|
// on doit augmenter la lb en fonction de cumule, si la largeur en noeud est différente
|
|
// de 1
|
|
{cumule = std::min(cumule,nbddl);
|
|
demi = parstock.demi + cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
if (demi > ancien_demi)
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << cumule << "old_1/2lb: "<<ancien_demi << " new_1/2lb: "<< demi <<" ";
|
|
}
|
|
else if ((pa.ContactType() == 2)|| (pa.ContactType() == 3)
|
|
||(pa.ContactType() == 4) )// cas d'un contact par pénalisation ou type 3 *** exploratoire
|
|
// dans ce cas on considère uniquement le LB maxi
|
|
{ demic = std::min(demic,nbddl);
|
|
int demi_inter = std::max(parstock.demi, demic);
|
|
if (demi_inter > ancien_demi)
|
|
if ((ParaGlob::NiveauImpression() >= 5) && (demic > demi))
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << (demic-demi) << "old_1/2lb: "<<ancien_demi << " new_1/2lb: "<< demi_inter <<" ";
|
|
demi = demi_inter;
|
|
};
|
|
};
|
|
}
|
|
else // sinon on applique la demande
|
|
{ demi = nouvelle_largeur_imposee->deux;
|
|
// et on met à jour : uniquement la partie relative aux maillages
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = nouvelle_largeur_imposee->trois;
|
|
parstock.total = 2 * nouvelle_largeur_imposee->trois -1;
|
|
};
|
|
// on limite au nombres total de ddl
|
|
demi = std::min(demi,nbddl);
|
|
|
|
// on change la taille, si elle doit augmenter, ou si elle est inférieur d'au moins 5% par rapport à la taille actuelle
|
|
if ( (demi > matglob->Nb_colonne()) ||
|
|
(demi < 0.95 * matglob->Nb_colonne()))
|
|
// on change la taille
|
|
{ if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation effective: LB/2+1 finale(en ddl) " << demi << " ";
|
|
switch (enumatrice)
|
|
{ case BANDE_SYMETRIQUE:
|
|
((MatBand*)matglob)->Change_taille(demi,nbddl );
|
|
break;
|
|
case BANDE_SYMETRIQUE_LAPACK:
|
|
((MatLapack*)matglob)->Change_taille(nbddl,demi);
|
|
break;
|
|
default:
|
|
cout << "\n erreur non prevue Algori::Mise_a_jour_Choix_matriciel_contact "<<endl;
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case BANDE_NON_SYMETRIQUE : case BANDE_NON_SYMETRIQUE_LAPACK :
|
|
{ // -- récup des anciennes tailles
|
|
int nbddl = matglob->Nb_ligne();
|
|
int ancien_lb = matglob->Nb_colonne();
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
//int demi = matglob->Nb_colonne();
|
|
// calcul de la largeur de bande effective en tenant compte du contact
|
|
int demic=0,totalc=0,cumule=0;
|
|
int total = parstock.total; // init
|
|
if (nouvelle_largeur_imposee == NULL) // cas où il faut calculer
|
|
{// on n'intervient que si la largeur en noeud augmente
|
|
if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule))
|
|
{// la mise à jour dépend du type de contact
|
|
if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation
|
|
// on doit augmenter la lb en fonction de cumule
|
|
{ cumule = std::min(cumule,nbddl);
|
|
int total_inter = parstock.total + 2 * cumule;
|
|
if (total_inter > ancien_lb)
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << cumule << "old_lb: "<<ancien_lb << " new_lb: "<< total_inter <<" ";
|
|
total = total_inter;
|
|
}
|
|
|
|
else if ((pa.ContactType() == 2)|| (pa.ContactType() == 3)
|
|
|| (pa.ContactType() == 4))// cas d'un contact par pénalisation ou type 3 *** exploratoire
|
|
// dans ce cas on considère uniquement le LB maxi
|
|
{ totalc = std::min(totalc,2*nbddl-1);
|
|
int total_inter = std::max(parstock.total, totalc);
|
|
if (total_inter > ancien_lb)
|
|
if ((ParaGlob::NiveauImpression() >= 5) && (totalc > total))
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << (totalc-total) << "old_lb: "<<ancien_lb << " new_lb: "<< total_inter << " ";
|
|
total = total_inter;
|
|
};
|
|
};
|
|
}
|
|
else // sinon on applique la demande
|
|
{ total = nouvelle_largeur_imposee->un;
|
|
// et on met à jour : uniquement la partie relative aux maillages
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = nouvelle_largeur_imposee->trois;
|
|
parstock.total = 2 * nouvelle_largeur_imposee->trois -1;
|
|
};
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,2*nbddl-1);
|
|
|
|
// on change la taille, si elle doit augmenter, ou si elle est inférieur d'au moins 5% par rapport à la taille actuelle
|
|
if ( (total > matglob->Nb_colonne()) ||
|
|
(total < 0.95 * matglob->Nb_colonne()))
|
|
// on change la taille
|
|
{ if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation effective: LB finale(en ddl) " << total << " ";
|
|
switch (enumatrice)
|
|
{ case BANDE_NON_SYMETRIQUE:
|
|
((MatBand*)matglob)->Change_taille(total,nbddl );
|
|
break;
|
|
case BANDE_NON_SYMETRIQUE_LAPACK:
|
|
((MatLapack*)matglob)->Change_taille(nbddl,total);
|
|
break;
|
|
|
|
default:
|
|
cout << "\n erreur2 non prevue Algori::Mise_a_jour_Choix_matriciel_contact "<<endl;
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case CREUSE_COMPRESSEE_COLONNE :
|
|
{ cout << "\n *** cas avec contact non actuellement traite "
|
|
<< "\n Algori::Mise_a_jour_Choix_matriciel_contact(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
break;
|
|
}
|
|
default :
|
|
cout << "\nErreur : valeur incorrecte ou non implante du type de matrice retenue, type !\n"
|
|
<< " = " << enumatrice ;
|
|
cout << "\n Algori::Mise_a_jour_Choix_matriciel_contact(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n stockage raideur " << enumatrice << " taille (entiers) :"
|
|
<< matglob->Place() << endl;
|
|
};
|
|
};
|
|
|
|
// choix de la matrice de la matrice de masse globale
|
|
// ou mise à jour de la matrice masse si elle existe
|
|
Mat_abstraite* Algori::Choix_matrice_masse
|
|
(int nbddl,Mat_abstraite* mat_mass,LesMaillages * lesMail,LesReferences* lesRef
|
|
,const Nb_assemb& nb_casAssemb,LesContacts* ,LesCondLim* lesCondLim)
|
|
{
|
|
int nbddl_MPI = nbddl; // init
|
|
bool cal_parallele_et_rang_non_nul = false;
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la matrice du CPU 0 est initialisée
|
|
// à la taille nécessaire pour une résolution globale
|
|
// pour les autres CPU on définit une matrice de taille unitaire
|
|
// qui ne sera pas utilisée mais qui sera valide
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
{nbddl_MPI = 1;
|
|
cal_parallele_et_rang_non_nul = true;
|
|
};
|
|
#endif
|
|
|
|
// tout d'abord le choix de la matrice de stockage
|
|
// s'il n'y a pas de condition linéaires classiques, la largeur de bande ne doit pas changer
|
|
if ( ((pa.Type_calcul_masse() == MASSE_DIAG_COEF_EGAUX) || (pa.Type_calcul_masse() == MASSE_DIAG_COEF_VAR))
|
|
&& (!(lesCondLim->ExisteCondiLimite()))
|
|
// && (pa.ContactType() != 1) // non ce sera géré dans la mise à jour, pour éviter
|
|
// // un stockage en bande systématique
|
|
)
|
|
{ // on utilise une matrice diagonale
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatDiag (nbddl_MPI);
|
|
if ((ParaGlob::NiveauImpression() > 2)&&(!cal_parallele_et_rang_non_nul))
|
|
cout << "\n stockage initial matrice masse --> diagonal, nbddl= " << nbddl_MPI ;
|
|
}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ if (mat_mass->Type_matrice() != DIAGONALE)
|
|
{ delete mat_mass; mat_mass = new MatDiag (nbddl_MPI);} // cas où on change de matrice
|
|
else { MatDiag * mat_mass_diag = (MatDiag*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_diag->Change_taille(nbddl_MPI);
|
|
};
|
|
if ((ParaGlob::NiveauImpression() > 2)&&(!cal_parallele_et_rang_non_nul))
|
|
cout << "\n changement stockage matrice masse --> diagonal, nbddl= " << nbddl_MPI ;
|
|
};
|
|
// --- on stocke les largeurs initiales de ddl
|
|
// on redimensionne si nécessaire
|
|
int nombre_cas_assemb = tab_para_stockage.Taille();
|
|
if (nb_casAssemb.n > nombre_cas_assemb)
|
|
tab_para_stockage.Change_taille(nb_casAssemb.n);
|
|
// maintenant on stocke
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = parstock.total = 1; // tout est diagonal
|
|
}
|
|
else if ( ((pa.Type_calcul_masse() == MASSE_DIAG_COEF_EGAUX) ||
|
|
(pa.Type_calcul_masse() == MASSE_DIAG_COEF_VAR))
|
|
&&
|
|
((lesCondLim->ExisteCondiLimite())
|
|
|| (pa.ContactType() == 1) // on part avec l'idée d'une largeur de 1 en noeud
|
|
// ce qui est le cas d'un contact solide - déformable
|
|
// sera ensuite éventuellement augmenté
|
|
// || contact_type_1_et_maitre_deformable
|
|
)
|
|
// && (pa.Type_Matrice() == DIAGONALE)
|
|
)
|
|
{ // dans le cas ou on devrait utiliser une matrice diagonale, on va arbitrairement utiliser une matrice bande
|
|
// mais avec une largeur uniquement déterminé par les conditions linéaires
|
|
// en particulier, si les CLL => un stockage diagonale en noeuds, on utilise une matrice de bande = dim espace
|
|
// calcul de la largeur de bande effective due à l'influence des conditions linéaires d'entrée
|
|
// --- on stocke les largeurs initiales de ddl
|
|
// on redimensionne si nécessaire
|
|
int nombre_cas_assemb = tab_para_stockage.Taille();
|
|
if (nb_casAssemb.n > nombre_cas_assemb)
|
|
tab_para_stockage.Change_taille(nb_casAssemb.n);
|
|
// maintenant on stocke
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = parstock.total = 1; // tout est diagonal
|
|
|
|
int demic=0,totalc=0,cumule=0;
|
|
int demi=0,total=0;
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
// et que l'on est sur le CPU 0
|
|
if ( (lesCondLim->Largeur_Bande(demic,totalc,nb_casAssemb,lesMail,lesRef,cumule))
|
|
&& (!cal_parallele_et_rang_non_nul)
|
|
)
|
|
{ demi = 1 + cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total = 1 + 2 * cumule;
|
|
}
|
|
else // sinon on est dans le cas où on peut utiliser une matrice bande = dim espace (ex: si dim 3: tridiagonale)
|
|
{ int dim_espace = ParaGlob::Dimension();
|
|
demi = dim_espace;
|
|
total = 1 + 2 * (dim_espace-1);
|
|
};
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,nbddl_MPI);
|
|
demi = std::min(demi,nbddl_MPI);
|
|
// si la matrice actuelle est de type diagonale il faut la supprimer et définir une
|
|
// matrice bande
|
|
bool change_stockage = false;
|
|
if (mat_mass != NULL)
|
|
if (mat_mass->Type_matrice() == DIAGONALE)
|
|
{ delete mat_mass; mat_mass = NULL;change_stockage = true;}; // cas où on change de stockage
|
|
|
|
// maintenant on crée une matrice en fonction de la demande
|
|
switch (pa.Type_Matrice())
|
|
{ case CARREE :
|
|
{// cas d'une matrice carrée, là a priori on n'a pas besoin d'augmenter la largeur, on est au maxi
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_pleine (nbddl_MPI,nbddl_MPI);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ Mat_pleine * mat_mass_d = (Mat_pleine*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Initialise (nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case RECTANGLE :
|
|
{// cas s'une matrice rectangulaire, pour l'instant idem que le cas précédent
|
|
// car pour l'instant on ne voit pas très bien à quoi cela servirait d'être différent
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_pleine (nbddl_MPI,nbddl_MPI);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ Mat_pleine * mat_mass_d = (Mat_pleine*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Initialise (nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case CARREE_LAPACK :
|
|
{// cas s'une matrice carrée
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case CARREE_SYMETRIQUE_LAPACK :
|
|
{// cas s'une matrice carrée symétrique
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl_MPI,nbddl_MPI,true,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case RECTANGLE_LAPACK :
|
|
{// cas s'une matrice rectangulaire, pour l'instant idem que le cas précédent
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case BANDE_SYMETRIQUE :
|
|
{// initialisation a zero
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatBand (BANDE_SYMETRIQUE,demi,nbddl_MPI,0);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatBand * mat_mass_d = (MatBand*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(demi,nbddl_MPI);
|
|
mat_mass_d->Initialise (0.);
|
|
};
|
|
break;
|
|
}
|
|
case BANDE_NON_SYMETRIQUE_LAPACK : case BANDE_SYMETRIQUE_LAPACK: // le choix est fait au moment de l'allocation
|
|
{// initialisation a zero
|
|
if (pa.Type_Matrice() == BANDE_SYMETRIQUE_LAPACK)
|
|
{ if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack(pa.Type_Matrice(),demi,nbddl_MPI,true,0.0
|
|
,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(demi,nbddl_MPI,0.0);
|
|
};
|
|
}
|
|
else
|
|
{ if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack(pa.Type_Matrice(),total,nbddl_MPI,false,0.0
|
|
,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(total,nbddl_MPI,0.0);
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case CREUSE_COMPRESSEE_COLONNE :
|
|
{ // cas d'une matrice creuse compressée par colonne
|
|
// tout d'abord on demande l'ensemble des tables de connexion
|
|
// pour les éléments
|
|
Tableau < Tableau <int> > petites_matrices;
|
|
lesMail->Table_connexion(petites_matrices,nb_casAssemb);
|
|
// puis on définit la matrice en conséquence
|
|
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_creuse_CompCol(nbddl_MPI,nbddl_MPI, petites_matrices);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ if (mat_mass->Type_matrice() != CREUSE_COMPRESSEE_COLONNE)
|
|
{ delete mat_mass; mat_mass = new Mat_creuse_CompCol(nbddl_MPI,nbddl_MPI, petites_matrices);} // cas où on change de matrice
|
|
else {Mat_creuse_CompCol * mat_mass_d = (Mat_creuse_CompCol*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI, petites_matrices);
|
|
};
|
|
};
|
|
// pour l'instant on ne prend pas en compte les conditions linéaires initiales qui augmente la largeur
|
|
// diagonale par bloc de dim
|
|
// par contre on considère que par défaut la diagonale par bloc existe !!
|
|
if (change_stockage)
|
|
{ cout << "\n*** Erreur de choix de matrice de masse, il y a des conditions lineaires intiales,"
|
|
<< " qui vont changer le stockage a l'execution. Or le cas CREUSE_COMPRESSEE_COLONNE ne "
|
|
<< " prend pas en compte pour l'instant ce cas de changement !! \n";
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << " Algori::Choix_matrice_masse(..)";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
break;
|
|
}
|
|
default :
|
|
cout << "\nErreur : valeur incorrecte ou non implante du type de matrice retenue, type !\n"
|
|
<< " = " << pa.Type_Matrice() ;
|
|
cout << "\n Algori::Algori::Choix_matrice_masse(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
if ((ParaGlob::NiveauImpression() > 2)&&(!cal_parallele_et_rang_non_nul))
|
|
{ cout << "\n"; if (change_stockage) cout << " changement de ";
|
|
cout << " stockage matrice masse -->" << Nom_matrice(mat_mass->Type_matrice())
|
|
<< " nb_ligne= "<< mat_mass->Nb_ligne() <<" nb_col= "<< mat_mass->Nb_colonne() << endl;
|
|
};
|
|
}
|
|
else
|
|
// sinon on se trouve dans le cas de matrice voulue non diagonale car dont le calcul des coefs ne conduit pas
|
|
// à une matrice a priori diagonale (exemple: matrice consistante)
|
|
{switch (pa.Type_Matrice())
|
|
{ case CARREE :
|
|
{// cas d'une matrice carrée, là a priori on n'a pas besoin d'augmenter la largeur, on est au maxi
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_pleine (nbddl_MPI,nbddl_MPI);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ Mat_pleine * mat_mass_d = (Mat_pleine*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Initialise (nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case RECTANGLE :
|
|
{// cas s'une matrice rectangulaire, pour l'instant idem que le cas précédent
|
|
// car pour l'instant on ne voit pas très bien à quoi cela servirait d'être différent
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_pleine (nbddl_MPI,nbddl_MPI);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ Mat_pleine * mat_mass_d = (Mat_pleine*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Initialise (nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case CARREE_LAPACK :
|
|
{// cas s'une matrice carrée
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case CARREE_SYMETRIQUE_LAPACK :
|
|
{// cas s'une matrice carrée symétrique
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl_MPI,nbddl_MPI,true,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case RECTANGLE_LAPACK :
|
|
{// cas s'une matrice rectangulaire, pour l'instant idem que le cas précédent
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl_MPI,nbddl_MPI,false,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI,0.);
|
|
};
|
|
break;
|
|
}
|
|
case BANDE_SYMETRIQUE :
|
|
{// calcul de la largeur de bande effective
|
|
int demi=0,total=0;
|
|
lesMail->Largeur_Bande(demi,total,nb_casAssemb);
|
|
total = std::min(total,nbddl_MPI);
|
|
demi = std::min(demi,nbddl_MPI);
|
|
// --- on stocke les largeurs initiales de ddl
|
|
// on redimensionne si nécessaire
|
|
int nombre_cas_assemb = tab_para_stockage.Taille();
|
|
if (nb_casAssemb.n > nombre_cas_assemb)
|
|
tab_para_stockage.Change_taille(nb_casAssemb.n);
|
|
// maintenant on stocke
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = demi;
|
|
parstock.total = total;
|
|
// l'influence des CLL n'intervient que sur le CPU 0
|
|
if (!cal_parallele_et_rang_non_nul)
|
|
{if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n matrice masse: largeur de bande pour les elements (en ddl) " << total << " ";
|
|
// cas de l'influence des conditions linéaires d'entrée
|
|
int demic=0,totalc=0,cumule=0;
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
if (lesCondLim->Largeur_Bande(demic,totalc,nb_casAssemb,lesMail,lesRef,cumule))
|
|
{totalc = std::min(totalc,nbddl_MPI);
|
|
demic = std::min(demic,nbddl_MPI);
|
|
cumule = std::min(cumule,nbddl_MPI);
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n matrice masse: largeur de bande pour les conditions lineaires (en ddl) " << totalc << " ";
|
|
demi += cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total += 2 * cumule;
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,nbddl_MPI);
|
|
demi = std::min(demi,nbddl_MPI);
|
|
};
|
|
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n matrice masse: largeur de bande finale (en ddl) " << total << " "
|
|
<< "\n stockage symetrique d'ou utilisation de la demi largeur= " << demi << " ";
|
|
};
|
|
// initialisation a zero
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatBand (BANDE_SYMETRIQUE,demi,nbddl_MPI,0);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatBand * mat_mass_d = (MatBand*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(demi,nbddl_MPI);
|
|
mat_mass_d->Initialise (0.);
|
|
};
|
|
// // on vérifie que l'assemblage choisit est bien de type symétrique
|
|
// if (pa.Symetrie_matrice() != true)
|
|
// { cout << "Erreur de type d'assemblage, le type de matrice choisit est non symetrique"
|
|
// << " alors que l'assemblage n'est pas symetrique !! \n";
|
|
// cout << " Algori::Choix_matrice_masse(..)";
|
|
// Sortie(1);
|
|
// };
|
|
break;
|
|
}
|
|
case BANDE_NON_SYMETRIQUE_LAPACK : case BANDE_SYMETRIQUE_LAPACK: // le choix est fait au moment de l'allocation
|
|
{// calcul de la largeur de bande effective
|
|
int demi=0,total=0;
|
|
lesMail->Largeur_Bande(demi,total,nb_casAssemb);
|
|
total = std::min(total,2*nbddl_MPI-1);
|
|
demi = std::min(demi,nbddl_MPI);
|
|
// --- on stocke les largeurs initiales de ddl
|
|
// on redimensionne si nécessaire
|
|
int nombre_cas_assemb = tab_para_stockage.Taille();
|
|
if (nb_casAssemb.n > nombre_cas_assemb)
|
|
tab_para_stockage.Change_taille(nb_casAssemb.n);
|
|
// maintenant on stocke
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = demi;
|
|
parstock.total = total;
|
|
// cas de l'influence des conditions linéaires d'entrée
|
|
int demic=0,totalc=0,cumule=0;
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
// et que l'on est sur le CPU 0
|
|
if ( (lesCondLim->Largeur_Bande(demic,totalc,nb_casAssemb,lesMail,lesRef,cumule))
|
|
&& (!cal_parallele_et_rang_non_nul)
|
|
)
|
|
{totalc = std::min(totalc,2*nbddl_MPI-1);
|
|
demic = std::min(demic,nbddl_MPI);
|
|
cumule = std::min(cumule,nbddl_MPI);
|
|
demi += cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total += 2 * cumule;
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n matrice masse: augmentation de la largeur de bande pour les conditions lineaires (en ddl) " << cumule << " ";
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,2*nbddl_MPI-1);
|
|
demi = std::min(demi,nbddl_MPI);
|
|
};
|
|
if ((ParaGlob::NiveauImpression() >= 5)&& (!cal_parallele_et_rang_non_nul))
|
|
cout << "\n matrice masse: largeur de bande finale (en ddl) " << total << " ";
|
|
// initialisation a zero
|
|
if (pa.Type_Matrice() == BANDE_SYMETRIQUE_LAPACK)
|
|
{ if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack(pa.Type_Matrice(),demi,nbddl_MPI,true,0.0
|
|
,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(demi,nbddl_MPI,0.0);
|
|
};
|
|
}
|
|
else
|
|
{ if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack(pa.Type_Matrice(),total,nbddl_MPI,false,0.0
|
|
,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(total,nbddl_MPI,0.0);
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case CREUSE_COMPRESSEE_COLONNE :
|
|
{ // cas d'une matrice creuse compressée par colonne
|
|
// tout d'abord on demande l'ensemble des tables de connexion
|
|
// pour les éléments
|
|
Tableau < Tableau <int> > petites_matrices;
|
|
lesMail->Table_connexion(petites_matrices,nb_casAssemb);
|
|
// puis on définit la matrice en conséquence
|
|
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_creuse_CompCol(nbddl_MPI,nbddl_MPI, petites_matrices);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ if (mat_mass->Type_matrice() != CREUSE_COMPRESSEE_COLONNE)
|
|
{ delete mat_mass; mat_mass = new Mat_creuse_CompCol(nbddl_MPI,nbddl_MPI, petites_matrices);} // cas où on change de matrice
|
|
else {Mat_creuse_CompCol * mat_mass_d = (Mat_creuse_CompCol*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl_MPI,nbddl_MPI, petites_matrices);
|
|
};
|
|
};
|
|
// !!! pour l'instant on ne prend pas en compte les conditions linéaires initiales
|
|
// on vérifie
|
|
if (lesCondLim->ExisteCondiLimite())
|
|
{ cout << "\n*** Erreur de choix de matrice de masse, il y a des conditions lineaires intiales, ce qui conduit "
|
|
<< " a intervenir sur le stockage. Or le cas CREUSE_COMPRESSEE_COLONNE ne prend pas en compte pour l'instant "
|
|
<< " la presence de conditions limites !! \n";
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << " Algori::Choix_matrice_masse(..)";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
break;
|
|
}
|
|
default :
|
|
cout << "\nErreur : valeur incorrecte ou non implante du type de matrice retenue, type !\n"
|
|
<< " = " << pa.Type_Matrice() ;
|
|
cout << "\n Algori::Algori::Choix_matrice_masse(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
};
|
|
if ((ParaGlob::NiveauImpression() >= 5)&& (!cal_parallele_et_rang_non_nul))
|
|
cout << "\n Taille du stockage masse " << mat_mass->Type_matrice() << " (taille en entiers) :"
|
|
<< mat_mass->Place() << endl;
|
|
return mat_mass;
|
|
};
|
|
|
|
// mise à jour éventuelle du type et/ou de la taille de la matrice de masse
|
|
// retourne un pointeur sur la nouvelle matrice, s'il y a eu une modification
|
|
// l'ancienne est supprimée
|
|
// sinon retour d'un pointeur NULL
|
|
Mat_abstraite* Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite
|
|
(int nbddl,Mat_abstraite* mat_mass,LesMaillages * lesMail,LesReferences* lesRef
|
|
,const Nb_assemb& nb_casAssemb, LesContacts* lescontacts)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la matrice du CPU 0 est concernée
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return NULL;
|
|
#endif
|
|
|
|
|
|
//// préparation pour le cas particulier : pa.ContactType() == 1
|
|
// int contact_type_1_et_maitre_deformable = false;
|
|
// if (pa.ContactType() == 1)
|
|
// {// on veut savoir s'il y a des contacts autres que solide-déformables
|
|
// if (lescontacts->Maitres_avec_deplacement_imposer())
|
|
// // cas où tous les surfaces maîtres sont fixées
|
|
// {contact_type_1_et_maitre_deformable = true;};
|
|
// // dans ce cas on peut utiliser une tridiagonale !
|
|
// };
|
|
bool change_stockage = false; // init pour le retour
|
|
|
|
if (( pa.ContactType() == 2) || (pa.ContactType() == 0)
|
|
|| (pa.ContactType() == 3)|| (pa.ContactType() == 4))
|
|
|
|
// cas sans contact ou d'une pénalisation en explicite
|
|
// il n'y a rien n'a faire
|
|
{return NULL;}
|
|
else // sinon on statut en fonction du type existant de matrice
|
|
{ // en fait il n'y a que deux cas très différents:
|
|
// soit on est en diagonal, et on doit peut-être passer dans un autre type
|
|
// de stockage
|
|
// soit ce n'est pas du diagonal, et on regarde s'il faut agrandir
|
|
if (mat_mass->Type_matrice() == DIAGONALE)
|
|
{// si on a un contact de
|
|
// type 1 c-a-d qui induit des conditions linéaires, on va analyser
|
|
if (pa.ContactType() == 1)
|
|
{ // dans le cas ou on devrait utiliser une matrice diagonale, on va utiliser la matrice demandée
|
|
// mais avec une largeur uniquement déterminé par les conditions linéaires éventuelles de contact
|
|
// en particulier, si les CLL => un stockage diagonale en noeuds, on utilise une matrice de bande = dim espace
|
|
// calcul de la largeur de bande effective due à l'influence des conditions linéaires de contact
|
|
// --- on stocke les largeurs initiales de ddl
|
|
// on redimensionne si nécessaire
|
|
int nombre_cas_assemb = tab_para_stockage.Taille();
|
|
if (nb_casAssemb.n > nombre_cas_assemb)
|
|
tab_para_stockage.Change_taille(nb_casAssemb.n);
|
|
// maintenant on stocke
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
parstock.nbass = nb_casAssemb;
|
|
parstock.demi = parstock.total = 1; // tout est diagonal
|
|
|
|
int demic=0,totalc=0,cumule=0;
|
|
int demi=0,total=0;
|
|
// int ancien_lb = mat_mass->Nb_colonne();
|
|
|
|
//-- dans tous les cas, à minima il faut passer en tridiagonale
|
|
if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule))
|
|
{ demi = 1 + cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
total = 1 + 2 * cumule;
|
|
}
|
|
else // sinon on est dans le cas où on peut utiliser une matrice bande = dim espace (ex: si dim 3: tridiagonale)
|
|
{ int dim_espace = ParaGlob::Dimension();
|
|
demi = dim_espace;
|
|
total = 1 + 2 * (dim_espace-1);
|
|
};
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,nbddl);
|
|
demi = std::min(demi,nbddl);
|
|
if (ParaGlob::NiveauImpression() >= 2)
|
|
cout << "\n augmentation de la largeur de bande pour les conditions de contact (en ddl) " << cumule << " new_lb: "<< total <<" ";
|
|
// comme la matrice actuelle est de type diagonale il faut la supprimer et définir une autre
|
|
if (mat_mass != NULL)
|
|
if (mat_mass->Type_matrice() == DIAGONALE)
|
|
{ delete mat_mass; mat_mass = NULL;change_stockage = true;}; // cas où on change de stockage
|
|
|
|
// maintenant on crée une matrice en fonction de la demande
|
|
switch (pa.Type_Matrice())
|
|
{ case CARREE :
|
|
{// cas d'une matrice carrée, là a priori on n'a pas besoin d'augmenter la largeur, on est au maxi
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_pleine (nbddl,nbddl);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ Mat_pleine * mat_mass_d = (Mat_pleine*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Initialise (nbddl,nbddl,0.);
|
|
};
|
|
break;
|
|
}
|
|
case RECTANGLE :
|
|
{// cas s'une matrice rectangulaire, pour l'instant idem que le cas précédent
|
|
// car pour l'instant on ne voit pas très bien à quoi cela servirait d'être différent
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_pleine (nbddl,nbddl);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ Mat_pleine * mat_mass_d = (Mat_pleine*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Initialise (nbddl,nbddl,0.);
|
|
};
|
|
break;
|
|
}
|
|
case CARREE_LAPACK :
|
|
{// cas s'une matrice carrée
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl,nbddl,false,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl,nbddl,0.);
|
|
};
|
|
break;
|
|
}
|
|
case CARREE_SYMETRIQUE_LAPACK :
|
|
{// cas s'une matrice carrée symétrique
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl,nbddl,true,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl,nbddl,0.);
|
|
};
|
|
break;
|
|
}
|
|
case RECTANGLE_LAPACK :
|
|
{// cas s'une matrice rectangulaire, pour l'instant idem que le cas précédent
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack (nbddl,nbddl,false,0.,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl,nbddl,0.);
|
|
};
|
|
break;
|
|
}
|
|
case BANDE_SYMETRIQUE :
|
|
{// initialisation a zero
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new MatBand (BANDE_SYMETRIQUE,demi,nbddl,0);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ MatBand * mat_mass_d = (MatBand*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(demi,nbddl);
|
|
mat_mass_d->Initialise (0.);
|
|
};
|
|
break;
|
|
}
|
|
case BANDE_NON_SYMETRIQUE_LAPACK : case BANDE_SYMETRIQUE_LAPACK: // le choix est fait au moment de l'allocation
|
|
{// initialisation a zero
|
|
if (pa.Type_Matrice() == BANDE_SYMETRIQUE_LAPACK)
|
|
{ if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack(pa.Type_Matrice(),demi,nbddl,true,0.0
|
|
,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(demi,nbddl,0.0);
|
|
};
|
|
}
|
|
else
|
|
{ if (mat_mass == NULL)
|
|
{ mat_mass = new MatLapack(pa.Type_Matrice(),total,nbddl,false,0.0
|
|
,pa.Type_resolution(),pa.Type_preconditionnement());}
|
|
else // sinon on redimentionne si nécessaire
|
|
{ MatLapack * mat_mass_d = (MatLapack*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(total,nbddl,0.0);
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case CREUSE_COMPRESSEE_COLONNE :
|
|
{ // cas d'une matrice creuse compressée par colonne
|
|
// tout d'abord on demande l'ensemble des tables de connexion
|
|
// pour les éléments
|
|
Tableau < Tableau <int> > petites_matrices;
|
|
lesMail->Table_connexion(petites_matrices,nb_casAssemb);
|
|
// puis on définit la matrice en conséquence
|
|
|
|
if (mat_mass == NULL)
|
|
{ mat_mass = new Mat_creuse_CompCol(nbddl,nbddl, petites_matrices);}
|
|
else // sinon on redimentionne ou on change si nécessaire
|
|
{ if (mat_mass->Type_matrice() != CREUSE_COMPRESSEE_COLONNE)
|
|
{ delete mat_mass; mat_mass = new Mat_creuse_CompCol(nbddl,nbddl, petites_matrices);} // cas où on change de matrice
|
|
else {Mat_creuse_CompCol * mat_mass_d = (Mat_creuse_CompCol*) mat_mass; // cas où on redimentionne la matrice
|
|
mat_mass_d->Change_taille(nbddl,nbddl, petites_matrices);
|
|
};
|
|
};
|
|
// pour l'instant on ne prend pas en compte les conditions linéaires initiales qui augmente la largeur
|
|
// diagonale par bloc de dim
|
|
// par contre on considère que par défaut la diagonale par bloc existe !!
|
|
if (change_stockage)
|
|
{ cout << "\n*** Erreur de choix de matrice de masse, il y a des conditions lineaires intiales,"
|
|
<< " qui vont changer le stockage a l'execution. Or le cas CREUSE_COMPRESSEE_COLONNE ne "
|
|
<< " prend pas en compte pour l'instant ce cas de changement !! \n";
|
|
if (ParaGlob::NiveauImpression() >= 2)
|
|
cout << " Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite(..)";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
break;
|
|
}
|
|
default :
|
|
cout << "\nErreur : valeur incorrecte ou non implante du type de matrice retenue, type !\n"
|
|
<< " = " << pa.Type_Matrice() ;
|
|
cout << "\n Algori::Algori::Choix_matrice_masse(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
if (ParaGlob::NiveauImpression() > 2)
|
|
{ cout << "\n"; if (change_stockage) cout << " changement de ";
|
|
cout << " stockage matrice masse -->" << Nom_matrice(mat_mass->Type_matrice())
|
|
<< " nb_ligne= "<< mat_mass->Nb_ligne() <<" nb_col= "<< mat_mass->Nb_colonne() << endl;
|
|
};
|
|
}
|
|
else // sinon pour l'instant les autres cas de contact ne sont pas traités
|
|
{cout << "\n*** Erreur pour la mise a jour de la matrice de masse "
|
|
<< " avec du contact, le type de contact = " <<pa.ContactType()
|
|
<< " n'est pas pris en compte \n";
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << " Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite(..)";
|
|
};
|
|
}
|
|
else // sinon on peut augmenter la taille directement
|
|
{Enum_matrice enumatrice = mat_mass->Type_matrice();// init
|
|
|
|
switch (enumatrice)
|
|
{ case CARREE : break; // pas de modification
|
|
case RECTANGLE : break; // pas de modification
|
|
case CARREE_LAPACK : break; // pas de modification
|
|
case CARREE_SYMETRIQUE_LAPACK : break; // pas de modification
|
|
case RECTANGLE_LAPACK : break; // pas de modification
|
|
case BANDE_SYMETRIQUE : case BANDE_SYMETRIQUE_LAPACK:
|
|
{ // -- récup des anciennes tailles
|
|
int nbddl = mat_mass->Nb_ligne();
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
int ancien_demi = mat_mass->Nb_colonne();
|
|
// calcul de la largeur de bande effective en tenant compte du contact
|
|
int demic=0,totalc=0,cumule=0;
|
|
int demi = parstock.demi; // init
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule))
|
|
{// la mise à jour dépend du type de contact
|
|
if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation
|
|
// on doit augmenter la lb en fonction de cumule, si la largeur en noeud est différente
|
|
// de 1
|
|
{cumule = std::min(cumule,nbddl);
|
|
demi = parstock.demi + cumule; // c'est donc toute la largeur hors diag que l'on ajoute
|
|
if (demi > ancien_demi)
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << cumule << "old_1/2lb: "<<ancien_demi << " new_1/2lb: "<< demi <<" ";
|
|
}
|
|
else if ((pa.ContactType() == 2) // cas d'un contact par pénalisation
|
|
|| (pa.ContactType() == 3)|| (pa.ContactType() == 4)
|
|
)
|
|
// dans ce cas on considère uniquement le LB maxi
|
|
{ demic = std::min(demic,nbddl);
|
|
int demi_inter = std::max(parstock.demi, demic);
|
|
if (demi_inter > ancien_demi)
|
|
if ((ParaGlob::NiveauImpression() >= 5) && (demic > demi))
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << (demic-demi) << "old_1/2lb: "<<ancien_demi << " new_1/2lb: "<< demi_inter <<" ";
|
|
demi = demi_inter;
|
|
};
|
|
};
|
|
// on limite au nombres total de ddl et pas inférieur à la dimension de l'espace
|
|
// car on a au minimum une largeur de 1 noeud donc 3 ddl
|
|
// ( à moins qu'il n'y ait plus de contact) mais pour l'instant on n'en tient pas compte ....
|
|
demi = std::max(std::min(demi,nbddl),ParaGlob::Dimension());
|
|
|
|
// on change la taille, si elle doit augmenter, ou si elle est inférieur d'au moins 5% par rapport à la taille actuelle
|
|
if ( (demi > mat_mass->Nb_colonne()) ||
|
|
(demi < 0.95 * mat_mass->Nb_colonne()))
|
|
// on change la taille
|
|
{ if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation effective: LB/2+1 finale(en ddl) " << demi << " ";
|
|
switch (enumatrice)
|
|
{ case BANDE_SYMETRIQUE:
|
|
((MatBand*)mat_mass)->Change_taille(demi,nbddl );
|
|
break;
|
|
case BANDE_SYMETRIQUE_LAPACK:
|
|
((MatLapack*)mat_mass)->Change_taille(nbddl,demi);
|
|
break;
|
|
default:
|
|
cout << "\n erreur non prevue Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite "<<endl;
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case BANDE_NON_SYMETRIQUE : case BANDE_NON_SYMETRIQUE_LAPACK :
|
|
{ // -- récup des anciennes tailles
|
|
int nbddl = mat_mass->Nb_ligne();
|
|
int ancien_lb = mat_mass->Nb_colonne();
|
|
ParaStockage & parstock = (tab_para_stockage(nb_casAssemb.n));
|
|
//int demi = matglob->Nb_colonne();
|
|
// calcul de la largeur de bande effective en tenant compte du contact
|
|
int demic=0,totalc=0,cumule=0;
|
|
int total = parstock.total; // init
|
|
// on n'intervient que si la largeur en noeud augmente
|
|
if (lescontacts->Largeur_Bande(demic,totalc,nb_casAssemb,cumule))
|
|
{// la mise à jour dépend du type de contact
|
|
if (pa.ContactType() == 1) // contact cinématique, sans multiplicateur ni pénalisation
|
|
// on doit augmenter la lb en fonction de cumule
|
|
{ cumule = std::min(cumule,nbddl);
|
|
int total_inter = parstock.total + 2 * cumule;
|
|
if (total_inter > ancien_lb)
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << cumule << "old_lb: "<<ancien_lb << " new_lb: "<< total_inter <<" ";
|
|
total = total_inter;
|
|
}
|
|
|
|
else if ((pa.ContactType() == 2) // cas d'un contact par pénalisation
|
|
|| (pa.ContactType() == 3)|| (pa.ContactType() == 4)
|
|
)
|
|
// dans ce cas on considère uniquement le LB maxi
|
|
{ totalc = std::min(totalc,2*nbddl-1);
|
|
int total_inter = std::max(parstock.total, totalc);
|
|
if (total_inter > ancien_lb)
|
|
if ((ParaGlob::NiveauImpression() >= 5) && (totalc > total))
|
|
cout << "\n propositon d'augmentation de la largeur de bande pour les conditions de contact (en ddl) " << (totalc-total) << "old_lb: "<<ancien_lb << " new_lb: "<< total_inter << " ";
|
|
total = total_inter;
|
|
};
|
|
};
|
|
// on limite au nombres total de ddl
|
|
total = std::min(total,2*nbddl-1);
|
|
|
|
// on change la taille, si elle doit augmenter, ou si elle est inférieur d'au moins 5% par rapport à la taille actuelle
|
|
if ( (total > mat_mass->Nb_colonne()) ||
|
|
(total < 0.95 * mat_mass->Nb_colonne()))
|
|
// on change la taille
|
|
{ if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n augmentation effective: LB finale(en ddl) " << total << " ";
|
|
switch (enumatrice)
|
|
{ case BANDE_NON_SYMETRIQUE:
|
|
((MatBand*)mat_mass)->Change_taille(total,nbddl );
|
|
break;
|
|
case BANDE_NON_SYMETRIQUE_LAPACK:
|
|
((MatLapack*)mat_mass)->Change_taille(nbddl,total);
|
|
break;
|
|
|
|
default:
|
|
cout << "\n erreur2 non prevue Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite "<<endl;
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case CREUSE_COMPRESSEE_COLONNE :
|
|
{ cout << "\n *** cas avec contact non actuellement traite "
|
|
<< "\n Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
break;
|
|
}
|
|
default :
|
|
cout << "\nErreur : valeur incorrecte ou non implante du type de matrice retenue, type !\n"
|
|
<< " = " << enumatrice ;
|
|
cout << "\n Algori::Mise_a_jour_type_et_taille_matrice_masse_en_explicite(... ) \n";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
if (ParaGlob::NiveauImpression() >= 5)
|
|
cout << "\n stockage matrice masse " << enumatrice << " taille (entiers) :"
|
|
<< mat_mass->Place() << endl;
|
|
|
|
}; // fin changement matrice
|
|
|
|
|
|
};
|
|
|
|
if (ParaGlob::NiveauImpression() >= 7)
|
|
cout << "\n Taille du stockage masse " << mat_mass->Type_matrice() << " (taille en entiers) :"
|
|
<< mat_mass->Place() << endl;
|
|
// retour
|
|
if (change_stockage)
|
|
{return mat_mass;}
|
|
else {return NULL;};
|
|
};
|
|
|
|
// calcul la matrice de masse
|
|
// N_ddl : donne le ddl où doit être mis la masse
|
|
void Algori::Cal_matrice_masse(LesMaillages * lesMail,Assemblage& Ass
|
|
,Mat_abstraite& mat_mass
|
|
,const DiversStockage* divStoc,LesReferences* lesRef
|
|
,const Enum_ddl & N_ddl ,LesFonctions_nD* lesFonctionsnD)
|
|
{ bool use_diagonale = false; // par défaut on n'utilise pas de stockage diagonal
|
|
if ( (mat_mass.Type_matrice() == DIAGONALE)
|
|
|| (pa.Type_calcul_masse() == MASSE_DIAG_COEF_EGAUX)
|
|
|| (pa.Type_calcul_masse() == MASSE_DIAG_COEF_VAR)
|
|
)
|
|
{use_diagonale = true;}
|
|
else if ( (mat_mass.Type_matrice() == DIAGONALE)
|
|
&& (pa.Type_calcul_masse() == MASSE_CONSISTANTE)
|
|
)
|
|
{ cout << "\n *** erreur, le stockage globale est diagonale et on veut "
|
|
<< " egalement une matrice masse consistante !! c'est incoherent. ";
|
|
if (ParaGlob::NiveauImpression() > 5)
|
|
cout << "\n Algori::Cal_matrice_masse( ";
|
|
Sortie(1);
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
};
|
|
|
|
if (use_diagonale)
|
|
// on définit un vecteur identique à la diagonale si c'est la première fois
|
|
{ if (toto_masse == NULL)
|
|
toto_masse = new Vecteur(mat_mass.Nb_ligne());
|
|
else
|
|
// on initialise le vecteur
|
|
toto_masse->Zero();
|
|
};
|
|
// on initialise la matrice masse à 0
|
|
mat_mass.Initialise(0.);
|
|
|
|
// boucle sur les elements
|
|
for (int nbMail =1; nbMail<= lesMail->NbMaillage(); nbMail++)
|
|
for (int ne=1; ne<= lesMail->Nombre_element(nbMail);ne++)
|
|
{
|
|
//calcul de la matrice masse local
|
|
Element & el = lesMail->Element_LesMaille(nbMail,ne); // l'element
|
|
Tableau<Noeud *>& taN = el.Tab_noeud(); // tableau de noeuds de l'el
|
|
Mat_pleine * mat_mass_loc = el.CalculMatriceMasse (pa.Type_calcul_masse());
|
|
// cout << "numéro =" << ne << endl;
|
|
// mat_mass_loc->Affiche();
|
|
// mat_mass_loc->Affiche1(1,8,1,1,8,1);
|
|
// assemblage
|
|
// il faut distinguer si l'on a une matrice globale diagonale ou si l'on a une matrice pleine
|
|
// et ... il faut tenir compte du type de calcul de matrice masse locale
|
|
if (use_diagonale)
|
|
// if (mat_mass.Type_matrice() == DIAGONALE)
|
|
{ // récupération de la première ligne
|
|
Vecteur* vectloc = &(mat_mass_loc->Ligne_set(1)) ;
|
|
// ensuite on fait l'assemblage suivant un vecteur comme pour le second membre
|
|
Ass.AssemSM (*toto_masse,*vectloc,el.TableauDdl(),taN);
|
|
}
|
|
else // cas d'une matrice pleine, donc consistante
|
|
{ if (pa.Symetrie_matrice())
|
|
Ass.AssembMatSym (mat_mass,*mat_mass_loc,el.TableauDdl(),taN); // de la masse
|
|
else
|
|
Ass.AssembMatnonSym (mat_mass,*mat_mass_loc,el.TableauDdl(),taN); // de la masse
|
|
};
|
|
};
|
|
// ---- cas des masses concentrées -----
|
|
Ajout_masses_ponctuelles(lesMail,Ass,mat_mass,divStoc,lesRef,N_ddl,lesFonctionsnD);
|
|
// ---- fin cas des masses concentrées -----
|
|
|
|
|
|
// dans le cas où la masse est diagonale on transfert du vecteur assemblé à la matrice
|
|
// diagonale
|
|
if ((use_diagonale) && (mat_mass.Type_matrice() == DIAGONALE))
|
|
{ MatDiag & mat_d = *((MatDiag*) & mat_mass);
|
|
mat_d += (*toto_masse);
|
|
}
|
|
else if (use_diagonale)
|
|
{ // cas d'une matrice masse concentrée sur la diagonale, mais d'un stockage non diagonale
|
|
MatDiag mat_inter(mat_mass.Nb_ligne());
|
|
mat_inter = (*toto_masse);
|
|
mat_mass += mat_inter;
|
|
};
|
|
// sinon l'assemblage est déjà ok
|
|
|
|
// affichage éventuelle de la matrice de masse
|
|
if (ParaGlob::NiveauImpression() >= 10)
|
|
{ string entete = " affichage de la matrice masse ";
|
|
mat_mass.Affichage_ecran(entete);
|
|
};
|
|
};
|
|
|
|
|
|
// uniquement ajout dans la matrice de masse des masses ponctuelles si elles existent
|
|
// N_ddl : donne le ddl où doit être mis la masse
|
|
// par exemple, sert pour la relaxation dynamique
|
|
void Algori::Ajout_masses_ponctuelles(LesMaillages * lesMail,Assemblage& Ass,Mat_abstraite& mat_masse
|
|
,const DiversStockage* divStoc,LesReferences* lesRef
|
|
,const Enum_ddl & N_ddl,LesFonctions_nD* lesFonctionsnD)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la matrice du CPU 0 est concernée
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return ;
|
|
#endif
|
|
|
|
// prise en compte de masses ponctuelles
|
|
int dima = ParaGlob::Dimension();
|
|
// dans le cas où on est en axisymétrie il faut diminuer de 1
|
|
if (ParaGlob::AxiSymetrie())
|
|
dima--;
|
|
// int nbddl_X = mat_masse.Nb_ligne();
|
|
// ---- cas des masses concentrées -----
|
|
// on récupère les masses concentrées
|
|
const Tableau < BlocDdlLim<BlocScal_ou_fctnD> > & Tab_M_A = divStoc->TabMasseAddi();
|
|
int cas_assemblage = (Ass.Nb_cas_assemb()).n; // récup du cas d'assemblage
|
|
int posi = N_ddl -1;
|
|
// on balaie le tableau
|
|
int Tab_M_ATaille = Tab_M_A.Taille();
|
|
for (int i=1;i<= Tab_M_ATaille;i++)
|
|
{ // on récup la référence
|
|
const ReferenceNE & ref =
|
|
((ReferenceNE &) lesRef->Trouve(Tab_M_A(i).NomRef(),Tab_M_A(i).NomMaillage()));
|
|
|
|
// recup de la masse: soit c'est une valeur fixe soit une fonction nD
|
|
double val_mass = 0; // init par défaut
|
|
Fonction_nD * pt_fonct = NULL; // init
|
|
Coordonnee mass_noeu_differencie(dima);
|
|
int cas_masse = 0; // = 1 -> masse fixe sur tous les axes
|
|
// = 2 -> masse différenciée sur chaque axe
|
|
// = 0 -> n'a pas encore de valeur
|
|
string nom_fct_nD("_"); // ""
|
|
if ((Tab_M_A(i)).Val() != NULL) // cas d'une valeur fixe
|
|
{ val_mass = *((Tab_M_A(i)).Val()); // recup de la valeur
|
|
cas_masse = 1;
|
|
}
|
|
else if ((Tab_M_A(i)).Fct_nD() != NULL) // cas d'une fonction nD
|
|
{ nom_fct_nD = *((Tab_M_A(i)).Fct_nD());
|
|
// on récupère la fonction
|
|
if (lesFonctionsnD->Existe(nom_fct_nD))
|
|
{pt_fonct = lesFonctionsnD->Trouve(nom_fct_nD);
|
|
if (pt_fonct->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
|
|
{ // on vérifie qu'en retour on a un scalaire ou un vecteur de dima = la dima de l'espace
|
|
Tableau <double> & tava = pt_fonct->Valeur_pour_variables_globales(); // pour simplifier
|
|
if (pt_fonct->NbComposante() == 1)
|
|
{val_mass = tava(1);cas_masse=1;}
|
|
else if (pt_fonct->NbComposante() == dima)
|
|
{switch (dima)
|
|
{ case 3 : mass_noeu_differencie(3) = tava(3);
|
|
case 2 : mass_noeu_differencie(2) = tava(2);
|
|
case 1 : mass_noeu_differencie(1) = tava(1);
|
|
cas_masse=2;
|
|
};
|
|
}
|
|
else
|
|
{cout << "\n *** erreur en retour de l'utilisation d'une fonction nD avec grandeur(s) globale(s)"
|
|
<< " cas des masses ponctuelles sur la ref: "<< Tab_M_A(i).NomRef()
|
|
<< " en retour, le nombre de composante est different de 1 et la dimension de l'espace : "
|
|
<< dima << endl;
|
|
Sortie(1);
|
|
};
|
|
}; // fin du cas où la fonction ne dépend que de variables globales
|
|
}
|
|
else // sinon c'est un problème
|
|
{ cout << "\n *** erreur dans la definition des masses ponctuelles via la fonction nD "
|
|
<< nom_fct_nD << ", a priori cette fonction n'est pas disponible!! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else // sinon il y a un pb
|
|
{ cout << "\n *** erreur de definition des masses ponctuelles aux noeuds"
|
|
<< " les infos lues ne sont pas correctes: ";
|
|
(Tab_M_A(i)).Affiche();
|
|
Sortie(1);
|
|
};
|
|
|
|
// maintenant on va balayer les noeuds de la ref
|
|
int reftaille = ref.Taille();
|
|
// on boucle sur les noeuds de la référence
|
|
for (int nn =1; nn<= reftaille;nn++) // nn = position des num de noeud
|
|
{ Noeud & noe=lesMail->Noeud_LesMaille(ref.Nbmaille(),ref.Numero(nn));
|
|
if ((noe.Pointeur_assemblage(N_ddl,cas_assemblage) != -1)
|
|
&& (noe.En_service(N_ddl)) && (noe.UneVariable(N_ddl)))
|
|
{// les masses ponctuelles correspondent aux ddl N_ddl N_ddl+1 ...
|
|
switch (cas_masse)
|
|
{case 0: // il s'agit de l'utilisation d'une fonction nD qui ne doit dépendre que de M
|
|
{if ((pt_fonct->Depend_M() < 0) || (pt_fonct->Depend_Mt() < 0)
|
|
|| (pt_fonct->Depend_M0() < 0)
|
|
) // signifie que la fonction dépend exclusivement d'un des 3 temps: tdt, t ou 0
|
|
{ Coordonnee M(dima); // init
|
|
|
|
// on vérifie également qu'en retour on a un scalaire ou un vecteur de dimension = la dimension de l'espace
|
|
if ((pt_fonct->Depend_M()<0) && pt_fonct->Nom_variables().Taille() == dima)
|
|
M = noe.Coord2();
|
|
if ((pt_fonct->Depend_Mt()<0) && pt_fonct->Nom_variables().Taille() == dima)
|
|
M = noe.Coord1();
|
|
if ((pt_fonct->Depend_M0()<0) && pt_fonct->Nom_variables().Taille() == dima)
|
|
M = noe.Coord0();
|
|
|
|
// comme pt_fonct->Depend_M()<0, cela signifie que la fonction dépend que de M
|
|
// donc dans les paramètres d'appel on ne transmet que M
|
|
Tableau <Coordonnee> tab_M(1,M);
|
|
Tableau <double> & tava = pt_fonct->Val_FnD_Evoluee(NULL,&tab_M,NULL); // pour simplifier
|
|
if (pt_fonct->NbComposante() == 1)
|
|
{ double& val_masse_fct = tava(1);
|
|
for (int di=1;di<= dima;di++)
|
|
{ int pt_adres = noe.Pointeur_assemblage(Enum_ddl(posi+di),cas_assemblage);
|
|
mat_masse (pt_adres,pt_adres) += val_masse_fct;
|
|
};
|
|
}
|
|
else if (pt_fonct->NbComposante() == dima)
|
|
{ int pt_adres = noe.Pointeur_assemblage(Enum_ddl(posi),cas_assemblage);
|
|
|
|
|
|
switch (dima)
|
|
{ case 3 : mat_masse(pt_adres+3,pt_adres+3) += tava(3);
|
|
case 2 : mat_masse(pt_adres+2,pt_adres+2) += tava(2);
|
|
case 1 : mat_masse(pt_adres+1,pt_adres+1) += tava(1);
|
|
};
|
|
}
|
|
else
|
|
{cout << "\n *** erreur en retour de l'utilisation d'une fonction nD "
|
|
<< " cas des masses ponctuelles sur la ref: "<< Tab_M_A(i).NomRef()
|
|
<< " en retour, le nombre de composante: " << pt_fonct->NbComposante()
|
|
<< " est different de 1 ou de la dimension de l'espace : "
|
|
<< dima << endl;
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{cout << "\n *** erreur en retour de l'utilisation d'une fonction nD "
|
|
<< " cas des masses ponctuelles sur la ref: "<< Tab_M_A(i).NomRef()
|
|
<< " la fonction ne doit dependre que de M : valeur courante, ou a t "
|
|
<< " ou au temps initial "
|
|
<< dima ;
|
|
cout << "\n fonction nD: "; pt_fonct->Affiche();
|
|
Sortie(1);
|
|
};
|
|
}
|
|
break;
|
|
case 1: // la masse a déjà été déterminé, et elle est identique sur tous les axes
|
|
for (int di=1;di<= dima;di++)
|
|
{ int pt_adres = noe.Pointeur_assemblage(Enum_ddl(posi+di),cas_assemblage);
|
|
mat_masse(pt_adres,pt_adres) += val_mass;
|
|
};
|
|
break;
|
|
case 2: // la masse a déjà été déterminé, et elle est différentes sur tous les axes
|
|
for (int di=1;di<= dima;di++)
|
|
{ int pt_adres = noe.Pointeur_assemblage(Enum_ddl(posi+di),cas_assemblage);
|
|
mat_masse(pt_adres,pt_adres) += mass_noeu_differencie(di);
|
|
};
|
|
break;
|
|
default:
|
|
cout << "\n *** erreur dans l'ajout de masses ponctuelles "
|
|
<< " cas non prevu \n Algori::Ajout_masses_ponctuelles(...";
|
|
Sortie(1);
|
|
break;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
// ---- fin cas des masses concentrées -----
|
|
|
|
};
|
|
|
|
// définition de la matrice de viscosité numérique, dans le cas d'une approximation
|
|
// diagonale de la raideur, dans un calcul explicit
|
|
// la matrice masse doit être diagonale
|
|
// inita indique si l'on est dans une phase d'initialisation (creation de la matrice) ou non
|
|
// dans ce dernier cas il y a modification éventuelle des valeurs de C
|
|
// ramène un pointeur sur la matrice visqueuse instancié ou nul si aucune instantiation
|
|
Mat_abstraite* Algori::Cal_mat_visqueux_num_expli(const Mat_abstraite& mat_mass,Mat_abstraite* mat_C_pt
|
|
,const Vecteur & delta_X,bool inita, const Vecteur & vitesse)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la matrice du CPU 0 est concernée
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return mat_C_pt;
|
|
#endif
|
|
|
|
// on regarde s'il ne faut pas redimentionner la matrice:
|
|
// si inadéquation: on supprime la matrice C existante
|
|
if (inita)
|
|
{if (mat_C_pt != NULL)
|
|
{ if ((mat_mass.Type_matrice() != mat_C_pt->Type_matrice()) ||
|
|
(mat_mass.Nb_ligne() != mat_C_pt->Nb_ligne()))
|
|
delete mat_C_pt;
|
|
};
|
|
// maintenant création éventuelle
|
|
if (mat_C_pt == NULL)
|
|
{mat_C_pt = mat_mass.NouvelElement();}; // amortissement du même type que la masse
|
|
//idem avec la matrice de travail C_inter
|
|
if (C_inter != NULL)
|
|
{ if ((mat_mass.Type_matrice() != C_inter->Type_matrice()) ||
|
|
(mat_mass.Nb_ligne() != C_inter->Nb_ligne()))
|
|
delete C_inter;
|
|
};
|
|
// maintenant création éventuelle
|
|
if (C_inter == NULL)
|
|
C_inter = mat_mass.NouvelElement(); // amortissement du même type et de même valeur que la masse
|
|
// dimensionnement des forces int et ext mémorisée à l'itération précédente
|
|
F_int_tdt_prec.Change_taille(mat_C_pt->Nb_ligne());
|
|
F_ext_tdt_prec.Change_taille(mat_C_pt->Nb_ligne());
|
|
};
|
|
|
|
// on s'occupe maintenant des valeurs
|
|
switch (pa.Amort_visco_artificielle())
|
|
{case 1 : // cas d'un amortissement de Rayleigh classique
|
|
{if (inita)
|
|
{if ((ParaGlob::NiveauImpression() >= 0)&&((pa.CoefRayleighMasse()!= 1.)
|
|
||(pa.CoefRayleighRaideur()!=0.)))
|
|
{ cout << "\n ** ATTENTION : dans le cas d'un algorithme explicite avec un amortissement "
|
|
<< " de Rayleigh classique la matrice d'amortissement numerique [C] n'est construite"
|
|
<< " qu'avec la matrice masse selon : [C] = nu [M], ainsi le coefficient de"
|
|
<< " Rayleigh sur la raideur est impose a 0 et sur la masse a 1";
|
|
};
|
|
// on définit la matrice visqueuse en multipliant par la viscosité
|
|
(*mat_C_pt) = mat_mass; // assignation à la valeur de la masse
|
|
(*mat_C_pt) *= pa.Visco_artificielle();
|
|
};
|
|
break;
|
|
}
|
|
case 2 : // cas d'un amortissement en fonction de l'amortissement critique approché
|
|
// première méthode
|
|
{ if (inita)
|
|
{if (mat_mass.Type_matrice() != DIAGONALE)
|
|
{ cout << "\n erreur, la matrice masse doit etre diagonale ";
|
|
if (ParaGlob::NiveauImpression()>5)
|
|
cout << "\n Algori::Cal_mat_visqueux_num(...";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
}; // fin initialisation
|
|
|
|
// calcul des termes de la matrice visqueuse
|
|
MatDiag & m_masse = *((MatDiag*) & mat_mass);
|
|
MatDiag & m_C = *((MatDiag*) mat_C_pt);
|
|
int mtaille = m_masse.Nb_ligne();
|
|
double eta = pa.Visco_artificielle();
|
|
double coef_limite_C = pa.BorneMaxiSurCfonctionDeLaMasse();
|
|
for (int i=1;i<=mtaille;i++)
|
|
{ double deltaxi=delta_X(i);
|
|
if (Dabs(deltaxi) <= ConstMath::petit) deltaxi = ConstMath::petit;
|
|
double m_masseii=m_masse(i,i);
|
|
double m_Cii =2.*sqrt(Dabs(m_masseii *(F_int_tdt(i)-F_int_t(i)+F_ext_tdt(i)-F_ext_t(i))/deltaxi));
|
|
// on limite la valeur
|
|
if (m_Cii > coef_limite_C * m_masseii)
|
|
m_Cii = coef_limite_C * m_masseii;
|
|
m_C(i,i)=eta * m_Cii; // on définit directement chaque terme
|
|
};
|
|
break;
|
|
}
|
|
case 3 : // cas d'un amortissement en fonction de l'amortissement critique approché
|
|
// deuxième méthode à l'aide du quotient de Rayleight sur les forces internes
|
|
// C = eta * 2. sqrt(lambda_0) * M, avec lambda_0 = DX^T * (delta_F_int) / DX^T M DX
|
|
// le delta_F_int est supposé = K_tangent DX
|
|
{
|
|
// --- calcul des termes de la matrice visqueuse
|
|
// on ne modifie la valeur de la matrice visqueuse, que s'il y a eu un déplacement, sinon on garde la valeur précédament stockée
|
|
if (delta_X.Norme() > ConstMath::trespetit)
|
|
{ double lambda_0 = ((delta_X * F_int_tdt) - (delta_X * F_int_t)) / mat_mass.vectT_mat_vec(delta_X , delta_X );
|
|
(*mat_C_pt) = mat_mass; // assignation à la valeur de la masse
|
|
// prise en compte des limitations
|
|
double coef = 2. * sqrt(lambda_0);
|
|
double coef_limite_C = pa.BorneMaxiSurCfonctionDeLaMasse();
|
|
if (coef > coef_limite_C)
|
|
coef = coef_limite_C;
|
|
(*mat_C_pt) *= (pa.Visco_artificielle() * coef);
|
|
};
|
|
break;
|
|
}
|
|
// ----------------- cas de l'amortissement critique utilisé par exemple avec les algo de relaxation dynamique ----------------
|
|
case 4 :
|
|
CalculEnContinuMatriceViscositeCritique(mat_mass,*mat_C_pt,delta_X,vitesse);
|
|
break;
|
|
// dans les autres cas on ne fait rien
|
|
};
|
|
return mat_C_pt; // retour de la matrice
|
|
};
|
|
|
|
// mise à jour du calcul de la viscosité critique en continu
|
|
// on ajoute la viscosité critique ce qui permet de cumuler avec de la viscosité numérique
|
|
void Algori::CalculEnContinuMatriceViscositeCritique(const Mat_abstraite& mat_mass,Mat_abstraite& mat_C_pt
|
|
,const Vecteur & delta_X, const Vecteur & vitesse)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la matrice du CPU 0 est concernée
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return ;
|
|
#endif
|
|
|
|
// ---- on commence par calculer (omega_0)^2 qui représente la plus basse fréquence
|
|
double omega02=0.; // init
|
|
switch (opt_cal_C_critique)
|
|
{case -1 : // version test : c= 0
|
|
{ omega02 = 0.; // pas de prise en compte de viscosité
|
|
break;
|
|
};
|
|
case 0 : // utilisation d'une approximation d'un quotient de Rayleigh
|
|
// (omega_0)^2 \approx (dot X^T Delta R_{i(statique)}^n) / (dot X^T M dot X)
|
|
{ // on ne calcule que s'il y a eu une vitesse non nulle, sinon on ne fait rien
|
|
if (vitesse.Norme() > ConstMath::trespetit)
|
|
omega02 = -((vitesse * F_int_tdt) - (vitesse * F_int_t)
|
|
+ (vitesse * F_ext_tdt) - (vitesse * F_ext_t)) / mat_mass.vectT_mat_vec(vitesse , vitesse );
|
|
break;
|
|
};
|
|
case 1 : // utilisation d'une approximation d'un quotient de Rayleigh
|
|
// (omega_0)^2 \approx (Delta X^T Delta R_{i(statique)}^n) / (Delta X^T M Delta X)
|
|
{ // on ne calcule que s'il y a eu un déplacement, sinon on ne fait rien
|
|
if (delta_X.Norme() > ConstMath::trespetit)
|
|
omega02 = -((delta_X * F_int_tdt) - (delta_X * F_int_t)
|
|
+ (delta_X * F_ext_tdt) - (delta_X * F_ext_t)) / mat_mass.vectT_mat_vec(delta_X , delta_X );
|
|
break;
|
|
};
|
|
case 2 : // utilisation d'une approximation d'un quotient de Rayleigh
|
|
// (omega_0)^2 \approx (dot X^T Delta R_{i(statique)}^n) / (dot X^T M dot X)
|
|
{ // on ne calcule que s'il y a eu une vitesse non nulle, sinon on ne fait rien
|
|
if (vitesse.Norme() > ConstMath::trespetit)
|
|
omega02 = -((vitesse * F_int_tdt) - (vitesse * F_int_tdt_prec)
|
|
+ (vitesse * F_ext_tdt) - (vitesse * F_ext_tdt_prec)) / mat_mass.vectT_mat_vec(vitesse , vitesse );
|
|
break;
|
|
};
|
|
default :
|
|
cout << "*** erreur le cas du coefficient opt_cal_C_critique= " << opt_cal_C_critique
|
|
<< " n'est pas pris actuellement en compte car cela signifie qu'il n'est pas defini !!, "
|
|
<< "\n *** peut-etre revoir les pararametres de l'algorithme *** , "
|
|
<< "\n Algori::CalculEnContinuMatriceViscositeCritique(..." << endl;
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
// on regarde pour les limitations de la valeur de omega_0^2 et on en déduit la valeur d'omega0
|
|
double omega0 = 0.;
|
|
int nbcar = ParaGlob::NbdigdoEC();
|
|
|
|
//.... debug
|
|
if (ParaGlob::NiveauImpression() >= 8)
|
|
cout << "\n omega02= " << setprecision(nbcar)<< omega02
|
|
<< " llF_int_tdtll= " << setprecision(nbcar)<< F_int_tdt.Norme()
|
|
<< " llF_int_tll= " << setprecision(nbcar)<< F_int_t.Norme() << endl;
|
|
//.... fin debug
|
|
|
|
if (omega02 < 0.)
|
|
{ omega0 = 0.; }
|
|
else if (omega02 > (f_ * f_ * 4.))
|
|
{ omega0 = f_ * 2.; }
|
|
else { omega0 = sqrt(omega02);};
|
|
|
|
// ---- maintenant on calcul une viscosité critique globale
|
|
double viscosite = 0.;
|
|
switch (type_calcul_visqu_critique)
|
|
{ case 1: // cas de la méthode historique d'Underwood C_{ii} += c * M_{ii} et c = 2 * omega_0
|
|
{ viscosite = (omega0 * 2.);
|
|
break;
|
|
}
|
|
case 2: // Pajand: la matrice C est calculee selon: C_{ii} = c * M_{ii}, avec c = sqrt( 4*omega_0^2 - omega_0^4)
|
|
{ double coef = 4.* PUISSN(omega0, 2) - PUISSN(omega0, 4);
|
|
if (coef < 0.)
|
|
{ if (ParaGlob::NiveauImpression() > 7)
|
|
cout << "\n *** attention la grandeur ( 4*omega_0^2 - omega_0^4)= "
|
|
<< coef << " est negative, on la met a 0 ";
|
|
coef = 0.;
|
|
};
|
|
viscosite = sqrt(coef);
|
|
break;
|
|
}
|
|
case 3: // la matrice C est calculee selon: C_{ii} = c * M_{ii}, avec c = 2*sqrt(omega_0/(1+omega_0))
|
|
{ double coef = omega0/(1.+ omega0);
|
|
if (coef < 0.)
|
|
{ if (ParaGlob::NiveauImpression() > 7)
|
|
cout << "\n *** attention la grandeur omega_0/(1+omega_0)= "
|
|
<< coef << " est negative, on la met a 0 ";
|
|
coef = 0.;
|
|
}
|
|
viscosite = sqrt(coef);
|
|
break;
|
|
}
|
|
default:
|
|
{ cout << "\n **** erreur le cas type_calcul_visqu_critique= " << type_calcul_visqu_critique
|
|
<< " n'est pas pris actuellement en compte car cela signifie qu'il n'est pas defini !!, "
|
|
<< "\n *** peut-etre revoir les pararametres de l'algorithme *** , "
|
|
<< "\n Algori::CalculEnContinuMatriceViscositeCritique( ... ";
|
|
// dans le cas où un comptage du calcul est en cours on l'arrête
|
|
if (tempsCalEquilibre.Comptage_en_cours()) tempsCalEquilibre.Arret_du_comptage();
|
|
if (tempsInitialisation.Comptage_en_cours()) tempsInitialisation.Arret_du_comptage();
|
|
if (tempsMiseAjourAlgo.Comptage_en_cours()) tempsMiseAjourAlgo.Arret_du_comptage();
|
|
Sortie(1);
|
|
};
|
|
};
|
|
|
|
// affichage éventuelle de la viscosité
|
|
if (ParaGlob::NiveauImpression() >= 7)
|
|
{ cout << "\n viscosite c= " << setprecision(nbcar)<< viscosite << endl ;
|
|
cout << endl;
|
|
};
|
|
|
|
// ---- maintenant on va calculer la matrice visqueuse: C_{ii} += c * M_{ii}
|
|
|
|
//-- cas ou on cumulait, abandonné actuellement
|
|
// (*C_inter) = mat_mass;
|
|
// (*C_inter) *= viscosite * ampli_visco;
|
|
// mat_C_pt += (*C_inter);
|
|
//-- cas ou on cumulait, abandonné actuellement
|
|
|
|
|
|
mat_C_pt = mat_mass;
|
|
mat_C_pt *= viscosite * ampli_visco;
|
|
|
|
};
|
|
|
|
|
|
// calcul de l'impact d'une viscosité artificielle sur la raideur et sur le second membre
|
|
// l'algo travaille avec les vecteurs: delta_X, var_delta_X, et vitesse stockés dans Algori
|
|
// l'algo modifie mat_glob et calcul les forces visqueuses
|
|
void Algori::Cal_mat_visqueux_num_stat(Mat_abstraite& mat_glob,Vecteur& forces_vis_num)
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
// cas d'un calcul //, seule la matrice du CPU 0 est concernée
|
|
if (ParaGlob::Monde()->rank() != 0)
|
|
return ;
|
|
#endif
|
|
|
|
// le fonctionnement n'est pas identique au cas explicite
|
|
switch (pa.Amort_visco_artificielle())
|
|
{case 1 : // cas d'un amortissement de Rayleigh classique
|
|
{// ici on n'utilise que la matrice de raideur qui est la seule connue en statique
|
|
// K -> K*(1.-nu/delta_t)
|
|
// recup de l'incrément de temps
|
|
double deltat=ParaGlob::Variables_de_temps().IncreTempsCourant();
|
|
double unSurDeltat=0;
|
|
if (Abs(deltat) >= ConstMath::trespetit)
|
|
{unSurDeltat = 1./deltat;}
|
|
else
|
|
// si l'incrément de temps est tres petit on remplace 1/deltat par un nombre tres grand
|
|
{ // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb
|
|
if (unSurDeltat < 0)
|
|
{ cout << "\n le pas de temps est négatif !! "; };
|
|
unSurDeltat = ConstMath::tresgrand;
|
|
};
|
|
|
|
//CoefRayleighRaideur()
|
|
|
|
// on calcul les forces visqueuses
|
|
// ici il s'agit de force qui dépendent de la variation de delta_X d'une itération à l'autre
|
|
// cela ne doit pas être très stable mais ... à voir
|
|
// mais à convergence, les forces ne sont plus actives puisque var_delta_X = 0
|
|
mat_glob.Prod_mat_vec(
|
|
// ((-pa.Visco_artificielle()*unSurDeltat)*var_delta_X + (-pa.CoefRayleighRaideur()*unSurDeltat)*delta_X)
|
|
((pa.Visco_artificielle()*var_delta_X )+ (pa.CoefRayleighRaideur()*unSurDeltat)*delta_X)
|
|
,forces_vis_num);
|
|
// calcul de la nouvelle matrice de raideur qui tient compte des forces visqueuse
|
|
// mat_glob *= (1.+pa.Visco_artificielle()*unSurDeltat+pa.CoefRayleighRaideur()*unSurDeltat);
|
|
mat_glob *= (1.-pa.Visco_artificielle()-pa.CoefRayleighRaideur()*unSurDeltat);
|
|
break;
|
|
}
|
|
// dans les autres cas on ne fait rien
|
|
default:
|
|
if (ParaGlob::NiveauImpression()>0)
|
|
cout << "\n attention on cherche a utiliser de l'amortissement visqueux de type "
|
|
<< pa.Amort_visco_artificielle()
|
|
<< " celui-ci n'est pas disponible en statique, on n'en tient pas compte ! " << flush;
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|