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();
210void DynamicMeshChecker::
211checkValidConnectivity()
213 String func_name =
"MeshChecker::checkValidConnectivity";
214 debug() << func_name <<
" check";
218 for (
auto x = item_families.enumerator(); ++x;) {
223 if (!m_mesh->parentMesh()) {
229 if (front_cell.
null() && back_cell.
null())
240 bool has_found =
false;
241 for (
Node node2 : cell.nodes()) {
248 ARCANE_FATAL(
"Node uid={0} is connected to the cell uid={1} but the cell"
249 " is not connected to this node.",
258 if (!m_mesh->isAmrActivated()) {
264 bool has_found =
false;
265 for (
Edge edge2 : cell.edges()) {
272 ARCANE_FATAL(
"Edge uid={0} is connected to the cell uid={1} but the cell"
273 " is not connected to this edge.",
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"
294 " is not connected to this face.",
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}",
329 if (m_mesh->parentMesh()) {
334 for (
Integer i_kind = 0; i_kind < nb_kind; ++i_kind) {
338 error() <<
"Mesh " << m_mesh->name() <<
" : Family " << kind <<
" does not exist in mesh";
343 const Item& item = *iitem;
346 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent suppresssed parent item uid : "
351 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent item/parent item uid : " <<
ItemPrinter(item);
363 ItemGroup parent_group = m_mesh->parentGroup();
364 String var_name = String::format(
"SubMesh_{0}_GroupConsistencyChecker", parent_group.
name());
369 var[iitem] = iitem->owner();
374 ARCANE_FATAL(
"Mesh name={0} has parent group consistency {1}\n"
375 "This usually means that parent group was not symmetrically built",
379 if (m_is_check_items_owner) {
380 _checkValidItemOwner(m_mesh->nodeFamily());
381 _checkValidItemOwner(m_mesh->edgeFamily());
382 _checkValidItemOwner(m_mesh->faceFamily());
383 _checkValidItemOwner(m_mesh->cellFamily());
390void DynamicMeshChecker::
391updateAMRFaceOrientation()
393 String func_name =
"MeshChecker::updateAMRFaceOrientation";
400 if ((back_cell.
null() || front_cell.
null()) && nb_cell == 2)
403 if (nb_cell == 2 && back_cell != face.
cell(0))
404 ARCANE_FATAL(
"Bad face face.backCell()!=face.cell(0) face={0} back_cell={1} from_cell={2} cell0={3}",
408 fr.checkAndChangeOrientationAMR(face);
415void DynamicMeshChecker::
416updateAMRFaceOrientation(ArrayView<Int64> ghost_cell_to_refine)
418 ItemInternalList cells = m_mesh->itemsInternal(IK_Cell);
419 UniqueArray<Integer> lids(ghost_cell_to_refine.size());
420 m_mesh->cellFamily()->itemsUniqueIdToLocalId(lids, ghost_cell_to_refine,
true);
421 FaceReorienter fr(m_mesh);
423 typedef std::pair<std::set<Int64>::iterator,
bool> return_type;
424 for (Integer i = 0, n = lids.size(); i < n; ++i) {
425 Cell icell = cells[lids[i]];
426 for (Integer ic = 0, nchild = icell.nbHChildren(); ic < nchild; ++ic) {
427 Cell child = icell.hChild(ic);
428 for (Face face : child.faces()) {
429 return_type value = set.insert(face.
uniqueId());
431 fr.checkAndChangeOrientationAMR(face);
443void DynamicMeshChecker::
444_checkFacesOrientation()
446 bool is_1d = (m_mesh->dimension() == 1);
451 String func_name =
"MeshChecker::_checkFacesOrientation";
456 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
461 Int32 cell_nb_face =
type->nbLocalFace();
462 for (
Integer i_face = 0; i_face < cell_nb_face; ++i_face) {
466 work_face_orig_nodes_uid.
resize(face_nb_node);
467 for (
Integer z = 0; z < face_nb_node; ++z)
470 bool is_reorder =
false;
472 is_reorder = face_reorderer.reorder1D(i_face, work_face_orig_nodes_uid[0]);
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() != face_sorted_nodes[z])
486 ARCANE_FATAL(
"Bad node unique id for face: cell={0} face={1} cell_node_uid={2} face_node_uid={3} z={4}",
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}",
521void DynamicMeshChecker::
522_checkEdgesOrientation()
541 ARCANE_FATAL(
"Bad connectivity for '{0}' edges", nb_error);
547void DynamicMeshChecker::
556 bool allow_orphan_items = m_mesh->meshKind().isNonManifold();
559 if (!m_mesh->parentMesh()) {
570 if (cells.
size() == 0 && allow_orphan_items)
572 for (
Item cell : cells) {
573 if (cell.owner() == owner) {
581 ostr() <<
" nb_cell=" << cells.size();
582 for (Item cell : cells) {
583 ostr() <<
" SubCell i=" << index <<
" cell=" << ItemPrinter(cell);
586 error() <<
"Mesh " << m_mesh->name() <<
" family=" << family->
name()
587 <<
" Item" << ItemPrinter(item) <<
" has no cell with same owner:"
596 Item parent_item = item.
parent();
597 if (parent_item.owner() != item.owner()) {
598 error() <<
"Mesh " << m_mesh->name() <<
" : Inconsistent item/parent item owner : "
599 << ItemPrinter(item) <<
" / " << ItemPrinter(parent_item);
607 String::plural(nerror,
"owner error"));
613void DynamicMeshChecker::
614checkVariablesSynchronization()
618 for (VariableCollection::Enumerator i_var(used_vars); ++i_var;) {
634 ARCANE_FATAL(
"Error in checkVariablesSynchronization() nb_diff=", nb_diff);
640void DynamicMeshChecker::
641checkItemGroupsSynchronization()
654 ARCANE_FATAL(
"some groups are not synchronized nb_diff={0}", nb_diff);
667void DynamicMeshChecker::
671 Integer sid = m_mesh->meshPartInfo().partRank();
678 for (
Cell cell2 : node.cells()) {
679 if (cell2.owner() == sid) {
685 info() <<
"WARNING: Cell " <<
ItemPrinter(cell) <<
" should not be a ghost cell";
692void DynamicMeshChecker::
693checkMeshFromReferenceFile()
695 if (!m_compare_reference_file)
703 debug() <<
"Testing the mesh against the initial mesh";
704 String base_file_name(
"meshconnectivity");
710 XmlNode doc_node = xml_doc->documentNode();
711 if (!doc_node.
null())
712 mesh_utils::checkMeshConnectivity(m_mesh, doc_node,
true);
715 warning() <<
"Can't test the subdomain coherence "
716 <<
"against the initial mesh";
723void DynamicMeshChecker::
724checkValidReplication()
726 info() <<
"Checking valid replication";
740 wanted_same_family.
add(family);
747 vc.
areEqual(nb_family, max_nb_family,
"Bad number of family");
753 for (
Integer i = 0; i < nb_family; ++i)
754 families_size[i] = wanted_same_family[i]->nbItem();
757 vc.
areEqualArray(global_families_size, families_size,
"Bad family");
764 for (
Integer i = 0; i < nb_family; ++i) {
765 ItemGroup group = wanted_same_family[i]->allItems();
769 unique_ids[index] = iitem->uniqueId();
773 global_unique_ids.
copy(unique_ids);
775 String message = String::format(
"Bad unique ids for family '{0}'",
776 wanted_same_family[i]->name());
785void DynamicMeshChecker::
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Utility functions for the mesh.
void checkMeshProperties(IMesh *mesh, bool is_sorted, bool has_no_hole, bool check_faces)
Checks if the mesh has certain properties.
Integer size() const
Number of elements in the vector.
void resize(Int64 s)
Changes the number of elements in the array to s.
void copy(Span< const T > rhs)
Copies the values from rhs into the instance.
void add(ConstReferenceType val)
Adds element val to the end of the array.
ArrayView< T > view() const
Mutable view of this array.
Face face(Int32 i) const
i-th face of the cell
Int32 nbFace() const
Number of faces of the cell.
EnumeratorT< IItemFamily * > Enumerator
Constant view of an array of type T.
CellConnectedListViewType cells() const
List of edge cells.
Int32 nbNode() const
Number of vertices of the edge.
This function/class reorients faces.
Cell frontCell() const
Cell in front of the face (null cell if none).
Cell cell(Int32 i) const
i-th cell of the face
Int32 nbCell() const
Number of cells of the face (1 or 2).
CellConnectedListViewType cells() const
List of cells of the face.
Cell backCell() const
Cell behind the face (null cell if none).
Interface of the input/output manager.
virtual IXmlDocumentHolder * parseXmlFile(const String &filename, const String &schemaname=String{})=0
Reads and parses the XML file filename.
Interface of an entity family.
virtual ItemGroup allItems() const =0
Group of all entities.
virtual void checkValid()=0
Check the validity of internal structures (internal).
virtual String name() const =0
Family name.
virtual IItemFamily * parentFamily() const =0
IItemFamily parent.
virtual eItemKind itemKind() const =0
Entity kind.
virtual void checkValidConnectivity()=0
Verification of the validity of internal structures concerning connectivity.
Interface of the parallelism manager for a subdomain.
virtual IParallelReplication * replication() const =0
Replication information.
virtual IIOMng * ioMng() const =0
I/O manager.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
Brief information on parallel subdomain replication.
virtual bool hasReplication() const =0
Indicates if replication is active.
virtual IParallelMng * replicaParallelMng() const =0
Communicator associated with all replicas representing the same subdomain.
virtual String itemFamilyName() const =0
Name of the associated family (null if none).
virtual eItemKind itemKind() const =0
Kind of mesh entities on which the variable is based.
virtual Int32 checkIfSync(Integer max_print=0)=0
Checks if the variable is properly synchronized.
virtual IItemFamily * itemFamily() const =0
Associated entity family.
virtual String itemGroupName() const =0
Name of the associated entity group.
bool isSuppressed() const
True if the entity is suppressed.
const String & name() const
Group name.
Integer size() const
Number of elements in the group.
IItemFamily * itemFamily() const
Entity family to which this group belongs (0 for the null group).
ItemGroup own() const
Group equivalent to this one but containing only the local elements of the subdomain.
Utility class for printing information about an entity.
static ItemTypeId fromInteger(Int64 v)
Creates an instance from an integer.
Local information about a cell face.
Integer node(Integer i) const
Local index in the cell of the i-th node of the face.
Integer typeId() const
Type of the face entity.
Integer nbNode() const
Number of nodes of the face.
Info on a mesh entity type.
Mesh entity type manager.
Scalar variable on a mesh entity type.
View on a vector of entities.
Int32 size() const
Number of elements in the vector.
Node node(Int32 i) const
i-th node of the entity
NodeConnectedListViewType nodes() const
List of nodes of the entity.
Int32 nbNode() const
Number of nodes of the entity.
Base class for a mesh element.
const ItemTypeInfo * typeInfo() const
Information about the entity type.
Int32 owner() const
Owner subdomain number of the entity.
ItemUniqueId uniqueId() const
Unique identifier across all domains.
constexpr bool null() const
true if the entity is null (i.e. not connected to the mesh)
constexpr bool isOwn() const
true if the entity belongs to the subdomain
Item parent(Int32 i) const
i-th parent for submeshes
impl::ItemBase itemBase() const
Internal part of the entity.
Int16 type() const
Entity type.
GroupType itemGroup() const
Group associated with the quantity.
CellConnectedListViewType cells() const
List of cells of the node.
Utility class to reorder the nodes of an entity.
Encapsulation of an automatically destructing pointer.
Unicode character string.
static String plural(const Integer n, const String &str, const bool with_number=true)
Standard plural form by adding an 's'.
Parameters required to build a temporary variable.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
TraceMessage warning() const
Flow for a warning message.
TraceMessage pwarning() const
1D data vector with value semantics (STL style).
Checking the validity of certain values.
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)
Checks that the two arrays values and expected_values have the same values.
Parameters necessary for building a variable.
virtual Integer checkIfSync(int max_print=0)
Checks if the variable is synchronized.
IVariable * variable() const
Associated variable.
bool null() const
True if the node is null.
void checkValidConnectivity()
void checkValidMeshFull() override
Verification of mesh validity.
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
Group of cells.
MeshVariableArrayRefT< Cell, Int64 > VariableCellArrayInt64
Quantity at cell centers of integer array type.
MeshVariableScalarRefT< Face, Int64 > VariableFaceInt64
Quantity at the face of 64-bit integer type.
@ ReduceMax
Maximum of values.
bool arcaneIsCheck()
True if running in check mode.
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
Collection< IItemFamily * > IItemFamilyCollection
Collection of item families.
eItemKind
Mesh entity type.
@ IK_Particle
Particle mesh entity.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Unknown
Unknown or uninitialized mesh entity.
@ IK_Face
Face mesh entity.
@ IK_DoF
Degree of Freedom mesh entity.
@ IK_Edge
Edge mesh entity.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
std::int32_t Int32
Signed integer type of 32 bits.