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"
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"
39#include "arcane/std/IMeshGenerator.h"
40#include "arcane/std/SodMeshGenerator.h"
41#include "arcane/std/internal/SodStandardGroupsBuilder.h"
43#include "arcane/std/Sod3DMeshGenerator_axl.h"
60 bool z_is_total,
Int32 mesh_dimension,
Real random_coef,
63 , m_wanted_x(wanted_x)
64 , m_wanted_y(wanted_y)
65 , m_wanted_z(wanted_z)
68 , m_mesh_dimension(mesh_dimension)
69 , m_random_coef(random_coef)
80 return m_communicating_sub_domains;
123communicatingSubDomains()
const
126 return m_p->communicatingSubDomains();
133bool SodMeshGenerator::
134readOptions(XmlNode node)
136 Int32 wanted_x = node.child(
"x").valueAsInteger();
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";
149 else if (z_node.null()) {
150 info() <<
"[SodMeshGenerator] 2D";
154 wanted_z = y_node.valueAsInteger();
158 info() <<
"[SodMeshGenerator] 3D";
160 wanted_y = y_node.valueAsInteger();
161 wanted_z = z_node.valueAsInteger();
164 bool z_is_total = z_node.attr(
"total").valueAsBoolean();
166 Real delta0 = x_node.attr(
"delta").valueAsReal();
167 Real delta1 = y_node.attr(
"delta").valueAsReal();
168 Real delta2 = z_node.attr(
"delta").valueAsReal();
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>";
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);
202 Int64 unique_id = ay + (az + first_z) * anb_y +
ax * anb_y * total_para_z;
209bool SodMeshGenerator::
212 return m_p->generateMesh(m_mesh);
218bool SodMeshGenerator::Impl::
219generateMesh(IPrimaryMesh* mesh)
221 info() <<
"Generate Mesh from SodMeshGenerator";
223 IParallelMng* pm = mesh->parallelMng();
224 bool is_parallel = pm->isParallel();
225 Int32 nb_part = pm->commSize();
228 m_wanted_z /= nb_part;
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;
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);
243 Int32 my_part = pm->commRank();
244 bool is_first_proc = (my_part == 0);
245 bool is_last_proc = ((1 + my_part) == 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;
251 if (is_first_proc || is_last_proc) {
252 m_communicating_sub_domains.resize(1);
253 first_cell_z = nb_cell_z * my_part;
255 m_communicating_sub_domains[0] = my_part + 1;
258 else if (is_last_proc) {
259 m_communicating_sub_domains[0] = my_part - 1;
263 first_node_z = first_cell_z;
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;
275 Integer nb_node_x = nb_cell_x + 1;
277 Integer nb_node_z = nb_cell_z + 1;
279 if (m_mesh_dimension == 3) {
280 nb_node_y = nb_cell_y + 1;
282 else if (m_mesh_dimension == 2) {
285 else if (m_mesh_dimension == 1) {
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);
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);
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);
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;
308 const Int64 uid_multiplier = 1;
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;
317 info() <<
"Number of nodes " << mesh_nb_node;
318 info() <<
"Number of faces " << mesh_nb_face;
319 info() <<
"Number of cells " << mesh_nb_cell;
321 info() <<
"nb node_yz=" << nb_node_yz;
327 HashTableMapT<Int64, NodeInfo> nodes_infos(mesh_nb_node,
true);
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];
333 Real middle_x = ARCANE_REAL(0.5);
335 Real middle_height = ARCANE_REAL((nb_cell_y / 2) * ydelta);
337 if (m_xyz_delta[0] != 0.0)
338 middle_x = m_xyz_delta[0] * (nb_cell_x / 2);
340 if (m_mesh_dimension == 2) {
342 middle_height = (nb_cell_z / 2) * zdelta;
345 info() <<
"Xdelta=" << xdelta <<
", Ydelta=" << ydelta <<
", Zdelta=" << zdelta;
346 info() <<
"middle_x=" << middle_x <<
", middle_height=" << middle_height;
350 if (m_zyx_generate ==
false) {
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) {
358 Real nz = zdelta * (
Real)(z + first_node_z);
359 if (m_mesh_dimension == 2) {
363 else if (m_mesh_dimension == 1) {
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;
369 nodes_unique_id[node_local_id] = node_unique_id;
373 if (z == (nb_node_z - 1) && !is_last_proc)
376 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
385 nb_node_local_id = node_local_id;
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) {
394 Real nz = zdelta * (
Real)(z + first_node_z);
395 if (m_mesh_dimension == 2) {
399 else if (m_mesh_dimension == 1) {
403 node_unique_id *= uid_multiplier;
405 nodes_unique_id[node_local_id] = node_unique_id;
409 if (z == (nb_node_z - 1) && !is_last_proc)
411 nodes_infos.nocheckAdd(node_unique_id, NodeInfo(owner, Real3(nx, ny, nz)));
419 nb_node_local_id = node_local_id;
430 if (m_mesh_dimension == 1) {
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;
439 cell_unique_id *= uid_multiplier;
441 cells_infos[cells_infos_index] = IT_CellLine2;
444 cells_infos[cells_infos_index] = cell_unique_id;
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];
451 cells_infos_index += current_cell_nb_node;
456 else if (m_mesh_dimension == 2) {
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;
465 cell_unique_id *= uid_multiplier;
467 cells_infos[cells_infos_index] = IT_Quad4;
470 cells_infos[cells_infos_index] = cell_unique_id;
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];
479 cells_infos_index += current_cell_nb_node;
484 else if (m_mesh_dimension == 3) {
485 if (m_zyx_generate ==
false) {
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;
492 cell_unique_id *= uid_multiplier;
494 cells_infos[cells_infos_index] = IT_Hexaedron8;
496 cells_infos[cells_infos_index] = cell_unique_id;
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;
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;
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;
523 cells_infos[cells_infos_index] = cell_unique_id;
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;
550 mesh->setDimension(m_mesh_dimension);
551 mesh->allocateCells(mesh_nb_cell, cells_infos,
true);
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;
568 nodes_coord_var.synchronize();
571 SodStandardGroupsBuilder groups_builder(
traceMng());
572 Real max_x = xdelta * nb_cell_x;
573 Real max_y = ydelta * nb_cell_y;
575 if (m_mesh_dimension == 2) {
577 info() <<
"[SodMeshGenerator::generateMesh] max_y=" << max_y;
580 groups_builder.generateGroups(mesh, Real3::null(), Real3(max_x, max_y, max_z), middle_x, middle_height,
true);
583 bool is_random = !math::isNearlyZero(m_random_coef);
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) {
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)))) {
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;
604 if (m_mesh_dimension == 2) {
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;
612 pos += Real3(xd, yd, zd);
614 nodes_infos.add(node_unique_id, NodeInfo(0, pos));
620 nodes_coord_var[inode] = nodes_infos.lookupValue(node.uniqueId()).m_coord;
622 nodes_coord_var.synchronize();
624 info() <<
"End of mesh generation";
634class Sod3DMeshGenerator
647 ARCANE_UNUSED(build_info);
655 Real random_coef = 0.0;
659 bool z_is_total =
false;
661 z_is_total, 3, random_coef, delta0, delta1, delta2);
669ARCANE_REGISTER_SERVICE_SOD3DMESHGENERATOR(Sod3D, Sod3DMeshGenerator);
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.
Real m_xyz_delta[3]
the deltas
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.
Namespace for accelerator usage.
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.
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.
@ IK_Node
Node mesh entity.
double Real
Type representing a real number.
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
std::int32_t Int32
Signed integer type of 32 bits.