Gérard Rio
ea11c75ff8
- fct nD: amélioration message d'erreur (arguments), et en fct du niveau géré par une fct nD - première validation du fct. en // en implicite statique et en RD, nombreuses modifications et amélioration ! Signed-off-by: Gérard Rio <gerardrio56@free.fr>
375 lines
14 KiB
C++
375 lines
14 KiB
C++
|
|
// 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-2022 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
|
|
#include "Front.h"
|
|
#include "ParaAlgoControle.h"
|
|
|
|
// constructeur
|
|
//par defaut
|
|
Front::Front() :
|
|
boite_Front(),num_frontiere(0),elem(NULL),angle_mort(0)
|
|
#ifdef UTILISATION_MPI
|
|
,num_unique(0)
|
|
#endif
|
|
{ptEl = NULL; tabmitoyen=NULL; };
|
|
// normal
|
|
Front::Front ( const ElFrontiere& el, Element * pt, int num_front ,int ang_mort) :
|
|
boite_Front(ParaGlob::Dimension()),num_frontiere(num_front)
|
|
,angle_mort(ang_mort)
|
|
#ifdef UTILISATION_MPI
|
|
,num_unique(0)
|
|
#endif
|
|
,elem(el.NevezElemFront())
|
|
{ ptEl =(Element *) pt;
|
|
tabmitoyen=NULL;
|
|
// construction de la boite d'encombrement pour l'element
|
|
Enum_dure temps=TEMPS_0; // temps par défaut
|
|
if ((ptEl->Tab_noeud())(1)->ExisteCoord1()) temps = TEMPS_t;
|
|
// construction de la boite d'encombrement pour la frontière
|
|
Boite_encombrement_frontiere(temps,0.);
|
|
};
|
|
// de copie
|
|
Front::Front ( const Front& a) :
|
|
boite_Front(a.boite_Front),num_frontiere(a.num_frontiere)
|
|
,elem(a.elem->NevezElemFront()),angle_mort(a.angle_mort)
|
|
#ifdef UTILISATION_MPI
|
|
,num_unique(a.num_unique)
|
|
#endif
|
|
{ ptEl = (Element *) a.ptEl;
|
|
if (a.tabmitoyen != NULL)
|
|
{ int tabtaille = (a.tabmitoyen)->Taille();
|
|
if (tabtaille != 0)
|
|
{ tabmitoyen= new Tableau <Front*>;
|
|
*tabmitoyen = *(a.tabmitoyen);
|
|
}
|
|
else
|
|
tabmitoyen = NULL;
|
|
}
|
|
else
|
|
tabmitoyen = NULL;
|
|
};
|
|
// destructeur
|
|
Front::~Front()
|
|
{ if (elem != NULL)
|
|
delete elem;
|
|
// on efface le tableau mais pas les objets pointés
|
|
if (tabmitoyen != NULL)
|
|
delete tabmitoyen;
|
|
};
|
|
// ============= METHODES ==========
|
|
|
|
// affichage à l'écran des informations liées au contact
|
|
// cas = 0 : affichage en fonction du niveau de commentaire voulu
|
|
// cas = 1 : affichage minimal nécessaire pour repérer l'élément
|
|
void Front::Affiche(int cas) const
|
|
{ if (elem != NULL)
|
|
{if (cas == 1)
|
|
{ cout << " front " ;
|
|
if (angle_mort)
|
|
cout << "(angle mort) ";
|
|
cout << num_frontiere << " de l'EF " << ptEl->Num_elt() << " du mail. "
|
|
<< ptEl->Num_maillage() << flush;
|
|
}
|
|
else
|
|
{cout << "\n element de frontiere du maillage " << ptEl->Num_maillage() <<" , cree par l'element "
|
|
<< ptEl->Num_elt() << " de numero " << num_frontiere << " , de type de geometrie: "
|
|
<< Nom_type_geom(elem->Type_geom_front()) << " , avec une interpolation:"
|
|
<< Nom_interpol(elem->ElementGeometrique().TypeInterpolation());
|
|
if (angle_mort) cout << " ( represente un angle mort) , ";
|
|
cout << " , constitue des noeuds: " ;
|
|
const Tableau <Noeud *>& tabnoeud = elem->TabNoeud_const();
|
|
int tabtaille = tabnoeud.Taille();
|
|
for (int i=1;i<=tabtaille;i++)
|
|
cout << tabnoeud(i)->Num_noeud() << " , ";
|
|
cout << " , et contiend les degres de liberte suivants: "
|
|
<< elem->DdlElem_const();
|
|
if (this->tabmitoyen != NULL)
|
|
{int tai = this->tabmitoyen->Taille();
|
|
cout << "\n " << tai << " elements mitoyens: ( ";
|
|
for (int i=1;i<=tai;i++)
|
|
cout << (*tabmitoyen)(i)->PtEI()->Num_elt() << " , ";
|
|
cout << ") ";
|
|
}
|
|
else
|
|
cout << "\n *** aucun element mitoyen !!!! *** ";
|
|
};
|
|
}
|
|
else
|
|
{ cout << "\n element de frontiere associe a un element fini: FRONTIERE NON DEFINIE !! "; };
|
|
|
|
// cout << "\n ";
|
|
};
|
|
|
|
// affectation de toute les donnees
|
|
Front& Front::operator = ( const Front& a)
|
|
{ if (elem != NULL)
|
|
{ if (a.elem == NULL) {delete elem;}
|
|
else {*elem = *a.elem;};
|
|
}
|
|
else
|
|
{ if (a.elem != NULL)
|
|
{elem = a.elem->NevezElemFront();};
|
|
//sinon les deux sont nuls on n'à rien à faire
|
|
};
|
|
num_frontiere = a.num_frontiere;
|
|
ptEl = (Element *) a.ptEl;
|
|
if (a.tabmitoyen != NULL)
|
|
{ if (tabmitoyen == NULL)
|
|
tabmitoyen= new Tableau <Front*>;
|
|
*tabmitoyen = *(a.tabmitoyen);
|
|
}
|
|
else
|
|
{if (tabmitoyen != NULL)
|
|
{delete tabmitoyen;
|
|
tabmitoyen = NULL;
|
|
};
|
|
};
|
|
// boite d'encombrement
|
|
boite_Front = a.boite_Front;
|
|
// angle mort
|
|
angle_mort = a.angle_mort;
|
|
#ifdef UTILISATION_MPI
|
|
num_unique = a.num_unique;
|
|
#endif
|
|
return *this;
|
|
};
|
|
|
|
// definition des elements mitoyens
|
|
void Front::DefMitoyen(const Tableau <Front*>& tab)
|
|
{
|
|
int tabtaille = tab.Taille();
|
|
if (tabtaille != 0)
|
|
{if (tabmitoyen == NULL)
|
|
tabmitoyen= new Tableau <Front*>;
|
|
*tabmitoyen = tab;
|
|
}
|
|
else
|
|
{if (tabmitoyen != NULL)
|
|
{delete tabmitoyen;
|
|
tabmitoyen = NULL;
|
|
};
|
|
};
|
|
};
|
|
// ajout d'un élément mitoyens (l'ajout est effectif uniquement s'il n'existe pas déjà)
|
|
void Front::AjoutMitoyen(Front * mitoyen)
|
|
{ if (tabmitoyen == NULL)
|
|
// si le tableau n'existe pas, on le dimensionne à 1 et on ajoute l'unique élément
|
|
{tabmitoyen= new Tableau <Front*>;
|
|
tabmitoyen->Change_taille(1);
|
|
(*tabmitoyen)(1) = mitoyen;
|
|
}
|
|
else // sinon on commence par regarder si mitoyen existe déjà
|
|
{int tail = tabmitoyen->Taille();
|
|
bool trouver = false;
|
|
for (int i=1;i<= tail; i++ )
|
|
if (*(*tabmitoyen)(i) == *mitoyen)
|
|
{trouver = true; break;}
|
|
// s'il n'existe pas on l'ajoute
|
|
if (!trouver)
|
|
// on augmente la taille et on ajoute
|
|
{tabmitoyen->Change_taille(tail+1);
|
|
(*tabmitoyen)(tail+1)= mitoyen;
|
|
};
|
|
};
|
|
};
|
|
|
|
// test si le point passé en argument appartient à la boite d'encombrement de la frontière
|
|
// tous les points sont supposées avoir la même dimension
|
|
bool Front::In_boite_emcombrement_front(const Coordonnee& M) const
|
|
{ // on va essayer de faire efficace, pour cela on test le minimum
|
|
const Coordonnee& co_min = boite_Front.Premier(); // par commodité
|
|
const Coordonnee& co_max = boite_Front.Second(); // par commodité
|
|
#ifdef MISE_AU_POINT
|
|
if ((M.Dimension() != ParaGlob::Dimension())|| (M.Dimension() != co_min.Dimension()))
|
|
{ cout << "\n *** pb de dimensions non coherente !! "
|
|
<< "\n Front::In_boite_emcombrement_front(...";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
switch (ParaGlob::Dimension())
|
|
{ case 3: if ((M(3)<co_min(3)) || (M(3) > co_max(3))) return false;
|
|
case 2: if ((M(2)<co_min(2)) || (M(2) > co_max(2))) return false;
|
|
case 1: if ((M(1)<co_min(1)) || (M(1) > co_max(1))) return false;
|
|
};
|
|
// si on arrive ici c'est que le point est interne
|
|
return true;
|
|
};
|
|
|
|
// test si le point passé en argument appartient à la boite d'encombrement de la frontière
|
|
// tous les points sont supposées avoir la même dimension
|
|
// ici la boite est augmentée de extra dans tous les sens
|
|
bool Front::In_boite_emcombrement_front(const Coordonnee& M,double extra) const
|
|
{ // on va essayer de faire efficace, pour cela on test le minimum
|
|
const Coordonnee& co_min = boite_Front.Premier(); // par commodité
|
|
const Coordonnee& co_max = boite_Front.Second(); // par commodité
|
|
#ifdef MISE_AU_POINT
|
|
if ((M.Dimension() != ParaGlob::Dimension())|| (M.Dimension() != co_min.Dimension()))
|
|
{ cout << "\n *** pb de dimensions non coherente !! "
|
|
<< "\n Front::In_boite_emcombrement_front(...";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
switch (ParaGlob::Dimension())
|
|
{ case 3: if ((M(3)<(co_min(3)-extra)) || (M(3) > (co_max(3)+extra))) return false;
|
|
case 2: if ((M(2)<(co_min(2)-extra)) || (M(2) > (co_max(2)+extra))) return false;
|
|
case 1: if ((M(1)<(co_min(1)-extra)) || (M(1) > (co_max(1)+extra))) return false;
|
|
};
|
|
// si on arrive ici c'est que le point est interne à l'extra près
|
|
return true;
|
|
};
|
|
|
|
//----- lecture écriture base info -----
|
|
// lecture base info
|
|
// ici la lecture n'est pas complète il faut ensuite changer l'élément
|
|
// frontière et changer le pointeur de l'élément finis
|
|
// -> utilisation de : Change_elem_frontiere, Change_PtEI
|
|
void Front::Lecture_base_info_front(ifstream& ent)
|
|
{ // lecture et vérification du type
|
|
string nom_type;
|
|
ent >> nom_type;
|
|
if (nom_type != "Front")
|
|
Sortie(1);
|
|
// lecture des infos
|
|
string toto;
|
|
|
|
// les éléments spécifiques à l'élément frontière
|
|
int test = 0;
|
|
ent >> test;
|
|
if (test)
|
|
{elem->Lecture_base_info_ElFrontiere_pour_projection(ent);}
|
|
// on réutilise nom_type pour lire la chaine: am=
|
|
ent >> nom_type >> angle_mort;
|
|
|
|
// // la boite d'encombrement de la frontière
|
|
// ent >> nom_type >> boite_Front.Premier() >> boite_Front.Second() ;
|
|
};
|
|
// écriture base info
|
|
// on ne sauvegarde ici que les grandeurs spécifiques à ce niveau
|
|
// concernant les infos relatives à l'élément, la frontière, etc, ce n'est pas traité ici, mais au niveau de la classe LesContats
|
|
void Front::Ecriture_base_info_front(ofstream& sort)
|
|
{ // écriture du type
|
|
sort << "Front ";
|
|
// les données
|
|
// sort << "mail= " << ptEl->Num_maillage() << " NE= " << ptEl->Num_elt() << " fron= " << num_frontiere ;
|
|
// les éléments spécifiques à l'élément frontière
|
|
if (elem != NULL)
|
|
{ sort << " 1 "; elem->Ecriture_base_info_ElFrontiere_pour_projection(sort);}
|
|
else { sort << " 0 ";};
|
|
sort << " am= " << angle_mort << " ";
|
|
|
|
// la boite d'encombrement
|
|
// sort << "encombrements_surf " << boite_Front.Premier() << " " << boite_Front.Second() << " \n";
|
|
};
|
|
|
|
//====================================== fonctions internes ============================
|
|
// fonctions internes
|
|
|
|
// mise à jour de la boite d'encombrement de la frontière
|
|
// dep_max : déplacement maxi des noeuds du maillage
|
|
// , sert pour def des boites d'encombrement maxi des frontières
|
|
void Front::Boite_encombrement_frontiere(Enum_dure temps,double dep_max)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (elem == NULL)
|
|
{cout << "\n *** erreur, la frontiere n'est pas definie "
|
|
<< "\n Front::Boite_encombrement_frontiere(... " << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
|
|
Tableau <Noeud *>& tab = elem->TabNoeud();
|
|
int tab_taille= tab.Taille();
|
|
|
|
Coordonnee& encomb_min_fr=boite_Front.Premier();
|
|
Coordonnee& encomb_max_fr=boite_Front.Second();
|
|
switch (temps)
|
|
{ case TEMPS_0:
|
|
{encomb_min_fr=tab(1)->Coord0();encomb_max_fr=encomb_min_fr; // init
|
|
for (int i=2;i<=tab_taille;i++) // balayage des autres noeuds
|
|
{ Coordonnee co=tab(i)->Coord0();
|
|
encomb_min_fr.Modif_en_min(co); encomb_max_fr.Modif_en_max(co);
|
|
};
|
|
break;
|
|
}
|
|
case TEMPS_t:
|
|
{encomb_min_fr=tab(1)->Coord1();encomb_max_fr=encomb_min_fr; // init
|
|
for (int i=2;i<=tab_taille;i++) // balayage des autres noeuds
|
|
{ Coordonnee co=tab(i)->Coord1();
|
|
encomb_min_fr.Modif_en_min(co); encomb_max_fr.Modif_en_max(co);
|
|
};
|
|
break;
|
|
}
|
|
case TEMPS_tdt:
|
|
{encomb_min_fr=tab(1)->Coord2();encomb_max_fr=encomb_min_fr; // init
|
|
for (int i=2;i<=tab_taille;i++) // balayage des autres noeuds
|
|
{ Coordonnee co=tab(i)->Coord2();
|
|
encomb_min_fr.Modif_en_min(co); encomb_max_fr.Modif_en_max(co);
|
|
};
|
|
break;
|
|
}
|
|
}; // fin du switch
|
|
// maintenant on tiend compte d'un facteur majorant pour incertitude
|
|
Coordonnee delta=(encomb_max_fr- encomb_min_fr)
|
|
* (ParaGlob::param->ParaAlgoControleActifs().Extra_boite_prelocalisation()-1.);
|
|
// dans le cas de surface plane on peut avoir une boite avec une épaisseur nulle,
|
|
// comme il s'agit d'une boite d'encombrement assez grossière on ajoute une valeur par défaut
|
|
// par défaut on prend une valeur par défaut du max de delta
|
|
double miniajout = (ParaGlob::param->ParaAlgoControleActifs().Rapport_Extra_boite_mini_prelocalisation())
|
|
* delta.Max_val_abs();
|
|
// dans le cas d'un espace 3D et d'une frontière provenant d'un élément 2D avec une épaisseur,
|
|
// on prend le maxi de l'épaisseur et du miniajout déjà calculé
|
|
if ((ParaGlob::Dimension() == 3) && (Type_geom_generique(ptEl->ElementGeometrique().TypeGeometrie()) == SURFACE))
|
|
// ((ptEl->PoutrePlaqueCoque() == PLAQUE) || (ptEl->PoutrePlaqueCoque() == COQUE))
|
|
// )
|
|
{ // on récupère l'épaisseur
|
|
ElemMeca* elemmeca = (ElemMeca *) ptEl ;
|
|
miniajout = MaX(miniajout, elemmeca->EpaisseurMoyenne(temps));
|
|
};
|
|
|
|
delta.Ajout_meme_valeur(miniajout);
|
|
// ajout d'un extra dans toutes les directions
|
|
delta.Ajout_meme_valeur(ParaGlob::param->ParaAlgoControleActifs().Ajout_extra_boite_prelocalisation());
|
|
|
|
encomb_min_fr -= delta; encomb_max_fr += delta;
|
|
// on tiend enfin compte d'une majoration de 2 fois le déplacement maxi des noeuds du maillage
|
|
if (dep_max != 0.)
|
|
{encomb_min_fr.Ajout_meme_valeur(-2.*dep_max);
|
|
encomb_max_fr.Ajout_meme_valeur(2.*dep_max);
|
|
};
|
|
// -- debug
|
|
//if( ptEl->Num_elt() == 9)
|
|
// { cout << "\n elem " << ptEl->Num_elt() << " maillage " << ptEl->Num_maillage() << " frontiere N= " ;
|
|
// for (int i=1;i<= (elem->TabNoeud()).Taille();i++) cout << (elem->TabNoeud())(i)->Num_noeud() << " ";
|
|
// cout << "\n boite "; encomb_min_fr.Affiche(); encomb_max_fr.Affiche();
|
|
// cout << " Front::Boite_encombrement_frontiere( " << endl;
|
|
// };
|
|
//-- fin débug
|
|
|
|
};
|