14#include "arcane/utils/InvalidArgumentException.h"
15#include "arcane/utils/FatalErrorException.h"
16#include "arcane/utils/ParallelFatalErrorException.h"
17#include "arcane/utils/ArgumentException.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/Real3.h"
20#include "arcane/utils/HashTableMap.h"
21#include "arcane/utils/OStringStream.h"
22#include "arcane/utils/ScopedPtr.h"
23#include "arcane/utils/StringBuilder.h"
24#include "arcane/utils/CheckedConvert.h"
25#include "arcane/utils/PlatformUtils.h"
27#include "arcane/utils/NotImplementedException.h"
29#include "arcane/IMesh.h"
30#include "arcane/IMeshWriter.h"
31#include "arcane/IParallelMng.h"
32#include "arcane/MeshUtils.h"
33#include "arcane/IItemFamily.h"
34#include "arcane/ItemPrinter.h"
35#include "arcane/VariableTypes.h"
36#include "arcane/ItemPairGroup.h"
37#include "arcane/ISubDomain.h"
38#include "arcane/ServiceBuilder.h"
39#include "arcane/IParallelReplication.h"
40#include "arcane/Timer.h"
41#include "arcane/IMeshPartitioner.h"
42#include "arcane/IPrimaryMesh.h"
43#include "arcane/IMeshChecker.h"
45#include "arcane/mesh/UnstructuredMeshUtilities.h"
46#include "arcane/IItemFamilyNetwork.h"
47#include "arcane/ConnectivityItemVector.h"
48#include "arcane/mesh/NewItemOwnerBuilder.h"
49#include "arcane/mesh/ParticleFamily.h"
50#include "arcane/mesh/GraphDoFs.h"
51#include "arcane/mesh/BasicItemPairGroupComputeFunctor.h"
52#include "arcane/mesh/MeshNodeMerger.h"
53#include "arcane/mesh/ConnectivityNewWithDependenciesTypes.h"
66UnstructuredMeshUtilities::
67UnstructuredMeshUtilities(IMesh* mesh)
68: TraceAccessor(mesh->traceMng())
70, m_compute_adjency_functor(new BasicItemPairGroupComputeFunctor(traceMng()))
77UnstructuredMeshUtilities::
78~UnstructuredMeshUtilities()
80 delete m_compute_adjency_functor;
86void UnstructuredMeshUtilities::
87changeOwnersFromCells()
120#ifdef ARCANE_DEBUG_LOAD_BALANCING
124 <<
" current_cell_owner=" << cell.
owner()
138#ifdef ARCANE_DEBUG_LOAD_BALANCING
142 <<
" current_cell_owner=" << cell.
owner()
165 for(
IItemFamily* family : m_mesh->itemFamilies() ){
177 if(m_mesh->itemFamilyNetwork())
180 for(
IItemFamily* family : m_mesh->itemFamilies() )
182 if (family->itemKind()!=
IK_DoF || family->name()==mesh::GraphDoFs::linkFamilyName())
194 auto connectivity_name = mesh::connectivityName(family,
dualitem_family) ;
196 auto connectivity = m_mesh->itemFamilyNetwork()->getConnectivity(family,
dualitem_family,connectivity_name) ;
199 connectivity = m_mesh->itemFamilyNetwork()->getConnectivity(
dualitem_family,family,connectivity_name) ;
262void UnstructuredMeshUtilities::
263localIdsFromConnectivity(
eItemKind item_kind,
272 "IK_Cell or IK_Face expected",
279 "Size different from 'items_nb_node'",
286 for( Integer i=0; i<
nb_item; ++i ){
305 if (
j != 0)
sb +=
" ";
308 sb +=
") not found (first node ";
317 Face face(mesh_utils::getFaceFromNodesUnique(node,buf));
325 if (
j != 0)
sb +=
" ";
341Real3 UnstructuredMeshUtilities::
346 if (math::isNearlyZero(value.x))
348 if (math::isNearlyZero(value.y))
350 if (math::isNearlyZero(value.z))
353 if (math::isNearlyEqual(value.x,1.0))
355 if (math::isNearlyEqual(value.y,1.0))
357 if (math::isNearlyEqual(value.z,1.0))
360 if (math::isNearlyEqual(value.x,-1.0))
362 if (math::isNearlyEqual(value.y,-1.0))
364 if (math::isNearlyEqual(value.z,-1.0))
376 String func_name =
"UnstructuredMeshUtilities::computeNormal";
438 Node node = nodes_internal[d->key()];
440 if (node.owner()==rank){
441 single_nodes.add(node);
464 pm->broadcast(Real3ArrayView(1,&buf),max_rank);
465 total_global_normal = buf;
468 info() <<
"TOTAL SINGLE NODE= " << total_nb_single_node <<
" surface=" << face_group.name()
469 <<
" global_normal = " << total_global_normal;
470 if (total_nb_single_node<2){
471 ARCANE_FATAL(
"not enough nodes connected to only one face");
474 for( Integer i=0; i<nb_single_node; ++i ){
475 coords[i] = nodes_coord[single_nodes[i]];
478 UniqueArray<Real3> all_nodes_coord;
482 Real3 barycentre = Real3::null();
483 for( Integer i=0; i<total_nb_single_node; ++i ){
484 barycentre += all_nodes_coord[i];
486 barycentre /= (
Real)total_nb_single_node;
487 if (total_nb_single_node==2 && m_mesh->dimension()==3){
493 Real max_distance = 0.0;
495 Real3 s0 = all_nodes_coord[0];
496 Real3 s1 = all_nodes_coord[1];
497 nodes_occurence.each([&](NodeOccurenceMap::Data* d){
498 Node node = nodes_internal[d->key()];
499 Real3 coord = nodes_coord[node];
501 if (math::isNearlyEqual(coord,s0))
503 if (math::isNearlyEqual(coord,s1))
505 Real distance = (coord - barycentre).squareNormL2();
506 if (distance>max_distance){
507 Real3 normal = math::cross(coord-s0, s1-s0);
509 if (!math::isNearlyZero(normal.squareNormL2())){
510 max_distance = distance;
511 farthest_node = node;
516 if (!farthest_node.null()){
517 info() <<
" FARTHEST NODE= " << ItemPrinter(farthest_node) <<
" dist=" << max_distance;
520 Real3 farthest_coord = _broadcastFarthestNode(max_distance,farthest_node,nodes_coord);
521 info() <<
" FARTHEST NODE ALL coord=" << farthest_coord;
522 all_nodes_coord.add(farthest_coord);
527 std::sort(std::begin(all_nodes_coord),std::end(all_nodes_coord));
528 Integer nb_final_node = all_nodes_coord.size();
529 Real3 full_normal = Real3::null();
530 info() <<
" NB FINAL NODE=" << nb_final_node;
531 for( Integer i=0; i<nb_final_node; ++i )
532 info() <<
" NODE=" << all_nodes_coord[i];
533 if (m_mesh->dimension()==2){
534 if (nb_final_node!=2){
537 Real3 direction = all_nodes_coord[1] - all_nodes_coord[0];
538 full_normal.x = - direction.y;
539 full_normal.y = direction.x;
541 else if (m_mesh->dimension()==3){
550 Real3 first_normal = math::vecMul(all_nodes_coord[2]-all_nodes_coord[0],
551 all_nodes_coord[1]-all_nodes_coord[0]);
552 for( Integer i=0; i<nb_final_node; ++i ){
553 Real3 s0 = all_nodes_coord[i];
554 Real3 s1 = all_nodes_coord[(i+nb_final_node-1)%nb_final_node];
555 Real3 s2 = all_nodes_coord[(i+1)%nb_final_node];
556 Real3 normal = math::vecMul(s2-s0, s1-s0);
557 info() <<
" ADD NORMAL: " << normal;
558 full_normal += normal;
559 info() <<
" FULL: " << full_normal;
561 if (math::isNearlyZero(full_normal.squareNormL2()))
562 full_normal = first_normal;
565 ARCANE_FATAL(
"invalid mesh dimension (should be 2 or 3)");
566 Real a = full_normal.normL2();
572 info() <<
" Normal is " << full_normal;
573 if (!math::isZero(b)){
574 total_global_normal /= b;
575 dir = math::scaMul(full_normal,total_global_normal);
577 full_normal = -full_normal;
579 full_normal = _round(full_normal);
580 info() <<
" Final normal is " << full_normal <<
" dir=" << dir;
598 String func_name =
"UnstructuredMeshUtilities::computeDirection";
614 debug() <<
" BARYCENTRE COMPUTE DIRECTION = " <<
barycentre;
654 if (math::isZero(
norm)){
655 ARCANE_FATAL(
"Direction is null for group '{0}' first_coord={1} second_coord={2}",
658 return direction /
norm;
664Real3 UnstructuredMeshUtilities::
668 String func_name =
"UnstructuredMeshUtilities::_broadcastFarthestNode()";
681 <<
" distance=" << distance
685 debug() <<
" FARTHEST NODE myself coord=none"
686 <<
" distance=" << distance
695 debug() <<
" I AM FARTHEST NODE ALL coord=" << buf;
697 pm->broadcast(Real3ArrayView(1,&buf),max_rank);
698 Real3 farthest_coord(buf);
699 debug() <<
" FARTHEST NODE ALL coord=" << farthest_coord
700 <<
" rank=" << max_rank
701 <<
" max_distance=" << all_max_distance;
702 return farthest_coord;
708void UnstructuredMeshUtilities::
717bool UnstructuredMeshUtilities::
726 warning() << String::format(
"The specified service '{0}' to write the mesh is not available."
737void UnstructuredMeshUtilities::
743 if (mesh!=this->m_mesh)
755 info() <<
"Partition start date=" << platform::getCurrentDateTime();
756 if (
pr->isMasterRank()){
762 info() <<
"Waiting for partition information from the master replica";
768 mesh->
checker()->checkValidReplication();
780 if (!
pr->isMasterRank()){
781 changeOwnersFromCells();
785 info() <<
"Partition end date=" << platform::getCurrentDateTime();
790 info() <<
"Exchange end date=" << platform::getCurrentDateTime();
807void UnstructuredMeshUtilities::
811 mesh::MeshNodeMerger
merger(m_mesh);
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Gère la récupération des informations de connectivité.
ItemVectorView connectedItems(ItemLocalId item)
Retourne les entités connectées à item.
Cell frontCell() const
Maille devant la face (maille nulle si aucune)
bool isSubDomainBoundary() const
Indique si la face est au bord du sous-domaine (i.e nbCell()==1)
Cell boundaryCell() const
Maille associée à cette face frontière (maille nulle si aucune)
Interface d'une famille d'entités.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
Interface d'un partitionneur de maillage.
virtual IPrimaryMesh * primaryMesh()=0
Maillage associé
virtual void partitionMesh(bool initial_partition)=0
virtual void notifyEndPartition()=0
Notification lors de la fin d'un repartionnement (après échange des entités)
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IMeshChecker * checker() const =0
Interface du vérificateur.
virtual void prepareForDump()=0
Prépare l'instance en vue d'une protection.
Interface du gestionnaire de parallélisme pour un sous-domaine.
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 IParallelReplication * replication() const =0
Informations sur la réplication.
virtual ITimeStats * timeStats() const =0
Gestionnaire de statistiques associé (peut être nul)
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
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.
Informations sur la réplication des sous-domaines en parallèle.
Interface gérant les statistiques sur les temps d'exécution.
Exception lorsqu'une erreur fatale est survenue.
Index d'un Item dans une variable.
Tableau de listes d'entités.
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é
NodeLocalIdView nodeIds() const
Liste des noeuds de l'entité
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
bool isOwn() const
true si l'entité est appartient au sous-domaine
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Vue sur les informations des noeuds.
Classe gérant un vecteur de réel de dimension 3.
ARCCORE_HOST_DEVICE Real normL2() const
Retourne la norme L2 du triplet .
Postionne le nom de l'action en cours d'exécution.
Exception lorsqu'un argument est invalide.
Vue modifiable d'un tableau d'un type T.
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.
Vue constante d'un tableau de type T.
Exception lorsqu'une fonction n'est pas implémentée.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
Vecteur 1D de données avec sémantique par valeur (style STL).
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ SB_AllowNull
Autorise l'absence du service.
UniqueArray< Real3 > Real3UniqueArray
Tableau dynamique à une dimension de vecteurs de rang 3.
eItemKind
Genre d'entité de maillage.
@ IK_Particle
Entité de maillage de genre particule.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Face
Entité de maillage de genre face.
@ IK_DoF
Entité de maillage de genre degre de liberte.
@ IK_Edge
Entité de maillage de genre arête.
Int32 Integer
Type représentant un entier.