Arcane  4.1.12.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 Trace::Setter mci(traceMng(), "Mesh");
108
109 ItemGroupImpl& impl = *m_all_group.internal();
110 Integer internal_size = m_internals.size();
111
112 {
113 info(5) << A_FUNCNAME << " " << m_kind_name
114 << " nb_item=" << m_nb_item
115 << " internal size= " << internal_size
116 << " max_local_id=" << maxUsedLocalId();
117#if 0
118 for( Integer i=0; i<internal_size; ++i ){
119 ItemInternal* item = m_internals[i];
120 info() << "Item " << i << " lib=" << item->localId()
121 << " uid=" << item->uniqueId() << " owner=" << item->owner()
122 << " item=" << item
123 << " removed?=" << item->isSuppressed();
124 }
125#endif
126 }
127
128 Integer nb_added_items = m_added_items.size();
129 Integer nb_removed_items = m_removed_items.size();
130 bool test_mode = m_use_new_finalize;
131
132 info(5) << A_FUNCNAME << " " << m_kind_name
133 << " nb_item " << m_nb_item
134 << " internal size " << internal_size
135 << " nb_add=" << nb_added_items
136 << " nb_remove=" << nb_removed_items;
137
138 // GG: switched to OLD in 11/2018. If everything is OK on the IFPEN side
139 // we will be able to permanently remove this.
140#if OLD
141 IParallelMng* pm = m_mesh->parallelMng();
142 // In sequential mode, position the m_owner field of each entity.
143 // TODO: should not be done here, but in the mesh reader...
144 if (!pm->isParallel() && nb_added_items != 0) {
145 const Integer sid = pm->commRank();
146 for (Integer i = 0; i < nb_added_items; ++i)
147 m_internals[m_added_items[i]]->setOwner(sid, sid);
148 }
149#endif
150 // (HP) TODO: We can probably optimize the reorganization via
151 // addItems, removeItems, changeIds...
152 // The problem is that here we must not impact the calculated sub-groups
153 impl.beginTransaction();
154 if (nb_added_items == 0 && nb_removed_items != 0 && test_mode) {
155 impl.removeItems(m_removed_items, true);
156 }
157 else if (nb_added_items != 0 && nb_removed_items == 0 && test_mode) {
158 impl.addItems(m_added_items, true);
159 }
160 else {
161 impl.removeAddItems(m_removed_items, m_added_items, true);
162 }
163 impl.endTransaction();
164
165 // restore integrity of allItems group after this aggressive modification
166 impl.checkNeedUpdate();
167
168#if defined(ARCANE_DEBUG_MESH)
169 if (arcaneIsCheck())
170 m_all_group.checkValid();
171#endif
172 // We must also change the groups of the owned entities
173 // (To be done only in parallel?)
174 m_item_family->notifyItemsOwnerChanged();
175
176#if defined(ARCANE_DEBUG_MESH)
177 if (arcaneIsCheck())
178 checkValid();
179#endif
180
181 m_removed_items.clear();
182 m_added_items.clear();
183}
184
185/*---------------------------------------------------------------------------*/
186/*---------------------------------------------------------------------------*/
187
188void DynamicMeshKindInfos::
189itemsUniqueIdToLocalId(ArrayView<Int64> ids, bool do_fatal) const
190{
191 if (!m_has_unique_id_map)
192 _badUniqueIdMap();
193 if (!arcaneIsCheck()) {
194 if (do_fatal) {
195 for (Integer i = 0, s = ids.size(); i < s; ++i) {
196 Int64 unique_id = ids[i];
197 ids[i] = m_items_map.findLocalId(unique_id);
198 }
199 }
200 else {
201 for (Integer i = 0, s = ids.size(); i < s; ++i) {
202 Int64 unique_id = ids[i];
203 ids[i] = m_items_map.tryFindLocalId(unique_id);
204 }
205 }
206 }
207 else {
208 Integer nb_error = 0;
209 for (Integer i = 0, s = ids.size(); i < s; ++i) {
210 Int64 unique_id = ids[i];
211 ids[i] = m_items_map.tryFindLocalId(unique_id);
212 if ((ids[i] == NULL_ITEM_LOCAL_ID) && do_fatal) {
213 if (nb_error < 10) {
214 error() << "DynamicMeshKindInfos::itemsUniqueIdToLocalId() can't find "
215 << "entity " << m_kind_name << " with global id "
216 << unique_id << " in the subdomain.";
217 }
218 ++nb_error;
219 }
220 }
221 if (nb_error != 0) {
222 if (do_fatal)
223 ARCANE_FATAL("{0} entities not found", nb_error);
224 }
225 }
226}
227
228/*---------------------------------------------------------------------------*/
229/*---------------------------------------------------------------------------*/
230
231void DynamicMeshKindInfos::
232itemsUniqueIdToLocalId(Int32ArrayView local_ids,
233 Int64ConstArrayView unique_ids, bool do_fatal) const
234{
235 if (!m_has_unique_id_map)
236 _badUniqueIdMap();
237 if (!arcaneIsCheck()) {
238 if (do_fatal) {
239 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
240 Int64 unique_id = unique_ids[i];
241 local_ids[i] = (unique_id == NULL_ITEM_UNIQUE_ID) ? NULL_ITEM_LOCAL_ID : m_items_map.findLocalId(unique_id);
242 }
243 }
244 else {
245 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
246 Int64 unique_id = unique_ids[i];
247 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
248 }
249 }
250 }
251 else {
252 Integer nb_error = 0;
253 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
254 Int64 unique_id = unique_ids[i];
255 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
256 if ((local_ids[i] == NULL_ITEM_LOCAL_ID) && do_fatal && unique_id != NULL_ITEM_UNIQUE_ID) {
257 if (nb_error < 10) {
258 error() << "DynamicMeshKindInfos::itemsUniqueIdToLocalId() can't find "
259 << "entity " << m_kind_name << " with global id "
260 << unique_id << " in the subdomain.";
261 }
262 ++nb_error;
263 }
264 }
265 if (nb_error != 0) {
266 if (do_fatal)
267 ARCANE_FATAL("{0} entities not found", nb_error);
268 }
269 }
270}
271
272/*---------------------------------------------------------------------------*/
273/*---------------------------------------------------------------------------*/
274
275void DynamicMeshKindInfos::
276itemsUniqueIdToLocalId(Int32ArrayView local_ids,
277 ConstArrayView<ItemUniqueId> unique_ids, bool do_fatal) const
278{
279 if (!m_has_unique_id_map)
280 _badUniqueIdMap();
281 if (!arcaneIsCheck()) {
282 if (do_fatal) {
283 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
284 Int64 unique_id = unique_ids[i];
285 local_ids[i] = m_items_map.findLocalId(unique_id);
286 }
287 }
288 else {
289 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
290 Int64 unique_id = unique_ids[i];
291 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
292 }
293 }
294 }
295 else {
296 Integer nb_error = 0;
297 for (Integer i = 0, s = unique_ids.size(); i < s; ++i) {
298 Int64 unique_id = unique_ids[i];
299 local_ids[i] = m_items_map.tryFindLocalId(unique_id);
300 if ((local_ids[i] == NULL_ITEM_LOCAL_ID) && do_fatal) {
301 if (nb_error < 10) {
302 error() << "DynamicMeshKindInfos::itemsUniqueIdToLocalId() can't find "
303 << "entity " << m_kind_name << " with global id "
304 << unique_id << " in the subdomain.";
305 }
306 ++nb_error;
307 }
308 }
309 if (nb_error != 0) {
310 if (do_fatal)
311 ARCANE_FATAL("{0} entities not found", nb_error);
312 }
313 }
314}
315
316/*---------------------------------------------------------------------------*/
317/*---------------------------------------------------------------------------*/
318
323
324/*---------------------------------------------------------------------------*/
325/*---------------------------------------------------------------------------*/
326
329{
330 m_all_group = m_mesh->findGroup(m_all_group_name);
331 // Remove all entities
332 m_nb_item = 0;
333 m_internals.clear();
334 _updateItemSharedInfoInternalView();
335 m_free_internals.clear();
336 m_items_map.clear();
339 m_free_internals_in_multi_buffer.clear();
340}
341
342/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
347{
348 Int32 sid = m_mesh->meshPartInfo().partRank();
349
350 debug() << "DynamicMeshKindInfos::checkValid(): " << m_kind_name;
351
352 Integer nb_killed_item = 0;
353 Integer nb_internal = m_internals.size();
354 Integer nb_error = 0;
355
356 // First, item->localId() must correspond to the index
357 // in the m_internal array
358 for (Integer i = 0; i < nb_internal; ++i) {
359 ItemInternal* item = m_internals[i];
360 if (item->localId() != i && nb_error < 10) {
361 error() << "The local id (" << item->localId() << ") of the entity "
362 << m_kind_name << ':' << item->uniqueId() << " is not "
363 << "consistent with its internal value (" << i << ")";
364 ++nb_error;
365 }
366 if (item->isSuppressed()) {
367 ++nb_killed_item;
368 continue;
369 }
370 if (item->owner() == NULL_SUB_DOMAIN_ID && nb_error < 10) {
371 error() << "entity " << m_kind_name << ":lid=" << item->localId()
372 << ":uid=" << item->uniqueId() << " belongs to no subdomain";
373 ++nb_error;
374 }
375
376 if (item->owner() != sid && item->isOwn() && nb_error < 10) {
377 error() << "entity " << m_kind_name << ":lid=" << item->localId()
378 << ":uid=" << item->uniqueId() << " incoherence between isOwn() and owner()"
379 << " " << item->owner() << ' ' << sid;
380 ++nb_error;
381 }
382 }
383 Integer nb_free = m_free_internals.size();
384 if (nb_killed_item != nb_free) {
385 error() << "DynamicMeshKindInfos::checkValid(): " << m_kind_name
386 << ": incoherence between killed and free entities"
387 << " free=" << nb_free
388 << " killed=" << nb_killed_item
389 << " internal=" << nb_internal
390 << " count=" << m_nb_item;
391 ++nb_error;
392 }
393
394 if (nb_error != 0)
395 ARCANE_FATAL("Internal error in the mesh structure mesh={0} part={1}",
396 m_mesh->name(), sid);
397}
398
399/*---------------------------------------------------------------------------*/
400/*---------------------------------------------------------------------------*/
401
402#ifdef OLD
403class ItemParticleCompareWithSuppression
404{
405 public:
406
407 bool operator()(const ItemInternal* item1, const ItemInternal* item2) const
408 {
409 // Deleted entities must be placed at the end of the list
410 //cout << "Compare: " << item1->uniqueId() << " " << item2->uniqueId() << '\n';
411 bool s1 = item1->isSuppressed();
412 bool s2 = item2->isSuppressed();
413 if (s1 && !s2)
414 return false;
415 if (!s1 && s2)
416 return true;
417 Int64 uid1 = Particle(item1).cell(0)->uniqueId();
418 Int64 uid2 = Particle(item2).cell(0)->uniqueId();
419 if (uid1 == uid2)
420 return item1->uniqueId() < item2->uniqueId();
421 return uid1 < uid2;
422 }
423};
424#endif
425
426/*---------------------------------------------------------------------------*/
427/*---------------------------------------------------------------------------*/
428
430{
431 public:
432
433 bool operator()(const ItemLocalIdAndUniqueId& item1, const ItemLocalIdAndUniqueId item2) const
434 {
435 return item1.m_unique_id < item2.m_unique_id;
436 }
437 Integer m_local_id;
438 Integer m_unique_id;
439};
440
441/*---------------------------------------------------------------------------*/
442/*---------------------------------------------------------------------------*/
443
445oldToNewLocalIds() const
446{
447 if (!m_compact_infos)
448 return Int32ConstArrayView();
449 return m_compact_infos->oldToNewLocalIds();
450}
451
452/*---------------------------------------------------------------------------*/
453/*---------------------------------------------------------------------------*/
454
456newToOldLocalIds() const
457{
458 if (!m_compact_infos)
459 return Int32ConstArrayView();
460 return m_compact_infos->newToOldLocalIds();
461}
462
463/*---------------------------------------------------------------------------*/
464/*---------------------------------------------------------------------------*/
480{
481 m_compact_infos = &compact_infos;
482 bool do_sort = compact_infos.compacter()->isSorted();
483
484 if (arcaneIsCheck())
485 checkValid();
486
487 Integer nb_internal = m_internals.size();
488 info(4) << m_kind_name << " beginCompactItems() Family Internal Size=" << nb_internal
489 << " max_id=" << maxUsedLocalId()
490 << " nb_item=" << m_nb_item
491 << " do_sort=" << do_sort;
492
493 if (nb_internal == 0)
494 return;
495
496 UniqueArray<Int32> old_to_new_local_ids(maxUsedLocalId());
497 UniqueArray<Int32> new_to_old_local_ids(m_nb_item);
498 // 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
499 // 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
500 old_to_new_local_ids.fill(NULL_ITEM_LOCAL_ID);
501 // après compactage, il ne peut y avoir que m_nb_item items actifs (et forcément en tête de numérotation)
502 new_to_old_local_ids.fill(NULL_ITEM_LOCAL_ID);
503
504 if (do_sort) {
505 // Fait une copie temporaire des ItemInternal pour le tri
507
508 debug() << "BEGIN = " << items.data() << " " << m_internals.data()
509 << " S1=" << items.size() << " S2=" << m_internals.size();
510 const bool print_infos = false;
511 {
512 ITimerMng* tm = m_mesh->parallelMng()->timerMng();
513 Timer timer(tm, "DynamicMeshKindInfos::beginCompactItems()", Timer::TimerReal);
514 IItemInternalSortFunction* sort_func = m_item_family->itemSortFunction();
515 if (print_infos) {
516 for (Integer i = 0, is = items.size(); i < is; ++i) {
517 info() << "Before Sort: " << i << " uid=" << items[i]->uniqueId()
518 << " lid=" << items[i]->localId()
519 << " destroyed?=" << items[i]->isSuppressed();
520 }
521 }
522 {
523 Timer::Sentry sentry(&timer);
524 sort_func->sortItems(items);
525 }
526 info(4) << "Temps pour trier les entités <" << m_kind_name << "> "
527 << timer.lastActivationTime()
528 << " sort_func_name=" << sort_func->name();
529 info(4) << "Sort Infos: size=" << items.size() << " nb_item=" << m_nb_item;
530 if (print_infos) {
531 for (Integer i = 0, n = items.size(); i < n; ++i) {
532 info() << "After Sort: " << i << " uid=" << items[i]->uniqueId()
533 << " lid=" << items[i]->localId()
534 << " destroyed?=" << items[i]->isSuppressed();
535 }
536 }
537 }
538
539#ifdef ARCANE_TEST_ADD_MESH
540 typedef std::set<ItemInternal*, ItemCompare> ItemSet;
541 ItemSet items_set;
542 items_set.insert(m_internals.begin(), m_internals.end());
544 {
545 ItemSet::const_iterator b = items_set.begin();
546 ItemSet::const_iterator e = items_set.end();
547 for (Integer z = 0; b != e; ++b, ++z)
548 items[z] = *b;
549 }
550#endif
551
552 for (Integer i = 0, n = m_nb_item; i < n; ++i) {
553 Integer current_local_id = items[i]->localId();
554 //info() << "Item: " << " uid=" << items[i]->uniqueId() << " lid="
555 //<< current_local_id << " newid=" << i;
556 old_to_new_local_ids[current_local_id] = i;
557 new_to_old_local_ids[i] = current_local_id;
558 }
559 }
560 else {
561 const bool use_old = true;
562 if (use_old) {
563 info(4) << "USE_OLD_METHOD";
564 Int32ConstArrayView existing_items = m_all_group.internal()->itemsLocalId();
565
566 for (Integer i = 0; i < m_nb_item; ++i) {
567 Integer current_local_id = existing_items[i];
568 old_to_new_local_ids[current_local_id] = i;
569 new_to_old_local_ids[i] = current_local_id;
570 }
571
572 // Place les éléments détruits en fin de liste et vérifie
573 // que le nombre de trous + le nombre d'entités est égal à #nb_internal
574 {
575 Integer old_index = m_nb_item;
576 Integer total_nb = maxUsedLocalId();
577 for (Integer i = 0, n = total_nb; i < n; ++i) {
578 //bool is_destroyed = false;
579 if (old_to_new_local_ids[i] == NULL_ITEM_ID) {
580 //is_destroyed = true;
581 old_to_new_local_ids[i] = old_index;
582 //m_new_to_old_local_ids[old_index] = i;
583 ++old_index;
584 }
585 //debug() << "OLD_TO_NEW i=" << i
586 // << " old=" << m_old_to_new_local_ids[i]
587 // << " destroyed=" << is_destroyed;
588 }
589 if (old_index != total_nb) {
590 ARCANE_FATAL("Family '{0}' bad indices: expected={1} found={2} (nb_internal={3})",
591 itemFamily()->name(), old_index, total_nb, nb_internal);
592 }
593 }
594 }
595 else {
596 // Compactage sans triage, ce qui revient à déplacer les trous à la fin
597
598 // Place les éléments détruits en fin de liste et vérifie
599 // que l'on a bien tout rangé (on conserve l'ordre relatif des items)
600 Integer new_index = 0;
601 Integer free_index = m_nb_item;
602 for (Integer i = 0, n = maxUsedLocalId(); i < n; ++i) {
603 if (m_internals[i]->isSuppressed()) {
604 old_to_new_local_ids[i] = free_index;
605 // m_new_to_old_local_ids[free_index] = i; // non utilisé quand m_new_to_old_local_ids restreint à m_nb_item
606 ++free_index;
607 }
608 else {
609 old_to_new_local_ids[i] = new_index;
610 new_to_old_local_ids[new_index] = i;
611 ++new_index;
612 }
613 //debug() << "OLD_TO_NEW i=" << i
614 // << " old=" << m_old_to_new_local_ids[i]
615 // << " destroyed=" << m_internals[i]->isSuppressed();
616 }
617 if (new_index != m_nb_item) {
618 ARCANE_FATAL("Family '{0}' bad indices: expected={1} found={2}",
619 itemFamily()->name(), m_nb_item, new_index);
620 }
621 }
622 }
623 compact_infos.setOldToNewLocalIds(std::move(old_to_new_local_ids));
624 compact_infos.setNewToOldLocalIds(std::move(new_to_old_local_ids));
625}
626
627/*---------------------------------------------------------------------------*/
628/*---------------------------------------------------------------------------*/
629
630void DynamicMeshKindInfos::
631finishCompactItems(ItemFamilyCompactInfos& compact_infos)
632{
633 if (arcaneIsCheck())
634 checkValid();
635
636 Int32ConstArrayView old_to_new_local_ids = compact_infos.oldToNewLocalIds();
637 Int32ConstArrayView new_to_old_local_ids = compact_infos.newToOldLocalIds();
638
639 Integer nb_internal = m_internals.size();
640
641 info(4) << m_kind_name << " Family Compression: nb_item=" << m_nb_item
642 << " nb_internal=" << nb_internal
643 << " buf_size=" << m_item_internals_buffer->bufferSize()
644 << " nb_allocated_buf=" << m_item_internals_buffer->nbAllocatedBuffer()
645 << " nb_free" << m_free_internals_in_multi_buffer.size();
646
647 if (nb_internal == 0)
648 return;
649
650 // Finalise la réorganisation des structures après un tri
651 // 1. Il faut mettre à jour la structure m_items_map pour référencer
652 // le nouveau local_id
653 // 2. Il faut recopier les valeurs de chaque ItemInternal pour qu'il
654 // soit bien placé dans la nouvelle numérotation.
655 // IMPORTANT: Cette opération doit toujours être la dernière car ensuite
656 // on perd la relation entre les anciens local_ids et les nouveaux à
657 // travers cette structure
658 m_items_map._changeLocalIds(m_internals, old_to_new_local_ids);
659
660 if (m_is_verbose) {
661 info() << "DumpItemsBefore:";
662 _dumpList();
663 }
664
665 // Pour l'instant, utilise un tableau temporaire
666 // TODO: tableau a supprimer
669 UniqueArray<Int32> new_owners(m_nb_item);
670 UniqueArray<Int32> new_flags(m_nb_item);
671 UniqueArray<Int16> new_typeids(m_nb_item);
672
673 for (Integer i = 0, n = m_nb_item; i < n; ++i) {
674 ItemInternal* old_item = m_internals[new_to_old_local_ids[i]];
675 new_uids[i] = old_item->uniqueId().asInt64();
676 new_owners[i] = old_item->owner();
677 new_flags[i] = old_item->flags();
678 new_typeids[i] = old_item->typeId();
679 new_items[i] = *old_item;
680 }
681
682 Integer nb_error = 0;
683 Int32 sid = m_mesh->meshPartInfo().partRank();
684
685 for (Integer i = 0; i < m_nb_item; ++i) {
686 ItemInternal* ii = m_internals[i];
687 *ii = new_items[i];
688 ii->setLocalId(i);
689 ii->setFlags(new_flags[i]);
690 ii->setOwner(new_owners[i], sid);
691 ii->setUniqueId(new_uids[i]);
692 ItemSharedInfo* isi = ItemInternalCompatibility::_getSharedInfo(ii);
693 ii->_setSharedInfo(isi, ItemTypeId(new_typeids[i]));
694 // L'entité est marqué comme créée
695 //_setAdded(ii);
696#ifdef ARCANE_CHECK
697 if (ii->isSuppressed()) {
698 if (nb_error < 10)
699 error() << "Entity deleted from the list of created entities "
700 << ItemPrinter(ii) << " index=" << i;
701 ++nb_error;
702 }
703#endif /* ARCANE_CHECK */
704 }
705
706 // Il faut remplir les m_free_internals_in_multi_buffer avec les entités supprimées
707 // pour qu'elles puissent être réutilisées sinon on va réallouer
708 // des blocs dans m_item_internals_buffer à chaque recréation des
709 // entités
710 for (Integer i = m_nb_item, n = m_internals.size(); i < n; ++i) {
711 // Empile dans l'ordre inverse pour que allocOne()
712 // dépile dans l'ordre des m_internals et profite des
713 // effets de cache.
714 ItemInternal* removed_item = m_internals[m_nb_item + n - (i + 1)];
715 m_free_internals_in_multi_buffer.add(removed_item);
716 }
717
718 // Retaillage optimal des tableaux
719 m_internals.resize(m_nb_item);
720 _updateItemSharedInfoInternalView();
721 m_free_internals.clear();
722
723 if (m_is_verbose) {
724 info() << "DumpItemsAfter:";
725 _dumpList();
726 }
727
728 if (nb_error != 0)
729 ARCANE_FATAL("Error in compacting nb_error={0}", nb_error);
730
731 debug() << "Compression: old=" << nb_internal << " new=" << m_nb_item
732 << " internal=" << m_internals.size()
733 << " free=" << m_free_internals.size();
734
735 // Vide les tableaux de 'compact_infos' car ils ne sont plus valides.
736 compact_infos.clear();
737
738 m_compact_infos = nullptr;
740}
741
742/*---------------------------------------------------------------------------*/
743/*---------------------------------------------------------------------------*/
744
745namespace
746{
747 class _Inverse
748 {
749 public:
750
751 bool operator()(Int32 i1, Int32 i2) const
752 {
753 return i1 > i2;
754 }
755 };
756} // namespace
757
758/*---------------------------------------------------------------------------*/
759/*---------------------------------------------------------------------------*/
760
762clear()
763{
764 Int32ConstArrayView items_id = m_all_group.internal()->itemsLocalId();
765
766 // Pour réutiliser au moins les m_free_internals afin
767 // d'avoir des localId() consécutifs, il faut trier
768 // les ids par ordre décroissant.
769 Int32UniqueArray ids(items_id);
770 std::sort(std::begin(ids), std::end(ids), _Inverse());
771
772 removeMany(ids);
773 //printFreeInternals(10000);
774}
775
776/*---------------------------------------------------------------------------*/
777/*---------------------------------------------------------------------------*/
778
779void DynamicMeshKindInfos::
780printFreeInternals(Integer max_print)
781{
782 Integer nb_free = m_free_internals.size();
783 max_print = math::min(nb_free, max_print);
784 for (Integer i = 0; i < max_print; ++i) {
785 Integer pos = (nb_free - 1) - i;
786 Int32 index = m_free_internals[pos];
787 ItemInternal* iitem = m_internals[index];
788 info() << "I=" << i << " pos=" << pos << " index=" << index
789 << " local_id=" << iitem->localId();
790 }
791}
792
793/*---------------------------------------------------------------------------*/
794/*---------------------------------------------------------------------------*/
795
798{
799 Int64ArrayView uids = *(m_item_family->uniqueIds());
800 Integer nb_item = local_ids.size();
801
802 if (m_has_unique_id_map) {
803 for (Integer i = 0; i < nb_item; ++i) {
804 Int32 lid = local_ids[i];
805 ItemInternal* item = m_internals[lid];
806#ifdef ARCANE_CHECK
807 _checkActiveItem(item);
808#endif
809 _setSuppressed(item);
810 if (uids[lid] != NULL_ITEM_UNIQUE_ID)
811 m_items_map.remove(uids[lid]);
812 }
813 }
814 else {
815 for (Integer i = 0; i < nb_item; ++i) {
816 Int32 lid = local_ids[i];
817 ItemInternal* item = m_internals[lid];
818#ifdef ARCANE_CHECK
819 _checkActiveItem(item);
820#endif
821 _setSuppressed(item);
822 }
823 }
824
825 m_nb_item -= nb_item;
826 Integer nb_removed = m_removed_items.size();
827 m_removed_items.resize(nb_removed + nb_item);
828 memcpy(m_removed_items.data() + nb_removed, local_ids.data(), sizeof(Int32) * nb_item);
829 Integer nb_free = m_free_internals.size();
830 m_free_internals.resize(nb_free + nb_item);
831 memcpy(m_free_internals.data() + nb_free, local_ids.data(), sizeof(Int32) * nb_item);
832}
833
834/*---------------------------------------------------------------------------*/
835/*---------------------------------------------------------------------------*/
836
837void DynamicMeshKindInfos::
838setHasUniqueIdMap(bool v)
839{
840 if (m_nb_item != 0)
841 ARCANE_FATAL("family is not empty");
842 m_has_unique_id_map = v;
843}
844
845/*---------------------------------------------------------------------------*/
846/*---------------------------------------------------------------------------*/
847
848void DynamicMeshKindInfos::
849_checkActiveItem(ItemInternal* item)
850{
851 if (item->isSuppressed())
852 ARCANE_FATAL("Attempting to remove an entity already deleted item={0}",
853 ItemPrinter(item));
854}
855
856/*---------------------------------------------------------------------------*/
857/*---------------------------------------------------------------------------*/
858
859void DynamicMeshKindInfos::
860_dumpList()
861{
862 Integer nb_internal = m_internals.size();
863 Integer computed_nb_item = 0;
864 for (Integer i = 0; i < nb_internal; ++i) {
865 ItemInternal* item = m_internals[i];
866 bool is_suppressed = item->isSuppressed();
867 if (is_suppressed)
868 ++computed_nb_item;
869 info() << "Item: INDEX=" << i
870 << " LID=" << item->localId()
871 << " UID=" << item->uniqueId()
872 << " KILLED=" << is_suppressed;
873 }
874 info() << "EndOfDump: "
875 << " nb_internal=" << nb_internal
876 << " nb_item=" << m_nb_item
877 << " computed_nb_item= " << (nb_internal - computed_nb_item);
878}
879
880/*---------------------------------------------------------------------------*/
881/*---------------------------------------------------------------------------*/
882
883void DynamicMeshKindInfos::
884_badSameUniqueId(Int64 unique_id) const
885{
886 ARCANE_FATAL("duplicate unique id family={0} uid={1}",
887 m_item_family->name(), unique_id);
888}
889
890/*---------------------------------------------------------------------------*/
891/*---------------------------------------------------------------------------*/
892
893void DynamicMeshKindInfos::
894_badUniqueIdMap() const
895{
896 if (m_has_unique_id_map)
897 ARCANE_FATAL("family have unique id map");
898 else
899 ARCANE_FATAL("family does not have unique id map");
900}
901
902/*---------------------------------------------------------------------------*/
903/*---------------------------------------------------------------------------*/
904
905void DynamicMeshKindInfos::
906setItemFamily(ItemFamily* item_family)
907{
908 m_item_family = item_family;
909 m_common_item_shared_info = item_family->commonItemSharedInfo();
910}
911
912/*---------------------------------------------------------------------------*/
913/*---------------------------------------------------------------------------*/
914
915void DynamicMeshKindInfos::
916_updateItemSharedInfoInternalView()
917{
918 if (m_common_item_shared_info)
919 m_common_item_shared_info->m_items_internal = m_internals.constView();
920}
921
922/*---------------------------------------------------------------------------*/
923/*---------------------------------------------------------------------------*/
924
925EventObservableView<const ItemFamilyItemListChangedEventArgs&> DynamicMeshKindInfos::
926itemListChangedEvent()
927{
928 return EventObservableView<const ItemFamilyItemListChangedEventArgs&>(m_item_list_change_event);
929}
930
931/*---------------------------------------------------------------------------*/
932/*---------------------------------------------------------------------------*/
933
934void DynamicMeshKindInfos::
935_notifyRemove2(ItemInternal* item)
936{
937 ItemFamilyItemListChangedEventArgs args(m_item_family, item->localId(), item->uniqueId());
938 m_item_list_change_event.notify(args);
939 args.setIsAdd(false);
940}
941
942/*---------------------------------------------------------------------------*/
943/*---------------------------------------------------------------------------*/
944
945void DynamicMeshKindInfos::
946_notifyAdd2(ItemInternal* item, Int64 uid)
947{
948 ItemFamilyItemListChangedEventArgs args(m_item_family, item->localId(), uid);
949 args.setIsAdd(true);
950 m_item_list_change_event.notify(args);
951}
952
953/*---------------------------------------------------------------------------*/
954/*---------------------------------------------------------------------------*/
955
956} // End namespace Arcane::mesh
957
958/*---------------------------------------------------------------------------*/
959/*---------------------------------------------------------------------------*/
#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.
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:451
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:482
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
eItemKind
Mesh entity type.
std::int32_t Int32
Signed integer type of 32 bits.