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/core/ISubDomain.h"
25#include "arcane/core/IParallelMng.h"
27#include "arcane/core/IPrimaryMesh.h"
28#include "arcane/core/Properties.h"
29#include "arcane/core/ItemGroup.h"
30#include "arcane/core/Service.h"
31#include "arcane/core/Timer.h"
32#include "arcane/core/FactoryService.h"
33#include "arcane/core/ItemPrinter.h"
34#include "arcane/core/IItemFamily.h"
35#include "arcane/core/MeshVariable.h"
36#include "arcane/core/VariableBuildInfo.h"
37#include "arcane/std/MeshPartitionerBase.h"
38#include "arcane/std/SplitSDMeshPartitioner.h"
50SplitSDMeshPartitioner::
51SplitSDMeshPartitioner(
const ServiceBuildInfo& sbi)
52: ArcaneSplitSDMeshPartitionerObject(sbi)
53, m_poids_aux_mailles(VariableBuildInfo(sbi.mesh(),
"MeshPartitionerCellsWeight",IVariable::PNoDump|IVariable::PNoRestore))
55 info() <<
"SplitSDMeshPartitioner::SplitSDMeshPartitioner(...)";
61void SplitSDMeshPartitioner::
64 info() <<
"Equilibrage de charge avec SplitSDMeshPartitioner";
70 _initArrayCellsWithConstraints();
71 if (haveConstraints())
72 throw FatalErrorException(
"SplitSDMeshPartitioner: On ne supporte pas les contraintes avec SplitSD");
91void SplitSDMeshPartitioner::
113 info() <<
"Initialize new owners";
115 IMesh* mesh = this->mesh();
121 changeOwnersFromCells();
151void SplitSDMeshPartitioner::
157 IMesh* mesh = this->mesh();
173void SplitSDMeshPartitioner::
176 info() <<
"SplitSDMeshPartitioner::fin(...)";
191void SplitSDMeshPartitioner::
194 debug() <<
" ----------------------------------------";
195 debug() <<
"SplitSDMeshPartitioner::MAJDomaine(...)";
199 int me = subDomain()->subDomainId();
203 IMesh* mesh = this->mesh();
205 debug() <<
" all_faces.size() = =" <<
all_faces.size();
250 Domaine->PoidsDom += m_poids_aux_mailles[cell];
254 info() <<
"Domaine->NbIntf = "<<
Domaine->NbIntf;
255 info() <<
"Domaine->NbElements = "<<
Domaine->NbElements;
256 info() <<
"Domaine->PoidsDom = "<<
Domaine->PoidsDom;
260 unsigned int ind = 0;
266 Domaine->Intf[
ind].NoDomVois = (*iter_vois).first;
270 info() <<
"Domaine->Intf["<<
ind<<
"].NoDomVois = "<<
Domaine->Intf[
ind].NoDomVois;
271 info() <<
" v_face.size() = "<<
v_face.size();
274 for (
int i = 0; i<
v_face.size(); i++){
279 for( Integer z=0; z<face.
nbNode(); ++z ){
290 info() <<
" ListeNoeuds.size() = "<<
Domaine->Intf[
ind].ListeNoeuds.size();
297 info() <<
"MAJDomaine => ";
299 info() <<
" ----------------------------------------";
304void SplitSDMeshPartitioner::
310 info() <<
"SplitSDMeshPartitioner::MAJMaillageMaitre(...)";
329 info()<<
" ***************************";
330 info()<<
" * Avant MAJMaillageMaitre *";
332 info()<<
" ***************************";
389 info()<<
" ***************************";
390 info()<<
" * Apres MAJMaillageMaitre *";
394 info()<<
" ***************************";
402void SplitSDMeshPartitioner::
406 info()<<
" on entre dans verifMaillageMaitre";
421 if (
k==ListeDomaines[
iVois].NbVoisins){
422 printf(
"on ne trouve pas le numéro de voisin \n");
424 perror() <<
"verifMaillageMaitre en erreur sur le voisinage !!!";
427 if (ListeDomaines[
iVois].ListeVoisins[
k].NbNoeudsInterface != NbNoeudsInterface){
428 printf(
"on ne trouve pas le même nombre de noeuds entre les voisins \n");
429 printf(
"pour info: iDom = %d, iVois = %d, NbNoeudsInterface %d != %d\n"
430 ,
iDom,
iVois,NbNoeudsInterface,ListeDomaines[
iVois].ListeVoisins[
k].NbNoeudsInterface);
431 perror() <<
"verifMaillageMaitre en erreur sur le nombre de noeuds !!!";
436 info()<<
" on sort de verifMaillageMaitre";
443void SplitSDMeshPartitioner::
471 info()<<
" ------------------------------------";
472 info()<<
" on entre dans MAJDeltaGlobal, tolerance = "<<
tolerance;
473 info()<<
" ------------------------------------";
474 info()<<
" ......... Maillage Initial ...........";
475 AfficheListeDomaines(ListeDomaines,
NbDomaines);
479 info()<<
" SplitSDMeshPartitioner::MAJDeltaGlobal : NbDomaines nul !";
484 info()<<
" \n = on sort de MAJDeltaGlobal sans rien faire (NbDomainesPleins = "<<
Maillage->NbDomainesPleins;
485 info()<<
" ------------------------------------";
496 ListeDomaines[i].ListeVoisins[
j].Delta = 0.0;
504 if (ListeDomaines[i].NbElements != 0)
526 info()<<
" Après Poids -= PoidsMoyen";
527 AfficheListeDomaines(ListeDomaines,
NbDomaines);
562 info()<<
" FrontSuiv[0] = "<<
iDomDep;
584 fatal()<<
" partitionner/MAJDeltaGlobal: on ne trouve plus de domaine alors que l'on n'a pas terminé !!!";
620 info()<<
" ListeDomaines["<<
iDom<<
"].Poids = "<<ListeDomaines[
iDom].
Poids;
624 if (ListeDomaines[
iDom].Poids < 0.0){
626 double don = MIN(-ListeDomaines[
iDom].Poids, ListeDomaines[
iDomDep].Poids);
675 info()<<
" ......... Maillage Final ...........";
676 AfficheListeDomaines(ListeDomaines,
NbDomaines);
677 info()<<
" = on sort de MAJDeltaGlobal =";
678 info()<<
" ------------------------------------";
683void SplitSDMeshPartitioner::
694 if (
j == ListeDomaines[
iDom].NbVoisins)
696 info()<<
"on ne trouve pas le numéro de voisin";
697 info()<<
"pour info: ajout = "<<
ajout<<
", iDom = "<<
iDom<<
", iVois = "<<
iVois;
698 pfatal()<<
"Erreur dans Partitionner/MAJDelta, pas de voisin !";
707double SplitSDMeshPartitioner::
715 debug()<<
" on entre dans SplitSDMeshPartitioner::CalculDeltaMin, deltaMin = "<<
deltaMin
739 if (ListeDomaines[
iDom].Poids>0.0)
755#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
770void SplitSDMeshPartitioner::
794 info()<<
" -------------------------------------";
795 info()<<
" on entre dans SplitSDMeshPartitioner::Equilibrage, deltaMin = "<<
deltaMin;
800 CHECK_IF_NOT_NULL(
TabTMP);
823 info()<<
" SplitSDMeshPartitioner::Equilibrage de la charge (iteration No "<<
iterEquilibrage<<
")";
871#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
939 info() <<
"cells_new_owner.synchronize() et changeOwnersFromCells()";
944 changeOwnersFromCells();
946 bool compact = mesh->
properties()->getBool(
"compact");
947 mesh->
properties()->setBool(
"compact",
false);
949 mesh->
properties()->setBool(
"compact", compact);
978 debug()<<
" = on sort de SplitSDMeshPartitioner::Equilibrage";
979 debug()<<
" -------------------------------------";
985void SplitSDMeshPartitioner::
992 debug()<<
" on entre dans Equil2Dom (indDomCharge:"<<
indDomCharge<<
", indDomVois:"<<
indDomVois<<
", Delta:"<<Delta;
1007#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
1034 info()<<
" on sort de Equil2Dom";
1039void SplitSDMeshPartitioner::
1045 info()<<
"SplitSDMeshPartitioner::SelectElements(Domaine, Delta = "<<Delta<<
", indDomVois = "<<
indDomVois<<
")";
1046 info()<<
" Domaine->NbElements = " <<
Domaine->NbElements;
1047 info()<<
" Domaine->PoidsDom = " <<
Domaine->PoidsDom;
1051 perror() <<
"Delta <= 0 !!!";
1054 IMesh* mesh = this->mesh();
1056 if (Delta>=
Domaine->PoidsDom){
1058 pinfo()<<
" Tout le domaine est sélectionné sur le domaine "<<subDomain()->subDomainId()
1059 <<
", avec SelectElements, PoidsDom = " <<
Domaine->PoidsDom
1060 <<
", Delta = "<<Delta;
1083 pfatal()<<
" SelectElements ne trouve pas l'interface parmis les voisins !!!";
1104 for (
int i=0; i<
Domaine->Intf[
iIntf].ListeNoeuds.size(); i++)
1113 int me = subDomain()->subDomainId();
1117 if (cell.
owner() != me)
1158 info()<<
" en sortie: ListeElements.size() = "<<
ListeElements.size();
1162int SplitSDMeshPartitioner::
1171 info()<<
" = on entre dans ParcoursFront : (NbFronts = "<<*
pNbFronts<<
", NbFrontsMax = "<<
NbFrontsMax<<
")";
1172 info()<<
" FrontsNoeuds.size() = "<<
FrontsNoeuds.size();
1266 info()<<
" Delta = "<<Delta;
1270 info()<<
" bloque = "<<(
bloque?
"VRAI":
"FAUX");
1273 info()<<
" = on arete apres avoir obtenu le nombre maximum de fronts "<<
NbFrontsMax;
1276 info()<<
" = on arete apres avoir obtenu le poids desire "<<
PoidsActuel;
1279 info()<<
" = on est bloque (non connexe ?) =";
1282 info()<<
" = on arete parce que l'on a tout vu =";
1284 info()<<
" = on sort de ParcoursFront . =";
1292void SplitSDMeshPartitioner::
1301 debug()<<
" on entre dans LissageDuFront : NbFronts = "<<
NbFronts;
1343 info()<<
" on sort de LissageDuFront ("<<
NbElementsAjoutes<<
" elements ajoutes)";
1348void SplitSDMeshPartitioner::
1353 info()<<
" on entre dans ConnexifieDomaine, tolConnexite = "<<
tolConnexite;
1372 if (cell.
owner() != me)
1419 pfatal()<<
"ConnexifieDomaine est bloqué lors de la recherche d'un élément de départ";
1462 info()<<
" seuil = "<<
seuil;
1503 info() <<
" Nombre de composantes transférées : "<<
nbCCTransf;
1535#if defined(ARCANE_DEBUG) || defined(DEBUG_PARTITIONER)
1536 info()<<
" ConnexifieDomaine: nbCCTransfSum = "<<
nbCCTransfSum;
1541 info()<<
" on fait la synchronisation";
1546 changeOwnersFromCells();
1548 bool compact = mesh->
properties()->getBool(
"compact");
1549 mesh->
properties()->setBool(
"compact",
false);
1551 mesh->
properties()->setBool(
"compact", compact);
1560 info()<<
" on sort de ConnexifieDomaine";
1565int SplitSDMeshPartitioner::
1583 if (id1 == me && id2 != me)
1585 else if (id1 != me && id2 == me)
1593 std::map<int,int>::iterator iter;
1605 pfatal()<<
"indDomVois toujours à -1 !!!";
1608 pinfo()<<
" getDomVoisMaxFace, me = "<<me<<
", ListeElements.size() = "<<
ListeElements.size()
1615int* SplitSDMeshPartitioner::
1620 IMesh* mesh = this->mesh();
1630 info() <<
"SplitSDMeshPartitioner::GetMasqueDesNoeuds(), maxNodeLocalId = "<<
maxNodeLocalId;
1641int* SplitSDMeshPartitioner::
1646 IMesh* mesh = this->mesh();
1657 info() <<
"SplitSDMeshPartitioner::GetMasqueDesElements(), maxCellLocalId = "<<
maxCellLocalId;
1669void SplitSDMeshPartitioner::
1678void SplitSDMeshPartitioner::
1682 info()<<
"LibereDomaine(...)";
1685 if (Domaine->
NbIntf != 0){
1686 if (Domaine->
Intf != NULL){
1687 for (
int i=0; i<Domaine->
NbIntf; i++)
1689 delete [] Domaine->
Intf;
1690 Domaine->
Intf = NULL;
1700void SplitSDMeshPartitioner::
1704 info()<<
"LibereMaillage(...)";
1720 Maillage->
Poids = 0.0;
1726void SplitSDMeshPartitioner::
1732 for (idom=0; idom<NbDom; idom++) {
1733 info()<<
" --------------------";
1734 info()<<
" --- Domaine ("<<idom<<
") ---";
1735 info()<<
" --------------------";
1737 if (Domaine == NULL){
1738 info()<<
" Domaine vide ! (pointeur NULL)";
1740 else if (Domaine[idom].NbElements == 0) {
1741 info()<<
" Domaine vide ! (pas d'éléments)";
1744 info()<<
" NbElements = "<<Domaine[idom].
NbElements;
1745 info()<<
" PoidsDom = "<<Domaine[idom].
PoidsDom;
1746 info()<<
" Interfaces (NbIntf = "<<Domaine[idom].
NbIntf<<
") :";
1747 for (i=0; i<Domaine[idom].
NbIntf; i++) {
1748 info()<<
" ("<<i<<
") NoDomVois = "<<Domaine[idom].
Intf[i].
NoDomVois
1757void SplitSDMeshPartitioner::
1760 info()<<
" ----------------";
1761 info()<<
" --- Maillage ---";
1762 info()<<
" ----------------";
1763 if (Maillage==NULL){
1764 info()<<
" structure Maillage vide !";
1767 info()<<
" NbElements (total) = "<<Maillage->
NbElements;
1768 info()<<
" Poids (total) = "<<Maillage->
Poids;
1774 info()<<
" Maillage.ListeDomaines == NULL";
1784void SplitSDMeshPartitioner::
1787 info()<<
" ListeDomaines :";
1788 for (
int i=0; i<NbDomaines; i++) {
1789 info()<<
" ("<<i<<
") NbElements = "<<ListeDomaines[i].
NbElements<<
"; Poids = "<<ListeDomaines[i].
Poids;
1790 info()<<
" ("<<i<<
") NbVoisins = "<<ListeDomaines[i].
NbVoisins<<
"; ListeVoisins :";
1791 for (
int j=0; j<ListeDomaines[i].
NbVoisins; j++) {
1800void SplitSDMeshPartitioner::
1803 info()<<
" AfficheEquilMaillage(...)";
1805 double poidsMin = 0.0;
1806 double poidsMax = 0.0;
1815 if (poidsDom > poidsMax)
1816 poidsMax = poidsDom;
1817 if (poidsDom < poidsMin)
1818 poidsMin = poidsDom;
1821 info()<<
" INFO equilibrage / noeuds : max : "<<poidsMax<<
", min : "<<poidsMin
1825 info()<<
"AfficheEquilMaillage : Maillage->ListeDomaines == NULL";
1880 <<
FromProc<<
", lors de MPI_Get_count";
1888 CHECK_IF_NOT_NULL(
TabTMP);
1941 <<
ToProc<<
", lors de MPI_Send";
2013 InfoProc->m_service->
pfatal()<<
"DiffuseMessage depuis "<<
InfoProc->me<<
", il est nécessaire que la taille du tableau soit connue !!!\n";
2022 CHECK_IF_NOT_NULL(
TabTMP);
2054Integer SplitSDMeshPartitioner::
2057 size_t s = (2+2*
Domaine->NbIntf)*
sizeof(
int)+
sizeof(
double);
2075void SplitSDMeshPartitioner::
2083 CHECK_MPI_PACK_ERR(
ier);
2086 CHECK_MPI_PACK_ERR(
ier);
2089 CHECK_MPI_PACK_ERR(
ier);
2091 for (
int i=0; i<
Domaine->NbIntf; i++){
2093 CHECK_MPI_PACK_ERR(
ier);
2097 CHECK_MPI_PACK_ERR(
ier);
2124 for (
int i=0; i<
DomMail->NbVoisins; i++){
2127 DomMail->ListeVoisins[i].Delta = 0.0;
2137int SplitSDMeshPartitioner::TailleEquil()
2139 return 2*
sizeof(
int) +
sizeof(
double);
2151 CHECK_MPI_PACK_ERR(
ier);
2154 CHECK_MPI_PACK_ERR(
ier);
2157 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