14#include "arcane/utils/ScopedPtr.h"
15#include "arcane/utils/StringBuilder.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/ITraceMng.h"
19#include "arcane/core/BasicService.h"
20#include "arcane/core/ISubDomain.h"
21#include "arcane/core/ServiceFinder2.h"
22#include "arcane/core/FactoryService.h"
23#include "arcane/core/SerializeBuffer.h"
24#include "arcane/core/IMeshPartitioner.h"
25#include "arcane/core/IMainFactory.h"
26#include "arcane/core/IMeshModifier.h"
27#include "arcane/core/Properties.h"
28#include "arcane/core/IInitialPartitioner.h"
29#include "arcane/core/Timer.h"
30#include "arcane/core/IMesh.h"
31#include "arcane/core/IMeshSubMeshTransition.h"
32#include "arcane/core/IItemFamily.h"
33#include "arcane/core/IDirectExecution.h"
34#include "arcane/core/IParallelMng.h"
35#include "arcane/core/IMeshUtilities.h"
36#include "arcane/core/IMeshWriter.h"
37#include "arcane/core/ITimeStats.h"
38#include "arcane/core/ServiceBuilder.h"
39#include "arcane/core/IMeshPartitionConstraintMng.h"
40#include "arcane/core/ExternalPartitionConstraint.h"
42#include "arcane/std/ArcaneCasePartitioner_axl.h"
55class ArcaneCasePartitioner;
78 void build()
override {}
91 ISubDomain* m_sub_domain =
nullptr;
92 ArcaneCasePartitioner* m_main =
nullptr;
133 std::ofstream m_sortiesCorrespondance;
137 void _partitionMesh(Int32
nb_part);
152 Integer
nb_mesh = meshes.size();
156 IMesh* mesh = meshes[0];
160 tm->
info()<<
" _regroupeContraintes: nbMailles = "<<meshes[0]->nbCell() <<
", nbMaillesLocales = "<< meshes[0]->ownCells().size();
173 sd->timeStats()->dumpTimeAndMemoryUsage(
sd->parallelMng());
179 mesh->
utilities()->changeOwnersFromCells();
181 bool compact = mesh->
properties()->getBool(
"compact");
184 mesh->
properties()->setBool(
"compact", compact);
217 if (!mesh_partitioner.get())
222 Integer
nb_mesh = meshes.size();
232 for( Integer i=0; i<
nb_mesh; ++i ){
233 IMesh* mesh = meshes[i];
253 sd->timeStats()->dumpTimeAndMemoryUsage(pm);
257 mesh_partitioner->partitionMesh(mesh,
nb_part);
259 tm->
info() <<
"Partitioning time t=" <<
t.lastActivationTime();
260 sd->timeStats()->dumpTimeAndMemoryUsage(pm);
271 mesh->
utilities()->changeOwnersFromCells();
274 bool compact = mesh->
properties()->getBool(
"compact");
278 mesh->
properties()->setBool(
"compact", compact);
283 IMesh* mesh = meshes[0];
284 if (m_main->
options()->nbGhostLayer()==2)
285 mesh->updateGhostLayers(
false);
302 tm->
info() <<
" -- Partitioning statistics --";
303 tm->
info() <<
" Part NbCell";
304 for( Integer i=0; i<
nb_part; ++i ){
312ArcaneCasePartitioner::
317 info() <<
"** ** SET INITIAL PARTITIONER 2";
324ArcaneCasePartitioner::
325~ArcaneCasePartitioner()
336 info() <<
"ArcaneCasePartitioner::execute() nb_part=" <<
nb_part;
338 subDomain()->timeStats()->dumpTimeAndMemoryUsage(subDomain()->parallelMng());
349void ArcaneCasePartitioner::
362 pfatal() <<
"No service selected to write the mesh";
367 info() <<
"Mesh file pattern=" << pattern;
386 new_mesh->setDimension(mesh()->dimension());
388 new_mesh->properties()->setBool(
"compact",
false);
389 new_mesh->properties()->setBool(
"sort",
false);
390 new_mesh->modifier()->setDynamic(
true);
397 if (
options()->createCorrespondances())
406 for(
IItemFamily* family : mesh()->itemFamilies() ){
408 iitem->mutableItemBase().setOwner(0,0);
415 info() <<
"NbPart=" << nb_part <<
" my_rank=" << my_rank;
416 for( Integer i=0; i<nb_part; ++i ){
417 if ((i % nb_rank)!=my_rank){
418 if (my_rank==0 &&
options()->createCorrespondances()){
420 info()<<
"Receive on master to build correspondence file on sub-domain "<<i
421 <<
" sent from processor "<<i % nb_rank;
426 pm->
recv(taillesTab, i % nb_rank);
427 nodesUniqueId.resize(taillesTab[0]);
428 cellsUniqueId.resize(taillesTab[1]);
429 pm->
recv(nodesUniqueId, i % nb_rank);
430 pm->
recv(cellsUniqueId, i % nb_rank);
439 UniqueArray<Cell> cells_selected_for_new_mesh;
441 if (true_cells_owner[icell]==i){
443 cells_selected_for_new_mesh.add(cell);
449 _addGhostLayers(current_all_cells, cells_selected_for_new_mesh,
options()->nbGhostLayer(), maxLocalIdCell, maxLocalIdNode);
453 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
454 Cell cell = cells_selected_for_new_mesh[j];
455 cells_local_id.add(cell.localId());
456 cells_unique_id.add(
static_cast<Int64>(cell.uniqueId()));
459 Integer nb_cell_to_copy = cells_local_id.size();
460 SerializeBuffer buffer;
462 info() <<
"NB_CELL_TO_SERIALIZE=" << nb_cell_to_copy;
463 new_mesh->
modifier()->addCells(&buffer);
472 new_mesh->
cellFamily()->itemsUniqueIdToLocalId(new_cells_local_id,cells_unique_id);
473 for( Integer zid=0; zid<nb_cell_to_copy; ++zid ){
474 Cell current_cell = current_cells[cells_local_id[zid]];
475 Cell new_cell = new_cells[new_cells_local_id[zid]];
476 if (current_cell.uniqueId()!=new_cell.uniqueId())
477 fatal() <<
"Inconsistent unique ids";
478 Integer nb_node = current_cell.nbNode();
482 for( Integer z2=0; z2<nb_node; ++z2 ){
483 Real3 coord = current_coordinates[current_cell.node(z2)];
486 new_coordinates[new_cell.node(z2)] = coord;
488 new_cell.node(z2).mutableItemBase().setOwner(true_nodes_owner[current_cell.node(z2)],0);
498 if (
options()->nbGhostLayer()>0)
499 _addGhostGroups(new_mesh, cells_selected_for_new_mesh, true_cells_owner, true_nodes_owner, new_cells_local_id, i);
502 info() <<
"NB_NEW_CELL=" << new_nb_cell;
503 min_nb_cell =
math::min(min_nb_cell,new_nb_cell);
504 max_nb_cell =
math::max(max_nb_cell,new_nb_cell);
505 saved_nb_cell += new_nb_cell;
507 if (pattern.
empty()){
508 StringBuilder sfilename =
"cut_mesh_";
510 sfilename +=
".mli2";
511 filename = sfilename;
517 if (pattern.
length()>128){
518 pfatal() <<
"Pattern too long (max=128)";
521 filename = String(StringView(buf));
524 info() <<
"Writing mesh file filename='" << filename <<
"'";
525 bool is_bad = mesh_writer->writeMeshToFile(new_mesh, filename);
527 ARCANE_FATAL(
"Can not write mesh file '{0}'", filename);
531 if (
options()->createCorrespondances()){
532 info()<<
"Participation to build correspondence file on sub-domain "<<i;
536 taillesTab.add(new_mesh->
cellFamily()->nbItem());
540 NodeInfoListView nodes(new_mesh->
nodeFamily());
541 for(
int j=0; j<taillesTab[0]; ++j ){
542 Node node = nodes[j];
543 nodesUniqueId[j] = node.uniqueId();
546 CellInfoListView cells(new_mesh->
cellFamily());
547 for(
int j=0; j<taillesTab[1]; ++j ){
548 Cell cell = cells[j];
549 cellsUniqueId[j] = cell.uniqueId();
553 pm->send(taillesTab, 0);
554 pm->send(nodesUniqueId, 0);
555 pm->send(cellsUniqueId, 0);
563 Integer total_new_nb_cell = pm->
reduce(Parallel::ReduceSum,saved_nb_cell);
564 Integer total_min_nb_cell = pm->
reduce(Parallel::ReduceMin,min_nb_cell);
565 Integer total_max_nb_cell = pm->
reduce(Parallel::ReduceMax,max_nb_cell);
566 info() <<
"TOTAL_NEW_NB_CELL=" << total_new_nb_cell
567 <<
" min=" << total_min_nb_cell
568 <<
" max=" << total_max_nb_cell
569 <<
" computed_average=" << (total_current_nb_cell/nb_part);
571 subDomain()->timeStats()->dumpTimeAndMemoryUsage(pm);
573 if (
options()->createCorrespondances())
576 if (
options()->nbGhostLayer()==0)
577 if (total_new_nb_cell!=total_current_nb_cell)
578 pfatal() <<
"Bad number of saved cells current=" << total_current_nb_cell
579 <<
" saved=" << total_new_nb_cell;
581 pinfo()<<
"Total Memory Used : "<<platform::getMemoryUsed();
595 m_sortiesCorrespondance.open(
"Correspondances");
597 if (m_sortiesCorrespondance.fail ()){
598 pfatal() <<
"Unable to write to file 'Correspondances' ";
601 m_sortiesCorrespondance <<
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
602 m_sortiesCorrespondance <<
"<!-- Correspondance file generated by Arcane/Decoupe3D V2 -->\n";
603 m_sortiesCorrespondance <<
"\n<cpus>\n";
612 info()<<
" _writeCorrespondance("<<rank<<
", nodesUniqueId.size() = "
615 m_sortiesCorrespondance <<
" <cpu id=\"" << rank <<
"\">" <<
"\n"
616 <<
" <noeuds>" <<
"\n" <<
" ";
620 m_sortiesCorrespondance <<
"\n" <<
" </noeuds>"
622 <<
" <mailles>" <<
"\n"
626 m_sortiesCorrespondance <<
"\n" <<
" </mailles>" <<
"\n"
627 <<
" </cpu>" <<
"\n";
639 m_sortiesCorrespondance <<
"</cpus>\n";
640 m_sortiesCorrespondance.close ();
695 if (
new_lid!=NULL_ITEM_LOCAL_ID)
706void ArcaneCasePartitioner::
726 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
727 Cell cell = cells_selected_for_new_mesh[j];
730 for( Integer k=0, ks=nodes.size(); k<ks; ++k){
731 Node node = nodes[k];
732 if (filtre_lid_node[node.localId()]==0){
736 for( Integer i=0, is=cells_vois.size(); i<is; ++i ){
737 Cell cell_vois = cells_vois[i];
738 if (filtre_lid_cell[cell_vois.localId()]==0){
741 cells_selected_for_new_mesh.add(cell_vois);
743 filtre_lid_cell[cell_vois.localId()] = 1;
746 filtre_lid_node[node.localId()] = 1;
752 _addGhostLayers(current_all_cells, cells_selected_for_new_mesh, nbCouches-1, maxLocalIdCell, maxLocalIdNode);
760void ArcaneCasePartitioner::
761_addGhostGroups(IMesh* new_mesh, Array<Cell>& cells_selected_for_new_mesh,
VariableCellInt32& true_cells_owner,
763 Int32Array& new_cells_local_id, Integer id_loc)
765 info()<<
"ArcaneCasePartitioner::_addGhostGroups (id_loc = "<<id_loc<<
")";
768 std::map<Integer, Integer> dom_vois;
769 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
770 Cell cell = cells_selected_for_new_mesh[j];
771 dom_vois[true_cells_owner[cell]] += 1;
775 std::map<Integer,SharedArray<Int32> > map_groupes;
776 for (std::map<Integer, Integer>::const_iterator iter=dom_vois.begin(); iter!=dom_vois.end(); ++iter){
777 Integer no_sous_dom = iter->first;
778 Integer nb_mailles_sous_dom = iter->second;
782 tab.
reserve(nb_mailles_sous_dom);
785 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
786 Cell cell = cells_selected_for_new_mesh[j];
787 Integer no_sous_dom = true_cells_owner[cell];
790 Int32Array & liste_lid = map_groupes[no_sous_dom];
791 liste_lid.
add(new_cells_local_id[j]);
795 for (std::map<Integer,SharedArray<Int32> >::iterator iter=map_groupes.begin(); iter!=map_groupes.end(); ++iter){
796 Integer no_sous_dom = iter->first;
799 ItemGroup groupe_loc;
800 if (no_sous_dom==id_loc)
801 groupe_loc = new_mesh->cellFamily()->findGroup(
"LOCAL",
true);
803 String nom_mf(
"MF_");
804 nom_mf = nom_mf+no_sous_dom;
805 groupe_loc = new_mesh->cellFamily()->findGroup(nom_mf,
true);
808 groupe_loc.addItems(liste_lid,
false);
815 Integer nbnodes = new_mesh->nodeFamily()->nbItem();
816 liste_lid.reserve(nbnodes);
817 NodeInfoListView nodes(new_mesh->nodeFamily());
818 for (
int j= 0 ; j < nbnodes ; ++j) {
820 if (true_nodes_owner[node] == id_loc)
821 liste_lid.add(node.localId());
824 ItemGroup groupe_loc = new_mesh->nodeFamily()->findGroup(
"LOCALN",
true);
825 groupe_loc.addItems(liste_lid,
false);
830 ItemGroup groupe_glob = new_mesh->cellFamily()->findGroup(
"TOUT",
true);
832 groupe_glob.addItems(new_cells_local_id,
false);
837ARCANE_REGISTER_SERVICE_ARCANECASEPARTITIONER(ArcaneCasePartitioner,ArcaneCasePartitioner);
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Generation de la classe de base du Service.
CaseOptionsArcaneCasePartitioner * options() const
Options du jeu de données du service.
Service de partitionnement externe du maillage.
bool isActive() const override
Vrai si le service est actif.
void execute() override
Exécute l'opération du service.
void _initCorrespondance(Int32 my_rank)
Ouverture du fichier Correspondance (seulement sur le proc 0)
void _computeGroups(IItemFamily *current_family, IItemFamily *new_family)
Recopie les groupes de la famille courante dans la nouvelle.
void build() override
Construction de niveau build du service.
void _finalizeCorrespondance(Int32 my_rank)
Fermeture du fichier Correspondance (seulement sur le proc 0)
void setParallelMng(IParallelMng *) override
Positionne le gestionnaire de parallèlisme associé. Cette méthode doit être appelée avant execute()
void _writeCorrespondance(Int32 rank, Int64Array &nodesUniqueId, Int64Array &cellsUniqueId)
Ecriture du fichier Correspondance.
void partitionAndDistributeMeshes(ConstArrayView< IMesh * > meshes) override
Partitionne les maillages.
void _printStats(Integer nb_part, IMesh *mesh, VariableCellInt32 &new_owners)
Affiche des statistiques sur le partitionnement.
void _mergeConstraints(ConstArrayView< IMesh * > meshes)
Regroupe les mailles associées aux contraintes sur un même proc.
UniqueArray< TrueOwnerInfo > m_part_indexes
Stocke pour chaque maillage une variable indiquant pour chaque maille quelle partie la possède.
Tableau d'items de types quelconques.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
Interface d'un partitionneur initial.
Interface d'une famille d'entités.
Manufacture des classes d'Arcane.
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual Integer nbCell()=0
Nombre de mailles du maillage.
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
virtual IItemFamily * edgeFamily()=0
Retourne la famille des arêtes.
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
Interface d'une contrainte de partitionnement d'un maillage.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual ItemInternalList itemsInternal(eItemKind)=0
Tableau interne des éléments du maillage de type type.
virtual IMeshModifier * modifier()=0
Interface de modification associée.
virtual ARCANE_DEPRECATED_240 void serializeCells(ISerializer *buffer, Int32ConstArrayView cells_local_id)=0
virtual void destroyGroups()=0
Détruit tous les groupes de toutes les familles.
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.
virtual bool isDynamic() const =0
Indique si le maillage est dynamique (peut évoluer)
virtual Properties * properties()=0
Propriétés associées à ce maillage.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual IParallelMng * sequentialParallelMng()=0
Retourne un gestionnaire de parallélisme séquentiel.
virtual void recv(ArrayView< char > values, Int32 rank)=0
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.
Interface du gestionnaire d'un sous-domaine.
virtual void setInitialPartitioner(IInitialPartitioner *partitioner)=0
Positionne le partitionneur initial.
Groupe d'entités de maillage.
const String & name() const
Nom du groupe.
bool isOwn() const
Retourne si le groupe contient uniquement des éléments propres au sous-domaine.
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Structure contenant les informations pour créer un service.
Sentinelle pour le timer. La sentinelle associée à un timer permet de déclancher celui-ci au moment d...
@ TimerReal
Timer utilisant le temps réel.
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 add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Interface du gestionnaire de traces.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
bool empty() const
Vrai si la chaîne est vide (nulle ou "")
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Int64 length() const
Retourne la longueur de la chaîne.
TraceMessage pinfo() const
Flot pour un message d'information en parallèle.
TraceMessage pfatal() const
Flot pour un message d'erreur fatale en parallèle.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage fatal() const
Flot pour un message d'erreur fatale.
Formattage du flot en longueur.
Vecteur 1D de données avec sémantique par valeur (style STL).
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.
ItemVectorViewT< Node > NodeVectorView
Vue sur un vecteur de noeuds.
ItemVectorViewT< Cell > CellVectorView
Vue sur un vecteur de mailles.
MeshVariableScalarRefT< Node, Int32 > VariableNodeInt32
Grandeur au noeud de type entier 32 bits.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableScalarRefT< Cell, Int32 > VariableCellInt32
Grandeur au centre des mailles de type entier 32 bits.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ SB_Collective
Indique que tous les processus font la même opération.
@ SB_AllowNull
Autorise l'absence du service.
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
@ IK_Cell
Entité de maillage de genre maille.
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Int32 Integer
Type représentant un entier.