Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
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/* Adding entities one by one. */
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/internal/ItemTypeMngInternal.h"
26
27#include "arcane/mesh/DynamicMesh.h"
28#include "arcane/mesh/DynamicMeshIncrementalBuilder.h"
29#include "arcane/mesh/ItemTools.h"
30#include "arcane/mesh/ConnectivityNewWithDependenciesTypes.h"
31#include "arcane/mesh/GraphDoFs.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane::mesh
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
43{
44 public:
45
46 CellInfoProxy(ItemTypeId type_id, ItemTypeInfo* type_info,
47 Int64 cell_uid, Int32 owner,
49 bool allow_build_face = false)
50 : m_type_info(type_info)
51 , m_cell_uid(cell_uid)
52 , m_info(info)
53 , m_owner(owner)
54 , m_type_id(type_id)
55 , m_allow_build_face(allow_build_face)
56 {}
57
58 Int64 uniqueId() const { return m_cell_uid; }
59 ItemTypeId itemTypeId() const { return m_type_id; }
60 ItemTypeInfo* typeInfo() const { return m_type_info; }
61 Int32 owner() const { return m_owner; }
62 Integer nbNode() const { return m_info.size(); }
63 Integer nbFace() const { return m_type_info->nbLocalFace(); }
64 Integer nbEdge() const { return m_type_info->nbLocalEdge(); }
65 Int64 nodeUniqueId(Integer i_node) const { return m_info[i_node]; }
66 Int32 nodeOwner(Integer) const { return m_owner; }
67 Int32 faceOwner(Integer) const { return m_owner; }
68 Int32 edgeOwner(Integer) const { return m_owner; }
69 bool allowBuildFace() const { return m_allow_build_face; }
70 bool allowBuildEdge() const { return m_allow_build_face; }
71
72 ConstArrayView<Int64> connectivityInfos() const { return m_info; }
73
74 private:
75
76 ItemTypeInfo* m_type_info = nullptr;
77 Int64 m_cell_uid = NULL_ITEM_UNIQUE_ID;
79 Int32 m_owner = A_NULL_RANK;
80 ItemTypeId m_type_id;
81 bool m_allow_build_face = false;
82};
83
84/*---------------------------------------------------------------------------*/
85/*---------------------------------------------------------------------------*/
86
87OneMeshItemAdder::
88OneMeshItemAdder(DynamicMeshIncrementalBuilder* mesh_builder)
89: TraceAccessor(mesh_builder->mesh()->traceMng())
90, m_mesh(mesh_builder->mesh())
91, m_mesh_builder(mesh_builder)
92, m_cell_family(m_mesh->trueCellFamily())
93, m_node_family(m_mesh->trueNodeFamily())
94, m_face_family(m_mesh->trueFaceFamily())
95, m_edge_family(m_mesh->trueEdgeFamily())
96, m_item_type_mng(m_mesh->itemTypeMng())
97, m_mesh_info(m_mesh->meshPartInfo().partRank())
98, m_face_reorderer(m_item_type_mng)
99{
100 //m_work_face_sorted_nodes.reserve(100);
101 m_work_face_orig_nodes_uid.reserve(100);
102}
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
107ItemInternal* OneMeshItemAdder::
108addOneNode(Int64 node_uid, Int32 owner)
109{
110 bool is_add = false;
111 ItemInternal* node = m_node_family.findOrAllocOne(node_uid, is_add);
112 if (is_add) {
114 node->setOwner(owner, owner);
115 }
116 return node;
117}
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
130{
131 Int32 nb_node = nodes_uid.size();
132 // Checks that the number of nodes is the same
133 if (item.nbNode() != nb_node)
134 ARCANE_FATAL("Trying to add existing item (kind='{0}', uid={1}) with different number of node (existing={2} new={3})",
135 item.kind(), item.uniqueId(), item.nbNode(), nb_node);
136
137 // Checks that the nodes correspond to the existing ones
138 for (Int32 i = 0; i < nb_node; ++i) {
139 Int64 new_uid = nodes_uid[i];
140 Int64 current_uid = item.node(i).uniqueId();
141 if (new_uid != current_uid) {
142 std::ostringstream ostr;
143 for (Int32 k = 0; k < nb_node; ++k)
144 ostr << " " << item.node(k).uniqueId();
145 ARCANE_FATAL("Trying to add existing item (kind='{0}', uid={1}) with different nodes (index={2} existing='{3}' new='{4}')",
146 item.kind(), item.uniqueId(), i, ostr.str(), nodes_uid);
147 }
148 }
149}
150
151/*---------------------------------------------------------------------------*/
152/*---------------------------------------------------------------------------*/
160{
161 if (uid != NULL_ITEM_UNIQUE_ID)
162 return uid;
164 uid = MeshUtils::generateHashUniqueId(nodes_uid);
165 else
166 uid = m_next_face_uid++;
167 return uid;
168}
169
170/*---------------------------------------------------------------------------*/
171/*---------------------------------------------------------------------------*/
185addOneFace(ItemTypeId type_id, Int64 face_uid, Int32 owner_rank, Int64ConstArrayView nodes_uid)
186{
187 const Integer face_nb_node = nodes_uid.size();
188
189 //m_work_face_sorted_nodes.resize(face_nb_node);
190 //m_work_face_orig_nodes_uid.resize(face_nb_node);
191 //for( Integer z=0; z<face_nb_node; ++z )
192 //m_work_face_orig_nodes_uid[z] = nodes_uid[z];
193 m_face_reorderer.reorder(type_id, nodes_uid);
194 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
195 // TODO: in the case where the face will be orphaned (not connected to a cell),
196 // check if the face needs reorientation because this risks introducing
197 // an inconsistency if one later wishes to calculate a normal.
198 //MeshUtils::reorderNodesOfFace(m_work_face_orig_nodes_uid,m_work_face_sorted_nodes);
199 face_uid = _checkGenerateFaceUniqueId(face_uid, face_sorted_nodes);
200 bool is_add_face = false;
201 Face face = m_face_family.findOrAllocOne(face_uid, type_id, is_add_face);
202 // The face does not exist
203 if (is_add_face) {
204 ++m_mesh_info.nbFace();
205 face.mutableItemBase().setOwner(owner_rank, m_mesh_info.rank());
206 for (Integer i_node = 0; i_node < face_nb_node; ++i_node) {
207 Node node = addOneNode(face_sorted_nodes[i_node], m_mesh_info.rank());
208 m_face_family.replaceNode(face, i_node, node);
209 m_node_family.addFaceToNode(node, face);
210 }
211 }
212 else {
213 if (arcaneIsCheck())
214 _checkSameItemCoherency(face, face_sorted_nodes);
215 }
216
217 return ItemCompatibility::_itemInternal(face);
218}
219
220/*---------------------------------------------------------------------------*/
221/*---------------------------------------------------------------------------*/
222
223ItemInternal* OneMeshItemAdder::
224addOneEdge(Int64 edge_uid, Int32 rank, Int64ConstArrayView nodes_uid)
225{
226 m_work_edge_sorted_nodes.resize(2);
227 m_work_edge_orig_nodes_uid.resize(2);
228
229 for (Integer z = 0; z < 2; ++z)
230 m_work_edge_orig_nodes_uid[z] = nodes_uid[z];
231 // reorderNodesOfFace behaves correctly here for edges == faces in 2D
232 MeshUtils::reorderNodesOfFace(m_work_edge_orig_nodes_uid, m_work_edge_sorted_nodes);
233
234 bool is_add_edge = false;
235 ItemInternal* edge = m_edge_family.findOrAllocOne(edge_uid, is_add_edge);
236
237 // The edge does not exist
238 if (is_add_edge) {
240 edge->setOwner(rank, m_mesh_info.rank());
241 for (Integer i_node = 0; i_node < 2; ++i_node) {
242 ItemInternal* current_node_internal = addOneNode(m_work_edge_sorted_nodes[i_node], m_mesh_info.rank());
243 m_edge_family.replaceNode(ItemLocalId(edge), i_node, ItemLocalId(current_node_internal));
244 m_node_family.addEdgeToNode(current_node_internal, edge);
245 }
246 }
247 return edge;
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
253template <>
254Face OneMeshItemAdder::
255_findInternalFace(Integer i_face, const FullCellInfo& cell_info, bool& is_add)
256{
257 const Int64 face_unique_id = cell_info.faceUniqueId(i_face);
258 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
259 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
260 ItemTypeInfo* face_type_info = m_item_type_mng->typeFromId(lf.typeId());
261 return m_face_family.findOrAllocOne(face_unique_id, face_type_info, is_add);
262}
263
264/*---------------------------------------------------------------------------*/
265/*---------------------------------------------------------------------------*/
266
267template <>
268Face OneMeshItemAdder::
269_findInternalFace(Integer i_face, const CellInfoProxy& cell_info, bool& is_add)
270{
271 const ItemInternalMap& nodes_map = m_mesh->nodesMap();
272 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
273 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
274 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
275 Int64 face_unique_id = NULL_ITEM_UNIQUE_ID;
276 Face face_internal;
277 const bool use_hash = m_use_hash_for_edge_and_face_unique_id;
278 // If calculating face uniqueIds from nodes,
279 // we can directly know if the face already exists. Otherwise, we
280 // call ItemTools::findFaceInNode2(), but this function is more
281 // costly because it searches for the face by traversing the faces connected
282 // to the first node of the face.
283 if (use_hash) {
284 face_unique_id = _checkGenerateFaceUniqueId(NULL_ITEM_UNIQUE_ID, face_sorted_nodes);
285 face_internal = m_face_family.itemsMap().tryFind(face_unique_id);
286 }
287 else {
288 // Retrieves the oriented nodes of the face
289 // (One must have called one of the face addition methods before)
290 Node nbi = nodes_map.findItem(face_sorted_nodes[0]);
291 face_internal = ItemTools::findFaceInNode2(nbi, lf.typeId(), face_sorted_nodes);
292 }
293 if (face_internal.null()) {
294 // The face was not found. It therefore does not exist in our sub-domain.
295 // If this is allowed, the new face is created.
296 if (!cell_info.allowBuildFace() && !m_use_hash_for_edge_and_face_unique_id) {
297 info() << "BadCell uid=" << cell_info.uniqueId();
298 for (Int32 i = 0; i < cell_info.nbNode(); ++i)
299 info() << "Cell node I=" << i << " uid=" << cell_info.nodeUniqueId(i);
300 ARCANE_FATAL("On the fly face allocation is not allowed here.\n"
301 " You need to add faces with IMeshModifier::addFaces().\n"
302 " CellUid={0} LocalFace={1} FaceNodes={2}",
303 cell_info.uniqueId(), i_face, face_sorted_nodes);
304 }
305 // Only recalculate the hash if it hasn't been done already.
306 if (!use_hash)
307 face_unique_id = _checkGenerateFaceUniqueId(NULL_ITEM_UNIQUE_ID, face_sorted_nodes);
308 is_add = true;
309 ItemTypeInfo* face_type = m_item_type_mng->typeFromId(lf.typeId());
310 return m_face_family.allocOne(face_unique_id, face_type);
311 }
312 else {
313 is_add = false;
314 return face_internal;
315 }
316}
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
320
321template <>
322Edge OneMeshItemAdder::
323_findInternalEdge(Integer i_edge, const FullCellInfo& cell_info,
324 Int64 first_node, Int64 second_node, bool& is_add)
325{
326 ARCANE_UNUSED(first_node);
327 ARCANE_UNUSED(second_node);
328
329 const Int64 edge_unique_id = cell_info.edgeUniqueId(i_edge);
330 return m_edge_family.findOrAllocOne(edge_unique_id, is_add);
331}
332
333/*---------------------------------------------------------------------------*/
334/*---------------------------------------------------------------------------*/
335
336template <>
337Edge OneMeshItemAdder::
338_findInternalEdge(Integer i_edge, const CellInfoProxy& cell_info, Int64 first_node, Int64 second_node, bool& is_add)
339{
340 ARCANE_UNUSED(i_edge);
341
342 const bool use_hash = m_use_hash_for_edge_and_face_unique_id;
343 FixedArray<Int64, 2> nodes;
344 Int64 edge_unique_id = NULL_ITEM_UNIQUE_ID;
345 Edge edge_internal;
346 if (use_hash) {
347 nodes[0] = first_node;
348 nodes[1] = second_node;
349 edge_unique_id = MeshUtils::generateHashUniqueId(nodes.view());
350 edge_internal = m_edge_family.itemsMap().tryFind(edge_unique_id);
351 }
352 else {
353 const ItemInternalMap& nodes_map = m_mesh->nodesMap();
354 Node nbi = nodes_map.findItem(first_node);
355 edge_internal = ItemTools::findEdgeInNode2(nbi, first_node, second_node);
356 }
357 if (edge_internal.null()) {
358 if (!cell_info.allowBuildEdge() && !use_hash)
359 ARCANE_FATAL("On the fly edge allocation is not allowed here."
360 " You need to add edges before with IMeshModifier::addEdges()");
361 if (!use_hash)
362 edge_unique_id = m_next_edge_uid++;
363 is_add = true;
364 return m_edge_family.allocOne(edge_unique_id);
365 }
366 else {
367 is_add = false;
368 return edge_internal;
369 }
370}
371
372/*---------------------------------------------------------------------------*/
373/*---------------------------------------------------------------------------*/
390ItemInternal* OneMeshItemAdder::
391addOneCell(ItemTypeId type_id, Int64 cell_uid, Int32 owner,
392 ConstArrayView<Int64> nodes_uid, bool allow_build_face)
393{
394 if (type_id == ITI_GenericPolyhedron)
395 return _addOnePolyhedron(cell_uid, nodes_uid, owner, allow_build_face);
396 CellInfoProxy cell_info_proxy(type_id, m_item_type_mng->typeFromId(type_id), cell_uid, owner, nodes_uid, allow_build_face);
397 return _addOneCell(cell_info_proxy);
398}
399
400/*---------------------------------------------------------------------------*/
401/*---------------------------------------------------------------------------*/
407ItemInternal* OneMeshItemAdder::
408addOneCell(const FullCellInfo& cell_info)
409{
410 return _addOneCell(cell_info);
411}
412
413/*---------------------------------------------------------------------------*/
414/*---------------------------------------------------------------------------*/
415
416ItemInternal* OneMeshItemAdder::
417addOneItem(IItemFamily* family,
418 IItemFamilyModifier* family_modifier,
419 ItemTypeId type_id,
420 Int64 item_uid,
421 Integer item_owner,
422 Integer sub_domain_id,
423 Integer nb_connected_family,
424 Int64ConstArrayView connectivity_info)
425{
426 ARCANE_ASSERT(m_mesh->itemFamilyNetwork(), ("ItemFamilyNetwork is required to call OneMeshItemAdder::addOneItem"));
427 bool is_alloc = true;
428 Item item = family_modifier->findOrAllocOne(item_uid, type_id, m_mesh_info, is_alloc); // don't forget to add print in the class method
429 item.mutableItemBase().setOwner(item_owner, sub_domain_id);
430 // Add connectivities if needed
431 Integer info_index = 0;
432 for (Integer family_index = 0; family_index < nb_connected_family; ++family_index) {
433 // get connected family
434 eItemKind family_kind = static_cast<eItemKind>(connectivity_info[info_index++]); // another way ?
435 Int32 nb_connected_item = CheckedConvert::toInt32(connectivity_info[info_index++]);
436 IItemFamily* connected_family = m_mesh->itemFamily(family_kind);
437 // get connectivities family -> connected_family and reverse
438 String connectivity_name = mesh::connectivityName(family, connected_family);
439 String reverse_connectivity_name = mesh::connectivityName(connected_family, family);
440 bool is_dependency = false;
441 IIncrementalItemConnectivity* family_to_connected_family = m_mesh->itemFamilyNetwork()->getStoredConnectivity(family, connected_family, connectivity_name, is_dependency);
442 IIncrementalItemConnectivity* connected_family_to_family = m_mesh->itemFamilyNetwork()->getStoredConnectivity(connected_family, family, reverse_connectivity_name);
443 // Clear connectivities for already allocated items (except dependencies since replace is used)
444 if (!is_alloc) {
445 if (!is_dependency)
446 _clearConnectivity(ItemLocalId(item), family_to_connected_family);
447 if (connected_family_to_family)
448 _clearReverseConnectivity(ItemLocalId(item), family_to_connected_family, connected_family_to_family);
449 }
450 // get connected item lids
451 Int32UniqueArray connected_item_lids(nb_connected_item);
452 connected_family->itemsUniqueIdToLocalId(connected_item_lids, connectivity_info.subView(info_index, nb_connected_item), true);
453 for (Integer connected_item_index = 0; connected_item_index < nb_connected_item; ++connected_item_index) {
454 if (family_to_connected_family) {
455 // pre-alloc are done (=> use replace) when a dependency relation ("owning relation") while not when only a relation (use add)
456 if (!is_dependency)
457 family_to_connected_family->addConnectedItem(ItemLocalId(item), ItemLocalId(connected_item_lids[connected_item_index]));
458 else
459 family_to_connected_family->replaceConnectedItem(ItemLocalId(item), connected_item_index, ItemLocalId(connected_item_lids[connected_item_index])); // does not work with face to edges...
460 }
461 if (connected_family_to_family)
462 connected_family_to_family->addConnectedItem(ItemLocalId(connected_item_lids[connected_item_index]), ItemLocalId(item));
463 }
464 info_index += nb_connected_item;
465 }
466 // debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
467 debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
468 return ItemCompatibility::_itemInternal(item);
469}
470
471/*---------------------------------------------------------------------------*/
472
473ItemInternal* OneMeshItemAdder::
474addOneItem2(IItemFamily* family,
475 IItemFamilyModifier* family_modifier,
476 ItemTypeId type_id,
477 Int64 item_uid,
478 Integer item_owner,
479 Integer sub_domain_id,
480 Integer nb_connected_family,
481 Int64ConstArrayView connectivity_info)
482{
483 ARCANE_ASSERT(m_mesh->itemFamilyNetwork(), ("ItemFamilyNetwork is required to call OneMeshItemAdder::addOneItem"));
484 bool is_alloc = true;
485 Item item = family_modifier->findOrAllocOne(item_uid, type_id, m_mesh_info, is_alloc); // don't forget to add print in the class method
486 item.mutableItemBase().setOwner(item_owner, sub_domain_id);
487 // Add connectivities if needed
488 Integer info_index = 0;
489 for (Integer family_index = 0; family_index < nb_connected_family; ++family_index) {
490 // Prepare connection
491 // get connected family
492 eItemKind family_kind = static_cast<eItemKind>(connectivity_info[info_index++]); // another way ?
493 Int32 nb_connected_item = CheckedConvert::toInt32(connectivity_info[info_index++]);
494 if (nb_connected_item == 0)
495 continue;
496 IItemFamily* connected_family = nullptr;
497 switch (family_kind) {
498 case IK_Particle:
499 connected_family = m_mesh->findItemFamily(family_kind, ParticleFamily::defaultFamilyName(), false, false);
500 break;
501 case IK_DoF:
502 if (family->name() == GraphDoFs::dualNodeFamilyName())
503 connected_family = m_mesh->findItemFamily(family_kind, GraphDoFs::linkFamilyName(), false, false);
504 else
505 connected_family = m_mesh->findItemFamily(family_kind, GraphDoFs::dualNodeFamilyName(), false, false);
506 break;
507 default:
508 connected_family = m_mesh->itemFamily(family_kind);
509 break;
510 }
511 // get connectivities family -> connected_family and reverse
512 String connectivity_name = mesh::connectivityName(family, connected_family);
513 bool is_dependency = false;
514 IIncrementalItemConnectivity* family_to_connected_family = m_mesh->itemFamilyNetwork()->getConnectivity(family, connected_family, connectivity_name, is_dependency);
515 if (!family_to_connected_family)
516 ARCANE_FATAL("Cannot find connectivity name={0}", connectivity_name);
517 bool is_deep_connectivity = m_mesh->itemFamilyNetwork()->isDeep(family_to_connected_family);
518 bool is_relation = !(is_dependency && is_deep_connectivity);
519 // Build connection
520 // get connected item lids
521 Int32UniqueArray connected_item_lids(nb_connected_item);
522 bool do_fatal = is_relation ? false : true; // for relations, connected items may not be present and will be skipped.
523 connected_family->itemsUniqueIdToLocalId(connected_item_lids, connectivity_info.subView(info_index, nb_connected_item), do_fatal);
524 // if connection is relation, connected item not necessarily present: remove absent (ie null) items
525 Integer nb_connected_item_found = nb_connected_item;
526 if (is_relation) {
527 for (Integer index = 0; index < connected_item_lids.size();) {
528 if (connected_item_lids[index] == NULL_ITEM_LOCAL_ID) {
529 connected_item_lids.remove(index);
530 --nb_connected_item_found;
531 }
532 else
533 ++index;
534 }
535 }
536 for (Integer connected_item_index = 0; connected_item_index < nb_connected_item_found; ++connected_item_index) {
537 if (family_to_connected_family) {
538 // Only strategy : check and add
539 auto connected_item_lid = ItemLocalId{ connected_item_lids[connected_item_index] };
540 if (is_relation) {
541 if (!family_to_connected_family->hasConnectedItem(ItemLocalId(item), connected_item_lid)) {
542 family_to_connected_family->addConnectedItem(ItemLocalId(item), connected_item_lid);
543 }
544 }
545 else {
546 family_to_connected_family->replaceConnectedItem(ItemLocalId(item), connected_item_index, connected_item_lid);
547 }
548 }
549 }
550 info_index += nb_connected_item;
551 }
552 if (is_alloc)
553 debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
554 // debug(Trace::Highest) << "[addItems] DEPENDENCIES for " << family->name() << FullItemPrinter(item) ; // debug info
555 // _printRelations(item); // debug info
556 return ItemCompatibility::_itemInternal(item);
557}
558
559/*---------------------------------------------------------------------------*/
560
561void OneMeshItemAdder::
562_printRelations(ItemInternal* item)
563{
564 debug(Trace::Highest) << "[addItems] RELATIONS for " << ItemPrinter(item) << " in " << item->family()->name();
565 for (const auto& relation : m_mesh->itemFamilyNetwork()->getChildRelations(item->family())) {
566 // debug(Trace::Highest) << " Relation " << relation->name();
567 // debug(Trace::Highest) << " Relation " << relation->nbConnectedItem(ItemLocalId(item));
568 ConnectivityItemVector connected_items(relation);
569 for (const auto& connected_item : connected_items.connectedItems(ItemLocalId(item))) {
570 debug(Trace::Highest) << ItemPrinter(connected_item);
571 }
572 }
573}
574
575/*---------------------------------------------------------------------------*/
576/*---------------------------------------------------------------------------*/
577
578void OneMeshItemAdder::
579_clearConnectivity(ItemLocalId item, IIncrementalItemConnectivity* connectivity)
580{
581
582 ConnectivityItemVector accessor(connectivity);
583 ENUMERATE_ITEM (connected_item, accessor.connectedItems(item)) {
584 connectivity->removeConnectedItem(item, connected_item);
585 }
586}
587
588/*---------------------------------------------------------------------------*/
589/*---------------------------------------------------------------------------*/
590
591void OneMeshItemAdder::
592_clearReverseConnectivity(ItemLocalId item, IIncrementalItemConnectivity* connectivity, IIncrementalItemConnectivity* reverse_connectivity)
593{
594 ConnectivityItemVector accessor(connectivity);
595 ENUMERATE_ITEM (connected_item, accessor.connectedItems(item)) {
596 reverse_connectivity->removeConnectedItem(connected_item, item);
597 }
598}
599
600/*---------------------------------------------------------------------------*/
601/*---------------------------------------------------------------------------*/
602
603template <> void OneMeshItemAdder::
604_AMR_Patch(Cell new_cell, const FullCellInfo& cell_info)
605{
607 if (m_mesh->isAmrActivated()) {
608 // FIXME doit-on traiter les mailles de niveau 0
609 //comme celles de niveau superieur
610 if (cell_info.level() != 0) {
611 Integer child_rank = cell_info.whichChildAmI();
612 Int64 hParent_uid = cell_info.hParentCellUniqueId();
613 ItemTypeId cell_type = ItemTypeId::fromInteger(cell_info.typeId());
614 bool is_add;
615 Cell hParent_cell = m_cell_family.findOrAllocOne(hParent_uid, cell_type, is_add);
616 m_cell_family._addParentCellToCell(new_cell, hParent_cell);
617 m_cell_family._addChildCellToCell(hParent_cell, child_rank, new_cell);
618 }
619 }
620}
621
622template <> void OneMeshItemAdder::
623_AMR_Patch(Cell cell, const CellInfoProxy& cell_info)
624{
625 ARCANE_UNUSED(cell);
626 ARCANE_UNUSED(cell_info);
627}
628
629/*---------------------------------------------------------------------------*/
630/*---------------------------------------------------------------------------*/
636template <typename CellInfo>
638_addOneCell(const CellInfo& cell_info)
639{
640 bool is_check = arcaneIsCheck();
641
642 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
643 ItemTypeId cell_type_id = cell_type_info->itemTypeId();
644 const bool is_verbose = false;
645 if (is_verbose)
646 info() << "AddNewCell type_id=" << cell_type_id << " nb_node=" << cell_info.nbNode()
647 << " type=" << cell_type_info->typeName();
648 // Checks if the cell already exists (in which case nothing is done).
649 Cell inew_cell;
650 {
651 bool is_add; // ce flag est toujours correctement positionné via les findOrAllocOne
652 inew_cell = m_cell_family.findOrAllocOne(cell_info.uniqueId(), cell_type_info, is_add);
653 if (!is_add) {
654 if (is_check) {
655 Cell cell2(inew_cell);
656 // Verifies that the nodes match those that exist.
657 for (Integer i = 0, is = cell_info.nbNode(); i < is; ++i)
658 if (cell_info.nodeUniqueId(i) != cell2.node(i).uniqueId())
659 ARCANE_FATAL("trying to add existing cell (uid={0}) with different nodes",
660 cell_info.uniqueId());
661 }
662 return ItemCompatibility::_itemInternal(inew_cell);
663 }
664 }
665
666 Cell new_cell(inew_cell);
667
668 ++m_mesh_info.nbCell();
669
670 const MeshKind& mesh_kind = m_mesh->meshKind();
671 const bool allow_multi_dim_cell = !mesh_kind.isMonoDimension();
672 const Int32 cell_nb_face = cell_info.nbFace();
673 MutableItemBase mut_cell = new_cell.mutableItemBase();
674 if (cell_type_info->dimension() == 2 && cell_type_info->nbLocalFace() == 0)
675 mut_cell.addFlags(ItemFlags::II_HasEdgeFor1DItems);
676 mut_cell.setOwner(cell_info.owner(), m_mesh_info.rank());
677 // Vérifie la cohérence entre le type local et la maille créée.
678 if (is_check) {
679 if (cell_info.nbNode() != inew_cell.nbNode())
680 ARCANE_FATAL("Incoherent number of nodes v={0} expected={1}", inew_cell.nbNode(), cell_info.nbNode());
681 if (cell_nb_face != inew_cell.nbFace())
682 ARCANE_FATAL("Incoherent number of faces v={0} expected={1}", inew_cell.nbFace(), cell_nb_face);
683 if (!cell_type_info->isValidForCell())
684 ARCANE_FATAL("Type '{0}' is not allowed for 'Cell' (cell_uid={1})",
685 cell_type_info->typeName(), cell_info.uniqueId());
686 if (!allow_multi_dim_cell) {
687 Int32 cell_dimension = cell_type_info->dimension();
688 Int32 mesh_dimension = m_mesh->dimension();
689 if (cell_dimension >= 0 && cell_dimension != mesh_dimension)
690 ARCANE_FATAL("Incoherent dimension for cell uid={0} cell_dim={1} mesh_dim={2} type={3}",
691 cell_info.uniqueId(), cell_dimension, mesh_dimension, cell_type_info->typeName());
692 }
693 }
694
696 ItemInternalMap& nodes_map = m_node_family.itemsMap();
697
698 _addNodesToCell(inew_cell, cell_info);
699
700 if (m_mesh_builder->hasEdge()) {
701 const Int32 cell_nb_edge = cell_info.nbEdge();
702 // Adds the necessary edges.
703 for (Integer i_edge = 0; i_edge < cell_nb_edge; ++i_edge) {
704 const ItemTypeInfo::LocalEdge& le = cell_type_info->localEdge(i_edge);
705 Int64 first_node = cell_info.nodeUniqueId(le.beginNode());
706 Int64 second_node = cell_info.nodeUniqueId(le.endNode());
707 if (first_node > second_node)
708 std::swap(first_node, second_node);
709
710 bool is_add = false;
711 Edge edge_internal = _findInternalEdge(i_edge, cell_info, first_node, second_node, is_add);
712 if (is_add) {
713 if (is_verbose)
714 info() << "Create edge " << edge_internal.uniqueId() << ' ' << edge_internal.localId();
715
716 edge_internal.mutableItemBase().setOwner(cell_info.edgeOwner(i_edge), m_mesh_info.rank());
717 {
718 Node current_node = nodes_map.findItem(first_node);
719 m_edge_family.replaceNode(ItemLocalId(edge_internal), 0, current_node);
720 m_node_family.addEdgeToNode(current_node, edge_internal);
721 }
722 {
723 Node current_node = nodes_map.findItem(second_node);
724 m_edge_family.replaceNode(ItemLocalId(edge_internal), 1, current_node);
725 m_node_family.addEdgeToNode(current_node, edge_internal);
726 }
727 ++m_mesh_info.nbEdge();
728 }
729
730 m_cell_family.replaceEdge(ItemLocalId(new_cell), i_edge, ItemLocalId(edge_internal));
731 m_edge_family.addCellToEdge(edge_internal, inew_cell);
732 }
733 }
734
735 // Adds the necessary faces.
736 for (Integer i_face = 0; i_face < cell_nb_face; ++i_face) {
737 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
738 const Integer face_nb_node = lf.nbNode();
739 // en effet de bord, _isReorder positionne m_face_reorderer.sortedNodes();
740 const bool is_reorder = _isReorder(i_face, lf, cell_info);
741 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
742 bool is_add = false;
743 Face face = _findInternalFace(i_face, cell_info, is_add);
744 if (is_add) {
745 // For elements of order greater than 1, faces are added to the nodes
746 // corresponding to the associated order 1 (linear) element.
747 const ItemTypeInfo* face_type_info = m_item_type_mng->typeFromId(lf.typeId());
748 const Int32 face_nb_linear_node = face_type_info->linearTypeInfo()->nbLocalNode();
749 if (is_verbose) {
750 info() << "AddFaceToCell (cell_uid=" << new_cell.uniqueId() << ": Create face (index=" << i_face
751 << ") uid=" << face.uniqueId()
752 << " lid=" << face.localId()
753 << " type=" << face_type_info->typeName()
754 << " face_nb_linear_node=" << face_nb_linear_node
755 << " sorted_nodes=" << face_sorted_nodes;
756 }
757 face.mutableItemBase().setOwner(cell_info.faceOwner(i_face), m_mesh_info.rank());
758
759 for (Integer i_node = 0; i_node < face_nb_node; ++i_node) {
760 if (is_verbose)
761 info() << "AddNodeToFace i_node=" << i_node << " uid=" << face_sorted_nodes[i_node];
762 Node current_node = nodes_map.findItem(face_sorted_nodes[i_node]);
763 m_face_family.replaceNode(face, i_node, current_node);
764 if (i_node < face_nb_linear_node) {
765 m_node_family.addFaceToNode(current_node, face);
766 }
767 }
768
769 if (m_mesh_builder->hasEdge()) {
770 Integer face_nb_edge = lf.nbEdge();
771 for (Integer i_edge = 0; i_edge < face_nb_edge; ++i_edge) {
772 Edge current_edge = new_cell.edge(lf.edge(i_edge));
773 m_face_family.addEdgeToFace(face, current_edge);
774 m_edge_family.addFaceToEdge(current_edge, face);
775 }
776 }
777 ++m_mesh_info.nbFace();
778 }
779 m_cell_family.replaceFace(new_cell, i_face, face);
780
782 if (m_mesh->isAmrActivated()) {
783 if (is_reorder) {
784 if (face.nbCell() == 2)
785 m_face_family.replaceFrontCellToFace(face, new_cell);
786 else
787 m_face_family.addFrontCellToFace(face, inew_cell);
788 }
789 else {
790 if (face.nbCell() == 2)
791 m_face_family.replaceBackCellToFace(face, new_cell);
792 else
793 m_face_family.addBackCellToFace(face, inew_cell);
794 }
795 }
796 else {
797 if (is_reorder) {
798 m_face_family.addFrontCellToFace(face, inew_cell);
799 }
800 else {
801 m_face_family.addBackCellToFace(face, inew_cell);
802 }
803 }
804 }
805
806 _AMR_Patch(inew_cell, cell_info);
807 return ItemCompatibility::_itemInternal(inew_cell);
808}
809
810/*---------------------------------------------------------------------------*/
811/*---------------------------------------------------------------------------*/
812
813ItemInternal* OneMeshItemAdder::
814_addOnePolyhedron(Int64 cell_uid, ConstArrayView<Int64> connectivity_infos, Int32 owner, bool allow_build_face)
815{
816 const bool is_verbose = false;
817 if (is_verbose)
818 info() << "AddNewPolyhedronCell nb_connectivity=" << connectivity_infos.size()
819 << " c=" << connectivity_infos;
820
821 // Checks if the cell already exists (in which case nothing is done).
822 // TODO: Search if a cell with same uniqueId() already exists.
823
824 UniqueArray<Int16> local_nodes_of_cell;
825 UniqueArray<Int64> nodes_of_cell;
826 UniqueArray<Int32> nodes_of_face;
827
828 // Infos for creating the corresponding Arcane type
829 UniqueArray<Int16> arcane_faces_nb_node;
830 UniqueArray<Int16> arcane_faces_nodes;
831 // Local index in the cell of the nodes;
832 impl::HashTableMap2<Int64, Int16> connectivity_to_local_index(500);
833
834 Int16 nb_local_node = 0;
835 nodes_of_cell.clear();
836 connectivity_to_local_index.clear();
837 local_nodes_of_cell.clear();
838 arcane_faces_nb_node.clear();
839 arcane_faces_nodes.clear();
840
841 // [0] is the size of array
842 // [1] is the scheme version (at the moment the only value supported is only '1'
843 // [2] is the number of face (for scheme version 1)
844 // the next elements are nodes of face0, then node of face1, ...
845
846 SmallArray<Int64> cell_nodes_uid;
847 Int32 array_size = connectivity_infos[0];
848 if (array_size != connectivity_infos.size())
849 ARCANE_FATAL("Incoherent size array_size={0} connectivity_info={1}", array_size, connectivity_infos.size());
850 Int32 scheme_version = connectivity_infos[1];
851 if (scheme_version != 1)
852 ARCANE_FATAL("Insupported scheme version '{0}'. Only supported value is 1", scheme_version);
853 const Int32 cell_nb_face = static_cast<Int32>(connectivity_infos[2]);
854 if (is_verbose)
855 info() << "NB_FACE=" << cell_nb_face;
856 Int32 index_in_connectivity = 3;
857 for (Int32 z = 0; z < cell_nb_face; ++z) {
858 const Int16 face_nb_node = static_cast<Int16>(connectivity_infos[index_in_connectivity]);
859 ++index_in_connectivity;
860 if (is_verbose)
861 info() << "NB_FACE_NODE=" << face_nb_node;
862 nodes_of_face.resize(face_nb_node);
863 arcane_faces_nb_node.add(face_nb_node);
864 for (Int16 k = 0; k < face_nb_node; ++k) {
865 Int64 node_id = connectivity_infos[index_in_connectivity];
866 ++index_in_connectivity;
867 auto x = connectivity_to_local_index.find(node_id);
868 Int16 local_node_index = -1;
869 // Check if node is already in the list
870 if (x == connectivity_to_local_index.end()) {
871 local_node_index = nb_local_node;
872 connectivity_to_local_index[node_id] = nb_local_node;
873 ++nb_local_node;
874 local_nodes_of_cell.add(local_node_index);
875 nodes_of_cell.add(node_id);
876 cell_nodes_uid.add(node_id);
877 }
878 else
879 local_node_index = x->second;
880 nodes_of_face[k] = local_node_index;
881 arcane_faces_nodes.add(local_node_index);
882 //Int32 face_nb_node = face_indexes[z+1] - face_indexes[z];
883 }
884 if (is_verbose)
885 info() << " Polyhedral face=" << z << " nb_node=" << face_nb_node
886 << " nodes=" << nodes_of_face.view() << " index=" << index_in_connectivity;
887 }
888
889 if (is_verbose)
890 info() << "EndCreateTypeForPolyhedron nb_node=" << nodes_of_cell.size();
891 ItemTypeMngInternal* api = m_item_type_mng->_internalApi();
892 ItemTypeInfo* cell_type_info = api->findOrAddPolyhedron(nodes_of_cell.size(),
893 arcane_faces_nb_node, arcane_faces_nodes);
894 CellInfoProxy cell_info_proxy(ITI_GenericPolyhedron, cell_type_info, cell_uid, owner, nodes_of_cell, allow_build_face);
895 return _addOneCell(cell_info_proxy);
896}
897
898/*---------------------------------------------------------------------------*/
899/*---------------------------------------------------------------------------*/
916addOneParentItem(const Item& item, const eItemKind submesh_kind, const bool fatal_on_existing_item)
917{
918 //bool is_check = arcaneIsCheck();
919 ItemTypeMng* itm = m_mesh->itemTypeMng();
920 eItemKind kind = item.kind();
921 ItemTypeInfo* type = itm->typeFromId(item.type());
922
923 if (item.type() == IT_Line2 && submesh_kind == IK_Cell)
924 type = itm->typeFromId(IT_CellLine2);
925 if (item.type() == IT_Vertex && submesh_kind == IK_Face)
926 type = itm->typeFromId(IT_FaceVertex);
927 ItemTypeId type_id = type->itemTypeId();
928
929 if (MeshToMeshTransposer::kindTranspose(submesh_kind, m_mesh, m_mesh->parentMesh()) != kind)
930 ARCANE_FATAL("Incompatible kind/sub-kind");
931
932 // Checks if the cell already exists
933 bool is_add; // this flag is always correctly set via findOrAllocOne
934 Item new_item;
935
936 switch (submesh_kind) {
937 case IK_Node:
938 new_item = m_node_family.findOrAllocOne(item.uniqueId(), is_add);
939 ++m_mesh_info.nbNode();
940 break;
941 case IK_Edge:
942 new_item = m_edge_family.findOrAllocOne(item.uniqueId(), is_add);
943 ++m_mesh_info.nbEdge();
944 break;
945 case IK_Face:
946 new_item = m_face_family.findOrAllocOne(item.uniqueId(), type, is_add);
947 ++m_mesh_info.nbFace();
948 break;
949 case IK_Cell:
950 if (kind == IK_Face && !(item.toFace().isSubDomainBoundary()))
951 ARCANE_FATAL("Bad boundary face");
952 new_item = m_cell_family.findOrAllocOne(item.uniqueId(), type_id, is_add);
953 ++m_mesh_info.nbCell();
954 break;
955 default:
956 throw NotSupportedException(A_FUNCINFO, String::format("Kind {0} not supported", submesh_kind));
957 }
958
959 if (!is_add) {
960 if (fatal_on_existing_item)
961 ARCANE_FATAL("Cannot add already existing parent item in submesh");
962 else
963 return ItemCompatibility::_itemInternal(new_item);
964 }
965
966 new_item.mutableItemBase().setParent(0, item.localId());
967 new_item.mutableItemBase().setOwner(item.owner(), m_mesh_info.rank());
968
969 // Localizes these sub-items relative to the item to be inserted
970 // By default everything is 0, which also corresponds to the submesh_kind==IK_Node case
971 Integer item_nb_node = 0;
972 Integer item_nb_face = 0;
973 Integer item_nb_edge = 0;
974
975 switch (submesh_kind) {
976 case IK_Cell:
977 item_nb_face = type->nbLocalFace();
978 item_nb_edge = type->nbLocalEdge();
979 item_nb_node = type->nbLocalNode();
980 break;
981 case IK_Face:
982 item_nb_edge = type->nbLocalEdge();
983 item_nb_node = type->nbLocalNode();
984 break;
985 case IK_Edge:
986 item_nb_node = type->nbLocalNode();
987 default: // les autres sont déjà filtrés avant
988 break;
989 }
990
991 // Handling the case of edge deactivation
992 if (!m_mesh_builder->hasEdge())
993 item_nb_edge = 0;
994
995#if OLD
996 // Ne fonctionne plus si on désactive les anciennes connectivités
997 if (is_check) {
998 for (Integer z = 0; z < item_nb_face; ++z)
999 new_item->_setFace(z, NULL_ITEM_ID);
1000 for (Integer z = 0; z < item_nb_edge; ++z)
1001 new_item->_setEdge(z, NULL_ITEM_ID);
1002 for (Integer z = 0; z < item_nb_node; ++z)
1003 new_item->_setNode(z, NULL_ITEM_ID);
1004 }
1005#endif
1006
1008 DynamicMeshKindInfos::ItemInternalMap& nodes_map = m_mesh->nodesMap();
1009 auto* parent_mesh = ARCANE_CHECK_POINTER(dynamic_cast<DynamicMesh*>(m_mesh->parentMesh()));
1010 DynamicMeshKindInfos::ItemInternalMap& parent_nodes_map = parent_mesh->nodesMap();
1011
1012 // Processing new nodes
1013
1014 // The vertices are used in the item order except for surface submeshes.
1015 const bool direct_node_order =
1016 !(submesh_kind == IK_Cell && kind == IK_Face && !(item.toFace().isSubDomainBoundaryOutside()));
1017
1018 Int64UniqueArray nodes_uid(item_nb_node, NULL_ITEM_UNIQUE_ID);
1019 for (Integer i_node = 0; i_node < item_nb_node; ++i_node) {
1020 Item parent_item;
1021 if (type->typeId() == IT_FaceVertex)
1022 parent_item = item;
1023 else {
1024 Int32 idx = ((direct_node_order) ? i_node : (item_nb_node - 1 - i_node));
1025 parent_item = item.toItemWithNodes().node(idx);
1026 }
1027 Int64 new_node_uid = nodes_uid[i_node] = parent_item.uniqueId();
1028 ItemInternal* node_internal = m_node_family.findOrAllocOne(new_node_uid, is_add);
1029 if (is_add) {
1030#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1031 info() << "Création node " << new_node_uid << ' '
1032 << node_internal->uniqueId() << ' ' << node_internal->localId();
1033#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
1034 node_internal->setParent(0, parent_item.localId());
1035 node_internal->setOwner(parent_item.owner(), m_mesh_info.rank());
1036 ++m_mesh_info.nbNode();
1037 }
1038
1039 // Connecting the item to the nodes
1040 ItemLocalId node_lid(node_internal);
1041 ItemLocalId new_item_lid(new_item);
1042 switch (submesh_kind) {
1043 case IK_Cell:
1044 m_cell_family.replaceNode(new_item_lid, i_node, node_lid);
1045 m_node_family.addCellToNode(node_internal, new_item.toCell());
1046 break;
1047 case IK_Face:
1048 m_face_family.replaceNode(new_item_lid, i_node, node_lid);
1049 m_node_family.addFaceToNode(node_internal, new_item.toFace());
1050 break;
1051 case IK_Edge:
1052 m_edge_family.replaceNode(new_item_lid, i_node, node_lid);
1053 m_node_family.addEdgeToNode(node_internal, new_item.toEdge());
1054 break;
1055 default: // les autres sont déjà filtrés avant
1056 break;
1057 }
1058 }
1059
1060 // Processing new edges (the has_edge filter is already taken into account in item_nb_edge)
1061 for (Integer i_edge = 0; i_edge < item_nb_edge; ++i_edge) {
1062 const ItemTypeInfo::LocalEdge& le = type->localEdge(i_edge);
1063
1064 Int64 first_node = nodes_uid[le.beginNode()];
1065 Int64 second_node = nodes_uid[le.endNode()];
1066 if (first_node > second_node)
1067 std::swap(first_node, second_node);
1068
1069 Edge parent_item = item.itemBase().edgeBase(i_edge);
1070 if (parent_item.null())
1071 ARCANE_FATAL("Cannot find parent edge");
1072
1073 Int64 new_edge_uid = parent_item.uniqueId();
1074
1075 ItemInternal* edge_internal = m_edge_family.findOrAllocOne(new_edge_uid, is_add);
1076 if (is_add) {
1077#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1078 info() << "Création edge " << new_edge_uid << ' '
1079 << edge_internal->uniqueId() << ' ' << edge_internal->localId();
1080#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
1081 edge_internal->setParent(0, parent_item.localId());
1082 edge_internal->setOwner(parent_item.owner(), m_mesh_info.rank());
1083
1084 {
1085 Node current_node = nodes_map.findItem(first_node);
1086 m_edge_family.replaceNode(ItemLocalId(edge_internal), 0, current_node);
1087 m_node_family.addEdgeToNode(current_node, edge_internal);
1088 }
1089 {
1090 Node current_node = nodes_map.findItem(second_node);
1091 m_edge_family.replaceNode(ItemLocalId(edge_internal), 1, current_node);
1092 m_node_family.addEdgeToNode(current_node, edge_internal);
1093 }
1094 ++m_mesh_info.nbEdge();
1095 }
1096
1097 // Connecting the item to the nodes
1098 switch (submesh_kind) {
1099 case IK_Cell: {
1100 m_cell_family.replaceEdge(ItemLocalId(new_item), i_edge, ItemLocalId(edge_internal));
1101 m_edge_family.addCellToEdge(edge_internal, new_item.toCell());
1102 } break;
1103 case IK_Face: {
1104 m_face_family.replaceEdge(ItemLocalId(new_item), i_edge, ItemLocalId(edge_internal));
1105 m_edge_family.addFaceToEdge(edge_internal, new_item.toFace());
1106 } break;
1107 default: // les autres sont déjà filtrés avant
1108 break;
1109 }
1110 }
1111
1112 // Processing new faces
1113 // item_nb_face already materializes that this context only occurs with submesh_kind==IK_Cell
1114 for (Integer i_face = 0; i_face < item_nb_face; ++i_face) {
1115 const ItemTypeInfo::LocalFace& lf = type->localFace(i_face);
1116 Integer face_nb_node = lf.nbNode();
1117
1118 m_work_face_orig_nodes_uid.resize(face_nb_node);
1119 for (Integer z = 0; z < face_nb_node; ++z)
1120 m_work_face_orig_nodes_uid[z] = nodes_uid[lf.node(z)];
1121 bool is_reorder = false;
1122 if (m_mesh->dimension() == 1) { // is 1d mesh
1123 is_reorder = m_face_reorderer.reorder1D(i_face, m_work_face_orig_nodes_uid[0]);
1124 }
1125 else {
1126 is_reorder = m_face_reorderer.reorder(ItemTypeId::fromInteger(lf.typeId()), m_work_face_orig_nodes_uid);
1127 }
1128 ConstArrayView<Int64> face_sorted_nodes(m_face_reorderer.sortedNodes());
1129 // find parent item
1130 Item parent_item;
1131 if (kind == IK_Cell) {
1132 parent_item = item.toCell().face(i_face);
1133 }
1134 else if (kind == IK_Face) {
1135 if (m_mesh->dimension() == 1) { // is 1d mesh
1136 parent_item = parent_nodes_map.findItem(face_sorted_nodes[0]);
1137 }
1138 else {
1139 // Algo sans CT_FaceToEdge
1140 Int64 first_node = face_sorted_nodes[0];
1141 Int64 second_node = face_sorted_nodes[1];
1142 if (first_node > second_node)
1143 std::swap(first_node, second_node);
1144 Node nbi = parent_nodes_map.findItem(first_node);
1145 parent_item = ItemTools::findEdgeInNode2(nbi, first_node, second_node);
1146 }
1147 }
1148
1149 if (parent_item.null())
1150 ARCANE_FATAL("Cannot find parent face");
1151 Int64 new_face_uid = parent_item.uniqueId();
1152 ItemTypeInfo* face_type = itm->typeFromId(lf.typeId());
1153
1154 ItemInternal* face_internal = m_face_family.findOrAllocOne(new_face_uid, face_type, is_add);
1155 if (is_add) {
1156#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1157 info() << "Création face " << new_face_uid << ' '
1158 << face_internal->uniqueId() << ' ' << face_internal->localId();
1159#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
1160 face_internal->setParent(0, parent_item.localId());
1161 face_internal->setOwner(parent_item.owner(), m_mesh_info.rank());
1162
1163 for (Integer i_node = 0; i_node < face_nb_node; ++i_node) {
1164 Node current_node = nodes_map.findItem(face_sorted_nodes[i_node]);
1165 m_face_family.replaceNode(ItemLocalId(face_internal), i_node, current_node);
1166 m_node_family.addFaceToNode(current_node, face_internal);
1167 }
1168
1169 if (m_mesh_builder->hasEdge()) {
1170 Integer face_nb_edge = lf.nbEdge();
1171 for (Integer i_edge = 0; i_edge < face_nb_edge; ++i_edge) {
1172 Int32 edge_idx = lf.edge(i_edge);
1173 Edge current_edge = new_item.itemBase().edgeBase(edge_idx);
1174 m_face_family.addEdgeToFace(face_internal, current_edge);
1175 m_edge_family.addFaceToEdge(current_edge, face_internal);
1176 }
1177 }
1178 ++m_mesh_info.nbFace();
1179 }
1180 m_cell_family.replaceFace(ItemLocalId(new_item), i_face, ItemLocalId(face_internal));
1181 if (is_reorder) {
1182 m_face_family.addFrontCellToFace(face_internal, new_item.toCell());
1183 }
1184 else {
1185 m_face_family.addBackCellToFace(face_internal, new_item.toCell());
1186 }
1187 }
1188
1189 return ItemCompatibility::_itemInternal(new_item);
1190}
1191
1192/*---------------------------------------------------------------------------*/
1193/*---------------------------------------------------------------------------*/
1194
1198template <typename CellInfo>
1200_addNodesToCell(Cell cell, const CellInfo& cell_info)
1201{
1202 Integer cell_nb_node = cell_info.nbNode();
1203
1204 // Adds new nodes if necessary
1205 for (Integer i_node = 0; i_node < cell_nb_node; ++i_node) {
1206 Int64 node_unique_id = cell_info.nodeUniqueId(i_node);
1207 bool is_add = false;
1208 ItemInternal* node_internal = m_node_family.findOrAllocOne(node_unique_id, is_add);
1209 if (is_add) {
1210 ++m_mesh_info.nbNode();
1211 node_internal->setOwner(cell_info.nodeOwner(i_node), m_mesh_info.rank());
1212 }
1213 m_node_family.addCellToNode(node_internal, cell);
1214 m_cell_family.replaceNode(cell, i_node, ItemLocalId(node_internal));
1215 }
1216}
1217
1218/*---------------------------------------------------------------------------*/
1219/*---------------------------------------------------------------------------*/
1220
1221template <typename CellInfo>
1222bool OneMeshItemAdder::
1223_isReorder(Integer i_face, const ItemTypeInfo::LocalFace& lf, const CellInfo& cell_info)
1224{
1225 const Integer face_nb_node = lf.nbNode();
1226 m_work_face_orig_nodes_uid.resize(face_nb_node);
1227 for (Integer i_node = 0; i_node < face_nb_node; ++i_node)
1228 m_work_face_orig_nodes_uid[i_node] = cell_info.nodeUniqueId(lf.node(i_node));
1229 bool is_reorder = false;
1230 if (m_mesh->dimension() == 1) { // is 1d mesh
1231 is_reorder = m_face_reorderer.reorder1D(i_face, m_work_face_orig_nodes_uid[0]);
1232 }
1233 else {
1234 is_reorder = m_face_reorderer.reorder(ItemTypeId::fromInteger(lf.typeId()), m_work_face_orig_nodes_uid);
1235 }
1236
1237 return is_reorder;
1238}
1239
1240/*---------------------------------------------------------------------------*/
1241/*---------------------------------------------------------------------------*/
1242
1246{
1247 m_next_face_uid = 0;
1248 m_next_edge_uid = 0;
1249 m_mesh_info.reset();
1250}
1251
1252/*---------------------------------------------------------------------------*/
1253/*---------------------------------------------------------------------------*/
1254
1257{
1258 if (m_next_face_uid != 0 || m_next_edge_uid != 0)
1259 ARCANE_FATAL("Can not call this method when edge or face are already created");
1261 info() << "Is Generate Edge and Face uniqueId() from Nodes=" << m_use_hash_for_edge_and_face_unique_id;
1262}
1263
1264/*---------------------------------------------------------------------------*/
1265/*---------------------------------------------------------------------------*/
1266
1267} // End namespace Arcane::mesh
1268
1269/*---------------------------------------------------------------------------*/
1270/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
bool reorderNodesOfFace(Int64ConstArrayView before_ids, Int64ArrayView after_ids)
Reorders the nodes of a face.
Int64 generateHashUniqueId(SmallSpan< const Int64 > nodes_unique_id)
Generates a unique identifier from a list of node identifiers.
Integer size() const
Number of elements in the vector.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
ArrayView< T > view() const
Mutable view of this array.
Cell of a mesh.
Definition Item.h:1300
Face face(Int32 i) const
i-th face of the cell
Definition Item.h:1400
Int32 nbFace() const
Number of faces of the cell.
Definition Item.h:1397
Edge edge(Int32 i) const
i-th edge of the cell
Definition Item.h:1415
Constant view of an array of type T.
constexpr ConstArrayView< T > subView(Integer abegin, Integer asize) const noexcept
Sub-view (constant) starting from element abegin and containing asize elements.
constexpr Integer size() const noexcept
Number of elements in the array.
Edge of a cell.
Definition Item.h:875
Face of a cell.
Definition Item.h:1032
Int32 nbCell() const
Number of cells of the face (1 or 2).
Definition Item.h:1129
bool isSubDomainBoundary() const
Indicates if the face is on the subdomain boundary (i.e nbCell()==1).
Definition Item.h:1148
Interface for managing an incremental connectivity.
virtual void replaceConnectedItem(ItemLocalId source_item, Integer index, ItemLocalId target_local_id)=0
Replaces the entity at index index of source_item with the entity with localId() target_local_id.
virtual void addConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id)=0
Adds the entity with localId() target_local_id to the connectivity of source_item.
Interface for modifying a family.
virtual IIncrementalItemConnectivity * getStoredConnectivity(IItemFamily *source_family, IItemFamily *target_family, const String &name)=0
Returns, if associated with storage, the connectivity between the families source_family and target_f...
Interface of an entity family.
Definition IItemFamily.h:85
virtual String name() const =0
Family name.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converts an array of unique numbers to local numbers.
ItemUniqueId uniqueId() const
Unique number of the entity.
ItemTypeInfo * typeInfo() const
Type of the entity.
Int32 localId() const
Local number (in the subdomain) of the entity.
Internal structure of a mesh entity.
Index of an Item in a variable.
Definition ItemLocalId.h:42
Type of an entity (Item).
Definition ItemTypeId.h:33
static ItemTypeId fromInteger(Int64 v)
Creates an instance from an integer.
Local information about a cell edge.
Integer endNode() const
Local index in the cell of the ending node of the edge.
Integer beginNode() const
Local index in the cell of the starting node of the edge.
Local information about a cell face.
Integer node(Integer i) const
Local index in the cell of the i-th node of the face.
Integer nbEdge() const
Number of edges of the face.
Integer typeId() const
Type of the face entity.
Integer edge(Integer i) const
Edge of the face.
Integer nbNode() const
Number of nodes of the face.
Info on a mesh entity type.
LocalEdge localEdge(Integer id) const
Local connectivity of the i-th edge of the cell.
LocalFace localFace(Integer id) const
Local connectivity of the i-th face of the cell.
const ItemTypeInfo * linearTypeInfo() const
Type of the corresponding linear element.
Int16 dimension() const
Dimension of the element (<0 if unknown).
Integer nbLocalNode() const
Number of nodes of the entity.
String typeName() const
Type name.
Integer nbLocalFace() const
Number of faces of the entity.
bool isValidForCell() const
Indicates if the type is valid for creating a cell.
ItemTypeId itemTypeId() const
Type number.
Mesh entity type manager.
Definition ItemTypeMng.h:64
ItemTypeInfo * typeFromId(Integer id) const
Type corresponding to the number id.
Mesh element based on nodes (Edge,Face,Cell).
Definition Item.h:773
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
Base class for a mesh element.
Definition Item.h:84
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
Edge toEdge() const
Converts the entity to the Edge kind.
Definition Item.h:1816
Int32 owner() const
Owner subdomain number of the entity.
Definition Item.h:252
ItemWithNodes toItemWithNodes() const
Converts the entity to the ItemWithNodes kind.
Definition Item.h:1802
Cell toCell() const
Converts the entity to the Cell kind.
Definition Item.h:1830
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
constexpr bool null() const
true if the entity is null (i.e. not connected to the mesh)
Definition Item.h:230
Face toFace() const
Converts the entity to the Face kind.
Definition Item.h:1823
impl::ItemBase itemBase() const
Internal part of the entity.
Definition Item.h:383
constexpr eItemKind kind() const
Entity kind.
Definition Item.h:264
Int16 type() const
Entity type.
Definition Item.h:255
Characteristics of a mesh.
Definition MeshKind.h:113
bool isMonoDimension() const
True if the mesh structure is eMeshCellDimensionKind::MonoDimension.
Definition MeshKind.h:122
static eItemKind kindTranspose(eItemKind kindA, IMesh *meshA, IMesh *meshB)
Transpose the kind kindA of mesh meshA to the associated kind in meshB.
Methods allowing modification of ItemBase.
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
void setParent(Int32 aindex, Int32 parent_local_id)
Sets the i-th parent (currently aindex must be 0).
void addFlags(Int32 added_flags)
Adds the flags added_flags to those of the entity.
Node of a mesh.
Definition Item.h:598
1D data array with pre-allocated stack buffer.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Implementation of std::unordered_map.
Implementation of a mesh.
Definition DynamicMesh.h:98
IItemFamily * itemFamily(eItemKind ik) override
Returns the entity family of type ik.
Integer dimension() override
Mesh dimension (1D, 2D, or 3D).
IItemFamilyNetwork * itemFamilyNetwork() override
Family network interface (connected families).
Item findOrAllocOne(Int64 uid, ItemTypeId type_id, MeshInfos &mesh_info, bool &is_alloc) override
Retrieves or allocates a unique numbered edge uid and of type type.Generic item addition.
void replaceNode(ItemLocalId edge, Integer index, ItemLocalId node)
Replaces the node at index index of the edge edge with * that of localId() node_lid.
Info to create/serialize a cell knowing the uniqueId() and owner() of all these sub-entities (cells,...
Integer level() const
AMR.
Associative array of ItemInternal.
impl::ItemBase findItem(Int64 uid) const
Returns the unique ID entity 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
Number of this subdomain.
Definition MeshInfos.h:54
Integer & nbEdge()
Number of edges in the mesh.
Definition MeshInfos.h:61
Integer & nbNode()
Number of nodes in the mesh.
Definition MeshInfos.h:57
void _checkSameItemCoherency(ItemWithNodes item, ConstArrayView< Int64 > nodes_uid)
Checks the coherence of nodes for an already added item.
void _addNodesToCell(Cell cell, const CellInfo &cell_info)
Adds the nodes nodes_uid to the cell cell.
NodesOfItemReorderer m_face_reorderer
Work arrays.
ItemInternal * _addOneCell(const CellInfo &cell_info)
Adds a cell.
MeshInfos m_mesh_info
General information about the mesh (sub-domain number, number of items...).
Int64 _checkGenerateFaceUniqueId(Int64 uid, ConstArrayView< Int64 > nodes_uid)
Generates a uniqueId() for the face if uid is null.
Int64 m_next_edge_uid
Next uniqueId() number used for generating edges.
void setUseNodeUniqueIdToGenerateEdgeAndFaceUniqueId(bool v)
Positions the uniqueId() numbering mechanism.
void resetAfterDeallocate()
Resets the structures to allow for re-allocation.
bool m_use_hash_for_edge_and_face_unique_id
If true, generates face uniqueIds from node uniqueIds.
Int64 m_next_face_uid
Next uniqueId() number used for generating faces.
ItemInternal * addOneParentItem(const Item &item, const eItemKind submesh_kind, const bool fatal_on_existing_item=true)
Adds a parent item.
ItemInternal * addOneFace(ItemTypeId type_id, Int64 face_uid, Int32 owner_rank, Int64ConstArrayView nodes_uid)
Adds a face.
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:333
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:474
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
eItemKind
Mesh entity type.
@ IK_Particle
Particle mesh entity.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Face
Face mesh entity.
@ IK_DoF
Degree of Freedom mesh entity.
@ IK_Edge
Edge mesh entity.
std::int16_t Int16
Signed integer type of 16 bits.
std::int32_t Int32
Signed integer type of 32 bits.