Arcane  v3.14.10.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-2023 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CartesianMeshGenerator.cc (C) 2000-2023 */
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 HashTableMapT<Int64, NodeInfo> nodes_infos(CheckedConvert::toInteger(own_nb_node_xyz), true);
663
664 // Calcule des infos blocs et des offset associés à tous les sub_domain_id
665 IntegerUniqueArray sd_x_ibl, sd_x_obl; // Numéro et offset dans le bloc
666 IntegerUniqueArray sd_y_ibl, sd_y_obl;
667 IntegerUniqueArray sd_z_ibl, sd_z_obl;
668 Int64UniqueArray sd_x_nbl, sd_y_nbl, sd_z_nbl; // Nombre dans le bloc
669 Int64UniqueArray sd_x_node_offset;
670 Int64UniqueArray sd_y_node_offset;
671 Int64UniqueArray sd_z_node_offset;
672 Int64UniqueArray sd_x_cell_offset;
673 Int64UniqueArray sd_y_cell_offset;
674 Int64UniqueArray sd_z_cell_offset;
675
676 // Scan des sous domaines: i_ème (isd) et n_ème (nsd) noeud pour marquer la frontière sous domaine
677 // Scan des des blocs: i_ème (ibl), o_ème offset (obl) et n_ème (nbl) noeud pour marquer la frontière bloc
678
679 // Selon la direction X
680 xScan(all_nb_cell_x,
681 sd_x_ibl, sd_x_obl, sd_x_nbl,
682 sd_x_node_offset, sd_x_cell_offset);
683
684 // Selon la direction Y
685 yScan(all_nb_cell_y,
686 sd_y_ibl, sd_y_obl, sd_y_nbl,
687 sd_y_node_offset, sd_y_cell_offset,
688 all_nb_node_x, all_nb_cell_x);
689
690 // Selon la direction Z
691 zScan(all_nb_cell_z,
692 sd_z_ibl, sd_z_obl, sd_z_nbl,
693 sd_z_node_offset, sd_z_cell_offset,
694 all_nb_node_xy, all_nb_cell_xy);
695
696 // Calcule pour les mailles l'offset global du début de la grille pour chaque direction.
697 Int64x3 first_own_cell_offset;
698 {
699 Int64 cell_offset_x = sd_x_cell_offset[sdXOffset()];
700 Int64 cell_offset_y = sd_y_cell_offset[sdYOffset()] / all_nb_cell_x;
701 Int64 cell_offset_z = 0;
702 if (m_mesh_dimension == 3) {
703 cell_offset_z = sd_z_cell_offset[sdZOffset()] / all_nb_cell_xy;
704 }
705 first_own_cell_offset = Int64x3(cell_offset_x,cell_offset_y,cell_offset_z);
706 info() << "OwnCellOffset info X=" << cell_offset_x << " Y=" << cell_offset_y << " Z=" << cell_offset_z;
707 m_generation_info->setOwnCellOffsets(cell_offset_x,cell_offset_y,cell_offset_z);
708 }
709 // IBL, NBL
710 info() << " sd_x_ibl=" << sd_x_ibl;
711 info() << " sd_x_obl=" << sd_x_obl;
712 info() << " sd_x_nbl=" << sd_x_nbl;
713
714 info() << " sd_y_ibl=" << sd_y_ibl;
715 info() << " sd_y_obl=" << sd_y_obl;
716 info() << " sd_y_nbl=" << sd_y_nbl;
717
718 info() << " sd_z_ibl=" << sd_z_ibl;
719 info() << " sd_z_obl=" << sd_z_obl;
720 info() << " sd_z_nbl=" << sd_z_nbl;
721
722 // NODE OFFSET
723 info() << " sd_x_node_offset=" << sd_x_node_offset;
724 info() << " sd_y_node_offset=" << sd_y_node_offset;
725 info() << " sd_z_node_offset=" << sd_z_node_offset;
726
727 // CELL OFFSET
728 info() << " sd_x_cell_offset=" << sd_x_cell_offset;
729 info() << " sd_y_cell_offset=" << sd_y_cell_offset;
730 info() << " sd_z_cell_offset=" << sd_z_cell_offset;
731
732 // On calcule le premier node_local_id en fonction de notre sub_domain_id
733 Integer node_local_id = 0;
734 Int64 node_unique_id_offset = 0;
735 info() << " sdXOffset=" << sdXOffset()
736 << " sdYOffset=" << sdYOffset()
737 << " sdZOffset=" << sdZOffset();
738 // On calcule l'offset en x des node_unique_id
739 node_unique_id_offset += sd_x_node_offset.at(sdXOffset());
740 info() << " node_unique_id_offset=" << node_unique_id_offset;
741 // On calcule l'offset en y des node_unique_id
742 node_unique_id_offset += (sd_y_node_offset.at(sdYOffset()));
743 info() << " node_unique_id_offset=" << node_unique_id_offset;
744 if (m_mesh_dimension == 3) {
745 // On calcule l'offset en z des node_unique_id
746 node_unique_id_offset += (sd_z_node_offset.at(sdZOffset()));
747 info() << " node_unique_id_offset=" << node_unique_id_offset;
748 }
749
750 Integer z_ibl = 0;
751 Integer z_obl = 0;
752 Int64 z_nbl = 0;
753 if (m_mesh_dimension == 3) {
754 z_ibl = sd_z_ibl.at(sdZOffset());
755 z_obl = sd_z_obl.at(sdZOffset());
756 z_nbl = sd_z_nbl.at(sdZOffset());
757 }
758 for (Int64 z = 0; z < own_nb_node_z; ++z) {
759 if (m_mesh_dimension == 3) {
760 // On saute l'éventuelle dernière frontière bl coincidante avec les sd
761 // Et si on découvre une frontière bloc, on reset les origines
762 if (((z + 1) != own_nb_node_z) &&
763 ((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))) {
764 info() << " Creation hit z bloc boundarz: @ node " << z;
765 z_nbl += m_build_info.m_bloc_nz.at(z_ibl) * all_nb_node_xy;
766 // On incrémente de bloc
767 z_ibl += 1;
768 z_obl = 0;
769 }
770 }
771 Real nz = 0.0;
772 if (m_mesh_dimension == 3)
773 nz = nzDelta(z_obl, z_ibl);
774 Integer y_ibl = sd_y_ibl.at(sdYOffset());
775 Integer y_obl = sd_y_obl.at(sdYOffset());
776 Int64 y_nbl = sd_y_nbl.at(sdYOffset());
777 for (Int64 y = 0; y < own_nb_node_y; ++y) {
778 // On saute l'éventuelle dernière frontière bl coincidante avec les sd
779 // Et si on découvre une frontière bloc, on reset les origines
780 if (((y + 1) != own_nb_node_y) &&
781 ((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))) {
782 info() << " Creation hit y bloc boundary: @ node " << y;
783 y_nbl += m_build_info.m_bloc_ny.at(y_ibl) * all_nb_node_x;
784 // On incrémente de bloc
785 y_ibl += 1;
786 y_obl = 0;
787 }
788 Real ny = nyDelta(y_obl, y_ibl);
789 // Récupération du numéro de bloc courant
790 Integer x_ibl = sd_x_ibl.at(sdXOffset());
791 // Récupération de l'offset dans le bloc courant
792 Integer x_obl = sd_x_obl.at(sdXOffset());
793 // Récupération du nombre de noeuds dans le bloc courant
794 Int64 x_nbl = sd_x_nbl.at(sdXOffset());
795 for (Int64 x = 0; x < own_nb_node_x; ++x) {
796 Int64 node_unique_id = node_unique_id_offset + x + y * all_nb_node_x + z * all_nb_node_xy;
797 nodes_unique_id[node_local_id] = node_unique_id;
798 Int32 owner = m_my_mesh_part;
799 // Si on est pas sur sur un sd des bords
800 // Et si on touche aux noeuds des bords du sd de bord
801 if (((sdXOffset() + 1) != m_build_info.m_nsdx) && ((x + 1) == own_nb_node_x))
802 owner += 1;
803 if (((sdYOffset() + 1) != m_build_info.m_nsdy) && ((y + 1) == own_nb_node_y))
804 owner += m_build_info.m_nsdx;
805 if (((sdZOffset() + 1) != m_build_info.m_nsdz) && ((z + 1) == own_nb_node_z))
806 owner += m_build_info.m_nsdx * m_build_info.m_nsdy;
807 // On saute l'éventuelle dernière frontière bl coincidante avec les sd
808 // Et si on découvre une frontière bloc, on reset les origines
809 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)))) {
810 info() << " Creation hit x bloc boundary: @ node " << x;
811 x_nbl += m_build_info.m_bloc_nx.at(x_ibl);
812 // On incrémente de bloc
813 x_ibl += 1;
814 x_obl = 0;
815 }
816 Real nx = nxDelta(x_obl, x_ibl);
817 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] node @ "<<x<<"x"<<y<<"x"<<z
818 <<":"<< ", uid=" << node_unique_id<< ", owned by " << owner
819 << ", ␛[1;32m coords=("<<nx<<","<<ny<<","<<nz<<")"<<"␛[0m";*/
820 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
821 node_local_id += 1;
822 x_obl += 1;
823 }
824 y_obl += 1;
825 }
826 z_obl += 1;
827 }
828
829 // Création des mailles
830 // Infos pour la création des mailles
831 // par maille: 1 pour son unique id,
832 // 1 pour son type,
833 // 8 pour chaque noeud
834 Int64 cell_unique_id_offset = 0;
835 // On calcule l'offset en x des cell_unique_id
836 cell_unique_id_offset += sd_x_cell_offset.at(sdXOffset());
837 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
838 // On calcule l'offset en y des cell_unique_id
839 cell_unique_id_offset += sd_y_cell_offset.at(sdYOffset());
840 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
841 if (m_mesh_dimension == 3) {
842 // On calcule l'offset en z des cell_unique_id
843 cell_unique_id_offset += sd_z_cell_offset.at(sdZOffset());
844 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
845 }
846 info() << "cell_unique_id_offset=" << cell_unique_id_offset;
847 m_generation_info->setFirstOwnCellUniqueId(cell_unique_id_offset);
848
849 const Int32 face_numbering_version = m_build_info.m_face_numbering_version;
850 info() << "FaceNumberingVersion = " << face_numbering_version;
851 const Int32 edge_numbering_version = m_build_info.m_edge_numbering_version;
852 info() << "EdgeNumberingVersion = " << edge_numbering_version;
853
854 {
855 info() << "Set Specific info for cartesian mesh";
856 if (m_mesh_dimension==3)
857 cartesian_mesh_build_info.setInfos3D({all_nb_cell_x,all_nb_cell_y,all_nb_cell_z},
858 {own_nb_cell_x,own_nb_cell_y,own_nb_cell_z},
859 {first_own_cell_offset.x,first_own_cell_offset.y,first_own_cell_offset.z},
860 0 );
861 else if (m_mesh_dimension==2){
862 cartesian_mesh_build_info.setInfos2D({all_nb_cell_x,all_nb_cell_y},
863 {own_nb_cell_x,own_nb_cell_y},
864 {first_own_cell_offset.x,first_own_cell_offset.y},
865 0 );
866 }
867 else
868 ARCANE_FATAL("Invalid dimensionn '{0}' (valid values are 2 or 3)",m_mesh_dimension);
869
870 if (face_numbering_version>=0)
871 cartesian_mesh_build_info._internal()->setFaceBuilderVersion(face_numbering_version);
872 if (edge_numbering_version>=0)
873 cartesian_mesh_build_info._internal()->setEdgeBuilderVersion(edge_numbering_version);
874 }
875
876 cartesian_mesh_build_info.allocateMesh();
877
878 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
879 {
880 info() << "Fills the variable containing the coordinates of the nodes";
881 Int32UniqueArray nodes_local_id(nodes_unique_id.size());
882 IItemFamily* family = mesh->nodeFamily();
883 family->itemsUniqueIdToLocalId(nodes_local_id, nodes_unique_id);
884 NodeInfoListView nodes_internal(family);
885 for (Integer i = 0; i < node_local_id; ++i) {
886 Node node = nodes_internal[nodes_local_id[i]];
887 Int64 unique_id = nodes_unique_id[i];
888 nodes_coord_var[node] = nodes_infos.lookupValue(unique_id).m_coord;
889 /*debug() << "␛[2;33m[CartesianMeshGenerator::generateMesh] Set coord "
890 << ItemPrinter(node) << " coord=" << nodes_coord_var[node]<< "␛[0m";*/
891 }
892 }
893 nodes_coord_var.synchronize();
894
895 if (m_build_info.m_is_generate_sod_groups){
896 SodStandardGroupsBuilder groups_builder(traceMng());
897 Real3 origin = m_build_info.m_origine;
898 Real3 length(m_l.x,m_l.y,m_l.z);
899 Real3 max_pos = origin + length;
900 // TODO: Comme il peut y avoir des progressions geométriques il faut définir
901 // le milieu à partir de la position de la maille d'offset le milieu
902 // et pas à partir des coordonnées
903 // Calculer middle_x comme position du milieu
904 Real middle_x = (origin.x + max_pos.x) / 2.0;
905 Real middle_height = (origin.y + max_pos.y) / 2.0;
906 groups_builder.generateGroups(mesh,origin,origin+length,middle_x,middle_height);
907 }
908
909 return false; // false == ok
910}
911
912/*---------------------------------------------------------------------------*/
913/*---------------------------------------------------------------------------*/
914
915/*---------------------------------------------------------------------------*/
916/*---------------------------------------------------------------------------*/
922{
923 public:
924
927
928 public:
929
931 {
932 ARCANE_UNUSED(build_info);
933 info() << "Cartesian2DMeshGenerator: fillMeshBuildInfo()";
934 m_build_info.m_nsdx = options()->nbPartX();
935 m_build_info.m_nsdy = options()->nbPartY();
936
937 m_build_info.m_mesh_dimension = 2;
938 Real2 origin = options()->origin;
939 m_build_info.m_origine.x = origin.x;
940 m_build_info.m_origine.y = origin.y;
941 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
942 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
943
944 for( auto& o : options()->x() ){
945 m_build_info.m_bloc_lx.add(o->length);
946 m_build_info.m_bloc_nx.add(o->n);
947 m_build_info.m_bloc_px.add(o->progression);
948 }
949
950 for( auto& o : options()->y() ){
951 m_build_info.m_bloc_ly.add(o->length);
952 m_build_info.m_bloc_ny.add(o->n);
953 m_build_info.m_bloc_py.add(o->progression);
954 }
955 }
956
958 {
959 info() << "Cartesian2DMeshGenerator: allocateMeshItems()";
961 // Regarde s'il faut calculer dynamiquement le découpage
962 auto [ x, y ] = _computePartition(pm,m_build_info.m_nsdx,m_build_info.m_nsdy);
963 m_build_info.m_nsdx = x;
964 m_build_info.m_nsdy = y;
965 g.setBuildInfo(m_build_info);
966 g.generateMesh();
967 }
968
969 private:
970
972
973 static std::tuple<Integer,Integer>
974 _computePartition(IPrimaryMesh* pm,Integer nb_x,Integer nb_y)
975 {
976 Int32 nb_part = pm->meshPartInfo().nbPart();
977 // En séquentiel, ne tient pas compte des valeurs de jeu de données.
978 if (nb_part==1)
979 return {1,1};
980 // Si le découpage en X et en Y est spécifié, l'utilise directement.
981 if (nb_x!=0 && nb_y!=0)
982 return {nb_x, nb_y};
983 // Aucun découpage spécifié. Il faut que math::sqrt(nb_part)
984 // soit un entier
985 if (nb_x==0 && nb_y==0){
986 double s = math::sqrt((double)(nb_part));
987 Integer s_int = (Integer)(::floor(s));
988 if ((s_int*s_int) != nb_part)
989 ARCANE_FATAL("Invalid number of part '{0}' for automatic partitioning: sqrt({1}) is not an integer",
990 nb_part,nb_part);
991 return {s_int,s_int};
992 }
993 // Ici, on a un des deux découpages qui n'est pas spécifié.
994 if (nb_x==0){
995 if ( (nb_part % nb_y) != 0 )
996 ARCANE_FATAL("Invalid number of Y part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
997 nb_y,nb_part,nb_y);
998 nb_x = nb_part / nb_y;
999 }
1000 else{
1001 if ( (nb_part % nb_x) != 0 )
1002 ARCANE_FATAL("Invalid number of X part '{0}' for automatic partitioning: can not divide '{1}' by '{2}'",
1003 nb_x,nb_part,nb_x);
1004 nb_y = nb_part / nb_x;
1005 }
1006 return {nb_x,nb_y};
1007 }
1008};
1009
1010ARCANE_REGISTER_SERVICE_CARTESIAN2DMESHGENERATOR(Cartesian2D,Cartesian2DMeshGenerator);
1011
1012/*---------------------------------------------------------------------------*/
1013/*---------------------------------------------------------------------------*/
1019{
1020 public:
1023 public:
1025 {
1026 ARCANE_UNUSED(build_info);
1027 info() << "Cartesian3DMeshGenerator: fillMeshBuildInfo()";
1028 m_build_info.m_nsdx = options()->nbPartX();
1029 m_build_info.m_nsdy = options()->nbPartY();
1030 m_build_info.m_nsdz = options()->nbPartZ();
1031
1032 m_build_info.m_mesh_dimension = 3;
1033 Real3 origin = options()->origin;
1034 m_build_info.m_origine.x = origin.x;
1035 m_build_info.m_origine.y = origin.y;
1036 m_build_info.m_origine.z = origin.z;
1037 m_build_info.m_is_generate_sod_groups = options()->generateSodGroups();
1038 m_build_info.m_face_numbering_version = options()->faceNumberingVersion();
1039 m_build_info.m_edge_numbering_version = options()->edgeNumberingVersion();
1040
1041 for( auto& o : options()->x() ){
1042 m_build_info.m_bloc_lx.add(o->length);
1043 m_build_info.m_bloc_nx.add(o->n);
1044 m_build_info.m_bloc_px.add(o->progression);
1045 }
1046
1047 for( auto& o : options()->y() ){
1048 m_build_info.m_bloc_ly.add(o->length);
1049 m_build_info.m_bloc_ny.add(o->n);
1050 m_build_info.m_bloc_py.add(o->progression);
1051 }
1052
1053 for( auto& o : options()->z() ){
1054 m_build_info.m_bloc_lz.add(o->length);
1055 m_build_info.m_bloc_nz.add(o->n);
1056 m_build_info.m_bloc_pz.add(o->progression);
1057 }
1058 }
1059
1061 {
1062 info() << "Cartesian3DMeshGenerator: allocateMeshItems()";
1064 g.setBuildInfo(m_build_info);
1065 g.generateMesh();
1066 }
1067
1069};
1070
1071ARCANE_REGISTER_SERVICE_CARTESIAN3DMESHGENERATOR(Cartesian3D,Cartesian3DMeshGenerator);
1072
1073/*---------------------------------------------------------------------------*/
1074/*---------------------------------------------------------------------------*/
1075
1076} // End namespace Arcane
1077
1078/*---------------------------------------------------------------------------*/
1079/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur le maillage.
Generation de la classe de base du Service.
Generation de la classe de base du Service.
Service de génération de maillage cartésien en 2D.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Remplit build_info avec les informations nécessaires pour créer le maillage.
void allocateMeshItems(IPrimaryMesh *pm) override
Alloue les entités du maillage géré par ce service.
Service de génération de maillage cartésien en en 3D.
void allocateMeshItems(IPrimaryMesh *pm) override
Alloue les entités du maillage géré par ce service.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Remplit build_info avec les informations nécessaires pour créer le maillage.
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.
bool m_is_generate_sod_groups
Indique si on génère les groupes pour un cas test de sod.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Paramètres nécessaires à la construction d'un maillage.
Classe gérant un vecteur de réel de dimension 2.
Definition Real2.h:121
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Structure contenant les informations pour créer un service.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Positionne une classe de message.
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:513
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:519
Int32 Integer
Type représentant un entier.
Real y
deuxième composante du couple
Definition Real2.h:35
Real x
première composante du couple
Definition Real2.h:34
Real y
deuxième composante du triplet
Definition Real3.h:36
Real z
troisième composante du triplet
Definition Real3.h:37
Real x
première composante du triplet
Definition Real3.h:35