// 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 "Debug.h" # include "Deformation.h" #include "ConstMath.h" #include "ParaGlob.h" #include "MathUtil.h" #include "Tenseur3.h" #include "Tenseur2.h" #include "Tenseur1.h" # include "TypeConsTens.h" #include "Util.h" #include "MathUtil2.h" //================== initialisation des variables static ====================== // change 2 mai 2020: int Deformation::numInteg = 0; // indicateur utilisé par VerifCal_deflog int Deformation::indic_VerifCal_implicit = 0; // def de deux tableaux d'indices pour avoir la suite: 12 21 13 31 23 32 à partir de 6 nombres const Deformation::UtilIndexDeformation Deformation::ccdex; // partie statique ou sont stocké tous les cas différents des variables de travail list > Deformation::list_var_tens_BH; list > > Deformation::list_var_var_tens_BH; list > Deformation::list_tab_coor; int Deformation::nombre_d_instance_deformation=0; //================== fin d'initialisation des variables static ================ // def du constructeur par défaut de UtilIndexDeformation Deformation::UtilIndexDeformation::UtilIndexDeformation() : iii(6),jjj(6) { iii(6); iii(1)=1; iii(2)=2;iii(3)=1;iii(4)=3;iii(5)=2;iii(6)=3; jjj(6); jjj(1)=2; jjj(2)=1;jjj(3)=3;jjj(4)=1;jjj(5)=3;jjj(6)=2; }; // ---------- constructeur---------------------------------------- Deformation::Deformation () // constructeur ne devant pas etre utilise //#ifndef ENLINUX : tabnoeud((new Tableau )) // dans le cas de linux on ne déclare pas le tableau ,saveDefResul(NULL),numInteg(0),sauve_numInteg(0) //#endif // : tabnoeud() { #ifdef MISE_AU_POINT { cout << "\nErreur : le constructeur par defaut ne doit pa etre utilise !\n"; cout << "Deformation::Deformation () \n"; Sortie(1); }; #endif }; // constructeur normal dans le cas d'un ou de plusieurs pt d'integration Deformation::Deformation (Met_abstraite & a,Tableau& b, Tableau const & tabdphi,Tableau const & tabphi ,Enum_type_deformation type_de_deformation) : tabnoeud(&b),type_deformation(type_de_deformation) ,type_gradient_vitesse(GRADVITESSE_VCONST) // pour l'instant ********* en test ,saveDefResul(NULL) // variables de travail pour log ,B_BH_tr(NULL),d_B_BH_tr(NULL),ki(),d_ki(NULL),Palpha_BH_tr(NULL),d_Palpha_BH_tr(NULL) ,dimensionnement_tableaux(0),numInteg(0) ,sauve_numInteg(0) { metrique = &a; tabDphi = &tabdphi; tabPhi = &tabphi; nbNoeud = (*tabPhi)(1).Taille(); // par defaut numInteg = 1; // 1 pt d'integ par defaut nombre_d_instance_deformation++; }; // constructeur de copie Deformation::Deformation (const Deformation& a) : tabnoeud(a.tabnoeud), type_deformation(a.type_deformation) ,type_gradient_vitesse(a.type_gradient_vitesse),saveDefResul(NULL) // variables de travail pour log ,B_BH_tr(a.B_BH_tr),d_B_BH_tr(a.d_B_BH_tr),ki(a.ki),d_ki(a.d_ki) ,Palpha_BH_tr(a.Palpha_BH_tr),d_Palpha_BH_tr(a.d_Palpha_BH_tr) ,dimensionnement_tableaux(a.dimensionnement_tableaux) ,numInteg(a.numInteg),sauve_numInteg(a.sauve_numInteg) { metrique = a.metrique; tabDphi = a.tabDphi; tabPhi = a.tabPhi; nbNoeud = a.nbNoeud; nombre_d_instance_deformation++; }; Deformation::~Deformation () { LibereTenseur() ; nombre_d_instance_deformation--; if (nombre_d_instance_deformation==0) {// cas de la dernière instance // ---- cas de list_var_tens_BH ---- list >::iterator ilv,ilvend= list_var_tens_BH.end(); for (ilv=list_var_tens_BH.begin();ilv!=ilvend;ilv++) { int tailletab=(*ilv).Taille(); for (int i=1;i<=tailletab;i++) delete (*ilv)(i); }; list_var_tens_BH.erase(list_var_tens_BH.begin(),ilvend); // ---- cas de list_var_var_tens_BH ---- list > > ::iterator ilv1,ilvend1= list_var_var_tens_BH.end(); for (ilv1=list_var_var_tens_BH.begin();ilv1!=ilvend1;ilv1++) { int tailletab=(*ilv1).Taille(); for (int i=1;i<=tailletab;i++) { int tailletab2=(*ilv1)(i).Taille(); for (int j=1;j<=tailletab2;j++) delete (*ilv1)(i)(j); }; }; list_var_var_tens_BH.erase(list_var_var_tens_BH.begin(),ilvend1); // ---- cas de list_tab_coor ---- list_tab_coor.erase(list_tab_coor.begin(),list_tab_coor.end()); }; }; // réafectation du pointeur de tableau de noeuds interne // il faut que le nouveau tableau ait la même taille que l'ancien (sert pour créer de nouveau éléments // de même type, sinon ce n'est pas la bonne solution, // il vaut mieux creer une nouvelle def void Deformation::PointeurTableauNoeud(Tableau & tabN) { // on vérifie la cohérence if (tabN.Taille() != tabnoeud->Taille()) { cout << "\n erreur de re-affectation de tableau de noeud dans la deformation ! " << " ancien nombre de noeud: " << tabnoeud->Taille() << " nouveau nombre: " << tabN.Taille() << "\n Deformation::PointeurTableauNoeud(.."; Sortie(1); }; // sinon c'est ok tabnoeud = &tabN; }; // surcharge de l'opérateur d'affectation Deformation& Deformation::operator= (const Deformation& def) { metrique = def.metrique; tabnoeud = def.tabnoeud; tabDphi = def.tabDphi; tabPhi = def.tabPhi; nbNoeud = def.nbNoeud;type_deformation=def.type_deformation; numInteg = def.numInteg; saveDefResul = def.saveDefResul; // variables de travail pour log B_BH_tr=def.B_BH_tr;d_B_BH_tr=def.d_B_BH_tr;ki=def.ki;d_ki=def.d_ki; Palpha_BH_tr=def.Palpha_BH_tr;d_Palpha_BH_tr=def.d_Palpha_BH_tr; return (*this); }; // change le type de déformation void Deformation::Change_type_de_deformation(Enum_type_deformation type_de_def) { // le changement de déformation doit-être cohérent avec la déformation actuelle d'où les // différents choix restreinds if ((type_de_def==DEFORMATION_STANDART) || (type_de_def==DEFORMATION_LOGARITHMIQUE) || (type_de_def==DEFORMATION_CUMU_LOGARITHMIQUE) || (type_de_def==DEF_CUMUL_CORROTATIONNEL) || (type_de_def==DEF_CUMUL_ROTATION_PROPRE) ) { if ((type_deformation==DEFORMATION_STANDART) || (type_deformation==DEFORMATION_LOGARITHMIQUE) || (type_deformation==DEFORMATION_CUMU_LOGARITHMIQUE) || (type_deformation==DEF_CUMUL_CORROTATIONNEL) || (type_deformation==DEF_CUMUL_ROTATION_PROPRE) ) type_deformation = type_de_def; // ok cohérent } // sinon le type n'est pas pris en compte dans cette méthode donc erreur else { cout << "\nErreur : valeur incorrecte du nouvrau type Enum_type_deformation !" << "\n type actuelle: " << Nom_type_deformation(type_deformation) << " type demande: " << Nom_type_deformation(type_de_def); cout << "Deformation::Change_type_de_deformation(...) \n"; Sortie(1); }; }; // affichage des informations void Deformation::Affiche() const { cout << "\n -- deformation: --- " << "\n nb noeud concerne = "<< nbNoeud << " numInteg= "<< numInteg; if (tabnoeud != NULL) {cout << "\n -- information concernant les noeuds: \n"; for (int i = 1;i<= tabnoeud->Taille();i++) (*tabnoeud)(i)->Affiche(); }; if (metrique != NULL) {cout << "\n -- information concernant la metrique actuelle au pti --"; metrique->Affiche(); }; cout << flush; }; // ============ METHODES PUBLIQUES : ================== // ---------------- calcul des variables primaires pour la mécanique -------- // calcul explicit à t :tous les parametres sont des resultats const Met_abstraite::Expli& Deformation::Cal_explicit_t // ( bool gradV_instantane,TenseurBB & epsBB_t,Tableau & d_epsBB // ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul) // def_equi_t: est la def equi au debut du pas, et def_equi est la def finale ( const Tableau & def_equi_t,TenseurBB & epsBB_t,Tableau & d_epsBB ,Tableau & def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul) {bool gradV_instantane = false; // ************ pour l'instant figé // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes const Met_abstraite::Expli& ex = metrique->Cal_explicit_t(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg), nbNoeud,(*tabPhi)(numInteg),premier_calcul); // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange .. switch (type_deformation) { case DEFORMATION_STANDART : {Cal_explicit_Almansi (gradV_instantane,epsBB_t,d_epsBB,DepsBB,delta_epsBB,premier_calcul,ex); break; } case DEFORMATION_LOGARITHMIQUE: {Cal_explicit_Logarithmique (gradV_instantane,epsBB_t,d_epsBB,DepsBB,delta_epsBB,premier_calcul,ex); break; } // case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE : // {Cal_explicit_def_cumule // (gradV_instantane,epsBB_t,d_epsBB,DepsBB,delta_epsBB,premier_calcul,ex); // break; // } default : cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation) << " ) non traite !\n"; cout << "Deformation::Cal_explicit(... \n"; Sortie(1); }; // --- on calcul la déformation cumulée {TenseurBH * delta_epsBH = NevezTenseurBH(delta_epsBB.Dimension(), 0.); *delta_epsBH = delta_epsBB * (*ex.gijHH_t); double delta_eps_equi = sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. )); def_equi(1) = def_equi_t(1) + delta_eps_equi; def_equi(4) = delta_eps_equi; delete delta_epsBH; }; {TenseurBH * epsBH = NevezTenseurBH(epsBB_t.Dimension(), 0.); *epsBH = epsBB_t * (*ex.gijHH_t); def_equi(2) = sqrt(2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. )); delete epsBH; if (def_equi(2) > def_equi_t(3)) def_equi(3) = def_equi(2); }; // sauvegarde des infos à 0 éventuellement et init par recopie des grandeurs sur t if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique); // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici // const Met_abstraite::Expli& toto = * (new Met_abstraite::Expli()); return toto; return ex; }; // calcul explicit à tdt :tous les parametres sont des resultats const Met_abstraite::Expli_t_tdt& Deformation::Cal_explicit_tdt // ( bool gradV_instantane,TenseurBB & epsBB_tdt,Tableau & d_epsBB,TenseurBB& DepsBB // ,TenseurBB& delta_epsBB_tdt,bool premier_calcul) ( const Tableau & def_equi_t,TenseurBB & epsBB_tdt,Tableau & d_epsBB ,Tableau & def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB_tdt,bool premier_calcul) { bool gradV_instantane = false; // ************ pour l'instant figé // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes const Met_abstraite::Expli_t_tdt& ex = metrique->Cal_explicit_tdt(*tabnoeud,gradV_instantane,(*tabDphi)(numInteg), nbNoeud,(*tabPhi)(numInteg),premier_calcul); // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange .. switch (type_deformation) { case DEFORMATION_STANDART : {Cal_explicit_Almansi_tdt (gradV_instantane,epsBB_tdt,d_epsBB,DepsBB,delta_epsBB_tdt,premier_calcul,ex); break; } case DEFORMATION_LOGARITHMIQUE: {Cal_explicit_logarithmique_tdt (gradV_instantane,epsBB_tdt,d_epsBB,DepsBB,delta_epsBB_tdt,premier_calcul,ex); break; } // case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE : // {Cal_explicit_def_cumule_tdt // (gradV_instantane,epsBB_tdt,d_epsBB,DepsBB,delta_epsBB_tdt,premier_calcul,ex); // break; // } default : cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation) << " ) non traite !\n"; cout << "Deformation::Cal_explicit_tdt(... \n"; Sortie(1); }; // sauvegarde des infos à 0 éventuellement et init par recopie des grandeurs sur t if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique); // sauvegarde des infos à t à chaque passage saveDefResul->MiseAJourGrandeurs_a_tdt(metrique,DepsBB); // --- on calcul la déformation cumulée {TenseurBH * delta_epsBH = NevezTenseurBH(delta_epsBB_tdt.Dimension(), 0.); *delta_epsBH = delta_epsBB_tdt * (*ex.gijHH_tdt); double delta_eps_equi = sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. )); def_equi(1) = def_equi_t(1) + delta_eps_equi; def_equi(4) = delta_eps_equi; delete delta_epsBH; }; {TenseurBH * epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.); *epsBH = epsBB_tdt * (*ex.gijHH_tdt); def_equi(2) = sqrt(2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. )); delete epsBH; if (def_equi(2) > def_equi_t(3)) def_equi(3) = def_equi(2); }; // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici // const Met_abstraite::Expli_t_tdt& toto = * (new Met_abstraite::Expli_t_tdt()); return toto; return ex; }; // calcul et récupération de la dérivée de la vitesse de déformation virtuelle à tdt // dans le cas d'une discrétisation classique simple, ce calcul est indépendant des coordonnées // donc peut être effectué indépendament du reste, il dépend cependant du point d'intégration // dans le cas de discrétisation complexe, il faut s'assurer que les autres grandeurs utiles de la métrique // sont déjà calculé (cf. D2_gijBB_tdt() ) // total = true : indique que le calcul est complet, à partir des données de base // c-a-d calcul de la variation de vecteur de base puis calcul de la variation seconde // = false: le calcul est simplifié, on considère que la variation des vecteurs de base vient // juste d'être calculé, dans un calcul implicit, on ne calcul alors que la variation seconde void Deformation::Cal_var_def_virtuelle(bool total,Tableau2 & d2_epsBB_tdt) { const Tableau2 & d2_gijBB_tdt = metrique->CalVar2GijBBtdt(total, (*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg)); int d2_epsBB_tdtTaille1 = d2_epsBB_tdt.Taille1(); for (int i=1; i<= d2_epsBB_tdtTaille1; i++) for (int j=1; j<= i; j++) // symétrie du tableau et du tenseur { *(d2_epsBB_tdt(i,j)) = 0.5 * (*((d2_gijBB_tdt)(i,j))) ; *(d2_epsBB_tdt(j,i)) = *(d2_epsBB_tdt(i,j)) ; }; }; // cas implicite : tous les parametres sont de resultats //const Met_abstraite::Impli& Deformation::Cal_implicit( bool gradV_instantane // ,TenseurBB & epsBB_tdt,Tableau & d_epsBB_tdt // ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul) const Met_abstraite::Impli& Deformation::Cal_implicit(const Tableau & def_equi_t ,TenseurBB & epsBB_tdt,Tableau & d_epsBB_tdt ,Tableau & def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul) { bool gradV_instantane = false; // ************ pour l'instant figé // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes // toutes les variables de passage a metrique apres l'appel // pointeront sur des variables deja dimensionnees // pour les Tableau <> il y a dim //------debug //premier_calcul=true; //---- fin debug const Met_abstraite::Impli& ex =metrique->Cal_implicit ( *tabnoeud,gradV_instantane,(*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg) ,premier_calcul); // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange .. switch (type_deformation) { case DEFORMATION_STANDART : {Cal_implicit_Almansi (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex); break; } case DEFORMATION_LOGARITHMIQUE: {Cal_implicit_Logarithmique (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex); break; } case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE : {Cal_implicit_def_cumule (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex); break; } default : cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation) << " ) non traite !\n"; cout << "Deformation::Cal_implicit(... \n"; Sortie(1); }; // sauvegarde des infos à 0 et à t // *** non car dans le cas d'un restart ce n'est pas vrai !!!! // éventuellement et init par recopie des grandeurs sur t if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique); // sauvegarde des infos à tdt à chaque passage saveDefResul->MiseAJourGrandeurs_a_tdt(metrique,DepsBB); // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici // const Met_abstraite::Impli& toto = * (new Met_abstraite::Impli()); return toto; // --- on calcul la déformation cumulée {TenseurBH * delta_epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.); *delta_epsBH = delta_epsBB * (*ex.gijHH_tdt); double x_inter = (2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. )); if (x_inter < 0) {if (Dabs(x_inter) < ConstMath::trespetit) { //debug //cout << "\n **************** x_inter= "< 0) cout << "\n erreur calcul def equi: delta_def_equi2 est negatif ("< nan! " << " on met a 0, mais ce n'est pas normal !! "; if (ParaGlob::NiveauImpression() > 5) cout << "\n Deformation::Cal_implicit(.." << endl; }; }; double delta_eps_equi = sqrt(x_inter); def_equi(1) = def_equi_t(1) + delta_eps_equi; def_equi(4) = delta_eps_equi; delete delta_epsBH; }; {TenseurBH * epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.); *epsBH = epsBB_tdt * (*ex.gijHH_tdt); double y_inter = 2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. ); if (y_inter < 0) {if (Dabs(y_inter) < ConstMath::trespetit) { //debug //cout << "\n **************** x_inter= "< 0) cout << "\n erreur calcul def equi: sqr(def_dual_mises est negatif) ("< nan! " << " on met a 0, mais ce n'est pas normal !! "; if (ParaGlob::NiveauImpression() > 5) cout << "\n Deformation::Cal_implicit(.." << endl; }; }; def_equi(2) = sqrt(y_inter); delete epsBH; if (def_equi(2) > def_equi_t(3)) def_equi(3) = def_equi(2); }; return ex; }; // ------------------------ flambage linéaire ------------------------------ const Met_abstraite::flambe_lin& Deformation::Cal_flambe_lin // ( bool gradV_instantane,TenseurBB & epsBB_tdt,Tableau & d_epsBB_tdt,Tableau2 & d2_epsBB_tdt // ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul) ( const Tableau & def_equi_t,TenseurBB & epsBB_tdt,Tableau & d_epsBB_tdt ,Tableau & def_equi,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul) { bool gradV_instantane = false; // ************ pour l'instant figé // --- le calcul est identique au cas implicite sauf que // l'on doit absolument calculer la dérivée seconde de la déformation // appel de la metrique: on le fait ici et non dans les méthodes Cal_explicit_Almansi_tdt etc // car pour d'autre déformation, par exemple sfe ou plaque, la méthode Deformation::Cal_explicit_tdt // est surchargée car différentes, par contre les méthodes Cal_explicit_Almansi_tdt etc sont les mêmes // toutes les variables de passage a metrique apres l'appel // pointeront sur des variables deja dimensionnees // pour les Tableau <> il y a dimensionnement auto a l'affectation const Met_abstraite::Impli& ex =metrique->Cal_implicit ( *tabnoeud,gradV_instantane,(*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg) ,premier_calcul); // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange .. switch (type_deformation) { case DEFORMATION_STANDART : {Cal_implicit_Almansi(gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex); break; } case DEFORMATION_LOGARITHMIQUE: {Cal_implicit_Logarithmique(gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex); break; } // case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE : // {Cal_implicit_def_cumule // (gradV_instantane,epsBB_tdt,d_epsBB_tdt,DepsBB,delta_epsBB,premier_calcul,ex); // break; // } default : cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation) << " ) non traite !\n"; cout << "Deformation::Cal_flambe_lin(... \n"; Sortie(1); }; // --- on calcul la déformation cumulée {TenseurBH * delta_epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.); *delta_epsBH = delta_epsBB * (*ex.gijHH_tdt); double delta_eps_equi = sqrt(2./3. * ( ((*delta_epsBH) && (*delta_epsBH)) - Sqr(delta_epsBH->Trace()) /3. )); def_equi(1) = def_equi_t(1) + delta_eps_equi; def_equi(4) = delta_eps_equi; delete delta_epsBH; }; {TenseurBH * epsBH = NevezTenseurBH(epsBB_tdt.Dimension(), 0.); *epsBH = epsBB_tdt * (*ex.gijHH_tdt); def_equi(2) = sqrt(2./3. * ( ((*epsBH) && (*epsBH)) - Sqr(epsBH->Trace()) /3. )); delete epsBH; if (def_equi(2) > def_equi_t(3)) def_equi(3) = def_equi(2); }; // sauvegarde des infos à 0 éventuellement et init par recopie des grandeurs sur t if (premier_calcul) saveDefResul->MiseAJourGrandeurs_a_0(metrique); // sauvegarde des infos à tdt à chaque passage saveDefResul->MiseAJourGrandeurs_a_tdt(metrique,DepsBB); // *** pour supprimer les warnings à la compilation *** mais on ne doit jamais passer ici // const Met_abstraite::flambe_lin& toto = * (new Met_abstraite::flambe_lin()); return toto; return (Met_abstraite::flambe_lin&) ex; }; // ------------------------- cas de la dilatation thermique ------------------------ // l'objectif est de calculer la déformation d'origine thermique et la déformation d'origine mécanique // temperature_tdt,temperature_t : températures, temperature_0: température initiale // atdt : booléen qui indique si les grandeurs à tdt sont disponible ou pas // avec_repercution_sur_def_meca: si oui on met à jour la déformation méca, sinon, on ne calcul que les def thermiques void Deformation::DeformationThermoMecanique(const double& temperature_0,const ThermoDonnee& dTP ,const TenseurBB & epsBB_totale,TenseurBB & epsBB_therm,const double& temperature_tdt,TenseurBB & epsBB_meca ,const TenseurBB & delta_epsBB_totale,TenseurBB & delta_epsBB_therm,TenseurBB & delta_epsBB_meca ,const double& temperature_t,TenseurBB & DepsBB_totale,TenseurBB & DepsBB_therm,TenseurBB & DepsBB_meca ,const Met_abstraite::Impli* ex_impli ,const Met_abstraite::Expli_t_tdt* ex_expli_tdt ,const Met_abstraite::Umat_cont* ex_umat ,bool atdt,bool avec_repercution_sur_def_meca) { // la dilatation est déterminée par l'élévation de température double coef_dila_global = dTP.Dilatation() * (temperature_tdt-temperature_0); // éléments de métrique TenseurHH* gijHH;TenseurBB* gijBB;BaseB* giB; BaseH* giH_0;BaseH* giH; BaseB* giB_0;BaseB* giB_t; bool pas_de_metrique_dispo = false; // init if (ex_impli != NULL) { gijHH = ex_impli->gijHH_tdt;gijBB = ex_impli->gijBB_tdt; giB = ex_impli->giB_tdt; giH_0 = ex_impli->giH_0;giH = ex_impli->giH_tdt; giB_t = ex_impli->giB_t; giB_0 = ex_impli->giB_0; } else if (ex_expli_tdt != NULL) {gijHH = ex_expli_tdt->gijHH_tdt;gijBB = ex_expli_tdt->gijBB_tdt; giB = ex_expli_tdt->giB_tdt; giH_0 = ex_expli_tdt->giH_0;giH = ex_expli_tdt->giH_tdt; giB_t = ex_expli_tdt->giB_t; giB_0 = ex_expli_tdt->giB_0; } else if (ex_umat != NULL) {gijHH = ex_umat->gijHH_t;gijBB = ex_umat->gijBB_t; giB = giB_t = ex_umat->giB_t; giH_0 = ex_umat->giH_0;giH = ex_umat->giH_t; giB_0 = ex_umat->giB_0; } else { pas_de_metrique_dispo = true; }; // -- cas de la déformation epsBB_therm = coef_dila_global * (*gijBB); // -- cas de l'incrément de déformation if (atdt) { // cas d'un calcul avec les grandeurs à tdt disponibles double coef_dila_t_tdt = dTP.Dilatation() * (temperature_tdt-temperature_t); delta_epsBB_therm = coef_dila_t_tdt * (*gijBB) ; } else { // cas où les valeurs à tdt ne sont pas dispo, on considère un coef moyen sur toute la durée // et on considère que le delta = la valeur totale de la déformation // donc c'est le même calcul que pour la déformation totale delta_epsBB_therm = coef_dila_global * (*gijBB) ; }; // -- cas de la vitesse de déformation // 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; }; if (atdt) { // cas d'un calcul avec les grandeurs à tdt disponibles double coef_dila_t_tdt = dTP.Dilatation() * (temperature_tdt-temperature_t); DepsBB_therm = coef_dila_t_tdt * (*gijBB) * unSurDeltat; } else { // cas où les valeurs à tdt ne sont pas dispo, on considère un coef moyen sur toute la durée // recup de l'incrément du temps global double ttemps=ParaGlob::Variables_de_temps().TempsCourant(); double unSurttemps=0; if (Abs(ttemps) >= ConstMath::trespetit) {unSurttemps = 1./ttemps;} else // si l'incrément de temps est tres petit on remplace 1/ttemps par un nombre tres grand { // un pas de temps doit être positif !! or certaine fois il peut y avoir des pb if (unSurttemps < 0) { cout << "\n le pas de temps est négatif !! "; }; unSurttemps = ConstMath::tresgrand; }; DepsBB_therm = coef_dila_global * (*gijBB) * unSurttemps; }; // switch (abs(epsBB_meca.Dimension())) // { case 1: epsBB_therm = coef_dila * IdBB1; // case 2: epsBB_therm = coef_dila * IdBB2; // case 3: epsBB_therm = coef_dila * IdBB3; // } if (avec_repercution_sur_def_meca) { epsBB_meca = epsBB_totale - epsBB_therm; // pour la déformation delta_epsBB_meca = delta_epsBB_totale - delta_epsBB_therm; // pour la déformation DepsBB_meca = DepsBB_totale - DepsBB_therm; // pour la vitesse de déformation }; //// -- debug //if (!pas_de_metrique_dispo) // {cout << "\n debug Deformation::DeformationThermoMecanique( "; // cout << "\n coef_dila_global= " << coef_dila_global // << " delta_temp total= "<< (temperature_tdt-temperature_0) // << " increment temp= "<< (temperature_tdt-temperature_t); // // on sort les tenseurs en absolue // Tenseur3BB tiutiu; // epsBB_therm.BaseAbsolue(tiutiu,*giH); // cout << "\n epsBB_therm(1,1)=" << tiutiu(1,1); // epsBB_meca.BaseAbsolue(tiutiu,*giH); // cout << " epsBB_meca(1,1)=" << tiutiu(1,1); // delta_epsBB_therm.BaseAbsolue(tiutiu,*giH); // cout << " \n delta_epsBB_therm(1,1)= "<< tiutiu(1,1); // delta_epsBB_meca.BaseAbsolue(tiutiu,*giH); // cout << " delta_epsBB_meca(1,1)=" << tiutiu(1,1) << endl; // }; //// -- fin debug }; // ========== remontee aux informations ========================= // cas sortie d'un calcul implicit // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::InfoImp Deformation::RemontImp(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin) { Met_abstraite::InfoImp ex = metrique->Cal_InfoImp ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_tdt); BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin); return ex; }; // cas sortie d'un calcul implicit // sans le calcul des matrices de passage const Met_abstraite::InfoImp Deformation::RemontImp() { Met_abstraite::InfoImp ex = metrique->Cal_InfoImp ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_tdt); return ex; }; // cas sortie d'un calcul explicit à t // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::InfoExp_t Deformation::RemontExp_t(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin) { Met_abstraite::InfoExp_t ex = metrique->Cal_InfoExp_t ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_t); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_t); BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin); return ex; }; // cas sortie d'un calcul explicit à t // sans le calcul des matrices de passage const Met_abstraite::InfoExp_t Deformation::RemontExp_t() { Met_abstraite::InfoExp_t ex = metrique->Cal_InfoExp_t ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_t); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_t); return ex; }; // cas sortie d'un calcul explicit à tdt // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::InfoExp_tdt Deformation::RemontExp_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin) { Met_abstraite::InfoExp_tdt ex = metrique->Cal_InfoExp_tdt ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_tdt); BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin); return ex; }; // cas sortie d'un calcul explicit à tdt // sans le calcul des matrices de passage const Met_abstraite::InfoExp_tdt Deformation::RemontExp_tdt() { Met_abstraite::InfoExp_tdt ex = metrique->Cal_InfoExp_tdt ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_tdt); return ex; }; // cas sortie d'un calcul à 0, t et tdt // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::Info0_t_tdt Deformation::Remont0_t_tdt(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt) { Met_abstraite::Info0_t_tdt ex = metrique->Cal_Info0_t_tdt ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giBt = *(ex.giB_t); BaseB & giBtdt = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giHt = *(ex.giH_t); BaseH & giHtdt = *(ex.giH_tdt); BasePassage(absolue,giB0,giBt,giBtdt,giH0,giHt,giHtdt,Aa0,Aat,Aatdt); return ex; }; // cas sortie d'un calcul à 0, t et tdt // sans le calcul des matrices de passage const Met_abstraite::Info0_t_tdt Deformation::Remont0_t_tdt() { Met_abstraite::Info0_t_tdt ex = metrique->Cal_Info0_t_tdt ( *tabnoeud,(*tabDphi)(numInteg),(*tabPhi)(numInteg),nbNoeud); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giBt = *(ex.giB_t); BaseB & giBtdt = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giHt = *(ex.giH_t); BaseH & giHtdt = *(ex.giH_tdt); return ex; }; // cas sortie d'un calcul implicit // mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes // d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices // Aa0 et Aafin // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::InfoImp Deformation::RemontImpSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin) { Met_abstraite::InfoImp ex = metrique->Recup_InfoImp(); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_tdt); BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin); return ex; }; // cas sortie d'un calcul explicit à t // mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes // d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices // Aa0 et Aafin // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::InfoExp_t Deformation::RemontExp_tSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin) { Met_abstraite::InfoExp_t ex = metrique->Recup_InfoExp_t(); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_t); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_t); BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin); return ex; }; // cas sortie d'un calcul explicit à tdt // mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes // d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices // Aa0 et Aafin // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::InfoExp_tdt Deformation::RemontExp_tdtSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aafin) { Met_abstraite::InfoExp_tdt ex = metrique->Recup_InfoExp_tdt(); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giB = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giH = *(ex.giH_tdt); BasePassage(absolue,giB0,giB,giH0,giH,Aa0,Aafin); return ex; }; // cas sortie d'un calcul à 0, t et tdt // mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes // d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices // Aa0 et Aafin // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::Info0_t_tdt Deformation::Remont0_t_tdtSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt) { Met_abstraite::Info0_t_tdt ex = metrique->Recup_Info0_t_tdt(); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giBt = *(ex.giB_t); BaseB & giBtdt = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giHt = *(ex.giH_t); BaseH & giHtdt = *(ex.giH_tdt); BasePassage(absolue,giB0,giBt,giBtdt,giH0,giHt,giHtdt,Aa0,Aat,Aatdt); return ex; }; // cas sortie d'un calcul à 0, t et tdt avec tous les métriques associées // mêmes fct que précédemment mais dans le cas où les éléments de métrique viennent justes // d'être calculés, donc les seules grandeurs qui sont réellement calculées sont les matrices // Aa0 et Aafin // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer const Met_abstraite::Info_et_metrique_0_t_tdt Deformation::Remont_et_metrique_0_t_tdtSansCalMet(bool absolue,Mat_pleine& Aa0,Mat_pleine& Aat,Mat_pleine& Aatdt) { Met_abstraite::Info_et_metrique_0_t_tdt ex = metrique->Recup_Info_et_metrique_0_t_tdt(); // determination des matrices de transformation de base BaseB & giB0 = *(ex.giB_0); BaseB & giBt = *(ex.giB_t); BaseB & giBtdt = *(ex.giB_tdt); BaseH & giH0 = *(ex.giH_0); BaseH & giHt = *(ex.giH_t); BaseH & giHtdt = *(ex.giH_tdt); BasePassage(absolue,giB0,giBt,giBtdt,giH0,giHt,giHtdt,Aa0,Aat,Aatdt); return ex; }; // cas où l'on veut les matrices de passages à 0 et final // voir Deformation.h pour plus d'info // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer // (voir Deformation.h pour un descriptif plus complet) // si absolue = true: on fait un passage vers la base absolue // si = false : on fait un passage vers une base ad hoc void Deformation::BasePassage (bool absolue,const BaseB & giB0,const BaseB & giB,const BaseH & giH0,const BaseH & giH, Mat_pleine& Aa0,Mat_pleine& Aafin) { // determination des matrices de transformation de base int dim = giB0.NbVecteur(); // dim_espace X nb_vecteur X taille_matrice // cas d'une sortie en globale // 1X1X1 ou 2X2X2 ou 3X3X3 if ((dim == ParaGlob::Dimension()) && (Aa0.Nb_ligne() == dim)) { // --- ici il n'y a pas a priori de repère ad hoc, donc le calcul ne dépend pas de "absolue" // petite vérif #ifdef MISE_AU_POINT if ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) && (Aafin.Nb_ligne() != dim) && (Aafin.Nb_colonne() !=dim)) { cout << "\nErreur1 : les matrices Aa0 et /ou Aafin ne sont pas correctement" << " dimensionnees ! \n"; cout << "\n Aa0= "; Aa0.Affiche(); cout << "\n Aafin= "; Aafin.Affiche(); cout << "void Deformation::BasePassage( \n"; Sortie(1); }; #endif for (int i=1;i<=dim;i++) for (int j=1;j<=dim;j++) {Aa0 (i,j) = giH0(i)(j); Aafin(i,j) =giH(i)(j); }; } else if ((dim==2)&&(ParaGlob::Dimension()==3)) // cela comprend les cas: 3X2X2 -> un repère local ad hoc en 2D // 3X2X3 -> un repère local ad hoc en 3D // ==== cas d'élément de membrane en 3D ==== {// 1) si absolue = false: l'objectif est de determiner un repere pertinant dans le cas de membrane . // choix : un repere qui appartiend a la facette, obtenu apres projection // du repere global //------ cas de la config initiale, on regarde si la projection de I1 n'est pas trop petite // def de la normale a la facette // 2) si absolue = true; on complète le repère des gi avec la normale et la matrice de passage // correspond au passage des gi complètés -> I_a Coordonnee N = (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer(); Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1) double norve = ve.Norme(); Tableau vi(2); // les vecteurs plans orthonormes de la facette if (!absolue) {Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1) double norve = ve.Norme(); Tableau vi(2); // les vecteurs plans orthonormes de la facette if (norve >= 0.01) { vi(2) = ve.Normer(); vi(1) = Util::ProdVec_coor(vi(2),N); } else { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N) vi(1) = ve.Normer(); vi(2) = Util::ProdVec_coor(N,vi(1)); }; for (int al=1 ;al<=2;al++) {Aa0(1,al) = giH0.Coordo(1) * vi(al) ; Aa0(2,al) = giH0.Coordo(2) * vi(al) ; }; // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur // comme les vi sont normaux à N, le troisième vecteur est le vecteur N // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis // du troisième vecteur qui n'est autre que N if (Aa0.Nb_ligne()==3) // ici on a Ip_3 == N et également g_3=g^3=N {for (int al=1 ;al<=2;al++) {Aa0(3,al) = N * vi(al) ; Aa0(al,3) = giH0.Coordo(al) * N ; }; Aa0(3,3)= 1.; // == N . N }; } else // cas on l'on veut le passage des gi et N vers I_a {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i for (int al=1 ;al < 4;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aa0(2,al) = giH0.Coordo(2)(al) ; }; // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N Aa0.RemplaceLigneSpe(3,N.Vect()); }; //------ cas de la config finale, N = (Util::ProdVec_coorBN(giB(1),giB(2))).Normer(); if (!absolue) {ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec(N,I1) norve = ve.Norme(); Tableau Aa(2); if (norve >= ConstMath::petit) { Aa(2) = ve.Normer(); Aa(1) = Util::ProdVec_coor(Aa(2),N); } else { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N) Aa(1) = ve.Normer(); Aa(2) = Util::ProdVec_coor(N,Aa(1)); }; for (int be=1;be<=2;be++) { Aafin(1,be) = giH.Coordo(1) * Aa(be); Aafin(2,be) = giH.Coordo(2) * Aa(be); }; // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur // comme les vi sont normaux à N, le troisième vecteur est le vecteur N // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis // du troisième vecteur qui n'est autre que N if (Aafin.Nb_ligne()==3) // ici on a Ip_3 == N et également g_3=g^3=N {for (int al=1 ;al<=2;al++) {Aafin(3,al) = N * vi(al) ; Aafin(al,3) = giH.Coordo(al) * N ; }; Aafin(3,3)= 1.; // == N . N }; } else // cas on l'on veut le passage des gi et N vers I_a {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i for (int al=1 ;al < 4;al++) {Aafin(1,al) = giH.Coordo(1)(al) ; Aafin(2,al) = giH.Coordo(2)(al) ; }; // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N Aafin.RemplaceLigneSpe(3,N.Vect()); }; } else if (dim==1) // ==== cas des éléments 1D en espace 1D, 2D ou 3D ==== { if (!absolue) {switch (ParaGlob::Dimension()) { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début {cout << "\nErreur : bug!! on ne devrait pas passer ici \n"; cout << "void Deformation::BasePassage( \n"; Sortie(1); break; } case 3: // on est dans un espace 3D, ici on ne fait que le particulier à 3D et le reste est // fait dans le case 2: qui suit // 3X1X1 ou 3X1X2 ou 3X1X3, 2X1X1 , 2X1X2 if (Aa0.Nb_ligne() == 3 ) // 3X1X3 { // tous les tenseurs vont utiliser que le premier vecteur, donc le troisième peut être quelconque // et l'expression de giH(3) n'existant pas on dit que par défaut (et par simplicité) // giH(3) = 1 * IP(3) d'où Aa0 (3,3) = Aafin(3,3) = 1.; // et on initialise les autres composantes au cas où Aa0 (1,3) = Aa0 (3,1) = Aafin(1,3) = Aafin(3,1) = 0.; Aa0 (2,3) = Aa0 (3,2) = Aafin(2,3) = Aafin(3,2) = 0.; // pas de break, on continue sur le 2D }; case 2: // on est dans un espace 2D, 3X1X1 ou 3X1X2 ou 3X1X3 { // le premier vecteur intéressant c'est le vecteur collinéaire avec gH(1), mais normé double norme0 = giH0(1).Norme(); double norme = giH(1).Norme(); Aa0 (1,1) = norme0; Aafin(1,1) = norme; // fin du cas 3X1X1 et 2X1X1 if (Aa0.Nb_ligne() > 1) // 3X1X2 , 3X1X3 , 2X1X2 // tous les tenseurs vont utiliser que le premier vecteur, donc le second peut être quelconque // et l'expression de giH(2) n'existant pas on dit que par défaut (et par simplicité) // giH(2) = 1 * IP(2) d'où {Aa0 (2,2) = Aafin(2,2) = 1.; // et on initialise les autres composantes au cas où Aa0 (1,2) = Aa0 (2,1) = Aafin(1,2) = Aafin(2,1) = 0.; }; break; } default: cout << "\n erreur grossiere de dimension !! \n Deformation::BasePassage(.. "; Sortie(1); }; } else // sinon on veut arriver en Ia { // On ne connait que le premier vecteur et normalement c'est seulement celui-là qui est // utilisé, par contre il faut complèter la matrice pour qu'elle ne soit pas singulière Aa0.Initialise(0.);Aafin.Initialise(0.); switch (ParaGlob::Dimension()) { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début {cout << "\nErreur : bug!! on ne devrait pas passer ici \n"; cout << "void Deformation::BasePassage( \n"; Sortie(1); break; } case 3: // on est dans un espace 3D, {CoordonneeH V02(3); CoordonneeH V03(3); // on calcule deux vecteurs arbitraires normaux, avec un résultat orthonormé V2,V3 // mais pas giH0(1) ! MathUtil2::Def_vecteurs_plan(giH0(1),V02,V03); // idem pour le final CoordonneeH V2(3); CoordonneeH V3(3); MathUtil2::Def_vecteurs_plan(giH(1),V2,V3); int bornesup = ParaGlob::Dimension() +1; for (int al=1 ;al < bornesup;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aafin(1,al) = giH.Coordo(1)(al); Aa0(2,al) = V02(al) ; Aafin(2,al) = V2(al) ; Aa0(3,al) = V03(al) ; Aafin(3,al) = V3(al) ; }; break; } case 2: // on est dans un espace 2D, {CoordonneeH V02(2); // on calcule le vecteur normal, // mais pas giH0(1) ! MathUtil2::Def_vecteurs_plan(giH0(1),V02); // idem pour le final CoordonneeH V2(2); MathUtil2::Def_vecteurs_plan(giH(1),V2); int bornesup = ParaGlob::Dimension() +1; for (int al=1 ;al < bornesup;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aafin(1,al) = giH.Coordo(1)(al); Aa0(2,al) = V02(al) ; Aafin(2,al) = V2(al) ; }; break; } default: cout << "\n erreur2 grossiere de dimension !! \n Deformation::BasePassage(.. "; Sortie(1); }; }; } else {// pour les autres cas on ramene la matrice identite #ifdef MISE_AU_POINT if ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) && (Aafin.Nb_ligne() != dim) && (Aafin.Nb_colonne() !=dim)) { cout << "\nErreur : les matrices Aa0 et /ou Aafin ne sont pas correctement" << " dimensionnees !\n"; cout << "void Deformation::BasePassage( \n"; Sortie(1); }; #endif for (int i=1;i<=dim;i++) { for (int j=1;j<=dim;j++) {Aa0 (i,j) = 0.;Aafin(i,j) = 0.;} Aa0 (i,i) = 1.; Aafin(i,i) = 1.; }; }; // retour return; }; // cas où l'on veut les matrices de passages à 0 t et tdt // voir Deformation.h pour plus d'info // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer // (voir Deformation.h pour un descriptif plus complet) void Deformation::BasePassage(bool absolue,const BaseB & giB0,const BaseB & giB_t,const BaseB & giB_tdt ,const BaseH & giH0,const BaseH & giH_t,const BaseH & giH_tdt ,Mat_pleine& Aa0,Mat_pleine& Aa_t,Mat_pleine& Aa_tdt) { // determination des matrices de transformation de base int dim = giB0.NbVecteur(); // dim_espace X nb_vecteur X taille_matrice // cas d'une sortie en globale // 1X1X1 ou 2X2X2 ou 3X3X3 if ((dim == ParaGlob::Dimension()) && (Aa0.Nb_ligne() == dim)) { // --- ici il n'y a pas a priori de repère ad hoc, donc le calcul ne dépend pas de "absolue" // petite vérif #ifdef MISE_AU_POINT if ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) && (Aa_t.Nb_ligne() != dim) && (Aa_t.Nb_colonne() !=dim) && (Aa_tdt.Nb_ligne() != dim) && (Aa_tdt.Nb_colonne() !=dim)) { cout << "\nErreur1 : les matrices Aa0 et /ou Aa_t et / ou Aa_tdt ne sont pas correctement" << " dimensionnees ! \n"; cout << "\n Aa0= "; Aa0.Affiche(); cout << "\n Aa_t= "; Aa_t.Affiche(); cout << "\n Aa_tdt= "; Aa_tdt.Affiche(); cout << "void Deformation::BasePassage( \n"; Sortie(1); }; #endif for (int i=1;i<=dim;i++) for (int j=1;j<=dim;j++) {Aa0 (i,j) = giH0(i)(j); Aa_t(i,j) =giH_t(i)(j); Aa_tdt(i,j) =giH_tdt(i)(j); }; } else if ((dim==2)&&(ParaGlob::Dimension()==3)) // cela comprend les cas: 3X2X2 -> un repère local ad hoc en 2D // 3X2X3 -> un repère local ad hoc en 3D // ==== cas d'élément de membrane en 3D ==== {// 1) si absolue = false: l'objectif est de determiner un repere pertinant dans le cas de membrane . // choix : un repere qui appartiend a la facette, obtenu apres projection // du repere global //------ cas de la config initiale, on regarde si la projection de I1 n'est pas trop petite // def de la normale a la facette // 2) si absolue = true; on complète le repère des gi avec la normale et la matrice de passage // correspond au passage des gi complètés -> I_a Coordonnee N = (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer(); Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1), donc normal à N double norve = ve.Norme(); Tableau vi(2); // les vecteurs plans orthonormes de la facette if (!absolue) {if (norve >= 0.01) { vi(2) = ve.Normer(); vi(1) = Util::ProdVec_coor(vi(2),N);// donc normal à N } else { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N), donc normal à N vi(1) = ve.Normer(); vi(2) = Util::ProdVec_coor(N,vi(1));// donc normal à N }; // maintenant expression dans le repère local // Aa^i_{.a} = g^i . Ip_a avec les Ip_a == vi(a) for (int al=1 ;al<=2;al++) {Aa0(1,al) = giH0.Coordo(1) * vi(al) ; Aa0(2,al) = giH0.Coordo(2) * vi(al) ; }; // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur // comme les vi sont normaux à N, le troisième vecteur est le vecteur N // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis // du troisième vecteur qui n'est autre que N if (Aa0.Nb_ligne()==3) // ici on a Ip_3 == N et également g_3=g^3=N {for (int al=1 ;al<=2;al++) {Aa0(3,al) = N * vi(al) ; Aa0(al,3) = giH0.Coordo(al) * N ; }; Aa0(3,3)= 1.; // == N . N }; } else // cas on l'on veut le passage des gi et N vers I_a {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i for (int al=1 ;al < 4;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aa0(2,al) = giH0.Coordo(2)(al) ; }; // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N Aa0.RemplaceLigneSpe(3,N.Vect()); }; //------ cas de la config à t, N = (Util::ProdVec_coorBN(giB_t(1),giB_t(2))).Normer(); Tableau Aa(2); if (!absolue) {ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec(N,I1) norve = ve.Norme(); if (norve >= 0.01) { Aa(2) = ve.Normer(); Aa(1) = Util::ProdVec_coor(Aa(2),N); } else { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N) Aa(1) = ve.Normer(); Aa(2) = Util::ProdVec_coor(N,Aa(1)); }; for (int be=1;be<=2;be++) { Aa_t(1,be) = giH_t.Coordo(1) * Aa(be); Aa_t(2,be) = giH_t.Coordo(2) * Aa(be); }; // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur // comme les vi sont normaux à N, le troisième vecteur est le vecteur N // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis // du troisième vecteur qui n'est autre que N if (Aa_t.Nb_ligne()==3) // ici on a Ip_3 == N et également g_3=g^3=N {for (int al=1 ;al<=2;al++) {Aa_t(3,al) = N * vi(al) ; Aa_t(al,3) = giH_t.Coordo(al) * N ; }; Aa_t(3,3)= 1.; // == N . N }; } else // cas on l'on veut le passage des gi et N vers I_a {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i for (int al=1 ;al < 4;al++) {Aa_t(1,al) = giH_t.Coordo(1)(al) ; Aa_t(2,al) = giH_t.Coordo(2)(al) ; }; // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N Aa_t.RemplaceLigneSpe(3,N.Vect()); }; //// ---- vérification que le déterminant n'est pas nul //{double det = Aa_t(1,1) * Aa_t(2,2) - Aa_t(1,2) * Aa_t(2,1); // if (Abs(det) < 0.00001) // cout << "\n erreur det0 null " << det << " dans Deformation::BasePassage( "; //}; //// ---- fin vérification //------ cas de la config finale à tdt, N = (Util::ProdVec_coorBN(giB_tdt(1),giB_tdt(2))).Normer(); if (!absolue) {ve.Change_Coordonnee(3,0.,-N(3),N(2)); // = ProdVec(N,I1) norve = ve.Norme(); if (norve >= 0.01) { Aa(2) = ve.Normer(); Aa(1) = Util::ProdVec_coor(Aa(2),N); } else { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N) Aa(1) = ve.Normer(); Aa(2) = Util::ProdVec_coor(N,Aa(1)); }; for (int be=1;be<=2;be++) { Aa_tdt(1,be) = giH_tdt.Coordo(1) * Aa(be); Aa_tdt(2,be) = giH_tdt.Coordo(2) * Aa(be); }; // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur // comme les vi sont normaux à N, le troisième vecteur est le vecteur N // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis // du troisième vecteur qui n'est autre que N if (Aa_tdt.Nb_ligne()==3) // ici on a Ip_3 == N et également g_3=g^3=N {for (int al=1 ;al<=2;al++) {Aa_tdt(3,al) = N * vi(al) ; Aa_tdt(al,3) = giH_tdt.Coordo(al) * N ; }; Aa_tdt(3,3)= 1.; // == N . N }; } else // cas on l'on veut le passage des gi et N vers I_a {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i for (int al=1 ;al < 4;al++) {Aa_tdt(1,al) = giH_tdt.Coordo(1)(al) ; Aa_tdt(2,al) = giH_tdt.Coordo(2)(al) ; }; // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N Aa_tdt.RemplaceLigneSpe(3,N.Vect()); }; //// ---- vérification que le déterminant n'est pas nul //{double det = Aa_tdt(1,1) * Aa_tdt(2,2) - Aa_tdt(1,2) * Aa_tdt(2,1); // if (Abs(det) < 0.00001) // cout << "\n erreur det0 null " << det << " dans Deformation::BasePassage( "; //}; //// ---- fin vérification } else if (dim==1) // ==== cas des éléments 1D en espace 1D, 2D ou 3D ==== { if (!absolue) {switch (ParaGlob::Dimension()) { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début {cout << "\nErreur : bug!! on ne devrait pas passer ici \n"; cout << "void Deformation::BasePassage( \n"; Sortie(1); break; } case 3: // on est dans un espace 3D, ici on ne fait que le particulier à 3D et le reste est // fait dans le case 2: qui suit // 3X1X1 ou 3X1X2 ou 3X1X3, 2X1X1 , 2X1X2 if (Aa0.Nb_ligne() == 3 ) // 3X1X3 { // tous les tenseurs vont utiliser que le premier vecteur, donc le troisième peut être quelconque // et l'expression de giH(3) n'existant pas on dit que par défaut (et par simplicité) // giH(3) = 1 * IP(3) d'où Aa0 (3,3) = Aa_t(3,3)= Aa_tdt(3,3) = 1.; // et on initialise les autres composantes au cas où Aa0 (1,3) = Aa0 (3,1) = Aa_t(1,3) = Aa_t(3,1) = Aa_tdt(1,3) = Aa_tdt(3,1) = 0.; Aa0 (2,3) = Aa0 (3,2) = Aa_t(2,3) = Aa_t(3,2) = Aa_tdt(2,3) = Aa_tdt(3,2) = 0.; // pas de break, on continue sur le 2D } case 2: // on est dans un espace 2D, 3X1X1 ou 3X1X2 ou 3X1X3 { // le premier vecteur intéressant c'est le vecteur collinéaire avec gH(1), mais normé double norme0 = giH0(1).Norme(); double normet = giH_t(1).Norme(); double normetdt = giH_tdt(1).Norme(); Aa0 (1,1) = norme0; Aa_t(1,1) = normet; Aa_tdt(1,1) = normetdt; // fin du cas 3X1X1 et 2X1X1 if (Aa0.Nb_ligne() > 1) // 3X1X2 , 3X1X3 , 2X1X2 // tous les tenseurs vont utiliser que le premier vecteur, donc le second peut être quelconque // et l'expression de giH(2) n'existant pas on dit que par défaut (et par simplicité) // giH(2) = 1 * IP(2) d'où {Aa0 (2,2) = Aa_t(2,2) = Aa_tdt(2,2)= 1.; // et on initialise les autres composantes au cas où Aa0 (1,2) = Aa0 (2,1) = Aa_t(1,2) = Aa_t(2,1)= Aa_tdt(1,2) = Aa_tdt(2,1) = 0.; }; break; } default: cout << "\n erreur grossiere de dimension !! \n Deformation::BasePassage(.. "; Sortie(1); }; } else // sinon on veut arriver en Ia { // On ne connait que le premier vecteur et normalement c'est seulement celui-là qui est // utilisé, par contre il faut complèter la matrice pour qu'elle ne soit pas singulière Aa0.Initialise(0.);Aa_t.Initialise(0.);Aa_tdt.Initialise(0.); switch (ParaGlob::Dimension()) { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début {cout << "\nErreur : bug!! on ne devrait pas passer ici \n"; cout << "void Deformation::BasePassage( \n"; Sortie(1); break; } case 3: // on est dans un espace 3D, {CoordonneeH V02(3); CoordonneeH V03(3); // on calcule deux vecteurs arbitraires normaux, avec un résultat orthonormé V2,V3 // mais pas giH0(1) ! MathUtil2::Def_vecteurs_plan(giH0(1),V02,V03); // idem pour t et tdt CoordonneeH V2_t(3); CoordonneeH V3_t(3); MathUtil2::Def_vecteurs_plan(giH_t(1),V2_t,V3_t); CoordonneeH V2_tdt(3); CoordonneeH V3_tdt(3); MathUtil2::Def_vecteurs_plan(giH_tdt(1),V2_tdt,V3_tdt); int bornesup = ParaGlob::Dimension() +1; for (int al=1 ;al < bornesup;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aa_t(1,al) = giH_t.Coordo(1)(al) ; Aa_tdt(1,al) = giH_tdt.Coordo(1)(al) ; Aa0(2,al) = V02(al) ; Aa_t(2,al) = V2_t(al) ; Aa_tdt(2,al) = V2_tdt(al) ; Aa0(3,al) = V03(al) ; Aa_t(3,al) = V3_t(al) ; Aa_tdt(3,al) = V3_tdt(al) ; }; break; } case 2: // on est dans un espace 2D, {CoordonneeH V02(2); // on calcule le vecteur normal, // mais pas giH0(1) ! MathUtil2::Def_vecteurs_plan(giH0(1),V02); // idem pour t et tdt CoordonneeH V2_t(3); MathUtil2::Def_vecteurs_plan(giH_t(1),V2_t); CoordonneeH V2_tdt(3); MathUtil2::Def_vecteurs_plan(giH_tdt(1),V2_tdt); int bornesup = ParaGlob::Dimension() +1; for (int al=1 ;al < bornesup;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aa_t(1,al) = giH_t.Coordo(1)(al) ; Aa_tdt(1,al) = giH_tdt.Coordo(1)(al) ; Aa0(2,al) = V02(al) ; Aa_t(2,al) = V2_t(al) ; Aa_tdt(2,al) = V2_tdt(al) ; }; break; } default: cout << "\n erreur2 grossiere de dimension !! \n Deformation::BasePassage(.. "; Sortie(1); }; }; } else {// pour les autres cas on ramene la matrice identite #ifdef MISE_AU_POINT if ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) && (Aa_t.Nb_ligne() != dim) && (Aa_t.Nb_colonne() !=dim) && (Aa_tdt.Nb_ligne() != dim) && (Aa_tdt.Nb_colonne() !=dim)) { cout << "\nErreur : les matrices Aa0 et /ou Aa_t et /ou Aa_tdt ne sont pas correctement" << " dimensionnees !\n"; cout << "void Deformation::RemontImp( \n"; Sortie(1); }; #endif for (int i=1;i<=dim;i++) { for (int j=1;j<=dim;j++) {Aa0 (i,j) = 0.;Aa_t(i,j) = 0.;Aa_tdt(i,j) = 0.;} Aa0 (i,i) = 1.; Aa_t(i,i) = 1.;Aa_tdt(i,i) = 1.; }; }; // retour return; }; // cas où l'on veut la matrice de passage à 0 uniquement // Aa(i,a) = Aa^i_{.a}, avec g^i = Aa^i_{.a} * Ip^a // tout ce passe comme si Ip^a est la nouvelle base vers laquelle on veut évoluer // (voir Deformation.h pour un descriptif plus complet) void Deformation::BasePassage(bool absolue,const BaseB & giB0,const BaseH & giH0,Mat_pleine& Aa0) { // determination des matrices de transformation de base int dim = giB0.NbVecteur(); // dim_espace X nb_vecteur X taille_matrice // cas d'une sortie en globale // 1X1X1 ou 2X2X2 ou 3X3X3 if ((dim == ParaGlob::Dimension()) && (Aa0.Nb_ligne() == dim)) { // petite vérif #ifdef MISE_AU_POINT if ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim)) { cout << "\nErreur1 : la matrice Aa0 n'est pas correctement" << " dimensionnee ! \n"; cout << "\n Aa0= "; Aa0.Affiche(); cout << "void Deformation::BasePassage( \n"; Sortie(1); }; #endif for (int i=1;i<=dim;i++) for (int j=1;j<=dim;j++) {Aa0 (i,j) = giH0(i)(j); }; } else if ((dim==2)&&(ParaGlob::Dimension()==3)) // cela comprend les cas: 3X2X2 -> un repère local ad hoc en 2D // 3X2X3 -> un repère local ad hoc en 3D // ==== cas d'élément de membrane en 3D ==== {// 1) si absolue = false: l'objectif est de determiner un repere pertinant dans le cas de membrane . // choix : un repere qui appartiend a la facette, obtenu apres projection // du repere global //------ cas de la config initiale, on regarde si la projection de I1 n'est pas trop petite // def de la normale a la facette // 2) si absolue = true; on complète le repère des gi avec la normale et la matrice de passage // correspond au passage des gi complètés -> I_a Coordonnee N ( (Util::ProdVec_coorBN(giB0(1),giB0(2))).Normer() ); Coordonnee ve(0.,-N(3),N(2)); // = ProdVec(N,I1), donc normal à N double norve = ve.Norme(); Tableau vi(2); // les vecteurs plans orthonormes de la facette if (!absolue) {if (norve >= 0.01) { vi(2) = ve.Normer(); vi(1) = Util::ProdVec_coor(vi(2),N);// donc normal à N } else { ve.Change_Coordonnee(3,N(3),0.,-N(1)); // = ProdVec(I2,N), donc normal à N vi(1) = ve.Normer(); vi(2) = Util::ProdVec_coor(N,vi(1));// donc normal à N }; // maintenant expression dans le repère local for (int al=1 ;al<=2;al++) {Aa0(1,al) = giH0.Coordo(1) * vi(al) ; Aa0(2,al) = giH0.Coordo(2) * vi(al) ; }; // si on veut une matrice 3x3, il faut complèter la matrice avec un troisième vecteur // comme les vi sont normaux à N, le troisième vecteur est le vecteur N // qui ne peut pas s'exprimer dans le repère local des gi donc on considère qu'il s'exprime vis-à-vis // du troisième vecteur qui n'est autre que N if (Aa0.Nb_ligne()==3) // ici on a Ip_3 == N et également g_3=g^3=N {for (int al=1 ;al<=2;al++) {Aa0(3,al) = N * vi(al) ; Aa0(al,3) = giH0.Coordo(al) * N ; }; Aa0(3,3)= 1.; // == N . N }; } else // cas on l'on veut le passage des gi et N vers I_a {// g^i = Aa^i_{.a} * I^a -> donc Aa^i_{.a} c'est directement les coordonnées de g^i for (int al=1 ;al < 4;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aa0(2,al) = giH0.Coordo(2)(al) ; }; // pour le troisième: N = Aa^3_{.a} * I^a -> c'est aussi directement les coordonnées de N Aa0.RemplaceLigneSpe(3,N.Vect()); }; //// ---- vérification que le déterminant n'est pas nul //{double det = Aa0(1,1) * Aa0(2,2) - Aa0(1,2) * Aa0(2,1); // if (Abs(det) < 0.00001) // cout << "\n erreur det0 null " << det << " dans Deformation::BasePassage( "; //}; //// ---- fin vérification } else if (dim==1) // ==== cas des éléments 1D en espace 1D, 2D ou 3D ==== { if (!absolue) {switch (ParaGlob::Dimension()) { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début {cout << "\nErreur : bug!! on ne devrait pas passer ici \n"; cout << "void Deformation::BasePassage( \n"; Sortie(1); break; } case 3: // on est dans un espace 3D, ici on ne fait que le particulier à 3D et le reste est // fait dans le case 2: qui suit // 3X1X1 ou 3X1X2 ou 3X1X3, 2X1X1 , 2X1X2 if (Aa0.Nb_ligne() == 3 ) // 3X1X3 { // tous les tenseurs vont utiliser que le premier vecteur, donc le troisième peut être quelconque // et l'expression de giH(3) n'existant pas on dit que par défaut (et par simplicité) // giH(3) = 1 * IP(3) d'où Aa0 (3,3) = 1.; // et on initialise les autres composantes au cas où Aa0 (1,3) = Aa0 (3,1) = 0.; Aa0 (2,3) = Aa0 (3,2) = 0.; // pas de break, on continue sur le 2D } case 2: // on est dans un espace 2D, 3X1X1 ou 3X1X2 ou 3X1X3 { // le premier vecteur intéressant c'est le vecteur collinéaire avec gH(1), mais normé double norme0 = giH0(1).Norme(); Aa0 (1,1) = norme0; // fin du cas 3X1X1 et 2X1X1 if (Aa0.Nb_ligne() > 1) // 3X1X2 , 3X1X3 , 2X1X2 // tous les tenseurs vont utiliser que le premier vecteur, donc le second peut être quelconque // et l'expression de giH(2) n'existant pas on dit que par défaut (et par simplicité) // giH(2) = 1 * IP(2) d'où {Aa0 (2,2) = 1.; // et on initialise les autres composantes au cas où Aa0 (1,2) = Aa0 (2,1) = 0.; }; break; } default: cout << "\n erreur grossiere de dimension !! \n Deformation::BasePassage(.. "; Sortie(1); }; } else // sinon on veut arriver en Ia { // On ne connait que le premier vecteur et normalement c'est seulement celui-là qui est // utilisé, par contre il faut complèter la matrice pour qu'elle ne soit pas singulière Aa0.Initialise(0.); switch (ParaGlob::Dimension()) { case 1: // normalement on ne devrait pas passer ici !! car ce cas est déjà traité au début {cout << "\nErreur : bug!! on ne devrait pas passer ici \n"; cout << "void Deformation::BasePassage( \n"; Sortie(1); break; } case 3: // on est dans un espace 3D, {CoordonneeH V02(3); CoordonneeH V03(3); // on calcule deux vecteurs arbitraires normaux, avec un résultat orthonormé V2,V3 // mais pas giH0(1) ! MathUtil2::Def_vecteurs_plan(giH0(1),V02,V03); int bornesup = ParaGlob::Dimension() +1; for (int al=1 ;al < bornesup;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aa0(2,al) = V02(al) ; Aa0(3,al) = V03(al) ; }; break; } case 2: // on est dans un espace 2D, {CoordonneeH V02(2); // on calcule le vecteur normal, // mais pas giH0(1) ! MathUtil2::Def_vecteurs_plan(giH0(1),V02); int bornesup = ParaGlob::Dimension() +1; for (int al=1 ;al < bornesup;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; Aa0(2,al) = V02(al) ; }; break; } default: cout << "\n erreur2 grossiere de dimension !! \n Deformation::BasePassage(.. "; Sortie(1); }; int bornesup = ParaGlob::Dimension() +1; for (int al=1 ;al < bornesup;al++) {Aa0(1,al) = giH0.Coordo(1)(al) ; if (al!=1) {Aa0 (al,al) = 1.;}; }; }; } else {// pour les autres cas on ramene la matrice identite #ifdef MISE_AU_POINT if ((Aa0.Nb_ligne() != dim) && (Aa0.Nb_colonne() !=dim) ) { cout << "\nErreur : la matrices Aa0 n'est pas correctement" << " dimensionnee !\n"; cout << "void Deformation::RemontImp( \n"; Sortie(1); }; #endif for (int i=1;i<=dim;i++) { for (int j=1;j<=dim;j++) {Aa0 (i,j) = 0.;} Aa0 (i,i) = 1.; }; }; // retour return; }; // on suppose que gijHH et gijBB ont déjà été calculé et sont donc transmis // on suppose que gijHH et gijBB ont déjà été calculé à t=0, et à temps void Deformation::Cal_deformation (Enum_dure temps, TenseurBB & epsBB) { // ici il y a le choix entre les différents types de calcul de la déformation (Almansi, Green-Lagrange .. switch (type_deformation) { case DEFORMATION_STANDART : {return Cal_Almansi_auTemps(temps,epsBB); break; } case DEFORMATION_LOGARITHMIQUE: {return Cal_logarithmique_auTemps(temps,epsBB); break; } case DEFORMATION_CUMU_LOGARITHMIQUE : case DEF_CUMUL_CORROTATIONNEL : case DEF_CUMUL_ROTATION_PROPRE : {return Cal_def_cumule_auTemps(temps,epsBB); break; } default : cout << "\nErreur : type de deformation ( " << Nom_type_deformation(type_deformation) << " ) non traite !\n"; cout << "Deformation::Cal_deformation (... \n"; Sortie(1); }; }; // calcul de la deformation au temps donné dans le cas d'une déformation d'Almansi // on suppose que les métriques en HH ou BB sont définis à 0 et au temps void Deformation::Cal_def_cumule_auTemps (Enum_dure , TenseurBB & ) { cout << "\n methode pas encore implante (dommage!) " << "\n Deformation::Cal_def_cumule_auTemps (.."; Sortie(1); }; // gestion du parcours de tous les points d'integration void Deformation::PremierPtInteg() { sauve_numInteg = numInteg; numInteg = 1; }; bool Deformation::DernierPtInteg() { sauve_numInteg = numInteg; // sauvegarde if (numInteg <= tabPhi->Taille()) return true; else return false; }; void Deformation::NevezPtInteg() { sauve_numInteg = numInteg; // sauvegarde numInteg++; }; // méthode pour revenir au pti précédant void Deformation::Retour_pti_precedant() {numInteg=sauve_numInteg;}; //==================================== méthodes protégées =============================== // calcul implicite dans le cas d'une déformation tensorielle cumulée const Met_abstraite::Impli& Deformation::Cal_implicit_def_cumule (bool ,TenseurBB & epsBB_tdt,Tableau & d_epsBB_tdt ,TenseurBB& DepsBB,TenseurBB& delta_epsBB,bool premier_calcul ,const Met_abstraite::Impli& ex) { // dans le cas où ce n'est pas le premier calcul on récupère les datas qui ne sont pas recalculée if (!premier_calcul) { Deformation::Stmet& a_0 = saveDefResul->meti_00; // pour simplifier Deformation::Stmet& a_t = saveDefResul->meti_t; // pour simplifier metrique->Recup_grandeur_0_t(*a_0.giB_,*a_0.giH_,*a_t.giB_,*a_t.giH_ ,*a_0.gijBB_,*a_0.gijHH_,*a_t.gijBB_,*a_t.gijHH_ ,*a_t.gradVmoyBB_,*a_t.jacobien_,*a_0.jacobien_); }; // 1- calcul de la base duale et de la métrique à t=0, utiliser en 3- // non déjà fait dans le calcul actuel de la métrique // const Met_abstraite::gijHH_0_et_giH_0& ex1 = metrique->Cal_gijHH_0_et_giH_0_apres_im_expli(); // 2- calcul de l'opérateur gradient F(a,b)=d Xc^a/d X0^b, stockage sous forme d'un spseudo-tenseur // alors que c'est un bi-tenseur !! permet ainsi une manipulation aisée int dim = ParaGlob::Dimension(); TenseurHB * ftHB = NevezTenseurHB(dim); for (int i=1;i<=dim;i++) { TenseurHB * interHB = Produit_tensorielHB((*ex.giH_0)(i),(*ex.giB_tdt)(i)); *ftHB += *interHB; delete interHB; }; // 3- calcul du gradient de vitesse // plusieurs possibilités, // 1) . soit on calcul le gradient à partir du champ de vitesse au temps finale // 2) . soit on calcul le gradient à partir d'une hypothèse de vitesse contante sur le pas de temps // avec la vitesse = delta X / delta t, le gradient étant déterminé à t+ (deltat/2) // 3) . soit on calcul le gradient à partir d'une hypothèse de vitesse moyenne au temps t+ (deltat/2) // c-a-d en utilisant la vitesse moyenne entre t et t+dt, ceci dans le cas de l'utilisation // directe des ddl vitesse /* switch (type_gradient_vitesse) // traitement en fonction du cas { case GRADVITESSE_V_TDT : // le gradient est déterminé à partir de ddl de vitesse à t+dt #ifdef MISE_AU_POINT // on vérifie que le gradient a été calculé dans l'appel de la métrique if (pas_de_gradV) { cout << "\nErreur : le gradient de vitesse n'a pas ete calcule dans la metrique" << " ce qui est contraire au type de calcul de gradient demande"; cout << "\n Deformation::Cal_implicit_def_cumule(... \n"; Sortie(1); }; #endif // donc ici le gradient est dans (*ex.gradVBB_tdt) break; case GRADVITESSE_VCONST : // calcul en considérant V constant =delta X/delta t // dans la config à t+(delta t)/2 // // 2) calcul du gradient à partir du champ de vitesse au temps final // if (!pas_de_gradV) // {// cas où le gradient a été calculé // DepsBB = 0.5 * ((*ex.gradVBB_tdt) + ex.gradVBB_tdt->Transpose());} // else // { // } break; case GRADVITESSE_VT_VTDT : //calcul à partir des ddl de vitesse : moyenne de t et t+dt, //dans la config à t+(delta t)/2 break; };*/ /* // epsBB_tdt et delta_epsBB est dimensionne auparavant epsBB_tdt = 0.5 * (*(ex.gijBB_tdt) - *(ex.gijBB_0)); delta_epsBB = 0.5 * (*(ex.gijBB_tdt) - *(ex.gijBB_t)); if (pas_de_gradV) { // on choisit une vitesse de déformation pour l'instant identique à deltaeps/t const VariablesTemps& vartemps = ParaGlob::Variables_de_temps(); // dans le cas où l'incrément de temps est nul on garde la vitesse actuelle double deltat=vartemps.IncreTempsCourant(); if (deltat >= ConstMath::trespetit) DepsBB = delta_epsBB/deltat; } else // cas où le gradient a été calculé DepsBB = 0.5 * ((*ex.gradVBB_tdt) + ex.gradVBB_tdt->Transpose()); // variation de la déformation / au ddl int d_epsBB_tdtTaille = d_epsBB_tdt.Taille(); for (int i=1; i<= d_epsBB_tdtTaille; i++) *(d_epsBB_tdt(i)) = 0.5 * (*((*(ex.d_gijBB_tdt))(i))); // calcul éventuelle de la dérivée seconde de la déformation if (pa.Var_D()) {// recup des variations secondes de la déformation int d2_epsBB_tdtTaille1 = d2_epsBB_tdt.Taille1(); for (int i=1; i<= d2_epsBB_tdtTaille1; i++) for (int j=1; j<= i; j++) // symétrie du tableau et du tenseur { *(d2_epsBB_tdt(i,j)) = 0.5 * (*((*(ex.d2_gijBB_tdt))(i,j))) ; *(d2_epsBB_tdt(j,i)) = *(d2_epsBB_tdt(i,j)) ; } } */ // vérification éventuelle // VerifCal_implicit( ex); // suppression des tenseurs de travail delete ftHB; // retour return ex; }; // calcul d'une vitesse de rotation cohérente avec un référentiel objectif particulier void Deformation::Cal_vite_rota_objectif(EnumTypeViteRotat type_rotation,bool variation ,const TenseurBB& gradVBB,const Tableau & d_gradVBB ,const TenseurBH& gij_HH_0,const TenseurBB& gij_BB,Tableau & d_gijBB ,const TenseurHH& gij_HH,Tableau & d_gijHH ,const TenseurBB& D_BB, Tableau & d_D_BB ,TenseurBB& OmegaBB,Tableau & d_OmegaBB) { // on calcul le pseudo vecteur W représentant le tenseur anti-symétrique: rotation du gradient de vitesse // TenseurBB W_BB = 0.5 * (gradVBB - gradVBB.Transpose()); int dima=Abs(gradVBB.Dimension()); /* CoordonneeB W_B(dima); switch (dima) { case 3: W_B(1) = W_BB(3,2);W_B(2) = W_BB(1,3);W_B(3) = W_BB(2,1);break; case 2: W_B(1) = W_BB(1,2);W_B(2) = 0.;break; // en attente case 1: W_B(1) = 0.;break;}; // en attente*/ int dimddl=d_gradVBB.Taille(); // dimension pour les variations switch (type_rotation) { case R_CORROTATIONNEL: OmegaBB =0.5 * (gradVBB - gradVBB.Transpose()); // dans le cas où l'on veut également des variations if (variation) { for (int i=1;i<=dimddl;i++) (*(d_OmegaBB(i))) = 0.5*( (*(d_gradVBB(i))) - (d_gradVBB(i))->Transpose()); } break; case R_REF_ROT_PROPRE: case R_ROT_LOGARITHMIQUE: // calcul des projections propres switch (dima) { case 3: {// simplification et transformation en tenseur de dim 3 (optimisation des calculs) const Tenseur3HH & gijHH_0 = (const Tenseur3HH &) gij_HH_0; const Tenseur3BB & gijBB = (const Tenseur3BB &) gij_BB; const Tenseur3HH & gijHH = (const Tenseur3HH &) gij_HH; // def des grandeurs de travail DimensionementVarLog(dima,variation,dimddl); // def du tenseur B_BH (cauchy_green gauche) (*B_BH_tr) = gijBB * gijHH_0; Tenseur3BH& B_BH= *((Tenseur3BH*) B_BH_tr); // calcul des valeurs propres et projection propres du tenseur B_BH Tableau & d_B_BH=*((Tableau *) d_B_BH_tr); if (variation) // dans le cas de variation, calcul des variation de B_BH { for (int ic=1;ic<=dimddl;ic++) {(*(*d_B_BH_tr)(ic))= (*(d_gijBB(ic))) * gijHH_0;};}; // def des grandeurs de travail Tableau & Palpha_BH=*((Tableau *) Palpha_BH_tr); // les projections propres Tableau >& d_Palpha_BH =*((Tableau >*) d_Palpha_BH_tr); // variation des projections propres // appel de la méthode calculant les grandeurs de travail int cas_ki; // indique le cas des valeurs propres traitées (cf TenseurBH) Val_et_projection_prop_tenseur(*B_BH_tr,*d_B_BH_tr,ki,*Palpha_BH_tr,variation,*d_ki,*d_Palpha_BH_tr,cas_ki); // -- calcul de la rotation // calcul de la vitesse de rotation en mixte Tenseur3BH D_BH(D_BB * gijHH); // tout d'abord: calcul de tenseurs intermédiaires Tableau P_i_D_BH(3); Tableau D_P_i_BH(3); P_i_D_BH(1)=((*Palpha_BH(1)) * D_BH); Tenseur3BH P_1_D_P_2_BH(P_i_D_BH(1) * (*Palpha_BH(2))); P_i_D_BH(2)=((*Palpha_BH(2)) * D_BH); Tenseur3BH P_2_D_P_1_BH(P_i_D_BH(2) * (*Palpha_BH(1))); D_P_i_BH(1)=(D_BH * (*Palpha_BH(1))); Tenseur3BH P_1_D_P_3_BH(P_i_D_BH(1) * (*Palpha_BH(3))); P_i_D_BH(3)=((*Palpha_BH(3)) * D_BH); Tenseur3BH P_3_D_P_1_BH(P_i_D_BH(3) * (*Palpha_BH(1))); D_P_i_BH(2)=(D_BH * (*Palpha_BH(2))); Tenseur3BH P_2_D_P_3_BH(P_i_D_BH(2) * (*Palpha_BH(3))); D_P_i_BH(3)=(D_BH * (*Palpha_BH(3))); Tenseur3BH P_3_D_P_2_BH(P_i_D_BH(3) * (*Palpha_BH(2))); double F_rot_1sur2= F_pour_rotat_objectif(type_rotation,ki(1)/ki(2)); double F_rot_1sur3= F_pour_rotat_objectif(type_rotation,ki(1)/ki(3)); double F_rot_2sur1= F_pour_rotat_objectif(type_rotation,ki(2)/ki(1)); double F_rot_3sur1= F_pour_rotat_objectif(type_rotation,ki(3)/ki(1)); double F_rot_2sur3= F_pour_rotat_objectif(type_rotation,ki(2)/ki(3)); double F_rot_3sur2= F_pour_rotat_objectif(type_rotation,ki(3)/ki(2)); OmegaBB =0.5 * (gradVBB - gradVBB.Transpose()); Tenseur3BH sup_OmegaBH ( F_rot_1sur2 * P_1_D_P_2_BH + F_rot_2sur1 * P_2_D_P_1_BH + F_rot_1sur3 * P_1_D_P_3_BH + F_rot_3sur1 * P_3_D_P_1_BH + F_rot_2sur3 * P_2_D_P_3_BH + F_rot_3sur2 * P_3_D_P_2_BH ); OmegaBB += sup_OmegaBH* gijBB ; // calcul éventuel des variations if (variation) { // mise sous forme indicée suivant l'ordre 1->12 2->21 3->13 4->31 5->23 6->32 à partir de 6 nombres Tableau P_i_D_j_BH(6); P_i_D_j_BH(1)=&P_1_D_P_2_BH; P_i_D_j_BH(2)=&P_2_D_P_1_BH; P_i_D_j_BH(3)=&P_1_D_P_3_BH; P_i_D_j_BH(4)=&P_3_D_P_1_BH; P_i_D_j_BH(5)=&P_2_D_P_3_BH; P_i_D_j_BH(6)=&P_3_D_P_2_BH; Tableau F_rot_isurj(6); F_rot_isurj(1)=&F_rot_1sur2; F_rot_isurj(2)=&F_rot_2sur1; F_rot_isurj(3)=&F_rot_1sur3; F_rot_isurj(4)=&F_rot_3sur1; F_rot_isurj(5)=&F_rot_2sur3; F_rot_isurj(6)=&F_rot_3sur2; // boucle sur les ddl for (int ici=1;ici<=dimddl;ici++) { const Tenseur3BB & dgijBB = *((Tenseur3BB*)(d_gijBB(ici))) ; // pour simplifier l'ecriture const Tenseur3HH & dgijHH = *((Tenseur3HH*)(d_gijHH(ici))) ; // pour simplifier l'ecriture const Tenseur3BB & dD_BB = *((Tenseur3BB*)(d_D_BB(ici))) ; // pour simplifier l'ecriture // variation du tenseur vitesse de déformation en mixte Tenseur3BH dD_BH(dD_BB * gijHH + D_BB * dgijHH); // variation du tenseur de rotation Tenseur3BB & dOmegaBB = *((Tenseur3BB* ) (d_OmegaBB(ici))); // pour simplifier l'ecriture dOmegaBB = 0.5*( (*(d_gradVBB(ici))) - (d_gradVBB(ici))->Transpose()); for (int m=1;m<=6;m++) { int i1=ccdex.iii(m); int i2=ccdex.jjj(m); dOmegaBB += (( Fprime_pour_rotat_objectif(type_rotation,ki(i1)/ki(i2)) / (ki(i2)*ki(i2)) * (ki(i2) * ((*d_ki)(ici))(i1) - ki(i1) * ((*d_ki)(ici))(i2)) ) * (* P_i_D_j_BH(m)) + (*F_rot_isurj(m)) * ( (*d_Palpha_BH(ici)(i2)) * D_P_i_BH(i2) + (*Palpha_BH(i1)) * dD_BH * (*Palpha_BH(i2)) + P_i_D_BH(i1) * (*d_Palpha_BH(ici)(i2)) )) * gijBB + sup_OmegaBH * dgijBB; }; }; }; // -- fin du grand "if variation " // effacement des tenseurs de travail for (int it=1;it<=dima;it++) delete Palpha_BH(it); if (variation) for (int ic=1;ic<=dimddl;ic++) for (int it=1;it<=dima;it++) delete d_Palpha_BH(ic)(it); break; } default: cout << "\n dimension (premier) non encore pris en compte: " << dima << "\n Deformation::Cal_vite_rota_objectif(..."; Sortie(1); } break; default: cout << "\n type de rotation non encore pris en compte" << "\n Deformation::Cal_vite_rota_objectif(..."; Sortie(1); }; // liberation des tenseurs intermediaires LibereTenseur(); }; // fonction f et f' utilisé dans la méthode Cal_vite_rota_objectif: double Deformation::F_pour_rotat_objectif(EnumTypeViteRotat type_rotation,const double& x) {switch (type_rotation) { case R_CORROTATIONNEL: return 0.; break; case R_REF_ROT_PROPRE: return (1.-sqrt(x))/(1.+sqrt(x)); break; case R_ROT_LOGARITHMIQUE: return (1.+x)/(1.-x) + 2./log(x); break; default: cout << "\n type de rotation non encore pris en compte: " << Nom_TypeViteRotat(type_rotation) << "\n Deformation::F_pour_rotat_objectif(..."; Sortie(1); } return 0.; // pour éviter le warning du retour }; double Deformation::Fprime_pour_rotat_objectif(EnumTypeViteRotat type_rotation,const double& x) {switch (type_rotation) { case R_CORROTATIONNEL: return 0.; break; case R_REF_ROT_PROPRE: return 1./(2.*x+sqrt(x)*(x+1.)); break; case R_ROT_LOGARITHMIQUE: {double logx = log(x); double log2_x=logx*logx; return 2.*(x*log2_x-x*x+2.*x-1.)/((x*x*x-2.*x*x+x)*log2_x); break;} default: cout << "\n type de rotation non encore pris en compte: " << Nom_TypeViteRotat(type_rotation) << "\n Deformation::Fprime_pour_rotat_objectif(..."; Sortie(1); } return 0.; // pour éviter le warning du retour }; // ----------------- méthodes de vérifications------- ---- void Deformation::VerifCal_implicit(bool gradV_instantane,const Met_abstraite::Impli & ex,TenseurBB& ) { // l'idée est de faire une vérification des dérivées à l'aide d'une méthode de différence finie int dim = ParaGlob::Dimension(); // dans le cas du premier passage on indique qu'il y a vérification if (indic_VerifCal_implicit == 0) { cout << "\n ****vérification du calcul de la déformation et des éléments de la métrique associé****"; cout << "\n Deformation::VerifCal_implicit \n"; } indic_VerifCal_implicit++; // on cré une seconde métrique pour éviter de détruire la métrique originale Met_abstraite metrique_bis(*metrique); // ici on considère que l'on a même nombre de ddl par noeud = dim // on va modifier chaque ddl de chaque noeud systématiquement int nbnoeud = tabnoeud->Taille(); // le deltat pour les différences finis double delta = ConstMath::unpeupetit; double mini_val = ConstMath::pasmalpetit; int numddl = 1; // le compteur de ddl bool erreur = false; // indicateur d'erreur bool premier_calcul=true; for (int inoeud=1;inoeud<=nbnoeud;inoeud++) {// on récupère les coordonnées du noeud Coordonnee coordtdt = (*tabnoeud)(inoeud)->Coord2(); for (int ix= 1;ix<=dim;ix++,numddl++) { Coordonnee X(dim); X(ix) += delta; (*tabnoeud)(inoeud)->Ajout_coord2(X); // appel de la métrique Met_abstraite::Expli_t_tdt ex_n =metrique_bis.Cal_explicit_tdt (*tabnoeud,premier_calcul,(*tabDphi)(numInteg),nbNoeud,(*tabPhi)(numInteg),gradV_instantane); premier_calcul=false; // calcul des dérivées numériques et vérification for (int j=1;j<=dim;j++) { // variation des vecteurs giB_tdt CoordonneeB dgiB = ((*ex_n.giB_tdt)(j) -(*ex.giB_tdt)(j))/delta; for (int i=1;i<=dim;i++) if (diffpourcent(dgiB(i),(*ex.d_giB_tdt)(numddl)(j)(i),MaX(Dabs(dgiB(i)),Dabs((*ex.d_giB_tdt)(numddl)(j)(i))),0.05)) {if (MiN(Dabs(dgiB(i)),Dabs((*ex.d_giB_tdt)(numddl)(j)(i))) <= mini_val) {if ( MaX(Dabs(dgiB(i)),Dabs((*ex.d_giB_tdt)(numddl)(j)(i))) > 50.*delta) erreur = true;} else erreur = true; }; // variation des vecteurs giH_tdt CoordonneeH dgiH = ((*ex_n.giH_tdt)(j) - (*ex.giH_tdt)(j))/delta; for (int i=1;i<=dim;i++) if (diffpourcent(dgiH(i),(*ex.d_giH_tdt)(numddl)(j)(i),MaX(Dabs(dgiH(i)),Dabs((*ex.d_giH_tdt)(numddl)(j)(i))),0.05)) {if (MiN(Dabs(dgiH(i)),Dabs((*ex.d_giH_tdt)(numddl)(j)(i))) <= mini_val) {if ( MaX(Dabs(dgiH(i)),Dabs((*ex.d_giH_tdt)(numddl)(j)(i))) > 50.*delta) erreur = true;} else erreur = true; }; } // variation du tenseur gijBB_tdt TenseurBB * gijBB = NevezTenseurBB(*ex_n.gijBB_tdt); *gijBB = (*ex_n.gijBB_tdt - *ex.gijBB_tdt) / delta; for (int i1=1;i1<=dim;i1++) for (int j1=1;j1<=dim;j1++) if (diffpourcent((*gijBB)(i1,j1),(*(*ex. d_gijBB_tdt)(numddl))(i1,j1), MaX(Dabs((*gijBB)(i1,j1)),Dabs((*(*ex. d_gijBB_tdt)(numddl))(i1,j1))),0.05)) {if (MiN(Dabs((*gijBB)(i1,j1)),Dabs((*(*ex. d_gijBB_tdt)(numddl))(i1,j1))) <= mini_val) {if( MaX(Dabs((*gijBB)(i1,j1)),Dabs((*(*ex. d_gijBB_tdt)(numddl))(i1,j1))) > 50.*delta) erreur = true;} else erreur = true; }; // variation du tenseur gijHH_tdt TenseurHH * gijHH = NevezTenseurHH(*ex_n.gijHH_tdt); *gijHH = (*ex_n.gijHH_tdt - *ex.gijHH_tdt) / delta; for (int i1=1;i1<=dim;i1++) for (int j1=1;j1<=dim;j1++) if (diffpourcent((*gijHH)(i1,j1),(*(*ex. d_gijHH_tdt)(numddl))(i1,j1), MaX(Dabs((*gijHH)(i1,j1)),Dabs((*(*ex. d_gijHH_tdt)(numddl))(i1,j1))),0.05)) {if (MiN(Dabs((*gijHH)(i1,j1)),Dabs((*(*ex. d_gijHH_tdt)(numddl))(i1,j1))) <= mini_val) {if( MaX(Dabs((*gijHH)(i1,j1)),Dabs((*(*ex. d_gijHH_tdt)(numddl))(i1,j1))) > 50.*delta) erreur = true;} else erreur = true; }; // variation du jacobien double djaco = ((*ex_n.jacobien_tdt) - (*ex.jacobien_tdt))/delta; if (diffpourcent(djaco,(*ex.d_jacobien_tdt)(numddl),MaX(Dabs(djaco),Dabs((*ex.d_jacobien_tdt)(numddl))),0.05)) if (MiN(Dabs(djaco),Dabs((*ex.d_jacobien_tdt)(numddl))) <= mini_val) {if( MaX(Dabs(djaco),Dabs((*ex.d_jacobien_tdt)(numddl))) > 50.*delta) erreur = true; else erreur = true; }; // effacement des tenseurs intermédiaires delete gijBB; delete gijHH; // maintenant on remet les coordonnées du noeud à l'état initial (*tabnoeud)(inoeud)->Change_coord2(coordtdt); } // fin de boucle sur la dimension de coordonnée } // fin de boucle sur les noeuds // message d'erreur si besoin if (erreur) { cout << "\n erreur dans le calcul analytique des dérivees de la metrique"; cout << "\n Deformation::VerifCal_implicit(.." << " , numero d'increment = " << indic_VerifCal_implicit; Sortie(1); } };