14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/ArcanePrecomp.h"
16#include "arcane/utils/Convert.h"
17#include "arcane/utils/CheckedConvert.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/StringBuilder.h"
20#include "arcane/utils/Iostream.h"
21#include "arcane/utils/ScopedPtr.h"
22#include "arcane/utils/NotImplementedException.h"
23#include "arcane/utils/ArgumentException.h"
25#include "arcane/ISubDomain.h"
26#include "arcane/IParallelMng.h"
27#include "arcane/ItemEnumerator.h"
28#include "arcane/IMeshSubMeshTransition.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/CommonVariables.h"
38#include "arcane/utils/HashTableMap.h"
41#define MPICH_SKIP_MPICXX
42#define OMPI_SKIP_MPICXX
45#include "arcane/std/MeshPartitionerBase.h"
46#include "arcane/std/ZoltanMeshPartitioner_axl.h"
55#define ARCANE_DEBUG_ZOLTAN
72 ZOLTAN_GRAPH = (1<<1),
93 , m_edge_weight_multiplier(edgeWeightMultiplier)
95 m_own_cells = m_mesh_partitionner_base->
mesh()->
ownCells();
106 Real m_edge_weight_multiplier;
107 std::set<std::pair<Int64, Int64> > m_weight_set;
111 info() <<
"ZoltanInfo::build()";
112 if (m_model & ZOLTAN_GEOM)
118 if (m_model & ZOLTAN_HG) {
121 if (m_model & ZOLTAN_GRAPH) {
133 for (
int i = 0 ; i < pm->
commRank() ; ++i) {
141 if (!m_mesh_partitionner_base->cellUsedWithConstraints(*
iCell))
144 int nbNgb = m_mesh_partitionner_base->nbNeighbourCellsWithConstraints(*
iCell);
145 if (m_model & ZOLTAN_HG) {
147 m_nbPins +=
nbNgb + 1;
149 if (m_model & ZOLTAN_GRAPH) {
151 m_nbPins += (
nbNgb*2);
155 info() <<
"nbEdges=" << m_nbEdges <<
" ; nbPins=" << m_nbPins;
157 if(m_mesh_partitionner_base->haveWeakConstraints())
178 static int getHgNumVertices(
void *data,
int *
ierr)
193 return zi->m_mesh_partitionner_base->nbOwnCellsWithConstraints();
216 if (
zi->m_mesh_partitionner_base->nbCellWeight() <=
wgt_dim) {
221 cells_weights =
zi->m_mesh_partitionner_base->cellsSizeWithConstraints();
230 if (!
zi->m_mesh_partitionner_base->cellUsedWithConstraints(*
icell))
233 gids[index] = (*icell).uniqueId().asInt32();
234 lids[index] =
zi->m_mesh_partitionner_base->localIdWithConstraints(*
icell);
241 (*
zi->m_ofile) <<
" Weight uid=" <<
gids[index] <<
" w=" <<
weight <<
'\n';
253 zi->
info() <<
" ZoltanInfo::getHgSizeAndFormat() ";
269 zi->
info() <<
" ZoltanInfo::getHgSizeAndFormat() " <<
" num_list= " << *
num_lists <<
" num_pins= " << *
num_pins;
279 zi->
info() <<
" ZoltanInfo::getHg() "
282 <<
" npins= " <<
npins
283 <<
" format= " << format;
290 int gid =
zi->m_edgeGIDStart;
295 if (!
zi->m_mesh_partitionner_base->cellUsedWithConstraints(item))
299 zi->m_mesh_partitionner_base->getNeighbourCellsUidWithConstraints(item,
302 if (
zi->m_model & ZOLTAN_HG)
313 if (
zi->m_model & ZOLTAN_GRAPH)
327 for (
int i = 0 ; i <
nrowcol ; ++i) {
333 (*
zi->m_ofile) <<
'\n';
348 int *sizes,
int *
ierr)
358 for (
int i = 0 ; i <
num_ids ; ++i)
366 static void getHgEdgeWeightSize(
void *data,
int *
num_edges,
int *
ierr)
395 zi->
info() <<
" ZoltanInfo::getHgEdgeWeights() "
409 if (!
zi->m_mesh_partitionner_base->cellUsedWithConstraints(item))
417 zi->m_mesh_partitionner_base->getNeighbourCellsUidWithConstraints(item,
420 if (
zi->m_model & ZOLTAN_HG) {
421 if (!(
zi->m_model & ZOLTAN_GRAPH)) {
432 if (
zi->m_model & ZOLTAN_GRAPH) {
440 if (
zi->m_mesh_partitionner_base->haveWeakConstraints()){
442 if(
zi->m_mesh_partitionner_base->cellUsedWithWeakConstraints(items)){
454 static int get_num_geometry(
void *data,
int *
ierr)
462 static void get_geometry_list(
void *data,
int sizeGID,
int sizeLID,
482 if (!
zi->m_mesh_partitionner_base->cellUsedWithConstraints(*
icell))
489 for( Integer z=0,
zs = (*icell).nbNode(); z<
zs; ++z ){
490 const Node& node = (*icell).node(z);
501 String s = platform::getEnvironmentVariable(
"ZOLTAN_MODEL");
502 if (!s.
null() && (s ==
"MYGEOM")) {
503 for (
int i = 0 ; i <
num_obj ; ++i) {
542ZoltanMeshPartitioner::
543ZoltanMeshPartitioner(
const ServiceBuildInfo& sbi)
544 : ArcaneZoltanMeshPartitionerObject(sbi)
564 info() <<
"Load balancing with Zoltan\n";
568 int rc = ::Zoltan_Initialize(0,0,&
ver);
571 fatal() <<
"Can not initialize zoltan (r=" <<
rc <<
")";
572 IMesh* mesh = this->mesh();
580 warning() <<
"Unable to test load balancing on a single sub-domain";
584 Integer nb_weight = nbCellWeight();
586 struct Zoltan_Struct *zz;
591 ZOLTAN_ID_PTR importGlobalIds;
592 ZOLTAN_ID_PTR importLocalIds;
596 ZOLTAN_ID_PTR exportGlobalIds;
607 zz = Zoltan_Create(*(MPI_Comm*)getCommunicator());
609 Zoltan_Set_Param(zz,
"RCB_REUSE",
"1");
615 String s = platform::getEnvironmentVariable(
"ZOLTAN_MODEL");
618 if (!s.null() &&
options()->model.isPresent())
619 fatal() <<
"Conflicting configuration between ZOLTAN_MODEL environment variable and user data set";
620 usePHG =
options()->useHypergraphe();
625 }
else if (s.null()) {
631 if (subDomain()->commonVariables().globalIteration() <= 2)
637 String algo =
"HYPERGRAPH";
638 if (s ==
"MYHG" || s ==
"OLDHG" || s ==
"DUALHG" || s ==
"GRAPH") {
641 }
else if (s ==
"RIB" || s==
"HSFC") {
644 }
else if (s ==
"RCB" || s ==
"MYGEOM") {
648 fatal() <<
"Undefined zoltan model '" << s <<
"'";
651 int model = ZOLTAN_HG;
652 if (usePHG ==
false) {
657 model |= ZOLTAN_GRAPH;
658 }
else if (s ==
"GRAPH") {
659 model = ZOLTAN_GRAPH;
666 Real edgeWeightMultiplier = 1;
667 Integer repartitionFrequency = 10;
668 Real imbalanceTol = 1.05;
669 Real phgRepartMultiplier = 10;
675 edgeWeightMultiplier =
options()->edgeWeightMultiplier();
676 repartitionFrequency =
options()->repartFrequency();
677 imbalanceTol =
options()->imbalanceTol();
678 phgRepartMultiplier =
options()->phgRepartMultiplier();
679 phgOutputLevel =
options()->phgOutputLevel();
680 debugLevel =
options()->debugLevel();
684 info() <<
"Zoltan: utilise un repartitionnement " << algo <<
" (" << s <<
").";
685 Zoltan_Set_Param(zz,
"LB_METHOD", algo.localstr());
686 Zoltan_Set_Param(zz,
"HYPERGRAPH_PACKAGE",
"PHG");
688 if(mesh->
subDomain()->commonVariables().globalIteration()==1)
690 Zoltan_Set_Param(zz,
"LB_APPROACH",
"PARTITION");
691 info() <<
"Zoltan: Partition";
693 else if(mesh->
subDomain()->commonVariables().globalIteration()%repartitionFrequency==0 && repartitionFrequency!=-1)
695 Zoltan_Set_Param(zz,
"LB_APPROACH",
"REPARTITION");
696 info() <<
"Zoltan: Repartition";
700 Zoltan_Set_Param(zz,
"LB_APPROACH",
"REFINE");
701 info() <<
"Zoltan: Refine";
704 String s_imbalaceTol(String::fromNumber(imbalanceTol));
705 Zoltan_Set_Param(zz,
"IMBALANCE_TOL", s_imbalaceTol.localstr());
707 String s_nb_part(String::fromNumber(nb_part));
708 Zoltan_Set_Param(zz,
"NUM_GLOBAL_PARTS", s_nb_part.localstr());
710 Zoltan_Set_Param(zz,
"NUM_GID_ENTRIES",
"1");
711 Zoltan_Set_Param(zz,
"NUM_LID_ENTRIES",
"1");
712 Zoltan_Set_Param(zz,
"RETURN_LISTS",
"EXPORT");
713 String s_nb_weight(String::fromNumber(nb_weight));
715 Zoltan_Set_Param(zz,
"OBJ_WEIGHT_DIM", s_nb_weight.localstr());
718 Zoltan_Set_Param(zz,
"ADD_OBJ_WEIGHT",
"NONE");
722 Zoltan_Set_Param(zz,
"FINAL_OUTPUT",
"0");
723 Zoltan_Set_Param(zz,
"PHG_USE_TIMERS",
"1");
725 String s_phgOutputLevel(String::fromNumber(phgOutputLevel));
726 Zoltan_Set_Param(zz,
"PHG_OUTPUT_LEVEL", s_phgOutputLevel.localstr());
729 Zoltan_Set_Param(zz,
"CHECK_HYPERGRAPH",
"0");
730 String s_debugLevel(String::fromNumber(debugLevel));
731 Zoltan_Set_Param(zz,
"DEBUG_LEVEL", s_debugLevel.localstr());
736 Zoltan_Set_Param(zz,
"PHG_COARSENING_METHOD",
"IPM");
740 Zoltan_Set_Param(zz,
"EDGE_WEIGHT_DIM",
"1");
741 Zoltan_Set_Param(zz,
"PHG_EDGE_WEIGHT_OPERATION",
"add");
743 if(!initial_partition)
747 String s_phgRepartMultiplier(String::fromNumber(phgRepartMultiplier));
748 Zoltan_Set_Param(zz,
"PHG_REPART_MULTIPLIER", s_phgRepartMultiplier.localstr());
753 Zoltan_Set_Param(zz,
"KEEP_CUTS",
"0");
754 Zoltan_Set_Param(zz,
"RCB_OUTPUT_LEVEL",
"0");
755 Zoltan_Set_Param(zz,
"RCB_RECTILINEAR_BLOCKS",
"0");
758 Zoltan_Set_Param(zz,
"OBJ_WEIGHTS_COMPARABLE",
"0");
762 Zoltan_Set_Param(zz,
"RCB_MULTICRITERIA_NORM",
"3");
763 Zoltan_Set_Param(zz,
"RCB_MAX_ASPECT_RATIO",
"10");
766 bool dump_infos =
false;
767 if (platform::getEnvironmentVariable(
"ARCANE_DEBUG_PARTITION")==
"TRUE")
778 ofile.open(f.localstr());
790 ScopedPtrT<ZoltanInfo> zoltan_info(
new ZoltanInfo(
this,zofile, model, edgeWeightMultiplier));
791 Zoltan_Set_Num_Obj_Fn(zz,&ZoltanInfo::getHgNumVertices, zoltan_info.get());
792 Zoltan_Set_Obj_List_Fn(zz, &ZoltanInfo::getHgVerticesAndWeights, zoltan_info.get());
793 if (!initial_partition) {
794 Zoltan_Set_Obj_Size_Multi_Fn(zz, &ZoltanInfo::getHgVertexSizes,
798 info() <<
"Setting up HG Callbacks";
799 Zoltan_Set_HG_Size_CS_Fn(zz, &ZoltanInfo::getHgSizeAndFormat, zoltan_info.get());
800 Zoltan_Set_HG_CS_Fn(zz, &ZoltanInfo::getHg, zoltan_info.get());
801 Zoltan_Set_HG_Size_Edge_Weights_Fn(zz, &ZoltanInfo::getHgEdgeWeightSize, zoltan_info.get());
802 Zoltan_Set_HG_Edge_Weights_Fn(zz, &ZoltanInfo::getHgEdgeWeights, zoltan_info.get());
806 info() <<
"Setting up Geom Callbacks";
807 Zoltan_Set_Num_Geom_Fn(zz, ZoltanInfo::get_num_geometry, zoltan_info.get());
808 Zoltan_Set_Geom_Multi_Fn(zz, ZoltanInfo::get_geometry_list, zoltan_info.get());
813 int* export_partitions = 0;
814 ZOLTAN_ID_PTR export_local_ids = 0;
816 info() <<
"Doing partition";
817 rc = Zoltan_LB_Partition(zz, &changes, &numGidEntries, &numLidEntries,
818 &numImport, &importGlobalIds, &importLocalIds,
819 &importProcs, &importToPart,
820 &numExport, &exportGlobalIds, &export_local_ids,
821 &exportProcs, &export_partitions);
826 cells_new_owner[icell] = (*icell).owner();
829 invertArrayLid2LidCompacted();
832 CellInfoListView items_internal(m_cell_family);
834 info() <<
"numExport = "<<numExport;
835 for( Integer i=0; i<nb_export; ++i ){
836 Item item = items_internal[ localIdWithConstraints(export_local_ids[i]) ];
838 changeCellOwner(item, cells_new_owner, export_partitions[i]);
840 ofile <<
"EXPORT: uid=" << ItemPrinter(item) <<
" OLD=" << item.owner()
841 <<
" NEW=" << cells_new_owner[item] <<
" PROC=" << exportProcs[i] <<
'\n';
855 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
858 Zoltan_LB_Free_Part(&exportGlobalIds, &export_local_ids,
859 &exportProcs, &export_partitions);
866 cells_new_owner.synchronize();
887#if ARCANE_DEFAULT_PARTITIONER == ZOLTAN_DEFAULT_PARTITIONER
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Generation de la classe de base du Service.
CaseOptionsZoltanMeshPartitioner * options() const
Options du jeu de données du service.
Cell frontCell() const
Maille devant la face (maille nulle si aucune)
Cell backCell() const
Maille derrière la face (maille nulle si aucune)
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
virtual FaceGroup ownFaces()=0
Groupe de toutes les faces propres au domaine.
Interface d'un partitionneur de maillage.
Interface d'un partitionneur de maillage.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual ISubDomain * subDomain()=0
Sous-domaine associé
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void scan(eReduceType rt, ArrayView< char > v)=0
Applique un algorithme de prefix-um sur les valeurs de v via l'opération rt.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void barrier()=0
Effectue une barière.
Integer size() const
Nombre d'éléments du groupe.
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Classe de base d'un service d'équilibrage de charge.
IMesh * mesh() const
Maillage associé au partitionneur.
virtual void changeOwnersFromCells()
Positionne les nouveaux propriétaires des noeuds, arêtes et faces à partir des mailles.
Classe gérant un vecteur de réel de dimension 3.
Structure contenant les informations pour créer un service.
Propriétés de création d'un service.
Paramètres nécessaires à la construction d'une variable.
Informations pour le partitionnement avec Zoltan.
Partitioneur de maillage utilisant la bibliotheque Zoltan.
virtual void notifyEndPartition()
Notification lors de la fin d'un repartionnement (après échange des entités)
virtual void build()
Construction de niveau build du service.
virtual void partitionMesh(bool initial_partition)
Exception lorsqu'un argument est invalide.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Classe d'accès aux traces.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage warning() const
Flot pour un message d'avertissement.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage fatal() const
Flot pour un message d'erreur fatale.
Vecteur 1D de données avec sémantique par valeur (style STL).
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
Integer toInteger(Real r)
Converti un Int64 en un Integer.
Integer toInteger(Real r)
Converti un Real en Integer.
double toDouble(Real r)
Converti un Real en double.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.
@ IK_Cell
Entité de maillage de genre maille.
Int32 Integer
Type représentant un entier.