Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
SodMeshGenerator.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/* SodMeshGenerator.cc (C) 2000-2025 */
9/* */
10/* Service for generating a 'sod'-style mesh. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Array.h"
15#include "arcane/utils/HashTableMap.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/Real3.h"
19#include "arcane/utils/CheckedConvert.h"
20
21#include "arcane/core/IMeshReader.h"
22#include "arcane/core/ISubDomain.h"
23#include "arcane/core/ICaseDocument.h"
24#include "arcane/core/XmlNode.h"
25#include "arcane/core/Service.h"
26#include "arcane/core/IParallelMng.h"
27#include "arcane/core/Item.h"
28#include "arcane/core/ItemGroup.h"
29#include "arcane/core/IPrimaryMesh.h"
30#include "arcane/core/IItemFamily.h"
31#include "arcane/core/MeshVariable.h"
33#include "arcane/core/ItemPrinter.h"
34#include "arcane/core/FactoryService.h"
35#include "arcane/core/AbstractService.h"
36#include "arcane/core/Properties.h"
37#include "arcane/core/IMeshBuilder.h"
38
39#include "arcane/std/IMeshGenerator.h"
40#include "arcane/std/SodMeshGenerator.h"
41#include "arcane/std/internal/SodStandardGroupsBuilder.h"
42
43#include "arcane/std/Sod3DMeshGenerator_axl.h"
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48namespace Arcane
49{
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
55: public TraceAccessor
56{
57 public:
58
59 Impl(ITraceMng* tm, bool zyx, Int32 wanted_x, Int32 wanted_y, Int32 wanted_z,
60 bool z_is_total, Int32 mesh_dimension, Real random_coef,
61 Real delta0, Real delta1, Real delta2)
62 : TraceAccessor(tm)
63 , m_wanted_x(wanted_x)
64 , m_wanted_y(wanted_y)
65 , m_wanted_z(wanted_z)
66 , m_zyx_generate(zyx)
67 , m_z_is_total(z_is_total)
68 , m_mesh_dimension(mesh_dimension)
69 , m_random_coef(random_coef)
70 {
71 m_xyz_delta[0] = delta0;
72 m_xyz_delta[1] = delta1;
73 m_xyz_delta[2] = delta2;
74 }
75
76 public:
77
78 IntegerConstArrayView communicatingSubDomains() const
79 {
80 return m_communicating_sub_domains;
81 }
82 bool generateMesh(IPrimaryMesh* mesh);
83
84 private:
85
86 Integer m_wanted_x;
87 Integer m_wanted_y;
88 Integer m_wanted_z;
89 UniqueArray<Integer> m_communicating_sub_domains;
93 int m_mesh_dimension;
94 Real m_random_coef;
95
96 private:
97};
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102SodMeshGenerator::
103SodMeshGenerator(IPrimaryMesh* mesh, bool zyx)
105, m_mesh(mesh)
106, m_zyx_generate(zyx)
107{
108}
109
110/*---------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------*/
112
113SodMeshGenerator::
114~SodMeshGenerator()
115{
116 // Necessary for std::unique_ptr.
117}
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
122IntegerConstArrayView SodMeshGenerator::
123communicatingSubDomains() const
124{
125 if (m_p.get())
126 return m_p->communicatingSubDomains();
127 return {};
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133bool SodMeshGenerator::
134readOptions(XmlNode node)
135{
136 Int32 wanted_x = node.child("x").valueAsInteger();
137 Int32 wanted_y = 0;
138 Int32 wanted_z = 0;
139 Int32 mesh_dimension = 1;
140 XmlNode x_node = node.child("x");
141 XmlNode y_node = node.child("y");
142 XmlNode z_node = node.child("z");
143 if (z_node.null() && y_node.null()) {
144 info() << "[SodMeshGenerator] 1D";
145 mesh_dimension = 1;
146 wanted_z = 1;
147 wanted_y = 1;
148 }
149 else if (z_node.null()) {
150 info() << "[SodMeshGenerator] 2D";
151 // WARNING: In 2D Z and Y are switched
152 mesh_dimension = 2;
153 //z_node = node.child("y");
154 wanted_z = y_node.valueAsInteger();
155 wanted_y = 1;
156 }
157 else {
158 info() << "[SodMeshGenerator] 3D";
159 mesh_dimension = 3;
160 wanted_y = y_node.valueAsInteger();
161 wanted_z = z_node.valueAsInteger();
162 }
163
164 bool z_is_total = z_node.attr("total").valueAsBoolean();
165
166 Real delta0 = x_node.attr("delta").valueAsReal();
167 Real delta1 = y_node.attr("delta").valueAsReal();
168 Real delta2 = z_node.attr("delta").valueAsReal();
169
170 Real random_coef = node.child("random-coef").valueAsReal();
171 if (wanted_x == 0 || wanted_y == 0 || wanted_z == 0) {
172 info() << "Bad syntax for <meshgenerator>";
173 info() << "Expected is <meshgenerator><sod><x>nx</x><y>ny</y><z>nz</z></sod></meshgenerator>";
174 info() << "or <meshgenerator><sod><x>nx</x><y>ny</y></sod></meshgenerator>";
175 info() << "or <meshgenerator><sod><x>nx</x></sod></meshgenerator>";
176 error() << "Bad syntax for <meshgenerator>";
177 return true;
178 }
179 m_p = std::make_unique<Impl>(traceMng(), m_zyx_generate, wanted_x, wanted_y, wanted_z, z_is_total,
180 mesh_dimension, random_coef, delta0, delta1, delta2);
181 return false;
182}
183
184/*---------------------------------------------------------------------------*/
185/*---------------------------------------------------------------------------*/
186
193inline Int64
195 Int64 first_z, Int64 total_para_z)
196{
197 Int64 ax = x;
198 Int64 ay = y;
199 Int64 az = z;
200 Int64 anb_y = nb_y;
201
202 Int64 unique_id = ay + (az + first_z) * anb_y + ax * anb_y * total_para_z;
203 return unique_id;
204}
205
206/*---------------------------------------------------------------------------*/
207/*---------------------------------------------------------------------------*/
208
209bool SodMeshGenerator::
210generateMesh()
211{
212 return m_p->generateMesh(m_mesh);
213}
214
215/*---------------------------------------------------------------------------*/
216/*---------------------------------------------------------------------------*/
217
218bool SodMeshGenerator::Impl::
219generateMesh(IPrimaryMesh* mesh)
220{
221 info() << "Generate Mesh from SodMeshGenerator";
222
223 IParallelMng* pm = mesh->parallelMng();
224 bool is_parallel = pm->isParallel();
225 Int32 nb_part = pm->commSize();
226 if (is_parallel) {
227 if (m_z_is_total)
228 m_wanted_z /= nb_part;
229 }
230 Integer nb_cell_x = m_wanted_x;
231 Integer nb_cell_y = m_wanted_y;
232 Integer nb_cell_z = m_wanted_z;
233 info() << "nb x=" << nb_cell_x << " y=" << nb_cell_y << " z=" << nb_cell_z;
234
235 // Positions properties on the mesh so that it can know
236 // the number of cells in each direction. This is used
237 // notably by CartesianMesh.
238 Properties* mesh_properties = mesh->properties();
239 mesh_properties->setInt64("GlobalNbCellX", nb_cell_x);
240 mesh_properties->setInt64("GlobalNbCellY", nb_cell_y);
241 mesh_properties->setInt64("GlobalNbCellZ", nb_cell_z);
242
243 Int32 my_part = pm->commRank();
244 bool is_first_proc = (my_part == 0);
245 bool is_last_proc = ((1 + my_part) == nb_part);
246 Int64 total_para_cell_z = ((Int64)nb_cell_z) * ((Int64)nb_part);
247 Int64 total_para_node_z = total_para_cell_z + 1;
248 Int64 first_cell_z = 0;
249 Int64 first_node_z = 0;
250 if (is_parallel) {
251 if (is_first_proc || is_last_proc) {
252 m_communicating_sub_domains.resize(1);
253 first_cell_z = nb_cell_z * my_part;
254 if (is_first_proc) {
255 m_communicating_sub_domains[0] = my_part + 1;
256 first_cell_z = 0;
257 }
258 else if (is_last_proc) {
259 m_communicating_sub_domains[0] = my_part - 1;
260 }
261 else {
262 }
263 first_node_z = first_cell_z;
264 }
265 else {
266 m_communicating_sub_domains.resize(2);
267 m_communicating_sub_domains[0] = my_part - 1;
268 m_communicating_sub_domains[1] = my_part + 1;
269 first_cell_z = (nb_cell_z * my_part);
270 first_node_z = first_cell_z;
271 }
272 }
273
274 //Integer nb_face_node = 0;
275 Integer nb_node_x = nb_cell_x + 1;
276 Integer nb_node_y = -1;
277 Integer nb_node_z = nb_cell_z + 1;
278
279 if (m_mesh_dimension == 3) {
280 nb_node_y = nb_cell_y + 1;
281 }
282 else if (m_mesh_dimension == 2) {
283 nb_node_y = 1;
284 }
285 else if (m_mesh_dimension == 1) {
286 nb_node_y = 1;
287 nb_node_z = 1;
288 }
289
290 Integer nb_node_xy = CheckedConvert::multiply(nb_node_x, nb_node_y);
291 Integer nb_node_yz = CheckedConvert::multiply(nb_node_y, nb_node_z);
292
293 Integer nb_cell_xy = CheckedConvert::multiply(nb_cell_x, nb_cell_y);
294 Integer nb_cell_yz = CheckedConvert::multiply(nb_cell_y, nb_cell_z);
295 Integer nb_cell_xz = CheckedConvert::multiply(nb_cell_x, nb_cell_z);
296
297 Integer nb_face_x = CheckedConvert::multiply(nb_node_x, nb_cell_yz);
298 Integer nb_face_y = CheckedConvert::multiply(nb_node_y, nb_cell_xz);
299 Integer nb_face_z = CheckedConvert::multiply(nb_node_z, nb_cell_xy);
300
301 Integer mesh_nb_cell = CheckedConvert::multiply(nb_cell_x, nb_cell_y, nb_cell_z);
302 Integer mesh_nb_node = CheckedConvert::multiply(nb_node_x, nb_node_y, nb_node_z);
303 Integer mesh_nb_face = nb_face_x + nb_face_y + nb_face_z;
304
305 // To test uid > 32 bits, it is enough
306 // to change this multiplier and set it
307 // for example to 1000000
308 const Int64 uid_multiplier = 1;
309 //const Int64 uid_multiplier = 12500000;
310
311 info() << "mesh generation dim=" << m_mesh_dimension;
312 info() << "First mesh layer: " << first_cell_z;
313 info() << "Number of cells layers: " << nb_cell_z << '/' << total_para_cell_z;
314 info() << "First node layer: " << first_node_z;
315 info() << "Number of nodes layers: " << nb_node_z << '/' << total_para_node_z;
316
317 info() << "Number of nodes " << mesh_nb_node;
318 info() << "Number of faces " << mesh_nb_face;
319 info() << "Number of cells " << mesh_nb_cell;
320
321 info() << "nb node_yz=" << nb_node_yz;
322
323 // Creation of nodes
324
325 Int64UniqueArray nodes_unique_id(mesh_nb_node);
326
327 HashTableMapT<Int64, NodeInfo> nodes_infos(mesh_nb_node, true);
328
329 Real ydelta = (m_xyz_delta[1] == 0.0) ? ARCANE_REAL(0.02) : m_xyz_delta[1];
330 Real zdelta = (m_xyz_delta[2] == 0.0) ? ARCANE_REAL(0.02) : m_xyz_delta[2];
331 Real xdelta = (m_xyz_delta[0] == 0.0) ? ARCANE_REAL(1.0) / (Real)(nb_cell_x) : m_xyz_delta[0];
332 // The middle to determine ZG and ZD
333 Real middle_x = ARCANE_REAL(0.5);
334 // The middle to determine TOP and BOTTOM
335 Real middle_height = ARCANE_REAL((nb_cell_y / 2) * ydelta);
336
337 if (m_xyz_delta[0] != 0.0)
338 middle_x = m_xyz_delta[0] * (nb_cell_x / 2);
339
340 if (m_mesh_dimension == 2) {
341 zdelta = ydelta;
342 middle_height = (nb_cell_z / 2) * zdelta;
343 }
344
345 info() << "Xdelta=" << xdelta << ", Ydelta=" << ydelta << ", Zdelta=" << zdelta;
346 info() << "middle_x=" << middle_x << ", middle_height=" << middle_height;
347
348 // Node creation
349 Integer nb_node_local_id = 0;
350 if (m_zyx_generate == false) {
351 Integer node_local_id = 0;
352 for (Integer x = 0; x < nb_node_x; ++x) {
353 for (Integer z = 0; z < nb_node_z; ++z) {
354 for (Integer y = 0; y < nb_node_y; ++y) {
355
356 Real nx = xdelta * (Real)(x);
357 Real ny = ydelta * (Real)(y);
358 Real nz = zdelta * (Real)(z + first_node_z);
359 if (m_mesh_dimension == 2) {
360 ny = nz;
361 nz = 0.0;
362 }
363 else if (m_mesh_dimension == 1) {
364 ny = nz = 0.0;
365 }
366 Int64 node_unique_id = (Int64)y + ((Int64)z + first_node_z) * (Int64)nb_node_y + (Int64)x * nb_node_y * total_para_node_z;
367 node_unique_id *= uid_multiplier;
368
369 nodes_unique_id[node_local_id] = node_unique_id;
370 Integer owner = my_part;
371 // If this is the top node layer (z max),
372 // it belongs to the next subdomain
373 if (z == (nb_node_z - 1) && !is_last_proc)
374 owner = my_part + 1;
375
376 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
377
378 //debug(Trace::High) << "Add coord uid=" << node_unique_id << " pos=" << Real3(nx,ny,nz);
379 //info() << "Add coord uid=" << node_unique_id << " pos=" << Real3(nx,ny,nz);
380
381 ++node_local_id;
382 }
383 }
384 }
385 nb_node_local_id = node_local_id;
386 }
387 else { // m_zyx_generate
388 Integer node_local_id = 0;
389 for (Integer z = 0; z < nb_node_z; ++z) {
390 for (Integer y = 0; y < nb_node_y; ++y) {
391 for (Integer x = 0; x < nb_node_x; ++x) {
392 Real nx = xdelta * (Real)(x);
393 Real ny = ydelta * (Real)(y);
394 Real nz = zdelta * (Real)(z + first_node_z);
395 if (m_mesh_dimension == 2) {
396 ny = nz;
397 nz = 0.0;
398 }
399 else if (m_mesh_dimension == 1) {
400 ny = nz = 0.0;
401 }
402 Int64 node_unique_id = (Int64)x + (Int64)y * nb_node_x + ((Int64)z + first_node_z) * (Int64)nb_node_x * (Int64)nb_node_y;
403 node_unique_id *= uid_multiplier;
404
405 nodes_unique_id[node_local_id] = node_unique_id;
406 Integer owner = my_part;
407 // If this is the top node layer (z max),
408 // it belongs to the next subdomain
409 if (z == (nb_node_z - 1) && !is_last_proc)
410 owner = my_part + 1;
411 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
412 //debug(Trace::High) << "Add coord uid=" << node_unique_id << " pos=" << Real3(nx,ny,nz);
413 //info() << "Add coord uid=" << node_unique_id << " pos=" << Real3(nx,ny,nz);
414 //info() << "[SodMeshGenerator::generateMesh] node @ "<<x<<"x"<<y<<"x"<<z<<":"<<", uid=" << node_unique_id;
415 ++node_local_id;
416 }
417 }
418 }
419 nb_node_local_id = node_local_id;
420 }
421
422 // Cell creation
423
424 // Info for cell creation
425 // per cell: 1 for its unique id,
426 // 1 for its type,
427 // 8 for each node
428 Int64UniqueArray cells_infos(mesh_nb_cell * 10);
429
430 if (m_mesh_dimension == 1) {
431 Integer cells_infos_index = 0;
432
433 for (Integer x = 0; x < nb_cell_x; ++x) {
434 for (Integer z = 0; z < nb_cell_z; ++z) {
435 for (Integer y = 0; y < nb_cell_y; ++y) {
436 Integer current_cell_nb_node = 2;
437
438 Int64 cell_unique_id = _generateCellUniqueId(x, y, z, nb_cell_y, first_cell_z, total_para_cell_z);
439 cell_unique_id *= uid_multiplier;
440
441 cells_infos[cells_infos_index] = IT_CellLine2;
442 ++cells_infos_index;
443
444 cells_infos[cells_infos_index] = cell_unique_id;
445 ++cells_infos_index;
446
447 Integer base_id = y + z * nb_node_y + x * nb_node_yz;
448 cells_infos[cells_infos_index + 0] = nodes_unique_id[base_id];
449 cells_infos[cells_infos_index + 1] = nodes_unique_id[base_id + 1];
450
451 cells_infos_index += current_cell_nb_node;
452 }
453 }
454 }
455 }
456 else if (m_mesh_dimension == 2) {
457 Integer cells_infos_index = 0;
458
459 for (Integer x = 0; x < nb_cell_x; ++x) {
460 for (Integer z = 0; z < nb_cell_z; ++z) {
461 for (Integer y = 0; y < nb_cell_y; ++y) {
462 Integer current_cell_nb_node = 4;
463
464 Int64 cell_unique_id = _generateCellUniqueId(x, y, z, nb_cell_y, first_cell_z, total_para_cell_z);
465 cell_unique_id *= uid_multiplier;
466
467 cells_infos[cells_infos_index] = IT_Quad4;
468 ++cells_infos_index;
469
470 cells_infos[cells_infos_index] = cell_unique_id;
471 ++cells_infos_index;
472
473 Integer base_id = y + z * nb_node_y + x * nb_node_yz;
474 cells_infos[cells_infos_index + 0] = nodes_unique_id[base_id];
475 cells_infos[cells_infos_index + 1] = nodes_unique_id[base_id + nb_node_yz];
476 cells_infos[cells_infos_index + 2] = nodes_unique_id[base_id + nb_node_yz + 1];
477 cells_infos[cells_infos_index + 3] = nodes_unique_id[base_id + 1];
478
479 cells_infos_index += current_cell_nb_node;
480 }
481 }
482 }
483 }
484 else if (m_mesh_dimension == 3) {
485 if (m_zyx_generate == false) {
486 Integer cells_infos_index = 0;
487 for (Integer x = 0; x < nb_cell_x; ++x) {
488 for (Integer z = 0; z < nb_cell_z; ++z) {
489 for (Integer y = 0; y < nb_cell_y; ++y) {
490 Integer current_cell_nb_node = 8;
491 Int64 cell_unique_id = _generateCellUniqueId(x, y, z, nb_cell_y, first_cell_z, total_para_cell_z);
492 cell_unique_id *= uid_multiplier;
493 // info() << "[SodMeshGenerator::generateMesh] "<<x<<"x"<<y<<"x"<<z<<":"<<", uid=" << cell_unique_id;
494 cells_infos[cells_infos_index] = IT_Hexaedron8;
495 ++cells_infos_index;
496 cells_infos[cells_infos_index] = cell_unique_id;
497 ++cells_infos_index;
498 Integer base_id = y + z * nb_node_y + x * nb_node_yz;
499 cells_infos[cells_infos_index + 0] = nodes_unique_id[base_id];
500 cells_infos[cells_infos_index + 1] = nodes_unique_id[base_id + 1];
501 cells_infos[cells_infos_index + 2] = nodes_unique_id[base_id + nb_node_y + 1];
502 cells_infos[cells_infos_index + 3] = nodes_unique_id[base_id + nb_node_y + 0];
503 cells_infos[cells_infos_index + 4] = nodes_unique_id[base_id + nb_node_yz];
504 cells_infos[cells_infos_index + 5] = nodes_unique_id[base_id + nb_node_yz + 1];
505 cells_infos[cells_infos_index + 6] = nodes_unique_id[base_id + nb_node_yz + nb_node_y + 1];
506 cells_infos[cells_infos_index + 7] = nodes_unique_id[base_id + nb_node_yz + nb_node_y + 0];
507 cells_infos_index += current_cell_nb_node;
508 }
509 }
510 }
511 }
512 else { // m_zyx_generate
513 Integer cells_infos_index = 0;
514 for (Integer z = 0; z < nb_cell_z; ++z) {
515 for (Integer y = 0; y < nb_cell_y; ++y) {
516 for (Integer x = 0; x < nb_cell_x; ++x) {
517 Integer current_cell_nb_node = 8;
518 Int64 cell_unique_id = _generateCellUniqueId(x, y, z, nb_cell_y, first_cell_z, total_para_cell_z);
519 cell_unique_id *= uid_multiplier;
520 debug() << "[SodMeshGenerator::generateMesh] + m_zyx_generate " << x << "x" << y << "x" << z << ":" << ", uid=" << cell_unique_id;
521 cells_infos[cells_infos_index] = IT_Hexaedron8;
522 ++cells_infos_index;
523 cells_infos[cells_infos_index] = cell_unique_id;
524 ++cells_infos_index;
525 Integer base_id = x + y * nb_node_x + z * nb_node_xy;
526 cells_infos[cells_infos_index + 0] = nodes_unique_id[base_id];
527 cells_infos[cells_infos_index + 1] = nodes_unique_id[base_id + 1];
528 cells_infos[cells_infos_index + 2] = nodes_unique_id[base_id + nb_node_x + 1];
529 cells_infos[cells_infos_index + 3] = nodes_unique_id[base_id + nb_node_x + 0];
530 cells_infos[cells_infos_index + 4] = nodes_unique_id[base_id + nb_node_xy];
531 cells_infos[cells_infos_index + 5] = nodes_unique_id[base_id + nb_node_xy + 1];
532 cells_infos[cells_infos_index + 6] = nodes_unique_id[base_id + nb_node_xy + nb_node_x + 1];
533 cells_infos[cells_infos_index + 7] = nodes_unique_id[base_id + nb_node_xy + nb_node_x + 0];
534 debug() << "[SodMeshGenerator::generateMesh] + m_zyx_generate nodes: "
535 << cells_infos[cells_infos_index + 0] << ", "
536 << cells_infos[cells_infos_index + 1] << ", "
537 << cells_infos[cells_infos_index + 2] << ", "
538 << cells_infos[cells_infos_index + 3] << ", "
539 << cells_infos[cells_infos_index + 4] << ", "
540 << cells_infos[cells_infos_index + 5] << ", "
541 << cells_infos[cells_infos_index + 6] << ", "
542 << cells_infos[cells_infos_index + 7];
543 cells_infos_index += current_cell_nb_node;
544 }
545 }
546 }
547 }
548 }
549
550 mesh->setDimension(m_mesh_dimension);
551 mesh->allocateCells(mesh_nb_cell, cells_infos, true);
552
553 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
554 {
555 // Fills the variable containing node coordinates
556 Int32UniqueArray nodes_local_id(nodes_unique_id.size());
557 IItemFamily* family = mesh->itemFamily(IK_Node);
558 family->itemsUniqueIdToLocalId(nodes_local_id, nodes_unique_id);
559 NodeInfoListView nodes_internal(family);
560 for (Integer i = 0; i < nb_node_local_id; ++i) {
561 Node node = nodes_internal[nodes_local_id[i]];
562 Int64 unique_id = nodes_unique_id[i];
563 nodes_coord_var[node] = nodes_infos.lookupValue(unique_id).m_coord;
564 //info() << "Set coord " << ItemPrinter(node) << " coord=" << nodes_coord_var[node]
565 // << " coord2=" << nodes_infos.lookupValue(unique_id).m_coord;
566 }
567 }
568 nodes_coord_var.synchronize();
569
570 {
571 SodStandardGroupsBuilder groups_builder(traceMng());
572 Real max_x = xdelta * nb_cell_x;
573 Real max_y = ydelta * nb_cell_y;
574 // In the 2D case, nb_cell_z and nb_cell_y are swapped
575 if (m_mesh_dimension == 2) {
576 max_y = ydelta * Convert::toReal(total_para_cell_z);
577 info() << "[SodMeshGenerator::generateMesh] max_y=" << max_y;
578 }
579 const Real max_z = zdelta * Convert::toReal(total_para_cell_z);
580 groups_builder.generateGroups(mesh, Real3::null(), Real3(max_x, max_y, max_z), middle_x, middle_height, true);
581 }
582
583 bool is_random = !math::isNearlyZero(m_random_coef);
584 if (is_random) {
585 if (m_mesh_dimension == 1)
586 throw NotImplementedException(A_FUNCINFO, "Randomisation for 1D mesh");
587 info() << "** ** ** Randomize node positions coef=" << m_random_coef;
588 for (Integer x = 0; x < nb_node_x; ++x) {
589 for (Integer z = 0; z < nb_node_z; ++z) {
590 for (Integer y = 0; y < nb_node_y; ++y) {
591 Real xd = xdelta;
592 Real yd = ydelta;
593 Real zd = zdelta;
594 if (x != 0 && (x + 1) != nb_node_x && (z + first_node_z) != 0 && (z + first_node_z) != (total_para_node_z - 1) && (m_mesh_dimension == 2 || (y != 0 && y != (nb_node_y - 1)))) {
595 Real xr = (Real)::rand() / (Real)RAND_MAX;
596 Real yr = (Real)::rand() / (Real)RAND_MAX;
597 Real zr = (Real)::rand() / (Real)RAND_MAX;
598 //info() << " xr=" << xr << "yr=" << yr << " zr=" << zr;
599 xd = xd + (xr - 0.5) * xdelta * m_random_coef;
600 yd = yd + (yr - 0.5) * ydelta * m_random_coef;
601 zd = zd + (zr - 0.5) * zdelta * m_random_coef;
602 }
603
604 if (m_mesh_dimension == 2) {
605 yd = zd;
606 zd = 0.0;
607 }
608
609 Int64 node_unique_id = y + (z + first_node_z) * nb_node_y + x * nb_node_y * total_para_node_z;
610 Real3 pos = nodes_infos.lookupValue(node_unique_id).m_coord;
611
612 pos += Real3(xd, yd, zd);
613
614 nodes_infos.add(node_unique_id, NodeInfo(0, pos));
615 }
616 }
617 }
618 ENUMERATE_NODE (inode, mesh->ownNodes()) {
619 Node node = *inode;
620 nodes_coord_var[inode] = nodes_infos.lookupValue(node.uniqueId()).m_coord;
621 }
622 nodes_coord_var.synchronize();
623 }
624 info() << "End of mesh generation";
625 return false;
626}
627
628/*---------------------------------------------------------------------------*/
629/*---------------------------------------------------------------------------*/
630
634class Sod3DMeshGenerator
636{
637 public:
638
639 Sod3DMeshGenerator(const ServiceBuildInfo& sbi)
641 {}
642
643 public:
644
645 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
646 {
647 ARCANE_UNUSED(build_info);
648 }
650 {
651 bool zyx = false;
652 Int32 wanted_x = options()->x();
653 Int32 wanted_y = options()->y();
654 Int32 wanted_z = options()->z();
655 Real random_coef = 0.0;
656 Real delta0 = 0.0;
657 Real delta1 = 0.0;
658 Real delta2 = 0.0;
659 bool z_is_total = false;
660 SodMeshGenerator::Impl x(traceMng(), zyx, wanted_x, wanted_y, wanted_z,
661 z_is_total, 3, random_coef, delta0, delta1, delta2);
662 x.generateMesh(pm);
663 }
664};
665
666/*---------------------------------------------------------------------------*/
667/*---------------------------------------------------------------------------*/
668
669ARCANE_REGISTER_SERVICE_SOD3DMESHGENERATOR(Sod3D, Sod3DMeshGenerator);
670
671/*---------------------------------------------------------------------------*/
672/*---------------------------------------------------------------------------*/
673
674} // End namespace Arcane
675
676/*---------------------------------------------------------------------------*/
677/*---------------------------------------------------------------------------*/
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
ArcaneSod3DMeshGeneratorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsSod3DMeshGenerator * options() const
Options du jeu de données du service.
Parameters necessary for building a mesh.
Structure containing the information to create a 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.
bool m_zyx_generate
true if generating in z, then y, and finally x
bool m_z_is_total
true if z is the total number of layers for all procs.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
Real toReal(Real r)
Converts r to a Real.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int64 _generateCellUniqueId(Integer x, Integer y, Integer z, Integer nb_y, Int64 first_z, Int64 total_para_z)
Generates a UniqueId from block indices (x,y,z).
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
@ IK_Node
Node mesh entity.
double Real
Type representing a real number.
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
Definition UtilsTypes.h:486
std::int32_t Int32
Signed integer type of 32 bits.