Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
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/* Cartesian mesh generation service. */
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 // Check that we have at least three x, y & z data and an origin
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 // Retrieve the origin
86 bool is_bad_origin = builtInGetValue(m_origine, origine_value);
87
88 // Check if we have a node in Z
89 if (lz_node_list.size() == 0) {
90 m_mesh_dimension = 2;
91 // In 2D, we allow the origin to have 2 components
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 // Retrieve the block lengths, + true for throw_exception
108 // Also retrieve the number of cells per block + true for throw_exception
109 // Also retrieve the geometric progressions
110 // Default progressions to 1.0
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 // Retrieve the number of sub-domains + 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/*---------------------------------------------------------------------------*/
205
209bool CartesianMeshGenerator::
210_readOptions()
211{
212 Trace::Setter mci(traceMng(), "CartesianMeshGenerator");
213
214 m_mesh_dimension = m_build_info.m_mesh_dimension;
215 Int32 nb_sub_domain = m_mesh->parallelMng()->commSize();
216
217 // Set default number of sub-domains
218 if (m_build_info.m_nsdx == 0 || nb_sub_domain == 1)
219 m_build_info.m_nsdx = 1;
220 if (m_build_info.m_nsdy == 0 || nb_sub_domain == 1)
221 m_build_info.m_nsdy = 1;
222 if (m_build_info.m_nsdz == 0 || nb_sub_domain == 1)
223 m_build_info.m_nsdz = 1;
224
225 // Sum up the block lengths
226 m_l.x = m_l.y = m_l.z = 0.;
227 for (int i = 0; i < m_build_info.m_bloc_lx.size(); i += 1)
228 m_l.x += m_build_info.m_bloc_lx.at(i);
229 for (int i = 0; i < m_build_info.m_bloc_ly.size(); i += 1)
230 m_l.y += m_build_info.m_bloc_ly.at(i);
231 if (m_mesh_dimension == 3)
232 for (int i = 0; i < m_build_info.m_bloc_lz.size(); i += 1)
233 m_l.z += m_build_info.m_bloc_lz.at(i);
234
235 // Sum up the origins for each block
236 m_bloc_ox.add(m_build_info.m_origine.x);
237 m_bloc_oy.add(m_build_info.m_origine.y);
238 if (m_mesh_dimension == 3)
239 m_bloc_oz.add(m_build_info.m_origine.z);
240 for (int i = 0; i < m_build_info.m_bloc_lx.size(); i += 1)
241 m_bloc_ox.add(m_bloc_ox.at(i) + m_build_info.m_bloc_lx.at(i));
242 for (int i = 0; i < m_build_info.m_bloc_ly.size(); i += 1)
243 m_bloc_oy.add(m_bloc_oy.at(i) + m_build_info.m_bloc_ly.at(i));
244 if (m_mesh_dimension == 3)
245 for (int i = 0; i < m_build_info.m_bloc_lz.size(); i += 1)
246 m_bloc_oz.add(m_bloc_oz.at(i) + m_build_info.m_bloc_lz.at(i));
247
248 // Sum up the number of cells per block and total
249 m_nx = m_ny = m_nz = 0;
250
251 for (int i = 0; i < m_build_info.m_bloc_nx.size(); ++i)
252 m_nx += m_build_info.m_bloc_nx.at(i);
253 for (int i = 0; i < m_build_info.m_bloc_ny.size(); ++i)
254 m_ny += m_build_info.m_bloc_ny.at(i);
255
256 if (m_mesh_dimension == 3)
257 for (int i = 0; i < m_build_info.m_bloc_nz.size(); i += 1)
258 m_nz += m_build_info.m_bloc_nz.at(i);
259 else
260 m_nz += 1;
261
262 // Dump the information retrieved so far
263 info() << " mesh_name=" << m_mesh->name();
264 info() << " dimension=" << m_mesh_dimension;
265 info() << " origin:" << m_build_info.m_origine;
266 info() << " length x =" << m_l.x << "," << m_build_info.m_bloc_lx;
267 info() << " length y=" << m_l.y << "," << m_build_info.m_bloc_ly;
268 if (m_build_info.m_mesh_dimension == 3)
269 info() << " length z=" << m_l.z << "," << m_build_info.m_bloc_lz;
270 info() << "cells number:" << m_nx << "x" << m_ny << "x" << m_nz;
271 info() << "progression x:" << m_build_info.m_bloc_px;
272 info() << "progression y:" << m_build_info.m_bloc_py;
273 if (m_mesh_dimension == 3)
274 info() << "progression z:" << m_build_info.m_bloc_pz;
275 info() << " nb_sub_domain:" << nb_sub_domain;
276 info() << " decomposing the subdomains:" << m_build_info.m_nsdx << "x"
277 << m_build_info.m_nsdy << "x" << m_build_info.m_nsdz;
278
279 // Check the number of subdomains vs what was specified
280 if (m_build_info.m_nsdx * m_build_info.m_nsdy * m_build_info.m_nsdz != nb_sub_domain)
281 ARCANE_FATAL("Specified partition {0}x{1}x{2} has to be equal to number of parts ({3})",
282 m_build_info.m_nsdx, m_build_info.m_nsdy, m_build_info.m_nsdz, nb_sub_domain);
283
284 return false; // false == ok
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289// ******************************************************************************
290// * sd[X|Y|Z]Offset
291// ******************************************************************************
292inline Integer CartesianMeshGenerator::
293sdXOffset(Int32 this_sub_domain_id)
294{
295 return this_sub_domain_id % m_build_info.m_nsdx;
296}
297
298inline Integer CartesianMeshGenerator::
299sdYOffset(Int32 this_sub_domain_id)
300{
301 return (this_sub_domain_id / m_build_info.m_nsdx) % m_build_info.m_nsdy;
302}
303
304inline Integer CartesianMeshGenerator::
305sdZOffset(Int32 this_sub_domain_id)
306{
307 return (this_sub_domain_id / (m_build_info.m_nsdx * m_build_info.m_nsdy)) % m_build_info.m_nsdz;
308}
309
310inline Integer CartesianMeshGenerator::
311sdXOffset()
312{
313 return sdXOffset(m_my_mesh_part);
314}
315
316inline Integer CartesianMeshGenerator::
317sdYOffset()
318{
319 return sdYOffset(m_my_mesh_part);
320}
321
322inline Integer CartesianMeshGenerator::
323sdZOffset()
324{
325 return sdZOffset(m_my_mesh_part);
326}
327
328/*---------------------------------------------------------------------------*/
329/*---------------------------------------------------------------------------*/
330// ******************************************************************************
331// * own[X|Y|Z]NbCell
332// ******************************************************************************
333inline Int32 ownNbCell(Int64 n, Integer nsd, int sd_offset)
334{
335 Int64 q = n / nsd;
336 Int64 r = n % nsd;
337 // If we are in 'first approach', there is no remainder
338 if (r == 0)
339 return CheckedConvert::toInt32(q);
340 // Otherwise, the remainder of cells is distributed among the last subdomains
341 if (sd_offset < (nsd - r))
342 return CheckedConvert::toInt32(q);
343 return CheckedConvert::toInt32(q + 1);
344}
345
346inline Int32 CartesianMeshGenerator::
347ownXNbCell()
348{
349 return ownNbCell(m_nx, m_build_info.m_nsdx, sdXOffset());
350}
351inline Int32 CartesianMeshGenerator::
352ownXNbCell(int isd)
353{
354 return ownNbCell(m_nx, m_build_info.m_nsdx, sdXOffset(isd));
355}
356inline Int32 CartesianMeshGenerator::
357ownYNbCell()
358{
359 return ownNbCell(m_ny, m_build_info.m_nsdy, sdYOffset());
360}
361inline Int32 CartesianMeshGenerator::
362ownYNbCell(int isd)
363{
364 return ownNbCell(m_ny, m_build_info.m_nsdy, sdYOffset(isd));
365}
366inline Int32 CartesianMeshGenerator::
367ownZNbCell()
368{
369 return ownNbCell(m_nz, m_build_info.m_nsdz, sdZOffset());
370}
371inline Int32 CartesianMeshGenerator::
372ownZNbCell(int isd)
373{
374 return ownNbCell(m_nz, m_build_info.m_nsdz, sdZOffset(isd));
375}
376
377// ******************************************************************************
378// * iProgression
379// ******************************************************************************
380inline Real
381iDelta(int iBloc,
382 const RealArray& bloc_p,
383 const Int32Array& bloc_n,
384 const RealArray& bloc_l,
385 const Real all_l,
386 const Int64 all_n)
387{
388 Real p = bloc_p.at(iBloc);
389 Real n = (Real)bloc_n.at(iBloc);
390 Real l = bloc_l.at(iBloc);
391 if (p <= 1.0)
392 return all_l / (Real)all_n;
393 return (p - 1.0) / (math::pow(p, n) - 1.0) * l;
394}
395
396inline Real
397kDelta(Real k,
398 int iBloc,
399 const RealArray& bloc_p,
400 const Int32Array& bloc_n,
401 const RealArray& bloc_l,
402 const Real all_l,
403 const Int64 all_n)
404{
405 ARCANE_UNUSED(all_l);
406 ARCANE_UNUSED(all_n);
407
408 Real p = bloc_p.at(iBloc);
409 Real n = (Real)bloc_n.at(iBloc);
410 Real l = bloc_l.at(iBloc);
411 if (p == 1.0)
412 return l * k / n;
413 return l * (math::pow(p, k) - 1.0) / (math::pow(p, (Real)n) - 1.0);
414}
415
416inline Real CartesianMeshGenerator::
417nxDelta(Real k, int iBloc)
418{
419 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);
420}
421inline Real CartesianMeshGenerator::
422xDelta(int iBloc)
423{
424 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);
425}
426
427inline Real CartesianMeshGenerator::
428nyDelta(Real k, int iBloc)
429{
430 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);
431}
432inline Real CartesianMeshGenerator::
433yDelta(int iBloc)
434{
435 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);
436}
437
438inline Real CartesianMeshGenerator::
439nzDelta(Real k, int iBloc)
440{
441 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);
442}
443
444inline Real CartesianMeshGenerator::
445zDelta(int iBloc)
446{
447 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);
448}
449
450/*---------------------------------------------------------------------------*/
451/*---------------------------------------------------------------------------*/
452// ******************************************************************************
453// * X scanning
454// ******************************************************************************
455void CartesianMeshGenerator::
456xScan(const Int64 all_nb_cell_x,
457 IntegerArray& sd_x_ibl,
458 IntegerArray& sd_x_obl,
459 Int64Array& sd_x_nbl,
460 Int64Array& sd_x_node_offset,
461 Int64Array& sd_x_cell_offset)
462{
463 sd_x_ibl.add(0);
464 sd_x_obl.add(0);
465 sd_x_nbl.add(0);
466 sd_x_node_offset.add(0);
467 sd_x_cell_offset.add(0);
468 // Reset des indices, offset et frontières
469 Int64 nsd = 0;
470 Integer isd = 0;
471 Integer ibl = 0;
472 Integer obl = 0;
473 Int64 nbl = 0;
474 for (Int64 x = 0; x < all_nb_cell_x; ++x) {
475 // Si on découvre la frontière d'un bloc
476 if (x == (nbl + m_build_info.m_bloc_nx.at(ibl))) {
477 nbl += m_build_info.m_bloc_nx.at(ibl);
478 info(4) << "\t␛[2;33m[CartesianMeshGenerator::xScan] Scan hit x bloc boundary: @ node " << nbl << "␛[0m";
479 // On saute de bloc
480 ibl += 1;
481 // On reset l'offset de calcul dans le bloc
482 obl = 0;
483 }
484 // Si on découvre la frontière d'un sous-domaine
485 if (x == (nsd + ownXNbCell(isd))) {
486 nsd += ownXNbCell(isd);
487 info(4) << "\t␛[2;33m[CartesianMeshGenerator::xScan] Scan hit x sub domain boundary: @ node " << nsd << "␛[0m";
488 // On sauvegarde les infos nécessaire à la reprise par sous-domaine
489 sd_x_ibl.add(ibl);
490 sd_x_obl.add(obl);
491 sd_x_nbl.add(nbl);
492 sd_x_node_offset.add(nsd);
493 sd_x_cell_offset.add(nsd);
494 isd += 1;
495 info(4) << "\t␛[2;33m[CartesianMeshGenerator::xScan] Saving state: "
496 << ", node_offset=" << sd_x_node_offset.at(isd)
497 << ", cell_offset=" << sd_x_cell_offset.at(isd)
498 << ", ibl=" << sd_x_ibl.at(isd)
499 << ", nbl=" << sd_x_nbl.at(isd) << "␛[0m";
500 }
501 // On incrémente l'offset de calcul dans le bloc
502 obl += 1;
503 }
504}
505
506/*---------------------------------------------------------------------------*/
507/*---------------------------------------------------------------------------*/
508// ******************************************************************************
509// * Y scanning
510// ******************************************************************************
511void CartesianMeshGenerator::
512yScan(const Integer all_nb_cell_y,
513 IntegerArray& sd_y_ibl,
514 IntegerArray& sd_y_obl,
515 Int64Array& sd_y_nbl,
516 Int64Array& sd_y_node_offset,
517 Int64Array& sd_y_cell_offset,
518 Int64 all_nb_node_x,
519 Int64 all_nb_cell_x)
520{
521 sd_y_ibl.add(0);
522 sd_y_obl.add(0);
523 sd_y_nbl.add(0);
524 sd_y_node_offset.add(0);
525 sd_y_cell_offset.add(0);
526 Int64 nsd = 0;
527 Integer isd = 0;
528 Integer ibl = 0;
529 Integer obl = 0;
530 Int64 nbl = 0;
531 for (Int64 y = 0; y < all_nb_cell_y; ++y) {
532 if (y == (nbl + m_build_info.m_bloc_ny.at(ibl))) {
533 nbl += m_build_info.m_bloc_ny.at(ibl);
534 info(4) << "\t␛[2;33m[CartesianMeshGenerator::generateMesh] Scan hit y bloc boundary: @ node " << nbl << "␛[0m";
535 ibl += 1;
536 obl = 0;
537 }
538 if (y == (nsd + ownYNbCell(isd))) {
539 nsd += ownYNbCell(isd);
540 info(4) << "\t␛[2;33m[CartesianMeshGenerator::generateMesh] Scan hit y sub domain boundary: @ node " << nsd << "␛[0m";
541 sd_y_ibl.add(ibl);
542 sd_y_obl.add(obl);
543 sd_y_nbl.add(nbl * all_nb_node_x);
544 sd_y_node_offset.add(nsd * all_nb_node_x);
545 sd_y_cell_offset.add(nsd * all_nb_cell_x);
546 isd += m_build_info.m_nsdx;
547 }
548 obl += 1;
549 }
550}
551
552/*---------------------------------------------------------------------------*/
553/*---------------------------------------------------------------------------*/
554// ******************************************************************************
555// * Z scanning
556// ******************************************************************************
557void CartesianMeshGenerator::
558zScan(const Int64 all_nb_cell_z,
559 IntegerArray& sd_z_ibl,
560 IntegerArray& sd_z_obl,
561 Int64Array& sd_z_nbl,
562 Int64Array& sd_z_node_offset,
563 Int64Array& sd_z_cell_offset,
564 Int64 all_nb_node_xy,
565 Int64 all_nb_cell_xy)
566{
567 if (m_mesh_dimension != 3)
568 return;
569 sd_z_ibl.add(0);
570 sd_z_obl.add(0);
571 sd_z_nbl.add(0);
572 sd_z_node_offset.add(0);
573 sd_z_cell_offset.add(0);
574 Int64 nsd = 0;
575 Integer isd = 0;
576 Integer ibl = 0;
577 Integer obl = 0;
578 Int64 nbl = 0;
579 for (Int64 z = 0; z < all_nb_cell_z; ++z) {
580 if (z == (nbl + m_build_info.m_bloc_nz.at(ibl))) {
581 nbl += m_build_info.m_bloc_nz.at(ibl);
582 ibl += 1;
583 obl = 0;
584 }
585 if (z == (nsd + ownZNbCell(isd))) {
586 nsd += ownZNbCell(isd);
587 sd_z_ibl.add(ibl);
588 sd_z_obl.add(obl);
589 sd_z_nbl.add(nbl * all_nb_node_xy);
590 sd_z_node_offset.add(nsd * all_nb_node_xy);
591 sd_z_cell_offset.add(nsd * all_nb_cell_xy);
592 isd += m_build_info.m_nsdx * m_build_info.m_nsdy;
593 }
594 obl += 1;
595 }
596}
597
598// ******************************************************************************
599// * generateMesh
600// ******************************************************************************
601
602bool CartesianMeshGenerator::
603generateMesh()
604{
605 Trace::Setter mci(traceMng(), "CartesianMeshGenerator");
606 IPrimaryMesh* mesh = m_mesh;
607
608 m_generation_info = ICartesianMeshGenerationInfo::getReference(mesh, true);
609
610 CartesianMeshAllocateBuildInfo cartesian_mesh_build_info(mesh);
611
612 info() << " decomposing the subdomains:" << m_build_info.m_nsdx << "x"
613 << m_build_info.m_nsdy << "x" << m_build_info.m_nsdz;
614 info() << "sub domain offset @ " << sdXOffset() << "x" << sdYOffset() << "x" << sdZOffset();
615 // All Cells Setup
616 Integer all_nb_cell_x = m_nx;
617 Integer all_nb_cell_y = m_ny;
618 Integer all_nb_cell_z = m_nz;
619 // Positionne des propriétés sur le maillage pour qu'il puisse connaître
620 // le nombre de mailles dans chaque direction ainsi que l'offset du sous-domaine.
621 // Cela est utilisé notammement par CartesianMesh.
622 //Properties* mesh_properties = mesh->properties();
623 m_generation_info->setGlobalNbCells(all_nb_cell_x, all_nb_cell_y, all_nb_cell_z);
624 m_generation_info->setSubDomainOffsets(sdXOffset(), sdYOffset(), sdZOffset());
625 m_generation_info->setNbSubDomains(m_build_info.m_nsdx, m_build_info.m_nsdy, m_build_info.m_nsdz);
626
627 m_generation_info->setGlobalOrigin(m_build_info.m_origine);
628 m_generation_info->setGlobalLength(m_l);
629
630 Int64 all_nb_cell_xy = ((Int64)all_nb_cell_x) * ((Int64)all_nb_cell_y);
631 Int64 all_nb_cell_xyz = ((Int64)all_nb_cell_xy) * ((Int64)all_nb_cell_z);
632 info() << " all cells: " << all_nb_cell_x << "x" << all_nb_cell_y << "y"
633 << all_nb_cell_z << "=" << all_nb_cell_xyz;
634
635 // Own Cells Setup
636 Int32 own_nb_cell_x = ownXNbCell();
637 Int32 own_nb_cell_y = ownYNbCell();
638 Int32 own_nb_cell_z = ownZNbCell();
639 m_generation_info->setOwnNbCells(own_nb_cell_x, own_nb_cell_y, own_nb_cell_z);
640 Integer own_nb_cell_xy = CheckedConvert::multiply(own_nb_cell_x, own_nb_cell_y);
641 Integer own_nb_cell_xyz = CheckedConvert::multiply(own_nb_cell_xy, own_nb_cell_z);
642 info() << " own cells: " << own_nb_cell_x << "x" << own_nb_cell_y << "y"
643 << own_nb_cell_z << "=" << own_nb_cell_xyz;
644
645 // All Nodes Setup
646 Integer all_nb_node_x = all_nb_cell_x + 1;
647 Integer all_nb_node_y = all_nb_cell_y + 1;
648 Int64 all_nb_node_xy = ((Int64)all_nb_node_x) * ((Int64)all_nb_node_y);
649
650 // Own Nodes Setup
651 Integer own_nb_node_x = own_nb_cell_x + 1;
652 Integer own_nb_node_y = own_nb_cell_y + 1;
653 Integer own_nb_node_z = (m_mesh_dimension == 3) ? own_nb_cell_z + 1 : own_nb_cell_z;
654 Integer own_nb_node_xy = CheckedConvert::multiply(own_nb_node_x, own_nb_node_y);
655 Integer own_nb_node_xyz = CheckedConvert::multiply(own_nb_node_xy, own_nb_node_z);
656 info() << " own nodes: "
657 << own_nb_node_x << "x"
658 << own_nb_node_y << "y"
659 << own_nb_node_z << "=" << own_nb_node_xyz;
660
661 // Création hash-table des noeuds et préparation de leurs uid
662 UniqueArray<Int64> nodes_unique_id(CheckedConvert::toInteger(own_nb_node_xyz));
663 // The size of a HashTableMapT is a number of buckets and not a number of
664 // entries: it rehashes as soon as its count passes 0.85 * nb_bucket, so the
665 // table is sized for the load factor and holds every node without rehashing.
666 const Int64 wanted_bucket = static_cast<Int64>(own_nb_node_xyz / 0.85) + 1;
667 HashTableMapT<Int64, NodeInfo> nodes_infos(CheckedConvert::toInteger(wanted_bucket), true);
668
669 // Calcule des infos blocs et des offset associés à tous les sub_domain_id
670 IntegerUniqueArray sd_x_ibl, sd_x_obl; // Numéro et offset dans le bloc
671 IntegerUniqueArray sd_y_ibl, sd_y_obl;
672 IntegerUniqueArray sd_z_ibl, sd_z_obl;
673 Int64UniqueArray sd_x_nbl, sd_y_nbl, sd_z_nbl; // Nombre dans le bloc
674 Int64UniqueArray sd_x_node_offset;
675 Int64UniqueArray sd_y_node_offset;
676 Int64UniqueArray sd_z_node_offset;
677 Int64UniqueArray sd_x_cell_offset;
678 Int64UniqueArray sd_y_cell_offset;
679 Int64UniqueArray sd_z_cell_offset;
680
681 // Scan des sous domaines: i_ème (isd) et n_ème (nsd) noeud pour marquer la frontière sous domaine
682 // Scan des des blocs: i_ème (ibl), o_ème offset (obl) et n_ème (nbl) noeud pour marquer la frontière bloc
683
684 // Selon la direction X
685 xScan(all_nb_cell_x,
686 sd_x_ibl, sd_x_obl, sd_x_nbl,
687 sd_x_node_offset, sd_x_cell_offset);
688
689 // Selon la direction Y
690 yScan(all_nb_cell_y,
691 sd_y_ibl, sd_y_obl, sd_y_nbl,
692 sd_y_node_offset, sd_y_cell_offset,
693 all_nb_node_x, all_nb_cell_x);
694
695 // Selon la direction Z
696 zScan(all_nb_cell_z,
697 sd_z_ibl, sd_z_obl, sd_z_nbl,
698 sd_z_node_offset, sd_z_cell_offset,
699 all_nb_node_xy, all_nb_cell_xy);
700
701 // Calcule pour les mailles l'offset global du début de la grille pour chaque direction.
702 Int64x3 first_own_cell_offset;
703 {
704 Int64 cell_offset_x = sd_x_cell_offset[sdXOffset()];
705 Int64 cell_offset_y = sd_y_cell_offset[sdYOffset()] / all_nb_cell_x;
706 Int64 cell_offset_z = 0;
707 if (m_mesh_dimension == 3) {
708 cell_offset_z = sd_z_cell_offset[sdZOffset()] / all_nb_cell_xy;
709 }
710 first_own_cell_offset = Int64x3(cell_offset_x, cell_offset_y, cell_offset_z);
711 info() << "OwnCellOffset info X=" << cell_offset_x << " Y=" << cell_offset_y << " Z=" << cell_offset_z;
712 m_generation_info->setOwnCellOffsets(cell_offset_x, cell_offset_y, cell_offset_z);
713 }
714 // IBL, NBL
715 info() << " sd_x_ibl=" << sd_x_ibl;
716 info() << " sd_x_obl=" << sd_x_obl;
717 info() << " sd_x_nbl=" << sd_x_nbl;
718
719 info() << " sd_y_ibl=" << sd_y_ibl;
720 info() << " sd_y_obl=" << sd_y_obl;
721 info() << " sd_y_nbl=" << sd_y_nbl;
722
723 info() << " sd_z_ibl=" << sd_z_ibl;
724 info() << " sd_z_obl=" << sd_z_obl;
725 info() << " sd_z_nbl=" << sd_z_nbl;
726
727 // NODE OFFSET
728 info() << " sd_x_node_offset=" << sd_x_node_offset;
729 info() << " sd_y_node_offset=" << sd_y_node_offset;
730 info() << " sd_z_node_offset=" << sd_z_node_offset;
731
732 // CELL OFFSET
733 info() << " sd_x_cell_offset=" << sd_x_cell_offset;
734 info() << " sd_y_cell_offset=" << sd_y_cell_offset;
735 info() << " sd_z_cell_offset=" << sd_z_cell_offset;
736
737 // We calculate the first node_local_id based on our sub_domain_id
738 Integer node_local_id = 0;
739 Int64 node_unique_id_offset = 0;
740 info() << " sdXOffset=" << sdXOffset()
741 << " sdYOffset=" << sdYOffset()
742 << " sdZOffset=" << sdZOffset();
743 // We calculate the x offset of node_unique_id
744 node_unique_id_offset += sd_x_node_offset.at(sdXOffset());
745 info() << " node_unique_id_offset=" << node_unique_id_offset;
746 // We calculate the y offset of node_unique_id
747 node_unique_id_offset += (sd_y_node_offset.at(sdYOffset()));
748 info() << " node_unique_id_offset=" << node_unique_id_offset;
749 if (m_mesh_dimension == 3) {
750 // We calculate the z offset of node_unique_id
751 node_unique_id_offset += (sd_z_node_offset.at(sdZOffset()));
752 info() << " node_unique_id_offset=" << node_unique_id_offset;
753 }
754
755 Integer z_ibl = 0;
756 Integer z_obl = 0;
757 Int64 z_nbl = 0;
758 if (m_mesh_dimension == 3) {
759 z_ibl = sd_z_ibl.at(sdZOffset());
760 z_obl = sd_z_obl.at(sdZOffset());
761 z_nbl = sd_z_nbl.at(sdZOffset());
762 }
763 for (Int64 z = 0; z < own_nb_node_z; ++z) {
764 if (m_mesh_dimension == 3) {
765 // Skip the possible last bl boundary coinciding with the sd
766 // And if we discover a block boundary, we reset the origins
767 if (((z + 1) != own_nb_node_z) &&
768 ((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))) {
769 info() << " Creation hit z bloc boundarz: @ node " << z;
770 z_nbl += m_build_info.m_bloc_nz.at(z_ibl) * all_nb_node_xy;
771 // Increment by block
772 z_ibl += 1;
773 z_obl = 0;
774 }
775 }
776 Real nz = 0.0;
777 if (m_mesh_dimension == 3)
778 nz = nzDelta(z_obl, z_ibl);
779 Integer y_ibl = sd_y_ibl.at(sdYOffset());
780 Integer y_obl = sd_y_obl.at(sdYOffset());
781 Int64 y_nbl = sd_y_nbl.at(sdYOffset());
782 for (Int64 y = 0; y < own_nb_node_y; ++y) {
783 // Skip the possible last bl boundary coinciding with the sd
784 // And if we discover a block boundary, we reset the origins
785 if (((y + 1) != own_nb_node_y) &&
786 ((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))) {
787 info() << " Creation hit y bloc boundary: @ node " << y;
788 y_nbl += m_build_info.m_bloc_ny.at(y_ibl) * all_nb_node_x;
789 // Increment by block
790 y_ibl += 1;
791 y_obl = 0;
792 }
793 Real ny = nyDelta(y_obl, y_ibl);
794 // Retrieve the current block number
795 Integer x_ibl = sd_x_ibl.at(sdXOffset());
796 // Retrieve the offset within the current block
797 Integer x_obl = sd_x_obl.at(sdXOffset());
798 // Retrieve the number of nodes in the current block
799 Int64 x_nbl = sd_x_nbl.at(sdXOffset());
800 for (Int64 x = 0; x < own_nb_node_x; ++x) {
801 Int64 node_unique_id = node_unique_id_offset + x + y * all_nb_node_x + z * all_nb_node_xy;
802 nodes_unique_id[node_local_id] = node_unique_id;
803 Int32 owner = m_my_mesh_part;
804 // If we are not on a boundary sd
805 // And if we touch the edge nodes of the boundary sd
806 if (((sdXOffset() + 1) != m_build_info.m_nsdx) && ((x + 1) == own_nb_node_x))
807 owner += 1;
808 if (((sdYOffset() + 1) != m_build_info.m_nsdy) && ((y + 1) == own_nb_node_y))
809 owner += m_build_info.m_nsdx;
810 if (((sdZOffset() + 1) != m_build_info.m_nsdz) && ((z + 1) == own_nb_node_z))
811 owner += m_build_info.m_nsdx * m_build_info.m_nsdy;
812 // Skip the possible last bl boundary coinciding with the sd
813 // And if we discover a block boundary, we reset the origins
814 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)))) {
815 info() << " Creation hit x bloc boundary: @ node " << x;
816 x_nbl += m_build_info.m_bloc_nx.at(x_ibl);
817 // Increment by block
818 x_ibl += 1;
819 x_obl = 0;
820 }
821 Real nx = nxDelta(x_obl, x_ibl);
822 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] node @ "<<x<<"x"<<y<<"x"<<z
823 <<":"<< ", uid=" << node_unique_id<< ", owned by " << owner
824 << ", ␛[1;32m coords=("<<nx<<","<<ny<<","<<nz<<")"<<"␛[0m";*/
825 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
826 node_local_id += 1;
827 x_obl += 1;
828 }
829 y_obl += 1;
830 }
831 z_obl += 1;
832 }
833
834 // Cell creation
835 // Info for cell creation
836 // per cell: 1 for its unique id,
837 // 1 for its type,
838 // 8 for each node
839 Int64 cell_unique_id_offset = 0;
840 // We calculate the x offset of cell_unique_id
841 cell_unique_id_offset += sd_x_cell_offset.at(sdXOffset());
842 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
843 // We calculate the y offset of cell_unique_id
844 cell_unique_id_offset += sd_y_cell_offset.at(sdYOffset());
845 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
846 if (m_mesh_dimension == 3) {
847 // We calculate the z offset of cell_unique_id
848 cell_unique_id_offset += sd_z_cell_offset.at(sdZOffset());
849 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
850 }
851 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
852 m_generation_info->setFirstOwnCellUniqueId(cell_unique_id_offset);
853
854 const Int32 face_numbering_version = m_build_info.m_face_numbering_version;
855 info() << "FaceNumberingVersion = " << face_numbering_version;
856 const Int32 edge_numbering_version = m_build_info.m_edge_numbering_version;
857 info() << "EdgeNumberingVersion = " << edge_numbering_version;
858
859 {
860 info() << "Set Specific info for cartesian mesh";
861 if (m_mesh_dimension == 3)
862 cartesian_mesh_build_info.setInfos3D({ all_nb_cell_x, all_nb_cell_y, all_nb_cell_z },
863 { own_nb_cell_x, own_nb_cell_y, own_nb_cell_z },
864 { first_own_cell_offset.x, first_own_cell_offset.y, first_own_cell_offset.z },
865 0);
866 else if (m_mesh_dimension == 2) {
867 cartesian_mesh_build_info.setInfos2D({ all_nb_cell_x, all_nb_cell_y },
868 { own_nb_cell_x, own_nb_cell_y },
869 { first_own_cell_offset.x, first_own_cell_offset.y },
870 0);
871 }
872 else
873 ARCANE_FATAL("Invalid dimensionn '{0}' (valid values are 2 or 3)", m_mesh_dimension);
874
875 if (face_numbering_version >= 0)
876 cartesian_mesh_build_info._internal()->setFaceBuilderVersion(face_numbering_version);
877 if (edge_numbering_version >= 0)
878 cartesian_mesh_build_info._internal()->setEdgeBuilderVersion(edge_numbering_version);
879 }
880
881 cartesian_mesh_build_info.allocateMesh();
882
883 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
884 {
885 info() << "Fills the variable containing the coordinates of the nodes";
886 Int32UniqueArray nodes_local_id(nodes_unique_id.size());
887 IItemFamily* family = mesh->nodeFamily();
888 family->itemsUniqueIdToLocalId(nodes_local_id, nodes_unique_id);
889 NodeInfoListView nodes_internal(family);
890 for (Integer i = 0; i < node_local_id; ++i) {
891 Node node = nodes_internal[nodes_local_id[i]];
892 Int64 unique_id = nodes_unique_id[i];
893 nodes_coord_var[node] = nodes_infos.lookupValue(unique_id).m_coord;
894 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] Set coord "
895 << ItemPrinter(node) << " coord=" << nodes_coord_var[node]<< "␛[0m";*/
896 }
897 }
898 nodes_coord_var.synchronize();
899
900 // Create groups corresponding to the mesh edges
901 // If requested, we also create groups to test a Sod shock tube.
902 {
903 SodStandardGroupsBuilder groups_builder(traceMng());
904 Real3 origin = m_build_info.m_origine;
905 Real3 length(m_l.x, m_l.y, m_l.z);
906 Real3 max_pos = origin + length;
907 // TODO: Since there can be geometric progressions, we must define
908 // the middle based on the position of the offset cell the middle
909 // and not from the coordinates
910 // Calculate middle_x as the middle position
911 bool do_zg_and_zd = m_build_info.m_is_generate_sod_groups;
912 Real middle_x = (origin.x + max_pos.x) / 2.0;
913 Real middle_height = (origin.y + max_pos.y) / 2.0;
914 groups_builder.generateGroups(mesh, origin, origin + length, middle_x, middle_height, do_zg_and_zd);
915 }
916
917 return false; // false == ok
918}
919
920/*---------------------------------------------------------------------------*/
921/*---------------------------------------------------------------------------*/
922
923/*---------------------------------------------------------------------------*/
924/*---------------------------------------------------------------------------*/
925
929class Cartesian2DMeshGenerator
931{
932 public:
933
934 explicit Cartesian2DMeshGenerator(const ServiceBuildInfo& sbi)
936 {}
937
938 public:
939
940 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
941 {
942 ARCANE_UNUSED(build_info);
943 info() << "Cartesian2DMeshGenerator: fillMeshBuildInfo()";
944 m_build_info.m_nsdx = options()->nbPartX();
945 m_build_info.m_nsdy = options()->nbPartY();
946
947 m_build_info.m_mesh_dimension = 2;
948 Real2 origin = options()->origin;
949 m_build_info.m_origine.x = origin.x;
950 m_build_info.m_origine.y = origin.y;
951 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
952 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
953
954 for (auto& o : options()->x()) {
955 m_build_info.m_bloc_lx.add(o->length);
956 m_build_info.m_bloc_nx.add(o->n);
957 m_build_info.m_bloc_px.add(o->progression);
958 }
959
960 for (auto& o : options()->y()) {
961 m_build_info.m_bloc_ly.add(o->length);
962 m_build_info.m_bloc_ny.add(o->n);
963 m_build_info.m_bloc_py.add(o->progression);
964 }
965 }
966
968 {
969 info() << "Cartesian2DMeshGenerator: allocateMeshItems()";
971 // Check if the partitioning needs to be calculated dynamically
972 auto [x, y] = _computePartition(pm, m_build_info.m_nsdx, m_build_info.m_nsdy);
973 m_build_info.m_nsdx = x;
974 m_build_info.m_nsdy = y;
975 g.setBuildInfo(m_build_info);
976 g.generateMesh();
977 }
978
979 private:
980
982
983 static std::tuple<Integer, Integer>
984 _computePartition(IPrimaryMesh* pm, Integer nb_x, Integer nb_y)
985 {
986 Int32 nb_part = pm->meshPartInfo().nbPart();
987 // In sequential mode, it does not take into account the dataset values.
988 if (nb_part == 1)
989 return { 1, 1 };
990 // If the partitioning in X and Y is specified, use it directly.
991 if (nb_x != 0 && nb_y != 0)
992 return { nb_x, nb_y };
993 // No partitioning specified. math::sqrt(nb_part)
994 // must be an integer
995 if (nb_x == 0 && nb_y == 0) {
996 double s = math::sqrt((double)(nb_part));
997 Integer s_int = (Integer)(::floor(s));
998 if ((s_int * s_int) != nb_part)
999 ARCANE_FATAL("Invalid number of part '{0}' for automatic partitioning: sqrt({1}) is not an integer",
1000 nb_part, nb_part);
1001 return { s_int, s_int };
1002 }
1003 // Here, one of the two partitions is not specified.
1004 if (nb_x == 0) {
1005 if ((nb_part % nb_y) != 0)
1006 ARCANE_FATAL("Invalid number of Y part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
1007 nb_y, nb_part, nb_y);
1008 nb_x = nb_part / nb_y;
1009 }
1010 else {
1011 if ((nb_part % nb_x) != 0)
1012 ARCANE_FATAL("Invalid number of X part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
1013 nb_x, nb_part, nb_x);
1014 nb_y = nb_part / nb_x;
1015 }
1016 return { nb_x, nb_y };
1017 }
1018};
1019
1020ARCANE_REGISTER_SERVICE_CARTESIAN2DMESHGENERATOR(Cartesian2D, Cartesian2DMeshGenerator);
1021
1022/*---------------------------------------------------------------------------*/
1023/*---------------------------------------------------------------------------*/
1024
1028class Cartesian3DMeshGenerator
1030{
1031 public:
1032
1033 Cartesian3DMeshGenerator(const ServiceBuildInfo& sbi)
1035 {}
1036
1037 public:
1038
1039 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1040 {
1041 ARCANE_UNUSED(build_info);
1042 info() << "Cartesian3DMeshGenerator: fillMeshBuildInfo()";
1043 m_build_info.m_nsdx = options()->nbPartX();
1044 m_build_info.m_nsdy = options()->nbPartY();
1045 m_build_info.m_nsdz = options()->nbPartZ();
1046
1047 m_build_info.m_mesh_dimension = 3;
1048 Real3 origin = options()->origin;
1049 m_build_info.m_origine.x = origin.x;
1050 m_build_info.m_origine.y = origin.y;
1051 m_build_info.m_origine.z = origin.z;
1052 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
1053 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
1054 m_build_info.m_edge_numbering_version = options()->edgeNumberingVersion();
1055
1056 for (auto& o : options()->x()) {
1057 m_build_info.m_bloc_lx.add(o->length);
1058 m_build_info.m_bloc_nx.add(o->n);
1059 m_build_info.m_bloc_px.add(o->progression);
1060 }
1061
1062 for (auto& o : options()->y()) {
1063 m_build_info.m_bloc_ly.add(o->length);
1064 m_build_info.m_bloc_ny.add(o->n);
1065 m_build_info.m_bloc_py.add(o->progression);
1066 }
1067
1068 for (auto& o : options()->z()) {
1069 m_build_info.m_bloc_lz.add(o->length);
1070 m_build_info.m_bloc_nz.add(o->n);
1071 m_build_info.m_bloc_pz.add(o->progression);
1072 }
1073 }
1074
1076 {
1077 info() << "Cartesian3DMeshGenerator: allocateMeshItems()";
1079 g.setBuildInfo(m_build_info);
1080 g.generateMesh();
1081 }
1082
1084};
1085
1086/*---------------------------------------------------------------------------*/
1087/*---------------------------------------------------------------------------*/
1088
1089ARCANE_REGISTER_SERVICE_CARTESIAN3DMESHGENERATOR(Cartesian3D, Cartesian3DMeshGenerator);
1090
1091/*---------------------------------------------------------------------------*/
1092/*---------------------------------------------------------------------------*/
1093
1094} // End namespace Arcane
1095
1096/*---------------------------------------------------------------------------*/
1097/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Utility functions for the mesh.
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
Fills build_info with the necessary information to create the mesh.
void allocateMeshItems(IPrimaryMesh *pm) override
Allocates the mesh entities managed by this service.
void allocateMeshItems(IPrimaryMesh *pm) override
Allocates the mesh entities managed by this service.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Fills build_info with the necessary information to create the mesh.
Int32 m_face_numbering_version
Version of the face numbering algorithm.
Int32 m_edge_numbering_version
Version of the edge numbering algorithm.
virtual const MeshPartInfo & meshPartInfo() const =0
Mesh part information.
Parameters necessary for building a mesh.
Class managing a 2-dimensional real vector.
Class managing a 3-dimensional real vector.
Structure containing the information to create a service.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
Node of a DOM tree.
Definition XmlNode.h:51
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:333
Int32 Integer
Type representing an integer.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
double Real
Type representing a real number.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:341
std::int32_t Int32
Signed integer type of 32 bits.
Real y
second component of the pair
Real x
first component of the pair
Real y
second component of the triplet
Real z
third component of the triplet
Real x
first component of the triplet