14#include "arcane/utils/ScopedPtr.h"
15#include "arcane/utils/ValueChecker.h"
17#include "arcane/mesh/DynamicMesh.h"
18#include "arcane/mesh/ItemGroupsSynchronize.h"
19#include "arcane/mesh/FaceReorienter.h"
20#include "arcane/mesh/DynamicMeshChecker.h"
23#include "arcane/core/Properties.h"
24#include "arcane/core/ItemPrinter.h"
25#include "arcane/core/TemporaryVariableBuildInfo.h"
26#include "arcane/core/IXmlDocumentHolder.h"
27#include "arcane/core/XmlNodeList.h"
28#include "arcane/core/IIOMng.h"
29#include "arcane/core/IParallelMng.h"
30#include "arcane/core/IParallelReplication.h"
31#include "arcane/core/VariableCollection.h"
45DynamicMeshChecker(IMesh* mesh)
46: TraceAccessor(mesh->traceMng())
59 delete m_var_cells_faces;
60 delete m_var_cells_nodes;
73void DynamicMeshChecker::
76 info(4) <<
"Check mesh coherence.";
82 if (family->
itemKind()>=NB_ITEM_KIND)
93 const bool global_check =
false;
94 if (m_check_level>=1 && global_check){
95 if (!m_var_cells_faces)
98 if (!m_var_cells_nodes)
108 if (nb_face>max_nb_face)
109 max_nb_face = nb_face;
110 if (nb_node>max_nb_node)
111 max_nb_node = nb_node;
113 m_var_cells_faces->resize(max_nb_face);
114 m_var_cells_nodes->resize(max_nb_node);
118 for(
Integer z=0; z<nb_face; ++z )
119 (*m_var_cells_faces)[cell][z] = cell.
face(z).
uniqueId().asInt64();
121 for(
Integer z=0; z<nb_node; ++z )
122 (*m_var_cells_nodes)[cell][z] = cell.
node(z).
uniqueId().asInt64();
131void DynamicMeshChecker::
134 String func_name(
"DynamicMesh::checkValidMeshFull");
135 info() << func_name <<
" on " << m_mesh->name();
139 <<
" NAME=" << var_faces.
itemGroup().name()
146 var_faces[face] = uid;
148 var_faces.synchronize();
153 if (uid!=var_faces[face] && uid!=NULL_ITEM_ID && var_faces[face]!=NULL_ITEM_ID){
154 error() << func_name <<
" bad back cell in face uid=" << face.
uniqueId();
163 var_faces[face] = uid;
165 var_faces.synchronize();
170 if (uid!=var_faces[face] && uid!=NULL_ITEM_ID && var_faces[face]!=NULL_ITEM_ID){
171 error() << func_name <<
" bad front cell in face uid=" << face.
uniqueId();
179 if (cell_type == IT_Line2) {
180 error() << func_name <<
" bad cell type in face uid=" << cell.
uniqueId();
188 if (face_type == IT_Vertex) {
189 error() << func_name <<
" bad face type in face uid=" << face.
uniqueId();
212void DynamicMeshChecker::
213checkValidConnectivity()
215 String func_name =
"MeshChecker::checkValidConnectivity";
216 debug() << func_name <<
" check";
220 for(
auto x = item_families.enumerator(); ++x; ){
225 if (!m_mesh->parentMesh()){
231 if (front_cell.
null() && back_cell.
null())
242 bool has_found =
false;
243 for(
Node node2 : cell.nodes() ){
250 ARCANE_FATAL(
"Node uid={0} is connected to the cell uid={1} but the cell"
259 if(!m_mesh->isAmrActivated()){
265 bool has_found =
false;
266 for(
Edge edge2 : cell.edges() ){
273 ARCANE_FATAL(
"Edge uid={0} is connected to the cell uid={1} but the cell"
283 if(!m_mesh->isAmrActivated()){
285 bool has_found =
false;
286 for(
Face face2 : cell.faces() ){
293 ARCANE_FATAL(
"Face uid={0} is connected to the cell uid={1} but the cell"
299 bool has_found =
false;
300 for(
Face face2 : cell.faces() ){
309 <<
" but the cell (level "<< cell.level()<<
")"
310 <<
" is not connected to the face.";
317 if ((back_cell.
null() || front_cell.
null()) && nb_cell==2)
320 if (nb_cell==2 && back_cell!=face.
cell(0))
321 ARCANE_FATAL(
"Bad face face.backCell()!=face.cell(0) face={0} back_cell={1} from_cell={2} cell0={3}",
327 if (m_mesh->parentMesh()){
332 for(
Integer i_kind=0;i_kind<nb_kind;++i_kind){
336 error() <<
"Mesh " << m_mesh->name() <<
" : Family " << kind <<
" does not exist in mesh";
341 const Item & item = *iitem;
344 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent suppresssed parent item uid : "
349 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent item/parent item uid : " <<
ItemPrinter(item);
361 ItemGroup parent_group = m_mesh->parentGroup();
362 String var_name = String::format(
"SubMesh_{0}_GroupConsistencyChecker",parent_group.
name());
367 var[iitem] = iitem->owner();
372 ARCANE_FATAL(
"Mesh name={0} has parent group consistency {1}\n"
373 "This usually means that parent group was not symmetrically built",
377 _checkValidItemOwner(m_mesh->nodeFamily());
378 _checkValidItemOwner(m_mesh->edgeFamily());
379 _checkValidItemOwner(m_mesh->faceFamily());
380 _checkValidItemOwner(m_mesh->cellFamily());
386void DynamicMeshChecker::
387updateAMRFaceOrientation()
389 String func_name =
"MeshChecker::updateAMRFaceOrientation";
396 if ((back_cell.
null() || front_cell.
null()) && nb_cell==2)
399 if (nb_cell==2 && back_cell!=face.
cell(0))
400 ARCANE_FATAL(
"Bad face face.backCell()!=face.cell(0) face={0} back_cell={1} from_cell={2} cell0={3}",
404 fr.checkAndChangeOrientationAMR(face);
411void DynamicMeshChecker::
412updateAMRFaceOrientation(ArrayView<Int64> ghost_cell_to_refine)
414 ItemInternalList cells = m_mesh->itemsInternal(IK_Cell) ;
415 UniqueArray<Integer> lids(ghost_cell_to_refine.size()) ;
416 m_mesh->cellFamily()->itemsUniqueIdToLocalId(lids,ghost_cell_to_refine,
true) ;
417 FaceReorienter fr(m_mesh);
418 std::set<Int64> set ;
419 typedef std::pair<std::set<Int64>::iterator,
bool> return_type ;
420 for(Integer i=0, n=lids.size();i<n;++i){
421 Cell icell = cells[lids[i]] ;
422 for( Integer ic=0, nchild=icell.nbHChildren();ic<nchild;++ic){
423 Cell child = icell.hChild(ic) ;
424 for( Face face : child.faces() ){
425 return_type value = set.insert(face.
uniqueId());
427 fr.checkAndChangeOrientationAMR(face);
439void DynamicMeshChecker::
440_checkFacesOrientation()
442 bool is_1d = (m_mesh->dimension()==1);
447 String func_name =
"MeshChecker::_checkFacesOrientation";
457 Int32 cell_nb_face =
type->nbLocalFace();
458 for(
Integer i_face=0; i_face<cell_nb_face; ++i_face ){
462 m_work_face_sorted_nodes.
resize(face_nb_node);
463 m_work_face_nodes_index.
resize(face_nb_node);
464 m_work_face_orig_nodes_uid.
resize(face_nb_node);
465 for(
Integer z=0; z<face_nb_node; ++z )
468 bool is_reorder =
false;
470 is_reorder = (i_face==1);
471 m_work_face_nodes_index[0] = 0;
475 for(
Integer z=0; z<face_nb_node; ++z )
476 m_work_face_sorted_nodes[z] = m_work_face_orig_nodes_uid[m_work_face_nodes_index[z]];
479 if (cell_face.
nbNode()!=face_nb_node)
480 ARCANE_FATAL(
"Incoherent number of node for 'face' and 'localFace'"
481 " cell={0} face={1} nb_local_node={2} nb_face_node={3}",
484 for(
Integer z=0; z<face_nb_node; ++z ){
485 if (cell_face.
node(z).
uniqueId()!=m_work_face_sorted_nodes[z])
486 ARCANE_FATAL(
"Bad unique id for face: cell={0} face={1} cell_node_uid={2} face_node_uid={3}",
492 if (front_cell!=cell){
493 if (!front_cell.
null())
494 ARCANE_FATAL(
"Bad orientation for face. Should be front cell: cell={0} face={1} front_cell={2}",
497 ARCANE_FATAL(
"Bad orientation for face. Should be front cell (no front cell) cell={0} face={1}",
503 if (back_cell!=cell){
504 if (!back_cell.
null())
505 ARCANE_FATAL(
"Bad orientation for face. Should be back cell: cell={0} face={1} front_cell={2}",
508 ARCANE_FATAL(
"Bad orientation for face. Should be back cell (no back cell) cell={0} face={1}",
519void DynamicMeshChecker::
528 bool allow_orphan_items = m_mesh->meshKind().isNonManifold();
531 if (!m_mesh->parentMesh()){
542 if (cells.
size()==0 && allow_orphan_items)
544 for(
Item cell : cells ){
545 if (cell.owner()==owner){
553 ostr() <<
" nb_cell=" << cells.size();
554 for( Item cell : cells ){
555 ostr() <<
" SubCell i=" << index <<
" cell=" << ItemPrinter(cell);
558 error() <<
"Mesh " << m_mesh->name() <<
" family=" << family->
name()
559 <<
" Item" << ItemPrinter(item) <<
" has no cell with same owner:"
568 Item parent_item = item.
parent();
569 if (parent_item.owner() != item.owner()) {
570 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent item/parent item owner : "
571 << ItemPrinter(item) <<
" / " << ItemPrinter(parent_item);
579 String::plural(nerror,
"owner error"));
585void DynamicMeshChecker::
586checkVariablesSynchronization()
590 for( VariableCollection::Enumerator i_var(used_vars); ++i_var; ){
606 ARCANE_FATAL(
"Error in checkVariablesSynchronization() nb_diff=",nb_diff);
612void DynamicMeshChecker::
613checkItemGroupsSynchronization()
626 ARCANE_FATAL(
"some groups are not synchronized nb_diff={0}",nb_diff);
640void DynamicMeshChecker::
644 Integer sid = m_mesh->meshPartInfo().partRank();
651 for (
Cell cell2 : node.cells()) {
652 if (cell2.owner() == sid) {
658 info() <<
"WARNING: Cell " <<
ItemPrinter(cell) <<
" should not be a ghost cell";
665void DynamicMeshChecker::
666checkMeshFromReferenceFile()
668 if (!m_compare_reference_file)
676 debug() <<
"Testing the mesh against the initial mesh";
677 String base_file_name(
"meshconnectivity");
683 XmlNode doc_node = xml_doc->documentNode();
684 if (!doc_node.
null())
685 mesh_utils::checkMeshConnectivity(m_mesh,doc_node,
true);
688 warning() <<
"Can't test the subdomain coherence "
689 <<
"against the initial mesh";
696void DynamicMeshChecker::
697checkValidReplication()
699 info() <<
"Checking valid replication";
713 wanted_same_family.
add(family);
720 vc.
areEqual(nb_family,max_nb_family,
"Bad number of family");
726 for(
Integer i=0; i<nb_family; ++i )
727 families_size[i] = wanted_same_family[i]->nbItem();
730 vc.
areEqualArray(global_families_size,families_size,
"Bad family");
737 for(
Integer i=0; i<nb_family; ++i ){
738 ItemGroup group = wanted_same_family[i]->allItems();
742 unique_ids[index] = iitem->uniqueId();
746 global_unique_ids.
copy(unique_ids);
748 String message = String::format(
"Bad unique ids for family '{0}'",
749 wanted_same_family[i]->name());
758void DynamicMeshChecker::
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur le maillage.
void checkMeshProperties(IMesh *mesh, bool is_sorted, bool has_no_hole, bool check_faces)
Vérifie que le maillage possède certaines propriétés.
bool reorderNodesOfFace2(Int64ConstArrayView nodes_unique_id, IntegerArrayView new_index)
Réordonne les noeuds d'une face.
Integer size() const
Nombre d'éléments du vecteur.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void copy(Span< const T > rhs)
Copie les valeurs de rhs dans l'instance.
ArrayView< T > view() const
Vue mutable sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Face face(Int32 i) const
i-ème face de la maille
Int32 nbFace() const
Nombre de faces de la maille.
EnumeratorT< IItemFamily * > Enumerator
CellConnectedListViewType cells() const
Liste des mailles de l'arête.
Cette fonction/classe réoriente les faces.
Cell frontCell() const
Maille devant la face (maille nulle si aucune)
Cell cell(Int32 i) const
i-ème maille de la face
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
CellConnectedListViewType cells() const
Liste des mailles de la face.
Cell backCell() const
Maille derrière la face (maille nulle si aucune)
Interface du gestionnaire des entrées sorties.
virtual IXmlDocumentHolder * parseXmlFile(const String &filename, const String &schemaname=String())=0
Lit et analyse le fichier XML filename.
Interface d'une famille d'entités.
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual void checkValid()=0
Vérification de la validité des structures internes (interne)
virtual String name() const =0
Nom de la famille.
virtual IItemFamily * parentFamily() const =0
IItemFamily parent.
virtual eItemKind itemKind() const =0
Genre des entités.
virtual void checkValidConnectivity()=0
Vérification de la validité des structures internes concernant la connectivité.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual IParallelReplication * replication() const =0
Informations sur la réplication.
virtual IIOMng * ioMng() const =0
Gestionnaire des entrées/sorties.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
Informations sur la réplication des sous-domaines en parallèle.
virtual bool hasReplication() const =0
Indique si la réplication est active.
virtual IParallelMng * replicaParallelMng() const =0
Communicateur associé à tous les réplicats représentant un même sous-domaine.
Interface d'une variable.
virtual String itemFamilyName() const =0
Nom de la famille associée (nul si aucune).
virtual eItemKind itemKind() const =0
Type des entités du maillage sur lequel repose la variable.
virtual Integer checkIfSync(Integer max_print=0)=0
Vérifie si la variable est bien synchronisée.
virtual IItemFamily * itemFamily() const =0
Famille d'entité associée.
virtual String itemGroupName() const =0
Nom du groupe d'entité associée.
bool isSuppressed() const
Vrai si l'entité est supprimée.
Groupe d'entités de maillage.
const String & name() const
Nom du groupe.
Integer size() const
Nombre d'éléments du groupe.
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul)
ItemGroup own() const
Groupe équivalent à celui-ci mais contenant uniquement les éléments propres au sous-domaine.
Informations pour synchroniser les groupes entre sous-domaines.
Integer checkSynchronize()
Vérifie si les groupes sont synchronisé.
Classe utilitaire pour imprimer les infos sur une entité.
Informations locales sur une face d'une maille.
Integer node(Integer i) const
Indice locale dans la maille du i-ème noeud de la face.
Integer nbNode() const
Nombre de noeuds de la face.
Infos sur un type d'entité du maillage.
Variable scalaire sur un type d'entité du maillage.
Vue sur un vecteur d'entités.
Int32 size() const
Nombre d'éléments du vecteur.
Node node(Int32 i) const
i-ème noeud de l'entité
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Int32 nbNode() const
Nombre de noeuds de l'entité
Classe de base d'un élément de maillage.
const ItemTypeInfo * typeInfo() const
Infos sur le type de l'entité.
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é
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Item parent(Int32 i) const
i-ème parent pour les sous-maillages
impl::ItemBase itemBase() const
Partie interne de l'entité.
Int16 type() const
Type de l'entité
GroupType itemGroup() const
Groupe associé à la grandeur.
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Encapsulation d'un pointeur qui se détruit automatiquement.
Chaîne de caractères unicode.
static String plural(const Integer n, const String &str, const bool with_number=true)
Forme standard du pluriel par ajout d'un 's'.
Paramètres nécessaires à la construction d'une variable temporaire.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage warning() const
Flot pour un message d'avertissement.
TraceMessage pwarning() const
Vecteur 1D de données avec sémantique par valeur (style STL).
Vérification de la validité de certaines valeurs.
void areEqual(const T1 &value, const T2 &expected_value, const String &message)
void areEqualArray(const T1 &x_values, const T2 &x_expected_values, const String &message)
Vérifie que les deux tableaux values et expected_values ont les mêmes valeurs.
Paramètres nécessaires à la construction d'une variable.
virtual Integer checkIfSync(int max_print=0)
Vérifie si la variable est bien synchronisée.
IVariable * variable() const
Variable associée.
bool null() const
Vrai si le noeud est nul.
void checkValidConnectivity()
void checkValidMeshFull() override
Vérification de la validité du maillage.
void _checkFacesOrientation()
Vérifie que les faces sont correctement orientées et connectées.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
MeshVariableArrayRefT< Cell, Int64 > VariableCellArrayInt64
Grandeur au centre des mailles de type tableau d'entiers.
MeshVariableScalarRefT< Face, Int64 > VariableFaceInt64
Grandeur aux faces de type entier 64 bits.
@ ReduceMax
Maximum des valeurs.
bool arcaneIsCheck()
Vrai si on est en mode vérification.
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
Collection< IItemFamily * > IItemFamilyCollection
Collection de familles d'entités.
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_Unknown
Entité de maillage de genre inconnu ou non initialisé
@ 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.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
std::int32_t Int32
Type entier signé sur 32 bits.