Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
PolyhedralMesh.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/* PolyhedralMesh.cc (C) 2000-2026 */
9/* */
10/* Polyhedral mesh implementation using Neo data structure. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include <memory>
15
16#include "arcane/mesh/PolyhedralMesh.h"
17
18#include "ItemFamilyNetwork.h"
19#include "ItemFamilyPolicyMng.h"
20#include "arcane/mesh/MeshExchangeMng.h"
21#include "arcane/core/ISubDomain.h"
22#include "arcane/core/ItemSharedInfo.h"
23#include "arcane/core/ItemTypeInfo.h"
24#include "arcane/core/ItemTypeMng.h"
25#include "arcane/core/VariableBuildInfo.h"
26#include "arcane/core/MeshBuildInfo.h"
28#include "arcane/core/AbstractService.h"
29#include "arcane/core/CommonVariables.h"
30#include "arcane/core/IMeshFactory.h"
31#include "arcane/core/ItemInternal.h"
32#include "arcane/core/IDoFFamily.h"
33#include "arcane/core/IMeshCompactMng.h"
34#include "arcane/core/IMeshCompacter.h"
35#include "arcane/core/IMeshExchanger.h"
36#include "arcane/core/IGhostLayerMng.h"
37#include "arcane/core/MeshVisitor.h"
38#include "arcane/core/internal/IItemFamilyInternal.h"
39#include "arcane/core/internal/IItemFamilySerializerMngInternal.h"
40#include "arcane/core/internal/IVariableMngInternal.h"
41#include "arcane/core/internal/IPolyhedralMeshModifier.h"
42#include "arcane/core/internal/IMeshModifierInternal.h"
43#include "arcane/core/Connectivity.h"
44
45#include "arcane/mesh/ItemFamily.h"
46#include "arcane/mesh/DynamicMeshKindInfos.h"
47#include "arcane/mesh/UnstructuredMeshUtilities.h"
48#include "arcane/mesh/GhostLayerMng.h"
49#include "arcane/utils/ITraceMng.h"
50#include "arcane/utils/FatalErrorException.h"
51#include "arccore/base/StringBuilder.h"
52
53#ifdef ARCANE_HAS_POLYHEDRAL_MESH_TOOLS
54
55#include "arcane/core/IMeshMng.h"
56#include "arcane/core/MeshHandle.h"
57#include "arcane/core/IItemFamily.h"
58#include "arcane/core/internal/IMeshInternal.h"
59#include "arcane/core/IVariableSynchronizer.h"
60#include "arcane/mesh/ItemFamilyPolicyMng.h"
61#include "arcane/mesh/ItemFamilySerializer.h"
62#include "arcane/utils/Collection.h"
63#include "arcane/utils/List.h"
64#include "arcane/utils/PlatformUtils.h"
65
66#include "neo/Mesh.h"
67#include "neo/Utils.h"
68
69#include "arcane/mesh/ItemConnectivityMng.h"
70#include "arcane/core/ItemPrinter.h"
71#include "arcane/mesh/FaceFamily.h"
72
73#endif
74
75// #define ARCANE_DEBUG_POLYHEDRAL_MESH
76#define ARCANE_DEBUG_LOAD_BALANCING
77
78#ifdef ARCANE_DEBUG_LOAD_BALANCING
79static bool arcane_debug_load_balancing = true;
80#else
81static bool arcane_debug_load_balancing = false;
82#endif
83
84/*---------------------------------------------------------------------------*/
85/*---------------------------------------------------------------------------*/
86
87void Arcane::mesh::PolyhedralMesh::
88_errorEmptyMesh() const
89{
90 ARCANE_FATAL("Cannot use PolyhedralMesh if Arcane is not linked with lib Neo");
91}
92
93/*---------------------------------------------------------------------------*/
94/*---------------------------------------------------------------------------*/
95
96#ifdef ARCANE_HAS_POLYHEDRAL_MESH_TOOLS
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101namespace Arcane::mesh
102{
103namespace PolyhedralTools
104{
105 class ItemLocalIds
106 {
107 Neo::FutureItemRange m_future_items;
108 std::shared_ptr<Neo::EndOfMeshUpdate> m_mesh_state = nullptr;
109
110 public:
111
112 void fillArrayView(Int32ArrayView local_ids, Neo::EndOfMeshUpdate mesh_state)
113 {
114 auto lids = m_future_items.get(mesh_state);
115 if (local_ids.size() != lids.size())
116 ARCANE_FATAL("Cannot fill local_ids view, its size {0} != {1} (added item size)", local_ids.size(), m_future_items.size());
117 std::copy(lids.begin(), lids.end(), local_ids.begin());
118 }
119
120 void fillArrayView(Int32ArrayView local_ids)
121 {
122 ARCANE_CHECK_POINTER2(m_mesh_state.get(), "PolyhedralTools::ItemLocalIds must have a valid end of mesh state");
123 fillArrayView(local_ids, *m_mesh_state);
124 }
125
126 Integer size() const noexcept { return m_future_items.size(); }
127 bool isFilled() const noexcept { return m_mesh_state.get() != nullptr; };
128 void checkIsFilled(String error_message) const noexcept
129 {
130 if (!isFilled())
131 ARCANE_FATAL("Item local ids are not filled." + error_message);
132 }
133 friend class mesh::PolyhedralMeshImpl;
134 friend class mesh::PolyhedralMesh;
135 };
136} // namespace PolyhedralTools
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
140
141class PolyhedralFamilySerializer;
142class PolyhedralFamilySerializerMng : public IItemFamilySerializerMngInternal
143{
144 PolyhedralMesh* m_mesh = nullptr;
145 Integer m_nb_serializers = 0;
146 UniqueArray<PolyhedralFamilySerializer*> m_serializers;
147
148 public:
149
150 explicit PolyhedralFamilySerializerMng(PolyhedralMesh* mesh)
151 : m_mesh(mesh)
152 {
153 ARCANE_CHECK_POINTER2(mesh, "Must give a non null PolyhedralMesh pointer.");
154 }
155
156 void addSerializer(PolyhedralFamilySerializer* serializer)
157 {
158 m_serializers.push_back(serializer);
159 ++m_nb_serializers;
160 }
161
162 void finalizeItemAllocation() override;
163};
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
167
168class PolyhedralFamilySerializer : public IItemFamilySerializer
169{
170 private:
171
172 PolyhedralMesh* m_mesh = nullptr;
173 IItemFamily* m_family = nullptr;
174 PolyhedralFamilySerializerMng* m_mng = nullptr;
175 ItemData m_item_data;
176 UniqueArray<Int32Array*> m_deserialized_lids_array;
177 UniqueArray<std::shared_ptr<PolyhedralTools::ItemLocalIds>> m_future_item_lids_array;
178 ItemAllocationInfo::FamilyInfo m_family_info;
179
180 public:
181
182 explicit PolyhedralFamilySerializer(PolyhedralMesh* mesh, IItemFamily* family, PolyhedralFamilySerializerMng* mng)
183 : m_mesh(mesh)
184 , m_family(family)
185 , m_mng(mng)
186 {}
187
188 PolyhedralFamilySerializer(const PolyhedralFamilySerializer&) = delete;
189 PolyhedralFamilySerializer& operator=(const PolyhedralFamilySerializer&) = delete;
190
191 ArrayView<std::shared_ptr<PolyhedralTools::ItemLocalIds>> itemLidsArray() { return m_future_item_lids_array.view(); }
192
193 public:
194
195 void serializeItems(ISerializer* buf, Int32ConstArrayView items_local_ids) override;
196 void deserializeItems(ISerializer* buf, Int32Array* items_local_ids) override;
197
198 void clear()
199 {
200 m_item_data.clear();
201 m_deserialized_lids_array.clear();
202 m_future_item_lids_array.clear();
203 m_family_info.clear();
204 }
205
206 void fillDeserializedLocalIds()
207 {
208 auto index = 0;
209 for (auto item_lids_array : m_deserialized_lids_array) {
210 auto& future_item_lids = m_future_item_lids_array[index];
211 future_item_lids->checkIsFilled("Cannot fill deserialized local ids, future item local ids are not filled.");
212 item_lids_array->resize(future_item_lids->size());
213 future_item_lids->fillArrayView(item_lids_array->view());
214 ++index;
215 }
216 clear();
217 }
218
219 IItemFamilySerializerMngInternal* mng()
220 {
221 return m_mng;
222 }
223
224 // no need to distinguish between dependency or relation in Neo graph
225 void serializeItemRelations(ISerializer*, Int32ConstArrayView) override {}
226 void deserializeItemRelations(ISerializer*, Int32Array*) override {}
227
228 private:
229
230 void _fillItemData(Int32ConstArrayView items_local_ids);
231 void _fillItemFamilyInfo(const ItemData& item_data,
232 StringConstArrayView connected_family_names,
233 StringConstArrayView connectivity_names)
234 {
235 // clear data
236 m_family_info.clear();
237 // Check info in ItemData
238 if (m_family != item_data.itemFamily())
239 ARCANE_FATAL("PolyhedralFamilySerializer: Family mismatch. Synchronized family is {0} and serialized family is {1}",
240 m_family->name(), item_data.itemFamily()->name());
241 m_family_info.name = item_data.itemFamily()->name();
242 m_family_info.item_kind = item_data.itemFamily()->itemKind();
243 auto& connected_family_infos = m_family_info.connected_family_infos;
244 auto nb_connected_family = item_data.itemInfos()[0];
245 connected_family_infos.resize(nb_connected_family);
246 auto& item_uids = m_family_info._item_uids_data;
247 item_uids.reserve(item_data.nbItems());
248 auto item_infos = item_data.itemInfos();
249 for (auto connected_family_info : connected_family_infos) {
250 connected_family_info._connected_items_uids_data.reserve(4 * item_uids.size());
251 connected_family_info._nb_connected_items_per_item_data.reserve(item_uids.size());
252 }
253 for (auto index = 1; index < item_infos.size();) {
254 item_uids.push_back(item_infos[index + 1]); // first index is item type, not used in polyhedral
255 index += 2;
256 for (auto connected_family_index = 0; connected_family_index < nb_connected_family; ++connected_family_index) {
257 eItemKind family_kind = static_cast<eItemKind>(item_infos[index]);
258 auto* connected_family = m_mesh->findItemFamily(family_kind, connected_family_names[connected_family_index], false, false);
259 ARCANE_CHECK_POINTER(connected_family);
260 auto& current_connected_family_infos = connected_family_infos[connected_family_index];
261 current_connected_family_infos.item_kind = family_kind;
262 current_connected_family_infos.name = connected_family->name();
263 current_connected_family_infos.connectivity_name = connectivity_names[connected_family_index];
264 ++index;
265 auto nb_connected_items = static_cast<Int32>(item_infos[index]);
266 ++index;
267 current_connected_family_infos._nb_connected_items_per_item_data.push_back(nb_connected_items);
268 auto real_nb_connected_items = nb_connected_items;
269 if (m_family->itemKind() == IK_Face && connected_family->itemKind() == IK_Cell)
270 real_nb_connected_items = 2; // 2 cells are stored, even if one is null (boundary)
271 current_connected_family_infos._connected_items_uids_data.addRange(item_infos.subView(index, real_nb_connected_items));
272 index += real_nb_connected_items;
273 }
274 }
275 // Update FamilyInfo views
276 m_family_info.updateViewsFromInternalData();
277 // get owners
278 m_family_info.item_owners = item_data.itemOwners();
279 }
280
281 IItemFamily* family() const override
282 {
283 return m_family;
284 }
285};
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290void PolyhedralFamilySerializerMng::
291finalizeItemAllocation()
292{
293 UniqueArray<std::shared_ptr<PolyhedralTools::ItemLocalIds>> future_item_lids;
294 for (auto family_serializer : m_serializers) {
295 for (auto& item_lids : family_serializer->itemLidsArray()) {
296 future_item_lids.push_back(item_lids);
297 }
298 }
299 m_mesh->applyScheduledAllocateItems(future_item_lids);
300 for (auto family_serializer : m_serializers) {
301 family_serializer->fillDeserializedLocalIds();
302 }
303 m_serializers.clear();
304}
305
306/*---------------------------------------------------------------------------*/
307/*---------------------------------------------------------------------------*/
308
309class PolyhedralFamilyPolicyMng
310: public ItemFamilyPolicyMng
311{
312 public:
313
314 PolyhedralFamilyPolicyMng(PolyhedralMesh* mesh, ItemFamily* family)
315 : ItemFamilyPolicyMng(family)
316 , m_mesh(mesh)
317 , m_family(family)
318 {}
319
320 public:
321
322 IItemFamilySerializer* createSerializer(bool) override
323 {
324 return new PolyhedralFamilySerializer(m_mesh, m_family, m_mesh->polyhedralFamilySerializerMng());
325 }
326
327 private:
328
329 PolyhedralMesh* m_mesh = nullptr;
330 ItemFamily* m_family = nullptr;
331};
332
333/*---------------------------------------------------------------------------*/
334/*---------------------------------------------------------------------------*/
335
336class PolyhedralFamily
337: public ItemFamily
338, public IDoFFamily
339{
340 ItemSharedInfoWithType* m_shared_info = nullptr;
341 Int32UniqueArray m_empty_connectivity{ 0 };
342 Int32UniqueArray m_empty_connectivity_indexes;
343 Int32UniqueArray m_empty_connectivity_nb_item;
344 PolyhedralMesh* m_mesh = nullptr;
345
346 public:
347
348 inline static const String m_arcane_item_lids_property_name{ "Arcane_Item_Lids" }; // inline used to initialize within the declaration
349 inline static const String m_arcane_remove_item_property_name{ "Arcane_Remove_Items" }; // inline used to initialize within the declaration
350
351 public:
352
353 PolyhedralFamily(PolyhedralMesh* mesh, eItemKind ik, String name)
354 : ItemFamily(mesh, ik, name)
355 , m_mesh(mesh)
356 {}
357
358 public:
359
360 void preAllocate(Integer nb_item)
361 {
362 Integer nb_hash = itemsMap().nbBucket();
363 Integer wanted_size = 2 * (nb_item + nbItem());
364 if (nb_hash < wanted_size)
365 itemsMap().resize(wanted_size, true);
366 m_empty_connectivity_indexes.resize(nb_item + nbItem(), 0);
367 m_empty_connectivity_nb_item.resize(nb_item + nbItem(), 0);
368 _updateEmptyConnectivity();
369 }
370
371 ItemInternal* _allocItem(const Int64 uid, const Int32 owner)
372 {
373 bool need_alloc; // given by alloc
374 ItemInternal* item_internal = ItemFamily::_findOrAllocOne(uid, need_alloc);
375 if (!need_alloc)
376 item_internal->setUniqueId(uid);
377 else {
378 _allocateInfos(item_internal, uid, m_shared_info);
379 }
380 item_internal->setOwner(owner, m_sub_domain_id);
381 return item_internal;
382 }
383
384 void addItems(Int64ConstSmallSpan uids, Int32ArrayView items)
385 {
386 Int32UniqueArray owners(uids.size(), m_sub_domain_id);
387 addItems(uids, items, owners);
388 }
389
390 void addItems(Int64ConstSmallSpan uids, Int32ArrayView items, Int32ConstArrayView owners)
391 {
392 if (uids.empty())
393 return;
394 ARCANE_ASSERT((uids.size() == items.size()), ("one must have items.size==uids.size()"));
395 preAllocate(uids.size());
396 auto index{ 0 };
397 for (auto uid : uids) {
398 ItemInternal* ii = _allocItem(uid, owners[index]);
399 items[index] = ii->localId();
400 ++index;
401 }
402 m_need_prepare_dump = true;
403 _updateItemInternalList();
404 }
405
406 void removeItems(Int32ConstArrayView local_ids)
407 {
408 _removeMany(local_ids);
409 }
410
411 void _updateItemInternalList()
412 {
413 switch (itemKind()) {
414 case IK_Cell:
415 m_item_internal_list->cells = _itemsInternal();
416 break;
417 case IK_Face:
418 m_item_internal_list->faces = _itemsInternal();
419 break;
420 case IK_Edge:
421 m_item_internal_list->edges = _itemsInternal();
422 break;
423 case IK_Node:
424 m_item_internal_list->nodes = _itemsInternal();
425 break;
426 case IK_DoF:
427 case IK_Particle:
428 case IK_Unknown:
429 break;
430 }
431 }
432
433 void _updateEmptyConnectivity()
434 {
435 auto item_internal_connectivity_list = itemInternalConnectivityList();
436 for (auto item_kind = 0; item_kind < ItemInternalConnectivityList::MAX_ITEM_KIND; ++item_kind) {
437 item_internal_connectivity_list->_setConnectivityList(item_kind, m_empty_connectivity);
438 item_internal_connectivity_list->_setConnectivityIndex(item_kind, m_empty_connectivity_indexes);
439 item_internal_connectivity_list->_setConnectivityNbItem(item_kind, m_empty_connectivity_nb_item);
440 }
441 }
442
443 // IItemFamily
444 IDoFFamily* toDoFFamily() override
445 {
446 return this;
447 }
448 // todo block all IItemFamily allocation methods
449
450 void build() override
451 {
452 ItemFamily::build();
453 m_sub_domain_id = subDomain()->subDomainId();
454 ItemTypeMng* itm = m_mesh->itemTypeMng();
455 ItemTypeInfo* dof_type_info = itm->typeFromId(IT_NullType);
456 m_shared_info = _findSharedInfo(dof_type_info);
457 _updateEmptyConnectivity();
458 ItemFamily::setPolicyMng(new PolyhedralFamilyPolicyMng{ m_mesh, this });
459 }
460
461 void addGhostItems(Int64ConstArrayView unique_ids, Int32ArrayView items, Int32ConstArrayView owners) override
462 {
463 auto* polyhedral_mesh_modifier = m_mesh->_internalApi()->polyhedralMeshModifier();
464 ARCANE_CHECK_POINTER(polyhedral_mesh_modifier);
465 polyhedral_mesh_modifier->addItems(unique_ids, items, owners, ItemFamily::itemKind(), name());
466 }
467
468 // IDoFFamily
469 String name() const override { return ItemFamily::name(); }
470 String fullName() const override { return ItemFamily::fullName(); }
471 Integer nbItem() const override { return ItemFamily::nbItem(); }
472 ItemGroup allItems() const override { return ItemFamily::allItems(); }
473 void endUpdate() override
474 {
475 return ItemFamily::endUpdate();
476 }
477 IItemFamily* itemFamily() override { return this; }
478
479 DoFVectorView addDoFs(Int64ConstArrayView dof_uids, Int32ArrayView dof_lids) override
480 {
481 auto* polyhedral_mesh_modifier = m_mesh->_internalApi()->polyhedralMeshModifier();
482 ARCANE_CHECK_POINTER(polyhedral_mesh_modifier);
483 polyhedral_mesh_modifier->addItems(dof_uids, dof_lids, ItemFamily::itemKind(), name());
484 return ItemFamily::view(dof_lids);
485 }
486
487 DoFVectorView addGhostDoFs(Int64ConstArrayView dof_uids, Int32ArrayView dof_lids,
488 Int32ConstArrayView owners) override
489 {
490 addGhostItems(dof_uids, dof_lids, owners);
491 return ItemFamily::view(dof_lids);
492 }
493
494 void removeDoFs(Int32ConstArrayView items_local_id) override
495 {
496 auto* mesh_modifier = m_mesh->_internalApi()->polyhedralMeshModifier();
497 mesh_modifier->removeItems(items_local_id, ItemFamily::itemKind(), m_name);
498 }
499};
500
501} // namespace Arcane::mesh
502/*---------------------------------------------------------------------------*/
503/*---------------------------------------------------------------------------*/
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
508namespace Arcane
509{
510
511/*---------------------------------------------------------------------------*/
512/*---------------------------------------------------------------------------*/
513
514namespace mesh
515{
516
517 /*---------------------------------------------------------------------------*/
518 /*---------------------------------------------------------------------------*/
519
521 {
522 ISubDomain* m_subdomain;
523 Neo::Mesh m_mesh{ "Test" };
524
525 template <eItemKind IK>
526 class ItemKindTraits
527 {
528 static const Neo::ItemKind item_kind = Neo::ItemKind::IK_None;
529 };
530
531 public:
532
533 static Neo::ItemKind itemKindArcaneToNeo(eItemKind ik)
534 {
535 switch (ik) {
536 case IK_Cell:
537 return Neo::ItemKind::IK_Cell;
538 case IK_Face:
539 return Neo::ItemKind::IK_Face;
540 case IK_Edge:
541 return Neo::ItemKind::IK_Edge;
542 case IK_Node:
543 return Neo::ItemKind::IK_Node;
544 case IK_DoF:
545 return Neo::ItemKind::IK_Dof;
546 case IK_Unknown:
547 case IK_Particle:
548 return Neo::ItemKind::IK_None;
549 }
550 return Neo::ItemKind::IK_Node;
551 }
552
553 static eItemKind itemKindNeoToArcane(Neo::ItemKind ik)
554 {
555 switch (ik) {
556 case Neo::ItemKind::IK_Cell:
557 return IK_Cell;
558 case Neo::ItemKind::IK_Face:
559 return IK_Face;
560 case Neo::ItemKind::IK_Edge:
561 return IK_Edge;
562 case Neo::ItemKind::IK_Node:
563 return IK_Node;
564 case Neo::ItemKind::IK_Dof:
565 return IK_DoF;
566 case Neo::ItemKind::IK_None:
567 return IK_Unknown;
568 }
569 return IK_Node;
570 }
571
572 public:
573
574 explicit PolyhedralMeshImpl(ISubDomain* subDomain)
575 : m_subdomain(subDomain)
576 , m_mesh(String::format(subDomain->defaultMeshHandle().meshName(), "Polyhedral").localstr(), subDomain->parallelMng()->commRank())
577 {}
578
579 public:
580
581 String name() const { return m_mesh.name(); }
582
583 Integer dimension() const { return m_mesh.dimension(); }
584
585 Integer nbNode() const { return m_mesh.nbNodes(); }
586 Integer nbEdge() const { return m_mesh.nbEdges(); }
587 Integer nbFace() const { return m_mesh.nbFaces(); }
588 Integer nbCell() const { return m_mesh.nbCells(); }
589 Integer nbItem(eItemKind ik) const { return m_mesh.nbItems(itemKindArcaneToNeo(ik)); }
590
591 SmallSpan<const Neo::Mesh::Connectivity> connectivities(IItemFamily* source_family)
592 {
593 auto& neo_source_family = m_mesh.findFamily(itemKindArcaneToNeo(source_family->itemKind()), source_family->name().localstr());
594 auto connectivities = m_mesh.getConnectivities(neo_source_family);
595 return { connectivities.begin(), connectivities.size() };
596 }
597
598 static void _setFaceInfos(Int32 mod_flags, Face& face)
599 {
600 Int32 face_flags = face.itemBase().flags();
601 face_flags &= ~ItemFlags::II_InterfaceFlags;
602 face_flags |= mod_flags;
603 face.mutableItemBase().setFlags(face_flags);
604 }
605
606 /*---------------------------------------------------------------------------*/
607
608 void addFamily(eItemKind ik, const String& name)
609 {
610 m_mesh.addFamily(itemKindArcaneToNeo(ik), name.localstr());
611 }
612
613 /*---------------------------------------------------------------------------*/
614
615 void scheduleAddItems(PolyhedralFamily* arcane_item_family,
617 PolyhedralTools::ItemLocalIds& item_local_ids)
618 {
619 scheduleAddItems(arcane_item_family, uids, Int32ConstSmallSpan{}, item_local_ids);
620 }
621
622 /*---------------------------------------------------------------------------*/
623
624 void scheduleAddItems(PolyhedralFamily* arcane_item_family,
626 Int32ConstSmallSpan owners,
627 PolyhedralTools::ItemLocalIds& item_local_ids)
628 {
629 auto& added_items = item_local_ids.m_future_items;
630 auto& item_family = m_mesh.findFamily(itemKindArcaneToNeo(arcane_item_family->itemKind()),
631 arcane_item_family->name().localstr());
632 m_mesh.scheduleAddItems(item_family, std::vector<Int64>{ uids.begin(), uids.end() }, added_items);
633 // add arcane items
634 auto& mesh_graph = m_mesh.internalMeshGraph();
635 item_family.addMeshScalarProperty<Neo::utils::Int32>(PolyhedralFamily::m_arcane_item_lids_property_name.localstr());
636 // copy uids and owners to send them to Neo
637 UniqueArray<Int64> uids_copy(uids);
638 UniqueArray<Int32> owners_copy(owners);
639 mesh_graph.addAlgorithm(Neo::MeshKernel::InProperty{ item_family, item_family.lidPropName() },
640 Neo::MeshKernel::OutProperty{ item_family, PolyhedralFamily::m_arcane_item_lids_property_name.localstr() },
641 "AddArcaneItems"+std::string{arcane_item_family->name().localstr()},
642 [arcane_item_family, uids_local=std::move(uids_copy), &added_items, owners_local=std::move(owners_copy)]
643 ([[maybe_unused]] Neo::ItemLidsProperty const& lids_property,
644 Neo::MeshScalarPropertyT<Neo::utils::Int32>&) {
645 auto new_items_lids{added_items.new_items.localIds()};
646 Int32ConstSpan neo_items{ new_items_lids.data(), static_cast<Int32>(new_items_lids.size()) };
647 UniqueArray<Int32> arcane_items(added_items.new_items.size());
648 if (owners_local.empty())
649 arcane_item_family->addItems(uids_local, arcane_items);
650 else
651 arcane_item_family->addItems(uids_local, arcane_items, Int32ConstArrayView{ owners_local.size(), owners_local.data() });
652 // debug check lid matching.
653 if (!arcane_items.size() == added_items.new_items.size())
654 arcane_item_family->traceMng()->fatal() << "Inconsistent item lids generation between Arcane and Neo, nb items Neo "
655 << added_items.new_items.size() << " nb items Arcane " << arcane_items.size();
656 if (!std::equal(added_items.new_items.begin(), added_items.new_items.end(), arcane_items.begin())) {
657 arcane_item_family->traceMng()->info() << "Arcane Items " << arcane_items;
658 std::cout << "Neo Items ";
659 std::ranges::copy(neo_items,std::ostream_iterator<int>(std::cout," "));
660 std::cout << "\n";
661 arcane_item_family->traceMng()->fatal() << "Inconsistent item lids generation between Arcane and Neo in ItemFamily " << arcane_item_family->name();
662 }
663 });
664 }
665
666 /*---------------------------------------------------------------------------*/
667
668 void scheduleRemoveItems(PolyhedralFamily* arcane_item_family,
669 Int32ConstArrayView local_ids)
670 {
671 auto& item_family = m_mesh.findFamily(itemKindArcaneToNeo(arcane_item_family->itemKind()),
672 arcane_item_family->name().localstr());
673 Neo::ItemRange removed_items{ Neo::ItemLocalIds{ { local_ids.begin(), local_ids.end() }, 0, 0 } };
674 m_mesh.scheduleRemoveItems(item_family, removed_items);
675 // Remove Arcane items
676 auto& mesh_graph = m_mesh.internalMeshGraph();
677 item_family.addMeshScalarProperty<Neo::utils::Int32>(PolyhedralFamily::m_arcane_remove_item_property_name.localstr());
678 mesh_graph.addAlgorithm(Neo::MeshKernel::InProperty{ item_family, m_mesh._removeItemPropertyName(item_family) },
679 Neo::MeshKernel::OutProperty{ item_family, PolyhedralFamily::m_arcane_remove_item_property_name.localstr() },
680 "RemoveArcaneFamily"+std::string{arcane_item_family->name().localstr()},
681 [arcane_item_family, local_ids](Neo::MeshScalarPropertyT<Neo::utils::Int32> const&,
682 Neo::MeshScalarPropertyT<Neo::utils::Int32>&) {
683 arcane_item_family->removeItems(local_ids);
684 });
685 }
686
687 /*---------------------------------------------------------------------------*/
688
689 void scheduleAddConnectivity(PolyhedralFamily* arcane_source_item_family,
690 PolyhedralTools::ItemLocalIds& source_items,
691 Integer nb_connected_items_per_item,
692 PolyhedralFamily* arcane_target_item_family,
693 Int64ConstArrayView target_items_uids,
694 String const& name)
695 {
696 // add connectivity in Neo
697 _scheduleAddConnectivity(arcane_source_item_family,
698 source_items,
699 nb_connected_items_per_item,
700 arcane_target_item_family,
701 target_items_uids,
702 name);
703 }
704
705 /*---------------------------------------------------------------------------*/
706
707 void scheduleAddConnectivity(PolyhedralFamily* arcane_source_item_family,
708 PolyhedralTools::ItemLocalIds& source_items,
709 Int32ConstSmallSpan nb_connected_items_per_item,
710 PolyhedralFamily* arcane_target_item_family,
711 Int64ConstSmallSpan target_items_uids,
712 String const& connectivity_name)
713 {
714 _scheduleAddConnectivity(arcane_source_item_family,
715 source_items,
716 std::vector<Int32>{ nb_connected_items_per_item.begin(), nb_connected_items_per_item.end() },
717 arcane_target_item_family,
718 target_items_uids,
719 connectivity_name);
720 }
721
722 /*---------------------------------------------------------------------------*/
723 /*---------------------------------------------------------------------------*/
724
725 void scheduleUpdateConnectivity(PolyhedralFamily* arcane_source_item_family,
726 PolyhedralTools::ItemLocalIds& source_items,
727 Integer nb_connected_items_per_item,
728 PolyhedralFamily* arcane_target_item_family,
729 Int64ConstArrayView target_items_uids,
730 String const& name)
731 {
732 // add connectivity in Neo
733 _scheduleAddConnectivity(arcane_source_item_family,
734 source_items,
735 nb_connected_items_per_item,
736 arcane_target_item_family,
737 target_items_uids,
738 name,
739 Neo::Mesh::ConnectivityOperation::Modify);
740 }
741
742 /*---------------------------------------------------------------------------*/
743
744 void scheduleUpdateConnectivity(PolyhedralFamily* arcane_source_item_family,
745 PolyhedralTools::ItemLocalIds& source_items,
746 Int32ConstSmallSpan nb_connected_items_per_item,
747 PolyhedralFamily* arcane_target_item_family,
748 Int64ConstSmallSpan target_items_uids,
749 String const& connectivity_name)
750 {
751 _scheduleAddConnectivity(arcane_source_item_family,
752 source_items,
753 std::vector<Int32>{ nb_connected_items_per_item.begin(), nb_connected_items_per_item.end() },
754 arcane_target_item_family,
755 target_items_uids,
756 connectivity_name,
757 Neo::Mesh::ConnectivityOperation::Modify);
758 }
759
760 /*---------------------------------------------------------------------------*/
761
762 // template to handle nb_items_per_item type (an int or an array)
763 template <typename ConnectivitySizeType>
764 void _scheduleAddConnectivity(PolyhedralFamily* arcane_source_item_family,
765 PolyhedralTools::ItemLocalIds& source_items,
766 ConnectivitySizeType&& nb_connected_items_per_item,
767 PolyhedralFamily* arcane_target_item_family,
768 Int64ConstSmallSpan target_item_uids,
769 String const& connectivity_name,
770 Neo::Mesh::ConnectivityOperation operation = Neo::Mesh::ConnectivityOperation::Add)
771 {
772 // add connectivity in Neo
773 auto& source_family = m_mesh.findFamily(itemKindArcaneToNeo(arcane_source_item_family->itemKind()),
774 arcane_source_item_family->name().localstr());
775 auto& target_family = m_mesh.findFamily(itemKindArcaneToNeo(arcane_target_item_family->itemKind()),
776 arcane_target_item_family->name().localstr());
777 // Copy data to send them to Neo
778 UniqueArray<Int64> target_item_uids_copy(target_item_uids);
779 // Remove connectivities with a null item
780 std::vector<Int64> target_item_uids_filtered;
781 target_item_uids_filtered.reserve(target_item_uids.size());
782 std::copy_if(target_item_uids.begin(),
783 target_item_uids.end(),
784 std::back_inserter(target_item_uids_filtered),
785 [](auto uid) { return uid != NULL_ITEM_UNIQUE_ID; });
786 // Add connectivity in Neo (async)
787 m_mesh.scheduleAddConnectivity(source_family, source_items.m_future_items, target_family,
788 std::forward<ConnectivitySizeType>(nb_connected_items_per_item),
789 std::move(target_item_uids_filtered),
790 connectivity_name.localstr(),
791 operation);
792 // Register Neo connectivities in Arcane
793 auto& mesh_graph = m_mesh.internalMeshGraph();
794 std::string connectivity_add_output_property_name = std::string{ "EndOf" } + connectivity_name.localstr() + "Add";
795 source_family.addScalarProperty<Neo::utils::Int32>(connectivity_add_output_property_name);
796 // todo is operation == Modify, the update algo should not be needed. To check
797 mesh_graph.addAlgorithm(Neo::MeshKernel::InProperty{ source_family, connectivity_name.localstr() },
798 Neo::MeshKernel::OutProperty{ source_family, connectivity_add_output_property_name },
799 "UpdateArcaneConnectivity"+std::string{connectivity_name.localstr()},
800 [arcane_source_item_family, arcane_target_item_family, &source_family, &target_family, this]
801 (Neo::Mesh::ConnectivityPropertyType const& neo_connectivity,
802 Neo::ScalarPropertyT<Neo::utils::Int32>&) {
803 auto rank = arcane_source_item_family->mesh()->parallelMng()->commRank();
804 Neo::printer(rank) << "==Algorithm update Arcane connectivity: "<< neo_connectivity.name() << Neo::endline;
805 auto item_internal_connectivity_list = arcane_source_item_family->itemInternalConnectivityList();
806 // todo check if families are default families
807 auto connectivity = m_mesh.getConnectivity(source_family, target_family, neo_connectivity.name());
808 // to access connectivity data (for initializing Arcane connectivities) create a proxy on Neo connectivity
809 auto& connectivity_values = source_family.getConcreteProperty<Neo::Mesh::ConnectivityPropertyType>(neo_connectivity.name());
810 Neo::MeshArrayPropertyProxyT<Neo::Mesh::ConnectivityPropertyType::PropertyDataType> connectivity_proxy{ connectivity_values };
811 auto nb_item_data = connectivity_proxy.arrayPropertySizes();
812 auto nb_item_size = connectivity_proxy.arrayPropertySizesSize();
813 item_internal_connectivity_list->_setConnectivityNbItem(arcane_target_item_family->itemKind(),
814 Int32ArrayView{ Integer(nb_item_size), nb_item_data });
815 auto max_nb_connected_items = connectivity.maxNbConnectedItems();
816 item_internal_connectivity_list->_setMaxNbConnectedItem(arcane_target_item_family->itemKind(), max_nb_connected_items);
817 auto connectivity_values_data = connectivity_proxy.arrayPropertyData();
818 auto connectivity_values_size = connectivity_proxy.arrayPropertyDataSize();
819 item_internal_connectivity_list->_setConnectivityList(arcane_target_item_family->itemKind(),
820 Int32ArrayView{ Integer(connectivity_values_size), connectivity_values_data });
821 auto connectivity_index_data = connectivity_proxy.arrayPropertyIndex();
822 auto connectivity_index_size = connectivity_proxy.arrayPropertyIndexSize();
823 item_internal_connectivity_list->_setConnectivityIndex(arcane_target_item_family->itemKind(),
824 Int32ArrayView{ Integer(connectivity_index_size), connectivity_index_data }); }, Neo::MeshKernel::AlgorithmPropertyGraph::AlgorithmPersistence::KeepAfterExecution);
825 // If FaceToCellConnectivity Add face flags II_Boundary, II_SubdomainBoundary, II_HasFrontCell, II_HasBackCell
826 if (arcane_source_item_family->itemKind() == IK_Face && arcane_target_item_family->itemKind() == IK_Cell) {
827 std::string flag_definition_output_property_name{ "EndOfFlagDefinition" };
828 source_family.addScalarProperty<Neo::utils::Int32>(flag_definition_output_property_name);
829 // update Face flags after connectivity add
830 mesh_graph.addAlgorithm(Neo::MeshKernel::InProperty{ source_family, connectivity_add_output_property_name }, Neo::MeshKernel::OutProperty{ source_family, flag_definition_output_property_name },
831 "UpdateFaceFlagsAfterConnectivityDefinition",
832 [arcane_source_item_family, arcane_target_item_family, target_item_uids_local = std::move(target_item_uids_copy), &source_items](Neo::ScalarPropertyT<Neo::utils::Int32> const&, Neo::ScalarPropertyT<Neo::utils::Int32> const&) {
833 auto current_face_index = 0;
834 auto arcane_faces = arcane_source_item_family->itemInfoListView();
835 Int32UniqueArray target_item_lids(target_item_uids_local.size());
836 arcane_target_item_family->itemsUniqueIdToLocalId(target_item_lids, target_item_uids_local, false);
837 for (auto face_lid : source_items.m_future_items.new_items) {
838 Face current_face = arcane_faces[face_lid].toFace();
839 if (target_item_lids[2 * current_face_index + 1] == NULL_ITEM_LOCAL_ID) {
840 // Only back cell or none
841 Int32 mod_flags = (target_item_lids[2 * current_face_index] != NULL_ITEM_LOCAL_ID) ? (ItemFlags::II_Boundary | ItemFlags::II_HasBackCell | ItemFlags::II_BackCellIsFirst) : 0;
842 _setFaceInfos(mod_flags, current_face);
843 }
844 else if (target_item_lids[2 * current_face_index] == NULL_ITEM_LOCAL_ID) {
845 // Only front cell or none
847 }
848 else {
849 // Both back and front cells
851 }
852 ++current_face_index;
853 }
854 });
855 // Add an algorithm to update Face flags when a connected cell is removed
856 auto const isolated_items_property_name = m_mesh._isolatedItemLidsPropertyName(source_family,target_family);
857 std::string const flag_update_output_property_name{ "EndOfFlagUpdate" };
858 source_family.addScalarProperty<Neo::utils::Int32>(flag_update_output_property_name);
859
860 mesh_graph.addAlgorithm(Neo::MeshKernel::InProperty{ source_family, isolated_items_property_name },
861 Neo::MeshKernel::OutProperty{ source_family, flag_update_output_property_name },
862 "UpdateFaceFlagsAfterCellRemoval",
863 [arcane_source_item_family,&source_family,connectivity_name](Neo::MeshScalarPropertyT<Neo::utils::Int32> const&, Neo::ScalarPropertyT<Neo::utils::Int32> const&) {
864 auto const rank = arcane_source_item_family->mesh()->parallelMng()->commRank();
865 Neo::printer(rank) << "==Algorithm update Face flags after cell removal" << Neo::endline;
866 // todo should be an input property
867 auto const removed_target_item_index_prop_name = Neo::Mesh::removedTargetItemIndexfilteredItemPropertyName(connectivity_name.localstr());
868 auto& null_item_connected = source_family.getConcreteProperty<Neo::MeshArrayPropertyT<Neo::utils::Int32>>(removed_target_item_index_prop_name);
869 null_item_connected.debugPrint(rank);
870 ENUMERATE_(Face,iface,arcane_source_item_family->allItems())
871 {
872 Face current_face = *iface;
873 auto null_items_connected_to_face = null_item_connected[iface.localId()];
874 if (null_items_connected_to_face.size() > 2)
875 {
876 ARCANE_FATAL("More than one null item connected to face {0}",iface.localId());
877 }
878 // If no cell removed nothing to do
879 if (null_items_connected_to_face.size() == 0)
880 continue;
881 // If only one cell, check if back or front remains
882 // front cell remains
883 if (null_items_connected_to_face[0] == 0)
884 {
887 }
888 else if (null_items_connected_to_face[0] == 1)
889 {
892 }
893 }
894
895 },
896 Neo::MeshKernel::AlgorithmPropertyGraph::AlgorithmPersistence::KeepAfterExecution
897 );
898 }
899 // Add an algorithm to remove items isolated after a connectivity update. Add it only once, when connectivity is added
900 if (operation == Neo::Mesh::ConnectivityOperation::Modify)
901 return;
902 auto isolated_item_property_name = m_mesh._isolatedItemLidsPropertyName(source_family, target_family);
903 auto end_of_isolated_removal_property_name = std::string{ "EndOf" } + isolated_item_property_name;
904 source_family.addScalarProperty<Neo::utils::Int32>(end_of_isolated_removal_property_name);
905 mesh_graph.addAlgorithm(Neo::MeshKernel::InProperty{ source_family, isolated_item_property_name },
906 Neo::MeshKernel::OutProperty{ source_family, end_of_isolated_removal_property_name },
907 "RemoveIsolatedArcaneItemsIn"+std::string{ arcane_source_item_family->name().localstr() },
908 [arcane_source_item_family](Neo::MeshScalarPropertyT<Neo::utils::Int32> const& isolated_items_lids_property,
909 Neo::ScalarPropertyT<Neo::utils::Int32>& end_of_isolated_removal_property) {
910 end_of_isolated_removal_property.set(1);
911 // remove Arcane items
912 Int32UniqueArray isolated_item_lids;
913 isolated_item_lids.reserve(isolated_items_lids_property.size());
914 ENUMERATE_(Item,iitem,arcane_source_item_family->allItems()) {
915 if (isolated_items_lids_property[iitem->localId()] == 1) {
916 isolated_item_lids.push_back(iitem->localId());
917 }
918 }
919 std::sort(isolated_item_lids.begin(), isolated_item_lids.end());
920 arcane_source_item_family->traceMng()->info() << "Remove isolated in Arcane for family "
921 << arcane_source_item_family->name() << " lids : " << isolated_item_lids;
922 isolated_items_lids_property.debugPrint();
923 arcane_source_item_family->removeItems(isolated_item_lids);
924 }, Neo::MeshKernel::AlgorithmPropertyGraph::AlgorithmPersistence::KeepAfterExecution);
925 }
926
927 /*---------------------------------------------------------------------------*/
928
929 void scheduleSetItemCoordinates(PolyhedralFamily* item_family, PolyhedralTools::ItemLocalIds& local_ids, Real3ConstSmallSpan item_coords, VariableItemReal3& arcane_coords)
930 {
931 auto& _item_family = m_mesh.findFamily(itemKindArcaneToNeo(item_family->itemKind()), item_family->name().localstr());
932 std::vector<Neo::utils::Real3> _node_coords(item_coords.size());
933 auto node_index = 0;
934 for (auto&& node_coord : item_coords) {
935 _node_coords[node_index++] = Neo::utils::Real3{ node_coord.x, node_coord.y, node_coord.z };
936 }
937 m_mesh.scheduleSetItemCoords(_item_family, local_ids.m_future_items, _node_coords);
938 // Fill Arcane Variable
939 auto& mesh_graph = m_mesh.internalMeshGraph();
940 _item_family.addScalarProperty<Int32>("NoOutProperty42"); // todo remove : create noOutput algo in Neo
941 mesh_graph.addAlgorithm(Neo::MeshKernel::InProperty{ _item_family, m_mesh._itemCoordPropertyName(_item_family) },
942 Neo::MeshKernel::OutProperty{ _item_family, "NoOutProperty42" },
943 "UpdateArcaneCoordsIn"+std::string{item_family->name().localstr()},
944 [this, item_family, &_item_family, &arcane_coords](Neo::Mesh::CoordPropertyType const& item_coords_property,
945 Neo::ScalarPropertyT<Neo::utils::Int32>&) {
946 // enumerate nodes : ensure again Arcane/Neo local_ids are identicals
947 auto& all_items = _item_family.all();
948 VariableNodeReal3 node_coords{ VariableBuildInfo{ item_family->mesh(), "NodeCoord" } };
949 for (auto item : all_items) {
950 arcane_coords[ItemLocalId{ item }] = { item_coords_property[item].x,
951 item_coords_property[item].y,
952 item_coords_property[item].z };
953 }
954 });
955 }
956
957 /*---------------------------------------------------------------------------*/
958
959 Neo::EndOfMeshUpdate applyScheduledOperations() noexcept
960 {
961 return m_mesh.applyScheduledOperations();
962 }
963 };
964
965 template <> class PolyhedralMeshImpl::ItemKindTraits<IK_Cell>
966 {
967 static const Neo::ItemKind item_kind = Neo::ItemKind::IK_Cell;
968 };
969 template <> class PolyhedralMeshImpl::ItemKindTraits<IK_Face>
970 {
971 static const Neo::ItemKind item_kind = Neo::ItemKind::IK_Face;
972 };
973 template <> class PolyhedralMeshImpl::ItemKindTraits<IK_Edge>
974 {
975 static const Neo::ItemKind item_kind = Neo::ItemKind::IK_Edge;
976 };
977 template <> class PolyhedralMeshImpl::ItemKindTraits<IK_Node>
978 {
979 static const Neo::ItemKind item_kind = Neo::ItemKind::IK_Node;
980 };
981 template <> class PolyhedralMeshImpl::ItemKindTraits<IK_DoF>
982 {
983 static const Neo::ItemKind item_kind = Neo::ItemKind::IK_Dof;
984 };
985
986 /*---------------------------------------------------------------------------*/
987
988 void PolyhedralFamilySerializer::serializeItems(ISerializer* buf, Int32ConstArrayView items_local_ids)
989 {
990 ARCANE_CHECK_POINTER(m_family);
992
993 switch (buf->mode()) {
994 case ISerializer::ModeReserve: {
995 _fillItemData(items_local_ids);
996 m_item_data.serialize(buf);
997 auto connectivities = m_mesh->_impl()->connectivities(m_family);
998 for (auto out_connectivity : connectivities) {
999 buf->reserve(out_connectivity.target_family.name());
1000 buf->reserve(out_connectivity.name);
1001 }
1002 break;
1003 }
1004 case ISerializer::ModePut: {
1005 m_item_data.serialize(buf);
1006 auto connectivities = m_mesh->_impl()->connectivities(m_family);
1007 for (auto out_connectivity : connectivities) {
1008 buf->put(out_connectivity.target_family.name());
1009 buf->put(out_connectivity.name);
1010 }
1011 clear();
1012 break;
1013 }
1014 case ISerializer::ModeGet: {
1015 deserializeItems(buf, nullptr);
1016 break;
1017 }
1018 }
1019 }
1020
1021 /*---------------------------------------------------------------------------*/
1022
1023 void PolyhedralFamilySerializer::deserializeItems(ISerializer* buf, Int32Array* items_local_ids)
1024 {
1025 ARCANE_ASSERT((buf->mode() == ISerializer::ModeGet),
1026 ("Impossible to deserialize a buffer not in ModeGet. In ItemData::deserialize.Exiting"))
1027 ARCANE_CHECK_POINTER(m_mesh);
1028 ARCANE_CHECK_POINTER(m_family);
1029 ARCANE_CHECK_POINTER(m_mng);
1030 ItemData item_data;
1031 if (items_local_ids)
1032 item_data.deserialize(buf, m_mesh, *items_local_ids);
1033 else
1034 item_data.deserialize(buf, m_mesh);
1035 auto connectivities = m_mesh->_impl()->connectivities(m_family);
1036 auto nb_connectivities = connectivities.size();
1037 StringUniqueArray connected_family_names(nb_connectivities);
1038 StringUniqueArray connectivity_names(nb_connectivities);
1039 auto index = 0;
1040 for (auto out_connectivity : connectivities) {
1041 buf->get(connected_family_names[index]);
1042 buf->get(connectivity_names[index]);
1043 ++index;
1044 }
1045 _fillItemFamilyInfo(item_data, connected_family_names, connectivity_names);
1046
1047 if (items_local_ids) {
1048 m_deserialized_lids_array.push_back(items_local_ids);
1049 // and that's all, they will be filled in finalizeItemAllocation
1050 }
1051 m_future_item_lids_array.push_back(std::make_shared<PolyhedralTools::ItemLocalIds>());
1052 m_mesh->scheduleAllocateItems(m_family_info, *m_future_item_lids_array.back().get());
1053
1054 // Add serializer in mng. Update is triggered when finalizeItemAllocation is called
1055 m_mng->addSerializer(this);
1056 }
1057
1058 /*---------------------------------------------------------------------------*/
1059 void PolyhedralFamilySerializer::_fillItemData(Int32ConstArrayView items_local_ids)
1060 {
1061 m_item_data = ItemData{ items_local_ids.size(), 0, m_family, nullptr, m_family->parallelMng()->commRank() };
1062 Int64Array& item_infos = m_item_data.itemInfos();
1063 Int32ArrayView item_owners = m_item_data.itemOwners();
1064 // Reserve size
1065 const Integer nb_item = items_local_ids.size();
1066 item_infos.reserve(1 + nb_item * 32); // Size evaluation for hexa cell (the more data to store) : 1_family_info + nb_item *(2_info_per_family + 6 (faces) + 12 (edges) + 8 (vertices) connected elements) = 1 + nb_item *(6 + 6 + 12 +8)
1067 // Fill item data (cf ItemData.h)
1068 PolyhedralMeshImpl* mesh_impl = m_mesh->_impl();
1069 auto connectivities = mesh_impl->connectivities(m_family);
1070 item_infos.add(connectivities.size());
1071 bool is_face_family = m_family->itemKind() == IK_Face;
1072 ENUMERATE_ITEM (item, m_family->view(items_local_ids)) {
1073 item_infos.add(42); // Item type, not used for polyhedral mesh
1074 item_infos.add(item->uniqueId().asInt64());
1075 item_owners[item.index()] = item->owner();
1076 for (auto out_connectivity : connectivities) {
1077 auto target_family = m_mesh->findItemFamily(PolyhedralMeshImpl::itemKindNeoToArcane(out_connectivity.target_family.itemKind()),
1078 out_connectivity.target_family.name(), false, false);
1079 // auto arcane_connected_items = target_family->view();
1080 auto arcane_connected_items = target_family->itemInfoListView();
1081 bool is_face_cell_connection = is_face_family && target_family->itemKind() == IK_Cell;
1082 item_infos.add(PolyhedralMeshImpl::itemKindNeoToArcane(out_connectivity.target_family.itemKind()));
1083 auto connected_items = out_connectivity[item.localId()];
1084 auto nb_connected_items = connected_items.size();
1085 item_infos.add(nb_connected_items);
1086 if (is_face_cell_connection && item->itemBase().isBoundary() && item->itemBase().backCell().isNull()) {
1087 item_infos.add(NULL_ITEM_UNIQUE_ID);
1088 }
1089 for (auto connected_item_lid : connected_items) {
1090 item_infos.add(arcane_connected_items[connected_item_lid].uniqueId().asInt64());
1091 }
1092 if (is_face_cell_connection && item->itemBase().isBoundary() && !item->itemBase().backCell().isNull()) {
1093 item_infos.add(NULL_ITEM_UNIQUE_ID);
1094 }
1095 }
1096 }
1097 }
1098
1099} // End namespace mesh
1100
1101/*---------------------------------------------------------------------------*/
1102/*---------------------------------------------------------------------------*/
1103
1104class mesh::PolyhedralMesh::PolyhedralMeshModifier
1106{
1107 public:
1108
1109 explicit PolyhedralMeshModifier(PolyhedralMesh* mesh)
1110 : m_mesh(mesh)
1111 {}
1112
1113 void addItems(Int64ConstArrayView unique_ids, Int32ArrayView local_ids, eItemKind ik, const String& family_name) override
1114 {
1115 m_mesh->addItems(unique_ids, local_ids, ik, family_name);
1116 }
1117
1118 void addItems(Int64ConstArrayView unique_ids, Int32ArrayView local_ids, Int32ConstArrayView owners, eItemKind ik, const String& family_name) override
1119 {
1120 m_mesh->addItems(unique_ids, local_ids, owners, ik, family_name);
1121 }
1122
1123 void removeItems(Int32ConstArrayView local_ids, eItemKind ik, const String& family_name) override
1124 {
1125 m_mesh->removeItems(local_ids, ik, family_name);
1126 }
1127
1128 private:
1129
1130 PolyhedralMesh* m_mesh;
1131};
1132
1133/*---------------------------------------------------------------------------*/
1134/*---------------------------------------------------------------------------*/
1135
1136class mesh::PolyhedralMesh::InternalApi
1137: public IMeshInternal
1138, public IMeshModifierInternal
1139{
1140 public:
1141
1142 explicit InternalApi(PolyhedralMesh* mesh)
1143 : m_mesh(mesh)
1144 , m_connectivity_mng(std::make_unique<ItemConnectivityMng>(mesh->traceMng()))
1145 , m_polyhedral_mesh_modifier(std::make_unique<PolyhedralMeshModifier>(mesh))
1146 {}
1147
1148 public:
1149
1150 void setMeshKind(const MeshKind& v) override
1151 {
1152 if (v.meshStructure() != eMeshStructure::Polyhedral && v.meshAMRKind() != eMeshAMRKind::None) {
1153 ARCANE_FATAL("Incompatible mesh structure ({0}) and amr kind ({1}) for Polyhedral mesh {2}. Must be (Polyhedral,None). ",
1154 v.meshStructure(), v.meshAMRKind(), m_mesh->name());
1155 }
1156 m_mesh->m_mesh_kind = v;
1157 }
1158
1159 IItemConnectivityMng* dofConnectivityMng() const noexcept override
1160 {
1161 return m_connectivity_mng.get();
1162 }
1163
1164 IPolyhedralMeshModifier* polyhedralMeshModifier() const noexcept override
1165 {
1166 return m_polyhedral_mesh_modifier.get();
1167 }
1168
1169 void removeNeedRemoveMarkedItems() override
1170 {
1171 m_mesh->removeNeedRemoveMarkedItems();
1172 }
1173 NodeLocalId addNode([[maybe_unused]] ItemUniqueId unique_id) override
1174 {
1175 ARCANE_THROW(NotImplementedException, "");
1176 }
1177 FaceLocalId addFace([[maybe_unused]] ItemUniqueId unique_id,
1178 [[maybe_unused]] ItemTypeId type_id,
1179 [[maybe_unused]] ConstArrayView<Int64> nodes_uid) override
1180 {
1181 ARCANE_THROW(NotImplementedException, "");
1182 }
1183 CellLocalId addCell([[maybe_unused]] ItemUniqueId unique_id,
1184 [[maybe_unused]] ItemTypeId type_id,
1185 [[maybe_unused]] ConstArrayView<Int64> nodes_uid) override
1186 {
1187 ARCANE_THROW(NotImplementedException, "");
1188 }
1189
1190 IItemFamilySerializerMngInternal* familySerializerMng() const noexcept override
1191 {
1192 return m_mesh->polyhedralFamilySerializerMng();
1193 }
1194
1195 ItemInternalMap& nodesMap() override
1196 {
1197 return m_mesh->_itemFamily(IK_Node)->itemsMap();
1198 }
1199
1200 ItemInternalMap& edgesMap() override
1201 {
1202 return m_mesh->_itemFamily(IK_Edge)->itemsMap();
1203 }
1204
1205 ItemInternalMap& facesMap() override
1206 {
1207 return m_mesh->_itemFamily(IK_Face)->itemsMap();
1208 }
1209
1210 ItemInternalMap& cellsMap() override
1211 {
1212 return m_mesh->_itemFamily(IK_Cell)->itemsMap();
1213 }
1214
1215 FaceFamily& trueFaceFamily() override
1216 {
1217 ARCANE_FATAL("PolyhedralMesh::trueFaceFamily() is not implemented. PolyhedralMesh has no concrete FaceFamily.");
1218 }
1219
1220 void printStats(Int32 level)
1221 {
1222 m_mesh->traceMng()->info(level) << "-- -- Statistics";
1223 m_mesh->traceMng()->info(level) << "Number of nodes after addition &: "
1224 << " hashmap=" << m_mesh->_internalApi()->nodesMap().count();
1225 m_mesh->traceMng()->info(level) << "Number of edges after addition : "
1226 << " hashmap=" << m_mesh->_internalApi()->edgesMap().count();
1227 m_mesh->traceMng()->info(level) << "Number of faces after addition : "
1228 << " hashmap=" << m_mesh->_internalApi()->facesMap().count();
1229 m_mesh->traceMng()->info(level) << "Number of cells after addition : "
1230 << " hashmap=" << m_mesh->_internalApi()->cellsMap().count();
1231 m_mesh->traceMng()->info(level) << "--";
1232 }
1233
1234 private:
1235
1236 PolyhedralMesh* m_mesh = nullptr;
1237 std::unique_ptr<IItemConnectivityMng> m_connectivity_mng = nullptr;
1238 std::unique_ptr<IPolyhedralMeshModifier> m_polyhedral_mesh_modifier = nullptr;
1239};
1240
1241/*---------------------------------------------------------------------------*/
1242/*---------------------------------------------------------------------------*/
1243
1244class mesh::PolyhedralMesh::NoCompactionMeshCompacter
1245: public IMeshCompacter
1246{
1247 public:
1248
1249 explicit NoCompactionMeshCompacter(PolyhedralMesh* mesh)
1250 : m_mesh(mesh)
1251 , m_trace_mng(mesh->traceMng())
1252 {}
1253
1254 void doAllActions() override { _info(); };
1255
1256 void beginCompact() override { _info(); };
1257 void compactVariablesAndGroups() override { _info(); };
1258 void updateInternalReferences() override { _info(); };
1259 void endCompact() override { _info(); };
1260 void finalizeCompact() override { _info(); };
1261
1262 IMesh* mesh() const override { return m_mesh; };
1263
1264 const ItemFamilyCompactInfos* findCompactInfos(IItemFamily*) const override
1265 {
1266 _info();
1267 return nullptr;
1268 }
1269
1270 ePhase phase() const override
1271 {
1272 _info();
1273 return ePhase::Ended;
1274 }
1275
1276 void setSorted(bool) override { _info(); };
1277
1278 bool isSorted() const override
1279 {
1280 _info();
1281 return false;
1282 };
1283
1284 ItemFamilyCollection families() const override
1285 {
1286 _info();
1287 return ItemFamilyCollection{};
1288 };
1289
1290 void _setCompactVariablesAndGroups(bool) override { _info(); };
1291
1292 private:
1293
1294 PolyhedralMesh* m_mesh = nullptr;
1295 ITraceMng* m_trace_mng = nullptr;
1296
1297 void _info() const { m_trace_mng->info() << A_FUNCINFO << "No compacting in PolyhedralMesh"; }
1298};
1299
1300/*---------------------------------------------------------------------------*/
1301/*---------------------------------------------------------------------------*/
1302
1303class mesh::PolyhedralMesh::NoCompactionMeshCompactMng
1304: public IMeshCompactMng
1305{
1306 public:
1307
1308 explicit NoCompactionMeshCompactMng(PolyhedralMesh* mesh)
1309 : m_mesh(mesh)
1310 , m_trace_mng(mesh->traceMng())
1311 , m_mesh_compacter{ std::make_unique<NoCompactionMeshCompacter>(m_mesh) }
1312 {}
1313
1314 IMesh* mesh() const override { return m_mesh; }
1315 IMeshCompacter* beginCompact() override
1316 {
1317 _info();
1318 return m_mesh_compacter.get();
1319 }
1320
1321 IMeshCompacter* beginCompact(IItemFamily* family) override
1322 {
1323 ARCANE_UNUSED(family);
1324 _info();
1325 return m_mesh_compacter.get();
1326 };
1327
1328 void endCompact() override { _info(); };
1329
1330 IMeshCompacter* compacter() override
1331 {
1332 _info();
1333 return m_mesh_compacter.get();
1334 };
1335
1336 private:
1337
1338 PolyhedralMesh* m_mesh = nullptr;
1339 ITraceMng* m_trace_mng = nullptr;
1340 std::unique_ptr<IMeshCompacter> m_mesh_compacter = nullptr;
1341
1342 void _info() const { m_trace_mng->info() << A_FUNCINFO << "No compacting in PolyhedralMesh"; }
1343};
1344
1345/*---------------------------------------------------------------------------*/
1346/*---------------------------------------------------------------------------*/
1347
1348mesh::PolyhedralMesh::
1349~PolyhedralMesh()
1350{
1351 m_mesh_handle._setMesh(nullptr);
1352}
1353
1354/*---------------------------------------------------------------------------*/
1355/*---------------------------------------------------------------------------*/
1356
1357ITraceMng* mesh::PolyhedralMesh::
1358traceMng()
1359{
1360 return m_subdomain->traceMng();
1361}
1362
1363/*---------------------------------------------------------------------------*/
1364/*---------------------------------------------------------------------------*/
1365
1366MeshHandle mesh::PolyhedralMesh::
1367handle() const
1368{
1369 return m_mesh_handle;
1370}
1371
1372/*---------------------------------------------------------------------------*/
1373/*---------------------------------------------------------------------------*/
1374mesh::PolyhedralMesh::
1375PolyhedralMesh(ISubDomain* subdomain, const MeshBuildInfo& mbi)
1376: EmptyMesh{ subdomain->traceMng() }
1377, m_name{ mbi.name() }
1378, m_subdomain{ subdomain }
1379, m_mesh_handle{ m_subdomain->defaultMeshHandle() }
1380, m_properties(std::make_unique<Properties>(subdomain->propertyMng(), String("ArcaneMeshProperties_") + m_name))
1381, m_mesh{ std::make_unique<mesh::PolyhedralMeshImpl>(m_subdomain) }
1382, m_parallel_mng{ mbi.parallelMngRef().get() }
1383, m_mesh_part_info{ makeMeshPartInfoFromParallelMng(m_parallel_mng) }
1384, m_item_type_mng(ItemTypeMng::_singleton())
1385, m_mesh_kind(mbi.meshKind())
1386, m_polyhedral_family_serializer_mng{ std::make_unique<PolyhedralFamilySerializerMng>(this) }
1387, m_initial_allocator(*this)
1388, m_variable_mng{ subdomain->variableMng() }
1389, m_mesh_checker{ this }
1390, m_internal_api{ std::make_unique<InternalApi>(this) }
1391, m_compact_mng{ std::make_unique<NoCompactionMeshCompactMng>(this) }
1392, m_mesh_utilities{ std::make_unique<UnstructuredMeshUtilities>(this) }
1393, m_mesh_exchange_mng{ std::make_unique<MeshExchangeMng>(this) }
1394, m_item_family_network{ std::make_unique<ItemFamilyNetwork>(m_trace_mng) }
1395, m_ghost_layer_mng{ std::make_unique<GhostLayerMng>(m_trace_mng) }
1396, m_connectivity(VariableBuildInfo{ subdomain, mbi.name() + "MeshConnectivity" })
1397{
1398 m_mesh_handle._setMesh(this);
1399 m_mesh_item_internal_list.mesh = this;
1400 m_default_arcane_families.fill(nullptr);
1401}
1402
1403/*---------------------------------------------------------------------------*/
1404/*---------------------------------------------------------------------------*/
1405
1406void Arcane::mesh::PolyhedralMesh::
1407allocateItems(const Arcane::ItemAllocationInfo& item_allocation_info)
1408{
1409 _allocateItems(item_allocation_info, ArrayView<Int32UniqueArray>{});
1410}
1411
1412/*---------------------------------------------------------------------------*/
1413
1414void Arcane::mesh::PolyhedralMesh::
1415allocateItems(const Arcane::ItemAllocationInfo& item_allocation_info, ArrayView<Int32UniqueArray> family_lids)
1416{
1417 _allocateItems(item_allocation_info, family_lids);
1418}
1419
1420/*---------------------------------------------------------------------------*/
1421
1422void Arcane::mesh::PolyhedralMesh::
1423_allocateItems(const Arcane::ItemAllocationInfo& item_allocation_info, ArrayView<Int32UniqueArray> family_lids)
1424{
1425 // Second step read a vtk polyhedral mesh
1426 m_subdomain->traceMng()->info() << "--PolyhedralMesh: allocate items --";
1427 UniqueArray<PolyhedralTools::ItemLocalIds> item_local_ids(item_allocation_info.family_infos.size());
1428 auto family_index = 0;
1429 // Prepare item creation
1430 for (auto& family_info : item_allocation_info.family_infos) {
1431 bool create_if_needed = true;
1432 auto* item_family = _findItemFamily(family_info.item_kind, family_info.name, create_if_needed);
1433 m_trace_mng->debug(Trace::High) << "- Create items " << family_info.name;
1434 m_mesh->scheduleAddItems(item_family, family_info.item_uids, family_info.item_owners.constSmallSpan(), item_local_ids[family_index++]);
1435 }
1436 // Prepare connectivity creation
1437 family_index = 0;
1438 for (auto& family_info : item_allocation_info.family_infos) {
1439 auto* item_family = _findItemFamily(family_info.item_kind, family_info.name);
1440 m_trace_mng->debug(Trace::High) << "- Current family " << family_info.name;
1441 for (auto& current_connected_family_info : family_info.connected_family_infos) {
1442 auto connected_family = _findItemFamily(current_connected_family_info.item_kind, current_connected_family_info.name);
1443 m_trace_mng->debug(Trace::High) << "- Create connectivity " << current_connected_family_info.connectivity_name;
1444 // check if connected family exists
1445 if (!connected_family) {
1446 ARCANE_WARNING((String::format("Cannot find family {0} with kind {1} "
1447 "The connectivity between {1} and this family is skipped",
1448 current_connected_family_info.name,
1449 current_connected_family_info.item_kind,
1450 item_family->name())
1451 .localstr()));
1452 continue;
1453 }
1454 m_mesh->scheduleAddConnectivity(item_family,
1455 item_local_ids[family_index],
1456 current_connected_family_info.nb_connected_items_per_item,
1457 connected_family,
1458 current_connected_family_info.connected_items_uids,
1459 current_connected_family_info.connectivity_name);
1460 Connectivity connectivity{ m_connectivity };
1461 connectivity.enableConnectivity(Connectivity::kindsToConnectivity(item_family->itemKind(), connected_family->itemKind()));
1462 }
1463 ++family_index;
1464 }
1465 // Create items and connectivities
1466 m_mesh->applyScheduledOperations();
1467 // Create variable for coordinates. This has to be done before call to family::endUpdate. Todo add to the graph
1468 for (auto& family_info : item_allocation_info.family_infos) {
1469 if (family_info.item_kind != IK_Node && family_info.item_coordinates.empty()) { // variable is created for node even if no coords (parallel)
1470 continue;
1471 }
1472 auto* item_family = _findItemFamily(family_info.item_kind, family_info.name);
1473 if (item_family == itemFamily(IK_Node)) { // create mesh node coords if doesn't exist
1474 if (!m_arcane_node_coords.get()) {
1475 m_arcane_node_coords = std::make_unique<VariableNodeReal3>(VariableBuildInfo(this, family_info.item_coordinates_variable_name));
1476 m_arcane_node_coords->setUsed(true);
1477 }
1478 }
1479 else {
1480 auto arcane_item_coords_var_ptr = std::make_unique<VariableItemReal3>(VariableBuildInfo(this, family_info.item_coordinates_variable_name),
1481 item_family->itemKind());
1482 arcane_item_coords_var_ptr->setUsed(true);
1483 m_arcane_item_coords.push_back(std::move(arcane_item_coords_var_ptr));
1484 }
1485 }
1486 // Call Arcane ItemFamily endUpdate
1487 for (auto& family : m_arcane_families) {
1488 family->endUpdate();
1489 }
1490 endUpdate();
1491 // Add coordinates when needed (nodes, or dof, or particles...)
1492 family_index = 0;
1493 auto index = 0;
1494 for (auto& family_info : item_allocation_info.family_infos) {
1495 if (family_info.item_coordinates.empty()) {
1496 ++family_index;
1497 continue;
1498 }
1499 auto* item_family = _findItemFamily(family_info.item_kind, family_info.name);
1500 if (item_family == itemFamily(IK_Node)) { // mesh node coords
1501 m_mesh->scheduleSetItemCoordinates(item_family, item_local_ids[family_index], family_info.item_coordinates, *m_arcane_node_coords);
1502 }
1503 else
1504 m_mesh->scheduleSetItemCoordinates(item_family, item_local_ids[family_index], family_info.item_coordinates, *m_arcane_item_coords[index++].get());
1505 }
1506 auto mesh_state = m_mesh->applyScheduledOperations();
1507 m_is_allocated = true;
1508 // indicates mesh contains general Cells
1509 itemTypeMng()->setMeshWithGeneralCells(this);
1510
1511 if (!family_lids.empty()) {
1512 auto index = 0;
1513 ARCANE_ASSERT((family_lids.size() == item_local_ids.size()), ("Incoherence in item number"));
1514 for (auto& lid_array : item_local_ids) {
1515 family_lids[index].resize(lid_array.size());
1516 lid_array.fillArrayView(family_lids[index].view(), mesh_state);
1517 ++index;
1518 }
1519 }
1520}
1521
1522/*---------------------------------------------------------------------------*/
1523
1524void Arcane::mesh::PolyhedralMesh::
1525scheduleAllocateItems(const Arcane::ItemAllocationInfo::FamilyInfo& family_info, mesh::PolyhedralTools::ItemLocalIds& item_local_ids)
1526{
1527 // Second step read a vtk polyhedral mesh
1528 m_subdomain->traceMng()->info() << "--PolyhedralMesh: schedule allocate items --";
1529 // Prepare item creation
1530 bool create_if_needed = true;
1531 auto* item_family = _findItemFamily(family_info.item_kind, family_info.name, create_if_needed);
1532 m_trace_mng->debug(Trace::High) << "- Current family " << family_info.name;
1533 m_trace_mng->debug(Trace::High) << "- Create items ";
1534 m_mesh->scheduleAddItems(item_family, family_info.item_uids, family_info.item_owners.constSmallSpan(), item_local_ids);
1535 // Prepare connectivity creation
1536 for (auto& current_connected_family_info : family_info.connected_family_infos) {
1537 auto connected_family = _findItemFamily(current_connected_family_info.item_kind, current_connected_family_info.name);
1538 m_trace_mng->debug(Trace::High) << "- Create connectivity " << current_connected_family_info.connectivity_name;
1539 // check if connected family exists
1540 if (!connected_family) {
1541 ARCANE_WARNING((String::format("Cannot find family {0} with kind {1} "
1542 "The connectivity between {1} and this family is skipped",
1543 current_connected_family_info.name,
1544 current_connected_family_info.item_kind,
1545 item_family->name())
1546 .localstr()));
1547 continue;
1548 }
1549 m_mesh->scheduleUpdateConnectivity(item_family,
1550 item_local_ids,
1551 current_connected_family_info.nb_connected_items_per_item,
1552 connected_family,
1553 current_connected_family_info.connected_items_uids,
1554 current_connected_family_info.connectivity_name);
1555 }
1556}
1557
1558/*---------------------------------------------------------------------------*/
1559
1560void Arcane::mesh::PolyhedralMesh::
1561applyScheduledAllocateItems(UniqueArray<std::shared_ptr<PolyhedralTools::ItemLocalIds>> item_lids)
1562{
1563 // Create items and connectivities
1564 auto mesh_state = m_mesh->applyScheduledOperations();
1565 // Fill item_lids (they are already filled in applyScheduledOperations: unlock them setting the mesh_state)
1566 for (auto item_local_ids : item_lids) {
1567 item_local_ids->m_mesh_state = std::make_shared<Neo::EndOfMeshUpdate>(mesh_state);
1568 }
1569
1570 // Call Arcane ItemFamily endUpdate and mesh end update
1571 for (auto& family : m_arcane_families) {
1572 family->endUpdate();
1573 }
1574 endUpdate();
1575 m_is_allocated = true;
1576 // indicates mesh contains general Cells
1577 itemTypeMng()->setMeshWithGeneralCells(this);
1578}
1579
1580/*---------------------------------------------------------------------------*/
1581
1582void mesh::PolyhedralMesh::removeNeedRemoveMarkedItems()
1583{
1584 // Loop through all item families in the mesh: must include DoF and Particles
1585 for (auto family_index = 0; family_index < m_arcane_families.size(); ++family_index) {
1586 // Get the list of local IDs for items to remove
1587 auto* family = m_arcane_families[family_index].get();
1588 Int32UniqueArray items_to_remove;
1589 items_to_remove.reserve(family->nbItem());
1590 auto& items_map = family->itemsMap();
1591 if (items_map.count() == 0)
1592 continue;
1593 items_map.eachItem([&](ItemBase item) {
1594 // Schedule removal of items marked for removal
1595 auto f = item.flags();
1596 if (f & ItemFlags::II_NeedRemove) {
1597 f &= ~ItemFlags::II_NeedRemove & ItemFlags::II_Suppressed;
1598 item.toMutable().setFlags(f);
1599 items_to_remove.add(item.localId());
1600 }
1601 });
1602 if (!items_to_remove.empty()) {
1603 removeItems(items_to_remove, family);
1604 }
1605 }
1606}
1607
1608/*---------------------------------------------------------------------------*/
1609
1610Arcane::mesh::PolyhedralFamilySerializerMng* mesh::PolyhedralMesh::
1611polyhedralFamilySerializerMng()
1612{
1613 return m_polyhedral_family_serializer_mng.get();
1614}
1615
1616/*---------------------------------------------------------------------------*/
1617/*---------------------------------------------------------------------------*/
1618
1619void Arcane::mesh::PolyhedralMesh::
1620_endUpdateFamilies()
1621{
1622 for (auto& family : m_arcane_families) {
1623 family->endUpdate();
1624 }
1625}
1626
1627/*---------------------------------------------------------------------------*/
1628/*---------------------------------------------------------------------------*/
1629
1630void Arcane::mesh::PolyhedralMesh::
1631_computeFamilySynchronizeInfos()
1632{
1633 m_subdomain->traceMng()->info() << "Computing family synchronization information for " << name();
1634 for (auto& family : m_arcane_families) {
1635 family->computeSynchronizeInfos();
1636 }
1637
1638 // Write topology for cell synchronization
1639 if (!platform::getEnvironmentVariable("ARCANE_DUMP_VARIABLE_SYNCHRONIZER_TOPOLOGY").null()) {
1640 auto* var_syncer = cellFamily()->allItemsSynchronizer();
1641 Int32 iteration = m_subdomain->commonVariables().globalIteration();
1642 String file_name = String::format("{0}_sync_topology_iter{1}.json", name(), iteration);
1643 mesh_utils::dumpSynchronizerTopologyJSON(var_syncer, file_name);
1644 }
1645}
1646
1647/*---------------------------------------------------------------------------*/
1648/*---------------------------------------------------------------------------*/
1649
1650void Arcane::mesh::PolyhedralMesh::
1651_notifyEndUpdateForFamilies()
1652{
1653 for (auto& family : m_arcane_families)
1654 family->_internalApi()->notifyEndUpdateFromMesh();
1655}
1656
1657/*---------------------------------------------------------------------------*/
1658/*---------------------------------------------------------------------------*/
1659
1660void Arcane::mesh::PolyhedralMesh::
1661_computeGroupSynchronizeInfos()
1662{
1663 auto action = [](ItemGroup& group) {
1664 if (group.hasSynchronizer())
1665 group.synchronizer()->compute();
1666 };
1667
1668 m_trace_mng->info() << "Computing group synchronization information for " << name();
1669 meshvisitor::visitGroups(this, action);
1670}
1671
1672/*---------------------------------------------------------------------------*/
1673/*---------------------------------------------------------------------------*/
1674
1676name() const
1677{
1678 return m_name;
1679}
1680
1681/*---------------------------------------------------------------------------*/
1682/*---------------------------------------------------------------------------*/
1683
1685dimension()
1686{
1687 return m_mesh->dimension();
1688}
1689
1690/*---------------------------------------------------------------------------*/
1691/*---------------------------------------------------------------------------*/
1692
1694nbNode()
1695{
1696 return m_mesh->nbNode();
1697}
1698
1699/*---------------------------------------------------------------------------*/
1700/*---------------------------------------------------------------------------*/
1701
1703nbEdge()
1704{
1705 return m_mesh->nbEdge();
1706}
1707
1708/*---------------------------------------------------------------------------*/
1709/*---------------------------------------------------------------------------*/
1710
1712nbFace()
1713{
1714 return m_mesh->nbFace();
1715}
1716
1717/*---------------------------------------------------------------------------*/
1718/*---------------------------------------------------------------------------*/
1719
1721nbCell()
1722{
1723 return m_mesh->nbCell();
1724}
1725
1726/*---------------------------------------------------------------------------*/
1727/*---------------------------------------------------------------------------*/
1728
1730nbItem(eItemKind ik)
1731{
1732 return m_mesh->nbItem(ik);
1733}
1734
1735/*---------------------------------------------------------------------------*/
1736/*---------------------------------------------------------------------------*/
1737
1739allNodes()
1740{
1741 if (m_default_arcane_families[IK_Node])
1742 return m_default_arcane_families[IK_Node]->allItems();
1743 else
1744 return NodeGroup{};
1745}
1746
1747/*---------------------------------------------------------------------------*/
1748/*---------------------------------------------------------------------------*/
1749
1751allEdges()
1752{
1753 if (m_default_arcane_families[IK_Edge])
1754 return m_default_arcane_families[IK_Edge]->allItems();
1755 else
1756 return EdgeGroup{};
1757}
1758
1759/*---------------------------------------------------------------------------*/
1760/*---------------------------------------------------------------------------*/
1761
1763allFaces()
1764{
1765 if (m_default_arcane_families[IK_Face])
1766 return m_default_arcane_families[IK_Face]->allItems();
1767 else
1768 return FaceGroup{};
1769}
1770
1771/*---------------------------------------------------------------------------*/
1772/*---------------------------------------------------------------------------*/
1773
1775allCells()
1776{
1777 if (m_default_arcane_families[IK_Cell])
1778 return m_default_arcane_families[IK_Cell]->allItems();
1779 else
1780 return CellGroup{};
1781}
1782
1783/*---------------------------------------------------------------------------*/
1784/*---------------------------------------------------------------------------*/
1785
1787ownNodes()
1788{
1789 if (m_default_arcane_families[IK_Node])
1790 return m_default_arcane_families[IK_Node]->allItems().own();
1791 else
1792 return NodeGroup{};
1793}
1794
1795/*---------------------------------------------------------------------------*/
1796/*---------------------------------------------------------------------------*/
1797
1799ownEdges()
1800{
1801 if (m_default_arcane_families[IK_Edge])
1802 return m_default_arcane_families[IK_Edge]->allItems().own();
1803 else
1804 return EdgeGroup{};
1805}
1806
1807/*---------------------------------------------------------------------------*/
1808/*---------------------------------------------------------------------------*/
1809
1811ownFaces()
1812{
1813 if (m_default_arcane_families[IK_Face])
1814 return m_default_arcane_families[IK_Face]->allItems().own();
1815 else
1816 return FaceGroup{};
1817}
1818
1819/*---------------------------------------------------------------------------*/
1820/*---------------------------------------------------------------------------*/
1821
1823ownCells()
1824{
1825 if (m_default_arcane_families[IK_Cell])
1826 return m_default_arcane_families[IK_Cell]->allItems().own();
1827 else
1828 return CellGroup{};
1829}
1830
1831/*---------------------------------------------------------------------------*/
1832/*---------------------------------------------------------------------------*/
1833
1835outerFaces()
1836{
1837 if (m_default_arcane_families[IK_Cell])
1838 return m_default_arcane_families[IK_Cell]->allItems().outerFaceGroup();
1839 else
1840 return FaceGroup{};
1841}
1842
1843/*---------------------------------------------------------------------------*/
1844/*---------------------------------------------------------------------------*/
1845
1846mesh::PolyhedralFamily* mesh::PolyhedralMesh::
1847_createItemFamily(eItemKind ik, const String& name)
1848{
1849 m_mesh->addFamily(ik, name);
1850 m_arcane_families.push_back(std::make_unique<PolyhedralFamily>(this, ik, name));
1851 auto current_family = m_arcane_families.back().get();
1852 if (m_default_arcane_families[ik] == nullptr) {
1853 m_default_arcane_families[ik] = current_family;
1854 _updateMeshInternalList(ik);
1855 }
1856 m_item_family_collection.add(current_family);
1857 current_family->build();
1858 return current_family;
1859}
1860
1861/*---------------------------------------------------------------------------*/
1862/*---------------------------------------------------------------------------*/
1863
1864IItemFamily* mesh::PolyhedralMesh::
1865createItemFamily(eItemKind ik, const String& name)
1866{
1867 return _createItemFamily(ik, name);
1868}
1869
1870/*---------------------------------------------------------------------------*/
1871/*---------------------------------------------------------------------------*/
1872
1873void mesh::PolyhedralMesh::
1874_createUnitMesh()
1875{
1876 createItemFamily(IK_Cell, "CellFamily");
1877 createItemFamily(IK_Node, "NodeFamily");
1878 auto cell_family = m_default_arcane_families[IK_Cell];
1879 auto node_family = m_default_arcane_families[IK_Node];
1880 Int64UniqueArray cell_uids{ 0 }, node_uids{ 0, 1, 2, 3, 4, 5 };
1881 // todo add a cell_lids struct (containing future)
1882 PolyhedralTools::ItemLocalIds cell_lids, node_lids;
1883 m_mesh->scheduleAddItems(cell_family, cell_uids.constView(), cell_lids);
1884 m_mesh->scheduleAddItems(node_family, node_uids.constView(), node_lids);
1885 int nb_node = 6;
1886 Int64UniqueArray node_cells_uids{ 0, 0, 0, 0, 0, 0 };
1887 m_mesh->scheduleAddConnectivity(cell_family, cell_lids, nb_node, node_family, node_uids, String{ "CellToNodes" });
1888 m_mesh->scheduleAddConnectivity(node_family, node_lids, 1, cell_family,
1889 node_cells_uids, String{ "NodeToCells" });
1890 m_mesh->applyScheduledOperations();
1891 cell_family->endUpdate();
1892 node_family->endUpdate();
1893 endUpdate();
1894 // Mimic what IMeshModifier::endUpdate would do => default families are completed.
1895 // Families created after a first endUpdate call are not default families
1896}
1897
1898/*---------------------------------------------------------------------------*/
1899/*---------------------------------------------------------------------------*/
1900
1902endUpdate()
1903{
1904 // create empty default families not already created
1905 for (auto ik = 0; ik < NB_ITEM_KIND; ++ik) {
1906 if (m_default_arcane_families[ik] == nullptr && ik != eItemKind::IK_DoF) {
1907 String name = String::concat(itemKindName((eItemKind)ik), "EmptyFamily");
1908 m_empty_arcane_families[ik] = std::make_unique<mesh::PolyhedralFamily>(this, (eItemKind)ik, name);
1909 m_default_arcane_families[ik] = m_empty_arcane_families[ik].get();
1910 }
1911 }
1912}
1913
1914/*---------------------------------------------------------------------------*/
1915/*---------------------------------------------------------------------------*/
1916
1917IItemFamily* mesh::PolyhedralMesh::
1918nodeFamily()
1919{
1920 return m_default_arcane_families[IK_Node];
1921}
1922
1923/*---------------------------------------------------------------------------*/
1924/*---------------------------------------------------------------------------*/
1925
1926IItemFamily* mesh::PolyhedralMesh::
1927edgeFamily()
1928{
1929 return m_default_arcane_families[IK_Edge];
1930}
1931
1932/*---------------------------------------------------------------------------*/
1933/*---------------------------------------------------------------------------*/
1934
1935IItemFamily* mesh::PolyhedralMesh::
1936faceFamily()
1937{
1938 return m_default_arcane_families[IK_Face];
1939}
1940
1941/*---------------------------------------------------------------------------*/
1942/*---------------------------------------------------------------------------*/
1943
1944IItemFamily* mesh::PolyhedralMesh::
1945cellFamily()
1946{
1947 return m_default_arcane_families[IK_Cell];
1948}
1949
1950void mesh::PolyhedralMesh::
1951_updateMeshInternalList(eItemKind kind)
1952{
1953 switch (kind) {
1954 case IK_Cell:
1955 m_mesh_item_internal_list.cells = m_default_arcane_families[kind]->itemsInternal();
1956 m_mesh_item_internal_list._internalSetCellSharedInfo(m_default_arcane_families[kind]->commonItemSharedInfo());
1957 break;
1958 case IK_Face:
1959 m_mesh_item_internal_list.faces = m_default_arcane_families[kind]->itemsInternal();
1960 m_mesh_item_internal_list._internalSetFaceSharedInfo(m_default_arcane_families[kind]->commonItemSharedInfo());
1961 break;
1962 case IK_Edge:
1963 m_mesh_item_internal_list.edges = m_default_arcane_families[kind]->itemsInternal();
1964 m_mesh_item_internal_list._internalSetEdgeSharedInfo(m_default_arcane_families[kind]->commonItemSharedInfo());
1965 break;
1966 case IK_Node:
1967 m_mesh_item_internal_list.nodes = m_default_arcane_families[kind]->itemsInternal();
1968 m_mesh_item_internal_list._internalSetNodeSharedInfo(m_default_arcane_families[kind]->commonItemSharedInfo());
1969 break;
1970 case IK_DoF:
1971 case IK_Particle:
1972 case IK_Unknown:
1973 break;
1974 }
1975}
1976
1977/*---------------------------------------------------------------------------*/
1978/*---------------------------------------------------------------------------*/
1979
1980mesh::PolyhedralFamily* mesh::PolyhedralMesh::
1981_itemFamily(eItemKind ik)
1982{
1983 return m_default_arcane_families[ik];
1984}
1985
1986/*---------------------------------------------------------------------------*/
1987/*---------------------------------------------------------------------------*/
1988
1989IItemFamily* mesh::PolyhedralMesh::
1991{
1992 return _itemFamily(ik);
1993}
1994
1995/*---------------------------------------------------------------------------*/
1996/*---------------------------------------------------------------------------*/
1997
1998ItemTypeMng* mesh::PolyhedralMesh::
1999itemTypeMng() const
2000{
2001 return m_item_type_mng;
2002}
2003
2004/*---------------------------------------------------------------------------*/
2005/*---------------------------------------------------------------------------*/
2006
2007mesh::PolyhedralFamily* mesh::PolyhedralMesh::
2008_findItemFamily(eItemKind ik, const String& name, bool create_if_needed)
2009{
2010 // Check if is a default family
2011 auto found_family = _itemFamily(ik);
2012 if (found_family) {
2013 if (found_family->name() == name)
2014 return found_family;
2015 }
2016 for (auto& family : m_arcane_families) {
2017 if (family->itemKind() == ik && family->name() == name)
2018 return family.get();
2019 }
2020 if (!create_if_needed)
2021 return nullptr;
2022 return _createItemFamily(ik, name);
2023}
2024
2025/*---------------------------------------------------------------------------*/
2026/*---------------------------------------------------------------------------*/
2027
2028IItemFamily* mesh::PolyhedralMesh::
2029findItemFamily(eItemKind ik, const String& name, bool create_if_needed, bool register_modifier_if_created)
2030{
2031 ARCANE_UNUSED(register_modifier_if_created); // IItemFamilyModifier not yet used in polyhedral mesh
2032 return _findItemFamily(ik, name, create_if_needed);
2033}
2034
2035/*---------------------------------------------------------------------------*/
2036/*---------------------------------------------------------------------------*/
2037
2038mesh::PolyhedralFamily* mesh::PolyhedralMesh::
2039arcaneDefaultFamily(eItemKind ik)
2040{
2041 return m_default_arcane_families[ik];
2042}
2043
2044/*---------------------------------------------------------------------------*/
2045/*---------------------------------------------------------------------------*/
2046
2049{
2050 ARCANE_ASSERT(m_arcane_node_coords, ("Node coordinates not yet loaded."));
2051 return *m_arcane_node_coords;
2052}
2053
2054/*---------------------------------------------------------------------------*/
2055/*---------------------------------------------------------------------------*/
2056
2057ItemGroup mesh::PolyhedralMesh::
2058findGroup(const String& name)
2059{
2060 ItemGroup group;
2061 for (auto& family : m_arcane_families) {
2062 group = family->findGroup(name);
2063 if (!group.null())
2064 return group;
2065 }
2066 return group;
2067}
2068
2069/*---------------------------------------------------------------------------*/
2070/*---------------------------------------------------------------------------*/
2071
2073groups()
2074{
2075 m_all_groups.clear();
2076 for (auto& family : m_arcane_families) {
2077 for (ItemGroupCollection::Enumerator i_group(family->groups()); ++i_group;)
2078 m_all_groups.add(*i_group);
2079 }
2080 return m_all_groups;
2081}
2082
2083/*---------------------------------------------------------------------------*/
2084/*---------------------------------------------------------------------------*/
2085
2088{
2089 for (auto& family : m_arcane_families) {
2090 family->destroyGroups();
2091 }
2092}
2093
2094/*---------------------------------------------------------------------------*/
2095/*---------------------------------------------------------------------------*/
2096
2097IItemFamilyCollection mesh::PolyhedralMesh::
2098itemFamilies()
2099{
2100 return m_item_family_collection;
2101}
2102
2103/*---------------------------------------------------------------------------*/
2104/*---------------------------------------------------------------------------*/
2105
2106IMeshInternal* mesh::PolyhedralMesh::
2108{
2109 return m_internal_api.get();
2110}
2111
2112/*---------------------------------------------------------------------------*/
2113/*---------------------------------------------------------------------------*/
2114
2115IMeshCompactMng* mesh::PolyhedralMesh::
2117{
2118 return m_compact_mng.get();
2119}
2120
2121/*---------------------------------------------------------------------------*/
2122/*---------------------------------------------------------------------------*/
2123
2124void mesh::PolyhedralMesh::
2125addItems(Int64ConstArrayView unique_ids, Int32ArrayView local_ids, eItemKind ik, const String& family_name)
2126{
2127 ARCANE_ASSERT((unique_ids.size() == local_ids.size()), ("local and unique ids arrays must have same size"))
2128 auto* item_family = _findItemFamily(ik, family_name, false);
2129 PolyhedralTools::ItemLocalIds item_local_ids;
2130 m_mesh->scheduleAddItems(item_family, unique_ids, item_local_ids);
2131 auto mesh_state = m_mesh->applyScheduledOperations();
2132 item_local_ids.fillArrayView(local_ids, mesh_state);
2133}
2134
2135/*---------------------------------------------------------------------------*/
2136/*---------------------------------------------------------------------------*/
2137
2138void mesh::PolyhedralMesh::
2139addItems(Int64ConstArrayView unique_ids, Int32ArrayView local_ids, Int32ConstArrayView owners, eItemKind ik, const String& family_name)
2140{
2141 ARCANE_ASSERT((unique_ids.size() == local_ids.size() && (unique_ids.size() == owners.size())), ("local/unique ids and owners arrays must have same size"))
2142 auto* item_family = _findItemFamily(ik, family_name, false);
2143 PolyhedralTools::ItemLocalIds item_local_ids;
2144 m_mesh->scheduleAddItems(item_family, unique_ids, owners, item_local_ids);
2145 auto mesh_state = m_mesh->applyScheduledOperations();
2146 item_local_ids.fillArrayView(local_ids, mesh_state);
2147}
2148
2149/*---------------------------------------------------------------------------*/
2150/*---------------------------------------------------------------------------*/
2151
2152void mesh::PolyhedralMesh::
2153removeItems(Int32ConstArrayView local_ids, eItemKind ik, const String& family_name)
2154{
2155 auto* item_family = _findItemFamily(ik, family_name, false);
2156 if (!item_family) {
2157 ARCANE_FATAL("ItemFamily with name {0} and kind {1} does not exist in the mesh.", family_name, ik);
2158 }
2159 m_mesh->scheduleRemoveItems(item_family, local_ids);
2160 m_mesh->applyScheduledOperations();
2161}
2162
2163/*---------------------------------------------------------------------------*/
2164/*---------------------------------------------------------------------------*/
2165
2166void mesh::PolyhedralMesh::
2167removeItems(Int32ConstArrayView local_ids, IItemFamily* family)
2168{
2169 if (local_ids.empty())
2170 return;
2171 if (!family) {
2172 ARCANE_FATAL("Invalid IItemFamily passed to removeItems.");
2173 }
2174 removeItems(local_ids, family->itemKind(), family->name());
2175}
2176
2177/*---------------------------------------------------------------------------*/
2178/*---------------------------------------------------------------------------*/
2179
2181addNodes(Int64ConstArrayView nodes_uid, Int32ArrayView nodes_lid)
2182{
2183 addItems(nodes_uid, nodes_lid, IK_Node, nodeFamily()->name());
2184}
2185
2186/*---------------------------------------------------------------------------*/
2187/*---------------------------------------------------------------------------*/
2188
2191{
2192 m_trace_mng->info() << "PolyhedralMesh::_exchangeItems() do_compact?=" << "false"
2193 << " nb_exchange=" << 0 << " version=" << 0;
2194 _exchangeItems();
2195 String check_exchange = platform::getEnvironmentVariable("ARCANE_CHECK_EXCHANGE");
2196 if (!check_exchange.null()) {
2197 m_mesh_checker.checkGhostCells();
2198 m_trace_mng->pwarning() << "CHECKING SYNCHRONISATION !";
2199 m_mesh_checker.checkVariablesSynchronization();
2200 m_mesh_checker.checkItemGroupsSynchronization();
2201 }
2202 if (checkLevel() >= 2)
2203 m_mesh_checker.checkValidMesh();
2204 else if (checkLevel() >= 1)
2205 m_mesh_checker.checkValidConnectivity();
2206}
2207
2208/*---------------------------------------------------------------------------*/
2209/*---------------------------------------------------------------------------*/
2210
2211void mesh::PolyhedralMesh::
2212_exchangeItems()
2213{
2214 // todo handle submeshes, cf. DynamicMesh
2215
2216 Trace::Setter mci(traceMng(), _className());
2217
2218 if (!m_is_dynamic)
2219 ARCANE_FATAL("property isDynamic() has to be 'true'");
2220
2221 if (arcane_debug_load_balancing) {
2222 for (auto& family : m_arcane_families) {
2223 family->itemsNewOwner().checkIfSync();
2224 }
2225 }
2226
2227 IMeshExchanger* iexchanger = m_mesh_exchange_mng->beginExchange();
2228
2229 // If no entity to exchange return
2230 if (iexchanger->computeExchangeInfos()) {
2231 m_trace_mng->pwarning() << "No load balance is performed";
2232 m_mesh_exchange_mng->endExchange();
2233 return;
2234 }
2235
2236 // Do exchange info
2237 iexchanger->processExchange();
2238
2239 // Remove items no longer on the current subdomain
2240 iexchanger->removeNeededItems();
2241
2242 // Update groups : remove gone entities
2243 // invalidate computed groups
2244 {
2245 auto action = [](ItemGroup& group) {
2246 if (group.internal()->hasComputeFunctor() || group.isLocalToSubDomain())
2247 group.invalidate();
2248 else
2249 group.internal()->removeSuppressedItems();
2250 };
2251 meshvisitor::visitGroups(this, action);
2252 }
2253
2254 iexchanger->allocateReceivedItems();
2255
2256 // Equivalent of DynamicMesh::_internalEndUpdateInit
2257 _endUpdateFamilies();
2258 _computeFamilySynchronizeInfos();
2259
2260 // Update groups
2261 iexchanger->updateItemGroups();
2262
2263 _computeGroupSynchronizeInfos();
2264
2265 iexchanger->updateVariables();
2266
2267 // Equivalent DynamicMesh::_internalEndUpdateFinal(bool)
2268 // check mesh is conform with reference (complete sequential connectivity on a file)
2269 m_mesh_checker.checkMeshFromReferenceFile();
2270 _notifyEndUpdateForFamilies();
2271
2272 iexchanger->finalizeExchange();
2273
2274 m_mesh_exchange_mng->endExchange();
2275
2276 // // todo handle extra ghost
2277 // if (m_extra_ghost_cells_builder->hasBuilder() || m_extra_ghost_particles_builder->hasBuilder())
2278 // this->endUpdate(true,false);
2279 // else
2280 this->endUpdate();
2281}
2282
2283/*---------------------------------------------------------------------------*/
2284/*---------------------------------------------------------------------------*/
2285
2288{
2289 // do nothing for now
2290 auto want_dump = false;
2291 auto need_compact = false;
2292 m_trace_mng->info(4) << "DynamicMesh::prepareForDump() name=" << name()
2293 << " need_compact?=" << need_compact
2294 << " want_dump?=" << want_dump
2295 << " timestamp=" << 0;
2296
2297 {
2299 m_mesh_events.eventObservable(t).notify(MeshEventArgs(this, t));
2300 }
2301
2302 // todo use Properties
2303 if (want_dump) {
2304 for (auto& family : m_arcane_families) {
2305 family->prepareForDump();
2306 }
2307 }
2308
2309 {
2311 m_mesh_events.eventObservable(t).notify(MeshEventArgs(this, t));
2312 }
2313}
2314
2315/*---------------------------------------------------------------------------*/
2316/*---------------------------------------------------------------------------*/
2317
2320{
2321 return allCells().activeCellGroup();
2322}
2323
2324/*---------------------------------------------------------------------------*/
2325/*---------------------------------------------------------------------------*/
2326
2328{
2329 return allCells().ownActiveCellGroup();
2330}
2331
2332/*---------------------------------------------------------------------------*/
2333/*---------------------------------------------------------------------------*/
2334
2336allLevelCells(const Integer& level)
2337{
2338 return allCells().levelCellGroup(level);
2339}
2340
2341/*---------------------------------------------------------------------------*/
2342/*---------------------------------------------------------------------------*/
2343
2345ownLevelCells(const Integer& level)
2346{
2347 return allCells().ownLevelCellGroup(level);
2348}
2349
2350/*---------------------------------------------------------------------------*/
2351/*---------------------------------------------------------------------------*/
2352
2355{
2356 return allCells().activeFaceGroup();
2357}
2358
2359/*---------------------------------------------------------------------------*/
2360/*---------------------------------------------------------------------------*/
2361
2364{
2365 return allCells().ownActiveFaceGroup();
2366}
2367
2368/*---------------------------------------------------------------------------*/
2369/*---------------------------------------------------------------------------*/
2370
2373{
2374 return allCells().innerActiveFaceGroup();
2375}
2376
2377/*---------------------------------------------------------------------------*/
2378/*---------------------------------------------------------------------------*/
2379
2382{
2383 return allCells().outerActiveFaceGroup();
2384}
2385
2386/*---------------------------------------------------------------------------*/
2387/*---------------------------------------------------------------------------*/
2388
2389IMeshUtilities* mesh::PolyhedralMesh::
2390utilities()
2391{
2392 return m_mesh_utilities.get();
2393}
2394
2395/*---------------------------------------------------------------------------*/
2396/*---------------------------------------------------------------------------*/
2397
2400{
2401 IItemFamily* item_family = _itemFamily(ik);
2402 ARCANE_CHECK_POINTER(item_family);
2403 return item_family->itemsNewOwner();
2404}
2405
2406/*---------------------------------------------------------------------------*/
2407/*---------------------------------------------------------------------------*/
2408
2410checkLevel() const
2411{
2412 return m_mesh_checker.checkLevel();
2413}
2414
2415/*---------------------------------------------------------------------------*/
2416/*---------------------------------------------------------------------------*/
2417
2418IItemFamilyNetwork* mesh::PolyhedralMesh::
2420{
2421 return m_item_family_network.get();
2422}
2423
2424/*---------------------------------------------------------------------------*/
2425/*---------------------------------------------------------------------------*/
2426
2427IGhostLayerMng* mesh::PolyhedralMesh::
2428ghostLayerMng() const
2429{
2430 return m_ghost_layer_mng.get();
2431}
2432
2433/*---------------------------------------------------------------------------*/
2434/*---------------------------------------------------------------------------*/
2435
2436IMeshModifierInternal* mesh::PolyhedralMesh::
2438{
2439 return m_internal_api.get();
2440}
2441
2442/*---------------------------------------------------------------------------*/
2443/*---------------------------------------------------------------------------*/
2444
2445mesh::PolyhedralMeshImpl* mesh::PolyhedralMesh::_impl()
2446{
2447 return m_mesh.get();
2448}
2449
2450/*---------------------------------------------------------------------------*/
2451/*---------------------------------------------------------------------------*/
2452
2453} // End namespace Arcane
2454
2455/*---------------------------------------------------------------------------*/
2456/*---------------------------------------------------------------------------*/
2457
2458#else // ARCANE_HAS_POLYHEDRAL_MESH_TOOLS
2459
2460/*---------------------------------------------------------------------------*/
2461/*---------------------------------------------------------------------------*/
2462
2463namespace Arcane::mesh
2464{
2467} // namespace Arcane::mesh
2468
2469/*---------------------------------------------------------------------------*/
2470/*---------------------------------------------------------------------------*/
2471
2472Arcane::mesh::PolyhedralMesh::
2473~PolyhedralMesh() = default;
2474
2475/*---------------------------------------------------------------------------*/
2476/*---------------------------------------------------------------------------*/
2477
2478Arcane::mesh::PolyhedralMesh::
2479PolyhedralMesh(ISubDomain* subdomain, const MeshBuildInfo& mbi)
2480: EmptyMesh{ subdomain->traceMng() }
2481, m_subdomain{ subdomain }
2482, m_mesh{ nullptr }
2483, m_mesh_kind(mbi.meshKind())
2484{
2485}
2486
2487/*---------------------------------------------------------------------------*/
2488/*---------------------------------------------------------------------------*/
2489
2490void Arcane::mesh::PolyhedralMesh::
2491read([[maybe_unused]] const String& filename)
2492{
2493 _errorEmptyMesh();
2494}
2495
2496/*---------------------------------------------------------------------------*/
2497/*---------------------------------------------------------------------------*/
2498
2499void Arcane::mesh::PolyhedralMesh::
2500allocateItems(const Arcane::ItemAllocationInfo& item_allocation_info)
2501{
2502 ARCANE_UNUSED(item_allocation_info);
2503 _errorEmptyMesh();
2504}
2505
2506/*---------------------------------------------------------------------------*/
2507/*---------------------------------------------------------------------------*/
2508
2509#endif // ARCANE_HAS_POLYHEDRAL_MESH_TOOLS
2510
2511/*---------------------------------------------------------------------------*/
2512/*---------------------------------------------------------------------------*/
2513
2514namespace Arcane
2515{
2516
2517class ARCANE_MESH_EXPORT PolyhedralMeshFactory
2518: public AbstractService
2519, public IMeshFactory
2520{
2521 public:
2522
2523 explicit PolyhedralMeshFactory(const ServiceBuildInfo& sbi)
2524 : AbstractService(sbi)
2525 {}
2526
2527 public:
2528
2529 void build() override {}
2530 IPrimaryMesh* createMesh(IMeshMng* mm, const MeshBuildInfo& build_info) override
2531 {
2533 return new mesh::PolyhedralMesh(sd, build_info);
2534 }
2535
2536 static String name() { return "ArcanePolyhedralMeshFactory"; }
2537};
2538
2540 ServiceProperty(PolyhedralMeshFactory::name().localstr(), ST_Application),
2542
2543/*---------------------------------------------------------------------------*/
2544/*---------------------------------------------------------------------------*/
2545
2546#if ARCANE_HAS_POLYHEDRAL_MESH_TOOLS
2547
2548/*---------------------------------------------------------------------------*/
2549/*---------------------------------------------------------------------------*/
2550
2552factoryName() const
2553{
2554 return PolyhedralMeshFactory::name();
2555}
2556
2557/*---------------------------------------------------------------------------*/
2558/*---------------------------------------------------------------------------*/
2559
2560#endif // ARCANE_HAS_POLYHEDRAL_MESH_TOOLS
2561
2562/*---------------------------------------------------------------------------*/
2563/*---------------------------------------------------------------------------*/
2564
2565} // End namespace Arcane
2566
2567/*---------------------------------------------------------------------------*/
2568/*---------------------------------------------------------------------------*/
#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_CHECK_POINTER2(ptr, text)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
This file contains the various service factories and macros for registering services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
constexpr Integer size() const noexcept
Returns the size of the array.
SmallSpan< const T > constSmallSpan() const
Immutable view of this array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
void clear()
Removes all elements from the collection.
static Integer kindsToConnectivity(eItemKind kindA, eItemKind kindB)
Type to connectivity conversion.
virtual ITraceMng * traceMng()=0
Associated message manager.
virtual NodeGroup ownNodes()=0
Group of all domain-specific nodes.
virtual MeshHandle handle() const =0
Handle on this mesh.
virtual IItemFamily * nodeFamily()=0
Returns the node family.
virtual String name() const =0
Mesh name.
virtual Integer nbCell()=0
Number of mesh cells.
virtual CellGroup ownCells()=0
Group of all domain-specific cells.
virtual FaceGroup ownFaces()=0
Group of all domain-specific faces.
virtual FaceGroup allFaces()=0
Group of all faces.
virtual Integer nbEdge()=0
Number of mesh edges.
virtual IItemFamily * itemFamily(eItemKind ik)=0
Returns the entity family of type ik.
virtual IItemFamily * edgeFamily()=0
Returns the edge family.
virtual Integer nbNode()=0
Number of mesh nodes.
virtual FaceGroup outerFaces()=0
Group of all faces on the boundary.
virtual IItemFamily * findItemFamily(eItemKind ik, const String &name, bool create_if_needed=false, bool register_modifier_if_created=false)=0
Returns the family named name.
virtual Integer nbItem(eItemKind ik)=0
Number of elements of type ik.
virtual Integer dimension()=0
Mesh dimension (1D, 2D, or 3D).
virtual IItemFamily * faceFamily()=0
Returns the face family.
virtual EdgeGroup ownEdges()=0
Group of all domain-specific edges.
virtual NodeGroup allNodes()=0
Group of all nodes.
virtual CellGroup allCells()=0
Group of all cells.
virtual Integer nbFace()=0
Number of mesh faces.
virtual IItemFamily * cellFamily()=0
Returns the cell family.
virtual IItemFamily * createItemFamily(eItemKind ik, const String &name)=0
Create a particle family named name.
virtual EdgeGroup allEdges()=0
Group of all edges.
Interface for managing the compaction of mesh families.
Management of mesh family compaction.
Interface of the service managing mesh reading.
Internal part of IMesh.
Mesh manager interface.
Definition IMeshMng.h:41
virtual IVariableMng * variableMng() const =0
Variable manager associated with this manager.
Internal part of IMeshModifier.
virtual void addNodes(Int64ConstArrayView nodes_uid, Int32ArrayView nodes_lid=Int32ArrayView())=0
Adds nodes.
virtual IMeshModifierInternal * _modifierInternalApi()=0
Internal API for Arcane.
virtual VariableNodeReal3 & nodesCoordinates()=0
Node coordinates.
virtual FaceGroup outerActiveFaces()=0
Group of all active faces on the boundary.
virtual void destroyGroups()=0
Destroys all groups of all families.
virtual IMeshUtilities * utilities()=0
Associated utility functions interface.
virtual CellGroup allLevelCells(const Integer &level)=0
Group of all cells of level level.
virtual FaceGroup innerActiveFaces()=0
Group of all active faces.
virtual ItemGroupCollection groups()=0
List of groups.
virtual ItemGroup findGroup(const String &name)=0
Returns the group with name name or a null group if none exists.
virtual String factoryName() const =0
Name of the factory used to create the mesh.
virtual IMeshInternal * _internalApi()=0
Internal Arcane API.
virtual CellGroup allActiveCells()=0
virtual FaceGroup allActiveFaces()=0
Group of all active faces.
virtual ItemTypeMng * itemTypeMng() const =0
Associated entity type manager.
virtual void prepareForDump()=0
Prepares the instance for dumping.
virtual CellGroup ownActiveCells()=0
Group of all active cells specific to the domain.
virtual CellGroup ownLevelCells(const Integer &level)=0
Group of all cells specific to the domain of level level.
virtual IGhostLayerMng * ghostLayerMng() const =0
Associated ghost layer manager.
virtual FaceGroup ownActiveFaces()=0
Group of all active faces specific to the domain.
virtual IItemFamilyNetwork * itemFamilyNetwork()=0
Family network interface (connected families).
virtual IMeshCompactMng * _compactMng()=0
virtual Integer checkLevel() const =0
Current check level.
virtual void exchangeItems()=0
Changes the owning subdomains of entities.
virtual VariableItemInt32 & itemsNewOwner(eItemKind kind)=0
Variable containing the identifier of the owning subdomain.
Interface of the subdomain manager.
Definition ISubDomain.h:78
virtual ISubDomain * internalSubDomain() const =0
Temporary internal function to retrieve the subdomain.
virtual IVariableMngInternal * _internalApi()=0
Internal Arcane API.
@ II_FrontCellIsFirst
The first cell of the entity is the front cell.
Definition ItemFlags.h:54
@ II_NeedRemove
The entity must be removed.
Definition ItemFlags.h:63
@ II_HasBackCell
The entity has a back cell.
Definition ItemFlags.h:53
@ II_SubDomainBoundary
The entity is at the boundary of two subdomains.
Definition ItemFlags.h:60
@ II_Suppressed
The entity has just been suppressed.
Definition ItemFlags.h:58
@ II_Boundary
The entity is on the boundary.
Definition ItemFlags.h:51
@ II_HasFrontCell
The entity has a front cell.
Definition ItemFlags.h:52
@ II_BackCellIsFirst
The first cell of the entity is the back cell.
Definition ItemFlags.h:55
FaceGroup activeFaceGroup() const
Group of active faces.
Definition ItemGroup.cc:344
FaceGroup innerActiveFaceGroup() const
Group of internal faces of the elements of this group.
Definition ItemGroup.cc:371
FaceGroup ownActiveFaceGroup() const
Group of active faces belonging to the domain of the elements of this group.
Definition ItemGroup.cc:356
CellGroup levelCellGroup(const Integer &level) const
Group of level l cells of the elements of this group.
Definition ItemGroup.cc:321
CellGroup ownActiveCellGroup() const
Group of own active cells of the elements of this group.
Definition ItemGroup.cc:309
CellGroup ownLevelCellGroup(const Integer &level) const
Group of own level l cells of the elements of this group.
Definition ItemGroup.cc:333
FaceGroup outerActiveFaceGroup() const
Group of active external faces of the elements of this group.
Definition ItemGroup.cc:383
CellGroup activeCellGroup() const
AMR.
Definition ItemGroup.cc:297
FaceGroup outerFaceGroup() const
Group of external faces of the elements of this group.
Definition ItemGroup.cc:282
Parameters necessary for building a mesh.
void build() override
Build-level construction of the service.
IPrimaryMesh * createMesh(IMeshMng *mm, const MeshBuildInfo &build_info) override
Creates a mesh with the information from build_info.
Structure containing the information to create a service.
Service creation properties.
Manager for the policies of a family of entities.
Interface for the mesh exchange manager between subdomains.
void endUpdate()
Notifies the instance that mesh modification is finished.
ItemVectorViewT< DoF > DoFVectorView
View over a vector of degrees of freedom.
Definition ItemTypes.h:316
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
ItemGroupT< Face > FaceGroup
Group of faces.
Definition ItemTypes.h:179
ItemGroupT< Edge > EdgeGroup
Group of edges.
Definition ItemTypes.h:174
ItemGroupT< Node > NodeGroup
Group of nodes.
Definition ItemTypes.h:168
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
ItemVariableScalarRefT< Real3 > VariableItemReal3
3D coordinate type quantity
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
String getEnvironmentVariable(const String &name)
Environment variable named name.
Array< Int64 > Int64Array
Dynamic one-dimensional array of 64-bit integers.
Definition UtilsTypes.h:119
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:333
Collection< ItemGroup > ItemGroupCollection
Collection of mesh item groups.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:476
Collection< IItemFamily * > ItemFamilyCollection
Collection of item families.
Collection< IItemFamily * > IItemFamilyCollection
Collection of item families.
@ ST_Application
The service is used at the application level.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:474
SmallSpan< const Real3 > Real3ConstSmallSpan
Read-only view of a 1D array of Real3.
Definition UtilsTypes.h:626
eMeshEventType
Events generated by IMesh.
Definition MeshEvents.h:30
@ EndPrepareDump
Event sent at the end of prepareForDump().
Definition MeshEvents.h:34
@ BeginPrepareDump
Event sent at the beginning of prepareForDump().
Definition MeshEvents.h:32
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:447
eItemKind
Mesh entity type.
@ IK_Particle
Particle mesh entity.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Unknown
Unknown or uninitialized mesh entity.
@ IK_Face
Face mesh entity.
@ IK_DoF
Degree of Freedom mesh entity.
@ IK_Edge
Edge mesh entity.
SmallSpan< const Int64 > Int64ConstSmallSpan
Read-only view of a 1D array of 64-bit integers.
Definition UtilsTypes.h:610
ARCCORE_SERIALIZE_EXPORT Ref< ISerializer > createSerializer()
Creates an instance of ISerializer.
const char * itemKindName(eItemKind kind)
Entity kind name.
Array< Int32 > Int32Array
Dynamic one-dimensional array of 32-bit integers.
Definition UtilsTypes.h:121
UniqueArray< String > StringUniqueArray
Dynamic 1D array of strings.
Definition UtilsTypes.h:353
Span< const Int32 > Int32ConstSpan
Read-only view of a 1D array of 32-bit integers.
Definition UtilsTypes.h:548
SmallSpan< const Int32 > Int32ConstSmallSpan
Read-only view of a 1D array of 32-bit integers.
Definition UtilsTypes.h:612
std::int32_t Int32
Signed integer type of 32 bits.