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/core/ISubDomain.h"
26#include "arcane/core/IParallelMng.h"
28#include "arcane/core/IMeshSubMeshTransition.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/core/CommonVariables.h"
39#include "arcane_internal_config.h"
44#define MPICH_SKIP_MPICXX
45#define OMPI_SKIP_MPICXX
51#include "arcane/std/MeshPartitionerBase.h"
52#include "arcane/std/PTScotchMeshPartitioner_axl.h"
53#include "arcane/std/PartitionConverter.h"
54#include "arcane/std/GraphDistributor.h"
74class PTScotchMeshPartitioner
94PTScotchMeshPartitioner::
95PTScotchMeshPartitioner(
const ServiceBuildInfo& sbi)
96: ArcanePTScotchMeshPartitionerObject(sbi)
106 Int32 nb_part =
mesh()->parallelMng()->commSize();
116 ARCANE_UNUSED(initial_partition);
118 info() <<
"Load balancing with PTScotch\n";
124 bool dumpGraph =
false;
125 bool checkGraph =
false;
127 dumpGraph =
options()->dumpGraph();
128 checkGraph =
options()->checkGraph();
131 if (nb_part < nb_rank)
132 throw ArgumentException(A_FUNCINFO,
"partition with nb_part<nb_rank");
135 initConstraints(
false);
143 Integer nb_own_cell = nbOwnCellsWithConstraints();
146 UniqueArray<SCOTCH_Num> scotch_vtkdist(nb_rank + 1);
148 scotch_vtkdist[0] = 0;
149 for (
Integer i = 0; i < nb_rank; ++i) {
150 total_nb_cell += global_nb_own_cell[i];
151 scotch_vtkdist[i + 1] =
static_cast<SCOTCH_Num
>(total_nb_cell);
159 Integer nb_max_face_neighbour_cell = 0;
165 const Cell& item = *i_item;
166 if (cellUsedWithConstraints(item)) {
167 cell_scotch_uid[item] = mid;
170 nb_max_face_neighbour_cell += item.nbFace();
173 cell_scotch_uid.synchronize();
176 _initUidRef(cell_scotch_uid);
179 cell_scotch_uid.setUsed(
false);
181 SharedArray<SCOTCH_Num> scotch_xadj;
182 scotch_xadj.reserve(nb_own_cell + 1);
184 SharedArray<SCOTCH_Num> scotch_adjncy;
185 scotch_adjncy.reserve(nb_max_face_neighbour_cell);
190 UniqueArray<float> edgeWeights;
191 edgeWeights.resize(0);
192 UniqueArray<float>* edgeWeightsPtr = &edgeWeights;
198 const Cell& item = *i_item;
200 if (!cellUsedWithConstraints(item))
203 scotch_xadj.
add(scotch_adjncy.size());
205 getNeighbourCellsUidWithConstraints(item, neighbour_cells, edgeWeightsPtr);
207 for (
Integer z = 0; z < neighbour_cells.size(); ++z)
208 scotch_adjncy.add(
static_cast<SCOTCH_Num
>(neighbour_cells[z]));
210 scotch_xadj.add(scotch_adjncy.size());
212 int nparts =
static_cast<int>(nb_part);
215 SharedArray<float> cells_weights;
217 if (nbCellWeight() == 1) {
218 cells_weights = cellsWeightsWithConstraints(1,
true);
222 cells_weights = cellsSizeWithConstraints();
226 PartitionConverter<float, SCOTCH_Num> converter(pm, (
double)SCOTCH_NUMMAX / 2.0, cells_weights);
227 ArrayConverter<float, SCOTCH_Num, PartitionConverter<float, SCOTCH_Num>> scotch_vwgtConvert(cells_weights, converter);
229 ArrayConverter<float, SCOTCH_Num> scotch_vwgtConvert(cells_weights);
231 SharedArray<SCOTCH_Num> scotch_vwgt(scotch_vwgtConvert.array().constView());
235 if (edgeWeights.size() == 0)
237 converter.computeContrib(edgeWeights);
238 ArrayConverter<float, SCOTCH_Num, PartitionConverter<float, SCOTCH_Num>> scotch_ewgtConvert(edgeWeights, converter);
240 ArrayConverter<float, SCOTCH_Num> scotch_ewgtConvert(edgeWeights);
243 SharedArray<SCOTCH_Num> scotch_ewgt((UniqueArray<SCOTCH_Num>)scotch_ewgtConvert.array());
245 MPI_Comm scotch_mpicomm = *(MPI_Comm*)getCommunicator();
246#ifdef ARCANE_PART_DUMP
248 Integer iteration =
mesh()->subDomain()->commonVariables().globalIteration();
249 StringBuilder filename(
"mesh-");
250 filename += iteration;
255 GraphDistributor gd(pm);
256#ifndef SCOTCH_MAPPING
257 gd.initWithOneRankPerNode(
true);
259 gd.initWithMaxRank(1);
263 SharedArray<SCOTCH_Num> scotch_part;
265 scotch_xadj = gd.convert<SCOTCH_Num>(scotch_xadj, &scotch_part,
true);
266 scotch_vwgt = gd.convert<SCOTCH_Num>(scotch_vwgt);
267 scotch_adjncy = gd.convert<SCOTCH_Num>(scotch_adjncy);
268 scotch_ewgt = gd.convert<SCOTCH_Num>(scotch_ewgt);
269 scotch_mpicomm = gd.getCommunicator();
271 if (gd.contribute()) {
274#ifndef SCOTCH_MAPPING
276 retval = SCOTCH_dgraphInit(&graph, scotch_mpicomm);
278 error() <<
"Error in dgraphInit() r=" << retval;
280 info() <<
"Build Scotch graph";
283 SCOTCH_randomReset();
285 retval = SCOTCH_dgraphBuild(&graph,
287 scotch_xadj.size() - 1,
288 scotch_xadj.size() - 1,
293 scotch_adjncy.size(),
294 scotch_adjncy.size(),
295 scotch_adjncy.data(),
300 error() <<
"Error in dgraphBuild() r=" << retval;
303 Integer iteration =
mesh()->subDomain()->commonVariables().globalIteration();
304 StringBuilder filename(
"graph-");
305 filename += iteration;
309 String name(filename.toString());
310 FILE* ofile = ::fopen(name.localstr(),
"w");
311 SCOTCH_dgraphSave(&graph, ofile);
317 info() <<
"Check Scotch graph";
318 retval = SCOTCH_dgraphCheck(&graph);
320 error() <<
"Error in dgraphCheck() r=" << retval;
323 SCOTCH_Strat strategy;
324 retval = SCOTCH_stratInit(&strategy);
326 error() <<
"Error in SCOTCH_stratInit() r=" << retval;
329 char* strat = (
char*)malloc(
options()->strategy().length() + 1);
330 ::strncpy(strat,
options()->strategy().localstr(),
options()->strategy().length() + 1);
331 retval = SCOTCH_stratDgraphMap(&strategy, strat);
333 error() <<
"Error in SCOTCH_stratDgraphMap() r=" << retval;
337 info() <<
"Execute 'SCOTCH_dgraphPart'";
338 retval = SCOTCH_dgraphPart(&graph,
341 scotch_part.unguardedBasePointer()
344 SCOTCH_stratExit(&strategy);
345 SCOTCH_dgraphExit(&graph);
347 error() <<
"Error in dgraphPart() r=" << retval;
350 SCOTCH_Arch architecture;
351 info() <<
"Build Scotch graph";
354 SCOTCH_randomReset();
356 retval = SCOTCH_graphBuild(&graph,
358 scotch_xadj.size() - 1,
359 scotch_xadj.unguardedBasePointer(),
363 scotch_adjncy.size(),
364 scotch_adjncy.unguardedBasePointer(),
368 error() <<
"Error in graphBuild() r=" << retval;
374 Array<SCOTCH_Num> sizetab(level);
375 Array<SCOTCH_Num> linktab(level);
377 nb_nodes = nb_rank / 32;
378 sizetab[0] = nb_nodes;
382 retval = SCOTCH_archTleaf(&architecture, level, sizetab.unguardedBasePointer(), linktab.unguardedBasePointer());
384 error() <<
"Error in archTleaf() r=" << retval;
386 SCOTCH_Strat strategy;
387 retval = SCOTCH_stratInit(&strategy);
389 error() <<
"Error in SCOTCH_stratInit() r=" << retval;
391 retval = SCOTCH_graphMap(&graph, &architecture, &strategy, scotch_part.unguardedBasePointer());
395 info() <<
"PART retval=" << retval;
399 String filename(
"s_part");
401 FILE* ofile = ::fopen(filename.localstr(),
"w");
403 ::fprintf(ofile,
"%d\n", *val);
404 info() <<
"GRAPH SAVED in '" << filename <<
"'";
410 scotch_part = gd.convertBack<SCOTCH_Num>(scotch_part, nb_own_cell);
413 String filename(
"scotch_part");
415 FILE* ofile = ::fopen(filename.localstr(),
"w");
417 ::fprintf(ofile,
"%d\n", *val);
418 info() <<
"GRAPH SAVED in '" << filename <<
"'";
428 const Cell& item = *i_item;
429 if (!cellUsedWithConstraints(item))
432 auto new_owner =
static_cast<Int32>(scotch_part[index]);
434 changeCellOwner(item, cells_new_owner, new_owner);
441 cells_new_owner.synchronize();
455#if ARCANE_DEFAULT_PARTITIONER == PTSCOTCH_DEFAULT_PARTITIONER
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
ArcanePTScotchMeshPartitionerObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsPTScotchMeshPartitioner * options() const
Options du jeu de données du service.
void add(ConstReferenceType val)
Adds element val to the end of the array.
ArrayIterator< const_pointer > const_iterator
Type of the constant iterator over an array element.
virtual CellGroup ownCells()=0
Group of all domain-specific cells.
Interface of a mesh partitioner.
Interface of a mesh partitioner.
virtual IMesh * mesh() const =0
Mesh associated with the partitioner.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Performs an all-gather operation across all processors. This is a collective operation....
@ PNoRestore
Indicates that the variable should not be restored.
@ PNoDump
Indicates that the variable should not be saved.
virtual void dumpObject(String filename="toto")
Dumps the partitioning information to disk.
virtual void changeOwnersFromCells()
Positions the new owners of nodes, edges and faces based on the cells.
Mesh partitioner using the PtScotch library.
void build() override
Build-level construction of the service.
void partitionMesh(bool initial_partition) override
Structure containing the information to create a service.
Service creation properties.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
ItemGroupT< Cell > CellGroup
Group of cells.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
MeshVariableScalarRefT< Cell, Integer > VariableCellInteger
Quantity at the cell center of integer type.
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Int32 Integer
Type representing an integer.
@ ST_SubDomain
The service is used at the subdomain level.
@ IK_Cell
Cell mesh entity.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
@ Cell
The mesh is AMR by cell.
std::int32_t Int32
Signed integer type of 32 bits.