Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
CartesianMeshPatch.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/* CartesianMeshPatch.cc (C) 2000-2026 */
9/* */
10/* Information about an AMR patch of a Cartesian mesh. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/cartesianmesh/internal/CartesianMeshPatch.h"
15
16#include "arcane/core/IMesh.h"
17#include "arcane/core/ItemPrinter.h"
18
19#include "arcane/cartesianmesh/ICartesianMesh.h"
20#include "arcane/cartesianmesh/CartesianConnectivity.h"
21
22#include <set>
23
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
26
27namespace Arcane
28{
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33CartesianMeshPatch::
34CartesianMeshPatch(ICartesianMesh* cmesh, Integer patch_index, const AMRPatchPosition& position)
35: TraceAccessor(cmesh->traceMng())
36, m_mesh(cmesh)
37, m_position(position)
38, m_amr_patch_index(patch_index)
39, m_impl(this)
40{
41 Integer nb_dir = cmesh->mesh()->dimension();
42 for (Integer i = 0; i < nb_dir; ++i) {
43 eMeshDirection dir = static_cast<eMeshDirection>(i);
44 m_cell_directions[i]._internalInit(cmesh, dir, patch_index);
45 m_face_directions[i]._internalInit(cmesh, dir, patch_index);
46 m_node_directions[i]._internalInit(cmesh, dir, patch_index);
47 }
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53CartesianMeshPatch::
54CartesianMeshPatch(ICartesianMesh* cmesh, Integer patch_index)
55: CartesianMeshPatch(cmesh, patch_index, {})
56{
57}
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62CartesianMeshPatch::
63~CartesianMeshPatch()
64{
65 for (Integer i = 0; i < 3; ++i) {
66 m_cell_directions[i]._internalDestroy();
67 m_face_directions[i]._internalDestroy();
68 m_node_directions[i]._internalDestroy();
69 }
70}
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77
78CellGroup CartesianMeshPatch::
79cells()
80{
81 // The cell group of the patch is the same in all directions.
82 return cellDirection(MD_DirX).allCells();
83}
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88CellGroup CartesianMeshPatch::
89inPatchCells()
90{
91 return cellDirection(MD_DirX).inPatchCells();
92}
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
97CellGroup CartesianMeshPatch::
98overlapCells()
99{
100 return cellDirection(MD_DirX).overlapCells();
101}
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
106/*
107 * \brief Calculates the information about the before/after and left/right nodes of a cell
108 * for each direction.
109 */
110void CartesianMeshPatch::
111_computeNodeCellInformations2D(Cell cell0, Real3 cell0_coord, VariableNodeReal3& nodes_coord)
112{
113 using Int8 = std::int8_t;
114 Int8 nodes_indirection_i[CellDirectionMng::MAX_NB_NODE];
115 ArrayView<Int8> nodes_indirection(CellDirectionMng::MAX_NB_NODE, nodes_indirection_i);
116 Int32 nb_node = cell0.nbNode();
117 if (nb_node != 4)
118 ARCANE_FATAL("Number of nodes should be '4' (v={0})", nb_node);
119 Int8 i8_nb_node = 4;
120 Real3 cell_coord = cell0_coord;
121 bool is_2d = m_mesh->mesh()->dimension() == 2;
122 if (!is_2d)
123 ARCANE_FATAL("Invalid call. This mesh is not a 2D mesh");
124
125 // Direction X
126 nodes_indirection.fill(-1);
127 for (Int8 i = 0; i < i8_nb_node; ++i) {
128 Node node = cell0.node(i);
129 Real3 node_coord = nodes_coord[node];
130 if (node_coord.x > cell_coord.x) {
131 if (node_coord.y > cell_coord.y)
132 nodes_indirection[CNP_NextLeft] = i;
133 else
134 nodes_indirection[CNP_NextRight] = i;
135 }
136 else {
137 if (node_coord.y > cell_coord.y)
138 nodes_indirection[CNP_PreviousLeft] = i;
139 else
140 nodes_indirection[CNP_PreviousRight] = i;
141 }
142 }
143 cellDirection(MD_DirX).setNodesIndirection(nodes_indirection);
144
145 // Direction Y
146 nodes_indirection.fill(-1);
147 for (Int8 i = 0; i < i8_nb_node; ++i) {
148 Node node = cell0.node(i);
149 Real3 node_coord = nodes_coord[node];
150 if (node_coord.y > cell_coord.y) {
151 if (node_coord.x > cell_coord.x)
152 nodes_indirection[CNP_NextRight] = i;
153 else
154 nodes_indirection[CNP_NextLeft] = i;
155 }
156 else {
157 if (node_coord.x > cell_coord.x)
158 nodes_indirection[CNP_PreviousRight] = i;
159 else
160 nodes_indirection[CNP_PreviousLeft] = i;
161 }
162 }
163 cellDirection(MD_DirY).setNodesIndirection(nodes_indirection);
164}
165
166/*---------------------------------------------------------------------------*/
167/*---------------------------------------------------------------------------*/
168/*
169 * \brief Calculates the information about the before/after and left/right nodes of a cell
170 * for each direction.
171 */
172void CartesianMeshPatch::
173_computeNodeCellInformations3D(Cell cell0, Real3 cell0_coord, VariableNodeReal3& nodes_coord)
174{
175 using Int8 = std::int8_t;
176 Int8 nodes_indirection_i[CellDirectionMng::MAX_NB_NODE];
177 ArrayView<Int8> nodes_indirection(CellDirectionMng::MAX_NB_NODE, nodes_indirection_i);
178 Integer nb_node = cell0.nbNode();
179 if (nb_node != 8)
180 ARCANE_FATAL("Number of nodes should be '8' (v={0})", nb_node);
181 Int8 i8_nb_node = 8;
182 Real3 cell_coord = cell0_coord;
183 bool is_3d = m_mesh->mesh()->dimension() == 3;
184 if (!is_3d)
185 ARCANE_FATAL("Invalid call. This mesh is not a 3D mesh");
186
187 // Direction X
188 nodes_indirection.fill(-1);
189 for (Int8 i = 0; i < i8_nb_node; ++i) {
190 Node node = cell0.node(i);
191 Real3 node_coord = nodes_coord[node];
192 if (node_coord.z > cell_coord.z) {
193 if (node_coord.x > cell_coord.x) {
194 if (node_coord.y > cell_coord.y)
195 nodes_indirection[CNP_TopNextLeft] = i;
196 else
197 nodes_indirection[CNP_TopNextRight] = i;
198 }
199 else {
200 if (node_coord.y > cell_coord.y)
201 nodes_indirection[CNP_TopPreviousLeft] = i;
202 else
203 nodes_indirection[CNP_TopPreviousRight] = i;
204 }
205 }
206 else {
207 if (node_coord.x > cell_coord.x) {
208 if (node_coord.y > cell_coord.y)
209 nodes_indirection[CNP_NextLeft] = i;
210 else
211 nodes_indirection[CNP_NextRight] = i;
212 }
213 else {
214 if (node_coord.y > cell_coord.y)
215 nodes_indirection[CNP_PreviousLeft] = i;
216 else
217 nodes_indirection[CNP_PreviousRight] = i;
218 }
219 }
220 }
221 cellDirection(MD_DirX).setNodesIndirection(nodes_indirection);
222
223 // Direction Y
224 nodes_indirection.fill(-1);
225 for (Int8 i = 0; i < i8_nb_node; ++i) {
226 Node node = cell0.node(i);
227 Real3 node_coord = nodes_coord[node];
228 if (node_coord.z > cell_coord.z) {
229 if (node_coord.y > cell_coord.y) {
230 if (node_coord.x > cell_coord.x)
231 nodes_indirection[CNP_TopNextRight] = i;
232 else
233 nodes_indirection[CNP_TopNextLeft] = i;
234 }
235 else {
236 if (node_coord.x > cell_coord.x)
237 nodes_indirection[CNP_TopPreviousRight] = i;
238 else
239 nodes_indirection[CNP_TopPreviousLeft] = i;
240 }
241 }
242 else {
243 if (node_coord.y > cell_coord.y) {
244 if (node_coord.x > cell_coord.x)
245 nodes_indirection[CNP_NextRight] = i;
246 else
247 nodes_indirection[CNP_NextLeft] = i;
248 }
249 else {
250 if (node_coord.x > cell_coord.x)
251 nodes_indirection[CNP_PreviousRight] = i;
252 else
253 nodes_indirection[CNP_PreviousLeft] = i;
254 }
255 }
256 }
257 cellDirection(MD_DirY).setNodesIndirection(nodes_indirection);
258
259 nodes_indirection.fill(-1);
260 for (Int8 i = 0; i < i8_nb_node; ++i) {
261 Node node = cell0.node(i);
262 Real3 node_coord = nodes_coord[node];
263 if (node_coord.y > cell_coord.y) {
264 if (node_coord.z > cell_coord.z) {
265 if (node_coord.x > cell_coord.x)
266 nodes_indirection[CNP_TopNextRight] = i;
267 else
268 nodes_indirection[CNP_TopNextLeft] = i;
269 }
270 else {
271 if (node_coord.x > cell_coord.x)
272 nodes_indirection[CNP_TopPreviousRight] = i;
273 else
274 nodes_indirection[CNP_TopPreviousLeft] = i;
275 }
276 }
277 else {
278 if (node_coord.z > cell_coord.z) {
279 if (node_coord.x > cell_coord.x)
280 nodes_indirection[CNP_NextRight] = i;
281 else
282 nodes_indirection[CNP_NextLeft] = i;
283 }
284 else {
285 if (node_coord.x > cell_coord.x)
286 nodes_indirection[CNP_PreviousRight] = i;
287 else
288 nodes_indirection[CNP_PreviousLeft] = i;
289 }
290 }
291 }
292 cellDirection(MD_DirZ).setNodesIndirection(nodes_indirection);
293}
294
295/*---------------------------------------------------------------------------*/
296/*---------------------------------------------------------------------------*/
297
298void CartesianMeshPatch::
299_internalComputeNodeCellInformations(Cell cell0, Real3 cell0_coord, VariableNodeReal3& nodes_coord)
300{
301 int dim = m_mesh->mesh()->dimension();
302 if (dim == 3)
303 _computeNodeCellInformations3D(cell0, cell0_coord, nodes_coord);
304 else if (dim == 2)
305 _computeNodeCellInformations2D(cell0, cell0_coord, nodes_coord);
306 else
307 ARCANE_THROW(NotImplementedException, "this method is implemented only for 2D and 3D mesh (dim={0})", dim);
308}
309
310/*---------------------------------------------------------------------------*/
311/*---------------------------------------------------------------------------*/
312
313void CartesianMeshPatch::
314_internalComputeNodeCellInformations()
315{
316 int dim = m_mesh->mesh()->dimension();
317 Int8 nodes_indirection[CellDirectionMng::MAX_NB_NODE];
318 ArrayView av_nodes_indirection(CellDirectionMng::MAX_NB_NODE, nodes_indirection);
319 // DirX (Top->Z=1 / Previous->X=0 / Next->X=1 / Right->Y=0 / Left->Y=1)
320 av_nodes_indirection.fill(-1);
321 av_nodes_indirection[CNP_NextLeft] = 2;
322 av_nodes_indirection[CNP_NextRight] = 1;
323 av_nodes_indirection[CNP_PreviousRight] = 0;
324 av_nodes_indirection[CNP_PreviousLeft] = 3;
325 if (dim == 3) {
326 av_nodes_indirection[CNP_TopNextLeft] = 6;
327 av_nodes_indirection[CNP_TopNextRight] = 5;
328 av_nodes_indirection[CNP_TopPreviousRight] = 4;
329 av_nodes_indirection[CNP_TopPreviousLeft] = 7;
330 }
331 cellDirection(MD_DirX).setNodesIndirection(av_nodes_indirection);
332
333 // DirY (Top->Z=1 / Previous->Y=0 / Next->Y=1 / Right->X=1 / Left->X=0)
334 av_nodes_indirection.fill(-1);
335 av_nodes_indirection[CNP_NextLeft] = 3;
336 av_nodes_indirection[CNP_NextRight] = 2;
337 av_nodes_indirection[CNP_PreviousRight] = 1;
338 av_nodes_indirection[CNP_PreviousLeft] = 0;
339 if (dim == 3) {
340 av_nodes_indirection[CNP_TopNextLeft] = 7;
341 av_nodes_indirection[CNP_TopNextRight] = 6;
342 av_nodes_indirection[CNP_TopPreviousRight] = 5;
343 av_nodes_indirection[CNP_TopPreviousLeft] = 4;
344 }
345 cellDirection(MD_DirY).setNodesIndirection(av_nodes_indirection);
346
347 if (dim == 3) {
348 // DirZ (Top->Y=1 / Previous->Z=0 / Next->Z=1 / Right->X=1 / Left->X=0)
349 av_nodes_indirection.fill(-1);
350 av_nodes_indirection[CNP_NextLeft] = 4;
351 av_nodes_indirection[CNP_NextRight] = 5;
352 av_nodes_indirection[CNP_PreviousRight] = 1;
353 av_nodes_indirection[CNP_PreviousLeft] = 0;
354 av_nodes_indirection[CNP_TopNextLeft] = 7;
355 av_nodes_indirection[CNP_TopNextRight] = 6;
356 av_nodes_indirection[CNP_TopPreviousRight] = 2;
357 av_nodes_indirection[CNP_TopPreviousLeft] = 3;
358 cellDirection(MD_DirZ).setNodesIndirection(av_nodes_indirection);
359 }
360}
361
362/*---------------------------------------------------------------------------*/
363/*---------------------------------------------------------------------------*/
364
365void CartesianMeshPatch::
366checkValid() const
367{
368 // Checks that all before/after cells belong to the direction cell group
369 Integer nb_dir = m_mesh->mesh()->dimension();
370 for (Integer i = 0; i < nb_dir; ++i) {
371 CellDirectionMng dm = m_cell_directions[i];
372 FaceDirectionMng face_dm = m_face_directions[i];
373 std::set<Int32> cells_ids;
374 CellGroup dm_cells = dm.allCells();
375 info(4) << "PATCH i=" << m_amr_patch_index << " nb_cell=" << dm_cells.size();
376 ENUMERATE_CELL (icell, dm_cells) {
377 cells_ids.insert(icell.itemLocalId());
378 }
379 Int64 nb_null_face_cell = 0;
380 ENUMERATE_CELL (icell, dm_cells) {
381 Cell cell = *icell;
382 DirCell cc(dm.cell(cell));
383 Cell next_cell = cc.next();
384 if (!next_cell.null()) {
385 if (cells_ids.find(next_cell.localId()) == cells_ids.end())
386 ARCANE_FATAL("Bad next cell dir={0} cell={1} next={2}", i, ItemPrinter(cell), ItemPrinter(next_cell));
387 }
388 Cell previous_cell = cc.previous();
389 if (!previous_cell.null()) {
390 if (cells_ids.find(previous_cell.localId()) == cells_ids.end())
391 ARCANE_FATAL("Bad previous cell dir={0} cell={1} previous={2}", i, ItemPrinter(cell), ItemPrinter(previous_cell));
392 }
393 // Check if face infos are valid
394
395 DirCellFace cell_face(dm.cellFace(cell));
396 Face prev_face = cell_face.previous();
397 Face next_face = cell_face.next();
398 DirFace dir_face_prev(face_dm[prev_face]);
399 Cell face_cell_prev = dir_face_prev.previousCell();
400 if (face_cell_prev.null())
401 ++nb_null_face_cell;
402 DirFace dir_face_next(face_dm[next_face]);
403 Cell face_cell_next = dir_face_next.nextCell();
404 if (face_cell_next.null())
405 ++nb_null_face_cell;
406 }
407 info(4) << "PATCH i=" << m_amr_patch_index << " nb_null_face_cell=" << nb_null_face_cell;
408 }
409}
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
413
414} // End namespace Arcane
415
416/*---------------------------------------------------------------------------*/
417/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
Class allowing the definition of a patch position in the Cartesian mesh.
CellDirectionMng & cellDirection(eMeshDirection dir) override
List of cells in direction dir.
Info about the cells in a specific X, Y, or Z direction of a structured mesh.
CellGroup allCells() const
Group of all cells in the direction.
DirCellFace cellFace(Cell c) const
cell with directional info at faces corresponding to cell c.
DirCell cell(Cell c) const
Directional cell corresponding to cell c.
Cell of a mesh.
Definition Item.h:1300
Cell with directional face information.
Face next() const
Face connected to the cell after the current cell in the direction.
Face previous() const
Face connected to the cell before the current cell in the direction.
Cell before and after a cell along a direction.
Info on the cell before and after a face along a direction.
Cell previousCell() const
Previous cell.
Info on the faces of a specific direction X, Y, or Z of a structured mesh.
Face of a cell.
Definition Item.h:1032
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
constexpr bool null() const
true if the entity is null (i.e. not connected to the mesh)
Definition Item.h:230
TraceMessage info() const
Flow for an information message.
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int8_t Int8
Signed integer type of 8 bits.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
eMeshDirection
Direction type for a structured mesh.
@ MD_DirX
X Direction.