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