Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshPartitionConstraintMng.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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/* Gestionnaire de contraintes de partitionnement de maillage. */
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/IMesh.h"
24#include "arcane/IParallelMng.h"
25#include "arcane/IItemFamily.h"
26#include "arcane/Item.h"
27#include "arcane/VariableTypes.h"
28#include "arcane/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 typedef HashTableMapT<Int64,Int64>::Data ItemFirstUidData;
52 public:
53 Helper(IMesh* mesh,bool is_debug)
54 : TraceAccessor(mesh->traceMng()),
55 m_mesh(mesh), m_is_debug(is_debug), m_true_first_uid(5000,true),
56 m_uids_owner(5000,true)
57 {
58 }
59 public:
61 void changeOwners();
62 void computeList(MultiArray2<Int64> & tied_uids);
63 private:
64 IMesh* m_mesh;
65 bool m_is_debug;
66 HashTableMapT<Int64,Int64> m_true_first_uid;
67 HashTableMapT<Int64,Int32> m_uids_owner;
68};
69
70/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
72
73MeshPartitionConstraintMng::
74MeshPartitionConstraintMng(IMesh* mesh)
75: TraceAccessor(mesh->traceMng())
76, m_mesh(mesh)
77, m_is_debug(false)
78{
79}
80
81/*---------------------------------------------------------------------------*/
82/*---------------------------------------------------------------------------*/
83
84MeshPartitionConstraintMng::
85~MeshPartitionConstraintMng()
86{
87 m_constraints.each(Deleter());
88 m_weak_constraints.each(Deleter());
89}
90
91/*---------------------------------------------------------------------------*/
92/*---------------------------------------------------------------------------*/
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
99{
100 m_constraints.add(constraint);
101}
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
107removeConstraint(IMeshPartitionConstraint* constraint)
108{
109 m_constraints.remove(constraint);
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
117{
118 Helper h(m_mesh,m_is_debug);
119 _computeAndApplyConstraints(h);
120 h.changeOwners();
121}
122
123/*---------------------------------------------------------------------------*/
124/*---------------------------------------------------------------------------*/
125
128{
129 Helper h(m_mesh,m_is_debug);
130 _computeAndApplyConstraints(h);
131 h.computeList(tied_uids);
132}
133
134/*---------------------------------------------------------------------------*/
135/*---------------------------------------------------------------------------*/
136
137void MeshPartitionConstraintMng::
138_computeAndApplyConstraints(Helper& h)
139{
140 Int64UniqueArray linked_cells;
141 Int32UniqueArray linked_owners;
142 for( List<IMeshPartitionConstraint*>::Enumerator i(m_constraints); ++i; ){
143 IMeshPartitionConstraint* c = *i;
144 c->addLinkedCells(linked_cells,linked_owners);
145 }
146 h.merge(linked_cells,linked_owners);
147}
148
149void MeshPartitionConstraintMng::
150_computeAndApplyWeakConstraints(Helper& h)
151{
152 Int64UniqueArray linked_cells;
153 Int32UniqueArray linked_owners;
154 for( List<IMeshPartitionConstraint*>::Enumerator i(m_weak_constraints); ++i; ){
155 IMeshPartitionConstraint* c = *i;
156 c->addLinkedCells(linked_cells,linked_owners);
157 }
158 h.merge(linked_cells,linked_owners);
159}
160
161/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
163
165addWeakConstraint(IMeshPartitionConstraint* constraint)
166{
167 m_weak_constraints.add(constraint);
168}
169
171removeWeakConstraint(IMeshPartitionConstraint* constraint)
172{
173 m_weak_constraints.remove(constraint);
174}
175
178{
179 Helper h(m_mesh,m_is_debug);
180 _computeAndApplyWeakConstraints(h);
181 h.changeOwners();
182}
183
186{
187 Helper h(m_mesh,m_is_debug);
188 _computeAndApplyWeakConstraints(h);
189 h.computeList(tied_uids);
190}
191
192/*---------------------------------------------------------------------------*/
193/*---------------------------------------------------------------------------*/
194
195void MeshPartitionConstraintMng::Helper::
196merge(Int64Array& linked_items,Int32Array& linked_owners)
197{
198 //TODO: ne pas faire un allGather mais plutot dispatcher la liste
199 // sur plusieurs processeurs, chaque processeur faisant
200 // le tri sur ses entités locales et ensuite faire
201 // plusieurs itérations pour fusionner.
202 IParallelMng* pm = m_mesh->parallelMng();
203 Int64UniqueArray global_linked_items;
204 pm->allGatherVariable(linked_items.view(),global_linked_items);
205 Int32UniqueArray global_linked_owners;
206 pm->allGatherVariable(linked_owners.view(),global_linked_owners);
207 Integer nb_global = global_linked_items.size() / 2;
208 info() << "NB_GLOBAL_LINKED_CELL=" << nb_global;
209 //ItemLinkedList linked_list;
210 m_true_first_uid.clear();
211 m_uids_owner.clear();
212 Integer nb_changed = 0;
213 Integer nb_iter = 0;
214 if (m_is_debug){
215 for( Integer i=0; i<nb_global; ++i ){
216 Int64 first_uid = global_linked_items[(i*2)];
217 Int64 second_uid = global_linked_items[(i*2)+1];
218 Int32 first_owner = global_linked_owners[i];
219 info() << "LinkedItem: first_uid=" << first_uid
220 << " second_uid=" << second_uid
221 << " first_owner=" << first_owner;
222 }
223 }
224 do {
225 nb_changed = 0;
226 ++nb_iter;
227 for( Integer i=0; i<nb_global; ++i ){
228 Int64 first_uid = global_linked_items[(i*2)];
229 Int64 second_uid = global_linked_items[(i*2)+1];
230 if (nb_iter==1){
231 Int32 first_owner = global_linked_owners[i];
232 m_uids_owner.add(first_uid,first_owner);
233 }
234 // IL FAUT TOUJOURS first_uid < second_uid
235 ItemFirstUidData* first_data = m_true_first_uid.lookup(first_uid);
236 ItemFirstUidData* second_data = m_true_first_uid.lookup(second_uid);
237 Int64 first_data_uid = first_uid;
238 Int64 second_data_uid = second_uid;
239 if (first_data)
240 first_data_uid = first_data->value();
241 if (second_data)
242 second_data_uid = second_data->value();
243 Int64 smallest_uid = math::min(first_data_uid,second_data_uid);
244 if (second_data){
245 if (second_data_uid>smallest_uid){
246 if (m_is_debug)
247 info() << "Changed second current=" << second_data->value() << " to " << smallest_uid
248 << " (first=" << first_uid << ",second=" << second_uid << ")";
249 second_data->setValue(smallest_uid);
250 ++nb_changed;
251 }
252 }
253 else{
254 if (m_is_debug)
255 info() << "Changed second add current=" << second_uid << " to " << smallest_uid
256 << " (first=" << first_uid << ",second=" << second_uid << ")";
257 // Attention, cela peut invalider first_data et second_data
258 m_true_first_uid.add(second_uid,smallest_uid);
259 ++nb_changed;
260 }
261
262 if (first_data){
263 if (first_data_uid>smallest_uid){
264 if (m_is_debug)
265 info() << "Changed first current=" << first_data->value() << " to " << smallest_uid
266 << " (first=" << first_uid << ",second=" << second_uid << ")";
267 first_data->setValue(smallest_uid);
268 ++nb_changed;
269 }
270 }
271 else{
272 if (m_is_debug)
273 info() << "Changed first add current=" << first_uid << " to " << smallest_uid
274 << " (first=" << first_uid << ",second=" << second_uid << ")";
275 // Attention, cela peut invalider first_data et second_data
276 m_true_first_uid.add(first_uid,smallest_uid);
277 ++nb_changed;
278 }
279 //linked_list.add(first_uid,second_uid);
280 }
281 debug(Trace::High) << "NB_CHANGED=" << nb_changed << " iter=" << nb_iter;
282 } while (nb_changed!=0 && nb_iter<100);
283 if (nb_iter>=100)
284 fatal() << "Too many iterations";
285 // Ajoute tous les uids qui ne sont pas encore dans la table de hashage.
286 // Leur propriétaire est celui directement spécifié dans linked_cells
287 for( Integer i=0; i<nb_global; ++i ){
288 Int64 first_uid = global_linked_items[(i*2)];
289 Int64 second_uid = global_linked_items[(i*2)+1];
290 ItemFirstUidData* first_data = m_true_first_uid.lookup(first_uid);
291 if (!first_data)
292 m_true_first_uid.add(first_uid,first_uid);
293 ItemFirstUidData* second_data = m_true_first_uid.lookup(second_uid);
294 if (!second_data)
295 m_true_first_uid.add(second_uid,first_uid);
296 }
297}
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
301
302void MeshPartitionConstraintMng::Helper::
303changeOwners()
304{
305 // Positionne les propriétaires pour chaque maille
306 // de notre sous-domaine.
307 Int64UniqueArray cells_uid;
308 Int32UniqueArray cells_owner;
309
310 for( auto i : m_true_first_uid.buckets() )
311 for( ItemFirstUidData* nbid = i; nbid; nbid = nbid->next() ){
312 cells_uid.add(nbid->key());
313 cells_owner.add(m_uids_owner[nbid->value()]);
314 }
315 Integer nb_cell = cells_uid.size();
316 Int32UniqueArray cells_local_id(nb_cell);
317 IItemFamily* cell_family = m_mesh->cellFamily();
318 cell_family->itemsUniqueIdToLocalId(cells_local_id,cells_uid,false);
319 VariableItemInt32& cells_new_owner = cell_family->itemsNewOwner();
320 CellInfoListView cells_internal(cell_family);
321 for( Integer i=0; i<nb_cell; ++i ){
322 Int32 lid = cells_local_id[i];
323 if (lid!=NULL_ITEM_LOCAL_ID){
324 Cell cell = cells_internal[lid];
325 if (m_is_debug)
326 info() << "Change cell owner uid=" << cell.uniqueId() << " old=" << cell.owner()
327 << " new=" << cells_owner[i];
328 cells_new_owner[cell] = cells_owner[i];
329 }
330 }
331 // Pas besoin de synchroniser car le maillage s'en occupe, ni de mettre
332 // à jour les autres types d'éléments.
333 cells_new_owner.synchronize();
334}
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
339void MeshPartitionConstraintMng::Helper::
340computeList(MultiArray2<Int64> & tied_uids)
341{
342 IntegerUniqueArray nb_tieds;
343 nb_tieds.reserve(1000);
344 HashTableMapT<Int64,Integer> uids_tied_index(5000,true);
345
346 for( auto i : m_true_first_uid.buckets() )
347 for( ItemFirstUidData* nbid = i; nbid; nbid = nbid->next() ){
348 Int64 tied_uid = nbid->value();
349 HashTableMapT<Int64,Integer>::Data* d = uids_tied_index.lookup(tied_uid);
350 if (d)
351 ++nb_tieds[d->value()];
352 else{
353 Integer index = nb_tieds.size();
354 uids_tied_index.add(tied_uid,index);
355 nb_tieds.add(1);
356 }
357 }
358
359 info() << "NB_TIED=" << nb_tieds.size();
360 tied_uids.resize(nb_tieds);
361 nb_tieds.fill(0);
362
363 for( auto i : m_true_first_uid.buckets() )
364 for( ItemFirstUidData* nbid = i; nbid; nbid = nbid->next() ){
365 Int64 tied_uid = nbid->value();
366 Integer index = uids_tied_index[tied_uid];
367 Integer index2 = nb_tieds[index];
368 ++nb_tieds[index];
369 tied_uids.setAt(index,index2,nbid->key());
370 }
371#ifdef ARCANE_DEBUG
372 for( Integer i=0, n=tied_uids.dim1Size(); i<n; ++i ){
373 Int64ConstArrayView uids(tied_uids[i]);
374 debug(Trace::Highest) << " N=" << uids.size();
375 for( Integer j=0, js=uids.size(); j<js; ++j ){
376 debug(Trace::Highest) << " " << uids[j];
377 }
378 }
379#endif
380}
381
382/*---------------------------------------------------------------------------*/
383/*---------------------------------------------------------------------------*/
384
385} // End namespace Arcane::mesh
386
387/*---------------------------------------------------------------------------*/
388/*---------------------------------------------------------------------------*/
Tableau d'items de types quelconques.
Classe utilitaire pour la destruction des objets alloués par new.
Definition Deleter.h:31
virtual ITraceMng * traceMng()=0
Gestionnaire de message associé
Interface d'une contrainte de partitionnement d'un maillage.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
ListEnumeratorT< T > Enumerator
Type d'un itérateur constant sur tout le tableau.
Definition List.h:243
virtual void computeConstraintList(Int64MultiArray2 &tied_uids)
Calcule les contraintes et retourne une liste d'entités liées.
virtual void computeAndApplyWeakConstraints()
Calcule et applique des contraintes.
virtual void removeWeakConstraint(IMeshPartitionConstraint *constraint)
Supprime une contrainte.
virtual void computeWeakConstraintList(Int64MultiArray2 &tied_uids)
Calcule les contraintes et retourne une liste d'entités liées.
virtual void addWeakConstraint(IMeshPartitionConstraint *constraint)
Ajoute une contrainte.
virtual void addConstraint(IMeshPartitionConstraint *constraint)
Ajoute une contrainte.
virtual void removeConstraint(IMeshPartitionConstraint *constraint)
Supprime une contrainte.
virtual void computeAndApplyConstraints()
Calcule et applique des contraintes.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
ARCCORE_HOST_DEVICE Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Definition MathUtils.h:336
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:325
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:513
MultiArray2< Int64 > Int64MultiArray2
Tableau 2D a taille variable d'entiers 64 bits.
Definition UtilsTypes.h:577
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:327
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:638
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:519
Int32 Integer
Type représentant un entier.