// This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-2022 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . #include "Algori.h" #include "string" #include "MathUtil.h" #include // pour utiliser la classe istrstream #include // nouveau dans CW5.3 // -- la liste des algorithems actuellement disponibles#include "Projet.h" #include "AlgoriNonDyna.h" #include "ImpliNonDynaCont.h" #include "AlgoriFlambLineaire.h" #include "AlgoInformations.h" #include "AlgoUtils.h" #include "AlgoriDynaExpli.h" #include "AlgoriNewmark.h" #include "Algori_chung_lee.h" #include "AlgoriDynaExpli_zhai.h" #include "Algori_tchamwa.h" #include "AlgoUmatAbaqus.h" #include "AlgoRungeKutta.h" #include "AlgoBonelli.h" #include "Algori_relax_dyna.h" #include "AlgoriCombine.h" //-- fin liste algo #include "ReferenceNE.h" #include "ReferenceAF.h" // passage aux noeuds éventuellement des grandeurs globales, pour une sortie de post-traitement par exemple // mais pas seulement, c'est aussi utilisé pour récupérer des infos dans le contact avec le type 4 // le principe est que ce passage s'effectue si les conteneurs existent au niveau des noeuds void Algori::Passage_aux_noeuds_grandeurs_globales(LesMaillages * lesMail) { // on va boucler sur tous les grandeurs, mais on utilise le premier noeud actif pour savoir si // a priori le transfert est à faire int nb_maillage = lesMail->NbMaillage(); // récup du nombre de maillage List_io < TypeQuelconque >::iterator il,ilfin=listeVecGlob.end(); for (il=listeVecGlob.begin();il!=ilfin;il++) {TypeQuelconque& tq = (*il); TypeQuelconque_enum_etendu enuq = tq.EnuTypeQuelconque(); // l'enumeré du type Enum_ddl enuDdl = tq.Enum(); // de ddl associé definissant le point ou est calculé tq Noeud* noe=NULL; // on recherche un noeud où enuDdl est actif for (int imail=1;imail<=nb_maillage;imail++) {int nb_N = lesMail->Nombre_noeud(imail); for (int inoe=1;inoe<=nb_N;inoe++) if (lesMail->Noeud_LesMaille(imail,inoe).En_service(enuDdl)) {noe=&lesMail->Noeud_LesMaille(imail,inoe); break;}; // sort de la première boucle if (noe != NULL) break; // sortie de la boucle sur les maillages }; if (noe == NULL) // cela veut que la grandeur n'est pas active et donc pas à transférer break; // on sort de la boucle sur les grandeurs globales // arrivée ici la suite est spécifique à chaque grandeur switch (enuq.EnumTQ()) { case FORCE_GENE_EXT: lesMail->Quelconque_glob_vers_local(enuDdl,F_ext_tdt,tq); //debug //cout << "\n debug: Algori::Passage_aux_noeuds_grandeurs_globales "; //F_ext_tdt.Affiche(); //fin debug break; case FORCE_GENE_INT: lesMail->Quelconque_glob_vers_local(enuDdl,F_int_tdt,tq); break; case FORCE_GENE_TOT: F_totale_tdt.Change_taille(F_ext_tdt.Taille()); // au cas où F_totale_tdt = F_ext_tdt; F_totale_tdt += F_int_tdt; lesMail->Quelconque_glob_vers_local(enuDdl,F_totale_tdt,tq); break; case RESIDU_GLOBAL: lesMail->Quelconque_glob_vers_local(enuDdl,residu_final,tq); break; case DELTA_XI: lesMail->Quelconque_glob_vers_local(enuDdl,delta_X,tq); break; default: cout << "\n ** erreur, pour l'instant le transfert depuis global vers noeud de " << enuq.NomPlein() << " n'est pas implante ... le demander !! " << "\n Algori::Passage_aux_noeuds_grandeurs_globales(..."<Quelconque_glob_vers_local(X1,F_ext_t,typQ_gene_ext_t); lesMail->Quelconque_glob_vers_local(X1,F_int_t,typQ_gene_int_t); }; // passage aux noeuds éventuellement d'une grandeur globale particulière, // typeGeneriqu : indique le type de grandeur à passer // Le passage s'effectue si le conteneur existe au niveau des noeuds sinon erreur // seules les grandeurs globales qui n'ont pas été transférées par la méthode // Passage_aux_noeuds_grandeurs_globales , sont concernées void Algori::Passage_aux_noeuds_grandeur_globale_particuliere(const TypeQuelconque& typeGeneriqu, LesMaillages * lesMail) { TypeQuelconque_enum_etendu enuq = typeGeneriqu.EnuTypeQuelconque(); // l'enumeré du type Enum_ddl enuDdl = typeGeneriqu.Enum(); // de ddl associé definissant le point ou est calculé tq // arrivée ici la suite est spécifique à chaque grandeur switch (enuq.EnumTQ()) { case FORCE_GENE_EXT: lesMail->Quelconque_glob_vers_local(enuDdl,F_ext_tdt,typeGeneriqu); //debug //cout << "\n debug: Algori::Passage_aux_noeuds_grandeurs_globales "; //F_ext_tdt.Affiche(); //fin debug break; case FORCE_GENE_INT: lesMail->Quelconque_glob_vers_local(enuDdl,F_int_tdt,typeGeneriqu); break; case FORCE_GENE_TOT: F_totale_tdt.Change_taille(F_ext_tdt.Taille()); // au cas où F_totale_tdt = F_ext_tdt; F_totale_tdt += F_int_tdt; lesMail->Quelconque_glob_vers_local(enuDdl,F_totale_tdt,typeGeneriqu); break; case RESIDU_GLOBAL: lesMail->Quelconque_glob_vers_local(enuDdl,residu_final,typeGeneriqu); break; case DELTA_XI: lesMail->Quelconque_glob_vers_local(enuDdl,delta_X,typeGeneriqu); break; default: cout << "\n ** erreur, pour l'instant le transfert depuis global vers noeud de " << enuq.NomPlein() << " n'est pas implante ... le demander !! " << "\n Algori::Passage_aux_noeuds_grandeur_globale(..."<& liQuel = varExpor->List_noeud_type_quelconque(); List_io ::const_iterator it,itfin=liQuel.end(); for (it = liQuel.begin(); it!=itfin;it++) { const TypeQuelconque_enum_etendu& ty = (*it).Quelc_const(); // la grandeur constante switch (ty.EnumTQ()) { case FORCE_GENE_EXT: {// récup de la reférence const ReferenceNE & ref = ((ReferenceNE &) lesRef.Trouve((*it).Ref_const(),&(*it).Nom_mail_const())); int ne = ref.Numero(1); // le num du noeud: uniquement le premier // int ne = (*it).Num_NE_const(); // le num du noeud int nmail = 1; if ((*it).Nom_mail_const() != "") nmail = lesMail->NumMaillage((*it).Nom_mail_const()); // num du maillage // recup du noeud Noeud * noo = & lesMail->Noeud_LesMaille(nmail,ne); // si le noeud n'est pas actif pour ce ddl, on ne continue pas if (noo->Existe_ici(X1)) // ellimine les noeuds non concernés // ** en fait cela pourrait changer pour la thermique pure, mais pour l'instant ce n'est // pas pris en compte, a voir si on veut les forces généralisées associées à de la thermique pure {if ((noo->Existe_ici(ty)) && (noo->En_service(X1))) {// FORCE_GENE_EXT est associé au type coordonnée TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(ty); // récup du conteneur du noeud // récup de la grandeur Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées int iglob = noo->Pointeur_assemblage(X1,nb_casAssemb.n); #ifdef MISE_AU_POINT if ( iglob == -1 ) { cout << "\nErreur : ddl " << X1 << " inexistant pour le cas de charge " << nb_casAssemb.n << '\n' << "Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(\n"; Sortie(1); }; #endif switch (dim) // on rempli les coordonnées { case 3: conoe(3)=F_ext_tdt(iglob+2); case 2: conoe(2)=F_ext_tdt(iglob+1); case 1: conoe(1)=F_ext_tdt(iglob); }; }; }; break; } case FORCE_GENE_INT: {// récup de la reférence const ReferenceNE & ref = ((ReferenceNE &) lesRef.Trouve((*it).Ref_const(),&(*it).Nom_mail_const())); int ne = ref.Numero(1); // le num du noeud: uniquement le premier // int ne = (*it).Num_NE_const(); // le num du noeud int nmail = 1; if ((*it).Nom_mail_const() != "") nmail = lesMail->NumMaillage((*it).Nom_mail_const()); // num du maillage // recup du noeud Noeud * noo = & lesMail->Noeud_LesMaille(nmail,ne); // le type FORCE_GENE_INT est associé au ddl X1 // si le noeud n'est pas actif pour ce ddl, on ne continue pas if (noo->Existe_ici(X1)) // ellimine les noeuds non concernés // ** en fait cela pourrait changer pour la thermique pure, mais pour l'instant ce n'est // pas pris en compte, a voir si on veut les forces généralisées associées à de la thermique pure {if ((noo->Existe_ici(ty)) && (noo->En_service(X1))) {// FORCE_GENE_INT est associé au type coordonnée TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(ty); // récup du conteneur du noeud // récup de la grandeur Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées int iglob = noo->Pointeur_assemblage(X1,nb_casAssemb.n); #ifdef MISE_AU_POINT if ( iglob == -1 ) { cout << "\nErreur : ddl " << X1 << " inexistant pour le cas de charge " << nb_casAssemb.n << '\n' << "Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(\n"; Sortie(1); }; #endif switch (dim) // on rempli les coordonnées { case 3: conoe(3)=F_int_tdt(iglob+2); case 2: conoe(2)=F_int_tdt(iglob+1); case 1: conoe(1)=F_int_tdt(iglob); }; }; }; break; } case FORCE_GENE_TOT: {// récup de la reférence const ReferenceNE & ref = ((ReferenceNE &) lesRef.Trouve((*it).Ref_const(),&(*it).Nom_mail_const())); int ne = ref.Numero(1); // le num du noeud: uniquement le premier //int ne = (*it).Num_NE_const(); // le num du noeud int nmail = 1; if ((*it).Nom_mail_const() != "") nmail = lesMail->NumMaillage((*it).Nom_mail_const()); // num du maillage // recup du noeud Noeud * noo = & lesMail->Noeud_LesMaille(nmail,ne); // le type FORCE_GENE_TOT est associé au ddl X1 // si le noeud n'est pas actif pour ce ddl, on ne continue pas if (noo->Existe_ici(X1)) // ellimine les noeuds non concernés // ** en fait cela pourrait changer pour la thermique pure, mais pour l'instant ce n'est // pas pris en compte, a voir si on veut les forces généralisées associées à de la thermique pure {if ((noo->Existe_ici(ty)) && (noo->En_service(X1))) {// FORCE_GENE_TOT est associé au type coordonnée TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(ty); // récup du conteneur du noeud // récup de la grandeur Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées int iglob = noo->Pointeur_assemblage(X1,nb_casAssemb.n); #ifdef MISE_AU_POINT if ( iglob == -1 ) { cout << "\nErreur : ddl " << X1 << " inexistant pour le cas de charge " << nb_casAssemb.n << '\n' << "Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(\n"; Sortie(1); }; #endif switch (dim) // on rempli les coordonnées { case 3: conoe(3)=F_int_tdt(iglob+2)+F_ext_tdt(iglob+2); case 2: conoe(2)=F_int_tdt(iglob+1)+F_ext_tdt(iglob+1); case 1: conoe(1)=F_int_tdt(iglob)+F_ext_tdt(iglob); }; }; }; break; } case RESIDU_GLOBAL: {// récup de la reférence const ReferenceNE & ref = ((ReferenceNE &) lesRef.Trouve((*it).Ref_const(),&(*it).Nom_mail_const())); int ne = ref.Numero(1); // le num du noeud: uniquement le premier // int ne = (*it).Num_NE_const(); // le num du noeud int nmail = 1; if ((*it).Nom_mail_const() != "") nmail = lesMail->NumMaillage((*it).Nom_mail_const()); // num du maillage // recup du noeud Noeud * noo = & lesMail->Noeud_LesMaille(nmail,ne); // le type RESIDU_GLOBAL est associé au ddl X1 // si le noeud n'est pas actif pour ce ddl, on ne continue pas if (noo->Existe_ici(X1)) // ellimine les noeuds non concernés // ** en fait cela pourrait changer pour la thermique pure, mais pour l'instant ce n'est // pas pris en compte, a voir si on veut les forces généralisées associées à de la thermique pure {if ((noo->Existe_ici(ty)) && (noo->En_service(X1))) {// RESIDU_GLOBAL est associé au type coordonnée TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(ty); // récup du conteneur du noeud // récup de la grandeur Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées int iglob = noo->Pointeur_assemblage(X1,nb_casAssemb.n); #ifdef MISE_AU_POINT if ( iglob == -1 ) { cout << "\nErreur : ddl " << X1 << " inexistant pour le cas de charge " << nb_casAssemb.n << '\n' << "Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(\n"; Sortie(1); }; #endif switch (dim) // on rempli les coordonnées { case 3: conoe(3)=residu_final(iglob+2); case 2: conoe(2)=residu_final(iglob+1); case 1: conoe(1)=residu_final(iglob); }; }; }; break; } case DELTA_XI: {// récup de la reférence const ReferenceNE & ref = ((ReferenceNE &) lesRef.Trouve((*it).Ref_const(),&(*it).Nom_mail_const())); int ne = ref.Numero(1); // le num du noeud: uniquement le premier //int ne = (*it).Num_NE_const(); // le num du noeud int nmail = 1; if ((*it).Nom_mail_const() != "") nmail = lesMail->NumMaillage((*it).Nom_mail_const()); // num du maillage // recup du noeud Noeud * noo = & lesMail->Noeud_LesMaille(nmail,ne); // le type DELTA_XI est associé au ddl X1 // si le noeud n'est pas actif pour ce ddl, on ne continue pas if (noo->Existe_ici(X1)) // ellimine les noeuds non concernés // ** en fait cela pourrait changer pour la thermique pure, mais pour l'instant ce n'est // pas pris en compte, a voir si on veut les forces généralisées associées à de la thermique pure {if ((noo->Existe_ici(ty)) && (noo->En_service(X1))) {// DELTA_XI est associé au type coordonnée TypeQuelconque& typQ = noo->ModifGrandeur_quelconque(ty); // récup du conteneur du noeud // récup de la grandeur Grandeur_coordonnee* gcoor = (Grandeur_coordonnee*) typQ.Grandeur_pointee(); Coordonnee& conoe = *(gcoor->ConteneurCoordonnee()); // les coordonnées int iglob = noo->Pointeur_assemblage(X1,nb_casAssemb.n); #ifdef MISE_AU_POINT if ( iglob == -1 ) { cout << "\nErreur : ddl " << X1 << " inexistant pour le cas de charge " << nb_casAssemb.n << '\n' << "Algori::Passage_de_grandeurs_globales_vers_noeuds_pour_variables_globales(\n"; Sortie(1); }; #endif switch (dim) // on rempli les coordonnées { case 3: conoe(3)=delta_X(iglob+2); case 2: conoe(2)=delta_X(iglob+1); case 1: conoe(1)=delta_X(iglob); }; }; }; break; } default: // on ne fait rien break; }; }; }; // //------- 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 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 // méthode qui sert au transfert entre les variables "Temps_CPU_HZpp" et le tableau "lesTempsCpu" // et qui doit-être appelé avant l'utilisation du tableau via listeVarGlob par exemple void Algori::Temps_CPU_HZpp_to_lesTempsCpu (const LesCondLim& lesCondLim, const Charge& charge, const LesContacts& contact) { lesTempsCpu(1)(1)=tempsInitialisation.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(1)(2)=tempsInitialisation.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(1)(3)=tempsInitialisation.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(2)(1)=tempsMiseAjourAlgo.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(2)(2)=tempsMiseAjourAlgo.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(2)(3)=tempsMiseAjourAlgo.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(3)(1)=tempsCalEquilibre.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(3)(2)=tempsCalEquilibre.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(3)(3)=tempsCalEquilibre.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(4)(1)=tempsRaidSmEner.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(4)(2)=tempsRaidSmEner.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(4)(3)=tempsRaidSmEner.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(5)(1)=tempsSecondMembreEnerg.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(5)(2)=tempsSecondMembreEnerg.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(5)(3)=tempsSecondMembreEnerg.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(6)(1)=tempsResolSystemLineaire.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(6)(2)=tempsResolSystemLineaire.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(6)(3)=tempsResolSystemLineaire.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(7)(1)=tempsSauvegarde.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(7)(2)=tempsSauvegarde.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(7)(3)=tempsSauvegarde.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(8)(1)=tempsSortieFilCalcul.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(8)(2)=tempsSortieFilCalcul.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(8)(3)=tempsSortieFilCalcul.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(9)(1)=tempsRaidSmEnerContact.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(9)(2)=tempsRaidSmEnerContact.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(9)(3)=tempsRaidSmEnerContact.Temps_CPU_System(); // conversion de long long en double lesTempsCpu(10)(1)=tempsSecondMembreEnergContact.Temps_CPU_User(); // conversion de long long en double // lesTempsCpu(10)(2)=tempsSecondMembreEnergContact.Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(10)(3)=tempsSecondMembreEnergContact.Temps_CPU_System(); // conversion de long long en double // pour les temps cpu relatifs aux CL et CLL, on les récupères temps_CL=lesCondLim.Temps_cpu_CL(); lesTempsCpu(11)(1)=temps_CL.Temps_CPU_User(); // lesTempsCpu(11)(2)=lesCondLim.Temps_cpu_CL().Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(11)(3)=lesCondLim.Temps_cpu_CL().Temps_CPU_System(); // conversion de long long en double temps_CLL=lesCondLim.Temps_cpu_CLL(); lesTempsCpu(12)(1)=temps_CLL.Temps_CPU_User(); // lesTempsCpu(12)(2)=lesCondLim.Temps_cpu_CLL().Temps_CPU_Reel(); // conversion de long long en double // lesTempsCpu(12)(3)=lesCondLim.Temps_cpu_CLL().Temps_CPU_System(); // conversion de long long en double lesTempsCpu(13)(1)=temps_lois_comportement.Temps_CPU_User(); lesTempsCpu(14)(1)=temps_metrique_K_SM.Temps_CPU_User(); temps_chargement = charge.Temps_cpu_chargement(); lesTempsCpu(15)(1)= temps_chargement.Temps_CPU_User(); temps_rech_contact = contact.Temps_cpu_Contact(); lesTempsCpu(16)(1)= temps_rech_contact.Temps_CPU_User(); #ifdef UTILISATION_MPI lesTempsCpu(17)(1)= temps_transfert_court.Temps_CPU_User(); lesTempsCpu(19)(1)= temps_transfert_long.Temps_CPU_User(); lesTempsCpu(18)(1)= temps_attente.Temps_CPU_User(); #endif }; // idem la méthode de transfert si-dessus mais concerne uniquement les temps internes à l'algo // ajoute au tableau passé en paramètre, les temps de l'algo Tableau & Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(Tableau & lesTsCpu) { // test éventuel de la taille du tableau #ifdef MISE_AU_POINT if (lesTsCpu.Taille() != 10) {cout << "\n erreur de dim de tableau: dim lesTsCpu= " << lesTsCpu.Taille() << " au lieu de 10 !! " << "\n Algori::Ajout_Temps_CPU_HZpp_to_lesTempsCpu(... " ; Sortie(1); }; #endif // on stocke les infos lesTsCpu(1) += tempsInitialisation; // conversion de long long en double lesTsCpu(2) += tempsMiseAjourAlgo; // conversion de long long en double lesTsCpu(3) += tempsCalEquilibre; // conversion de long long en double lesTsCpu(4) += tempsRaidSmEner; // conversion de long long en double lesTsCpu(5) += tempsSecondMembreEnerg; // conversion de long long en double lesTsCpu(6) += tempsResolSystemLineaire; // conversion de long long en double lesTsCpu(7) += tempsSauvegarde; // conversion de long long en double lesTsCpu(8) += tempsSortieFilCalcul; // conversion de long long en double lesTsCpu(9) += tempsRaidSmEnerContact; // conversion de long long en double lesTsCpu(10) += tempsSecondMembreEnergContact; // conversion de long long en double #ifdef UTILISATION_MPI lesTsCpu(17) += temps_transfert_court; lesTsCpu(19) += temps_transfert_long; lesTsCpu(18) += temps_attente; #endif // retour return lesTsCpu; }; // une méthode qui a pour objectif de terminer tous les comptages, utile // dans le cas d'un arrêt impromptu void Algori::Arret_du_comptage_CPU() { tempsInitialisation.Arret_du_comptage(); tempsMiseAjourAlgo.Arret_du_comptage(); tempsCalEquilibre.Arret_du_comptage(); tempsRaidSmEner.Arret_du_comptage(); tempsSecondMembreEnerg.Arret_du_comptage(); tempsResolSystemLineaire.Arret_du_comptage(); tempsSauvegarde.Arret_du_comptage(); tempsSortieFilCalcul.Arret_du_comptage(); tempsRaidSmEnerContact.Arret_du_comptage(); tempsSecondMembreEnergContact.Arret_du_comptage(); temps_CL.Arret_du_comptage(); temps_CLL.Arret_du_comptage(); temps_lois_comportement.Arret_du_comptage(); temps_metrique_K_SM.Arret_du_comptage(); temps_chargement.Arret_du_comptage(); temps_rech_contact.Arret_du_comptage(); #ifdef UTILISATION_MPI temps_transfert_court.Arret_du_comptage(); temps_transfert_long.Arret_du_comptage(); temps_attente.Arret_du_comptage(); #endif }; // sortie sur fichier des temps cpu void Algori::Sortie_temps_cpu(const LesCondLim& lesCondLim , const Charge& charge,const LesContacts & contact) { // la petite méthode qui sert au transfert et qui doit-être appelé avant les sorties Temps_CPU_HZpp_to_lesTempsCpu(lesCondLim,charge,contact); // on récupère le fichier des temps cpu entreePrinc->Ouverture_fichier_temps_cpu(); // ouverture au cas où // récupération du fichier des temps cpu ofstream & sort_cpu = entreePrinc->Sort_temps_cpu(); // on concatène la totalité pour ensuite sortir également des pourcentage double total_cpu = tempsInitialisation.Temps_CPU_User(); total_cpu += tempsMiseAjourAlgo.Temps_CPU_User(); total_cpu += tempsCalEquilibre.Temps_CPU_User(); // total_cpu += tempsRaidSmEner.Temps_CPU_User(); // total_cpu += tempsSecondMembreEnerg.Temps_CPU_User(); // total_cpu += tempsResolSystemLineaire.Temps_CPU_User(); total_cpu += tempsSauvegarde.Temps_CPU_User(); total_cpu += tempsSortieFilCalcul.Temps_CPU_User(); // total_cpu += tempsRaidSmEnerContact.Temps_CPU_User(); // total_cpu += tempsSecondMembreEnergContact.Temps_CPU_User(); // total_cpu += temps_CL.Temps_CPU_User(); // total_cpu += temps_CLL.Temps_CPU_User(); // total_cpu += temps_lois_comportement.Temps_CPU_User(); // total_cpu += temps_metrique_K_SM.Temps_CPU_User(); // il ne faut pas ajouter la métrique // total_cpu += temps_chargement.Temps_CPU_User(); // total_cpu += temps_rech_contact.Temps_CPU_User(); int nbdigit = 6; // pour le pourcentage // int nbdigit_temps = 14; // pour les temps // écriture des temps cpu de l'algo: sort_cpu << "\n=========================================================================="; #ifndef UTILISATION_MPI sort_cpu << "\n Herezh++ : bilan temps cpu pour l'algorithme: " << Nom_TypeCalcul(TypeDeCalcul());; #else sort_cpu << "\n Herezh++ : (CPU "<< ParaGlob::Monde()->rank() << ") bilan temps cpu pour l'algorithme: " << Nom_TypeCalcul(TypeDeCalcul());; #endif sort_cpu << "\n==========================================================================\n"; // puis affichage de la version ParaGlob::Sortie_Version(sort_cpu); #ifndef MISE_AU_POINT sort_cpu << " (version la plus rapide )"; #endif #ifdef MISE_AU_POINT sort_cpu << " (version avec le plus de verifications pendant le calcul et les I/O ) "; #endif sort_cpu << "\n \n --------------- temps_locaux_cpu_en_milliseconde: ---------"; sort_cpu << fixed; sort_cpu.precision(2); // pour éviter de faire une division par 0 total_cpu = MaX(ConstMath::trespetit, total_cpu); sort_cpu << "\n ---> tps_total_algo " << "("<< std::setw(nbdigit) << total_cpu/1000. << " ) "; sort_cpu << "\n tps_InitAlgo " << "("<< std::setw(nbdigit) << (100*tempsInitialisation.Temps_CPU_User()/total_cpu) << " % ) " << tempsInitialisation.Temps_CPU_User_milli(); sort_cpu << "\n tps_MiseAJourAlgo " << "("<< std::setw(nbdigit) << (100*tempsMiseAjourAlgo.Temps_CPU_User()/total_cpu) << " % ) " << tempsMiseAjourAlgo.Temps_CPU_User_milli(); sort_cpu << "\n tps_CalEquilibre " << "("<< std::setw(nbdigit) << (100*tempsCalEquilibre.Temps_CPU_User()/total_cpu) << " % ) " << tempsCalEquilibre.Temps_CPU_User_milli() ; sort_cpu << "\n tps_MatSmLoc " << ".("<< std::setw(nbdigit) << (100*tempsRaidSmEner.Temps_CPU_User()/total_cpu) << " % ) " << tempsRaidSmEner.Temps_CPU_User_milli() ; sort_cpu << "\n tps_SmLoc " << ".("<< std::setw(nbdigit) << (100*tempsSecondMembreEnerg.Temps_CPU_User()/total_cpu) << " % ) " << tempsSecondMembreEnerg.Temps_CPU_User_milli() ; sort_cpu << "\n tps_lois_comp " << "..("<< std::setw(nbdigit) << (100*temps_lois_comportement.Temps_CPU_User()/total_cpu) << " % ) " << temps_lois_comportement.Temps_CPU_User_milli() ; sort_cpu << "\n tps_metrique_KSM " << "...("<< std::setw(nbdigit) << (100*temps_metrique_K_SM.Temps_CPU_User()/total_cpu) << " % ) " << temps_metrique_K_SM.Temps_CPU_User_milli() ; sort_cpu << "\n tps_chargement " << ".("<< std::setw(nbdigit) << (100*temps_chargement.Temps_CPU_User()/total_cpu) << " % ) " << temps_chargement.Temps_CPU_User_milli() ; sort_cpu << "\n tps_rech_contact " << ".("<< std::setw(nbdigit) << (100*temps_rech_contact.Temps_CPU_User()/total_cpu) << " % ) " << temps_rech_contact.Temps_CPU_User_milli() ; sort_cpu << "\n tps_contactMatSmLoc " << ".("<< std::setw(nbdigit) << (100*tempsRaidSmEnerContact.Temps_CPU_User()/total_cpu) << " % ) " << tempsRaidSmEnerContact.Temps_CPU_User_milli() ; sort_cpu << "\n tps_contactSmLoc " << ".("<< std::setw(nbdigit) << (100*tempsSecondMembreEnergContact.Temps_CPU_User()/total_cpu) << " % ) " << tempsSecondMembreEnergContact.Temps_CPU_User_milli() ; sort_cpu << "\n tps_CL " << ".("<< std::setw(nbdigit) << (100*temps_CL.Temps_CPU_User()/total_cpu) << " % ) " << temps_CL.Temps_CPU_User_milli() ; sort_cpu << "\n tps_CLL " << ".("<< std::setw(nbdigit) << (100*temps_CLL.Temps_CPU_User()/total_cpu) << " % ) " << temps_CLL.Temps_CPU_User_milli() ; sort_cpu << "\n tps_ResSystLineaire " << "("<< std::setw(nbdigit) << (100*tempsResolSystemLineaire.Temps_CPU_User()/total_cpu) << " % ) " << tempsResolSystemLineaire.Temps_CPU_User_milli() ; sort_cpu << "\n tps_Sauvegarde " << "("<< std::setw(nbdigit) << (100*tempsSauvegarde.Temps_CPU_User()/total_cpu) << " % ) " << tempsSauvegarde.Temps_CPU_User_milli() ; sort_cpu << "\n tps_SortieFilCalcul " << "("<< std::setw(nbdigit) << (100*tempsSortieFilCalcul.Temps_CPU_User()/total_cpu) << " % ) " << tempsSortieFilCalcul.Temps_CPU_User_milli() ; #ifdef UTILISATION_MPI sort_cpu << "\n tps__transfert_cour_inter_cpu " << "("<< std::setw(nbdigit) << (100*temps_transfert_court.Temps_CPU_User()/total_cpu) << " % ) " << temps_transfert_court.Temps_CPU_User_milli() ; sort_cpu << "\n tps__transfert_long_inter_cpu " << "("<< std::setw(nbdigit) << (100*temps_transfert_long.Temps_CPU_User()/total_cpu) << " % ) " << temps_transfert_long.Temps_CPU_User_milli() ; sort_cpu << "\n tps__attente_inter_cpu " << "("<< std::setw(nbdigit) << (100*temps_attente.Temps_CPU_User()/total_cpu) << " % ) " << temps_attente.Temps_CPU_User_milli() ; #endif sort_cpu << "\n"; }; // mise à jour qui sont gérées par la classe mère algo // a priori que des choses génériques du type gestion des variables privées void Algori::MiseAJourAlgoMere(ParaGlob * paraGlob,LesMaillages * lesMail,LesReferences* lesRef ,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD ,VariablesExporter* varExpor ,LesLoisDeComp* lesLoisDeComp,DiversStockage* diversStockage ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts ,Resultats* resultats) { // ---------- on initialise les conteneurs quelconques pour varExpor varExpor->InitialisationConteneursQuelconques(*lesMail,listeVecGlob,*lesRef); // -- 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; }; }; }; // on récupère éventuellement la modulation de précision if (nom_modulation_precision.length()) {modulation_precision = lesFonctionsnD->Trouve(nom_modulation_precision); if (modulation_precision->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales {// on vérifie qu'en retour on a un scalaire modulation_precision->Valeur_pour_variables_globales(); // pour simplifier if (modulation_precision->NbComposante() != 1) {cout << "\n *** erreur parametre algorithme: la fonction nD " << nom_modulation_precision << " de modulation de la precision d'equilibre globale " << " ne retourne pas un scalaire unique !! a priori ce n'est pas correct "; Sortie(1); }; } else {cout << "\n *** erreur parametre algorithme: la fonction nD " << nom_modulation_precision << " de modulation de la precision d'equilibre globale " << " utilise des variables autres que globales, ce n'est pas possible ! "; Sortie(1); }; }; // on récupère éventuellement la fonction nD définissant la norme if (pa.Norme().nom1 == "fonction_nD:") {fct_norme = lesFonctionsnD->Trouve(pa.Norme().nom2); if (fct_norme->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales {// on vérifie qu'en retour on a un scalaire fct_norme->Valeur_pour_variables_globales(); // pour simplifier if (fct_norme->NbComposante() != 1) {cout << "\n *** erreur parametre algorithme: la fonction nD " << pa.Norme().nom2 << " de definition de la norme de convergence d'equilibre globale " << " ne retourne pas un scalaire unique !! a priori ce n'est pas correct "; Sortie(1); }; } else {cout << "\n *** erreur parametre algorithme: la fonction nD " << pa.Norme().nom2 << " de definition de la norme de convergence d'equilibre globale " << " utilise des variables autres que globales, ce n'est pas possible ! "; Sortie(1); }; }; // on récupère éventuellement la fonction correspondant à nom_fct_nD_inter_nb_entre_relax if (nom_fct_nD_inter_nb_entre_relax.length()) {fct_nD_inter_nb_entre_relax = lesFonctionsnD->Trouve(nom_fct_nD_inter_nb_entre_relax); if (fct_nD_inter_nb_entre_relax->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales {// on vérifie qu'en retour on a un scalaire fct_nD_inter_nb_entre_relax->Valeur_pour_variables_globales(); // pour simplifier if (fct_nD_inter_nb_entre_relax->NbComposante() != 1) {cout << "\n *** erreur parametre algorithme: la fonction nD " << nom_fct_nD_inter_nb_entre_relax << " qui permet de cacluler la valeur du parametre inter_nb_entre_relax " << " ne retourne pas un scalaire unique !! a priori ce n'est pas correct "; Sortie(1); }; } else {cout << "\n *** erreur parametre algorithme: la fonction nD " << nom_fct_nD_inter_nb_entre_relax << " qui permet de cacluler la valeur du parametre inter_nb_entre_relax " << " utilise des variables autres que globales, ce n'est pas possible ! "; Sortie(1); }; }; // on met à jour les repères d'anisotropie éventuelle lesMail->Mise_a_jour_repere_anisotropie(diversStockage,lesFonctionsnD); // on introduit au niveau des noeuds, si cela n'est pas déjà fait // les conteneurs pour les forces internes et externes à t {// def d'un type générique, utilisé pour le transfert des forces internes, vers les conteneurs noeuds Coordonnee coor(ParaGlob::Dimension()); // un type coordonnee typique Grandeur_coordonnee gt(coor); // une grandeur typique de type Grandeur_coordonnee // def d'un type quelconque représentatif pour un vecteur force à chaque noeud TypeQuelconque typQ_gene_int(FORCE_GENE_INT_t,X1,gt); lesMail->AjoutConteneurAuNoeud(typQ_gene_int); TypeQuelconque typQ_gene_ext(FORCE_GENE_EXT_t,X1,gt); lesMail->AjoutConteneurAuNoeud(typQ_gene_ext); }; // on initialise certaines énergies qui sont stockées au niveau de l'algo // mais qui sont en fait indépendantes de l'algo, donc il faut que ces énergies soient à jour // elles sont donc initialisées à partir des grandeurs globales qui elles mêmes ont été mise à jour // l'objectif est d'éviter une initialisation par défaut à 0 lorsque l'algo fait suite à un autre algo // du coup, avant tout calcul du nouvel algo, on utilise les grandeurs déjà calculées par le précédent algo // // --- cas des énergies internes venants des lois de comportement : // ENERGIE_ELASTIQUE,ENERGIE_PLASTIQUE,ENERGIE_VISQUEUSE, {{void* pt_void = ParaGlob::param->Mise_a_jour_grandeur_consultable(ENERGIE_ELASTIQUE); TypeQuelconque* pt_quelc = (TypeQuelconque*) pt_void; Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) pt_quelc->Grandeur_pointee()); // pour simplifier energTotal.ChangeEnergieElastique(*(gr.ConteneurDouble())) ; }; {void* pt_void = ParaGlob::param->Mise_a_jour_grandeur_consultable(ENERGIE_PLASTIQUE); TypeQuelconque* pt_quelc = (TypeQuelconque*) pt_void; Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) pt_quelc->Grandeur_pointee()); // pour simplifier energTotal.ChangeDissipationPlastique( *(gr.ConteneurDouble()) ); }; {void* pt_void = ParaGlob::param->Mise_a_jour_grandeur_consultable(ENERGIE_VISQUEUSE); TypeQuelconque* pt_quelc = (TypeQuelconque*) pt_void; Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) pt_quelc->Grandeur_pointee()); // pour simplifier energTotal.ChangeDissipationVisqueuse(*(gr.ConteneurDouble())); }; }; // --- cas des énergies de contact : // ENERGIE_PENALISATION,ENERGIE_FROT_ELAST,ENERGIE_FROT_PLAST,ENERGIE_FROT_VISQ {{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 ////------- debug //cout << "\n debug*** Algori::MiseAJourAlgoMere " // << "\n pt_void= " << pt_void << " gr.ContDouble()= " << gr.ContDouble() // << " (*(gr.ConteneurDouble())) = " << (*(gr.ConteneurDouble())) // << flush; // //// --- fin debug energPenalisation = *(gr.ConteneurDouble()); }; {void* pt_void = ParaGlob::param->Mise_a_jour_grandeur_consultable(ENERGIE_FROT_ELAST); TypeQuelconque* pt_quelc = (TypeQuelconque*) pt_void; Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) pt_quelc->Grandeur_pointee()); // pour simplifier energFrottement.ChangeEnergieElastique(*(gr.ConteneurDouble())); }; {void* pt_void = ParaGlob::param->Mise_a_jour_grandeur_consultable(ENERGIE_FROT_PLAST); TypeQuelconque* pt_quelc = (TypeQuelconque*) pt_void; Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) pt_quelc->Grandeur_pointee()); // pour simplifier energFrottement.ChangeDissipationPlastique( *(gr.ConteneurDouble()) ); }; {void* pt_void = ParaGlob::param->Mise_a_jour_grandeur_consultable(ENERGIE_FROT_VISQ); TypeQuelconque* pt_quelc = (TypeQuelconque*) pt_void; Grandeur_scalaire_double& gr = *((Grandeur_scalaire_double*) pt_quelc->Grandeur_pointee()); // pour simplifier energFrottement.ChangeDissipationVisqueuse(*(gr.ConteneurDouble())); }; }; }; // gestion éventuelle d'une renumérotation, qui prend en compte les éléments de contact // premier_calcul: indique s'il s'agit d'un premier calcul on non // nouvelle_situation_contact : indique s'il y a du nouveau sur le contact // 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 // ramène true si la matrice a été changée bool Algori::Gestion_stockage_et_renumerotation_avec_contact(bool premier_calcul ,LesMaillages * lesMail, bool & nouvelle_situation_contact ,LesCondLim* lesCondLim,LesReferences* lesRef ,Tableau & tab_mato,const Nb_assemb& nb_casAssemb ,LesContacts* lescontacts,int niveau_substitution) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées // donc s'il s'agit d'un CPU différent, on revient immédiatement if (ParaGlob::Monde()->rank() != 0) return false; #endif TroisEntiers nevez_largeurs; bool retour = false; // init pas de changement a priori au niveau des matrices if (premier_calcul) {// si demandé, renumérotation en fonction des éléments en contact if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation()) { // récup des connexions entre noeud dues aux contacts const Tableau & tabCondLine= lescontacts->ConnectionCLL(); if (tabCondLine.Taille() > 0) //cas où il faut en tenir compte {// récup des connexions entre noeuds dues aux CLL externes Tableau > tabCLL(lesCondLim->ConnectionCLL(lesMail,lesRef)); int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); tabCLL(tailtabCLL+1) = tabCondLine; // ajout de la partie contact if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation en tenant compte des elements de contact "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation {//lesMail->MiseAJourPointeurAssemblage(nb_casAssemb);// mise a jour des pointeurs d'assemblage // il faut regarder un peu partout: élément, frontière etc // on met à jour le tableau indice pour LesContacts lescontacts->Mise_a_jour_indice(lesMail->Indice()); // enfin il faut renuméroter la matrice Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,lescontacts,niveau_substitution,&nevez_largeurs); retour = true; } else { Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,lescontacts,niveau_substitution,NULL); retour = true; }; }; } else { Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,lescontacts,niveau_substitution,NULL); retour = true; }; } //-- fin du cas si premier calcul else {if (nouvelle_situation_contact) {if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_numerotation()) { // récup des connexions entre noeud dues aux contacts const Tableau & tabCondLine= lescontacts->ConnectionCLL(); if (tabCondLine.Taille() > 0) //cas où il faut en tenir compte {// récup des connexions entre noeuds dues aux CLL externes: comme les cll ont été mises à jour // on récupère directement le tableau Tableau > tabCLL(lesCondLim->Tab_CLinApplique()); int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); tabCLL(tailtabCLL+1) = tabCondLine; // ajout de la partie contact if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation en tenant compte d'un changement de contact "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation { // on met à jour le tableau indice pour LesContacts lescontacts->Mise_a_jour_indice(lesMail->Indice()); //lesMail->MiseAJourPointeurAssemblage(nb_casAssemb);// mise a jour des pointeurs d'assemblage Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,lescontacts,niveau_substitution,&nevez_largeurs); retour = true; } else { Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,lescontacts,niveau_substitution,NULL); retour = true; }; }; } else { Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,lescontacts,niveau_substitution,NULL); retour = true; }; } else {retour = false; }; }; //-- fin du cas si ce n'est pas un premier calcul // retour return retour; }; // --- même chose mais sans le contact, par contre prise en compte d'un changement éventuelle // imposé par exemple par les CLL // gestion éventuelle d'une renumérotation des pointeurs d'assemblage , qui prend en compte les CLL // premier_calcul : indique s'il s'agit d'un premier calcul on non // nouvelle_situation_CLL : indique s'il y a du nouveau sur les CLL // -> la renumérotation des pointeurs s'effectue que si: // a) ParaAlgoControleActifs().Optimisation_pointeur_assemblage() est ok // b) soit c'est un premier calcul, soit il y a du nouveau sur les CLL // 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 // ramène true si la matrice a été changée // NB: lescontacts est quand même passé en paramètre, car on doit le renseigner au niveau d'un // tableau d'indice (num de noeuds) lorsque les num ont changés, ceci pour être opérationnel // par la suite si le contact devient actif bool Algori::Gestion_stockage_et_renumerotation_sans_contact(LesContacts* lescontacts,bool premier_calcul ,LesMaillages * lesMail, bool & nouvelle_situation_CLL ,LesCondLim* lesCondLim,LesReferences* lesRef ,Tableau & tab_mato,const Nb_assemb& nb_casAssemb ,int niveau_substitution) { #ifdef UTILISATION_MPI // cas d'un calcul //, seule la (ou les) matrices du CPU 0 sont concernées // donc s'il s'agit d'un CPU différent, on revient immédiatement if (ParaGlob::Monde()->rank() != 0) return false; #endif TroisEntiers nevez_largeurs; bool retour = false; // init pas de changement a priori au niveau des matrices if (premier_calcul) {// si demandé, renumérotation des pointeurs d'assemblage if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_pointeur_assemblage()) { // récup des connexions entre noeuds dues aux CLL externes Tableau > tabCLL(lesCondLim->ConnectionCLL(lesMail,lesRef)); // int tailtabCLL = tabCLL.Taille();tabCLL.Change_taille(tailtabCLL+1); // tabCLL(tailtabCLL+1) = tabCondLine; // ajout de la partie contact if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation des pointeurs d'assemblage en tenant compte des CLL "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation {//lesMail->MiseAJourPointeurAssemblage(nb_casAssemb);// mise a jour des pointeurs d'assemblage // il faut regarder un peu partout: élément, frontière etc // on met à jour le tableau indice pour LesContacts lescontacts->Mise_a_jour_indice(lesMail->Indice()); // enfin il faut renuméroter la matrice // ici on ne se sert pas du contact Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,NULL,niveau_substitution,&nevez_largeurs); retour = true; }; // sinon on ne fait rien }; } //-- fin du cas si premier calcul else {if (nouvelle_situation_CLL) {if (ParaGlob::param->ParaAlgoControleActifs().Optimisation_pointeur_assemblage()) { // récup des connexions entre noeuds dues aux CLL externes: comme les cll ont été mises à jour // on récupère directement le tableau Tableau > tabCLL(lesCondLim->Tab_CLinApplique()); if ( ((permet_affichage==0) && (ParaGlob::NiveauImpression() > 2)) || (permet_affichage > 2)) cout << "\n -- renumerotation des pointeurs d'assemblage en tenant compte des CLL "; // appel de l'utilitaire dans lesMaillages: avec mise à jour dans la foulée de l'assemblage bool calcul_ok = lesMail->Renumerotation(*lesRef,tabCLL,nevez_largeurs,&nb_casAssemb,true); if (calcul_ok) // cas où il y a eu effectivement un changement de numérotation { // on met à jour le tableau indice pour LesContacts lescontacts->Mise_a_jour_indice(lesMail->Indice()); //lesMail->MiseAJourPointeurAssemblage(nb_casAssemb);// mise a jour des pointeurs d'assemblage Mise_a_jour_Choix_matriciel_contact (tab_mato,nb_casAssemb,NULL,niveau_substitution,&nevez_largeurs); retour = true; }; // sinon on ne fait rien }; }; }; //-- fin du cas si ce n'est pas un premier calcul // retour return retour; }; // mise à jour de delta_X, var_delta_X et passage en global des maxi void Algori::Cal_Transfert_delta_et_var_X(double& max_delta_X, double& max_var_delta_X) { var_delta_X = -delta_X; // sauvegarde de la dernière valeur // calcul du nouveau delta_X delta_X.Zero(); delta_X += X_tdt; delta_X -= X_t;// X_tdt - X_t // calcul de la variation de delta_X var_delta_X += delta_X; // calcul des maxis en valeurs absolue max_delta_X = delta_X.Max_val_abs(); max_var_delta_X = var_delta_X.Max_val_abs(); // passage au niveau global ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(MAXdeltaX,max_delta_X); ParaGlob::param->Mise_a_jour_grandeur_consultable_Scalaire_double(MAXvarDeltaX,max_var_delta_X); }; // ---------- static pour la création d'un algorithme particulier --------- // ramène un pointeur sur l'algorithme spécifique correspondant aux paramètres // IMPORTANT : il y a création de l'algorithme correspondant (utilisation d'un new) Algori* Algori::New_Agori(EnumTypeCalcul id_TypeCalcul,const bool avec_typeDeCalcul ,const list & soustype ,const list & avec_soustypeDeCalcul ,UtilLecture& entreePrinc ) { // définition du pointeur de retour Algori* algo_specifique; switch (id_TypeCalcul) {case NON_DYNA : { algo_specifique = new AlgoriNonDyna (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case NON_DYNA_CONT : { algo_specifique = new ImpliNonDynaCont (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case FLAMB_LINEAIRE : { algo_specifique = new AlgoriFlambLineaire (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case INFORMATIONS : { algo_specifique = new AlgoInformations (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case UTILITAIRES : { algo_specifique = new AlgoUtils (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case DYNA_EXP : { algo_specifique = new AlgoriDynaExpli (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case DYNA_EXP_TCHAMWA : { algo_specifique = new AlgoriTchamwa (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case DYNA_EXP_CHUNG_LEE : { algo_specifique = new Algori_chung_lee (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case DYNA_EXP_ZHAI : { algo_specifique = new AlgoriDynaExpli_zhai (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case DYNA_IMP : { algo_specifique = new AlgoriNewmark (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case UMAT_ABAQUS : { algo_specifique = new AlgoUmatAbaqus (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case DYNA_RUNGE_KUTTA : { algo_specifique = new AlgoriRungeKutta (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case DYNA_EXP_BONELLI : { algo_specifique = new AlgoBonelli (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case RELAX_DYNA : { algo_specifique = new AlgoriRelaxDyna (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } case COMBINER : { algo_specifique = new AlgoriCombine (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); break; } default : { cout << "\n type d\'algorithme non encore implante, desole ! \n"; cout << " agorithme demande = " << Nom_TypeCalcul(id_TypeCalcul); cout << endl; entreePrinc.MessageBuffer("** lecture du type d\'algorithme **"); throw (UtilLecture::ErrNouvelleDonnee(-1)); Sortie(1); }; }; return algo_specifique; }; // ramène un tableau de pointeurs sur tous les algorithmes spécifique existants // IMPORTANT : il y a création des algorithmes (utilisation d'un new) Tableau Algori::New_tous_les_Algo (const bool avec_typeDeCalcul ,const list & soustype ,const list & avec_soustypeDeCalcul ,UtilLecture& entreePrinc) { // définition du tableau de pointeurs de retour Tableau tab_algo_specifique(15); // la méthode ne doit pas fonctionner dans le cas d'un calcul // #ifndef UTILISATION_MPI tab_algo_specifique(1) = new AlgoriNonDyna (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(2) = new ImpliNonDynaCont (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(3) = new AlgoriFlambLineaire (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(4) = new AlgoInformations (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(5) = new AlgoUtils (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(6) = new AlgoriDynaExpli (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(7) = new AlgoriTchamwa (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(8) = new Algori_chung_lee (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(9) = new AlgoriDynaExpli_zhai (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(10) = new AlgoriNewmark (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(11) = new AlgoUmatAbaqus (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(12) = new AlgoriRungeKutta (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(13) = new AlgoBonelli (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(14) = new AlgoriRelaxDyna (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); tab_algo_specifique(15) = new AlgoriCombine (avec_typeDeCalcul,soustype,avec_soustypeDeCalcul,entreePrinc); #else // c'est une erreur cout << "\n *** erreur: la methode Algori::New_tous_les_Algo n'est pas prevu " << " pour fonctionner en calcul parallele, veuillez utiliser la version " << " mono processeur! "<< endl; Sortie(1); #endif return tab_algo_specifique; }; #ifdef UTILISATION_MPI // cas d'un calcul parallèle, passage des indicateurs // calculés par le process 0 aux process de calcul void Algori::Passage_indicConvergenceAuxProcCalcul() {// seule le process 0 a fait la résolution globale // il gère seul également la convergence, mais il doit tenir au courant les autres process // on utilise un std::array pour passer en une fois les infos temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu std::array indic_convergence = {phase_de_convergence,nombre_de_bonnes_convergences ,nombre_de_mauvaises_convergences,a_converge ,a_converge_iterMoins1,nb_cycle_test_max_var_residu }; broadcast(*ParaGlob::Monde(), indic_convergence, 0); // ParaGlob::Monde()->barrier(); if (ParaGlob::Monde()->rank() != 0) // on récupère les grandeurs {phase_de_convergence = indic_convergence[0]; nombre_de_bonnes_convergences = indic_convergence[1]; nombre_de_mauvaises_convergences = indic_convergence[2]; a_converge = indic_convergence[3]; a_converge_iterMoins1 = indic_convergence[4]; nb_cycle_test_max_var_residu = indic_convergence[5]; }; temps_transfert_court.Arret_du_comptage(); // fin comptage cpu }; // globalisation des grandeurs globales: proc de calcul -> maitre puis transmission à ParaGlob // et transmission aux proc de calcul: // on ne demande pas à ParaGlob de faire la transmission, car il ne sait pas ce qu'il transmet // et les infos ne sont pas contigües, le transfert ne sera pas performant void Algori::Globalisation_et_transfert_auxProcCalcul_grandeurs_globales() { // on s'occupe tout d'abord des grandeurs directement gérées par Algori Vecteur inter(10); // vecteur de passage // inter(1) = // ENERGIE_CINETIQUE -> inter(1) // ENERGIE_EXTERNE -> 2 // ENERGIE_INTERNE -> 3 // PUISSANCE_ACCELERATION); // PUISSANCE_INTERNE); // PUISSANCE_EXTERNE); // PUISSANCE_BILAN); // ENERGIE_ELASTIQUE); // ENERGIE_PLASTIQUE); // ENERGIE_VISQUEUSE); // ENERGIE_BILAN); // QUANTITE_MOUVEMENT); // ENERGIE_PENALISATION); // ENERGIE_FROT_ELAST); // ENERGIE_FROT_PLAST); // ENERGIE_FROT_VISQ); // ENERGIE_VISCO_NUMERIQUE); // ENERGIE_BULK_VISCOSITY); // ENERGIE_HOURGLASS_); // ENERGIE_STABILISATION_MEMB_BIEL); // VOLUME_TOTAL_MATIERE); // MAXPUISSEXT); // MAXPUISSINT); // MAXREACTION); // MAXRESIDUGLOBAL); // MAXdeltaX); // MAXvarDeltaX); // MAXvarDdl); // 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); }; #endif