Arcane  v3.14.10.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-2022 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-2023 */
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
22#include "arcane/MeshUtils.h"
23#include "arcane/ItemPrinter.h"
24#include "arcane/TemporaryVariableBuildInfo.h"
25#include "arcane/IXmlDocumentHolder.h"
26#include "arcane/XmlNodeList.h"
27#include "arcane/IIOMng.h"
28#include "arcane/IParallelMng.h"
29#include "arcane/IParallelReplication.h"
30#include "arcane/VariableCollection.h"
31
32#include <set>
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37namespace Arcane::mesh
38{
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43DynamicMeshChecker::
44DynamicMeshChecker(IMesh* mesh)
45: TraceAccessor(mesh->traceMng())
46, m_mesh(mesh)
47, m_check_level(0)
48, m_var_cells_faces(0)
49, m_var_cells_nodes(0)
50, m_compare_reference_file(false)
51{
52 if (arcaneIsCheck())
53 m_check_level = 1;
54}
55
56/*---------------------------------------------------------------------------*/
57/*---------------------------------------------------------------------------*/
58
59DynamicMeshChecker::
60~DynamicMeshChecker()
61{
62 delete m_var_cells_faces;
63 delete m_var_cells_nodes;
64}
65
66/*---------------------------------------------------------------------------*/
67/*---------------------------------------------------------------------------*/
76void DynamicMeshChecker::
77checkValidMesh()
78{
79 info(4) << "Check mesh coherence.";
80 checkValidConnectivity();
81
82 for( IItemFamilyCollection::Enumerator i(m_mesh->itemFamilies()); ++i; ){
83 IItemFamily* family = *i;
84 //GG: regarder pourquoi il y a ce test.
85 if (family->itemKind()>=NB_ITEM_KIND)
86 continue;
87 family->checkValid();
88 }
89 mesh_utils::checkMeshProperties(m_mesh,false,false,true);
90
91 // Sauve dans une variable aux mailles la liste des faces et
92 // noeuds qui la composent.
93 // Ceci n'est utile que pour des vérifications
94 // NOTE: pour l'instant mis a false car fait planter si utilise
95 // partitionnement initial dans Arcane
96 const bool global_check = false;
97 if (m_check_level>=1 && global_check){
98 if (!m_var_cells_faces)
99 m_var_cells_faces = new VariableCellArrayInt64(VariableBuildInfo(m_mesh,"MeshTestCellFaces"));
100
101 if (!m_var_cells_nodes)
102 m_var_cells_nodes = new VariableCellArrayInt64(VariableBuildInfo(m_mesh,"MeshTestCellNodes"));
103
104 CellGroup all_cells(m_mesh->allCells());
105 Integer max_nb_face = 0;
106 Integer max_nb_node = 0;
108 Cell cell = *i;
109 Integer nb_face = cell.nbFace();
110 Integer nb_node = cell.nbNode();
115 }
116 m_var_cells_faces->resize(max_nb_face);
117 m_var_cells_nodes->resize(max_nb_node);
119 Cell cell = *i;
120 Integer nb_face = cell.nbFace();
121 for( Integer z=0; z<nb_face; ++z )
122 (*m_var_cells_faces)[cell][z] = cell.face(z).uniqueId().asInt64();
123 Integer nb_node = cell.nbNode();
124 for( Integer z=0; z<nb_node; ++z )
125 (*m_var_cells_nodes)[cell][z] = cell.node(z).uniqueId().asInt64();
126 }
127 }
128 checkValidMeshFull();
129}
130
131/*---------------------------------------------------------------------------*/
132/*---------------------------------------------------------------------------*/
133
134void DynamicMeshChecker::
135checkValidMeshFull()
136{
137 String func_name("DynamicMesh::checkValidMeshFull");
138 info() << func_name << " on " << m_mesh->name();
139 Integer nb_error = 0;
140 VariableFaceInt64 var_faces(VariableBuildInfo(m_mesh,"MeshCheckFaces"));
141 debug() << " VAR_FACE GROUP=" << var_faces.variable()->itemFamily()
142 << " NAME=" << var_faces.itemGroup().name()
143 << " FAMILY_NAME=" << var_faces.variable()->itemFamilyName()
144 << " GROUP_NAME=" << var_faces.variable()->itemGroupName();
145 ENUMERATE_FACE(iface,m_mesh->allFaces()){
146 Face face = *iface;
147 Cell c = face.backCell();
148 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
149 var_faces[face] = uid;
150 }
151 var_faces.synchronize();
152 ENUMERATE_FACE(iface,m_mesh->allFaces()){
153 Face face = *iface;
154 Cell c = face.backCell();
155 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
156 if (uid!=var_faces[face] && uid!=NULL_ITEM_ID && var_faces[face]!=NULL_ITEM_ID){
157 error() << func_name << " bad back cell in face uid=" << face.uniqueId();
158 ++nb_error;
159 }
160 }
161
162 ENUMERATE_FACE(iface,m_mesh->allFaces()){
163 Face face = *iface;
164 Cell c = face.frontCell();
165 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
166 var_faces[face] = uid;
167 }
168 var_faces.synchronize();
169 ENUMERATE_FACE(iface,m_mesh->allFaces()){
170 Face face = *iface;
171 Cell c = face.frontCell();
172 Int64 uid = c.null() ? NULL_ITEM_UNIQUE_ID : c.uniqueId();
173 if (uid!=var_faces[face] && uid!=NULL_ITEM_ID && var_faces[face]!=NULL_ITEM_ID){
174 error() << func_name << " bad front cell in face uid=" << face.uniqueId();
175 ++nb_error;
176 }
177 }
178
179 ENUMERATE_CELL(icell,m_mesh->allCells()){
180 Cell cell = *icell;
181 Integer cell_type = cell.type();
182 if (cell_type == IT_Line2) {
183 error() << func_name << " bad cell type in face uid=" << cell.uniqueId();
184 ++nb_error;
185 }
186 }
187
188 ENUMERATE_FACE(iface,m_mesh->allFaces()){
189 Face face = *iface;
190 Integer face_type = face.type();
191 if (face_type == IT_Vertex) {
192 error() << func_name << " bad face type in face uid=" << face.uniqueId();
193 ++nb_error;
194 }
195 }
196
197 if (nb_error!=0)
198 ARCANE_FATAL("Invalid mesh");
199}
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203/*
204 * \brief Vérifie que la connectivité est valide.
205 *
206 * Les vérifications portent sur les points suivants:
207 * - pas d'entités du maillage ayant un indice nul.
208 * - pour les faces, vérifie qu'il existe au moins une frontCell ou une
209 * backCell. De plus, si elle a deux mailles, la backCell doit
210 * toujours être la première.
211 * - les noeuds et les faces doivent avoir le même propriétaire
212 * qu'une des mailles attenante.
213 * - vérifie que les faces sont bien ordonnées et orientées
214 */
215void DynamicMeshChecker::
216checkValidConnectivity()
217{
218 String func_name = "DynamicMesh::checkValidConnectivity";
219 debug() << func_name << " check";
220
221 // Appelle la méthode de vérification de chaque famille.
222 IItemFamilyCollection item_families = m_mesh->itemFamilies();
223 for( auto x = item_families.enumerator(); ++x; ){
224 IItemFamily* f = *x;
226 }
227
228 if (!m_mesh->parentMesh()){
229 Integer index = 0;
230 ENUMERATE_FACE(i,m_mesh->allFaces()){
231 Face elem = *i;
232 Cell front_cell = elem.frontCell();
233 Cell back_cell = elem.backCell();
234 if (front_cell.null() && back_cell.null())
235 ARCANE_FATAL("Local face '{0}' has two null cell face=",index,ItemPrinter(elem));
236 index++;
237 }
238 }
239
240 // Vérifie que la connective maille<->noeud
241 // est réciproque
242 ENUMERATE_NODE(inode,m_mesh->allNodes()){
243 Node node = *inode;
244 for( Cell cell : node.cells() ){
245 bool has_found = false;
246 for( Node node2 : cell.nodes() ){
247 if (node2==node){
248 has_found = true;
249 break;
250 }
251 }
252 if (!has_found){
253 ARCANE_FATAL("Node uid={0} is connected to the cell uid={1} but the cell"
254 " is not connected to this node.",ItemPrinter(node),ItemPrinter(cell));
255 }
256 }
257 }
258
259 // ATT: les verifications suivantes ne sont pas compatible avec l'AMR
260 // TODO : etendre les verifs au cas AMR
262 if(!m_mesh->isAmrActivated()){
263 // Vérifie que la connective maille<->arêtes
264 // est réciproque
265 ENUMERATE_EDGE(iedge,m_mesh->allEdges()){
266 Edge edge = *iedge;
267 for( Cell cell : edge.cells() ){
268 bool has_found = false;
269 for( Edge edge2 : cell.edges() ){
270 if (edge2==edge){
271 has_found = true;
272 break;
273 }
274 }
275 if (!has_found){
276 ARCANE_FATAL("Edge uid={0} is connected to the cell uid={1} but the cell"
277 " is not connected to this edge.",ItemPrinter(edge),ItemPrinter(cell));
278 }
279 }
280 }
281 }
282 // Vérifie que la connective maille<->face
283 // est réciproque
284 ENUMERATE_FACE(iface,m_mesh->allFaces()){
285 Face face = *iface;
286 if(!m_mesh->isAmrActivated()){
287 for( Cell cell : face.cells() ){
288 bool has_found = false;
289 for( Face face2 : cell.faces() ){
290 if (face2==face){
291 has_found = true;
292 break;
293 }
294 }
295 if (!has_found){
296 ARCANE_FATAL("Face uid={0} is connected to the cell uid={1} but the cell"
297 " is not connected to this face.",ItemPrinter(face),ItemPrinter(cell));
298 }
299 }
300 }
301 for( Cell cell : face.cells() ){
302 bool has_found = false;
303 for( Face face2 : cell.faces() ){
304 if (face2==face){
305 has_found = true;
306 break;
307 }
308 }
309 if (!has_found && (face.backCell().level() == face.frontCell().level())){
310 warning() << func_name << ". The face " << FullItemPrinter(face)
311 << " is connected to the cell " << FullItemPrinter(cell)
312 << " but the cell (level "<< cell.level()<< ")"
313 << " is not connected to the face.";
314 }
315 }
316
317 Integer nb_cell = face.nbCell();
318 Cell back_cell = face.backCell();
319 Cell front_cell = face.frontCell();
320 if ((back_cell.null() || front_cell.null()) && nb_cell==2)
321 ARCANE_FATAL("Face uid='{0}' bad number of cells face",ItemPrinter(face));
322 // Si on a deux mailles connectées, alors la back cell doit être la première
323 if (nb_cell==2 && back_cell!=face.cell(0))
324 ARCANE_FATAL("Bad face face.backCell()!=face.cell(0) face={0} back_cell={1} from_cell={2} cell0={3}",
326 }
327
328 _checkFacesOrientation();
329
330 if (m_mesh->parentMesh()){
331 Integer nerror = 0;
333 Integer nb_kind = sizeof(kinds)/sizeof(eItemKind);
334
335 for(Integer i_kind=0;i_kind<nb_kind;++i_kind){
336 const eItemKind kind = kinds[i_kind];
337 IItemFamily * family = m_mesh->itemFamily(kind);
338 if (!family->parentFamily()){
339 error() << "Mesh " << m_mesh->name() << " : Family " << kind << " does not exist in mesh";
340 ++nerror;
341 }
342 else{
343 ENUMERATE_ITEM(iitem,family->allItems()){
344 const Item & item = *iitem;
345 const Item & parent_item = item.parent();
346 if (parent_item.itemBase().isSuppressed()){
347 error() << "Mesh " << m_mesh->name() << " : Inconsistent suppresssed parent item uid : "
348 << ItemPrinter(item) << " / " << ItemPrinter(parent_item);
349 ++nerror;
350 }
351 if (parent_item.uniqueId() != item.uniqueId()){
352 error() << "Mesh " << m_mesh->name() << " : Inconsistent item/parent item uid : " << ItemPrinter(item);
353 ++nerror;
354 }
355 }
356 }
357 }
358 if (nerror > 0)
359 ARCANE_FATAL("Mesh name={0} has {1} (see above)",m_mesh->name(),String::plural(nerror, "error"));
360
361 // Vérifie la consistence parallèle du groupe parent
362 nerror = 0;
363 {
364 ItemGroup parent_group = m_mesh->parentGroup();
365 String var_name = String::format("SubMesh_{0}_GroupConsistencyChecker",parent_group.name());
366 TemporaryVariableBuildInfo tvbi(m_mesh->parentMesh(),var_name,parent_group.itemFamily()->name());
367 ItemVariableScalarRefT<Integer> var(tvbi,m_mesh->parentGroup().itemKind());
368 var.fill(-1);
369 ENUMERATE_ITEM(iitem, m_mesh->parentGroup()){
370 var[iitem] = iitem->owner();
371 }
372 nerror += var.checkIfSync(10);
373 }
374 if (nerror > 0)
375 ARCANE_FATAL("Mesh name={0} has parent group consistency {1}\n"
376 "This usually means that parent group was not symmetrically built",
377 m_mesh->name(),String::plural(nerror, "error", false));
378 }
379
380 _checkValidItemOwner(m_mesh->nodeFamily());
381 _checkValidItemOwner(m_mesh->edgeFamily());
382 _checkValidItemOwner(m_mesh->faceFamily());
383 _checkValidItemOwner(m_mesh->cellFamily());
384}
385
386/*---------------------------------------------------------------------------*/
387/*---------------------------------------------------------------------------*/
388
389void DynamicMeshChecker::
390updateAMRFaceOrientation()
391{
392 String func_name = "DynamicMesh::updateAMRFaceOrientation";
393 FaceReorienter fr(m_mesh);
394 ENUMERATE_FACE(iface,m_mesh->allFaces()){
395 Face face = *iface;
396 Integer nb_cell = face.nbCell();
397 Cell back_cell = face.backCell();
398 Cell front_cell = face.frontCell();
399 if ((back_cell.null() || front_cell.null()) && nb_cell==2)
400 ARCANE_FATAL("Bad number of cells for face={0}",ItemPrinter(face));
401 // Si on a deux mailles connectées, alors la back cell doit être la première
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}",
405
406 // Ceci pourrait sans doutes etre optimise
407 fr.checkAndChangeOrientationAMR(face);
408 }
409}
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
413
414void DynamicMeshChecker::
415updateAMRFaceOrientation(ArrayView<Int64> ghost_cell_to_refine)
416{
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);
421 std::set<Int64> set ;
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());
429 if(value.second){
430 fr.checkAndChangeOrientationAMR(face);
431 }
432 }
433 }
434 }
435}
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
442void DynamicMeshChecker::
443_checkFacesOrientation()
444{
445 bool is_1d = (m_mesh->dimension()==1);
446 //Temporaire: pour l'instant, ne teste pas l'orientation en 1D.
447 if (is_1d)
448 return;
449
450 String func_name = "DynamicMesh::_checkFacesOrientation";
451
452 Int64UniqueArray m_work_face_sorted_nodes;
454 Int64UniqueArray m_work_face_orig_nodes_uid;
455
456
457 ENUMERATE_CELL(icell,m_mesh->allCells()){
458 Cell cell = *icell;
459 const ItemTypeInfo* type = cell.typeInfo();
460 Integer cell_nb_face = type->nbLocalFace();
461 for( Integer i_face=0; i_face<cell_nb_face; ++i_face ){
463 Integer face_nb_node = lf.nbNode();
464
465 m_work_face_sorted_nodes.resize(face_nb_node);
467 m_work_face_orig_nodes_uid.resize(face_nb_node);
468 for( Integer z=0; z<face_nb_node; ++z )
469 m_work_face_orig_nodes_uid[z] = cell.node(lf.node(z)).uniqueId();
470
471 bool is_reorder = false;
472 if (is_1d){
473 is_reorder = (i_face==1);
475 }
476 else
477 is_reorder = mesh_utils::reorderNodesOfFace2(m_work_face_orig_nodes_uid,m_work_face_nodes_index);
478 for( Integer z=0; z<face_nb_node; ++z )
479 m_work_face_sorted_nodes[z] = m_work_face_orig_nodes_uid[m_work_face_nodes_index[z]];
480
481 Face cell_face = cell.face(i_face);
482 if (cell_face.nbNode()!=face_nb_node)
483 ARCANE_FATAL("Incoherent number of node for 'face' and 'localFace'"
484 " cell={0} face={1} nb_local_node={2} nb_face_node={3}",
486
487 for( Integer z=0; z<face_nb_node; ++z ){
488 if (cell_face.node(z).uniqueId()!=m_work_face_sorted_nodes[z])
489 ARCANE_FATAL("Bad unique id for face: cell={0} face={1} cell_node_uid={2} face_node_uid={3}",
490 ItemPrinter(cell),ItemPrinter(cell_face),m_work_face_sorted_nodes[z],
491 cell_face.node(z).uniqueId());
492 }
493 if (is_reorder){
494 Cell front_cell = cell_face.frontCell();
495 if (front_cell!=cell){
496 if (!front_cell.null())
497 ARCANE_FATAL("Bad orientation for face. Should be front cell: cell={0} face={1} front_cell={2}",
499 else
500 ARCANE_FATAL("Bad orientation for face. Should be front cell (no front cell) cell={0} face={1}",
502 }
503 }
504 else{
505 Cell back_cell = cell_face.backCell();
506 if (back_cell!=cell){
507 if (!back_cell.null())
508 ARCANE_FATAL("Bad orientation for face. Should be back cell: cell={0} face={1} front_cell={2}",
510 else
511 ARCANE_FATAL("Bad orientation for face. Should be back cell (no back cell) cell={0} face={1}",
513 }
514 }
515 }
516 }
517}
518
519/*---------------------------------------------------------------------------*/
520/*---------------------------------------------------------------------------*/
521
522void DynamicMeshChecker::
523_checkValidItemOwner(IItemFamily* family)
524{
525 String func_name = "DynamicMesh::_checkValidItemOwner";
526
527 // Pour les maillages non sous-maillages, il faut que tout sub-item est une cellule voisine de même propriétaire
528 // Pour les sous-maillages, il faut, en plus, que tout item soit de même propriétaire que son parent
529
530 Integer nerror = 0;
531
532 if (!m_mesh->parentMesh()){
533
534 if (family->itemKind() == IK_Cell)
535 return; // implicitement valide pour les cellules
536
537 ItemGroup own_items = family->allItems().own();
539 Item item = *iitem;
540 Int32 owner = item.owner();
541 bool is_ok = false;
542 ItemVectorView cells = item.itemBase().cellList();
543 for( Item cell : cells ){
544 if (cell.owner()==owner){
545 is_ok = true;
546 break;
547 }
548 }
549 if (!is_ok) {
550 OStringStream ostr;
551 Integer index = 0;
552 for( Item cell : cells ){
553 ostr() << " SubCell i=" << index << " cell=" << ItemPrinter(cell);
554 ++index;
555 }
556 error() << "Mesh " << m_mesh->name() << " 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());
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();
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
702 IParallelMng* pm = pr->replicaParallelMng();
703
704 // Vérifie que toutes les familles (sauf les particules) sont les mêmes
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 {
723 for( Integer i=0; i<nb_family; ++i )
724 families_size[i] = wanted_same_family[i]->nbItem();
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 {
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());
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_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.
Maille d'un maillage.
Definition Item.h:1178
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1255
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1252
Int32 level() const
Definition Item.h:1328
Arête d'une maille.
Definition Item.h:798
CellConnectedListViewType cells() const
Liste des mailles de l'arête.
Definition Item.h:884
Cette fonction/classe réoriente les faces.
Face d'une maille.
Definition Item.h:932
Cell frontCell() const
Maille devant la face (maille nulle si aucune)
Definition Item.h:1604
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1617
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
Definition Item.h:1006
CellConnectedListViewType cells() const
Liste des mailles de la face.
Definition Item.h:1012
Cell backCell() const
Maille derrière la face (maille nulle si aucune)
Definition Item.h:1598
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:54
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.
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:771
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:765
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:377
bool isOwn() const
true si l'entité est appartient au sous-domaine
Definition Item.h:244
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:229
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
Item parent(Int32 i) const
i-ème parent pour les sous-maillages
Definition Item.h:277
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:354
Int16 type() const
Type de l'entité
Definition Item.h:232
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Noeud d'un maillage.
Definition Dom.h:204
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Definition Item.h:670
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:151
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466
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.
Int32 Integer
Type représentant un entier.