Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CartesianFaceUniqueIdBuilder.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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 des indentifiants uniques des faces en cartésien. */
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
59: TraceAccessor(mesh->traceMng())
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
99 Int64x3 nb_face_dir = grid_dimension.nbFaceParallelToDirection();
100
101 Int64 nb_cell_xy = nb_cell.x * nb_cell.y;
102
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();
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();
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();
131 info() << "NbSubDomain: X=" << nb_sub_domain_x << " Y=" << nb_sub_domain_y << " Z=" << nb_sub_domain_z;
132
133 // Détermine le rang inférieur dans chaque 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)
144 if (sub_domain_offset_y > 0)
146 info() << "PreviousRank X=" << previous_rank_x << " Y=" << previous_rank_y;
149
150 // Les mailles sont des quadrangles
151 std::array<Int64, 4> face_uids;
152 std::array<Int64, 4> face_uids2;
153 cells_map.eachItem([&](Cell cell) {
154 // Récupère l'indice (I,J) de la maille
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 // Pour test. A supprimer par la suite
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 // Pour test. A supprimer par la suite et garder celui de face_uid_computer.
173 // Faces selon 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 selon 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 // Positionne le propriétaire de la face inférieure en X
197 // Positionne le propriétaire de la face inférieure en Y
200 });
201 }
202 else if (dimension == 3) {
203 if (sub_domain_offset_x > 0)
205 if (sub_domain_offset_y > 0)
207 if (sub_domain_offset_z > 0)
209 info() << "PreviousRank X=" << previous_rank_x << " Y=" << previous_rank_y << " Z=" << previous_rank_z;
212 // Les mailles sont des hexaèdres
213 std::array<Int64, 6> face_uids;
214 std::array<Int64, 6> face_uids2;
215 cells_map.eachItem([&](Cell cell) {
216 // Récupère l'indice (I,J) de la maille
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 // Pour test. A supprimer par la suite
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 // Pour test. A supprimer par la suite et garder celui de face_uid_computer.
245 // Faces selon 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 selon 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 selon 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 // Positionne le propriétaire de la face inférieure en X
277 // Positionne le propriétaire de la face inférieure en Y
280 // Positionne le propriétaire de la face inférieure en Z
283 });
284 }
285 else
286 ARCANE_FATAL("Invalid dimension");
287}
288
289 /*---------------------------------------------------------------------------*/
290 /*---------------------------------------------------------------------------*/
291
292 extern "C++" void
293 arcaneComputeCartesianFaceUniqueId(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 pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classe pour calculer en 2D le uniqueId() d'une maille en fonction de sa position dans la grille.
Classe pour calculer en 3D le uniqueId() d'une maille en fonction de sa position dans la grille.
Classe pour calculer en 2D le uniqueId() d'une face en fonction de sa position dans la grille.
Classe pour calculer en 2D le uniqueId() d'une face en fonction de sa position dans la grille.
Informations sur les dimensions d'une grille cartésienne.
Maille d'un maillage.
Definition Item.h:1178
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1255
Face d'une maille.
Definition Item.h:932
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:365
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
Construction des uniqueId() des faces pour un maillage cartésien.
CartesianFaceUniqueIdBuilder(DynamicMesh *mesh)
Construit une instance pour le maillage mesh.
void computeFacesUniqueIdAndOwner()
Calcule les uniqueId() et les propriétaires.
Implémentation d'un maillage.
Definition DynamicMesh.h:97
IParallelMng * parallelMng() override
Gestionnaire de parallèlisme.
Integer dimension() override
Dimension du maillage (1D, 2D ou 3D).
Tableau associatif de ItemInternal.
Vue constante d'un tableau de type T.
Exception lorsqu'une opération n'est pas supportée.
TraceMessage info() const
Flot pour un message d'information.