Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
CartesianFaceUniqueIdBuilder.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/* CartesianFaceUniqueIdBuilder.cc (C) 2000-2024 */
9/* */
10/* Construction of unique face IDs in cartesian coordinates. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/DynamicMesh.h"
15
16#include "arcane/core/ICartesianMeshGenerationInfo.h"
17#include "arcane/core/IParallelMng.h"
18#include "arcane/core/CartesianGridDimension.h"
19
20#include "arcane/mesh/ItemInternalMap.h"
21
22#include <array>
23
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
26
27namespace Arcane::mesh
28{
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
36: public TraceAccessor
37{
38 public:
39
42
43 public:
44
46
47 private:
48
49 DynamicMesh* m_mesh = nullptr;
50 IParallelMng* m_parallel_mng = nullptr;
51 bool m_is_verbose = false;
52};
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
60, m_mesh(mesh)
61, m_parallel_mng(mesh->parallelMng())
62{
63}
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68/*---------------------------------------------------------------------------*/
69/*---------------------------------------------------------------------------*/
81{
82 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, false);
83 if (!cmgi)
84 ARCANE_FATAL("No 'ICartesianMeshGenerationInfo'. The mesh is not a cartesian mesh "
85 "or was not generated by 'CartesianMeshGenerator'");
86
87 Integer dimension = m_mesh->dimension();
88 if (dimension != 2 && dimension != 3)
89 ARCANE_THROW(NotSupportedException, "Bad value '{0}' for dimension. Only dimensions 2 or 3 are supported",
90 dimension);
91 Int32 my_rank = m_mesh->parallelMng()->commRank();
92
93 Int64ConstArrayView global_nb_cells = cmgi->globalNbCells();
94 info() << "Dim=" << dimension;
95
96 CartesianGridDimension grid_dimension(global_nb_cells[0], global_nb_cells[1], global_nb_cells[2]);
97 Int64x3 nb_cell = grid_dimension.nbCell();
98 Int64x3 nb_face = grid_dimension.nbFace();
99 Int64x3 nb_face_dir = grid_dimension.nbFaceParallelToDirection();
100
101 Int64 nb_cell_xy = nb_cell.x * nb_cell.y;
102
103 Int64 face_offset_z = nb_face_dir.x + nb_face_dir.y;
104 Int64 nb_face_xyz = face_offset_z + nb_cell_xy;
105 Int64 total_nb_face_xy = (nb_face_dir.x + nb_face_dir.y) * nb_cell.z;
106 Int64 total_nb_face_x = (nb_face_dir.x * nb_cell.z);
107
108 info() << "NB_Cell: X=" << nb_cell.x << " Y=" << nb_cell.y << " Z=" << nb_cell.z
109 << " XY=" << nb_cell_xy;
110 info() << "NB_Face: X=" << nb_face.x << " Y=" << nb_face.y << " Z=" << nb_face.z
111 << " NbDirX=" << nb_face_dir.x << " NbDirY=" << nb_face_dir.y << " NbDirZ=" << nb_face_dir.z
112 << " NbFaceXYZ=" << nb_face_xyz << " OffsetZ=" << face_offset_z
113 << " TotalNbFaceX=" << total_nb_face_x << " TotalNbFaceXY=" << total_nb_face_xy;
114
115 auto own_cells_offsets = cmgi->ownCellOffsets();
116 Int64 own_cell_offset_x = own_cells_offsets[0];
117 Int64 own_cell_offset_y = own_cells_offsets[1];
118 Int64 own_cell_offset_z = own_cells_offsets[2];
119 info() << "CellOffset: X=" << own_cell_offset_x << " Y=" << own_cell_offset_y << " Z=" << own_cell_offset_z;
120
121 auto sub_domain_offsets = cmgi->subDomainOffsets();
122 Int64 sub_domain_offset_x = sub_domain_offsets[0];
123 Int64 sub_domain_offset_y = sub_domain_offsets[1];
124 Int64 sub_domain_offset_z = sub_domain_offsets[2];
125 info() << "SubDomainOffset: X=" << sub_domain_offset_x << " Y=" << sub_domain_offset_y << " Z=" << sub_domain_offset_z;
126
127 auto nb_sub_domains = cmgi->nbSubDomains();
128 Int32 nb_sub_domain_x = nb_sub_domains[0];
129 Int32 nb_sub_domain_y = nb_sub_domains[1];
130 Int32 nb_sub_domain_z = nb_sub_domains[2];
131 info() << "NbSubDomain: X=" << nb_sub_domain_x << " Y=" << nb_sub_domain_y << " Z=" << nb_sub_domain_z;
132
133 // Determines the lower rank in each direction
134 Int32 previous_rank_x = my_rank;
135 Int32 previous_rank_y = my_rank;
136 Int32 previous_rank_z = my_rank;
137
138 ItemInternalMap& cells_map = m_mesh->cellsMap();
139 bool is_verbose = m_is_verbose;
140
141 if (dimension == 2) {
142 if (sub_domain_offset_x > 0)
143 previous_rank_x = my_rank - 1;
144 if (sub_domain_offset_y > 0)
145 previous_rank_y = my_rank - nb_sub_domain_x;
146 info() << "PreviousRank X=" << previous_rank_x << " Y=" << previous_rank_y;
147 CartesianGridDimension::CellUniqueIdComputer2D cell_uid_computer(0, nb_cell.x);
148 CartesianGridDimension::FaceUniqueIdComputer2D face_uid_computer(grid_dimension.getFaceComputer2D(0));
149
150 // The cells are quadrangles
151 std::array<Int64, 4> face_uids;
152 std::array<Int64, 4> face_uids2;
153 cells_map.eachItem([&](Cell cell) {
154 // Retrieves the index (I,J) of the cell
155 Int64 uid = cell.uniqueId();
156 const Int64 y2 = uid / nb_cell.x;
157 const Int64 x2 = uid % nb_cell.x;
158 Int64x3 xyz = cell_uid_computer.compute(uid);
159 Int64 x = xyz.x;
160 Int64 y = xyz.y;
161 // For test. To be removed later
162 if (x != x2)
163 ARCANE_FATAL("Bad X {0} {1}", x, x2);
164 if (y != y2)
165 ARCANE_FATAL("Bad Y {0} {1}", y, y2);
166 if (is_verbose)
167 info() << "CELL (UID=" << uid << ",XY=" << x << "," << y << ") "
168 << " N0=" << cell.node(0).uniqueId()
169 << " N1=" << cell.node(1).uniqueId()
170 << " N2=" << cell.node(2).uniqueId()
171 << " N3=" << cell.node(3).uniqueId();
172 // For test. To be removed later and keep the one from face_uid_computer.
173 // Faces according to Y
174 face_uids[0] = (x + 0) + ((y + 0) * nb_cell.x) + nb_face_dir.x;
175 face_uids[2] = (x + 0) + ((y + 1) * nb_cell.x) + nb_face_dir.x;
176
177 // Faces according to X
178 face_uids[1] = (x + 1) + (y + 0) * nb_face.x;
179 face_uids[3] = (x + 0) + (y + 0) * nb_face.x;
180 face_uids2 = face_uid_computer.computeForCell(x, y);
181 for (int i = 0; i < 4; ++i) {
182 if (face_uids[i] != face_uids2[i])
183 ARCANE_FATAL("Bad face uid i={0} ref={1} new={2}", i, face_uids[i], face_uids2[i]);
184 }
185 for (int i = 0; i < 4; ++i) {
186 Face face = cell.face(i);
187 if (is_verbose)
188 info() << "CELL=" << uid << " Face=" << i << " uid=" << face_uids[i]
189 << " N0=" << face.node(0).uniqueId()
190 << " N1=" << face.node(1).uniqueId();
191
192 face.mutableItemBase().setUniqueId(face_uids[i]);
193 }
194 // Positions the owner of the lower face in X
195 if (x == own_cell_offset_x && previous_rank_x != my_rank)
196 cell.face(3).mutableItemBase().setOwner(previous_rank_x, my_rank);
197 // Positions the owner of the lower face in Y
198 if (y == own_cell_offset_y && previous_rank_y != my_rank)
199 cell.face(0).mutableItemBase().setOwner(previous_rank_y, my_rank);
200 });
201 }
202 else if (dimension == 3) {
203 if (sub_domain_offset_x > 0)
204 previous_rank_x = my_rank - 1;
205 if (sub_domain_offset_y > 0)
206 previous_rank_y = my_rank - nb_sub_domain_x;
207 if (sub_domain_offset_z > 0)
208 previous_rank_z = my_rank - (nb_sub_domain_x * nb_sub_domain_y);
209 info() << "PreviousRank X=" << previous_rank_x << " Y=" << previous_rank_y << " Z=" << previous_rank_z;
210 CartesianGridDimension::CellUniqueIdComputer3D cell_uid_computer(0, nb_cell.x, nb_cell_xy);
211 CartesianGridDimension::FaceUniqueIdComputer3D face_uid_computer(grid_dimension.getFaceComputer3D(0));
212 // The cells are hexahedrons
213 std::array<Int64, 6> face_uids;
214 std::array<Int64, 6> face_uids2;
215 cells_map.eachItem([&](Cell cell) {
216 // Retrieves the index (I,J) of the cell
217 Int64 uid = cell.uniqueId();
218 Int64 z2 = uid / nb_cell_xy;
219 Int64 v2 = uid - (z2 * nb_cell_xy);
220 Int64 y2 = v2 / nb_cell.x;
221 Int64 x2 = v2 % nb_cell.x;
222 Int64x3 xyz = cell_uid_computer.compute(uid);
223 Int64 x = xyz.x;
224 Int64 y = xyz.y;
225 Int64 z = xyz.z;
226 // For test. To be removed later
227 if (x != x2)
228 ARCANE_FATAL("Bad X {0} {1}", x, x2);
229 if (y != y2)
230 ARCANE_FATAL("Bad Y {0} {1}", y, y2);
231 if (z != z2)
232 ARCANE_FATAL("Bad Z {0} {1}", z, z2);
233 if (is_verbose)
234 info() << "CELL (UID=" << uid << ",XYZ=" << x << "," << y << "," << z << ") "
235 << " N0=" << cell.node(0).uniqueId()
236 << " N1=" << cell.node(1).uniqueId()
237 << " N2=" << cell.node(2).uniqueId()
238 << " N3=" << cell.node(3).uniqueId()
239 << " N4=" << cell.node(4).uniqueId()
240 << " N5=" << cell.node(5).uniqueId()
241 << " N6=" << cell.node(6).uniqueId()
242 << " N7=" << cell.node(7).uniqueId();
243
244 // For test. To be removed later and keep the one from face_uid_computer.
245 // Faces according to Z
246 face_uids[0] = (x + 0) + ((y + 0) * nb_cell.x) + ((z + 0) * nb_face_dir.z) + total_nb_face_xy;
247 face_uids[3] = (x + 0) + ((y + 0) * nb_cell.x) + ((z + 1) * nb_face_dir.z) + total_nb_face_xy;
248
249 // Faces according to X
250 face_uids[1] = (x + 0) + ((y + 0) * nb_face.x) + ((z + 0) * nb_face_dir.x);
251 face_uids[4] = (x + 1) + ((y + 0) * nb_face.x) + ((z + 0) * nb_face_dir.x);
252
253 // Faces according to Y
254 face_uids[2] = (x + 0) + ((y + 0) * nb_cell.x) + ((z + 0) * nb_face_dir.y) + total_nb_face_x;
255 face_uids[5] = (x + 0) + ((y + 1) * nb_cell.x) + ((z + 0) * nb_face_dir.y) + total_nb_face_x;
256
257 face_uids2 = face_uid_computer.computeForCell(x, y, z);
258 for (int i = 0; i < 6; ++i) {
259 if (face_uids[i] != face_uids2[i])
260 ARCANE_FATAL("Bad face uid i={0} ref={1} new={2}", i, face_uids[i], face_uids2[i]);
261 }
262
263 for (int i = 0; i < 6; ++i) {
264 Face face = cell.face(i);
265 if (is_verbose)
266 info() << "CELL=" << uid << " Face=" << i << " uid=" << face_uids[i]
267 << " N0=" << face.node(0).uniqueId()
268 << " N1=" << face.node(1).uniqueId()
269 << " N2=" << face.node(2).uniqueId()
270 << " N3=" << face.node(3).uniqueId();
271 face.mutableItemBase().setUniqueId(face_uids[i]);
272 }
273
274 // Positions the owner of the lower face in X
275 if (x == own_cell_offset_x && previous_rank_x != my_rank)
276 cell.face(1).mutableItemBase().setOwner(previous_rank_x, my_rank);
277 // Positions the owner of the lower face in Y
278 if (y == own_cell_offset_y && previous_rank_y != my_rank)
279 cell.face(2).mutableItemBase().setOwner(previous_rank_y, my_rank);
280 // Positions the owner of the lower face in Z
281 if (z == own_cell_offset_z && previous_rank_z != my_rank)
282 cell.face(0).mutableItemBase().setOwner(previous_rank_z, my_rank);
283 });
284 }
285 else
286 ARCANE_FATAL("Invalid dimension");
287}
288
289/*---------------------------------------------------------------------------*/
290/*---------------------------------------------------------------------------*/
291
292extern "C++" void
293arcaneComputeCartesianFaceUniqueId(DynamicMesh* mesh)
294{
296 f.computeFacesUniqueIdAndOwner();
297}
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
301
302} // End namespace Arcane::mesh
303
304/*---------------------------------------------------------------------------*/
305/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Class for calculating the uniqueId() of a cell in 2D based on its position in the grid.
Class for calculating the uniqueId() of a cell in 3D based on its position in the grid.
Int64 compute(Int64 x, Int64 y, Int64 z)
Calculates the uniqueId() based on coordinates.
Class for calculating the uniqueId() of a face in 2D based on its position in the grid.
std::array< Int64, 4 > computeForCell(Int64 x, Int64 y)
Calculates the uniqueIds() of the 4 faces of the topological coordinate cell (x,y).
Class for calculating the uniqueId() of a face in 2D based on its position in the grid.
std::array< Int64, 6 > computeForCell(Int64 x, Int64 y, Int64 z)
Calculates the uniqueIds() of the 6 faces of the topological coordinate cell (x,y,...
Information about the dimensions of a Cartesian grid.
constexpr Int64x3 nbCell() const
Number of cells in each direction.
FaceUniqueIdComputer3D getFaceComputer3D(Int64 offset) const
Instance to calculate the uniqueIds() of faces for this grid.
constexpr Int64x3 nbFace() const
Number of faces in each direction.
constexpr Int64x3 nbFaceParallelToDirection() const
Total number of faces parallel to a given direction.
FaceUniqueIdComputer2D getFaceComputer2D(Int64 offset) const
Instance to calculate the uniqueIds() of faces for this grid.
Cell of a mesh.
Definition Item.h:1300
Face face(Int32 i) const
i-th face of the cell
Definition Item.h:1400
Face of a cell.
Definition Item.h:1032
Interface of the parallelism manager for a subdomain.
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
Construction of uniqueId() for faces in a cartesian mesh.
CartesianFaceUniqueIdBuilder(DynamicMesh *mesh)
Constructs an instance for the mesh mesh.
void computeFacesUniqueIdAndOwner()
Calculates the uniqueIds() and owners.
Implementation of a mesh.
Definition DynamicMesh.h:98
Associative array of ItemInternal.
void eachItem(const Lambda &lambda)
Template function to iterate over the instance's entities.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
std::int32_t Int32
Signed integer type of 32 bits.