14#include "arcane/utils/StringBuilder.h"
15#include "arcane/utils/Iostream.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/Convert.h"
19#include "arcane/utils/Array.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"
42#define MPICH_SKIP_MPICXX
43#define OMPI_SKIP_MPICXX
50#include "arcane/std/MeshPartitionerBase.h"
51#include "arcane/std/PTScotchMeshPartitioner_axl.h"
52#include "arcane/std/PartitionConverter.h"
53#include "arcane/std/GraphDistributor.h"
92PTScotchMeshPartitioner::
93PTScotchMeshPartitioner(
const ServiceBuildInfo& sbi)
94: ArcanePTScotchMeshPartitionerObject(sbi)
116 info() <<
"Load balancing with PTScotch\n";
122 bool dumpGraph =
false;
123 bool checkGraph =
false;
125 dumpGraph =
options()->dumpGraph();
126 checkGraph =
options()->checkGraph();
131 throw ArgumentException(A_FUNCINFO,
"partition with nb_part<nb_rank");
134 initConstraints(
false);
142 Integer nb_own_cell = nbOwnCellsWithConstraints();
144 Integer total_nb_cell = 0;
145 UniqueArray<SCOTCH_Num> scotch_vtkdist(nb_rank+1);
147 scotch_vtkdist[0] = 0;
148 for( Integer i=0; i<nb_rank; ++i ){
149 total_nb_cell += global_nb_own_cell[i];
150 scotch_vtkdist[i+1] =
static_cast<SCOTCH_Num
>(total_nb_cell);
158 Integer nb_max_face_neighbour_cell = 0;
164 const Cell& item = *i_item;
165 if (cellUsedWithConstraints(item)){
166 cell_scotch_uid[item] = mid;
169 nb_max_face_neighbour_cell += item.nbFace();
172 cell_scotch_uid.synchronize();
175 _initUidRef(cell_scotch_uid);
178 cell_scotch_uid.setUsed(
false);
180 SharedArray<SCOTCH_Num> scotch_xadj;
181 scotch_xadj.reserve(nb_own_cell+1);
183 SharedArray<SCOTCH_Num> scotch_adjncy;
184 scotch_adjncy.reserve(nb_max_face_neighbour_cell);
189 UniqueArray<float> edgeWeights;
190 edgeWeights.resize(0);
191 UniqueArray<float>* edgeWeightsPtr = &edgeWeights;
197 const Cell& item = *i_item;
199 if (!cellUsedWithConstraints(item))
202 scotch_xadj.add(scotch_adjncy.size());
204 getNeighbourCellsUidWithConstraints(item, neighbour_cells, edgeWeightsPtr);
206 for( Integer z=0; z<neighbour_cells.size(); ++z )
207 scotch_adjncy.add(
static_cast<SCOTCH_Num
>(neighbour_cells[z]));
209 scotch_xadj.add(scotch_adjncy.size());
211 int nparts =
static_cast<int>(nb_part);
214 SharedArray<float> cells_weights;
216 if (nbCellWeight() == 1) {
217 cells_weights = cellsWeightsWithConstraints(1,
true);
221 cells_weights = cellsSizeWithConstraints();
225 PartitionConverter<float,SCOTCH_Num> converter(pm, (
double)SCOTCH_NUMMAX / 2.0, cells_weights);
226 ArrayConverter<float,SCOTCH_Num,PartitionConverter<float,SCOTCH_Num> > scotch_vwgtConvert(cells_weights, converter);
228 ArrayConverter<float,SCOTCH_Num> scotch_vwgtConvert(cells_weights);
230 SharedArray<SCOTCH_Num> scotch_vwgt(scotch_vwgtConvert.array().constView());
236 if (edgeWeights.size() == 0)
238 converter.computeContrib(edgeWeights);
239 ArrayConverter<float,SCOTCH_Num,PartitionConverter<float,SCOTCH_Num> > scotch_ewgtConvert(edgeWeights, converter);
241 ArrayConverter<float,SCOTCH_Num> scotch_ewgtConvert(edgeWeights);
244 SharedArray<SCOTCH_Num> scotch_ewgt((UniqueArray<SCOTCH_Num>)scotch_ewgtConvert.array());
247 MPI_Comm scotch_mpicomm = *(MPI_Comm*)getCommunicator();
248#ifdef ARCANE_PART_DUMP
251 StringBuilder filename(
"mesh-");
252 filename += iteration;
258 GraphDistributor gd(pm);
259#ifndef SCOTCH_MAPPING
260 gd.initWithOneRankPerNode(
true);
262 gd.initWithMaxRank(1);
266 SharedArray<SCOTCH_Num> scotch_part;
268 scotch_xadj = gd.convert<SCOTCH_Num>(scotch_xadj, &scotch_part,
true);
269 scotch_vwgt = gd.convert<SCOTCH_Num>(scotch_vwgt);
270 scotch_adjncy = gd.convert<SCOTCH_Num>(scotch_adjncy);
271 scotch_ewgt = gd.convert<SCOTCH_Num>(scotch_ewgt);
272 scotch_mpicomm = gd.getCommunicator();
274 if (gd.contribute()) {
277#ifndef SCOTCH_MAPPING
279 retval = SCOTCH_dgraphInit(&graph,scotch_mpicomm);
281 error() <<
"Error in dgraphInit() r=" << retval;
283 info() <<
"Build Scotch graph";
286 SCOTCH_randomReset();
288 retval = SCOTCH_dgraphBuild(&graph,
290 scotch_xadj.size()-1,
291 scotch_xadj.size()-1,
296 scotch_adjncy.size(),
297 scotch_adjncy.size(),
298 scotch_adjncy.data(),
303 error() <<
"Error in dgraphBuild() r=" << retval;
307 StringBuilder filename(
"graph-");
308 filename += iteration;
312 String name(filename.toString());
313 FILE* ofile = ::fopen(name.localstr(),
"w");
314 SCOTCH_dgraphSave(&graph,ofile);
321 info() <<
"Check Scotch graph";
322 retval = SCOTCH_dgraphCheck(&graph);
324 error() <<
"Error in dgraphCheck() r=" << retval;
327 SCOTCH_Strat strategy;
328 retval = SCOTCH_stratInit(&strategy);
330 error() <<
"Error in SCOTCH_stratInit() r=" << retval;
333 char* strat = (
char*)malloc(
options()->strategy().length()+1);
334 ::strncpy(strat,
options()->strategy().localstr(),
options()->strategy().length()+1);
335 retval = SCOTCH_stratDgraphMap(&strategy, strat);
337 error() <<
"Error in SCOTCH_stratDgraphMap() r=" << retval;
341 info() <<
"Execute 'SCOTCH_dgraphPart'";
342 retval = SCOTCH_dgraphPart(&graph,
345 scotch_part.unguardedBasePointer()
348 SCOTCH_stratExit(&strategy);
349 SCOTCH_dgraphExit(&graph);
351 error() <<
"Error in dgraphPart() r=" << retval;
354 SCOTCH_Arch architecture;
355 info() <<
"Build Scotch graph";
358 SCOTCH_randomReset();
360 retval = SCOTCH_graphBuild(&graph,
362 scotch_xadj.size()-1,
363 scotch_xadj.unguardedBasePointer(),
367 scotch_adjncy.size(),
368 scotch_adjncy.unguardedBasePointer(),
372 error() <<
"Error in graphBuild() r=" << retval;
378 Array<SCOTCH_Num> sizetab(level);
379 Array<SCOTCH_Num> linktab(level);
381 nb_nodes = nb_rank/32;
382 sizetab[0] = nb_nodes;
386 retval =SCOTCH_archTleaf(&architecture, level, sizetab.unguardedBasePointer(), linktab.unguardedBasePointer());
388 error() <<
"Error in archTleaf() r=" << retval;
390 SCOTCH_Strat strategy;
391 retval = SCOTCH_stratInit(&strategy);
393 error() <<
"Error in SCOTCH_stratInit() r=" << retval;
395 retval = SCOTCH_graphMap(&graph, &architecture, &strategy, scotch_part.unguardedBasePointer());
401 info() <<
"PART retval=" << retval;
406 String filename(
"s_part");
408 FILE* ofile = ::fopen(filename.localstr(),
"w");
409 for (Array<SCOTCH_Num>::const_iterator val(scotch_part.begin()) ; val != scotch_part.end() ; val++)
410 ::fprintf(ofile,
"%d\n", *val);
411 info() <<
"GRAPH SAVED in '" << filename <<
"'";
417 scotch_part = gd.convertBack<SCOTCH_Num>(scotch_part, nb_own_cell);
420 String filename(
"scotch_part");
422 FILE* ofile = ::fopen(filename.localstr(),
"w");
423 for (Array<SCOTCH_Num>::const_iterator val(scotch_part.begin()) ; val != scotch_part.end() ; val++)
424 ::fprintf(ofile,
"%d\n", *val);
425 info() <<
"GRAPH SAVED in '" << filename <<
"'";
435 const Cell& item = *i_item;
436 if (!cellUsedWithConstraints(item))
439 auto new_owner =
static_cast<Int32>(scotch_part[index]);
441 changeCellOwner(item, cells_new_owner, new_owner);
449 cells_new_owner.synchronize();
461ARCANE_REGISTER_SERVICE_PTSCOTCHMESHPARTITIONER(PTScotch,PTScotchMeshPartitioner);
463#if ARCANE_DEFAULT_PARTITIONER == PTSCOTCH_DEFAULT_PARTITIONER
468ARCANE_REGISTER_SERVICE_PTSCOTCHMESHPARTITIONER(DefaultPartitioner,PTScotchMeshPartitioner);
#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.
CaseOptionsPTScotchMeshPartitioner * options() const
Options du jeu de données du service.
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
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 Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Effectue un regroupement sur tous les processeurs. Il s'agit d'une opération collective....
@ PNoRestore
Indique que la variable ne doit pas être restaurée.
@ PNoDump
Indique que la variable ne doit pas être sauvegardée.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
IMesh * mesh() const
Maillage associé au partitionneur.
virtual void dumpObject(String filename="toto")
Dump les informations de repartitionnement sur le disque.
virtual void changeOwnersFromCells()
Positionne les nouveaux propriétaires des noeuds, arêtes et faces à partir des mailles.
Partitionneur de maillage utilisant la bibliothèque PtScotch.
void build() override
Construction de niveau build du service.
void partitionMesh(bool initial_partition) override
Structure contenant les informations pour créer un service.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage info() const
Flot pour un message d'information.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
MeshVariableScalarRefT< Cell, Integer > VariableCellInteger
Grandeur au centre des mailles de type entier.
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.
@ IK_Cell
Entité de maillage de genre maille.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Int32 Integer
Type représentant un entier.