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"
59 bool z_is_total,
Int32 mesh_dimension,
Real random_coef,
62 m_wanted_x(wanted_x), m_wanted_y(wanted_y), m_wanted_z(wanted_z),
64 m_random_coef(random_coef)
74 return m_communicating_sub_domains;
117communicatingSubDomains()
const
120 return m_p->communicatingSubDomains();
127bool SodMeshGenerator::
128readOptions(XmlNode node)
130 Int32 wanted_x = node.child(
"x").valueAsInteger();
133 Int32 mesh_dimension = 1;
134 XmlNode x_node = node.child(
"x");
135 XmlNode y_node = node.child(
"y");
136 XmlNode z_node = node.child(
"z");
137 if (z_node.null() && y_node.null()){
138 info() <<
"[SodMeshGenerator] 1D";
143 else if (z_node.null()){
144 info() <<
"[SodMeshGenerator] 2D";
148 wanted_z = y_node.valueAsInteger();
152 info() <<
"[SodMeshGenerator] 3D";
154 wanted_y = y_node.valueAsInteger();
155 wanted_z = z_node.valueAsInteger();
158 bool z_is_total = z_node.attr(
"total").valueAsBoolean();
160 Real delta0 = x_node.attr(
"delta").valueAsReal();
161 Real delta1 = y_node.attr(
"delta").valueAsReal();
162 Real delta2 = z_node.attr(
"delta").valueAsReal();
164 Real random_coef = node.child(
"random-coef").valueAsReal();
165 if (wanted_x==0 || wanted_y==0 || wanted_z==0){
166 info() <<
"Bad syntax for <meshgenerator>";
167 info() <<
"Expected is <meshgenerator><sod><x>nx</x><y>ny</y><z>nz</z></sod></meshgenerator>";
168 info() <<
"or <meshgenerator><sod><x>nx</x><y>ny</y></sod></meshgenerator>";
169 info() <<
"or <meshgenerator><sod><x>nx</x></sod></meshgenerator>";
170 error() <<
"Bad syntax for <meshgenerator>";
173 m_p = std::make_unique<Impl>(
traceMng(),m_zyx_generate,wanted_x,wanted_y,wanted_z,z_is_total,
174 mesh_dimension,random_coef,delta0,delta1,delta2);
195 Int64 unique_id = ay + (az+first_z)*anb_y +
ax*anb_y*total_para_z;
202bool SodMeshGenerator::
205 return m_p->generateMesh(m_mesh);
211bool SodMeshGenerator::Impl::
212generateMesh(IPrimaryMesh* mesh)
214 info() <<
"Generate Mesh from SodMeshGenerator";
216 IParallelMng* pm = mesh->parallelMng();
217 bool is_parallel = pm->isParallel();
218 Int32 nb_part = pm->commSize();
221 m_wanted_z /= nb_part;
223 Integer nb_cell_x = m_wanted_x;
224 Integer nb_cell_y = m_wanted_y;
225 Integer nb_cell_z = m_wanted_z;
226 info() <<
"nb x=" << nb_cell_x <<
" y=" << nb_cell_y <<
" z=" << nb_cell_z;
231 Properties* mesh_properties = mesh->properties();
232 mesh_properties->setInt64(
"GlobalNbCellX",nb_cell_x);
233 mesh_properties->setInt64(
"GlobalNbCellY",nb_cell_y);
234 mesh_properties->setInt64(
"GlobalNbCellZ",nb_cell_z);
236 Int32 my_part = pm->commRank();
237 bool is_first_proc = (my_part==0);
238 bool is_last_proc = ((1+my_part)==nb_part);
240 Int64 total_para_node_z = total_para_cell_z+1;
241 Int64 first_cell_z = 0;
242 Int64 first_node_z = 0;
244 if (is_first_proc || is_last_proc){
245 m_communicating_sub_domains.resize(1);
246 first_cell_z = nb_cell_z*my_part;
248 m_communicating_sub_domains[0] = my_part+1;
251 else if (is_last_proc){
252 m_communicating_sub_domains[0] = my_part-1;
256 first_node_z = first_cell_z;
259 m_communicating_sub_domains.resize(2);
260 m_communicating_sub_domains[0] = my_part-1;
261 m_communicating_sub_domains[1] = my_part+1;
262 first_cell_z = (nb_cell_z*my_part);
263 first_node_z = first_cell_z;
268 Integer nb_node_x = nb_cell_x+1;
270 Integer nb_node_z = nb_cell_z+1;
272 if (m_mesh_dimension==3){
273 nb_node_y = nb_cell_y + 1;
275 else if (m_mesh_dimension==2){
278 else if (m_mesh_dimension==1){
283 Integer nb_node_xy = CheckedConvert::multiply(nb_node_x,nb_node_y);
284 Integer nb_node_yz = CheckedConvert::multiply(nb_node_y,nb_node_z);
286 Integer nb_cell_xy = CheckedConvert::multiply(nb_cell_x,nb_cell_y);
287 Integer nb_cell_yz = CheckedConvert::multiply(nb_cell_y,nb_cell_z);
288 Integer nb_cell_xz = CheckedConvert::multiply(nb_cell_x,nb_cell_z);
290 Integer nb_face_x = CheckedConvert::multiply(nb_node_x,nb_cell_yz);
291 Integer nb_face_y = CheckedConvert::multiply(nb_node_y,nb_cell_xz);
292 Integer nb_face_z = CheckedConvert::multiply(nb_node_z,nb_cell_xy);
294 Integer mesh_nb_cell = CheckedConvert::multiply(nb_cell_x,nb_cell_y,nb_cell_z);
295 Integer mesh_nb_node = CheckedConvert::multiply(nb_node_x,nb_node_y,nb_node_z);
296 Integer mesh_nb_face = nb_face_x + nb_face_y + nb_face_z;
301 const Int64 uid_multiplier = 1;
304 info() <<
"mesh generation dim=" << m_mesh_dimension;
305 info() <<
"First mesh layer: " << first_cell_z;
306 info() <<
"Number of cells layers: " << nb_cell_z <<
'/' << total_para_cell_z;
307 info() <<
"First node layer: " << first_node_z;
308 info() <<
"Number of nodes layers: " << nb_node_z <<
'/' << total_para_node_z;
310 info() <<
"Number of nodes " << mesh_nb_node;
311 info() <<
"Number of faces " << mesh_nb_face;
312 info() <<
"Number of cells " << mesh_nb_cell;
314 info() <<
"nb node_yz=" << nb_node_yz;
320 HashTableMapT<Int64,NodeInfo> nodes_infos(mesh_nb_node,
true);
322 Real ydelta = (m_xyz_delta[1]==0.0) ? ARCANE_REAL(0.02) : m_xyz_delta[1];
323 Real zdelta = (m_xyz_delta[2]==0.0) ? ARCANE_REAL(0.02) : m_xyz_delta[2];
324 Real xdelta = (m_xyz_delta[0]==0.0) ? ARCANE_REAL(1.0)/(
Real)(nb_cell_x):m_xyz_delta[0];
326 Real middle_x = ARCANE_REAL(0.5);
328 Real middle_height = ARCANE_REAL((nb_cell_y/2)*ydelta);
330 if (m_xyz_delta[0]!=0.0)
331 middle_x = m_xyz_delta[0] * (nb_cell_x/2);
333 if (m_mesh_dimension==2){
335 middle_height = (nb_cell_z/2)*zdelta;
338 info() <<
"Xdelta=" << xdelta<<
", Ydelta=" << ydelta <<
", Zdelta=" << zdelta;
339 info() <<
"middle_x=" << middle_x<<
", middle_height=" << middle_height;
343 if (m_zyx_generate==
false){
345 for(
Integer x=0; x<nb_node_x; ++x ){
346 for(
Integer z=0; z<nb_node_z; ++z ){
347 for(
Integer y=0; y<nb_node_y; ++y ){
351 Real nz = zdelta * (
Real)(z+first_node_z);
352 if (m_mesh_dimension==2){
356 else if (m_mesh_dimension==1){
360 node_unique_id *= uid_multiplier;
362 nodes_unique_id[node_local_id] = node_unique_id;
366 if (z==(nb_node_z-1) && !is_last_proc)
369 nodes_infos.nocheckAdd(node_unique_id,NodeInfo(owner,Real3(nx,ny,nz)));
378 nb_node_local_id = node_local_id;
382 for(
Integer z=0; z<nb_node_z; ++z ){
383 for(
Integer y=0; y<nb_node_y; ++y ){
384 for(
Integer x=0; x<nb_node_x; ++x ){
387 Real nz = zdelta * (
Real)(z+first_node_z);
388 if (m_mesh_dimension==2){
391 }
else if (m_mesh_dimension==1){
395 node_unique_id *= uid_multiplier;
397 nodes_unique_id[node_local_id] = node_unique_id;
401 if (z==(nb_node_z-1) && !is_last_proc) owner = my_part+1;
402 nodes_infos.nocheckAdd(node_unique_id,NodeInfo(owner,Real3(nx,ny,nz)));
410 nb_node_local_id = node_local_id;
421 if (m_mesh_dimension==1){
424 for(
Integer x=0; x<nb_cell_x; ++x ){
425 for(
Integer z=0; z<nb_cell_z; ++z ){
426 for(
Integer y=0; y<nb_cell_y; ++y ){
427 Integer current_cell_nb_node = 2;
430 cell_unique_id *= uid_multiplier;
432 cells_infos[cells_infos_index] = IT_CellLine2;
435 cells_infos[cells_infos_index] = cell_unique_id;
438 Integer base_id = y + z*nb_node_y + x*nb_node_yz;
439 cells_infos[cells_infos_index+0] = nodes_unique_id[base_id];
440 cells_infos[cells_infos_index+1] = nodes_unique_id[base_id + 1];
442 cells_infos_index += current_cell_nb_node;
447 else if (m_mesh_dimension==2){
450 for(
Integer x=0; x<nb_cell_x; ++x ){
451 for(
Integer z=0; z<nb_cell_z; ++z ){
452 for(
Integer y=0; y<nb_cell_y; ++y ){
453 Integer current_cell_nb_node = 4;
456 cell_unique_id *= uid_multiplier;
458 cells_infos[cells_infos_index] = IT_Quad4;
461 cells_infos[cells_infos_index] = cell_unique_id;
464 Integer base_id = y + z*nb_node_y + x*nb_node_yz;
465 cells_infos[cells_infos_index+0] = nodes_unique_id[base_id];
466 cells_infos[cells_infos_index+1] = nodes_unique_id[base_id + nb_node_yz];
467 cells_infos[cells_infos_index+2] = nodes_unique_id[base_id + nb_node_yz + 1];
468 cells_infos[cells_infos_index+3] = nodes_unique_id[base_id + 1];
470 cells_infos_index += current_cell_nb_node;
475 else if (m_mesh_dimension==3){
476 if (m_zyx_generate==
false){
478 for(
Integer x=0; x<nb_cell_x; ++x ){
479 for(
Integer z=0; z<nb_cell_z; ++z ){
480 for(
Integer y=0; y<nb_cell_y; ++y ){
481 Integer current_cell_nb_node = 8;
483 cell_unique_id *= uid_multiplier;
485 cells_infos[cells_infos_index] = IT_Hexaedron8;
487 cells_infos[cells_infos_index] = cell_unique_id;
489 Integer base_id = y + z*nb_node_y + x*nb_node_yz;
490 cells_infos[cells_infos_index+0] = nodes_unique_id[base_id];
491 cells_infos[cells_infos_index+1] = nodes_unique_id[base_id + 1];
492 cells_infos[cells_infos_index+2] = nodes_unique_id[base_id + nb_node_y + 1];
493 cells_infos[cells_infos_index+3] = nodes_unique_id[base_id + nb_node_y + 0];
494 cells_infos[cells_infos_index+4] = nodes_unique_id[base_id + nb_node_yz];
495 cells_infos[cells_infos_index+5] = nodes_unique_id[base_id + nb_node_yz + 1];
496 cells_infos[cells_infos_index+6] = nodes_unique_id[base_id + nb_node_yz + nb_node_y + 1];
497 cells_infos[cells_infos_index+7] = nodes_unique_id[base_id + nb_node_yz + nb_node_y + 0];
498 cells_infos_index += current_cell_nb_node;
504 for(
Integer z=0; z<nb_cell_z; ++z ){
505 for(
Integer y=0; y<nb_cell_y; ++y ){
506 for(
Integer x=0; x<nb_cell_x; ++x ){
507 Integer current_cell_nb_node = 8;
509 cell_unique_id *= uid_multiplier;
510 debug() <<
"[SodMeshGenerator::generateMesh] + m_zyx_generate "<<x<<
"x"<<y<<
"x"<<z<<
":"<<
", uid=" << cell_unique_id;
511 cells_infos[cells_infos_index] = IT_Hexaedron8;
513 cells_infos[cells_infos_index] = cell_unique_id;
515 Integer base_id = x + y*nb_node_x + z*nb_node_xy;
516 cells_infos[cells_infos_index+0] = nodes_unique_id[base_id];
517 cells_infos[cells_infos_index+1] = nodes_unique_id[base_id + 1];
518 cells_infos[cells_infos_index+2] = nodes_unique_id[base_id + nb_node_x + 1];
519 cells_infos[cells_infos_index+3] = nodes_unique_id[base_id + nb_node_x + 0];
520 cells_infos[cells_infos_index+4] = nodes_unique_id[base_id + nb_node_xy];
521 cells_infos[cells_infos_index+5] = nodes_unique_id[base_id + nb_node_xy + 1];
522 cells_infos[cells_infos_index+6] = nodes_unique_id[base_id + nb_node_xy + nb_node_x + 1];
523 cells_infos[cells_infos_index+7] = nodes_unique_id[base_id + nb_node_xy + nb_node_x + 0];
524 debug() <<
"[SodMeshGenerator::generateMesh] + m_zyx_generate nodes: "
525 << cells_infos[cells_infos_index+0] <<
", "
526 << cells_infos[cells_infos_index+1] <<
", "
527 << cells_infos[cells_infos_index+2] <<
", "
528 << cells_infos[cells_infos_index+3] <<
", "
529 << cells_infos[cells_infos_index+4] <<
", "
530 << cells_infos[cells_infos_index+5] <<
", "
531 << cells_infos[cells_infos_index+6] <<
", "
532 << cells_infos[cells_infos_index+7];
533 cells_infos_index += current_cell_nb_node;
540 mesh->setDimension(m_mesh_dimension);
541 mesh->allocateCells(mesh_nb_cell,cells_infos,
true);
547 IItemFamily* family = mesh->itemFamily(
IK_Node);
548 family->itemsUniqueIdToLocalId(nodes_local_id,nodes_unique_id);
549 NodeInfoListView nodes_internal(family);
550 for(
Integer i=0; i<nb_node_local_id; ++i ){
551 Node node = nodes_internal[nodes_local_id[i]];
552 Int64 unique_id = nodes_unique_id[i];
553 nodes_coord_var[node] = nodes_infos.lookupValue(unique_id).m_coord;
558 nodes_coord_var.synchronize();
561 SodStandardGroupsBuilder groups_builder(
traceMng());
562 Real max_x = xdelta * nb_cell_x;
563 Real max_y = ydelta * nb_cell_y;
565 if (m_mesh_dimension==2){
567 info()<<
"[SodMeshGenerator::generateMesh] max_y=" << max_y;
570 groups_builder.generateGroups(mesh,Real3::null(),Real3(max_x,max_y,max_z),middle_x,middle_height);
573 bool is_random = !math::isNearlyZero(m_random_coef);
575 if (m_mesh_dimension==1)
576 throw NotImplementedException(A_FUNCINFO,
"Randomisation for 1D mesh");
577 info() <<
"** ** ** Randomize node positions coef=" << m_random_coef;
578 for(
Integer x=0; x<nb_node_x; ++x ){
579 for(
Integer z=0; z<nb_node_z; ++z ){
580 for(
Integer y=0; y<nb_node_y; ++y ){
584 if (x!=0 && (x+1)!=nb_node_x && (z+first_node_z)!=0
585 && (z+first_node_z)!=(total_para_node_z-1)
586 && (m_mesh_dimension==2 || (y!=0 && y!=(nb_node_y-1)))){
591 xd = xd + (xr-0.5)*xdelta*m_random_coef;
592 yd = yd + (yr-0.5)*ydelta*m_random_coef;
593 zd = zd + (zr-0.5)*zdelta*m_random_coef;
596 if (m_mesh_dimension==2){
601 Int64 node_unique_id = y + (z+first_node_z)*nb_node_y + x*nb_node_y*total_para_node_z;
602 Real3 pos = nodes_infos.lookupValue(node_unique_id).m_coord;
604 pos += Real3(xd,yd,zd);
606 nodes_infos.add(node_unique_id,NodeInfo(0,pos));
612 nodes_coord_var[inode] = nodes_infos.lookupValue(node.uniqueId()).m_coord;
614 nodes_coord_var.synchronize();
616 info() <<
"End of mesh generation";
628class Sod3DMeshGenerator
637 ARCANE_UNUSED(build_info);
645 Real random_coef = 0.0;
649 bool z_is_total =
false;
651 z_is_total,3,random_coef,delta0,delta1,delta2);
656ARCANE_REGISTER_SERVICE_SOD3DMESHGENERATOR(Sod3D,Sod3DMeshGenerator);
Fonctions utilitaires sur le maillage.
ArcaneSod3DMeshGeneratorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsSod3DMeshGenerator * options() const
Options du jeu de données du service.
Interface du gestionnaire de traces.
Paramètres nécessaires à la construction d'un maillage.
Structure contenant les informations pour créer un service.
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.
bool m_zyx_generate
true si on génère en z, puis y et enfin x
bool m_z_is_total
true si z est le nombre total de couche pour l'ensemble des procs.
Real m_xyz_delta[3]
les deltas
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
Espace de nom pour l'utilisation des accélérateurs.
Real toReal(Real r)
Converti r en un 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)
Génère un UniqueId à partir des indices de bloc (x,y,z).
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
@ IK_Node
Entité de maillage de genre noeud.
double Real
Type représentant un réel.
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
std::int32_t Int32
Type entier signé sur 32 bits.