Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
MeshPartitionerTesterService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* MeshPartitionerTesterService.cc (C) 2000-2022 */
9/* */
10/* Mesh partitioner tester. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/NotImplementedException.h"
15#include "arcane/utils/CheckedConvert.h"
16
17#include "arcane/core/IParallelMng.h"
18#include "arcane/core/ISubDomain.h"
19#include "arcane/core/CommonVariables.h"
20#include "arcane/core/IMesh.h"
21#include "arcane/core/IMeshSubMeshTransition.h"
22#include "arcane/core/IMeshUtilities.h"
23#include "arcane/core/FactoryService.h"
25#include "arcane/core/Service.h"
26#include "arcane/core/ItemPrinter.h"
27#include "arcane/core/IMeshPartitioner.h"
28#include "arcane/core/BasicService.h"
29
30#include "arcane/core/IMeshPartitionConstraintMng.h"
31#include "arcane/impl/MeshPartitionerTesterService_axl.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane
37{
38
39// TODO: eventually (mid 2022), remove the implementation of 'IMeshPartitioner' and only
40// keep that of 'IMeshPartitionerBase'.
41// This will allow removing all methods with NotImplementedException.
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
54class MeshPartitionerTester
56, public IMeshPartitioner
57{
58 public:
59 public:
60
61 MeshPartitionerTester(const ServiceBuildInfo& sbi);
62
63 public:
64
65 IMesh* mesh() const override { return BasicService::mesh(); }
66
67 void build() override {}
68 void partitionMesh(bool initial_partition) override;
69 void partitionMesh(bool initial_partition, Int32 nb_part) override
70 {
71 ARCANE_UNUSED(initial_partition);
72 ARCANE_UNUSED(nb_part);
73 throw NotImplementedException(A_FUNCINFO);
74 }
75
76 void notifyEndPartition() override {}
77
78 public:
79
80 void setMaximumComputationTime(Real v) override { m_max_computation_time = v; }
81 Real maximumComputationTime() const override { return m_max_computation_time; }
82 void setComputationTimes(RealConstArrayView v) override { m_computation_times.copy(v); }
83 RealConstArrayView computationTimes() const override { return m_computation_times; }
84 void setImbalance(Real v) override { m_imbalance = v; }
85 Real imbalance() const override { return m_imbalance; }
86 void setMaxImbalance(Real v) override { m_max_imbalance = v; }
87 Real maxImbalance() const override { return m_max_imbalance; }
88
89 ArrayView<float> cellsWeight() const override { return m_cells_weight; }
90
91 void setCellsWeight(ArrayView<float> weights, Integer nb_weight) override
92 {
93 m_cells_weight = weights;
94 m_nb_weight = nb_weight;
95 }
96
98 {
99 throw NotImplementedException(A_FUNCINFO);
100 }
101
102 ILoadBalanceMng* loadBalanceMng() const override
103 {
104 throw NotImplementedException(A_FUNCINFO);
105 }
106
107 private:
108
109 Real m_imbalance;
110 Real m_max_imbalance;
111 Real m_max_computation_time;
112 Integer m_nb_weight;
113 ArrayView<float> m_cells_weight;
114 RealUniqueArray m_computation_times;
115};
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
120MeshPartitionerTester::
121MeshPartitionerTester(const ServiceBuildInfo& sbi)
123, m_imbalance(0.0)
124, m_max_imbalance(0.0)
125, m_max_computation_time(0.0)
126, m_nb_weight(0)
127{
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
134partitionMesh(bool initial_partition)
135{
136 IPrimaryMesh* mesh = this->mesh()->toPrimaryMesh();
137
138 Int32 sub_rank_divider = 0;
139 if (options()) {
140 sub_rank_divider = options()->subRankDivider();
141 }
142 info() << "Using MeshPartitionerTester sub_rank_divider=" << sub_rank_divider;
143
144 ISubDomain* sd = subDomain();
145 IParallelMng* pm = sd->parallelMng();
146 Int32 nb_rank = pm->commSize();
147 Int32 sid = pm->commRank();
148
149 if (nb_rank == 1) {
150 warning() << "Can't test the mesh repartitioning with"
151 << "only one subdomain...";
152 return;
153 }
154
155 VariableItemInt32& cells_new_owner = mesh->itemsNewOwner(IK_Cell);
156
157 if (initial_partition) {
158 // The goal is to have a correct partition but not
159 // perfect, especially in the case of cuboids, because after
160 // a real partitioner has nothing to do.
161 // For the initial partitioning, assume that the mesh
162 // initially generates cells with localId() that are topologically similar
163 // to each other.
164 // If we take a consecutive sequence of cells, we thus have a
165 // not too badly formed cell block. To test the partitioner,
166 // we generate 3x more blocks than subdomains and distribute them
167 // among the subdomains.
168 Int64 nb_cell = mesh->ownCells().size();
169 Int64 nb_bloc = nb_rank * 3;
170 Int64 cell_index = 0;
171 ENUMERATE_CELL (icell, mesh->ownCells()) {
172 Cell cell = *icell;
173 // Use Int64 instead of Int32 to ensure no overflow.
174 Int64 new_owner = ((cell_index * nb_bloc) / nb_cell) % nb_rank;
175 cells_new_owner[cell] = CheckedConvert::toInt32(new_owner);
176 ++cell_index;
177 }
178 }
179 else {
180 Integer current_iteration = sd->commonVariables().globalIteration();
181 Integer nb_cell = mesh->ownCells().size();
182
183 //Integer max_cell_index = (nb_rank+1)*5;
184 Integer max_cell_index = nb_cell / 2;
185
186 {
187 Integer cell_index = 0;
188 ENUMERATE_CELL (i_cell, mesh->ownCells()) {
189 Cell cell = *i_cell;
190 Int32 new_owner = cell.owner();
191 if (cell_index < (max_cell_index + (sid * 10))) {
192 // Force the first cell to remain in this subdomain
193 // to ensure there is at least one left.
194 if (cell_index != 0) {
195 Int32 xx = (new_owner * 2 + current_iteration + cell_index / 10 + 17) % nb_rank;
196 if (sub_rank_divider > 0) {
197 xx = xx / sub_rank_divider;
198 xx = (xx * sub_rank_divider + new_owner) % nb_rank;
199 }
200 new_owner = xx;
201 }
202 ++cell_index;
203 }
204 cells_new_owner[cell] = new_owner;
205 }
206 }
207 }
208
209 cells_new_owner.synchronize();
210 if (mesh->partitionConstraintMng()) {
211 // Deal with Tied Cells
212 mesh->partitionConstraintMng()->computeAndApplyConstraints();
213 }
214 mesh->utilities()->changeOwnersFromCells();
215}
216
217/*---------------------------------------------------------------------------*/
218/*---------------------------------------------------------------------------*/
219
221 ServiceProperty("MeshPartitionerTester", ST_SubDomain | ST_CaseOption),
224
225/*---------------------------------------------------------------------------*/
226/*---------------------------------------------------------------------------*/
227
228} // End namespace Arcane
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
This file contains the various service factories and macros for registering services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
ArcaneMeshPartitionerTesterServiceObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsMeshPartitionerTesterService * options() const
Options du jeu de données du service.
Modifiable view of an array of type T.
Cell of a mesh.
Definition Item.h:1300
Int32 globalIteration() const
Current iteration number.
Interface for registering variables for load balancing.
Interface of a mesh partitioner.
Interface of a mesh partitioner.
virtual IPrimaryMesh * toPrimaryMesh()=0
Returns the instance in the form of an IPrimaryMesh.
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.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual const CommonVariables & commonVariables() const =0
Information on standard variables.
virtual IParallelMng * parallelMng()=0
Returns the parallelism manager.
Int32 owner() const
Owner subdomain number of the entity.
Definition Item.h:252
Mesh repartitioning test class.
void setCellsWeight(ArrayView< float > weights, Integer nb_weight) override
Allows defining the weights of objects to be partitioned: ILoadBalanceMng must now be used.
void notifyEndPartition() override
Notification when a re-partitioning finishes (after entity exchange).
Real maxImbalance() const override
Maximum allowed imbalance.
void setMaximumComputationTime(Real v) override
Sets the proportion of computation time.
void setILoadBalanceMng(ILoadBalanceMng *) override
Changes the ILoadBalanceMng to use.
void setComputationTimes(RealConstArrayView v) override
Computation time of this subdomain. The first element indicates the computation time of the subdomain...
Real imbalance() const override
Computation time imbalance.
void setImbalance(Real v) override
Sets the computation time imbalance.
IMesh * mesh() const override
Mesh associated with the partitioner.
void build() override
Build-level construction of the service.
void partitionMesh(bool initial_partition) override
void setMaxImbalance(Real v) override
Sets the maximum allowed imbalance.
Structure containing the information to create a service.
Service creation properties.
TraceMessage info() const
Flow for an information message.
TraceMessage warning() const
Flow for a warning message.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
@ ST_CaseOption
The service is used at the dataset level.
@ ST_SubDomain
The service is used at the subdomain level.
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
Definition UtilsTypes.h:349
@ IK_Cell
Cell mesh entity.
double Real
Type representing a real number.
std::int32_t Int32
Signed integer type of 32 bits.
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:488