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"
22#define INSURE_CONSTRAINTS
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"
42#include "arcane/std/MeshPartitionerBase.h"
54MeshPartitionerBase(
const ServiceBuildInfo& sbi)
56, m_sub_domain(sbi.subDomain())
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)
65, m_unique_id_reference(nullptr)
67 IParallelMng* pm = m_mesh->parallelMng();
78 delete m_unique_id_reference;
83void* MeshPartitionerBase::
84getCommunicator()
const
86 return m_pm_sub->getMPICommunicator();
89Parallel::Communicator MeshPartitionerBase::
92 return m_pm_sub->communicator();
98void MeshPartitionerBase::
99changeOwnersFromCells()
101 m_mesh->utilities()->changeOwnersFromCells();
107void MeshPartitionerBase::
108initConstraints(
bool uidref)
110 _initArrayCellsWithConstraints();
112 _initFilterLidCells();
117 _initLid2LidCompacted();
119 _initNbCellsWithConstraints();
121 m_lb_mng_internal->initAccess(m_mesh);
123 info() <<
"Weight (" << subDomain()->commonVariables().globalIteration()
124 <<
"): " << m_lb_mng_internal->nbCriteria(m_mesh);
130void MeshPartitionerBase::
133 m_lb_mng_internal->endAccess();
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;
148bool MeshPartitionerBase::
149_createConstraintsLists(Int64MultiArray2& tied_uids)
154 m_cells_with_constraints.clear();
156 IItemFamily* cellFamily = m_mesh->itemFamily(IK_Cell);
159 for( Integer i=0, n=tied_uids.dim1Size(); i<n; ++i ){
165 cellFamily->itemsUniqueIdToLocalId(lids,uids,
false);
170 for( Integer j=0, js=lids.size(); j<js; ++j ){
172 if (lid!=NULL_ITEM_LOCAL_ID)
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());
184 allLocal += (((cells.size() == 0)||
185 (cells.size() == uids.size()))?0:1);
189 m_cells_with_constraints.add(cells);
191 IParallelMng* pm = m_mesh->parallelMng();
194 int sum = pm->
reduce(Parallel::ReduceSum,allLocal);
201void MeshPartitionerBase::
202_initArrayCellsWithConstraints()
205 m_cells_with_constraints.clear();
206 m_cells_with_weak_constraints.clear();
208 if (!m_mesh->partitionConstraintMng())
220 m_mesh->partitionConstraintMng()->computeConstraintList(tied_uids);
222#ifdef INSURE_CONSTRAINTS
223 if (!_createConstraintsLists(tied_uids)) {
227 cells_new_owner[icell] = (*icell).owner();
229 m_mesh->modifier()->setDynamic(
true);
230 m_mesh->partitionConstraintMng()->computeAndApplyConstraints();
231 m_mesh->utilities()->changeOwnersFromCells();
232 m_mesh->toPrimaryMesh()->exchangeItems();
234 if (!_createConstraintsLists(tied_uids))
235 throw FatalErrorException(A_FUNCINFO,
"Issue with constraints !");
236#ifdef INSURE_CONSTRAINTS
238 m_mesh->partitionConstraintMng()->computeWeakConstraintList(tied_uids);
240 for(Integer i=0;i<tied_uids.dim1Size();++i)
242 std::pair<Int64, Int64> ids(tied_uids[i][0],tied_uids[i][1]);
243 m_cells_with_weak_constraints.insert(ids);
251void MeshPartitionerBase::
254 CellGroup all_cells = m_mesh->allCells();
257 m_filter_lid_cells.resize(m_mesh->cellFamily()->maxLocalId());
258 m_filter_lid_cells.fill(eCellGhost);
261 m_filter_lid_cells[icell->localId()] = eCellClassical;
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) {
269 if (m_filter_lid_cells[listCell[j].localId()] != eCellClassical)
270 info() <<
"Pb in constraint " << i <<
" with cell[" << j
271 <<
"] = " << listCell[j].uniqueId();
273 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
281void MeshPartitionerBase::
284 if (!m_unique_id_reference)
285 m_unique_id_reference =
new VariableCellInt64(VariableBuildInfo(m_mesh,
"CellUniqueIdRef", IVariable::PNoDump));
291void MeshPartitionerBase::
300 uids_ref[icell] = icell->uniqueId();
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;
308 uids_ref.synchronize();
314void MeshPartitionerBase::
315_initUidRef(VariableCellInteger& cell_renum_uid)
324 uids_ref[icell] = cell_renum_uid[icell];
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;
332 uids_ref.synchronize();
339void MeshPartitionerBase::
340_initLid2LidCompacted()
345 m_local_id_2_local_id_compacted.resize(m_mesh->cellFamily()->maxLocalId());
346 m_check.resize(m_mesh->cellFamily()->maxLocalId());
350 switch (m_filter_lid_cells[
icell.itemLocalId()]){
353 m_local_id_2_local_id_compacted[
icell->localId()] = index++;
358 m_local_id_2_local_id_compacted[
icell->localId()] = -1;
368void MeshPartitionerBase::
369_initNbCellsWithConstraints()
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);
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";
385 info() <<
"Group of size " << i <<
" : " << listCell.size();
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;
396Int32 MeshPartitionerBase::
397nbOwnCellsWithConstraints()
const
399 return m_nb_cells_with_constraints;
405nbNeighbourCellsWithConstraints(Cell cell)
409 if (m_filter_lid_cells[cell.localId()] == eCellClassical
410 || m_filter_lid_cells[cell.localId()] == eCellReference) {
413 getNeighbourCellsUidWithConstraints(cell, neighbors);
414 nbNeighbors = neighbors.size();
418 return (nbNeighbors);
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)
430 ARCANE_UNUSED(contrib);
433 Int64 uid = (*m_unique_id_reference)[cell];
435 Int32 myoffset = neighbourcells.size();
440 if ((!special) &&(m_filter_lid_cells[cell.localId()] == eCellClassical))
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]);
451 neighbourcells.add(uid);
453 (*ptrcommWeights).add((
float)(commCost[face]));
474Real MeshPartitionerBase::
475getNeighbourCellsUidWithConstraints(Cell cell, Int64Array& neighbourcells,
476 Array<float> *ptrcommWeights,
477 bool no_cell_contrib)
479 ARCANE_UNUSED(no_cell_contrib);
484 if ((m_filter_lid_cells[cell.localId()] != eCellClassical)
485 &&(m_filter_lid_cells[cell.localId()] != eCellReference))
489 offset = (*ptrcommWeights).size();
491 neighbourcells.resize(0);
495 Int64 uid = uids_ref[cell];
499 Integer nbFaces = cell.nbFace();
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){
505 if (index==m_cells_with_constraints.size())
506 throw FatalErrorException(A_FUNCINFO,
"Unable to find cell");
508 Array<Cell>& listCell = m_cells_with_constraints[index];
511 for (Integer j=1; j<listCell.size(); ++j) {
512 m_filter_lid_cells[listCell[j].localId()] = eCellInAConstraint;
513 nbFaces += listCell[j].nbFace();
517 HashTableMapT<Int64,Int32> difficultNgb(nbFaces,
true);
518 HashTableMapT<Int32,Int32> lids(nbFaces,
true);
519 UniqueArray<bool>contrib(nbFaces);
523 if (m_filter_lid_cells[cell.localId()] == eCellClassical){
525 for( Integer z=0; z<cell.nbFace(); ++z ){
526 const Face& face = cell.face(z);
528 if (face.nbCell()==2){
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);
545 Array<Cell>& listCell = m_cells_with_constraints[index];
546 m_filter_lid_cells[listCell[0].localId()] = eCellInAConstraint;
548 for (Integer j=0; j<listCell.size(); ++j){
552 for( Integer z=0; z<listCell[j].nbFace(); ++z ){
553 const Face& face = listCell[j].face(z);
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)){
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);
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;
583void MeshPartitionerBase::
584getNeighbourNodesUidWithConstraints(Cell cell, Int64UniqueArray neighbournodes)
586 neighbournodes.resize(cell.nbNode());
588 for( Integer z=0; z<cell.nbNode(); ++z ){
589 neighbournodes[z] = cell.node(z).uniqueId();
594Int32 MeshPartitionerBase::
595localIdWithConstraints(Cell cell)
597 return m_local_id_2_local_id_compacted[cell.localId()];
600Int32 MeshPartitionerBase::
601localIdWithConstraints(
Int32 cell_lid)
604 return m_local_id_2_local_id_compacted[cell_lid];
608void MeshPartitionerBase::
609invertArrayLid2LidCompacted()
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;
617 for (;index<m_mesh->allCells().size(); index++)
618 m_local_id_2_local_id_compacted[index] = -2;
622SharedArray<float> MeshPartitionerBase::
623cellsSizeWithConstraints()
626 return _cellsProjectWeights(mWgt);
629SharedArray<float> MeshPartitionerBase::
630cellsWeightsWithConstraints(
Int32 max_nb_weight,
bool ask_lb_cells)
632 ARCANE_UNUSED(ask_lb_cells);
634 Int32 nb_weight = max_nb_weight;
636 Int32 nb_criteria = m_lb_mng_internal->nbCriteria(m_mesh);
638 if (max_nb_weight <= 0 || max_nb_weight > nb_criteria)
639 nb_weight = nb_criteria;
641 info() <<
"Number of weights " << nb_weight <<
" / " << nb_criteria;
644 return _cellsProjectWeights(mWgt, nb_weight);
650SharedArray<float> MeshPartitionerBase::
651_cellsProjectWeights(VariableCellArrayReal& cellWgtIn,
Int32 nbWgt)
const
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());
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;
666 for(
auto& ptr : m_cells_with_constraints ){
668 for(
const auto& cell : ptr ){
669 for (
int i = 0 ; i <nbWgt ; ++i)
670 w[i] += cellWgtIn[cell][i];
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]);
681SharedArray<float> MeshPartitionerBase::
682_cellsProjectWeights(VariableCellReal& cellWgtIn)
const
684 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints());
687 if(m_filter_lid_cells[icell->localId()]==eCellClassical)
688 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()]]
689 = (float)cellWgtIn[icell];
691 for(
auto& ptr : m_cells_with_constraints ){
693 for( Cell cell : ptr ){
694 w += cellWgtIn[cell];
696 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()]]
704bool MeshPartitionerBase::
705cellUsedWithConstraints(Cell cell)
707 eMarkCellWithConstraint marque = m_filter_lid_cells[cell.localId()];
709 return (marque == eCellClassical || marque == eCellReference);
712bool MeshPartitionerBase::
713cellUsedWithWeakConstraints(std::pair<Int64,Int64>& paired_item)
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());
720void MeshPartitionerBase::
721changeCellOwner(Item cell, VariableItemInt32& cells_new_owner,
Int32 new_owner)
726 cells_new_owner[cell] = new_owner;
728 if (m_filter_lid_cells[cell.localId()] == eCellReference){
730 for (index=0; index<m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index){
732 if (index==m_cells_with_constraints.size())
733 throw FatalErrorException(
"MeshPartitionerBase::changeCellOwner(): unable to find cell");
735 Array<Cell>& listCell = m_cells_with_constraints[index];
737 for (Integer i=1; i<listCell.size(); i++)
738 cells_new_owner[listCell[i]] = new_owner;
750 m_lb_mng_internal->reset(m_mesh);
758 IVariable::PNoDump|IVariable::PTemporary|IVariable::PExecutionDepend));
762 m_lb_mng_internal->addCriterion(
myvar, m_mesh);
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);
773Integer MeshPartitionerBase::
776 return math::max(m_lb_mng_internal->nbCriteria(m_mesh), 1);
780MeshPartitionerBase::cellsWeight()
const
782 throw FatalErrorException(A_FUNCINFO,
"not implemented");
786MeshPartitionerBase::_clearCellWgt() {
794template <
class ArrayType> Parallel::Request
817 ofile << sum << std::endl;
820 for (
int rank = 0 ; rank < pm->
commSize() ; ++rank) {
852 if ((m_filter_lid_cells[
icell->localId()]!=eCellClassical)
853 &&(m_filter_lid_cells[
icell->localId()]!=eCellReference))
882 if ((m_filter_lid_cells[
icell->localId()]!=eCellClassical)
883 &&(m_filter_lid_cells[
icell->localId()]!=eCellReference))
887 for( Integer z=0,
zs = (*icell).nbNode(); z<
zs; ++z ){
888 const Node& node = (*icell).node(z);
891 my_coords[i] /= Convert::toDouble((*icell).nbNode());
904 if ((m_filter_lid_cells[
icell->localId()]!=eCellClassical)
905 &&(m_filter_lid_cells[
icell->localId()]!=eCellReference))
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
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.
Classe gérant un vecteur de réel de dimension 3.
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.
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.
Vecteur 1D de données avec sémantique par valeur (style STL).
ItemGroupT< Cell > CellGroup
Groupe de mailles.
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.
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.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Int32 Integer
Type représentant un entier.