14#include "arcane/utils/NotSupportedException.h"
15#include "arcane/utils/PlatformUtils.h"
16#include "arcane/utils/ScopedPtr.h"
18#include "arcane/IGridMeshPartitioner.h"
19#include "arcane/BasicService.h"
20#include "arcane/IPrimaryMesh.h"
21#include "arcane/ServiceFactory.h"
22#include "arcane/IParallelMng.h"
23#include "arcane/ItemPrinter.h"
24#include "arcane/IExtraGhostCellsBuilder.h"
26#include "arcane/IMeshPartitionConstraintMng.h"
27#include "arcane/IMeshUtilities.h"
28#include "arcane/IMeshModifier.h"
29#include "arcane/IItemFamily.h"
74 for (
const auto& v : m_ghost_cell_uids) {
85 auto x = m_ghost_cell_local_ids.find(rank);
86 if (x == m_ghost_cell_local_ids.end())
91 std::map<Int32, UniqueArray<ItemUniqueId>> m_ghost_cell_uids;
92 std::map<Int32, UniqueArray<Int32>> m_ghost_cell_local_ids;
101 Int32 m_nb_direction = 0;
102 Int32 m_offset_y = 0;
103 Int32 m_offset_z = 0;
123 m_is_bounding_box_set =
true;
140 std::array<Int32, 3> m_ijk_part;
141 bool m_is_bounding_box_set =
false;
142 bool m_is_ijk_set =
false;
143 bool m_is_verbose =
false;
144 GhostCellsBuilder* m_ghost_cells_builder =
nullptr;
150 void _addGhostCell(Int32 rank,
Cell cell);
151 void _buildGridInfo();
152 void _computeSpecificGhostLayer();
159SimpleGridMeshPartitioner::
160SimpleGridMeshPartitioner(
const ServiceBuildInfo& sbi)
163 if (platform::getEnvironmentVariable(
"ARCANE_DEBUG_SIMPLE_GRID_MESH_PARTITIONER") ==
"1")
180 if (position < coords[0])
185 for (Int32 z = 0; z <
nb_value; ++z) {
187 info() <<
" z=" << z <<
" coord=" << coords[z] <<
" part=" <<
part_id;
188 if (position > coords[z])
203void SimpleGridMeshPartitioner::
204_addGhostCell(Int32 rank,
Cell cell)
206 m_ghost_cells_builder->m_ghost_cell_uids[rank].add(cell.
uniqueId());
212void SimpleGridMeshPartitioner::
215 m_grid_info =
new GridInfo();
217 if (!m_is_bounding_box_set)
218 ARCANE_FATAL(
"Bounding box is not set. call method setBoundingBox() before");
220 ARCANE_FATAL(
"Part index is not set. call method setPartIndex() before");
223 const Int32 dimension = mesh->dimension();
225 IParallelMng* pm = mesh->parallelMng();
229 std::array<Int32, 3> nb_part_by_direction_buf = { 0, 0, 0 };
230 ArrayView<Int32> nb_part_by_direction(3, nb_part_by_direction_buf.data());
231 for (Integer i = 0; i < 3; ++i)
232 if (m_ijk_part[i] >= 0)
233 nb_part_by_direction[i] = m_ijk_part[i] + 1;
235 auto& nb_direction = m_grid_info->m_nb_direction;
238 if (nb_part_by_direction[2] > 0)
240 else if (nb_part_by_direction[1] > 0)
243 ARCANE_THROW(NotImplementedException,
"SimpleGridMeshPartitioner for 1D mesh");
245 if (nb_direction != dimension)
246 ARCANE_FATAL(
"Invalid number of direction: mesh_dimension={0} nb_direction={1}", dimension, nb_direction);
248 pm->
reduce(Parallel::ReduceMax, nb_part_by_direction);
249 info() <<
"NB_DIRECTION=" << nb_direction <<
" NB_PART=" << nb_part_by_direction;
252 const Real min_value = -FloatInfo<Real>::maxValue();
253 auto& grid_coord = m_grid_info->m_grid_coord;
255 grid_coord.resize(nb_direction);
256 grid_coord.resize(nb_direction);
257 for (Integer i = 0; i < nb_direction; ++i)
258 grid_coord[i].resize(nb_part_by_direction[i], min_value);
260 for (Integer i = 0; i < nb_direction; ++i) {
261 Int32 index = m_ijk_part[i];
263 grid_coord[i][index] = m_min_box[i];
265 for (Integer i = 0; i < nb_direction; ++i) {
266 pm->
reduce(Parallel::ReduceMax, grid_coord[i]);
267 info() <<
"GRID_COORD dir=" << i <<
" V=" << grid_coord[i];
271 for (Integer i = 0; i < nb_direction; ++i) {
272 ConstArrayView<Real> coords(grid_coord[0].view());
273 Int32 nb_value = coords.size();
276 for (
Int32 z = 0; z < (nb_value - 1); ++z)
277 if (coords[z] > coords[z + 1])
278 ARCANE_FATAL(
"Grid coord '{0}' is not sorted: {1} > {2}", i, coords[z], coords[z + 1]);
281 m_grid_info->m_offset_y = (nb_direction >= 2) ? nb_part_by_direction[0] : 0;
282 m_grid_info->m_offset_z = (nb_direction == 3) ? (nb_part_by_direction[0] * nb_part_by_direction[1]) : 0;
291 if (m_grid_info.get())
292 ARCANE_FATAL(
"partitionMesh() has already been called. Only one call par SimpleGridMeshPartitioner instance is allowed");
302 const Int32
offset_y = m_grid_info->m_offset_y;
303 const Int32
offset_z = m_grid_info->m_offset_z;
310 std::array<Int32, 3>
cell_part = { -1, -1, -1 };
341 mesh->
utilities()->changeOwnersFromCells();
353 const Int32
offset_y = m_grid_info->m_offset_y;
354 const Int32
offset_z = m_grid_info->m_offset_z;
355 const Int32 cell_owner = cell.
owner();
365 if (owner != cell_owner)
366 _addGhostCell(owner, cell);
373void SimpleGridMeshPartitioner::
374_computeSpecificGhostLayer()
376 if (!m_grid_info.get())
377 ARCANE_FATAL(
"partitionMesh() has to be called before this method.");
387 std::array<Int32, 3>
min_part = { -1, -1, -1 };
388 std::array<Int32, 3> max_part = { -1, -1, -1 };
389 std::array<Int32, 3> nb_node_part = { 1, 1, 1 };
392 Real max_value = FloatInfo<Real>::maxValue();
393 Real min_value = -max_value;
394 Real3 min_box(max_value,max_value,max_value);
395 Real3 max_box(min_value,min_value,min_value);
396 for (Node node : cell.nodes()) {
397 Real3 pos = nodes_coord[node];
402 for (Integer idir = 0; idir < nb_direction; ++idir) {
403 ConstArrayView<Real> coords(m_grid_info->m_grid_coord[idir].view());
404 Integer nb_coord = coords.size();
406 const Real min_pos = min_box[idir];
407 const Real max_pos = max_box[idir];
412 info() <<
" Cell uid=" << cell.
uniqueId() <<
" idir=" << idir
413 <<
" min_pos=" << min_pos <<
" max_pos=" << max_pos
414 <<
" min_part=" << min_part_id <<
" max_part_id=" << max_part_id;
423 min_part[idir] = min_part_id;
424 max_part[idir] = max_part_id;
427 Int32 total_nb_part = 1;
428 for (Integer idir = 0; idir < nb_direction; ++idir) {
429 Int32 nb_part = 1 + (max_part[idir] - min_part[idir]);
430 nb_node_part[idir] = nb_part;
431 total_nb_part *= nb_part;
435 info() <<
" Cell uid=" << cell.
uniqueId() <<
" min_part=" << ArrayView<Int32>(min_part)
436 <<
" max_part=" << ArrayView<Int32>(max_part)
437 <<
" nb_part=" << ArrayView<Int32>(nb_node_part)
438 <<
" total=" << total_nb_part;
444 info() <<
"GHOST_CELLS_TO_SEND";
445 for (
const auto& v : m_ghost_cells_builder->m_ghost_cell_uids) {
446 info() <<
"RANK=" << v.first <<
" ids=" << v.second;
458 if (mesh != this->mesh())
459 ARCANE_FATAL(
"mesh argument should be the same mesh that the one used to create this instance");
461 if (m_ghost_cells_builder)
462 ARCANE_FATAL(
"Only one call to this method is allower per instance.");
465 mesh->
utilities()->partitionAndExchangeMeshWithReplication(
this,
true);
469 mesh->
modifier()->addExtraGhostCellsBuilder(m_ghost_cells_builder);
472 _computeSpecificGhostLayer();
473 mesh->
modifier()->updateGhostLayers();
475 mesh->
modifier()->removeExtraGhostCellsBuilder(m_ghost_cells_builder);
477 m_ghost_cells_builder =
nullptr;
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Classe de base de service lié à un sous-domaine.
Interface d'un partitionneur de maillage sur une grille.
virtual CellGroup allCells()=0
Groupe de toutes les mailles.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IMeshModifier * modifier()=0
Interface de modification associée.
virtual IMeshUtilities * utilities()=0
Interface des fonctions utilitaires associée.
virtual IMeshPartitionConstraintMng * partitionConstraintMng()=0
Gestionnaire des contraintes de partitionnement associées à ce maillage.
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual VariableItemInt32 & itemsNewOwner(eItemKind kind)=0
Variable contenant l'identifiant du sous-domaine propriétaire.
Classe utilitaire pour imprimer les infos sur une entité.
Node node(Int32 i) const
i-ème noeud de l'entité
Int32 nbNode() const
Nombre de noeuds de l'entité
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Classe gérant un vecteur de réel de dimension 3.
Structure contenant les informations pour créer un service.
Propriétés de création d'un service.
Informations sur les mailles fantômes supplémentaires.
Int32ConstArrayView extraCellsToSend(Int32 rank) const override
Indices locaux des mailles "extraordinaires" pour envoi.
void computeExtraCellsToSend() override
Calcul des mailles "extraordinaires" à envoyer.
Partitionneur de maillage sur une grille.
void setPartIndex(Int32 i, Int32 j, Int32 k) override
Indice (i,j,k) de la partie.
void build() override
Construction de niveau build du service.
void notifyEndPartition() override
Notification lors de la fin d'un repartionnement (après échange des entités)
void _addCellToIntersectedParts(Cell cell, std::array< Int32, 3 > min_part, std::array< Int32, 3 > nb_part)
IPrimaryMesh * primaryMesh() override
Maillage associé
Int32 _findPart(RealConstArrayView coords, Real center)
Retourne l'indice dans coords de la valeur immédiatement inférieure à position.
void setBoundingBox(Real3 min_val, Real3 max_val) override
Positionne la bounding box de notre sous-domaine.
void applyMeshPartitioning(IMesh *mesh) override
Applique le repartitionnement sur le maillage mesh.
void partitionMesh(bool initial_partition) override
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
TraceMessage info() const
Flot pour un message d'information.
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
ARCCORE_HOST_DEVICE Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
constexpr ARCCORE_HOST_DEVICE bool isNearlyEqual(const _Type &a, const _Type &b)
Teste si deux valeurs sont à un peu près égales. Pour les types entiers, cette fonction est équivalen...
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.
@ IK_Cell
Entité de maillage de genre maille.
Int32 Integer
Type représentant un entier.