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