Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
NodesOfItemReorderer.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/* NodesOfItemReorderer.cc (C) 2000-2025 */
9/* */
10/* Utility class for reordering the nodes of an entity. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/NodesOfItemReorderer.h"
15
16#include "arcane/utils/NotImplementedException.h"
17
18#include "arcane/core/ItemTypeId.h"
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Arcane
25{
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30// TODO: merge with the order 1 version
31// Only implemented for edges
32bool NodesOfItemReorderer::
33_reorderOrder3(ConstArrayView<Int64> nodes_uid,
34 ArrayView<Int64> sorted_nodes_uid,
35 [[maybe_unused]] bool has_center_node)
36{
37 // \a true if faces need to be reoriented so that their orientation
38 // is independent of the initial mesh partitioning.
39
40 Int32 nb_node = nodes_uid.size();
41
42 // Only handles the case of order 3 edges, which therefore have 4 nodes
43 if (nb_node != 4)
44 ARCANE_THROW(NotImplementedException, "Node reordering for 2D type of order 3 or more");
45
46 if (nodes_uid[0] < nodes_uid[1]) {
47 // Nothing to do
48 sorted_nodes_uid[0] = nodes_uid[0];
49 sorted_nodes_uid[1] = nodes_uid[1];
50 sorted_nodes_uid[2] = nodes_uid[2];
51 sorted_nodes_uid[3] = nodes_uid[3];
52 return false;
53 }
54 sorted_nodes_uid[0] = nodes_uid[1];
55 sorted_nodes_uid[1] = nodes_uid[0];
56 sorted_nodes_uid[2] = nodes_uid[3];
57 sorted_nodes_uid[3] = nodes_uid[2];
58 return true;
59}
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
64// TODO: merge with the order 1 version
65bool NodesOfItemReorderer::
66_reorderOrder2(ConstArrayView<Int64> nodes_uid,
67 ArrayView<Int64> sorted_nodes_uid, bool has_center_node)
68{
69 // \a true if faces need to be reoriented so that their orientation
70 // is independent of the initial mesh partitioning.
71 bool need_swap_orientation = false;
72 Int32 min_node_index = 0;
73
74 Int32 nb_node = nodes_uid.size();
75
76 // Directly handles the case of order 2 edges
77 if (nb_node == 3) {
78 if (nodes_uid[0] < nodes_uid[1]) {
79 sorted_nodes_uid[0] = nodes_uid[0];
80 sorted_nodes_uid[1] = nodes_uid[1];
81 sorted_nodes_uid[2] = nodes_uid[2];
82 return false;
83 }
84 sorted_nodes_uid[0] = nodes_uid[1];
85 sorted_nodes_uid[1] = nodes_uid[0];
86 sorted_nodes_uid[2] = nodes_uid[2];
87 return true;
88 }
89 // If there is a center node, it is the last node in the list
90 // and it should not be sorted
91 // NOTE: In this case, the number of nodes in the entity is odd.
92 if (has_center_node)
93 sorted_nodes_uid[nb_node - 1] = nodes_uid[nb_node - 1];
94
95 // For order 2, if we have N nodes, we only need to test the first N/2 nodes
96 // TODO: use type information.
97 nb_node = nb_node / 2;
98
99 // The following algorithm orients the faces by taking into account only
100 // the order of the numbering of these nodes. If this order is
101 // preserved during partitioning, then the orientation of the faces
102 // will also be preserved.
103
104 // The algorithm is as follows:
105 // - Finds node n with the smallest index.
106 // - Finds n-1 and n+1, the indices of its 2 neighboring nodes.
107 // - If (n+1) is less than (n-1), the orientation n is not modified.
108 // - If (n+1) is greater than (n-1), the orientation is inverted.
109
110 // Finds the node with the smallest index
111
112 Int64 min_node = INT64_MAX;
113 for (Integer k = 0; k < nb_node; ++k) {
114 Int64 id = nodes_uid[k];
115 if (id < min_node) {
116 min_node = id;
117 min_node_index = k;
118 }
119 }
120 Int64 next_node = nodes_uid[(min_node_index + 1) % nb_node];
121 Int64 prev_node = nodes_uid[(min_node_index + (nb_node - 1)) % nb_node];
122 Integer incr = 0;
123 Integer incr2 = 0;
124 // Tests the case where the previous or next nodes
125 // are the same as the node with the smallest uniqueId().
126 // (in this case, the entity is semi-degenerate)
127 {
128 if (next_node == min_node) {
129 next_node = nodes_uid[(min_node_index + (nb_node + 2)) % nb_node];
130 incr = 1;
131 }
132 if (prev_node == min_node) {
133 prev_node = nodes_uid[(min_node_index + (nb_node - 2)) % nb_node];
134 incr2 = nb_node - 1;
135 }
136 }
137 if (next_node > prev_node)
138 need_swap_orientation = true;
139 if (need_swap_orientation) {
140 for (Integer k = 0; k < nb_node; ++k) {
141 Integer index = (nb_node - k + min_node_index + incr) % nb_node;
142 Int32 index2 = ((2 * nb_node - 1) + incr + min_node_index - k) % nb_node;
143 sorted_nodes_uid[k] = nodes_uid[index];
144 sorted_nodes_uid[k + nb_node] = nodes_uid[index2 + nb_node];
145 }
146 }
147 else {
148 for (Integer k = 0; k < nb_node; ++k) {
149 Integer index = (k + min_node_index + incr2) % nb_node;
150 sorted_nodes_uid[k] = nodes_uid[index];
151 sorted_nodes_uid[k + nb_node] = nodes_uid[index + nb_node];
152 }
153 }
154 return need_swap_orientation;
155}
156
157/*---------------------------------------------------------------------------*/
158/*---------------------------------------------------------------------------*/
159
160bool NodesOfItemReorderer::
161reorder(ItemTypeId type_id, ConstArrayView<Int64> nodes_uids)
162{
163 ItemTypeInfo* iti = m_item_type_mng->typeFromId(type_id);
164 Int32 order = iti->order();
165 Int32 nb_node = nodes_uids.size();
166 m_work_sorted_nodes.resize(nb_node);
167 if (order > 3)
168 ARCANE_THROW(NotImplementedException, "Node reordering for type of order 4 or more");
169 if (order == 3)
170 return _reorderOrder3(nodes_uids, m_work_sorted_nodes, iti->hasCenterNode());
171 if (order == 2)
172 return _reorderOrder2(nodes_uids, m_work_sorted_nodes, iti->hasCenterNode());
173 return MeshUtils::reorderNodesOfFace(nodes_uids, m_work_sorted_nodes);
174}
175
176/*---------------------------------------------------------------------------*/
177/*---------------------------------------------------------------------------*/
178
179} // End namespace Arcane
180
181/*---------------------------------------------------------------------------*/
182/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
Utility functions for the mesh.
Modifiable view of an array of type T.
Constant view of an array of type T.
Type of an entity (Item).
Definition ItemTypeId.h:33
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
std::int32_t Int32
Signed integer type of 32 bits.