Arcane  v3.16.0.0
Documentation développeur
Tout Classes Espaces de nommage Fichiers Fonctions Variables Définitions de type Énumérations Valeurs énumérées Amis Macros Groupes Pages Concepts
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/*---------------------------------------------------------------------------*/
42class SimpleSequentialMeshBuilder
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
69 explicit SimpleSequentialMeshBuilder(IMesh* pm)
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();
84 m_nodes_coordinates.add(coord);
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;
95 for (Real3 coord : nodes_coords)
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
163 CellLineInfo(Real2 first_center, Int32 nb_cell)
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)
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/*---------------------------------------------------------------------------*/
274class HoneyComb2DMeshGeneratorService
276{
277 public:
278
279 explicit HoneyComb2DMeshGeneratorService(const ServiceBuildInfo& sbi)
281 {}
282
283 public:
284
285 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
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)
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/*---------------------------------------------------------------------------*/
451class HoneyComb3DMeshGeneratorService
453{
454 public:
455
456 explicit HoneyComb3DMeshGeneratorService(const ServiceBuildInfo& sbi)
458 {}
459
460 public:
461
462 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
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.
Integer size() const
Nombre d'éléments du vecteur.
CaseOptionsHoneyComb2DMeshGenerator * options() const
Options du jeu de données du service.
ArcaneHoneyComb2DMeshGeneratorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
ArcaneHoneyComb3DMeshGeneratorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsHoneyComb3DMeshGenerator * options() const
Options du jeu de données du service.
Vue modifiable d'un tableau d'un type T.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
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.
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 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).
Paramètres nécessaires à la construction d'un maillage.
MeshBuildInfo & addNeedPartitioning(bool v)
Indique si le générateur nécessite d'appeler un partitionneur.
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.
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.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
__host__ __device__ double sqrt(double v)
Racine carrée de v.
Definition Math.h:135
constexpr __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
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:567
double Real
Type représentant un réel.
std::int32_t Int32
Type entier signé sur 32 bits.
Real y
deuxième composante du triplet
Definition Real3.h:36
Real z
troisième composante du triplet
Definition Real3.h:37
Real x
première composante du triplet
Definition Real3.h:35