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