19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/ArcanePrecomp.h"
21#include "arcane/utils/Convert.h"
22#include "arcane/utils/Array.h"
24#include "arcane/ISubDomain.h"
25#include "arcane/IParallelMng.h"
26#include "arcane/ItemEnumerator.h"
27#include "arcane/IPrimaryMesh.h"
28#include "arcane/Properties.h"
29#include "arcane/ItemGroup.h"
30#include "arcane/Service.h"
31#include "arcane/Timer.h"
32#include "arcane/FactoryService.h"
33#include "arcane/ItemPrinter.h"
34#include "arcane/IItemFamily.h"
35#include "arcane/MeshVariable.h"
36#include "arcane/VariableBuildInfo.h"
37#include "arcane/std/MeshPartitionerBase.h"
41#include "arcane/cea/SplitSDMeshPartitioner.h"
51SplitSDMeshPartitioner::
52SplitSDMeshPartitioner(
const ServiceBuildInfo& sbi)
53: ArcaneSplitSDMeshPartitionerObject(sbi)
54, m_poids_aux_mailles(VariableBuildInfo(sbi.mesh(),
"MeshPartitionerCellsWeight",IVariable::PNoDump|IVariable::PNoRestore))
56 info() <<
"SplitSDMeshPartitioner::SplitSDMeshPartitioner(...)";
62void SplitSDMeshPartitioner::
65 info() <<
"Equilibrage de charge avec SplitSDMeshPartitioner";
71 _initArrayCellsWithConstraints();
72 if (haveConstraints())
73 throw FatalErrorException(
"SplitSDMeshPartitioner: On ne supporte pas les contraintes avec SplitSD");
92void SplitSDMeshPartitioner::
114 info() <<
"Initialize new owners";
116 IMesh* mesh = this->mesh();
122 changeOwnersFromCells();
152void SplitSDMeshPartitioner::
158 IMesh* mesh = this->mesh();
174void SplitSDMeshPartitioner::
177 info() <<
"SplitSDMeshPartitioner::fin(...)";
192void SplitSDMeshPartitioner::
195 debug() <<
" ----------------------------------------";
196 debug() <<
"SplitSDMeshPartitioner::MAJDomaine(...)";
200 int me = subDomain()->subDomainId();
204 IMesh* mesh = this->mesh();
206 debug() <<
" all_faces.size() = =" <<
all_faces.size();
251 Domaine->PoidsDom += m_poids_aux_mailles[cell];
255 info() <<
"Domaine->NbIntf = "<<
Domaine->NbIntf;
256 info() <<
"Domaine->NbElements = "<<
Domaine->NbElements;
257 info() <<
"Domaine->PoidsDom = "<<
Domaine->PoidsDom;
261 unsigned int ind = 0;
267 Domaine->Intf[
ind].NoDomVois = (*iter_vois).first;
271 info() <<
"Domaine->Intf["<<
ind<<
"].NoDomVois = "<<
Domaine->Intf[
ind].NoDomVois;
272 info() <<
" v_face.size() = "<<
v_face.size();
275 for (
int i = 0; i<
v_face.size(); i++){
280 for( Integer z=0; z<face.
nbNode(); ++z ){
291 info() <<
" ListeNoeuds.size() = "<<
Domaine->Intf[
ind].ListeNoeuds.size();
298 info() <<
"MAJDomaine => ";
300 info() <<
" ----------------------------------------";
305void SplitSDMeshPartitioner::
311 info() <<
"SplitSDMeshPartitioner::MAJMaillageMaitre(...)";
330 info()<<
" ***************************";
331 info()<<
" * Avant MAJMaillageMaitre *";
333 info()<<
" ***************************";
390 info()<<
" ***************************";
391 info()<<
" * Apres MAJMaillageMaitre *";
395 info()<<
" ***************************";
403void SplitSDMeshPartitioner::
407 info()<<
" on entre dans verifMaillageMaitre";
422 if (
k==ListeDomaines[
iVois].NbVoisins){
423 printf(
"on ne trouve pas le numéro de voisin \n");
425 perror() <<
"verifMaillageMaitre en erreur sur le voisinage !!!";
428 if (ListeDomaines[
iVois].ListeVoisins[
k].NbNoeudsInterface != NbNoeudsInterface){
429 printf(
"on ne trouve pas le même nombre de noeuds entre les voisins \n");
430 printf(
"pour info: iDom = %d, iVois = %d, NbNoeudsInterface %d != %d\n"
431 ,
iDom,
iVois,NbNoeudsInterface,ListeDomaines[
iVois].ListeVoisins[
k].NbNoeudsInterface);
432 perror() <<
"verifMaillageMaitre en erreur sur le nombre de noeuds !!!";
437 info()<<
" on sort de verifMaillageMaitre";
444void SplitSDMeshPartitioner::
472 info()<<
" ------------------------------------";
473 info()<<
" on entre dans MAJDeltaGlobal, tolerance = "<<
tolerance;
474 info()<<
" ------------------------------------";
475 info()<<
" ......... Maillage Initial ...........";
476 AfficheListeDomaines(ListeDomaines,
NbDomaines);
480 info()<<
" SplitSDMeshPartitioner::MAJDeltaGlobal : NbDomaines nul !";
485 info()<<
" \n = on sort de MAJDeltaGlobal sans rien faire (NbDomainesPleins = "<<
Maillage->NbDomainesPleins;
486 info()<<
" ------------------------------------";
497 ListeDomaines[i].ListeVoisins[
j].Delta = 0.0;
505 if (ListeDomaines[i].NbElements != 0)
527 info()<<
" Après Poids -= PoidsMoyen";
528 AfficheListeDomaines(ListeDomaines,
NbDomaines);
563 info()<<
" FrontSuiv[0] = "<<
iDomDep;
585 fatal()<<
" partitionner/MAJDeltaGlobal: on ne trouve plus de domaine alors que l'on n'a pas terminé !!!";
621 info()<<
" ListeDomaines["<<
iDom<<
"].Poids = "<<ListeDomaines[
iDom].
Poids;
625 if (ListeDomaines[
iDom].Poids < 0.0){
627 double don = MIN(-ListeDomaines[
iDom].Poids, ListeDomaines[
iDomDep].Poids);
676 info()<<
" ......... Maillage Final ...........";
677 AfficheListeDomaines(ListeDomaines,
NbDomaines);
678 info()<<
" = on sort de MAJDeltaGlobal =";
679 info()<<
" ------------------------------------";
684void SplitSDMeshPartitioner::
695 if (
j == ListeDomaines[
iDom].NbVoisins)
697 info()<<
"on ne trouve pas le numéro de voisin";
698 info()<<
"pour info: ajout = "<<
ajout<<
", iDom = "<<
iDom<<
", iVois = "<<
iVois;
699 pfatal()<<
"Erreur dans Partitionner/MAJDelta, pas de voisin !";
708double SplitSDMeshPartitioner::
716 debug()<<
" on entre dans SplitSDMeshPartitioner::CalculDeltaMin, deltaMin = "<<
deltaMin
740 if (ListeDomaines[
iDom].Poids>0.0)
756#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
771void SplitSDMeshPartitioner::
795 info()<<
" -------------------------------------";
796 info()<<
" on entre dans SplitSDMeshPartitioner::Equilibrage, deltaMin = "<<
deltaMin;
801 CHECK_IF_NOT_NULL(
TabTMP);
824 info()<<
" SplitSDMeshPartitioner::Equilibrage de la charge (iteration No "<<
iterEquilibrage<<
")";
872#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
940 info() <<
"cells_new_owner.synchronize() et changeOwnersFromCells()";
945 changeOwnersFromCells();
947 bool compact = mesh->
properties()->getBool(
"compact");
948 mesh->
properties()->setBool(
"compact",
false);
950 mesh->
properties()->setBool(
"compact", compact);
979 debug()<<
" = on sort de SplitSDMeshPartitioner::Equilibrage";
980 debug()<<
" -------------------------------------";
986void SplitSDMeshPartitioner::
993 debug()<<
" on entre dans Equil2Dom (indDomCharge:"<<
indDomCharge<<
", indDomVois:"<<
indDomVois<<
", Delta:"<<Delta;
1008#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
1035 info()<<
" on sort de Equil2Dom";
1040void SplitSDMeshPartitioner::
1046 info()<<
"SplitSDMeshPartitioner::SelectElements(Domaine, Delta = "<<Delta<<
", indDomVois = "<<
indDomVois<<
")";
1047 info()<<
" Domaine->NbElements = " <<
Domaine->NbElements;
1048 info()<<
" Domaine->PoidsDom = " <<
Domaine->PoidsDom;
1052 perror() <<
"Delta <= 0 !!!";
1055 IMesh* mesh = this->mesh();
1057 if (Delta>=
Domaine->PoidsDom){
1059 pinfo()<<
" Tout le domaine est sélectionné sur le domaine "<<subDomain()->subDomainId()
1060 <<
", avec SelectElements, PoidsDom = " <<
Domaine->PoidsDom
1061 <<
", Delta = "<<Delta;
1084 pfatal()<<
" SelectElements ne trouve pas l'interface parmis les voisins !!!";
1105 for (
int i=0; i<
Domaine->Intf[
iIntf].ListeNoeuds.size(); i++)
1114 int me = subDomain()->subDomainId();
1118 if (cell.
owner() != me)
1159 info()<<
" en sortie: ListeElements.size() = "<<
ListeElements.size();
1163int SplitSDMeshPartitioner::
1172 info()<<
" = on entre dans ParcoursFront : (NbFronts = "<<*
pNbFronts<<
", NbFrontsMax = "<<
NbFrontsMax<<
")";
1173 info()<<
" FrontsNoeuds.size() = "<<
FrontsNoeuds.size();
1267 info()<<
" Delta = "<<Delta;
1271 info()<<
" bloque = "<<(
bloque?
"VRAI":
"FAUX");
1274 info()<<
" = on arete apres avoir obtenu le nombre maximum de fronts "<<
NbFrontsMax;
1277 info()<<
" = on arete apres avoir obtenu le poids desire "<<
PoidsActuel;
1280 info()<<
" = on est bloque (non connexe ?) =";
1283 info()<<
" = on arete parce que l'on a tout vu =";
1285 info()<<
" = on sort de ParcoursFront . =";
1293void SplitSDMeshPartitioner::
1302 debug()<<
" on entre dans LissageDuFront : NbFronts = "<<
NbFronts;
1344 info()<<
" on sort de LissageDuFront ("<<
NbElementsAjoutes<<
" elements ajoutes)";
1349void SplitSDMeshPartitioner::
1354 info()<<
" on entre dans ConnexifieDomaine, tolConnexite = "<<
tolConnexite;
1373 if (cell.
owner() != me)
1420 pfatal()<<
"ConnexifieDomaine est bloqué lors de la recherche d'un élément de départ";
1463 info()<<
" seuil = "<<
seuil;
1504 info() <<
" Nombre de composantes transférées : "<<
nbCCTransf;
1536#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
1537 info()<<
" ConnexifieDomaine: nbCCTransfSum = "<<
nbCCTransfSum;
1542 info()<<
" on fait la synchronisation";
1547 changeOwnersFromCells();
1549 bool compact = mesh->
properties()->getBool(
"compact");
1550 mesh->
properties()->setBool(
"compact",
false);
1552 mesh->
properties()->setBool(
"compact", compact);
1561 info()<<
" on sort de ConnexifieDomaine";
1566int SplitSDMeshPartitioner::
1584 if (id1 == me && id2 != me)
1586 else if (id1 != me && id2 == me)
1594 std::map<int,int>::iterator iter;
1606 pfatal()<<
"indDomVois toujours à -1 !!!";
1609 pinfo()<<
" getDomVoisMaxFace, me = "<<me<<
", ListeElements.size() = "<<
ListeElements.size()
1616int* SplitSDMeshPartitioner::
1621 IMesh* mesh = this->mesh();
1631 info() <<
"SplitSDMeshPartitioner::GetMasqueDesNoeuds(), maxNodeLocalId = "<<
maxNodeLocalId;
1642int* SplitSDMeshPartitioner::
1647 IMesh* mesh = this->mesh();
1658 info() <<
"SplitSDMeshPartitioner::GetMasqueDesElements(), maxCellLocalId = "<<
maxCellLocalId;
1670void SplitSDMeshPartitioner::
1679void SplitSDMeshPartitioner::
1683 info()<<
"LibereDomaine(...)";
1686 if (Domaine->
NbIntf != 0){
1687 if (Domaine->
Intf != NULL){
1688 for (
int i=0; i<Domaine->
NbIntf; i++)
1690 delete [] Domaine->
Intf;
1691 Domaine->
Intf = NULL;
1701void SplitSDMeshPartitioner::
1705 info()<<
"LibereMaillage(...)";
1721 Maillage->
Poids = 0.0;
1727void SplitSDMeshPartitioner::
1733 for (idom=0; idom<NbDom; idom++) {
1734 info()<<
" --------------------";
1735 info()<<
" --- Domaine ("<<idom<<
") ---";
1736 info()<<
" --------------------";
1738 if (Domaine == NULL){
1739 info()<<
" Domaine vide ! (pointeur NULL)";
1741 else if (Domaine[idom].NbElements == 0) {
1742 info()<<
" Domaine vide ! (pas d'éléments)";
1745 info()<<
" NbElements = "<<Domaine[idom].
NbElements;
1746 info()<<
" PoidsDom = "<<Domaine[idom].
PoidsDom;
1747 info()<<
" Interfaces (NbIntf = "<<Domaine[idom].
NbIntf<<
") :";
1748 for (i=0; i<Domaine[idom].
NbIntf; i++) {
1749 info()<<
" ("<<i<<
") NoDomVois = "<<Domaine[idom].
Intf[i].
NoDomVois
1758void SplitSDMeshPartitioner::
1761 info()<<
" ----------------";
1762 info()<<
" --- Maillage ---";
1763 info()<<
" ----------------";
1764 if (Maillage==NULL){
1765 info()<<
" structure Maillage vide !";
1768 info()<<
" NbElements (total) = "<<Maillage->
NbElements;
1769 info()<<
" Poids (total) = "<<Maillage->
Poids;
1775 info()<<
" Maillage.ListeDomaines == NULL";
1785void SplitSDMeshPartitioner::
1788 info()<<
" ListeDomaines :";
1789 for (
int i=0; i<NbDomaines; i++) {
1790 info()<<
" ("<<i<<
") NbElements = "<<ListeDomaines[i].
NbElements<<
"; Poids = "<<ListeDomaines[i].
Poids;
1791 info()<<
" ("<<i<<
") NbVoisins = "<<ListeDomaines[i].
NbVoisins<<
"; ListeVoisins :";
1792 for (
int j=0; j<ListeDomaines[i].
NbVoisins; j++) {
1801void SplitSDMeshPartitioner::
1804 info()<<
" AfficheEquilMaillage(...)";
1806 double poidsMin = 0.0;
1807 double poidsMax = 0.0;
1816 if (poidsDom > poidsMax)
1817 poidsMax = poidsDom;
1818 if (poidsDom < poidsMin)
1819 poidsMin = poidsDom;
1822 info()<<
" INFO equilibrage / noeuds : max : "<<poidsMax<<
", min : "<<poidsMin
1826 info()<<
"AfficheEquilMaillage : Maillage->ListeDomaines == NULL";
1881 <<
FromProc<<
", lors de MPI_Get_count";
1889 CHECK_IF_NOT_NULL(
TabTMP);
1942 <<
ToProc<<
", lors de MPI_Send";
2014 InfoProc->m_service->
pfatal()<<
"DiffuseMessage depuis "<<
InfoProc->me<<
", il est nécessaire que la taille du tableau soit connue !!!\n";
2023 CHECK_IF_NOT_NULL(
TabTMP);
2055Integer SplitSDMeshPartitioner::
2058 size_t s = (2+2*
Domaine->NbIntf)*
sizeof(
int)+
sizeof(
double);
2076void SplitSDMeshPartitioner::
2084 CHECK_MPI_PACK_ERR(
ier);
2087 CHECK_MPI_PACK_ERR(
ier);
2090 CHECK_MPI_PACK_ERR(
ier);
2092 for (
int i=0; i<
Domaine->NbIntf; i++){
2094 CHECK_MPI_PACK_ERR(
ier);
2098 CHECK_MPI_PACK_ERR(
ier);
2125 for (
int i=0; i<
DomMail->NbVoisins; i++){
2128 DomMail->ListeVoisins[i].Delta = 0.0;
2138int SplitSDMeshPartitioner::TailleEquil()
2140 return 2*
sizeof(
int) +
sizeof(
double);
2152 CHECK_MPI_PACK_ERR(
ier);
2155 CHECK_MPI_PACK_ERR(
ier);
2158 CHECK_MPI_PACK_ERR(
ier);
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Face face(Int32 i) const
i-ème face de la maille
Int32 nbFace() const
Nombre de faces de la maille.
Cell frontCell() const
Maille devant la face (maille nulle si aucune)
bool isSubDomainBoundary() const
Indique si la face est au bord du sous-domaine (i.e nbCell()==1)
Cell backCell() const
Maille derrière la face (maille nulle si aucune)
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
virtual FaceGroup allFaces()=0
Groupe de toutes les faces.
virtual NodeGroup allNodes()=0
Groupe de tous les noeuds.
virtual CellGroup allCells()=0
Groupe de toutes les mailles.
Interface d'un partitionneur de maillage.
Interface d'un partitionneur de maillage.
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
virtual Properties * properties()=0
Propriétés associées à ce maillage.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual void computeMinMaxSum(char val, char &min_val, char &max_val, char &sum_val, Int32 &min_rank, Int32 &max_rank)=0
Calcule en une opération la somme, le min, le max d'une valeur.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void exchangeItems()=0
Change les sous-domaines propriétaires des entités.
virtual VariableItemInt32 & itemsNewOwner(eItemKind kind)=0
Variable contenant l'identifiant du sous-domaine propriétaire.
Interface du gestionnaire d'un sous-domaine.
Node node(Int32 i) const
i-ème noeud de l'entité
Int32 nbNode() const
Nombre de noeuds de l'entité
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Cell cell(Int32 i) const
i-ème maille du noeud
Int32 nbCell() const
Nombre de mailles connectées au noeud.
Propriétés de création d'un service.
Partitioneur de maillage inspiré de la bibliothèque SplitSD, développé initialement à l'ONERA pour Da...
Exception lorsqu'une erreur fatale est survenue.
TraceMessage pfatal() const
Flot pour un message d'erreur fatale en parallèle.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
bool arcaneIsDebug()
Vrai si la macro ARCANE_DEBUG est définie.
@ IK_Cell
Entité de maillage de genre maille.
StrucListeVoisMail * ListeVoisins
StrucListeDomMail * ListeDomaines
StructureInterface * Intf
Arcane::UniqueArray< Arcane::Node > ListeNoeuds