Arcane  v3.16.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DynamicMeshChecker.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* DynamicMeshChecker.cc (C) 2000-2025 */
9/* */
10/* Classe fournissant des méthodes de vérification sur le maillage. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ScopedPtr.h"
15#include "arcane/utils/ValueChecker.h"
16
17#include "arcane/mesh/DynamicMesh.h"
18#include "arcane/mesh/ItemGroupsSynchronize.h"
19#include "arcane/mesh/FaceReorienter.h"
20#include "arcane/mesh/DynamicMeshChecker.h"
21
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"
33
34#include <set>
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace Arcane::mesh
40{
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
45DynamicMeshChecker::
46DynamicMeshChecker(IMesh* mesh)
47: TraceAccessor(mesh->traceMng())
48, m_mesh(mesh)
49{
50 if (arcaneIsCheck())
51 m_check_level = 1;
52}
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
57DynamicMeshChecker::
58~DynamicMeshChecker()
59{
60 delete m_var_cells_faces;
61 delete m_var_cells_nodes;
62}
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
74void DynamicMeshChecker::
75checkValidMesh()
76{
77 info(4) << "Check mesh coherence.";
79
80 for( IItemFamilyCollection::Enumerator i(m_mesh->itemFamilies()); ++i; ){
81 IItemFamily* family = *i;
82 //GG: regarder pourquoi il y a ce test.
83 if (family->itemKind()>=NB_ITEM_KIND)
84 continue;
85 family->checkValid();
86 }
87 mesh_utils::checkMeshProperties(m_mesh,false,false,true);
88
89 // Sauve dans une variable aux mailles la liste des faces et
90 // noeuds qui la composent.
91 // Ceci n'est utile que pour des vérifications
92 // NOTE: pour l'instant mis a false car fait planter si utilise
93 // partitionnement initial dans Arcane
94 const bool global_check = false;
95 if (m_check_level>=1 && global_check){
96 if (!m_var_cells_faces)
97 m_var_cells_faces = new VariableCellArrayInt64(VariableBuildInfo(m_mesh,"MeshTestCellFaces"));
98
99 if (!m_var_cells_nodes)
100 m_var_cells_nodes = new VariableCellArrayInt64(VariableBuildInfo(m_mesh,"MeshTestCellNodes"));
101
102 CellGroup all_cells(m_mesh->allCells());
103 Integer max_nb_face = 0;
104 Integer max_nb_node = 0;
105 ENUMERATE_CELL(i,all_cells){
106 Cell cell = *i;
107 Integer nb_face = cell.nbFace();
108 Integer nb_node = cell.nbNode();
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;
113 }
114 m_var_cells_faces->resize(max_nb_face);
115 m_var_cells_nodes->resize(max_nb_node);
116 ENUMERATE_CELL(i,all_cells){
117 Cell cell = *i;
118 Integer nb_face = cell.nbFace();
119 for( Integer z=0; z<nb_face; ++z )
120 (*m_var_cells_faces)[cell][z] = cell.face(z).uniqueId().asInt64();
121 Integer nb_node = cell.nbNode();
122 for( Integer z=0; z<nb_node; ++z )
123 (*m_var_cells_nodes)[cell][z] = cell.node(z).uniqueId().asInt64();
124 }
125 }
127}
128
129/*---------------------------------------------------------------------------*/
130/*---------------------------------------------------------------------------*/
131
132void DynamicMeshChecker::
133checkValidMeshFull()
134{
135 String func_name("DynamicMesh::checkValidMeshFull");
136 info() << func_name << " on " << m_mesh->name();
137 Integer nb_error = 0;
138 VariableFaceInt64 var_faces(VariableBuildInfo(m_mesh,"MeshCheckFaces"));
139 debug() << " VAR_FACE GROUP=" << var_faces.variable()->itemFamily()
140 << " NAME=" << var_faces.itemGroup().name()
141 << " FAMILY_NAME=" << var_faces.variable()->itemFamilyName()
142 << " GROUP_NAME=" << var_faces.variable()->itemGroupName();
143 ENUMERATE_FACE(iface,m_mesh->allFaces()){
144 Face face = *iface;
145 Cell c = face.backCell();
146 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
147 var_faces[face] = uid;
148 }
149 var_faces.synchronize();
150 ENUMERATE_FACE(iface,m_mesh->allFaces()){
151 Face face = *iface;
152 Cell c = face.backCell();
153 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
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();
156 ++nb_error;
157 }
158 }
159
160 ENUMERATE_FACE(iface,m_mesh->allFaces()){
161 Face face = *iface;
162 Cell c = face.frontCell();
163 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
164 var_faces[face] = uid;
165 }
166 var_faces.synchronize();
167 ENUMERATE_FACE(iface,m_mesh->allFaces()){
168 Face face = *iface;
169 Cell c = face.frontCell();
170 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
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();
173 ++nb_error;
174 }
175 }
176
177 ENUMERATE_CELL(icell,m_mesh->allCells()){
178 Cell cell = *icell;
179 Integer cell_type = cell.type();
180 if (cell_type == IT_Line2) {
181 error() << func_name << " bad cell type in face uid=" << cell.uniqueId();
182 ++nb_error;
183 }
184 }
185
186 ENUMERATE_FACE(iface,m_mesh->allFaces()){
187 Face face = *iface;
188 Integer face_type = face.type();
189 if (face_type == IT_Vertex) {
190 error() << func_name << " bad face type in face uid=" << face.uniqueId();
191 ++nb_error;
192 }
193 }
194
195 if (nb_error!=0)
196 ARCANE_FATAL("Invalid mesh");
197}
198
199/*---------------------------------------------------------------------------*/
200/*---------------------------------------------------------------------------*/
201/*
202 * \brief Vérifie que la connectivité est valide.
203 *
204 * Les vérifications portent sur les points suivants:
205 * - pas d'entités du maillage ayant un indice nul.
206 * - pour les faces, vérifie qu'il existe au moins une frontCell ou une
207 * backCell. De plus, si elle a deux mailles, la backCell doit
208 * toujours être la première.
209 * - les noeuds et les faces doivent avoir le même propriétaire
210 * qu'une des mailles attenante.
211 * - vérifie que les faces sont bien ordonnées et orientées
212 */
213void DynamicMeshChecker::
214checkValidConnectivity()
215{
216 String func_name = "MeshChecker::checkValidConnectivity";
217 debug() << func_name << " check";
218
219 // Appelle la méthode de vérification de chaque famille.
220 IItemFamilyCollection item_families = m_mesh->itemFamilies();
221 for( auto x = item_families.enumerator(); ++x; ){
222 IItemFamily* f = *x;
224 }
225
226 if (!m_mesh->parentMesh()){
227 Integer index = 0;
228 ENUMERATE_(Face,i,m_mesh->allFaces()){
229 Face elem = *i;
230 Cell front_cell = elem.frontCell();
231 Cell back_cell = elem.backCell();
232 if (front_cell.null() && back_cell.null())
233 ARCANE_FATAL("Local face '{0}' has two null cell face=",index,ItemPrinter(elem));
234 index++;
235 }
236 }
237
238 // Vérifie que la connective maille<->noeud
239 // est réciproque
240 ENUMERATE_NODE(inode,m_mesh->allNodes()){
241 Node node = *inode;
242 for( Cell cell : node.cells() ){
243 bool has_found = false;
244 for( Node node2 : cell.nodes() ){
245 if (node2==node){
246 has_found = true;
247 break;
248 }
249 }
250 if (!has_found){
251 ARCANE_FATAL("Node uid={0} is connected to the cell uid={1} but the cell"
252 " is not connected to this node.",ItemPrinter(node),ItemPrinter(cell));
253 }
254 }
255 }
256
257 // ATT: les verifications suivantes ne sont pas compatible avec l'AMR
258 // TODO : etendre les verifs au cas AMR
260 if(!m_mesh->isAmrActivated()){
261 // Vérifie que la connective maille<->arêtes
262 // est réciproque
263 ENUMERATE_EDGE(iedge,m_mesh->allEdges()){
264 Edge edge = *iedge;
265 for( Cell cell : edge.cells() ){
266 bool has_found = false;
267 for( Edge edge2 : cell.edges() ){
268 if (edge2==edge){
269 has_found = true;
270 break;
271 }
272 }
273 if (!has_found){
274 ARCANE_FATAL("Edge uid={0} is connected to the cell uid={1} but the cell"
275 " is not connected to this edge.",ItemPrinter(edge),ItemPrinter(cell));
276 }
277 }
278 }
279 }
280 // Vérifie que la connective maille<->face
281 // est réciproque
282 ENUMERATE_FACE(iface,m_mesh->allFaces()){
283 Face face = *iface;
284 if(!m_mesh->isAmrActivated()){
285 for( Cell cell : face.cells() ){
286 bool has_found = false;
287 for( Face face2 : cell.faces() ){
288 if (face2==face){
289 has_found = true;
290 break;
291 }
292 }
293 if (!has_found){
294 ARCANE_FATAL("Face uid={0} is connected to the cell uid={1} but the cell"
295 " is not connected to this face.",ItemPrinter(face),ItemPrinter(cell));
296 }
297 }
298 }
299 for( Cell cell : face.cells() ){
300 bool has_found = false;
301 for( Face face2 : cell.faces() ){
302 if (face2==face){
303 has_found = true;
304 break;
305 }
306 }
307 if (!has_found && (face.backCell().level() == face.frontCell().level())){
308 warning() << func_name << ". The face " << FullItemPrinter(face)
309 << " is connected to the cell " << FullItemPrinter(cell)
310 << " but the cell (level "<< cell.level()<< ")"
311 << " is not connected to the face.";
312 }
313 }
314
315 Integer nb_cell = face.nbCell();
316 Cell back_cell = face.backCell();
317 Cell front_cell = face.frontCell();
318 if ((back_cell.null() || front_cell.null()) && nb_cell==2)
319 ARCANE_FATAL("Face uid='{0}' bad number of cells face",ItemPrinter(face));
320 // Si on a deux mailles connectées, alors la back cell doit être la première
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}",
323 ItemPrinter(face),ItemPrinter(back_cell),ItemPrinter(front_cell),ItemPrinter(face.cell(0)));
324 }
325
327
328 if (m_mesh->parentMesh()){
329 Integer nerror = 0;
330 eItemKind kinds[] = { IK_Node, IK_Edge, IK_Face, IK_Cell };
331 Integer nb_kind = sizeof(kinds)/sizeof(eItemKind);
332
333 for(Integer i_kind=0;i_kind<nb_kind;++i_kind){
334 const eItemKind kind = kinds[i_kind];
335 IItemFamily * family = m_mesh->itemFamily(kind);
336 if (!family->parentFamily()){
337 error() << "Mesh " << m_mesh->name() << " : Family " << kind << " does not exist in mesh";
338 ++nerror;
339 }
340 else{
341 ENUMERATE_ITEM(iitem,family->allItems()){
342 const Item & item = *iitem;
343 const Item & parent_item = item.parent();
344 if (parent_item.itemBase().isSuppressed()){
345 error() << "Mesh " << m_mesh->name() << " : Inconsistent suppresssed parent item uid : "
346 << ItemPrinter(item) << " / " << ItemPrinter(parent_item);
347 ++nerror;
348 }
349 if (parent_item.uniqueId() != item.uniqueId()){
350 error() << "Mesh " << m_mesh->name() << " : Inconsistent item/parent item uid : " << ItemPrinter(item);
351 ++nerror;
352 }
353 }
354 }
355 }
356 if (nerror > 0)
357 ARCANE_FATAL("Mesh name={0} has {1} (see above)",m_mesh->name(),String::plural(nerror, "error"));
358
359 // Vérifie la consistence parallèle du groupe parent
360 nerror = 0;
361 {
362 ItemGroup parent_group = m_mesh->parentGroup();
363 String var_name = String::format("SubMesh_{0}_GroupConsistencyChecker",parent_group.name());
364 TemporaryVariableBuildInfo tvbi(m_mesh->parentMesh(),var_name,parent_group.itemFamily()->name());
365 ItemVariableScalarRefT<Integer> var(tvbi,m_mesh->parentGroup().itemKind());
366 var.fill(-1);
367 ENUMERATE_ITEM(iitem, m_mesh->parentGroup()){
368 var[iitem] = iitem->owner();
369 }
370 nerror += var.checkIfSync(10);
371 }
372 if (nerror > 0)
373 ARCANE_FATAL("Mesh name={0} has parent group consistency {1}\n"
374 "This usually means that parent group was not symmetrically built",
375 m_mesh->name(),String::plural(nerror, "error", false));
376 }
377
378 _checkValidItemOwner(m_mesh->nodeFamily());
379 _checkValidItemOwner(m_mesh->edgeFamily());
380 _checkValidItemOwner(m_mesh->faceFamily());
381 _checkValidItemOwner(m_mesh->cellFamily());
382}
383
384/*---------------------------------------------------------------------------*/
385/*---------------------------------------------------------------------------*/
386
387void DynamicMeshChecker::
388updateAMRFaceOrientation()
389{
390 String func_name = "MeshChecker::updateAMRFaceOrientation";
391 FaceReorienter fr(m_mesh);
392 ENUMERATE_FACE(iface,m_mesh->allFaces()){
393 Face face = *iface;
394 Integer nb_cell = face.nbCell();
395 Cell back_cell = face.backCell();
396 Cell front_cell = face.frontCell();
397 if ((back_cell.null() || front_cell.null()) && nb_cell==2)
398 ARCANE_FATAL("Bad number of cells for face={0}",ItemPrinter(face));
399 // Si on a deux mailles connectées, alors la back cell doit être la première
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}",
402 ItemPrinter(face),ItemPrinter(back_cell),ItemPrinter(front_cell),ItemPrinter(face.cell(0)));
403
404 // Ceci pourrait sans doutes etre optimise
405 fr.checkAndChangeOrientationAMR(face);
406 }
407}
408
409/*---------------------------------------------------------------------------*/
410/*---------------------------------------------------------------------------*/
411
412void DynamicMeshChecker::
413updateAMRFaceOrientation(ArrayView<Int64> ghost_cell_to_refine)
414{
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());
427 if(value.second){
428 fr.checkAndChangeOrientationAMR(face);
429 }
430 }
431 }
432 }
433}
434
435/*---------------------------------------------------------------------------*/
436/*---------------------------------------------------------------------------*/
440void DynamicMeshChecker::
441_checkFacesOrientation()
442{
443 bool is_1d = (m_mesh->dimension()==1);
444 //Temporaire: pour l'instant, ne teste pas l'orientation en 1D.
445 if (is_1d)
446 return;
447
448 String func_name = "MeshChecker::_checkFacesOrientation";
449
450 Int64UniqueArray work_face_sorted_nodes;
451 IntegerUniqueArray work_face_nodes_index;
452 Int64UniqueArray work_face_orig_nodes_uid;
453 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
454 NodesOfItemReorderer face_reorderer(item_type_mng);
455 ENUMERATE_(Cell,icell,m_mesh->allCells()){
456 Cell cell = *icell;
457 const ItemTypeInfo* type = cell.typeInfo();
458 Int32 cell_nb_face = type->nbLocalFace();
459 for( Integer i_face=0; i_face<cell_nb_face; ++i_face ){
460 const ItemTypeInfo::LocalFace& lf = type->localFace(i_face);
461 Integer face_nb_node = lf.nbNode();
462
463 work_face_orig_nodes_uid.resize(face_nb_node);
464 for( Integer z=0; z<face_nb_node; ++z )
465 work_face_orig_nodes_uid[z] = cell.node(lf.node(z)).uniqueId();
466
467 bool is_reorder = false;
468 if (is_1d){
469 is_reorder = face_reorderer.reorder1D(i_face, work_face_orig_nodes_uid[0]);
470 }
471 else
472 is_reorder = face_reorderer.reorder(ItemTypeId::fromInteger(lf.typeId()), work_face_orig_nodes_uid);
473 ConstArrayView<Int64> face_sorted_nodes(face_reorderer.sortedNodes());
474
475 Face cell_face = cell.face(i_face);
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}",
479 ItemPrinter(cell),ItemPrinter(cell_face),face_nb_node,cell_face.nbNode());
480
481 for( Integer z=0; z<face_nb_node; ++z ){
482 if (cell_face.node(z).uniqueId()!=face_sorted_nodes[z])
483 ARCANE_FATAL("Bad node unique id for face: cell={0} face={1} cell_node_uid={2} face_node_uid={3} z={4}",
484 ItemPrinter(cell),ItemPrinter(cell_face),face_sorted_nodes[z],
485 cell_face.node(z).uniqueId());
486 }
487 if (is_reorder){
488 Cell front_cell = cell_face.frontCell();
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}",
492 ItemPrinter(cell),ItemPrinter(cell_face),ItemPrinter(front_cell));
493 else
494 ARCANE_FATAL("Bad orientation for face. Should be front cell (no front cell) cell={0} face={1}",
495 ItemPrinter(cell),ItemPrinter(cell_face));
496 }
497 }
498 else{
499 Cell back_cell = cell_face.backCell();
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}",
503 ItemPrinter(cell),ItemPrinter(cell_face),ItemPrinter(back_cell));
504 else
505 ARCANE_FATAL("Bad orientation for face. Should be back cell (no back cell) cell={0} face={1}",
506 ItemPrinter(cell),ItemPrinter(cell_face));
507 }
508 }
509 }
510 }
511}
512
513/*---------------------------------------------------------------------------*/
514/*---------------------------------------------------------------------------*/
515
516void DynamicMeshChecker::
517_checkValidItemOwner(IItemFamily* family)
518{
519 // Pour les maillages non sous-maillages, il faut que tout sub-item
520 // (Node, Edge ou Face) ait une cellule voisine de même propriétaire,
521 // sauf si on autorise les entités orphelines et que l'entité n'est
522 // connectée à aucune maille.
523 // Pour les sous-maillages, il faut, en plus, que tout item soit de
524 // même propriétaire que son parent.
525 bool allow_orphan_items = m_mesh->meshKind().isNonManifold();
526
527 Integer nerror = 0;
528 if (!m_mesh->parentMesh()){
529
530 if (family->itemKind() == IK_Cell)
531 return; // implicitement valide pour les cellules
532
533 ItemGroup own_items = family->allItems().own();
534 ENUMERATE_ITEM(iitem,own_items){
535 Item item = *iitem;
536 Int32 owner = item.owner();
537 bool is_ok = false;
538 ItemVectorView cells = item.itemBase().cellList();
539 if (cells.size()==0 && allow_orphan_items)
540 continue;
541 for( Item cell : cells ){
542 if (cell.owner()==owner){
543 is_ok = true;
544 break;
545 }
546 }
547 if (!is_ok) {
548 OStringStream ostr;
549 Integer index = 0;
550 ostr() << " nb_cell=" << cells.size();
551 for( Item cell : cells ){
552 ostr() << " SubCell i=" << index << " cell=" << ItemPrinter(cell);
553 ++index;
554 }
555 error() << "Mesh " << m_mesh->name() << " family=" << family->name()
556 << " Item" << ItemPrinter(item) << " has no cell with same owner:"
557 << ostr.str();
558 ++nerror;
559 }
560 }
561 }
562 else {
563 ENUMERATE_ITEM(iitem,family->allItems()){
564 Item item = *iitem;
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);
569 ++nerror;
570 }
571 }
572 }
573
574 if (nerror>0)
575 ARCANE_FATAL("mesh {0} family={1} has {2}",m_mesh->name(),family->name(),
576 String::plural(nerror,"owner error"));
577}
578
579/*---------------------------------------------------------------------------*/
580/*---------------------------------------------------------------------------*/
581
582void DynamicMeshChecker::
583checkVariablesSynchronization()
584{
585 Int64 nb_diff = 0;
586 VariableCollection used_vars(m_mesh->variableMng()->usedVariables());
587 for( VariableCollection::Enumerator i_var(used_vars); ++i_var; ){
588 IVariable* var = *i_var;
589 switch (var->itemKind()){
590 case IK_Node:
591 case IK_Edge:
592 case IK_Face:
593 case IK_Cell:
594 case IK_DoF:
595 nb_diff += var->checkIfSync(10);
596 break;
597 case IK_Particle:
598 case IK_Unknown:
599 break;
600 }
601 }
602 if (nb_diff!=0)
603 ARCANE_FATAL("Error in checkVariablesSynchronization() nb_diff=",nb_diff);
604}
605
606/*---------------------------------------------------------------------------*/
607/*---------------------------------------------------------------------------*/
608
609void DynamicMeshChecker::
610checkItemGroupsSynchronization()
611{
612 Int64 nb_diff = 0;
613 // TODO: parcourir toutes les familles (sauf particules)
614 ItemGroupsSynchronize node_sync(m_mesh->nodeFamily());
615 nb_diff += node_sync.checkSynchronize();
616 ItemGroupsSynchronize edge_sync(m_mesh->edgeFamily());
617 nb_diff += edge_sync.checkSynchronize();
618 ItemGroupsSynchronize face_sync(m_mesh->faceFamily());
619 nb_diff += face_sync.checkSynchronize();
620 ItemGroupsSynchronize cell_sync(m_mesh->cellFamily());
621 nb_diff += cell_sync.checkSynchronize();
622 if (nb_diff!=0)
623 ARCANE_FATAL("some groups are not synchronized nb_diff={0}",nb_diff);
624}
625
626/*---------------------------------------------------------------------------*/
627/*---------------------------------------------------------------------------*/
637void DynamicMeshChecker::
638checkGhostCells()
639{
640 pwarning() << "CHECK GHOST CELLS";
641 Integer sid = m_mesh->meshPartInfo().partRank();
642 ENUMERATE_CELL (icell, m_mesh->cellFamily()->allItems()) {
643 Cell cell = *icell;
644 if (cell.isOwn())
645 continue;
646 bool is_ok = false;
647 for (Node node : cell.nodes()) {
648 for (Cell cell2 : node.cells()) {
649 if (cell2.owner() == sid) {
650 is_ok = true;
651 }
652 }
653 }
654 if (!is_ok)
655 info() << "WARNING: Cell " << ItemPrinter(cell) << " should not be a ghost cell";
656 }
657}
658
659/*---------------------------------------------------------------------------*/
660/*---------------------------------------------------------------------------*/
661
662void DynamicMeshChecker::
663checkMeshFromReferenceFile()
664{
665 if (!m_compare_reference_file)
666 return;
667
668 IParallelMng* pm = m_mesh->parallelMng();
669
670 if (!pm->isParallel())
671 return; // uniquement en parallèle
672
673 debug() << "Testing the mesh against the initial mesh";
674 String base_file_name("meshconnectivity");
675 // En parallèle, compare le maillage actuel avec le fichier
676 // contenant la connectivité complète (cas séquentiel)
677 IIOMng* io_mng = pm->ioMng();
678 ScopedPtrT<IXmlDocumentHolder> xml_doc(io_mng->parseXmlFile(base_file_name));
679 if (xml_doc.get()){
680 XmlNode doc_node = xml_doc->documentNode();
681 if (!doc_node.null())
682 mesh_utils::checkMeshConnectivity(m_mesh,doc_node,true);
683 }
684 else{
685 warning() << "Can't test the subdomain coherence "
686 << "against the initial mesh";
687 }
688}
689
690/*---------------------------------------------------------------------------*/
691/*---------------------------------------------------------------------------*/
692
693void DynamicMeshChecker::
694checkValidReplication()
695{
696 info() << "Checking valid replication";
697 IParallelMng* mesh_pm = m_mesh->parallelMng();
698 IParallelReplication* pr = mesh_pm->replication();
699 if (!pr->hasReplication())
700 return;
701
703
704 // Vérifie que toutes les familles (sauf les particules) sont les mêmes
705 UniqueArray<IItemFamily*> wanted_same_family;
706
707 for( IItemFamilyCollection::Enumerator i(m_mesh->itemFamilies()); ++i; ){
708 IItemFamily* family = *i;
709 if (family->itemKind()!=IK_Particle)
710 wanted_same_family.add(family);
711 }
712 ValueChecker vc(A_FUNCINFO);
713
714 // Vérifie que tout le monde à le même nombre de famille.
715 Integer nb_family = wanted_same_family.size();
716 Integer max_nb_family = pm->reduce(Parallel::ReduceMax,nb_family);
717 vc.areEqual(nb_family,max_nb_family,"Bad number of family");
718
719 // Vérifie que toutes les familles ont le même nombre d'éléments.
720 //TODO: il faudrait vérifier aussi que les noms des familles correspondent.
721 {
722 UniqueArray<Int32> families_size(nb_family);
723 for( Integer i=0; i<nb_family; ++i )
724 families_size[i] = wanted_same_family[i]->nbItem();
725 UniqueArray<Int32> global_families_size(families_size);
726 pm->reduce(Parallel::ReduceMax,global_families_size.view());
727 vc.areEqualArray(global_families_size,families_size,"Bad family");
728 }
729
730 // Vérifie que toutes les familles ont les mêmes entités (même uniqueId())
731 {
732 UniqueArray<Int64> unique_ids;
733 UniqueArray<Int64> global_unique_ids;
734 for( Integer i=0; i<nb_family; ++i ){
735 ItemGroup group = wanted_same_family[i]->allItems();
736 unique_ids.resize(group.size());
737 Integer index = 0;
738 ENUMERATE_ITEM(iitem,group){
739 unique_ids[index] = iitem->uniqueId();
740 ++index;
741 }
742 global_unique_ids.resize(group.size());
743 global_unique_ids.copy(unique_ids);
744 pm->reduce(Parallel::ReduceMax,global_unique_ids.view());
745 String message = String::format("Bad unique ids for family '{0}'",
746 wanted_same_family[i]->name());
747 vc.areEqualArray(global_unique_ids,unique_ids,message);
748 }
749 }
750}
751
752/*---------------------------------------------------------------------------*/
753/*---------------------------------------------------------------------------*/
754
755void DynamicMeshChecker::
756_checkReplicationFamily(IItemFamily*)
757{
758}
759
760/*---------------------------------------------------------------------------*/
761/*---------------------------------------------------------------------------*/
762
763} // End namespace Arcane::mesh
764
765/*---------------------------------------------------------------------------*/
766/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_EDGE(name, group)
Enumérateur générique d'un groupe d'arêtes.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
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.
Maille d'un maillage.
Definition Item.h:1199
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1277
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1274
Int32 level() const
Definition Item.h:1350
EnumeratorT< IItemFamily * > Enumerator
Definition Collection.h:129
Vue constante d'un tableau de type T.
Arête d'une maille.
Definition Item.h:817
CellConnectedListViewType cells() const
Liste des mailles de l'arête.
Definition Item.h:904
Cette fonction/classe réoriente les faces.
Face d'une maille.
Definition Item.h:952
Cell frontCell() const
Maille devant la face (maille nulle si aucune)
Definition Item.h:1628
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1641
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
Definition Item.h:1027
CellConnectedListViewType cells() const
Liste des mailles de la face.
Definition Item.h:1033
Cell backCell() const
Maille derrière la face (maille nulle si aucune)
Definition Item.h:1622
Interface du gestionnaire des entrées sorties.
Definition IIOMng.h:42
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.
Definition IItemFamily.h:84
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.
Definition IVariable.h:56
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.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul)
Definition ItemGroup.h:123
ItemGroup own() const
Groupe équivalent à celui-ci mais contenant uniquement les éléments propres au sous-domaine.
Definition ItemGroup.cc:190
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é.
Definition ItemPrinter.h:35
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.
Definition ItemTypeMng.h:65
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é
Definition Item.h:782
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:785
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:779
Classe de base d'un élément de maillage.
Definition Item.h:83
const ItemTypeInfo * typeInfo() const
Infos sur le type de l'entité.
Definition Item.h:386
bool isOwn() const
true si l'entité est appartient au sous-domaine
Definition Item.h:253
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
Item parent(Int32 i) const
i-ème parent pour les sous-maillages
Definition Item.h:286
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:363
Int16 type() const
Type de l'entité
Definition Item.h:241
GroupType itemGroup() const
Groupe associé à la grandeur.
Noeud d'un maillage.
Definition Item.h:576
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Definition Item.h:683
Classe utilitaire pour réordonner les noeuds d'une entité.
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
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'.
Definition String.cc:1040
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.
Collection de variables.
virtual Integer checkIfSync(int max_print=0)
Vérifie si la variable est bien synchronisée.
IVariable * variable() const
Variable associée.
Noeud d'un arbre DOM.
Definition XmlNode.h:51
bool null() const
Vrai si le noeud est nul.
Definition XmlNode.h:294
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.
Definition ItemTypes.h:183
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.
Definition Misc.cc:68
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:426
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.
Definition UtilsTypes.h:434
std::int32_t Int32
Type entier signé sur 32 bits.