Arcane  4.1.12.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-2025 */
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
21#include "arcane/core/MeshToMeshTransposer.h"
22#include "arcane/core/IParallelMng.h"
23#include "arcane/core/ItemPrinter.h"
24
25#include "arcane/mesh/DynamicMesh.h"
26#include "arcane/mesh/DynamicMeshIncrementalBuilder.h"
27#include "arcane/mesh/ItemTools.h"
28#include "arcane/mesh/ConnectivityNewWithDependenciesTypes.h"
29#include "arcane/mesh/GraphDoFs.h"
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34namespace Arcane::mesh
35{
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
41{
42 public:
43
44 CellInfoProxy(ItemTypeInfo* type_info,
45 Int64 cell_uid,
46 Int32 sub_domain_id,
48 bool allow_build_face = false)
49 : m_type_info(type_info)
50 , m_cell_uid(cell_uid)
51 , m_info(info)
52 , m_owner(sub_domain_id)
53 , m_allow_build_face(allow_build_face)
54 {}
55
56 Int64 uniqueId() const { return m_cell_uid; }
57 ItemTypeInfo* typeInfo() const { return m_type_info; }
58 Int32 owner() const { return m_owner; }
59 Integer nbNode() const { return m_info.size(); }
60 Integer nbFace() const { return m_type_info->nbLocalFace(); }
61 Integer nbEdge() const { return m_type_info->nbLocalEdge(); }
62 Int64 nodeUniqueId(Integer i_node) const { return m_info[i_node]; }
63 Int32 nodeOwner(Integer) const { return m_owner; }
64 Int32 faceOwner(Integer) const { return m_owner; }
65 Int32 edgeOwner(Integer) const { return m_owner; }
66 ItemTypeInfo::LocalFace localFace(Integer i_face) const { return m_type_info->localFace(i_face); }
67 bool allowBuildFace() const { return m_allow_build_face; }
68 bool allowBuildEdge() const { return m_allow_build_face; }
69
70 private:
71
72 ItemTypeInfo* m_type_info = nullptr;
73 Int64 m_cell_uid = NULL_ITEM_UNIQUE_ID;
75 Int32 m_owner = A_NULL_RANK;
76 bool m_allow_build_face = false;
77};
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
82OneMeshItemAdder::
83OneMeshItemAdder(DynamicMeshIncrementalBuilder* mesh_builder)
84: TraceAccessor(mesh_builder->mesh()->traceMng())
85, m_mesh(mesh_builder->mesh())
86, m_mesh_builder(mesh_builder)
87, m_cell_family(m_mesh->trueCellFamily())
88, m_node_family(m_mesh->trueNodeFamily())
89, m_face_family(m_mesh->trueFaceFamily())
90, m_edge_family(m_mesh->trueEdgeFamily())
91, m_item_type_mng(m_mesh->itemTypeMng())
92, m_mesh_info(m_mesh->meshPartInfo().partRank())
93, m_face_reorderer(m_item_type_mng)
94{
95 //m_work_face_sorted_nodes.reserve(100);
96 m_work_face_orig_nodes_uid.reserve(100);
97}
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102ItemInternal* OneMeshItemAdder::
103addOneNode(Int64 node_uid, Int32 owner)
104{
105 bool is_add = false;
106 ItemInternal* node = m_node_family.findOrAllocOne(node_uid, is_add);
107 if (is_add) {
109 node->setOwner(owner, owner);
110 }
111 return node;
112}
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
125{
126 Int32 nb_node = nodes_uid.size();
127 // Checks that the number of nodes is the same
128 if (item.nbNode() != nb_node)
129 ARCANE_FATAL("Trying to add existing item (kind='{0}', uid={1}) with different number of node (existing={2} new={3})",
130 item.kind(), item.uniqueId(), item.nbNode(), nb_node);
131
132 // Checks that the nodes correspond to the existing ones
133 for (Int32 i = 0; i < nb_node; ++i) {
134 Int64 new_uid = nodes_uid[i];
135 Int64 current_uid = item.node(i).uniqueId();
136 if (new_uid != current_uid) {
137 std::ostringstream ostr;
138 for (Int32 k = 0; k < nb_node; ++k)
139 ostr << " " << item.node(k).uniqueId();
140 ARCANE_FATAL("Trying to add existing item (kind='{0}', uid={1}) with different nodes (index={2} existing='{3}' new='{4}')",
141 item.kind(), item.uniqueId(), i, ostr.str(), nodes_uid);
142 }
143 }
144}
145
146/*---------------------------------------------------------------------------*/
147/*---------------------------------------------------------------------------*/
155{
156 if (uid != NULL_ITEM_UNIQUE_ID)
157 return uid;
159 uid = MeshUtils::generateHashUniqueId(nodes_uid);
160 else
161 uid = m_next_face_uid++;
162 return uid;
163}
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
180addOneFace(ItemTypeId type_id, Int64 face_uid, Int32 owner_rank, Int64ConstArrayView nodes_uid)
181{
182 const Integer face_nb_node = nodes_uid.size();
183
184 //m_work_face_sorted_nodes.resize(face_nb_node);
185 //m_work_face_orig_nodes_uid.resize(face_nb_node);
186 //for( Integer z=0; z<face_nb_node; ++z )
187 //m_work_face_orig_nodes_uid[z] = nodes_uid[z];
188 m_face_reorderer.reorder(type_id, nodes_uid);
189 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
190 // TODO: in the case where the face will be orphaned (not connected to a cell),
191 // check if the face needs reorientation because this risks introducing
192 // an inconsistency if one later wishes to calculate a normal.
193 //MeshUtils::reorderNodesOfFace(m_work_face_orig_nodes_uid,m_work_face_sorted_nodes);
194 face_uid = _checkGenerateFaceUniqueId(face_uid, face_sorted_nodes);
195 bool is_add_face = false;
196 Face face = m_face_family.findOrAllocOne(face_uid, type_id, is_add_face);
197 // The face does not exist
198 if (is_add_face) {
199 ++m_mesh_info.nbFace();
200 face.mutableItemBase().setOwner(owner_rank, m_mesh_info.rank());
201 for (Integer i_node = 0; i_node < face_nb_node; ++i_node) {
202 Node node = addOneNode(face_sorted_nodes[i_node], m_mesh_info.rank());
203 m_face_family.replaceNode(face, i_node, node);
204 m_node_family.addFaceToNode(node, face);
205 }
206 }
207 else {
208 if (arcaneIsCheck())
209 _checkSameItemCoherency(face, face_sorted_nodes);
210 }
211
212 return ItemCompatibility::_itemInternal(face);
213}
214
215/*---------------------------------------------------------------------------*/
216/*---------------------------------------------------------------------------*/
217
218ItemInternal* OneMeshItemAdder::
219addOneEdge(Int64 edge_uid, Int32 rank, Int64ConstArrayView nodes_uid)
220{
221 m_work_edge_sorted_nodes.resize(2);
222 m_work_edge_orig_nodes_uid.resize(2);
223
224 for (Integer z = 0; z < 2; ++z)
225 m_work_edge_orig_nodes_uid[z] = nodes_uid[z];
226 // reorderNodesOfFace behaves correctly here for edges == faces in 2D
227 MeshUtils::reorderNodesOfFace(m_work_edge_orig_nodes_uid, m_work_edge_sorted_nodes);
228
229 bool is_add_edge = false;
230 ItemInternal* edge = m_edge_family.findOrAllocOne(edge_uid, is_add_edge);
231
232 // The edge does not exist
233 if (is_add_edge) {
235 edge->setOwner(rank, m_mesh_info.rank());
236 for (Integer i_node = 0; i_node < 2; ++i_node) {
237 ItemInternal* current_node_internal = addOneNode(m_work_edge_sorted_nodes[i_node], m_mesh_info.rank());
238 m_edge_family.replaceNode(ItemLocalId(edge), i_node, ItemLocalId(current_node_internal));
239 m_node_family.addEdgeToNode(current_node_internal, edge);
240 }
241 }
242 return edge;
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248template <>
249Face OneMeshItemAdder::
250_findInternalFace(Integer i_face, const FullCellInfo& cell_info, bool& is_add)
251{
252 const Int64 face_unique_id = cell_info.faceUniqueId(i_face);
253 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
254 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
255 ItemTypeInfo* face_type_info = m_item_type_mng->typeFromId(lf.typeId());
256 return m_face_family.findOrAllocOne(face_unique_id, face_type_info, is_add);
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
262template <>
263Face OneMeshItemAdder::
264_findInternalFace(Integer i_face, const CellInfoProxy& cell_info, bool& is_add)
265{
266 const ItemInternalMap& nodes_map = m_mesh->nodesMap();
267 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
268 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
269 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
270 Int64 face_unique_id = NULL_ITEM_UNIQUE_ID;
271 Face face_internal;
272 const bool use_hash = m_use_hash_for_edge_and_face_unique_id;
273 // If calculating face uniqueIds from nodes,
274 // we can directly know if the face already exists. Otherwise, we
275 // call ItemTools::findFaceInNode2(), but this function is more
276 // costly because it searches for the face by traversing the faces connected
277 // to the first node of the face.
278 if (use_hash) {
279 face_unique_id = _checkGenerateFaceUniqueId(NULL_ITEM_UNIQUE_ID, face_sorted_nodes);
280 face_internal = m_face_family.itemsMap().tryFind(face_unique_id);
281 }
282 else {
283 // Retrieves the oriented nodes of the face
284 // (One must have called one of the face addition methods before)
285 Node nbi = nodes_map.findItem(face_sorted_nodes[0]);
286 face_internal = ItemTools::findFaceInNode2(nbi, lf.typeId(), face_sorted_nodes);
287 }
288 if (face_internal.null()) {
289 // The face was not found. It therefore does not exist in our sub-domain.
290 // If this is allowed, the new face is created.
291 if (!cell_info.allowBuildFace() && !m_use_hash_for_edge_and_face_unique_id) {
292 info() << "BadCell uid=" << cell_info.uniqueId();
293 for (Int32 i = 0; i < cell_info.nbNode(); ++i)
294 info() << "Cell node I=" << i << " uid=" << cell_info.nodeUniqueId(i);
295 ARCANE_FATAL("On the fly face allocation is not allowed here.\n"
296 " You need to add faces with IMeshModifier::addFaces().\n"
297 " CellUid={0} LocalFace={1} FaceNodes={2}",
298 cell_info.uniqueId(), i_face, face_sorted_nodes);
299 }
300 // Only recalculate the hash if it hasn't been done already.
301 if (!use_hash)
302 face_unique_id = _checkGenerateFaceUniqueId(NULL_ITEM_UNIQUE_ID, face_sorted_nodes);
303 is_add = true;
304 ItemTypeInfo* face_type = m_item_type_mng->typeFromId(lf.typeId());
305 return m_face_family.allocOne(face_unique_id, face_type);
306 }
307 else {
308 is_add = false;
309 return face_internal;
310 }
311}
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
316template <>
317Edge OneMeshItemAdder::
318_findInternalEdge(Integer i_edge, const FullCellInfo& cell_info,
319 Int64 first_node, Int64 second_node, bool& is_add)
320{
321 ARCANE_UNUSED(first_node);
322 ARCANE_UNUSED(second_node);
323
324 const Int64 edge_unique_id = cell_info.edgeUniqueId(i_edge);
325 return m_edge_family.findOrAllocOne(edge_unique_id, is_add);
326}
327
328/*---------------------------------------------------------------------------*/
329/*---------------------------------------------------------------------------*/
330
331template <>
332Edge OneMeshItemAdder::
333_findInternalEdge(Integer i_edge, const CellInfoProxy& cell_info, Int64 first_node, Int64 second_node, bool& is_add)
334{
335 ARCANE_UNUSED(i_edge);
336
337 const bool use_hash = m_use_hash_for_edge_and_face_unique_id;
338 FixedArray<Int64, 2> nodes;
339 Int64 edge_unique_id = NULL_ITEM_UNIQUE_ID;
340 Edge edge_internal;
341 if (use_hash) {
342 nodes[0] = first_node;
343 nodes[1] = second_node;
344 edge_unique_id = MeshUtils::generateHashUniqueId(nodes.view());
345 edge_internal = m_edge_family.itemsMap().tryFind(edge_unique_id);
346 }
347 else {
348 const ItemInternalMap& nodes_map = m_mesh->nodesMap();
349 Node nbi = nodes_map.findItem(first_node);
350 edge_internal = ItemTools::findEdgeInNode2(nbi, first_node, second_node);
351 }
352 if (edge_internal.null()) {
353 if (!cell_info.allowBuildEdge() && !use_hash)
354 ARCANE_FATAL("On the fly edge allocation is not allowed here."
355 " You need to add edges before with IMeshModifier::addEdges()");
356 if (!use_hash)
357 edge_unique_id = m_next_edge_uid++;
358 is_add = true;
359 return m_edge_family.allocOne(edge_unique_id);
360 }
361 else {
362 is_add = false;
363 return edge_internal;
364 }
365}
366
367/*---------------------------------------------------------------------------*/
368/*---------------------------------------------------------------------------*/
369
387addOneCell(ItemTypeId type_id,
388 Int64 cell_uid,
389 Int32 sub_domain_id,
390 Int64ConstArrayView nodes_uid,
391 bool allow_build_face)
392{
393 CellInfoProxy cell_info_proxy(m_item_type_mng->typeFromId(type_id), cell_uid, sub_domain_id, nodes_uid, allow_build_face);
394
395 return _addOneCell(cell_info_proxy);
396}
397
398/*---------------------------------------------------------------------------*/
399/*---------------------------------------------------------------------------*/
406addOneCell(const FullCellInfo& cell_info)
407{
408 return _addOneCell(cell_info);
409}
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
413
414ItemInternal* OneMeshItemAdder::
415addOneItem(IItemFamily* family,
416 IItemFamilyModifier* family_modifier,
417 ItemTypeId type_id,
418 Int64 item_uid,
419 Integer item_owner,
420 Integer sub_domain_id,
421 Integer nb_connected_family,
422 Int64ConstArrayView connectivity_info)
423{
424 ARCANE_ASSERT(m_mesh->itemFamilyNetwork(), ("ItemFamilyNetwork is required to call OneMeshItemAdder::addOneItem"));
425 bool is_alloc = true;
426 Item item = family_modifier->findOrAllocOne(item_uid, type_id, m_mesh_info, is_alloc); // don't forget to add print in the class method
427 item.mutableItemBase().setOwner(item_owner, sub_domain_id);
428 // Add connectivities if needed
429 Integer info_index = 0;
430 for (Integer family_index = 0; family_index < nb_connected_family; ++family_index) {
431 // get connected family
432 eItemKind family_kind = static_cast<eItemKind>(connectivity_info[info_index++]); // another way ?
433 Int32 nb_connected_item = CheckedConvert::toInt32(connectivity_info[info_index++]);
434 IItemFamily* connected_family = m_mesh->itemFamily(family_kind);
435 // get connectivities family -> connected_family and reverse
436 String connectivity_name = mesh::connectivityName(family, connected_family);
437 String reverse_connectivity_name = mesh::connectivityName(connected_family, family);
438 bool is_dependency = false;
439 IIncrementalItemConnectivity* family_to_connected_family = m_mesh->itemFamilyNetwork()->getStoredConnectivity(family, connected_family, connectivity_name, is_dependency);
440 IIncrementalItemConnectivity* connected_family_to_family = m_mesh->itemFamilyNetwork()->getStoredConnectivity(connected_family, family, reverse_connectivity_name);
441 // Clear connectivities for already allocated items (except dependencies since replace is used)
442 if (!is_alloc) {
443 if (!is_dependency)
444 _clearConnectivity(ItemLocalId(item), family_to_connected_family);
445 if (connected_family_to_family)
446 _clearReverseConnectivity(ItemLocalId(item), family_to_connected_family, connected_family_to_family);
447 }
448 // get connected item lids
449 Int32UniqueArray connected_item_lids(nb_connected_item);
450 connected_family->itemsUniqueIdToLocalId(connected_item_lids, connectivity_info.subView(info_index, nb_connected_item), true);
451 for (Integer connected_item_index = 0; connected_item_index < nb_connected_item; ++connected_item_index) {
452 if (family_to_connected_family) {
453 // pre-alloc are done (=> use replace) when a dependency relation ("owning relation") while not when only a relation (use add)
454 if (!is_dependency)
455 family_to_connected_family->addConnectedItem(ItemLocalId(item), ItemLocalId(connected_item_lids[connected_item_index]));
456 else
457 family_to_connected_family->replaceConnectedItem(ItemLocalId(item), connected_item_index, ItemLocalId(connected_item_lids[connected_item_index])); // does not work with face to edges...
458 }
459 if (connected_family_to_family)
460 connected_family_to_family->addConnectedItem(ItemLocalId(connected_item_lids[connected_item_index]), ItemLocalId(item));
461 }
462 info_index += nb_connected_item;
463 }
464 // debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
465 debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
466 return ItemCompatibility::_itemInternal(item);
467}
468
469/*---------------------------------------------------------------------------*/
470
471ItemInternal* OneMeshItemAdder::
472addOneItem2(IItemFamily* family,
473 IItemFamilyModifier* family_modifier,
474 ItemTypeId type_id,
475 Int64 item_uid,
476 Integer item_owner,
477 Integer sub_domain_id,
478 Integer nb_connected_family,
479 Int64ConstArrayView connectivity_info)
480{
481 ARCANE_ASSERT(m_mesh->itemFamilyNetwork(), ("ItemFamilyNetwork is required to call OneMeshItemAdder::addOneItem"));
482 bool is_alloc = true;
483 Item item = family_modifier->findOrAllocOne(item_uid, type_id, m_mesh_info, is_alloc); // don't forget to add print in the class method
484 item.mutableItemBase().setOwner(item_owner, sub_domain_id);
485 // Add connectivities if needed
486 Integer info_index = 0;
487 for (Integer family_index = 0; family_index < nb_connected_family; ++family_index) {
488 // Prepare connection
489 // get connected family
490 eItemKind family_kind = static_cast<eItemKind>(connectivity_info[info_index++]); // another way ?
491 Int32 nb_connected_item = CheckedConvert::toInt32(connectivity_info[info_index++]);
492 if (nb_connected_item == 0)
493 continue;
494 IItemFamily* connected_family = nullptr;
495 switch (family_kind) {
496 case IK_Particle:
497 connected_family = m_mesh->findItemFamily(family_kind, ParticleFamily::defaultFamilyName(), false, false);
498 break;
499 case IK_DoF:
500 if (family->name() == GraphDoFs::dualNodeFamilyName())
501 connected_family = m_mesh->findItemFamily(family_kind, GraphDoFs::linkFamilyName(), false, false);
502 else
503 connected_family = m_mesh->findItemFamily(family_kind, GraphDoFs::dualNodeFamilyName(), false, false);
504 break;
505 default:
506 connected_family = m_mesh->itemFamily(family_kind);
507 break;
508 }
509 // get connectivities family -> connected_family and reverse
510 String connectivity_name = mesh::connectivityName(family, connected_family);
511 bool is_dependency = false;
512 IIncrementalItemConnectivity* family_to_connected_family = m_mesh->itemFamilyNetwork()->getConnectivity(family, connected_family, connectivity_name, is_dependency);
513 if (!family_to_connected_family)
514 ARCANE_FATAL("Cannot find connectivity name={0}", connectivity_name);
515 bool is_deep_connectivity = m_mesh->itemFamilyNetwork()->isDeep(family_to_connected_family);
516 bool is_relation = !(is_dependency && is_deep_connectivity);
517 // Build connection
518 // get connected item lids
519 Int32UniqueArray connected_item_lids(nb_connected_item);
520 bool do_fatal = is_relation ? false : true; // for relations, connected items may not be present and will be skipped.
521 connected_family->itemsUniqueIdToLocalId(connected_item_lids, connectivity_info.subView(info_index, nb_connected_item), do_fatal);
522 // if connection is relation, connected item not necessarily present: remove absent (ie null) items
523 Integer nb_connected_item_found = nb_connected_item;
524 if (is_relation) {
525 for (Integer index = 0; index < connected_item_lids.size();) {
526 if (connected_item_lids[index] == NULL_ITEM_LOCAL_ID) {
527 connected_item_lids.remove(index);
528 --nb_connected_item_found;
529 }
530 else
531 ++index;
532 }
533 }
534 for (Integer connected_item_index = 0; connected_item_index < nb_connected_item_found; ++connected_item_index) {
535 if (family_to_connected_family) {
536 // Only strategy : check and add
537 auto connected_item_lid = ItemLocalId{ connected_item_lids[connected_item_index] };
538 if (is_relation) {
539 if (!family_to_connected_family->hasConnectedItem(ItemLocalId(item), connected_item_lid)) {
540 family_to_connected_family->addConnectedItem(ItemLocalId(item), connected_item_lid);
541 }
542 }
543 else {
544 family_to_connected_family->replaceConnectedItem(ItemLocalId(item), connected_item_index, connected_item_lid);
545 }
546 }
547 }
548 info_index += nb_connected_item;
549 }
550 if (is_alloc)
551 debug(Trace::Highest) << "[addItems] ADD_ITEM " << ItemPrinter(item) << " in " << family->name();
552 // debug(Trace::Highest) << "[addItems] DEPENDENCIES for " << family->name() << FullItemPrinter(item) ; // debug info
553 // _printRelations(item); // debug info
554 return ItemCompatibility::_itemInternal(item);
555}
556
557/*---------------------------------------------------------------------------*/
558
559void OneMeshItemAdder::
560_printRelations(ItemInternal* item)
561{
562 debug(Trace::Highest) << "[addItems] RELATIONS for " << ItemPrinter(item) << " in " << item->family()->name();
563 for (const auto& relation : m_mesh->itemFamilyNetwork()->getChildRelations(item->family())) {
564 // debug(Trace::Highest) << " Relation " << relation->name();
565 // debug(Trace::Highest) << " Relation " << relation->nbConnectedItem(ItemLocalId(item));
566 ConnectivityItemVector connected_items(relation);
567 for (const auto& connected_item : connected_items.connectedItems(ItemLocalId(item))) {
568 debug(Trace::Highest) << ItemPrinter(connected_item);
569 }
570 }
571}
572
573/*---------------------------------------------------------------------------*/
574/*---------------------------------------------------------------------------*/
575
576void OneMeshItemAdder::
577_clearConnectivity(ItemLocalId item, IIncrementalItemConnectivity* connectivity)
578{
579
580 ConnectivityItemVector accessor(connectivity);
581 ENUMERATE_ITEM (connected_item, accessor.connectedItems(item)) {
582 connectivity->removeConnectedItem(item, connected_item);
583 }
584}
585
586/*---------------------------------------------------------------------------*/
587/*---------------------------------------------------------------------------*/
588
589void OneMeshItemAdder::
590_clearReverseConnectivity(ItemLocalId item, IIncrementalItemConnectivity* connectivity, IIncrementalItemConnectivity* reverse_connectivity)
591{
592 ConnectivityItemVector accessor(connectivity);
593 ENUMERATE_ITEM (connected_item, accessor.connectedItems(item)) {
594 reverse_connectivity->removeConnectedItem(connected_item, item);
595 }
596}
597
598/*---------------------------------------------------------------------------*/
599/*---------------------------------------------------------------------------*/
600
601template <> void OneMeshItemAdder::
602_AMR_Patch(Cell new_cell, const FullCellInfo& cell_info)
603{
605 if (m_mesh->isAmrActivated()) {
606 // FIXME doit-on traiter les mailles de niveau 0
607 //comme celles de niveau superieur
608 if (cell_info.level() != 0) {
609 Integer child_rank = cell_info.whichChildAmI();
610 Int64 hParent_uid = cell_info.hParentCellUniqueId();
611 ItemTypeId cell_type = ItemTypeId::fromInteger(cell_info.typeId());
612 bool is_add;
613 Cell hParent_cell = m_cell_family.findOrAllocOne(hParent_uid, cell_type, is_add);
614 m_cell_family._addParentCellToCell(new_cell, hParent_cell);
615 m_cell_family._addChildCellToCell(hParent_cell, child_rank, new_cell);
616 }
617 }
618}
619
620template <> void OneMeshItemAdder::
621_AMR_Patch(Cell cell, const CellInfoProxy& cell_info)
622{
623 ARCANE_UNUSED(cell);
624 ARCANE_UNUSED(cell_info);
625}
626
627/*---------------------------------------------------------------------------*/
628/*---------------------------------------------------------------------------*/
634template <typename CellInfo>
636_addOneCell(const CellInfo& cell_info)
637{
638 bool is_check = arcaneIsCheck();
639
640 ItemTypeInfo* cell_type_info = cell_info.typeInfo();
641 ItemTypeId cell_type_id = cell_type_info->itemTypeId();
642 const bool is_verbose = false;
643 if (is_verbose)
644 info() << "AddNewCell type_id=" << cell_type_id << " nb_node=" << cell_info.nbNode()
645 << " type=" << cell_type_info->typeName();
646 // Checks if the cell already exists (in which case nothing is done).
647 Cell inew_cell;
648 {
649 bool is_add; // ce flag est toujours correctement positionné via les findOrAllocOne
650 inew_cell = m_cell_family.findOrAllocOne(cell_info.uniqueId(), cell_type_id, is_add);
651 if (!is_add) {
652 if (is_check) {
653 Cell cell2(inew_cell);
654 // Verifies that the nodes match those that exist.
655 for (Integer i = 0, is = cell_info.nbNode(); i < is; ++i)
656 if (cell_info.nodeUniqueId(i) != cell2.node(i).uniqueId())
657 ARCANE_FATAL("trying to add existing cell (uid={0}) with different nodes",
658 cell_info.uniqueId());
659 }
660 return ItemCompatibility::_itemInternal(inew_cell);
661 }
662 }
663
664 Cell new_cell(inew_cell);
665
666 ++m_mesh_info.nbCell();
667
668 const MeshKind& mesh_kind = m_mesh->meshKind();
669 const bool allow_multi_dim_cell = !mesh_kind.isMonoDimension();
670 const Int32 cell_nb_face = cell_info.nbFace();
671 MutableItemBase mut_cell = new_cell.mutableItemBase();
672 if (cell_type_info->dimension() == 2 && cell_type_info->nbLocalFace() == 0)
673 mut_cell.addFlags(ItemFlags::II_HasEdgeFor1DItems);
674 mut_cell.setOwner(cell_info.owner(), m_mesh_info.rank());
675 // Vérifie la cohérence entre le type local et la maille créée.
676 if (is_check) {
677 if (cell_info.nbNode() != inew_cell.nbNode())
678 ARCANE_FATAL("Incoherent number of nodes v={0} expected={1}", inew_cell.nbNode(), cell_info.nbNode());
679 if (cell_nb_face != inew_cell.nbFace())
680 ARCANE_FATAL("Incoherent number of faces v={0} expected={1}", inew_cell.nbFace(), cell_nb_face);
681 if (!cell_type_info->isValidForCell())
682 ARCANE_FATAL("Type '{0}' is not allowed for 'Cell' (cell_uid={1})",
683 cell_type_info->typeName(), cell_info.uniqueId());
684 if (!allow_multi_dim_cell) {
685 Int32 cell_dimension = cell_type_info->dimension();
686 Int32 mesh_dimension = m_mesh->dimension();
687 if (cell_dimension >= 0 && cell_dimension != mesh_dimension)
688 ARCANE_FATAL("Incoherent dimension for cell uid={0} cell_dim={1} mesh_dim={2} type={3}",
689 cell_info.uniqueId(), cell_dimension, mesh_dimension, cell_type_info->typeName());
690 }
691 }
692
694 ItemInternalMap& nodes_map = m_node_family.itemsMap();
695
696 _addNodesToCell(inew_cell, cell_info);
697
698 if (m_mesh_builder->hasEdge()) {
699 const Int32 cell_nb_edge = cell_info.nbEdge();
700 // Adds the necessary edges.
701 for (Integer i_edge = 0; i_edge < cell_nb_edge; ++i_edge) {
702 const ItemTypeInfo::LocalEdge& le = cell_type_info->localEdge(i_edge);
703 Int64 first_node = cell_info.nodeUniqueId(le.beginNode());
704 Int64 second_node = cell_info.nodeUniqueId(le.endNode());
705 if (first_node > second_node)
706 std::swap(first_node, second_node);
707
708 bool is_add = false;
709 Edge edge_internal = _findInternalEdge(i_edge, cell_info, first_node, second_node, is_add);
710 if (is_add) {
711 if (is_verbose)
712 info() << "Create edge " << edge_internal.uniqueId() << ' ' << edge_internal.localId();
713
714 edge_internal.mutableItemBase().setOwner(cell_info.edgeOwner(i_edge), m_mesh_info.rank());
715 {
716 Node current_node = nodes_map.findItem(first_node);
717 m_edge_family.replaceNode(ItemLocalId(edge_internal), 0, current_node);
718 m_node_family.addEdgeToNode(current_node, edge_internal);
719 }
720 {
721 Node current_node = nodes_map.findItem(second_node);
722 m_edge_family.replaceNode(ItemLocalId(edge_internal), 1, current_node);
723 m_node_family.addEdgeToNode(current_node, edge_internal);
724 }
725 ++m_mesh_info.nbEdge();
726 }
727
728 m_cell_family.replaceEdge(ItemLocalId(new_cell), i_edge, ItemLocalId(edge_internal));
729 m_edge_family.addCellToEdge(edge_internal, inew_cell);
730 }
731 }
732
733 // Adds the necessary faces.
734 for (Integer i_face = 0; i_face < cell_nb_face; ++i_face) {
735 const ItemTypeInfo::LocalFace& lf = cell_type_info->localFace(i_face);
736 const Integer face_nb_node = lf.nbNode();
737 // en effet de bord, _isReorder positionne m_face_reorderer.sortedNodes();
738 const bool is_reorder = _isReorder(i_face, lf, cell_info);
739 ConstArrayView<Int64> face_sorted_nodes = m_face_reorderer.sortedNodes();
740 bool is_add = false;
741 Face face = _findInternalFace(i_face, cell_info, is_add);
742 if (is_add) {
743 // For elements of order greater than 1, faces are added to the nodes
744 // corresponding to the associated order 1 (linear) element.
745 const ItemTypeInfo* face_type_info = m_item_type_mng->typeFromId(lf.typeId());
746 const Int32 face_nb_linear_node = face_type_info->linearTypeInfo()->nbLocalNode();
747 if (is_verbose) {
748 info() << "AddFaceToCell (cell_uid=" << new_cell.uniqueId() << ": Create face (index=" << i_face
749 << ") uid=" << face.uniqueId()
750 << " lid=" << face.localId()
751 << " type=" << face_type_info->typeName()
752 << " face_nb_linear_node=" << face_nb_linear_node
753 << " sorted_nodes=" << face_sorted_nodes;
754 }
755 face.mutableItemBase().setOwner(cell_info.faceOwner(i_face), m_mesh_info.rank());
756
757 for (Integer i_node = 0; i_node < face_nb_node; ++i_node) {
758 if (is_verbose)
759 info() << "AddNodeToFace i_node=" << i_node << " uid=" << face_sorted_nodes[i_node];
760 Node current_node = nodes_map.findItem(face_sorted_nodes[i_node]);
761 m_face_family.replaceNode(face, i_node, current_node);
762 if (i_node < face_nb_linear_node) {
763 m_node_family.addFaceToNode(current_node, face);
764 }
765 }
766
767 if (m_mesh_builder->hasEdge()) {
768 Integer face_nb_edge = lf.nbEdge();
769 for (Integer i_edge = 0; i_edge < face_nb_edge; ++i_edge) {
770 Edge current_edge = new_cell.edge(lf.edge(i_edge));
771 m_face_family.addEdgeToFace(face, current_edge);
772 m_edge_family.addFaceToEdge(current_edge, face);
773 }
774 }
775 ++m_mesh_info.nbFace();
776 }
777 m_cell_family.replaceFace(new_cell, i_face, face);
778
780 if (m_mesh->isAmrActivated()) {
781 if (is_reorder) {
782 if (face.nbCell() == 2)
783 m_face_family.replaceFrontCellToFace(face, new_cell);
784 else
785 m_face_family.addFrontCellToFace(face, inew_cell);
786 }
787 else {
788 if (face.nbCell() == 2)
789 m_face_family.replaceBackCellToFace(face, new_cell);
790 else
791 m_face_family.addBackCellToFace(face, inew_cell);
792 }
793 }
794 else {
795 if (is_reorder) {
796 m_face_family.addFrontCellToFace(face, inew_cell);
797 }
798 else {
799 m_face_family.addBackCellToFace(face, inew_cell);
800 }
801 }
802 }
803
804 _AMR_Patch(inew_cell, cell_info);
805 return ItemCompatibility::_itemInternal(inew_cell);
806}
807
808/*---------------------------------------------------------------------------*/
809/*---------------------------------------------------------------------------*/
826addOneParentItem(const Item& item, const eItemKind submesh_kind, const bool fatal_on_existing_item)
827{
828 //bool is_check = arcaneIsCheck();
829 ItemTypeMng* itm = m_mesh->itemTypeMng();
830 eItemKind kind = item.kind();
831 ItemTypeInfo* type = itm->typeFromId(item.type());
832
833 if (item.type() == IT_Line2 && submesh_kind == IK_Cell)
834 type = itm->typeFromId(IT_CellLine2);
835 if (item.type() == IT_Vertex && submesh_kind == IK_Face)
836 type = itm->typeFromId(IT_FaceVertex);
837 ItemTypeId type_id = type->itemTypeId();
838
839 if (MeshToMeshTransposer::kindTranspose(submesh_kind, m_mesh, m_mesh->parentMesh()) != kind)
840 ARCANE_FATAL("Incompatible kind/sub-kind");
841
842 // Checks if the cell already exists
843 bool is_add; // this flag is always correctly set via findOrAllocOne
844 Item new_item;
845
846 switch (submesh_kind) {
847 case IK_Node:
848 new_item = m_node_family.findOrAllocOne(item.uniqueId(), is_add);
849 ++m_mesh_info.nbNode();
850 break;
851 case IK_Edge:
852 new_item = m_edge_family.findOrAllocOne(item.uniqueId(), is_add);
853 ++m_mesh_info.nbEdge();
854 break;
855 case IK_Face:
856 new_item = m_face_family.findOrAllocOne(item.uniqueId(), type, is_add);
857 ++m_mesh_info.nbFace();
858 break;
859 case IK_Cell:
860 if (kind == IK_Face && !(item.toFace().isSubDomainBoundary()))
861 ARCANE_FATAL("Bad boundary face");
862 new_item = m_cell_family.findOrAllocOne(item.uniqueId(), type_id, is_add);
863 ++m_mesh_info.nbCell();
864 break;
865 default:
866 throw NotSupportedException(A_FUNCINFO, String::format("Kind {0} not supported", submesh_kind));
867 }
868
869 if (!is_add) {
870 if (fatal_on_existing_item)
871 ARCANE_FATAL("Cannot add already existing parent item in submesh");
872 else
873 return ItemCompatibility::_itemInternal(new_item);
874 }
875
876 new_item.mutableItemBase().setParent(0, item.localId());
877 new_item.mutableItemBase().setOwner(item.owner(), m_mesh_info.rank());
878
879 // Localizes these sub-items relative to the item to be inserted
880 // By default everything is 0, which also corresponds to the submesh_kind==IK_Node case
881 Integer item_nb_node = 0;
882 Integer item_nb_face = 0;
883 Integer item_nb_edge = 0;
884
885 switch (submesh_kind) {
886 case IK_Cell:
887 item_nb_face = type->nbLocalFace();
888 item_nb_edge = type->nbLocalEdge();
889 item_nb_node = type->nbLocalNode();
890 break;
891 case IK_Face:
892 item_nb_edge = type->nbLocalEdge();
893 item_nb_node = type->nbLocalNode();
894 break;
895 case IK_Edge:
896 item_nb_node = type->nbLocalNode();
897 default: // les autres sont déjà filtrés avant
898 break;
899 }
900
901 // Handling the case of edge deactivation
902 if (!m_mesh_builder->hasEdge())
903 item_nb_edge = 0;
904
905#if OLD
906 // Ne fonctionne plus si on désactive les anciennes connectivités
907 if (is_check) {
908 for (Integer z = 0; z < item_nb_face; ++z)
909 new_item->_setFace(z, NULL_ITEM_ID);
910 for (Integer z = 0; z < item_nb_edge; ++z)
911 new_item->_setEdge(z, NULL_ITEM_ID);
912 for (Integer z = 0; z < item_nb_node; ++z)
913 new_item->_setNode(z, NULL_ITEM_ID);
914 }
915#endif
916
918 DynamicMeshKindInfos::ItemInternalMap& nodes_map = m_mesh->nodesMap();
919 auto* parent_mesh = ARCANE_CHECK_POINTER(dynamic_cast<DynamicMesh*>(m_mesh->parentMesh()));
920 DynamicMeshKindInfos::ItemInternalMap& parent_nodes_map = parent_mesh->nodesMap();
921
922 // Processing new nodes
923
924 // The vertices are used in the item order except for surface submeshes.
925 const bool direct_node_order =
926 !(submesh_kind == IK_Cell && kind == IK_Face && !(item.toFace().isSubDomainBoundaryOutside()));
927
928 Int64UniqueArray nodes_uid(item_nb_node, NULL_ITEM_UNIQUE_ID);
929 for (Integer i_node = 0; i_node < item_nb_node; ++i_node) {
930 Item parent_item;
931 if (type->typeId() == IT_FaceVertex)
932 parent_item = item;
933 else {
934 Int32 idx = ((direct_node_order) ? i_node : (item_nb_node - 1 - i_node));
935 parent_item = item.toItemWithNodes().node(idx);
936 }
937 Int64 new_node_uid = nodes_uid[i_node] = parent_item.uniqueId();
938 ItemInternal* node_internal = m_node_family.findOrAllocOne(new_node_uid, is_add);
939 if (is_add) {
940#ifdef ARCANE_DEBUG_DYNAMIC_MESH
941 info() << "Création node " << new_node_uid << ' '
942 << node_internal->uniqueId() << ' ' << node_internal->localId();
943#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
944 node_internal->setParent(0, parent_item.localId());
945 node_internal->setOwner(parent_item.owner(), m_mesh_info.rank());
946 ++m_mesh_info.nbNode();
947 }
948
949 // Connecting the item to the nodes
950 ItemLocalId node_lid(node_internal);
951 ItemLocalId new_item_lid(new_item);
952 switch (submesh_kind) {
953 case IK_Cell:
954 m_cell_family.replaceNode(new_item_lid, i_node, node_lid);
955 m_node_family.addCellToNode(node_internal, new_item.toCell());
956 break;
957 case IK_Face:
958 m_face_family.replaceNode(new_item_lid, i_node, node_lid);
959 m_node_family.addFaceToNode(node_internal, new_item.toFace());
960 break;
961 case IK_Edge:
962 m_edge_family.replaceNode(new_item_lid, i_node, node_lid);
963 m_node_family.addEdgeToNode(node_internal, new_item.toEdge());
964 break;
965 default: // les autres sont déjà filtrés avant
966 break;
967 }
968 }
969
970 // Processing new edges (the has_edge filter is already taken into account in item_nb_edge)
971 for (Integer i_edge = 0; i_edge < item_nb_edge; ++i_edge) {
972 const ItemTypeInfo::LocalEdge& le = type->localEdge(i_edge);
973
974 Int64 first_node = nodes_uid[le.beginNode()];
975 Int64 second_node = nodes_uid[le.endNode()];
976 if (first_node > second_node)
977 std::swap(first_node, second_node);
978
979 Edge parent_item = item.itemBase().edgeBase(i_edge);
980 if (parent_item.null())
981 ARCANE_FATAL("Cannot find parent edge");
982
983 Int64 new_edge_uid = parent_item.uniqueId();
984
985 ItemInternal* edge_internal = m_edge_family.findOrAllocOne(new_edge_uid, is_add);
986 if (is_add) {
987#ifdef ARCANE_DEBUG_DYNAMIC_MESH
988 info() << "Création edge " << new_edge_uid << ' '
989 << edge_internal->uniqueId() << ' ' << edge_internal->localId();
990#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
991 edge_internal->setParent(0, parent_item.localId());
992 edge_internal->setOwner(parent_item.owner(), m_mesh_info.rank());
993
994 {
995 Node current_node = nodes_map.findItem(first_node);
996 m_edge_family.replaceNode(ItemLocalId(edge_internal), 0, current_node);
997 m_node_family.addEdgeToNode(current_node, edge_internal);
998 }
999 {
1000 Node current_node = nodes_map.findItem(second_node);
1001 m_edge_family.replaceNode(ItemLocalId(edge_internal), 1, current_node);
1002 m_node_family.addEdgeToNode(current_node, edge_internal);
1003 }
1004 ++m_mesh_info.nbEdge();
1005 }
1006
1007 // Connecting the item to the nodes
1008 switch (submesh_kind) {
1009 case IK_Cell: {
1010 m_cell_family.replaceEdge(ItemLocalId(new_item), i_edge, ItemLocalId(edge_internal));
1011 m_edge_family.addCellToEdge(edge_internal, new_item.toCell());
1012 } break;
1013 case IK_Face: {
1014 m_face_family.replaceEdge(ItemLocalId(new_item), i_edge, ItemLocalId(edge_internal));
1015 m_edge_family.addFaceToEdge(edge_internal, new_item.toFace());
1016 } break;
1017 default: // les autres sont déjà filtrés avant
1018 break;
1019 }
1020 }
1021
1022 // Processing new faces
1023 // item_nb_face already materializes that this context only occurs with submesh_kind==IK_Cell
1024 for (Integer i_face = 0; i_face < item_nb_face; ++i_face) {
1025 const ItemTypeInfo::LocalFace& lf = type->localFace(i_face);
1026 Integer face_nb_node = lf.nbNode();
1027
1028 m_work_face_orig_nodes_uid.resize(face_nb_node);
1029 for (Integer z = 0; z < face_nb_node; ++z)
1030 m_work_face_orig_nodes_uid[z] = nodes_uid[lf.node(z)];
1031 bool is_reorder = false;
1032 if (m_mesh->dimension() == 1) { // is 1d mesh
1033 is_reorder = m_face_reorderer.reorder1D(i_face, m_work_face_orig_nodes_uid[0]);
1034 }
1035 else {
1036 is_reorder = m_face_reorderer.reorder(ItemTypeId::fromInteger(lf.typeId()), m_work_face_orig_nodes_uid);
1037 }
1038 ConstArrayView<Int64> face_sorted_nodes(m_face_reorderer.sortedNodes());
1039 // find parent item
1040 Item parent_item;
1041 if (kind == IK_Cell) {
1042 parent_item = item.toCell().face(i_face);
1043 }
1044 else if (kind == IK_Face) {
1045 if (m_mesh->dimension() == 1) { // is 1d mesh
1046 parent_item = parent_nodes_map.findItem(face_sorted_nodes[0]);
1047 }
1048 else {
1049 // Algo sans CT_FaceToEdge
1050 Int64 first_node = face_sorted_nodes[0];
1051 Int64 second_node = face_sorted_nodes[1];
1052 if (first_node > second_node)
1053 std::swap(first_node, second_node);
1054 Node nbi = parent_nodes_map.findItem(first_node);
1055 parent_item = ItemTools::findEdgeInNode2(nbi, first_node, second_node);
1056 }
1057 }
1058
1059 if (parent_item.null())
1060 ARCANE_FATAL("Cannot find parent face");
1061 Int64 new_face_uid = parent_item.uniqueId();
1062 ItemTypeInfo* face_type = itm->typeFromId(lf.typeId());
1063
1064 ItemInternal* face_internal = m_face_family.findOrAllocOne(new_face_uid, face_type, is_add);
1065 if (is_add) {
1066#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1067 info() << "Création face " << new_face_uid << ' '
1068 << face_internal->uniqueId() << ' ' << face_internal->localId();
1069#endif /* ARCANE_DEBUG_DYNAMIC_MESH */
1070 face_internal->setParent(0, parent_item.localId());
1071 face_internal->setOwner(parent_item.owner(), m_mesh_info.rank());
1072
1073 for (Integer i_node = 0; i_node < face_nb_node; ++i_node) {
1074 Node current_node = nodes_map.findItem(face_sorted_nodes[i_node]);
1075 m_face_family.replaceNode(ItemLocalId(face_internal), i_node, current_node);
1076 m_node_family.addFaceToNode(current_node, face_internal);
1077 }
1078
1079 if (m_mesh_builder->hasEdge()) {
1080 Integer face_nb_edge = lf.nbEdge();
1081 for (Integer i_edge = 0; i_edge < face_nb_edge; ++i_edge) {
1082 Int32 edge_idx = lf.edge(i_edge);
1083 Edge current_edge = new_item.itemBase().edgeBase(edge_idx);
1084 m_face_family.addEdgeToFace(face_internal, current_edge);
1085 m_edge_family.addFaceToEdge(current_edge, face_internal);
1086 }
1087 }
1088 ++m_mesh_info.nbFace();
1089 }
1090 m_cell_family.replaceFace(ItemLocalId(new_item), i_face, ItemLocalId(face_internal));
1091 if (is_reorder) {
1092 m_face_family.addFrontCellToFace(face_internal, new_item.toCell());
1093 }
1094 else {
1095 m_face_family.addBackCellToFace(face_internal, new_item.toCell());
1096 }
1097 }
1098
1099 return ItemCompatibility::_itemInternal(new_item);
1100}
1101
1102/*---------------------------------------------------------------------------*/
1103/*---------------------------------------------------------------------------*/
1104
1108template <typename CellInfo>
1110_addNodesToCell(Cell cell, const CellInfo& cell_info)
1111{
1112 Integer cell_nb_node = cell_info.nbNode();
1113
1114 // Adds new nodes if necessary
1115 for (Integer i_node = 0; i_node < cell_nb_node; ++i_node) {
1116 Int64 node_unique_id = cell_info.nodeUniqueId(i_node);
1117 bool is_add = false;
1118 ItemInternal* node_internal = m_node_family.findOrAllocOne(node_unique_id, is_add);
1119 if (is_add) {
1120 ++m_mesh_info.nbNode();
1121 node_internal->setOwner(cell_info.nodeOwner(i_node), m_mesh_info.rank());
1122 }
1123 m_node_family.addCellToNode(node_internal, cell);
1124 m_cell_family.replaceNode(cell, i_node, ItemLocalId(node_internal));
1125 }
1126}
1127
1128/*---------------------------------------------------------------------------*/
1129/*---------------------------------------------------------------------------*/
1130
1131template <typename CellInfo>
1132bool OneMeshItemAdder::
1133_isReorder(Integer i_face, const ItemTypeInfo::LocalFace& lf, const CellInfo& cell_info)
1134{
1135 const Integer face_nb_node = lf.nbNode();
1136 m_work_face_orig_nodes_uid.resize(face_nb_node);
1137 for (Integer i_node = 0; i_node < face_nb_node; ++i_node)
1138 m_work_face_orig_nodes_uid[i_node] = cell_info.nodeUniqueId(lf.node(i_node));
1139 bool is_reorder = false;
1140 if (m_mesh->dimension() == 1) { // is 1d mesh
1141 is_reorder = m_face_reorderer.reorder1D(i_face, m_work_face_orig_nodes_uid[0]);
1142 }
1143 else {
1144 is_reorder = m_face_reorderer.reorder(ItemTypeId::fromInteger(lf.typeId()), m_work_face_orig_nodes_uid);
1145 }
1146
1147 return is_reorder;
1148}
1149
1150/*---------------------------------------------------------------------------*/
1151/*---------------------------------------------------------------------------*/
1152
1156{
1157 m_next_face_uid = 0;
1158 m_next_edge_uid = 0;
1159 m_mesh_info.reset();
1160}
1161
1162/*---------------------------------------------------------------------------*/
1163/*---------------------------------------------------------------------------*/
1164
1167{
1168 if (m_next_face_uid != 0 || m_next_edge_uid != 0)
1169 ARCANE_FATAL("Can not call this method when edge or face are already created");
1171 info() << "Is Generate Edge and Face uniqueId() from Nodes=" << m_use_hash_for_edge_and_face_unique_id;
1172}
1173
1174/*---------------------------------------------------------------------------*/
1175/*---------------------------------------------------------------------------*/
1176
1177} // End namespace Arcane::mesh
1178
1179/*---------------------------------------------------------------------------*/
1180/*---------------------------------------------------------------------------*/
#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.
void resize(Int64 s)
Changes the number of elements in the array to s.
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:83
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:66
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
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.
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.
ItemInternal * addOneCell(ItemTypeId type_id, Int64 cell_uid, Int32 sub_domain_id, Int64ConstArrayView nodes_uid, bool allow_build_face)
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:339
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:480
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
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::int32_t Int32
Signed integer type of 32 bits.