Arcane  4.1.12.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 HashTableMapT<Int64, NodeInfo> nodes_infos(CheckedConvert::toInteger(own_nb_node_xyz), true);
664
665 // Calcule des infos blocs et des offset associés à tous les sub_domain_id
666 IntegerUniqueArray sd_x_ibl, sd_x_obl; // Numéro et offset dans le bloc
667 IntegerUniqueArray sd_y_ibl, sd_y_obl;
668 IntegerUniqueArray sd_z_ibl, sd_z_obl;
669 Int64UniqueArray sd_x_nbl, sd_y_nbl, sd_z_nbl; // Nombre dans le bloc
670 Int64UniqueArray sd_x_node_offset;
671 Int64UniqueArray sd_y_node_offset;
672 Int64UniqueArray sd_z_node_offset;
673 Int64UniqueArray sd_x_cell_offset;
674 Int64UniqueArray sd_y_cell_offset;
675 Int64UniqueArray sd_z_cell_offset;
676
677 // Scan des sous domaines: i_ème (isd) et n_ème (nsd) noeud pour marquer la frontière sous domaine
678 // Scan des des blocs: i_ème (ibl), o_ème offset (obl) et n_ème (nbl) noeud pour marquer la frontière bloc
679
680 // Selon la direction X
681 xScan(all_nb_cell_x,
682 sd_x_ibl, sd_x_obl, sd_x_nbl,
683 sd_x_node_offset, sd_x_cell_offset);
684
685 // Selon la direction Y
686 yScan(all_nb_cell_y,
687 sd_y_ibl, sd_y_obl, sd_y_nbl,
688 sd_y_node_offset, sd_y_cell_offset,
689 all_nb_node_x, all_nb_cell_x);
690
691 // Selon la direction Z
692 zScan(all_nb_cell_z,
693 sd_z_ibl, sd_z_obl, sd_z_nbl,
694 sd_z_node_offset, sd_z_cell_offset,
695 all_nb_node_xy, all_nb_cell_xy);
696
697 // Calcule pour les mailles l'offset global du début de la grille pour chaque direction.
698 Int64x3 first_own_cell_offset;
699 {
700 Int64 cell_offset_x = sd_x_cell_offset[sdXOffset()];
701 Int64 cell_offset_y = sd_y_cell_offset[sdYOffset()] / all_nb_cell_x;
702 Int64 cell_offset_z = 0;
703 if (m_mesh_dimension == 3) {
704 cell_offset_z = sd_z_cell_offset[sdZOffset()] / all_nb_cell_xy;
705 }
706 first_own_cell_offset = Int64x3(cell_offset_x, cell_offset_y, cell_offset_z);
707 info() << "OwnCellOffset info X=" << cell_offset_x << " Y=" << cell_offset_y << " Z=" << cell_offset_z;
708 m_generation_info->setOwnCellOffsets(cell_offset_x, cell_offset_y, cell_offset_z);
709 }
710 // IBL, NBL
711 info() << " sd_x_ibl=" << sd_x_ibl;
712 info() << " sd_x_obl=" << sd_x_obl;
713 info() << " sd_x_nbl=" << sd_x_nbl;
714
715 info() << " sd_y_ibl=" << sd_y_ibl;
716 info() << " sd_y_obl=" << sd_y_obl;
717 info() << " sd_y_nbl=" << sd_y_nbl;
718
719 info() << " sd_z_ibl=" << sd_z_ibl;
720 info() << " sd_z_obl=" << sd_z_obl;
721 info() << " sd_z_nbl=" << sd_z_nbl;
722
723 // NODE OFFSET
724 info() << " sd_x_node_offset=" << sd_x_node_offset;
725 info() << " sd_y_node_offset=" << sd_y_node_offset;
726 info() << " sd_z_node_offset=" << sd_z_node_offset;
727
728 // CELL OFFSET
729 info() << " sd_x_cell_offset=" << sd_x_cell_offset;
730 info() << " sd_y_cell_offset=" << sd_y_cell_offset;
731 info() << " sd_z_cell_offset=" << sd_z_cell_offset;
732
733 // We calculate the first node_local_id based on our sub_domain_id
734 Integer node_local_id = 0;
735 Int64 node_unique_id_offset = 0;
736 info() << " sdXOffset=" << sdXOffset()
737 << " sdYOffset=" << sdYOffset()
738 << " sdZOffset=" << sdZOffset();
739 // We calculate the x offset of node_unique_id
740 node_unique_id_offset += sd_x_node_offset.at(sdXOffset());
741 info() << " node_unique_id_offset=" << node_unique_id_offset;
742 // We calculate the y offset of node_unique_id
743 node_unique_id_offset += (sd_y_node_offset.at(sdYOffset()));
744 info() << " node_unique_id_offset=" << node_unique_id_offset;
745 if (m_mesh_dimension == 3) {
746 // We calculate the z offset of node_unique_id
747 node_unique_id_offset += (sd_z_node_offset.at(sdZOffset()));
748 info() << " node_unique_id_offset=" << node_unique_id_offset;
749 }
750
751 Integer z_ibl = 0;
752 Integer z_obl = 0;
753 Int64 z_nbl = 0;
754 if (m_mesh_dimension == 3) {
755 z_ibl = sd_z_ibl.at(sdZOffset());
756 z_obl = sd_z_obl.at(sdZOffset());
757 z_nbl = sd_z_nbl.at(sdZOffset());
758 }
759 for (Int64 z = 0; z < own_nb_node_z; ++z) {
760 if (m_mesh_dimension == 3) {
761 // Skip the possible last bl boundary coinciding with the sd
762 // And if we discover a block boundary, we reset the origins
763 if (((z + 1) != own_nb_node_z) &&
764 ((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))) {
765 info() << " Creation hit z bloc boundarz: @ node " << z;
766 z_nbl += m_build_info.m_bloc_nz.at(z_ibl) * all_nb_node_xy;
767 // Increment by block
768 z_ibl += 1;
769 z_obl = 0;
770 }
771 }
772 Real nz = 0.0;
773 if (m_mesh_dimension == 3)
774 nz = nzDelta(z_obl, z_ibl);
775 Integer y_ibl = sd_y_ibl.at(sdYOffset());
776 Integer y_obl = sd_y_obl.at(sdYOffset());
777 Int64 y_nbl = sd_y_nbl.at(sdYOffset());
778 for (Int64 y = 0; y < own_nb_node_y; ++y) {
779 // Skip the possible last bl boundary coinciding with the sd
780 // And if we discover a block boundary, we reset the origins
781 if (((y + 1) != own_nb_node_y) &&
782 ((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))) {
783 info() << " Creation hit y bloc boundary: @ node " << y;
784 y_nbl += m_build_info.m_bloc_ny.at(y_ibl) * all_nb_node_x;
785 // Increment by block
786 y_ibl += 1;
787 y_obl = 0;
788 }
789 Real ny = nyDelta(y_obl, y_ibl);
790 // Retrieve the current block number
791 Integer x_ibl = sd_x_ibl.at(sdXOffset());
792 // Retrieve the offset within the current block
793 Integer x_obl = sd_x_obl.at(sdXOffset());
794 // Retrieve the number of nodes in the current block
795 Int64 x_nbl = sd_x_nbl.at(sdXOffset());
796 for (Int64 x = 0; x < own_nb_node_x; ++x) {
797 Int64 node_unique_id = node_unique_id_offset + x + y * all_nb_node_x + z * all_nb_node_xy;
798 nodes_unique_id[node_local_id] = node_unique_id;
799 Int32 owner = m_my_mesh_part;
800 // If we are not on a boundary sd
801 // And if we touch the edge nodes of the boundary sd
802 if (((sdXOffset() + 1) != m_build_info.m_nsdx) && ((x + 1) == own_nb_node_x))
803 owner += 1;
804 if (((sdYOffset() + 1) != m_build_info.m_nsdy) && ((y + 1) == own_nb_node_y))
805 owner += m_build_info.m_nsdx;
806 if (((sdZOffset() + 1) != m_build_info.m_nsdz) && ((z + 1) == own_nb_node_z))
807 owner += m_build_info.m_nsdx * m_build_info.m_nsdy;
808 // Skip the possible last bl boundary coinciding with the sd
809 // And if we discover a block boundary, we reset the origins
810 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)))) {
811 info() << " Creation hit x bloc boundary: @ node " << x;
812 x_nbl += m_build_info.m_bloc_nx.at(x_ibl);
813 // Increment by block
814 x_ibl += 1;
815 x_obl = 0;
816 }
817 Real nx = nxDelta(x_obl, x_ibl);
818 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] node @ "<<x<<"x"<<y<<"x"<<z
819 <<":"<< ", uid=" << node_unique_id<< ", owned by " << owner
820 << ", ␛[1;32m coords=("<<nx<<","<<ny<<","<<nz<<")"<<"␛[0m";*/
821 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
822 node_local_id += 1;
823 x_obl += 1;
824 }
825 y_obl += 1;
826 }
827 z_obl += 1;
828 }
829
830 // Cell creation
831 // Info for cell creation
832 // per cell: 1 for its unique id,
833 // 1 for its type,
834 // 8 for each node
835 Int64 cell_unique_id_offset = 0;
836 // We calculate the x offset of cell_unique_id
837 cell_unique_id_offset += sd_x_cell_offset.at(sdXOffset());
838 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
839 // We calculate the y offset of cell_unique_id
840 cell_unique_id_offset += sd_y_cell_offset.at(sdYOffset());
841 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
842 if (m_mesh_dimension == 3) {
843 // We calculate the z offset of cell_unique_id
844 cell_unique_id_offset += sd_z_cell_offset.at(sdZOffset());
845 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
846 }
847 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
848 m_generation_info->setFirstOwnCellUniqueId(cell_unique_id_offset);
849
850 const Int32 face_numbering_version = m_build_info.m_face_numbering_version;
851 info() << "FaceNumberingVersion = " << face_numbering_version;
852 const Int32 edge_numbering_version = m_build_info.m_edge_numbering_version;
853 info() << "EdgeNumberingVersion = " << edge_numbering_version;
854
855 {
856 info() << "Set Specific info for cartesian mesh";
857 if (m_mesh_dimension == 3)
858 cartesian_mesh_build_info.setInfos3D({ all_nb_cell_x, all_nb_cell_y, all_nb_cell_z },
859 { own_nb_cell_x, own_nb_cell_y, own_nb_cell_z },
860 { first_own_cell_offset.x, first_own_cell_offset.y, first_own_cell_offset.z },
861 0);
862 else if (m_mesh_dimension == 2) {
863 cartesian_mesh_build_info.setInfos2D({ all_nb_cell_x, all_nb_cell_y },
864 { own_nb_cell_x, own_nb_cell_y },
865 { first_own_cell_offset.x, first_own_cell_offset.y },
866 0);
867 }
868 else
869 ARCANE_FATAL("Invalid dimensionn '{0}' (valid values are 2 or 3)", m_mesh_dimension);
870
871 if (face_numbering_version >= 0)
872 cartesian_mesh_build_info._internal()->setFaceBuilderVersion(face_numbering_version);
873 if (edge_numbering_version >= 0)
874 cartesian_mesh_build_info._internal()->setEdgeBuilderVersion(edge_numbering_version);
875 }
876
877 cartesian_mesh_build_info.allocateMesh();
878
879 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
880 {
881 info() << "Fills the variable containing the coordinates of the nodes";
882 Int32UniqueArray nodes_local_id(nodes_unique_id.size());
883 IItemFamily* family = mesh->nodeFamily();
884 family->itemsUniqueIdToLocalId(nodes_local_id, nodes_unique_id);
885 NodeInfoListView nodes_internal(family);
886 for (Integer i = 0; i < node_local_id; ++i) {
887 Node node = nodes_internal[nodes_local_id[i]];
888 Int64 unique_id = nodes_unique_id[i];
889 nodes_coord_var[node] = nodes_infos.lookupValue(unique_id).m_coord;
890 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] Set coord "
891 << ItemPrinter(node) << " coord=" << nodes_coord_var[node]<< "␛[0m";*/
892 }
893 }
894 nodes_coord_var.synchronize();
895
896 // Create groups corresponding to the mesh edges
897 // If requested, we also create groups to test a Sod shock tube.
898 {
899 SodStandardGroupsBuilder groups_builder(traceMng());
900 Real3 origin = m_build_info.m_origine;
901 Real3 length(m_l.x, m_l.y, m_l.z);
902 Real3 max_pos = origin + length;
903 // TODO: Since there can be geometric progressions, we must define
904 // the middle based on the position of the offset cell the middle
905 // and not from the coordinates
906 // Calculate middle_x as the middle position
907 bool do_zg_and_zd = m_build_info.m_is_generate_sod_groups;
908 Real middle_x = (origin.x + max_pos.x) / 2.0;
909 Real middle_height = (origin.y + max_pos.y) / 2.0;
910 groups_builder.generateGroups(mesh, origin, origin + length, middle_x, middle_height, do_zg_and_zd);
911 }
912
913 return false; // false == ok
914}
915
916/*---------------------------------------------------------------------------*/
917/*---------------------------------------------------------------------------*/
918
919/*---------------------------------------------------------------------------*/
920/*---------------------------------------------------------------------------*/
921
925class Cartesian2DMeshGenerator
927{
928 public:
929
930 explicit Cartesian2DMeshGenerator(const ServiceBuildInfo& sbi)
932 {}
933
934 public:
935
936 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
937 {
938 ARCANE_UNUSED(build_info);
939 info() << "Cartesian2DMeshGenerator: fillMeshBuildInfo()";
940 m_build_info.m_nsdx = options()->nbPartX();
941 m_build_info.m_nsdy = options()->nbPartY();
942
943 m_build_info.m_mesh_dimension = 2;
944 Real2 origin = options()->origin;
945 m_build_info.m_origine.x = origin.x;
946 m_build_info.m_origine.y = origin.y;
947 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
948 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
949
950 for (auto& o : options()->x()) {
951 m_build_info.m_bloc_lx.add(o->length);
952 m_build_info.m_bloc_nx.add(o->n);
953 m_build_info.m_bloc_px.add(o->progression);
954 }
955
956 for (auto& o : options()->y()) {
957 m_build_info.m_bloc_ly.add(o->length);
958 m_build_info.m_bloc_ny.add(o->n);
959 m_build_info.m_bloc_py.add(o->progression);
960 }
961 }
962
964 {
965 info() << "Cartesian2DMeshGenerator: allocateMeshItems()";
967 // Check if the partitioning needs to be calculated dynamically
968 auto [x, y] = _computePartition(pm, m_build_info.m_nsdx, m_build_info.m_nsdy);
969 m_build_info.m_nsdx = x;
970 m_build_info.m_nsdy = y;
971 g.setBuildInfo(m_build_info);
972 g.generateMesh();
973 }
974
975 private:
976
978
979 static std::tuple<Integer, Integer>
980 _computePartition(IPrimaryMesh* pm, Integer nb_x, Integer nb_y)
981 {
982 Int32 nb_part = pm->meshPartInfo().nbPart();
983 // In sequential mode, it does not take into account the dataset values.
984 if (nb_part == 1)
985 return { 1, 1 };
986 // If the partitioning in X and Y is specified, use it directly.
987 if (nb_x != 0 && nb_y != 0)
988 return { nb_x, nb_y };
989 // No partitioning specified. math::sqrt(nb_part)
990 // must be an integer
991 if (nb_x == 0 && nb_y == 0) {
992 double s = math::sqrt((double)(nb_part));
993 Integer s_int = (Integer)(::floor(s));
994 if ((s_int * s_int) != nb_part)
995 ARCANE_FATAL("Invalid number of part '{0}' for automatic partitioning: sqrt({1}) is not an integer",
996 nb_part, nb_part);
997 return { s_int, s_int };
998 }
999 // Here, one of the two partitions is not specified.
1000 if (nb_x == 0) {
1001 if ((nb_part % nb_y) != 0)
1002 ARCANE_FATAL("Invalid number of Y part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
1003 nb_y, nb_part, nb_y);
1004 nb_x = nb_part / nb_y;
1005 }
1006 else {
1007 if ((nb_part % nb_x) != 0)
1008 ARCANE_FATAL("Invalid number of X part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
1009 nb_x, nb_part, nb_x);
1010 nb_y = nb_part / nb_x;
1011 }
1012 return { nb_x, nb_y };
1013 }
1014};
1015
1016ARCANE_REGISTER_SERVICE_CARTESIAN2DMESHGENERATOR(Cartesian2D, Cartesian2DMeshGenerator);
1017
1018/*---------------------------------------------------------------------------*/
1019/*---------------------------------------------------------------------------*/
1020
1024class Cartesian3DMeshGenerator
1026{
1027 public:
1028
1029 Cartesian3DMeshGenerator(const ServiceBuildInfo& sbi)
1031 {}
1032
1033 public:
1034
1035 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1036 {
1037 ARCANE_UNUSED(build_info);
1038 info() << "Cartesian3DMeshGenerator: fillMeshBuildInfo()";
1039 m_build_info.m_nsdx = options()->nbPartX();
1040 m_build_info.m_nsdy = options()->nbPartY();
1041 m_build_info.m_nsdz = options()->nbPartZ();
1042
1043 m_build_info.m_mesh_dimension = 3;
1044 Real3 origin = options()->origin;
1045 m_build_info.m_origine.x = origin.x;
1046 m_build_info.m_origine.y = origin.y;
1047 m_build_info.m_origine.z = origin.z;
1048 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
1049 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
1050 m_build_info.m_edge_numbering_version = options()->edgeNumberingVersion();
1051
1052 for (auto& o : options()->x()) {
1053 m_build_info.m_bloc_lx.add(o->length);
1054 m_build_info.m_bloc_nx.add(o->n);
1055 m_build_info.m_bloc_px.add(o->progression);
1056 }
1057
1058 for (auto& o : options()->y()) {
1059 m_build_info.m_bloc_ly.add(o->length);
1060 m_build_info.m_bloc_ny.add(o->n);
1061 m_build_info.m_bloc_py.add(o->progression);
1062 }
1063
1064 for (auto& o : options()->z()) {
1065 m_build_info.m_bloc_lz.add(o->length);
1066 m_build_info.m_bloc_nz.add(o->n);
1067 m_build_info.m_bloc_pz.add(o->progression);
1068 }
1069 }
1070
1072 {
1073 info() << "Cartesian3DMeshGenerator: allocateMeshItems()";
1075 g.setBuildInfo(m_build_info);
1076 g.generateMesh();
1077 }
1078
1080};
1081
1082/*---------------------------------------------------------------------------*/
1083/*---------------------------------------------------------------------------*/
1084
1085ARCANE_REGISTER_SERVICE_CARTESIAN3DMESHGENERATOR(Cartesian3D, Cartesian3DMeshGenerator);
1086
1087/*---------------------------------------------------------------------------*/
1088/*---------------------------------------------------------------------------*/
1089
1090} // End namespace Arcane
1091
1092/*---------------------------------------------------------------------------*/
1093/*---------------------------------------------------------------------------*/
#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.
Definition Real2.h:122
Class managing a 3-dimensional real vector.
Definition Real3.h:132
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:339
Int32 Integer
Type representing an integer.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
double Real
Type representing a real number.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
std::int32_t Int32
Signed integer type of 32 bits.
Real y
second component of the pair
Definition Real2.h:35
Real x
first component of the pair
Definition Real2.h:34
Real y
second component of the triplet
Definition Real3.h:36
Real z
third component of the triplet
Definition Real3.h:37
Real x
first component of the triplet
Definition Real3.h:35