Arcane  4.1.12.0
User 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.
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
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.
Int32 Integer
Type representing an integer.
eMeshDirection
Direction type for a structured mesh.
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53