Arcane  4.2.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CartesianMeshGenerator.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/* CartesianMeshGenerator.cc (C) 2000-2025 */
9/* */
10/* Service de génération de maillage cartésien. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/std/CartesianMeshGenerator.h"
15
16#include "arcane/utils/Array.h"
17#include "arcane/utils/HashTableMap.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/Real3.h"
21#include "arcane/utils/ValueConvert.h"
22#include "arcane/utils/CheckedConvert.h"
23#include "arcane/utils/Vector3.h"
24#include "arcane/utils/Vector2.h"
25
26#include "arcane/core/IMeshReader.h"
27#include "arcane/core/ISubDomain.h"
28#include "arcane/core/ICaseDocument.h"
29#include "arcane/core/XmlNode.h"
30#include "arcane/core/XmlNodeList.h"
31#include "arcane/core/XmlNodeIterator.h"
32#include "arcane/core/Service.h"
33#include "arcane/core/IParallelMng.h"
34#include "arcane/core/Item.h"
35#include "arcane/core/ItemGroup.h"
36#include "arcane/core/IMesh.h"
37#include "arcane/core/IMeshSubMeshTransition.h"
38#include "arcane/core/IItemFamily.h"
39#include "arcane/core/MeshVariable.h"
41#include "arcane/core/ItemPrinter.h"
42#include "arcane/core/FactoryService.h"
43#include "arcane/core/AbstractService.h"
44#include "arcane/core/Properties.h"
45#include "arcane/core/MeshPartInfo.h"
46#include "arcane/core/IMeshBuilder.h"
47#include "arcane/core/IMeshUniqueIdMng.h"
48#include "arcane/core/IMeshInitialAllocator.h"
49#include "arcane/core/ICartesianMeshGenerationInfo.h"
50#include "arcane/core/CartesianMeshAllocateBuildInfo.h"
51#include "arcane/core/internal/CartesianMeshAllocateBuildInfoInternal.h"
52
53#include "arcane/std/Cartesian2DMeshGenerator_axl.h"
54#include "arcane/std/Cartesian3DMeshGenerator_axl.h"
55
56#include "arcane/std/internal/SodStandardGroupsBuilder.h"
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61namespace Arcane
62{
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67void CartesianMeshGeneratorBuildInfo::
68readOptionsFromXml(XmlNode cartesian_node)
69{
70 XmlNode origine_node = cartesian_node.child("origine");
71 XmlNode nsd_node = cartesian_node.child("nsd");
72 XmlNodeList lx_node_list = cartesian_node.children("lx");
73 XmlNodeList ly_node_list = cartesian_node.children("ly");
74 XmlNodeList lz_node_list = cartesian_node.children("lz");
75
76 // On vérifie qu'on a bien au moins trois données x, y & z et une origine
77 if (origine_node.null())
78 ARCANE_FATAL("No <origin> element found");
79 if (lx_node_list.size() == 0)
80 ARCANE_FATAL("No <lx> elements found");
81 if (ly_node_list.size() == 0)
82 ARCANE_FATAL("No <ly> elements found");
83
84 String origine_value = origine_node.value();
85 // On récupère l'origine
86 bool is_bad_origin = builtInGetValue(m_origine, origine_value);
87
88 // On regarde si on a un noeud en Z
89 if (lz_node_list.size() == 0) {
90 m_mesh_dimension = 2;
91 // En 2D, on autorise l'origine a avoir 2 composantes
92 if (is_bad_origin) {
93 Real2 xy(0.0, 0.0);
94 is_bad_origin = builtInGetValue(xy, origine_value);
95 if (!is_bad_origin) {
96 m_origine.x = xy.x;
97 m_origine.y = xy.y;
98 }
99 }
100 }
101 else {
102 m_mesh_dimension = 3;
103 }
104 if (is_bad_origin)
105 ARCANE_FATAL("Element '{0}' : can not convert value '{1}' to type Real3", origine_node.xpathFullName(), origine_value);
106
107 // On récupère les longueurs des blocs, + true pour throw_exception
108 // On récupère aussi les nombres de mailles des blocs + true pour throw_exception
109 // On récupère aussi les progressions géométriques
110 // On met les progressions à 1.0 par défaut
111 for (XmlNode& lx_node : lx_node_list) {
112 m_bloc_lx.add(lx_node.valueAsReal(true));
113 m_bloc_nx.add(lx_node.attr("nx", true).valueAsInteger(true));
114 Real px = lx_node.attr("prx").valueAsReal(true);
115 if (px == 0.0)
116 px = 1.0;
117 m_bloc_px.add(px);
118 }
119 for (XmlNode& ly_node : ly_node_list) {
120 m_bloc_ly.add(ly_node.valueAsReal(true));
121 m_bloc_ny.add(ly_node.attr("ny", true).valueAsInteger(true));
122 Real py = ly_node.attr("pry").valueAsReal(true);
123 if (py == 0.0)
124 py = 1.0;
125 m_bloc_py.add(py);
126 }
127 if (m_mesh_dimension == 3) {
128 for (XmlNode& lz_node : lz_node_list) {
129 m_bloc_lz.add(lz_node.valueAsReal(true));
130 m_bloc_nz.add(lz_node.attr("nz", true).valueAsInteger(true));
131 Real pz = lz_node.attr("prz").valueAsReal(true);
132 if (pz == 0.0)
133 pz = 1.0;
134 m_bloc_pz.add(pz);
135 }
136 }
137
138 // On récupère les nombres de sous-domaines + throw_exception
139 String nsd_value = nsd_node.value();
141 if (builtInGetValue(nsd, nsd_value))
142 ARCANE_FATAL("Can not convert string '{0}' to Int[]", nsd_value);
143 if (nsd.size() != m_mesh_dimension)
144 ARCANE_FATAL("Number of sub-domain '<nsd>={0}' has to be equal to mesh dimension '{1}'",
145 nsd.size(), m_mesh_dimension);
146
147 m_nsdx = nsd[0];
148 m_nsdy = nsd[1];
149 m_nsdz = (m_mesh_dimension == 3) ? nsd[2] : 0;
150
151 {
152 XmlNode version_node = cartesian_node.child("face-numbering-version");
153 if (!version_node.null()){
154 Int32 v = version_node.valueAsInteger(true);
155 if (v>=0)
157 }
158 }
159 {
160 XmlNode version_node = cartesian_node.child("edge-numbering-version");
161 if (!version_node.null()){
162 Int32 v = version_node.valueAsInteger(true);
163 if (v>=0)
165 }
166 }
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172/*---------------------------------------------------------------------------*/
173/*---------------------------------------------------------------------------*/
174
175CartesianMeshGenerator::
176CartesianMeshGenerator(IPrimaryMesh* mesh)
177: TraceAccessor(mesh->traceMng())
178, m_mesh(mesh)
179, m_my_mesh_part(mesh->parallelMng()->commRank())
180{
181}
182
183/*---------------------------------------------------------------------------*/
184/*---------------------------------------------------------------------------*/
185
186bool CartesianMeshGenerator::
187readOptions(XmlNode cartesian_node)
188{
189 m_build_info.readOptionsFromXml(cartesian_node);
190 return _readOptions();
191}
192
193/*---------------------------------------------------------------------------*/
194/*---------------------------------------------------------------------------*/
195
196void CartesianMeshGenerator::
197setBuildInfo(const CartesianMeshGeneratorBuildInfo& build_info)
198{
199 m_build_info = build_info;
200 _readOptions();
201}
202
203/*---------------------------------------------------------------------------*/
204/*---------------------------------------------------------------------------*/
208bool CartesianMeshGenerator::
209_readOptions()
210{
211 Trace::Setter mci(traceMng(),"CartesianMeshGenerator");
212
213 m_mesh_dimension = m_build_info.m_mesh_dimension;
214 Int32 nb_sub_domain = m_mesh->parallelMng()->commSize();
215
216 // On met les nombres de sous-domaines par défaut
217 if (m_build_info.m_nsdx == 0 || nb_sub_domain == 1)
218 m_build_info.m_nsdx = 1;
219 if (m_build_info.m_nsdy == 0 || nb_sub_domain == 1)
220 m_build_info.m_nsdy = 1;
221 if (m_build_info.m_nsdz == 0 || nb_sub_domain == 1)
222 m_build_info.m_nsdz = 1;
223
224 // Synthèse des longueurs des blocs
225 m_l.x = m_l.y = m_l.z = 0.;
226 for (int i = 0; i < m_build_info.m_bloc_lx.size(); i += 1)
227 m_l.x += m_build_info.m_bloc_lx.at(i);
228 for (int i = 0; i < m_build_info.m_bloc_ly.size(); i += 1)
229 m_l.y += m_build_info.m_bloc_ly.at(i);
230 if (m_mesh_dimension == 3)
231 for (int i = 0; i < m_build_info.m_bloc_lz.size(); i += 1)
232 m_l.z += m_build_info.m_bloc_lz.at(i);
233
234 // Synthèse des origines pour chaque bloc
235 m_bloc_ox.add(m_build_info.m_origine.x);
236 m_bloc_oy.add(m_build_info.m_origine.y);
237 if (m_mesh_dimension == 3)
238 m_bloc_oz.add(m_build_info.m_origine.z);
239 for (int i = 0; i < m_build_info.m_bloc_lx.size(); i += 1)
240 m_bloc_ox.add(m_bloc_ox.at(i) + m_build_info.m_bloc_lx.at(i));
241 for (int i = 0; i < m_build_info.m_bloc_ly.size(); i += 1)
242 m_bloc_oy.add(m_bloc_oy.at(i) + m_build_info.m_bloc_ly.at(i));
243 if (m_mesh_dimension == 3)
244 for (int i = 0; i < m_build_info.m_bloc_lz.size(); i += 1)
245 m_bloc_oz.add(m_bloc_oz.at(i) + m_build_info.m_bloc_lz.at(i));
246
247 // Synthèse des nombres de mailles des blocs et en total
248 m_nx = m_ny = m_nz = 0;
249
250 for (int i = 0; i < m_build_info.m_bloc_nx.size(); ++i)
251 m_nx += m_build_info.m_bloc_nx.at(i);
252 for (int i = 0; i < m_build_info.m_bloc_ny.size(); ++i)
253 m_ny += m_build_info.m_bloc_ny.at(i);
254
255 if (m_mesh_dimension == 3)
256 for (int i = 0; i < m_build_info.m_bloc_nz.size(); i += 1)
257 m_nz += m_build_info.m_bloc_nz.at(i);
258 else
259 m_nz += 1;
260
261 // On dump les infos récupérées jusque là
262 info() << " mesh_name=" << m_mesh->name();
263 info() << " dimension=" << m_mesh_dimension;
264 info() << " origin:" << m_build_info.m_origine;
265 info() << " length x =" << m_l.x << "," << m_build_info.m_bloc_lx;
266 info() << " length y=" << m_l.y << "," << m_build_info.m_bloc_ly;
267 if (m_build_info.m_mesh_dimension == 3)
268 info() << " length z=" << m_l.z << "," << m_build_info.m_bloc_lz;
269 info() << "cells number:" << m_nx << "x" << m_ny << "x" << m_nz;
270 info() << "progression x:" << m_build_info.m_bloc_px;
271 info() << "progression y:" << m_build_info.m_bloc_py;
272 if (m_mesh_dimension == 3)
273 info() << "progression z:" << m_build_info.m_bloc_pz;
274 info() << " nb_sub_domain:" << nb_sub_domain;
275 info() << " decomposing the subdomains:" << m_build_info.m_nsdx << "x"
276 << m_build_info.m_nsdy << "x" << m_build_info.m_nsdz;
277
278 // Vérification du nombre de sous domaines vs ce qui a été spécifié
279 if (m_build_info.m_nsdx * m_build_info.m_nsdy * m_build_info.m_nsdz != nb_sub_domain)
280 ARCANE_FATAL("Specified partition {0}x{1}x{2} has to be equal to number of parts ({3})",
281 m_build_info.m_nsdx,m_build_info.m_nsdy,m_build_info.m_nsdz,nb_sub_domain);
282
283 return false; // false == ok
284}
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
288// ******************************************************************************
289// * sd[X|Y|Z]Offset
290// ******************************************************************************
291inline Integer CartesianMeshGenerator::
292sdXOffset(Int32 this_sub_domain_id)
293{
294 return this_sub_domain_id % m_build_info.m_nsdx;
295}
296
297inline Integer CartesianMeshGenerator::
298sdYOffset(Int32 this_sub_domain_id)
299{
300 return (this_sub_domain_id / m_build_info.m_nsdx) % m_build_info.m_nsdy;
301}
302
303inline Integer CartesianMeshGenerator::
304sdZOffset(Int32 this_sub_domain_id)
305{
306 return (this_sub_domain_id / (m_build_info.m_nsdx * m_build_info.m_nsdy)) % m_build_info.m_nsdz;
307}
308
309inline Integer CartesianMeshGenerator::
310sdXOffset()
311{
312 return sdXOffset(m_my_mesh_part);
313}
314
315inline Integer CartesianMeshGenerator::
316sdYOffset()
317{
318 return sdYOffset(m_my_mesh_part);
319}
320
321inline Integer CartesianMeshGenerator::
322sdZOffset()
323{
324 return sdZOffset(m_my_mesh_part);
325}
326
327/*---------------------------------------------------------------------------*/
328/*---------------------------------------------------------------------------*/
329// ******************************************************************************
330// * own[X|Y|Z]NbCell
331// ******************************************************************************
332inline Int32 ownNbCell(Int64 n, Integer nsd, int sd_offset)
333{
334 Int64 q = n / nsd;
335 Int64 r = n % nsd;
336 // Si on est en 'première approche', on a pas de reste
337 if (r == 0)
338 return CheckedConvert::toInt32(q);
339 // Sinon, le reste des mailles est réparti sur les derniers sous domaines
340 if (sd_offset < (nsd - r))
341 return CheckedConvert::toInt32(q);
342 return CheckedConvert::toInt32(q + 1);
343}
344
345inline Int32 CartesianMeshGenerator::
346ownXNbCell()
347{
348 return ownNbCell(m_nx, m_build_info.m_nsdx, sdXOffset());
349}
350inline Int32 CartesianMeshGenerator::
351ownXNbCell(int isd)
352{
353 return ownNbCell(m_nx, m_build_info.m_nsdx, sdXOffset(isd));
354}
355inline Int32 CartesianMeshGenerator::
356ownYNbCell()
357{
358 return ownNbCell(m_ny, m_build_info.m_nsdy, sdYOffset());
359}
360inline Int32 CartesianMeshGenerator::
361ownYNbCell(int isd)
362{
363 return ownNbCell(m_ny, m_build_info.m_nsdy, sdYOffset(isd));
364}
365inline Int32 CartesianMeshGenerator::
366ownZNbCell()
367{
368 return ownNbCell(m_nz, m_build_info.m_nsdz, sdZOffset());
369}
370inline Int32 CartesianMeshGenerator::
371ownZNbCell(int isd)
372{
373 return ownNbCell(m_nz, m_build_info.m_nsdz, sdZOffset(isd));
374}
375
376// ******************************************************************************
377// * iProgression
378// ******************************************************************************
379inline Real
380iDelta(int iBloc,
381 const RealArray& bloc_p,
382 const Int32Array& bloc_n,
383 const RealArray& bloc_l,
384 const Real all_l,
385 const Int64 all_n)
386{
387 Real p = bloc_p.at(iBloc);
388 Real n = (Real)bloc_n.at(iBloc);
389 Real l = bloc_l.at(iBloc);
390 if (p <= 1.0)
391 return all_l / (Real)all_n;
392 return (p - 1.0) / (math::pow(p, n) - 1.0) * l;
393}
394
395inline Real
396kDelta(Real k,
397 int iBloc,
398 const RealArray& bloc_p,
399 const Int32Array& bloc_n,
400 const RealArray& bloc_l,
401 const Real all_l,
402 const Int64 all_n)
403{
404 ARCANE_UNUSED(all_l);
405 ARCANE_UNUSED(all_n);
406
407 Real p = bloc_p.at(iBloc);
408 Real n = (Real)bloc_n.at(iBloc);
409 Real l = bloc_l.at(iBloc);
410 if (p == 1.0)
411 return l * k / n;
412 return l * (math::pow(p, k) - 1.0) / (math::pow(p, (Real)n) - 1.0);
413}
414
415inline Real CartesianMeshGenerator::
416nxDelta(Real k, int iBloc)
417{
418 return m_bloc_ox.at(iBloc) + kDelta(k, iBloc, m_build_info.m_bloc_px, m_build_info.m_bloc_nx, m_build_info.m_bloc_lx, m_l.x, m_nx);
419}
420inline Real CartesianMeshGenerator::
421xDelta(int iBloc)
422{
423 return iDelta(iBloc, m_build_info.m_bloc_px, m_build_info.m_bloc_nx, m_build_info.m_bloc_lx, m_l.x, m_nx);
424}
425
426inline Real CartesianMeshGenerator::
427nyDelta(Real k, int iBloc)
428{
429 return m_bloc_oy.at(iBloc) + kDelta(k, iBloc, m_build_info.m_bloc_py, m_build_info.m_bloc_ny, m_build_info.m_bloc_ly, m_l.y, m_ny);
430}
431inline Real CartesianMeshGenerator::
432yDelta(int iBloc)
433{
434 return iDelta(iBloc, m_build_info.m_bloc_py, m_build_info.m_bloc_ny, m_build_info.m_bloc_ly, m_l.y, m_ny);
435}
436
437inline Real CartesianMeshGenerator::
438nzDelta(Real k, int iBloc)
439{
440 return m_bloc_oz.at(iBloc) + kDelta(k, iBloc, m_build_info.m_bloc_pz, m_build_info.m_bloc_nz, m_build_info.m_bloc_lz, m_l.z, m_nz);
441}
442
443inline Real CartesianMeshGenerator::
444zDelta(int iBloc)
445{
446 return iDelta(iBloc, m_build_info.m_bloc_pz, m_build_info.m_bloc_nz, m_build_info.m_bloc_lz, m_l.z, m_nz);
447}
448
449/*---------------------------------------------------------------------------*/
450/*---------------------------------------------------------------------------*/
451// ******************************************************************************
452// * X scanning
453// ******************************************************************************
454void CartesianMeshGenerator::
455xScan(const Int64 all_nb_cell_x,
456 IntegerArray& sd_x_ibl,
457 IntegerArray& sd_x_obl,
458 Int64Array& sd_x_nbl,
459 Int64Array& sd_x_node_offset,
460 Int64Array& sd_x_cell_offset)
461{
462 sd_x_ibl.add(0);
463 sd_x_obl.add(0);
464 sd_x_nbl.add(0);
465 sd_x_node_offset.add(0);
466 sd_x_cell_offset.add(0);
467 // Reset des indices, offset et frontières
468 Int64 nsd = 0;
469 Integer isd = 0;
470 Integer ibl = 0;
471 Integer obl = 0;
472 Int64 nbl = 0;
473 for (Int64 x = 0; x < all_nb_cell_x; ++x) {
474 // Si on découvre la frontière d'un bloc
475 if (x == (nbl + m_build_info.m_bloc_nx.at(ibl))) {
476 nbl += m_build_info.m_bloc_nx.at(ibl);
477 info(4) << "\t␛[2;33m[CartesianMeshGenerator::xScan] Scan hit x bloc boundary: @ node " << nbl << "␛[0m";
478 // On saute de bloc
479 ibl += 1;
480 // On reset l'offset de calcul dans le bloc
481 obl = 0;
482 }
483 // Si on découvre la frontière d'un sous-domaine
484 if (x == (nsd + ownXNbCell(isd))) {
485 nsd += ownXNbCell(isd);
486 info(4) << "\t␛[2;33m[CartesianMeshGenerator::xScan] Scan hit x sub domain boundary: @ node " << nsd << "␛[0m";
487 // On sauvegarde les infos nécessaire à la reprise par sous-domaine
488 sd_x_ibl.add(ibl);
489 sd_x_obl.add(obl);
490 sd_x_nbl.add(nbl);
491 sd_x_node_offset.add(nsd);
492 sd_x_cell_offset.add(nsd);
493 isd += 1;
494 info(4) << "\t␛[2;33m[CartesianMeshGenerator::xScan] Saving state: "
495 << ", node_offset=" << sd_x_node_offset.at(isd)
496 << ", cell_offset=" << sd_x_cell_offset.at(isd)
497 << ", ibl=" << sd_x_ibl.at(isd)
498 << ", nbl=" << sd_x_nbl.at(isd) << "␛[0m";
499 }
500 // On incrémente l'offset de calcul dans le bloc
501 obl += 1;
502 }
503}
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507// ******************************************************************************
508// * Y scanning
509// ******************************************************************************
510void CartesianMeshGenerator::
511yScan(const Integer all_nb_cell_y,
512 IntegerArray& sd_y_ibl,
513 IntegerArray& sd_y_obl,
514 Int64Array& sd_y_nbl,
515 Int64Array& sd_y_node_offset,
516 Int64Array& sd_y_cell_offset,
517 Int64 all_nb_node_x,
518 Int64 all_nb_cell_x)
519{
520 sd_y_ibl.add(0);
521 sd_y_obl.add(0);
522 sd_y_nbl.add(0);
523 sd_y_node_offset.add(0);
524 sd_y_cell_offset.add(0);
525 Int64 nsd = 0;
526 Integer isd = 0;
527 Integer ibl = 0;
528 Integer obl = 0;
529 Int64 nbl = 0;
530 for (Int64 y = 0; y < all_nb_cell_y; ++y) {
531 if (y == (nbl + m_build_info.m_bloc_ny.at(ibl))) {
532 nbl += m_build_info.m_bloc_ny.at(ibl);
533 info(4) << "\t␛[2;33m[CartesianMeshGenerator::generateMesh] Scan hit y bloc boundary: @ node " << nbl << "␛[0m";
534 ibl += 1;
535 obl = 0;
536 }
537 if (y == (nsd + ownYNbCell(isd))) {
538 nsd += ownYNbCell(isd);
539 info(4) << "\t␛[2;33m[CartesianMeshGenerator::generateMesh] Scan hit y sub domain boundary: @ node " << nsd << "␛[0m";
540 sd_y_ibl.add(ibl);
541 sd_y_obl.add(obl);
542 sd_y_nbl.add(nbl * all_nb_node_x);
543 sd_y_node_offset.add(nsd * all_nb_node_x);
544 sd_y_cell_offset.add(nsd * all_nb_cell_x);
545 isd += m_build_info.m_nsdx;
546 }
547 obl += 1;
548 }
549}
550
551/*---------------------------------------------------------------------------*/
552/*---------------------------------------------------------------------------*/
553// ******************************************************************************
554// * Z scanning
555// ******************************************************************************
556void CartesianMeshGenerator::
557zScan(const Int64 all_nb_cell_z,
558 IntegerArray& sd_z_ibl,
559 IntegerArray& sd_z_obl,
560 Int64Array& sd_z_nbl,
561 Int64Array& sd_z_node_offset,
562 Int64Array& sd_z_cell_offset,
563 Int64 all_nb_node_xy,
564 Int64 all_nb_cell_xy)
565{
566 if (m_mesh_dimension != 3)
567 return;
568 sd_z_ibl.add(0);
569 sd_z_obl.add(0);
570 sd_z_nbl.add(0);
571 sd_z_node_offset.add(0);
572 sd_z_cell_offset.add(0);
573 Int64 nsd = 0;
574 Integer isd = 0;
575 Integer ibl = 0;
576 Integer obl = 0;
577 Int64 nbl = 0;
578 for (Int64 z = 0; z < all_nb_cell_z; ++z) {
579 if (z == (nbl + m_build_info.m_bloc_nz.at(ibl))) {
580 nbl += m_build_info.m_bloc_nz.at(ibl);
581 ibl += 1;
582 obl = 0;
583 }
584 if (z == (nsd + ownZNbCell(isd))) {
585 nsd += ownZNbCell(isd);
586 sd_z_ibl.add(ibl);
587 sd_z_obl.add(obl);
588 sd_z_nbl.add(nbl * all_nb_node_xy);
589 sd_z_node_offset.add(nsd * all_nb_node_xy);
590 sd_z_cell_offset.add(nsd * all_nb_cell_xy);
591 isd += m_build_info.m_nsdx * m_build_info.m_nsdy;
592 }
593 obl += 1;
594 }
595}
596
597// ******************************************************************************
598// * generateMesh
599// ******************************************************************************
600
601bool CartesianMeshGenerator::
602generateMesh()
603{
604 Trace::Setter mci(traceMng(),"CartesianMeshGenerator");
605 IPrimaryMesh* mesh = m_mesh;
606
607 m_generation_info = ICartesianMeshGenerationInfo::getReference(mesh,true);
608
609 CartesianMeshAllocateBuildInfo cartesian_mesh_build_info(mesh);
610
611 info() << " decomposing the subdomains:" << m_build_info.m_nsdx << "x"
612 << m_build_info.m_nsdy << "x" << m_build_info.m_nsdz;
613 info() << "sub domain offset @ " << sdXOffset() << "x" << sdYOffset() << "x" << sdZOffset();
614 // All Cells Setup
615 Integer all_nb_cell_x = m_nx;
616 Integer all_nb_cell_y = m_ny;
617 Integer all_nb_cell_z = m_nz;
618 // Positionne des propriétés sur le maillage pour qu'il puisse connaître
619 // le nombre de mailles dans chaque direction ainsi que l'offset du sous-domaine.
620 // Cela est utilisé notammement par CartesianMesh.
621 //Properties* mesh_properties = mesh->properties();
622 m_generation_info->setGlobalNbCells(all_nb_cell_x,all_nb_cell_y,all_nb_cell_z);
623 m_generation_info->setSubDomainOffsets(sdXOffset(),sdYOffset(),sdZOffset());
624 m_generation_info->setNbSubDomains(m_build_info.m_nsdx,m_build_info.m_nsdy,m_build_info.m_nsdz);
625
626 m_generation_info->setGlobalOrigin(m_build_info.m_origine);
627 m_generation_info->setGlobalLength(m_l);
628
629 Int64 all_nb_cell_xy = ((Int64)all_nb_cell_x) * ((Int64)all_nb_cell_y);
630 Int64 all_nb_cell_xyz = ((Int64)all_nb_cell_xy) * ((Int64)all_nb_cell_z);
631 info() << " all cells: " << all_nb_cell_x << "x" << all_nb_cell_y << "y"
632 << all_nb_cell_z << "=" << all_nb_cell_xyz;
633
634 // Own Cells Setup
635 Int32 own_nb_cell_x = ownXNbCell();
636 Int32 own_nb_cell_y = ownYNbCell();
637 Int32 own_nb_cell_z = ownZNbCell();
638 m_generation_info->setOwnNbCells(own_nb_cell_x,own_nb_cell_y,own_nb_cell_z);
639 Integer own_nb_cell_xy = CheckedConvert::multiply(own_nb_cell_x, own_nb_cell_y);
640 Integer own_nb_cell_xyz = CheckedConvert::multiply(own_nb_cell_xy, own_nb_cell_z);
641 info() << " own cells: " << own_nb_cell_x << "x" << own_nb_cell_y << "y"
642 << own_nb_cell_z << "=" << own_nb_cell_xyz;
643
644 // All Nodes Setup
645 Integer all_nb_node_x = all_nb_cell_x + 1;
646 Integer all_nb_node_y = all_nb_cell_y + 1;
647 Int64 all_nb_node_xy = ((Int64)all_nb_node_x) * ((Int64)all_nb_node_y);
648
649 // Own Nodes Setup
650 Integer own_nb_node_x = own_nb_cell_x + 1;
651 Integer own_nb_node_y = own_nb_cell_y + 1;
652 Integer own_nb_node_z = (m_mesh_dimension == 3) ? own_nb_cell_z + 1 : own_nb_cell_z;
653 Integer own_nb_node_xy = CheckedConvert::multiply(own_nb_node_x, own_nb_node_y);
654 Integer own_nb_node_xyz = CheckedConvert::multiply(own_nb_node_xy, own_nb_node_z);
655 info() << " own nodes: "
656 << own_nb_node_x << "x"
657 << own_nb_node_y << "y"
658 << own_nb_node_z << "=" << own_nb_node_xyz;
659
660 // Création hash-table des noeuds et préparation de leurs uid
661 UniqueArray<Int64> nodes_unique_id(CheckedConvert::toInteger(own_nb_node_xyz));
662 // La taille d'une HashTableMapT est un nombre de buckets et non un
663 // nombre d'éléments : elle rehache dès que son nombre dépasse 0.85 * nb_bucket, donc la
664 // table est dimensionnée pour le facteur de charge et contient tous les noeuds sans rehachage.
665 const Int64 wanted_bucket = static_cast<Int64>(own_nb_node_xyz / 0.85) + 1;
666 HashTableMapT<Int64, NodeInfo> nodes_infos(CheckedConvert::toInteger(wanted_bucket), true);
667
668 // Calcule des infos blocs et des offset associés à tous les sub_domain_id
669 IntegerUniqueArray sd_x_ibl, sd_x_obl; // Numéro et offset dans le bloc
670 IntegerUniqueArray sd_y_ibl, sd_y_obl;
671 IntegerUniqueArray sd_z_ibl, sd_z_obl;
672 Int64UniqueArray sd_x_nbl, sd_y_nbl, sd_z_nbl; // Nombre dans le bloc
673 Int64UniqueArray sd_x_node_offset;
674 Int64UniqueArray sd_y_node_offset;
675 Int64UniqueArray sd_z_node_offset;
676 Int64UniqueArray sd_x_cell_offset;
677 Int64UniqueArray sd_y_cell_offset;
678 Int64UniqueArray sd_z_cell_offset;
679
680 // Scan des sous domaines: i_ème (isd) et n_ème (nsd) noeud pour marquer la frontière sous domaine
681 // Scan des des blocs: i_ème (ibl), o_ème offset (obl) et n_ème (nbl) noeud pour marquer la frontière bloc
682
683 // Selon la direction X
684 xScan(all_nb_cell_x,
685 sd_x_ibl, sd_x_obl, sd_x_nbl,
686 sd_x_node_offset, sd_x_cell_offset);
687
688 // Selon la direction Y
689 yScan(all_nb_cell_y,
690 sd_y_ibl, sd_y_obl, sd_y_nbl,
691 sd_y_node_offset, sd_y_cell_offset,
692 all_nb_node_x, all_nb_cell_x);
693
694 // Selon la direction Z
695 zScan(all_nb_cell_z,
696 sd_z_ibl, sd_z_obl, sd_z_nbl,
697 sd_z_node_offset, sd_z_cell_offset,
698 all_nb_node_xy, all_nb_cell_xy);
699
700 // Calcule pour les mailles l'offset global du début de la grille pour chaque direction.
701 Int64x3 first_own_cell_offset;
702 {
703 Int64 cell_offset_x = sd_x_cell_offset[sdXOffset()];
704 Int64 cell_offset_y = sd_y_cell_offset[sdYOffset()] / all_nb_cell_x;
705 Int64 cell_offset_z = 0;
706 if (m_mesh_dimension == 3) {
707 cell_offset_z = sd_z_cell_offset[sdZOffset()] / all_nb_cell_xy;
708 }
709 first_own_cell_offset = Int64x3(cell_offset_x,cell_offset_y,cell_offset_z);
710 info() << "OwnCellOffset info X=" << cell_offset_x << " Y=" << cell_offset_y << " Z=" << cell_offset_z;
711 m_generation_info->setOwnCellOffsets(cell_offset_x,cell_offset_y,cell_offset_z);
712 }
713 // IBL, NBL
714 info() << " sd_x_ibl=" << sd_x_ibl;
715 info() << " sd_x_obl=" << sd_x_obl;
716 info() << " sd_x_nbl=" << sd_x_nbl;
717
718 info() << " sd_y_ibl=" << sd_y_ibl;
719 info() << " sd_y_obl=" << sd_y_obl;
720 info() << " sd_y_nbl=" << sd_y_nbl;
721
722 info() << " sd_z_ibl=" << sd_z_ibl;
723 info() << " sd_z_obl=" << sd_z_obl;
724 info() << " sd_z_nbl=" << sd_z_nbl;
725
726 // NODE OFFSET
727 info() << " sd_x_node_offset=" << sd_x_node_offset;
728 info() << " sd_y_node_offset=" << sd_y_node_offset;
729 info() << " sd_z_node_offset=" << sd_z_node_offset;
730
731 // CELL OFFSET
732 info() << " sd_x_cell_offset=" << sd_x_cell_offset;
733 info() << " sd_y_cell_offset=" << sd_y_cell_offset;
734 info() << " sd_z_cell_offset=" << sd_z_cell_offset;
735
736 // On calcule le premier node_local_id en fonction de notre sub_domain_id
737 Integer node_local_id = 0;
738 Int64 node_unique_id_offset = 0;
739 info() << " sdXOffset=" << sdXOffset()
740 << " sdYOffset=" << sdYOffset()
741 << " sdZOffset=" << sdZOffset();
742 // On calcule l'offset en x des node_unique_id
743 node_unique_id_offset += sd_x_node_offset.at(sdXOffset());
744 info() << " node_unique_id_offset=" << node_unique_id_offset;
745 // On calcule l'offset en y des node_unique_id
746 node_unique_id_offset += (sd_y_node_offset.at(sdYOffset()));
747 info() << " node_unique_id_offset=" << node_unique_id_offset;
748 if (m_mesh_dimension == 3) {
749 // On calcule l'offset en z des node_unique_id
750 node_unique_id_offset += (sd_z_node_offset.at(sdZOffset()));
751 info() << " node_unique_id_offset=" << node_unique_id_offset;
752 }
753
754 Integer z_ibl = 0;
755 Integer z_obl = 0;
756 Int64 z_nbl = 0;
757 if (m_mesh_dimension == 3) {
758 z_ibl = sd_z_ibl.at(sdZOffset());
759 z_obl = sd_z_obl.at(sdZOffset());
760 z_nbl = sd_z_nbl.at(sdZOffset());
761 }
762 for (Int64 z = 0; z < own_nb_node_z; ++z) {
763 if (m_mesh_dimension == 3) {
764 // On saute l'éventuelle dernière frontière bl coincidante avec les sd
765 // Et si on découvre une frontière bloc, on reset les origines
766 if (((z + 1) != own_nb_node_z) &&
767 ((z * all_nb_node_xy + sd_z_node_offset.at(sdZOffset())) == (z_nbl + m_build_info.m_bloc_nz.at(z_ibl) * all_nb_node_xy))) {
768 info() << " Creation hit z bloc boundarz: @ node " << z;
769 z_nbl += m_build_info.m_bloc_nz.at(z_ibl) * all_nb_node_xy;
770 // On incrémente de bloc
771 z_ibl += 1;
772 z_obl = 0;
773 }
774 }
775 Real nz = 0.0;
776 if (m_mesh_dimension == 3)
777 nz = nzDelta(z_obl, z_ibl);
778 Integer y_ibl = sd_y_ibl.at(sdYOffset());
779 Integer y_obl = sd_y_obl.at(sdYOffset());
780 Int64 y_nbl = sd_y_nbl.at(sdYOffset());
781 for (Int64 y = 0; y < own_nb_node_y; ++y) {
782 // On saute l'éventuelle dernière frontière bl coincidante avec les sd
783 // Et si on découvre une frontière bloc, on reset les origines
784 if (((y + 1) != own_nb_node_y) &&
785 ((y * all_nb_node_x + sd_y_node_offset.at(sdYOffset())) == (y_nbl + m_build_info.m_bloc_ny.at(y_ibl) * all_nb_node_x))) {
786 info() << " Creation hit y bloc boundary: @ node " << y;
787 y_nbl += m_build_info.m_bloc_ny.at(y_ibl) * all_nb_node_x;
788 // On incrémente de bloc
789 y_ibl += 1;
790 y_obl = 0;
791 }
792 Real ny = nyDelta(y_obl, y_ibl);
793 // Récupération du numéro de bloc courant
794 Integer x_ibl = sd_x_ibl.at(sdXOffset());
795 // Récupération de l'offset dans le bloc courant
796 Integer x_obl = sd_x_obl.at(sdXOffset());
797 // Récupération du nombre de noeuds dans le bloc courant
798 Int64 x_nbl = sd_x_nbl.at(sdXOffset());
799 for (Int64 x = 0; x < own_nb_node_x; ++x) {
800 Int64 node_unique_id = node_unique_id_offset + x + y * all_nb_node_x + z * all_nb_node_xy;
801 nodes_unique_id[node_local_id] = node_unique_id;
802 Int32 owner = m_my_mesh_part;
803 // Si on est pas sur sur un sd des bords
804 // Et si on touche aux noeuds des bords du sd de bord
805 if (((sdXOffset() + 1) != m_build_info.m_nsdx) && ((x + 1) == own_nb_node_x))
806 owner += 1;
807 if (((sdYOffset() + 1) != m_build_info.m_nsdy) && ((y + 1) == own_nb_node_y))
808 owner += m_build_info.m_nsdx;
809 if (((sdZOffset() + 1) != m_build_info.m_nsdz) && ((z + 1) == own_nb_node_z))
810 owner += m_build_info.m_nsdx * m_build_info.m_nsdy;
811 // On saute l'éventuelle dernière frontière bl coincidante avec les sd
812 // Et si on découvre une frontière bloc, on reset les origines
813 if (((x + 1) != own_nb_node_x) && ((x + sd_x_node_offset.at(sdXOffset())) == (x_nbl + m_build_info.m_bloc_nx.at(x_ibl)))) {
814 info() << " Creation hit x bloc boundary: @ node " << x;
815 x_nbl += m_build_info.m_bloc_nx.at(x_ibl);
816 // On incrémente de bloc
817 x_ibl += 1;
818 x_obl = 0;
819 }
820 Real nx = nxDelta(x_obl, x_ibl);
821 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] node @ "<<x<<"x"<<y<<"x"<<z
822 <<":"<< ", uid=" << node_unique_id<< ", owned by " << owner
823 << ", ␛[1;32m coords=("<<nx<<","<<ny<<","<<nz<<")"<<"␛[0m";*/
824 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
825 node_local_id += 1;
826 x_obl += 1;
827 }
828 y_obl += 1;
829 }
830 z_obl += 1;
831 }
832
833 // Création des mailles
834 // Infos pour la création des mailles
835 // par maille: 1 pour son unique id,
836 // 1 pour son type,
837 // 8 pour chaque noeud
838 Int64 cell_unique_id_offset = 0;
839 // On calcule l'offset en x des cell_unique_id
840 cell_unique_id_offset += sd_x_cell_offset.at(sdXOffset());
841 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
842 // On calcule l'offset en y des cell_unique_id
843 cell_unique_id_offset += sd_y_cell_offset.at(sdYOffset());
844 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
845 if (m_mesh_dimension == 3) {
846 // On calcule l'offset en z des cell_unique_id
847 cell_unique_id_offset += sd_z_cell_offset.at(sdZOffset());
848 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
849 }
850 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
851 m_generation_info->setFirstOwnCellUniqueId(cell_unique_id_offset);
852
853 const Int32 face_numbering_version = m_build_info.m_face_numbering_version;
854 info() << "FaceNumberingVersion = " << face_numbering_version;
855 const Int32 edge_numbering_version = m_build_info.m_edge_numbering_version;
856 info() << "EdgeNumberingVersion = " << edge_numbering_version;
857
858 {
859 info() << "Set Specific info for cartesian mesh";
860 if (m_mesh_dimension==3)
861 cartesian_mesh_build_info.setInfos3D({all_nb_cell_x,all_nb_cell_y,all_nb_cell_z},
862 {own_nb_cell_x,own_nb_cell_y,own_nb_cell_z},
863 {first_own_cell_offset.x,first_own_cell_offset.y,first_own_cell_offset.z},
864 0 );
865 else if (m_mesh_dimension==2){
866 cartesian_mesh_build_info.setInfos2D({all_nb_cell_x,all_nb_cell_y},
867 {own_nb_cell_x,own_nb_cell_y},
868 {first_own_cell_offset.x,first_own_cell_offset.y},
869 0 );
870 }
871 else
872 ARCANE_FATAL("Invalid dimensionn '{0}' (valid values are 2 or 3)",m_mesh_dimension);
873
874 if (face_numbering_version>=0)
875 cartesian_mesh_build_info._internal()->setFaceBuilderVersion(face_numbering_version);
876 if (edge_numbering_version>=0)
877 cartesian_mesh_build_info._internal()->setEdgeBuilderVersion(edge_numbering_version);
878 }
879
880 cartesian_mesh_build_info.allocateMesh();
881
882 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
883 {
884 info() << "Fills the variable containing the coordinates of the nodes";
885 Int32UniqueArray nodes_local_id(nodes_unique_id.size());
886 IItemFamily* family = mesh->nodeFamily();
887 family->itemsUniqueIdToLocalId(nodes_local_id, nodes_unique_id);
888 NodeInfoListView nodes_internal(family);
889 for (Integer i = 0; i < node_local_id; ++i) {
890 Node node = nodes_internal[nodes_local_id[i]];
891 Int64 unique_id = nodes_unique_id[i];
892 nodes_coord_var[node] = nodes_infos.lookupValue(unique_id).m_coord;
893 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] Set coord "
894 << ItemPrinter(node) << " coord=" << nodes_coord_var[node]<< "␛[0m";*/
895 }
896 }
897 nodes_coord_var.synchronize();
898
899 // Créé les groupes correspondants aux bords du maillage
900 // Si demandé, on créé aussi les groupes pour tester un tube à choc de Sod.
901 {
902 SodStandardGroupsBuilder groups_builder(traceMng());
903 Real3 origin = m_build_info.m_origine;
904 Real3 length(m_l.x,m_l.y,m_l.z);
905 Real3 max_pos = origin + length;
906 // TODO: Comme il peut y avoir des progressions geométriques il faut définir
907 // le milieu à partir de la position de la maille d'offset le milieu
908 // et pas à partir des coordonnées
909 // Calculer middle_x comme position du milieu
910 bool do_zg_and_zd = m_build_info.m_is_generate_sod_groups;
911 Real middle_x = (origin.x + max_pos.x) / 2.0;
912 Real middle_height = (origin.y + max_pos.y) / 2.0;
913 groups_builder.generateGroups(mesh, origin, origin + length, middle_x, middle_height, do_zg_and_zd);
914 }
915
916 return false; // false == ok
917}
918
919/*---------------------------------------------------------------------------*/
920/*---------------------------------------------------------------------------*/
921
922/*---------------------------------------------------------------------------*/
923/*---------------------------------------------------------------------------*/
927class Cartesian2DMeshGenerator
929{
930 public:
931
932 explicit Cartesian2DMeshGenerator(const ServiceBuildInfo& sbi)
934
935 public:
936
937 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
938 {
939 ARCANE_UNUSED(build_info);
940 info() << "Cartesian2DMeshGenerator: fillMeshBuildInfo()";
941 m_build_info.m_nsdx = options()->nbPartX();
942 m_build_info.m_nsdy = options()->nbPartY();
943
944 m_build_info.m_mesh_dimension = 2;
945 Real2 origin = options()->origin;
946 m_build_info.m_origine.x = origin.x;
947 m_build_info.m_origine.y = origin.y;
948 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
949 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
950
951 for( auto& o : options()->x() ){
952 m_build_info.m_bloc_lx.add(o->length);
953 m_build_info.m_bloc_nx.add(o->n);
954 m_build_info.m_bloc_px.add(o->progression);
955 }
956
957 for( auto& o : options()->y() ){
958 m_build_info.m_bloc_ly.add(o->length);
959 m_build_info.m_bloc_ny.add(o->n);
960 m_build_info.m_bloc_py.add(o->progression);
961 }
962 }
963
965 {
966 info() << "Cartesian2DMeshGenerator: allocateMeshItems()";
968 // Regarde s'il faut calculer dynamiquement le découpage
969 auto [ x, y ] = _computePartition(pm,m_build_info.m_nsdx,m_build_info.m_nsdy);
970 m_build_info.m_nsdx = x;
971 m_build_info.m_nsdy = y;
972 g.setBuildInfo(m_build_info);
973 g.generateMesh();
974 }
975
976 private:
977
979
980 static std::tuple<Integer,Integer>
981 _computePartition(IPrimaryMesh* pm,Integer nb_x,Integer nb_y)
982 {
983 Int32 nb_part = pm->meshPartInfo().nbPart();
984 // En séquentiel, ne tient pas compte des valeurs de jeu de données.
985 if (nb_part==1)
986 return {1,1};
987 // Si le découpage en X et en Y est spécifié, l'utilise directement.
988 if (nb_x!=0 && nb_y!=0)
989 return {nb_x, nb_y};
990 // Aucun découpage spécifié. Il faut que math::sqrt(nb_part)
991 // soit un entier
992 if (nb_x==0 && nb_y==0){
993 double s = math::sqrt((double)(nb_part));
994 Integer s_int = (Integer)(::floor(s));
995 if ((s_int*s_int) != nb_part)
996 ARCANE_FATAL("Invalid number of part '{0}' for automatic partitioning: sqrt({1}) is not an integer",
997 nb_part,nb_part);
998 return {s_int,s_int};
999 }
1000 // Ici, on a un des deux découpages qui n'est pas spécifié.
1001 if (nb_x==0){
1002 if ( (nb_part % nb_y) != 0 )
1003 ARCANE_FATAL("Invalid number of Y part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
1004 nb_y,nb_part,nb_y);
1005 nb_x = nb_part / nb_y;
1006 }
1007 else{
1008 if ( (nb_part % nb_x) != 0 )
1009 ARCANE_FATAL("Invalid number of X part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
1010 nb_x,nb_part,nb_x);
1011 nb_y = nb_part / nb_x;
1012 }
1013 return {nb_x,nb_y};
1014 }
1015};
1016
1017ARCANE_REGISTER_SERVICE_CARTESIAN2DMESHGENERATOR(Cartesian2D,Cartesian2DMeshGenerator);
1018
1019/*---------------------------------------------------------------------------*/
1020/*---------------------------------------------------------------------------*/
1024class Cartesian3DMeshGenerator
1026{
1027 public:
1028 Cartesian3DMeshGenerator(const ServiceBuildInfo& sbi)
1030 public:
1031 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1032 {
1033 ARCANE_UNUSED(build_info);
1034 info() << "Cartesian3DMeshGenerator: fillMeshBuildInfo()";
1035 m_build_info.m_nsdx = options()->nbPartX();
1036 m_build_info.m_nsdy = options()->nbPartY();
1037 m_build_info.m_nsdz = options()->nbPartZ();
1038
1039 m_build_info.m_mesh_dimension = 3;
1040 Real3 origin = options()->origin;
1041 m_build_info.m_origine.x = origin.x;
1042 m_build_info.m_origine.y = origin.y;
1043 m_build_info.m_origine.z = origin.z;
1044 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
1045 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
1046 m_build_info.m_edge_numbering_version = options()->edgeNumberingVersion();
1047
1048 for( auto& o : options()->x() ){
1049 m_build_info.m_bloc_lx.add(o->length);
1050 m_build_info.m_bloc_nx.add(o->n);
1051 m_build_info.m_bloc_px.add(o->progression);
1052 }
1053
1054 for( auto& o : options()->y() ){
1055 m_build_info.m_bloc_ly.add(o->length);
1056 m_build_info.m_bloc_ny.add(o->n);
1057 m_build_info.m_bloc_py.add(o->progression);
1058 }
1059
1060 for( auto& o : options()->z() ){
1061 m_build_info.m_bloc_lz.add(o->length);
1062 m_build_info.m_bloc_nz.add(o->n);
1063 m_build_info.m_bloc_pz.add(o->progression);
1064 }
1065 }
1066
1068 {
1069 info() << "Cartesian3DMeshGenerator: allocateMeshItems()";
1071 g.setBuildInfo(m_build_info);
1072 g.generateMesh();
1073 }
1074
1076};
1077
1078ARCANE_REGISTER_SERVICE_CARTESIAN3DMESHGENERATOR(Cartesian3D,Cartesian3DMeshGenerator);
1079
1080/*---------------------------------------------------------------------------*/
1081/*---------------------------------------------------------------------------*/
1082
1083} // End namespace Arcane
1084
1085/*---------------------------------------------------------------------------*/
1086/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur le maillage.
ArcaneCartesian2DMeshGeneratorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsCartesian2DMeshGenerator * options() const
Options du jeu de données du service.
ArcaneCartesian3DMeshGeneratorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsCartesian3DMeshGenerator * options() const
Options du jeu de données du service.
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.
Int32 m_face_numbering_version
Version de l'algorithme de numérotation des faces.
Int32 m_edge_numbering_version
Version de l'algorithme de numérotation des arêtes.
virtual const MeshPartInfo & meshPartInfo() const =0
Informations sur les parties du maillage.
Paramètres nécessaires à la construction d'un maillage.
Classe gérant un vecteur réel 2-dimensionnel.
Classe gérant un vecteur réel de 3 dimensions.
Structure contenant les informations pour créer un service.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Positionne une classe de message.
Noeud d'un arbre DOM.
Definition XmlNode.h:51
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:337
Int32 Integer
Type représentant un entier.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:339
double Real
Type représentant un réel.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:345
std::int32_t Int32
Type entier signé sur 32 bits.
Real y
deuxième composante du couple
Real x
première composante du couple
Real y
deuxième composante du triplet
Real z
troisième composante du triplet
Real x
première composante du triplet