804 lines
40 KiB
C++
804 lines
40 KiB
C++
|
// 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) <https://www.irdl.fr/>.
|
||
|
//
|
||
|
// 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 <https://www.gnu.org/licenses/>.
|
||
|
//
|
||
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
||
|
|
||
|
|
||
|
# include <iostream>
|
||
|
using namespace std; //introduces namespace std
|
||
|
#include <stdlib.h>
|
||
|
#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
|
||
|
<< " est par rapport a delta la trace de sigma = "
|
||
|
<< traceSig << " 10 fois inferieur !! ce n'est pas normal a priori "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurAtdtExp_et_vol_pti(..."
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
|
||
|
double delta_traceSig = traceSig-traceSig_t;
|
||
|
// maintenant on regarde si le module peut conduire à une épaisseur négative
|
||
|
if (delta_traceSig > (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 = "<<troisK/3
|
||
|
<< " est inferieur a delta trace de sigma = "
|
||
|
<< delta_traceSig
|
||
|
<< " ce qui va donner une epaisseur finale negative !! "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurAtdtExp_et_vol_pti(..."
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
|
||
|
// maintenant on regarde si le module n'est pas trop petit
|
||
|
// si oui il y a aussi un pb
|
||
|
if ((Dabs(troisK) <= ConstMath::unpeupetit)
|
||
|
&& (Dabs(delta_traceSig) > 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 = "<<troisK/3
|
||
|
<< " et delta trace de sigma = "
|
||
|
<< delta_traceSig
|
||
|
<< " sont de valeurs trop faibles (et un peu etrange) !! "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurAtdtExp_et_vol_pti(..."
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
if (cas_particulier)
|
||
|
{ epaisseur_tdt = epaisseur_t;
|
||
|
ptIntegMeca.Volume_pti() *= epaisseur_t;
|
||
|
}
|
||
|
else // sinon cas sans pb
|
||
|
{
|
||
|
// epaisseur_tdt = (epaisseur0 * (*(ex.jacobien_0))) / (*(ex.jacobien_tdt))
|
||
|
// * troisK / (troisK - traceSig);
|
||
|
epaisseur_tdt = (epaisseur_t * (*(ex.jacobien_t))) / (*(ex.jacobien_tdt))
|
||
|
* troisK / (troisK - traceSig+traceSig_t);
|
||
|
// calcul du volume au pti
|
||
|
ptIntegMeca.Volume_pti() *= epaisseur_tdt ;
|
||
|
};
|
||
|
};
|
||
|
// calcul de la nouvelle épaisseur (sans raideur) avec métrique en implicite
|
||
|
// cas où l'épaisseur est stocké dans l'élément
|
||
|
// mise à jour du volume au pti
|
||
|
void SfeMembT::CalEpaisseurAtdtImp_et_vol_pti(const double& epaisseur0, const ParaAlgoControle &
|
||
|
,const double & epaisseur_t, PtIntegMecaInterne & ptIntegMeca
|
||
|
,double & epaisseur_tdt, const Met_abstraite::Impli& 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();
|
||
|
double traceSig = (ptIntegMeca.SigHH_const() && (* ex.gijBB_tdt));
|
||
|
double traceSig_t = (ptIntegMeca.SigHH_t_const() && (* ex.gijBB_t));
|
||
|
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
|
||
|
<< "\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
|
||
|
<< " est par rapport a delta la trace de sigma = "
|
||
|
<< traceSig << " 10 fois inferieur !! ce n'est pas normal a priori "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurAtdtImp_et_vol_pti...) "
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
|
||
|
double delta_traceSig = traceSig-traceSig_t;
|
||
|
// maintenant on regarde si le module peut conduire à une épaisseur négative
|
||
|
if (delta_traceSig > (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 = "<<troisK/3
|
||
|
<< " est inferieur a delta trace de sigma = "
|
||
|
<< delta_traceSig
|
||
|
<< " ce qui va donner une epaisseur finale negative !! "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurAtdtImp_et_vol_pti...) "
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
|
||
|
// maintenant on regarde si le module n'est pas trop petit
|
||
|
// si oui il y a aussi un pb
|
||
|
if ((Dabs(troisK) <= ConstMath::unpeupetit)
|
||
|
&& (Dabs(delta_traceSig) > 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 = "<<troisK/3
|
||
|
<< " et delta trace de sigma = "
|
||
|
<< delta_traceSig
|
||
|
<< " sont de valeurs trop faibles (et un peu etrange) !! "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurAtdtImp_et_vol_pti...) "
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
if (cas_particulier)
|
||
|
{ epaisseur_tdt = epaisseur_t;
|
||
|
ptIntegMeca.Volume_pti() *= epaisseur_t;
|
||
|
}
|
||
|
else // sinon cas sans pb
|
||
|
{
|
||
|
epaisseur_tdt = (epaisseur_t * (*(ex.jacobien_t))) / (*(ex.jacobien_tdt))
|
||
|
* troisK / (troisK - traceSig+traceSig_t);
|
||
|
// calcul du volume au pti
|
||
|
ptIntegMeca.Volume_pti() *= epaisseur_tdt ;
|
||
|
};
|
||
|
};
|
||
|
// calcul de la nouvelle épaisseur moyenne finale (sans raideur)
|
||
|
// mise à jour des volumes aux pti
|
||
|
// ramène l'épaisseur moyenne calculée à atdt
|
||
|
const double& SfeMembT::CalEpaisseurMoyenne_et_vol_pti(bool atdt)
|
||
|
{ // .. en bouclant sur les pt d'integ enregistré ..
|
||
|
// -- on récupère et on calcule les jacobiens moyens à 0 et final
|
||
|
double jacobien_moy_fin = 0.; // init
|
||
|
double jacobien_moy_ini = 0.;
|
||
|
// -- de même on récupère et on calcul la trace moyenne de la contrainte
|
||
|
double traceSig_moy = 0.;double traceSig_moy_ini = 0.;
|
||
|
// -- de même on récupère et on calcul le module de compressibilité moyen
|
||
|
double troisK_moy = 0.;
|
||
|
if (donnee_specif.epais != NULL)
|
||
|
{Epai& epais = *(donnee_specif.epais); // pour simplifier
|
||
|
int indice = 1;
|
||
|
SfeMembT::DonnComSfe* CoSfe = unefois->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.
|
||
|
<< " est par rapport a delta la trace de sigma = "
|
||
|
<< delta_traceSig << " 10 fois inferieur !! ce n'est pas normal a priori "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurMoyenne_et_vol_pti(... "
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
|
||
|
// maintenant on regarde si le module peut conduire à une épaisseur négative
|
||
|
if (delta_traceSig > (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 = "<<troisK_moy/3.
|
||
|
<< " est inferieur a delta la trace de sigma = "
|
||
|
<< delta_traceSig
|
||
|
<< " ce qui va donner une epaisseur finale negative !! "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurMoyenne_et_vol_pti(... "
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
|
||
|
// maintenant on regarde si le module n'est pas trop petit
|
||
|
// si oui il y a aussi un pb
|
||
|
if ((Dabs(troisK_moy) <= ConstMath::unpeupetit)
|
||
|
&& (Dabs(traceSig_moy) > 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 = "<<troisK_moy/3
|
||
|
<< " et delta trace de sigma = "
|
||
|
<< delta_traceSig
|
||
|
<< " sont de valeurs trop faibles (et un peu etrange) !! "
|
||
|
<< " on continue sans changer l'epaisseur ... "
|
||
|
<< "\n SfeMembT::CalEpaisseurMoyenne_et_vol_pti(... "
|
||
|
<< endl;
|
||
|
// on ne change pas l'épaisseur
|
||
|
cas_particulier = true;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
// si cas particulier: on ne peut pas calculer, on reste sur les valeurs précédentes
|
||
|
if (cas_particulier)
|
||
|
{if (atdt)
|
||
|
{ // on met à jour l'épaisseur
|
||
|
epais.epaisseur_tdt = epais.epaisseur_t;
|
||
|
// puis retour
|
||
|
return epais.epaisseur_tdt;
|
||
|
}
|
||
|
else
|
||
|
{// retour
|
||
|
return epais.epaisseur_t;
|
||
|
};
|
||
|
}
|
||
|
else // sinon c'est ok
|
||
|
{if (atdt)
|
||
|
{epais.epaisseur_tdt = (epais.epaisseur_t * jacobien_moy_ini) / jacobien_moy_fin
|
||
|
* troisK_moy / (troisK_moy - traceSig_moy+traceSig_moy_ini);
|
||
|
|
||
|
//epais.epaisseur_tdt = (epais.epaisseur0 * jacobien_moy_0) / jacobien_moy_fin
|
||
|
// * troisK_moy / (troisK_moy + traceSig_moy);
|
||
|
//--debug
|
||
|
//if (num_elt==1)
|
||
|
// { Noeud* noe = tab_noeud(1);
|
||
|
// double R_0 = noe->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 "<<nisur
|
||
|
<< "\n element SFE: num= " << Num_elt_const()
|
||
|
<< ", num maillage= " << Num_maillage()
|
||
|
<< "\n SfeMembT::Delta_Jacobien_anormal(..."<<flush;
|
||
|
Sortie(1);
|
||
|
};
|
||
|
if (donsfe->Meti_tdt().giB_ == NULL)
|
||
|
{cout << "\n*** erreur, la bas giB_tdt n'est pas attribue ! "
|
||
|
<< " pti de surface "<<nisur << " et au pti d'epaisseur " << niepais
|
||
|
<< "\n element SFE: num= " << Num_elt_const()
|
||
|
<< ", num maillage= " << Num_maillage()
|
||
|
<< "\n SfeMembT::Delta_Jacobien_anormal(..."<<flush;
|
||
|
Sortie(1);
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
double jaco_init = *(donsfe->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 "<<nisur << " et au pti d'epaisseur " << niepais
|
||
|
<< " est en dehors de l'intervalle ["<<1./(limite+ConstMath::pasmalpetit) <<","<<limite<<"] "
|
||
|
<< "( peut-etre que les courbure-epaisseur sont trop importantes localement ? )"
|
||
|
<< "\n element SFE: num= " << Num_elt_const()
|
||
|
<< ", num maillage= " << Num_maillage()
|
||
|
<< flush;
|
||
|
};
|
||
|
|
||
|
// retourne la liste abond้e de tous les donn้es particuli่res interne actuellement utilis้s
|
||
|
// par l'้l้ment (actif ou non), sont exclu de cette liste les donn้es particuli่res des noeuds
|
||
|
// reli้s เ l'้l้ment
|
||
|
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
||
|
List_io <TypeQuelconque> SfeMembT::Les_types_particuliers_internes(bool absolue) const
|
||
|
{ // on commence par récupérer la liste général provenant d'ElemMeca
|
||
|
List_io <TypeQuelconque> ret = ElemMeca::Les_types_particuliers_internes(absolue);
|
||
|
// ensuite on va ajouter les données particulières aux sfe
|
||
|
Grandeur_scalaire_double grand_courant; // def d'une grandeur courante
|
||
|
if (donnee_specif.epais != NULL)
|
||
|
{ // $$$ cas de l'้paisseur initiale
|
||
|
TypeQuelconque typQ1(EPAISSEUR_MOY_INITIALE,SIG11,grand_courant);
|
||
|
ret.push_back(typQ1);
|
||
|
// $$$ cas de l'้paisseur finale
|
||
|
TypeQuelconque typQ2(EPAISSEUR_MOY_FINALE,SIG11,grand_courant);
|
||
|
ret.push_back(typQ2);
|
||
|
};
|
||
|
// $$$ cas des efforts normaux classiques, linéique
|
||
|
{TypeQuelconque typQ1(NN_11,SIG11,grand_courant); ret.push_back(typQ1);};
|
||
|
{TypeQuelconque typQ1(NN_22,SIG11,grand_courant); ret.push_back(typQ1);};
|
||
|
{TypeQuelconque typQ1(NN_12,SIG11,grand_courant); ret.push_back(typQ1);};
|
||
|
// $$$ cas des moments linéiques
|
||
|
{TypeQuelconque typQ1(MM_11,SIG11,grand_courant); ret.push_back(typQ1);};
|
||
|
{TypeQuelconque typQ1(MM_22,SIG11,grand_courant); ret.push_back(typQ1);};
|
||
|
{TypeQuelconque typQ1(MM_12,SIG11,grand_courant); ret.push_back(typQ1);};
|
||
|
|
||
|
// $$$ cas du tenseur de courbure
|
||
|
// on ne l'exprime jamais (pour l'instant) dans le repère absolu)
|
||
|
// mais on sort toutes les infos: repère local et courbures principales
|
||
|
Tenseur2BB tens; // un tenseur typique
|
||
|
Grandeur_TenseurBB grand2(tens); // def d'une grandeur courante TenseurBB
|
||
|
TypeQuelconque typQ3(TENSEUR_COURBURE,SIG11,grand2);
|
||
|
ret.push_back(typQ3);
|
||
|
// $$$ cas du vecteur contenant les courbures principales
|
||
|
Tableau <double> t_d(2); // un tableau qui sert d'indicateur de type
|
||
|
Tab_Grandeur_scalaire_double grand3(t_d); // def d'une grandeur courante tab de scalaire
|
||
|
TypeQuelconque typQ4(COURBURES_PRINCIPALES,SIG11,grand3);
|
||
|
ret.push_back(typQ4);
|
||
|
// $$$ cas des directions principales de courbure (dans le rep่re local
|
||
|
Coordonnee3 v_c_princ; // un vecteur qui sert d'indicateur de type
|
||
|
Tab_Grandeur_Coordonnee grand4(v_c_princ,2); // def d'une grandeur courante coordonn้e
|
||
|
TypeQuelconque typQ5(DIRECTIONS_PRINC_COURBURE,SIG11,grand4);
|
||
|
ret.push_back(typQ5);
|
||
|
// $$$ cas du repère local orthonormé d'expression
|
||
|
Coordonnee3 v_rep;
|
||
|
Tab_Grandeur_Coordonnee grand5(v_rep,3); // def d'une grandeur courante coordonn้e
|
||
|
TypeQuelconque typQ6(REPERE_LOCAL_ORTHO,SIG11,grand5);
|
||
|
ret.push_back(typQ6);
|
||
|
|
||
|
// liberation des tenseurs intermediaires
|
||
|
LibereTenseur();
|
||
|
return ret;
|
||
|
};
|
||
|
|
||
|
// récupération de grandeurs particulières au numéro d'ordre = iteg
|
||
|
// celles-ci peuvent être quelconques
|
||
|
// en retour liTQ est modifié et contiend les infos sur les grandeurs particulières
|
||
|
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
||
|
void SfeMembT::Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ,int iteg)
|
||
|
{ // *** pour l'instant on ne sort rien de particulier dans le repère absolue !! cf. les grandeurs
|
||
|
// on balaie la liste transmise pour les grandeurs propres
|
||
|
List_io<TypeQuelconque>::iterator il,ilfin = liTQ.end();
|
||
|
// on fait un premier passage pour voir s'il y a une demande d'infos relatives à la courbure
|
||
|
bool besoin_tenseur_courbure=false;TenseurBB * curbBB_tdt = NULL;
|
||
|
bool besoin_courbures_principales=false;Coordonnee2 val_princ;
|
||
|
bool besoin_dir_princ_courb=false; Tableau <Coordonnee3 > t_vec_princ;
|
||
|
bool besoin_rep_local_ortho=false; Tableau <Coordonnee3 > t_ortho_local;
|
||
|
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())
|
||
|
{ case EPAISSEUR_MOY_INITIALE: (*il).Inactive(); break; // on inactive la grandeur quelconque
|
||
|
case EPAISSEUR_MOY_FINALE: (*il).Inactive(); break; // on inactive la grandeur quelconque
|
||
|
// --- cas des éléments liés à la courbure on inactive et on crée des booléen adoc
|
||
|
case TENSEUR_COURBURE:
|
||
|
{ (*il).Inactive();besoin_tenseur_courbure=true;break;}
|
||
|
case COURBURES_PRINCIPALES:
|
||
|
{ (*il).Inactive();besoin_courbures_principales=true;break;}
|
||
|
case DIRECTIONS_PRINC_COURBURE:
|
||
|
{ (*il).Inactive();besoin_dir_princ_courb=true;break;}
|
||
|
case REPERE_LOCAL_ORTHO:
|
||
|
{ (*il).Inactive();besoin_rep_local_ortho=true;break;}
|
||
|
default: break; // on ne fait rien
|
||
|
};
|
||
|
};
|
||
|
// dans le cas où on demande des infos relatives à la courbure on les récupères
|
||
|
if ((besoin_tenseur_courbure)||(besoin_courbures_principales)||(besoin_dir_princ_courb)
|
||
|
||(besoin_rep_local_ortho))
|
||
|
{// ----- def de grandeurs de travail
|
||
|
// def de la dimension des tenseurs
|
||
|
int dim = lesPtIntegMecaInterne->DimTens();
|
||
|
PtIntegMecaInterne & ptIntegMeca = (*lesPtIntegMecaInterne)(iteg);
|
||
|
// on recupère le tableau pour la lecture des coordonnées des tenseurs
|
||
|
int nbcompo = ParaGlob::NbCompTens();
|
||
|
const Tableau2 <int> & OrdreCont = OrdreContrainteR(nbcompo);
|
||
|
// définition des grandeurs qui sont indépendante de la boucle sur les ddl_enum_etendue
|
||
|
def->ChangeNumInteg(iteg); // on change le num้ro de point d'int้gration courant
|
||
|
// def du cas de sortie
|
||
|
int cas=0;
|
||
|
if ((unefois->dualSortSfe == 0) && (unefois->CalimpPrem != 0))
|
||
|
{ cas=1;unefois->dualSortSfe = 1;
|
||
|
}
|
||
|
else if ((unefois->dualSortSfe == 1) && (unefois->CalimpPrem != 0))
|
||
|
{ cas = 11;}
|
||
|
else if ((unefois->dualSortSfe == 0) && (unefois->CalResPrem_tdt != 0))
|
||
|
{ cas=2;unefois->dualSortSfe = 1;
|
||
|
}
|
||
|
else if ((unefois->dualSortSfe == 1) && (unefois->CalResPrem_tdt != 0))
|
||
|
{ cas = 12;}
|
||
|
// sinon problème
|
||
|
else
|
||
|
{ cout << "\n warning: les grandeurs ne sont pas calculees : il faudrait au moins un pas de calcul"
|
||
|
<< " pour inialiser les conteneurs des tenseurs resultats ";
|
||
|
if (ParaGlob::NiveauImpression() >= 4)
|
||
|
cout << "\n cas non pr้vu, unefois->dualSortSfe= " << unefois->dualSortSfe
|
||
|
<< " unefois->CalimpPrem= " << unefois->CalimpPrem
|
||
|
<< "\n SfeMembT::Grandeur_particuliere(List_io<TypeQuelconque>&...";
|
||
|
Sortie(1);
|
||
|
};
|
||
|
// choix d'init en fonction de la valeur de "cas"
|
||
|
if (((cas == 1) || (cas == 2)))
|
||
|
{ // cas d'une premiere initialisation
|
||
|
Tableau<Enum_variable_metrique> 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= "<<noe.Num_noeud()
|
||
|
<< " du maillage "<< noe.Num_Mail()
|
||
|
<< " ne fait pas parti de l'element "
|
||
|
<< num_elt << " du maillage "<< noe.Num_Mail()
|
||
|
<< " on ne peut pas calculer la normale au noeud !!"
|
||
|
<< "\n SfeMembT::CalculNormale_noeud(...";
|
||
|
retour = 0;
|
||
|
Sortie(1);
|
||
|
}
|
||
|
};
|
||
|
// retour
|
||
|
return retour;
|
||
|
|
||
|
};
|