Herezh_dev/herezh_pp/Elements/Mecanique/SFE/Met_Sfe1s3.cc

1439 lines
69 KiB
C++
Raw Permalink Normal View History

// FICHIER : Met_Sfe1s3.cc
// CLASSE : Met_Sfe1
// 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 <math.h>
#include <stdlib.h>
#include "Sortie.h"
#include "Met_Sfe1.h"
// =========================================================================================
// vu la taille des executables le fichier est decompose en quatre
// le premier : Met_Sfe1s1.cp concerne les constructeurs, destructeur et
// la gestion des variables
// le second : Met_Sfe1s2.cp concerne le calcul des grandeurs publics
// le troisieme : Met_Sfe1s3.cp concerne le calcul des grandeurs protegees, et des courbures pour SFE1 et SFE2 et QSFE1
// le quatrième : Met_Sfe1s4.cp concerne le calcul des courbures pour les éléments SFE3 et QSFE3
// =========================================================================================
//==================== METHODES PROTEGEES===============================
// calcul des normales a la facette
void Met_Sfe1::Calcul_N_0 ()
{ N_0 = (Util::ProdVec_coorB((*aiB_0)(1),(*aiB_0)(2))).Normer();};
void Met_Sfe1::Calcul_N_t ()
{ N_t = (Util::ProdVec_coorB((*aiB_t)(1),(*aiB_t)(2)));
norme_N_t = N_t.Norme();
N_t /= norme_N_t;
};
void Met_Sfe1::Calcul_N_tdt ()
{ N_tdt = (Util::ProdVec_coorB((*aiB_tdt)(1),(*aiB_tdt)(2)));
norme_N_tdt = N_tdt.Norme();
N_tdt /= norme_N_tdt;
};
//== calcul des variations de la normales
// il faut avant le calcul des ap_alpha_t et de épaisseur à t
void Met_Sfe1::Cal_d_N_t()
{ int nbddlx = tab_ddl.NbDdl_famille(X1);
CoordonneeB d_NN; // un vecteur de travail
for (int iddl=1;iddl<= nbddlx;iddl++)
{ // tout d'abord on calcul la variation de la normale non normée
d_NN = (Util::ProdVec_coorB((*d_aiB_t)(iddl)(1),(*aiB_t)(2)))
+ (Util::ProdVec_coorB((*aiB_t)(1),(*d_aiB_t)(iddl)(2)));
// maintenant on calcul la variation du vecteur normal unitaire
(*d_N_t)(iddl) = Util::VarUnVect_coorB(N_t,d_NN,norme_N_t);
};
};
// il faut avant le calcul des ap_alpha_tdt et de épaisseur à tdt
void Met_Sfe1::Cal_d_N_tdt()
{ int nbddlx = tab_ddl.NbDdl_famille(X1);
CoordonneeB d_NN; // un vecteur de travail
for (int iddl=1;iddl<= nbddlx;iddl++)
{ // tout d'abord on calcul la variation de la normale non normée
d_NN = (Util::ProdVec_coorB((*d_aiB_tdt)(iddl)(1),(*aiB_tdt)(2)))
+ (Util::ProdVec_coorB((*aiB_tdt)(1),(*d_aiB_tdt)(iddl)(2)));
// maintenant on calcul la variation du vecteur normal unitaire
(*d_N_tdt)(iddl) = Util::VarUnVect_coorB(N_tdt,d_NN,norme_N_tdt);
};
};
// ---- calcul des points
// calcul du point a t0
void Met_Sfe1::Calcul_M0( const Tableau<Noeud *>& , const Vecteur& phiH, int )
{ // on considère qu'il y a deux points dans l'épaisseur, un a -h/2 et l'autre à h/2
*M0 = *P0 + (N_0 * (epais.epaisseur0 * 0.5 * (phiH(2)-phiH(1)))).Coor_const();};
void Met_Sfe1::Calcul_Mt( const Tableau<Noeud *>& , const Vecteur& phiH, int )
{ // on considère qu'il y a deux points dans l'épaisseur, un a -h/2 et l'autre à h/2
*Mt = *Pt + (N_t * (epais.epaisseur_t * 0.5 * (phiH(2)-phiH(1)))).Coor_const();};
void Met_Sfe1::Calcul_Mtdt( const Tableau<Noeud *>& , const Vecteur& phiH, int )
{ // on considère qu'il y a deux points dans l'épaisseur, un a -h/2 et l'autre à h/2
*Mtdt = *Ptdt + (N_tdt * (epais.epaisseur_tdt * 0.5 * (phiH(2)-phiH(1)))).Coor_const();};
// cas de l'épaisseur interpolée à 0
void Met_Sfe1::Calcul_epaisseur_0(const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS)
{ double & epaisseur = epais.epaisseur0;
epaisseur = 0.; // init
for (int r=1;r<=nbNoeudCentral;r++)
epaisseur += tab_noeud(r)->Valeur_0(EPAIS) * phiS(r);
};
// cas de l'épaisseur interpolée à t
void Met_Sfe1::Calcul_epaisseur_t(const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS)
{ double & epaisseur = epais.epaisseur_t;
epaisseur = 0.; // init
for (int r=1;r<=nbNoeudCentral;r++)
epaisseur += tab_noeud(r)->Valeur_t(EPAIS) * phiS(r);
};
// cas de l'épaisseur interpolée à tdt
void Met_Sfe1::Calcul_epaisseur_tdt(const Tableau<Noeud *>& tab_noeud, const Vecteur& phiS)
{ double & epaisseur = epais.epaisseur_tdt;
epaisseur = 0.; // init
for (int r=1;r<=nbNoeudCentral;r++)
epaisseur += tab_noeud(r)->Valeur_tdt(EPAIS) * phiS(r);
};
// calcul de la variation de l'épaisseur par rapport aux ddl
void Met_Sfe1::D_epaisseur_t(const Vecteur& phiS)
{ // l'épaisseur ne dépend que des ddl d'épaisseur
for (int r=1;r<=nbNoeudCentral;r++)
(*d_epais)(r).epaisseur_t = phiS(r);
};
// calcul de la variation de l'épaisseur par rapport aux ddl
void Met_Sfe1::D_epaisseur_tdt(const Vecteur& phiS)
{ // l'épaisseur ne dépend que des ddl d'épaisseur
for (int r=1;r<=nbNoeudCentral;r++)
(*d_epais)(r).epaisseur_tdt = phiS(r);
};
//== calcul de la variation de N,alpha
void Met_Sfe1::Cal_d_N_alpha_t()
{ int nbddlx = tab_ddl.NbDdl_famille(X1);
for (int iddl=1;iddl<= nbddlx;iddl++)
{ // variation de la derivee du vecteur normal
(*d_N_alpha_t_1)(iddl).ConstructionAPartirDe_H(
-(dcurb_t(iddl)(1,1) * (*aiH_t)(1) + curb_t(1,1) * (*d_aiH_t)(iddl)(1)
+dcurb_t(iddl)(1,2) * (*aiH_t)(2) + curb_t(1,2) * (*d_aiH_t)(iddl)(2)));
(*d_N_alpha_t_2)(iddl).ConstructionAPartirDe_H(
-(dcurb_t(iddl)(2,1) * (*aiH_t)(1) + curb_t(2,1) * (*d_aiH_t)(iddl)(1)
+ dcurb_t(iddl)(2,2) * (*aiH_t)(2) + curb_t(2,2) * (*d_aiH_t)(iddl)(2)));
};
};
void Met_Sfe1::Cal_d_N_alpha_tdt()
{ int nbddlx = tab_ddl.NbDdl_famille(X1);
for (int iddl=1;iddl<= nbddlx;iddl++)
{ // variation de la derivee du vecteur normal
(*d_N_alpha_tdt_1)(iddl).ConstructionAPartirDe_H(
-(dcurb_tdt(iddl)(1,1) * (*aiH_tdt)(1) + curb_tdt(1,1) * (*d_aiH_tdt)(iddl)(1)
+dcurb_tdt(iddl)(1,2) * (*aiH_tdt)(2) + curb_tdt(1,2) * (*d_aiH_tdt)(iddl)(2)));
(*d_N_alpha_tdt_2)(iddl).ConstructionAPartirDe_H(
-(dcurb_tdt(iddl)(2,1) * (*aiH_tdt)(1) + curb_tdt(2,1) * (*d_aiH_tdt)(iddl)(1)
+ dcurb_tdt(iddl)(2,2) * (*aiH_tdt)(2) + curb_tdt(2,2) * (*d_aiH_tdt)(iddl)(2)));
};
};
// ------ calcul des bases pour la surface médiane -------
// calcul de la base naturel a t0 pour la surface médiane: partie a_alpha
void Met_Sfe1::Calcul_a_alpha_B_0
( const Tableau<Noeud *>& tab_noeud, const Mat_pleine& dphi, int ,const Vecteur&)
{
#ifdef MISE_AU_POINT
if (aiB_0 == NULL)
{ cout << "\nErreur : la base a t=0 n'est pas dimensionne !\n";
cout << "void Met_Sfe1::Calcul_aiB_0 \n";
Sortie(1);
};
#endif
for (int i=1;i<= 2;i++)
{for (int a=1;a<= dim_base;a++)
{ double & aib0_i_a = aiB_0->CoordoB(i)(a);
aib0_i_a = 0.;
for (int r=1;r<=nbNoeudCentral;r++)
{ aib0_i_a += tab_noeud(r)->Coord0()(a) * dphi(i,r);
};
};
};
};
// calcul de la base naturel a t pour la surface médiane: partie a_alpha
void Met_Sfe1::Calcul_a_alpha_B_t
( const Tableau<Noeud *>& tab_noeud, const Mat_pleine& dphi, int ,const Vecteur&)
{
#ifdef MISE_AU_POINT
if (aiB_t == NULL)
{ cout << "\nErreur : la base a t n'est pas dimensionne !\n";
cout << "void Met_Sfe1::Calcul_aiB_t \n";
Sortie(1);
};
#endif
for (int i=1;i<= 2;i++)
{for (int a=1;a<= dim_base;a++)
{ double & aibt_i_a = aiB_t->CoordoB(i)(a);
aibt_i_a = 0.;
for (int r=1;r<=nbNoeudCentral;r++)
{ aibt_i_a += tab_noeud(r)->Coord1()(a) * dphi(i,r);
};
};
};
};
// calcul de la base naturel a tdt pour la surface médiane: partie a_alpha
void Met_Sfe1::Calcul_a_alpha_B_tdt
( const Tableau<Noeud *>& tab_noeud, const Mat_pleine& dphi, int ,const Vecteur&)
{
#ifdef MISE_AU_POINT
if (aiB_tdt == NULL)
{ cout << "\nErreur : la base a t+dt n'est pas dimensionne !\n";
cout << "void Met_Sfe1::Calcul_aiB_tdt \n";
Sortie(1);
};
#endif
for (int i=1;i<= 2;i++)
{for (int a=1;a<= dim_base;a++)
{ double & aibtdt_i_a = aiB_tdt->CoordoB(i)(a);
aibtdt_i_a = 0.;
for (int r=1;r<=nbNoeudCentral;r++)
{ aibtdt_i_a += tab_noeud(r)->Coord2()(a) * dphi(i,r);
};
};
};
};
//== calcul de la variation des bases pour la surface médiane: partie a_alpha
// ici il ne s'agit uniquement que de la variation de a_alpha et pas a_3
void Met_Sfe1::D_a_alpha_B_t( const Mat_pleine& dphi, int ,const Vecteur & )
{ int indice;
// derivees de aBi par rapport a XHbr
for (int b = 1; b<= dim_base; b++)
for (int r = 1; r <= nbNoeudCentral; r++)
{ indice = (r-1)*dim_base + b;
BaseB & d_aiB_t_indice=(*d_aiB_t)(indice);
for (int i =1;i<=2;i++) // alpha = 1 et 2 uniquement
{ d_aiB_t_indice.CoordoB(i).Zero();
d_aiB_t_indice.CoordoB(i)(b)=dphi(i,r);
}
};
};
// ici il ne s'agit uniquement que de la variation de a_alpha et pas a_3
void Met_Sfe1::D_a_alpha_B_tdt( const Mat_pleine& dphi, int ,const Vecteur &)
{ int indice;
for (int b = 1; b<= dim_base; b++)
for (int r = 1; r <= nbNoeudCentral; r++)
{ indice = (r-1)*dim_base + b;
BaseB & d_aiB_tdt_indice=(*d_aiB_tdt)(indice);
for (int i =1;i<=2;i++) // alpha = 1 et 2 uniquement
{ d_aiB_tdt_indice.CoordoB(i).Zero();
d_aiB_tdt_indice.CoordoB(i)(b)=dphi(i,r);
}
}
};
//== calcul de la variation de a_3_B
void Met_Sfe1::D_a_3_B_t()
{ int nbddlx = tab_ddl.NbDdl_famille(X1);
// calcul de la variation de a3B par rapport au ddlxi
for (int iddl=1;iddl<= nbddlx;iddl++)
(*d_aiB_t)(iddl).CoordoB(3) = (epais.epaisseur_t * 0.5) * (*d_N_t)(iddl);
// calcul de la variation en fonction des ddl d'épaisseur
int nbddl_total = nbddlx + nbNoeudCentral;int ih=1;
for (int iddl=nbddlx+1;iddl <= nbddl_total;iddl++,ih++)
(*d_aiB_t)(iddl).CoordoB(3) = ((*d_epais)(ih).epaisseur_t * 0.5 ) * N_t;
};
void Met_Sfe1::D_a_3_B_tdt()
{ int nbddlx = tab_ddl.NbDdl_famille(X1);
// calcul de la variation de a3B par rapport au ddlxi
for (int iddl=1;iddl<= nbddlx;iddl++)
(*d_aiB_tdt)(iddl).CoordoB(3) = (epais.epaisseur_tdt * 0.5) * (*d_N_tdt)(iddl);
// calcul de la variation en fonction des ddl d'épaisseur
int nbddl_total = nbddlx + nbNoeudCentral;int ih=1;
for (int iddl=nbddlx+1;iddl <= nbddl_total;iddl++,ih++)
(*d_aiB_tdt)(iddl).CoordoB(3) = ((*d_epais)(ih).epaisseur_tdt * 0.5 ) * N_tdt;
};
// --------- calcul de la base naturel a t0 ------
// neccessite le calcul prealable de la courbure et de la base naturelle et duale de la facette
// également l'épaisseur interpolée si on est avec des éléments 3D
void Met_Sfe1::Calcul_giB_0
( const Tableau<Noeud *>& , const Mat_pleine& , int , const Vecteur& phiH)
{
#ifdef MISE_AU_POINT
if (giB_0 == NULL)
{ cout << "\nErreur : la base a t=0 n'est pas dimensionne !\n";
cout << "void Met_Sfe1::Calcul_giB_0 \n";
Sortie(1);
};
#endif
// vecteur de base gi,
// theta^3 = (phiH(2)-phiH(1));
double z0 = epais.epaisseur0 * 0.5 * (phiH(2)-phiH(1));
// ici il n'y a pas le terme de variation de h par rapport au theta^alpha
giB_0->CoordoB(1) = (*aiB_0)(1) + N_alpha_0_1 * z0;
giB_0->CoordoB(2) = (*aiB_0)(2) + N_alpha_0_2 * z0;
if (tCalEpais) // cas 3D
giB_0->CoordoB(3) = (*aiB_0)(3);
};
// calcul de la base naturel a t
// neccessite le calcul prealable de la courbure et de la base naturelle et duale de la facette
void Met_Sfe1::Calcul_giB_t
( const Tableau<Noeud *>& , const Mat_pleine& , int, const Vecteur& phiH)
{
#ifdef MISE_AU_POINT
if (giB_t == NULL)
{ cout << "\nErreur : la base a t n'est pas dimensionne !\n";
cout << "void Met_Sfe1::Calcul_giB_t \n";
Sortie(1);
};
#endif
// vecteur de base gi
double z_t = epais.epaisseur_t * 0.5 * (phiH(2)-phiH(1));
// ici il n'y a pas le terme de variation de h par rapport au theta^alpha
giB_t->CoordoB(1) = (*aiB_t)(1) + N_alpha_t_1 * z_t;
giB_t->CoordoB(2) = (*aiB_t)(2) + N_alpha_t_2 * z_t;
if (tCalEpais) // cas 3D
giB_t->CoordoB(3) = (*aiB_t)(3);
};
// calcul de la base naturel a tdt
// neccessite le calcul prealable de la courbure et de la base naturelle et duale de la facette
void Met_Sfe1::Calcul_giB_tdt
( const Tableau<Noeud *>& , const Mat_pleine& , int, const Vecteur& phiH)
{
#ifdef MISE_AU_POINT
if (giB_tdt == NULL)
{ cout << "\nErreur : la base a t+dt n'est pas dimensionne !\n";
cout << "void Met_Sfe1::Calcul_giB_tdt \n";
Sortie(1);
};
#endif
// vecteur de base gi
double z_tdt = epais.epaisseur_tdt * 0.5 * (phiH(2)-phiH(1));
// ici il n'y a pas le terme de variation de h par rapport au theta^alpha
giB_tdt->CoordoB(1) = (*aiB_tdt)(1) + N_alpha_tdt_1 * z_tdt;
giB_tdt->CoordoB(2) = (*aiB_tdt)(2) + N_alpha_tdt_2 * z_tdt;
if (tCalEpais) // cas 3D
giB_tdt->CoordoB(3) = (*aiB_tdt)(3);
};
//------------// variation des vecteurs de base
// il faut au par avant avoir calculé la variation de l'épaisseur si on est en 3D
void Met_Sfe1::D_giB_t( const Mat_pleine& , int , const Vecteur & phiH)
{ double z_t = epais.epaisseur_t * 0.5 * (phiH(2)-phiH(1));
int nbddlx = tab_ddl.NbDdl_famille(X1);
for (int iddl=1;iddl<= nbddlx;iddl++)
{ // vecteur de base gi
(*d_giB_t)(iddl).CoordoB(1) = (*d_aiB_t)(iddl)(1) + (*d_N_alpha_t_1)(iddl) * z_t;
(*d_giB_t)(iddl).CoordoB(2) = (*d_aiB_t)(iddl)(2) + (*d_N_alpha_t_2)(iddl) * z_t;
};
// cas 3D
if (tCalEpais)
{// variation de giB3 = en fait celle de aiB3
int nbddl_total = nbddlx + nbNoeudCentral;
for (int iddl=1;iddl<= nbddl_total;iddl++)
(*d_giB_t)(iddl).CoordoB(3) = (*d_aiB_t)(iddl)(3);
// ensuite les vecteurs g1B et g2B dépendent aussi des ddl d'épaisseur
// on calcul donc cette variation, et on en profite pour calculer également la variation de g3B
// en fonction des ddl d'épaisseur
int ih=1;
for (int iddl=nbddlx+1;iddl <= nbddl_total;iddl++,ih++)
{(*d_giB_t)(iddl).CoordoB(1) = ((*d_epais)(ih).epaisseur_t * 0.5 * (phiH(2)-phiH(1))) * N_alpha_t_1;
(*d_giB_t)(iddl).CoordoB(2) = ((*d_epais)(ih).epaisseur_t * 0.5 * (phiH(2)-phiH(1))) * N_alpha_t_2;
};
};
};
void Met_Sfe1::D_giB_tdt( const Mat_pleine& , int , const Vecteur & phiH)
{ double z_tdt = epais.epaisseur_tdt * 0.5 * (phiH(2)-phiH(1));
int nbddlx = tab_ddl.NbDdl_famille(X1);
for (int iddl=1;iddl<= nbddlx;iddl++)
{// vecteur de base gi
(*d_giB_tdt)(iddl).CoordoB(1) = (*d_aiB_tdt)(iddl)(1) + (*d_N_alpha_tdt_1)(iddl) * z_tdt;
(*d_giB_tdt)(iddl).CoordoB(2) = (*d_aiB_tdt)(iddl)(2) + (*d_N_alpha_tdt_2)(iddl) * z_tdt;
#ifdef MISE_AU_POINT
if (ParaGlob::NiveauImpression() > 5)
{if (((*d_giB_tdt)(iddl)(1).Norme() > 10000.) || ((*d_giB_tdt)(iddl)(1).Norme() < -10000.)
|| ((*d_giB_tdt)(iddl)(2).Norme() > 10000.) || ((*d_giB_tdt)(iddl)(2).Norme() < -10000.) )
{cout << "\n attention erreur , les d_giB_tdt sont trop grand "
<< "\n Met_Sfe1::D_giB_tdt(..."
<< " (*d_giB_tdt)(iddl)(1).Norme()=" << (*d_giB_tdt)(iddl)(1).Norme()
<< " (*d_giB_tdt)(iddl)(2).Norme()=" << (*d_giB_tdt)(iddl)(2).Norme()
<< " (*d_aiB_tdt)(iddl)(1).Norme()=" << (*d_aiB_tdt)(iddl)(1).Norme()
<< " (*d_aiB_tdt)(iddl)(2).Norme()=" << (*d_aiB_tdt)(iddl)(2).Norme()
<< " (*d_N_alpha_tdt_1)(iddl).Norme()=" << (*d_N_alpha_tdt_1)(iddl).Norme()
<< " (*d_N_alpha_tdt_2)(iddl).Norme()=" << (*d_N_alpha_tdt_2)(iddl).Norme()
<< endl ;
};
};
#endif
};
// cas 3D
if (tCalEpais)
{// variation de giB3 = en fait celle de aiB3
int nbddl_total = nbddlx + nbNoeudCentral;
for (int iddl=1;iddl<= nbddl_total;iddl++)
(*d_giB_tdt)(iddl).CoordoB(3) = (*d_aiB_tdt)(iddl)(3);
// ensuite les vecteurs g1B et g2B dépendent aussi des ddl d'épaisseur
// on calcul donc cette variation, et on en profite pour calculer également la variation de g3B
// en fonction des ddl d'épaisseur
int ih=1;
for (int iddl=nbddlx+1;iddl <= nbddl_total;iddl++,ih++)
{(*d_giB_tdt)(iddl).CoordoB(1) = ((*d_epais)(ih).epaisseur_tdt * 0.5 * (phiH(2)-phiH(1))) * N_alpha_tdt_1;
(*d_giB_tdt)(iddl).CoordoB(2) = ((*d_epais)(ih).epaisseur_tdt * 0.5 * (phiH(2)-phiH(1))) * N_alpha_tdt_2;
};
};
};
//-----------// calcul du tenseur de courbure dans la base naturelle
// on utilise un tenseur non symétrique, bien qu'en théorie la courbure est symétrique
// suivant les différentes méthodes de calcul, le tenseur en sortie est symétrique ou pas
// on peut toujours le symétriser, si l'on veut un tenseur symétrique
// on a : N,al = - b_{al be} . a^{be}
// plusieurs cas sont etudies suivant l'instant considere
// a l'instant t = 0
Tenseur_ns2BB& Met_Sfe1::courbure_0 ( const Tableau<Noeud *>& tab_noeud
,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan)
{ Tableau<Coordonnee3> tab_coor(6);
// actuellement les courbures s'obtiennent à l'aide des noeuds sommets du triangle
// du milieu et des noeuds externes: on est pour l'instant dans un cadre de triangle
for (int i=1;i< 4;i++) // les 3 noeuds sommet interne
tab_coor(i) = tab_noeud(i)->Coord0();
for (int i=1;i< 4;i++) // les noeuds externes
tab_coor(i+3) = tab_noeud(i+nbNoeudCentral)->Coord0();
// for (int i=1;i<=6;i++)
// tab_coor(i) = tab_noeud(i)->Coord0();
curb_0 = (this->*PtCourbure)(tab_coor,(*aiB_0),(*aiH_0),tabTypeCL,vplan);
return curb_0;
};
// a l'instant t
Tenseur_ns2BB& Met_Sfe1::courbure_t ( const Tableau<Noeud *>& tab_noeud
,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan)
{ Tableau<Coordonnee3> tab_coor(6);
// actuellement les courbures s'obtiennent à l'aide des noeuds sommets du triangle
// du milieu et des noeuds externes: on est pour l'instant dans un cadre de triangle
for (int i=1;i< 4;i++) // les 3 noeuds sommet interne
tab_coor(i) = tab_noeud(i)->Coord1();
for (int i=1;i< 4;i++) // les noeuds externes
tab_coor(i+3) = tab_noeud(i+nbNoeudCentral)->Coord1();
// for (int i=1;i<=6;i++)
// tab_coor(i) = tab_noeud(i)->Coord1();
curb_t = (this->*PtCourbure)(tab_coor,(*aiB_t),(*aiH_t),tabTypeCL,vplan);
return curb_t;
};
// a l'instant t+dt
Tenseur_ns2BB& Met_Sfe1::courbure_tdt ( const Tableau<Noeud *>& tab_noeud
,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan)
{ Tableau<Coordonnee3> tab_coor(6);
// actuellement les courbures s'obtiennent à l'aide des noeuds sommets du triangle
// du milieu et des noeuds externes: on est pour l'instant dans un cadre de triangle
for (int i=1;i< 4;i++) // les 3 noeuds sommet interne
tab_coor(i) = tab_noeud(i)->Coord2();
for (int i=1;i< 4;i++) // les noeuds externes
tab_coor(i+3) = tab_noeud(i+nbNoeudCentral)->Coord2();
// for (int i=1;i<=6;i++)
// tab_coor(i) = tab_noeud(i)->Coord2();
curb_tdt = (this->*PtCourbure)(tab_coor,(*aiB_tdt),(*aiH_tdt),tabTypeCL,vplan);
return curb_tdt;
};
//--------------// calcul du tenseur de courbure et de sa variation
// plusieurs cas sont etudies suivant l'instant considere
// a l'instant t
void Met_Sfe1::Dcourbure_t
( const Tableau<Noeud *>& tab_noeud,Tenseur_ns2BB& curb,TabOper<Tenseur_ns2BB>& dcurb
,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan)
{ Tableau<Coordonnee3> tab_coor(6);
// actuellement les courbures s'obtiennent à l'aide des noeuds sommets du triangle
// du milieu et des noeuds externes: on est pour l'instant dans un cadre de triangle
for (int i=1;i< 4;i++) // les 3 noeuds sommet interne
tab_coor(i) = tab_noeud(i)->Coord1();
for (int i=1;i< 4;i++) // les noeuds externes
tab_coor(i+3) = tab_noeud(i+nbNoeudCentral)->Coord1();
// for (int i=1;i<=6;i++)
// tab_coor(i) = tab_noeud(i)->Coord1();
(this->*PtDcourbure) (tab_coor,(*aiB_t),*d_aiB_t,(*aiH_t),*d_aiH_t,curb,dcurb,tabTypeCL,vplan);
};
// a l'instant t+dt
void Met_Sfe1::Dcourbure_tdt
( const Tableau<Noeud *>& tab_noeud,Tenseur_ns2BB& curb,TabOper<Tenseur_ns2BB>& dcurb
,Tableau <EnuTypeCL> const & tabTypeCL,Tableau <Coordonnee3> const & vplan)
{ Tableau<Coordonnee3> tab_coor(6);
// actuellement les courbures s'obtiennent à l'aide des noeuds sommets du triangle
// du milieu et des noeuds externes: on est pour l'instant dans un cadre de triangle
for (int i=1;i< 4;i++) // les 3 noeuds sommet interne
tab_coor(i) = tab_noeud(i)->Coord2();
for (int i=1;i< 4;i++) // les noeuds externes
tab_coor(i+3) = tab_noeud(i+nbNoeudCentral)->Coord2();
// for (int i=1;i<=6;i++)
// tab_coor(i) = tab_noeud(i)->Coord2();
(this->*PtDcourbure) (tab_coor,(*aiB_tdt),*d_aiB_tdt,(*aiH_tdt),*d_aiH_tdt,curb,dcurb,tabTypeCL,vplan);
};
// ----------- routines internes pour calculer les différentes formes de courbures
// routine generale de calcul de la courbure
// cas 1: calcul des 3 courbures suivant les 3 cotés
Tenseur_ns2BB Met_Sfe1::Courbure1
( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH & aiH
,Tableau <EnuTypeCL> const & ,Tableau <Coordonnee3> const & )
{ Vecteur curbp(3),curbi(3); // : les tenseurs de courbures d'abord dans les axes
// locaux des arretes du triangle puis dans le repere naturel: b11,b12,b22
Mat_pleine mat(3,3); // matrice pour calculer le tenseur de courbure
// calcul de la normale centrale
Coordonnee3 N(Util::ProdVec_coorBN(aiB(1),aiB(2)).Normer());
// calcul du centre de gravite
Coordonnee3 G((tab_coor(1) + tab_coor(2) + tab_coor(3)) / 3.);
// le meme calcul est effectue pour les trois cotes du triangle principale
//1- on utilise indi un tableau d'indice pour ne pas etre embete par les modulos 3
// 2- on boucle sur le cotes du triangle
Coordonnee3 Ni(3); // normale du triangle exterieur
// def des différentes grandeurs
Coordonnee3 G2;
Coordonnee3 H2G2,CB,U1,CG2,C_G,CA,dNdV;
Coordonnee3 U2p;
for (int ncot=1;ncot<=3;ncot++)
{ // on utilise les notations : triangle principal DBC et secondaire BAC
// on cherche a calculer la longueur H2G2
// simplification de l'ecriture (vérifiée)
const Coordonnee3& D = tab_coor(indi(ncot));
const Coordonnee3& B = tab_coor(indi(ncot+1));
const Coordonnee3& C = tab_coor(indi(ncot+2));
const Coordonnee3& A = tab_coor(indi(ncot)+3);
if (D != A) // cas ou le noeud externe existe
{ // calcul de G2, centre de gravite du triangle exterieur
G2 = (B + C + A) / 3.;
// calcul de U1
CB = B - C;
U1 = CB / CB.Norme();
// vecteur CG2
CG2 = G2 - C;
// longueur h2G2 et g_h1 et calcul du vecteur H2G2 norme
// tout d'abord H2G2 ce situe dans le plan de la facette externe
H2G2 = CG2 - (CG2 * U1) * U1;
double h2G2 = H2G2.Norme();
double unSurh2G2= 1./h2G2;
// maintenant on considere la direction H2G2, ramenée dans le plan de la facette centrale: U2p
U2p = Util::ProdVec_coor(N,U1);
C_G = G - C; // on met un _ car ce nom existe pour une autre routine
double g_h1 = sqrt ( C_G * C_G - ( C_G * U1)* ( C_G * U1)) ;
// calcul de la normale du triangle exterieur
CA = A - C;
Ni = (Util::ProdVec_coor(CB,CA)).Normer();
// calcul de la derivee de la normale
dNdV = ( Ni - N) / ( g_h1 + h2G2);
// courbure dans la direction U2p
curbp(ncot) = - dNdV * U2p;
}
else // cas ou il n'y a pas de noeud externe
{ // la courbure est nulle
curbp(ncot) = 0.;
// la direction de la courbure nulle est normale au cote
// c-a-d le produit vectoriel de la normale avec le cote
CB = B - C;
double norCB = CB.Norme();
U1 = CB / norCB;
U2p = Util::ProdVec_coor(N,U1);
}
// calcul de la matrice de passage de Ualpha a aalpha
double Beta21 = U2p * aiH.Coordo(1);
double Beta22 = U2p * aiH.Coordo(2);
// remplissage de la matrice mat
mat(ncot,1) = Beta21*Beta21;
mat(ncot,2) = 2.* Beta21*Beta22;
mat(ncot,3) = Beta22*Beta22;
};
// calcul du tenseur de courbure dans la base ai
Mat_pleine mati = mat.Inverse();
curbi = mati * curbp;
// retour de la courbure
Tenseur_ns2BB curb;
curb.Coor(1,1)=curbi(1); curb.Coor(1,2)=curb.Coor(2,1)=curbi(2); curb.Coor(2,2)=curbi(3);
return curb;
};
// routine generale de calcul de la courbure et de sa variation
// en sortie : curb , la courbure b11,b12,b22
// dcurb , la variation de courbure.
// On ne considere dans les variations que les termes relatif aux ddl qui font varier
// les normales
// cas 1: calcul des 3 courbures suivant les 3 cotés
void Met_Sfe1::Dcourbure1
( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
, const Tableau <BaseB>& DaiB,const BaseH & aiH
, const Tableau <BaseH>& DaiH,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
,Tableau <EnuTypeCL> const & ,Tableau <Coordonnee3> const & )
{ int nbddl = (nbNoeudCentral+3)*3; //18; // nombre de ddl total
Coordonnee3 Nul; // le vecteur nul de dim 3, pour les initialisations
Vecteur curbi(3); // la courbure sous forme de vecteur
Vecteur curbp(3); // : les tenseurs de courbures dans les axes
// locaux des arretes du triangle
double untiers=1./3.;
Vecteur vecNul(3); // un vecteur nul pour l'initialisation
Tableau <Vecteur> dcurbp(nbddl,vecNul); // variation des courbures
Mat_pleine mat(3,3); // matrice pour calculer le tenseur de courbure
Tableau <Mat_pleine> dmat(nbddl,mat);
// calcul de la normale centrale
Coordonnee3 NN(Util::ProdVec_coorBN(aiB(1),aiB(2))); // normale non normee
double nor = NN.Norme(); // la norme
Coordonnee3 N = NN / nor;
Coordonnee3 DNN; // vecteur intermediaire
// calcul du centre de gravite
Coordonnee3 G ((tab_coor(1) + tab_coor(2) + tab_coor(3)) * untiers);
// et le tableau de ses variations
Tableau <Coordonnee3> dG(nbddl,Nul);
// calcul de la variation de la normale centrale et du centre de gravité: vérifiée
Tableau <Coordonnee3> dN(nbddl,Nul);
// on s'intéresse ici qu'aux ddl de la face centrale
for (int inc=1;inc<=3;inc++) // indice du numéro de noeud de la face centrale
for (int ib=1;ib<=3;ib++)
{ // cas de la normale
int i1=(inc-1)*3+ib;
DNN = Util::ProdVec_coorBN(DaiB(i1)(1),aiB(2)) + Util::ProdVec_coorBN(aiB(1),DaiB(i1)(2));
dN(i1) = Util::VarUnVect_coor(NN,DNN,nor);
// cas du centre de gravité
dG(i1)=untiers*Ia(ib);
};
// le meme calcul est effectue pour les trois cotes du triangle principale
//1- on utilise un tableau d'indice pour ne pas etre embete par les modulos 3
// 2- on boucle sur le cotes du triangle
Coordonnee3 NNi,Ni; // normale du triangle exterieur
// -------- declaration pour la boucle sur les 3 cotes ------------
Coordonnee3 G2(3); // init a zero et a 3 composantes
Tableau <Coordonnee3> dB(nbddl,Nul),dC(nbddl,Nul),dA(nbddl,Nul),dG2(nbddl,Nul) ; // variation des points
Vecteur d_g_h1(nbddl);
Coordonnee3 CB,U1,CG2,H2G2,U2p;
Tableau <Coordonnee3> dCB(nbddl,Nul),dU1(nbddl,Nul);
Coordonnee3 C_G,CA,dNdV;
Tableau <Coordonnee3> dCA(nbddl,Nul),dNi(nbddl,Nul);
Coordonnee3 ddNdv;
for (int ncot=1;ncot<=3;ncot++)
{ // on utilise les notations : triangle principal DBC et secondaire BAC
// on cherche a calculer la longueur H2G2
// simplification de l'ecriture
const Coordonnee3& D = tab_coor(indi(ncot));
const Coordonnee3& B = tab_coor(indi(ncot+1));
const Coordonnee3& C = tab_coor(indi(ncot+2));
const Coordonnee3& A = tab_coor(indi(ncot)+3);
if (D != A) // cas ou le noeud externe existe
{// calcul de G2, centre de gravite du triangle exterieur
G2 = (B + C + A) * untiers;
// calcul de U1
CB = B - C;
double norCB = CB.Norme();
U1 = CB / norCB;
// vecteur CG2
CG2 = G2 - C;
// longueur h2G2 et g_h1 et calcul du vecteur H2G2 norme
// tout d'abord H2G2 ce citue dans le plan de la facette externe
H2G2 = CG2 - (CG2 * U1) * U1;
double h2G2 = H2G2.Norme();
double unSurh2G2= 1./h2G2;
// maintenant on considere la direction H2G2, ramenée dans le plan de la facette centrale: U2p
U2p = Util::ProdVec_coor(N,U1);
C_G = G - C;
double g_h1 = sqrt ( C_G * C_G - ( C_G * U1) * ( C_G * U1) ) ;
// calcul de la normale du triangle exterieur
CA = A - C;
NNi = Util::ProdVec_coor(CB,CA);
double norNi = NNi.Norme();
Ni = NNi/norNi;
// calcul de la derivee de la normale
dNdV = ( Ni - N) / ( g_h1 + h2G2);
// courbure dans la direction U2p
curbp(ncot) = - dNdV * U2p;
// calcul de la matrice de passage de Ualpha a aalpha
double Beta21 = U2p * aiH.Coordo(1);
double Beta22 = U2p * aiH.Coordo(2);
// remplissage de la matrice mat
mat(ncot,1) = Beta21*Beta21;
mat(ncot,2) = 2.* Beta21*Beta22;
mat(ncot,3) = Beta22*Beta22;
// calcul des variations
// 1 - initialisation des vecteurs inter
ddNdv.Zero();
// 2 - init en fct des ddl
for (int idi=1; idi<= nbddl; idi++)
{ dCA(idi).Zero(); dCB(idi).Zero();dNi(idi).Zero();
dB(idi).Zero();dC(idi).Zero();dA(idi).Zero();
dU1(idi).Zero();d_g_h1.Zero();dG2(idi).Zero();
};
// 3 - variation non nulle des Ni pour certaine valeur d'indice
for (int ia=1;ia<= 3;ia++)
{ // on a 3 indices pour chaque ia, pour lesquels la variation est non nulle
// dans cette boucle on n'utilise pas systematiquement les 4 indices
int jnB = (indi(ncot+1)-1)*3+ia; // vérifié
int jnC = (indi(ncot+2)-1)*3+ia;
int jnA = 9+(ncot-1)*3+ia; //vérifié
// tout d'abord les variations des points
dB(jnB) = Ia(ia);
dC(jnC) = Ia(ia);dA(jnA) = Ia(ia);
dG2(jnA) = untiers * Ia(ia);dG2(jnB) = untiers * Ia(ia);dG2(jnC) = untiers * Ia(ia);
// vecteur CB
dCB(jnB) = dB(jnB); dCB(jnC) = - dC(jnC);
// Vecteur CA = A - C
dCA(jnC) = -dC(jnC); dCA(jnA) = dA(jnA);
// Vecteur Ni = (Util::ProdVec_coor(CB,CA)).Normer()
dNi(jnC) = Util::VarUnVect_coor(NNi,(Util::ProdVec_coor(dCB(jnC),CA)+Util::ProdVec_coor(CB,dCA(jnC))),norNi);
dNi(jnB) = Util::VarUnVect_coor(NNi,(Util::ProdVec_coor(dCB(jnB),CA)+Util::ProdVec_coor(CB,dCA(jnB))),norNi);
dNi(jnA) = Util::VarUnVect_coor(NNi,(Util::ProdVec_coor(dCB(jnA),CA)+Util::ProdVec_coor(CB,dCA(jnA))),norNi);
// Vecteur U1 = CB / norCB;
dU1(jnC) = Util::VarUnVect_coor(CB,dCB(jnC),norCB);
dU1(jnB) = Util::VarUnVect_coor(CB,dCB(jnB),norCB);
};
for (int ib=1;ib<= 3;ib++) // indice de coordonnées
{ // on a 4 indices pour chaque ia, pour lesquels la variation est non nulle
// mais ici on utilise systematiquement les 4 indices d'ou une seconde boucle
// egalement moins de stockage intermediaire
// jnb[0] -> D, jnb[1] -> B, jnb[2] -> C, jnb[3] -> A,
int jnb[4] = {(indi(ncot)-1)*3+ib,(indi(ncot+1)-1)*3+ib,
(indi(ncot+2)-1)*3+ib,9+(ncot-1)*3+ib};
for (int jb=0;jb<=3;jb++)
{ // variation de g_h1
Coordonnee3 d_CG =dC(jnb[jb])-dG(jnb[jb]);
double d_CGsur2 = (d_CG * C_G);
double d_CG_U1 = d_CG * U1 + C_G * dU1(jnb[jb]);
double d_g_h1 = (d_CGsur2 - d_CG_U1)/g_h1;
// variation de h2G2
Coordonnee3 d_CG2 =dC(jnb[jb])-dG2(jnb[jb]);
Coordonnee3 d_H2G2 =d_CG2 - (d_CG2 * U1 + CG2 * dU1(jnb[jb])) * U1
- (CG2 * U1) *dU1(jnb[jb]);
double d_h2G2 = (H2G2 * d_H2G2)/h2G2;
// vecteur dNdV = ( Ni - N) / ( g_h1 + h2G2)
ddNdv = ((dNi(jnb[jb]) - dN(jnb[jb]))
- (Ni-N) * (d_g_h1 + d_h2G2) / ( g_h1 + h2G2)) / ( g_h1 + h2G2);
// variation de U2p
Coordonnee3 d_U2p = Util::ProdVec_coor(dN(jnb[jb]),U1)+Util::ProdVec_coor(N,dU1(jnb[jb]));
// courbure curbp(ncot) = dNdV * U2p;
dcurbp(jnb[jb])(ncot) = - (ddNdv * U2p + dNdV * d_U2p);
// -- variation des composantes de mat
double d_Beta21 = d_U2p * aiH.Coordo(1) + U2p * DaiH(jnb[jb]).Coordo(1);
double d_Beta22 = d_U2p * aiH.Coordo(2) + U2p * DaiH(jnb[jb]).Coordo(2);
dmat(jnb[jb])(ncot,1)= 2. * Beta21 * d_Beta21;
dmat(jnb[jb])(ncot,2)= 2. * (d_Beta21 * Beta22 + Beta21 * d_Beta22);
dmat(jnb[jb])(ncot,3)= 2. * Beta22 * d_Beta22;
};
}
}
else // cas ou il n'y a pas de noeud externe
{ // la courbure est nulle
curbp(ncot) = 0.;
// la direction de la courbure nulle est normale au cote
// c-a-d le produit vectoriel de la normale avec le cote
CB = B - C;
double norCB = CB.Norme();
U1 = CB / norCB;
H2G2 = Util::ProdVec_coor(N,U1);
// calcul de la matrice de passage de Ualpha a aalpha
double Beta21 = H2G2 * aiH.Coordo(1);
double Beta22 = H2G2 * aiH.Coordo(2);
// remplissage de la matrice mat
mat(ncot,1) = Beta21*Beta21;
mat(ncot,2) = 2.* Beta21*Beta22;
mat(ncot,3) = Beta22*Beta22;
}
}; //-- fin de la boucle sur les trois cotés
// calcul du tenseur de courbure dans la base ai
Mat_pleine mati = mat.Inverse();
curbi = mati * curbp;
curb.Coor(1,1)=curbi(1); curb.Coor(1,2)=curb.Coor(2,1)=curbi(2); curb.Coor(2,2)=curbi(3);
// idem pour les variations
Mat_pleine dmata(mat); // une matrice intermédiaire
for (int ddl=1;ddl<=nbddl;ddl++)
{ // tout d'abord le calcul de la variation de l'inverse de mat
dmata = -(mati * dmat(ddl) * mati);
// puis la variation de la courbure
curbi = mati * dcurbp(ddl) + dmata * curbp;
Tenseur_ns2BB& dcur = dcurb(ddl);
dcur.Coor(1,1)=curbi(1); dcur.Coor(1,2)=dcur.Coor(2,1)=curbi(2); dcur.Coor(2,2)=curbi(3);
};
};
// test si la courbure est anormalement trop grande
// inf_normale : indique en entrée le det mini pour la courbure en locale
// retour 1: si tout est ok,
// 0: une courbure trop grande a été détecté
int Met_Sfe1::Test_courbure_anormale1(double inf_normale,const Tableau<Coordonnee3>& tab_coor
, const BaseB & aiB , const BaseH & aiH)
{// pour l'instant cette méthode n'est pas alimentée on le signale
if (ParaGlob::NiveauImpression()> 8)
cout << "\n *** attention, cette methode n'est pas implante pour la courbure 1 "
<< "\n Met_Sfe1::Test_courbure_anormale1(... "<<endl;
return 1; // retour par défaut
};
// routine generale de calcul de la courbure
// cas 2: moyenne des normales de part et autres des arrêtes
Tenseur_ns2BB Met_Sfe1::Courbure2
( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH &
,Tableau <EnuTypeCL> const & ,Tableau <Coordonnee3> const & )
{ Tenseur_ns2BB curb; // : les tenseurs de courbures d'abord dans les axes
// au lieu d'utiliser des expressions condensées (en commentaire)
// on utilise exactement la même procédure que pour dcurb
// car sinon on a de très petites différences qui ensuite
// conduisent à des différences non négligeables sur les def
// calcul de la normale centrale
// Coordonnee3 N((Util::ProdVec_coorBN(aiB(1),aiB(2))).Normer());
// calcul de la normale centrale
Coordonnee3 NN(Util::ProdVec_coorBN(aiB(1),aiB(2))); // normale non normee
double nor = NN.Norme(); // la norme
Coordonnee3 N = NN / nor;
// le meme calcul est effectue pour les trois cotes du triangle principale
//1- on utilise indi un tableau d'indice pour ne pas etre embete par les modulos 3
// 2- on boucle sur le cotes du triangle
Tableau <Coordonnee3> t_Ni(3); // les 3 normales du triangle exterieur
//cout << "\n N= "<<N;
Coordonnee3 NNi,Ni,NietN; // normale du triangle exterieur
for (int ncot=1;ncot<=3;ncot++)
{ // on utilise les notations : triangle principal DBC et secondaire BAC
// on cherche a calculer la longueur H2G2
// simplification de l'ecriture (vérifiée)
const Coordonnee3& D = tab_coor(indi(ncot));
const Coordonnee3& B = tab_coor(indi(ncot+1));
const Coordonnee3& C = tab_coor(indi(ncot+2));
const Coordonnee3& A = tab_coor(indi(ncot)+3);
if (D != A) // cas ou le noeud externe existe
{// calcul de la normale du triangle exterieur
Coordonnee3 CB = B - C;
Coordonnee3 CA = A - C;
//t_Ni(ncot) = ((Util::ProdVec_coor(CB,CA)).Normer() + N).Normer();
NNi = Util::ProdVec_coor(CB,CA);
double norNi = NNi.Norme();
Ni = NNi/norNi;
NietN=(Ni + N);
double norNietN = NietN.Norme();
t_Ni(ncot) = NietN / norNietN;
}
else // cas ou il n'y a pas de noeud externe
{ // on utilise la normale actuelle comme normale sur l'arrête
t_Ni(ncot) = N;
};
};
// calcul de la variation de la normale
Coordonnee3 dN_1 = 2.*(t_Ni(1)-t_Ni(2));
Coordonnee3 dN_2 = 2.*(t_Ni(1)-t_Ni(3));
// courbure
curb.Coor(1,1)=-dN_1 * aiB.Coordo(1);
curb.Coor(1,2)=-dN_1 * aiB.Coordo(2);
curb.Coor(2,1)=-dN_2 * aiB.Coordo(1);
curb.Coor(2,2)=-dN_2 * aiB.Coordo(2);
// retour de la courbure
return curb;
};
// routine generale de calcul de la courbure et de sa variation
// en sortie : curb , la courbure b11,b12,b22
// dcurb , la variation de courbure.
// On ne considere dans les variations que les termes relatif aux ddl qui font varier
// les normales
// cas 2: moyenne des normales de part et autres des arrêtes
void Met_Sfe1::Dcourbure2
( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
, const Tableau <BaseB>& DaiB,const BaseH &
, const Tableau <BaseH>& ,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
,Tableau <EnuTypeCL> const & ,Tableau <Coordonnee3> const & )
{ int nbddl = (nbNoeudCentral+3)*3; //18; // nombre de ddl total
Coordonnee3 Nul; // le vecteur nul de dim 3, pour les initialisations
double untiers=1./3.;
// calcul de la normale centrale
Coordonnee3 NN(Util::ProdVec_coorBN(aiB(1),aiB(2))); // normale non normee
double nor = NN.Norme(); // la norme
Coordonnee3 N = NN / nor;
Coordonnee3 DNN; // vecteur intermediaire
// calcul de la variation de la normale centrale et du centre de gravité: vérifiée
Tableau <Coordonnee3> dN(nbddl,Nul);
// on s'intéresse ici qu'aux ddl de la face centrale
for (int inc=1;inc<=3;inc++) // indice du numéro de noeud de la face centrale
for (int ib=1;ib<=3;ib++)
{ // cas de la normale
int i1=(inc-1)*3+ib;
DNN = Util::ProdVec_coorBN(DaiB(i1)(1),aiB(2))
+ Util::ProdVec_coorBN(aiB(1),DaiB(i1)(2));
dN(i1) = Util::VarUnVect_coor(NN,DNN,nor);
};
// le meme calcul est effectue pour les trois cotes du triangle principale
//1- on utilise un tableau d'indice pour ne pas etre embete par les modulos 3
// 2- on boucle sur le cotes du triangle
Coordonnee3 NNi,Ni,NietN; // normale du triangle exterieur
// -------- declaration pour la boucle sur les 3 cotes ------------
Coordonnee3 CB,CA;
Tableau <Coordonnee3> t_Ni(3); // les 3 normales du triangle exterieur
Tableau <Tableau <Coordonnee3> > d_t_Ni(nbddl,t_Ni); // le tableau des variations
Coordonnee3 dA,dB,dC,dNi;
//cout << "\n NN= "<<NN <<" nor= "<< nor <<" N= "<<N;
for (int ncot=1;ncot<=3;ncot++)
{ // on utilise les notations : triangle principal DBC et secondaire BAC
// on cherche a calculer la longueur H2G2
// simplification de l'ecriture
const Coordonnee3& D = tab_coor(indi(ncot));
const Coordonnee3& B = tab_coor(indi(ncot+1));
const Coordonnee3& C = tab_coor(indi(ncot+2));
const Coordonnee3& A = tab_coor(indi(ncot)+3);
if (D != A) // cas ou le noeud externe existe
{CB = B - C;
double norCB = CB.Norme();
// calcul de la normale du triangle exterieur
CA = A - C;
NNi = Util::ProdVec_coor(CB,CA);
double norNi = NNi.Norme();
Ni = NNi/norNi;
NietN=(Ni + N);
double norNietN = NietN.Norme();
t_Ni(ncot) = NietN / norNietN;
//cout << "\n CB= "<<CB <<" CA= "<< CA
// << "t_Ni("<<ncot<<")= "<<t_Ni(ncot);
//cout << "\n norNi= "<< norNi<< " norNietN= "<< norNietN;
// calcul des variations
for (int ia=1;ia<= 3;ia++)
{{// indice de A: jnA
// int jnA = 9+(ncot-1)*3+ia;
//modif pour généraliser int jnA = 9+(ncot-1)*3+ia; //vérifié
int jnA = nbNoeudCentral*3+(ncot-1)*3+ia;
dA = Ia(ia);
//dCA = dA;
// Vecteur Ni = (Util::ProdVec_coor(CB,CA)).Normer()
dNi = Util::VarUnVect_coor(NNi,(Util::ProdVec_coor(CB,dA)),norNi);
d_t_Ni(jnA)(ncot) = Util::VarUnVect_coor(NietN,(dNi+dN(jnA)),norNietN);
}
{// indice de B: jnB
int jnB = (indi(ncot+1)-1)*3+ia;
dB = Ia(ia);
//dCB = dB;
// Vecteur Ni = (Util::ProdVec_coor(CB,CA)).Normer()
dNi = Util::VarUnVect_coor(NNi,(Util::ProdVec_coor(dB,CA)),norNi);
d_t_Ni(jnB)(ncot) = Util::VarUnVect_coor(NietN,(dNi+dN(jnB)),norNietN);
}
{// indice de C: jnC
int jnC = (indi(ncot+2)-1)*3+ia;
dC = Ia(ia);
//dCB = -dC; dCA= -dC;
// Vecteur Ni = (Util::ProdVec_coor(CB,CA)).Normer()
dNi = Util::VarUnVect_coor(NNi,-(Util::ProdVec_coor(dC,CA)+Util::ProdVec_coor(CB,dC)),norNi);
d_t_Ni(jnC)(ncot) = Util::VarUnVect_coor(NietN,(dNi+dN(jnC)),norNietN);
}
{// indice de D: jnD
int jnD = (indi(ncot)-1)*3+ia;
// Vecteur Ni = (Util::ProdVec_coor(CB,CA)).Normer()
// dNi = vecteur nul;
d_t_Ni(jnD)(ncot) = Util::VarUnVect_coor(NietN,(dN(jnD)),norNietN);
}
}; // fin du for sur ia
}
else // cas ou il n'y a pas de noeud externe
{ // on utilise la normale actuelle comme normale sur l'arrête
t_Ni(ncot) = N;
//cout << "\n t_Ni("<<ncot<<")= "<<t_Ni(ncot);
// et pour les variations, celle de N
for (int ia=1;ia<= 3;ia++)
{ // indice de B: jnB
int jnB = (indi(ncot+1)-1)*3+ia;
d_t_Ni(jnB)(ncot) = dN(jnB);
// indice de C: jnC
int jnC = (indi(ncot+2)-1)*3+ia;
d_t_Ni(jnC)(ncot) = dN(jnC);
// indice de D: jnD
int jnD = (indi(ncot)-1)*3+ia;
d_t_Ni(jnD)(ncot) = dN(jnD);
}; // fin du for sur ia
};
}; //-- fin de la boucle sur les trois cotés
// calcul de la variation de la normale
Coordonnee3 dN_1 = 2.*(t_Ni(1)-t_Ni(2));
Coordonnee3 dN_2 = 2.*(t_Ni(1)-t_Ni(3));
// courbure
curb.Coor(1,1)=-dN_1 * aiB.Coordo(1);
curb.Coor(1,2)=-dN_1 * aiB.Coordo(2);
curb.Coor(2,1)=-dN_2 * aiB.Coordo(1);
curb.Coor(2,2)=-dN_2 * aiB.Coordo(2);
//cout << "\n 2) curb= "; curb.Ecriture(cout);
//cout << endl;
// calcul des variations de la courbure par rapport au ddl
for (int ddl=1;ddl<=nbddl;ddl++)
{Tenseur_ns2BB& dcur = dcurb(ddl);
dcur.Coor(1,1) = (-2.) * ((d_t_Ni(ddl)(1)-d_t_Ni(ddl)(2)) * aiB.Coordo(1)) - dN_1 * DaiB(ddl).Coordo(1);
dcur.Coor(1,2)= -(2.* (d_t_Ni(ddl)(1)-d_t_Ni(ddl)(2)) * aiB.Coordo(2) + (dN_1 * DaiB(ddl).Coordo(2)));
dcur.Coor(2,1)= -(2.*(d_t_Ni(ddl)(1)-d_t_Ni(ddl)(3)) * aiB.Coordo(1) + (dN_2 * DaiB(ddl).Coordo(1)));
dcur.Coor(2,2) = (-2.) * ((d_t_Ni(ddl)(1)-d_t_Ni(ddl)(3)) * aiB.Coordo(2)) - dN_2 * DaiB(ddl).Coordo(2);
};
};
// test si la courbure est anormalement trop grande
// inf_normale : indique en entrée le det mini pour la courbure en locale
// retour 1: si tout est ok,
// 0: une courbure trop grande a été détecté
int Met_Sfe1::Test_courbure_anormale2(double inf_normale,const Tableau<Coordonnee3>& tab_coor
, const BaseB & aiB , const BaseH & aiH)
{// pour l'instant cette méthode n'est pas alimentée on le signale
if (ParaGlob::NiveauImpression()> 8)
cout << "\n *** attention, cette methode n'est pas implante pour la courbure 2 "
<< "\n Met_Sfe1::Test_courbure_anormale2(... "<<endl;
return 1; // retour par défaut
};
// routine (3) generale de calcul de la courbure
// cas 3: moyenne pondérée des normales de part et autres des arrêtes, et localisation du point sur l'arrête
Tenseur_ns2BB Met_Sfe1::Courbure3
( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB , const BaseH & aiH
,Tableau <EnuTypeCL> const & ,Tableau <Coordonnee3> const & )
{ // calcul de la normale centrale
Coordonnee3 N((Util::ProdVec_coorBN(aiB(1),aiB(2))).Normer());
// calcul du centre de gravite
Coordonnee3 G = (tab_coor(1) + tab_coor(2) + tab_coor(3)) / 3.;
// les coordonnées locales non nulles des points origines des normales sur les arrêtes
// on les initialise comme si les points étaient au milieu des arrêtes
double theta1_H1=0.5; double theta2_H1=0.5;
double theta2_H2=0.5; double theta1_H3=0.5;
// origine
const Coordonnee3& Op=tab_coor(1);// origine du repère local
// le meme calcul est effectue pour les trois cotes du triangle principale
//1- on utilise indi un tableau d'indice pour ne pas etre embete par les modulos 3
// 2- on boucle sur le cotes du triangle
Tableau <Coordonnee3> t_Ni(3); // normale du triangle exterieur
// def des différentes grandeurs
Coordonnee3 Ne; // normale courante du triangle extérieur
Coordonnee3 CB,CA,CD; Coordonnee3 G2;
Coordonnee3 U1,HaA,OpHi;
for (int ncot=1;ncot<=3;ncot++)
{ // on utilise les notations : triangle principal DBC et secondaire BAC
// on cherche a calculer la longueur H2G2
// simplification de l'ecriture (vérifiée)
const Coordonnee3& D = tab_coor(indi(ncot));
const Coordonnee3& B = tab_coor(indi(ncot+1));
const Coordonnee3& C = tab_coor(indi(ncot+2));
const Coordonnee3& A = tab_coor(indi(ncot)+3);
if (D != A) // cas ou le noeud externe existe
{// calcul de G2, centre de gravite du triangle exterieur
G2 = (B + C + A) / 3.;
// calcul de U1
CB = B - C;
CA = A - C;
U1 = CB / CB.Norme();
// longueur HaA et HdD et calcul du vecteur HaA norme
// tout d'abord HaA ce situe dans le plan de la facette externe
HaA = CA - (CA * U1) * U1;
double haA = HaA.Norme();
double unSurhaA= 1./haA;
CD = D - C;
double dHd = sqrt ( CD * CD - ( CD * U1)* ( CD * U1)) ;
// calcul de la normale du triangle exterieur
Ne = (Util::ProdVec_coor(CB,CA)).Normer();
// calcul de la normale
t_Ni(ncot) = (Ne*(dHd/(dHd+haA)) + N*(haA/(dHd+haA))).Normer();
// calcul des coordonnées de la position des normales sur les arrêtes
double beta = 0.5 * (G + G2 - 2. * B) * U1;
OpHi=B+beta*U1-Op;
switch (ncot)
{case 1: theta1_H1=OpHi*aiH.Coordo(1);theta2_H1=OpHi*aiH.Coordo(2); break;
case 2: theta2_H2=OpHi*aiH.Coordo(2); break;
case 3: theta1_H3=OpHi*aiH.Coordo(1); break;
};
}
else // cas ou il n'y a pas de noeud externe
{// on utilise comme normale extérieure la normale du triangle central
t_Ni(ncot) = N;
// on utilise le point milieu de l'arrête pour le positionnement de la normale
// normalement les points sont déjà initialisés
};
};
// calcul des coefficients des fonctions d'interpolation
double s= theta1_H1 * theta2_H2 - theta1_H3 * theta2_H2 + theta2_H1 * theta1_H3;
double a_r1= theta2_H2 / s; double b_r1 = theta1_H3 / s; double c_r1 = -theta1_H3 * theta2_H2/s;
double a_r2= -theta2_H1 / s; double b_r2 = 1./theta2_H2 - theta1_H3 * theta2_H1 /theta2_H2/ s;
double c_r2 = -theta1_H3 * theta2_H1/s;
double a_r3= 1./theta1_H3 - theta1_H1 * theta2_H2 /theta1_H3/ s; double b_r3 = - theta1_H1 / s;
double c_r3 = theta2_H2 * theta1_H1 /s;
// calcul de la variation de la normale
Coordonnee3 d_N_1= t_Ni(1) * a_r1 + t_Ni(2) * a_r2 + t_Ni(3) * a_r3 ;
Coordonnee3 d_N_2= t_Ni(1) * b_r1 + t_Ni(2) * b_r2 + t_Ni(3) * b_r3 ;
// calcul de la courbure
Tenseur_ns2BB curb;
curb.Coor(1,1) = - d_N_1 * aiB.Coordo(1); curb.Coor(1,2) = - d_N_1 * aiB.Coordo(2);
curb.Coor(2,1) = - d_N_2 * aiB.Coordo(1); curb.Coor(2,2) = - d_N_2 * aiB.Coordo(2);
// retour de la courbure
return curb;
};
// test si la courbure est anormalement trop grande
// inf_normale : indique en entrée le det mini pour la courbure en locale
// retour 1: si tout est ok,
// 0: une courbure trop grande a été détecté
int Met_Sfe1::Test_courbure_anormale3(double inf_normale,const Tableau<Coordonnee3>& tab_coor
, const BaseB & aiB , const BaseH & aiH)
{// pour l'instant cette méthode n'est pas alimentée on le signale
if (ParaGlob::NiveauImpression()> 8)
cout << "\n *** attention, cette methode n'est pas implante pour la courbure 3 "
<< "\n Met_Sfe1::Test_courbure_anormale1(... "<<endl;
return 1; // retour par défaut
};
// routine (3) generale de calcul de la courbure et de sa variation
// en sortie : curb , la courbure b11,b12,b22
// dcurb , la variation de courbure.
// On ne considere dans les variations que les termes relatif aux ddl qui font varier
// les normales
// cas 3: moyenne pondérée des normales de part et autres des arrêtes, et localisation du point sur l'arrête
void Met_Sfe1::Dcourbure3
( const Tableau<Coordonnee3>& tab_coor, const BaseB & aiB
, const Tableau <BaseB>& DaiB,const BaseH & aiH
, const Tableau <BaseH>& DaiH,Tenseur_ns2BB& curb,TabOper <Tenseur_ns2BB>& dcurb
,Tableau <EnuTypeCL> const & ,Tableau <Coordonnee3> const & )
{ int nbddl = (nbNoeudCentral+3)*3; //18; // nombre de ddl total
Coordonnee3 Nul; // le vecteur nul de dim 3, pour les initialisations
// les coordonnées locales non nulles des points origines des normales sur les arrêtes
// on les initialise comme si les points étaient au milieu des arrêtes
double theta1_H1=0.5; double theta2_H1=0.5;
double theta2_H2=0.5; double theta1_H3=0.5;
// origine
const Coordonnee3& Op=tab_coor(1);// origine du repère local
Tableau <Coordonnee3> dOp(nbddl,Nul);
dOp(1)=Ia(1);dOp(2)=Ia(2);dOp(3)=Ia(3);
// et les variations
Vecteur d_theta1_H1(nbddl), d_theta2_H1(nbddl), d_theta2_H2(nbddl), d_theta1_H3(nbddl);
double untiers=1./3.;
// calcul du centre de gravite
Coordonnee3 G = (tab_coor(1) + tab_coor(2) + tab_coor(3)) * untiers;
// et le tableau de ses variations
Tableau <Coordonnee3> dG(nbddl,Nul);
// calcul de la normale centrale
Coordonnee3 NN(Util::ProdVec_coorBN(aiB(1),aiB(2))); // normale non normee
double nor = NN.Norme(); // la norme
Coordonnee3 N = NN / nor;
Coordonnee3 DNN; // vecteur intermediaire
// calcul de la variation de la normale centrale et du centre de gravité: vérifiée
Tableau <Coordonnee3> dN(nbddl,Nul);
// on s'intéresse ici qu'aux ddl de la face centrale
for (int inc=1;inc<=3;inc++) // indice du numéro de noeud de la face centrale
for (int ib=1;ib<=3;ib++)
{ // cas de la normale
int i1=(inc-1)*3+ib;
DNN = Util::ProdVec_coorBN(DaiB(i1)(1),aiB(2))
+ Util::ProdVec_coorBN(aiB(1),DaiB(i1)(2));
dN(i1) = Util::VarUnVect_coor(NN,DNN,nor);
// cas du centre de gravité
dG(i1)=untiers*Ia(ib);
};
// le meme calcul est effectue pour les trois cotes du triangle principale
//1- on utilise un tableau d'indice pour ne pas etre embete par les modulos 3
// 2- on boucle sur le cotes du triangle
Tableau <Coordonnee3> t_Ni(3); // normale du triangle exterieur
Tableau < Tableau <Coordonnee3> > d_t_Ni(nbddl,t_Ni); // les dérivées, initialisées à celle de dN
Coordonnee3 NNi; // normale du triangle exterieur
// def des différentes grandeurs
Coordonnee3 Ne,NNe; // normale courante du triangle extérieur et sa valeur non normée
Coordonnee3 CB,CA,CD; Coordonnee3 G2,dG2;
Coordonnee3 U1,HaA,OpHi; Coordonnee3 BgimoinsGB;
// -------- declaration pour la boucle sur les 3 cotes ------------
Coordonnee3 dA,dB,dC,dD,d_U1,dNe,d_HaA,d_NNi,d_Op,d_OpHi;
Coordonnee3 t_NNi; // normale courante non normée sur l'arrête
for (int ncot=1;ncot<=3;ncot++)
{ // on utilise les notations : triangle principal DBC et secondaire BAC
// on cherche a calculer la longueur H2G2
// simplification de l'ecriture
const Coordonnee3& D = tab_coor(indi(ncot));
const Coordonnee3& B = tab_coor(indi(ncot+1));
const Coordonnee3& C = tab_coor(indi(ncot+2));
const Coordonnee3& A = tab_coor(indi(ncot)+3);
if (D != A) // cas ou le noeud externe existe
{// calcul de G2, centre de gravite du triangle exterieur
G2 = (B + C + A) * untiers;
// calcul de U1
CB = B - C;
CA = A - C;
double norCB = CB.Norme();
U1 = CB / norCB;
// longueur HaA et HdD et calcul du vecteur HaA norme
// tout d'abord HaA ce situe dans le plan de la facette externe
HaA = CA - (CA * U1) * U1;
double haA = HaA.Norme();
double unSurhaA= 1./haA;
CD = D - C;
double dHd = sqrt ( CD * CD - ( CD * U1)* ( CD * U1)) ;
// double distH = dHd + haA;
// double inv_distH = 1./distH; double inv_distH2 = inv_distH * inv_distH;
// calcul de la normale du triangle exterieur
NNe = (Util::ProdVec_coor(CB,CA));
double norNe = NNe.Norme();
Ne = NNe/norNe;
// calcul de la normale
t_NNi = (Ne*(dHd/(dHd+haA)) + N*(haA/(dHd+haA)));
double nor_t_NNi = t_NNi.Norme();
t_Ni(ncot) = t_NNi / nor_t_NNi;
// calcul des coordonnées de la position des normales sur les arrêtes
BgimoinsGB = (G + G2 - 2. * B);
double beta = 0.5 * BgimoinsGB * U1;
OpHi=B+beta*U1-Op;
switch (ncot)
{case 1: theta1_H1=OpHi*aiH.Coordo(1);theta2_H1=OpHi*aiH.Coordo(2); break;
case 2: theta2_H2=OpHi*aiH.Coordo(2); break;
case 3: theta1_H3=OpHi*aiH.Coordo(1); break;
};
// calcul des variations
for (int ia=1;ia<= 3;ia++)
{{// indice de A: jnA, noeud extérieur
// modif pour généraliser int jnA = 9+(ncot-1)*3+ia;
int jnA = nbNoeudCentral*3+(ncot-1)*3+ia;
dA = Ia(ia);
//dCA = dA;
// Vecteur Ne = (Util::ProdVec_coor(CB,CA)).Normer()
dNe = Util::VarUnVect_coor(NNe,(Util::ProdVec_coor(CB,dA)),norNe);
// ici d_CB=0 donc d_U1=0
// ici d_CD=0 donc d_dHd=0
d_HaA = dA - (dA * U1) * U1;
double d_haA = HaA * d_HaA * unSurhaA ;
// t_Ni(ncot) = (Ne*(dHd/(dHd+haA)) + N*(haA/(dHd+haA))).Normer();
d_NNi = (dNe*(dHd/(dHd+haA)) + dN(jnA)*(haA/(dHd+haA)))
+ (Ne*(-dHd*d_haA/(dHd+haA)/(dHd+haA)) + N*(d_haA/(dHd+haA)))
+ ( N*(-haA*d_haA/(dHd+haA)/(dHd+haA)));
d_t_Ni(jnA)(ncot) = Util::VarUnVect_coor(t_NNi,d_NNi,nor_t_NNi);
// maintenant la variation des theta
// G2 = (B + C + A) * untiers;
dG2 = dA * untiers;
// beta = 0.5 * (G + G2 - 2. * B) * U1;
// ici dG(jnA) = 0
double d_beta = 0.5 * (dG2 * U1);
d_OpHi=d_beta*U1; // OpHi=B+beta*U1-Op;
switch (ncot)
{case 1: {d_theta1_H1(jnA)=d_OpHi*aiH.Coordo(1);d_theta2_H1(jnA)=d_OpHi*aiH.Coordo(2); break;}
case 2: d_theta2_H2(jnA)=d_OpHi*aiH.Coordo(2); break;
case 3: d_theta1_H3(jnA)=d_OpHi*aiH.Coordo(1); break;
};
}
{// indice de B: jnB, noeud de la facette centrale
int jnB = (indi(ncot+1)-1)*3+ia;
dB = Ia(ia); // d_CB = dB, d_CA=0
d_U1= Util::VarUnVect_coor(CB,dB,norCB);
// HaA = CA - (CA * U1) * U1;
d_HaA = - ((CA*d_U1) * U1 +(CA * U1) * d_U1);
double d_haA = HaA * d_HaA * unSurhaA ;
// d_CD = 0; dHd = sqrt ( CD * CD - ( CD * U1)* ( CD * U1)) ;
double d_dHd = - ( CD * d_U1)* ( CD * U1) / dHd ;
// Vecteur Ne = (Util::ProdVec_coor(CB,CA)).Normer()
dNe = Util::VarUnVect_coor(NNe,(Util::ProdVec_coor(dB,CA)),norNe);
// t_Ni(ncot) = (Ne*(dHd/(dHd+haA)) + N*(haA/(dHd+haA))).Normer();
d_NNi = (dNe*(dHd/(dHd+haA)) + dN(jnB)*(haA/(dHd+haA)))
+ (Ne*(d_dHd/(dHd+haA)) + N*(d_haA/(dHd+haA)))
+ (Ne*(-dHd*d_haA/(dHd+haA)/(dHd+haA))+ N*(-haA*d_haA/(dHd+haA)/(dHd+haA)))
+ (Ne*(-dHd*d_dHd/(dHd+haA)/(dHd+haA)) + N*(-haA*d_dHd/(dHd+haA)/(dHd+haA)));
d_t_Ni(jnB)(ncot) = Util::VarUnVect_coor(t_NNi,d_NNi,nor_t_NNi);
// maintenant la variation des theta
// G2 = (B + C + A) * untiers;
dG2 = dB * untiers;
// beta = 0.5 * (G + G2 - 2. * B) * U1;
double d_beta = 0.5 * ((dG(jnB) + dG2 - 2. * dB) * U1 + BgimoinsGB * d_U1);
// if (ncot == 3) {d_Op=dB;} else { d_Op= Nul;};
// d_OpHi=dB + d_beta*U1+beta*d_U1-d_Op;
d_OpHi=dB + d_beta*U1+beta*d_U1-dOp(jnB);
switch (ncot)
{case 1: {d_theta1_H1(jnB)=d_OpHi*aiH.Coordo(1)+OpHi*DaiH(jnB).Coordo(1);
d_theta2_H1(jnB)=d_OpHi*aiH.Coordo(2)+OpHi*DaiH(jnB).Coordo(2); break; }
case 2: d_theta2_H2(jnB)=d_OpHi*aiH.Coordo(2)+OpHi*DaiH(jnB).Coordo(2); break;
case 3: d_theta1_H3(jnB)=d_OpHi*aiH.Coordo(1)+OpHi*DaiH(jnB).Coordo(1); break;
};
}
{// indice de C: jnC
int jnC = (indi(ncot+2)-1)*3+ia;
dC = Ia(ia);
//dCB = -dC; dCA= -dC; U1 = CB / norCB;
d_U1= Util::VarUnVect_coor(CB,-dC,norCB);
// HaA = CA - (CA * U1) * U1;
d_HaA = -dC - ((-dC * U1)+(CA*d_U1)) * U1 -(CA * U1) * d_U1;
double d_haA = HaA * d_HaA * unSurhaA ;
// d_CD = -dC; dHd = sqrt ( CD * CD - ( CD * U1)* ( CD * U1)) ;
double d_dHd = - (CD*dC + ( CD * d_U1- dC*U1) * ( CD * U1) ) / dHd ;
// Vecteur Ne = (Util::ProdVec_coor(CB,CA)).Normer()
dNe = Util::VarUnVect_coor(NNe,(-(Util::ProdVec_coor(dC,CA)+Util::ProdVec_coor(CB,dC))),norNe);
// t_Ni(ncot) = (Ne*(dHd/(dHd+haA)) + N*(haA/(dHd+haA))).Normer();
d_NNi = (dNe*(dHd/(dHd+haA)) + dN(jnC)*(haA/(dHd+haA)))
+ (Ne*(d_dHd/(dHd+haA)) + N*(d_haA/(dHd+haA)))
+ (Ne*(-dHd*d_haA/(dHd+haA)/(dHd+haA)) + N*(-haA*d_haA/(dHd+haA)/(dHd+haA)))
+ (Ne*(-dHd*d_dHd/(dHd+haA)/(dHd+haA)) + N*(-haA*d_dHd/(dHd+haA)/(dHd+haA)));
d_t_Ni(jnC)(ncot) = Util::VarUnVect_coor(t_NNi,d_NNi,nor_t_NNi);
// maintenant la variation des theta
// G2 = (B + C + A) * untiers;
dG2 = dC * untiers;
// beta = 0.5 * (G + G2 - 2. * B) * U1;
double d_beta = 0.5 * ((dG(jnC) + dG2 ) * U1 + BgimoinsGB * d_U1);
// if (ncot == 2) {d_Op=dC;} else { d_Op= Nul;};
// d_OpHi=d_beta*U1+beta*d_U1-d_Op;
d_OpHi=d_beta*U1+beta*d_U1-dOp(jnC);
switch (ncot)
{case 1: {d_theta1_H1(jnC)=d_OpHi*aiH.Coordo(1)+OpHi*DaiH(jnC).Coordo(1);
d_theta2_H1(jnC)=d_OpHi*aiH.Coordo(2)+OpHi*DaiH(jnC).Coordo(2); break; }
case 2: d_theta2_H2(jnC)=d_OpHi*aiH.Coordo(2)+OpHi*DaiH(jnC).Coordo(2); break;
case 3: d_theta1_H3(jnC)=d_OpHi*aiH.Coordo(1)+OpHi*DaiH(jnC).Coordo(1); break;
};
}
{// indice de D: jnD
int jnD = (indi(ncot)-1)*3+ia;
// d_CB = 0; d_CA = 0 ==> d_U1=0
// d_HaA = 0, et d_haA = 0
// d_CD = dD;
// dHd = sqrt ( CD * CD - ( CD * U1)* ( CD * U1)) ;
double d_dHd = (CD*dD - (dD * U1) * ( CD * U1) ) / dHd ;
// Vecteur Ne = (Util::ProdVec_coor(CB,CA)).Normer()
//dNe = 0
// t_Ni(ncot) = (Ne*(dHd/(dHd+haA)) + N*(haA/(dHd+haA))).Normer();
d_NNi = (dN(jnD)*(haA/(dHd+haA)))
+ (Ne*(d_dHd/(dHd+haA)))
+ (Ne*(-dHd*d_dHd/(dHd+haA)/(dHd+haA)) + N*(-haA*d_dHd/(dHd+haA)/(dHd+haA)));
d_t_Ni(jnD)(ncot) = Util::VarUnVect_coor(t_NNi,d_NNi,nor_t_NNi);
// maintenant la variation des theta
// G2 = (B + C + A) * untiers;
//dG2 = 0;
// beta = 0.5 * (G + G2 - 2. * B) * U1;
double d_beta = 0.5 * (dG(jnD) * U1);
// if (ncot == 1) {d_Op=dD;} else { d_Op= Nul;};
// dB=0
// d_OpHi=d_beta*U1-d_Op;
d_OpHi=d_beta*U1-dOp(jnD);
switch (ncot)
{case 1: {d_theta1_H1(jnD)=d_OpHi*aiH.Coordo(1)+OpHi*DaiH(jnD).Coordo(1);
d_theta2_H1(jnD)=d_OpHi*aiH.Coordo(2)+OpHi*DaiH(jnD).Coordo(2); break; }
case 2: d_theta2_H2(jnD)=d_OpHi*aiH.Coordo(2)+OpHi*DaiH(jnD).Coordo(2); break;
case 3: d_theta1_H3(jnD)=d_OpHi*aiH.Coordo(1)+OpHi*DaiH(jnD).Coordo(1); break;
};
}
}; // fin du for sur ia
}
else // cas ou il n'y a pas de noeud externe
{ // on utilise la normale actuelle comme normale sur l'arrête
t_Ni(ncot) = N;
// et pour les variations, celle de N
for (int ia=1;ia<= 3;ia++)
{ // indice de B: jnB
int jnB = (indi(ncot+1)-1)*3+ia;
d_t_Ni(jnB)(ncot) = dN(jnB);
// indice de C: jnC
int jnC = (indi(ncot+2)-1)*3+ia;
d_t_Ni(jnC)(ncot) = dN(jnC);
// indice de D: jnD
int jnD = (indi(ncot)-1)*3+ia;
d_t_Ni(jnD)(ncot) = dN(jnD);
}; // fin du for sur ia
// concernant les variations des coordonnées des positions des normales,
// ces variations sont nulles, on n'y touche pas
};
}; //-- fin de la boucle sur les trois cotés
// calcul des coefficients des fonctions d'interpolation
double s= theta1_H1 * theta2_H2 - theta1_H3 * theta2_H2 + theta2_H1 * theta1_H3;
double a_r1= theta2_H2 / s; double b_r1 = theta1_H3 / s; double c_r1 = -theta1_H3 * theta2_H2/s;
double a_r2= -theta2_H1 / s; double b_r2 = 1./theta2_H2 - theta1_H3 * theta2_H1 /theta2_H2/ s;
double c_r2 = -theta1_H3 * theta2_H1/s;
double a_r3= 1./theta1_H3 - theta1_H1 * theta2_H2 /theta1_H3/ s; double b_r3 = - theta1_H1 / s;
double c_r3 = theta2_H2 * theta1_H1 /s;
// calcul de la variation de la normale
Coordonnee3 d_N_1= t_Ni(1) * a_r1 + t_Ni(2) * a_r2 + t_Ni(3) * a_r3 ;
Coordonnee3 d_N_2= t_Ni(1) * b_r1 + t_Ni(2) * b_r2 + t_Ni(3) * b_r3 ;
// calcul de la courbure (non symétrique)
curb.Coor(1,1) = - d_N_1 * aiB.Coordo(1); curb.Coor(1,2) = - d_N_1 * aiB.Coordo(2);
curb.Coor(2,1) = - d_N_2 * aiB.Coordo(1); curb.Coor(2,2) = - d_N_2 * aiB.Coordo(2);
// retour de la courbure
double unsurs = 1./s; double unsurs2=unsurs * unsurs ;
for (int ddl=1;ddl<=nbddl;ddl++)
{ // tout d'abord le calcul de la variation des coeff des fonctions d'interpolation
double d_s = d_theta1_H1(ddl) * theta2_H2 + theta1_H1 * d_theta2_H2(ddl)
- d_theta1_H3(ddl) * theta2_H2 - theta1_H3 * d_theta2_H2(ddl)
+ d_theta2_H1(ddl) * theta1_H3 + theta2_H1 * d_theta1_H3(ddl);
double d_a_r1 = d_theta2_H2(ddl) * unsurs - theta2_H2 * d_s * unsurs2;
double d_b_r1 = d_theta1_H3(ddl) * unsurs - theta1_H3 * d_s * unsurs2;
double d_a_r2 = -d_theta2_H1(ddl) * unsurs + theta2_H1 * d_s * unsurs2;
double d_b_r2 = - d_theta2_H2(ddl)/theta2_H2/theta2_H2
- d_theta1_H3(ddl) * theta2_H1 /theta2_H2* unsurs
- theta1_H3 * d_theta2_H1(ddl) /theta2_H2* unsurs
+ theta1_H3 * theta2_H1 * d_theta2_H2(ddl)/theta2_H2/theta2_H2 * unsurs
+ theta1_H3 * theta2_H1 * d_s /theta2_H2 * unsurs2;
double d_a_r3 = -d_theta1_H3(ddl)/theta1_H3/theta1_H3
- d_theta1_H1(ddl) * theta2_H2 /theta1_H3* unsurs
- theta1_H1 * d_theta2_H2(ddl) /theta1_H3* unsurs
+ theta1_H1 * theta2_H2 * d_theta1_H3(ddl)/theta1_H3/theta1_H3 * unsurs
+ theta1_H1 * theta2_H2 * d_s/theta1_H3 * unsurs2;
double d_b_r3 = - d_theta1_H1(ddl) * unsurs + theta1_H1 * d_s * unsurs2;
// calcul de la variation de la normale
Coordonnee3 d_d_N_1= d_t_Ni(ddl)(1) * a_r1 + t_Ni(1) * d_a_r1
+ d_t_Ni(ddl)(2) * a_r2 + t_Ni(2) * d_a_r2
+ d_t_Ni(ddl)(3) * a_r3 + t_Ni(3) * d_a_r3;
Coordonnee3 d_d_N_2= d_t_Ni(ddl)(1) * b_r1 + t_Ni(1) * d_b_r1
+ d_t_Ni(ddl)(2) * b_r2 + t_Ni(2) * d_b_r2
+ d_t_Ni(ddl)(3) * b_r3 + t_Ni(3) * d_b_r3;
// variation de la courbure
Tenseur_ns2BB& dcur = dcurb(ddl);
dcur.Coor(1,1) = - (d_d_N_1 * aiB.Coordo(1)+ d_N_1 * DaiB(ddl).Coordo(1));
dcur.Coor(1,2) = - (d_d_N_1 * aiB.Coordo(2)- d_N_1 * DaiB(ddl).Coordo(2));
dcur.Coor(2,1) = - (d_d_N_2 * aiB.Coordo(1)- d_N_2 * DaiB(ddl).Coordo(2));
dcur.Coor(2,2) = - (d_d_N_2 * aiB.Coordo(2)- d_N_2 * DaiB(ddl).Coordo(1));
};
};