Arcane  v4.1.3.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
FaceDirectionMng.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/* FaceDirectionMng.cc (C) 2000-2026 */
9/* */
10/* Infos sur les faces d'une direction X Y ou Z d'un maillage structuré. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/cartesianmesh/FaceDirectionMng.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/Real3.h"
18#include "arcane/utils/PlatformUtils.h"
19
20#include "arcane/core/IItemFamily.h"
21#include "arcane/core/ItemGroup.h"
22#include "arcane/core/IMesh.h"
23#include "arcane/core/VariableTypes.h"
24
25#include "arcane/cartesianmesh/ICartesianMesh.h"
26#include "arcane/cartesianmesh/CellDirectionMng.h"
27#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
28
29#include <set>
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34namespace Arcane
35{
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
41{
42 public:
43 Impl() : m_infos(platform::getDefaultDataAllocator()){}
44 public:
45 FaceGroup m_inner_all_items;
46 FaceGroup m_outer_all_items;
47 FaceGroup m_inpatch_all_items;
48 FaceGroup m_overlap_all_items;
49 FaceGroup m_all_items;
50 ICartesianMesh* m_cartesian_mesh = nullptr;
51 Integer m_patch_index = -1;
53};
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
57
60: m_direction(MD_DirInvalid)
61, m_p (nullptr)
62{
63}
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68void FaceDirectionMng::
69_internalInit(ICartesianMesh* cm,eMeshDirection dir,Integer patch_index)
70{
71 if (m_p)
72 ARCANE_FATAL("Initialisation already done");
73 m_p = new Impl();
74 m_direction = dir;
75 m_p->m_cartesian_mesh = cm;
76 m_p->m_patch_index = patch_index;
77}
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
82void FaceDirectionMng::
83_internalDestroy()
84{
85 delete m_p;
86 m_p = nullptr;
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
91
92void FaceDirectionMng::
93_internalResizeInfos(Int32 new_size)
94{
95 m_p->m_infos.resize(new_size);
96 m_infos_view = m_p->m_infos.view();
97}
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102void FaceDirectionMng::
103_internalComputeInfos(const CellDirectionMng& cell_dm,const VariableCellReal3& cells_center,
104 const VariableFaceReal3& faces_center)
105{
106 IMesh* mesh = m_p->m_cartesian_mesh->mesh();
107 IItemFamily* face_family = mesh->faceFamily();
108 IItemFamily* cell_family = mesh->cellFamily();
109 int dir = (int)m_direction;
110 String base_group_name = String("Direction")+dir;
111 if (m_p->m_patch_index>=0)
112 base_group_name = base_group_name + String("AMRPatch")+m_p->m_patch_index;
113
114 // Calcule la liste des faces dans une direction donnée.
115 // Il faut pour chaque maille ajouter dans la liste des faces
116 // les deux faces de la direction souhaitées en prenant bien soin
117 // de ne pas ajouter deux fois la même face.
118 UniqueArray<Int32> faces_lid;
119 {
120 CellGroup all_cells = cell_dm.allCells();
121 faces_lid.reserve(all_cells.size());
122 // Ensemble des faces déjà ajoutées
123 std::set<Int32> done_faces;
124 ENUMERATE_CELL(icell,all_cells){
125 DirCellFace dcf(cell_dm.cellFace(*icell));
126 Face next_face = dcf.next();
127 Face prev_face = dcf.previous();
128
129 //! Ajoute la face d'avant à la liste des faces de cette direction
130 Int32 prev_lid = prev_face.localId();
131 if (done_faces.find(prev_lid)==done_faces.end()){
132 faces_lid.add(prev_lid);
133 done_faces.insert(prev_lid);
134 }
135 Int32 next_lid = next_face.localId();
136 if (done_faces.find(next_lid)==done_faces.end()){
137 faces_lid.add(next_lid);
138 done_faces.insert(next_lid);
139 }
140 }
141 }
142
143 FaceGroup all_faces = face_family->createGroup(String("AllFaces")+base_group_name,Int32ConstArrayView(),true);
144 all_faces.setItems(faces_lid,true);
145
146 UniqueArray<Int32> inner_lids;
147 UniqueArray<Int32> outer_lids;
148 ENUMERATE_FACE (iitem, all_faces) {
149 Int32 lid = iitem.itemLocalId();
150 Face face = *iitem;
151 // TODO: ne pas utiser nbCell() mais faire cela via le std::set utilisé précédemment
152 if (face.nbCell() == 1)
153 outer_lids.add(lid);
154 else
155 inner_lids.add(lid);
156 }
157 m_p->m_inner_all_items = face_family->createGroup(String("AllInner")+base_group_name,inner_lids,true);
158 m_p->m_outer_all_items = face_family->createGroup(String("AllOuter")+base_group_name,outer_lids,true);
159 m_p->m_all_items = all_faces;
160 m_cells = CellInfoListView(cell_family);
161
162 _computeCellInfos(cell_dm,cells_center,faces_center);
163}
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
167
168void FaceDirectionMng::
169_internalComputeInfos(const CellDirectionMng& cell_dm)
170{
171 IMesh* mesh = m_p->m_cartesian_mesh->mesh();
172 IItemFamily* face_family = mesh->faceFamily();
173 IItemFamily* cell_family = mesh->cellFamily();
174 int dir = (int)m_direction;
175 String base_group_name = String("Direction") + dir;
176 if (m_p->m_patch_index >= 0)
177 base_group_name = base_group_name + String("AMRPatch") + m_p->m_patch_index;
178
179 // Calcule la liste des faces dans une direction donnée.
180 // Il faut pour chaque maille ajouter dans la liste des faces
181 // les deux faces de la direction souhaitées en prenant bien soin
182 // de ne pas ajouter deux fois la même face.
183 UniqueArray<Int32> faces_lid;
184 {
185 CellGroup all_cells = cell_dm.allCells();
186 faces_lid.reserve(all_cells.size());
187 // Ensemble des faces déjà ajoutées
188 std::set<Int32> done_faces;
189 ENUMERATE_ (Cell, icell, all_cells) {
190 DirCellFace dcf(cell_dm.cellFace(*icell));
191 Face next_face = dcf.next();
192 Face prev_face = dcf.previous();
193
194 //! Ajoute la face d'avant à la liste des faces de cette direction
195 Int32 prev_lid = prev_face.localId();
196 if (done_faces.find(prev_lid) == done_faces.end()) {
197 faces_lid.add(prev_lid);
198 done_faces.insert(prev_lid);
199 }
200 Int32 next_lid = next_face.localId();
201 if (done_faces.find(next_lid) == done_faces.end()) {
202 faces_lid.add(next_lid);
203 done_faces.insert(next_lid);
204 }
205 }
206 }
207
208 FaceGroup all_faces = face_family->createGroup(String("AllFaces") + base_group_name, Int32ConstArrayView(), true);
209 all_faces.setItems(faces_lid, true);
210
211 UniqueArray<Int32> inner_cells_lid;
212 UniqueArray<Int32> outer_cells_lid;
213 cell_dm.innerCells().view().fillLocalIds(inner_cells_lid);
214 cell_dm.outerCells().view().fillLocalIds(outer_cells_lid);
215
216 UniqueArray<Int32> inner_lids;
217 UniqueArray<Int32> outer_lids;
218 UniqueArray<Int32> inpatch_lids;
219 UniqueArray<Int32> overlap_lids;
220 ENUMERATE_ (Face, iface, all_faces) {
221 Int32 lid = iface.itemLocalId();
222 Face face = *iface;
223 if (face.nbCell() == 1) {
224 if (inner_cells_lid.contains(face.cell(0).localId())) {
225 inner_lids.add(lid);
226 inpatch_lids.add(lid);
227 }
228 else if (outer_cells_lid.contains(face.cell(0).localId())) {
229 outer_lids.add(lid);
230 inpatch_lids.add(lid);
231 }
232 else {
233 overlap_lids.add(lid);
234 }
235 }
236 else {
237 bool c0_inner_cell = inner_cells_lid.contains(face.cell(0).localId());
238 bool c1_inner_cell = inner_cells_lid.contains(face.cell(1).localId());
239 if (c0_inner_cell || c1_inner_cell) {
240 inner_lids.add(lid);
241 inpatch_lids.add(lid);
242 }
243 else {
244 bool c0_outer_cell = outer_cells_lid.contains(face.cell(0).localId());
245 bool c1_outer_cell = outer_cells_lid.contains(face.cell(1).localId());
246 if (c0_outer_cell || c1_outer_cell) {
247 outer_lids.add(lid);
248 inpatch_lids.add(lid);
249 }
250 else {
251 overlap_lids.add(lid);
252 }
253 }
254 }
255 }
256 m_p->m_inner_all_items = face_family->createGroup(String("AllInner") + base_group_name, inner_lids, true);
257 m_p->m_outer_all_items = face_family->createGroup(String("AllOuter") + base_group_name, outer_lids, true);
258 m_p->m_inpatch_all_items = face_family->createGroup(String("AllInPatch") + base_group_name, inpatch_lids, true);
259 m_p->m_overlap_all_items = face_family->createGroup(String("AllOverlap") + base_group_name, overlap_lids, true);
260 m_p->m_all_items = all_faces;
261 m_cells = CellInfoListView(cell_family);
262
263 _computeCellInfos();
264}
265
266/*---------------------------------------------------------------------------*/
267/*---------------------------------------------------------------------------*/
268
269bool FaceDirectionMng::
270_hasFace(Cell cell,Int32 face_local_id) const
271{
272 for( FaceLocalId iface_lid : cell.faceIds() ){
273 if (iface_lid==face_local_id)
274 return true;
275 }
276 return false;
277}
278
279/*---------------------------------------------------------------------------*/
280/*---------------------------------------------------------------------------*/
281/*!
282 * \brief Calcule des mailles avant et après une face, dans une direction donnée.
283 *
284 * Pour être indépendant de la façon dont est créé le maillage, on utilise les coordonnées
285 * des centres des faces et des centres des mailles.
286 */
287void FaceDirectionMng::
288_computeCellInfos(const CellDirectionMng& cell_dm,const VariableCellReal3& cells_center,
289 const VariableFaceReal3& faces_center)
290{
291 eMeshDirection dir = m_direction;
292
293 // Créé l'ensemble des mailles du patch et s'en sert
294 // pour être sur que chaque maille devant/derrière est dans
295 // cet ensemble
296 std::set<Int32> patch_cells_set;
297 ENUMERATE_CELL(icell,cell_dm.allCells()){
298 patch_cells_set.insert(icell.itemLocalId());
299 }
300
301 ENUMERATE_FACE(iface,m_p->m_all_items){
302 Face face = *iface;
303 Int32 face_lid = iface.itemLocalId();
304 Real3 face_coord = faces_center[iface];
305 Cell front_cell = face.frontCell();
306 Cell back_cell = face.backCell();
307
308 // Vérifie que les mailles sont dans notre patch.
309 if (!front_cell.null())
310 if (patch_cells_set.find(front_cell.localId()) == patch_cells_set.end())
311 front_cell = Cell();
312 if (!back_cell.null())
313 if (patch_cells_set.find(back_cell.localId()) == patch_cells_set.end())
314 back_cell = Cell();
315
316 bool is_inverse = false;
317 if (!front_cell.null()){
318 Real3 front_coord = cells_center[front_cell];
319 if (dir==MD_DirX){
320 if (front_coord.x<face_coord.x)
321 is_inverse = true;
322 }
323 else if (dir==MD_DirY){
324 if (front_coord.y<face_coord.y)
325 is_inverse = true;
326 }
327 else if (dir==MD_DirZ){
328 if (front_coord.z<face_coord.z)
329 is_inverse = true;
330 }
331 }
332 else{
333 Real3 back_coord = cells_center[back_cell];
334 if (dir==MD_DirX){
335 if (back_coord.x>face_coord.x)
336 is_inverse = true;
337 }
338 else if (dir==MD_DirY){
339 if (back_coord.y>face_coord.y)
340 is_inverse = true;
341 }
342 else if (dir==MD_DirZ){
343 if (back_coord.z>face_coord.z)
344 is_inverse = true;
345 }
346 }
347 // Si la face a deux mailles connectées, regarde le niveau AMR de ces
348 // deux mailles et s'il est différent, ne conserve que la maille
349 // dont le niveau AMR est celui de la face.
350 if (!back_cell.null() && !front_cell.null()){
351 Int32 back_level = back_cell.level();
352 Int32 front_level = front_cell.level();
353 if (back_level!=front_level){
354 // La face n'a pas l'information de son niveau mais si les deux
355 // mailles ne sont pas de même niveau la face n'appartient qu'à une
356 // seule des deux mailles. On ne garde donc que cette dernière.
357 if (!_hasFace(back_cell,face_lid))
358 back_cell = Cell();
359 if (!_hasFace(front_cell,face_lid))
360 front_cell = Cell();
361 }
362 }
363 if (is_inverse)
364 m_infos_view[face_lid] = ItemDirectionInfo(back_cell, front_cell);
365 else
366 m_infos_view[face_lid] = ItemDirectionInfo(front_cell, back_cell);
367 }
368}
369
370/*---------------------------------------------------------------------------*/
371/*---------------------------------------------------------------------------*/
372
373void FaceDirectionMng::
374_computeCellInfos() const
375{
376 Ref<ICartesianMeshNumberingMngInternal> numbering = m_p->m_cartesian_mesh->_internalApi()->cartesianMeshNumberingMngInternal();
377 eMeshDirection dir = m_direction;
378 // ITraceMng* tm = m_p->m_cartesian_mesh->traceMng();
379
380 ENUMERATE_ (Face, iface, m_p->m_all_items) {
381 Face face = *iface;
382 Cell front_cell = face.frontCell();
383 Cell back_cell = face.backCell();
384 // tm->info() << "FaceUID : " << face.uniqueId()
385 // << " -- backCellUID : " << back_cell.uniqueId()
386 // << " -- backCellLevel : " << back_cell.level()
387 // << " -- frontCellUID : " << front_cell.uniqueId()
388 // << " -- frontCellLevel : " << front_cell.level()
389 // << " -- dir : " << dir;
390 bool is_inverse = false;
391 if (!front_cell.null() && !back_cell.null()) {
392
393 // Si la face a deux mailles connectées, regarde le niveau AMR de ces
394 // deux mailles et s'il est différent, ne conserve que la maille
395 // dont le niveau AMR est celui de la face.
396 Int32 front_cell_level = front_cell.level();
397 Int32 back_cell_level = back_cell.level();
398 if (front_cell_level != back_cell_level) {
399 Int32 face_level = numbering->faceLevel(face.uniqueId());
400 if (front_cell_level != face_level) {
401 front_cell = Cell();
402 }
403 else {
404 back_cell = Cell();
405 }
406 }
407
408 if (back_cell.uniqueId() > front_cell.uniqueId()) {
409 is_inverse = true;
410 }
411 }
412 // L'ordre de la numérotation est décrit dans le fichier
413 // CartesianMeshAMRPatchMng.cc (tag #priority_owner_2d).
414 if (back_cell.null()) {
415 Int64 uids[6];
416 ArrayView av_uids(numbering->nbFaceByCell(), uids);
417 numbering->cellFaceUniqueIds(front_cell, av_uids);
418 if (m_p->m_cartesian_mesh->mesh()->dimension() == 2) {
419 if (dir == MD_DirX) {
420 if (face.uniqueId() == av_uids[1])
421 is_inverse = true;
422 else if (face.uniqueId() != av_uids[3])
423 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[3], face.uniqueId());
424 }
425 else if (dir == MD_DirY) {
426 if (face.uniqueId() == av_uids[2])
427 is_inverse = true;
428 else if (face.uniqueId() != av_uids[0])
429 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[0], face.uniqueId());
430 }
431 }
432 else if (m_p->m_cartesian_mesh->mesh()->dimension() == 3) {
433 if (dir == MD_DirX) {
434 if (face.uniqueId() == av_uids[4])
435 is_inverse = true;
436 else if (face.uniqueId() != av_uids[1])
437 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[1], face.uniqueId());
438 }
439 else if (dir == MD_DirY) {
440 if (face.uniqueId() == av_uids[5])
441 is_inverse = true;
442 else if (face.uniqueId() != av_uids[2])
443 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[2], face.uniqueId());
444 }
445 else if (dir == MD_DirZ) {
446 if (face.uniqueId() == av_uids[3])
447 is_inverse = true;
448 else if (face.uniqueId() != av_uids[0])
449 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[0], face.uniqueId());
450 }
451 }
452 }
453 else if (front_cell.null()) {
454 Int64 uids[6];
455 ArrayView av_uids(numbering->nbFaceByCell(), uids);
456 numbering->cellFaceUniqueIds(back_cell, av_uids);
457 if (m_p->m_cartesian_mesh->mesh()->dimension() == 2) {
458 if (dir == MD_DirX) {
459 if (face.uniqueId() == av_uids[3])
460 is_inverse = true;
461 else if (face.uniqueId() != av_uids[1])
462 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[1], face.uniqueId());
463 }
464 else if (dir == MD_DirY) {
465 if (face.uniqueId() == av_uids[0])
466 is_inverse = true;
467 else if (face.uniqueId() != av_uids[2])
468 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[2], face.uniqueId());
469 }
470 }
471 else if (m_p->m_cartesian_mesh->mesh()->dimension() == 3) {
472 if (dir == MD_DirX) {
473 if (face.uniqueId() == av_uids[1])
474 is_inverse = true;
475 else if (face.uniqueId() != av_uids[4])
476 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[4], face.uniqueId());
477 }
478 else if (dir == MD_DirY) {
479 if (face.uniqueId() == av_uids[2])
480 is_inverse = true;
481 else if (face.uniqueId() != av_uids[5])
482 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[5], face.uniqueId());
483 }
484 else if (dir == MD_DirZ) {
485 if (face.uniqueId() == av_uids[0])
486 is_inverse = true;
487 else if (face.uniqueId() != av_uids[3])
488 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[3], face.uniqueId());
489 }
490 }
491 }
492 // tm->info() << "FaceUID : " << face.uniqueId()
493 // << " -- backCellUID : " << back_cell.uniqueId()
494 // << " -- frontCellUID : " << front_cell.uniqueId()
495 // << " -- is_inverse : " << is_inverse
496 // << " -- dir : " << dir;
497
498 if (is_inverse)
499 m_infos_view[iface.itemLocalId()] = ItemDirectionInfo(back_cell, front_cell);
500 else
501 m_infos_view[iface.itemLocalId()] = ItemDirectionInfo(front_cell, back_cell);
502 }
503}
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
509allFaces() const
510{
511 return m_p->m_all_items;
512}
513
514/*---------------------------------------------------------------------------*/
515/*---------------------------------------------------------------------------*/
516
518overlapFaces() const
519{
520 return m_p->m_overlap_all_items;
521}
522
523/*---------------------------------------------------------------------------*/
524/*---------------------------------------------------------------------------*/
525
527inPatchFaces() const
528{
529 return m_p->m_inpatch_all_items;
530}
531
532/*---------------------------------------------------------------------------*/
533/*---------------------------------------------------------------------------*/
534
536innerFaces() const
537{
538 return m_p->m_inner_all_items;
539}
540
541/*---------------------------------------------------------------------------*/
542/*---------------------------------------------------------------------------*/
543
545outerFaces() const
546{
547 return m_p->m_outer_all_items;
548}
549
550/*---------------------------------------------------------------------------*/
551/*---------------------------------------------------------------------------*/
552
553} // End namespace Arcane
554
555/*---------------------------------------------------------------------------*/
556/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
Infos sur les mailles d'une direction spécifique X,Y ou Z d'un maillage structuré.
Maille d'un maillage.
Definition Item.h:1214
FaceGroup inPatchFaces() const
Groupe de toutes les faces du patch dans la direction.
DirFace face(Face f) const
Face direction correspondant à la face f.
FaceGroup overlapFaces() const
Groupe de toutes les faces de recouvrement dans la direction.
FaceDirectionMng()
Créé une instance vide.
FaceGroup innerFaces() const
Groupe de toutes les faces internes dans la direction.
FaceGroup outerFaces() const
Groupe de toutes les faces externes dans la direction.
FaceGroup allFaces() const
Groupe de toutes les faces dans la direction.
Interface d'un maillage cartésien.
void setItems(Int32ConstArrayView items_local_id)
Positionne les entités du groupe.
Definition ItemGroup.cc:489
Vecteur 1D de données avec sémantique par valeur (style STL).
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
MeshVariableScalarRefT< Cell, Real3 > VariableCellReal3
Grandeur au centre des mailles de type coordonnées.
MeshVariableScalarRefT< Face, Real3 > VariableFaceReal3
Grandeur aux faces de type coordonnées.
IMemoryAllocator * getDefaultDataAllocator()
Allocateur par défaut pour les données.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:482
eMeshDirection
Type de la direction pour un maillage structuré
@ MD_DirInvalid
Direction invalide ou non initialisée.
@ MD_DirZ
Direction Z.
@ MD_DirY
Direction Y.
@ MD_DirX
Direction X.
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52
std::int32_t Int32
Type entier signé sur 32 bits.