Arcane  v3.16.2.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-2025 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-2025 */
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
22#define INSURE_CONSTRAINTS
23
24#include "arcane/core/ServiceBuildInfo.h"
25#include "arcane/core/IMesh.h"
26#include "arcane/core/IMeshModifier.h"
27#include "arcane/core/IMeshSubMeshTransition.h"
28#include "arcane/core/IMeshUtilities.h"
29#include "arcane/core/IItemFamily.h"
30#include "arcane/core/ItemGroup.h"
31#include "arcane/core/ItemPrinter.h"
32#include "arcane/core/ISubDomain.h"
33#include "arcane/core/IParallelMng.h"
35#include "arcane/core/IVariableMng.h"
36#include "arcane/core/VariableTypes.h"
37#include "arcane/core/CommonVariables.h"
38#include "arcane/core/IMeshPartitionConstraintMng.h"
39#include "arcane/core/ILoadBalanceMng.h"
40#include "arcane/core/MeshKind.h"
41#include "arcane/core/internal/ILoadBalanceMngInternal.h"
42
43#include "arcane/std/MeshPartitionerBase.h"
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48namespace Arcane
49{
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54MeshPartitionerBase::
55MeshPartitionerBase(const ServiceBuildInfo& sbi)
56: AbstractService(sbi)
57, m_sub_domain(sbi.subDomain())
58, m_mesh(sbi.mesh())
59, m_cell_family(sbi.mesh()->cellFamily())
60, m_lbMng(sbi.subDomain()->loadBalanceMng())
61, m_lb_mng_internal(sbi.subDomain()->loadBalanceMng()->_internalApi())
62{
63 IParallelMng* pm = m_mesh->parallelMng();
64 m_pm_sub = pm;
65 m_is_non_manifold_mesh = m_mesh->meshKind().isNonManifold();
66}
67
68/*---------------------------------------------------------------------------*/
69/*---------------------------------------------------------------------------*/
70
71MeshPartitionerBase::
72~MeshPartitionerBase()
73{
74 freeConstraints();
75 delete m_unique_id_reference;
76}
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80
81void* MeshPartitionerBase::
82getCommunicator() const
83{
84 return m_pm_sub->getMPICommunicator();
85}
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
90Parallel::Communicator MeshPartitionerBase::
91communicator() const
92{
93 return m_pm_sub->communicator();
94}
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
98
99void MeshPartitionerBase::
100changeOwnersFromCells()
101{
102 m_mesh->utilities()->changeOwnersFromCells();
103}
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108void MeshPartitionerBase::
109initConstraints(bool uidref)
110{
111 m_mesh_dimension = m_mesh->dimension();
112
113 _initArrayCellsWithConstraints();
114
115 _initFilterLidCells();
116
117 if (uidref)
118 _initUidRef();
119
120 _initLid2LidCompacted();
121
122 _initNbCellsWithConstraints();
123
124 m_lb_mng_internal->initAccess(m_mesh);
125
126 info() << "Weight (" << subDomain()->commonVariables().globalIteration()
127 << "): " << m_lb_mng_internal->nbCriteria(m_mesh);
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133void MeshPartitionerBase::
134freeConstraints()
135{
136 m_lb_mng_internal->endAccess();
137 _clearCellWgt();
138 m_cells_with_constraints.clear();
139 m_cells_with_weak_constraints.clear();
140 m_nb_cells_with_constraints = 0;
141 m_filter_lid_cells.clear();
142 m_local_id_2_local_id_compacted.clear();
143 delete m_unique_id_reference;
144 m_unique_id_reference = nullptr;
145 m_check.clear();
146}
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
151bool MeshPartitionerBase::
152_createConstraintsLists(Int64MultiArray2& tied_uids)
153{
154 int allLocal = 0;
155
156 // It is important to define constraints only once !
157 m_cells_with_constraints.clear();
158
159 IItemFamily* cellFamily = m_mesh->itemFamily(IK_Cell);
160
161// info()<<"tied_uids.dim1Size() = "<<tied_uids.dim1Size();
162 for( Integer i=0, n=tied_uids.dim1Size(); i<n; ++i ){
163 // la liste d'uniqueId pour une contrainte
164 Int64ConstArrayView uids(tied_uids[i]);
165
166 // cette même liste en localId, sachant que certaines mailles ne sont pas locales
167 Int32UniqueArray lids(uids.size());
168 cellFamily->itemsUniqueIdToLocalId(lids,uids,false);
169
170 // la liste locale en localId (sans les id des mailles sur d'autres procs)
171 Int32UniqueArray lids_loc;
172 lids_loc.reserve(lids.size());
173 for( Integer j=0, js=lids.size(); j<js; ++j ){
174 Int32 lid = lids[j];
175 if (lid!=NULL_ITEM_LOCAL_ID)
176 lids_loc.add(lid);
177 }
178
179 // le tableau avec les mailles de cette contrainte
180 ItemVectorView items_view = cellFamily->view(lids_loc);
181 SharedArray<Cell> cells;
182 for ( Integer j=0, js=items_view.size(); j<js; j++)
183 if (items_view[j].isOwn())
184 cells.add(items_view[j].toCell());
185
186 // Les elements ne sont pas a cheval avec ce processeur
187 allLocal += (((cells.size() == 0)||
188 (cells.size() == uids.size()))?0:1);
189
190 // on ajoute ce tableau à la liste
191 if (!cells.empty())
192 m_cells_with_constraints.add(cells);
193 }
194 IParallelMng* pm = m_mesh->parallelMng();
195
196 // Return reduction because we need all subdomains to be correct
197 int sum = pm->reduce(Parallel::ReduceSum,allLocal);
198 return (sum == 0);
199}
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
204void MeshPartitionerBase::
205_initArrayCellsWithConstraints()
206{
207 // It is important to define constraints only once !
208 m_cells_with_constraints.clear();
209 m_cells_with_weak_constraints.clear();
210
211 if (!m_mesh->partitionConstraintMng())
212 return;
213
214 // c'est ici qu'il faut récupérer les listes de listes de mailles
215 // avec comme contrainte de ne pas être séparé lors du repartitionnement
216
217 // un tableau 2D avec les uniqueId des mailles
218 Int64MultiArray2 tied_uids;
219
220 // Compute tied_uids first because we cannot use this after redistribution
221 // Nota: It is correct to do so because ConstraintList is global, so not changed
222 // by the redistribution.
223 m_mesh->partitionConstraintMng()->computeConstraintList(tied_uids);
224 // Be sure that constraints are local !
225#ifdef INSURE_CONSTRAINTS
226 if (!_createConstraintsLists(tied_uids)) {
227 if (m_is_non_manifold_mesh)
228 ARCANE_FATAL("Constraints are not supported for non manifold mesh");
229 // Only appends for the first iteration because constraints are not set before !
230 VariableItemInt32& cells_new_owner(m_mesh->cellFamily()->itemsNewOwner());
231 ENUMERATE_CELL(icell,m_mesh->cellFamily()->allItems()){
232 cells_new_owner[icell] = (*icell).owner();
233 }
234 m_mesh->modifier()->setDynamic(true);
235 m_mesh->partitionConstraintMng()->computeAndApplyConstraints();
236 m_mesh->utilities()->changeOwnersFromCells();
237 m_mesh->toPrimaryMesh()->exchangeItems();
238#endif // INSURE_CONSTRAINTS
239 if (!_createConstraintsLists(tied_uids))
240 throw FatalErrorException(A_FUNCINFO, "Issue with constraints !");
241#ifdef INSURE_CONSTRAINTS
242 }
243 m_mesh->partitionConstraintMng()->computeWeakConstraintList(tied_uids);
244
245 for(Integer i=0;i<tied_uids.dim1Size();++i)
246 {
247 std::pair<Int64, Int64> ids(tied_uids[i][0],tied_uids[i][1]);
248 m_cells_with_weak_constraints.insert(ids);
249 }
250#endif //INSURE_CONSTRAINTS
251
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/*---------------------------------------------------------------------------*/
343
344void MeshPartitionerBase::
345_initLid2LidCompacted()
346{
347 // Construction du tableau d'indirection entre la numérotation locale pour toutes les mailles
348 // et une numérotation sans les mailles fantômes ni les mailles regroupées
349 Integer index = 0;
350 m_local_id_2_local_id_compacted.resize(m_mesh->cellFamily()->maxLocalId());
351 m_check.resize(m_mesh->cellFamily()->maxLocalId());
352 m_check.fill(-1);
353
354 ENUMERATE_CELL(icell, m_mesh->allCells()){
355 switch (m_filter_lid_cells[icell.itemLocalId()]){
356 case eCellClassical:
357 case eCellReference:
358 m_local_id_2_local_id_compacted[icell->localId()] = index++;
360 break;
361 case eCellGrouped:
362 case eCellGhost:
363 m_local_id_2_local_id_compacted[icell->localId()] = -1;
364 break;
365 default:
366 throw FatalErrorException(A_FUNCINFO,"Invalid filter value");
367 }
368 }
369 // info()<<"m_local_id_2_local_id_compacted de 0 à "<<index-1;
370}
371/*---------------------------------------------------------------------------*/
372/*---------------------------------------------------------------------------*/
373void MeshPartitionerBase::
374_initNbCellsWithConstraints()
375{
376 // Calcul le nombre de mailles internes en tenant compte des regroupement suivant les contraintes
377 m_nb_cells_with_constraints = m_mesh->ownCells().size();
378 for (Integer i=0; i<m_cells_with_constraints.size(); ++i){
379 m_nb_cells_with_constraints -= (m_cells_with_constraints[i].size()-1);
380 }
381
382#if 0
383 for (Integer i=0; i<m_cells_with_constraints.size(); ++i){
384 Array<Cell> & listCell = m_cells_with_constraints[i];
385 for (Integer j = 1 ; j < listCell.size() ; ++j) {
386 if (m_filter_lid_cells[listCell[j].localId()] != eCellGrouped) {
387 info() << "Pb in group " << i << " " << listCell[j].localId() << "is not grouped";
388 }
389 }
390 info() << "Group of size " << i << " : " << listCell.size();
391 }
392#endif
393
394 info() <<"allCells().size() = "<<m_mesh->allCells().size();
395 info() <<"ownCells().size() = "<<m_mesh->ownCells().size();
396 info() <<"m_nb_cells_with_constraints = "<<m_nb_cells_with_constraints;
397}
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
415 || m_filter_lid_cells[cell.localId()] == eCellReference) {
416 Int64UniqueArray neighbors;
417 neighbors.resize(0);
418 getNeighbourCellsUidWithConstraints(cell, neighbors);
419 nbNeighbors = neighbors.size();
420 }
421 else
422 nbNeighbors = -1;
423 return (nbNeighbors);
424}
425/*---------------------------------------------------------------------------*/
426/*---------------------------------------------------------------------------*/
427//< Add a ngb cell if not already present.
428Real MeshPartitionerBase::
429_addNgb(const Cell& cell, const Face& face,
430 Int64Array& neighbourcells, Array<bool>& contrib,
431 HashTableMapT<Int64,Int32>& map,
432 Array<float> *ptrcommWeights, Int32 offset,
433 HashTableMapT<Int32,Int32>& lids, bool special)
434{
435 ARCANE_UNUSED(contrib);
436 ARCANE_UNUSED(lids);
437
438 Int64 uid = (*m_unique_id_reference)[cell];
439 bool toAdd = false;
440 Int32 myoffset = neighbourcells.size();
441 Real hg_contrib = 0;
442 const VariableItemReal& commCost = m_lb_mng_internal->commCost(m_mesh);
443 const float face_comm_cost = static_cast<float>(commCost[face]);
444 // Maille traditionnelle, on peut ajouter
445 if ((!special) &&(m_filter_lid_cells[cell.localId()] == eCellClassical))
446 toAdd = true;
447 else {
448 HashTableMapT<Int64,Int32>::Data* ptr;
449 ptr = map.lookupAdd(uid, myoffset, toAdd);
450 if (!toAdd && ptrcommWeights) {
451 myoffset = ptr->value();
452 (*ptrcommWeights)[offset + myoffset] += face_comm_cost;
453 }
454 }
455 if (toAdd) {
456 neighbourcells.add(uid);
457 if (ptrcommWeights){
458 (*ptrcommWeights).add(face_comm_cost);
459 }
460 }
461
462 // TODO make hg_contrib work again.
463 //contrib[myoffset] = true;
464
465 // Count cell contrib only once, even if it appears several times
466 // if (ptrcommWeights) {
467 // lids.lookupAdd(cell.localId(), myoffset, toAdd);
468 // if (toAdd) {
469 // hg_contrib = m_criteria.getResidentMemory(cell);
470 // (*ptrcommWeights)[offset + myoffset] += hg_contrib;
471 // }
472 // }
473
474 return (hg_contrib);
475}
476
477
478/*---------------------------------------------------------------------------*/
479Real MeshPartitionerBase::
480getNeighbourCellsUidWithConstraints(Cell cell, Int64Array& neighbourcells,
481 Array<float> *ptrcommWeights,
482 bool no_cell_contrib)
483{
484 ARCANE_UNUSED(no_cell_contrib);
485
486 Int32 offset = 0;
487 Real hg_contrib = 0;
488
489 if ((m_filter_lid_cells[cell.localId()] != eCellClassical)
490 &&(m_filter_lid_cells[cell.localId()] != eCellReference))
491 return 0.0;
492
493 if (ptrcommWeights)
494 offset = (*ptrcommWeights).size();
495
496 neighbourcells.resize(0);
497
498#ifdef MY_DEBUG
499 VariableCellInt64 uids_ref(*m_unique_id_reference);
500 Int64 uid = uids_ref[cell];
501#endif /* MY_DEBUG */
502
503 Integer index = -1;
504 Integer nbFaces = cell.nbFace();
505
506 // First compute max degree
507 if (m_filter_lid_cells[cell.localId()] == eCellReference) {
508 for (index=0; index<m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index){
509 }
510 if (index==m_cells_with_constraints.size())
511 throw FatalErrorException(A_FUNCINFO,"Unable to find cell");
512
513 Array<Cell>& listCell = m_cells_with_constraints[index];
514 nbFaces = 0;
515 // Activate constraint, but not the reference !
516 for (Integer j=1; j<listCell.size(); ++j) {
517 m_filter_lid_cells[listCell[j].localId()] = eCellInAConstraint;
518 nbFaces += listCell[j].nbFace();
519 }
520 }
521
522 HashTableMapT<Int64,Int32> difficultNgb(nbFaces,true);
523 HashTableMapT<Int32,Int32> lids(nbFaces,true);
524 UniqueArray<bool>contrib(nbFaces);
525 // Array<Real>memUsed(nbFaces); // (HP): bug sur cette structure dans la suite du code
526 contrib.fill(false);
527
528 if (m_filter_lid_cells[cell.localId()] == eCellClassical){
529 if (m_is_non_manifold_mesh && cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
530 // En cas de maillage non manifold, la maille peut contenir
531 // des arêtes au lieu des faces. Si c'est le cas, on utilise les arêtes
532 // pour déterminer les voisines.
533 // Dans ce cas, on ne prend en compte que les voisines ayant
534 // aussi 'ItemFlags::II_HasEdgeFro1DItems' positionné.
535 for (Edge sub_edge : cell.edges()) {
536 // on ne prend que les arêtes ayant une maille voisine
537 if (sub_edge.nbCell() >= 2) {
538 for (Cell sub_cell : sub_edge.cells()) {
539 if (sub_cell != cell && sub_cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
540 hg_contrib += 1.0;
541 neighbourcells.add((*m_unique_id_reference)[sub_cell]);
542 // TODO: regarder la valeur qu'il faut ajouter pour les communications
543 if (ptrcommWeights)
544 (*ptrcommWeights).add(1.0f);
545 }
546 }
547 }
548 }
549 }
550 else {
551 for (Integer z = 0; z < cell.nbFace(); ++z) {
552 Face face = cell.face(z);
553 // on ne prend que les faces ayant une maille voisine
554 if (face.nbCell() == 2) {
555 // recherche de la maille externe
556 Cell opposite_cell = (face.cell(0) != cell ? face.cell(0) : face.cell(1));
557 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
558 ptrcommWeights, offset, lids);
559 }
560 }
561 }
562 // //Now add cell contribution to edge weight
563 // if ((ptrcommWeights) &&(!noCellContrib)) {
564 // float mymem = m_criteria.getOverallMemory(cell);
565 // for (Integer j = 0 ; j < neighbourcells.size() ;++j) {
566 // (*ptrcommWeights)[offset+j] += mymem;
567 // }
568 // }
569 }
570 else { //if (m_filter_lid_cells[cell.localId()] == eCellReference){
571 Array<Cell>& listCell = m_cells_with_constraints[index];
572 m_filter_lid_cells[listCell[0].localId()] = eCellInAConstraint;
573 // memUsed.fill(0);
574 for (Integer j=0; j<listCell.size(); ++j){
575 contrib.fill(false);
576 // hg_contrib += m_criteria.getOverallMemory(listCell[j]);
577 // memUsed[j] = hg_contrib;
578 for( Integer z=0; z<listCell[j].nbFace(); ++z ){
579 const Face& face = listCell[j].face(z);
580 // on ne prend que les faces ayant une maille non marquée à eCellInAConstraint et avec une maille voisine
581 if ((face.nbCell()==2)
582 && (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint
583 || m_filter_lid_cells[face.cell(1).localId()] != eCellInAConstraint)){
584 // recherche de la maille externe
585 const Cell& opposite_cell = (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint?
586 face.cell(0):face.cell(1));
587 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
588 ptrcommWeights, offset, lids, true);
589 }
590 }
591 // //Now add cell contribution to edge weight
592 // if (ptrcommWeights && !noCellContrib) {
593 // for (Integer c = 0 ; c < neighbourcells.size() ;++c) {
594 // if (contrib[c])
595 // (*ptrcommWeights)[offset+c] += memUsed[j];
596 // }
597 // }
598 }
599 m_filter_lid_cells[listCell[0].localId()] = eCellReference;
600 for (Integer j=1; j<listCell.size(); ++j)
601 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
602
603 } // end if eCellReference
604
605 return (hg_contrib);
606}
607/*---------------------------------------------------------------------------*/
608/*---------------------------------------------------------------------------*/
609void MeshPartitionerBase::
610getNeighbourNodesUidWithConstraints(Cell cell, Int64UniqueArray neighbournodes)
611{
612 neighbournodes.resize(cell.nbNode());
613
614 for( Integer z=0; z<cell.nbNode(); ++z ){
615 neighbournodes[z] = cell.node(z).uniqueId();
616 }
617}
618/*---------------------------------------------------------------------------*/
619/*---------------------------------------------------------------------------*/
620Int32 MeshPartitionerBase::
621localIdWithConstraints(Cell cell)
622{
623 return m_local_id_2_local_id_compacted[cell.localId()];
624}
625/*---------------------------------------------------------------------------*/
626Int32 MeshPartitionerBase::
627localIdWithConstraints(Int32 cell_lid)
628{
629 //info()<<"localIdWithConstraints("<<cell_lid<<") => "<<m_local_id_2_local_id_compacted[cell_lid];
630 return m_local_id_2_local_id_compacted[cell_lid];
631}
632/*---------------------------------------------------------------------------*/
633/*---------------------------------------------------------------------------*/
634void MeshPartitionerBase::
635invertArrayLid2LidCompacted()
636{
637 //info()<<"MeshPartitionerBase::invertArrayLid2LidCompacted()";
638 Integer index = 0;
639 for (Integer i=0; i<m_mesh->allCells().size(); i++){
640 if (m_local_id_2_local_id_compacted[i] != -1)
641 m_local_id_2_local_id_compacted[index++] = i;
642 }
643 for (;index<m_mesh->allCells().size(); index++)
644 m_local_id_2_local_id_compacted[index] = -2;
645}
646/*---------------------------------------------------------------------------*/
647
648SharedArray<float> MeshPartitionerBase::
649cellsSizeWithConstraints()
650{
651 VariableCellReal mWgt = m_lb_mng_internal->massResWeight(m_mesh);
652 return _cellsProjectWeights(mWgt);
653}
654
655SharedArray<float> MeshPartitionerBase::
656cellsWeightsWithConstraints(Int32 max_nb_weight, bool ask_lb_cells)
657{
658 ARCANE_UNUSED(ask_lb_cells);
659
660 Int32 nb_weight = max_nb_weight;
661
662 Int32 nb_criteria = m_lb_mng_internal->nbCriteria(m_mesh);
663
664 if (max_nb_weight <= 0 || max_nb_weight > nb_criteria)
665 nb_weight = nb_criteria;
666
667 info() << "Number of weights " << nb_weight << " / " << nb_criteria;
668
669 VariableCellArrayReal mWgt = m_lb_mng_internal->mCriteriaWeight(m_mesh);
670 return _cellsProjectWeights(mWgt, nb_weight);
671}
672
673/*---------------------------------------------------------------------------*/
674/*---------------------------------------------------------------------------*/
675
676SharedArray<float> MeshPartitionerBase::
677_cellsProjectWeights(VariableCellArrayReal& cellWgtIn, Int32 nbWgt) const
678{
679 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints()*nbWgt);
680 if (nbWgt > cellWgtIn.arraySize()) {
681 ARCANE_FATAL("Asked for too many weights n={0} array_size={1}",nbWgt,cellWgtIn.arraySize());
682 }
683
684 ENUMERATE_CELL(icell, m_mesh->ownCells()){
685 if(m_filter_lid_cells[icell->localId()]==eCellClassical)
686 for ( int i = 0 ; i < nbWgt ; ++i){
687 float v = static_cast<float>(cellWgtIn[icell][i]);
688 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()]*nbWgt+i] = v;
689 }
690 }
691 RealUniqueArray w(nbWgt);
692 for( auto& ptr : m_cells_with_constraints ){
693 w.fill(0);
694 for( const auto& cell : ptr ){
695 for (int i = 0 ; i <nbWgt ; ++i)
696 w[i] += cellWgtIn[cell][i];
697 }
698 for (int i=0 ; i<nbWgt ; ++i)
699 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()]*nbWgt+i] = (float)(w[i]);
700 }
701
702 return cellWgtOut;
703}
704
705/*---------------------------------------------------------------------------*/
706/*---------------------------------------------------------------------------*/
707SharedArray<float> MeshPartitionerBase::
708_cellsProjectWeights(VariableCellReal& cellWgtIn) const
709{
710 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints());
711
712 ENUMERATE_CELL(icell, m_mesh->ownCells()){
713 if(m_filter_lid_cells[icell->localId()]==eCellClassical)
714 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()]]
715 = (float)cellWgtIn[icell];
716 }
717 for( auto& ptr : m_cells_with_constraints ){
718 Real w = 0;
719 for( Cell cell : ptr ){
720 w += cellWgtIn[cell];
721 }
722 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()]]
723 = (float)w;
724 }
725
726 return cellWgtOut;
727}
728
729/*---------------------------------------------------------------------------*/
730bool MeshPartitionerBase::
731cellUsedWithConstraints(Cell cell)
732{
733 eMarkCellWithConstraint marque = m_filter_lid_cells[cell.localId()];
734// info()<<"cellUsedWithConstraints("<<cell<<") => "<<(marque == eCellClassical || marque == eCellReference);
735 return (marque == eCellClassical || marque == eCellReference);
736}
737
738bool MeshPartitionerBase::
739cellUsedWithWeakConstraints(std::pair<Int64,Int64>& paired_item)
740{
741 std::pair<Int64,Int64> other_pair(paired_item.second, paired_item.first);
742 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());
743}
744/*---------------------------------------------------------------------------*/
745/*---------------------------------------------------------------------------*/
746void MeshPartitionerBase::
747changeCellOwner(Item cell, VariableItemInt32& cells_new_owner, Int32 new_owner)
748{
749 // TODO à optimiser pour le cas où il y aurait plein de petites contraintes
750
751 //info()<<"changeCellOwner "<<cell<<", new_owner = "<<new_owner;
752 cells_new_owner[cell] = new_owner;
753
754 if (m_filter_lid_cells[cell.localId()] == eCellReference){
755 Integer index = -1;
756 for (index=0; index<m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index){
757 }
758 if (index==m_cells_with_constraints.size())
759 throw FatalErrorException("MeshPartitionerBase::changeCellOwner(): unable to find cell");
760
761 Array<Cell>& listCell = m_cells_with_constraints[index];
762 //info()<<" changement en plus pour listCell: "<<listCell;
763 for (Integer i=1; i<listCell.size(); i++)
764 cells_new_owner[listCell[i]] = new_owner;
765 }
766}
767
768
769/*---------------------------------------------------------------------------*/
770/*---------------------------------------------------------------------------*/
771// Fonctions utiles pour l'ancienne interface de partitionnement.
772
773void
775{
776 m_lb_mng_internal->reset(m_mesh);
777 _clearCellWgt();
778
779 for (int i = 0 ; i <nb_weight ; ++i) {
780 StringBuilder varName("LB_wgt_");
781 varName += (i+1);
782
783 VariableCellReal myvar(VariableBuildInfo(m_mesh, varName.toString(),
785 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
786 (myvar)[icell] = weights[icell->localId()*nb_weight+i];
787 }
788 m_lb_mng_internal->addCriterion(myvar, m_mesh);
789 }
790
791 m_lb_mng_internal->initAccess(m_mesh);
792 m_lb_mng_internal->setMassAsCriterion(m_mesh, false);
793 m_lb_mng_internal->setNbCellsAsCriterion(m_mesh, false);
794}
795
796/*---------------------------------------------------------------------------*/
797/*---------------------------------------------------------------------------*/
798
799Integer MeshPartitionerBase::
800nbCellWeight() const
801{
802 return math::max(m_lb_mng_internal->nbCriteria(m_mesh), 1);
803}
804
805ArrayView<float> MeshPartitionerBase::
806cellsWeight() const
807{
808 ARCANE_FATAL("NotImplemented");
809}
810
811void MeshPartitionerBase::
812_clearCellWgt()
813{
814 //m_cell_wgt.clear();
815}
816
817/*---------------------------------------------------------------------------*/
818/*---------------------------------------------------------------------------*/
819
821template <class ArrayType> Parallel::Request
823 UniqueArray<ArrayType> data, String header, int step=1 )
824{
826 UniqueArray<Integer> sizes(pm->commSize());
827 UniqueArray<Integer> mysize(1);
828 mysize[0] = data.size();
829
830 pm->gather(mysize, sizes, pm->masterIORank());
831
832 req = pm->send(data, pm->masterIORank(),false);
833
834
835 if (pm->isMasterIO()) {
836 ofstream ofile;
837
838 ofile.open(filename.localstr());
839 if (!header.null()) {
840 ofile << header;
841 Int64 sum = 0;
842 for (ConstIterT<UniqueArray<Integer> > iter(sizes) ; iter() ; ++iter)
843 sum += *iter;
844 ofile << sum << std::endl;
845 }
846
847 for (int rank = 0 ; rank < pm->commSize() ; ++rank) {
848 UniqueArray<ArrayType> otherdata(sizes[rank]);
849 pm->recv(otherdata, rank, true);
850 for ( ConstIterT<ArrayView<ArrayType> > myiter(otherdata) ; myiter() ; ) {
851 for (int j = 0 ; (j < step) && myiter() ; ++j, ++myiter)
852 ofile << *myiter << " ";
853 ofile << std::endl ;
854 }
855 }
856 ofile.close();
857 }
858
859 return req;
860}
861
862/*---------------------------------------------------------------------------*/
863/*---------------------------------------------------------------------------*/
864
865void
867{
868 int i = 0;
869 IParallelMng* pm = m_mesh->parallelMng();
870 String header;
871
872 // ---
873 // Send vertex uid first
874 Int64UniqueArray uid(m_nb_cells_with_constraints);
875 uid.fill(-1);
876 VariableCellInt64 uids_ref(*m_unique_id_reference);
877 i=0;
878 ENUMERATE_CELL(icell, m_mesh->ownCells()) {
879 if ((m_filter_lid_cells[icell->localId()]!=eCellClassical)
880 &&(m_filter_lid_cells[icell->localId()]!=eCellReference))
881 continue;
882
883 uid[i++] = uids_ref[icell];
884 }
885
886
889 req = centralizePartInfo<Int64>(filebase+".uid", pm, uid, header);
890 reqs.add(req);
891
892 UniqueArray<float> vwgt = cellsWeightsWithConstraints(0);
893 // Hack: use Real to avoid bugs in pm->recv ...
894 // TODO: Fix this.
895 UniqueArray<Real> rvwgt(vwgt.size());
896 IterT<UniqueArray<Real> > myiterr(rvwgt);
897 for (ConstIterT<UniqueArray<float> > myiterf(vwgt) ;
898 myiterf() ; ++myiterf, ++myiterr)
899 (*myiterr) = (Real) (*myiterf);
900
901 req = centralizePartInfo<Real>(filebase+".vwgt", pm, rvwgt, header, nbCellWeight());
902 reqs.add(req);
903
904 // Send vertex coords
905 VariableNodeReal3& coords(mesh()->nodesCoordinates());
906 UniqueArray<Real3> my_coords(m_nb_cells_with_constraints);
907 i=0;
908 ENUMERATE_CELL(icell, m_mesh->ownCells()) {
909 if ((m_filter_lid_cells[icell->localId()]!=eCellClassical)
910 &&(m_filter_lid_cells[icell->localId()]!=eCellReference))
911 continue;
912
913 // on calcul un barycentre
914 for( Integer z=0, zs = (*icell).nbNode(); z<zs; ++z ){
915 const Node& node = (*icell).node(z);
916 my_coords[i] += coords[node];
917 }
918 my_coords[i] /= Convert::toDouble((*icell).nbNode());
919 i++;
920 }
921 req = centralizePartInfo<Real3>(filebase+".xyz", pm, my_coords, header);
922 reqs.add(req);
923
924
925 // Send relationships to master
927 ENUMERATE_CELL(icell, m_mesh->ownCells()) {
928 Int64UniqueArray neighbourcells;
929 UniqueArray<float> commWeights;
930
931 if ((m_filter_lid_cells[icell->localId()]!=eCellClassical)
932 &&(m_filter_lid_cells[icell->localId()]!=eCellReference))
933 continue;
934 getNeighbourCellsUidWithConstraints(*icell, neighbourcells, &commWeights);
935 Int64 my_uid = uids_ref[icell];
936 for (Integer j = 0 ; j < neighbourcells.size() ; ++j) {
937 if (neighbourcells[j] > my_uid)
938 continue;
939 Real3 tmp(static_cast<Real>(my_uid+1), static_cast<Real>(neighbourcells[j]+1), commWeights[j]);
940 nnz.add(tmp);
941 }
942 }
943 Integer nbvertices;
944 nbvertices = pm->reduce(Parallel::ReduceSum, m_nb_cells_with_constraints);
945 StringBuilder myheader = "%%MatrixMarket matrix coordinate real symmetric\n";
946 myheader += nbvertices;
947 myheader += " ";
948 myheader += nbvertices;
949 myheader += " ";
950 req = centralizePartInfo<Real3>(filebase+".mtx", pm, nnz, myheader.toString());
951 reqs.add(req);
952
953 pm->waitAllRequests(reqs);
954}
955
956/*---------------------------------------------------------------------------*/
957/*---------------------------------------------------------------------------*/
958
959} // End namespace Arcane
960
961/*---------------------------------------------------------------------------*/
962/*---------------------------------------------------------------------------*/
#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:128
@ PExecutionDepend
Indique que la valeur de la variable est dépendante de l'exécution.
Definition IVariable.h:108
@ PNoDump
Indique que la variable ne doit pas être sauvegardée.
Definition IVariable.h:74
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 de réel de dimension 3.
Definition Real3.h:132
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:304
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
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:392
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.
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
MeshVariableArrayRefT< Cell, Real > VariableCellArrayReal
Grandeur au centre des mailles de type tableau de réel.
double toDouble(Real r)
Converti un Real en double.
Definition Convert.h:32
@ 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:426
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:506
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:567
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:428
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:436
double Real
Type représentant un réel.
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52