Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshPartitionerBase.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/* MeshPartitionerBase.cc (C) 2000-2026 */
9/* */
10/* Classe de base d'un partitionneur de maillage */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15#include "arcane/utils/HashTableMap.h"
16#include "arcane/utils/ArgumentException.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/StringBuilder.h"
20#include "arcane/utils/MultiArray2.h"
21#include "arcane/utils/Convert.h"
22
23#define INSURE_CONSTRAINTS
24
25#include "arcane/core/ServiceBuildInfo.h"
26#include "arcane/core/IMesh.h"
27#include "arcane/core/IMeshModifier.h"
28#include "arcane/core/IMeshSubMeshTransition.h"
29#include "arcane/core/IMeshUtilities.h"
30#include "arcane/core/IItemFamily.h"
31#include "arcane/core/ItemGroup.h"
32#include "arcane/core/ItemPrinter.h"
33#include "arcane/core/ISubDomain.h"
34#include "arcane/core/IParallelMng.h"
36#include "arcane/core/IVariableMng.h"
37#include "arcane/core/VariableTypes.h"
38#include "arcane/core/CommonVariables.h"
39#include "arcane/core/IMeshPartitionConstraintMng.h"
40#include "arcane/core/ILoadBalanceMng.h"
41#include "arcane/core/MeshKind.h"
42#include "arcane/core/internal/ILoadBalanceMngInternal.h"
43
44#include "arcane/std/MeshPartitionerBase.h"
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
48
49namespace Arcane
50{
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
55MeshPartitionerBase::
56MeshPartitionerBase(const ServiceBuildInfo& sbi)
57: AbstractService(sbi)
58, m_sub_domain(sbi.subDomain())
59, m_mesh(sbi.mesh())
60, m_cell_family(sbi.mesh()->cellFamily())
61, m_lbMng(sbi.subDomain()->loadBalanceMng())
62, m_lb_mng_internal(sbi.subDomain()->loadBalanceMng()->_internalApi())
63{
64 IParallelMng* pm = m_mesh->parallelMng();
65 m_pm_sub = pm;
66 m_is_non_manifold_mesh = m_mesh->meshKind().isNonManifold();
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72MeshPartitionerBase::
73~MeshPartitionerBase()
74{
75 freeConstraints();
76 delete m_unique_id_reference;
77}
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
82void* MeshPartitionerBase::
83getCommunicator() const
84{
85 return m_pm_sub->getMPICommunicator();
86}
87
88/*---------------------------------------------------------------------------*/
89/*---------------------------------------------------------------------------*/
90
91Parallel::Communicator MeshPartitionerBase::
92communicator() const
93{
94 return m_pm_sub->communicator();
95}
96
97/*---------------------------------------------------------------------------*/
98/*---------------------------------------------------------------------------*/
99
100void MeshPartitionerBase::
101changeOwnersFromCells()
102{
103 m_mesh->utilities()->changeOwnersFromCells();
104}
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
109void MeshPartitionerBase::
110initConstraints(bool uidref)
111{
112 m_mesh_dimension = m_mesh->dimension();
113
114 _initArrayCellsWithConstraints();
115
116 _initFilterLidCells();
117
118 if (uidref)
119 _initUidRef();
120
121 _initLid2LidCompacted();
122
123 _initNbCellsWithConstraints();
124
125 m_lb_mng_internal->initAccess(m_mesh);
126
127 info() << "Weight (" << subDomain()->commonVariables().globalIteration()
128 << "): " << m_lb_mng_internal->nbCriteria(m_mesh);
129}
130
131/*---------------------------------------------------------------------------*/
132/*---------------------------------------------------------------------------*/
133
134void MeshPartitionerBase::
135freeConstraints()
136{
137 m_lb_mng_internal->endAccess();
138 _clearCellWgt();
139 m_cells_with_constraints.clear();
140 m_cells_with_weak_constraints.clear();
141 m_nb_cells_with_constraints = 0;
142 m_filter_lid_cells.clear();
143 m_local_id_2_local_id_compacted.clear();
144 delete m_unique_id_reference;
145 m_unique_id_reference = nullptr;
146 m_check.clear();
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
152bool MeshPartitionerBase::
153_createConstraintsLists(Int64MultiArray2& tied_uids)
154{
155 int allLocal = 0;
156
157 // Il est important de définir les contraintes une seule fois !
158 m_cells_with_constraints.clear();
159
160 IItemFamily* cellFamily = m_mesh->itemFamily(IK_Cell);
161
162 // info()<<"tied_uids.dim1Size() = "<<tied_uids.dim1Size();
163 for (Integer i = 0, n = tied_uids.dim1Size(); i < n; ++i) {
164 // la liste d'uniqueId pour une contrainte
165 Int64ConstArrayView uids(tied_uids[i]);
166
167 // cette même liste en localId, sachant que certaines mailles ne sont pas locales
168 Int32UniqueArray lids(uids.size());
169 cellFamily->itemsUniqueIdToLocalId(lids, uids, false);
170
171 // la liste locale en localId (sans les id des mailles sur d'autres procs)
172 Int32UniqueArray lids_loc;
173 lids_loc.reserve(lids.size());
174 for (Integer j = 0, js = lids.size(); j < js; ++j) {
175 Int32 lid = lids[j];
176 if (lid != NULL_ITEM_LOCAL_ID)
177 lids_loc.add(lid);
178 }
179
180 // le tableau avec les mailles de cette contrainte
181 ItemVectorView items_view = cellFamily->view(lids_loc);
182 SharedArray<Cell> cells;
183 for (Integer j = 0, js = items_view.size(); j < js; j++)
184 if (items_view[j].isOwn())
185 cells.add(items_view[j].toCell());
186
187 // Les elements ne sont pas a cheval avec ce processeur
188 allLocal += (((cells.size() == 0) ||
189 (cells.size() == uids.size()))
190 ? 0
191 : 1);
192
193 // on ajoute ce tableau à la liste
194 if (!cells.empty())
195 m_cells_with_constraints.add(cells);
196 }
197 IParallelMng* pm = m_mesh->parallelMng();
198
199 // Retourne la réduction car nous avons besoin que tous les sous-domaines soient corrects
200 int sum = pm->reduce(Parallel::ReduceSum, allLocal);
201 return (sum == 0);
202}
203
204/*---------------------------------------------------------------------------*/
205/*---------------------------------------------------------------------------*/
206
207void MeshPartitionerBase::
208_initArrayCellsWithConstraints()
209{
210 // Il est important de définir les contraintes une seule fois !
211 m_cells_with_constraints.clear();
212 m_cells_with_weak_constraints.clear();
213
214 if (!m_mesh->partitionConstraintMng())
215 return;
216
217 // c'est ici qu'il faut récupérer les listes de listes de mailles
218 // avec comme contrainte de ne pas être séparé lors du repartitionnement
219
220 // un tableau 2D avec les uniqueId des mailles
221 Int64MultiArray2 tied_uids;
222
223 // Calculer tied_uids d'abord car nous ne pouvons pas l'utiliser après la redistribution
224 // Note : C'est correct car ConstraintList est global, donc non modifié par la redistribution.
225 m_mesh->partitionConstraintMng()->computeConstraintList(tied_uids);
226 // Assurez-vous que les contraintes sont locales !
227#ifdef INSURE_CONSTRAINTS
228 if (!_createConstraintsLists(tied_uids)) {
229 if (m_is_non_manifold_mesh)
230 ARCANE_FATAL("Constraints are not supported for non manifold mesh");
231 // Seulement pour la première itération car les contraintes ne sont pas définies au préalable !
232 VariableItemInt32& cells_new_owner(m_mesh->cellFamily()->itemsNewOwner());
233 ENUMERATE_CELL (icell, m_mesh->cellFamily()->allItems()) {
234 cells_new_owner[icell] = (*icell).owner();
235 }
236 m_mesh->modifier()->setDynamic(true);
237 m_mesh->partitionConstraintMng()->computeAndApplyConstraints();
238 m_mesh->utilities()->changeOwnersFromCells();
239 m_mesh->toPrimaryMesh()->exchangeItems();
240#endif // INSURE_CONSTRAINTS
241 if (!_createConstraintsLists(tied_uids))
242 throw FatalErrorException(A_FUNCINFO, "Issue with constraints !");
243#ifdef INSURE_CONSTRAINTS
244 }
245 m_mesh->partitionConstraintMng()->computeWeakConstraintList(tied_uids);
246
247 for (Integer i = 0; i < tied_uids.dim1Size(); ++i) {
248 std::pair<Int64, Int64> ids(tied_uids[i][0], tied_uids[i][1]);
249 m_cells_with_weak_constraints.insert(ids);
250 }
251#endif //INSURE_CONSTRAINTS
252}
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
256void MeshPartitionerBase::
257_initFilterLidCells()
258{
259 CellGroup all_cells = m_mesh->allCells();
260
261 // Mise en place d'un filtre sur les localId avec comme marque un eMarkCellWithConstraint
262 m_filter_lid_cells.resize(m_mesh->cellFamily()->maxLocalId());
263 m_filter_lid_cells.fill(eCellGhost);
264
265 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
266 m_filter_lid_cells[icell->localId()] = eCellClassical;
267 }
268
269 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
270 Array<Cell>& listCell = m_cells_with_constraints[i];
271 m_filter_lid_cells[listCell[0].localId()] = eCellReference;
272 for (Integer j = 1; j < listCell.size(); ++j) {
273#if 0
274 if (m_filter_lid_cells[listCell[j].localId()] != eCellClassical)
275 info() << "Pb in constraint " << i << " with cell[" << j
276 <<"] = " << listCell[j].uniqueId();
277#endif
278 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
279 }
280 }
281}
282
283/*---------------------------------------------------------------------------*/
284/*---------------------------------------------------------------------------*/
285
286void MeshPartitionerBase::
287_checkCreateVar()
288{
289 if (!m_unique_id_reference)
290 m_unique_id_reference = new VariableCellInt64(VariableBuildInfo(m_mesh, "CellUniqueIdRef", IVariable::PNoDump));
291}
292
293/*---------------------------------------------------------------------------*/
294/*---------------------------------------------------------------------------*/
295
296void MeshPartitionerBase::
297_initUidRef()
298{
299 _checkCreateVar();
300 VariableCellInt64 uids_ref(*m_unique_id_reference);
301 // Mise en place d'un tableau d'indirection entre les cell et un uniqueId de référence
302 // permet de connaitre l'uid de la première maille de chacune des contraintes
303 // y compris pour les mailles fantômes
304 ENUMERATE_CELL (icell, m_mesh->allCells()) {
305 uids_ref[icell] = icell->uniqueId();
306 }
307 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
308 Array<Cell>& listCell = m_cells_with_constraints[i];
309 Int64 id_ref = listCell[0].uniqueId();
310 for (Integer j = 1; j < listCell.size(); ++j)
311 uids_ref[listCell[j]] = id_ref;
312 }
313 uids_ref.synchronize();
314}
315
316/*---------------------------------------------------------------------------*/
317/*---------------------------------------------------------------------------*/
318
319void MeshPartitionerBase::
320_initUidRef(VariableCellInteger& cell_renum_uid)
321{
322 _checkCreateVar();
323 VariableCellInt64 uids_ref(*m_unique_id_reference);
324
325 // Mise en place d'un tableau d'indirection entre les cell et un uniqueId de référence
326 // permet de connaitre l'uid de la première maille de chacune des contraintes
327 // y compris pour les mailles fantômes
328 ENUMERATE_CELL (icell, m_mesh->allCells()) {
329 uids_ref[icell] = cell_renum_uid[icell];
330 }
331 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
332 Array<Cell>& listCell = m_cells_with_constraints[i];
333 Int64 id_ref = cell_renum_uid[listCell[0]];
334 for (Integer j = 1; j < listCell.size(); ++j)
335 uids_ref[listCell[j]] = id_ref;
336 }
337 uids_ref.synchronize();
338}
339
340/*---------------------------------------------------------------------------*/
341/*---------------------------------------------------------------------------*/
342
343void MeshPartitionerBase::
344_initLid2LidCompacted()
345{
346 // Construction du tableau d'indirection entre la numérotation locale pour toutes les mailles
347 // et une numérotation sans les mailles fantômes ni les mailles regroupées
348 Integer index = 0;
349 m_local_id_2_local_id_compacted.resize(m_mesh->cellFamily()->maxLocalId());
350 m_check.resize(m_mesh->cellFamily()->maxLocalId());
351 m_check.fill(-1);
352
353 ENUMERATE_CELL (icell, m_mesh->allCells()) {
354 switch (m_filter_lid_cells[icell.itemLocalId()]) {
355 case eCellClassical:
356 case eCellReference:
357 m_local_id_2_local_id_compacted[icell->localId()] = index++;
359 break;
360 case eCellGrouped:
361 case eCellGhost:
362 m_local_id_2_local_id_compacted[icell->localId()] = -1;
363 break;
364 default:
365 throw FatalErrorException(A_FUNCINFO, "Invalid filter value");
366 }
367 }
368 // info()<<"m_local_id_2_local_id_compacted de 0 à "<<index-1;
369}
370
371/*---------------------------------------------------------------------------*/
372/*---------------------------------------------------------------------------*/
373
374void MeshPartitionerBase::
375_initNbCellsWithConstraints()
376{
377 // Calcul le nombre de mailles internes en tenant compte des regroupement suivant les contraintes
378 m_nb_cells_with_constraints = m_mesh->ownCells().size();
379 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
380 m_nb_cells_with_constraints -= (m_cells_with_constraints[i].size() - 1);
381 }
382
383#if 0
384 for (Integer i=0; i<m_cells_with_constraints.size(); ++i){
385 Array<Cell> & listCell = m_cells_with_constraints[i];
386 for (Integer j = 1 ; j < listCell.size() ; ++j) {
387 if (m_filter_lid_cells[listCell[j].localId()] != eCellGrouped) {
388 info() << "Pb in group " << i << " " << listCell[j].localId() << "is not grouped";
389 }
390 }
391 info() << "Group of size " << i << " : " << listCell.size();
392 }
393#endif
394
395 info() << "allCells().size() = " << m_mesh->allCells().size();
396 info() << "ownCells().size() = " << m_mesh->ownCells().size();
397 info() << "m_nb_cells_with_constraints = " << m_nb_cells_with_constraints;
398}
399
400/*---------------------------------------------------------------------------*/
401Int32 MeshPartitionerBase::
402nbOwnCellsWithConstraints() const
403{
404 return m_nb_cells_with_constraints;
405}
406/*---------------------------------------------------------------------------*/
407
408/*---------------------------------------------------------------------------*/
409Integer MeshPartitionerBase::
410nbNeighbourCellsWithConstraints(Cell cell)
411{
412 Integer nbNeighbors = 0;
413
414 if (m_filter_lid_cells[cell.localId()] == eCellClassical || m_filter_lid_cells[cell.localId()] == eCellReference) {
415 Int64UniqueArray neighbors;
416 neighbors.resize(0);
417 getNeighbourCellsUidWithConstraints(cell, neighbors);
418 nbNeighbors = neighbors.size();
419 }
420 else
421 nbNeighbors = -1;
422 return (nbNeighbors);
423}
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426//< Ajouter une maille NGB si elle n'est pas déjà présente.
427Real MeshPartitionerBase::
428_addNgb(const Cell& cell, const Face& face,
429 Int64Array& neighbourcells, Array<bool>& contrib,
430 HashTableMapT<Int64, Int32>& map,
431 Array<float>* ptrcommWeights, Int32 offset,
432 HashTableMapT<Int32, Int32>& lids, bool special)
433{
434 ARCANE_UNUSED(contrib);
435 ARCANE_UNUSED(lids);
436
437 Int64 uid = (*m_unique_id_reference)[cell];
438 bool toAdd = false;
439 Int32 myoffset = neighbourcells.size();
440 Real hg_contrib = 0;
441 const VariableItemReal& commCost = m_lb_mng_internal->commCost(m_mesh);
442 const float face_comm_cost = static_cast<float>(commCost[face]);
443 // Maille traditionnelle, on peut ajouter
444 if ((!special) && (m_filter_lid_cells[cell.localId()] == eCellClassical))
445 toAdd = true;
446 else {
447 HashTableMapT<Int64, Int32>::Data* ptr;
448 ptr = map.lookupAdd(uid, myoffset, toAdd);
449 if (!toAdd && ptrcommWeights) {
450 myoffset = ptr->value();
451 (*ptrcommWeights)[offset + myoffset] += face_comm_cost;
452 }
453 }
454 if (toAdd) {
455 neighbourcells.add(uid);
456 if (ptrcommWeights) {
457 (*ptrcommWeights).add(face_comm_cost);
458 }
459 }
460
461 // TODO faire fonctionner hg_contrib à nouveau.
462 //contrib[myoffset] = true;
463
464 // Compter la contribution de la maille une seule fois, même si elle apparaît plusieurs fois
465 // if (ptrcommWeights) {
466 // lids.lookupAdd(cell.localId(), myoffset, toAdd);
467 // if (toAdd) {
468 // hg_contrib = m_criteria.getResidentMemory(cell);
469 // (*ptrcommWeights)[offset + myoffset] += hg_contrib;
470 // }
471 // }
472 return (hg_contrib);
473}
474
475/*---------------------------------------------------------------------------*/
476Real MeshPartitionerBase::
477getNeighbourCellsUidWithConstraints(Cell cell, Int64Array& neighbourcells,
478 Array<float>* ptrcommWeights,
479 bool no_cell_contrib)
480{
481 ARCANE_UNUSED(no_cell_contrib);
482
483 Int32 offset = 0;
484 Real hg_contrib = 0;
485
486 if ((m_filter_lid_cells[cell.localId()] != eCellClassical) && (m_filter_lid_cells[cell.localId()] != eCellReference))
487 return 0.0;
488
489 if (ptrcommWeights)
490 offset = (*ptrcommWeights).size();
491
492 neighbourcells.resize(0);
493
494#ifdef MY_DEBUG
495 VariableCellInt64 uids_ref(*m_unique_id_reference);
496 Int64 uid = uids_ref[cell];
497#endif /* MY_DEBUG */
498
499 Integer index = -1;
500 Integer nbFaces = cell.nbFace();
501
502 // Calcule d'abord le degré maximum
503 if (m_filter_lid_cells[cell.localId()] == eCellReference) {
504 for (index = 0; index < m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index) {
505 }
506 if (index == m_cells_with_constraints.size())
507 throw FatalErrorException(A_FUNCINFO, "Unable to find cell");
508
509 Array<Cell>& listCell = m_cells_with_constraints[index];
510 nbFaces = 0;
511 // Active la contrainte, mais pas la référence !
512 for (Integer j = 1; j < listCell.size(); ++j) {
513 m_filter_lid_cells[listCell[j].localId()] = eCellInAConstraint;
514 nbFaces += listCell[j].nbFace();
515 }
516 }
517
518 HashTableMapT<Int64, Int32> difficultNgb(nbFaces, true);
519 HashTableMapT<Int32, Int32> lids(nbFaces, true);
520 UniqueArray<bool> contrib(nbFaces);
521 // Array<Real>memUsed(nbFaces); // (HP): bug sur cette structure dans la suite du code
522 contrib.fill(false);
523
524 if (m_filter_lid_cells[cell.localId()] == eCellClassical) {
525 if (m_is_non_manifold_mesh && cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
526 // En cas de maillage non manifold, la maille peut contenir
527 // des arêtes au lieu des faces. Si c'est le cas, on utilise les arêtes
528 // pour déterminer les voisines.
529 // Dans ce cas, on ne prend en compte que les voisines ayant
530 // aussi 'ItemFlags::II_HasEdgeFro1DItems' positionné.
531 for (Edge sub_edge : cell.edges()) {
532 // on ne prend que les arêtes ayant une maille voisine
533 if (sub_edge.nbCell() >= 2) {
534 for (Cell sub_cell : sub_edge.cells()) {
535 if (sub_cell != cell && sub_cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
536 hg_contrib += 1.0;
537 neighbourcells.add((*m_unique_id_reference)[sub_cell]);
538 // TODO: regarder la valeur qu'il faut ajouter pour les communications
539 if (ptrcommWeights)
540 (*ptrcommWeights).add(1.0f);
541 }
542 }
543 }
544 }
545 }
546 else {
547 for (Integer z = 0; z < cell.nbFace(); ++z) {
548 Face face = cell.face(z);
549 // on ne prend que les faces ayant une maille voisine
550 if (face.nbCell() == 2) {
551 // recherche de la maille externe
552 Cell opposite_cell = (face.cell(0) != cell ? face.cell(0) : face.cell(1));
553 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
554 ptrcommWeights, offset, lids);
555 }
556 }
557 }
558 // //Maintenant, ajouter la contribution de la maille au poids de l'arête
559 // if ((ptrcommWeights) &&(!noCellContrib)) {
560 // float mymem = m_criteria.getOverallMemory(cell);
561 // for (Integer j = 0 ; j < neighbourcells.size() ;++j) {
562 // (*ptrcommWeights)[offset+j] += mymem;
563 // }
564 // }
565 }
566 else { //if (m_filter_lid_cells[cell.localId()] == eCellReference){
567 Array<Cell>& listCell = m_cells_with_constraints[index];
568 m_filter_lid_cells[listCell[0].localId()] = eCellInAConstraint;
569 // memUsed.fill(0);
570 for (Integer j = 0; j < listCell.size(); ++j) {
571 contrib.fill(false);
572 // hg_contrib += m_criteria.getOverallMemory(listCell[j]);
573 // memUsed[j] = hg_contrib;
574 for (Integer z = 0; z < listCell[j].nbFace(); ++z) {
575 const Face& face = listCell[j].face(z);
576 // ne considérer que les faces ayant une maille non marquée comme eCellInAConstraint et avec une maille voisine
577 if ((face.nbCell() == 2) && (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint || m_filter_lid_cells[face.cell(1).localId()] != eCellInAConstraint)) {
578 // recherche de la maille externe
579 const Cell& opposite_cell = (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint ? face.cell(0) : face.cell(1));
580 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
581 ptrcommWeights, offset, lids, true);
582 }
583 }
584 // //Maintenant, ajouter la contribution de la maille au poids de l'arête
585 // if (ptrcommWeights && !noCellContrib) {
586 // for (Integer c = 0 ; c < neighbourcells.size() ;++c) {
587 // if (contrib[c])
588 // (*ptrcommWeights)[offset+c] += memUsed[j];
589 // }
590 // }
591 }
592 m_filter_lid_cells[listCell[0].localId()] = eCellReference;
593 for (Integer j = 1; j < listCell.size(); ++j)
594 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
595
596 } // end if eCellReference
597
598 return (hg_contrib);
599}
600/*---------------------------------------------------------------------------*/
601/*---------------------------------------------------------------------------*/
602void MeshPartitionerBase::
603getNeighbourNodesUidWithConstraints(Cell cell, Int64UniqueArray neighbournodes)
604{
605 neighbournodes.resize(cell.nbNode());
606
607 for (Integer z = 0; z < cell.nbNode(); ++z) {
608 neighbournodes[z] = cell.node(z).uniqueId();
609 }
610}
611/*---------------------------------------------------------------------------*/
612/*---------------------------------------------------------------------------*/
613Int32 MeshPartitionerBase::
614localIdWithConstraints(Cell cell)
615{
616 return m_local_id_2_local_id_compacted[cell.localId()];
617}
618/*---------------------------------------------------------------------------*/
619Int32 MeshPartitionerBase::
620localIdWithConstraints(Int32 cell_lid)
621{
622 //info()<<"localIdWithConstraints("<<cell_lid<<") => "<<m_local_id_2_local_id_compacted[cell_lid];
623 return m_local_id_2_local_id_compacted[cell_lid];
624}
625/*---------------------------------------------------------------------------*/
626/*---------------------------------------------------------------------------*/
627void MeshPartitionerBase::
628invertArrayLid2LidCompacted()
629{
630 //info()<<"MeshPartitionerBase::invertArrayLid2LidCompacted()";
631 Integer index = 0;
632 for (Integer i = 0; i < m_mesh->allCells().size(); i++) {
633 if (m_local_id_2_local_id_compacted[i] != -1)
634 m_local_id_2_local_id_compacted[index++] = i;
635 }
636 for (; index < m_mesh->allCells().size(); index++)
637 m_local_id_2_local_id_compacted[index] = -2;
638}
639/*---------------------------------------------------------------------------*/
640
641SharedArray<float> MeshPartitionerBase::
642cellsSizeWithConstraints()
643{
644 VariableCellReal mWgt = m_lb_mng_internal->massResWeight(m_mesh);
645 return _cellsProjectWeights(mWgt);
646}
647
648SharedArray<float> MeshPartitionerBase::
649cellsWeightsWithConstraints(Int32 max_nb_weight, bool ask_lb_cells)
650{
651 ARCANE_UNUSED(ask_lb_cells);
652
653 Int32 nb_weight = max_nb_weight;
654
655 Int32 nb_criteria = m_lb_mng_internal->nbCriteria(m_mesh);
656
657 if (max_nb_weight <= 0 || max_nb_weight > nb_criteria)
658 nb_weight = nb_criteria;
659
660 info() << "Nombre de poids " << nb_weight << " / " << nb_criteria;
661
662 VariableCellArrayReal mWgt = m_lb_mng_internal->mCriteriaWeight(m_mesh);
663 return _cellsProjectWeights(mWgt, nb_weight);
664}
665
666/*---------------------------------------------------------------------------*/
667/*---------------------------------------------------------------------------*/
668
669SharedArray<float> MeshPartitionerBase::
670_cellsProjectWeights(VariableCellArrayReal& cellWgtIn, Int32 nbWgt) const
671{
672 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints() * nbWgt);
673 if (nbWgt > cellWgtIn.arraySize()) {
674 ARCANE_FATAL("Demande trop de poids n={0} array_size={1}", nbWgt, cellWgtIn.arraySize());
675 }
676
677 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
678 if (m_filter_lid_cells[icell->localId()] == eCellClassical)
679 for (int i = 0; i < nbWgt; ++i) {
680 float v = static_cast<float>(cellWgtIn[icell][i]);
681 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()] * nbWgt + i] = v;
682 }
683 }
684 RealUniqueArray w(nbWgt);
685 for (auto& ptr : m_cells_with_constraints) {
686 w.fill(0);
687 for (const auto& cell : ptr) {
688 for (int i = 0; i < nbWgt; ++i)
689 w[i] += cellWgtIn[cell][i];
690 }
691 for (int i = 0; i < nbWgt; ++i)
692 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()] * nbWgt + i] = (float)(w[i]);
693 }
694
695 return cellWgtOut;
696}
697
698/*---------------------------------------------------------------------------*/
699/*---------------------------------------------------------------------------*/
700SharedArray<float> MeshPartitionerBase::
701_cellsProjectWeights(VariableCellReal& cellWgtIn) const
702{
703 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints());
704
705 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
706 if (m_filter_lid_cells[icell->localId()] == eCellClassical)
707 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()]] = (float)cellWgtIn[icell];
708 }
709 for (auto& ptr : m_cells_with_constraints) {
710 Real w = 0;
711 for (Cell cell : ptr) {
712 w += cellWgtIn[cell];
713 }
714 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()]] = (float)w;
715 }
716
717 return cellWgtOut;
718}
719
720/*---------------------------------------------------------------------------*/
721bool MeshPartitionerBase::
722cellUsedWithConstraints(Cell cell)
723{
724 eMarkCellWithConstraint marque = m_filter_lid_cells[cell.localId()];
725 // info()<<"cellUsedWithConstraints("<<cell<<") => "<<(marque == eCellClassical || marque == eCellReference);
726 return (marque == eCellClassical || marque == eCellReference);
727}
728
729bool MeshPartitionerBase::
730cellUsedWithWeakConstraints(std::pair<Int64, Int64>& paired_item)
731{
732 std::pair<Int64, Int64> other_pair(paired_item.second, paired_item.first);
733 return ((m_cells_with_weak_constraints.find(paired_item) != m_cells_with_weak_constraints.end()) || m_cells_with_weak_constraints.find(other_pair) != m_cells_with_weak_constraints.end());
734}
735/*---------------------------------------------------------------------------*/
736/*---------------------------------------------------------------------------*/
737void MeshPartitionerBase::
738changeCellOwner(Item cell, VariableItemInt32& cells_new_owner, Int32 new_owner)
739{
740 // TODO à optimiser pour le cas où il y aurait plein de petites contraintes
741
742 //info()<<"changeCellOwner "<<cell<<", new_owner = "<<new_owner;
743 cells_new_owner[cell] = new_owner;
744
745 if (m_filter_lid_cells[cell.localId()] == eCellReference) {
746 Integer index = -1;
747 for (index = 0; index < m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index) {
748 }
749 if (index == m_cells_with_constraints.size())
750 throw FatalErrorException("MeshPartitionerBase::changeCellOwner(): unable to find cell");
751
752 Array<Cell>& listCell = m_cells_with_constraints[index];
753 //info()<<" changement en plus pour listCell: "<<listCell;
754 for (Integer i = 1; i < listCell.size(); i++)
755 cells_new_owner[listCell[i]] = new_owner;
756 }
757}
758
759/*---------------------------------------------------------------------------*/
760/*---------------------------------------------------------------------------*/
761// Fonctions utiles pour l'ancienne interface de partitionnement.
762
764{
765 m_lb_mng_internal->reset(m_mesh);
766 _clearCellWgt();
767
768 for (int i = 0; i < nb_weight; ++i) {
769 StringBuilder varName("LB_wgt_");
770 varName += (i + 1);
771
772 VariableCellReal myvar(VariableBuildInfo(m_mesh, varName.toString(),
774 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
775 (myvar)[icell] = weights[icell->localId() * nb_weight + i];
776 }
777 m_lb_mng_internal->addCriterion(myvar, m_mesh);
778 }
779
780 m_lb_mng_internal->initAccess(m_mesh);
781 m_lb_mng_internal->setMassAsCriterion(m_mesh, false);
782 m_lb_mng_internal->setNbCellsAsCriterion(m_mesh, false);
783}
784
785/*---------------------------------------------------------------------------*/
786/*---------------------------------------------------------------------------*/
787
788Integer MeshPartitionerBase::
789nbCellWeight() const
790{
791 return math::max(m_lb_mng_internal->nbCriteria(m_mesh), 1);
792}
793
794ArrayView<float> MeshPartitionerBase::
795cellsWeight() const
796{
797 ARCANE_FATAL("NotImplemented");
798}
799
800void MeshPartitionerBase::
801_clearCellWgt()
802{
803 //m_cell_wgt.clear();
804}
805
806/*---------------------------------------------------------------------------*/
807/*---------------------------------------------------------------------------*/
808
810template <class ArrayType> Parallel::Request
812 UniqueArray<ArrayType> data, String header, int step = 1)
813{
815 UniqueArray<Integer> sizes(pm->commSize());
816 UniqueArray<Integer> mysize(1);
817 mysize[0] = data.size();
818
819 pm->gather(mysize, sizes, pm->masterIORank());
820
821 req = pm->send(data, pm->masterIORank(), false);
822
823 if (pm->isMasterIO()) {
824 ofstream ofile;
825
826 ofile.open(filename.localstr());
827 if (!header.null()) {
828 ofile << header;
829 Int64 sum = 0;
830 for (ConstIterT<UniqueArray<Integer>> iter(sizes); iter(); ++iter)
831 sum += *iter;
832 ofile << sum << std::endl;
833 }
834
835 for (int rank = 0; rank < pm->commSize(); ++rank) {
836 UniqueArray<ArrayType> otherdata(sizes[rank]);
837 pm->recv(otherdata, rank, true);
838 for (ConstIterT<ArrayView<ArrayType>> myiter(otherdata); myiter();) {
839 for (int j = 0; (j < step) && myiter(); ++j, ++myiter)
840 ofile << *myiter << " ";
841 ofile << std::endl;
842 }
843 }
844 ofile.close();
845 }
846
847 return req;
848}
849
850/*---------------------------------------------------------------------------*/
851/*---------------------------------------------------------------------------*/
852
854{
855 int i = 0;
856 IParallelMng* pm = m_mesh->parallelMng();
857 String header;
858
859 // ---
860 // Envoyer d'abord l'uid du sommet
861 Int64UniqueArray uid(m_nb_cells_with_constraints);
862 uid.fill(-1);
863 VariableCellInt64 uids_ref(*m_unique_id_reference);
864 i = 0;
865 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
866 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
867 continue;
868
869 uid[i++] = uids_ref[icell];
870 }
871
874 req = centralizePartInfo<Int64>(filebase + ".uid", pm, uid, header);
875 reqs.add(req);
876
877 UniqueArray<float> vwgt = cellsWeightsWithConstraints(0);
878 // Astuce : utiliser Real pour éviter les bugs dans pm->recv ...
879 // TODO: Corriger ceci.
880 UniqueArray<Real> rvwgt(vwgt.size());
881 IterT<UniqueArray<Real>> myiterr(rvwgt);
882 for (ConstIterT<UniqueArray<float>> myiterf(vwgt);
883 myiterf(); ++myiterf, ++myiterr)
884 (*myiterr) = (Real)(*myiterf);
885
886 req = centralizePartInfo<Real>(filebase + ".vwgt", pm, rvwgt, header, nbCellWeight());
887 reqs.add(req);
888
889 // Envoyer les coordonnées des sommets
890 VariableNodeReal3& coords(mesh()->nodesCoordinates());
891 UniqueArray<Real3> my_coords(m_nb_cells_with_constraints);
892 i = 0;
893 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
894 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
895 continue;
896
897 // on calcul un barycentre
898 for (Integer z = 0, zs = (*icell).nbNode(); z < zs; ++z) {
899 const Node& node = (*icell).node(z);
900 my_coords[i] += coords[node];
901 }
902 my_coords[i] /= Convert::toDouble((*icell).nbNode());
903 i++;
904 }
905 req = centralizePartInfo<Real3>(filebase + ".xyz", pm, my_coords, header);
906 reqs.add(req);
907
908 // Envoyer les relations au maître
910 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
911 Int64UniqueArray neighbourcells;
912 UniqueArray<float> commWeights;
913
914 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
915 continue;
916 getNeighbourCellsUidWithConstraints(*icell, neighbourcells, &commWeights);
917 Int64 my_uid = uids_ref[icell];
918 for (Integer j = 0; j < neighbourcells.size(); ++j) {
919 if (neighbourcells[j] > my_uid)
920 continue;
921 Real3 tmp(static_cast<Real>(my_uid + 1), static_cast<Real>(neighbourcells[j] + 1), commWeights[j]);
922 nnz.add(tmp);
923 }
924 }
925 Integer nbvertices;
926 nbvertices = pm->reduce(Parallel::ReduceSum, m_nb_cells_with_constraints);
927 StringBuilder myheader = "%%MatrixMarket matrix coordinate real symmetric\n";
928 myheader += nbvertices;
929 myheader += " ";
930 myheader += nbvertices;
931 myheader += " ";
932 req = centralizePartInfo<Real3>(filebase + ".mtx", pm, nnz, myheader.toString());
933 reqs.add(req);
934
935 pm->waitAllRequests(reqs);
936}
937
938/*---------------------------------------------------------------------------*/
939/*---------------------------------------------------------------------------*/
940
941} // End namespace Arcane
942
943/*---------------------------------------------------------------------------*/
944/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
Integer size() const
Nombre d'éléments du vecteur.
Classe de base d'un service.
Vue modifiable d'un tableau d'un type T.
void fill(const DataType &data)
Remplissage du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
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.
interval d'itérateurs constant
Exception lorsqu'une erreur fatale est survenue.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual bool isMasterIO() const =0
true si l'instance est un gestionnaire maître des entrées/sorties.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Bloque en attendant que les requêtes rvalues soient terminées.
virtual void gather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf, Int32 rank)=0
Effectue un regroupement sur un processeurs. Il s'agit d'une opération collective....
virtual Integer masterIORank() const =0
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai).
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
@ PTemporary
Indique que la variable est temporaire.
Definition IVariable.h:116
@ PExecutionDepend
Indique que la valeur de la variable est dépendante de l'exécution.
Definition IVariable.h:96
@ PNoDump
Indique que la variable ne doit pas être sauvegardée.
Definition IVariable.h:62
interval d'itérateursCette classe gère un couple d'itérateurs autorisant la modification des éléments...
void setCellsWeight(ArrayView< float > weights, Integer nb_weight) override
Permet de définir les poids des objets à partitionner : on doit utiliser le ILoadBalanceMng maintenan...
IMesh * mesh() const override
Maillage associé au partitionneur.
virtual void dumpObject(String filename="toto")
Dump les informations de repartitionnement sur le disque.
Requête d'un message.
Definition Request.h:77
Noeud d'un maillage.
Definition Item.h:582
Classe gérant un vecteur réel de 3 dimensions.
Structure contenant les informations pour créer un service.
Constructeur de chaîne de caractère unicode.
String toString() const
Retourne la chaîne de caractères construite.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:305
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:407
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Grandeur au centre des mailles de type réel.
MeshVariableScalarRefT< Cell, Int64 > VariableCellInt64
Grandeur au centre des mailles de type entier 64 bits.
ItemVariableScalarRefT< Real > VariableItemReal
Grandeur de type réel.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableArrayRefT< Cell, Real > VariableCellArrayReal
Grandeur au centre des mailles de type tableau de réel.
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
double toDouble(Real r)
Convertit un Real en double.
@ ReduceSum
Somme des valeurs.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:337
Parallel::Request centralizePartInfo(String filename, IParallelMng *pm, UniqueArray< ArrayType > data, String header, int step=1)
Fonction auxiliaire pour dumper le graphe.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
MultiArray2< Int64 > Int64MultiArray2
Tableau 2D a taille variable d'entiers 64 bits.
Definition UtilsTypes.h:417
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:478
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:339
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:347
double Real
Type représentant un réel.
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52