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;
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();
209void DynamicMeshChecker::
210checkValidConnectivity()
212 String func_name =
"MeshChecker::checkValidConnectivity";
213 debug() << func_name <<
" check";
217 for (
auto x = item_families.enumerator(); ++x;) {
222 if (!m_mesh->parentMesh()) {
228 if (front_cell.
null() && back_cell.
null())
239 bool has_found =
false;
240 for (
Node node2 : cell.nodes()) {
247 ARCANE_FATAL(
"Node uid={0} is connected to the cell uid={1} but the cell"
248 " is not connected to this node.",
257 if (!m_mesh->isAmrActivated()) {
263 bool has_found =
false;
264 for (
Edge edge2 : cell.edges()) {
271 ARCANE_FATAL(
"Edge uid={0} is connected to the cell uid={1} but the cell"
272 " is not connected to this edge.",
282 if (!m_mesh->isAmrActivated()) {
284 bool has_found =
false;
285 for (
Face face2 : cell.faces()) {
292 ARCANE_FATAL(
"Face uid={0} is connected to the cell uid={1} but the cell"
293 " is not connected to this face.",
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}",
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 if (m_is_check_items_owner) {
379 _checkValidItemOwner(m_mesh->nodeFamily());
380 _checkValidItemOwner(m_mesh->edgeFamily());
381 _checkValidItemOwner(m_mesh->faceFamily());
382 _checkValidItemOwner(m_mesh->cellFamily());
389void DynamicMeshChecker::
390updateAMRFaceOrientation()
392 String func_name =
"MeshChecker::updateAMRFaceOrientation";
399 if ((back_cell.
null() || front_cell.
null()) && nb_cell == 2)
402 if (nb_cell == 2 && back_cell != face.
cell(0))
403 ARCANE_FATAL(
"Bad face face.backCell()!=face.cell(0) face={0} back_cell={1} from_cell={2} cell0={3}",
407 fr.checkAndChangeOrientationAMR(face);
414void DynamicMeshChecker::
415updateAMRFaceOrientation(ArrayView<Int64> ghost_cell_to_refine)
417 ItemInternalList cells = m_mesh->itemsInternal(IK_Cell);
418 UniqueArray<Integer> lids(ghost_cell_to_refine.size());
419 m_mesh->cellFamily()->itemsUniqueIdToLocalId(lids, ghost_cell_to_refine,
true);
420 FaceReorienter fr(m_mesh);
422 typedef std::pair<std::set<Int64>::iterator,
bool> return_type;
423 for (Integer i = 0, n = lids.size(); i < n; ++i) {
424 Cell icell = cells[lids[i]];
425 for (Integer ic = 0, nchild = icell.nbHChildren(); ic < nchild; ++ic) {
426 Cell child = icell.hChild(ic);
427 for (Face face : child.faces()) {
428 return_type value = set.insert(face.
uniqueId());
430 fr.checkAndChangeOrientationAMR(face);
442void DynamicMeshChecker::
443_checkFacesOrientation()
445 bool is_1d = (m_mesh->dimension() == 1);
450 String func_name =
"MeshChecker::_checkFacesOrientation";
455 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
460 Int32 cell_nb_face =
type->nbLocalFace();
461 for (
Integer i_face = 0; i_face < cell_nb_face; ++i_face) {
465 work_face_orig_nodes_uid.
resize(face_nb_node);
466 for (
Integer z = 0; z < face_nb_node; ++z)
469 bool is_reorder =
false;
471 is_reorder = face_reorderer.reorder1D(i_face, work_face_orig_nodes_uid[0]);
478 if (cell_face.
nbNode() != face_nb_node)
479 ARCANE_FATAL(
"Incoherent number of node for 'face' and 'localFace'"
480 " cell={0} face={1} nb_local_node={2} nb_face_node={3}",
483 for (
Integer z = 0; z < face_nb_node; ++z) {
484 if (cell_face.
node(z).
uniqueId() != face_sorted_nodes[z])
485 ARCANE_FATAL(
"Bad node unique id for face: cell={0} face={1} cell_node_uid={2} face_node_uid={3} z={4}",
491 if (front_cell != cell) {
492 if (!front_cell.
null())
493 ARCANE_FATAL(
"Bad orientation for face. Should be front cell: cell={0} face={1} front_cell={2}",
496 ARCANE_FATAL(
"Bad orientation for face. Should be front cell (no front cell) cell={0} face={1}",
502 if (back_cell != cell) {
503 if (!back_cell.
null())
504 ARCANE_FATAL(
"Bad orientation for face. Should be back cell: cell={0} face={1} front_cell={2}",
507 ARCANE_FATAL(
"Bad orientation for face. Should be back cell (no back cell) cell={0} face={1}",
520void DynamicMeshChecker::
521_checkEdgesOrientation()
540 ARCANE_FATAL(
"Bad connectivity for '{0}' edges", nb_error);
546void DynamicMeshChecker::
555 bool allow_orphan_items = m_mesh->meshKind().isNonManifold();
558 if (!m_mesh->parentMesh()) {
569 if (cells.
size() == 0 && allow_orphan_items)
571 for (
Item cell : cells) {
572 if (cell.owner() == owner) {
580 ostr() <<
" nb_cell=" << cells.size();
581 for (Item cell : cells) {
582 ostr() <<
" SubCell i=" << index <<
" cell=" << ItemPrinter(cell);
585 error() <<
"Mesh " << m_mesh->name() <<
" family=" << family->
name()
586 <<
" Item" << ItemPrinter(item) <<
" has no cell with same owner:"
595 Item parent_item = item.
parent();
596 if (parent_item.owner() != item.owner()) {
597 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent item/parent item owner : "
598 << ItemPrinter(item) <<
" / " << ItemPrinter(parent_item);
606 String::plural(nerror,
"owner error"));
612void DynamicMeshChecker::
613checkVariablesSynchronization()
617 for (VariableCollection::Enumerator i_var(used_vars); ++i_var;) {
633 ARCANE_FATAL(
"Error in checkVariablesSynchronization() nb_diff=", nb_diff);
639void DynamicMeshChecker::
640checkItemGroupsSynchronization()
653 ARCANE_FATAL(
"some groups are not synchronized nb_diff={0}", nb_diff);
666void DynamicMeshChecker::
670 Integer sid = m_mesh->meshPartInfo().partRank();
677 for (
Cell cell2 : node.cells()) {
678 if (cell2.owner() == sid) {
684 info() <<
"WARNING: Cell " <<
ItemPrinter(cell) <<
" should not be a ghost cell";
691void DynamicMeshChecker::
692checkMeshFromReferenceFile()
694 if (!m_compare_reference_file)
702 debug() <<
"Testing the mesh against the initial mesh";
703 String base_file_name(
"meshconnectivity");
709 XmlNode doc_node = xml_doc->documentNode();
710 if (!doc_node.
null())
711 mesh_utils::checkMeshConnectivity(m_mesh, doc_node,
true);
714 warning() <<
"Can't test the subdomain coherence "
715 <<
"against the initial mesh";
722void DynamicMeshChecker::
723checkValidReplication()
725 info() <<
"Checking valid replication";
739 wanted_same_family.
add(family);
746 vc.
areEqual(nb_family, max_nb_family,
"Bad number of family");
752 for (
Integer i = 0; i < nb_family; ++i)
753 families_size[i] = wanted_same_family[i]->nbItem();
756 vc.
areEqualArray(global_families_size, families_size,
"Bad family");
763 for (
Integer i = 0; i < nb_family; ++i) {
764 ItemGroup group = wanted_same_family[i]->allItems();
768 unique_ids[index] = iitem->uniqueId();
772 global_unique_ids.
copy(unique_ids);
774 String message = String::format(
"Bad unique ids for family '{0}'",
775 wanted_same_family[i]->name());
784void 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.
Int32 nbNode() const
Nombre de sommets 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
Genre 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.
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é.
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)
constexpr bool isOwn() const
true si l'entité est appartient au sous-domaine
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 _checkEdgesOrientation()
Checks that edges are correctly numbered.
void _checkFacesOrientation()
Checks that faces are correctly oriented and connected.
Information to synchronize groups between sub-domains.
Integer checkSynchronize()
Checks if the groups are synchronized.
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.