Arcane  4.2.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
OneMeshItemAdder.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/* OneMeshItemAdder.cc (C) 2000-2026 */
9/* */
10/* Ajout des entités une par une. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/OneMeshItemAdder.h"
15
16#include "arcane/utils/NotSupportedException.h"
17#include "arcane/utils/ValueConvert.h"
18#include "arcane/utils/FixedArray.h"
19#include "arcane/utils/HashTableMap2.h"
20
22#include "arcane/core/MeshToMeshTransposer.h"
23#include "arcane/core/IParallelMng.h"
24#include "arcane/core/ItemPrinter.h"
25#include "arcane/core/ItemTypeInfoBuilder.h"
26#include "arcane/core/internal/ItemTypeMngInternal.h"
27
28#include "arcane/mesh/DynamicMesh.h"
29#include "arcane/mesh/DynamicMeshIncrementalBuilder.h"
30#include "arcane/mesh/ItemTools.h"
31#include "arcane/mesh/ConnectivityNewWithDependenciesTypes.h"
32#include "arcane/mesh/GraphDoFs.h"
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37namespace Arcane::mesh
38{
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
44{
45 public:
46
47 CellInfoProxy(ItemTypeId type_id, ItemTypeInfo* type_info,
48 Int64 cell_uid, Int32 owner,
50 bool allow_build_face = false)
51 : m_type_info(type_info)
52 , m_cell_uid(cell_uid)
53 , m_info(info)
54 , m_owner(owner)
55 , m_type_id(type_id)
56 , m_allow_build_face(allow_build_face)
57 {}
58
59 Int64 uniqueId() const { return m_cell_uid; }
60 ItemTypeId itemTypeId() const { return m_type_id; }
61 ItemTypeInfo* typeInfo() const { return m_type_info; }
62 Int32 owner() const { return m_owner; }
63 Integer nbNode() const { return m_info.size(); }
64 Integer nbFace() const { return m_type_info->nbLocalFace(); }
65 Integer nbEdge() const { return m_type_info->nbLocalEdge(); }
66 Int64 nodeUniqueId(Integer i_node) const { return m_info[i_node]; }
67 Int32 nodeOwner(Integer) const { return m_owner; }
68 Int32 faceOwner(Integer) const { return m_owner; }
69 Int32 edgeOwner(Integer) const { return m_owner; }
70 bool allowBuildFace() const { return m_allow_build_face; }
71 bool allowBuildEdge() const { return m_allow_build_face; }
72
73 ConstArrayView<Int64> connectivityInfos() const { return m_info; }
74
75 private:
76
77 ItemTypeInfo* m_type_info = nullptr;
78 Int64 m_cell_uid = NULL_ITEM_UNIQUE_ID;
80 Int32 m_owner = A_NULL_RANK;
81 ItemTypeId m_type_id;
82 bool m_allow_build_face = false;
83};
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88OneMeshItemAdder::
89OneMeshItemAdder(DynamicMeshIncrementalBuilder* mesh_builder)
90: TraceAccessor(mesh_builder->mesh()->traceMng())
91, m_mesh(mesh_builder->mesh())
92, m_mesh_builder(mesh_builder)
93, m_cell_family(m_mesh->trueCellFamily())
94, m_node_family(m_mesh->trueNodeFamily())
95, m_face_family(m_mesh->trueFaceFamily())
96, m_edge_family(m_mesh->trueEdgeFamily())
97, m_item_type_mng(m_mesh->itemTypeMng())
98, m_mesh_info(m_mesh->meshPartInfo().partRank())
99, m_face_reorderer(m_item_type_mng)
100{
101 //m_work_face_sorted_nodes.reserve(100);
102 m_work_face_orig_nodes_uid.reserve(100);
103}
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108ItemInternal* OneMeshItemAdder::
109addOneNode(Int64 node_uid,Int32 owner)
110{
111 bool is_add = false;
112 ItemInternal* node = m_node_family.findOrAllocOne(node_uid,is_add);
113 if (is_add) {
115 node->setOwner(owner,owner);
116 }
117 return node;
118}
119
120/*---------------------------------------------------------------------------*/
121/*---------------------------------------------------------------------------*/
131{
132 Int32 nb_node = nodes_uid.size();
133 // Vérifie que le nombre de noeuds est le même
134 if (item.nbNode()!=nb_node)
135 ARCANE_FATAL("Trying to add existing item (kind='{0}', uid={1}) with different number of node (existing={2} new={3})",
136 item.kind(), item.uniqueId(), item.nbNode(), nb_node);
137
138 // Vérifie que les noeuds correspondent bien à ceux existants
139 for( Int32 i=0; i<nb_node; ++i ){
140 Int64 new_uid = nodes_uid[i];
141 Int64 current_uid = item.node(i).uniqueId();
142 if (new_uid != current_uid){
143 std::ostringstream ostr;
144 for( Int32 k=0; k<nb_node; ++k )
145 ostr << " " << item.node(k).uniqueId();
146 ARCANE_FATAL("Trying to add existing item (kind='{0}', uid={1}) with different nodes (index={2} existing='{3}' new='{4}')",
147 item.kind(), item.uniqueId(), i, ostr.str(), nodes_uid);
148 }
149 }
150}
151
152/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
161{
162 if (uid!=NULL_ITEM_UNIQUE_ID)
163 return uid;
165 uid = MeshUtils::generateHashUniqueId(nodes_uid);
166 else
167 uid = m_next_face_uid++;
168 return uid;
169}
170
171/*---------------------------------------------------------------------------*/
172/*---------------------------------------------------------------------------*/
186addOneFace(ItemTypeId type_id, Int64 face_uid, Int32 owner_rank, Int64ConstArrayView nodes_uid)
187{
188 const Integer face_nb_node = nodes_uid.size();
189
190 //m_work_face_sorted_nodes.resize(face_nb_node);
191 //m_work_face_orig_nodes_uid.resize(face_nb_node);
192 //for( Integer z=0; z<face_nb_node; ++z )
193 //m_work_face_orig_nodes_uid[z] = nodes_uid[z];
194 m_face_reorderer.reorder(type_id,nodes_uid);
195 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
196 // TODO: dans le cas où la face sera orpheline (non connectée à une maille),
197 // vérifier s'il faut réorienter la face car cela risque d'introduire
198 // une incohérence si par la suite on souhaite calculer une normale.
199 //MeshUtils::reorderNodesOfFace(m_work_face_orig_nodes_uid,m_work_face_sorted_nodes);
200 face_uid = _checkGenerateFaceUniqueId(face_uid,face_sorted_nodes);
201 bool is_add_face = false;
202 Face face = m_face_family.findOrAllocOne(face_uid,type_id,is_add_face);
203 // La face n'existe pas
204 if (is_add_face) {
205 ++m_mesh_info.nbFace();
206 face.mutableItemBase().setOwner(owner_rank, m_mesh_info.rank());
207 for(Integer i_node=0; i_node<face_nb_node; ++i_node ){
208 Node node = addOneNode(face_sorted_nodes[i_node], m_mesh_info.rank());
209 m_face_family.replaceNode(face,i_node,node);
210 m_node_family.addFaceToNode(node, face);
211 }
212 }
213 else {
214 if (arcaneIsCheck())
215 _checkSameItemCoherency(face, face_sorted_nodes);
216 }
217
218 return ItemCompatibility::_itemInternal(face);
219}
220
221/*---------------------------------------------------------------------------*/
222/*---------------------------------------------------------------------------*/
223
224ItemInternal* OneMeshItemAdder::
225addOneEdge(Int64 edge_uid, Int32 rank, Int64ConstArrayView nodes_uid)
226{
227 m_work_edge_sorted_nodes.resize(2);
228 m_work_edge_orig_nodes_uid.resize(2);
229
230 for( Integer z=0; z<2; ++z )
231 m_work_edge_orig_nodes_uid[z] = nodes_uid[z];
232 // reorderNodesOfFace se comporte ici correctement pour des arêtes == face en 2D
233 MeshUtils::reorderNodesOfFace(m_work_edge_orig_nodes_uid,m_work_edge_sorted_nodes);
234
235 bool is_add_edge = false;
236 ItemInternal* edge = m_edge_family.findOrAllocOne(edge_uid,is_add_edge);
237
238 // L'arête n'existe pas
239 if (is_add_edge) {
241 edge->setOwner(rank,m_mesh_info.rank());
242 for(Integer i_node=0; i_node<2; ++i_node ){
243 ItemInternal *current_node_internal = addOneNode(m_work_edge_sorted_nodes[i_node], m_mesh_info.rank());
244 m_edge_family.replaceNode(ItemLocalId(edge),i_node, ItemLocalId(current_node_internal));
245 m_node_family.addEdgeToNode(current_node_internal, edge);
246 }
247 }
248 return edge;
249}
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
254template<>
255Face OneMeshItemAdder::
256_findInternalFace(Integer i_face, const FullCellInfo& cell_info, bool& is_add)
257{
258 const Int64 face_unique_id = cell_info.faceUniqueId(i_face);
259 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
260 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
261 ItemTypeInfo* face_type_info = m_item_type_mng->typeFromId(lf.typeId());
262 return m_face_family.findOrAllocOne(face_unique_id,face_type_info,is_add);
263}
264
265/*---------------------------------------------------------------------------*/
266/*---------------------------------------------------------------------------*/
267
268template<>
269Face OneMeshItemAdder::
270_findInternalFace(Integer i_face, const CellInfoProxy& cell_info, bool& is_add)
271{
272 const ItemInternalMap& nodes_map = m_mesh->nodesMap();
273 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
274 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
275 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
276 Int64 face_unique_id = NULL_ITEM_UNIQUE_ID;
277 Face face_internal;
278 const bool use_hash = m_use_hash_for_edge_and_face_unique_id;
279 // Si on calcule les uniqueId() des faces à partir des noeuds,
280 // on peut directement savoir la face existe déjà. Sinon, on
281 // appelle ItemTools::findFaceInNode2() mais cette fonction est plus
282 // couteuse car elle recherche la face en parcourant les faces connectées
283 // au premier noeud de la face.
284 if (use_hash){
285 face_unique_id = _checkGenerateFaceUniqueId(NULL_ITEM_UNIQUE_ID,face_sorted_nodes);
286 face_internal = m_face_family.itemsMap().tryFind(face_unique_id);
287 }
288 else{
289 // Récupère les noeuds orientés de la face
290 // (Il faut avoir appelé une des méthodes d'ajout de face avant)
291 Node nbi = nodes_map.findItem(face_sorted_nodes[0]);
292 face_internal = ItemTools::findFaceInNode2(nbi,lf.typeId(),face_sorted_nodes);
293 }
294 if (face_internal.null()) {
295 // La face n'est pas trouvée. Elle n'existe donc pas dans notre sous-domaine.
296 // Si cela est autorisé, on créée la nouvelle face.
297 if (!cell_info.allowBuildFace() && !m_use_hash_for_edge_and_face_unique_id){
298 info() << "BadCell uid=" << cell_info.uniqueId();
299 for( Int32 i=0; i<cell_info.nbNode(); ++i )
300 info() << "Cell node I=" << i << " uid=" << cell_info.nodeUniqueId(i);
301 ARCANE_FATAL("On the fly face allocation is not allowed here.\n"
302 " You need to add faces with IMeshModifier::addFaces().\n"
303 " CellUid={0} LocalFace={1} FaceNodes={2}",
304 cell_info.uniqueId(),i_face,face_sorted_nodes);
305 }
306 // Ne recalcule le hash que si ce n'est pas déjà fait.
307 if (!use_hash)
308 face_unique_id = _checkGenerateFaceUniqueId(NULL_ITEM_UNIQUE_ID,face_sorted_nodes);
309 is_add = true;
310 ItemTypeInfo* face_type = m_item_type_mng->typeFromId(lf.typeId());
311 return m_face_family.allocOne(face_unique_id,face_type);
312 }
313 else {
314 is_add = false;
315 return face_internal;
316 }
317}
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
322template<>
323Edge OneMeshItemAdder::
324_findInternalEdge(Integer i_edge, const FullCellInfo& cell_info,
325 Int64 first_node, Int64 second_node, bool& is_add)
326{
327 ARCANE_UNUSED(first_node);
328 ARCANE_UNUSED(second_node);
329
330 const Int64 edge_unique_id = cell_info.edgeUniqueId(i_edge);
331 return m_edge_family.findOrAllocOne(edge_unique_id,is_add);
332}
333
334/*---------------------------------------------------------------------------*/
335/*---------------------------------------------------------------------------*/
336
337template<>
338Edge OneMeshItemAdder::
339_findInternalEdge(Integer i_edge, const CellInfoProxy& cell_info, Int64 first_node, Int64 second_node, bool& is_add)
340{
341 ARCANE_UNUSED(i_edge);
342
343 const bool use_hash = m_use_hash_for_edge_and_face_unique_id;
344 FixedArray<Int64,2> nodes;
345 Int64 edge_unique_id = NULL_ITEM_UNIQUE_ID;
346 Edge edge_internal;
347 if (use_hash){
348 nodes[0] = first_node;
349 nodes[1] = second_node;
350 edge_unique_id = MeshUtils::generateHashUniqueId(nodes.view());
351 edge_internal = m_edge_family.itemsMap().tryFind(edge_unique_id);
352 }
353 else{
354 const ItemInternalMap& nodes_map = m_mesh->nodesMap();
355 Node nbi = nodes_map.findItem(first_node);
356 edge_internal = ItemTools::findEdgeInNode2(nbi,first_node,second_node);
357 }
358 if (edge_internal.null()){
359 if (!cell_info.allowBuildEdge() && !use_hash)
360 ARCANE_FATAL("On the fly edge allocation is not allowed here."
361 " You need to add edges before with IMeshModifier::addEdges()");
362 if (!use_hash)
363 edge_unique_id = m_next_edge_uid++;
364 is_add = true;
365 return m_edge_family.allocOne(edge_unique_id);
366 }
367 else {
368 is_add = false;
369 return edge_internal;
370 }
371}
372
373/*---------------------------------------------------------------------------*/
374/*---------------------------------------------------------------------------*/
391ItemInternal* OneMeshItemAdder::
392addOneCell(ItemTypeId type_id, Int64 cell_uid, Int32 owner,
393 ConstArrayView<Int64> nodes_uid, bool allow_build_face)
394{
395 if (type_id == ITI_GenericPolyhedron)
396 return _addOnePolyhedron(cell_uid, nodes_uid, owner, allow_build_face);
397 CellInfoProxy cell_info_proxy(type_id, m_item_type_mng->typeFromId(type_id), cell_uid, owner, nodes_uid, allow_build_face);
398 return _addOneCell(cell_info_proxy);
399}
400
401/*---------------------------------------------------------------------------*/
402/*---------------------------------------------------------------------------*/
408ItemInternal* OneMeshItemAdder::
409addOneCell(const FullCellInfo& cell_info)
410{
411 return _addOneCell(cell_info);
412}
413
414/*---------------------------------------------------------------------------*/
415/*---------------------------------------------------------------------------*/
416
417ItemInternal* OneMeshItemAdder::
418addOneItem(IItemFamily* family,
419 IItemFamilyModifier* family_modifier,
420 ItemTypeId type_id,
421 Int64 item_uid,
422 Integer item_owner,
423 Integer sub_domain_id,
424 Integer nb_connected_family,
425 Int64ConstArrayView connectivity_info)
426{
427 ARCANE_ASSERT(m_mesh->itemFamilyNetwork(),("ItemFamilyNetwork is required to call OneMeshItemAdder::addOneItem"));
428 bool is_alloc = true;
429 Item item = family_modifier->findOrAllocOne(item_uid,type_id,m_mesh_info,is_alloc); // don't forget to add print in the class method
430 item.mutableItemBase().setOwner(item_owner,sub_domain_id);
431 // Add connectivities if needed
432 Integer info_index = 0;
433 for (Integer family_index = 0; family_index < nb_connected_family; ++family_index){
434 // get connected family
435 eItemKind family_kind = static_cast<eItemKind>(connectivity_info[info_index++]); // another way ?
436 Int32 nb_connected_item = CheckedConvert::toInt32(connectivity_info[info_index++]);
437 IItemFamily* connected_family = m_mesh->itemFamily(family_kind);
438 // get connectivities family -> connected_family and reverse
439 String connectivity_name = mesh::connectivityName(family,connected_family);
440 String reverse_connectivity_name = mesh::connectivityName(connected_family,family);
441 bool is_dependency = false;
442 IIncrementalItemConnectivity* family_to_connected_family = m_mesh->itemFamilyNetwork()->getStoredConnectivity(family,connected_family,connectivity_name,is_dependency);
443 IIncrementalItemConnectivity* connected_family_to_family = m_mesh->itemFamilyNetwork()->getStoredConnectivity(connected_family,family,reverse_connectivity_name);
444 // Clear connectivities for already allocated items (except dependencies since replace is used)
445 if (!is_alloc) {
446 if(!is_dependency) _clearConnectivity(ItemLocalId(item), family_to_connected_family);
447 if (connected_family_to_family) _clearReverseConnectivity(ItemLocalId(item),family_to_connected_family,connected_family_to_family);
448 }
449 // get connected item lids
450 Int32UniqueArray connected_item_lids(nb_connected_item);
451 connected_family->itemsUniqueIdToLocalId(connected_item_lids,connectivity_info.subView(info_index,nb_connected_item),true);
452 for (Integer connected_item_index = 0; connected_item_index < nb_connected_item; ++connected_item_index){
453 if (family_to_connected_family) {
454 // pre-alloc are done (=> use replace) when a dependency relation ("owning relation") while not when only a relation (use add)
455 if (! is_dependency) family_to_connected_family->addConnectedItem(ItemLocalId(item),ItemLocalId(connected_item_lids[connected_item_index]));
456 else family_to_connected_family->replaceConnectedItem(ItemLocalId(item),connected_item_index,ItemLocalId(connected_item_lids[connected_item_index])); // does not work with face to edges...
457 }
458 if (connected_family_to_family)
459 connected_family_to_family->addConnectedItem(ItemLocalId(connected_item_lids[connected_item_index]),ItemLocalId(item));
460 }
461 info_index+= nb_connected_item;
462 }
463// debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
464 debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
465 return ItemCompatibility::_itemInternal(item);
466}
467
468/*---------------------------------------------------------------------------*/
469
470ItemInternal* OneMeshItemAdder::
471addOneItem2(IItemFamily* family,
472 IItemFamilyModifier* family_modifier,
473 ItemTypeId type_id,
474 Int64 item_uid,
475 Integer item_owner,
476 Integer sub_domain_id,
477 Integer nb_connected_family,
478 Int64ConstArrayView connectivity_info)
479{
480 ARCANE_ASSERT(m_mesh->itemFamilyNetwork(),("ItemFamilyNetwork is required to call OneMeshItemAdder::addOneItem"));
481 bool is_alloc = true;
482 Item item = family_modifier->findOrAllocOne(item_uid,type_id,m_mesh_info,is_alloc); // don't forget to add print in the class method
483 item.mutableItemBase().setOwner(item_owner,sub_domain_id);
484 // Add connectivities if needed
485 Integer info_index = 0;
486 for (Integer family_index = 0; family_index < nb_connected_family; ++family_index) {
487 // Prepare connection
488 // get connected family
489 eItemKind family_kind = static_cast<eItemKind>(connectivity_info[info_index++]); // another way ?
490 Int32 nb_connected_item = CheckedConvert::toInt32(connectivity_info[info_index++]);
491 if (nb_connected_item == 0) continue;
492 IItemFamily* connected_family = nullptr ;
493 switch(family_kind){
494 case IK_Particle:
495 connected_family = m_mesh->findItemFamily(family_kind, ParticleFamily::defaultFamilyName(), false,false);
496 break ;
497 case IK_DoF:
498 if(family->name()==GraphDoFs::dualNodeFamilyName())
499 connected_family = m_mesh->findItemFamily(family_kind, GraphDoFs::linkFamilyName(), false,false);
500 else
501 connected_family = m_mesh->findItemFamily(family_kind, GraphDoFs::dualNodeFamilyName(), false,false);
502 break ;
503 default:
504 connected_family = m_mesh->itemFamily(family_kind);
505 break ;
506 }
507 // get connectivities family -> connected_family and reverse
508 String connectivity_name = mesh::connectivityName(family,connected_family);
509 bool is_dependency = false;
510 IIncrementalItemConnectivity* family_to_connected_family = m_mesh->itemFamilyNetwork()->getConnectivity(family,connected_family,connectivity_name,is_dependency);
511 if (!family_to_connected_family)
512 ARCANE_FATAL("Cannot find connectivity name={0}",connectivity_name);
513 bool is_deep_connectivity = m_mesh->itemFamilyNetwork()->isDeep(family_to_connected_family) ;
514 bool is_relation = !(is_dependency && is_deep_connectivity);
515 // Build connection
516 // get connected item lids
517 Int32UniqueArray connected_item_lids(nb_connected_item);
518 bool do_fatal = is_relation ? false : true; // for relations, connected items may not be present and will be skipped.
519 connected_family->itemsUniqueIdToLocalId(connected_item_lids,connectivity_info.subView(info_index,nb_connected_item),do_fatal);
520 // if connection is relation, connected item not necessarily present: remove absent (ie null) items
521 Integer nb_connected_item_found = nb_connected_item;
522 if (is_relation)
523 {
524 for (Integer index = 0; index < connected_item_lids.size(); )
525 {
526 if (connected_item_lids[index] == NULL_ITEM_LOCAL_ID) {
527 connected_item_lids.remove(index);
528 --nb_connected_item_found;
529 }
530 else ++index;
531 }
532 }
533 for (Integer connected_item_index = 0; connected_item_index < nb_connected_item_found; ++connected_item_index)
534 {
535 if (family_to_connected_family)
536 {
537 // Only strategy : check and add
538 auto connected_item_lid = ItemLocalId{connected_item_lids[connected_item_index]};
539 if (is_relation)
540 {
541 if (!family_to_connected_family->hasConnectedItem(ItemLocalId(item),connected_item_lid))
542 {
543 family_to_connected_family->addConnectedItem(ItemLocalId(item),connected_item_lid);
544 }
545 }
546 else
547 {
548 family_to_connected_family->replaceConnectedItem(ItemLocalId(item),connected_item_index,connected_item_lid);
549 }
550 }
551 }
552 info_index+= nb_connected_item;
553 }
554 if (is_alloc)
555 debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
556 // debug(Trace::Highest) << "[addItems] DEPENDENCIES for " << family->name() << FullItemPrinter(item) ; // debug info
557 // _printRelations(item); // debug info
558 return ItemCompatibility::_itemInternal(item);
559}
560
561/*---------------------------------------------------------------------------*/
562
563void OneMeshItemAdder::
564_printRelations(ItemInternal* item)
565{
566 debug(Trace::Highest) << "[addItems] RELATIONS for " << ItemPrinter(item) << " in " << item->family()->name();
567 for (const auto& relation : m_mesh->itemFamilyNetwork()->getChildRelations(item->family())) {
568// debug(Trace::Highest) << " Relation " << relation->name();
569// debug(Trace::Highest) << " Relation " << relation->nbConnectedItem(ItemLocalId(item));
570 ConnectivityItemVector connected_items(relation);
571 for (const auto& connected_item : connected_items.connectedItems(ItemLocalId(item))) {
572 debug(Trace::Highest) << ItemPrinter(connected_item);
573 }
574 }
575}
576
577/*---------------------------------------------------------------------------*/
578/*---------------------------------------------------------------------------*/
579
580void OneMeshItemAdder::
581_clearConnectivity(ItemLocalId item, IIncrementalItemConnectivity* connectivity)
582{
583
584 ConnectivityItemVector accessor(connectivity);
585 ENUMERATE_ITEM(connected_item, accessor.connectedItems(item)) {
586 connectivity->removeConnectedItem(item,connected_item);
587 }
588}
589
590/*---------------------------------------------------------------------------*/
591/*---------------------------------------------------------------------------*/
592
593void OneMeshItemAdder::
594_clearReverseConnectivity(ItemLocalId item, IIncrementalItemConnectivity* connectivity, IIncrementalItemConnectivity* reverse_connectivity)
595{
596 ConnectivityItemVector accessor(connectivity);
597 ENUMERATE_ITEM(connected_item, accessor.connectedItems(item)) {
598 reverse_connectivity->removeConnectedItem(connected_item,item);
599 }
600}
601
602/*---------------------------------------------------------------------------*/
603/*---------------------------------------------------------------------------*/
604
605template<> void OneMeshItemAdder::
606_AMR_Patch(Cell new_cell, const FullCellInfo& cell_info)
607{
609 if(m_mesh->isAmrActivated()){
610 // FIXME doit-on traiter les mailles de niveau 0
611 //comme celles de niveau superieur
612 if(cell_info.level() != 0){
613 Integer child_rank = cell_info.whichChildAmI();
614 Int64 hParent_uid = cell_info.hParentCellUniqueId();
615 ItemTypeId cell_type = ItemTypeId::fromInteger(cell_info.typeId());
616 bool is_add;
617 Cell hParent_cell= m_cell_family.findOrAllocOne(hParent_uid,cell_type,is_add);
618 m_cell_family._addParentCellToCell(new_cell,hParent_cell);
619 m_cell_family._addChildCellToCell(hParent_cell,child_rank,new_cell);
620 }
621 }
622}
623
624template<> void OneMeshItemAdder::
625_AMR_Patch(Cell cell, const CellInfoProxy& cell_info)
626{
627 ARCANE_UNUSED(cell);
628 ARCANE_UNUSED(cell_info);
629}
630
631/*---------------------------------------------------------------------------*/
632/*---------------------------------------------------------------------------*/
638template<typename CellInfo>
640_addOneCell(const CellInfo& cell_info)
641{
642 bool is_check = arcaneIsCheck();
643
644 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
645 ItemTypeId cell_type_id = cell_type_info->itemTypeId();
646 const bool is_verbose = false;
647 if (is_verbose)
648 info() << "AddNewCell type_id=" << cell_type_id << " nb_node=" << cell_info.nbNode()
649 << " type=" << cell_type_info->typeName();
650 // Regarde si la maille existe déjà (auquel cas on ne fait rien)
651 Cell inew_cell;
652 {
653 bool is_add; // ce flag est toujours correctement positionné via les findOrAllocOne
654 inew_cell = m_cell_family.findOrAllocOne(cell_info.uniqueId(), cell_type_info, is_add);
655 if (!is_add) {
656 if (is_check) {
657 Cell cell2(inew_cell);
658 // Vérifie que les noeuds correspondent bien à ceux existants
659 for( Integer i=0, is=cell_info.nbNode(); i<is; ++i )
660 if (cell_info.nodeUniqueId(i)!=cell2.node(i).uniqueId())
661 ARCANE_FATAL("trying to add existing cell (uid={0}) with different nodes",
662 cell_info.uniqueId());
663 }
664 return ItemCompatibility::_itemInternal(inew_cell);
665 }
666 }
667
668 Cell new_cell(inew_cell);
669
670 ++m_mesh_info.nbCell();
671
672 const MeshKind& mesh_kind = m_mesh->meshKind();
673 const bool allow_multi_dim_cell = !mesh_kind.isMonoDimension();
674 const Int32 cell_nb_face = cell_info.nbFace();
675 MutableItemBase mut_cell = new_cell.mutableItemBase();
676 if (cell_type_info->dimension() == 2 && cell_type_info->nbLocalFace() == 0)
677 mut_cell.addFlags(ItemFlags::II_HasEdgeFor1DItems);
678 mut_cell.setOwner(cell_info.owner(), m_mesh_info.rank());
679 // Vérifie la cohérence entre le type local et la maille créée.
680 if (is_check){
681 if (cell_info.nbNode()!=inew_cell.nbNode())
682 ARCANE_FATAL("Incoherent number of nodes v={0} expected={1}",inew_cell.nbNode(),cell_info.nbNode());
683 if (cell_nb_face!=inew_cell.nbFace())
684 ARCANE_FATAL("Incoherent number of faces v={0} expected={1}",inew_cell.nbFace(),cell_nb_face);
685 if (!cell_type_info->isValidForCell())
686 ARCANE_FATAL("Type '{0}' is not allowed for 'Cell' (cell_uid={1})",
687 cell_type_info->typeName(),cell_info.uniqueId());
688 if (!allow_multi_dim_cell){
689 Int32 cell_dimension = cell_type_info->dimension();
690 Int32 mesh_dimension = m_mesh->dimension();
691 if (cell_dimension>=0 && cell_dimension!=mesh_dimension)
692 ARCANE_FATAL("Incoherent dimension for cell uid={0} cell_dim={1} mesh_dim={2} type={3}",
693 cell_info.uniqueId(),cell_dimension,mesh_dimension,cell_type_info->typeName());
694 }
695 }
696
698 ItemInternalMap& nodes_map = m_node_family.itemsMap();
699
700 _addNodesToCell(inew_cell,cell_info);
701
702 if (m_mesh_builder->hasEdge()) {
703 const Int32 cell_nb_edge = cell_info.nbEdge();
704 // Ajoute les nouvelles arêtes ci-nécessaire
705 for( Integer i_edge=0; i_edge<cell_nb_edge; ++i_edge ){
706 const ItemTypeInfo::LocalEdge& le = cell_type_info->localEdge(i_edge);
707 Int64 first_node = cell_info.nodeUniqueId( le.beginNode() );
708 Int64 second_node = cell_info.nodeUniqueId( le.endNode() );
709 if (first_node > second_node)
710 std::swap(first_node,second_node);
711
712 bool is_add = false;
713 Edge edge_internal = _findInternalEdge(i_edge, cell_info, first_node, second_node, is_add);
714 if (is_add){
715 if (is_verbose)
716 info() << "Create edge " << edge_internal.uniqueId() << ' ' << edge_internal.localId();
717
718 edge_internal.mutableItemBase().setOwner(cell_info.edgeOwner(i_edge),m_mesh_info.rank());
719 {
720 Node current_node = nodes_map.findItem(first_node);
721 m_edge_family.replaceNode(ItemLocalId(edge_internal), 0, current_node);
722 m_node_family.addEdgeToNode(current_node, edge_internal);
723 }
724 {
725 Node current_node = nodes_map.findItem(second_node);
726 m_edge_family.replaceNode(ItemLocalId(edge_internal), 1, current_node);
727 m_node_family.addEdgeToNode(current_node, edge_internal);
728 }
729 ++m_mesh_info.nbEdge();
730 }
731
732 m_cell_family.replaceEdge(ItemLocalId(new_cell),i_edge,ItemLocalId(edge_internal));
733 m_edge_family.addCellToEdge(edge_internal,inew_cell);
734 }
735 }
736
737 // Ajoute les nouvelles faces ci-nécessaire
738 for( Integer i_face=0; i_face<cell_nb_face; ++i_face ){
739 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
740 const Integer face_nb_node = lf.nbNode();
741 // en effet de bord, _isReorder positionne m_face_reorderer.sortedNodes();
742 const bool is_reorder = _isReorder(i_face, lf, cell_info);
743 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
744 bool is_add = false;
745 Face face = _findInternalFace(i_face, cell_info, is_add);
746 if (is_add){
747 // Pour les éléments d'ordre supérieur à 1, on ajoute les faces qu'aux noeuds
748 // qui correspondent à l'élément d'ordre 1 (linéaire) associé.
749 const ItemTypeInfo* face_type_info = m_item_type_mng->typeFromId(lf.typeId());
750 const Int32 face_nb_linear_node = face_type_info->linearTypeInfo()->nbLocalNode();
751 if (is_verbose){
752 info() << "AddFaceToCell (cell_uid=" << new_cell.uniqueId() << ": Create face (index=" << i_face
753 << ") uid=" << face.uniqueId()
754 << " lid=" << face.localId()
755 << " type=" << face_type_info->typeName()
756 << " face_nb_linear_node=" << face_nb_linear_node
757 << " sorted_nodes=" << face_sorted_nodes;
758 }
759 face.mutableItemBase().setOwner(cell_info.faceOwner(i_face),m_mesh_info.rank());
760
761 for (Integer i_node = 0; i_node < face_nb_node; ++i_node) {
762 if (is_verbose)
763 info() << "AddNodeToFace i_node=" << i_node << " uid=" << face_sorted_nodes[i_node];
764 Node current_node = nodes_map.findItem(face_sorted_nodes[i_node]);
765 m_face_family.replaceNode(face, i_node, current_node);
766 if (i_node<face_nb_linear_node){
767 m_node_family.addFaceToNode(current_node, face);
768 }
769 }
770
771 if (m_mesh_builder->hasEdge()) {
772 Integer face_nb_edge = lf.nbEdge();
773 for( Integer i_edge=0; i_edge<face_nb_edge; ++i_edge ){
774 Edge current_edge = new_cell.edge( lf.edge(i_edge) );
775 m_face_family.addEdgeToFace(face,current_edge);
776 m_edge_family.addFaceToEdge(current_edge,face);
777 }
778 }
779 ++m_mesh_info.nbFace();
780 }
781 m_cell_family.replaceFace(new_cell,i_face,face);
782
784 if(m_mesh->isAmrActivated()){
785 if (is_reorder){
786 if(face.nbCell() == 2)
787 m_face_family.replaceFrontCellToFace(face,new_cell);
788 else
789 m_face_family.addFrontCellToFace(face,inew_cell);
790 } else{
791 if(face.nbCell() == 2)
792 m_face_family.replaceBackCellToFace(face,new_cell);
793 else
794 m_face_family.addBackCellToFace(face,inew_cell);
795 }
796 } else {
797 if (is_reorder){
798 m_face_family.addFrontCellToFace(face,inew_cell);
799 } else{
800 m_face_family.addBackCellToFace(face,inew_cell);
801 }
802 }
803 }
804
805 _AMR_Patch(inew_cell, cell_info);
806 return ItemCompatibility::_itemInternal(inew_cell);
807}
808
809/*---------------------------------------------------------------------------*/
810/*---------------------------------------------------------------------------*/
811
812ItemInternal* OneMeshItemAdder::
813_addOnePolyhedron(Int64 cell_uid, ConstArrayView<Int64> connectivity_infos, Int32 owner, bool allow_build_face)
814{
815 const bool is_verbose = false;
816 if (is_verbose)
817 info() << "AddNewPolyhedronCell nb_connectivity=" << connectivity_infos.size()
818 << " c=" << connectivity_infos;
819
820 // TODO: utiliser une classe pour gérer la création du type et conserver
821 // tous les tampons de travail au lieu de les réallouer pour chaque polyèdre.
822
823 // Vérifie si la maille existe déjà (auquel cas on ne fait rien).
824 // TODO: rechercher si une maille avec le même uniqueId() existe déjà.
825
826 UniqueArray<Int16> local_nodes_of_cell;
827 UniqueArray<Int64> nodes_of_cell;
828 UniqueArray<Int32> nodes_of_face;
829
830 // Informations pour créer le type Arcane correspondant
831 UniqueArray<Int16> arcane_faces_nb_node;
832 UniqueArray<Int16> arcane_faces_nodes;
833 // Index local dans la maille des noeuds ;
834 impl::HashTableMap2<Int64, Int16> connectivity_to_local_index(500);
835
836 Int16 nb_local_node = 0;
837 nodes_of_cell.clear();
838 connectivity_to_local_index.clear();
839 local_nodes_of_cell.clear();
840 arcane_faces_nb_node.clear();
841 arcane_faces_nodes.clear();
842
843 // [0] est la taille du tableau
844 // [1] est la version du schéma (pour l'instant la seule valeur supportée est '1')
845 // [2] est le nombre de faces (pour la version 1 du schéma)
846 // les éléments suivants sont les noeuds de la face0, puis ceux de la face1, ...
847
848 SmallArray<Int64> cell_nodes_uid;
849 Int32 array_size = static_cast<Int32>(connectivity_infos[0]);
850 if (array_size != connectivity_infos.size())
851 ARCANE_FATAL("Incoherent size array_size={0} connectivity_info={1}", array_size, connectivity_infos.size());
852 Int32 scheme_version = static_cast<Int32>(connectivity_infos[1]);
853 if (scheme_version != 1)
854 ARCANE_FATAL("Insupported scheme version '{0}'. Only supported value is 1", scheme_version);
855 const Int32 cell_nb_face = static_cast<Int32>(connectivity_infos[2]);
856 if (is_verbose)
857 info() << "NB_FACE=" << cell_nb_face;
858 Int32 index_in_connectivity = 3;
859 for (Int32 z = 0; z < cell_nb_face; ++z) {
860 const Int16 face_nb_node = static_cast<Int16>(connectivity_infos[index_in_connectivity]);
861 ++index_in_connectivity;
862 if (is_verbose)
863 info() << "NB_FACE_NODE=" << face_nb_node;
864 nodes_of_face.resize(face_nb_node);
865 arcane_faces_nb_node.add(face_nb_node);
866 for (Int16 k = 0; k < face_nb_node; ++k) {
867 Int64 node_id = connectivity_infos[index_in_connectivity];
868 ++index_in_connectivity;
869 auto x = connectivity_to_local_index.find(node_id);
870 Int16 local_node_index = -1;
871 // Vérifie si le noeud est déjà dans la liste
872 if (x == connectivity_to_local_index.end()) {
873 local_node_index = nb_local_node;
874 connectivity_to_local_index[node_id] = nb_local_node;
875 ++nb_local_node;
876 local_nodes_of_cell.add(local_node_index);
877 nodes_of_cell.add(node_id);
878 cell_nodes_uid.add(node_id);
879 }
880 else
881 local_node_index = x->second;
882 nodes_of_face[k] = local_node_index;
883 arcane_faces_nodes.add(local_node_index);
884 //Int32 face_nb_node = face_indexes[z+1] - face_indexes[z];
885 }
886 if (is_verbose)
887 info() << " Polyhedral face=" << z << " nb_node=" << face_nb_node
888 << " nodes=" << nodes_of_face.view() << " index=" << index_in_connectivity;
889 }
890
891 if (is_verbose)
892 info() << "EndCreateTypeForPolyhedron nb_node=" << nodes_of_cell.size();
893 ItemTypeMngInternal* api = m_item_type_mng->_internalApi();
894 SmallArray<Int32> type_ids_buffer;
895 ItemTypeInfoBuilder cell_type_info;
896 api->fillTemporaryTypeForPolyhedron(&cell_type_info, &type_ids_buffer, nodes_of_cell.size(),
897 arcane_faces_nb_node, arcane_faces_nodes);
898 CellInfoProxy cell_info_proxy(ITI_GenericPolyhedron, &cell_type_info, cell_uid, owner, nodes_of_cell, allow_build_face);
899 return _addOneCell(cell_info_proxy);
900}
901
902/*---------------------------------------------------------------------------*/
903/*---------------------------------------------------------------------------*/
921addOneParentItem(const Item & item, const eItemKind submesh_kind, const bool fatal_on_existing_item)
922{
923 //bool is_check = arcaneIsCheck();
924 ItemTypeMng* itm = m_mesh->itemTypeMng();
925 eItemKind kind = item.kind();
926 ItemTypeInfo* type = itm->typeFromId(item.type());
927
928 if (item.type() == IT_Line2 && submesh_kind == IK_Cell)
929 type = itm->typeFromId(IT_CellLine2);
930 if (item.type() == IT_Vertex && submesh_kind == IK_Face)
931 type = itm->typeFromId(IT_FaceVertex);
932 ItemTypeId type_id = type->itemTypeId();
933
934 if (MeshToMeshTransposer::kindTranspose(submesh_kind, m_mesh, m_mesh->parentMesh()) != kind)
935 ARCANE_FATAL("Incompatible kind/sub-kind");
936
937 // Regarde si la maille existe déjà
938 bool is_add; // ce flag est toujours correctement positionné via les findOrAllocOne
939 Item new_item;
940
941 switch (submesh_kind) {
942 case IK_Node:
943 new_item = m_node_family.findOrAllocOne(item.uniqueId(),is_add);
944 ++m_mesh_info.nbNode();
945 break;
946 case IK_Edge:
947 new_item = m_edge_family.findOrAllocOne(item.uniqueId(),is_add);
948 ++m_mesh_info.nbEdge();
949 break;
950 case IK_Face:
951 new_item = m_face_family.findOrAllocOne(item.uniqueId(),type,is_add);
952 ++m_mesh_info.nbFace();
953 break;
954 case IK_Cell:
955 if (kind == IK_Face && !(item.toFace().isSubDomainBoundary()))
956 ARCANE_FATAL("Bad boundary face");
957 new_item = m_cell_family.findOrAllocOne(item.uniqueId(),type_id,is_add);
958 ++m_mesh_info.nbCell();
959 break;
960 default:
961 throw NotSupportedException(A_FUNCINFO,String::format("Kind {0} not supported", submesh_kind));
962 }
963
964 if (!is_add){
965 if (fatal_on_existing_item)
966 ARCANE_FATAL("Cannot add already existing parent item in submesh");
967 else
968 return ItemCompatibility::_itemInternal(new_item);
969 }
970
971 new_item.mutableItemBase().setParent(0,item.localId());
972 new_item.mutableItemBase().setOwner(item.owner(),m_mesh_info.rank());
973
974 // Localise vis-à-vis de l'item à insérer ces sous-items
975 // Par défaut tout à 0, qui correspond aussi au cas submesh_kind==IK_Node
976 Integer item_nb_node = 0;
977 Integer item_nb_face = 0;
978 Integer item_nb_edge = 0;
979
980 switch (submesh_kind) {
981 case IK_Cell:
982 item_nb_face = type->nbLocalFace();
983 item_nb_edge = type->nbLocalEdge();
984 item_nb_node = type->nbLocalNode();
985 break;
986 case IK_Face:
987 item_nb_edge = type->nbLocalEdge();
988 item_nb_node = type->nbLocalNode();
989 break;
990 case IK_Edge:
991 item_nb_node = type->nbLocalNode();
992 default: // les autres sont déjà filtrés avant avec une exception
993 break;
994 }
995
996 // Traitement du cas de désactivation des arêtes
997 if (!m_mesh_builder->hasEdge())
998 item_nb_edge = 0;
999
1000#if OLD
1001 // Ne fonctionne plus si on désactive les anciennes connectivités
1002 if (is_check){
1003 for( Integer z=0; z<item_nb_face; ++z )
1004 new_item->_setFace(z,NULL_ITEM_ID);
1005 for( Integer z=0; z<item_nb_edge; ++z )
1006 new_item->_setEdge(z,NULL_ITEM_ID);
1007 for( Integer z=0; z<item_nb_node; ++z )
1008 new_item->_setNode(z,NULL_ITEM_ID);
1009 }
1010#endif
1011
1013 DynamicMeshKindInfos::ItemInternalMap& nodes_map = m_mesh->nodesMap();
1014 auto* parent_mesh = ARCANE_CHECK_POINTER(dynamic_cast<DynamicMesh*>(m_mesh->parentMesh()));
1015 DynamicMeshKindInfos::ItemInternalMap& parent_nodes_map = parent_mesh->nodesMap();
1016
1017 // Traitement des nouveaux noeuds
1018
1019 // Les sommets sont utilisés dans l'ordre de l'item sauf les cellules de sous-maillages surfacique.
1020 const bool direct_node_order =
1021 !(submesh_kind == IK_Cell
1022 && kind == IK_Face
1023 && !(item.toFace().isSubDomainBoundaryOutside()));
1024
1025 Int64UniqueArray nodes_uid(item_nb_node,NULL_ITEM_UNIQUE_ID);
1026 for( Integer i_node=0; i_node<item_nb_node; ++i_node ){
1027 Item parent_item;
1028 if (type->typeId() == IT_FaceVertex)
1029 parent_item = item;
1030 else{
1031 Int32 idx = ((direct_node_order) ? i_node : (item_nb_node-1-i_node));
1032 parent_item = item.toItemWithNodes().node(idx);
1033 }
1034 Int64 new_node_uid = nodes_uid[i_node] = parent_item.uniqueId();
1035 ItemInternal* node_internal = m_node_family.findOrAllocOne(new_node_uid,is_add);
1036 if (is_add){
1037#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1038 info() << "Création node " << new_node_uid << ' '
1039 << node_internal->uniqueId() << ' ' << node_internal->localId();
1040#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
1041 node_internal->setParent(0,parent_item.localId());
1042 node_internal->setOwner(parent_item.owner(),m_mesh_info.rank());
1043 ++m_mesh_info.nbNode();
1044 }
1045
1046 // Connection de l'item aux sommets
1047 ItemLocalId node_lid(node_internal);
1048 ItemLocalId new_item_lid(new_item);
1049 switch (submesh_kind) {
1050 case IK_Cell:
1051 m_cell_family.replaceNode(new_item_lid,i_node, node_lid);
1052 m_node_family.addCellToNode(node_internal, new_item.toCell());
1053 break;
1054 case IK_Face:
1055 m_face_family.replaceNode(new_item_lid,i_node, node_lid);
1056 m_node_family.addFaceToNode(node_internal, new_item.toFace());
1057 break;
1058 case IK_Edge:
1059 m_edge_family.replaceNode(new_item_lid,i_node, node_lid);
1060 m_node_family.addEdgeToNode(node_internal, new_item.toEdge());
1061 break;
1062 default: // les autres sont déjà filtrés avant
1063 break;
1064 }
1065 }
1066
1067 // Traitement des nouvelles arêtes (le filtrage has_edge est déjà pris en compte dans item_nb_edge)
1068 for( Integer i_edge=0; i_edge<item_nb_edge; ++i_edge ) {
1069 const ItemTypeInfo::LocalEdge& le = type->localEdge(i_edge);
1070
1071 Int64 first_node = nodes_uid[ le.beginNode() ];
1072 Int64 second_node = nodes_uid[ le.endNode() ];
1073 if (first_node > second_node)
1074 std::swap(first_node,second_node);
1075
1076 Edge parent_item = item.itemBase().edgeBase(i_edge);
1077 if (parent_item.null())
1078 ARCANE_FATAL("Cannot find parent edge");
1079
1080 Int64 new_edge_uid = parent_item.uniqueId();
1081
1082 ItemInternal* edge_internal = m_edge_family.findOrAllocOne(new_edge_uid,is_add);
1083 if (is_add) {
1084#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1085 info() << "Création edge " << new_edge_uid << ' '
1086 << edge_internal->uniqueId() << ' ' << edge_internal->localId();
1087#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
1088 edge_internal->setParent(0,parent_item.localId());
1089 edge_internal->setOwner(parent_item.owner(),m_mesh_info.rank());
1090
1091 {
1092 Node current_node = nodes_map.findItem(first_node);
1093 m_edge_family.replaceNode(ItemLocalId(edge_internal), 0, current_node);
1094 m_node_family.addEdgeToNode(current_node, edge_internal);
1095 }
1096 {
1097 Node current_node = nodes_map.findItem(second_node);
1098 m_edge_family.replaceNode(ItemLocalId(edge_internal), 1, current_node);
1099 m_node_family.addEdgeToNode(current_node, edge_internal);
1100 }
1101 ++m_mesh_info.nbEdge();
1102 }
1103
1104
1105 // Connection de l'item aux sommets
1106 switch (submesh_kind) {
1107 case IK_Cell: {
1108 m_cell_family.replaceEdge(ItemLocalId(new_item),i_edge,ItemLocalId(edge_internal));
1109 m_edge_family.addCellToEdge(edge_internal, new_item.toCell());
1110 } break;
1111 case IK_Face: {
1112 m_face_family.replaceEdge(ItemLocalId(new_item),i_edge,ItemLocalId(edge_internal));
1113 m_edge_family.addFaceToEdge(edge_internal, new_item.toFace());
1114 } break;
1115 default: // les autres sont déjà filtrés avant
1116 break;
1117 }
1118 }
1119
1120 // Traitement des nouvelles faces
1121 // item_nb_face matérialise déjà que ce contexte ne se produit qu'avec submesh_kind==IK_Cell
1122 for( Integer i_face=0; i_face<item_nb_face; ++i_face ) {
1123 const ItemTypeInfo::LocalFace& lf = type->localFace(i_face);
1124 Integer face_nb_node = lf.nbNode();
1125
1126 m_work_face_orig_nodes_uid.resize(face_nb_node);
1127 for( Integer z=0; z<face_nb_node; ++z )
1128 m_work_face_orig_nodes_uid[z] = nodes_uid[ lf.node(z) ];
1129 bool is_reorder = false;
1130 if (m_mesh->dimension() == 1) { // is 1d mesh
1131 is_reorder = m_face_reorderer.reorder1D(i_face, m_work_face_orig_nodes_uid[0]);
1132 }
1133 else{
1134 is_reorder = m_face_reorderer.reorder(ItemTypeId::fromInteger(lf.typeId()), m_work_face_orig_nodes_uid);
1135 }
1136 ConstArrayView<Int64> face_sorted_nodes(m_face_reorderer.sortedNodes());
1137 // find parent item
1138 Item parent_item;
1139 if (kind==IK_Cell) {
1140 parent_item = item.toCell().face(i_face);
1141 }
1142 else if (kind==IK_Face) {
1143 if (m_mesh->dimension() == 1) { // is 1d mesh
1144 parent_item = parent_nodes_map.findItem(face_sorted_nodes[0]);
1145 } else {
1146 // Algo sans CT_FaceToEdge
1147 Int64 first_node = face_sorted_nodes[0];
1148 Int64 second_node = face_sorted_nodes[1];
1149 if (first_node > second_node)
1150 std::swap(first_node,second_node);
1151 Node nbi = parent_nodes_map.findItem(first_node);
1152 parent_item = ItemTools::findEdgeInNode2(nbi,first_node,second_node);
1153 }
1154 }
1155
1156 if (parent_item.null())
1157 ARCANE_FATAL("Cannot find parent face");
1158 Int64 new_face_uid = parent_item.uniqueId();
1159 ItemTypeInfo* face_type = itm->typeFromId(lf.typeId());
1160
1161 ItemInternal* face_internal = m_face_family.findOrAllocOne(new_face_uid,face_type,is_add);
1162 if (is_add){
1163#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1164 info() << "Création face " << new_face_uid << ' '
1165 << face_internal->uniqueId() << ' ' << face_internal->localId();
1166#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
1167 face_internal->setParent(0,parent_item.localId());
1168 face_internal->setOwner(parent_item.owner(),m_mesh_info.rank());
1169
1170 for( Integer i_node=0; i_node<face_nb_node; ++i_node ){
1171 Node current_node = nodes_map.findItem(face_sorted_nodes[i_node]);
1172 m_face_family.replaceNode(ItemLocalId(face_internal), i_node, current_node);
1173 m_node_family.addFaceToNode(current_node, face_internal);
1174 }
1175
1176 if (m_mesh_builder->hasEdge()) {
1177 Integer face_nb_edge = lf.nbEdge();
1178 for( Integer i_edge=0; i_edge<face_nb_edge; ++i_edge ){
1179 Int32 edge_idx = lf.edge(i_edge);
1180 Edge current_edge = new_item.itemBase().edgeBase(edge_idx);
1181 m_face_family.addEdgeToFace(face_internal,current_edge);
1182 m_edge_family.addFaceToEdge(current_edge,face_internal);
1183 }
1184 }
1185 ++m_mesh_info.nbFace();
1186 }
1187 m_cell_family.replaceFace(ItemLocalId(new_item),i_face,ItemLocalId(face_internal));
1188 if (is_reorder){
1189 m_face_family.addFrontCellToFace(face_internal,new_item.toCell());
1190 } else{
1191 m_face_family.addBackCellToFace(face_internal,new_item.toCell());
1192 }
1193 }
1194
1195 return ItemCompatibility::_itemInternal(new_item);
1196}
1197
1198/*---------------------------------------------------------------------------*/
1199/*---------------------------------------------------------------------------*/
1203template<typename CellInfo>
1205_addNodesToCell(Cell cell, const CellInfo& cell_info)
1206{
1207 Integer cell_nb_node = cell_info.nbNode();
1208
1209 // Ajoute les nouveaux noeuds si nécessaire
1210 for( Integer i_node=0; i_node<cell_nb_node; ++i_node ){
1211 Int64 node_unique_id = cell_info.nodeUniqueId(i_node);
1212 bool is_add = false;
1213 ItemInternal* node_internal = m_node_family.findOrAllocOne(node_unique_id,is_add);
1214 if (is_add){
1215 ++m_mesh_info.nbNode();
1216 node_internal->setOwner(cell_info.nodeOwner(i_node),m_mesh_info.rank());
1217 }
1218 m_node_family.addCellToNode(node_internal,cell);
1219 m_cell_family.replaceNode(cell,i_node,ItemLocalId(node_internal));
1220 }
1221}
1222
1223/*---------------------------------------------------------------------------*/
1224/*---------------------------------------------------------------------------*/
1225
1226template<typename CellInfo>
1227bool OneMeshItemAdder::
1228_isReorder(Integer i_face, const ItemTypeInfo::LocalFace& lf, const CellInfo& cell_info)
1229{
1230 const Integer face_nb_node = lf.nbNode();
1231 m_work_face_orig_nodes_uid.resize(face_nb_node);
1232 for(Integer i_node=0; i_node < face_nb_node; ++i_node)
1233 m_work_face_orig_nodes_uid[i_node] = cell_info.nodeUniqueId(lf.node(i_node));
1234 bool is_reorder = false;
1235 if (m_mesh->dimension() == 1) { // is 1d mesh
1236 is_reorder = m_face_reorderer.reorder1D(i_face, m_work_face_orig_nodes_uid[0]);
1237 }
1238 else{
1239 is_reorder = m_face_reorderer.reorder(ItemTypeId::fromInteger(lf.typeId()), m_work_face_orig_nodes_uid);
1240 }
1241
1242 return is_reorder;
1243}
1244
1245/*---------------------------------------------------------------------------*/
1246/*---------------------------------------------------------------------------*/
1247
1251{
1252 m_next_face_uid = 0;
1253 m_next_edge_uid = 0;
1254 m_mesh_info.reset();
1255}
1256
1257/*---------------------------------------------------------------------------*/
1258/*---------------------------------------------------------------------------*/
1259
1262{
1263 if (m_next_face_uid!=0 || m_next_edge_uid!=0)
1264 ARCANE_FATAL("Can not call this method when edge or face are already created");
1266 info() << "Is Generate Edge and Face uniqueId() from Nodes=" << m_use_hash_for_edge_and_face_unique_id;
1267}
1268
1269/*---------------------------------------------------------------------------*/
1270/*---------------------------------------------------------------------------*/
1271
1272} // End namespace Arcane::mesh
1273
1274/*---------------------------------------------------------------------------*/
1275/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
Fonctions utilitaires sur le maillage.
bool reorderNodesOfFace(Int64ConstArrayView before_ids, Int64ArrayView after_ids)
Réordonne les noeuds d'une face.
Int64 generateHashUniqueId(SmallSpan< const Int64 > nodes_unique_id)
Génère un identifiant unique à partir d'une liste d'identifiants de noeuds.
Integer size() const
Nombre d'éléments du vecteur.
void clear()
Supprime les éléments du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
ArrayView< T > view() const
Vue mutable sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Maille d'un maillage.
Definition Item.h:1214
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1295
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1292
Edge edge(Int32 i) const
i-ème arête de la maille
Definition Item.h:1310
Vue constante d'un tableau de type T.
constexpr ConstArrayView< T > subView(Integer abegin, Integer asize) const noexcept
Sous-vue (constante) à partir de l'élément abegin et contenant asize éléments.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Arête d'une maille.
Definition Item.h:826
Face d'une maille.
Definition Item.h:964
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2).
Definition Item.h:1042
bool isSubDomainBoundary() const
Indique si la face est au bord du sous-domaine (i.e nbCell()==1).
Definition Item.h:1061
Interface pour gérer une connectivité incrémentale.
virtual void replaceConnectedItem(ItemLocalId source_item, Integer index, ItemLocalId target_local_id)=0
Remplace l'entité d'index index de source_item par l'entité de localId() target_local_id.
virtual void addConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id)=0
Ajoute l'entité de localId() target_local_id à la connectivité de source_item.
Interface de modification d'une famille.
virtual IIncrementalItemConnectivity * getStoredConnectivity(IItemFamily *source_family, IItemFamily *target_family, const String &name)=0
Retourne, si elle est associée à un stockage, la connectivité entre les familles source_family et tar...
Interface d'une famille d'entités.
Definition IItemFamily.h:86
virtual String name() const =0
Nom de la famille.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converti un tableau de numéros uniques en numéros locaux.
ItemUniqueId uniqueId() const
Numéro unique de l'entité
ItemTypeInfo * typeInfo() const
Type de l'entité.
Int32 localId() const
Numéro local (au sous-domaine) de l'entité
Structure interne d'une entité de maillage.
Index d'un Item dans une variable.
Definition ItemLocalId.h:41
Type d'une entité (Item).
Definition ItemTypeId.h:32
static ItemTypeId fromInteger(Int64 v)
Créé une instance à partir d'un entier.
Informations locales sur une arête d'une maille.
Integer endNode() const
Indice local à la maille du sommet extrémité de l'arête.
Integer beginNode() const
Indice local à la maille du sommet origine de l'arête.
Informations locales sur une face d'une maille.
Integer node(Integer i) const
Indice locale dans la maille du i-ème noeud de la face.
Integer nbEdge() const
Nombre d'arête de la face.
Integer typeId() const
Type de l'entité face.
Integer edge(Integer i) const
Arête de la face.
Integer nbNode() const
Nombre de noeuds de la face.
Infos sur un type d'entité du maillage.
LocalEdge localEdge(Integer id) const
Connectivité locale de la i-ème arête de la maille.
LocalFace localFace(Integer id) const
Connectivité locale de la i-ème face de la maille.
const ItemTypeInfo * linearTypeInfo() const
Type de l'élément linéaire correspondant.
Int16 dimension() const
Dimension de l'élément (<0 si inconnu).
Integer nbLocalNode() const
Nombre de noeuds de l'entité
String typeName() const
Nom du type.
Integer nbLocalFace() const
Nombre de faces de l'entité
bool isValidForCell() const
Indique si le type est valide pour créér une maille (Cell).
ItemTypeId itemTypeId() const
Numéro du type.
Gestionnaire des types d'entités d'un maillage.
Definition ItemTypeMng.h:64
ItemTypeInfo * typeFromId(Integer id) const
Type correspondant au numéro id.
Elément de maillage s'appuyant sur des noeuds (Edge,Face,Cell).
Definition Item.h:736
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:791
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
Classe de base d'un élément de maillage.
Definition Item.h:83
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:380
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
Edge toEdge() const
Converti l'entité en le genre Edge.
Definition Item.h:1688
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemWithNodes toItemWithNodes() const
Converti l'entité en le genre ItemWithNodes.
Definition Item.h:1674
Cell toCell() const
Converti l'entité en le genre Cell.
Definition Item.h:1702
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
Face toFace() const
Converti l'entité en le genre Edge.
Definition Item.h:1695
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:369
constexpr eItemKind kind() const
Genre de l'entité
Definition Item.h:250
Int16 type() const
Type de l'entité
Definition Item.h:241
Caractéristiques d'un maillage.
Definition MeshKind.h:111
bool isMonoDimension() const
Vrai si la structure du maillage est eMeshCellDimensionKind::MonoDimension.
Definition MeshKind.h:120
static eItemKind kindTranspose(eItemKind kindA, IMesh *meshA, IMesh *meshB)
Transpose le genre kindA du maillage meshA en le genre associé dans meshB.
Méthodes permettant de modifier ItemBase.
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
void setParent(Int32 aindex, Int32 parent_local_id)
Positionne le i-ème parent (actuellement aindex doit valoir 0).
void addFlags(Int32 added_flags)
Ajoute les flags added_flags à ceux de l'entité
Noeud d'un maillage.
Definition Item.h:582
Exception lorsqu'une opération n'est pas supportée.
Tableau 1D de données avec buffer pré-alloué sur la pile.
Chaîne de caractères unicode.
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.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Implementation of std::unordered_map.
Construction d'un maillage de manière incrémentale.
Implémentation d'un maillage.
Definition DynamicMesh.h:98
IItemFamily * itemFamily(eItemKind ik) override
Retourne la famille d'entité de type ik.
Integer dimension() override
Dimension du maillage (1D, 2D ou 3D).
IItemFamilyNetwork * itemFamilyNetwork() override
Interface du réseau de familles (familles connectées).
Item findOrAllocOne(Int64 uid, ItemTypeId type_id, MeshInfos &mesh_info, bool &is_alloc) override
Récupère ou alloue une arête de numéro unique uid et de type type.Ajout générique d'item.
void replaceNode(ItemLocalId edge, Integer index, ItemLocalId node)
Remplace le noeud d'index index de l'arête edge avec celui de localId() node_lid.
Infos pour créer/sérialiser une maille connaissant les uniqueId() et owner() de toutes ces sous-entit...
Integer level() const
AMR.
Tableau associatif de ItemInternal.
impl::ItemBase findItem(Int64 uid) const
Retourne l'entité de numéro unique uid.
static Edge findEdgeInNode2(Node node, Int64 begin_node, Int64 end_node)
Definition ItemTools.cc:73
static Face findFaceInNode2(Node node, Integer face_type_id, Int64ConstArrayView face_nodes_uid)
Definition ItemTools.cc:44
Int32 rank() const
Numéro de ce sous-domaine.
Definition MeshInfos.h:53
Integer & nbEdge()
Nombre d'arêtes dans le maillage.
Definition MeshInfos.h:60
Integer & nbNode()
Nombre de noeuds dans le maillage.
Definition MeshInfos.h:56
void _checkSameItemCoherency(ItemWithNodes item, ConstArrayView< Int64 > nodes_uid)
Vérifie la cohérence des noeuds d'une entité ajouté déjà présente.
void _addNodesToCell(Cell cell, const CellInfo &cell_info)
Ajoute les noeuds nodes_uid à la maille cell.
NodesOfItemReorderer m_face_reorderer
Tableaux de travail.
ItemInternal * _addOneCell(const CellInfo &cell_info)
Ajoute une maille.
MeshInfos m_mesh_info
Info générale sur le maillage (numéro de sous-domaine, nombre d'items...).
Int64 _checkGenerateFaceUniqueId(Int64 uid, ConstArrayView< Int64 > nodes_uid)
Génère un uniqueId() pour la face si uid est nul.
Int64 m_next_edge_uid
Numéro du uniqueId() suivant utilisé pour générer les arêtes.
void setUseNodeUniqueIdToGenerateEdgeAndFaceUniqueId(bool v)
Positionne le mécanisme de numérotation des uniqueId().
void resetAfterDeallocate()
Remise à zéro des structures pour pouvoir faire à nouveau une allocation.
bool m_use_hash_for_edge_and_face_unique_id
Si vrai, génère les uniqueId() des faces à partir de ceux des noeuds.
Int64 m_next_face_uid
Numéro du uniqueId() suivant utilisé pour générer les faces.
ItemInternal * addOneParentItem(const Item &item, const eItemKind submesh_kind, const bool fatal_on_existing_item=true)
Ajoute d'un item parent.
ItemInternal * addOneFace(ItemTypeId type_id, Int64 face_uid, Int32 owner_rank, Int64ConstArrayView nodes_uid)
Ajoute une face.
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:68
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:337
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:478
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:339
eItemKind
Genre d'entité de maillage.
@ IK_Particle
Entité de maillage de genre particule.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Face
Entité de maillage de genre face.
@ IK_DoF
Entité de maillage de genre degre de liberte.
@ IK_Edge
Entité de maillage de genre arête.
std::int16_t Int16
Type entier signé sur 16 bits.
std::int32_t Int32
Type entier signé sur 32 bits.