Gérard Rio
a317216f06
- modification des sorties post pour loi hypo 2D_C et 1D_C - corr bug lecture fct_nD avec toutes les lois hypo isotropes - corr bug sur le calcul de la compressibilité pour les loi hypo 2D_C - première mise en place du calcul parallèle sur le contact - ajout d'une fct nD pour gérer le niveau de commentaire sur LesContacts (indépendante de celle qui gère le niveau de commentaire concernant les éléments de contact) - amélioration de la méthode d'initialisation du contact, utilisée en début d'incrément
2563 lines
121 KiB
C++
Executable file
2563 lines
121 KiB
C++
Executable file
|
|
// 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 "LesContacts.h"
|
|
#include <vector>
|
|
#include "ReferenceNE.h"
|
|
#include "ReferenceAF.h"
|
|
#include "CharUtil.h"
|
|
|
|
#include "Enum_TypeQuelconque.h"
|
|
#include "TypeQuelconqueParticulier.h"
|
|
#include "FrontPointF.h"
|
|
|
|
|
|
|
|
|
|
// récupération des ddl ou des grandeurs actives de tdt vers t
|
|
void LesContacts::TdtversT()
|
|
{ LaLIST <ElContact>::iterator il,ilfin=listContact.end();
|
|
for (il=listContact.begin();il != ilfin; il++)
|
|
(*il).TdtversT();
|
|
// on nettoie les indicateurs transitoires
|
|
listContact_nouveau_tatdt.clear();
|
|
listContact_efface_tatdt.clear();
|
|
};
|
|
|
|
// actualisation des ddl et des grandeurs actives de t vers tdt
|
|
// dans le cas //, on ajoute dans les messages, le num du prog
|
|
void LesContacts::TversTdt()
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
#endif
|
|
|
|
// on essaie de mettre la situation de contact comme elle était à t
|
|
// a) on supprime les nouveaux contacts
|
|
{LaLIST <LaLIST <ElContact>::iterator>::iterator al,alfin=listContact_nouveau_tatdt.end();
|
|
for (al=listContact_nouveau_tatdt.begin();al != alfin; al++)
|
|
{ ElContact& elc = (*(*al));
|
|
Noeud* no = elc.Esclave();
|
|
int n_noee = no->Num_noeud();
|
|
int num_mail_noe_esclave = no->Num_Mail();
|
|
#ifdef MISE_AU_POINT
|
|
if (tesN_encontact(num_mail_noe_esclave).find(no)
|
|
== tesN_encontact(num_mail_noe_esclave).end() )
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< "*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave "
|
|
<< n_noee << " du maillage " << num_mail_noe_esclave
|
|
<< " la suite n'est pas possible "
|
|
<< " LesContacts::TversTdt(.. \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
LaLIST < LaLIST<ElContact>::iterator > & list_tesN
|
|
= tesN_encontact(num_mail_noe_esclave)[no];
|
|
list_tesN.remove(*al);
|
|
// tesN_encontact(num_mail_noe_esclave)(n_noee).remove(*al);
|
|
listContact.erase(*al);
|
|
// cout << "\n debug toto ";
|
|
};
|
|
};
|
|
// b) on rajoute les contacts supprimés
|
|
{LaLIST <ElContact>::iterator al,alfin=listContact_efface_tatdt.end();
|
|
for (al=listContact_efface_tatdt.begin();al != alfin; al++)
|
|
{ ElContact& elc = (*al);
|
|
Noeud* no = elc.Esclave();
|
|
int n_noee = no->Num_noeud();
|
|
int num_mail_noe_esclave = no->Num_Mail();
|
|
#ifdef MISE_AU_POINT
|
|
if (Element_contact_deja_present(*al))
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< "\n*** Erreur : l'element de contact existe déjà, ce n'est pas normal "
|
|
<< (*al).Esclave()->Num_noeud()
|
|
<< " du maillage " << (*al).Esclave()->Num_Mail()
|
|
<< " la suite n'est pas possible "
|
|
<< " LesContacts::TversTdt(.. \n";
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
listContact.push_front(*al);
|
|
// on met à jour le tableau tesN_encontact
|
|
#ifdef MISE_AU_POINT
|
|
if (tesN_encontact(num_mail_noe_esclave).find(no)
|
|
== tesN_encontact(num_mail_noe_esclave).end() )
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< "\n*** Erreur : on ne trouve pas la liste d'element en contact avec le noeud esclave "
|
|
<< n_noee << " du maillage " << num_mail_noe_esclave
|
|
<< " la suite n'est pas possible "
|
|
<< " LesContacts::TversTdt(.. \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
tesN_encontact(num_mail_noe_esclave)[no].push_front(listContact.begin());
|
|
};
|
|
};
|
|
// c) on nettoie les indicateurs transitoires
|
|
listContact_nouveau_tatdt.clear();
|
|
listContact_efface_tatdt.clear();
|
|
// d) on revient à t pour les éléments en contact
|
|
{LaLIST <ElContact>::iterator il,ilfin=listContact.end();
|
|
for (il=listContact.begin();il != ilfin; il++)
|
|
(*il).TversTdt();
|
|
};
|
|
Calcul_Nb_contact_actif();
|
|
if ((ParaGlob::NiveauImpression() > 4) || (Permet_affichage() > 4 ))
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< "\n >> LesContacts::TversTdt : nb contact actif = "<< nb_contact_actif << endl ;
|
|
};
|
|
|
|
|
|
// cas d'une méthode avec pénalisation: calcul éventuel d'un pas de temps idéal,
|
|
// si oui retour de la valeur delta_t proposé
|
|
// sinon dans tous les autres cas retour de 0.
|
|
// le calcul se fait en fonction du pas de temps courant et de la pénétration
|
|
// donc nécessite que le contact ait déjà été étudié
|
|
// Dans le cas d'un calcul parallèle, il y a transfert du résultat au cpu 0
|
|
// seules les cpu i calculent le pas de temps idéal pour leur portion et le proc 0 choisit le min
|
|
double LesContacts::Pas_de_temps_ideal()
|
|
{ tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
double delta_optimal=ConstMath::tresgrand;
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
if (proc_en_cours != 0)
|
|
{
|
|
#endif
|
|
{
|
|
// on passe en revue tous les contacts
|
|
LaLIST <ElContact>::const_iterator il,ilfin=listContact.end();
|
|
for (il=listContact.begin();il != ilfin; il++)
|
|
{ double dtelem_optimal = (*il).Pas_de_temps_ideal();
|
|
if (dtelem_optimal != 0.)
|
|
delta_optimal = MiN(delta_optimal, dtelem_optimal);
|
|
};
|
|
// retour du temps proposé
|
|
if (delta_optimal==ConstMath::tresgrand)
|
|
// cela veut dire qu'il n'a pas été modifié, on le met à 0 pour indiquer que l'on a rien
|
|
// n'a proposer
|
|
delta_optimal = 0.;
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
}
|
|
#ifdef UTILISATION_MPI
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
// maintenant on va transmettre au cpu 0
|
|
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 56, delta_optimal);
|
|
// on attend pas
|
|
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
|
|
}
|
|
else // cas du cpu 0
|
|
{// l'objectif ici est de récupérer les infos
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
int nb_proc_terminer = 0; // permettra de terminer
|
|
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
|
|
{ // on récupère un résultat de cpu i
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
double dtelem_optimal ;
|
|
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 56, dtelem_optimal );
|
|
reqs1.wait(); // on attend que le conteneur soit rempli
|
|
delta_optimal = MiN(delta_optimal, dtelem_optimal);
|
|
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
|
|
};
|
|
};
|
|
#endif
|
|
|
|
return delta_optimal;
|
|
|
|
};
|
|
|
|
// écriture base info
|
|
// cas donne le niveau de sauvegarde
|
|
void LesContacts::Ecri_base_info_LesContacts(ofstream& sort)
|
|
{ // globalement on sauvegarde toujours tout, car les éléments de contact peuvent apparaître à tout moment
|
|
// tout d'abord on indique le type
|
|
sort << "\n LesContacts: taille " << listContact.size() << " " ;
|
|
// NB: le nombre de maillages esclave et en auto-contact, peut-être redéfinit lors d'un restart
|
|
// donc n'est pas sauvegardé
|
|
// ensuite on sauvegarde la liste des éléments de contact: en fait tout d'abord les infos
|
|
// qui permettent de construire un élément ad hoc, et ensuite les infos spécifiques internes à l'élément
|
|
for (LaLIST <ElContact>::iterator ic = listContact.begin();ic != listContact.end(); ic++)
|
|
{// les infos permettants de contruire l'élément de contact: on considère que les numéros des noeuds, maillages, éléments
|
|
// restent identiques, par contre on peut avoir un échange des zones de restriction de contact d'une sauvegarde à un restart
|
|
sort << "\nN_es " << (*ic).Esclave()->Num_Mail() <<" " << (*ic).Esclave()->Num_noeud(); // le noeud esclave
|
|
Front * elfront = (*ic).Elfront();
|
|
sort << " El " << elfront->NumMail() << " " << elfront->PtEI()->Num_elt_const() << " "
|
|
<< elfront->Eleme()->Type_geom_front() << " "<< elfront->Num_frontiere() ; // la frontière
|
|
// les infos spécifiques éventuelles
|
|
(*ic).Ecri_base_info_ElContact(sort);
|
|
};
|
|
sort << "\n tps_rech_contact: "<<tempsContact;
|
|
};
|
|
|
|
|
|
// Il s'agit ici de mettre à jour les conteneurs stockés aux noeuds et/ou aux éléments
|
|
// qui servent à récupérer les infos liés aux contact correspondant à liTQ
|
|
// actuellement les conteneurs passés en paramètre servent que pour
|
|
// les énumérés, et les informations résultantes sont stockées au niveau des noeuds
|
|
// constituant les éléments de contact
|
|
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
|
//--> important : les conteneurs sont supposés initialisés avec l'appel
|
|
void LesContacts::Mise_a_jour_Pour_Grandeur_particuliere(
|
|
List_io < TypeQuelconque >& li_restreinte_TQ
|
|
)
|
|
{
|
|
LaLIST<ElContact>::iterator ili_deb= listContact.begin();
|
|
LaLIST<ElContact>::iterator ilifin= listContact.end();
|
|
LaLIST<ElContact>::iterator ili;
|
|
|
|
// on passe en revue la liste de quelconque
|
|
{List_io<TypeQuelconque>::iterator itq,itqfin=li_restreinte_TQ.end();
|
|
for (itq=li_restreinte_TQ.begin();itq!=itqfin;itq++)
|
|
{const TypeQuelconque_enum_etendu& enuTypeQuelconque = (*itq).EnuTypeQuelconque();
|
|
if (enuTypeQuelconque.Nom_vide()) // veut dire que c'est un enum pur
|
|
switch (enuTypeQuelconque.EnumTQ())
|
|
{ case NOEUD_PROJECTILE_EN_CONTACT:
|
|
{// ----- cas des noeuds projectiles en contact
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
// on attribue une grandeur arbitraire de 100 aux noeuds pour un contact actif
|
|
// pour les éléments de contact inactif -> -0.1
|
|
// un noeud peut être plusieurs fois en contact -> les nombres sont cumulées
|
|
// on fait l'hypothèse qu'un ne sera jamais inactif plus de 99 fois, du coup
|
|
// en regardant le nombre modulo 100 on peut en déduire le nombre d'inactivité
|
|
// et en regardant le nombre de centaine on en déduit le nombre de contact
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += 100.; }
|
|
else
|
|
{*(tyTQ.ConteneurDouble()) -= 0.1; }
|
|
};
|
|
break;
|
|
}
|
|
case NOEUD_FACETTE_EN_CONTACT:
|
|
{// ----- cas des noeuds facettes en contact
|
|
// on parcours la liste des éléments de contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
// on attribue une grandeur arbitraire de 100 aux noeuds pour un contact actif
|
|
// pour les éléments de contact inactif -> -0.1
|
|
// un noeud peut être plusieurs fois en contact -> les nombres sont cumulées
|
|
// on fait l'hypothèse qu'un ne sera jamais inactif plus de 99 fois, du coup
|
|
// en regardant le nombre modulo 100 on peut en déduire le nombre d'inactivité
|
|
// et en regardant le nombre de centaine on en déduit le nombre de contact
|
|
Tableau <Noeud*>& tablN = elcont.TabNoeud();
|
|
int NBNF=tablN.Taille();
|
|
// on boucle sur les noeuds de la facette (le premier noeud = noeud esclave)
|
|
if (elcont.Actif())
|
|
{for (int i=2;i<=NBNF;i++)
|
|
{TypeQuelconque& tyqN = tablN(i)->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
*(tyTQ.ConteneurDouble()) += 100.;
|
|
}
|
|
}
|
|
else
|
|
{for (int i=2;i<=NBNF;i++)
|
|
{TypeQuelconque& tyqN = tablN(i)->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
*(tyTQ.ConteneurDouble()) -= 0.1;
|
|
}
|
|
};
|
|
};
|
|
break;
|
|
}
|
|
case PENETRATION_CONTACT:
|
|
{// ----- cas des noeuds projectiles en contact
|
|
// on parcours la liste des élément en contact
|
|
// on cumule s'il y a plusieurs contacts
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{// on définit un vecteur au niveau du noeud en contact, qui part du noeud
|
|
// projectile et va au point d'impact
|
|
const Coordonnee& Mtdt = elcont.Point_intersection();
|
|
*(tyTQ.ConteneurCoordonnee()) += Mtdt - elcont.Esclave()->Coord2();
|
|
}; // sinon on ne fait rien
|
|
};
|
|
break;
|
|
}
|
|
case GLISSEMENT_CONTACT:
|
|
{// ----- cas des noeuds projectiles en contact
|
|
// on parcours la liste des élément en contact
|
|
// on cumule s'il y a plusieurs contacts
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{// on définit un vecteur au niveau du noeud en contact, qui part du noeud
|
|
// projectile et va au point d'impact
|
|
*(tyTQ.ConteneurCoordonnee()) += elcont.Dep_tangentiel();
|
|
}; // sinon on ne fait rien
|
|
};
|
|
break;
|
|
}
|
|
case NORMALE_CONTACT:
|
|
{// ----- cas des noeuds projectiles en contact
|
|
// on parcours la liste des élément en contact
|
|
// on cumule s'il y a plusieurs contacts
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{// on définit un vecteur au niveau du noeud en contact, qui part du noeud
|
|
// projectile et va au point d'impact
|
|
*(tyTQ.ConteneurCoordonnee()) += elcont.Normale_actuelle();
|
|
}; // sinon on ne fait rien
|
|
};
|
|
break;
|
|
}
|
|
// case N_FRONT:
|
|
// {// ----- cas des noeuds projectiles en contact
|
|
// // on parcours la liste des élément en contact
|
|
// // on cumule s'il y a plusieurs contacts
|
|
// for (ili=ili_deb;ili!=ilifin;ili++)
|
|
// {ElContact & elcont = (*ili); // pour simplifier
|
|
// TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
// Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
|
|
// tyqN.Grandeur_pointee());
|
|
// // on récupère la normale au noeud projectile
|
|
// *(tyTQ.ConteneurCoordonnee()) = elcont.Normale_actuelle();
|
|
// };
|
|
// break;
|
|
// }
|
|
case FORCE_CONTACT:
|
|
{// ----- cas des noeuds projectiles en contact
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_coordonnee& tyTQ= *((Grandeur_coordonnee*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{// on récupère la force de contact
|
|
*(tyTQ.ConteneurCoordonnee()) += elcont.Force_contact();
|
|
}; // sinon on ne fait rien
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_PENALISATION_N:
|
|
{// ----- on attribue la pénalisation au noeud projectile
|
|
// on met la pénalisation totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.Penalisation(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_PENALISATION_T:
|
|
{// ----- on attribue la pénalisation au noeud projectile
|
|
// on met la pénalisation totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.Penalisation_tangentielle(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_PENAL:
|
|
{// ----- on attribue l'énergie de pénalisation au noeud projectile
|
|
// on met l'énergie totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.EnergiePenalisation(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_GLISSE_ELAS:
|
|
{// ----- on attribue l'énergie de pénalisation au noeud projectile
|
|
// on met l'énergie totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.EnergieFrottement().EnergieElastique(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_GLISSE_PLAS:
|
|
{// ----- on attribue l'énergie de pénalisation au noeud projectile
|
|
// on met l'énergie totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.EnergieFrottement().DissipationPlastique(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_GLISSE_VISQ:
|
|
{// ----- on attribue l'énergie de pénalisation au noeud projectile
|
|
// on met l'énergie totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.EnergieFrottement().DissipationVisqueuse(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_NB_DECOL:
|
|
{// ----- on attribue le nombre de décolement au noeud projectile
|
|
// on met le totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.Nb_decol(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_COLLANT:
|
|
{// ----- on attribue le fait d'être collant ou pas au noeud projectile
|
|
// on met le totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.Collant(); };
|
|
};
|
|
break;
|
|
}
|
|
case NUM_ZONE_CONTACT:
|
|
{// ----- on attribue le numéro de zone de contact au noeud projectile
|
|
// on met le totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.Num_zone_contact(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_NB_PENET:
|
|
{// ----- on attribue le nombre de décolement au noeud projectile
|
|
// on met le totale s'il y a plusieurs contacts
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) += elcont.Nb_pene(); };
|
|
};
|
|
break;
|
|
}
|
|
case CONTACT_CAS_SOLIDE:
|
|
{// ----- on attribue le nombre au noeud projectile
|
|
// =0 contact bi déformable, =1 le noeud est libre et la frontière est bloqué (solide)
|
|
// = 2 le noeud est bloqué (solide) la frontière est libre
|
|
// = 3 tout est solide
|
|
|
|
// ici on ne met pas le totale s'il y a plusieurs contacts !!
|
|
// c'est le dernier élément qui contient le noeud projectile, qui donne le résultat
|
|
|
|
// on parcours la liste des élément en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact & elcont = (*ili); // pour simplifier
|
|
TypeQuelconque& tyqN = elcont.Esclave()->ModifGrandeur_quelconque(enuTypeQuelconque);
|
|
Grandeur_scalaire_double& tyTQ= *((Grandeur_scalaire_double*)
|
|
tyqN.Grandeur_pointee());
|
|
if (elcont.Actif())
|
|
{*(tyTQ.ConteneurDouble()) = elcont.Cas_solide(); };
|
|
};
|
|
break;
|
|
}
|
|
|
|
default: ;// on ne fait rien
|
|
};
|
|
|
|
};
|
|
};
|
|
|
|
|
|
};
|
|
|
|
// récupération de la liste de tous les grandeurs particulières disponibles avec le contact
|
|
// cette liste est identique quelque soit le maillage: il n'y a donc pas de tableau indicé du num de maillage
|
|
// absolue: indique si oui ou non on sort les tenseurs dans la base absolue ou une base particulière
|
|
List_io<TypeQuelconque> LesContacts::ListeGrandeurs_particulieres(bool absolue) const
|
|
{
|
|
// def de la liste de retour
|
|
List_io <TypeQuelconque> liTQ;
|
|
|
|
// on ne ramène les infos que si le contact est actif
|
|
if (ParaGlob::param->ParaAlgoControleActifs().ContactType()!= 0)
|
|
{
|
|
// grandeurs de travail
|
|
int dim = ParaGlob::Dimension();
|
|
|
|
// ici on est en 3D et les grandeurs sont par principe en absolue, donc la variable absolue ne sert pas
|
|
Grandeur_scalaire_double grand_courant(0.);
|
|
|
|
Coordonnee inter(dim);
|
|
Grandeur_coordonnee grand_coor_courant(inter);
|
|
|
|
// def d'un type quelconque représentatif à chaque grandeur
|
|
// a priori ces grandeurs sont défini aux noeuds
|
|
//on regarde si ce type d'info existe déjà: si oui on augmente la taille du tableau, si non on crée
|
|
// $$$ cas de la visualisation des noeuds projectiles en contact
|
|
{TypeQuelconque typQ1(NOEUD_PROJECTILE_EN_CONTACT,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// $$$ cas de la visualisation des noeuds des facettes en contact
|
|
{TypeQuelconque typQ1(NOEUD_FACETTE_EN_CONTACT,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// $$$ cas de la visualisation du glissement des noeuds projectiles actifs
|
|
{TypeQuelconque typQ1(GLISSEMENT_CONTACT,X1,grand_coor_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// $$$ cas de la visualisation de la normale de contact (moyenne)
|
|
{TypeQuelconque typQ1(NORMALE_CONTACT,X1,grand_coor_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// // $$$ cas de la visualisation de la normale aux noeuds frontières
|
|
// {TypeQuelconque typQ1(N_FRONT,X1,grand_coor_courant);
|
|
// liTQ.push_back(typQ1);
|
|
// };
|
|
// $$$ cas de la visualisation de la pénétration en contact
|
|
{TypeQuelconque typQ1(PENETRATION_CONTACT,X1,grand_coor_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// $$$ cas de la visualisation des forces de contact
|
|
{TypeQuelconque typQ1(FORCE_CONTACT,X1,grand_coor_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// $$$ nombre de pénétration
|
|
{TypeQuelconque typQ1(CONTACT_NB_PENET,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// $$$ nombre de décolement
|
|
{TypeQuelconque typQ1(CONTACT_NB_DECOL,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
// $$$ cas_solide
|
|
{TypeQuelconque typQ1(CONTACT_CAS_SOLIDE,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(CONTACT_ENERG_PENAL,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(CONTACT_ENERG_GLISSE_ELAS,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(CONTACT_ENERG_GLISSE_PLAS,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(CONTACT_ENERG_GLISSE_VISQ,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(CONTACT_PENALISATION_N,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(CONTACT_PENALISATION_T,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(CONTACT_COLLANT,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
{TypeQuelconque typQ1(NUM_ZONE_CONTACT,X1,grand_courant);
|
|
liTQ.push_back(typQ1);
|
|
};
|
|
};
|
|
|
|
// retour
|
|
return liTQ;
|
|
|
|
};
|
|
|
|
|
|
// concernant les grandeurs gérées par le contact:
|
|
// ramène une liste d'enuméré correspondant aux List_io<TypeQuelconque> passé en paramètre
|
|
// idem pour une List_io < Ddl _enum_etendu >
|
|
void LesContacts::List_reduite_aux_contact(const List_io<TypeQuelconque>& liTQ
|
|
,List_io < TypeQuelconque >& li_restreinte_TQ
|
|
)
|
|
{
|
|
// initialisation des listes de retour
|
|
li_restreinte_TQ.clear();
|
|
// on passe en revue la liste
|
|
List_io<TypeQuelconque>::const_iterator itq,itqfin=liTQ.end();
|
|
for (itq=liTQ.begin();itq!=itqfin;itq++)
|
|
{const TypeQuelconque& tipParticu = (*itq); // pour simplifier
|
|
const TypeQuelconque_enum_etendu& enuTypeQuelconque = tipParticu.EnuTypeQuelconque();
|
|
if (enuTypeQuelconque.Nom_vide()) // veut dire que c'est un enum pur
|
|
switch (enuTypeQuelconque.EnumTQ())
|
|
{ case NOEUD_PROJECTILE_EN_CONTACT: case NOEUD_FACETTE_EN_CONTACT:
|
|
case PENETRATION_CONTACT: case FORCE_CONTACT:
|
|
case CONTACT_PENALISATION_N: case CONTACT_PENALISATION_T:
|
|
case CONTACT_ENERG_PENAL: case NORMALE_CONTACT:
|
|
case GLISSEMENT_CONTACT: case CONTACT_ENERG_GLISSE_ELAS:
|
|
case CONTACT_ENERG_GLISSE_VISQ: case CONTACT_ENERG_GLISSE_PLAS:
|
|
case CONTACT_NB_DECOL: case CONTACT_NB_PENET:
|
|
case CONTACT_CAS_SOLIDE: case CONTACT_COLLANT:
|
|
case NUM_ZONE_CONTACT: //case N_FRONT :
|
|
{// ----- cas des noeuds projectiles en contact
|
|
li_restreinte_TQ.push_front(TypeQuelconque(tipParticu));
|
|
break;
|
|
}
|
|
default: ;// on ne fait rien
|
|
};
|
|
};
|
|
};
|
|
|
|
// initialisation des listes de grandeurs qu'ils faudra transférérer aux niveaux des noeuds des élements
|
|
// de contact, on définit si besoin, les conteneurs ad hoc au niveau des noeuds
|
|
void LesContacts::Init_Grandeur_particuliere (bool absolue,List_io<TypeQuelconque>& liTQ)
|
|
{liQ_en_sortie = liTQ; // on récupère la liste --> sans doute que cela ne sert à rien
|
|
|
|
LaLIST<ElContact>::iterator ili_deb= listContact.begin();
|
|
LaLIST<ElContact>::iterator ilifin= listContact.end();
|
|
LaLIST<ElContact>::iterator ili;
|
|
|
|
// on passe en revue la liste
|
|
List_io<TypeQuelconque>::iterator itq,itqfin=liTQ.end();
|
|
// on part du principe qu'il y a plus de noeuds en contact que de grandeur donc on fait une
|
|
// boucle externe sur les noeuds en contact: on parcours la liste des noeuds en contact
|
|
for (ili=ili_deb;ili!=ilifin;ili++)
|
|
{ElContact& elcont = (*ili); // pour simplifier
|
|
for (itq=liTQ.begin();itq!=itqfin;itq++)
|
|
{TypeQuelconque& tipParticu = (*itq); // pour simplifier
|
|
EnumTypeQuelconque enuTQ = tipParticu.EnuTypeQuelconque().EnumTQ();
|
|
|
|
switch (enuTQ)
|
|
{ case NOEUD_PROJECTILE_EN_CONTACT: case NOEUD_FACETTE_EN_CONTACT:
|
|
case GLISSEMENT_CONTACT: case PENETRATION_CONTACT:
|
|
case FORCE_CONTACT: case CONTACT_NB_PENET:
|
|
case CONTACT_PENALISATION_N: case CONTACT_PENALISATION_T:
|
|
case CONTACT_NB_DECOL: case CONTACT_CAS_SOLIDE:
|
|
case CONTACT_ENERG_PENAL: case CONTACT_COLLANT:
|
|
case NUM_ZONE_CONTACT: //case N_FRONT :
|
|
case NORMALE_CONTACT: case CONTACT_ENERG_GLISSE_ELAS:
|
|
case CONTACT_ENERG_GLISSE_VISQ: case CONTACT_ENERG_GLISSE_PLAS:
|
|
|
|
{// ----- cas des noeuds projectiles en contact
|
|
elcont.Esclave()->AjoutUnTypeQuelconque(*itq); // ajout du conteneur
|
|
break;
|
|
}
|
|
default: ; // sinon rien
|
|
};
|
|
};
|
|
};
|
|
|
|
} ;
|
|
|
|
//========================== fonction protegee =============================
|
|
|
|
// mise à jour des boites d'encombrement pour les éléments qui contiennent une frontière
|
|
void LesContacts::Mise_a_jour_boite_encombrement_element_contenant_front()
|
|
{
|
|
list <Element *>::iterator il,ilfin = liste_elemens_front.end();
|
|
for (il = liste_elemens_front.begin();il!=ilfin;il++)
|
|
(*il)->Boite_encombre_element(TEMPS_tdt);
|
|
|
|
};
|
|
|
|
// suppression du gap de contact pour les noeuds "collant avec suppression de gap"
|
|
void LesContacts::Suppression_gap_pour_noeud_collant()
|
|
{
|
|
int niveau_commentaire_lescontacts = Permet_affichage();
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
#endif
|
|
// on passe en revue les zones de contact et si nécessaire on supprime les gaps
|
|
// sinon retour
|
|
bool continuer = false; // init par défaut
|
|
// list <Quatre_string_un_entier> nom_ref_zone_contact; // liste des noms de références des zones de contact
|
|
list <Quatre_string_un_entier>::iterator iu,iufin = nom_ref_zone_contact.end();
|
|
for (iu = nom_ref_zone_contact.begin();iu != iufin; iu++)
|
|
if ((*iu).n == 2)
|
|
{continuer = true; break;};
|
|
if (!continuer)
|
|
return;
|
|
|
|
// sinon il faut effectivement faire une suppression de gap
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts > 2)
|
|
cout << "\n >>>> Suppression_gap_pour_noeud_collant : ";
|
|
// on va iterer sur les noeuds esclaves collants dont on veut supprimer le gap
|
|
LaLIST_io <Front>::iterator iM,iMfin; // des itérator de travail
|
|
int nb_zone = MaX(1,nom_ref_zone_contact.size());
|
|
double dist_max = Dabs(ParaGlob::param->ParaAlgoControleActifs().DistanceMaxiAuPtProjete());
|
|
|
|
int tout_projeter = true; // init
|
|
int boucle_maxi = 10; // 10 boucle maxi
|
|
int boucle = 1;
|
|
do
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >2 )
|
|
cout << "\n boucle : "<<boucle << flush;
|
|
for (int intot = 1;intot<= nb_mail_Esclave;intot++) // boucle sur les maillages esclaves
|
|
for (int j=1;j<=nb_zone;j++) // boucle sur les zones de contact
|
|
{const Tableau <Noeud*>& tesc= tesctotal(intot)(j); // pour simplifier la notation:
|
|
const Tableau <int> tesN_col = tesN_collant(intot)(j); // pour simplifier
|
|
int tesc_taille=tesc.Taille(); // tab des noeuds esclaves à considérer
|
|
int compteur_noeuds_projecte=0; // le nombre de noeuds qui sont projetés
|
|
double le_maxi_des_distances_trouve = 0.;
|
|
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
|
|
if (tesN_col(inesc) == 2 ) // cas noeud collant avec volonté de supprimer le gap
|
|
{ Noeud* noee = tesc(inesc); // pour simplifier
|
|
//--- debug
|
|
//if (noee->Num_noeud() == 5)
|
|
// {cout << "\n arrivée au bon element ";
|
|
// }
|
|
const Coordonnee pt_esc = noee->Coord0(); // position du noeud esclave initial
|
|
list <Coordonnee > list_P; // la liste des projetés
|
|
list <LaLIST_io <Front>::iterator> li_pt_front_P; // liste sur les faces pour le debug
|
|
for (int jlf=1;jlf<=nbmailMaitre;jlf++) // boucle sur les maillages maitres
|
|
{//Tableau < Tableau < LaLIST_io <Front> > > t_listFront;
|
|
LaLIST_io <Front>& t_l_front = t_listFront(jlf)(j);
|
|
iMfin=t_l_front.end();
|
|
for (iM = t_l_front.begin() ; iM != iMfin; iM++) // boucle sur les front maitres
|
|
{// si c'est dans le volume de la frontière augmenté de la distance ad hoc on test
|
|
// plus précisément
|
|
if ((*iM).In_boite_emcombrement_front(pt_esc,dist_max))
|
|
{// on projete le noeud sur la frontière
|
|
Coordonnee P;
|
|
////--- debug
|
|
//if ((noee->Num_noeud() == 5) && ((*iM).PtEI()->Num_elt()==367))
|
|
// {cout << "\n arrivée au bon element ";
|
|
//
|
|
// }
|
|
//{double Ndis = (P-pt_esc).Norme();
|
|
// if (Ndis > 20)
|
|
// (*iM).Eleme()->Projection_normale(pt_esc,P);
|
|
//}
|
|
//-- fin debug
|
|
|
|
// //----debug
|
|
//{if ((noee->Num_noeud() == 12)
|
|
// && ((*iM).Num_frontiere() == 1) && ((*iM).PtEI()->Num_elt() == 3130))
|
|
// { cout << "\n debug : frontiere 1 de l'element 3130";}
|
|
//}
|
|
////----fin debug
|
|
|
|
// si la projection est valide on enregistre
|
|
if ((*iM).Eleme()->Projection_normale(pt_esc,P))
|
|
{ list_P.push_back(P);
|
|
li_pt_front_P.push_back(iM);
|
|
};
|
|
//--- debug
|
|
//{double Ndis = (P-pt_esc).Norme();
|
|
// if (Ndis > 20)
|
|
// (*iM).Eleme()->Projection_normale(pt_esc,P);
|
|
//}
|
|
//-- fin debug
|
|
|
|
};
|
|
};
|
|
};
|
|
// maintenant on va garder le plus proche
|
|
bool projection_ok = false; // init
|
|
if (list_P.size() != 0)
|
|
{list <Coordonnee >::iterator il,ilfin=list_P.end();
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >5 )
|
|
{cout << "\n " << list_P.size() << " proj trouvees "
|
|
<< " Noe: "<<noee->Num_noeud()
|
|
<< " mail: " << noee->Num_Mail() << " (zone"<<j<<")";
|
|
};
|
|
Coordonnee M = pt_esc; // init
|
|
Coordonnee P(M); // la projection
|
|
double distance = dist_max;
|
|
LaLIST_io <LaLIST_io <Front>::iterator>::iterator iface = li_pt_front_P.begin();
|
|
LaLIST_io <LaLIST_io <Front>::iterator>::iterator iface_maxi ;
|
|
for (il=list_P.begin(); il!= ilfin;il++,iface++)
|
|
{ double Ndis = (M-(*il)).Norme();
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >5 )
|
|
cout << " dist: " << Ndis ;
|
|
if (Ndis < distance)
|
|
{P = (*il); distance = Ndis;
|
|
projection_ok = true; // au moins un nouveau point
|
|
iface_maxi = iface;
|
|
};
|
|
};
|
|
// si la distance == 0., il n'y a pas à changer les coordonnées
|
|
// car le point projeté == le point initial
|
|
if (distance > ConstMath::petit)
|
|
{// on change les coordonnées du noeud
|
|
noee->Change_coord0(P);
|
|
noee->Change_coord1(P);
|
|
noee->Change_coord2(P);
|
|
compteur_noeuds_projecte++;
|
|
tout_projeter=false;
|
|
if (distance > le_maxi_des_distances_trouve)
|
|
le_maxi_des_distances_trouve = distance;
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >3 )
|
|
cout << "\n suppression gap=("<<distance<<") du noeud "<<noee->Num_noeud()
|
|
<< " du maillage " << noee->Num_Mail() << " (zone "<<j<<")";
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >4 )
|
|
{cout << "\n ancienne coordonnee "<< pt_esc
|
|
<< " nouvelle " << P;
|
|
// dans le cas où iface_maxi a été attribué
|
|
if (projection_ok)
|
|
(*(*iface_maxi)).Affiche();
|
|
|
|
////--- debug
|
|
//{
|
|
//const Coordonnee pt_esc = noee->Coord0();
|
|
//Coordonnee PP;
|
|
//(*(*iface_maxi)).Eleme()->Projection_normale(pt_esc,PP);
|
|
//cout << "\n $$$ nouvelle coordonnees projetee "<< PP;
|
|
//}
|
|
////-- fin debug
|
|
|
|
};
|
|
}
|
|
else if (projection_ok)
|
|
// si on n'a pas de projection avec changement de position
|
|
// mais par contre on a quand même trouvé un projeté on enregistre
|
|
{compteur_noeuds_projecte++;};
|
|
};
|
|
if ((!projection_ok) && (boucle==1)) // au premier passage
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >3 )
|
|
cout << "\n pas de projection trouvee donc de suppression gap du noeud "<<noee->Num_noeud()
|
|
<< " du maillage" << noee->Num_Mail() << " (zone "<<j<<")";
|
|
} ;
|
|
}; //-- fin de la boucle sur inesc
|
|
#ifdef UTILISATION_MPI
|
|
if (proc_en_cours == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >2 )
|
|
{if (compteur_noeuds_projecte)
|
|
cout << "\n zone: " << j <<", " << compteur_noeuds_projecte << " suppression(s) de gap, maxi_distance= "
|
|
<< le_maxi_des_distances_trouve << "( passage"<<boucle<<")" ;
|
|
int non_gap = tesc_taille-compteur_noeuds_projecte;
|
|
if ((non_gap)&& (boucle==1)) // au premier passage
|
|
cout << "\n zone: " << j <<", *** attention pour "<<non_gap
|
|
<< " noeud(s) pas de projection trouvee !! ";
|
|
};
|
|
}; //-- fin de la boucle sur intot
|
|
boucle++;
|
|
}
|
|
while ((!tout_projeter) && (boucle < boucle_maxi));
|
|
// Sortie(1);
|
|
};
|
|
|
|
// récupération de la zone de contact d'un élément de contact existant
|
|
// c'est un peu lourdinge, mais l'avantage c'est que cela s'adapte à une situation qui
|
|
// a par exemple changé
|
|
// si en retour le numéro de zone = 0, cela signifie que le contact ne peut plus exister
|
|
int LesContacts::Recup_ref( ElContact& al)
|
|
{ int nb_zone = MaX(1,nom_ref_zone_contact.size());
|
|
const Tableau <Noeud*>& tn = al.TabNoeud();
|
|
|
|
// on parcours la liste des frontières succeptibles d'entrer en contact
|
|
// pour repérer la zone
|
|
int num_zone = 0; // init
|
|
int nb_maitre = t_listFront.Taille();
|
|
int nb_esclave = tesctotal.Taille();
|
|
for (int i=1;i<=nb_maitre;i++)
|
|
{for (int j=1;j<=nb_zone;j++)
|
|
{LaLIST_io <Front> & list_fronta = t_listFront(i)(j); // pour simplifier
|
|
LaLIST_io <Front>::iterator il,ilfin = list_fronta.end();
|
|
for (il = list_fronta.begin();il != ilfin; il++)
|
|
{if ((*il)==(*al.Elfront()))
|
|
// les deux pointeurs pointent sur la même frontière, donc
|
|
// maintenant on regarde du coté des noeuds esclaves
|
|
{ for (int ie = 1; ie<=nb_esclave;ie++)
|
|
{const Tableau <Noeud*>& tesc= tesctotal(i)(j); // pour simplifier la notation:
|
|
int tesc_taille=tesc.Taille(); // tab des noeuds esclaves à considérer
|
|
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
|
|
{if (tesc(inesc) == al.Esclave())
|
|
// les deux pointeurs pointent sur le même noeud, c'est ok
|
|
{num_zone = j; break;};
|
|
};
|
|
if (num_zone)
|
|
break;
|
|
};
|
|
};
|
|
if (num_zone)
|
|
break;
|
|
};
|
|
if (num_zone)
|
|
break;
|
|
};
|
|
if (num_zone)
|
|
break;
|
|
};
|
|
// retour des infos
|
|
return num_zone;
|
|
};
|
|
|
|
|
|
// création d'un tableau de condition linéaire, correspondant à tous les éléments de contact en cours
|
|
// qu'ils soient actifs ou pas (a prior cette méthode est conçu pour donner des infos relativement à la largeur
|
|
// de bandes en noeuds due aux CLL)
|
|
// chacune des condition ne contient "d'exploitable" que le tableau de noeuds associés à la CLL,
|
|
list <Condilineaire>& LesContacts::ConnectionCLL()
|
|
{
|
|
tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
if (proc_en_cours != 0)
|
|
{
|
|
#endif
|
|
{
|
|
// // on boucle sur le tableau et pour chaque element on crée une condition lineaire
|
|
// int tabTaille = listContact.size();
|
|
// t_connectionCLL.Change_taille(tabTaille);
|
|
t_connectionCLL.clear();
|
|
// un tableau servant à la def de la CLL
|
|
Tableau <Enum_ddl > t_enu(1); t_enu(1)=X1 ;
|
|
LaLIST <ElContact>::const_iterator il,ilfin=listContact.end();
|
|
int posi=1; // init pour le tableau
|
|
for (il=listContact.begin();il != ilfin;il++,posi++)
|
|
{ const Tableau < Noeud *>& t_n = (*il).Const_TabNoeud();
|
|
// on est dans le cas ou l'on connait les infos relatives uniquements aux noeuds, aux enum ddl
|
|
t_connectionCLL.push_back(Condilineaire(t_enu, t_n));
|
|
};
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
}
|
|
#ifdef UTILISATION_MPI
|
|
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
|
|
// maintenant on va les transmettres au cpu 0
|
|
// pour cela on va utiliser un conteneur intermédiaire
|
|
// on calcul la taille nécessaire pour le conteneur (a découper éventuellement ??)
|
|
int taille_conteneur=0;
|
|
list <Condilineaire>::iterator il,ilfin = t_connectionCLL.end();
|
|
for (il = t_connectionCLL.begin();il != ilfin;il++)
|
|
taille_conteneur += (*il).Taille_Pack();
|
|
inter_transfer2.Change_taille(taille_conteneur); // le conteneur
|
|
// on rempli le conteneur
|
|
int rang = 1; // init
|
|
for (il = t_connectionCLL.begin();il != ilfin;il++)
|
|
rang = (*il).Pack_vecteur(inter_transfer2,rang);
|
|
temps_attente.Arret_du_comptage();
|
|
// on transfert
|
|
mpi::request reqs1 = ParaGlob::Monde()->isend(0, 42, taille_conteneur);
|
|
|
|
mpi::request reqs2 = inter_transfer2.Ienvoi_MPI(0,43);
|
|
// on attend pas
|
|
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
|
|
}
|
|
else // cas du cpu 0
|
|
{// l'objectif ici est de récupérer les conditions linéaires
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
temps_transfert_long.Mise_en_route_du_comptage(); // comptage cpu
|
|
int nb_proc_terminer = 0; // permettra de terminer
|
|
t_connectionCLL.clear();// Change_taille(nb_contact_actif);
|
|
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
|
|
{ // on récupère un résultat de cpu i
|
|
|
|
int taille_transfert;
|
|
mpi::request reqs1 = ParaGlob::Monde()->irecv(mpi::any_source, 42, taille_transfert);
|
|
mpi::status stat = reqs1.wait(); // on attend que le conteneur soit rempli
|
|
inter_transfer2.Change_taille(taille_transfert); // le conteneur
|
|
int source = stat.source(); // récupération du numéro de la source
|
|
// on récupère
|
|
mpi::request reqs2 = inter_transfer2.Irecup_MPI(source, 43);
|
|
reqs2.wait(); // on attend que le conteneur soit rempli
|
|
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
|
|
// on va remplir la liste des conditions limites
|
|
int rang = 1; // init
|
|
while (rang != 0)
|
|
{ Condilineaire condi; // une condition intermédiaire
|
|
rang = condi.UnPack_vecteur(*lesMaille,inter_transfer2,rang,
|
|
&LesMaillages::Noeud_LesMaille);
|
|
t_connectionCLL.push_back(condi);
|
|
};
|
|
};
|
|
temps_transfert_long.Arret_du_comptage();
|
|
};
|
|
#endif
|
|
|
|
// retour
|
|
return t_connectionCLL;
|
|
};
|
|
|
|
|
|
// récupère le nombre de contact actif et met à jour ce nombre
|
|
// normalement devrait toujours être correct mais ?? il y a quelque chose d'incorrecte quelque part
|
|
int LesContacts::Calcul_Nb_contact_actif()
|
|
{ LaLIST <ElContact>::iterator il,ilfin = listContact.end();
|
|
nb_contact_actif = 0; // init
|
|
for (il = listContact.begin();il != ilfin; il++)
|
|
if ((*il).Actif())
|
|
nb_contact_actif++;
|
|
return nb_contact_actif;
|
|
};
|
|
|
|
|
|
// création du conteneur Fct_nD_contact
|
|
void LesContacts::Creation_Fct_nD_contact()
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
#endif
|
|
|
|
{// cas de la penalisation normale
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penalisationPenetration();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_penalisationPenetration = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage de la penalisation normale "
|
|
<< " le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_penalisationPenetration=NULL;};
|
|
};
|
|
|
|
{// cas fct_nD_penetration_contact_maxi
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penetration_contact_maxi();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_penetration_contact_maxi = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage de la "
|
|
<< " penetration maxi, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_penetration_contact_maxi=NULL;};
|
|
};
|
|
|
|
{// cas Fct_nD_penetration_borne_regularisation
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penetration_borne_regularisation();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_penetration_borne_regularisation = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage de la "
|
|
<< " borne de regularisation, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_penetration_borne_regularisation=NULL;};
|
|
};
|
|
|
|
{// cas fct_nD_force_contact_noeud_maxi
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_force_contact_noeud_maxi();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_force_contact_noeud_maxi = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage de la "
|
|
<< " force de contact normale, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_force_contact_noeud_maxi=NULL;};
|
|
};
|
|
|
|
{// cas fct_nD_penalisationTangentielle
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_penalisationTangentielle();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_penalisationTangentielle = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage de la penalisation tangentielle "
|
|
<< " le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_penalisationTangentielle=NULL;};
|
|
};
|
|
|
|
{// cas fct_nD_tangentielle_contact_maxi
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_tangentielle_contact_maxi();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_tangentielle_contact_maxi = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage du "
|
|
<< " deplacement tangentiel maxi, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_tangentielle_contact_maxi=NULL;};
|
|
};
|
|
|
|
{// cas fct_nD_tangentielle_borne_regularisation
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_tangentielle_borne_regularisation();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_tangentielle_borne_regularisation = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage de la "
|
|
<< " borne de regularisation tangentielle, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_tangentielle_borne_regularisation=NULL;};
|
|
};
|
|
|
|
{// cas fct_nD_force_tangentielle_noeud_maxi
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_nD_force_tangentielle_noeud_maxi();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_nD_force_tangentielle_noeud_maxi = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage de la "
|
|
<< " force tangentielle maxi, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_nD_force_tangentielle_noeud_maxi=NULL;};
|
|
};
|
|
|
|
{// cas fct_niveau_commentaire
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_niveau_commentaire_contact();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_nD_contact.fct_niveau_commentaire = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage du "
|
|
<< " niveau de commentaire en contact, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_nD_contact.fct_niveau_commentaire=NULL;};
|
|
};
|
|
|
|
// initialisation des conteneurs statique des fonction nD
|
|
fct_nD_contact.Init_conteneur_statique();
|
|
|
|
|
|
};
|
|
|
|
/*// mise à jour du stockage inter, pour prendre en
|
|
// compte une nouvelle numérotation des noeuds
|
|
void LesContacts::Prise_en_compte_nouvelle_numerotation_noeud()
|
|
{ //on va reconstruire ta_inverse
|
|
int nb_zone = MaX(1,nom_ref_zone_contact.size());
|
|
// on garde en mémoire les anciens numéros pour faire le pontage
|
|
Tableau < Tableau < Tableau <int> > > ta_inverse_old(ta_inverse);
|
|
|
|
// on recherche les maxi des numéros de noeuds esclave, pour dimensionner ta_inverse !!
|
|
Tableau < Tableau <int> > maxi_num_noe_esclave(nb_mail_Esclave); // init à 0
|
|
for (int i=1;i<=nb_mail_Esclave;i++)
|
|
{maxi_num_noe_esclave(i).Change_taille(nb_zone);
|
|
for (int j=1;j<=nb_zone;j++)
|
|
{const Tableau <Noeud*>& tesc= tesctotal(i)(j); // pour simplifier la notation:
|
|
int tesc_taille=tesc.Taille(); // tab des noeuds esclaves à considérer
|
|
int& max_num_esclave = maxi_num_noe_esclave(i)(j); // pour simplifier
|
|
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
|
|
{ Noeud* noee = tesc(inesc); // pour simplifier
|
|
int num_noeud = noee->Num_noeud();
|
|
if (num_noeud > max_num_esclave)
|
|
max_num_esclave = num_noeud;
|
|
};
|
|
};
|
|
};
|
|
// Maintenant on peut dimensionner ta_inverse
|
|
for (int i=1;i<=nb_mail_Esclave;i++)
|
|
{ta_inverse(i).Change_taille(nb_zone);
|
|
for (int j=1;j<=nb_zone;j++)
|
|
ta_inverse(i)(j).Change_taille(maxi_num_noe_esclave(i)(j),0);
|
|
};
|
|
|
|
// ensuite on va remplir ta_inverse
|
|
for (int intot=1;intot<=nb_mail_Esclave;intot++)
|
|
{for (int j=1;j<=nb_zone;j++)
|
|
{const Tableau <Noeud*>& tesc= tesctotal(intot)(j); // pour simplifier la notation:
|
|
int tesc_taille=tesc.Taille(); // tab des noeuds esclaves à considérer
|
|
for (int inesc = 1;inesc<= tesc_taille;inesc++) // boucle sur les noeuds esclaves
|
|
{ Noeud* noee = tesc(inesc); // pour simplifier
|
|
ta_inverse(intot)(j)(noee->Num_noeud()) = inesc;
|
|
};
|
|
};
|
|
};
|
|
|
|
// on va créer un tableau de changement des numéros de noeuds
|
|
Tableau < Tableau <int> > nouveau_Noe(nb_mail_Esclave);
|
|
// on cherche la taille maxi
|
|
Tableau <int> maxi_maxi_num_noe_esclave(nb_mail_Esclave); // les maxis pour chaque maillage
|
|
for (int i=1;i<=nb_mail_Esclave;i++)
|
|
{int& max_max_esclave = maxi_maxi_num_noe_esclave(i) = 0; // init
|
|
for (int j=1;j<=nb_zone;j++)
|
|
{int& max_num_esclave = maxi_num_noe_esclave(i)(j); // pour simplifier
|
|
if (max_num_esclave > max_max_esclave)
|
|
max_max_esclave = max_num_esclave;
|
|
};
|
|
};
|
|
// on balaie les anciens noeuds
|
|
for (int i=1;i<=nb_mail_Esclave;i++)
|
|
{nouveau_Noe(i).Change_taille(maxi_maxi_num_noe_esclave(i));
|
|
Tableau <int>& nouveau_Noe_i = nouveau_Noe(i);
|
|
for (int j=1;j<=nb_zone;j++)
|
|
{ Tableau <int> & ta_inverse_old_ij = ta_inverse_old(i)(j);
|
|
Tableau <int> & ta_inverse_ij = ta_inverse(i)(j);
|
|
int nbN = ta_inverse_old_ij.Taille();
|
|
for (int k=1;k<= nbN;k++) // k c'est le numéro de l'ancien noeud
|
|
{if (ta_inverse_old_ij(k) != 0)
|
|
{for (int k2=1;k2<= nbN;k2++)
|
|
{ if (ta_inverse_old_ij(k) == ta_inverse_ij(k2))
|
|
{nouveau_Noe_i(k)=k2;break;};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
// // maintenant on met à jour le tableau tesN_encontact
|
|
// // Tableau < Tableau < LaLIST < LaLIST<ElContact>::iterator > > > tesN_encontact;
|
|
// // on sauvegarde l'ancien
|
|
// Tableau < Tableau < LaLIST < LaLIST<ElContact>::iterator > > > tesN_encontact_old(tesN_encontact);
|
|
// // et on fait la passation
|
|
// for (int i=1;i<=nb_mail_Esclave;i++)
|
|
// {Tableau <int>& nouveau_Noe_i = nouveau_Noe(i);
|
|
// int nbn = tesN_encontact(i).Taille();
|
|
// for (int j=1;j<=nbn;j++)
|
|
// { tesN_encontact(i)(nouveau_Noe_i(j)) = tesN_encontact_old(i)(j);
|
|
// };
|
|
// };
|
|
|
|
// on continue avec le tableau: liste pour chaque noeud, des éléments qui contient ce noeud
|
|
// indice(i)(j) : = la liste des éléments qui contiennent le noeud j, pour le maillage i
|
|
Tableau < const Tableau <List_io < Element* > > *> indice_old(indice);
|
|
int nb_mail = indice_old.Taille();
|
|
for (int i=1;i<=nb_mail;i++)
|
|
{if (indice_old(i) != NULL)
|
|
{ int nbn = indice_old(i)->Taille();
|
|
// const Tableau <List_io < Element* > > & indice_i = indice(i);
|
|
// for (int j=1;j<=nbn;j++)
|
|
//indice
|
|
|
|
}
|
|
|
|
}
|
|
cout << "\n LesContacts::Prise_en_compte_nouvelle_numerotation_noeud() pas terminé !!"
|
|
<< " il faut changer lesMaillages pour récupérer directement la nouvelle numérotation !!";
|
|
Sortie(1);
|
|
|
|
};
|
|
*/
|
|
|
|
|
|
// récupération via les éléments de contact des forces maxis
|
|
// et affichage éventuel
|
|
// un : le maxi en effort normal, deux: le maxi en effort tangentiel
|
|
// Dans le cas d'un calcul parallèle, il y a transfert du résultat au cpu 0
|
|
// seules les cpu i calculent
|
|
DeuxDoubles LesContacts::Forces_contact_maxi(bool affiche)
|
|
{tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
DeuxDoubles retour_min,retour_max; // def et init à 0
|
|
int niveau_commentaire_lescontacts = Permet_affichage();
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
if (proc_en_cours != 0)
|
|
{
|
|
#endif
|
|
{
|
|
LaLIST <ElContact>::const_iterator iNmin,iNmax,iTmax,il,ilfin = listContact.end();
|
|
LaLIST <ElContact>::const_iterator ilbegin = listContact.begin();
|
|
for (il = iNmax = iTmax = iNmin = ilbegin;il != ilfin; il++)
|
|
if ((*il).Actif())
|
|
{ const ElContact& icont = (*il); // pour simplifier
|
|
double fNmax = icont.F_N_MAX();
|
|
double fTmax = icont.F_T_MAX();
|
|
if (fNmax < retour_min.un )
|
|
{retour_min.un = fNmax;iNmin = il;
|
|
};
|
|
if (fNmax > retour_max.un )
|
|
{retour_max.un = fNmax;iNmax = il;
|
|
};
|
|
// fTmax est toujours positif, donc on ne teste que le maxi
|
|
if (fTmax > retour_max.deux)
|
|
{retour_max.deux = fTmax;iTmax = il;
|
|
};
|
|
};
|
|
// affichage si on n'est pas en //
|
|
#ifndef UTILISATION_MPI
|
|
if ((affiche && (ParaGlob::NiveauImpression() > 2))
|
|
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
|
|
)
|
|
{ cout << "\n F_N => [" << retour_min.un << " : " << retour_max.un << "]"
|
|
<< ", F_T max = " << retour_max.deux;
|
|
};
|
|
if (niveau_commentaire_lescontacts > 6)
|
|
{if (iNmin != ilbegin ){cout << "\n mini F_N : "; (*iNmin).Affiche(0);};
|
|
if (iNmax != ilbegin ){cout << "\n maxi F_N : "; (*iNmax).Affiche(0);};
|
|
if (iTmax != ilbegin ){cout << "\n maxi F_T : "; (*iTmax).Affiche(0);};
|
|
cout << "\n ";
|
|
}
|
|
else if (niveau_commentaire_lescontacts > 3)
|
|
{if (iNmin != ilbegin ) {cout << "\n mini F_N : "; (*iNmin).Affiche(1);};
|
|
if (iNmax != ilbegin ){cout << "\n maxi F_N : "; (*iNmax).Affiche(1);};
|
|
if (iTmax != ilbegin ){cout << "\n maxi F_T : "; (*iTmax).Affiche(1);};
|
|
cout << "\n ";
|
|
}
|
|
|
|
// cout << "\n contact: reaction ==> F_N max " << retour.un << " F_T max " << retour.deux;
|
|
// if (niveau_commentaire_lescontacts > 6)
|
|
// {if (iNmax != itbegin) {cout << "\n F_N max: "; (*iNmax).Affiche(0);};
|
|
// if (iTmax != itbegin) {cout << "\n F_T max: "; (*iTmax).Affiche(0);};
|
|
// cout << "\n";
|
|
// }
|
|
// else if (niveau_commentaire_lescontacts > 3)
|
|
// {if (iNmax != itbegin) {cout << "\n F_N max: "; (*iNmax).Affiche(1);};
|
|
// if (iTmax != itbegin) {cout << "\n F_T max: "; (*iTmax).Affiche(1);};
|
|
// cout << "\n";
|
|
// };
|
|
#endif
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
}
|
|
#ifdef UTILISATION_MPI
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
// maintenant on va transmettre au cpu 0
|
|
Vecteur v_inter(2);v_inter(1) = retour.un; v_inter(2) = retour.deux;
|
|
// envoi
|
|
v_inter.Ienvoi_MPI(0,66);
|
|
// on attend pas
|
|
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
|
|
}
|
|
else // cas du cpu 0
|
|
{// l'objectif ici est de récupérer les infos
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
int nb_proc_terminer = 0; // permettra de terminer
|
|
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
|
|
{ // on récupère un résultat de cpu i
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
Vecteur v_inter(2);
|
|
mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 66);
|
|
reqs1.wait(); // on attend que le conteneur soit rempli
|
|
|
|
if (Dabs(v_inter(1)) > Dabs(retour.un) )
|
|
{retour.un = v_inter(1);};
|
|
if (Dabs(v_inter(2)) > Dabs(retour.deux) )
|
|
{retour.deux = v_inter(2);
|
|
};
|
|
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
|
|
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
|
|
};
|
|
if ((affiche && (ParaGlob::NiveauImpression() > 2))
|
|
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
|
|
)
|
|
cout << "\n contact: reaction ==> |F_N max| " << Dabs(retour_min.un) << " |F_T max| " << DabsMaX(retour_min.deux,retour_max.deux);
|
|
};
|
|
#endif
|
|
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
return retour_max;
|
|
};
|
|
|
|
// récupération via les éléments de contact des gaps maxi en négatif, donc les mini
|
|
// un : le maxi en gap normal, deux: le maxi en gap tangentiel
|
|
// Dans le cas d'un calcul parallèle, il y a transfert du résultat au cpu 0
|
|
// seules les cpu i calculent
|
|
DeuxDoubles LesContacts::Gap_contact_maxi(bool affiche)
|
|
{tempsContact.Mise_en_route_du_comptage(); // def deb compt
|
|
DeuxDoubles retour_max,retour_min;
|
|
int niveau_commentaire_lescontacts = Permet_affichage();
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
if (proc_en_cours != 0)
|
|
{
|
|
#endif
|
|
{
|
|
LaLIST <ElContact>::const_iterator iNmax,iTmax,iNmin,iTmin,il,ilfin = listContact.end();
|
|
LaLIST <ElContact>::const_iterator ilbegin=listContact.begin();
|
|
for (il = iNmax = iTmax = iNmin = iTmin = ilbegin;il != ilfin; il++)
|
|
if ((*il).Actif())
|
|
{ const ElContact& icont = (*il); // pour simplifier
|
|
double fNmax = icont.Gaptdt();
|
|
double fTmax = icont.Dep_T_tdt();
|
|
if (fNmax > retour_max.un )
|
|
{retour_max.un = fNmax;iNmax = il;
|
|
};
|
|
if (fNmax < retour_min.un )
|
|
{retour_min.un = fNmax;iNmin = il;
|
|
};
|
|
if (fTmax > retour_max.deux )
|
|
{retour_max.deux = fTmax;iTmax = il;
|
|
};
|
|
if (fTmax < retour_min.deux )
|
|
{retour_min.deux = fTmax;iTmin = il;
|
|
};
|
|
};
|
|
// affichage si on n'est pas en //
|
|
#ifndef UTILISATION_MPI
|
|
if ((affiche && (ParaGlob::NiveauImpression() > 2))
|
|
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
|
|
)
|
|
cout << ", [" << retour_min.un << " <= gap_N <= " << retour_max.un << "], [" << retour_min.deux <<" <= gap_T <= " << retour_max.deux<<"] ";
|
|
if (niveau_commentaire_lescontacts > 6)
|
|
{if (iNmin != ilbegin ){cout << "\n mini gap_N : "; (*iNmin).Affiche(0);};
|
|
if (iNmax != ilbegin ){cout << "\n maxi gap_N : "; (*iNmax).Affiche(0);};
|
|
if (iTmin != ilbegin ){cout << "\n mini gap_T : "; (*iTmin).Affiche(0);};
|
|
if (iTmax != ilbegin ){cout << "\n maxi gap_T : "; (*iTmax).Affiche(0);};
|
|
cout << "\n ";
|
|
}
|
|
else if (niveau_commentaire_lescontacts > 3)
|
|
{if (iNmin != ilbegin ) {cout << "\n mini gap_N : "; (*iNmin).Affiche(1);};
|
|
if (iNmax != ilbegin ){cout << "\n maxi gap_N : "; (*iNmax).Affiche(1);};
|
|
if (iTmin != ilbegin ){cout << "\n mini gap_T : "; (*iTmin).Affiche(1);};
|
|
if (iTmax != ilbegin ){cout << "\n maxi gap_T : "; (*iTmax).Affiche(1);};
|
|
cout << "\n ";
|
|
}
|
|
#endif
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
}
|
|
#ifdef UTILISATION_MPI
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
// maintenant on va transmettre au cpu 0
|
|
Vecteur v_inter(2);v_inter(1) = retour.un; v_inter(2) = retour.deux;
|
|
// envoi
|
|
v_inter.Ienvoi_MPI(0,67);
|
|
// on attend pas
|
|
temps_transfert_long.Arret_du_comptage(); // fin comptage cpu
|
|
}
|
|
else // cas du cpu 0
|
|
{// l'objectif ici est de récupérer les infos
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
int nb_proc_terminer = 0; // permettra de terminer
|
|
while (nb_proc_terminer < (ParaGlob::Monde()->size()-1)) // gérer par les valeurs de tyfront
|
|
{ // on récupère un résultat de cpu i
|
|
temps_transfert_court.Mise_en_route_du_comptage(); // comptage cpu
|
|
Vecteur v_inter(2);
|
|
mpi::request reqs1 = v_inter.Irecup_MPI(mpi::any_source, 67);
|
|
reqs1.wait(); // on attend que le conteneur soit rempli
|
|
|
|
if (Dabs(v_inter(1)) > Dabs(retour.un) )
|
|
{retour.un = v_inter(1);};
|
|
if (Dabs(v_inter(2)) > Dabs(retour.deux) )
|
|
{retour.deux = v_inter(2);
|
|
};
|
|
temps_transfert_court.Arret_du_comptage(); // fin comptage cpu
|
|
nb_proc_terminer++; // on prend en compte que l'on a récupéré un conteneur
|
|
};
|
|
if ((affiche && (ParaGlob::NiveauImpression() > 2))
|
|
|| (niveau_commentaire_lescontacts > 3) // spécifiquement pour le contact
|
|
)
|
|
cout << ", [" << retour_min.un << " <= gap_N <= " << retour_max.un << "], [" << retour_min.deux <<" <= gap_T <= " << retour_max.deux<<"] ";
|
|
};
|
|
#endif
|
|
|
|
tempsContact.Arret_du_comptage(); // fin cpu
|
|
return retour_min;
|
|
};
|
|
|
|
|
|
// création et ajout des éléments de frontière correspondant aux angles morts
|
|
// en 2D : noeud frontière + éléments interne
|
|
// en 3D : ligne frontière + éléments interne
|
|
void LesContacts::ElementAngleMort(LesMaillages& lesMail)
|
|
{
|
|
// la liste des éléments qui contiennent des frontières, est reconstitué au démarrage avec Init_contact(..
|
|
//>>>>> list <Element *> liste_elemens_front;
|
|
// la liste pour chaque noeud, des éléments qui contient ce noeud : construite avec Init_contact
|
|
// indice(i)(j) : = la liste des éléments qui contiennent le noeud j, pour le maillage i
|
|
//>>>>> Tableau < const Tableau <List_io < Element* > > *> indice;
|
|
// la liste des éléments frontières succeptibles d'entrer en contact
|
|
// ces Front (qui contiennent que des pointeurs sauf une boite d'encombrement)
|
|
// sont différents de ceux des maillages, et sont donc stocké en interne
|
|
//>>>>> Tableau < Tableau < LaLIST_io <Front> > > t_listFront;
|
|
// t_listFront(i)(j)(k) : maillage maître (i)
|
|
// zone de contact (j)
|
|
// (K) = kième frontière (dans l'ordre de la liste)
|
|
// ** pour le tableaux t_listFront, le numéros dit de maillage, n'est pas le numéro
|
|
// ** intrinsèque de maillage (telle que ceux associés aux noeuds et éléments)
|
|
// ** mais uniquement un numéro locale d'ordre
|
|
// ** mais on a: les éléments de frontière de t_listFront(i) font partie du maillage
|
|
// i + (nb_mail_Esclave-nbmailautocontact)
|
|
int niveau_commentaire_lescontacts = Permet_affichage();
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts > 4)
|
|
cout << "\n ==> LesContacts::ElementAngleMort: ";
|
|
|
|
// --- à la fin du traitement on a besoin de mettre à jour les éléments mitoyens des Front
|
|
// --- on sauvegarde des infos
|
|
Tableau < Tableau < list <Front*> > > t_listFront_initial; // les pointeurs de front initiaux sans les angles morts
|
|
|
|
// t_liFront_noeud(i)(j)(k) : la liste des frontières initiales qui contiennent le noeud k de la zone j du maillage i
|
|
Tableau < Tableau < Tableau < list <Front*> > > > t_liFront_noeud;
|
|
t_liFront_noeud.Change_taille(lesMail.NbMaillage());
|
|
//**** à faire la même chose pour les elements segment .....
|
|
|
|
int tail1 = t_listFront.Taille(); // num ordre dans les maillages
|
|
t_listFront_initial.Change_taille(tail1);
|
|
for (int i =1;i<= tail1;i++)
|
|
{int i_mail = i + (nb_mail_Esclave-nbmailautocontact); // le num de maillage
|
|
int nb_noe_total = lesMail.Nombre_noeud(i_mail); // le nombre total de noeud du maillage
|
|
|
|
int tail2=t_listFront(i).Taille(); // nombre de zones
|
|
t_listFront_initial(i).Change_taille(tail2);
|
|
t_liFront_noeud(i).Change_taille(tail2);
|
|
|
|
for (int j=1;j<= tail2;j++) // on balaie les zones
|
|
{list <Front*> & t_listFront_initial_ij = t_listFront_initial(i)(j); // pour simplifier
|
|
LaLIST_io <Front> & t_listFront_ij = t_listFront(i)(j); // pour simplifier
|
|
// on dimensionne au nombre maxi de noeud pour chaque zone ...
|
|
// ça peut faire des gros tableaux mais il faut bien que l'on sache à quelle zone on s'intéresse ...
|
|
// donc pour l'instant c'est l'idée que je retiens
|
|
t_liFront_noeud(i)(j).Change_taille(nb_noe_total);
|
|
Tableau <list <Front*> >& t_liFront_noeud_ij = t_liFront_noeud(i)(j);
|
|
LaLIST_io <Front>::iterator il,ilfin=t_listFront_ij.end();
|
|
for (il = t_listFront_ij.begin();il != ilfin; il++)
|
|
{t_listFront_initial_ij.push_back(&(*il));
|
|
// on va remplir t_liFront_noeud_ij
|
|
ElFrontiere* elfro = (*il).Eleme(); // pour simplifier
|
|
const Tableau <Noeud *>& tabN = elfro->TabNoeud_const();
|
|
int nbNF = tabN.Taille();
|
|
for (int l=1;l<=nbNF;l++)
|
|
{ Noeud * noe = tabN(l);
|
|
t_liFront_noeud_ij(noe->Num_noeud()).push_back(&(*il));
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
// --- constitution des front d'angle mort
|
|
// l'idée est de rechercher les éléments qui sont en relation directe avec la frontière
|
|
// via une ligne ou un point, mais qui n'ont été pris en compte du fait qu'ils n'étaient pas
|
|
// reliés à une frontière de base
|
|
// on commence par les lignes ce qui conduit éventuellement à augmenter t_listFront
|
|
// ensuite on regarde les noeuds. Ainsi, si un élément nouveau est introduit via les lignes
|
|
// les noeuds de la ligne + l'élément ne vont pas s'ajouter
|
|
|
|
|
|
|
|
// 1) === cas des lignes frontières + éléments internes
|
|
// ce cas ne concerne que les espaces de travail 3D non axisymétrique
|
|
if ((ParaGlob::Dimension() == 3) && !(ParaGlob::AxiSymetrie()))
|
|
{ // on crée les frontières lignes au cas où
|
|
lesMail.CreeListFrontiere_ligne_3D();
|
|
// on récupère toutes les frontières lignes
|
|
// ramène le tableau de pointeurs de frontières ligne 3D créées par CreeListFrontiere_ligne_3D
|
|
Tableau <LaLIST <Front>*>& lifrLigne = lesMail.ListFront_ligne_3D();
|
|
if (nom_ref_zone_contact.size() == 0)
|
|
{ // cas d'un contact non restreint
|
|
// cela correspond finalement à une seule zone de contact (cf. Init_contact(..))
|
|
//on boucle sur les maillages maitres de t_listFront
|
|
for (int im=1;im<=nbmailMaitre;im++)
|
|
{ // ici on ne boucle pas sur les zones restreintes car il n'y en n'a pas
|
|
LaLIST_io <Front> & la_list_des_front = t_listFront(im)(1);
|
|
int nb_front_init = la_list_des_front.size(); // la taille initiale
|
|
LaLIST <Front>& lifrLigne_mail = *lifrLigne(im); // pour simplifier
|
|
|
|
// avant de balayer les lignes, on fait une liste des éléments qui contiennent des frontières déjà référencées
|
|
list <const Element* > li_Elem_avec_front;
|
|
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
|
|
for (il = la_list_des_front.begin(); il != ilfin; il++)
|
|
li_Elem_avec_front.push_back((*il).PtEI());
|
|
// on supprime les doublons et on ordonne, c'est pour l'opti des recherches ensuites
|
|
li_Elem_avec_front.sort(); // ordonne
|
|
li_Elem_avec_front.unique(); // supprime les doublons
|
|
|
|
// maintenant on regarde s'il faut ajouter des éléments d'angle mort
|
|
// on va boucler sur les frontières lignes 3D
|
|
LaLIST <Front>::iterator jl,jlfin=lifrLigne_mail.end();
|
|
for (jl = lifrLigne_mail.begin(); jl != jlfin; jl++)
|
|
{ Element * el = (*jl).PtEI();// récup de l'élément
|
|
// on regarde si cet élément ne fait pas partie de la liste d'élément
|
|
// qui contient déjà une frontière
|
|
if (find(li_Elem_avec_front.begin(),li_Elem_avec_front.end(),el) == li_Elem_avec_front.end())
|
|
// on n'a pas trouvé d'élément,
|
|
//on ajoute l'élément front sauf cas particulier
|
|
{// on fait quelques tests pour écarter des cas non recevable
|
|
bool continuer = true; // par défaut
|
|
// si on est en 3D et que l'élément est lui même un élément ligne, ou un
|
|
// élément de surface, il ne constitue pas un angle mort puisqu'il n'y à pas de volume mort associé
|
|
Enum_type_geom enu_type_geom_ele = Type_geom_generique(el->Id_geometrie());
|
|
if ((enu_type_geom_ele == LIGNE) && (enu_type_geom_ele == SURFACE))
|
|
{continuer = false;}
|
|
if (continuer)
|
|
// on doit indiquer qu'il s'agit d'un élément d'angle mort
|
|
// on se sert d'un élément intermédiaire
|
|
{Front inter((*jl));
|
|
inter.Change_angle_mort(1);
|
|
la_list_des_front.push_back(inter);
|
|
};
|
|
}
|
|
};
|
|
int nb_front_fin = la_list_des_front.size(); // la taille finale
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >2 )
|
|
cout << "\n mail. maitre "<<im<<" : "<<(nb_front_fin-nb_front_init)
|
|
<< " frontieres segment pour angle mort pour contact ";
|
|
|
|
}; // fin de la boucle sur les maillages maitres
|
|
}
|
|
else
|
|
{ // cas d'une zone restreinte de contact
|
|
// on va boucler sur les zones définies pour le contact
|
|
//on boucle sur les maillages maitres de t_listFront
|
|
for (int im=1;im<=nbmailMaitre;im++)
|
|
{ LaLIST <Front>& lifrLigne_mail = *lifrLigne(im); // pour simplifier
|
|
// ici on boucle sur les zones restreintes
|
|
int nb_zone_et1 = 1+t_listFront(im).Taille();
|
|
for (int i_zone=1;i_zone < nb_zone_et1;i_zone++)
|
|
{// la liste des front de la zone
|
|
LaLIST_io <Front> & la_list_des_front = t_listFront(im)(i_zone);
|
|
int nb_front_init = la_list_des_front.size(); // la taille initiale
|
|
// avant de balayer les lignes, on fait une liste des éléments relatifs à la zone
|
|
// qui contiennent des frontières déjà référencées
|
|
list <const Element* > li_Elem_avec_front;
|
|
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
|
|
for (il = la_list_des_front.begin(); il != ilfin; il++)
|
|
li_Elem_avec_front.push_back((*il).PtEI());
|
|
// on supprime les doublons et on ordonne, c'est pour l'opti des recherches ensuites
|
|
li_Elem_avec_front.sort(); // ordonne
|
|
li_Elem_avec_front.unique(); // supprime les doublons
|
|
|
|
// maintenant on regarde s'il faut ajouter des éléments d'angle mort
|
|
// on va boucler sur les frontières lignes 3D
|
|
LaLIST <Front>::iterator jl,jlfin=lifrLigne_mail.end();
|
|
for (jl = lifrLigne_mail.begin(); jl != jlfin; jl++)
|
|
{ Element * el = (*jl).PtEI();// récup de l'élément
|
|
// on regarde si cet élément ne fait pas partie de la liste d'élément
|
|
// qui contient déjà une frontière
|
|
if (find(li_Elem_avec_front.begin(),li_Elem_avec_front.end(),el) == li_Elem_avec_front.end())
|
|
// on n'a pas trouvé d'élément,
|
|
//on ajoute l'élément front sauf cas particulier
|
|
{// on fait quelques tests pour écarter des cas non recevable
|
|
bool continuer = true; // par défaut
|
|
// si on est en 3D et que l'élément est lui même un élément ligne, ou un
|
|
// élément de surface, il ne constitue pas un angle mort puisqu'il n'y à pas de volume mort associé
|
|
Enum_type_geom enu_type_geom_ele = Type_geom_generique(el->Id_geometrie());
|
|
if ((enu_type_geom_ele == LIGNE) && (enu_type_geom_ele == SURFACE))
|
|
{continuer = false;}
|
|
if (continuer)
|
|
// on n'a pas trouvé d'élément, on ajoute l'élément front
|
|
// on doit indiquer qu'il s'agit d'un élément d'angle mort
|
|
// on se sert d'un élément intermédiaire
|
|
{Front inter((*jl));
|
|
inter.Change_angle_mort(1);
|
|
la_list_des_front.push_back(inter);
|
|
};
|
|
};
|
|
};
|
|
int nb_front_fin = la_list_des_front.size(); // la taille finale
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >2 )
|
|
cout << "\n mail. maitre "<<im << " : zone de contact: " << i_zone
|
|
<<" : " <<(nb_front_fin-nb_front_init)
|
|
<< " frontieres segment pour angle mort pour contact ";
|
|
|
|
};// fin de la boucle sur les zones
|
|
}; // fin de la boucle sur les maillages maitres de t_listFront
|
|
}; // fin du test avec ou sans zone de contact
|
|
};
|
|
|
|
// 2) === maintenant on s'intéresse aux cas des noeuds frontières + éléments internes
|
|
Tableau <LaLIST <Front>*>& listFrontiere = lesMail.ListFrontiere();
|
|
int ntmail = listFrontiere.Taille(); // nb maxi de maillages
|
|
// on regarde si la zone de contact est restreinte
|
|
if (nom_ref_zone_contact.size() == 0)
|
|
{ // cas d'un contact non restreint
|
|
// cela correspond finalement à une seule zone de contact (cf. Init_contact(..))
|
|
|
|
int ilistfront = 1; // compteur pour le tableau t_listFront
|
|
// on parcours les elements maitres: à cause d'un auto contact
|
|
// éventuelle on peut avoir des maillages esclaves qui jouent le rôle également de
|
|
// maillages maitres
|
|
//on boucle sur les maillages maitres de t_listFront
|
|
for (int jf=ntmail-nbmailMaitre+1;jf<=ntmail;jf++,ilistfront++)
|
|
{ // ici on ne boucle pas sur les zones restreintes car il n'y en n'a pas
|
|
LaLIST_io <Front> & la_list_des_front = t_listFront(ilistfront)(1);
|
|
int nb_front_init = la_list_des_front.size(); // la taille initiale
|
|
// pour continuer il faut: 1) qu'il y a des front, 2) que ces fronts appartiennent au maillage
|
|
if (nb_front_init > 0)
|
|
if ((*la_list_des_front.begin()).NumMail() == jf )
|
|
{
|
|
// on va créer une liste de numéro des noeuds de la zone de frontière concernée
|
|
// et en même temps
|
|
// avant de balayer les noeuds, on fait une liste des éléments relatifs à la zone
|
|
// qui contiennent des frontières déjà référencées
|
|
list <int> num_noe_front;
|
|
list <const Element* > li_Elem_avec_front;
|
|
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
|
|
for (il = la_list_des_front.begin(); il != ilfin; il++)
|
|
{ const Tableau <Noeud *>& tnoe = (*il).Eleme()->TabNoeud_const();
|
|
int nb_noe_et1 = tnoe.Taille();
|
|
for (int m =1;m<nb_noe_et1;m++)
|
|
num_noe_front.push_back(tnoe(m)->Num_noeud());
|
|
li_Elem_avec_front.push_back((*il).PtEI());
|
|
};
|
|
// on ordonne et on supprime les doublons
|
|
num_noe_front.sort(); // ordonne
|
|
num_noe_front.unique(); // suppression des doublons
|
|
li_Elem_avec_front.sort(); // ordonne
|
|
li_Elem_avec_front.unique(); // supprime les doublons
|
|
|
|
// on définit une liste temporaire des nouvelles front d'angle mort créé
|
|
// c'est utilisé pour définir les mitoyens des éléments d'angle morts
|
|
// qui sont apparus avec les angles morts (== les mitoyens angle mort des éléments angle morts !!)
|
|
list <Front *> front_angle_mort;
|
|
|
|
// maintenant on parcours les noeuds contenu dans num_noe_front
|
|
// et on regarde s'il faut ajouter des éléments point d'angle mort
|
|
list <int>::iterator ih,ih_fin=num_noe_front.end();
|
|
for (ih = num_noe_front.begin();ih != ih_fin;ih++)
|
|
{int i_noe = (*ih); // le num du noeud maître que l'on va tester
|
|
Tableau <Noeud *> ttn(1);
|
|
ttn(1)= &(lesMail.Noeud_LesMaille(jf,i_noe)); // récup du pointeur de noeud
|
|
|
|
// récup de la liste pour le noeud i_noe, des éléments qui contient ce noeud : construite avec Init_contact
|
|
const List_io < Element* >& liel = (*indice(jf))(i_noe);
|
|
// on boucle sur chaque élément qui contient le noeud
|
|
List_io < Element* >::const_iterator il,ilfin=liel.end();
|
|
for (il = liel.begin();il != ilfin;il++)
|
|
{const Element* el=(*il); // pour simplifier
|
|
// on regarde si cet élément ne fait pas partie de la liste d'élément
|
|
// qui contient déjà une frontière
|
|
bool trouver = false;
|
|
list <const Element* >::const_iterator ikl,iklfin=li_Elem_avec_front.end();
|
|
for (ikl = li_Elem_avec_front.begin();ikl != iklfin; ikl++)
|
|
{if (((*ikl)->Num_elt_const() == el->Num_elt_const()) && ((*ikl)->Num_maillage() == el->Num_maillage()))
|
|
{trouver= true; break;}
|
|
};
|
|
if (!trouver)
|
|
{// on n'a pas trouvé d'élément,
|
|
// 1. on récup le num local EF du noeud
|
|
int nb_noeu_el_et_1 = 1+el->Nombre_noeud(); // le nombre de noeud de l'élément
|
|
int num_noe_local = 0;
|
|
for (int k =1;k<nb_noeu_el_et_1;k++)
|
|
if (el->Num_noeud(k) == ttn(1)->Num_noeud())
|
|
{num_noe_local=k; break;};
|
|
// 2. on récupère la frontière noeud correspondante en forçant une création éventuelle
|
|
// on passe par l'intermédiaire de lesMail pour pouvoir modifier l'élément
|
|
// car c'est l'élément qui stocke et gère la frontière
|
|
Element& elem_non_const = lesMail.Element_LesMaille(el->Num_maillage(), el->Num_elt_const());
|
|
// on fait quelques tests pour écarter des cas non recevable
|
|
bool continuer = true; // par défaut
|
|
// a) si on est en 2D axi et que l'élément est un élément noeud ou un élément ligne, cela veut dire
|
|
// qu'il génére par rotation en 3D : une ligne ou une surface, or lignes ou surfaces n'intègrent pas
|
|
// d'élément de contact d'angle mort puisqu'il n'y à pas de volume mort associé
|
|
Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie());
|
|
if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE)))
|
|
{continuer = false;}
|
|
// b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
|
|
else if ((ParaGlob::Dimension() == 3)
|
|
&& ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE))
|
|
)
|
|
{continuer = false;}
|
|
// on continue sauf cas particulier
|
|
if (continuer)
|
|
{// 3. on crée l'élément de frontière ad hoc
|
|
ElFrontiere* const elfpoint = elem_non_const.Frontiere_points(num_noe_local,true);
|
|
// ramene le numero de la frontière passée en argument si elle existe actuellement au niveau de l'élément
|
|
// sinon ramène 0
|
|
// ramene également type_front: qui indique le type de frontière: POINT_G, LIGNE ou SURFACE
|
|
// c'est une méthode très longue, a utiliser avec précaution
|
|
Enum_type_geom type_front;
|
|
int num_front = el->Num_frontiere(*elfpoint,type_front);
|
|
// 4. on crée l'élément front ad hoc et on l'ajoute à la liste
|
|
int angle_mort = 1;
|
|
la_list_des_front.push_front(Front(*elfpoint,&elem_non_const,num_front,angle_mort));
|
|
LaLIST_io <Front>::iterator iik = la_list_des_front.begin(); // récup de l'iterator
|
|
// on met à jour les frontières mitoyennes
|
|
int num_noeud = ttn(1)->Num_noeud(); // le num global du noeud
|
|
// récup de la liste des frontières initiales contenant le noeud
|
|
list <Front*> & t_liFront_noeud_ijk = t_liFront_noeud(ilistfront)(1)(num_noeud);
|
|
list <Front*>::iterator km,kmfin=t_liFront_noeud_ijk.end();
|
|
for (km=t_liFront_noeud_ijk.begin();km != kmfin;km++)
|
|
{(*km)->AjoutMitoyen(&(*iik));// ajout frontière pour la frontière initiale
|
|
(*iik).AjoutMitoyen(*km); // ajout frontière pour la nouvelle frontière d'angle mort
|
|
};
|
|
// on sauvegarde le nouvelle front dans une liste spécifique
|
|
front_angle_mort.push_front(&(*iik));
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >4 )
|
|
{ cout << "\n ajout front point: noeud "<<el->Num_noeud(num_noe_local)
|
|
<< " mail: " << jf //<< " zone "
|
|
<< " element: "<<el->Num_elt_const() ;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
int nb_front_fin = la_list_des_front.size(); // la taille finale
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >2 )
|
|
cout << "\n ajout angle mort pour contact: mail. maitre "<< jf <<" : "<<(nb_front_fin-nb_front_init)
|
|
<< " frontieres point ";
|
|
|
|
#ifdef MISE_AU_POINT
|
|
// petite vérif en passant
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if ((nb_front_fin-nb_front_init) != front_angle_mort.size())
|
|
{cout << "\n *** erreur dans la definition des elements point d'angle mort "
|
|
<< " on a deux listes qui les representent mais qui n'ont pas la meme taille "
|
|
<< (nb_front_fin-nb_front_init) << " et " << front_angle_mort.size()
|
|
<< "\n LesContacts::ElementAngleMort(..";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
|
|
// on utilise front_angle_mort pour définir les mitoyens angle mort des éléments angle morts
|
|
list <Front *>::iterator ag,agfin=front_angle_mort.end();
|
|
for (ag=front_angle_mort.begin();ag != agfin; ag++)
|
|
{list <Front *>::iterator bg;
|
|
bg = ag; bg++;
|
|
// on utilise deux boucles imbriquées
|
|
for ( ; bg!= agfin ; bg++)
|
|
{const Tableau <Noeud *>& tan = (*ag)->Eleme()->TabNoeud_const();
|
|
const Tableau <Noeud *>& tbn = (*bg)->Eleme()->TabNoeud_const();
|
|
// normalement c'est des FrontPoinF, donc il n'y a qu'un seul noeud frontière
|
|
if (tan(1)->Num_noeud() == tbn(1)->Num_noeud())
|
|
// les deux éléments FrontPoinF partage le même noeud,
|
|
// on met à jour les mitoyens
|
|
{ (*ag)->AjoutMitoyen((*bg));
|
|
(*bg)->AjoutMitoyen((*ag));
|
|
};
|
|
};
|
|
};
|
|
|
|
}; // fin du test if (nb_front_init > 0) et if ((*la_list_des_front.begin()).NumMail() == jf )
|
|
|
|
}; // fin de la boucle sur les maillages maitres de t_listFront
|
|
}
|
|
else
|
|
{ // cas d'une zone restreinte de contact
|
|
// on va boucler sur les zones définies pour le contact
|
|
|
|
int ilistfront = 1; // compteur pour le tableau t_listFront
|
|
// on parcours les elements maitres: à cause d'un auto contact
|
|
// éventuelle on peut avoir des maillages esclaves qui jouent le rôle également de
|
|
// maillages maitres
|
|
//on boucle sur les maillages maitres de t_listFront
|
|
for (int jf=ntmail-nbmailMaitre+1;jf<=ntmail;jf++,ilistfront++)
|
|
{ // ici on boucle sur les zones restreintes
|
|
int nb_zone_et1 = 1+t_listFront(ilistfront).Taille();
|
|
for (int i_zone=1;i_zone < nb_zone_et1;i_zone++)
|
|
{// la liste des front de la zone
|
|
LaLIST_io <Front> & la_list_des_front = t_listFront(ilistfront)(i_zone);
|
|
int nb_front_init = la_list_des_front.size(); // la taille initiale
|
|
// pour continuer il faut: 1) qu'il y a des front, 2) que ces fronts appartiennent au maillage
|
|
if (nb_front_init > 0)
|
|
if ((*la_list_des_front.begin()).NumMail() == jf )
|
|
{
|
|
// on va créer une liste de numéro des noeuds de la zone de frontière concernée
|
|
// et en même temps
|
|
// avant de balayer les noeuds, on fait une liste des éléments relatifs à la zone
|
|
// qui contiennent des frontières déjà référencées
|
|
list <int> num_noe_front;
|
|
list <const Element* > li_Elem_avec_front;
|
|
LaLIST_io <Front>::iterator il,ilfin = la_list_des_front.end();
|
|
for (il = la_list_des_front.begin(); il != ilfin; il++)
|
|
{ const Tableau <Noeud *>& tnoe = (*il).Eleme()->TabNoeud_const();
|
|
int nb_noe_et1 = tnoe.Taille();
|
|
for (int m =1;m<nb_noe_et1;m++)
|
|
num_noe_front.push_back(tnoe(m)->Num_noeud());
|
|
li_Elem_avec_front.push_back((*il).PtEI());
|
|
};
|
|
// on ordonne et on supprime les doublons
|
|
num_noe_front.sort(); // ordonne
|
|
num_noe_front.unique(); // suppression des doublons
|
|
li_Elem_avec_front.sort(); // ordonne
|
|
li_Elem_avec_front.unique(); // supprime les doublons
|
|
|
|
// on définit une liste temporaire des nouvelles front d'angle mort créé
|
|
// c'est utilisé pour définir les mitoyens des éléments d'angle morts
|
|
// qui sont apparus avec les angles morts (== les mitoyens angle mort des éléments angle morts !!)
|
|
list <Front *> front_angle_mort;
|
|
|
|
// maintenant on parcours les noeuds contenu dans num_noe_front
|
|
// et on regarde s'il faut ajouter des éléments point d'angle mort
|
|
list <int>::iterator ih,ih_fin=num_noe_front.end();
|
|
for (ih = num_noe_front.begin();ih != ih_fin;ih++)
|
|
{int i_noe = (*ih); // le num du noeud maître que l'on va tester
|
|
Tableau <Noeud *> ttn(1);
|
|
ttn(1)= &(lesMail.Noeud_LesMaille(jf,i_noe)); // récup du pointeur de noeud
|
|
|
|
// récup de la liste pour le noeud i_noe, des éléments qui contient ce noeud : construite avec Init_contact
|
|
const List_io < Element* >& liel = (*indice(jf))(i_noe);
|
|
// on boucle sur chaque élément qui contient le noeud
|
|
List_io < Element* >::const_iterator il,ilfin=liel.end();
|
|
for (il = liel.begin();il != ilfin;il++)
|
|
{const Element* el=(*il); // pour simplifier
|
|
// on regarde si cet élément ne fait pas partie de la liste d'élément
|
|
// qui contient déjà une frontière
|
|
bool trouver = false;
|
|
list <const Element* >::const_iterator ikl,iklfin=li_Elem_avec_front.end();
|
|
for (ikl = li_Elem_avec_front.begin();ikl != iklfin; ikl++)
|
|
{if (((*ikl)->Num_elt_const() == el->Num_elt_const()) && ((*ikl)->Num_maillage() == el->Num_maillage()))
|
|
{trouver= true; break;}
|
|
};
|
|
if (!trouver)
|
|
{// on n'a pas trouvé d'élément,
|
|
// 1. on récup le num local EF du noeud
|
|
int nb_noeu_el_et_1 = 1+el->Nombre_noeud(); // le nombre de noeud de l'élément
|
|
int num_noe_local = 0;
|
|
for (int k =1;k<nb_noeu_el_et_1;k++)
|
|
if (el->Num_noeud(k) == ttn(1)->Num_noeud())
|
|
{num_noe_local=k; break;};
|
|
// 2. on récupère la frontière noeud correspondante en forçant une création éventuelle
|
|
// on passe par l'intermédiaire de lesMail pour pouvoir modifier l'élément
|
|
// car c'est l'élément qui stocke et gère la frontière
|
|
Element& elem_non_const = lesMail.Element_LesMaille(el->Num_maillage(), el->Num_elt_const());
|
|
// on fait quelques tests pour écarter des cas non recevable
|
|
bool continuer = true; // par défaut
|
|
// a) si on est en 2D axi et que l'élément est un élément noeud ou un élément ligne, cela veut dire
|
|
// qu'il génére par rotation en 3D : une ligne ou une surface, or lignes ou surfaces n'intègrent pas
|
|
// d'élément de contact d'angle mort puisqu'il n'y à pas de volume mort associé
|
|
Enum_type_geom enu_type_geom_ele = Type_geom_generique(elem_non_const.Id_geometrie());
|
|
if (ParaGlob::AxiSymetrie() && ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE)))
|
|
{continuer = false;}
|
|
// b) si on est en 3D et que l'élément est un élément noeud, ou ligne, ou surface, même sentence
|
|
else if ((ParaGlob::Dimension() == 3)
|
|
&& ((enu_type_geom_ele == POINT_G) || (enu_type_geom_ele == LIGNE) || (enu_type_geom_ele == SURFACE))
|
|
)
|
|
{continuer = false;}
|
|
// on continue sauf cas particulier
|
|
if (continuer)
|
|
{// 3. on crée l'élément de frontière ad hoc
|
|
ElFrontiere* const elfpoint = elem_non_const.Frontiere_points(num_noe_local,true);
|
|
// ramene le numero de la frontière passée en argument si elle existe actuellement au niveau de l'élément
|
|
// sinon ramène 0
|
|
// ramene également type_front: qui indique le type de frontière: POINT_G, LIGNE ou SURFACE
|
|
// c'est une méthode très longue, a utiliser avec précaution
|
|
Enum_type_geom type_front;
|
|
int num_front = el->Num_frontiere(*elfpoint,type_front);
|
|
// 4. on crée l'élément front ad hoc et on l'ajoute à la liste
|
|
int angle_mort = 1;
|
|
la_list_des_front.push_front(Front(*elfpoint,&elem_non_const,num_front,angle_mort));
|
|
LaLIST_io <Front>::iterator iik = la_list_des_front.begin(); // récup de l'iterator
|
|
// on met à jour les frontières mitoyennes
|
|
// // t_liFront_noeud(i)(j)(k) : la liste des frontières initiales qui contiennent le noeud k de la zone j du maillage i
|
|
// Tableau < Tableau < Tableau < list <Front*> > > > t_liFront_noeud;
|
|
int num_noeud = ttn(1)->Num_noeud(); // le num global du noeud
|
|
// récup de la liste des frontières initiales contenant le noeud
|
|
list <Front*> & t_liFront_noeud_ijk = t_liFront_noeud(ilistfront)(i_zone)(num_noeud);
|
|
list <Front*>::iterator km,kmfin=t_liFront_noeud_ijk.end();
|
|
for (km=t_liFront_noeud_ijk.begin();km != kmfin;km++)
|
|
{(*km)->AjoutMitoyen(&(*iik));// ajout frontière pour la frontière initiale
|
|
(*iik).AjoutMitoyen(*km); // ajout frontière pour la nouvelle frontière d'angle mort
|
|
};
|
|
// on sauvegarde le nouvelle front dans une liste spécifique
|
|
front_angle_mort.push_front(&(*iik));
|
|
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >4 )
|
|
{ cout << "\n ajout front point: noeud "<<el->Num_noeud(num_noe_local)
|
|
<< " mail: " << jf << " zone "<< i_zone
|
|
<< " element: "<<el->Num_elt_const() ;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
int nb_front_fin = la_list_des_front.size(); // la taille finale
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >2 )
|
|
cout << "\n ajout angle mort pour contact: mail. maitre "<<jf << " : zone de contact: " << i_zone
|
|
<<" : " <<(nb_front_fin-nb_front_init)
|
|
<< " frontieres point ";
|
|
|
|
#ifdef MISE_AU_POINT
|
|
// petite vérif en passant
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if ((nb_front_fin-nb_front_init) != front_angle_mort.size())
|
|
{cout << "\n *** erreur dans la definition des elements point d'angle mort "
|
|
<< " on a deux listes qui les representent mais qui n'ont pas la meme taille "
|
|
<< (nb_front_fin-nb_front_init) << " et " << front_angle_mort.size()
|
|
<< "\n LesContacts::ElementAngleMort(..";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
|
|
// on utilise front_angle_mort pour définir les mitoyens angle mort des éléments angle morts
|
|
list <Front *>::iterator ag,agfin=front_angle_mort.end();
|
|
for (ag=front_angle_mort.begin();ag != agfin; ag++)
|
|
{list <Front *>::iterator bg;
|
|
bg = ag; bg++;
|
|
// on utilise deux boucles imbriquées
|
|
for ( ; bg!= agfin ; bg++)
|
|
{const Tableau <Noeud *>& tan = (*ag)->Eleme()->TabNoeud_const();
|
|
const Tableau <Noeud *>& tbn = (*bg)->Eleme()->TabNoeud_const();
|
|
// normalement c'est des FrontPoinF, donc il n'y a qu'un seul noeud frontière
|
|
if (tan(1)->Num_noeud() == tbn(1)->Num_noeud())
|
|
// les deux éléments FrontPoinF partage le même noeud,
|
|
// on met à jour les mitoyens
|
|
{ (*ag)->AjoutMitoyen((*bg));
|
|
(*bg)->AjoutMitoyen((*ag));
|
|
};
|
|
};
|
|
};
|
|
#ifdef UTILISATION_MPI
|
|
if (ParaGlob::Monde()->rank() == 0)
|
|
#endif
|
|
if (niveau_commentaire_lescontacts >7 )
|
|
{ cout << "\n liste finale des elements angle mort "
|
|
<< " mail: " << jf << " zone "<< i_zone;
|
|
for (ag=front_angle_mort.begin();ag != agfin; ag++)
|
|
(*ag)->Affiche();
|
|
};
|
|
|
|
}; // fin du test if (nb_front_init > 0) et if ((*la_list_des_front.begin()).NumMail() == jf )
|
|
|
|
};// fin de la boucle sur les zones
|
|
}; // fin de la boucle sur les maillages maitres de t_listFront
|
|
}; // fin du test avec ou sans zone de contact
|
|
|
|
|
|
};
|
|
|
|
// init éventuel du pilotage par fct nD du niveau de commentaire
|
|
void LesContacts::Init_fct_niveau_commentaire()
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
int proc_en_cours = ParaGlob::Monde()->rank();
|
|
#endif
|
|
string nom_fct = ParaGlob::param->ParaAlgoControleActifs().Fct_niveau_commentaire_LesContact();
|
|
if (nom_fct != "_")
|
|
{// on va récupérer la fonction
|
|
if (sauve_lesFonctionsnD->Existe(nom_fct))
|
|
{ Fonction_nD * pt_fonct = sauve_lesFonctionsnD->Trouve(nom_fct);
|
|
// sauvegarde
|
|
fct_niveau_commentaire = pt_fonct;
|
|
}
|
|
else
|
|
{
|
|
#ifdef UTILISATION_MPI
|
|
cout << "\n proc " << proc_en_cours
|
|
#else
|
|
cout << "\n"
|
|
#endif
|
|
<< " *** erreur dans la definition de la fonction nD de pilotage du "
|
|
<< " niveau de commentaire en contact, le nom : " << nom_fct
|
|
<< " ne correspond pas a une fonction nD existante !! ";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
else
|
|
{fct_niveau_commentaire=NULL;};
|
|
// initialisation des conteneurs de la fonction nD
|
|
if (fct_niveau_commentaire != NULL)
|
|
Definition_conteneurs_fctnD_TypeQuelconque
|
|
(fct_niveau_commentaire
|
|
,tqi_fct_nD_niveau_commentaire,tqi_const_fct_nD_niveau_commentaire
|
|
,t_num_ordre_fct_nD_niveau_commentaire);
|
|
};
|
|
|
|
|
|
// définition des conteneurs static des TypeQuelconque
|
|
void LesContacts::Definition_conteneurs_fctnD_TypeQuelconque
|
|
(Fonction_nD * pt_fonct,Tableau < TypeQuelconque * >& tqi,Tableau < const TypeQuelconque * >& tqii
|
|
,Tableau <int>& t_num_ordre )
|
|
{// on commence par récupérer le conteneurs des grandeurs à fournir
|
|
const Tableau <EnumTypeQuelconque>& tab_queconque = pt_fonct->Tab_enu_quelconque();
|
|
// on dimensionne
|
|
int tail_tab_queconque = tab_queconque.Taille();
|
|
tqi.Change_taille(tail_tab_queconque);
|
|
t_num_ordre.Change_taille(tail_tab_queconque);
|
|
Grandeur_scalaire_entier grand_courant_entier(0); // par défaut pour la création des conteneurs quelconques
|
|
Grandeur_scalaire_double grand_courant_double(0.); // par défaut pour la création des conteneurs quelconques
|
|
// grandeurs de travail
|
|
int dim = ParaGlob::Dimension();
|
|
Coordonnee inter(dim);
|
|
Grandeur_coordonnee grand_coor_courant(inter);
|
|
|
|
// on va balayer les grandeurs quelconques
|
|
for (int i=1;i<= tail_tab_queconque;i++)
|
|
{ bool trouver = false;
|
|
EnumTypeQuelconque enu = tab_queconque(i);
|
|
|
|
tqi(i) = NULL; // init
|
|
t_num_ordre(i) = 1; //***** pour l'instant uniquement la première coordonnée s'il s'agit d'un Coordonnee
|
|
// *** à abonder par la suite !!!!!!!!!!
|
|
|
|
// on regarde tout d'abord les grandeurs spécifiques
|
|
switch (enu)
|
|
{ // il y a des grandeurs vectorielles qui pour l'instant ne sont pas prises en compte
|
|
// cf. fct nD
|
|
// NORMALE_CONTACT, GLISSEMENT_CONTACT ,PENETRATION_CONTACT,FORCE_CONTACT,
|
|
case CONTACT_NB_DECOL:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_NB_DECOL,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_PENALISATION_N:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_PENALISATION_N,X1,grand_courant_double);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_PENALISATION_T:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_PENALISATION_T,X1,grand_courant_double);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_NB_PENET:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_NB_PENET,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_CAS_SOLIDE:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_CAS_SOLIDE,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_GLISSE_ELAS:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_ENERG_GLISSE_ELAS,X1,grand_courant_double);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_GLISSE_PLAS:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_ENERG_GLISSE_PLAS,X1,grand_courant_double);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_GLISSE_VISQ:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_ENERG_GLISSE_VISQ,X1,grand_courant_double);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_ENERG_PENAL:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_ENERG_PENAL,X1,grand_courant_double);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NOEUD_PROJECTILE_EN_CONTACT:
|
|
{ tqi(i) = new TypeQuelconque(NOEUD_PROJECTILE_EN_CONTACT,X1,grand_courant_double);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NOEUD_FACETTE_EN_CONTACT:
|
|
{ tqi(i) = new TypeQuelconque(NOEUD_FACETTE_EN_CONTACT,X1,grand_courant_double);
|
|
// Grandeur_scalaire_double& gr= *((Grandeur_scalaire_double*) ((*tqi(i)).Grandeur_pointee()));
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NUM_NOEUD:
|
|
{ tqi(i) = new TypeQuelconque(NUM_NOEUD,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NUM_MAIL_NOEUD:
|
|
{ tqi(i) = new TypeQuelconque(NUM_MAIL_NOEUD,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case POSITION_GEOMETRIQUE:
|
|
{tqi(i) = new TypeQuelconque(POSITION_GEOMETRIQUE,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case POSITION_GEOMETRIQUE_t:
|
|
{tqi(i) = new TypeQuelconque(POSITION_GEOMETRIQUE_t,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case POSITION_GEOMETRIQUE_t0:
|
|
{tqi(i) = new TypeQuelconque(POSITION_GEOMETRIQUE_t0,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
// *** pour l'instant la suite n'est pas opérationelle car il s'agit de vecteur
|
|
// dont les composantes n'ont pas d'équivalent en ddl_enum_etendu
|
|
// il faudrait les définir si on veut pouvoir s'en servir
|
|
case PENETRATION_CONTACT:
|
|
{tqi(i) = new TypeQuelconque(PENETRATION_CONTACT,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case PENETRATION_CONTACT_T:
|
|
{tqi(i) = new TypeQuelconque(PENETRATION_CONTACT_T,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case GLISSEMENT_CONTACT:
|
|
{tqi(i) = new TypeQuelconque(GLISSEMENT_CONTACT,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case GLISSEMENT_CONTACT_T:
|
|
{tqi(i) = new TypeQuelconque(GLISSEMENT_CONTACT_T,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NORMALE_CONTACT:
|
|
{tqi(i) = new TypeQuelconque(NORMALE_CONTACT,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case FORCE_CONTACT:
|
|
{tqi(i) = new TypeQuelconque(FORCE_CONTACT,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case FORCE_CONTACT_T:
|
|
{tqi(i) = new TypeQuelconque(POSITION_GEOMETRIQUE,X1,grand_coor_courant);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case CONTACT_COLLANT:
|
|
{ tqi(i) = new TypeQuelconque(CONTACT_COLLANT,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NUM_ZONE_CONTACT:
|
|
{ tqi(i) = new TypeQuelconque(NUM_ZONE_CONTACT,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NUM_ELEMENT:
|
|
{ tqi(i) = new TypeQuelconque(NUM_ELEMENT,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
case NUM_MAIL_ELEM:
|
|
{ tqi(i) = new TypeQuelconque(NUM_MAIL_ELEM,X1,grand_courant_entier);
|
|
trouver = true;
|
|
break;
|
|
}
|
|
//*** fin
|
|
|
|
default:
|
|
trouver = false;
|
|
break;
|
|
};
|
|
|
|
// si on n'a rien trouvé
|
|
if (!trouver)
|
|
{cout << "\n erreur***: la grandeur " << NomTypeQuelconque(enu)
|
|
<< " n'existe pas les elements de contact "
|
|
<< " la fonction nD " << pt_fonct->NomFonction()
|
|
<< " ne peut pas etre renseignee "
|
|
<< "\n ElContact::Fct_nD_contact::Definition_conteneurs_static_TypeQuelconque(.." << flush;
|
|
pt_fonct->Affiche();
|
|
Sortie(1);
|
|
};
|
|
|
|
};
|
|
// tableau de const intermédiaire pour l'appel de la fonction
|
|
tqii.Change_taille(tail_tab_queconque);
|
|
for (int i=1;i<= tail_tab_queconque;i++)
|
|
tqii(i) = tqi(i);
|
|
};
|
|
|
|
|
|
// calcul d'une fonction nD relative à des données de LesContacts
|
|
double LesContacts::Valeur_fct_nD_LesContacts
|
|
(Fonction_nD * pt_fonct,list<TypeQuelconque>* li
|
|
,Tableau < TypeQuelconque * >& tqi
|
|
,Tableau < const TypeQuelconque * >& tqii
|
|
,Tableau <int>& t_num_ordre) const
|
|
{ // on commence par récupérer les conteneurs des grandeurs à fournir
|
|
List_io <Ddl_enum_etendu>& li_enu_scal = pt_fonct->Li_enu_etendu_scalaire();
|
|
List_io <TypeQuelconque >& li_quelc = pt_fonct->Li_equi_Quel_evolue();
|
|
const Tableau <EnumTypeQuelconque>& tab_queconque = pt_fonct->Tab_enu_quelconque();
|
|
|
|
|
|
// on passe en revue les grandeurs pour les renseigner
|
|
|
|
// --- on balaie maintenant la liste des grandeurs à sortir
|
|
// 1) tout d'abord les ddl étendues
|
|
// pour l'instant cette liste doit-être vide
|
|
if (li_enu_scal.size() != 0)
|
|
{ cout << "\n *** erreur : LesContacts::Valeur_fct_nD_LesContacts "
|
|
<< " la fonction nD associe a l'affichage pour LesContacts ne doit pas "
|
|
<< " inclure des Ddl_enum_etendu !! changer la fonction ";
|
|
Sortie(1);
|
|
}
|
|
Tableau <double> val_ddl_enum (li_enu_scal.size()); // init par défaut
|
|
|
|
|
|
// 2) puis les grandeurs quelconques évoluées
|
|
{List_io<TypeQuelconque>::iterator ipq,ipqfin=li_quelc.end();
|
|
for (ipq=li_quelc.begin();ipq!=ipqfin;ipq++)
|
|
{ bool trouver = false;
|
|
TypeQuelconque& enuTQ = (*ipq); // pour simplifier
|
|
const TypeQuelconque_enum_etendu& en_ET_TQ = enuTQ.EnuTypeQuelconque().EnumTQ();
|
|
|
|
// si li est non nulle, li indique spécifiquement quelle grandeur on veut sortir
|
|
if (li != NULL)
|
|
{ // on va balayer la liste et voir si une grandeur correspond
|
|
list<TypeQuelconque>::iterator ili,ilifin = li->end();
|
|
for (ili = li->begin();ili != ilifin; ili++)
|
|
{ TypeQuelconque& enuTQ_li = (*ili); // pour simplifier
|
|
const TypeQuelconque_enum_etendu& en_ET_TQ_li = enuTQ_li.EnuTypeQuelconque().EnumTQ();
|
|
if (en_ET_TQ_li == en_ET_TQ ) // cas ou on a trouvé la grandeur demandée
|
|
{ // pour l'instant seules les grandeurs scalaires entières sont admises
|
|
Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) ((*ipq).Grandeur_pointee()));
|
|
Grandeur_scalaire_entier& gr_li= *((Grandeur_scalaire_entier*) ((*ili).Grandeur_pointee()));
|
|
(*gr.ConteneurEntier()) = (*gr_li.ConteneurEntier());
|
|
trouver = true;
|
|
};
|
|
};
|
|
};
|
|
if (!trouver) // si non existant, init par défaut
|
|
(*ipq).Grandeur_pointee()->InitParDefaut();
|
|
};
|
|
};
|
|
|
|
// 3) et enfin les grandeurs quelconques:
|
|
// >>> en fait même topo que pour la liste
|
|
// les conteneurs sont normalement déjà bien dimensionné
|
|
int tail_tab_queconque = tab_queconque.Taille();
|
|
|
|
// on va balayer les grandeurs quelconques
|
|
for (int i=1;i<= tail_tab_queconque;i++)
|
|
{ bool trouver = false;
|
|
EnumTypeQuelconque enu = tab_queconque(i);
|
|
|
|
// si li est non nulle, li indique spécifiquement quelle grandeur on veut sortir
|
|
if (li != NULL)
|
|
{ // on va balayer la liste et voir si une grandeur correspond
|
|
list<TypeQuelconque>::iterator ili,ilifin = li->end();
|
|
for (ili = li->begin();ili != ilifin; ili++)
|
|
{ TypeQuelconque& enuTQ_li = (*ili); // pour simplifier
|
|
EnumTypeQuelconque en_ET_TQ_li = enuTQ_li.EnuTypeQuelconque().EnumTQ();
|
|
if (en_ET_TQ_li == enu ) // cas ou on a trouvé la grandeur demandée
|
|
{ // pour l'instant seules les grandeurs scalaires entières sont admises
|
|
Grandeur_scalaire_entier& gr= *((Grandeur_scalaire_entier*) ((*tqi(i)).Grandeur_pointee()));
|
|
Grandeur_scalaire_entier& gr_li= *((Grandeur_scalaire_entier*) ((*ili).Grandeur_pointee()));
|
|
(*gr.ConteneurEntier()) = (*gr_li.ConteneurEntier());
|
|
trouver = true;
|
|
};
|
|
};
|
|
};
|
|
if (!trouver) // si non existant, init par défaut
|
|
(*tqi_fct_nD_niveau_commentaire(i)).Grandeur_pointee()->InitParDefaut();
|
|
|
|
};
|
|
// tqii pointe aux mêmes endroit que tqi mais est déclaré en const ...
|
|
// calcul de la valeur et retour dans tab_ret
|
|
Tableau <double> & tab_val = pt_fonct->Valeur_FnD_Evoluee(&val_ddl_enum,&li_enu_scal,&li_quelc,&(tqii),&t_num_ordre);
|
|
|
|
#ifdef MISE_AU_POINT
|
|
if (tab_val.Taille() != 1)
|
|
{ cout << "\nErreur : la fonction nD " << pt_fonct->NomFonction()
|
|
<< " doit calculer un scalaire or le tableau de retour est de taille "
|
|
<< tab_val.Taille() << " ce n'est pas normal !\n" << flush;
|
|
if (Permet_affichage() > 2 )
|
|
cout << "\n LesContacts::Valeur_fct_nD_LesContacts(... \n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
// on récupère le premier élément du tableau uniquement
|
|
return tab_val(1);
|
|
};
|
|
|
|
|
|
|