Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
MeshPartitionConstraintMng.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/* MeshPartitionConstraintMng.cc (C) 2000-2023 */
9/* */
10/* Mesh partitioning constraint manager. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/TraceInfo.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/MultiArray2.h"
20#include "arcane/utils/HashTableMap.h"
21#include "arcane/utils/Deleter.h"
22
23#include "arcane/core/IMesh.h"
24#include "arcane/core/IParallelMng.h"
25#include "arcane/core/IItemFamily.h"
26#include "arcane/core/Item.h"
27#include "arcane/core/VariableTypes.h"
28#include "arcane/core/IMeshPartitionConstraint.h"
29
30#include "arcane/mesh/MeshPartitionConstraintMng.h"
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane::mesh
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
48: public TraceAccessor
49{
50 private:
51
52 typedef HashTableMapT<Int64, Int64>::Data ItemFirstUidData;
53
54 public:
55
56 Helper(IMesh* mesh, bool is_debug)
57 : TraceAccessor(mesh->traceMng())
58 , m_mesh(mesh)
59 , m_is_debug(is_debug)
60 , m_true_first_uid(5000, true)
61 , m_uids_owner(5000, true)
62 {
63 }
64
65 public:
66
67 void merge(Int64Array& linked_items, Int32Array& linked_owners);
68 void changeOwners();
69 void computeList(MultiArray2<Int64>& tied_uids);
70
71 private:
72
73 IMesh* m_mesh;
74 bool m_is_debug;
75 HashTableMapT<Int64, Int64> m_true_first_uid;
76 HashTableMapT<Int64, Int32> m_uids_owner;
77};
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
82MeshPartitionConstraintMng::
83MeshPartitionConstraintMng(IMesh* mesh)
85, m_mesh(mesh)
86, m_is_debug(false)
87{
88}
89
90/*---------------------------------------------------------------------------*/
91/*---------------------------------------------------------------------------*/
92
93MeshPartitionConstraintMng::
94~MeshPartitionConstraintMng()
95{
96 m_constraints.each(Deleter());
97 m_weak_constraints.each(Deleter());
98}
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
108{
109 m_constraints.add(constraint);
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
117{
118 m_constraints.remove(constraint);
119}
120
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
126{
127 Helper h(m_mesh, m_is_debug);
128 _computeAndApplyConstraints(h);
129 h.changeOwners();
130}
131
132/*---------------------------------------------------------------------------*/
133/*---------------------------------------------------------------------------*/
134
137{
138 Helper h(m_mesh, m_is_debug);
139 _computeAndApplyConstraints(h);
140 h.computeList(tied_uids);
141}
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
146void MeshPartitionConstraintMng::
147_computeAndApplyConstraints(Helper& h)
148{
149 Int64UniqueArray linked_cells;
150 Int32UniqueArray linked_owners;
151 for (List<IMeshPartitionConstraint*>::Enumerator i(m_constraints); ++i;) {
153 c->addLinkedCells(linked_cells, linked_owners);
154 }
155 h.merge(linked_cells, linked_owners);
156}
157
158void MeshPartitionConstraintMng::
159_computeAndApplyWeakConstraints(Helper& h)
160{
161 Int64UniqueArray linked_cells;
162 Int32UniqueArray linked_owners;
163 for (List<IMeshPartitionConstraint*>::Enumerator i(m_weak_constraints); ++i;) {
164 IMeshPartitionConstraint* c = *i;
165 c->addLinkedCells(linked_cells, linked_owners);
166 }
167 h.merge(linked_cells, linked_owners);
168}
169
170/*---------------------------------------------------------------------------*/
171/*---------------------------------------------------------------------------*/
172
175{
176 m_weak_constraints.add(constraint);
177}
178
181{
182 m_weak_constraints.remove(constraint);
183}
184
187{
188 Helper h(m_mesh, m_is_debug);
189 _computeAndApplyWeakConstraints(h);
190 h.changeOwners();
191}
192
195{
196 Helper h(m_mesh, m_is_debug);
197 _computeAndApplyWeakConstraints(h);
198 h.computeList(tied_uids);
199}
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
204void MeshPartitionConstraintMng::Helper::
205merge(Int64Array& linked_items, Int32Array& linked_owners)
206{
207 //TODO: do not perform an allGather but rather dispatch the list
208 // across multiple processors, with each processor performing
209 // the sorting on its local entities and then performing
210 // several iterations to merge.
211 IParallelMng* pm = m_mesh->parallelMng();
212 Int64UniqueArray global_linked_items;
213 pm->allGatherVariable(linked_items.view(), global_linked_items);
214 Int32UniqueArray global_linked_owners;
215 pm->allGatherVariable(linked_owners.view(), global_linked_owners);
216 Integer nb_global = global_linked_items.size() / 2;
217 info() << "NB_GLOBAL_LINKED_CELL=" << nb_global;
218 //ItemLinkedList linked_list;
219 m_true_first_uid.clear();
220 m_uids_owner.clear();
221 Integer nb_changed = 0;
222 Integer nb_iter = 0;
223 if (m_is_debug) {
224 for (Integer i = 0; i < nb_global; ++i) {
225 Int64 first_uid = global_linked_items[(i * 2)];
226 Int64 second_uid = global_linked_items[(i * 2) + 1];
227 Int32 first_owner = global_linked_owners[i];
228 info() << "LinkedItem: first_uid=" << first_uid
229 << " second_uid=" << second_uid
230 << " first_owner=" << first_owner;
231 }
232 }
233 do {
234 nb_changed = 0;
235 ++nb_iter;
236 for (Integer i = 0; i < nb_global; ++i) {
237 Int64 first_uid = global_linked_items[(i * 2)];
238 Int64 second_uid = global_linked_items[(i * 2) + 1];
239 if (nb_iter == 1) {
240 Int32 first_owner = global_linked_owners[i];
241 m_uids_owner.add(first_uid, first_owner);
242 }
243 // IL FAUT TOUJOURS first_uid < second_uid
244 ItemFirstUidData* first_data = m_true_first_uid.lookup(first_uid);
245 ItemFirstUidData* second_data = m_true_first_uid.lookup(second_uid);
246 Int64 first_data_uid = first_uid;
247 Int64 second_data_uid = second_uid;
248 if (first_data)
249 first_data_uid = first_data->value();
250 if (second_data)
251 second_data_uid = second_data->value();
252 Int64 smallest_uid = math::min(first_data_uid, second_data_uid);
253 if (second_data) {
254 if (second_data_uid > smallest_uid) {
255 if (m_is_debug)
256 info() << "Changed second current=" << second_data->value() << " to " << smallest_uid
257 << " (first=" << first_uid << ",second=" << second_uid << ")";
258 second_data->setValue(smallest_uid);
259 ++nb_changed;
260 }
261 }
262 else {
263 if (m_is_debug)
264 info() << "Changed second add current=" << second_uid << " to " << smallest_uid
265 << " (first=" << first_uid << ",second=" << second_uid << ")";
266 // Attention, cela peut invalider first_data et second_data
267 m_true_first_uid.add(second_uid, smallest_uid);
268 ++nb_changed;
269 }
270
271 if (first_data) {
272 if (first_data_uid > smallest_uid) {
273 if (m_is_debug)
274 info() << "Changed first current=" << first_data->value() << " to " << smallest_uid
275 << " (first=" << first_uid << ",second=" << second_uid << ")";
276 first_data->setValue(smallest_uid);
277 ++nb_changed;
278 }
279 }
280 else {
281 if (m_is_debug)
282 info() << "Changed first add current=" << first_uid << " to " << smallest_uid
283 << " (first=" << first_uid << ",second=" << second_uid << ")";
284 // Attention, cela peut invalider first_data et second_data
285 m_true_first_uid.add(first_uid, smallest_uid);
286 ++nb_changed;
287 }
288 //linked_list.add(first_uid,second_uid);
289 }
290 debug(Trace::High) << "NB_CHANGED=" << nb_changed << " iter=" << nb_iter;
291 } while (nb_changed != 0 && nb_iter < 100);
292 if (nb_iter >= 100)
293 fatal() << "Too many iterations";
294 // Ajoute tous les uids qui ne sont pas encore dans la table de hashage.
295 // Leur propriétaire est celui directement spécifié dans linked_cells
296 for (Integer i = 0; i < nb_global; ++i) {
297 Int64 first_uid = global_linked_items[(i * 2)];
298 Int64 second_uid = global_linked_items[(i * 2) + 1];
299 ItemFirstUidData* first_data = m_true_first_uid.lookup(first_uid);
300 if (!first_data)
301 m_true_first_uid.add(first_uid, first_uid);
302 ItemFirstUidData* second_data = m_true_first_uid.lookup(second_uid);
303 if (!second_data)
304 m_true_first_uid.add(second_uid, first_uid);
305 }
306}
307
308/*---------------------------------------------------------------------------*/
309/*---------------------------------------------------------------------------*/
310
311void MeshPartitionConstraintMng::Helper::
312changeOwners()
313{
314 // Positionne les propriétaires pour chaque maille
315 // de notre sous-domaine.
316 Int64UniqueArray cells_uid;
317 Int32UniqueArray cells_owner;
318
319 for (auto i : m_true_first_uid.buckets())
320 for (ItemFirstUidData* nbid = i; nbid; nbid = nbid->next()) {
321 cells_uid.add(nbid->key());
322 cells_owner.add(m_uids_owner[nbid->value()]);
323 }
324 Integer nb_cell = cells_uid.size();
325 Int32UniqueArray cells_local_id(nb_cell);
326 IItemFamily* cell_family = m_mesh->cellFamily();
327 cell_family->itemsUniqueIdToLocalId(cells_local_id, cells_uid, false);
328 VariableItemInt32& cells_new_owner = cell_family->itemsNewOwner();
329 CellInfoListView cells_internal(cell_family);
330 for (Integer i = 0; i < nb_cell; ++i) {
331 Int32 lid = cells_local_id[i];
332 if (lid != NULL_ITEM_LOCAL_ID) {
333 Cell cell = cells_internal[lid];
334 if (m_is_debug)
335 info() << "Change cell owner uid=" << cell.uniqueId() << " old=" << cell.owner()
336 << " new=" << cells_owner[i];
337 cells_new_owner[cell] = cells_owner[i];
338 }
339 }
340 // Pas besoin de synchroniser car le maillage s'en occupe, ni de mettre
341 // à jour les autres types d'éléments.
342 cells_new_owner.synchronize();
343}
344
345/*---------------------------------------------------------------------------*/
346/*---------------------------------------------------------------------------*/
347
348void MeshPartitionConstraintMng::Helper::
349computeList(MultiArray2<Int64>& tied_uids)
350{
351 IntegerUniqueArray nb_tieds;
352 nb_tieds.reserve(1000);
353 HashTableMapT<Int64, Integer> uids_tied_index(5000, true);
354
355 for (auto i : m_true_first_uid.buckets())
356 for (ItemFirstUidData* nbid = i; nbid; nbid = nbid->next()) {
357 Int64 tied_uid = nbid->value();
358 HashTableMapT<Int64, Integer>::Data* d = uids_tied_index.lookup(tied_uid);
359 if (d)
360 ++nb_tieds[d->value()];
361 else {
362 Integer index = nb_tieds.size();
363 uids_tied_index.add(tied_uid, index);
364 nb_tieds.add(1);
365 }
366 }
367
368 info() << "NB_TIED=" << nb_tieds.size();
369 tied_uids.resize(nb_tieds);
370 nb_tieds.fill(0);
371
372 for (auto i : m_true_first_uid.buckets())
373 for (ItemFirstUidData* nbid = i; nbid; nbid = nbid->next()) {
374 Int64 tied_uid = nbid->value();
375 Integer index = uids_tied_index[tied_uid];
376 Integer index2 = nb_tieds[index];
377 ++nb_tieds[index];
378 tied_uids.setAt(index, index2, nbid->key());
379 }
380#ifdef ARCANE_DEBUG
381 for (Integer i = 0, n = tied_uids.dim1Size(); i < n; ++i) {
382 Int64ConstArrayView uids(tied_uids[i]);
383 debug(Trace::Highest) << " N=" << uids.size();
384 for (Integer j = 0, js = uids.size(); j < js; ++j) {
385 debug(Trace::Highest) << " " << uids[j];
386 }
387 }
388#endif
389}
390
391/*---------------------------------------------------------------------------*/
392/*---------------------------------------------------------------------------*/
393
394} // End namespace Arcane::mesh
395
396/*---------------------------------------------------------------------------*/
397/*---------------------------------------------------------------------------*/
Integer size() const
Number of elements in the vector.
void add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
ArrayView< T > view() const
Mutable view of this array.
Utility class for destroying objects allocated by new.
Definition Deleter.h:33
Hash table for associative arrays.
Interface of a mesh partitioning constraint.
virtual void addLinkedCells(Int64Array &linked_cells, Int32Array &linked_owners)=0
Adds a set of constraints on the cells.
virtual IParallelMng * parallelMng()=0
Parallelism manager.
Interface of the parallelism manager for a subdomain.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Performs an all-gather operation across all processors.
ListEnumeratorT< T > Enumerator
Type of a constant iterator over the entire array.
Base class for multi-sized 2D arrays.
Definition MultiArray2.h:60
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage fatal() const
Flow for a fatal error message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
virtual void computeConstraintList(Int64MultiArray2 &tied_uids)
Computes constraints and returns a list of linked entities.
virtual void removeConstraint(IMeshPartitionConstraint *constraint)
Removes a constraint.
virtual void computeAndApplyWeakConstraints()
Computes and applies constraints.
virtual void addConstraint(IMeshPartitionConstraint *constraint)
Adds a constraint.
virtual void addWeakConstraint(IMeshPartitionConstraint *constraint)
Adds a weak constraint.
virtual void computeWeakConstraintList(Int64MultiArray2 &tied_uids)
Computes constraints and returns a list of linked entities.
virtual void computeAndApplyConstraints()
Computes and applies constraints.
virtual void removeWeakConstraint(IMeshPartitionConstraint *constraint)
Removes a constraint.
__host__ __device__ Real2 min(Real2 a, Real2 b)
Returns the minimum of two Real2.
Definition MathUtils.h:346
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
Array< Int64 > Int64Array
Dynamic one-dimensional array of 64-bit integers.
Definition UtilsTypes.h:125
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
MultiArray2< Int64 > Int64MultiArray2
2D variable size array of 64-bit integers
Definition UtilsTypes.h:419
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
Array< Int32 > Int32Array
Dynamic one-dimensional array of 32-bit integers.
Definition UtilsTypes.h:127
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
std::int32_t Int32
Signed integer type of 32 bits.