Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
NodeFamily.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/* NodeFamily.cc (C) 2000-2025 */
9/* */
10/* Node family. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/NodeFamily.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/ITraceMng.h"
19#include "arcane/utils/ValueConvert.h"
20
21#include "arcane/core/ISubDomain.h"
22#include "arcane/core/ItemPrinter.h"
23#include "arcane/core/VariableTypes.h"
24#include "arcane/core/IMesh.h"
26#include "arcane/core/Connectivity.h"
27#include "arcane/core/ConnectivityItemVector.h"
28#include "arcane/core/Properties.h"
29
30#include "arcane/mesh/IncrementalItemConnectivity.h"
31#include "arcane/mesh/CompactIncrementalItemConnectivity.h"
32#include "arcane/mesh/ItemConnectivitySelector.h"
33#include "arcane/mesh/AbstractItemFamilyTopologyModifier.h"
34#include "arcane/mesh/NewWithLegacyConnectivity.h"
35#include "arcane/mesh/FaceFamily.h"
36#include "arcane/mesh/EdgeFamily.h"
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane::mesh
42{
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
48: public AbstractItemFamilyTopologyModifier
49{
50 public:
51
52 TopologyModifier(NodeFamily* f)
53 : AbstractItemFamilyTopologyModifier(f)
54 , m_true_family(f)
55 {}
56
57 public:
58
59 void replaceEdge(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
60 {
61 m_true_family->replaceEdge(item_lid, index, new_lid);
62 }
63 void replaceFace(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
64 {
65 m_true_family->replaceFace(item_lid, index, new_lid);
66 }
67 void replaceCell(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
68 {
69 m_true_family->replaceCell(item_lid, index, new_lid);
70 }
71
72 private:
73
74 NodeFamily* m_true_family;
75};
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79
80NodeFamily::
81NodeFamily(IMesh* mesh, const String& name)
82: ItemFamily(mesh, IK_Node, name)
83{
84 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_SORT_FACE_AND_EDGE_OF_NODE", true)) {
86 info() << "Set sort faces and edges of nodes v?=" << m_is_sort_connected_faces_and_edges;
87 }
88 _setTopologyModifier(new TopologyModifier(this));
89}
90
91/*---------------------------------------------------------------------------*/
92/*---------------------------------------------------------------------------*/
93
94NodeFamily::
95~NodeFamily()
96{
97 delete m_nodes_coords;
98}
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102
103void NodeFamily::
104build()
105{
106 ItemFamily::build();
107
108 ItemTypeMng* itm = m_mesh->itemTypeMng();
109 m_node_type = itm->typeFromId(IT_Vertex);
110 if (m_parent_family)
111 m_nodes_coords = nullptr;
112 else
113 m_nodes_coords = new VariableNodeReal3(VariableBuildInfo(mesh(), "NodeCoord"));
114
115 m_face_family = ARCANE_CHECK_POINTER(dynamic_cast<FaceFamily*>(mesh()->faceFamily()));
116 m_edge_family = ARCANE_CHECK_POINTER(dynamic_cast<EdgeFamily*>(mesh()->edgeFamily()));
117
118 if (m_mesh->useMeshItemFamilyDependencies()) // temporary to fill legacy, even with family dependencies
119 {
120 m_edge_connectivity = dynamic_cast<NewWithLegacyConnectivityType<NodeFamily, EdgeFamily>::type*>(m_mesh->itemFamilyNetwork()->getConnectivity(this, mesh()->edgeFamily(), connectivityName(this, mesh()->edgeFamily())));
121 m_face_connectivity = dynamic_cast<NewWithLegacyConnectivityType<NodeFamily, FaceFamily>::type*>(m_mesh->itemFamilyNetwork()->getConnectivity(this, m_face_family, connectivityName(this, mesh()->faceFamily())));
122 m_cell_connectivity = dynamic_cast<NewWithLegacyConnectivityType<NodeFamily, CellFamily>::type*>(m_mesh->itemFamilyNetwork()->getConnectivity(this, mesh()->cellFamily(), connectivityName(this, mesh()->cellFamily())));
123 }
124 else {
125 m_edge_connectivity = new EdgeConnectivity(this, mesh()->edgeFamily(), "NodeEdge");
126 m_face_connectivity = new FaceConnectivity(this, m_face_family, "NodeFace");
127 m_cell_connectivity = new CellConnectivity(this, mesh()->cellFamily(), "NodeCell");
128 }
129 m_hparent_connectivity = new HParentConnectivity(this, this, "HParentNode");
130 m_hchild_connectivity = new HChildConnectivity(this, this, "HChildNode");
131
132 _addConnectivitySelector(m_edge_connectivity);
133 _addConnectivitySelector(m_face_connectivity);
134 _addConnectivitySelector(m_cell_connectivity);
135 _addConnectivitySelector(m_hparent_connectivity);
136 _addConnectivitySelector(m_hchild_connectivity);
137
138 _buildConnectivitySelectors();
139}
140
141/*---------------------------------------------------------------------------*/
142/*---------------------------------------------------------------------------*/
143
144void NodeFamily::
145preAllocate(Integer nb_item)
146{
147 this->_preAllocate(nb_item, true);
148}
149
150/*---------------------------------------------------------------------------*/
151/*---------------------------------------------------------------------------*/
152
154edgeConnectivity() const
155{
156 return m_edge_connectivity->trueCustomConnectivity();
157}
158
159/*---------------------------------------------------------------------------*/
160/*---------------------------------------------------------------------------*/
161
162IncrementalItemConnectivity* NodeFamily::
163cellConnectivity() const
164{
165 return m_cell_connectivity->trueCustomConnectivity();
166}
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
171IncrementalItemConnectivity* NodeFamily::
172faceConnectivity() const
173{
174 return m_face_connectivity->trueCustomConnectivity();
175}
176
177/*---------------------------------------------------------------------------*/
178/*---------------------------------------------------------------------------*/
179
182{
183 m_item_internal_list->nodes = _itemsInternal();
184 _allocateInfosBulk(uids, m_node_type, owner, lids);
185 m_item_internal_list->nodes = _itemsInternal();
186}
187
188/*---------------------------------------------------------------------------*/
189/*---------------------------------------------------------------------------*/
190
191void NodeFamily::
192_endAllocate()
193{
194 if (m_nodes_coords)
195 m_nodes_coords->setUsed(true);
196 ItemFamily::_endAllocate();
197}
198
199/*---------------------------------------------------------------------------*/
200/*---------------------------------------------------------------------------*/
201
202void NodeFamily::
203addCellToNode(Node node, Cell new_cell)
204{
205 _checkValidSourceTargetItems(node, new_cell);
206 Int32 cell_lid = new_cell.localId();
207 m_cell_connectivity->addConnectedItem(ItemLocalId(node), ItemLocalId(cell_lid));
208}
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
213void NodeFamily::
214addFaceToNode(Node node, Face new_face)
215{
216 if (m_no_face_connectivity)
217 return;
218
219 _checkValidSourceTargetItems(node, new_face);
220 m_face_connectivity->addConnectedItem(ItemLocalId(node), ItemLocalId(new_face));
221}
222
223/*---------------------------------------------------------------------------*/
224/*---------------------------------------------------------------------------*/
225
226void NodeFamily::
227addEdgeToNode(Node node, Edge new_edge)
228{
229 if (!Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_NodeToEdge))
230 return;
231
232 _checkValidSourceTargetItems(node, new_edge);
233 m_edge_connectivity->addConnectedItem(ItemLocalId(node), ItemLocalId(new_edge));
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
238
239void NodeFamily::
240removeEdgeFromNode(ItemLocalId node, ItemLocalId edge_to_remove)
241{
242 if (!Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_NodeToEdge))
243 return;
244 m_edge_connectivity->removeConnectedItem(node, edge_to_remove);
245}
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250void NodeFamily::
251removeFaceFromNode(ItemLocalId node, ItemLocalId face_to_remove)
252{
253 if (m_no_face_connectivity)
254 return;
255
256 m_face_connectivity->removeConnectedItem(node, face_to_remove);
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
262void NodeFamily::
263removeCellFromNode(Node node, ItemLocalId cell_to_remove_lid)
264{
265 _checkValidItem(node);
266 m_cell_connectivity->removeConnectedItem(ItemLocalId(node), cell_to_remove_lid);
267}
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
271
274{
275 _checkValidItem(node);
276 if (!node.itemBase().isSuppressed()) {
277 Integer nb_cell = node.nbCell();
278 if (nb_cell == 0)
279 _removeNode(node);
280 }
281}
282
283/*---------------------------------------------------------------------------*/
284/*---------------------------------------------------------------------------*/
285
288{
289 debug() << "Creating the ghosts nodes list";
291}
292
293/*---------------------------------------------------------------------------*/
294/*---------------------------------------------------------------------------*/
295
296inline void NodeFamily::
297_removeNode(Node node)
298{
299 _removeOne(node);
300 // Do not remove other relationships here (edge->node, face->node)
301 // Because the order of deletion must always be cell, face, edge, node
302 // so node is last and everything is already done
303 // Furthermore, this avoids recursion problems
304}
305
306/*---------------------------------------------------------------------------*/
307/*---------------------------------------------------------------------------*/
308
315{
316 m_cell_connectivity->replaceItem(node, index, cell);
317}
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
327{
328 m_edge_connectivity->replaceItem(node, index, edge);
329}
330
331/*---------------------------------------------------------------------------*/
332/*---------------------------------------------------------------------------*/
339{
340 m_face_connectivity->replaceItem(node, index, face);
341}
342
343/*---------------------------------------------------------------------------*/
344/*---------------------------------------------------------------------------*/
345
348{
349 m_mesh_connectivity = c;
350 if (Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_HasEdge))
351 m_edge_prealloc = Connectivity::getPrealloc(m_mesh_connectivity, IK_Node, IK_Edge);
352 m_face_prealloc = Connectivity::getPrealloc(m_mesh_connectivity, IK_Node, IK_Face);
353 m_cell_prealloc = Connectivity::getPrealloc(m_mesh_connectivity, IK_Node, IK_Cell);
354 m_face_connectivity->setPreAllocatedSize(m_face_prealloc);
355 m_cell_connectivity->setPreAllocatedSize(m_cell_prealloc);
356 debug() << "Family " << name() << " prealloc "
357 << m_edge_prealloc << " by edge, "
358 << m_face_prealloc << " by face, "
359 << m_cell_prealloc << " by cell.";
360 m_no_face_connectivity = !Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_NodeToFace);
361}
362
363/*---------------------------------------------------------------------------*/
364/*---------------------------------------------------------------------------*/
365
367{
368 public:
369
370 explicit ItemCompare2(const ItemInfoListView& items)
371 : m_items(items)
372 {
373 }
374
375 public:
376
377 bool operator()(Int32 item1, Int32 item2) const
378 {
379 return m_items.uniqueId(item1) < m_items.uniqueId(item2);
380 }
381
382 private:
383
384 ItemInfoListView m_items;
385};
386
387/*---------------------------------------------------------------------------*/
388/*---------------------------------------------------------------------------*/
389
391{
392 public:
393
394 explicit ItemCompare3(ITraceMng* msg)
395 : m_msg(msg)
396 {}
397
398 public:
399
400 ITraceMng* m_msg;
401 ItemInternalArrayView m_items;
402
403 public:
404
405 bool operator()(Integer item1, Integer item2) const
406 {
407 m_msg->info() << "** Compare ptr=" << m_items.data()
408 << " i1=" << item1 << " i2=" << item2
409 << " i1=" << m_items[item1] << " i2=" << m_items[item2]
410 << " uid1=" << m_items[item1]->uniqueId()
411 << " uid2=" << m_items[item2]->uniqueId();
412 return m_items[item1]->uniqueId() < m_items[item2]->uniqueId();
413 }
414};
415
416/*---------------------------------------------------------------------------*/
417/*---------------------------------------------------------------------------*/
418
419void NodeFamily::
420_sortConnectedItems(IItemFamily* family, IncrementalItemConnectivity* connectivity)
421{
422 if (!connectivity)
423 return;
424
425 // Sort the entities connected to nodes by increasing uniqueId().
426 // This is useful to guarantee a traversal order of these entities
427 // that is identical regardless of the decomposition and thus improves
428 // reproducibility.
429 ItemInfoListView items_infos(family->itemInfoListView());
430 ItemCompare2 ic_items(items_infos);
431 ENUMERATE_ITEM (iitem, allItems()) {
432 ItemLocalId lid(iitem.itemLocalId());
433 Int32ArrayView conn_lids = connectivity->_connectedItemsLocalId(lid);
434 std::sort(std::begin(conn_lids), std::end(conn_lids), ic_items);
435 }
436}
437
438/*---------------------------------------------------------------------------*/
439/*---------------------------------------------------------------------------*/
440
441void NodeFamily::
442sortInternalReferences()
443{
444 // Sort the cells connected to nodes by increasing uniqueId().
445 _sortConnectedItems(mesh()->cellFamily(), m_cell_connectivity->trueCustomConnectivity());
446
447 // Do the same for faces and edges.
448 // For historical reasons, this is not active by default.
449 bool do_sort = properties()->getBoolWithDefault("sort-connected-faces-edges", m_is_sort_connected_faces_and_edges);
450 if (do_sort) {
451 info(4) << "Sorting connected faces and edges family=" << fullName();
452 _sortConnectedItems(m_face_family, m_face_connectivity->trueCustomConnectivity());
453 if (Connectivity::hasConnectivity(m_mesh_connectivity, Connectivity::CT_NodeToEdge))
454 _sortConnectedItems(mesh()->edgeFamily(), m_edge_connectivity->trueCustomConnectivity());
455 }
456}
457
458/*---------------------------------------------------------------------------*/
459/*---------------------------------------------------------------------------*/
460
463{
465 // If the uniqueId() of nodes change, this can influence
466 // the orientation of faces and edges. These must therefore be reoriented
467 m_face_family->reorientFacesIfNeeded();
468 m_edge_family->reorientEdgesIfNeeded();
469}
470
471/*---------------------------------------------------------------------------*/
472/*---------------------------------------------------------------------------*/
473
474void NodeFamily::
475_addParentNodeToNode(Node parent_node, Node child_node)
476{
477 m_hparent_connectivity->addConnectedItem(ItemLocalId(child_node), ItemLocalId(parent_node));
478}
479
480/*---------------------------------------------------------------------------*/
481/*---------------------------------------------------------------------------*/
482
483void NodeFamily::
484_addChildNodeToNode(Node parent_node, Node child_node)
485{
486 m_hchild_connectivity->addConnectedItem(ItemLocalId(parent_node), ItemLocalId(child_node));
487}
488
489/*---------------------------------------------------------------------------*/
490/*---------------------------------------------------------------------------*/
491
492} // End namespace Arcane::mesh
493
494/*---------------------------------------------------------------------------*/
495/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
Cell of a mesh.
Definition Item.h:1300
Template class for converting a type.
Interface of an entity family.
Definition IItemFamily.h:85
virtual TraceMessage info()=0
Stream for an information message.
bool isSuppressed() const
True if the entity is suppressed.
View of a list to obtain information about entities.
Index of an Item in a variable.
Definition ItemLocalId.h:42
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
impl::ItemBase itemBase() const
Internal part of the entity.
Definition Item.h:383
Node of a mesh.
Definition Item.h:598
Int32 nbCell() const
Number of cells connected to the node.
Definition Item.h:701
bool getBoolWithDefault(const String &name, bool default_value) const
Value of the property named name.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
IMesh * mesh() const override
Associated mesh.
String fullName() const override
Full family name (with the mesh's name).
Definition ItemFamily.h:141
ItemGroup allItems() const override
Group of all entities.
void notifyItemsUniqueIdChanged() override
Notifies that the unique IDs of the entities have been modified.
void computeSynchronizeInfos() override
Constructs the structures necessary for synchronization.
void _allocateInfosBulk(Int64ConstArrayView uids, ItemTypeInfo *type, Int32 owner, Int32ArrayView lids)
Allocates every item of uids at once.
Properties * properties() override
Properties associated with this family.
Definition ItemFamily.h:285
String name() const override
Family name.
Definition ItemFamily.h:140
void replaceCell(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
Replaces a cell of an entity.
Definition NodeFamily.cc:67
void replaceFace(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
Replaces a face of an entity.
Definition NodeFamily.cc:63
void replaceEdge(ItemLocalId item_lid, Integer index, ItemLocalId new_lid) override
Replaces an edge of an entity.
Definition NodeFamily.cc:59
void computeSynchronizeInfos() override
Constructs the structures necessary for synchronization.
void replaceCell(ItemLocalId node, Integer index, ItemLocalId cell)
Replaces the cell index index of the node node with that of localId() node_lid.
void removeNodeIfNotConnected(Node node)
Removes the node if it is no longer connected.
void replaceFace(ItemLocalId node, Integer index, ItemLocalId face)
Replaces the face index index of the node node with that of localId() face_lid.
void notifyItemsUniqueIdChanged() override
Notifies that the unique IDs of the entities have been modified.
void setConnectivity(const Integer c)
Sets the active connectivity for the associated mesh.
void replaceEdge(ItemLocalId node, Integer index, ItemLocalId edge)
Replaces the edge index index of the node node with that of localId() face_lid.
void allocateItemsBulk(Int64ConstArrayView uids, Int32 owner, Int32ArrayView lids)
Allocates every node of uids at once, in one pass per family array.
ItemTypeInfo * m_node_type
Instance containing the node type.
Definition NodeFamily.h:156
bool m_is_sort_connected_faces_and_edges
Indicates if connected faces and edges are sorted by nodes.
Definition NodeFamily.h:172
IncrementalItemConnectivity * edgeConnectivity() const
The true connectivity behind the selector, for a bulk fill.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
Int32 Integer
Type representing an integer.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:474
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:447
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Face
Face mesh entity.
@ IK_Edge
Edge mesh entity.
std::int32_t Int32
Signed integer type of 32 bits.