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