// FICHIER : SfeMembT.cc
// CLASSE : SfeMembT
// 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-2021 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
using namespace std; //introduces namespace std
#include
#include "Sortie.h"
#include "MathUtil.h"
#include "SfeMembT.h"
#include "TypeConsTens.h"
#include "FrontPointF.h"
#include "Loi_Umat.h"
#include "ExceptionsElemMeca.h"
#include "TypeQuelconqueParticulier.h"
#include "Coordonnee2.h"
#include "Coordonnee3.h"
#include "Util.h"
// calcul de la nouvelle épaisseur (sans raideur) avec métrique en explicite
// cas où l'épaisseur est stocké dans l'élément
// mise à jour du volume au pti
void SfeMembT::CalEpaisseurAtdtExp_et_vol_pti(const double& epaisseur0, const ParaAlgoControle &
,const double & epaisseur_t, PtIntegMecaInterne & ptIntegMeca
,double & epaisseur_tdt, const Met_abstraite::Expli_t_tdt& ex)
{ // on commence par calculer la trace du tenseur des contraintes
double traceSig = (ptIntegMeca.SigHH_const() * (* ex.gijBB_tdt)).Trace();
double traceSig_t = (ptIntegMeca.SigHH_t_const() * (* ex.gijBB_t)).Trace();
const double& troisK = 3. * ptIntegMeca.ModuleCompressibilite_const(); // récup de la compressibilité
// calcul de la nouvelle épaisseur
//--- vérification et gestion des cas particuliers ---
bool cas_particulier=false;
{// on suppose un module de compressibilité positif sinon ce n'est pas normal
if (troisK < 0.)
{if (ParaGlob::NiveauImpression()>2)
cout << "\n erreur*** on a trouve une compressibilite negative = " << troisK/3.
<< "\n SfeMembT::CalEpaisseurAtdtExp_et_vol_pti(...";
// on ne change pas l'épaisseur
cas_particulier = true;
};
// classiquement on suppose que troisK doit-être bien supérieur à traceSig:
// on considère un facteur 10 arbitraire
// si ce n'est pas le cas, on risque d'avoir un calcul d'épaisseur erroné
if (Dabs(traceSig) > 10. * Dabs(troisK/3.))
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " le coef de compressibilite = "< (troisK/3. - ConstMath::petit))
// dans le cas où delta traceSig > troisK, cela va donner une épaisseur négative !!
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite = "< 10. * Dabs(troisK/3.))
)
// on ne va pas pouvoir peut-être calculer une nouvelle épaisseur
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite = "<2)
cout << "\n erreur*** on a trouve une compressibilite negative = " << troisK
<< "\n SfeMembT::CalEpaisseurAtdtImp_et_vol_pti...) ";
// on ne change pas l'épaisseur
cas_particulier = true;
};
// classiquement on suppose que troisK doit-être bien supérieur à traceSig:
// on considère un facteur 10 arbitraire
// si ce n'est pas le cas, on risque d'avoir un calcul d'épaisseur erroné
if (Dabs(traceSig) > 10. * Dabs(troisK/3.))
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " le coef de compressibilite = "< (troisK/3. - ConstMath::petit))
// dans le cas où delta traceSig > troisK, cela va donner une épaisseur négative !!
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite = "< 10. * Dabs(troisK/3.))
)
// on ne va pas pouvoir peut-être calculer une nouvelle épaisseur
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite = "<doCoMemb; // pour simplifier l'écriture
int nbtotsurf =CoSfe->eleCentre->Nbi();
int nbtotepais =(CoSfe->segment).Nbi();
int nbi = nbtotsurf * nbtotepais;
for (int nisur =1; nisur<= nbtotsurf; nisur++) // boucle sur les pt d'integ de surface
for (int niepais =1; niepais<= nbtotepais; niepais++, indice++) // pt d'integ d'epaisseur
// for (int i=1;i<= nombre->nbi;i++)
{ // cas de la compressibilité
const double& troisK = 3. * (*lesPtIntegMecaInterne)(indice).ModuleCompressibilite_const();
troisK_moy += troisK;
// cas des jacobiens
const double& jacobien_0 = *(tabSaveDefDon(indice)->Meti_00().jacobien_);
if (atdt)
{ const double& jacobien_ini = *(tabSaveDefDon(indice)->Meti_t().jacobien_);
jacobien_moy_ini += jacobien_ini;
const double& jacobien_fin = *(tabSaveDefDon(indice)->Meti_tdt().jacobien_);
jacobien_moy_fin += jacobien_fin;
// cas de la trace de sigma
const double traceSig = (*lesPtIntegMecaInterne)(indice).SigHH_const() && (*(tabSaveDefDon(indice)->Meti_tdt().gijBB_));
traceSig_moy += traceSig;
const double traceSig_ini = (*lesPtIntegMecaInterne)(indice).SigHH_t_const() && (*(tabSaveDefDon(indice)->Meti_t().gijBB_));
traceSig_moy_ini += traceSig_ini;
(*lesPtIntegMecaInterne)(indice).Volume_pti() *= (epais.epaisseur_t * jacobien_ini) / jacobien_fin
* troisK / (troisK - traceSig+traceSig_ini); // la pression = - traceSig/3 !!!
}
else
{ const double& jacobien_ini = *(tabSaveDefDon(indice)->Meti_00().jacobien_);
jacobien_moy_ini += jacobien_ini;
const double& jacobien_fin = *(tabSaveDefDon(indice)->Meti_t().jacobien_);
jacobien_moy_fin += jacobien_fin;
// cas de la trace de sigma
double traceSig = (*lesPtIntegMecaInterne)(indice).SigHH_const() && (*(tabSaveDefDon(indice)->Meti_t().gijBB_));
traceSig_moy += traceSig;
(*lesPtIntegMecaInterne)(indice).Volume_pti() *= (epais.epaisseur0 * jacobien_ini) / jacobien_fin
* troisK / (troisK - traceSig);
};
};
jacobien_moy_ini /= nbi;
jacobien_moy_fin /= nbi;
traceSig_moy_ini /= nbi;
traceSig_moy /= nbi;
troisK_moy /= nbi;
// d'où le calcul de la nouvelle épaisseur en utilisant la relation:
// (V-V_0)/V = trace(sigma)/3 /K_moy
//--- vérification et gestion des cas particuliers ---
bool cas_particulier=false;
{// on suppose un module de compressibilité positif sinon ce n'est pas normal
if (troisK_moy < 0.)
{if (ParaGlob::NiveauImpression()>2)
cout << "\n erreur*** on a trouve une compressibilite moyenne negative = "
<< troisK_moy/3.
<< "\n SfeMembT::CalEpaisseurMoyenne_et_vol_pti(...";
// on ne change pas l'épaisseur
cas_particulier = true;
};
// classiquement on suppose que troisK_moy doit-être bien supérieur à traceSig_moy:
// on considère un facteur 10 arbitraire
// si ce n'est pas le cas, on risque d'avoir un calcul d'épaisseur erroné
double delta_traceSig = traceSig_moy-traceSig_moy_ini;
if (Dabs(delta_traceSig) > 10. * Dabs(troisK_moy))
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " le coef de compressibilite moyen = "< (troisK_moy/3. - ConstMath::petit))
// dans le cas où delta_traceSig > troisK_moy, cela va donner une épaisseur négative !!
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite moyen = "< 10. * Dabs(troisK_moy/3.))
)
// on ne va pas pouvoir peut-être calculer une nouvelle épaisseur
{if (ParaGlob::NiveauImpression()>2)
cout << "\n *** pb dans le calcul de la nouvelle epaisseur: "
<< " coef de compressibilite moyen = "<Coord0().Norme(); double R = noe->Coord2().Norme();
//cout << "\n e0= " << epais.epaisseur_tdt<< " troisK_moy=" << troisK_moy << " traceSig_moy=" << traceSig_moy
// << " J0= " << jacobien_moy_0 << " J= " << jacobien_moy_fin << " R_0 " << R_0 << " R= " << R;
// };
//-- fin debug
return epais.epaisseur_tdt;
}
else
{epais.epaisseur_t = (epais.epaisseur0 * jacobien_moy_ini) / jacobien_moy_fin
* troisK_moy / (troisK_moy - traceSig_moy);
return epais.epaisseur_t;
};
};
};
// sinon c'est une erreur
cout << "\n *** erreur dans SfeMembT::CalEpaisseurMoyenne_et_vol_pti( ";
Sortie(1);
};
//test si le jacobien due aux gi finaux est très différent du jacobien de la facette
bool SfeMembT::Delta_Jacobien_anormal(const Deformation::SaveDefResul* don
,int nisur,int niepais)
{// on récupère le jacobien de la surface médiane sans courbure
const DeformationSfe1::SaveDefResulSfe1* donsfe = ((DeformationSfe1::SaveDefResulSfe1*) don);
#ifdef MISE_AU_POINT
if (donsfe->Meti_a_tdt().jacobien_ == NULL)
{cout << "\n*** erreur, le jacobien de la facette n'est pas attribue ! "
<< " pti de surface "<Meti_tdt().giB_ == NULL)
{cout << "\n*** erreur, la bas giB_tdt n'est pas attribue ! "
<< " pti de surface "<Meti_a_tdt().jacobien_);
// on récupère la base au pti courant
const BaseB * giB_ = donsfe->Meti_tdt().giB_;
// on calcule le produit mixte pour les gi finaux
double jacobien_final = Util::ProduitMixte(*giB_);
double ratio = jacobien_final/(jaco_init+ConstMath::pasmalpetit);
double limite = ParaGlob::param->ParaAlgoControleActifs().Ratio_maxi_jacoMembrane_jacoPti();
if ((ratio > limite) || (ratio < 1./(limite+ConstMath::pasmalpetit)))
cout << "\n *** attention *** le rapport entre le jacobien initial ("<< jaco_init
<< ") et le jacobien ("<< jacobien_final
<< ") calcule au pti de surface "<= 4)
cout << "\n cas non pr้vu, unefois->dualSortSfe= " << unefois->dualSortSfe
<< " unefois->CalimpPrem= " << unefois->CalimpPrem
<< "\n SfeMembT::Grandeur_particuliere(List_io&...";
Sortie(1);
};
// choix d'init en fonction de la valeur de "cas"
if (((cas == 1) || (cas == 2)))
{ // cas d'une premiere initialisation
Tableau tab(5);
tab(1) = iM0; tab(2) = iMt; tab(3) = iMtdt;
tab(4) = igiH_0; tab(5) = igijHH_0;
met->PlusInitVariables(tab) ;
};
//él้ments de m้trique et matrices de passage
TenseurHH* gijHH;TenseurBB* gijBB;
Mat_pleine jB0(dim,dim),jBfin(dim,dim);
if ((cas==1) || (cas==11))
// calcul d'une ortho interessance de visualisation des tenseurs
// cas de tenseur 3D -> Ia, cas 1D on prend un vecteur norme collineaire
// avec g1, dans le cas 2D
// la nouvelle base jB est calculee dans def par projection de "Ia" sur Galpha
// le resultat est une matrice de passage utilisable pour le changement de base
// jB0 a t=0, B pour les tenseurs BB, jH0 idem pour les tenseurs HH
// resultat a t+dt
{const Met_abstraite::InfoImp& ex = def->RemontImp(absolue,jB0,jBfin);
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
}
else if ((cas==2) || (cas==12))
// resultat a t
{const Met_abstraite::InfoExp_tdt& ex= def->RemontExp_tdt(absolue,jB0,jBfin);
gijHH = ex.gijHH_tdt;gijBB = ex.gijBB_tdt;
};
// maintenant on récupère le tenseur de courbure
const Met_Sfe1::Courbure_t_tdt& curb = ((DeformationSfe1*)def)->RecupCourbure0_t_tdt();
// passage en absolu si nécessaire
if (besoin_tenseur_courbure)
{Tenseur_ns2BB& cur_ns_bBB_tdt = *((Tenseur_ns2BB*) curb.curbBB_tdt) ;
// on le symétrise
curbBB_tdt = NevezTenseurBB(dim);
(*curbBB_tdt).Coor(1,1) = cur_ns_bBB_tdt(1,1);(*curbBB_tdt).Coor(2,2) = cur_ns_bBB_tdt(2,2);
(*curbBB_tdt).Coor(1,2) = 0.5*(cur_ns_bBB_tdt(1,2) + cur_ns_bBB_tdt(2,1));
curbBB_tdt->ChBase(jBfin); // le tenseur de courbure dans le rep่re local
};
// --- bases ortho locales (du plan de la facette ---
if (besoin_dir_princ_courb || besoin_rep_local_ortho)
{ t_ortho_local.Change_taille(3);
t_ortho_local(1) = jBfin(1,1) * curb.aiB_tdt->Coordo(1) + jBfin(2,1) * curb.aiB_tdt->Coordo(2);
t_ortho_local(2) = jBfin(1,2) * curb.aiB_tdt->Coordo(1) + jBfin(2,2) * curb.aiB_tdt->Coordo(2);
t_ortho_local(3) = Util::ProdVec_coor(t_ortho_local(1),t_ortho_local(2));
};
// --- les directions principales et/ou les valeurs principales
int ret=0;
if (besoin_dir_princ_courb)
{ Tenseur_ns2BB& cur_ns_bBB_tdt = *((Tenseur_ns2BB*) curb.curbBB_tdt) ;
// on le sym้trise
Tenseur2BB curb_symBB_tdt;
curb_symBB_tdt.Coor(1,1) = cur_ns_bBB_tdt(1,1);curb_symBB_tdt.Coor(2,2) = cur_ns_bBB_tdt(2,2);
curb_symBB_tdt.Coor(1,2) = 0.5*(cur_ns_bBB_tdt(1,2) + cur_ns_bBB_tdt(2,1));
// on cr้e le BH correspondant
Tenseur2BH curbBH = curb_symBB_tdt * (*gijHH);
Mat_pleine mat(2,2);
val_princ = curbBH.ValPropre(ret,mat);
// // calcul des vecteurs principaux dans la base locale
// Coordonnee3 V_1=mat(1,1) * curb.aiB_tdt->Coordo(1) + mat(2,1) * curb.aiB_tdt->Coordo(2);
// Coordonnee3 V_2=mat(1,2) * curb.aiB_tdt->Coordo(1) + mat(2,2) * curb.aiB_tdt->Coordo(2);
// t_vec_princ.Change_taille(2);
// t_vec_princ(1)(1)= V_1 * t_ortho_local(1); t_vec_princ(1)(2)= V_1 * t_ortho_local(2);
// t_vec_princ(2)(1)= V_2 * t_ortho_local(1); t_vec_princ(2)(2)= V_2 * t_ortho_local(2);
// non finalement on les exprimes dans la base globale sinon on ne peut pas visualiser sans manip
t_vec_princ.Change_taille(2);
// s'il y a eu un pb dans le calcul des valeurs propres ou vecteurs propres on évite
if (ret != -1)
{t_vec_princ(1)=mat(1,1) * curb.aiH_tdt->Coordo(1) + mat(2,1) * curb.aiH_tdt->Coordo(2);
t_vec_princ(2)=mat(1,2) * curb.aiB_tdt->Coordo(1) + mat(2,2) * curb.aiB_tdt->Coordo(2);
t_vec_princ(1).Normer();t_vec_princ(2).Normer();
};
}
else if (besoin_courbures_principales)
// si on arrive ici c'est que l'on n'a pas besoin des directions principales mais
// seulement des valeurs propres de courbure
{ Tenseur_ns2BB& cur_ns_bBB_tdt = *((Tenseur_ns2BB*) curb.curbBB_tdt) ;
// on le sym้trise
Tenseur2BB curb_symBB_tdt;
curb_symBB_tdt.Coor(1,1) = cur_ns_bBB_tdt(1,1);curb_symBB_tdt.Coor(2,2) = cur_ns_bBB_tdt(2,2);
curb_symBB_tdt.Coor(1,2) = 0.5*(cur_ns_bBB_tdt(1,2) + cur_ns_bBB_tdt(2,1));
// on cr้e le BH correspondant
Tenseur2BH curbBH = curb_symBB_tdt * (*gijHH);
val_princ = curbBH.ValPropre(ret);
};
if (ret == -1)
{ cout << "\n pb dans le calcul de valeurs ou vecteurs propres du tenseur de courbure !";
if (ParaGlob::NiveauImpression() > 6 )
cout << "\n SfeMembT::Grandeur_particuliere (...";
};
};
// ------ maintenant on fait la sortie réelle -----
// on commence par appeler la fonction de la classe mère
// il n'y aura pas de calcul des grandeurs inactivées
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
ElemMeca::Grandeur_particuliere (absolue,liTQ,iteg);
// puis les grandeurs sp้cifiques
for (il=liTQ.begin();il!=ilfin;il++)
{TypeQuelconque& tipParticu = (*il); // pour simplifier
if (tipParticu.EnuTypeQuelconque().Nom_vide()) // veut dire que c'est un enum pur
switch (tipParticu.EnuTypeQuelconque().EnumTQ())
{
// 1) -----cas de l'้paisseur moyenne initiale, ici elle ne d้pend pas du point d'int้gration
case EPAISSEUR_MOY_INITIALE:
{if (donnee_specif.epais != NULL)
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.epais->epaisseur0;
(*il).Active();
}; break;
}
// 2) -----cas de l'้paisseur moyenne finale, ici elle ne d้pend pas du point d'int้gration
case EPAISSEUR_MOY_FINALE: (*il).Inactive(); break; // on inactive la grandeur quelconque
{ if (donnee_specif.epais != NULL)
{ *((Grandeur_scalaire_double*) tipParticu.Grandeur_pointee())=donnee_specif.epais->epaisseur_tdt;
(*il).Active();
}; break;
}
// 3) ฐฐฐฐฐฐฐฐฐฐฐฐฐ cas du tenseur de courbure ฐฐฐฐฐฐฐฐฐฐ
case TENSEUR_COURBURE:
{ ((Grandeur_TenseurBB*) tipParticu.Grandeur_pointee())->RefConteneurTenseur() = *curbBB_tdt;
(*il).Active();break;
}
// 4) ฐฐฐฐฐฐฐฐฐฐฐฐฐ cas du vecteur contenant les courbures principales ฐฐฐฐฐฐฐฐฐฐ
case COURBURES_PRINCIPALES:
{ (*((Tab_Grandeur_scalaire_double*) tipParticu.Grandeur_pointee()))(1) = val_princ(1);
(*((Tab_Grandeur_scalaire_double*) tipParticu.Grandeur_pointee()))(2) = val_princ(2);
(*il).Active();break;
}
// 5) ฐฐฐฐฐฐฐฐฐฐฐฐฐ cas des directions principales de courbure (dans le rep่re local ฐฐฐฐฐฐฐฐฐฐ
case DIRECTIONS_PRINC_COURBURE:
{ (*((Tab_Grandeur_Coordonnee*) tipParticu.Grandeur_pointee()))(1) = t_vec_princ(1);
(*((Tab_Grandeur_Coordonnee*) tipParticu.Grandeur_pointee()))(2) = t_vec_princ(2);
(*il).Active();break;
}
// 6) ฐฐฐฐฐฐฐฐฐฐฐฐฐ cas du rep่re local orthonorm้ d'expression ฐฐฐฐฐฐฐฐฐฐ
case REPERE_LOCAL_ORTHO:
{ (*((Tab_Grandeur_Coordonnee*) tipParticu.Grandeur_pointee()))(1) = t_ortho_local(1);
(*((Tab_Grandeur_Coordonnee*) tipParticu.Grandeur_pointee()))(2) = t_ortho_local(2);
(*((Tab_Grandeur_Coordonnee*) tipParticu.Grandeur_pointee()))(3) = t_ortho_local(3);
(*il).Active();break;
};
default: break; // on ne fait rien
};
};
// liberation des tenseurs intermediaires
LibereTenseur();
if (curbBB_tdt != NULL) delete curbBB_tdt;
};
// calcul éventuel de la normale à un noeud
// ce calcul existe pour les éléments 2D, 1D axi, et aussi pour les éléments 1D
// qui possède un repère d'orientation
// en retour coor = la normale si coor.Dimension() est = à la dimension de l'espace
// si le calcul n'existe pas --> coor.Dimension() = 0
// ramène un entier :
// == 1 : calcul normal
// == 0 : problème de calcul -> coor.Dimension() = 0
// == 2 : indique que le calcul n'est pas licite pour le noeud passé en paramètre
// c'est le cas par exemple des noeuds exterieurs pour les éléments SFE
// mais il n'y a pas d'erreur, c'est seulement que l'élément n'est pas ad hoc pour
// calculer la normale à ce noeud là
// temps: indique à quel moment on veut le calcul
// pour des éléments particulier (ex: SFE) la méthode est surchargée
int SfeMembT::CalculNormale_noeud(Enum_dure temps,const Noeud& noe,Coordonnee& coor)
{ // === par rapport à la méthode d'ElemMeca, ici on ne s'occupe des noeuds de l'élément central
int retour = 1; // on part avec l'idée que tout va être ok
Enum_type_geom enutygeom = Type_geom_generique(this->Id_geometrie());
// if ((enutygeom == LIGNE) || (enutygeom == SURFACE))
if (enutygeom != SURFACE) // dans une première étape on ne s'occupe que des surfaces
{coor.Libere(); // pas de calcul possible
retour = 0;
}
else // sinon le calcul est possible
{ // on commence par repérer le noeud dans la numérotation locale
int nuoe=0;
// int borne_nb_noeud=nombre->nbnce+1; // ici on ne prend en compte que les noeuds centraux
int borne_nb_noeud=tab_noeud.Taille()+1;
for (int i=1;i< borne_nb_noeud;i++)
{Noeud& noeloc = *tab_noeud(i);
if ( (noe.Num_noeud() == noeloc.Num_noeud())
&& (noe.Num_Mail() == noeloc.Num_Mail())
)
{nuoe = i; break;
};
};
// on ne continue que si on a trouvé le noeud
if (nuoe != 0)
{ // il y a deux cas: soit le noeud fait partie des noeuds centraux ou non
if (nuoe <= nombre->nbnce) // cas où le noeud fait partie du centre
{ElemGeomC0& elemgeom = ElementGeometrique(); // récup de la géométrie
// récup des coordonnées locales du noeuds
const Coordonnee& theta_noeud = elemgeom.PtelemRef()(nuoe);
// récup des phi et dphi au noeud
const Vecteur & phi = elemgeom.Phi(theta_noeud);
const Mat_pleine& dphi = elemgeom.Dphi(theta_noeud);
switch (temps)
{case TEMPS_0 :
{const BaseB& baseB = met->BaseNat_0(tab_noeud,dphi,phi);
coor = Util::ProdVec_coor( baseB.Coordo(1), baseB.Coordo(2));
coor.Normer();
break;
}
case TEMPS_t :
{const BaseB& baseB = met->BaseNat_t(tab_noeud,dphi,phi);
coor = Util::ProdVec_coor( baseB.Coordo(1), baseB.Coordo(2));
coor.Normer();
break;
}
case TEMPS_tdt :
{const BaseB& baseB = met->BaseNat_tdt(tab_noeud,dphi,phi);
coor = Util::ProdVec_coor( baseB.Coordo(1), baseB.Coordo(2));
coor.Normer();
break;
}
default :
cout << "\nErreur : valeur incorrecte du temps demande = "
<< Nom_dure(temps) << " !\n";
cout << "\n SfeMembT::CalculNormale_noeud(Enum_dure temps... \n";
retour = 0;
Sortie(1);
};
}
else // sinon le noeud fait partie des noeuds externes
// on considère que la normale n'est pas à calculer
{coor.Libere(); // pas de calcul possible
retour = 2;
};
}
else
{cout << "\n *** erreur le noeud demande num= "<