Arcane  v4.1.1.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-2025 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-2025 */
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_overall_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> overall_lids;
220 ENUMERATE_ (Face, iface, all_faces) {
221 Int32 lid = iface.itemLocalId();
222 Face face = *iface;
223 if (face.nbCell() == 1) {
224 if (outer_cells_lid.contains(face.cell(0).localId())) {
225 outer_lids.add(lid);
226 inpatch_lids.add(lid);
227 }
228 else {
229 overall_lids.add(lid);
230 }
231 }
232 else {
233 bool c0_inner_cell = inner_cells_lid.contains(face.cell(0).localId());
234 bool c1_inner_cell = inner_cells_lid.contains(face.cell(1).localId());
235 if (c0_inner_cell || c1_inner_cell) {
236 inner_lids.add(lid);
237 inpatch_lids.add(lid);
238 }
239 else {
240 bool c0_outer_cell = outer_cells_lid.contains(face.cell(0).localId());
241 bool c1_outer_cell = outer_cells_lid.contains(face.cell(1).localId());
242 if (c0_outer_cell || c1_outer_cell) {
243 outer_lids.add(lid);
244 inpatch_lids.add(lid);
245 }
246 else {
247 overall_lids.add(lid);
248 }
249 }
250 }
251 }
252 m_p->m_inner_all_items = face_family->createGroup(String("AllInner") + base_group_name, inner_lids, true);
253 m_p->m_outer_all_items = face_family->createGroup(String("AllOuter") + base_group_name, outer_lids, true);
254 m_p->m_inpatch_all_items = face_family->createGroup(String("AllInPatch") + base_group_name, inpatch_lids, true);
255 m_p->m_overall_all_items = face_family->createGroup(String("AllOverall") + base_group_name, overall_lids, true);
256 m_p->m_all_items = all_faces;
257 m_cells = CellInfoListView(cell_family);
258
259 _computeCellInfos();
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265bool FaceDirectionMng::
266_hasFace(Cell cell,Int32 face_local_id) const
267{
268 for( FaceLocalId iface_lid : cell.faceIds() ){
269 if (iface_lid==face_local_id)
270 return true;
271 }
272 return false;
273}
274
275/*---------------------------------------------------------------------------*/
276/*---------------------------------------------------------------------------*/
277/*!
278 * \brief Calcule des mailles avant et après une face, dans une direction donnée.
279 *
280 * Pour être indépendant de la façon dont est créé le maillage, on utilise les coordonnées
281 * des centres des faces et des centres des mailles.
282 */
283void FaceDirectionMng::
284_computeCellInfos(const CellDirectionMng& cell_dm,const VariableCellReal3& cells_center,
285 const VariableFaceReal3& faces_center)
286{
287 eMeshDirection dir = m_direction;
288
289 // Créé l'ensemble des mailles du patch et s'en sert
290 // pour être sur que chaque maille devant/derrière est dans
291 // cet ensemble
292 std::set<Int32> patch_cells_set;
293 ENUMERATE_CELL(icell,cell_dm.allCells()){
294 patch_cells_set.insert(icell.itemLocalId());
295 }
296
297 ENUMERATE_FACE(iface,m_p->m_all_items){
298 Face face = *iface;
299 Int32 face_lid = iface.itemLocalId();
300 Real3 face_coord = faces_center[iface];
301 Cell front_cell = face.frontCell();
302 Cell back_cell = face.backCell();
303
304 // Vérifie que les mailles sont dans notre patch.
305 if (!front_cell.null())
306 if (patch_cells_set.find(front_cell.localId()) == patch_cells_set.end())
307 front_cell = Cell();
308 if (!back_cell.null())
309 if (patch_cells_set.find(back_cell.localId()) == patch_cells_set.end())
310 back_cell = Cell();
311
312 bool is_inverse = false;
313 if (!front_cell.null()){
314 Real3 front_coord = cells_center[front_cell];
315 if (dir==MD_DirX){
316 if (front_coord.x<face_coord.x)
317 is_inverse = true;
318 }
319 else if (dir==MD_DirY){
320 if (front_coord.y<face_coord.y)
321 is_inverse = true;
322 }
323 else if (dir==MD_DirZ){
324 if (front_coord.z<face_coord.z)
325 is_inverse = true;
326 }
327 }
328 else{
329 Real3 back_coord = cells_center[back_cell];
330 if (dir==MD_DirX){
331 if (back_coord.x>face_coord.x)
332 is_inverse = true;
333 }
334 else if (dir==MD_DirY){
335 if (back_coord.y>face_coord.y)
336 is_inverse = true;
337 }
338 else if (dir==MD_DirZ){
339 if (back_coord.z>face_coord.z)
340 is_inverse = true;
341 }
342 }
343 // Si la face a deux mailles connectées, regarde le niveau AMR de ces
344 // deux mailles et s'il est différent, ne conserve que la maille
345 // dont le niveau AMR est celui de la face.
346 if (!back_cell.null() && !front_cell.null()){
347 Int32 back_level = back_cell.level();
348 Int32 front_level = front_cell.level();
349 if (back_level!=front_level){
350 // La face n'a pas l'information de son niveau mais si les deux
351 // mailles ne sont pas de même niveau la face n'appartient qu'à une
352 // seule des deux mailles. On ne garde donc que cette dernière.
353 if (!_hasFace(back_cell,face_lid))
354 back_cell = Cell();
355 if (!_hasFace(front_cell,face_lid))
356 front_cell = Cell();
357 }
358 }
359 if (is_inverse)
360 m_infos_view[face_lid] = ItemDirectionInfo(back_cell, front_cell);
361 else
362 m_infos_view[face_lid] = ItemDirectionInfo(front_cell, back_cell);
363 }
364}
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
369void FaceDirectionMng::
370_computeCellInfos() const
371{
372 Ref<ICartesianMeshNumberingMngInternal> numbering = m_p->m_cartesian_mesh->_internalApi()->cartesianMeshNumberingMngInternal();
373 eMeshDirection dir = m_direction;
374 // ITraceMng* tm = m_p->m_cartesian_mesh->traceMng();
375
376 ENUMERATE_ (Face, iface, m_p->m_all_items) {
377 Face face = *iface;
378 Cell front_cell = face.frontCell();
379 Cell back_cell = face.backCell();
380 // tm->info() << "FaceUID : " << face.uniqueId()
381 // << " -- backCellUID : " << back_cell.uniqueId()
382 // << " -- backCellLevel : " << back_cell.level()
383 // << " -- frontCellUID : " << front_cell.uniqueId()
384 // << " -- frontCellLevel : " << front_cell.level()
385 // << " -- dir : " << dir;
386 bool is_inverse = false;
387 if (!front_cell.null() && !back_cell.null()) {
388
389 // Si la face a deux mailles connectées, regarde le niveau AMR de ces
390 // deux mailles et s'il est différent, ne conserve que la maille
391 // dont le niveau AMR est celui de la face.
392 Int32 front_cell_level = front_cell.level();
393 Int32 back_cell_level = back_cell.level();
394 if (front_cell_level != back_cell_level) {
395 Int32 face_level = numbering->faceLevel(face.uniqueId());
396 if (front_cell_level != face_level) {
397 front_cell = Cell();
398 }
399 else {
400 back_cell = Cell();
401 }
402 }
403
404 if (back_cell.uniqueId() > front_cell.uniqueId()) {
405 is_inverse = true;
406 }
407 }
408 // L'ordre de la numérotation est décrit dans le fichier
409 // CartesianMeshAMRPatchMng.cc (tag #priority_owner_2d).
410 if (back_cell.null()) {
411 Int64 uids[6];
412 ArrayView av_uids(numbering->nbFaceByCell(), uids);
413 numbering->cellFaceUniqueIds(av_uids, front_cell);
414 if (m_p->m_cartesian_mesh->mesh()->dimension() == 2) {
415 if (dir == MD_DirX) {
416 if (face.uniqueId() == av_uids[1])
417 is_inverse = true;
418 else if (face.uniqueId() != av_uids[3])
419 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[3], face.uniqueId());
420 }
421 else if (dir == MD_DirY) {
422 if (face.uniqueId() == av_uids[2])
423 is_inverse = true;
424 else if (face.uniqueId() != av_uids[0])
425 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[0], face.uniqueId());
426 }
427 }
428 else if (m_p->m_cartesian_mesh->mesh()->dimension() == 3) {
429 if (dir == MD_DirX) {
430 if (face.uniqueId() == av_uids[4])
431 is_inverse = true;
432 else if (face.uniqueId() != av_uids[1])
433 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[1], face.uniqueId());
434 }
435 else if (dir == MD_DirY) {
436 if (face.uniqueId() == av_uids[5])
437 is_inverse = true;
438 else if (face.uniqueId() != av_uids[2])
439 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[2], face.uniqueId());
440 }
441 else if (dir == MD_DirZ) {
442 if (face.uniqueId() == av_uids[3])
443 is_inverse = true;
444 else if (face.uniqueId() != av_uids[0])
445 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[0], face.uniqueId());
446 }
447 }
448 }
449 else if (front_cell.null()) {
450 Int64 uids[6];
451 ArrayView av_uids(numbering->nbFaceByCell(), uids);
452 numbering->cellFaceUniqueIds(av_uids, back_cell);
453 if (m_p->m_cartesian_mesh->mesh()->dimension() == 2) {
454 if (dir == MD_DirX) {
455 if (face.uniqueId() == av_uids[3])
456 is_inverse = true;
457 else if (face.uniqueId() != av_uids[1])
458 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[1], face.uniqueId());
459 }
460 else if (dir == MD_DirY) {
461 if (face.uniqueId() == av_uids[0])
462 is_inverse = true;
463 else if (face.uniqueId() != av_uids[2])
464 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[2], face.uniqueId());
465 }
466 }
467 else if (m_p->m_cartesian_mesh->mesh()->dimension() == 3) {
468 if (dir == MD_DirX) {
469 if (face.uniqueId() == av_uids[1])
470 is_inverse = true;
471 else if (face.uniqueId() != av_uids[4])
472 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[4], face.uniqueId());
473 }
474 else if (dir == MD_DirY) {
475 if (face.uniqueId() == av_uids[2])
476 is_inverse = true;
477 else if (face.uniqueId() != av_uids[5])
478 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[5], face.uniqueId());
479 }
480 else if (dir == MD_DirZ) {
481 if (face.uniqueId() == av_uids[0])
482 is_inverse = true;
483 else if (face.uniqueId() != av_uids[3])
484 ARCANE_FATAL("Bad connectivity -- Expected : {0} -- Found : {1}", av_uids[3], face.uniqueId());
485 }
486 }
487 }
488 // tm->info() << "FaceUID : " << face.uniqueId()
489 // << " -- backCellUID : " << back_cell.uniqueId()
490 // << " -- frontCellUID : " << front_cell.uniqueId()
491 // << " -- is_inverse : " << is_inverse
492 // << " -- dir : " << dir;
493
494 if (is_inverse)
495 m_infos_view[iface.itemLocalId()] = ItemDirectionInfo(back_cell, front_cell);
496 else
497 m_infos_view[iface.itemLocalId()] = ItemDirectionInfo(front_cell, back_cell);
498 }
499}
500
501/*---------------------------------------------------------------------------*/
502/*---------------------------------------------------------------------------*/
503
505allFaces() const
506{
507 return m_p->m_all_items;
508}
509
510/*---------------------------------------------------------------------------*/
511/*---------------------------------------------------------------------------*/
512
514overallFaces() const
515{
516 return m_p->m_overall_all_items;
517}
518
519/*---------------------------------------------------------------------------*/
520/*---------------------------------------------------------------------------*/
521
523inPatchFaces() const
524{
525 return m_p->m_inpatch_all_items;
526}
527
528/*---------------------------------------------------------------------------*/
529/*---------------------------------------------------------------------------*/
530
532innerFaces() const
533{
534 return m_p->m_inner_all_items;
535}
536
537/*---------------------------------------------------------------------------*/
538/*---------------------------------------------------------------------------*/
539
541outerFaces() const
542{
543 return m_p->m_outer_all_items;
544}
545
546/*---------------------------------------------------------------------------*/
547/*---------------------------------------------------------------------------*/
548
549} // End namespace Arcane
550
551/*---------------------------------------------------------------------------*/
552/*---------------------------------------------------------------------------*/
#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.
FaceDirectionMng()
Créé une instance vide.
FaceGroup innerFaces() const
Groupe de toutes les faces internes dans la direction.
FaceGroup overallFaces() const
Groupe de toutes les faces de recouvrement 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:498
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.