Herezh_dev/herezh_pp/Maillage/DdlElement.cc

329 lines
12 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-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "DdlElement.h"
// CONSTRUCTEURS :
// par defaut
DdlElement::DdlElement () :
te(),nbddl(0),tab_enum_famille() {};
// definition du tableau pour n noeuds vide
DdlElement::DdlElement (int n) :
te(n),nbddl(0),tab_enum_famille()
{ };
// definition du tableau pour n noeuds et m ddl par noeud
// utile lorsque tous les noeuds ont le meme nombre de ddl
// par contre ici aucun ddl n'est encore défini
DdlElement::DdlElement (int n, int m) :
te(n),nbddl(n*m),tab_enum_famille()
{ for (int i=1; i<= n;i++)
{ Tableau <Enum_ddl>& tb=te(i).tb;
tb.Change_taille (m);
for (int j=1;j<=m;j++)
tb(j)=NU_DDL;
};
// def du nombre des types particuliers de ddl, ici il s'agit de NU_DDL
Calcul_NbDdl_typer();
};
// definition du tableau pour n noeuds et un nombre de ddl par noeud
// stocke dans le tableau mddl qui doit avoir la dimension n
// par contre ici aucun ddl n'est encore défini
DdlElement::DdlElement (int n,const Tableau <int>& mddl) :
te(n),tab_enum_famille()
{ if (mddl.Taille() == n)
for (int i=1; i<= n;i++)
{ Tableau <Enum_ddl>& tb=te(i).tb;
int m = mddl(i);
tb.Change_taille (m);
for (int j=1;j<=m;j++)
tb(j)=NU_DDL;
}
else
{ cout << "\n erreur de dimension pour le tableau mddl, il doit avoir la ";
cout << " dimension : " << n << ", alors qu\'il a la dimension : "
<< mddl.Taille() << "\nDdlElement (int n, Tableau <int> mddl)" << endl;
Sortie (1);
}
// def du nombre total et des types particuliers de ddl
Calcul_NbDdl(); Calcul_NbDdl_typer();
};
// definition du tableau pour n noeuds et une meme liste de ddl pour chaque
// noeud identique au second argument
DdlElement::DdlElement (int n, DdlNoeudElement d) :
te(n,d),nbddl(n * d.tb.Taille()),tab_enum_famille()
{ // def du nombre total et des types particuliers de ddl
Calcul_NbDdl(); Calcul_NbDdl_typer();
};
DdlElement::DdlElement (const DdlElement& a) :
te(a.te),nbddl(a.nbddl),tab_enum_famille(a.tab_enum_famille)
{}; // de copie
// DESTRUCTEUR :
DdlElement::~DdlElement () {};
// acces en modification au ddl j du noeud i
void DdlElement::Change_Enum(int i,int j,const Enum_ddl enu)
{tab_enum_famille[PremierDdlFamille((te(i)).tb(j))]--;
(te(i)).tb(j) = enu;
tab_enum_famille[PremierDdlFamille(enu)]++;
};
// nombre de ddl du noeudElement i contenu
int DdlElement::NbDdl(int i) const
{ return (te(i)).tb.Taille();};
// change la dimension du tableau de ddl pour n noeuds et m ddl par noeud
//dans le cas ou tous les noeuds ont le meme nombre de ddl
// si la nouvelle taille est plus petite: suppression
// si la nouvelle dimension est plus grande on met les ddl suplémentaires à NU_DDL
void DdlElement::Change_taille(int n,int m)
{ int oldTaille = te.Taille();
te.Change_taille(n);
int deltataille = n-oldTaille;
if (deltataille > 0)
{ // cas où on augmente la taille
// 1) on traite différemment les anciens ddl et les nouveaux
for (int i=1;i<=oldTaille;i++)
{ Tableau <Enum_ddl>& tb=te(i).tb;
int otaille = tb.Taille();
if (m<=otaille)
{// on supprime sans pb
tb.Change_taille(m);
}
else // on augmente avec des ddl NU_DDL
{tb.Change_taille(m);
for (int j=otaille+1;j<=m;j++)
tb(j)=NU_DDL;
};
};
// 2) les nouveaux DdlNoeudElement sont mis à NU_DDL
for (int i1=oldTaille+1;i1<= n;i1++)
{ Tableau <Enum_ddl>& tb=te(i1).tb;
for (int j1=1;j1<=m;j1++)
tb(j1)=NU_DDL;
};
}
else // si on diminue
{ for (int i=1;i<=oldTaille;i++)
{ Tableau <Enum_ddl>& tb=te(i).tb;
int otaille = tb.Taille();
if (m<=otaille)
{// on supprime sans pb
tb.Change_taille(m);
}
else // on augmente avec des ddl NU_DDL
{tb.Change_taille(m);
for (int j=otaille+1;j<=m;j++)
tb(j)=NU_DDL;
};
};
};
nbddl = n*m;
Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type
};
// change la dimension du tableau de ddl pour n noeuds et un nombre de ddl par noeud
// stocke dans le tableau mddl qui doit avoir la dimension n
// si la nouvelle taille est plus petite: suppression
// si la nouvelle dimension est plus grande on met les ddl suplémentaires à NU_DDL
void DdlElement::Change_taille(int n,Tableau <int> mddl)
{ int oldTaille = te.Taille();
te.Change_taille(n);
nbddl = 0;
if (mddl.Taille() == n)
{int deltataille = n-oldTaille;
if (deltataille > 0)
{ // cas où on augmente la taille
// 1) on traite différemment les anciens ddl et les nouveaux
for (int i=1;i<=oldTaille;i++)
{ Tableau <Enum_ddl>& tb=te(i).tb;
int otaille = tb.Taille();
int m = mddl(i);nbddl += m;
if (m<=otaille)
{// on supprime sans pb
tb.Change_taille(m);
}
else // on augmente avec des ddl NU_DDL
{tb.Change_taille(m);
for (int j=otaille+1;j<=m;j++)
tb(j)=NU_DDL;
};
};
// 2) les nouveaux DdlNoeudElement sont mis à NU_DDL
for (int i1=oldTaille+1;i1<= n;i1++)
{ Tableau <Enum_ddl>& tb=te(i1).tb;
int m = mddl(i1);nbddl += m;
for (int j1=1;j1<=m;j1++)
tb(j1)=NU_DDL;
};
}
else // si on diminue
{ for (int i=1;i<=oldTaille;i++)
{ Tableau <Enum_ddl>& tb=te(i).tb;
int otaille = tb.Taille();
int m = mddl(i); nbddl += m;
if (m<=otaille)
{// on supprime sans pb
tb.Change_taille(m);
}
else // on augmente avec des ddl NU_DDL
{tb.Change_taille(m);
for (int j=otaille+1;j<=m;j++)
tb(j)=NU_DDL;
};
};
};
}
else
{ cout << "\n erreur de dimension pour le tableau mddl, il doit avoir la ";
cout << " dimension : " << n << ", alors qu\'il a la dimension : "
<< mddl.Taille() << "\nChange_taille(int n,Tableau <int> mddl)" << endl;
Sortie (1);
}
Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type
};
// met le tableau de ddl a zero
void DdlElement::TailleZero()
{ int maxi_elem = te.Taille();
for (int i=1; i<=maxi_elem;i++)
(te(i)).tb.Change_taille (0);
te.Change_taille(0);
nbddl = 0;
tab_enum_famille.erase(tab_enum_famille.begin(),tab_enum_famille.end());
};
// change un des ddlNoeudElements
void DdlElement::Change_un_ddlNoeudElement(int i,const DdlNoeudElement& add)
{ int nbdold = te(i).tb.Taille();
nbddl -= nbdold;
int nbdnew = add.tb.Taille();
nbddl += nbdnew;
// mise en place de add
te(i)=add;
// mise à jour des ddl par famille
Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type
/*Tableau <Enum_ddl>& tb=te(i).tb;
for (int j=1;j<=nbdold;j++)
(tab_enum_famille[PremierDdlFamille(tb(j))])--;
for (int i=1;i<= nbdnew;i++)
(tab_enum_famille[PremierDdlFamille(add.tb(i))])++;*/
};
// surcharge de l'operateur d'affectation
DdlElement& DdlElement::operator = (const DdlElement & a)
{ int nb = a.NbNoeud();
this->te.Change_taille(nb);
for (int i=1;i<= nb;i++)
this->te(i) = a(i);
// mise à jour du nombre de ddl
nbddl = a.nbddl; tab_enum_famille = a.tab_enum_famille;
return *this;
};
// surcharge des operator de test
bool DdlElement::operator == (const DdlElement & a) const
{ int nb = a.NbNoeud();
for (int i=1;i<=nb;i++)
if (this->te(i) != a(i)) return false;
return true;
};
bool DdlElement::operator != (const DdlElement & a) const
{ if (*this == a) return false; else return true;
};
// surcharge de l'operator de lecture
istream & operator >> (istream & entree, DdlElement& a)
{ // vérification du type
string type;
entree >> type;
if (type != "DdlElement")
{Sortie (1);
return entree;
}
// entrée du tableau
entree >> a.te;
// puis def du nombre total de ddl
a.Calcul_NbDdl();
a.Calcul_NbDdl_typer(); // mise à jour du nombre de ddl de chaque type
return entree;
};
// surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort, const DdlElement& a)
{ // tout d'abord un indicateur donnant le type
sort << "DdlElement " ;
// puis le tableau
sort << a.te;
return sort;
};
// retour du nombre de ddl d'une famille donnée
int DdlElement::NbDdl_famille(Enum_ddl enu) const
{ // pour l'instant on sort la totalité des ddl ce qui est faux mais permet de fonctionner comme avant
// return nbddl;
map < Enum_ddl, Int_initer , std::less <Enum_ddl> >::const_iterator il = tab_enum_famille.find(enu);
if (il == tab_enum_famille.end()) return 0; else return (*il).second.vali;
};
//================================= methodes proteges ==================
// calcul du nb de ddl
void DdlElement::Calcul_NbDdl()
{ nbddl = 0;
int tetaille = te.Taille();
for (int i=1; i<= tetaille;i++)
nbddl += (te(i)).tb.Taille();
};
// calcul du nb de ddl de chaque type contenu
void DdlElement::Calcul_NbDdl_typer()
{ // méthode en utilisant "tab_enum_famille"
// qui est un tableau associatif
// on commence par initialiser le tableau
tab_enum_famille.erase(tab_enum_famille.begin(),tab_enum_famille.end());
// on passe en revue tous les ddl
int tetaille = te.Taille();
for (int i=1; i<= tetaille;i++)
{ Tableau <Enum_ddl>& tb=te(i).tb;
int nbd= tb.Taille();
for (int j=1;j<=nbd;j++)
(tab_enum_famille[PremierDdlFamille(tb(j))])++;
}
/* // pour vérif
map < Enum_ddl, Int_initer , std::less <Enum_ddl> >::iterator il,ilfin=tab_enum_famille.end();
for (il=tab_enum_famille.begin();il != ilfin;il++)
cout << "\n ddl= " << (*il).first << " nombre " << (*il).second.vali << endl;
cout << "toto ?";
int toto; cin >> toto; */
};