Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
FaceFamily.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* FaceFamily.cc (C) 2000-2025 */
9/* */
10/* Face family. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/FaceFamily.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/NotImplementedException.h"
18#include "arcane/utils/String.h"
19#include "arcane/utils/OStringStream.h"
20
21#include "arcane/mesh/NodeFamily.h"
22#include "arcane/mesh/EdgeFamily.h"
23#include "arcane/mesh/IncrementalItemConnectivity.h"
24#include "arcane/mesh/CompactIncrementalItemConnectivity.h"
25#include "arcane/mesh/ItemConnectivitySelector.h"
26#include "arcane/mesh/AbstractItemFamilyTopologyModifier.h"
27#include "arcane/mesh/ConnectivityNewWithDependenciesTypes.h"
28#include "arcane/mesh/NewWithLegacyConnectivity.h"
29#include "arcane/mesh/FaceReorienter.h"
30
31#include "arcane/core/IMesh.h"
32#include "arcane/core/ITiedInterface.h"
33#include "arcane/core/TiedFace.h"
35#include "arcane/core/ItemPrinter.h"
36#include "arcane/core/Connectivity.h"
37
39#include "arcane/core/GeometricUtilities.h"
40#include "arcane/core/SharedVariable.h"
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
45namespace Arcane::mesh
46{
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
52: public AbstractItemFamilyTopologyModifier
53{
54 public:
55
56 explicit TopologyModifier(FaceFamily* f)
57 : AbstractItemFamilyTopologyModifier(f)
58 , m_true_family(f)
59 {}
60 void replaceNode(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
61 {
62 m_true_family->replaceNode(item_lid, index, new_lid);
63 }
64 void replaceEdge(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
65 {
66 m_true_family->replaceEdge(item_lid, index, new_lid);
67 }
68 void replaceFace(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
69 {
70 m_true_family->replaceFace(item_lid, index, new_lid);
71 }
72 void replaceCell(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
73 {
74 m_true_family->replaceCell(item_lid, index, new_lid);
75 }
76 void setBackAndFrontCells(FaceLocalId face_lid, CellLocalId back_cell_lid,
77 CellLocalId front_cell_lid) override
78 {
79 Face face(m_true_family->_itemInternal(face_lid));
80 m_true_family->setBackAndFrontCells(face, back_cell_lid, front_cell_lid);
81 }
82
83 private:
84
85 FaceFamily* m_true_family = nullptr;
86};
87
88/*---------------------------------------------------------------------------*/
89/*---------------------------------------------------------------------------*/
90
91FaceFamily::
92FaceFamily(IMesh* mesh, const String& name)
93: ItemFamily(mesh, IK_Face, name)
94{
95 _setTopologyModifier(new TopologyModifier(this));
96}
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101FaceFamily::
102~FaceFamily()
103{
104}
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
109void FaceFamily::
110build()
111{
112 ItemFamily::build();
113
114 m_node_family = ARCANE_CHECK_POINTER(dynamic_cast<NodeFamily*>(m_mesh->nodeFamily()));
115 m_edge_family = ARCANE_CHECK_POINTER(dynamic_cast<EdgeFamily*>(m_mesh->edgeFamily()));
116
117 if (m_mesh->useMeshItemFamilyDependencies()) // temporary to fill legacy, even with family dependencies
118 {
119 m_node_connectivity = dynamic_cast<NewWithLegacyConnectivityType<FaceFamily, NodeFamily>::type*>(m_mesh->itemFamilyNetwork()->getConnectivity(this, mesh()->nodeFamily(), connectivityName(this, mesh()->nodeFamily())));
120 m_edge_connectivity = dynamic_cast<NewWithLegacyConnectivityType<FaceFamily, EdgeFamily>::type*>(m_mesh->itemFamilyNetwork()->getConnectivity(this, mesh()->edgeFamily(), connectivityName(this, mesh()->edgeFamily())));
121 m_face_connectivity = dynamic_cast<NewWithLegacyConnectivityType<FaceFamily, FaceFamily>::type*>(m_mesh->itemFamilyNetwork()->getConnectivity(this, mesh()->faceFamily(), connectivityName(this, mesh()->faceFamily())));
122 m_cell_connectivity = dynamic_cast<NewWithLegacyConnectivityType<FaceFamily, CellFamily>::type*>(m_mesh->itemFamilyNetwork()->getConnectivity(this, mesh()->cellFamily(), connectivityName(this, mesh()->cellFamily())));
123 }
124 else {
125 m_node_connectivity = new NodeConnectivity(this, mesh()->nodeFamily(), "FaceNode");
126 m_edge_connectivity = new EdgeConnectivity(this, mesh()->edgeFamily(), "FaceEdge");
127 m_face_connectivity = new FaceConnectivity(this, mesh()->faceFamily(), "FaceFace");
128 m_cell_connectivity = new CellConnectivity(this, mesh()->cellFamily(), "FaceCell");
129 }
130 m_hparent_connectivity = new HParentConnectivity(this, this, "HParentFace");
131 m_hchild_connectivity = new HChildConnectivity(this, this, "HChildFace");
132
133 _addConnectivitySelector(m_node_connectivity);
134 _addConnectivitySelector(m_edge_connectivity);
135 _addConnectivitySelector(m_face_connectivity);
136 _addConnectivitySelector(m_cell_connectivity);
137 _addConnectivitySelector(m_hparent_connectivity);
138 _addConnectivitySelector(m_hchild_connectivity);
139
140 _buildConnectivitySelectors();
141}
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
146inline void FaceFamily::
147_createOne(ItemInternal* item, Int64 uid, ItemTypeInfo* type)
148{
149 m_item_internal_list->faces = _itemsInternal();
150 _allocateInfos(item, uid, type);
151 auto nc = m_node_connectivity->trueCustomConnectivity();
152 if (nc)
153 nc->addConnectedItems(ItemLocalId(item), type->nbLocalNode());
154}
155
156/*---------------------------------------------------------------------------*/
157/*---------------------------------------------------------------------------*/
158
159inline void FaceFamily::
160_createOne(ItemInternal* item, Int64 uid, ItemTypeId type_id)
161{
162 _createOne(item, uid, _itemTypeMng()->typeFromId(type_id));
163}
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
175allocOne(Int64 uid, ItemTypeId type_id, MeshInfos& mesh_info)
176{
177 ++mesh_info.nbFace();
178 return allocOne(uid, type_id);
179}
180
181/*---------------------------------------------------------------------------*/
182/*---------------------------------------------------------------------------*/
188{
189 ItemInternal* item = _allocOne(uid);
190 _createOne(item, uid, type);
191 return item;
192}
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
207findOrAllocOne(Int64 uid, ItemTypeId type_id, MeshInfos& mesh_info, bool& is_alloc)
208{
209 auto face = findOrAllocOne(uid, type_id, is_alloc);
210 if (is_alloc)
211 ++mesh_info.nbFace();
212 return face;
213}
214
215/*---------------------------------------------------------------------------*/
216/*---------------------------------------------------------------------------*/
224findOrAllocOne(Int64 uid, ItemTypeInfo* type, bool& is_alloc)
225{
226 ItemInternal* item = _findOrAllocOne(uid, is_alloc);
227 if (is_alloc) {
228 _createOne(item, uid, type);
229 }
230 return item;
231}
232
233/*---------------------------------------------------------------------------*/
234/*---------------------------------------------------------------------------*/
235
237allocOne(Int64 uid, ItemTypeId type_id)
238{
239 ItemInternal* item = _allocOne(uid);
240 _createOne(item, uid, type_id);
241 return item;
242}
243
244/*---------------------------------------------------------------------------*/
245/*---------------------------------------------------------------------------*/
246
248findOrAllocOne(Int64 uid, ItemTypeId type_id, bool& is_alloc)
249{
250 ItemInternal* item = _findOrAllocOne(uid, is_alloc);
251 if (is_alloc) {
252 _createOne(item, uid, type_id);
253 }
254 return item;
255}
256
257/*---------------------------------------------------------------------------*/
258/*---------------------------------------------------------------------------*/
259
260void FaceFamily::
261preAllocate(Integer nb_item)
262{
263 if (!m_has_face)
264 return;
265 // We do not pre-allocate by default because we do not want to pre-allocate
266 // for face->face connectivity because it is only used
267 // if there are TiedInterfaces and this is not frequent.
268 // So we explicitly pre-allocate the connectivities we want.
269 this->_preAllocate(nb_item, false);
270 m_node_connectivity->trueCustomConnectivity()->reserveMemoryForNbSourceItems(nb_item, true);
271 if (Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_HasEdge))
272 m_edge_connectivity->trueCustomConnectivity()->reserveMemoryForNbSourceItems(nb_item, true);
273 m_cell_connectivity->trueCustomConnectivity()->reserveMemoryForNbSourceItems(nb_item, true);
274}
275
276/*---------------------------------------------------------------------------*/
277/*---------------------------------------------------------------------------*/
278
281{
282 debug() << "Creating the list of ghosts faces";
284}
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
294{
295 m_node_connectivity->replaceItem(face, index, node);
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
306{
307 m_edge_connectivity->replaceItem(face, index, edge);
308}
309
310/*---------------------------------------------------------------------------*/
311/*---------------------------------------------------------------------------*/
317replaceFace(ItemLocalId face, Integer index, ItemLocalId face2)
318{
319 m_face_connectivity->replaceItem(face, index, face2);
320}
321
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
330{
331 m_cell_connectivity->replaceItem(face, index, cell);
332}
333
334/*---------------------------------------------------------------------------*/
335/*---------------------------------------------------------------------------*/
345setBackAndFrontCells(Face face, Int32 iback_cell_lid, Int32 ifront_cell_lid)
346{
347 face.mutableItemBase()._setFaceBackAndFrontCells(iback_cell_lid, ifront_cell_lid);
348 ItemLocalId back_cell_lid(iback_cell_lid);
349 ItemLocalId front_cell_lid(ifront_cell_lid);
350 auto c = m_cell_connectivity->trueCustomConnectivity();
351 if (c) {
352 ItemLocalId face_lid(face.localId());
353 // Removes all connected cells.
354 // TODO: optimize by not deleting if it is not necessary to avoid
355 // reallocations.
356 c->removeConnectedItems(face_lid);
357 if (front_cell_lid == NULL_ITEM_LOCAL_ID) {
358 if (back_cell_lid != NULL_ITEM_LOCAL_ID) {
359 // Only the back_cell or no cell remains.
360 c->IncrementalItemConnectivity::addConnectedItem(face_lid, back_cell_lid); // add the class name for the case of Face to Cell connectivity. The class is overridden to handle family dependencies but the base method must be called here.
361 }
362 // Here no cell remains, but since we deleted everything there is nothing
363 // to do.
364 }
365 else if (back_cell_lid == NULL_ITEM_LOCAL_ID) {
366 // Only the front cell remains
367 c->IncrementalItemConnectivity::addConnectedItem(face_lid, front_cell_lid);
368 }
369 else {
370 // There are two connected cells. The back_cell is always the first.
371 c->IncrementalItemConnectivity::addConnectedItem(face_lid, back_cell_lid);
372 c->IncrementalItemConnectivity::addConnectedItem(face_lid, front_cell_lid);
373 }
374 }
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
381addBackCellToFace(Face face, Cell new_cell)
382{
383 _checkValidSourceTargetItems(face, new_cell);
384
385 Integer nb_cell = face.nbCell();
386
387 // SDP: the following tests are incompatible with refinement
388 // by layers
390 Cell current_cell = face.backCell();
392 ARCANE_FATAL("Face already having a back cell."
393 " This is most probably due to the fact that the face"
394 " is connected to a reverse cell with a negative volume."
395 " Face={0}. new_cell={1} current_cell={2}",
396 FullItemPrinter(face),
397 FullItemPrinter(new_cell), FullItemPrinter(current_cell));
398 }
399 }
400
401 if (nb_cell >= 2)
402 ARCANE_FATAL("face '{0}' already has two cells", FullItemPrinter(face));
403
404 _updateSharedInfo();
405
406 // If we already have a cell, it is the front cell.
407 Int32 front_cell_lid = (nb_cell == 1) ? face.cellId(0) : NULL_ITEM_LOCAL_ID;
408 setBackAndFrontCells(face, new_cell.localId(), front_cell_lid);
409}
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
413
415addFrontCellToFace(Face face, Cell new_cell)
416{
417 _checkValidSourceTargetItems(face, new_cell);
418
419 Integer nb_cell = face.nbCell();
420
421 // SDP: the following tests are incompatible with refinement
422 // by layers
424 Cell current_cell = face.frontCell();
426 ARCANE_FATAL("Face already having a front cell."
427 " This is most probably due to the fact that the face"
428 " is connected to a reverse cell with a negative volume."
429 " Face={0}. new_cell={1} current_cell={2}",
430 FullItemPrinter(face),
431 FullItemPrinter(new_cell), FullItemPrinter(current_cell));
432 }
433 }
434
435 if (nb_cell >= 2)
436 ARCANE_FATAL("face '{0}' already has two cells", FullItemPrinter(face));
437
438 _updateSharedInfo();
439
440 // If we already have a cell, it is the back cell.
441 Int32 back_cell_lid = (nb_cell == 1) ? face.cellId(0) : NULL_ITEM_LOCAL_ID;
442 setBackAndFrontCells(face, back_cell_lid, new_cell.localId());
443}
444
445/*---------------------------------------------------------------------------*/
446/*---------------------------------------------------------------------------*/
447
450{
451 ARCANE_ASSERT((face.nbCell() == 2), ("Face should have back and front cells"));
452
453 Cell current_cell = face.backCell();
454 _topologyModifier()->findAndReplaceCell(face, current_cell, new_cell);
455}
456
457/*---------------------------------------------------------------------------*/
458/*---------------------------------------------------------------------------*/
459
460void FaceFamily::
461replaceFrontCellToFace(Face face, ItemLocalId new_cell)
462{
463 ARCANE_ASSERT((face.nbCell() == 2), ("Face should have back and front cells"));
464
465 Cell current_cell = face.frontCell();
466 _topologyModifier()->findAndReplaceCell(face, current_cell, new_cell);
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471
472void FaceFamily::
473addBackFrontCellsFromParentFace(Face subface, Face face)
474{
475 Cell fcell = face.frontCell();
476 Cell bcell = face.backCell();
477
478 if (subface.hasFlags(ItemFlags::II_HasBackCell)) {
479 if (fcell.isActive())
480 addFrontCellToFace(subface, face.frontCell());
481 else if (bcell.isActive())
482 addFrontCellToFace(subface, face.backCell());
483 }
484 else if (subface.hasFlags(ItemFlags::II_HasFrontCell)) {
485 if (bcell.isActive())
486 addBackCellToFace(subface, face.backCell());
487 else if (fcell.isActive())
488 addBackCellToFace(subface, face.frontCell());
489 }
490 ARCANE_ASSERT((subface.backCell() != subface.frontCell()), ("back front cells error"));
491}
492
493/*---------------------------------------------------------------------------*/
494/*---------------------------------------------------------------------------*/
495
496void FaceFamily::
497replaceBackFrontCellsFromParentFace(Cell subcell, Face subface,
498 Cell cell, Face face)
499{
500 Cell fscell = subface.frontCell();
501 Cell bscell = subface.backCell();
502 Cell fcell = face.frontCell();
503 Cell bcell = face.backCell();
504 if (fscell.localId() == subcell.localId()) {
505 if (fcell.localId() == cell.localId()) {
506 if (bcell.level() > bscell.level()) {
507 replaceBackCellToFace(subface, bcell);
508 }
509 }
510 else {
511 if (fcell.level() > bscell.level()) {
512 replaceBackCellToFace(subface, fcell);
513 }
514 }
515 }
516 else {
517 if (fcell.localId() == cell.localId()) {
518 if (bcell.level() > fscell.level()) {
519 replaceFrontCellToFace(subface, bcell);
520 }
521 }
522 else {
523 if (fcell.level() > fscell.level()) {
524 replaceFrontCellToFace(subface, fcell);
525 }
526 }
527 }
528}
529
530/*---------------------------------------------------------------------------*/
531/*---------------------------------------------------------------------------*/
532
533bool FaceFamily::
534isSubFaceInFace(Face subface, Face face) const
535{
536 const Real tol = 1e-02;
537 bool is_true = false;
538
539 //TODO: a std::binary_search to speed up the search
540 for (Node inode : subface.nodes()) {
541 for (Node inode2 : face.nodes()) {
542 if (inode.uniqueId() == inode2.uniqueId()) { // it is enough that a single node coincides
543 is_true = true;
544 break;
545 }
546 }
547 }
548 if (!is_true)
549 return false;
550
551 SharedVariableNodeReal3 orig_nodes_coords(mesh()->sharedNodesCoordinates());
552 Real3 normal_face = _computeFaceNormal(face, orig_nodes_coords);
553 Real3 normal_subface = _computeFaceNormal(subface, orig_nodes_coords);
554 Real ps = math::dot(normal_face, normal_subface);
555 Real residual = math::abs(ps) - 1.;
556 return math::abs(residual) < tol ? true : false;
557}
558
559/*---------------------------------------------------------------------------*/
560/*---------------------------------------------------------------------------*/
561
562bool FaceFamily::
563isChildOnFace(ItemWithNodes child, Face face) const
564{
565 //TODO: a std::binary_search to speed up the search
566 for (Node inode : face.nodes()) {
567 for (Node inode2 : child.nodes()) {
568 if (inode.uniqueId() == inode2.uniqueId()) // it is enough that a single node coincides
569 return true;
570 }
571 }
572 return false;
573}
574
575/*---------------------------------------------------------------------------*/
576/*---------------------------------------------------------------------------*/
577
578void FaceFamily::
579subFaces(Face face, Array<ItemInternal*>& subfaces)
580{
581 Cell cell;
582 const Integer nb_cell = face.nbCell();
583
584 if (nb_cell == 2) {
585 Cell fcell = face.frontCell();
586 cell = (fcell.hasHChildren()) ? face.frontCell() : face.backCell();
587 }
588 else
589 cell = face.cell(0);
590
591 for (Integer c = 0; c < cell.nbHChildren(); c++) {
592 Cell child = cell.hChild(c);
593 if (isChildOnFace(child, face)) {
594 //debug() << "current FACE:" << FullItemPrinter(face)
595 //<< "\n current child CELL:" << FullItemPrinter(child)
596 //<< "\n";
597 for (Face subface : child.faces()) {
598 if (isSubFaceInFace(subface, face)) {
599 subfaces.add(ItemCompatibility::_itemInternal(subface));
600 }
601 }
602 }
603 }
604 //info() << "\n SUBFACE NB= " << subfaces.size();
605}
606
607/*---------------------------------------------------------------------------*/
608/*---------------------------------------------------------------------------*/
609
610void FaceFamily::
611allSubFaces(Face face, Array<ItemInternal*>& subfaces)
612{
613 subfaces.add(ItemCompatibility::_itemInternal(face));
614
615 Cell cell;
616 const Integer nb_cell = face.nbCell();
617 if (nb_cell == 2) {
618 Cell fcell = face.frontCell();
619 if (fcell.hasHChildren() && fcell.isOwn())
620 cell = face.frontCell();
621 else
622 cell = face.backCell();
623 }
624 else {
625 cell = face.cell(0);
626 }
627
628 for (Integer c = 0; c < cell.nbHChildren(); c++) {
629 Cell child = cell.hChild(c);
630 if (isChildOnFace(child, face)) {
631 for (Face subface : child.faces()) {
632 if (isSubFaceInFace(subface, face)) {
633 allSubFaces(subface, subfaces);
634 }
635 }
636 }
637 }
638}
639
640/*---------------------------------------------------------------------------*/
641/*---------------------------------------------------------------------------*/
642
643void FaceFamily::
644activeSubFaces(Face face, Array<ItemInternal*>& subfaces)
645{
646 Cell cell;
647 const Integer nb_cell = face.nbCell();
648
649 if (nb_cell == 2) {
650 Cell fcell = face.frontCell();
651 Cell bcell = face.backCell();
652 if (fcell.level() > bcell.level())
653 cell = face.frontCell();
654 else {
655 if (bcell.isOwn())
656 cell = face.backCell();
657 else
658 cell = face.frontCell();
659 }
660 }
661 else {
662 cell = face.cell(0);
663 }
664 Cell pcell = cell.topHParent();
665
666 UniqueArray<ItemInternal*> cell_family;
667 activeFamilyTree(cell_family, pcell);
668 for (Integer c = 0; c < cell_family.size(); c++) {
669 Cell child = cell_family[c];
670 if (isChildOnFace(child, face)) {
671 //debug() << "current FACE:" << FullItemPrinter(face)
672 //<< "\n current child CELL:" << FullItemPrinter(child)
673 //<< "\n";
674 for (Face subface : child.faces()) {
675 if (isSubFaceInFace(subface, face)) {
676 subfaces.add(ItemCompatibility::_itemInternal(subface));
677 }
678 }
679 }
680 }
681 //info() << "\n SUBFACE NB= " << subfaces.size();
682}
683
684/*---------------------------------------------------------------------------*/
685/*---------------------------------------------------------------------------*/
686
687void FaceFamily::
688familyTree(Array<ItemInternal*>& family, Cell item,
689 const bool reset) const
690{
691 ARCANE_ASSERT((!item.isSubactive()), ("The family tree doesn't include subactive items"));
692 // Clear the array if the flag reset tells us to.
693 if (reset)
694 family.clear();
695 // Add this item to the family tree.
696 family.add(ItemCompatibility::_itemInternal(item));
697 // Recurse into the items children, if it has them.
698 // Do not clear the array any more.
699 if (!item.isActive())
700 for (Integer c = 0, cs = item.nbHChildren(); c < cs; c++) {
701 Cell ichild = item.hChild(c);
702 familyTree(family, ichild, false);
703 }
704}
705
706/*---------------------------------------------------------------------------*/
707/*---------------------------------------------------------------------------*/
708
709void FaceFamily::
710activeFamilyTree(Array<ItemInternal*>& family, Cell item, const bool reset) const
711{
712 ARCANE_ASSERT((!item.isSubactive()), ("The family tree doesn't include subactive items"));
713 // Clear the array if the flag reset tells us to.
714 if (reset)
715 family.clear();
716 // Add this item to the family tree.
717 if (item.isActive())
718 family.add(ItemCompatibility::_itemInternal(item));
719 else
720 for (Integer c = 0, cs = item.nbHChildren(); c < cs; c++) {
721 Cell ichild = item.hChild(c);
722 if (ichild.isOwn())
723 activeFamilyTree(family, ichild, false);
724 }
725}
726
727/*---------------------------------------------------------------------------*/
728/*---------------------------------------------------------------------------*/
729
730void FaceFamily::
731_addParentFaceToFace(Face parent_face, Face child_face)
732{
733 m_hparent_connectivity->addConnectedItem(ItemLocalId(child_face), ItemLocalId(parent_face));
734}
735
736/*---------------------------------------------------------------------------*/
737/*---------------------------------------------------------------------------*/
738
739void FaceFamily::
740_addChildFaceToFace(Face parent_face, Face child_face)
741{
742 m_hchild_connectivity->addConnectedItem(ItemLocalId(parent_face), ItemLocalId(child_face));
743}
744
745// OFF AMR
746
747/*---------------------------------------------------------------------------*/
748/*---------------------------------------------------------------------------*/
749
751addEdgeToFace(Face face, Edge new_edge)
752{
753 if (!Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_FaceToEdge))
754 return;
755
756 _checkValidSourceTargetItems(face, new_edge);
757 m_edge_connectivity->addConnectedItem(ItemLocalId(face), ItemLocalId(new_edge));
758 ;
759}
760
761/*---------------------------------------------------------------------------*/
762/*---------------------------------------------------------------------------*/
763
765removeEdgeFromFace(Face face, Edge edge_to_remove)
766{
767 if (!Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_FaceToEdge))
768 return;
769
770 _checkValidSourceTargetItems(face, edge_to_remove);
771 m_edge_connectivity->removeConnectedItem(ItemLocalId(face), ItemLocalId(edge_to_remove));
772}
773
774/*---------------------------------------------------------------------------*/
775/*---------------------------------------------------------------------------*/
776
777inline void FaceFamily::
778_removeFace(Face face)
779{
780 ItemLocalId face_lid = face;
781 for (Int32 edge : face.edgeIds())
783 Int32 nb_linear_node = face.nbLinearNode();
784 for (Int32 i = 0; i < nb_linear_node; ++i) {
785 m_node_family->removeFaceFromNode(face.nodeId(i), face_lid);
786 }
787
788 _removeOne(face);
789 // We do not delete other relations here (none here)
790 // Because the other deletion must always be cell, face, edge, node
791 // so node is last and everything is already done
792 // Furthermore, this avoids recursion problems
793}
794
795/*---------------------------------------------------------------------------*/
796/*---------------------------------------------------------------------------*/
797
798Real3 FaceFamily::
799_computeFaceNormal(Face face, const SharedVariableNodeReal3& nodes_coord) const
800{
801 Real3 normal_face = Real3::zero();
802 Integer nb_node = face.nbNode();
803 Real3UniqueArray cord_face(nb_node);
804 for (Integer i = 0; i < nb_node; ++i) {
805 cord_face[i] = nodes_coord[face.node(i)];
806 }
807 switch (nb_node) {
808 case (4): {
809 GeometricUtilities::QuadMapping face_mapping;
810 face_mapping.m_pos[0] = cord_face[0];
811 face_mapping.m_pos[1] = cord_face[1];
812 face_mapping.m_pos[2] = cord_face[2];
813 face_mapping.m_pos[3] = cord_face[3];
814 normal_face = face_mapping.normal();
815 } break;
816 case (3): {
817 Real3 v1 = cord_face[1] - cord_face[0];
818 Real3 v2 = cord_face[2] - cord_face[0];
819 normal_face = math::vecMul(v1, v2).normalize();
820 } break;
821 case (2): {
822 normal_face = cord_face[0] - cord_face[1];
823 normal_face.normalize();
824 } break;
825 default:
826 ARCANE_FATAL("This kind of face is not handled");
827 }
828 return normal_face;
829}
830
831/*---------------------------------------------------------------------------*/
832/*---------------------------------------------------------------------------*/
833
835removeCellFromFace(Face face, ItemLocalId cell_to_remove_lid)
836{
837 _checkValidItem(face);
838
839 Integer nb_cell = face.nbCell();
840
841#ifdef ARCANE_CHECK
842 if (face.itemBase().isSuppressed())
843 ARCANE_FATAL("Can not remove cell from destroyed face={0}", ItemPrinter(face));
844 if (nb_cell == 0)
845 ARCANE_FATAL("Can not remove cell lid={0} from face uid={1} with no cell connected",
846 cell_to_remove_lid, face.uniqueId());
847#endif /* ARCANE_CHECK */
848
849 Integer nb_cell_after = nb_cell - 1;
850 const Int32 null_cell_lid = NULL_ITEM_LOCAL_ID;
852 // force the deletion of a face between two cells of different levels
853 // because this face is not topologically attached to the lower level cell
854 if (nb_cell == 2) {
855 if (face.backCell().level() != face.frontCell().level())
856 nb_cell_after = 0;
857 else if (!(face.backCell().isActive() && face.frontCell().isActive())) {
858 // TODO: GG: for performance reasons, it is better to avoid
859 // allocations in this method because it is called very often.
861 subFaces(face, subfaces);
862 for (Integer s = 0, ss = subfaces.size(); s < ss; s++) {
863 ItemInternal* face2 = subfaces[s];
864 Int32 cell0 = face2->cellId(0);
865 Int32 cell1 = face2->cellId(1);
866 // We previously had two connected cells,
867 // so the back_cell is cell 0, the front cell is cell 1
868 if (cell0 == cell_to_remove_lid) {
869 // The front cell remains
870 setBackAndFrontCells(face, null_cell_lid, cell1);
871 }
872 else {
873 // The back cell remains
874 setBackAndFrontCells(face, cell0, null_cell_lid);
875 }
876 _updateSharedInfo();
877 }
878 }
879 }
880 // OFF AMR
881 if (nb_cell_after != 0) {
882 Int32 cell0 = face.cellId(0);
883 Int32 cell1 = face.cellId(1);
884 // We previously had two connected cells,
885 // so the back_cell is cell 0, the front cell is cell 1
886 if (cell0 == cell_to_remove_lid) {
887 // The front cell remains
888 setBackAndFrontCells(face, null_cell_lid, cell1);
889 }
890 else {
891 // The back cell remains
892 setBackAndFrontCells(face, cell0, null_cell_lid);
893 }
894 }
895 else {
896 setBackAndFrontCells(face, null_cell_lid, null_cell_lid);
897 }
898
899 _updateSharedInfo();
900}
901
902/*---------------------------------------------------------------------------*/
903/*---------------------------------------------------------------------------*/
904
907{
908 _checkValidItem(face);
909
910 if (!face.itemBase().isSuppressed() && face.nbCell() == 0) {
911 _removeFace(face);
912 }
913}
914
915/*---------------------------------------------------------------------------*/
916/*---------------------------------------------------------------------------*/
917
918void FaceFamily::
919_addMasterFaceToFace(Face face, Face master_face)
920{
921 m_face_connectivity->addConnectedItem(face, master_face);
923}
924
925/*---------------------------------------------------------------------------*/
926/*---------------------------------------------------------------------------*/
927
928void FaceFamily::
929_addSlaveFacesToFace(Face master_face, Int32ConstArrayView slave_faces_lid)
930{
931 Integer nb_slave = slave_faces_lid.size();
932 for (Integer i = 0; i < nb_slave; ++i)
933 m_face_connectivity->addConnectedItem(master_face, ItemLocalId(slave_faces_lid[i]));
935}
936
937/*---------------------------------------------------------------------------*/
938/*---------------------------------------------------------------------------*/
939
940void FaceFamily::
941_removeMasterFaceToFace(Face face)
942{
943 m_face_connectivity->removeConnectedItems(face);
944 face.mutableItemBase().removeFlags(ItemFlags::II_SlaveFace);
945}
946
947/*---------------------------------------------------------------------------*/
948/*---------------------------------------------------------------------------*/
949
950void FaceFamily::
951_removeSlaveFacesToFace(Face master_face)
952{
953 m_face_connectivity->removeConnectedItems(master_face);
954 master_face.mutableItemBase().removeFlags(ItemFlags::II_MasterFace);
955}
956
957/*---------------------------------------------------------------------------*/
958/*---------------------------------------------------------------------------*/
959
962{
963 TiedInterfaceFaceList tied_faces(interface->tiedFaces());
964 Int32UniqueArray slave_faces;
965
966 ENUMERATE_FACE (imaster_face, interface->masterInterface()) {
967 Face master_face = *imaster_face;
968 Integer index = imaster_face.index();
969 ConstArrayView<TiedFace> slave_tied_faces(tied_faces[index]);
970 Integer nb_slave = slave_tied_faces.size();
971 slave_faces.clear();
972 for (Integer zz = 0; zz < nb_slave; ++zz) {
973 TiedFace tn = tied_faces[index][zz];
974 Face slave_face = tn.face();
975 slave_faces.add(slave_face.localId());
976 _addMasterFaceToFace(slave_face, master_face);
977 }
978 _addSlaveFacesToFace(master_face, slave_faces);
979 }
980}
981
982/*---------------------------------------------------------------------------*/
983/*---------------------------------------------------------------------------*/
984
987{
988 TiedInterfaceFaceList tied_faces(interface->tiedFaces());
989
990 ENUMERATE_FACE (imaster_face, interface->masterInterface()) {
991 Face master_face = *imaster_face;
992 Integer index = imaster_face.index();
993 ConstArrayView<TiedFace> slave_tied_faces(tied_faces[index]);
994 Integer nb_slave = slave_tied_faces.size();
995 for (Integer zz = 0; zz < nb_slave; ++zz) {
996 TiedFace tn = tied_faces[index][zz];
997 Face slave_face = tn.face();
998 _removeMasterFaceToFace(slave_face);
999 }
1000 _removeSlaveFacesToFace(master_face);
1001 }
1002}
1003
1004/*---------------------------------------------------------------------------*/
1005/*---------------------------------------------------------------------------*/
1006
1007void FaceFamily::
1008setConnectivity(const Integer c)
1009{
1010 m_mesh_connectivity = c;
1011 m_has_face = Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_HasFace);
1012 if (m_has_face) {
1013 m_node_prealloc = Connectivity::getPrealloc(m_mesh_connectivity, IK_Face, IK_Node);
1014 if (Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_HasEdge))
1015 m_edge_prealloc = Connectivity::getPrealloc(m_mesh_connectivity, IK_Face, IK_Edge);
1016 m_face_connectivity->setPreAllocatedSize(4);
1017 m_cell_prealloc = Connectivity::getPrealloc(m_mesh_connectivity, IK_Face, IK_Cell);
1018 m_node_connectivity->setPreAllocatedSize(m_node_prealloc);
1019 m_cell_connectivity->setPreAllocatedSize(m_cell_prealloc);
1020 debug() << "Family " << name() << " prealloc "
1021 << m_node_prealloc << " by node, "
1022 << m_edge_prealloc << " by edge, "
1023 << m_cell_prealloc << " by cell.";
1024 }
1025}
1026
1027/*---------------------------------------------------------------------------*/
1028/*---------------------------------------------------------------------------*/
1029
1030void FaceFamily::
1031reorientFacesIfNeeded()
1032{
1033 // Reorients the faces if necessary. This is the case, for example, if we
1034 // have changed the uniqueId() numbering of the nodes.
1035 mesh::FaceReorienter face_reorienter(mesh());
1036 ENUMERATE_ (Face, iface, allItems()) {
1037 face_reorienter.checkAndChangeOrientationAMR(*iface);
1038 }
1039}
1040
1041/*---------------------------------------------------------------------------*/
1042/*---------------------------------------------------------------------------*/
1043
1044} // End namespace Arcane::mesh
1045
1046/*---------------------------------------------------------------------------*/
1047/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
Integer size() const
Number of elements in the vector.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Cell of a mesh.
Definition Item.h:1300
bool isActive() const
Definition Item.h:1451
Int32 level() const
Definition Item.h:1473
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
Edge of a cell.
Definition Item.h:875
Face of a cell.
Definition Item.h:1032
Cell frontCell() const
Cell in front of the face (null cell if none).
Definition Item.h:1780
CellLocalId cellId(Int32 i) const
i-th cell of the face
Definition Item.h:1138
EdgeLocalIdView edgeIds() const
List of edges of the face.
Definition Item.h:1252
Int32 nbCell() const
Number of cells of the face (1 or 2).
Definition Item.h:1129
Cell backCell() const
Cell behind the face (null cell if none).
Definition Item.h:1774
virtual void findAndReplaceCell(ItemLocalId item_lid, ItemLocalId old_cell_lid, ItemLocalId new_cell_lid)=0
Finds and replaces a cell of an entity.
virtual IItemFamily * nodeFamily()=0
Returns the node family.
virtual IItemFamily * edgeFamily()=0
Returns the edge family.
virtual bool useMeshItemFamilyDependencies() const =0
check if the network itemFamily dependencies is activated
virtual IItemFamilyNetwork * itemFamilyNetwork()=0
Family network interface (connected families).
Interface of a class managing semi-conforming mesh.
virtual TiedInterfaceFaceList tiedFaces() const =0
List of information about the slave faces of a master face.
virtual FaceGroup masterInterface() const =0
Group containing the master faces.
bool isSuppressed() const
True if the entity is suppressed.
@ II_MasterFace
The entity is a master face of an interface.
Definition ItemFlags.h:65
@ II_HasBackCell
The entity has a back cell.
Definition ItemFlags.h:53
@ II_SlaveFace
The entity is a slave face of an interface.
Definition ItemFlags.h:64
@ II_HasFrontCell
The entity has a front cell.
Definition ItemFlags.h:52
Internal structure of a mesh entity.
Index of an Item in a variable.
Definition ItemLocalId.h:42
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
Type of an entity (Item).
Definition ItemTypeId.h:33
Info on a mesh entity type.
NodeLocalId nodeId(Int32 index) const
i-th node of the entity.
Definition Item.h:849
Int32 nbLinearNode() const
Number of nodes of the associated linear entity (if entity order 2 or more).
Definition Item.h:852
Base class for a mesh element.
Definition Item.h:84
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
constexpr bool hasFlags(Int32 flags) const
Returns if the flags are set for the entity.
Definition Item.h:352
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
impl::ItemBase itemBase() const
Internal part of the entity.
Definition Item.h:383
void _setFaceBackAndFrontCells(Int32 back_cell_lid, Int32 front_cell_lid)
For a face, positions both the back cell and the front cell.
void addFlags(Int32 added_flags)
Adds the flags added_flags to those of the entity.
Semi-conforming mesh face.
Definition TiedFace.h:35
Face face() const
Welded face.
Definition TiedFace.h:52
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
1D data vector with value semantics (STL style).
void removeFaceFromEdge(ItemLocalId edge, ItemLocalId face_to_remove)
Removes a face from an edge.
void replaceCell(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
Replaces a cell of an entity.
Definition FaceFamily.cc:72
void replaceEdge(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
Replaces an edge of an entity.
Definition FaceFamily.cc:64
void replaceNode(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
Replaces a node of an entity.
Definition FaceFamily.cc:60
void setBackAndFrontCells(FaceLocalId face_lid, CellLocalId back_cell_lid, CellLocalId front_cell_lid) override
Positions a cell in front and behind a face.
Definition FaceFamily.cc:76
void replaceFace(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
Replaces a face of an entity.
Definition FaceFamily.cc:68
void replaceNode(ItemLocalId face, Integer index, ItemLocalId node)
Replaces the node at index index of the face face with that of localId() node_lid.
void setBackAndFrontCells(Face face, Int32 back_cell_lid, Int32 front_cell_lid)
Positions the cell behind and in front of the face.
NodeFamily * m_node_family
Node family associated with this family.
Definition FaceFamily.h:158
void removeEdgeFromFace(Face face, Edge edge_to_remove)
Removes an edge from the face.
void replaceEdge(ItemLocalId face, Integer index, ItemLocalId edge)
Replaces the edge at index index of the face face with that of localId() edge_lid.
Item allocOne(Int64 uid, ItemTypeId type_id, MeshInfos &mesh_info) override
Allocates a face with unique number uid and type type. Generic item addition.
void applyTiedInterface(ITiedInterface *interface)
Sets the information related to the tied interface interface.
Item findOrAllocOne(Int64 uid, ItemTypeId type_id, MeshInfos &mesh_info, bool &is_alloc) override
Retrieves or allocates a face with unique number uid and type type.
EdgeFamily * m_edge_family
Edge family associated with this family.
Definition FaceFamily.h:161
void removeCellFromFace(Face face, ItemLocalId cell_to_remove_lid)
Removes a cell from the face.
void replaceCell(ItemLocalId face, Integer index, ItemLocalId cell)
Replaces the cell at index index of the face face with that of localId() cell_lid.
void addFrontCellToFace(Face face, Cell new_cell)
Adds a front cell to the face.
bool m_check_orientation
Indicates whether to check the orientation.
Definition FaceFamily.h:164
virtual void computeSynchronizeInfos() override
Constructs the structures necessary for synchronization.
void addEdgeToFace(Face face, Edge new_edge)
Adds an edge to the face.
void removeFaceIfNotConnected(Face face)
Removes the face if it is no longer connected.
void removeTiedInterface(ITiedInterface *interface)
Removes the information related to the tied interface interface.
void replaceBackCellToFace(Face face, ItemLocalId new_cell)
AMR.
void addBackCellToFace(Face face, Cell new_cell)
Adds a back cell to the face.
void replaceFace(ItemLocalId face, Integer index, ItemLocalId face2)
Replaces the face at index index of the face face with that of localId() face_lid.
IMesh * mesh() const override
Associated mesh.
IItemFamilyTopologyModifier * _topologyModifier() override
Topology modifier interface.
Definition ItemFamily.h:402
ItemGroup allItems() const override
Group of all entities.
void computeSynchronizeInfos() override
Constructs the structures necessary for synchronization.
String name() const override
Family name.
Definition ItemFamily.h:140
Class containing mesh information.
Definition MeshInfos.h:36
Integer & nbFace()
Number of faces in the mesh.
Definition MeshInfos.h:65
__host__ __device__ Real dot(Real2 u, Real2 v)
Dot product of u by v in .
Definition MathUtils.h:94
__host__ __device__ Real3 vecMul(Real3 u, Real3 v)
Vector cross product of u by v in .
Definition MathUtils.h:48
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
UniqueArray< Real3 > Real3UniqueArray
Dynamic 1D array of rank 3 vectors.
Definition UtilsTypes.h:363
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
SharedMeshVariableScalarRefT< Node, Real3 > SharedVariableNodeReal3
Quantity at the node of coordinate type.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Face
Face mesh entity.
@ IK_Edge
Edge mesh entity.
double Real
Type representing a real number.
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
std::int32_t Int32
Signed integer type of 32 bits.