14#include "arcane/utils/StringBuilder.h"
15#include "arcane/utils/Iostream.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/Convert.h"
18#include "arcane/utils/NotImplementedException.h"
19#include "arcane/utils/ArgumentException.h"
20#include "arcane/utils/FloatingPointExceptionSentry.h"
21#include "arcane/utils/ValueConvert.h"
23#include "arcane/ISubDomain.h"
24#include "arcane/IParallelMng.h"
25#include "arcane/ItemEnumerator.h"
26#include "arcane/IMesh.h"
27#include "arcane/IMeshSubMeshTransition.h"
28#include "arcane/ItemGroup.h"
29#include "arcane/Service.h"
30#include "arcane/Timer.h"
31#include "arcane/FactoryService.h"
32#include "arcane/ItemPrinter.h"
33#include "arcane/IItemFamily.h"
34#include "arcane/MeshVariable.h"
35#include "arcane/VariableBuildInfo.h"
37#include "arcane/std/MeshPartitionerBase.h"
38#include "arcane/std/MetisMeshPartitioner_axl.h"
41#define MPICH_SKIP_MPICXX
42#define OMPI_SKIP_MPICXX
46#if (PARMETIS_MAJOR_VERSION < 4)
47#error "Your version of Parmetis is too old .Version 4.0+ is required"
50typedef real_t realtype;
53#include "arcane/std/PartitionConverter.h"
54#include "arcane/std/GraphDistributor.h"
55#include "arcane/std/internal/MetisWrapper.h"
65using MetisCallStrategy = TypesMetisMeshPartitioner::MetisCallStrategy;
66using MetisEmptyPartitionStrategy = TypesMetisMeshPartitioner::MetisEmptyPartitionStrategy;
94 Integer m_random_seed;
95 bool m_disable_floatingexception;
112MetisMeshPartitioner::
113MetisMeshPartitioner(
const ServiceBuildInfo& sbi)
114: ArcaneMetisMeshPartitionerObject(sbi)
117, m_disable_floatingexception(false)
120 String s = platform::getEnvironmentVariable(
"ARCANE_DISABLE_METIS_FPE");
121 if (s==
"1" || s==
"TRUE")
122 m_disable_floatingexception =
true;
144 if (m_disable_floatingexception){
170 info() <<
"INFO: Unable to test load balancing on a single sub-domain";
187 info() <<
"WARNING: compensating the potential lack of 'Metis' options in case of manual instanciation";
192 MetisCallStrategy
call_strategy = MetisCallStrategy::one_processor_per_node;
232 initConstraints(
false);
246 <<
" disabling_fpe?=" << m_disable_floatingexception
247 <<
" sizeof(idxtype)==" <<
sizeof(idxtype);
267 for( Integer i=0; i<nb_rank; ++i ){
280 info() <<
"INFO: mesh '" << mesh->
name() <<
" has no cell. No partitioning is needed";
304 if (cellUsedWithConstraints(item)){
333 if (!cellUsedWithConstraints(item))
353 String s = platform::getEnvironmentVariable(
"ARCANE_LB_PARAM");
354 if (!s.
null() && (s.
upper() ==
"PARTICLES"))
383 info() <<
"We have to increase imbalance :";
399 Integer iteration = mesh->
subDomain()->commonVariables().globalIteration();
406 for (
int i = 0; i <
metis_xadj.size()-1 ; ++i) {
407 dumpy <<
" Weight uid=" << i;
456 std::chrono::high_resolution_clock
clock;
476 if (
call_strategy == MetisCallStrategy::two_processors_two_nodes ||
call_strategy == MetisCallStrategy::two_scattered_processors) {
502 info() <<
"Initialize GraphDistributor with max rank=1";
503 gd.initWithMaxRank(1);
505 else if (
call_strategy == MetisCallStrategy::two_gathered_processors && (nb_rank > 2)) {
507 info() <<
"Initialize GraphDistributor with max rank=2";
508 gd.initWithMaxRank(2);
511 info() <<
"Initialize GraphDistributor with one rank per node"
529 if (
gd.contribute()) {
552 Integer iteration =
sd->commonVariables().globalIteration();
573 info() <<
"Metis: use a complete partitioning.";
588 info() <<
"Metis: use a complete REpartitioning.";
608 info() <<
"Metis: use a diffusive REpartitioning";
631 info() <<
"Time to partition using parmetis = " <<
duration.count() <<
" us ";
637 switch(
options()->emptyPartitionStrategy()){
638 case MetisEmptyPartitionStrategy::DoNothing:
640 case MetisEmptyPartitionStrategy::TakeFromBiggestPartitionV1:
643 case MetisEmptyPartitionStrategy::TakeFromBiggestPartitionV2:
656 if (!cellUsedWithConstraints(item))
672 m_nb_refine = m_parallel_mng->
reduce(Parallel::ReduceMax, m_nb_refine);
710 for(
int i = 0; i <
nb_part ; i++) {
719 info() <<
"Parmetis: number empty parts " <<
nb_hole;
725 for(
int i = 0; i <
nb_part ; i++) {
776 for(
int i = 0; i <
nb_part ; i++) {
806 for(
int i = 0; i <
nb_part ; i++) {
848 pwarning() <<
"Can not remove all empty partitions. This is probably because you try"
849 <<
" to cut in too many partitions";
887#define METIS_ERROR ARCANE_FATAL("_writeGraph")
899 std::cerr <<
"_writeGraph : nvtx+1 = " <<
nvtx <<
" != " <<
metis_xadj.size() << std::endl;
918 file <<
"2" << std::endl;
963#if ARCANE_DEFAULT_PARTITIONER == METIS_DEFAULT_PARTITIONER
#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.
Generation de la classe de base du Service.
CaseOptionsMetisMeshPartitioner * options() const
Options du jeu de données du service.
Int32 nbFace() const
Nombre de faces de la maille.
Classe permettant d'activer/désactiver temporairement les exceptions flottantes du processeur.
Redistribute graph data to another "communicator".
virtual String name() const =0
Nom du maillage.
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
Interface d'un partitionneur de maillage.
Interface d'un partitionneur de maillage.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual ISubDomain * subDomain()=0
Sous-domaine associé
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual bool isThreadImplementation() const =0
Indique si l'implémentation utilise les threads.
virtual void computeMinMaxSum(char val, char &min_val, char &max_val, char &sum_val, Int32 &min_rank, Int32 &max_rank)=0
Calcule en une opération la somme, le min, le max d'une valeur.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Effectue un regroupement sur tous les processeurs. Il s'agit d'une opération collective....
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 void barrier()=0
Effectue une barière.
Interface du gestionnaire d'un sous-domaine.
virtual const CommonVariables & commonVariables() const =0
Informations sur les variables standards.
@ PNoDump
Indique que la variable ne doit pas être sauvegardée.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
IMesh * mesh() const
Maillage associé au partitionneur.
virtual Real imbalance() const
Déséquilibre de temps de calcul.
virtual Real maxImbalance() const
Déséquilibre maximal autorisé
virtual void changeOwnersFromCells()
Positionne les nouveaux propriétaires des noeuds, arêtes et faces à partir des mailles.
Partitioneur de maillage utilisant la bibliothèque PARMetis.
void partitionMesh(bool initial_partition) override
void _removeEmptyPartsV2(Int32 nb_part, ArrayView< idxtype > metis_part)
Comble les partitions vides (version 2).
Int32 _removeEmptyPartsV2Helper(Int32 nb_part, ArrayView< idxtype > metis_part, Int32 algo_iteration)
Applique une itération de l'algorithme de suppression des partitions vides.
void build() override
Construction de niveau build du service.
void _partitionMesh(bool initial_partition, Int32 nb_part)
int _writeGraph(IParallelMng *pm, Span< const idxtype > metis_vtkdist, Span< const idxtype > metis_xadj, Span< const idxtype > metis_adjncy, Span< const idxtype > metis_vwgt, Span< const idxtype > metis_ewgt, const String &Name) const
void _removeEmptyPartsV1(const Int32 nb_part, const Int32 nb_own_cell, ArrayView< idxtype > metis_part)
Comble les partitions vides (version 1).
Wrapper autour des appels de Parmetis.
Structure contenant les informations pour créer un service.
Propriétés de création d'un service.
Postionne le nom de l'action en cours d'exécution.
Paramètres nécessaires à la construction d'une variable.
Exception lorsqu'un argument est invalide.
virtual void flush()=0
Flush tous les flots.
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.
String upper() const
Transforme tous les caractères de la chaîne en majuscules.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
bool null() const
Retourne true si la chaîne est nulle.
TraceMessage pwarning() const
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
Vecteur 1D de données avec sémantique par valeur (style STL).
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
Integer toInteger(Real r)
Converti un Int64 en un Integer.
Int32 toInt32(Int64 v)
Converti un Int64 en un Int32.
Integer toInteger(Real r)
Converti un Real en Integer.
-*- 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.