Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
LoadBalanceMngInternal.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/* LoadBalanceMngInternal.cc (C) 2000-2024 */
9/* */
10/* Internal class managing mesh load balancing. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/internal/LoadBalanceMngInternal.h"
15
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/MultiArray2.h"
19#include "arcane/utils/ITraceMng.h"
20
21#include "arcane/core/IMesh.h"
22#include "arcane/core/IModule.h"
23#include "arcane/core/ItemPrinter.h"
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29namespace Arcane
30{
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
39class ProxyItemVariableNull
40: public IProxyItemVariable
41{
42 public:
43
44 ProxyItemVariableNull() {}
45 ~ProxyItemVariableNull() {}
46
48 {
49 return 1;
50 }
52 {
53 return 0;
54 }
55
56 protected:
57
58 void deleteMe() {}
59};
60
62static ProxyItemVariableNull nullProxy;
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
71template <typename DataType> class ProxyItemVariable
72: public IProxyItemVariable
73{
74 public:
75
76 explicit ProxyItemVariable(IVariable* var, Integer pos = 0)
77 : m_var(var)
78 , m_pos(pos)
79 {
80 }
81 ~ProxyItemVariable() {}
82
84 {
85 return static_cast<Real>(m_var[i]);
86 }
88 {
89 return m_pos;
90 }
91
92 private:
93
95 Integer m_pos;
96};
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
108{
109 if (!var)
110 return &nullProxy;
111 switch (var->dataType()) {
112 case DT_Real:
113 return new ProxyItemVariable<Real>(var, pos);
114 break;
115 case DT_Int32:
116 return new ProxyItemVariable<Int32>(var, pos);
117 break;
118 default:
119 // TODO : throw an exception
120 return &nullProxy;
121 }
122}
123
124/*---------------------------------------------------------------------------*/
125/*---------------------------------------------------------------------------*/
126
127CriteriaMng::
128CriteriaMng(bool use_legacy_init)
129: m_nb_cells_as_criterion(!use_legacy_init)
130, m_cell_comm(use_legacy_init)
131, m_need_compute_comm(use_legacy_init)
132, m_criteria(new PartitionerMemoryInfo())
133{
134 resetCriteria();
135};
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
143void CriteriaMng::
144init(IMesh* mesh)
145{
146 MeshHandle mesh_handle = mesh->handle();
148
149 m_cell_new_owner = new VariableCellInt32(VariableBuildInfo(mesh_handle, "CellFamilyNewOwner", IVariable::PExecutionDepend | IVariable::PNoDump));
150 m_comm_costs = new VariableFaceReal(VariableBuildInfo(mesh_handle, "LbMngCommCost", vflags));
151 m_mass_over_weight = new VariableCellReal(VariableBuildInfo(mesh_handle, "LbMngOverallMass", vflags));
152 m_mass_res_weight = new VariableCellReal(VariableBuildInfo(mesh_handle, "LbMngResidentMass", vflags));
153 m_event_weights = new VariableCellArrayReal(VariableBuildInfo(mesh_handle, "LbMngMCriteriaWgt", vflags));
154
155 m_comm_costs->fill(1);
156 m_mass_over_weight->fill(1);
157 m_mass_res_weight->fill(1);
158 m_is_init = true;
159 m_mesh = mesh;
160}
161
162/*---------------------------------------------------------------------------*/
163/*---------------------------------------------------------------------------*/
164
165void CriteriaMng::
166resetCriteria()
167{
168 m_mass_vars.clear();
169 m_comm_vars.clear();
170 m_event_vars.resize(1); // First slot booked by MemoryOverAll
171
172 clearVariables();
173}
174
175/*---------------------------------------------------------------------------*/
176/*---------------------------------------------------------------------------*/
177
178void CriteriaMng::
179clearVariables()
180{
181 m_event_weights = nullptr;
182 m_mass_res_weight = nullptr;
183 m_mass_over_weight = nullptr;
184 m_comm_costs = nullptr;
185 m_is_init = false;
186}
187
188/*---------------------------------------------------------------------------*/
189/*---------------------------------------------------------------------------*/
190
191Integer CriteriaMng::
192nbCriteria()
193{
194 Integer count;
195
196 count = m_event_vars.size();
197 count -= ((m_use_mass_as_criterion) ? 0 : 1); // First event is mass !
198 count += ((m_nb_cells_as_criterion) ? 1 : 0);
199 return count;
200}
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
204
206criteria()
207{
208 if (m_use_mass_as_criterion) {
209 StoreIProxyItemVariable cvar(m_mass_over_weight->variable());
210 m_event_vars[0] = cvar;
211 return m_event_vars;
212 }
213 return m_event_vars.subView(1, m_event_vars.size());
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219void CriteriaMng::
220computeCriteria()
221{
222 if (needComputeComm() || useMassAsCriterion()) { // Memory useful only for communication cost or mass lb criterion
223 m_criteria->computeMemory(m_mesh->variableMng());
224 _computeResidentMass();
225 }
226 if (needComputeComm()) {
227 _computeComm();
228 }
229 if (useMassAsCriterion()) {
230 _computeOverallMass();
231 }
232 _computeEvents();
233}
234
235/*---------------------------------------------------------------------------*/
236/*---------------------------------------------------------------------------*/
237
238void CriteriaMng::
239_computeOverallMass()
240{
241 VariableCellReal& mass_over_weigth = *m_mass_over_weight;
242 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
243 mass_over_weigth[icell] = m_criteria->getOverallMemory(*icell);
244 }
245}
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250void CriteriaMng::
251_computeComm()
252{
253 VariableFaceReal& comm_costs = *m_comm_costs;
254
255 Integer penalty = 2; // How many times we do synchronization ?
256
257 if (!m_comm_vars.empty())
258 comm_costs.fill(0);
259
260 for (auto& commvar : m_comm_vars) {
261 ENUMERATE_FACE (iface, m_mesh->ownFaces()) {
262 comm_costs[iface] += commvar[iface] * m_criteria->getResidentMemory(commvar.getPos());
263 }
264 }
265 if (m_cell_comm) {
266 VariableCellReal& mass_res_weight = *m_mass_res_weight;
267 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
268 Real mem = mass_res_weight[icell];
269 for (Face face : icell->faces()) {
270 comm_costs[face] += mem * penalty;
271 }
272 }
273 }
274
275 // Make sure that ghosts contribution is used
276 IVariable* ivar = m_comm_costs->variable();
277 ivar->itemFamily()->reduceFromGhostItems(ivar, Parallel::ReduceSum);
278 m_comm_costs->synchronize();
279}
280
281/*---------------------------------------------------------------------------*/
282/*---------------------------------------------------------------------------*/
283
284void CriteriaMng::
285_computeResidentMass()
286{
287 VariableCellReal& mass_res_weight = *m_mass_res_weight;
288 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
289 mass_res_weight[icell] = m_criteria->getResidentMemory(*icell);
290 }
291}
292
293/*---------------------------------------------------------------------------*/
294/*---------------------------------------------------------------------------*/
295
296void CriteriaMng::
297_computeEvents()
298{
299 ARCANE_CHECK_POINTER(m_mesh);
300
301 ITraceMng* tm = m_mesh->traceMng();
302 m_event_weights->resize(nbCriteria());
303
304 ArrayView<StoreIProxyItemVariable> event_vars = criteria();
305
306 const Int32 nb_event_var = event_vars.size();
307 const Int32 nb_criteria = nbCriteria();
308
309 tm->info() << "CriteriaMng: Compute Events nb_criteria=" << nb_criteria << " nb_event_var=" << nb_event_var;
310
311 VariableCellArrayReal& event_weights = *(m_event_weights);
312 // If no weight is specified and cells are taken as criteria, then
313 // directly fill the weights (otherwise they will not be filled)
314 if (nb_event_var == 0 && m_nb_cells_as_criterion) {
315 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
316 event_weights(icell, 0) = 1.0;
317 }
318 }
319 else {
320 for (Integer i = 0; i < event_vars.size(); ++i) {
321 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
322 Integer count = i;
323 if (m_nb_cells_as_criterion) {
324 count += 1;
325 event_weights(icell, 0) = 1;
326 }
327 event_weights(icell, count) = event_vars[i][icell];
328 }
329 }
330 }
331}
332
333/*---------------------------------------------------------------------------*/
334/*---------------------------------------------------------------------------*/
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
339LoadBalanceMngInternal::
340LoadBalanceMngInternal(bool mass_as_criterion, bool is_legacy_init)
341: m_default_mass_criterion(mass_as_criterion)
342, m_is_legacy_init(is_legacy_init)
343{}
344
345/*---------------------------------------------------------------------------*/
346/*---------------------------------------------------------------------------*/
347
348CriteriaMng& LoadBalanceMngInternal::
349_getCriteria(IMesh* mesh)
350{
351 auto x = m_mesh_criterion.find(mesh);
352 if (x != m_mesh_criterion.end())
353 return *(x->second.get());
354 auto c = createRef<CriteriaMng>(m_is_legacy_init);
355 auto v = m_mesh_criterion.emplace(mesh, c);
356 x = v.first;
357 return *(x->second.get());
358}
359
360/*---------------------------------------------------------------------------*/
361/*---------------------------------------------------------------------------*/
362
363void LoadBalanceMngInternal::
364reset(IMesh* mesh)
365{
366 _getCriteria(mesh).resetCriteria();
367 if (mesh) {
368 mesh->traceMng()->debug() << "LoadBalanceInternal -- Mesh : " << mesh->name() << " -- reset()";
369 }
370}
371
372/*---------------------------------------------------------------------------*/
373/*---------------------------------------------------------------------------*/
374
375void LoadBalanceMngInternal::
376initAccess(IMesh* mesh)
377{
378 if (!mesh)
379 ARCANE_FATAL("Null mesh");
380
381 m_mesh_handle = mesh->handle();
382
383 CriteriaMng& mesh_criterion = _getCriteria(mesh);
384 mesh_criterion.init(mesh);
385 mesh_criterion.defaultMassCriterion(m_default_mass_criterion);
386
387 mesh->traceMng()->info() << "LoadBalanceMngInternal::initAccess():"
388 << " use_memory=" << mesh_criterion.useMassAsCriterion()
389 << " use_nb_cell=" << mesh_criterion.useNbCellsAsCriterion()
390 << " nb_criteria=" << mesh_criterion.nbCriteria();
391
392 // If no criterion is defined, use the number of cells.
393 // At least one criterion is needed otherwise there will be no weights in the partitioning graph.
394 if (mesh_criterion.nbCriteria() == 0)
395 mesh_criterion.setNbCellsAsCriterion(true);
396
397 mesh_criterion.computeCriteria();
398
399 mesh->traceMng()->debug() << "LoadBalanceInternal -- Mesh : " << mesh->name() << " -- initAccess()";
400}
401
402/*---------------------------------------------------------------------------*/
403/*---------------------------------------------------------------------------*/
404
405void LoadBalanceMngInternal::
406endAccess()
407{
408 IMesh* mesh = m_mesh_handle.mesh();
409 if (!mesh)
410 return;
411
412 _getCriteria(mesh).clearVariables();
413
414 mesh->traceMng()->debug() << "LoadBalanceInternal -- Mesh : " << mesh->name() << " -- clearVariables()";
415}
416
417/*---------------------------------------------------------------------------*/
418/*---------------------------------------------------------------------------*/
419
420void LoadBalanceMngInternal::
421addMass(VariableCellInt32& count, IMesh* mesh, const String& entity)
422{
423 CriteriaMng& criterion = _getCriteria(mesh);
424 StoreIProxyItemVariable cvar(count.variable(), criterion.addEntity(entity));
425 criterion.addMass(cvar);
426 mesh->traceMng()->debug() << "Set mass (name=" << count.name() << ") criterion to mesh (name=" << mesh->name() << ")";
427}
428
429/*---------------------------------------------------------------------------*/
430/*---------------------------------------------------------------------------*/
431
432void LoadBalanceMngInternal::
433addCriterion(VariableCellInt32& count, IMesh* mesh)
434{
435 StoreIProxyItemVariable cvar(count.variable());
436 _getCriteria(mesh).addCriterion(cvar);
437 mesh->traceMng()->debug() << "Set criterion (name=" << count.name() << ") criterion to mesh (name=" << mesh->name() << ")";
438}
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442
443void LoadBalanceMngInternal::
444addCriterion(VariableCellReal& count, IMesh* mesh)
445{
446 //std::cerr << "Adding var " << count.variable()->fullName() << " ref # " << count.variable()->nbReference() << std::endl;
447 StoreIProxyItemVariable cvar(count.variable());
448 //std::cerr << "Adding var (2)" << count.variable()->fullName() << " ref # " << count.variable()->nbReference() << std::endl;
449 _getCriteria(mesh).addCriterion(cvar);
450 mesh->traceMng()->debug() << "Set criterion (name=" << count.name() << ") criterion to mesh (name=" << mesh->name() << ")";
451}
452
453/*---------------------------------------------------------------------------*/
454/*---------------------------------------------------------------------------*/
455
456void LoadBalanceMngInternal::
457addCommCost(VariableFaceInt32& count, IMesh* mesh, const String& entity)
458{
459 CriteriaMng& criterion = _getCriteria(mesh);
460 StoreIProxyItemVariable cvar(count.variable(), criterion.addEntity(entity));
461 criterion.addCommCost(cvar);
462 mesh->traceMng()->debug() << "Set CommCost (name=" << count.name() << ") criterion to mesh (name=" << mesh->name() << ")";
463}
464
465/*---------------------------------------------------------------------------*/
466/*---------------------------------------------------------------------------*/
467
468Integer LoadBalanceMngInternal::
469nbCriteria(IMesh* mesh)
470{
471 return _getCriteria(mesh).nbCriteria();
472}
473
474/*---------------------------------------------------------------------------*/
475/*---------------------------------------------------------------------------*/
476
477void LoadBalanceMngInternal::
478setMassAsCriterion(IMesh* mesh, bool active)
479{
480 _getCriteria(mesh).setMassCriterion(active);
481}
482
483/*---------------------------------------------------------------------------*/
484/*---------------------------------------------------------------------------*/
485
486void LoadBalanceMngInternal::
487setNbCellsAsCriterion(IMesh* mesh, bool active)
488{
489 _getCriteria(mesh).setNbCellsAsCriterion(active);
490}
491
492/*---------------------------------------------------------------------------*/
493/*---------------------------------------------------------------------------*/
494
495void LoadBalanceMngInternal::
496setCellCommContrib(IMesh* mesh, bool active)
497{
498 _getCriteria(mesh).setCellCommContrib(active);
499}
500
501/*---------------------------------------------------------------------------*/
502/*---------------------------------------------------------------------------*/
503
504bool LoadBalanceMngInternal::
505cellCommContrib(IMesh* mesh)
506{
507 if (m_mesh_criterion.find(mesh) == m_mesh_criterion.end()) {
508 return true;
509 }
510 return _getCriteria(mesh).cellCommContrib();
511}
512
513/*---------------------------------------------------------------------------*/
514/*---------------------------------------------------------------------------*/
515
516void LoadBalanceMngInternal::
517setComputeComm(IMesh* mesh, bool active)
518{
519 _getCriteria(mesh).setComputeComm(active);
520}
521
522/*---------------------------------------------------------------------------*/
523/*---------------------------------------------------------------------------*/
524
525const VariableFaceReal& LoadBalanceMngInternal::
526commCost(IMesh* mesh)
527{
528 return _getCriteria(mesh).commCost();
529}
530
531/*---------------------------------------------------------------------------*/
532/*---------------------------------------------------------------------------*/
533
534const VariableCellReal& LoadBalanceMngInternal::
535massWeight(IMesh* mesh)
536{
537 return _getCriteria(mesh).massWeight();
538}
539
540/*---------------------------------------------------------------------------*/
541/*---------------------------------------------------------------------------*/
542
543const VariableCellReal& LoadBalanceMngInternal::
544massResWeight(IMesh* mesh)
545{
546 return _getCriteria(mesh).massResWeight();
547}
548
549/*---------------------------------------------------------------------------*/
550/*---------------------------------------------------------------------------*/
551
552const VariableCellArrayReal& LoadBalanceMngInternal::
553mCriteriaWeight(IMesh* mesh)
554{
555 return _getCriteria(mesh).criteriaWeight();
556}
557
558/*---------------------------------------------------------------------------*/
559/*---------------------------------------------------------------------------*/
560
561void LoadBalanceMngInternal::
562notifyEndPartition()
563{
564 IMesh* mesh = m_mesh_handle.mesh();
565 _getCriteria(mesh).fillCellNewOwner();
566}
567
568/*---------------------------------------------------------------------------*/
569/*---------------------------------------------------------------------------*/
570
571} // End namespace Arcane
572
573/*---------------------------------------------------------------------------*/
574/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
Modifiable view of an array of type T.
constexpr ArrayView< T > subView(Integer abegin, Integer asize) noexcept
Sub-view starting from element abegin and containing asize elements.
Interface proxy to access variables defining weights.
Interface of a variable.
Definition IVariable.h:40
virtual eDataType dataType() const =0
Data type managed by the variable (Real, Integer, ...).
@ PTemporary
Indicates that the variable is temporary.
Definition IVariable.h:114
@ PExecutionDepend
Indicates that the variable value is dependent on the execution.
Definition IVariable.h:96
@ PNoDump
Indicates that the variable should not be saved.
Definition IVariable.h:62
Enumerator over a list of entities.
Scalar variable on a mesh entity type.
Class for managing partitioning criteria.
Integer getPos() const
Access to the associated family number.
void deleteMe()
Destroys this object.
Real operator[](ItemEnumerator) const
Access to the value associated with a mesh entity, in the form of a Real.
Implementation of the IProxyItemVariable interface.
Integer getPos() const
Access to the associated family number.
Real operator[](ItemEnumerator i) const
Access to the value associated with a mesh entity, in the form of a Real.
static IProxyItemVariable * proxyItemVariableFactory(IVariable *var, Integer pos=0)
Factory for construction based on the initial variable type.
MeshVariableScalarRefT< Face, Real > VariableFaceReal
Real type quantity at face.
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Real type quantity at cell center.
MeshVariableArrayRefT< Cell, Real > VariableCellArrayReal
Quantity at the cell center of real array type.
MeshVariableScalarRefT< Cell, Int32 > VariableCellInt32
Quantity at the cell center of 32-bit integer type.
MeshVariableScalarRefT< Face, Int32 > VariableFaceInt32
Quantity at the face of 32-bit integer type.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Ref< TrueType > createRef(Args &&... args)
Creates an instance of type TrueType with arguments Args and returns a reference to it.
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.
@ DT_Int32
32-bit integer data type
Definition DataTypes.h:45
@ DT_Real
Real data type.
Definition DataTypes.h:43
std::int32_t Int32
Signed integer type of 32 bits.