Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
HoneyCombMeshGenerator.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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/* HoneyCombMeshGenerator.cc (C) 2000-2023 */
9/* */
10/* Service de génération de maillage hexagonal. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/std/HoneyCombMeshGenerator.h"
15
16#include "arcane/utils/Real2.h"
17
18#include "arcane/IMeshBuilder.h"
19#include "arcane/IPrimaryMesh.h"
20#include "arcane/IItemFamily.h"
21#include "arcane/IParallelMng.h"
22#include "arcane/MeshBuildInfo.h"
23
24#include "arcane/std/HoneyComb2DMeshGenerator_axl.h"
25#include "arcane/std/HoneyComb3DMeshGenerator_axl.h"
26
27#include <map>
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32namespace Arcane
33{
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
43: public TraceAccessor
44{
45 private:
46
48 {
49 public:
50
51 bool operator()(const Real3& a, const Real3& b) const
52 {
53 if (!math::isNearlyEqualWithEpsilon(a.x, b.x, m_epsilon))
54 return a.x < b.x;
55 if (!math::isNearlyEqualWithEpsilon(a.y, b.y, m_epsilon))
56 return a.y < b.y;
57 if (!math::isNearlyEqualWithEpsilon(a.z, b.z, m_epsilon))
58 return a.z < b.z;
59 return false;
60 }
61
62 private:
63
64 Real m_epsilon = 1e-14;
65 };
66
67 public:
68
70 : TraceAccessor(pm->traceMng())
71 , m_mesh(pm)
72 {
73 }
74
75 public:
76
79 {
80 auto p = m_nodes_coord_map.find(coord);
81 if (p != m_nodes_coord_map.end())
82 return p->second;
83 Int32 v = m_nodes_coordinates.size();
85 m_nodes_coord_map.insert(std::make_pair(coord, v));
86 return v;
87 }
88
89 Int32 addCell(Int32 type, ConstArrayView<Real3> nodes_coords)
90 {
91 m_cells_infos.add(type);
92 const Int32 v = m_nb_cell;
93 m_cells_infos.add(v);
94 ++m_nb_cell;
96 m_cells_infos.add(addNode(coord));
97 return v;
98 }
99 ConstArrayView<Int64> cellsInfos() const { return m_cells_infos; }
100 Int32 nbCell() const { return m_nb_cell; }
101
102 void setNodesCoordinates() const
103 {
104 Int32 nb_node = m_nodes_coordinates.size();
105 UniqueArray<Int64> unique_ids(nb_node);
106 for (Integer i = 0; i < nb_node; ++i)
107 unique_ids[i] = i;
108 UniqueArray<Int32> local_ids(nb_node);
109 IItemFamily* node_family = m_mesh->nodeFamily();
110 node_family->itemsUniqueIdToLocalId(local_ids, unique_ids);
111
112 VariableNodeReal3& mesh_nodes_coordinates(m_mesh->nodesCoordinates());
113 NodeInfoListView nodes(node_family);
114
115 for (Integer i = 0; i < nb_node; ++i) {
116 Node node{ nodes[local_ids[i]] };
117 mesh_nodes_coordinates[node] = m_nodes_coordinates[i];
118 }
119 }
120
121 private:
122
123 using CoordMap = std::map<Real3, Int32, Real3Compare>;
124
125 IMesh* m_mesh = nullptr;
126 CoordMap m_nodes_coord_map;
127 Int32 m_nb_cell = 0;
128 UniqueArray<Int64> m_cells_infos;
131};
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
136/*---------------------------------------------------------------------------*/
137/*---------------------------------------------------------------------------*/
138
139namespace
140{
141 void
142 _buildCellNodesCoordinates(Real pitch, Real x, Real y, Real z, ArrayView<Real3> coords)
143 {
144 Real p = 0.5 * pitch;
145 Real q = 0.5 * pitch / (math::sqrt(3.0));
146 coords[0] = { x - q, y - p, z };
147 coords[1] = { x + q, y - p, z };
148 coords[2] = { x + 2 * q, y, z };
149 coords[3] = { x + q, y + p, z };
150 coords[4] = { x - q, y + p, z };
151 coords[5] = { x - 2 * q, y, z };
152 }
153
154} // namespace
155
156/*---------------------------------------------------------------------------*/
157/*---------------------------------------------------------------------------*/
158
160{
161 public:
162
164 : m_first_center(first_center)
165 , m_nb_cell(nb_cell)
166 {}
167
168 public:
169
170 Real2 m_first_center;
171 Int32 m_nb_cell;
172};
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
176
177HoneyComb2DMeshGenerator::
178HoneyComb2DMeshGenerator(IPrimaryMesh* mesh)
179: TraceAccessor(mesh->traceMng())
180, m_mesh(mesh)
181{
182}
183
184/*---------------------------------------------------------------------------*/
185/*---------------------------------------------------------------------------*/
186
187void HoneyComb2DMeshGenerator::
188_buildCells()
189{
190 // En parallèle, seul le rang 0 construit le maillage
191 IParallelMng* pm = m_mesh->parallelMng();
192 if (pm->commRank() == 0)
193 _buildCells2();
194 else {
195 m_mesh->setDimension(2);
196 m_mesh->allocateCells(0, Int64ConstArrayView(), true);
197 }
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
203void HoneyComb2DMeshGenerator::
204_buildCells2()
205{
206 SimpleSequentialMeshBuilder simple_mesh_builder(m_mesh);
207
208 const Real pitch = m_pitch;
209 const Integer nb_ring = m_nb_ring;
210
211 info() << "Build Hexagonal 2D Cells nb_layer=" << nb_ring;
212
213 UniqueArray<Real3> cell_nodes_coords(6);
214 UniqueArray<CellLineInfo> cells_line_info;
215
216 // u1, u2 and u3 are the directional vectors following the
217 // directions of the hexagon
218 Real2 u1(0.5 * pitch * math::sqrt(3.0), -0.5 * pitch);
219 Real2 u2(0.5 * pitch * math::sqrt(3.0), 0.5 * pitch);
220 Real2 u3(pitch * 0.0, pitch * 1.0);
221
222 // Mailles au dessus du centre
223 for (Integer i = (-nb_ring + 1); i < 1; ++i) {
224 Real x0 = u3[0] * i - u1[0] * (nb_ring - 1);
225 Real y0 = u3[1] * i - u1[1] * (nb_ring - 1);
226 Real2 pos(x0, y0);
227 pos += m_origin;
228 Integer nb_cell_in_line = 2 * nb_ring - 1 + i;
229 cells_line_info.add(CellLineInfo(pos, nb_cell_in_line));
230 }
231
232 // Mailles en dessous du centre
233 for (Integer i = 1; i < nb_ring; ++i) {
234 Real x0{ u2[0] * i - u1[0] * (nb_ring - 1) };
235 Real y0{ u2[1] * i - u1[1] * (nb_ring - 1) };
236 Real2 pos(x0, y0);
237 pos += m_origin;
238 Integer nb_cell_in_line = 2 * nb_ring - 1 - i;
239 cells_line_info.add(CellLineInfo(pos, nb_cell_in_line));
240 }
241
242 for (const CellLineInfo& cli : cells_line_info) {
243 Real2 xy = cli.m_first_center;
244 for (Integer j = 0, n = cli.m_nb_cell; j < n; ++j) {
245 _buildCellNodesCoordinates(m_pitch, xy.x, xy.y, 0.0, cell_nodes_coords);
246 simple_mesh_builder.addCell(IT_Hexagon6, cell_nodes_coords);
247 xy += u1;
248 }
249 }
250
251 m_mesh->setDimension(2);
252 m_mesh->allocateCells(simple_mesh_builder.nbCell(), simple_mesh_builder.cellsInfos(), true);
253
254 simple_mesh_builder.setNodesCoordinates();
255}
256
257/*---------------------------------------------------------------------------*/
258/*---------------------------------------------------------------------------*/
259
260void HoneyComb2DMeshGenerator::
261generateMesh(Real2 origin, Real pitch, Integer nb_ring)
262{
263 m_pitch = pitch;
264 m_nb_ring = nb_ring;
265 m_origin = origin;
266 _buildCells();
267}
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
276{
277 public:
278
281 {}
282
283 public:
284
286 {
287 build_info.addNeedPartitioning(true);
288 }
290 {
291 info() << "HoneyComb2DMeshGenerator: allocateMeshItems()";
293 Real pitch = options()->pitchSize();
294 Integer nb_layer = options()->nbLayer();
295 if (pitch <= 0.0)
296 ARCANE_FATAL("Invalid valid value '{0}' for pitch (should be > 0.0)", pitch);
297 if (nb_layer <= 0)
298 ARCANE_FATAL("Invalid valid value '{0}' for 'nb-layer' (should be > 0)", nb_layer);
299 g.generateMesh(options()->origin(), pitch, nb_layer);
300 }
301
302 private:
303};
304
305/*---------------------------------------------------------------------------*/
306/*---------------------------------------------------------------------------*/
307
308ARCANE_REGISTER_SERVICE_HONEYCOMB2DMESHGENERATOR(HoneyComb2D, HoneyComb2DMeshGeneratorService);
309
310/*---------------------------------------------------------------------------*/
311/*---------------------------------------------------------------------------*/
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
318{
319 public:
320
321 CellLineInfo(Real2 first_center, Real bottom, Real top, Int32 nb_cell)
322 : m_first_center(first_center)
323 , m_bottom(bottom)
324 , m_top(top)
325 , m_nb_cell(nb_cell)
326 {}
327
328 public:
329
330 Real2 m_first_center;
331 Real m_bottom;
332 Real m_top;
333 Int32 m_nb_cell;
334};
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
339HoneyComb3DMeshGenerator::
340HoneyComb3DMeshGenerator(IPrimaryMesh* mesh)
341: TraceAccessor(mesh->traceMng())
342, m_mesh(mesh)
343{
344}
345
346/*---------------------------------------------------------------------------*/
347/*---------------------------------------------------------------------------*/
348
349void HoneyComb3DMeshGenerator::
350generateMesh(Real2 origin, Real pitch, Integer nb_ring, ConstArrayView<Real> heights)
351{
352 m_pitch = pitch;
353 m_nb_ring = nb_ring;
354 m_origin = origin;
355 m_heights = heights;
356
357 // Vérifie qu'on a le bon nombre de valeurs et qu'elles sont croissantes
358 const Integer nb_height = m_heights.size();
359 if (nb_height < 2)
360 ARCANE_FATAL("Bad number of heights '{0}' (minimum=2)", nb_height);
361 for (Integer i = 0; i < (nb_height - 1); ++i)
362 if (m_heights[i] > m_heights[i + 1])
363 ARCANE_FATAL("Heights are not increasing ({0} < {1})", m_heights[i], m_heights[i + 1]);
364
365 _buildCells();
366}
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
371void HoneyComb3DMeshGenerator::
372_buildCells()
373{
374 // En parallèle, seul le rang 0 construit le maillage
375 IParallelMng* pm = m_mesh->parallelMng();
376 if (pm->commRank() == 0)
377 _buildCells2();
378 else {
379 m_mesh->setDimension(3);
380 m_mesh->allocateCells(0, Int64ConstArrayView(), true);
381 }
382}
383
384/*---------------------------------------------------------------------------*/
385/*---------------------------------------------------------------------------*/
386
387void HoneyComb3DMeshGenerator::
388_buildCells2()
389{
390 SimpleSequentialMeshBuilder simple_mesh_builder(m_mesh);
391
392 const Real pitch = m_pitch;
393 const Integer nb_ring = m_nb_ring;
394 const Integer nb_height = m_heights.size();
395 if (nb_height < 2)
396 ARCANE_FATAL("Bad number of heights '{0}' (minimum=2)", nb_height);
397 info() << "Build Hexagonal 3D Cells nb_layer=" << nb_ring << " nb_height=" << nb_height;
398
399 UniqueArray<Real3> cell_nodes_coords(12);
400 UniqueArray<CellLineInfo> cells_line_info;
401
402 // u1, u2 and u3 are the directional vectors following the
403 // directions of the hexagon
404 Real2 u1(0.5 * pitch * math::sqrt(3.0), -0.5 * pitch);
405 Real2 u2(0.5 * pitch * math::sqrt(3.0), 0.5 * pitch);
406 Real2 u3(pitch * 0.0, pitch * 1.0);
407
408 for (Integer zz = 0; zz < (nb_height - 1); ++zz) {
409 // Mailles au dessus du centre
410 for (Integer i = (-nb_ring + 1); i < 1; ++i) {
411 Real x0 = u3[0] * i - u1[0] * (nb_ring - 1);
412 Real y0 = u3[1] * i - u1[1] * (nb_ring - 1);
413 Real2 pos(x0, y0);
414 pos += m_origin;
415 Integer nb_cell_in_line = 2 * nb_ring - 1 + i;
416 cells_line_info.add(CellLineInfo(pos, m_heights[zz], m_heights[zz + 1], nb_cell_in_line));
417 }
418
419 // Mailles en dessous du centre
420 for (Integer i = 1; i < nb_ring; ++i) {
421 Real x0{ u2[0] * i - u1[0] * (nb_ring - 1) };
422 Real y0{ u2[1] * i - u1[1] * (nb_ring - 1) };
423 Real2 pos(x0, y0);
424 pos += m_origin;
425 Integer nb_cell_in_line = 2 * nb_ring - 1 - i;
426 cells_line_info.add(CellLineInfo(pos, m_heights[zz], m_heights[zz + 1], nb_cell_in_line));
427 }
428 }
429
430 for (const CellLineInfo& cli : cells_line_info) {
431 Real2 xy = cli.m_first_center;
432 for (Integer j = 0, n = cli.m_nb_cell; j < n; ++j) {
433 _buildCellNodesCoordinates(m_pitch, xy.x, xy.y, cli.m_bottom, cell_nodes_coords.subView(0, 6));
434 _buildCellNodesCoordinates(m_pitch, xy.x, xy.y, cli.m_top, cell_nodes_coords.subView(6, 6));
435 simple_mesh_builder.addCell(IT_Octaedron12, cell_nodes_coords);
436 xy += u1;
437 }
438 }
439
440 m_mesh->setDimension(3);
441 m_mesh->allocateCells(simple_mesh_builder.nbCell(), simple_mesh_builder.cellsInfos(), true);
442
443 simple_mesh_builder.setNodesCoordinates();
444}
445
446/*---------------------------------------------------------------------------*/
447/*---------------------------------------------------------------------------*/
453{
454 public:
455
458 {}
459
460 public:
461
463 {
464 build_info.addNeedPartitioning(true);
465 }
467 {
468 info() << "HoneyComb2DMeshGenerator: allocateMeshItems()";
470 Real pitch = options()->pitchSize();
471 Integer nb_layer = options()->nbLayer();
472 ConstArrayView<Real> heights = options()->heights();
473 Integer nb_height = heights.size();
474 if (pitch <= 0.0)
475 ARCANE_FATAL("Invalid valid value '{0}' for pitch (should be > 0.0)", pitch);
476 if (nb_layer <= 0)
477 ARCANE_FATAL("Invalid valid value '{0}' for 'nb-layer' (should be > 0)", nb_layer);
478 if (nb_height <= 2)
479 ARCANE_FATAL("Invalid valid value '{0}' for 'nb-height' (should be >= 2)", nb_height);
480 g.generateMesh(options()->origin(), pitch, nb_layer, heights);
481 }
482
483 private:
484};
485
486/*---------------------------------------------------------------------------*/
487/*---------------------------------------------------------------------------*/
488
489ARCANE_REGISTER_SERVICE_HONEYCOMB3DMESHGENERATOR(HoneyComb3D, HoneyComb3DMeshGeneratorService);
490
491/*---------------------------------------------------------------------------*/
492/*---------------------------------------------------------------------------*/
493
494} // End namespace Arcane
495
496/*---------------------------------------------------------------------------*/
497/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Generation de la classe de base du Service.
Generation de la classe de base du Service.
Service de génération de maillage cartésien en 2D.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Remplit build_info avec les informations nécessaires pour créer le maillage.
void allocateMeshItems(IPrimaryMesh *pm) override
Alloue les entités du maillage géré par ce service.
Service de génération de maillage cartésien en 3D.
void allocateMeshItems(IPrimaryMesh *pm) override
Alloue les entités du maillage géré par ce service.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Remplit build_info avec les informations nécessaires pour créer le maillage.
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void allocateCells(Integer nb_cell, Int64ConstArrayView cells_infos, bool one_alloc=true)=0
Allocation d'un maillage.
virtual void setDimension(Integer dim)=0
Positionne la dimension du maillage (1D, 2D ou 3D).
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Paramètres nécessaires à la construction d'un maillage.
Classe gérant un vecteur de réel de dimension 2.
Definition Real2.h:121
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Structure contenant les informations pour créer un service.
Classe d'aide pour générer un maillage séquentiel en se basant sur la connectivité est les coordonnée...
UniqueArray< Real3 > m_nodes_coordinates
Correspondante uid->coord pour les noeuds.
Int32 addNode(Real3 coord)
Ajoute ou récupère l'uniqueId() du noeud de coordonnées coord.
Integer size() const
Nombre d'éléments du vecteur.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
constexpr ARCCORE_HOST_DEVICE bool isNearlyEqualWithEpsilon(const _Type &a, const _Type &b, const _Type &epsilon)
Teste si deux valeurs sont à un peu près égales. Pour les types entiers, cette fonction est équivalen...
Definition Numeric.h:235
ARCCORE_HOST_DEVICE double sqrt(double v)
Racine carrée de v.
Definition Math.h:135
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:638
Int32 Integer
Type représentant un entier.