Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
DynamicMeshKindInfos.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/* DynamicMeshKindInfos.cc (C) 2000-2025 */
9/* */
10/* Mesh info for a given entity kind. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/FatalErrorException.h"
15#include "arcane/utils/PlatformUtils.h"
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/StringBuilder.h"
18
19#include "arcane/core/IMesh.h"
20#include "arcane/core/IItemFamily.h"
22#include "arcane/core/IParallelMng.h"
23#include "arcane/core/ItemPrinter.h"
24#include "arcane/core/VariableTypes.h"
25#include "arcane/core/Timer.h"
26#include "arcane/core/IItemInternalSortFunction.h"
27#include "arcane/core/ItemFamilyCompactInfos.h"
28#include "arcane/core/IMeshCompacter.h"
29#include "arcane/core/MeshPartInfo.h"
30#include "arcane/core/ItemFamilyItemListChangedEventArgs.h"
31
32#include "arcane/mesh/DynamicMeshKindInfos.h"
33#include "arcane/mesh/ItemFamily.h"
34
35#include <algorithm>
36#include <set>
37
38// #define ARCANE_DEBUG_MESH
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43namespace Arcane::mesh
44{
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
48
50DynamicMeshKindInfos(IMesh* mesh, eItemKind kind, const String& kind_name)
52, m_mesh(mesh)
53, m_item_family(nullptr)
54, m_kind(kind)
55, m_kind_name(kind_name)
56, m_nb_item(0)
57, m_is_verbose(false)
58, m_use_new_finalize(true)
59, m_is_first_finalize(true)
60, m_has_unique_id_map(true)
61, m_compact_infos(nullptr)
63{
64}
65
66/*---------------------------------------------------------------------------*/
67/*---------------------------------------------------------------------------*/
68
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77
78void DynamicMeshKindInfos::
79build()
80{
81 // Create the group containing all entities of this kind.
82 {
83 // If the name of this group changes, it must be updated
84 // the equivalent name in VariableInfo.cc
85 StringBuilder str("All");
86 str += m_kind_name;
87 str += "s";
88 m_all_group_name = str.toString();
90 m_all_group.internal()->setIsAllItems();
91 m_all_group.setLocalToSubDomain(true);
92 }
93 if (!platform::getEnvironmentVariable("ARCANE_OLD_FINALIZE").null()) {
94 m_use_new_finalize = false;
95 pwarning() << "USE OLD FINALIZE";
96 }
97 m_is_first_finalize = true;
98}
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
106{
107 const Int32 nb = uids.size();
108 if (nb == 0)
109 return;
110 // m_free_internals holds localIds to reuse, which would break the "consecutive
111 // from the current size" contract; the multi-buffer free list does not, it is
112 // only storage, and _allocOne() drains it the same way.
113 if (!m_free_internals.empty())
114 ARCANE_FATAL("allocMany() is only valid on a family holding no reusable localId");
115 m_internals.reserve(m_internals.size() + nb);
116 m_added_items.reserve(m_added_items.size() + nb);
117 for (Int32 i = 0; i < nb; ++i) {
118 ItemInternal* new_item = nullptr;
119 if (!m_free_internals_in_multi_buffer.empty()) {
120 new_item = m_free_internals_in_multi_buffer.back();
121 m_free_internals_in_multi_buffer.popBack();
122 }
123 else
124 new_item = m_item_internals_buffer->allocOne();
125 Int32 lid = m_internals.size();
126 new_item->setLocalId(lid);
127 m_internals.add(new_item);
128 m_added_items.add(lid);
129 lids[i] = lid;
130#ifdef ARCANE_ENABLE_EVENT_FOR_DYNAMICMESHKINDINFO
131 // Same notification as allocOne(): a family's item-list event is what some
132 // callers count items with, and a batch must not be silent.
133 _notifyAdd(new_item, uids[i]);
134#endif
135 }
136 m_nb_item += nb;
137 // Once for the whole batch, and not once per item.
138 _updateItemSharedInfoInternalView();
139 if (m_has_unique_id_map) {
140 m_items_map.resize(m_items_map.count() + nb, true);
141 for (Int32 i = 0; i < nb; ++i) {
142 if (!m_items_map.add(uids[i], m_internals[lids[i]]))
143 _badSameUniqueId(uids[i]);
144 }
145 }
146}
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
153{
154 Trace::Setter mci(traceMng(), "Mesh");
155
156 ItemGroupImpl& impl = *m_all_group.internal();
157 Integer internal_size = m_internals.size();
158
159 {
160 info(5) << A_FUNCNAME << " " << m_kind_name
161 << " nb_item=" << m_nb_item
162 << " internal size= " << internal_size
163 << " max_local_id=" << maxUsedLocalId();
164#if 0
165 for( Integer i=0; i<internal_size; ++i ){
166 ItemInternal* item = m_internals[i];
167 info() << "Item " << i << " lib=" << item->localId()
168 << " uid=" << item->uniqueId() << " owner=" << item->owner()
169 << " item=" << item
170 << " removed?=" << item->isSuppressed();
171 }
172#endif
173 }
174
175 Integer nb_added_items = m_added_items.size();
176 Integer nb_removed_items = m_removed_items.size();
177 bool test_mode = m_use_new_finalize;
178
179 info(5) << A_FUNCNAME << " " << m_kind_name
180 << " nb_item " << m_nb_item
181 << " internal size " << internal_size
182 << " nb_add=" << nb_added_items
183 << " nb_remove=" << nb_removed_items;
184
185 // GG: switched to OLD in 11/2018. If everything is OK on the IFPEN side
186 // we will be able to permanently remove this.
187#if OLD
188 IParallelMng* pm = m_mesh->parallelMng();
189 // In sequential mode, position the m_owner field of each entity.
190 // TODO: should not be done here, but in the mesh reader...
191 if (!pm->isParallel() && nb_added_items != 0) {
192 const Integer sid = pm->commRank();
193 for (Integer i = 0; i < nb_added_items; ++i)
194 m_internals[m_added_items[i]]->setOwner(sid, sid);
195 }
196#endif
197 // (HP) TODO: We can probably optimize the reorganization via
198 // addItems, removeItems, changeIds...
199 // The problem is that here we must not impact the calculated sub-groups
200 impl.beginTransaction();
201 if (nb_added_items == 0 && nb_removed_items != 0 && test_mode) {
202 impl.removeItems(m_removed_items, true);
203 }
204 else if (nb_added_items != 0 && nb_removed_items == 0 && test_mode) {
205 impl.addItems(m_added_items, true);
206 }
207 else {
208 impl.removeAddItems(m_removed_items, m_added_items, true);
209 }
210 impl.endTransaction();
211
212 // restore integrity of allItems group after this aggressive modification
213 impl.checkNeedUpdate();
214
215#if defined(ARCANE_DEBUG_MESH)
216 if (arcaneIsCheck())
217 m_all_group.checkValid();
218#endif
219 // We must also change the groups of the owned entities
220 // (To be done only in parallel?)
221 m_item_family->notifyItemsOwnerChanged();
222
223#if defined(ARCANE_DEBUG_MESH)
224 if (arcaneIsCheck())
225 checkValid();
226#endif
227
228 m_removed_items.clear();
229 m_added_items.clear();
230}
231
232/*---------------------------------------------------------------------------*/
233/*---------------------------------------------------------------------------*/
234
235void DynamicMeshKindInfos::
236itemsUniqueIdToLocalId(ArrayView<Int64> ids, bool do_fatal) const
237{
238 if (!m_has_unique_id_map)
239 _badUniqueIdMap();
240 if (!arcaneIsCheck()) {
241 if (do_fatal) {
242 for (Integer i = 0, s = ids.size(); i < s; ++i) {
243 Int64 unique_id = ids[i];
244 ids[i] = m_items_map.findLocalId(unique_id);
245 }
246 }
247 else {
248 for (Integer i = 0, s = ids.size(); i < s; ++i) {
249 Int64 unique_id = ids[i];
250 ids[i] = m_items_map.tryFindLocalId(unique_id);
251 }
252 }
253 }
254 else {
255 Integer nb_error = 0;
256 for (Integer i = 0, s = ids.size(); i < s; ++i) {
257 Int64 unique_id = ids[i];
258 ids[i] = m_items_map.tryFindLocalId(unique_id);
259 if ((ids[i] == NULL_ITEM_LOCAL_ID) && do_fatal) {
260 if (nb_error < 10) {
261 error() << "DynamicMeshKindInfos::itemsUniqueIdToLocalId() can't find "
262 << "entity " << m_kind_name << " with global id "
263 << unique_id << " in the subdomain.";
264 }
265 ++nb_error;
266 }
267 }
268 if (nb_error != 0) {
269 if (do_fatal)
270 ARCANE_FATAL("{0} entities not found", nb_error);
271 }
272 }
273}
274
275/*---------------------------------------------------------------------------*/
276/*---------------------------------------------------------------------------*/
277
278void DynamicMeshKindInfos::
279itemsUniqueIdToLocalId(Int32ArrayView local_ids,
280 Int64ConstArrayView unique_ids, bool do_fatal) const
281{
282 if (!m_has_unique_id_map)
283 _badUniqueIdMap();
284 if (!arcaneIsCheck()) {
285 if (do_fatal) {
286 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
287 Int64 unique_id = unique_ids[i];
288 local_ids[i] = (unique_id == NULL_ITEM_UNIQUE_ID) ? NULL_ITEM_LOCAL_ID : m_items_map.findLocalId(unique_id);
289 }
290 }
291 else {
292 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
293 Int64 unique_id = unique_ids[i];
294 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
295 }
296 }
297 }
298 else {
299 Integer nb_error = 0;
300 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
301 Int64 unique_id = unique_ids[i];
302 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
303 if ((local_ids[i] == NULL_ITEM_LOCAL_ID) && do_fatal && unique_id != NULL_ITEM_UNIQUE_ID) {
304 if (nb_error < 10) {
305 error() << "DynamicMeshKindInfos::itemsUniqueIdToLocalId() can't find "
306 << "entity " << m_kind_name << " with global id "
307 << unique_id << " in the subdomain.";
308 }
309 ++nb_error;
310 }
311 }
312 if (nb_error != 0) {
313 if (do_fatal)
314 ARCANE_FATAL("{0} entities not found", nb_error);
315 }
316 }
317}
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
322void DynamicMeshKindInfos::
323itemsUniqueIdToLocalId(Int32ArrayView local_ids,
324 ConstArrayView<ItemUniqueId> unique_ids, bool do_fatal) const
325{
326 if (!m_has_unique_id_map)
327 _badUniqueIdMap();
328 if (!arcaneIsCheck()) {
329 if (do_fatal) {
330 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
331 Int64 unique_id = unique_ids[i];
332 local_ids[i] = m_items_map.findLocalId(unique_id);
333 }
334 }
335 else {
336 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
337 Int64 unique_id = unique_ids[i];
338 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
339 }
340 }
341 }
342 else {
343 Integer nb_error = 0;
344 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
345 Int64 unique_id = unique_ids[i];
346 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
347 if ((local_ids[i] == NULL_ITEM_LOCAL_ID) && do_fatal) {
348 if (nb_error < 10) {
349 error() << "DynamicMeshKindInfos::itemsUniqueIdToLocalId() can't find "
350 << "entity " << m_kind_name << " with global id "
351 << unique_id << " in the subdomain.";
352 }
353 ++nb_error;
354 }
355 }
356 if (nb_error != 0) {
357 if (do_fatal)
358 ARCANE_FATAL("{0} entities not found", nb_error);
359 }
360 }
361}
362
363/*---------------------------------------------------------------------------*/
364/*---------------------------------------------------------------------------*/
365
370
371/*---------------------------------------------------------------------------*/
372/*---------------------------------------------------------------------------*/
373
376{
377 m_all_group = m_mesh->findGroup(m_all_group_name);
378 // Remove all entities
379 m_nb_item = 0;
380 m_internals.clear();
381 _updateItemSharedInfoInternalView();
382 m_free_internals.clear();
383 m_items_map.clear();
386 m_free_internals_in_multi_buffer.clear();
387}
388
389/*---------------------------------------------------------------------------*/
390/*---------------------------------------------------------------------------*/
391
394{
395 Int32 sid = m_mesh->meshPartInfo().partRank();
396
397 debug() << "DynamicMeshKindInfos::checkValid(): " << m_kind_name;
398
399 Integer nb_killed_item = 0;
400 Integer nb_internal = m_internals.size();
401 Integer nb_error = 0;
402
403 // First, item->localId() must correspond to the index
404 // in the m_internal array
405 for (Integer i = 0; i < nb_internal; ++i) {
406 ItemInternal* item = m_internals[i];
407 if (item->localId() != i && nb_error < 10) {
408 error() << "The local id (" << item->localId() << ") of the entity "
409 << m_kind_name << ':' << item->uniqueId() << " is not "
410 << "consistent with its internal value (" << i << ")";
411 ++nb_error;
412 }
413 if (item->isSuppressed()) {
414 ++nb_killed_item;
415 continue;
416 }
417 if (item->owner() == NULL_SUB_DOMAIN_ID && nb_error < 10) {
418 error() << "entity " << m_kind_name << ":lid=" << item->localId()
419 << ":uid=" << item->uniqueId() << " belongs to no subdomain";
420 ++nb_error;
421 }
422
423 if (item->owner() != sid && item->isOwn() && nb_error < 10) {
424 error() << "entity " << m_kind_name << ":lid=" << item->localId()
425 << ":uid=" << item->uniqueId() << " incoherence between isOwn() and owner()"
426 << " " << item->owner() << ' ' << sid;
427 ++nb_error;
428 }
429 }
430 Integer nb_free = m_free_internals.size();
431 if (nb_killed_item != nb_free) {
432 error() << "DynamicMeshKindInfos::checkValid(): " << m_kind_name
433 << ": incoherence between killed and free entities"
434 << " free=" << nb_free
435 << " killed=" << nb_killed_item
436 << " internal=" << nb_internal
437 << " count=" << m_nb_item;
438 ++nb_error;
439 }
440
441 if (nb_error != 0)
442 ARCANE_FATAL("Internal error in the mesh structure mesh={0} part={1}",
443 m_mesh->name(), sid);
444}
445
446/*---------------------------------------------------------------------------*/
447/*---------------------------------------------------------------------------*/
448
449#ifdef OLD
450class ItemParticleCompareWithSuppression
451{
452 public:
453
454 bool operator()(const ItemInternal* item1, const ItemInternal* item2) const
455 {
456 // Deleted entities must be placed at the end of the list
457 //cout << "Compare: " << item1->uniqueId() << " " << item2->uniqueId() << '\n';
458 bool s1 = item1->isSuppressed();
459 bool s2 = item2->isSuppressed();
460 if (s1 && !s2)
461 return false;
462 if (!s1 && s2)
463 return true;
464 Int64 uid1 = Particle(item1).cell(0)->uniqueId();
465 Int64 uid2 = Particle(item2).cell(0)->uniqueId();
466 if (uid1 == uid2)
467 return item1->uniqueId() < item2->uniqueId();
468 return uid1 < uid2;
469 }
470};
471#endif
472
473/*---------------------------------------------------------------------------*/
474/*---------------------------------------------------------------------------*/
475
477{
478 public:
479
480 bool operator()(const ItemLocalIdAndUniqueId& item1, const ItemLocalIdAndUniqueId item2) const
481 {
482 return item1.m_unique_id < item2.m_unique_id;
483 }
484 Integer m_local_id;
485 Integer m_unique_id;
486};
487
488/*---------------------------------------------------------------------------*/
489/*---------------------------------------------------------------------------*/
490
492oldToNewLocalIds() const
493{
494 if (!m_compact_infos)
495 return Int32ConstArrayView();
496 return m_compact_infos->oldToNewLocalIds();
497}
498
499/*---------------------------------------------------------------------------*/
500/*---------------------------------------------------------------------------*/
501
503newToOldLocalIds() const
504{
505 if (!m_compact_infos)
506 return Int32ConstArrayView();
507 return m_compact_infos->newToOldLocalIds();
508}
509
510/*---------------------------------------------------------------------------*/
511/*---------------------------------------------------------------------------*/
527{
528 m_compact_infos = &compact_infos;
529 bool do_sort = compact_infos.compacter()->isSorted();
530
531 if (arcaneIsCheck())
532 checkValid();
533
534 Integer nb_internal = m_internals.size();
535 info(4) << m_kind_name << " beginCompactItems() Family Internal Size=" << nb_internal
536 << " max_id=" << maxUsedLocalId()
537 << " nb_item=" << m_nb_item
538 << " do_sort=" << do_sort;
539
540 if (nb_internal == 0)
541 return;
542
543 UniqueArray<Int32> old_to_new_local_ids(maxUsedLocalId());
544 UniqueArray<Int32> new_to_old_local_ids(m_nb_item);
545 // m_new_to_old_local_ids[lid] contient l'ancien numéro local de l'entité dont le nouveau numéro local est \a lid
546 // m_old_to_new_local_ids[lid] contient le nouveau numéro local de l'entité dont l'ancien numéro local est \a lid
547 old_to_new_local_ids.fill(NULL_ITEM_LOCAL_ID);
548 // après compactage, il ne peut y avoir que m_nb_item items actifs (et forcément en tête de numérotation)
549 new_to_old_local_ids.fill(NULL_ITEM_LOCAL_ID);
550
551 if (do_sort) {
552 // Fait une copie temporaire des ItemInternal pour le tri
554
555 debug() << "BEGIN = " << items.data() << " " << m_internals.data()
556 << " S1=" << items.size() << " S2=" << m_internals.size();
557 const bool print_infos = false;
558 {
559 ITimerMng* tm = m_mesh->parallelMng()->timerMng();
560 Timer timer(tm, "DynamicMeshKindInfos::beginCompactItems()", Timer::TimerReal);
561 IItemInternalSortFunction* sort_func = m_item_family->itemSortFunction();
562 if (print_infos) {
563 for (Integer i = 0, is = items.size(); i < is; ++i) {
564 info() << "Before Sort: " << i << " uid=" << items[i]->uniqueId()
565 << " lid=" << items[i]->localId()
566 << " destroyed?=" << items[i]->isSuppressed();
567 }
568 }
569 {
570 Timer::Sentry sentry(&timer);
571 sort_func->sortItems(items);
572 }
573 info(4) << "Temps pour trier les entités <" << m_kind_name << "> "
574 << timer.lastActivationTime()
575 << " sort_func_name=" << sort_func->name();
576 info(4) << "Sort Infos: size=" << items.size() << " nb_item=" << m_nb_item;
577 if (print_infos) {
578 for (Integer i = 0, n = items.size(); i < n; ++i) {
579 info() << "After Sort: " << i << " uid=" << items[i]->uniqueId()
580 << " lid=" << items[i]->localId()
581 << " destroyed?=" << items[i]->isSuppressed();
582 }
583 }
584 }
585
586#ifdef ARCANE_TEST_ADD_MESH
587 typedef std::set<ItemInternal*, ItemCompare> ItemSet;
588 ItemSet items_set;
589 items_set.insert(m_internals.begin(), m_internals.end());
591 {
592 ItemSet::const_iterator b = items_set.begin();
593 ItemSet::const_iterator e = items_set.end();
594 for (Integer z = 0; b != e; ++b, ++z)
595 items[z] = *b;
596 }
597#endif
598
599 for (Integer i = 0, n = m_nb_item; i < n; ++i) {
600 Integer current_local_id = items[i]->localId();
601 //info() << "Item: " << " uid=" << items[i]->uniqueId() << " lid="
602 //<< current_local_id << " newid=" << i;
603 old_to_new_local_ids[current_local_id] = i;
604 new_to_old_local_ids[i] = current_local_id;
605 }
606 }
607 else {
608 const bool use_old = true;
609 if (use_old) {
610 info(4) << "USE_OLD_METHOD";
611 Int32ConstArrayView existing_items = m_all_group.internal()->itemsLocalId();
612
613 for (Integer i = 0; i < m_nb_item; ++i) {
614 Integer current_local_id = existing_items[i];
615 old_to_new_local_ids[current_local_id] = i;
616 new_to_old_local_ids[i] = current_local_id;
617 }
618
619 // Place les éléments détruits en fin de liste et vérifie
620 // que le nombre de trous + le nombre d'entités est égal à #nb_internal
621 {
622 Integer old_index = m_nb_item;
623 Integer total_nb = maxUsedLocalId();
624 for (Integer i = 0, n = total_nb; i < n; ++i) {
625 //bool is_destroyed = false;
626 if (old_to_new_local_ids[i] == NULL_ITEM_ID) {
627 //is_destroyed = true;
628 old_to_new_local_ids[i] = old_index;
629 //m_new_to_old_local_ids[old_index] = i;
630 ++old_index;
631 }
632 //debug() << "OLD_TO_NEW i=" << i
633 // << " old=" << m_old_to_new_local_ids[i]
634 // << " destroyed=" << is_destroyed;
635 }
636 if (old_index != total_nb) {
637 ARCANE_FATAL("Family '{0}' bad indices: expected={1} found={2} (nb_internal={3})",
638 itemFamily()->name(), old_index, total_nb, nb_internal);
639 }
640 }
641 }
642 else {
643 // Compactage sans triage, ce qui revient à déplacer les trous à la fin
644
645 // Place les éléments détruits en fin de liste et vérifie
646 // que l'on a bien tout rangé (on conserve l'ordre relatif des items)
647 Integer new_index = 0;
648 Integer free_index = m_nb_item;
649 for (Integer i = 0, n = maxUsedLocalId(); i < n; ++i) {
650 if (m_internals[i]->isSuppressed()) {
651 old_to_new_local_ids[i] = free_index;
652 // m_new_to_old_local_ids[free_index] = i; // non utilisé quand m_new_to_old_local_ids restreint à m_nb_item
653 ++free_index;
654 }
655 else {
656 old_to_new_local_ids[i] = new_index;
657 new_to_old_local_ids[new_index] = i;
658 ++new_index;
659 }
660 //debug() << "OLD_TO_NEW i=" << i
661 // << " old=" << m_old_to_new_local_ids[i]
662 // << " destroyed=" << m_internals[i]->isSuppressed();
663 }
664 if (new_index != m_nb_item) {
665 ARCANE_FATAL("Family '{0}' bad indices: expected={1} found={2}",
666 itemFamily()->name(), m_nb_item, new_index);
667 }
668 }
669 }
670 compact_infos.setOldToNewLocalIds(std::move(old_to_new_local_ids));
671 compact_infos.setNewToOldLocalIds(std::move(new_to_old_local_ids));
672}
673
674/*---------------------------------------------------------------------------*/
675/*---------------------------------------------------------------------------*/
676
677void DynamicMeshKindInfos::
678finishCompactItems(ItemFamilyCompactInfos& compact_infos)
679{
680 if (arcaneIsCheck())
681 checkValid();
682
683 Int32ConstArrayView old_to_new_local_ids = compact_infos.oldToNewLocalIds();
684 Int32ConstArrayView new_to_old_local_ids = compact_infos.newToOldLocalIds();
685
686 Integer nb_internal = m_internals.size();
687
688 info(4) << m_kind_name << " Family Compression: nb_item=" << m_nb_item
689 << " nb_internal=" << nb_internal
690 << " buf_size=" << m_item_internals_buffer->bufferSize()
691 << " nb_allocated_buf=" << m_item_internals_buffer->nbAllocatedBuffer()
692 << " nb_free" << m_free_internals_in_multi_buffer.size();
693
694 if (nb_internal == 0)
695 return;
696
697 // Finalise la réorganisation des structures après un tri
698 // 1. Il faut mettre à jour la structure m_items_map pour référencer
699 // le nouveau local_id
700 // 2. Il faut recopier les valeurs de chaque ItemInternal pour qu'il
701 // soit bien placé dans la nouvelle numérotation.
702 // IMPORTANT: Cette opération doit toujours être la dernière car ensuite
703 // on perd la relation entre les anciens local_ids et les nouveaux à
704 // travers cette structure
705 m_items_map._changeLocalIds(m_internals, old_to_new_local_ids);
706
707 if (m_is_verbose) {
708 info() << "DumpItemsBefore:";
709 _dumpList();
710 }
711
712 // Pour l'instant, utilise un tableau temporaire
713 // TODO: tableau a supprimer
716 UniqueArray<Int32> new_owners(m_nb_item);
717 UniqueArray<Int32> new_flags(m_nb_item);
718 UniqueArray<Int16> new_typeids(m_nb_item);
719
720 for (Integer i = 0, n = m_nb_item; i < n; ++i) {
721 ItemInternal* old_item = m_internals[new_to_old_local_ids[i]];
722 new_uids[i] = old_item->uniqueId().asInt64();
723 new_owners[i] = old_item->owner();
724 new_flags[i] = old_item->flags();
725 new_typeids[i] = old_item->typeId();
726 new_items[i] = *old_item;
727 }
728
729 Integer nb_error = 0;
730 Int32 sid = m_mesh->meshPartInfo().partRank();
731
732 for (Integer i = 0; i < m_nb_item; ++i) {
733 ItemInternal* ii = m_internals[i];
734 *ii = new_items[i];
735 ii->setLocalId(i);
736 ii->setFlags(new_flags[i]);
737 ii->setOwner(new_owners[i], sid);
738 ii->setUniqueId(new_uids[i]);
739 ItemSharedInfo* isi = ItemInternalCompatibility::_getSharedInfo(ii);
740 ii->_setSharedInfo(isi, ItemTypeId(new_typeids[i]));
741 // L'entité est marqué comme créée
742 //_setAdded(ii);
743#ifdef ARCANE_CHECK
744 if (ii->isSuppressed()) {
745 if (nb_error < 10)
746 error() << "Entity deleted from the list of created entities "
747 << ItemPrinter(ii) << " index=" << i;
748 ++nb_error;
749 }
750#endif /* ARCANE_CHECK */
751 }
752
753 // Il faut remplir les m_free_internals_in_multi_buffer avec les entités supprimées
754 // pour qu'elles puissent être réutilisées sinon on va réallouer
755 // des blocs dans m_item_internals_buffer à chaque recréation des
756 // entités
757 for (Integer i = m_nb_item, n = m_internals.size(); i < n; ++i) {
758 // Empile dans l'ordre inverse pour que allocOne()
759 // dépile dans l'ordre des m_internals et profite des
760 // effets de cache.
761 ItemInternal* removed_item = m_internals[m_nb_item + n - (i + 1)];
762 m_free_internals_in_multi_buffer.add(removed_item);
763 }
764
765 // Retaillage optimal des tableaux
766 m_internals.resize(m_nb_item);
767 _updateItemSharedInfoInternalView();
768 m_free_internals.clear();
769
770 if (m_is_verbose) {
771 info() << "DumpItemsAfter:";
772 _dumpList();
773 }
774
775 if (nb_error != 0)
776 ARCANE_FATAL("Error in compacting nb_error={0}", nb_error);
777
778 debug() << "Compression: old=" << nb_internal << " new=" << m_nb_item
779 << " internal=" << m_internals.size()
780 << " free=" << m_free_internals.size();
781
782 // Vide les tableaux de 'compact_infos' car ils ne sont plus valides.
783 compact_infos.clear();
784
785 m_compact_infos = nullptr;
787}
788
789/*---------------------------------------------------------------------------*/
790/*---------------------------------------------------------------------------*/
791
792namespace
793{
794 class _Inverse
795 {
796 public:
797
798 bool operator()(Int32 i1, Int32 i2) const
799 {
800 return i1 > i2;
801 }
802 };
803} // namespace
804
805/*---------------------------------------------------------------------------*/
806/*---------------------------------------------------------------------------*/
807
809clear()
810{
811 Int32ConstArrayView items_id = m_all_group.internal()->itemsLocalId();
812
813 // Pour réutiliser au moins les m_free_internals afin
814 // d'avoir des localId() consécutifs, il faut trier
815 // les ids par ordre décroissant.
816 Int32UniqueArray ids(items_id);
817 std::sort(std::begin(ids), std::end(ids), _Inverse());
818
819 removeMany(ids);
820 //printFreeInternals(10000);
821}
822
823/*---------------------------------------------------------------------------*/
824/*---------------------------------------------------------------------------*/
825
826void DynamicMeshKindInfos::
827printFreeInternals(Integer max_print)
828{
829 Integer nb_free = m_free_internals.size();
830 max_print = math::min(nb_free, max_print);
831 for (Integer i = 0; i < max_print; ++i) {
832 Integer pos = (nb_free - 1) - i;
833 Int32 index = m_free_internals[pos];
834 ItemInternal* iitem = m_internals[index];
835 info() << "I=" << i << " pos=" << pos << " index=" << index
836 << " local_id=" << iitem->localId();
837 }
838}
839
840/*---------------------------------------------------------------------------*/
841/*---------------------------------------------------------------------------*/
842
845{
846 Int64ArrayView uids = *(m_item_family->uniqueIds());
847 Integer nb_item = local_ids.size();
848
849 if (m_has_unique_id_map) {
850 for (Integer i = 0; i < nb_item; ++i) {
851 Int32 lid = local_ids[i];
852 ItemInternal* item = m_internals[lid];
853#ifdef ARCANE_CHECK
854 _checkActiveItem(item);
855#endif
856 _setSuppressed(item);
857 if (uids[lid] != NULL_ITEM_UNIQUE_ID)
858 m_items_map.remove(uids[lid]);
859 }
860 }
861 else {
862 for (Integer i = 0; i < nb_item; ++i) {
863 Int32 lid = local_ids[i];
864 ItemInternal* item = m_internals[lid];
865#ifdef ARCANE_CHECK
866 _checkActiveItem(item);
867#endif
868 _setSuppressed(item);
869 }
870 }
871
872 m_nb_item -= nb_item;
873 Integer nb_removed = m_removed_items.size();
874 m_removed_items.resize(nb_removed + nb_item);
875 memcpy(m_removed_items.data() + nb_removed, local_ids.data(), sizeof(Int32) * nb_item);
876 Integer nb_free = m_free_internals.size();
877 m_free_internals.resize(nb_free + nb_item);
878 memcpy(m_free_internals.data() + nb_free, local_ids.data(), sizeof(Int32) * nb_item);
879}
880
881/*---------------------------------------------------------------------------*/
882/*---------------------------------------------------------------------------*/
883
884void DynamicMeshKindInfos::
885setHasUniqueIdMap(bool v)
886{
887 if (m_nb_item != 0)
888 ARCANE_FATAL("family is not empty");
889 m_has_unique_id_map = v;
890}
891
892/*---------------------------------------------------------------------------*/
893/*---------------------------------------------------------------------------*/
894
895void DynamicMeshKindInfos::
896_checkActiveItem(ItemInternal* item)
897{
898 if (item->isSuppressed())
899 ARCANE_FATAL("Attempting to remove an entity already deleted item={0}",
900 ItemPrinter(item));
901}
902
903/*---------------------------------------------------------------------------*/
904/*---------------------------------------------------------------------------*/
905
906void DynamicMeshKindInfos::
907_dumpList()
908{
909 Integer nb_internal = m_internals.size();
910 Integer computed_nb_item = 0;
911 for (Integer i = 0; i < nb_internal; ++i) {
912 ItemInternal* item = m_internals[i];
913 bool is_suppressed = item->isSuppressed();
914 if (is_suppressed)
915 ++computed_nb_item;
916 info() << "Item: INDEX=" << i
917 << " LID=" << item->localId()
918 << " UID=" << item->uniqueId()
919 << " KILLED=" << is_suppressed;
920 }
921 info() << "EndOfDump: "
922 << " nb_internal=" << nb_internal
923 << " nb_item=" << m_nb_item
924 << " computed_nb_item= " << (nb_internal - computed_nb_item);
925}
926
927/*---------------------------------------------------------------------------*/
928/*---------------------------------------------------------------------------*/
929
930void DynamicMeshKindInfos::
931_badSameUniqueId(Int64 unique_id) const
932{
933 ARCANE_FATAL("duplicate unique id family={0} uid={1}",
934 m_item_family->name(), unique_id);
935}
936
937/*---------------------------------------------------------------------------*/
938/*---------------------------------------------------------------------------*/
939
940void DynamicMeshKindInfos::
941_badUniqueIdMap() const
942{
943 if (m_has_unique_id_map)
944 ARCANE_FATAL("family have unique id map");
945 else
946 ARCANE_FATAL("family does not have unique id map");
947}
948
949/*---------------------------------------------------------------------------*/
950/*---------------------------------------------------------------------------*/
951
952void DynamicMeshKindInfos::
953setItemFamily(ItemFamily* item_family)
954{
955 m_item_family = item_family;
956 m_common_item_shared_info = item_family->commonItemSharedInfo();
957}
958
959/*---------------------------------------------------------------------------*/
960/*---------------------------------------------------------------------------*/
961
962void DynamicMeshKindInfos::
963_updateItemSharedInfoInternalView()
964{
965 if (m_common_item_shared_info)
966 m_common_item_shared_info->m_items_internal = m_internals.constView();
967}
968
969/*---------------------------------------------------------------------------*/
970/*---------------------------------------------------------------------------*/
971
972EventObservableView<const ItemFamilyItemListChangedEventArgs&> DynamicMeshKindInfos::
973itemListChangedEvent()
974{
975 return EventObservableView<const ItemFamilyItemListChangedEventArgs&>(m_item_list_change_event);
976}
977
978/*---------------------------------------------------------------------------*/
979/*---------------------------------------------------------------------------*/
980
981void DynamicMeshKindInfos::
982_notifyRemove2(ItemInternal* item)
983{
984 ItemFamilyItemListChangedEventArgs args(m_item_family, item->localId(), item->uniqueId());
985 m_item_list_change_event.notify(args);
986 args.setIsAdd(false);
987}
988
989/*---------------------------------------------------------------------------*/
990/*---------------------------------------------------------------------------*/
991
992void DynamicMeshKindInfos::
993_notifyAdd2(ItemInternal* item, Int64 uid)
994{
995 ItemFamilyItemListChangedEventArgs args(m_item_family, item->localId(), uid);
996 args.setIsAdd(true);
997 m_item_list_change_event.notify(args);
998}
999
1000/*---------------------------------------------------------------------------*/
1001/*---------------------------------------------------------------------------*/
1002
1003} // End namespace Arcane::mesh
1004
1005/*---------------------------------------------------------------------------*/
1006/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
constexpr Integer size() const noexcept
Returns the size of the array.
void fill(ConstReferenceType value)
Fills the array with the value value.
const T * data() const
Access to the root of the array without any protection.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
Interface of an entity sorting function.
virtual void sortItems(ItemInternalMutableArrayView items)=0
Sorts the entities in the array items.
virtual const String & name() const =0
Name of the sorting function.
virtual bool isSorted() const =0
Indicates whether it wishes to sort the entities in addition to compacting them.
virtual const MeshPartInfo & meshPartInfo() const =0
Mesh part information.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
Interface of a timer manager.
Definition ITimerMng.h:50
bool isSuppressed() const
True if the entity is suppressed.
ItemUniqueId uniqueId() const
Unique number of the entity.
Int32 owner() const
Number of the owning subdomain of the entity.
Int32 flags() const
Flags of the entity.
Int16 typeId() const
Type of the entity.
bool isOwn() const
True if the entity belongs to the subdomain.
Int32 localId() const
Local number (in the subdomain) of the entity.
Information to manage the compaction of entities of a family.
Int32ConstArrayView newToOldLocalIds() const
Conversion between new and old local IDs.
Int32ConstArrayView oldToNewLocalIds() const
Conversion between old and new local IDs.
Brief: Implementation of a mesh entity group.
void setIsAllItems()
Indicates to this group that it is the group of all entities in the family.
void setLocalToSubDomain(bool v)
Sets the boolean indicating if the group is local to the subdomain.
Definition ItemGroup.h:243
ItemGroupImpl * internal() const
Returns the group implementation.
Definition ItemGroup.h:125
Internal structure of a mesh entity.
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
Buffer for multiple allocation.
Definition MultiBuffer.h:45
Particle.
Definition Item.h:1529
Cell cell() const
Cell to which the particle belongs. You must call setCell() before calling this function....
Definition Item.h:1606
Unicode character string constructor.
Sentinel for the timer. The sentinel associated with a timer allows it to be triggered upon its const...
Definition Timer.h:90
Management of a timer.
Definition Timer.h:63
@ TimerReal
Timer using real time.
Definition Timer.h:77
Real lastActivationTime() const
Returns the time (in seconds) spent during the last activation of the timer.
Definition Timer.h:243
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
ITraceMng * traceMng() const
Trace manager.
TraceMessage pwarning() const
1D data vector with value semantics (STL style).
Integer m_nb_item
Group of all entities.
String m_kind_name
Name of the entity kind (Node, Cell, ...).
Integer maxUsedLocalId() const
Largest local ID used.
MultiBufferT< ItemInternal > * m_item_internals_buffer
Buffer to store an instance of ItemInternal.
void finalizeMeshChanged()
Reallocates and recalculates structures after mesh modification.
void removeMany(Int32ConstArrayView local_ids)
Removes a list of entities.
void prepareForDump()
Prepares variables for dumps.
void beginCompactItems(ItemFamilyCompactInfos &compact_infos)
Calculates the new local IDs of the entities so that they are consecutive.
ARCANE_DEPRECATED_240 Int32ConstArrayView oldToNewLocalIds() const
Conversion between old and new local IDs.
UniqueArray< ItemInternal * > m_internals
ItemInternals of the entities.
void readFromDump()
Restores info from dumps.
DynamicMeshKindInfos(IMesh *mesh, eItemKind kind, const String &kind_name)
Creates an instance for a given mesh and kind.
ARCANE_DEPRECATED_240 Int32ConstArrayView newToOldLocalIds() const
Conversion between new and old local IDs.
ItemFamilyCompactInfos * m_compact_infos
Temporary while oldToNewLocalIds() and newToOldLocalIds() exist.
void checkValid()
Checks if the internal structures of the instance are valid.
String m_all_group_name
Name of the group containing all entities.
ItemInternalMap m_items_map
Hash table for uniqueId() -> ItemInternal* conversion.
Int32UniqueArray m_free_internals
List of free ItemInternals from m_item_internals_buffer.
void allocMany(Int64ConstArrayView uids, Int32ArrayView lids)
Allocates every item of uids at once, returning their localIds.
eItemKind m_kind
Corresponding kind.
ItemFamily * m_item_family
Associated mesh family.
ItemGroup createGroup(const String &name, Int32ConstArrayView elements, bool do_override=false) override
Creates an entity group named name containing the entities local_ids.
Int32 tryFindLocalId(Int64 key) const
Returns the localId() associated with key if found, or none otherwise.
Int32 findLocalId(Int64 uid) const
Returns the local number of the unique ID entity uid.
void _changeLocalIds(ArrayView< ItemInternal * > items_internal, ConstArrayView< Int32 > old_to_new_local_ids)
Changes the values of localId().
__host__ __device__ Real2 min(Real2 a, Real2 b)
Returns the minimum of two Real2.
Definition MathUtils.h:346
String getEnvironmentVariable(const String &name)
Environment variable named name.
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:445
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:476
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:474
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:447
eItemKind
Mesh entity type.
std::int32_t Int32
Signed integer type of 32 bits.