Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ArcaneBasicMeshSubdividerService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* ArcaneBasicMeshSubdividerService.cc (C) 2000-2024 */
9/* */
10/* Service Arcane gérant un maillage du jeu de données. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/IMeshSubdivider.h"
15
16#include "arcane/impl/ArcaneBasicMeshSubdividerService_axl.h"
17
18
19
20#include "arcane/core/ItemGroup.h"
21#include "arcane/core/ItemPrinter.h"
22#include "arcane/core/IItemFamily.h"
23#include "arcane/core/IGhostLayerMng.h"
25#include "arcane/core/IMeshModifier.h"
26
27#include "arcane/core/SimpleSVGMeshExporter.h" // Write au format svg pour le 2D
28// Write variables
29
30#include "arcane/core/ServiceBuilder.h"
31#include "arcane/core/Directory.h"
32#include "arcane/core/IVariableMng.h"
33#include "arcane/core/IParallelMng.h"
34#include "arcane/core/BasicService.h"
35#include "arcane/core/IPrimaryMesh.h"
36
37// get parameter
38#include "arcane/utils/ApplicationInfo.h"
39#include "arcane/utils/CommandLineArguments.h"
40
41// utils
42#include <unordered_set>
43#include <algorithm>
44#include <iterator>
45
46#include "arcane/core/IMeshUtilities.h"
47
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52namespace Arcane
53{
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
62{
63 public:
64
66
67 public:
68
69 void subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh) override;
70};
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75ArcaneBasicMeshSubdividerService::
76ArcaneBasicMeshSubdividerService(const ServiceBuildInfo& sbi)
78{
79}
80
81/*---------------------------------------------------------------------------*/
82/*---------------------------------------------------------------------------*/
83
86{
87 info() << "#subdivide mesh";
88 // Est-ce qu'on est en 3D ?
89 // Si non on fait rien;
90 bool is_hex=true;
91 ENUMERATE_CELL(icell,mesh->ownCells()){
92 const Cell & cell = *icell;
93 if( cell.itemTypeId() != IT_Hexaedron8)
94 is_hex = false;
95 }
96 if( !is_hex )
97 return ;
98
99 Int32 my_rank = mesh->parallelMng()->commRank();
100 IMeshModifier* mesh_modifier = mesh->modifier();
101
102 debug() << "PART 3D";
103 mesh->utilities()->writeToFile("3D_last_input"+std::to_string(my_rank)+".vtk", "VtkLegacyMeshWriter");
104
105 // PAS DE GHOST LAYER
106 IGhostLayerMng* gm = mesh->ghostLayerMng();
107 Int32 version = gm->builderVersion();
108 if (version < 3)
109 gm->setBuilderVersion(3);
110 gm->setNbGhostLayer(0);
111 mesh_modifier->setDynamic(true);
112 mesh_modifier->updateGhostLayers();
113
114 // Uniquement pour les vérifications asserts à la fin
115 Integer nb_cell_init = mesh->nbCell();
116 Integer nb_face_init = mesh->nbFace();
117 Integer nb_edge_init = mesh->nbEdge();
118 Integer nb_node_init = mesh->nbNode();
119
120 // Compter les arrêtes
121 // On cherche un moyen de compter les arrêtes pour faire un test facile sur le nombre de noeud inséré.
122 // ARCANE_ASSERT((nb_edge_init+ nb_cell_init + nb_face_init)== nb_node_added,("Mauvais nombre de noeuds insérés"));
123 //debug() << "#NOMBRE INITS " << nb_node_init << " " << mesh->allEdges().size() << " " << edg.size() << " " << nb_face_init << " " << nb_cell_init ;
124
125 // VARIABLES
126 // Items à ajouter avec connectivités pour E F et C
131
132 Integer nb_cell_to_add=0;
133 Integer nb_face_to_add=0;
134
135 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
136 std::unordered_map<Int64, Real3> nodes_to_add_coords;
137 debug() << "ARRAY SIZE " << nodes_coords.arraySize() ;
138 // Nodes on entities
139 std::set<Int64> new_nodes; // Utiliser une map permet s'assurer qu'on ajoute une seule fois un noeud avec un uniqueId()
140 std::set<Int64> new_faces; // ^--- Pareil pour les faces
141 // Maps owners
142 std::unordered_map<Int64, Int32> node_uid_to_owner;
143 std::unordered_map<Int64, Int32> edge_uid_to_owner; // pas utilisé
144 std::unordered_map<Int64, Int32> face_uid_to_owner;
145 std::unordered_map<Int64,Int32> child_cell_owner; // pas utilisé
146 std::unordered_map<Int32, Int32> old_face_lid_to_owner; // pas utilisé
147
148
149 UniqueArray<Int32> cells_to_detach; // Cellules à détacher
150
151 UniqueArray<Int64> faces_uids; // Contient uniquement les uids pas les connectivités
153
154 // Calcul nombre de noeuds à insérer
155 const Integer nb_node_to_add_total = mesh->nbCell()+mesh->nbFace()+mesh->nbEdge(); // Attention pattern dépendant
158
159 Arcane::VariableNodeReal3& nodes_coordinates = mesh->nodesCoordinates();
160 Integer ind_new_cell = 0 ;
161
162 ARCANE_ASSERT((mesh->nbEdge() == 0 ),("Wrong number of edge"));
163
164 // Traitement pour une cellule
165 ENUMERATE_CELL(icell,mesh->ownCells())
166 {
167 // Génération des nouveaux noeuds (uid et coordonnées)
168 // Sur Arrêtes
169 // Sur Faces
170 // Sur Cellule
171
172 // Génération des Faces (uid et composants (Noeuds))
173 // Internes
174 // Externes
175
176 // Génération des Cellules (uid et composants (Noeuds))
177 // Détachement des cellules
178 // Ajout des noeuds enfants
179 // Ajout des faces enfants
180 // Ajout des cellules enfants (et assignation propriétaire)
181
182 // Ajout d'une couche fantome
183 // Calcul des propriétaires des noeuds
184 // Calcul des propriétaires des faces
185 // Supression de la couche fantome
186
187 // Assignation des noeuds au propriétaire
188 // Assignation des faces au propriétaire
189
190 const Cell& cell = *icell;
191 //debug() << "CELL_OWNER " << cell.owner() ;
192 cells_to_detach.add(cell.localId());
193 // Génération des noeuds
194 Int64 node_in_cell[27];
195 // Noeuds initiaux
196 node_in_cell[0] = cell.node(0).uniqueId().asInt64();
197 node_in_cell[1] = cell.node(1).uniqueId().asInt64();
198 node_in_cell[2] = cell.node(2).uniqueId().asInt64();
199 node_in_cell[3] = cell.node(3).uniqueId().asInt64();
200 node_in_cell[4] = cell.node(4).uniqueId().asInt64();
201 node_in_cell[5] = cell.node(5).uniqueId().asInt64();
202 node_in_cell[6] = cell.node(6).uniqueId().asInt64();
203 node_in_cell[7] = cell.node(7).uniqueId().asInt64();
204 Integer index_27 = 8;
205 // Génération des nouveaux noeuds sur arrêtes
206 Integer new_nodes_on_edges_couple[][2] = {{0, 1},{0, 3},{0, 4},{1, 2},{1, 5},{2, 3},{2, 6},{3, 7},{4, 5},{4, 7},{5, 6},{6, 7}};
207 // ^--- Tableau d'arretes
208 for( Integer i = 0 ; i < 12 ; i++ ){
209 // uid
213 };
214 if( tmp[0] > tmp[1] ){
215 std::swap(tmp[0],tmp[1]);
216 }
217 debug() << "#TMP " << "cell" << cell.uniqueId() << ' ' << tmp ;
218 node_in_cell[index_27] = Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
219 // Coord on edge
220 Arcane::Real3 middle_coord(0.0,0.0,0.0);
221 middle_coord = (nodes_coordinates[cell.node(new_nodes_on_edges_couple[i][0])] + nodes_coordinates[cell.node(new_nodes_on_edges_couple[i][1])] ) / 2.0;
223
224 index_27++;
225 }
226 ARCANE_ASSERT((index_27 == 20),("wrong number"));
227 // Noeuds sur faces
228 Integer new_nodes_on_faces_quatuor[][4] ={
229 { 0, 1, 2, 3 },
230 { 0, 1, 5, 4 },
231 { 0, 4, 7, 3 },
232 { 1, 5, 6, 2 },
233 { 2, 3, 7, 6 },
234 { 4, 5, 6, 7 }
235 };
236
237 for( Integer i = 0 ; i < 6 ; i++ ){
243 };
244 std::sort(tmp.begin(),tmp.end());
245 Int64 nuid = Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
247 // Coord on face
248 Arcane::Real3 middle_coord(0.0,0.0,0.0);
249 middle_coord = ( nodes_coordinates[cell.node(new_nodes_on_faces_quatuor[i][0])] + nodes_coordinates[cell.node(new_nodes_on_faces_quatuor[i][1])] + nodes_coordinates[cell.node(new_nodes_on_faces_quatuor[i][2])] + nodes_coordinates[cell.node(new_nodes_on_faces_quatuor[i][3])] ) / 4.0;
251 index_27++;
252 }
253
254 ARCANE_ASSERT((index_27 == 26),("wrong number"));
255
256 Integer new_nodes_on_cell_oct[8] = {0, 1, 5, 4, 3, 2, 7, 6};
257 // Noeud sur cell
267 };
268
269 // Le noeud central à son uid généré a partir des uid de la cellule parent
270 node_in_cell[index_27] = Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
271
272 // Calcul des coordonnées du noeud central
273 Arcane::Real3 middle_coord(0.0,0.0,0.0);
274 for( Integer i = 0 ; i < 8 ; i++ ){
275 middle_coord += nodes_coordinates[cell.node(new_nodes_on_cell_oct[i])];
276 }
277 middle_coord /= 8.0;
279
280 // Génération des Edges
281 // Pas obligatoire
282 for( Integer i = 8 ; i < 27 ; i++){
283 // Nous calculons plusieurs fois les noeuds pour chaque Cellule (TODO améliorer ça)
284 // Si un noeud n'est pas dans la map, on l'ajoute
285 if( new_nodes.find(node_in_cell[i]) == new_nodes.end() ){
287 new_nodes.insert(node_in_cell[i]);
288 }
289 }
290 debug() << nodes_to_add_coords.size() << " " << nodes_to_add.size() ;
291
292 ARCANE_ASSERT((nodes_to_add_coords.size() == static_cast<size_t>(nodes_to_add.size())),("Has to be same"));
293 // Génération des Faces
294 // - Internes 12
295 Int64 internal_faces[][4]=
296 {
297 {8, 20, 26, 21}, // 6
298 {20, 13, 24, 26}, // 7
299 {9, 22, 26, 20}, // 8
300 {20, 26, 23, 11}, // 9
301 {21, 16, 25, 26}, // 10
302 {26, 25, 19, 24}, // 11
303 {22, 17, 25, 26}, // 12
304 {26, 25, 18, 23}, // 13
305 {10, 21, 26, 22}, // 22, 26, 21, 10}, // 14
306 {21, 12, 23, 26}, // 15 :21 12 23 26 ? 26, 23, 12, 21
307 {22, 26, 24, 15}, // 16 :22 26 24 15 ? // ici BUG
308 {26, 23, 14, 24}, // 17 : 26 23 14 24 // ici BUG
309 };
310
311 // Génération des faces enfants
312 // L'uid d'une nouvelle face est généré avec un hash utilisant les uid des noeuds triés
313 for( Integer i = 0 ; i < 12 ; i++ ){
315 std::sort(tmp.begin(),tmp.end());
316 Int64 uidface = Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
317
318 if( new_faces.find(uidface) == new_faces.end() ){ // Not already in map pas utile ici normalement
319 // Ajouter connectivités
320 faces_to_add.add(IT_Quad4);
326 // Ajouter dans tableau uids faces
327 faces_uids.add(uidface);
328 debug() << 6+ nb_face_to_add << " " << uidface ;
330 new_faces.insert(uidface);
331 }
332 }
333
334 // - Externes 6*4
335 const Int64 faces[][4] = {
336 {0, 8, 20, 9}, // Arr
337 {9, 20, 13, 3},
338 {8, 1, 11, 20},
339 {20, 11, 2, 13},
340 {0, 10, 22, 9}, // Gauche
341 {9, 22, 15, 3},
342 {10, 4, 17, 22},
343 {22, 17, 7, 15},
344 {1, 12, 23, 11}, // Droite
345 {11, 23, 14, 2},
346 {12, 5, 18, 23},
347 {23, 18, 6, 14},
348 {7, 19 ,24, 15}, // haut
349 {19, 6 ,14, 24},
350 {15, 24, 13, 3},
351 {24, 14, 2, 13},
352 {4, 16, 21, 10}, // bas
353 {10, 21, 8, 0},
354 {16, 5, 12, 21},
355 {21, 12, 1, 8},
356 {4 ,16, 25 ,17 }, //devant
357 {17, 25, 19, 7},
358 {16, 5, 18, 25 },
359 {25, 18, 6, 19}
360 };
361
362 for(Integer i = 0 ; i < 24 ; i++){
363 UniqueArray<Int64> tmp = {node_in_cell[faces[i][0]],node_in_cell[faces[i][1]],node_in_cell[faces[i][2]],node_in_cell[faces[i][3]]};
364 std::sort(tmp.begin(),tmp.end());
365 Int64 uidface = Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
366 if( new_faces.find(uidface) == new_faces.end() ){
367 faces_to_add.add(IT_Quad4);
369 faces_to_add.add(node_in_cell[faces[i][0]]);
370 faces_to_add.add(node_in_cell[faces[i][1]]);
371 faces_to_add.add(node_in_cell[faces[i][2]]);
372 faces_to_add.add(node_in_cell[faces[i][3]]);
373 // Ajouter dans tableau uids faces
374 faces_uids.add(uidface);
375 new_faces.insert(uidface);
377 }
378 }
379
380
381 // Génération des Hexs
382 const Integer new_hex_nodes_index[][8] = {
383 {0, 8, 20, 9, 10, 21, 26, 22 },
384 {10, 21, 26, 22, 4, 16, 25, 17 },
385 {8, 1, 11, 20, 21, 12, 23, 26 },
386 {21, 12, 23, 26, 16, 5, 18, 25 },
387 {9, 20, 13, 3, 22, 26, 24, 15 },
388 {22, 26, 24, 15, 17, 25, 19, 7 },
389 {20, 11, 2, 13, 26, 23, 14, 24 },
390 {26, 23, 14, 24, 25, 18, 6, 19 }
391 };
392
393 // Génération des cellules enfants
394 // L'uid est généré à partir du hash de chaque noeuds triés par ordre croissant
395 for( Integer i = 0 ; i < 8 ; i++ ){
396 // Le nouvel uid est généré avec le hash des nouveaux noeuds qui compose la nouvelle cellule
398 tmp.reserve(8);
399 for( Integer j = 0 ; j < 8 ; j++){
401 }
402 std::sort(tmp.begin(),tmp.end());
403 Int64 cell_uid = Arcane::MeshUtils::generateHashUniqueId(tmp.constView());//max_cell_uid+ind_new_cell;
404
405 //Int64 cell_uid = max_cell_uid+ind_new_cell;
406 cells_to_add.add(IT_Hexaedron8);
407 cells_to_add.add(cell_uid);// uid hex // TODO CHANGER par max_uid + cell_uid * max_nb_node
416 child_cell_owner[cell_uid] = cell.owner();
418 ind_new_cell++;
419 }
420 }
421 // Ajout des nouveaux Noeuds
422 Integer nb_node_added = nodes_to_add.size();
424
425 mesh->modifier()->addNodes(nodes_to_add, nodes_lid.view());
426
427 // Edges: Pas de génération d'arrête
428
429 // Ajout des Faces enfants
431
432 mesh->modifier()->addFaces(MeshModifierAddFacesArgs(nb_face_to_add, faces_to_add.constView(),face_lid.view()));
433 debug() << "addOneFac" << nb_face_to_add ;
434 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid,faces_uids,true);
435 debug() << "NB_FACE_ADDED AFTER " << face_lid.size() << " " << new_faces.size() ;
436
437 ARCANE_ASSERT((nb_face_to_add == (faces_to_add.size()/6)),("non consistant number of faces"));
438
439 // Ajout des cellules enfants
441 mesh->modifier()->addCells(nb_cell_to_add, cells_to_add.constView(),cells_lid);
442 mesh->modifier()->removeCells(cells_to_detach.constView());
443
444 mesh->modifier()->endUpdate();
445
446 // Gestion et assignation du propriétaire pour chaque cellule
447 // Le propriétaire est simplement le sous domaine qui a générer les nouvelles cellules
448 ENUMERATE_ (Cell, icell, mesh->allCells()){
449 Cell cell = *icell;
451 }
452 mesh->cellFamily()->notifyItemsOwnerChanged();
453
454 // Assignation des coords aux noeuds
455 ENUMERATE_(Node, inode, mesh->nodeFamily()->view(nodes_lid)){
456 Node node = *inode;
458 }
459
460 // Ajout d'une couche fantôme
461 Arcane::IGhostLayerMng * gm2 = mesh->ghostLayerMng();
462 gm2->setNbGhostLayer(1);
463 mesh->updateGhostLayers(true);
464
465 // Gestion des propriétaires de noeuds
466 // Le propriétaire est la cellule incidente au noeud avec le plus petit uniqueID()
467 ENUMERATE_(Node, inode, mesh->allNodes()){
468 Node node = *inode;
469 auto it = std::min_element(node.cells().begin(),node.cells().end());
470 Cell cell = node.cell(static_cast<Int32>(std::distance(node.cells().begin(),it)));
471 node_uid_to_owner[node.uniqueId().asInt64()] = cell.owner();
472 }
473
474 // Gestion des propriétaires des faces
475 // Le propriétaire est la cellule incidente à la face avec le plus petit uniqueID()
476 ENUMERATE_(Face, iface, mesh->allFaces()){
477 Face face = *iface;
478 auto it = std::min_element(face.cells().begin(),face.cells().end());
479 Cell cell = face.cell(static_cast<Int32>(std::distance(face.cells().begin(),it)));
480 face_uid_to_owner[face.uniqueId().asInt64()] = cell.owner();
481 }
482
483 // Supression de la couche fantôme
484 gm2->setNbGhostLayer(0);
485 mesh->updateGhostLayers(true);
486
487 // Assignation du nouveau propriétaire pour chaque noeud
488 ENUMERATE_ (Node, inode, mesh->allNodes()){
489 Node node = *inode;
490 node.mutableItemBase().setOwner(node_uid_to_owner[node.uniqueId().asInt64()], my_rank);
491 }
492 mesh->nodeFamily()->notifyItemsOwnerChanged();
493
494 // Assignation du nouveaux propriétaires pour chaque face
495 ENUMERATE_ (Face, iface, mesh->allFaces()){
496 Face face = *iface;
497 face.mutableItemBase().setOwner(face_uid_to_owner[face.uniqueId().asInt64()], my_rank);
498 }
499 mesh->faceFamily()->notifyItemsOwnerChanged();
500
501 // Ecriture au format VTK
502 mesh->utilities()->writeToFile("3Drefined"+std::to_string(my_rank)+".vtk", "VtkLegacyMeshWriter");
503 info() << "Writing VTK 3Drefine" ;
504 debug() << "END 3D fun" ;
505 debug() << "NB CELL " << mesh->nbCell() << " " << nb_cell_init*8 ;
506 debug() << mesh->nbNode() << " " << nb_node_init << " " << nb_edge_init << " " << nb_face_init << " " << nb_cell_init;
507 debug() << mesh->nbFace() << "nb_face_init " << nb_face_init << " " << nb_face_init << " " << nb_cell_init ;
508 debug() << "Faces: " << mesh->nbFace() << " theorical nb_face_to add: " << nb_face_init*4 + nb_cell_init*12 << " nb_face_init " << nb_face_init << " nb_cell_init " << nb_cell_init ;
509
510 // ARCANE_ASSERT((mesh->nbNode() == nb_edge_init + nb_face_init + nb_cell_init ),("Wrong number of node added")) // Ajouter en debug uniquement pour savoir combien de noeud on à la fin
511 ARCANE_ASSERT((mesh->nbCell() == nb_cell_init*8 ),("Wrong number of cell added"));
512 ARCANE_ASSERT((mesh->nbFace() <= nb_face_init*4 + 12 * nb_cell_init ),("Wrong number of face added"));
513}
514
515/*---------------------------------------------------------------------------*/
516/*---------------------------------------------------------------------------*/
517
518ARCANE_REGISTER_SERVICE_ARCANEBASICMESHSUBDIVIDERSERVICE(ArcaneBasicMeshSubdivider,
520
521/*---------------------------------------------------------------------------*/
522/*---------------------------------------------------------------------------*/
523
524} // End namespace Arcane
525
526/*---------------------------------------------------------------------------*/
527/*---------------------------------------------------------------------------*/
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
Fonctions utilitaires sur le maillage.
Service Arcane un maillage du jeu de données.
void subdivideMesh(IPrimaryMesh *mesh) override
Subdivise le maillage mesh.
Maille d'un maillage.
Definition Item.h:1178
Face d'une maille.
Definition Item.h:932
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1617
CellConnectedListViewType cells() const
Liste des mailles de la face.
Definition Item.h:1012
Interface de modification du maillage.
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:365
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:229
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
ItemTypeId itemTypeId() const
Type de l'entité
Definition Item.h:235
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Arguments pour IMeshModifier::addFaces().
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
Noeud d'un maillage.
Definition Dom.h:204
Cell cell(Int32 i) const
i-ème maille du noeud
Definition Item.h:1568
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Definition Item.h:670
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Structure contenant les informations pour créer un service.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-