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"
32#include "arcane/core/NodesOfItemReorderer.h"
46DynamicMeshChecker(IMesh* mesh)
47: TraceAccessor(mesh->traceMng())
60 delete m_var_cells_faces;
61 delete m_var_cells_nodes;
74void DynamicMeshChecker::
77 info(4) <<
"Check mesh coherence.";
83 if (family->
itemKind()>=NB_ITEM_KIND)
94 const bool global_check =
false;
95 if (m_check_level>=1 && global_check){
96 if (!m_var_cells_faces)
99 if (!m_var_cells_nodes)
109 if (nb_face>max_nb_face)
110 max_nb_face = nb_face;
111 if (nb_node>max_nb_node)
112 max_nb_node = nb_node;
114 m_var_cells_faces->resize(max_nb_face);
115 m_var_cells_nodes->resize(max_nb_node);
119 for(
Integer z=0; z<nb_face; ++z )
120 (*m_var_cells_faces)[cell][z] = cell.
face(z).
uniqueId().asInt64();
122 for(
Integer z=0; z<nb_node; ++z )
123 (*m_var_cells_nodes)[cell][z] = cell.
node(z).
uniqueId().asInt64();
132void DynamicMeshChecker::
135 String func_name(
"DynamicMesh::checkValidMeshFull");
136 info() << func_name <<
" on " << m_mesh->name();
140 <<
" NAME=" << var_faces.
itemGroup().name()
147 var_faces[face] = uid;
149 var_faces.synchronize();
154 if (uid!=var_faces[face] && uid!=NULL_ITEM_ID && var_faces[face]!=NULL_ITEM_ID){
155 error() << func_name <<
" bad back cell in face uid=" << face.
uniqueId();
164 var_faces[face] = uid;
166 var_faces.synchronize();
171 if (uid!=var_faces[face] && uid!=NULL_ITEM_ID && var_faces[face]!=NULL_ITEM_ID){
172 error() << func_name <<
" bad front cell in face uid=" << face.
uniqueId();
180 if (cell_type == IT_Line2) {
181 error() << func_name <<
" bad cell type in face uid=" << cell.
uniqueId();
189 if (face_type == IT_Vertex) {
190 error() << func_name <<
" bad face type in face uid=" << face.
uniqueId();
213void DynamicMeshChecker::
214checkValidConnectivity()
216 String func_name =
"MeshChecker::checkValidConnectivity";
217 debug() << func_name <<
" check";
221 for(
auto x = item_families.enumerator(); ++x; ){
226 if (!m_mesh->parentMesh()){
232 if (front_cell.
null() && back_cell.
null())
243 bool has_found =
false;
244 for(
Node node2 : cell.nodes() ){
251 ARCANE_FATAL(
"Node uid={0} is connected to the cell uid={1} but the cell"
260 if(!m_mesh->isAmrActivated()){
266 bool has_found =
false;
267 for(
Edge edge2 : cell.edges() ){
274 ARCANE_FATAL(
"Edge uid={0} is connected to the cell uid={1} but the cell"
284 if(!m_mesh->isAmrActivated()){
286 bool has_found =
false;
287 for(
Face face2 : cell.faces() ){
294 ARCANE_FATAL(
"Face uid={0} is connected to the cell uid={1} but the cell"
300 bool has_found =
false;
301 for(
Face face2 : cell.faces() ){
310 <<
" but the cell (level "<< cell.level()<<
")"
311 <<
" is not connected to the face.";
318 if ((back_cell.
null() || front_cell.
null()) && nb_cell==2)
321 if (nb_cell==2 && back_cell!=face.
cell(0))
322 ARCANE_FATAL(
"Bad face face.backCell()!=face.cell(0) face={0} back_cell={1} from_cell={2} cell0={3}",
328 if (m_mesh->parentMesh()){
333 for(
Integer i_kind=0;i_kind<nb_kind;++i_kind){
337 error() <<
"Mesh " << m_mesh->name() <<
" : Family " << kind <<
" does not exist in mesh";
342 const Item & item = *iitem;
345 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent suppresssed parent item uid : "
350 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent item/parent item uid : " <<
ItemPrinter(item);
362 ItemGroup parent_group = m_mesh->parentGroup();
363 String var_name = String::format(
"SubMesh_{0}_GroupConsistencyChecker",parent_group.
name());
368 var[iitem] = iitem->owner();
373 ARCANE_FATAL(
"Mesh name={0} has parent group consistency {1}\n"
374 "This usually means that parent group was not symmetrically built",
378 _checkValidItemOwner(m_mesh->nodeFamily());
379 _checkValidItemOwner(m_mesh->edgeFamily());
380 _checkValidItemOwner(m_mesh->faceFamily());
381 _checkValidItemOwner(m_mesh->cellFamily());
387void DynamicMeshChecker::
388updateAMRFaceOrientation()
390 String func_name =
"MeshChecker::updateAMRFaceOrientation";
397 if ((back_cell.
null() || front_cell.
null()) && nb_cell==2)
400 if (nb_cell==2 && back_cell!=face.
cell(0))
401 ARCANE_FATAL(
"Bad face face.backCell()!=face.cell(0) face={0} back_cell={1} from_cell={2} cell0={3}",
405 fr.checkAndChangeOrientationAMR(face);
412void DynamicMeshChecker::
413updateAMRFaceOrientation(ArrayView<Int64> ghost_cell_to_refine)
415 ItemInternalList cells = m_mesh->itemsInternal(IK_Cell) ;
416 UniqueArray<Integer> lids(ghost_cell_to_refine.size()) ;
417 m_mesh->cellFamily()->itemsUniqueIdToLocalId(lids,ghost_cell_to_refine,
true) ;
418 FaceReorienter fr(m_mesh);
419 std::set<Int64> set ;
420 typedef std::pair<std::set<Int64>::iterator,
bool> return_type ;
421 for(Integer i=0, n=lids.size();i<n;++i){
422 Cell icell = cells[lids[i]] ;
423 for( Integer ic=0, nchild=icell.nbHChildren();ic<nchild;++ic){
424 Cell child = icell.hChild(ic) ;
425 for( Face face : child.faces() ){
426 return_type value = set.insert(face.
uniqueId());
428 fr.checkAndChangeOrientationAMR(face);
440void DynamicMeshChecker::
441_checkFacesOrientation()
443 bool is_1d = (m_mesh->dimension()==1);
448 String func_name =
"MeshChecker::_checkFacesOrientation";
453 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
458 Int32 cell_nb_face =
type->nbLocalFace();
459 for(
Integer i_face=0; i_face<cell_nb_face; ++i_face ){
463 work_face_orig_nodes_uid.
resize(face_nb_node);
464 for(
Integer z=0; z<face_nb_node; ++z )
467 bool is_reorder =
false;
469 is_reorder = face_reorderer.reorder1D(i_face, work_face_orig_nodes_uid[0]);
476 if (cell_face.
nbNode()!=face_nb_node)
477 ARCANE_FATAL(
"Incoherent number of node for 'face' and 'localFace'"
478 " cell={0} face={1} nb_local_node={2} nb_face_node={3}",
481 for(
Integer z=0; z<face_nb_node; ++z ){
483 ARCANE_FATAL(
"Bad node unique id for face: cell={0} face={1} cell_node_uid={2} face_node_uid={3} z={4}",
489 if (front_cell!=cell){
490 if (!front_cell.
null())
491 ARCANE_FATAL(
"Bad orientation for face. Should be front cell: cell={0} face={1} front_cell={2}",
494 ARCANE_FATAL(
"Bad orientation for face. Should be front cell (no front cell) cell={0} face={1}",
500 if (back_cell!=cell){
501 if (!back_cell.
null())
502 ARCANE_FATAL(
"Bad orientation for face. Should be back cell: cell={0} face={1} front_cell={2}",
505 ARCANE_FATAL(
"Bad orientation for face. Should be back cell (no back cell) cell={0} face={1}",
516void DynamicMeshChecker::
525 bool allow_orphan_items = m_mesh->meshKind().isNonManifold();
528 if (!m_mesh->parentMesh()){
539 if (cells.
size()==0 && allow_orphan_items)
541 for(
Item cell : cells ){
542 if (cell.owner()==owner){
550 ostr() <<
" nb_cell=" << cells.size();
551 for( Item cell : cells ){
552 ostr() <<
" SubCell i=" << index <<
" cell=" << ItemPrinter(cell);
555 error() <<
"Mesh " << m_mesh->name() <<
" family=" << family->
name()
556 <<
" Item" << ItemPrinter(item) <<
" has no cell with same owner:"
565 Item parent_item = item.
parent();
566 if (parent_item.owner() != item.owner()) {
567 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent item/parent item owner : "
568 << ItemPrinter(item) <<
" / " << ItemPrinter(parent_item);
576 String::plural(nerror,
"owner error"));
582void DynamicMeshChecker::
583checkVariablesSynchronization()
587 for( VariableCollection::Enumerator i_var(used_vars); ++i_var; ){
603 ARCANE_FATAL(
"Error in checkVariablesSynchronization() nb_diff=",nb_diff);
609void DynamicMeshChecker::
610checkItemGroupsSynchronization()
623 ARCANE_FATAL(
"some groups are not synchronized nb_diff={0}",nb_diff);
637void DynamicMeshChecker::
641 Integer sid = m_mesh->meshPartInfo().partRank();
648 for (
Cell cell2 : node.cells()) {
649 if (cell2.owner() == sid) {
655 info() <<
"WARNING: Cell " <<
ItemPrinter(cell) <<
" should not be a ghost cell";
662void DynamicMeshChecker::
663checkMeshFromReferenceFile()
665 if (!m_compare_reference_file)
673 debug() <<
"Testing the mesh against the initial mesh";
674 String base_file_name(
"meshconnectivity");
680 XmlNode doc_node = xml_doc->documentNode();
681 if (!doc_node.
null())
682 mesh_utils::checkMeshConnectivity(m_mesh,doc_node,
true);
685 warning() <<
"Can't test the subdomain coherence "
686 <<
"against the initial mesh";
693void DynamicMeshChecker::
694checkValidReplication()
696 info() <<
"Checking valid replication";
710 wanted_same_family.
add(family);
717 vc.
areEqual(nb_family,max_nb_family,
"Bad number of family");
723 for(
Integer i=0; i<nb_family; ++i )
724 families_size[i] = wanted_same_family[i]->nbItem();
727 vc.
areEqualArray(global_families_size,families_size,
"Bad family");
734 for(
Integer i=0; i<nb_family; ++i ){
735 ItemGroup group = wanted_same_family[i]->allItems();
739 unique_ids[index] = iitem->uniqueId();
743 global_unique_ids.
copy(unique_ids);
745 String message = String::format(
"Bad unique ids for family '{0}'",
746 wanted_same_family[i]->name());
755void 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.
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
Vue constante d'un tableau de type T.
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 Int32 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é.
static ItemTypeId fromInteger(Int64 v)
Créé une instance à partir d'un entier.
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 typeId() const
Type de l'entité face.
Integer nbNode() const
Nombre de noeuds de la face.
Infos sur un type d'entité du maillage.
Gestionnaire des types d'entités d'un 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.
Classe utilitaire pour réordonner les noeuds d'une entité.
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.