Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
DynamicMesh.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/* DynamicMesh.cc (C) 2000-2026 */
9/* */
10/* Class for managing an evolving unstructured mesh. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/DynamicMesh.h"
15
16#include "arcane/utils/ValueConvert.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/ITraceMng.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/ArgumentException.h"
21#include "arcane/utils/ScopedPtr.h"
22
23#include "arcane/core/ISubDomain.h"
24#include "arcane/core/ITimeStats.h"
25#include "arcane/core/IVariableMng.h"
26#include "arcane/core/Properties.h"
27#include "arcane/core/SharedVariable.h"
28#include "arcane/core/IParallelMng.h"
29#include "arcane/core/ICaseDocument.h"
31#include "arcane/core/Timer.h"
32#include "arcane/core/ItemPrinter.h"
33#include "arcane/core/IPropertyMng.h"
34#include "arcane/core/CommonVariables.h"
35#include "arcane/core/MeshStats.h"
36#include "arcane/core/IMeshFactory.h"
37#include "arcane/core/IMeshPartitionConstraintMng.h"
38#include "arcane/core/IMeshWriter.h"
39#include "arcane/core/IMeshUtilities.h"
40#include "arcane/core/Connectivity.h"
41#include "arcane/core/FactoryService.h"
42#include "arcane/core/AbstractService.h"
43#include "arcane/core/ServiceBuilder.h"
44#include "arcane/core/MeshToMeshTransposer.h"
45#include "arcane/core/IItemFamilyCompactPolicy.h"
46#include "arcane/core/IItemFamilyExchanger.h"
47#include "arcane/core/IItemFamilySerializer.h"
48#include "arcane/core/IItemFamilyPolicyMng.h"
49#include "arcane/core/IMeshExchanger.h"
50#include "arcane/core/IMeshCompacter.h"
51#include "arcane/core/MeshVisitor.h"
52#include "arcane/core/IVariableSynchronizer.h"
53#include "arcane/core/IParallelReplication.h"
54#include "arcane/core/IMeshMng.h"
55#include "arcane/core/MeshBuildInfo.h"
56#include "arcane/core/ICaseMng.h"
57
58#include "arcane/core/internal/UnstructuredMeshAllocateBuildInfoInternal.h"
59#include "arcane/core/internal/IItemFamilyInternal.h"
60#include "arcane/core/internal/IVariableMngInternal.h"
61#include "arcane/core/internal/IMeshInternal.h"
62#include "arcane/core/internal/IMeshModifierInternal.h"
63
64#include "arcane/mesh/ExtraGhostCellsBuilder.h"
65#include "arcane/mesh/ExtraGhostParticlesBuilder.h"
66
67#include "arcane/mesh/MeshPartitionConstraintMng.h"
68#include "arcane/mesh/ItemGroupsSynchronize.h"
69#include "arcane/mesh/DynamicMeshIncrementalBuilder.h"
70#include "arcane/mesh/OneMeshItemAdder.h"
71#include "arcane/mesh/DynamicMeshChecker.h"
72#include "arcane/mesh/GhostLayerMng.h"
73#include "arcane/mesh/MeshUniqueIdMng.h"
74#include "arcane/mesh/ItemGroupDynamicMeshObserver.h"
75#include "arcane/mesh/ParticleFamily.h"
76#include "arcane/mesh/MeshExchange.h"
77#include "arcane/mesh/UnstructuredMeshUtilities.h"
78#include "arcane/mesh/TiedInterfaceMng.h"
79#include "arcane/mesh/MeshCompactMng.h"
80#include "arcane/mesh/MeshExchangeMng.h"
81#include "arcane/mesh/DynamicMeshMerger.h"
82#include "arcane/mesh/ItemFamilyNetwork.h"
83#include "arcane/mesh/IncrementalItemConnectivity.h"
84#include "arcane/mesh/MeshExchanger.h"
85#include "arcane/mesh/IndexedIncrementalItemConnectivityMng.h"
86#include "arcane/mesh/NodeFamily.h"
87#include "arcane/mesh/EdgeFamily.h"
88#include "arcane/mesh/FaceFamily.h"
89#include "arcane/mesh/CellFamily.h"
90#include "arcane/mesh/DoFFamily.h"
91
93#include "arcane/mesh/MeshRefinement.h"
94#include "arcane/mesh/FaceReorienter.h"
95#include "arcane/mesh/NewItemOwnerBuilder.h"
96
97#include "arcane/mesh/IncrementalItemConnectivity.h"
98#include "arcane/mesh/ItemConnectivityMng.h"
99
100#include "arcane/mesh/internal/DynamicMeshInternal.h"
101
102#include <functional>
103#include <memory>
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108namespace
109{
110// Public properties that the user can set
111const char* PROPERTY_SORT = "sort";
112const char* PROPERTY_COMPACT = "compact";
113const char* PROPERTY_COMPACT_AFTER_ALLOCATE = "compact-after-allocate";
114const char* PROPERTY_DUMP = "dump";
115const char* PROPERTY_DISPLAY_STATS = "display-stats";
116
117// Internal Arcane properties
118const char* PROPERTY_MESH_VERSION = "mesh-version";
119} // namespace
120
121namespace Arcane::mesh
122{
123
124/*---------------------------------------------------------------------------*/
125/*---------------------------------------------------------------------------*/
126
127extern "C++" ARCANE_MESH_EXPORT IItemFamilyPolicyMng*
128createNodeFamilyPolicyMng(ItemFamily* family);
129
130extern "C++" ARCANE_MESH_EXPORT IItemFamilyPolicyMng*
131createEdgeFamilyPolicyMng(ItemFamily* family);
132
133extern "C++" ARCANE_MESH_EXPORT IItemFamilyPolicyMng*
134createFaceFamilyPolicyMng(ItemFamily* family);
135
136extern "C++" ARCANE_MESH_EXPORT IItemFamilyPolicyMng*
137createCellFamilyPolicyMng(ItemFamily* family);
138
139extern "C++" ARCANE_MESH_EXPORT IItemFamilyPolicyMng*
140createParticleFamilyPolicyMng(ItemFamily* family);
141
142extern "C++" ARCANE_MESH_EXPORT IItemFamilyPolicyMng*
143createDoFFamilyPolicyMng(ItemFamily* family);
144
145extern "C++" ARCANE_MESH_EXPORT void
146allocateCartesianMesh(DynamicMesh* mesh, CartesianMeshAllocateBuildInfo& build_info);
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
151// #define ARCANE_DEBUG_DYNAMIC_MESH
152// #define ARCANE_DEBUG_LOAD_BALANCING
153
154#ifdef ARCANE_DEBUG_LOAD_BALANCING
155static bool arcane_debug_load_balancing = true;
156#else
157static bool arcane_debug_load_balancing = false;
158#endif
159
160#ifdef ACTIVATE_PERF_COUNTER
161const std::string DynamicMesh::PerfCounter::m_names[] = {
162 "UPGHOSTLAYER1",
163 "UPGHOSTLAYER2",
164 "UPGHOSTLAYER3",
165 "UPGHOSTLAYER4",
166 "UPGHOSTLAYER5",
167 "UPGHOSTLAYER6",
168 "UPGHOSTLAYER7"
169};
170#endif
171
172/*---------------------------------------------------------------------------*/
173/*---------------------------------------------------------------------------*/
174
175DynamicMesh::
176DynamicMesh(ISubDomain* sub_domain, const MeshBuildInfo& mbi, bool is_submesh)
177: MeshVariables(sub_domain, mbi.name())
178, TraceAccessor(mbi.parallelMngRef()->traceMng())
179, m_sub_domain(sub_domain)
180, m_mesh_mng(sub_domain->meshMng())
181, m_mesh_handle(m_mesh_mng->findMeshHandle(mbi.name()))
182, m_parallel_mng(mbi.parallelMngRef().get())
183, m_variable_mng(sub_domain->variableMng())
184, m_properties(new Properties(sub_domain->propertyMng(), String("ArcaneMeshProperties_") + mbi.name()))
185, m_timestamp(0)
186, m_is_allocated(false)
187, m_dimension(-1)
188, m_name(mbi.name())
189, m_factory_name(mbi.factoryName())
190, m_need_compact(true)
191, m_node_family(nullptr)
192, m_edge_family(nullptr)
193, m_face_family(nullptr)
194, m_cell_family(nullptr)
195, m_parent_mesh(nullptr)
196, m_parent_group(nullptr)
197, m_mesh_utilities(nullptr)
198, m_mesh_builder(nullptr)
199, m_mesh_checker(nullptr)
200, m_submesh_tools(nullptr)
202, m_mesh_refinement(nullptr)
203, m_new_item_owner_builder(nullptr)
204, m_extra_ghost_cells_builder(nullptr)
205, m_extra_ghost_particles_builder(nullptr)
206, m_initial_allocator(this)
207, m_internal_api(std::make_unique<DynamicMeshInternal>(this))
208, m_is_amr_activated(mbi.meshKind().meshAMRKind() != eMeshAMRKind::None)
209, m_amr_type(mbi.meshKind().meshAMRKind())
210, m_is_dynamic(false)
211, m_tied_interface_mng(nullptr)
212, m_is_sub_connectivity_set(false)
213, m_tied_interface_need_prepare_dump(true)
214, m_partition_constraint_mng(nullptr)
215, m_ghost_layer_mng(new GhostLayerMng(m_parallel_mng->traceMng()))
216, m_mesh_unique_id_mng(new MeshUniqueIdMng(m_parallel_mng->traceMng()))
217, m_mesh_exchange_mng(new MeshExchangeMng(this))
218, m_mesh_compact_mng(new MeshCompactMng(this))
219, m_connectivity_policy(InternalConnectivityPolicy::NewOnly)
220, m_mesh_part_info(makeMeshPartInfoFromParallelMng(m_parallel_mng))
221, m_item_type_mng(new ItemTypeMng())
222, m_indexed_connectivity_mng(new IndexedIncrementalItemConnectivityMng(m_parallel_mng->traceMng()))
223, m_mesh_kind(mbi.meshKind())
224{
225 m_node_family = new NodeFamily(this, "Node");
226 m_edge_family = new EdgeFamily(this, "Edge");
227 m_face_family = new FaceFamily(this, "Face");
228 m_cell_family = new CellFamily(this, "Cell");
229
230 _addFamily(m_node_family);
231 _addFamily(m_edge_family);
232 _addFamily(m_face_family);
233 _addFamily(m_cell_family);
234
235 m_properties->setBool(PROPERTY_SORT, true);
236 m_properties->setBool(PROPERTY_COMPACT, true);
237 m_properties->setBool(PROPERTY_COMPACT_AFTER_ALLOCATE, true);
238 m_properties->setBool(PROPERTY_DUMP, true);
239 m_properties->setBool(PROPERTY_DISPLAY_STATS, true);
240 m_properties->setInt32(PROPERTY_MESH_VERSION, 1);
241
242 m_item_internal_list.mesh = this;
243 m_item_internal_list._internalSetNodeSharedInfo(m_node_family->commonItemSharedInfo());
244 m_item_internal_list._internalSetEdgeSharedInfo(m_edge_family->commonItemSharedInfo());
245 m_item_internal_list._internalSetFaceSharedInfo(m_face_family->commonItemSharedInfo());
246 m_item_internal_list._internalSetCellSharedInfo(m_cell_family->commonItemSharedInfo());
247
248 info() << "Is AMR Activated? = " << m_is_amr_activated
249 << " AMR type = " << m_amr_type
250 << " allow_loose_items=" << m_mesh_kind.isNonManifold();
251
252 _printConnectivityPolicy();
253
254 // Adding the family dependencies if asked
255 if (_connectivityPolicy() == InternalConnectivityPolicy::NewWithDependenciesAndLegacy && !is_submesh && !m_is_amr_activated) {
256 m_use_mesh_item_family_dependencies = true;
257 m_item_family_network = new ItemFamilyNetwork(traceMng());
258 _addDependency(m_cell_family, m_node_family);
259 _addDependency(m_cell_family, m_face_family);
260 _addDependency(m_cell_family, m_edge_family);
261 _addDependency(m_face_family, m_node_family);
262 _addDependency(m_edge_family, m_node_family);
263 _addRelation(m_face_family, m_edge_family); // Not seen as a dependency in DynamicMesh : for example not possible to use replaceConnectedItem for Face to Edge...
264 _addRelation(m_face_family, m_face_family);
265 _addRelation(m_face_family, m_cell_family);
266 _addRelation(m_edge_family, m_cell_family);
267 _addRelation(m_edge_family, m_face_family);
268 _addRelation(m_node_family, m_cell_family);
269 _addRelation(m_node_family, m_face_family);
270 _addRelation(m_node_family, m_edge_family);
271 // The relation concerning edge family are only added when the dimension is known since they change with dimension
272 // cf. 3D Cell <-> Faces <-> Edges <-> Nodes
273 // 2D Cell <-> Faces <-> Nodes
274 // <-> Edges <-> Nodes
275 // 1D No edge...
276 m_family_modifiers.add(m_cell_family);
277 m_family_modifiers.add(m_face_family);
278 m_family_modifiers.add(m_node_family);
279 m_family_modifiers.add(m_edge_family);
280 }
281
282 {
283 String s = platform::getEnvironmentVariable("ARCANE_GRAPH_CONNECTIVITY_POLICY");
284#ifdef USE_GRAPH_CONNECTIVITY_POLICY
285 s = "1";
286#endif
287 if (s == "1") {
288 m_item_family_network = new ItemFamilyNetwork(traceMng());
289 info() << "Graph connectivity is activated";
290 m_family_modifiers.add(m_cell_family);
291 m_family_modifiers.add(m_face_family);
292 m_family_modifiers.add(m_node_family);
293 m_family_modifiers.add(m_edge_family);
294 }
295 }
296
297 m_extra_ghost_cells_builder = new ExtraGhostCellsBuilder(this);
298 m_extra_ghost_particles_builder = new ExtraGhostParticlesBuilder(this);
299
300 // To keep compatibility with the existing code, allows not to
301 // save the 'need-compact' attribute. This was added for version 3.10
302 // of Arcane (June 2023). To be removed before end of 2023.
303 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_NO_SAVE_NEED_COMPACT", true))
304 m_do_not_save_need_compact = v.value();
305
306 // Overrides the default value for the numbering mechanism
307 // of uniqueId() for edges and faces.
308 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_GENERATE_UNIQUE_ID_FROM_NODES", true)) {
309 bool is_generate = (v.value() != 0);
310 // Using free entities implies using uniqueId() generation
311 // from nodes.
312 if (!is_generate && meshKind().isNonManifold())
313 is_generate = true;
314 m_mesh_unique_id_mng->setUseNodeUniqueIdToGenerateEdgeAndFaceUniqueId(is_generate);
315 }
316}
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
320
321DynamicMesh::
322~DynamicMesh()
323{
324 // It might be better to throw an exception but in a
325 // destructor this is not necessarily advisable
326 if (m_extra_ghost_cells_builder->hasBuilder())
327 info() << "WARNING: pending ExtraGhostCellsBuilder reference";
328 if (m_extra_ghost_particles_builder->hasBuilder())
329 info() << "WARNING: pending ExtraGhostParticlesBuilder reference";
330
331 m_indexed_connectivity_mng = nullptr;
332 delete m_mesh_compact_mng;
333 delete m_mesh_exchange_mng;
334 delete m_extra_ghost_cells_builder;
335 delete m_extra_ghost_particles_builder;
336 delete m_mesh_unique_id_mng;
337 delete m_ghost_layer_mng;
338 delete m_tied_interface_mng;
339 delete m_partition_constraint_mng;
340 delete m_mesh_utilities;
341 delete m_mesh_builder;
342 delete m_mesh_checker;
344 delete m_mesh_refinement;
345 delete m_submesh_tools;
346 delete m_new_item_owner_builder;
347
348 // Destroys dynamically allocated families.
349 for (IItemFamily* family : m_item_families) {
350 eItemKind kind = family->itemKind();
351 // Only particle or DoF families are dynamically allocated.
352 // TODO: now they are all so they should all be
353 // deallocated by this loop
354 if (kind == IK_Particle || kind == IK_DoF)
355 delete family;
356 }
357 m_properties->destroy();
358 delete m_properties;
359
360 delete m_cell_family;
361 delete m_face_family;
362 delete m_edge_family;
363 delete m_node_family;
364
365 delete m_item_type_mng;
366}
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
371void DynamicMesh::
372build()
373{
374 Trace::Setter mci(traceMng(), _className());
375
376 info() << "Building DynamicMesh name=" << name()
377 << " ItemInternalMapImpl=" << ItemInternalMap::UseNewImpl;
378
379 m_item_type_mng->build(this);
380
381 m_tied_interface_mng = new TiedInterfaceMng(this);
382
383 // IMPORTANT: the first elements of m_item_families must
384 // correspond to the families associated with eItemKind values
385 // (IK_Node, IK_Edge, IK_Face, IK_Cell)
386 for (IItemFamily* family : m_item_families) {
387 _buildAndInitFamily(family);
388 }
389
390 // Allows calling the '_prepareDump' function when a
391 // dump is performed
392 IVariableMng* vm = subDomain()->variableMng();
393 m_observer_pool.addObserver(this,
395 vm->writeObservable());
396 // Allows calling the '_readFromDump' function when a
397 // dump is read
398 m_observer_pool.addObserver(this,
400 vm->readObservable());
401
402 m_mesh_builder = new DynamicMeshIncrementalBuilder(this);
403 m_mesh_checker = new DynamicMeshChecker(this);
404 m_partition_constraint_mng = new MeshPartitionConstraintMng(this);
405
406 if (parentMesh()) {
407 // This can induce segfaults if the DynamicMesh is not used correctly
408 m_submesh_tools = new SubMeshTools(this, m_mesh_builder);
411
412 this->properties()->setBool(PROPERTY_COMPACT, true);
413 this->properties()->setBool(PROPERTY_SORT, true);
414
416 m_parent_group->attachObserver(this, (obs = new ItemGroupDynamicMeshObserver(this)));
417
418 this->endAllocate();
419 Int32ConstArrayView localIds = m_parent_group->itemsLocalId();
420 obs->executeExtend(&localIds);
421 this->endUpdate();
422 }
423 else {
424 m_submesh_tools = 0;
426
427 // GG: does not build m_mesh_refinement if AMR is active
428 // This avoids creating unnecessary variables when AMR is not
429 // requested. The creation of m_mesh_refinement is now
430 // done in readAmrActivator(). This might not be the right place
431 // to do it and it can potentially be moved. It just needs
432 // m_mesh_refinement to be created only if AMR is active.
433 // SDC: OK. Restored because now the AMR (in)active info is known at
434 // construction. Removal of readAmrActivator.
435
436 if (m_is_amr_activated) {
437 if (m_amr_type == eMeshAMRKind::None || m_amr_type == eMeshAMRKind::Cell) {
439 }
440 else if (m_amr_type == eMeshAMRKind::Patch) {
441 ARCANE_FATAL("Patch AMR type is not implemented.");
442 }
443 else if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
444 // The AMR PatchCartesianMeshOnly is not handled by MeshRefinement().
445 // See in CartesianMesh.cc.
446 // TODO: CartesianMeshAMRPatchMng needs it for ghost cells.
447 // See to remove or replace the call to the method
448 // updateGhostLayerFromParent().
450 }
451 }
452 }
453
454 m_internal_api->build();
455}
456
457/*---------------------------------------------------------------------------*/
458/*---------------------------------------------------------------------------*/
459
460IParallelMng* DynamicMesh::
461parallelMng()
462{
463 return m_parallel_mng;
464}
465
466/*---------------------------------------------------------------------------*/
467/*---------------------------------------------------------------------------*/
468
469void DynamicMesh::
470_checkValidItem(ItemInternal* item)
471{
472 if (!item)
473 ARCANE_FATAL("INTERNAL: DynamicMesh: invalid use of a null entity");
474}
475
476/*---------------------------------------------------------------------------*/
477/*---------------------------------------------------------------------------*/
478
479void DynamicMesh::
480prepareForDump()
481{
483}
484
485/*---------------------------------------------------------------------------*/
486/*---------------------------------------------------------------------------*/
487
488void DynamicMesh::
489reloadMesh()
490{
491 Trace::Setter mci(traceMng(), _className());
492 info() << "Reloading the mesh " << name();
493 m_is_allocated = true;
494 Timer timer(subDomain(), "DynamicMesh::reloadMesh", Timer::TimerReal);
495 {
496 Timer::Sentry sentry(&timer);
498 m_mesh_checker->checkMeshFromReferenceFile();
499 }
500 info() << "Time to reallocate the mesh structures (direct method) (unit: second): "
501 << timer.lastActivationTime();
502}
503
504/*---------------------------------------------------------------------------*/
505/*---------------------------------------------------------------------------*/
506
507void DynamicMesh::
508setCheckLevel(Integer level)
509{
510 m_mesh_checker->setCheckLevel(level);
511}
512
513/*---------------------------------------------------------------------------*/
514/*---------------------------------------------------------------------------*/
515
516Integer DynamicMesh::
517checkLevel() const
518{
519 return m_mesh_checker->checkLevel();
520}
521
522/*---------------------------------------------------------------------------*/
523/*---------------------------------------------------------------------------*/
524
525void DynamicMesh::
526checkValidMesh()
527{
528 if (!m_is_allocated)
529 return;
530 m_mesh_checker->checkValidMesh();
531}
532
533/*---------------------------------------------------------------------------*/
534/*---------------------------------------------------------------------------*/
535
536void DynamicMesh::
537checkValidMeshFull()
538{
539 if (!m_is_allocated)
540 return;
541 m_mesh_checker->checkValidMeshFull();
542}
543
544/*---------------------------------------------------------------------------*/
545/*---------------------------------------------------------------------------*/
546
547void DynamicMesh::
548checkValidConnectivity()
549{
550 m_mesh_checker->checkValidConnectivity();
551}
552
553/*---------------------------------------------------------------------------*/
554/*---------------------------------------------------------------------------*/
555
556void DynamicMesh::
557destroyGroups()
558{
559 for (IItemFamily* family : m_item_families) {
560 family->destroyGroups();
561 }
562}
563
564/*---------------------------------------------------------------------------*/
565/*---------------------------------------------------------------------------*/
566
567ItemGroup DynamicMesh::
568findGroup(const String& name)
569{
570 ItemGroup group;
571 for (IItemFamily* family : m_item_families) {
572 group = family->findGroup(name);
573 if (!group.null())
574 return group;
575 }
576 return group;
577}
578
579/*---------------------------------------------------------------------------*/
580/*---------------------------------------------------------------------------*/
581
582ItemGroup DynamicMesh::
583findGroup(const String& name, eItemKind ik, bool create_if_needed)
584{
585 _checkKindRange(ik);
586 IItemFamily* family = m_item_families[ik];
587 return family->findGroup(name, create_if_needed);
588}
589
590/*---------------------------------------------------------------------------*/
591/*---------------------------------------------------------------------------*/
592
593ItemGroup DynamicMesh::
594createGroup(const String& name, eItemKind ik)
595{
596 _checkKindRange(ik);
597 IItemFamily* family = m_item_families[ik];
598 ARCANE_CHECK_PTR(family);
599 return family->findGroup(name);
600}
601
602/*---------------------------------------------------------------------------*/
603/*---------------------------------------------------------------------------*/
604
605ItemGroup DynamicMesh::
606createGroup(const String& name, const ItemGroup& parent)
607{
608 IItemFamily* family = parent.itemFamily();
609 ARCANE_CHECK_PTR(family);
610 return family->createGroup(name, parent);
611}
612
613/*--------------------------------------------------------------------------*/
614/*--------------------------------------------------------------------------*/
615
616void DynamicMesh::
617_computeSynchronizeInfos()
618{
619 _computeFamilySynchronizeInfos();
620 _computeGroupSynchronizeInfos();
621}
622
623/*--------------------------------------------------------------------------*/
624/*--------------------------------------------------------------------------*/
625
626void DynamicMesh::
627_computeFamilySynchronizeInfos()
628{
629 info() << "Computing family synchronization information for " << name();
630 for (IItemFamily* family : m_item_families) {
631 family->computeSynchronizeInfos();
632 }
633
634 // Writes the topology for cell synchronization
635 if (!platform::getEnvironmentVariable("ARCANE_DUMP_VARIABLE_SYNCHRONIZER_TOPOLOGY").null()) {
636 auto* var_syncer = cellFamily()->allItemsSynchronizer();
637 Int32 iteration = subDomain()->commonVariables().globalIteration();
638 String file_name = String::format("{0}_sync_topology_iter{1}.json", name(), iteration);
639 mesh_utils::dumpSynchronizerTopologyJSON(var_syncer, file_name);
640 }
641}
642
643/*--------------------------------------------------------------------------*/
644/*--------------------------------------------------------------------------*/
645
646void DynamicMesh::
647_computeGroupSynchronizeInfos()
648{
649 auto action = [](ItemGroup& group) {
650 if (group.hasSynchronizer())
651 group.synchronizer()->compute();
652 };
653
654 info() << "Computing group synchronization information for " << name();
655 meshvisitor::visitGroups(this, action);
656}
657
658/*--------------------------------------------------------------------------*/
659/*--------------------------------------------------------------------------*/
660
662groups()
663{
664 m_all_groups.clear();
665 for (IItemFamily* family : m_item_families) {
666 for (ItemGroupCollection::Enumerator i_group(family->groups()); ++i_group;)
667 m_all_groups.add(*i_group);
668 }
669 return m_all_groups;
670}
671
672/*---------------------------------------------------------------------------*/
673/*---------------------------------------------------------------------------*/
677void DynamicMesh::
678initializeVariables(const XmlNode& init_node)
679{
680 // TEMPORARY: copies the owner() field for each family into
681 // the corresponding variable.
682 for (IItemFamily* family : m_item_families) {
683 VariableItemInt32& items_owner(family->itemsNewOwner());
684 ENUMERATE_ITEM (iitem, family->allItems()) {
685 Item item = *iitem;
686 items_owner[iitem] = item.owner();
687 }
688 }
689
690 ICaseDocumentFragment* doc = subDomain()->caseMng()->caseDocumentFragment();
691 XmlNode root = doc->rootElement();
692 if (root.null())
693 return;
694
695 bool has_error = false;
696 IVariableMng* vm = m_sub_domain->variableMng();
697 XmlNodeList child_list = init_node.children(String("variable"));
698 for (const auto& i : child_list) {
699 String var_name = i.attrValue("nom");
700 IVariable* var = vm->findMeshVariable(this, var_name);
701 if (!var) {
702 error() << "Failed to initialize the variable '" << var_name
703 << "' : no variable with that name exists";
704 has_error = true;
705 continue;
706 }
707 // Does not initialize unused variables.
708 if (!var->isUsed())
709 continue;
710
711 // Tests if the variable has a family. Normally this is always
712 // the case because we used findMeshVariable() to find the variable.
713 IItemFamily* family = var->itemFamily();
714 if (!family) {
715 error() << "Variable '" << var->name() << "' has no family";
716 continue;
717 }
718 String grp_name = i.attrValue("groupe");
719 ItemGroup grp = family->findGroup(grp_name);
720
721 if (grp.null()) {
722 error() << "Failed to initialize the variable '" << var_name
723 << "' on the group `" << grp_name << "' : "
724 << "No group with that name exists for family '" << family->name() << "'\n";
725 has_error = true;
726 continue;
727 }
728 debug() << "Read value variable `" << grp_name
729 << "' `" << var_name << "' " << var;
730 String val_str = i.attrValue("valeur");
731 bool ret = var->initialize(grp, val_str);
732 if (ret) {
733 error() << "Failed to initialized the variable '" << var_name
734 << "' on the group `" << grp_name << "'";
735 has_error = true;
736 continue;
737 }
738 }
739 if (has_error)
740 ARCANE_FATAL("Variables initialization failed");
741}
742
743/*---------------------------------------------------------------------------*/
744/*---------------------------------------------------------------------------*/
745
746// NOTE: This method probably does not work if there are variables
747// partial because the groups they rely on will be destroyed
748// (To be checked)
749
750void DynamicMesh::
751deallocate()
752{
753 if (!m_is_allocated)
754 ARCANE_FATAL("mesh is not allocated");
755
756 clearItems();
758 m_mesh_builder->resetAfterDeallocate();
759
760 m_is_allocated = false;
761 m_mesh_dimension = (-1);
762}
763
764/*---------------------------------------------------------------------------*/
765/*---------------------------------------------------------------------------*/
766
767void DynamicMesh::
768allocateCells(Integer mesh_nb_cell, Int64ConstArrayView cells_infos, bool one_alloc)
769{
770 ARCANE_FATAL_IF(m_is_allocated, "mesh has already been allocated (via endAllocate() or allocateCells())");
771 if (mesh_nb_cell == 0 && !cells_infos.empty())
772 ARCANE_FATAL("Can not dynamically compute the number of cells");
773
774 Trace::Setter mci(traceMng(), _className());
775
776 setEstimatedCells(mesh_nb_cell);
777
778 Timer timer(subDomain(), "AllocateCells", Timer::TimerReal);
779 {
780 Timer::Sentry sentry(&timer);
781 _allocateCells(mesh_nb_cell, cells_infos);
782 if (one_alloc)
783 endAllocate();
784 }
785 info() << "Time to build the mesh structures (indirect method) (unit: second): "
786 << timer.lastActivationTime();
787}
788
789/*---------------------------------------------------------------------------*/
790/*---------------------------------------------------------------------------*/
791
792void DynamicMesh::
793endAllocate()
794{
795 ARCANE_FATAL_IF(m_is_allocated, "mesh has already been allocated (via endAllocate() or allocateCells())");
796
797 Trace::Setter mci(traceMng(), _className());
798
799 _checkDimension(); // HP: add control if endAllocate is called
800 _checkConnectivity(); // without any cell allocation
801
802 bool print_stats = true;
803 ITimeStats* ts = m_sub_domain->timeStats();
805 if (print_stats) {
806 info() << "Begin compute face unique ids";
808 }
809 m_mesh_builder->computeFacesUniqueIds();
810 if (print_stats) {
811 info() << "Begin compute ghost layer";
813 }
814 m_mesh_builder->addGhostLayers(true);
815 if (print_stats) {
816 info() << "Begin compact items";
818 }
819 _allocateCells2(m_mesh_builder);
820
821 if (m_properties->getBool(PROPERTY_COMPACT_AFTER_ALLOCATE))
822 _compactItems(true, false);
823
824 _compactItemInternalReferences();
825 for (IItemFamily* family : m_item_families)
826 family->_internalApi()->endAllocate();
827
828 if (print_stats)
830
831#ifdef ARCANE_DEBUG_DYNAMIC_MESH
832 {
833 String file_name("mesh-end-allocate");
834 if (parallelMng()->isParallel()) {
835 file_name += "-";
836 file_name += m_mesh_rank;
837 }
838 mesh_utils::writeMeshConnectivity(this, file_name);
839 }
840#endif
841
843 m_mesh_checker->checkMeshFromReferenceFile();
844
845 // Positions the owners so that it is like after
846 // an exchange. This is not strictly necessary
847 // but it ensures consistency with
848 // other calls to setOwnersFromCells()
849 if (parallelMng()->isParallel()) {
850 String s = platform::getEnvironmentVariable("ARCANE_CHANGE_OWNER_ON_INIT");
851 if (!s.null()) {
852 info() << "** Set owners from cells";
853 _setOwnersFromCells();
854 }
855 }
856
857 // Notifies the families that the mesh has just been updated
858 // So that they can recalculate the information they want.
859 _notifyEndUpdateForFamilies();
860
862
863 m_is_allocated = true;
864 if (arcaneIsCheck())
866
867 // Displays the statistics of the new mesh
868 {
869 MeshStats ms(traceMng(), this, m_parallel_mng);
870 ms.dumpStats();
871 }
872}
873
874/*---------------------------------------------------------------------------*/
875/*---------------------------------------------------------------------------*/
876
877void DynamicMesh::
878_allocateCells(Integer mesh_nb_cell,
879 Int64ConstArrayView cells_infos,
880 Int32ArrayView cells,
881 bool allow_build_face)
882{
883 Trace::Setter mci(traceMng(), _className());
884 _checkDimension();
885 _checkConnectivity();
886 Int32 rank = meshRank();
887 if (m_use_mesh_item_family_dependencies)
888 m_mesh_builder->addCells3(mesh_nb_cell, cells_infos, rank, cells, allow_build_face);
889 else
890 m_mesh_builder->addCells(mesh_nb_cell, cells_infos, rank, cells, allow_build_face);
891}
892
893/*---------------------------------------------------------------------------*/
894/*---------------------------------------------------------------------------*/
895
896void DynamicMesh::
897addCells(Integer nb_cell,
898 Int64ConstArrayView cells_infos,
899 Int32ArrayView cells)
900{
901 const bool allow_build_face = (m_parallel_mng->commSize() == 1);
902 _allocateCells(nb_cell, cells_infos, cells, allow_build_face);
903}
904
905/*---------------------------------------------------------------------------*/
906/*---------------------------------------------------------------------------*/
907
908void DynamicMesh::
909addCells(const MeshModifierAddCellsArgs& args)
910{
911 bool allow_build_face = args.isAllowBuildFaces();
912 // In parallel, we cannot build faces on the fly
913 // (because it is necessary to generate a uniqueId(), and this ID would not be consistent
914 // between the sub-domains)
915 if (m_parallel_mng->commSize() > 1)
916 allow_build_face = false;
917 _allocateCells(args.nbCell(), args.cellInfos(), args.cellLocalIds(), allow_build_face);
918}
919
920/*---------------------------------------------------------------------------*/
921/*---------------------------------------------------------------------------*/
922
923void DynamicMesh::
924addCells(ISerializer* buffer)
925{
926 _addCells(buffer, 0);
927}
928
929/*---------------------------------------------------------------------------*/
930/*---------------------------------------------------------------------------*/
931
932void DynamicMesh::
933addCells(ISerializer* buffer, Int32Array& cells_local_id)
934{
935 _addCells(buffer, &cells_local_id);
936}
937
938/*---------------------------------------------------------------------------*/
939/*---------------------------------------------------------------------------*/
940
941void DynamicMesh::
942_addCells(ISerializer* buffer, Int32Array* cells_local_id)
943{
944 Trace::Setter mci(traceMng(), _className());
945 _checkDimension();
946 _checkConnectivity();
947 if (!itemFamilyNetwork() ||
948 !(itemFamilyNetwork() && itemFamilyNetwork()->isActivated()) ||
949 !IItemFamilyNetwork::plug_serializer) {
951 ScopedPtrT<IItemFamilySerializer> cell_serializer(m_cell_family->policyMng()->createSerializer());
952 cell_serializer->deserializeItems(buffer, cells_local_id);
953 }
954 else {
955 _deserializeItems(buffer, cells_local_id, m_cell_family);
956 }
957}
958
959/*---------------------------------------------------------------------------*/
960/*---------------------------------------------------------------------------*/
961
962void DynamicMesh::
963allocate(UnstructuredMeshAllocateBuildInfo& build_info)
964{
965 auto* x = build_info._internal();
966 setDimension(x->meshDimension());
967 allocateCells(x->nbCell(), x->cellsInfos(), true);
968}
969
970/*---------------------------------------------------------------------------*/
971/*---------------------------------------------------------------------------*/
972
973void DynamicMesh::
974allocate(CartesianMeshAllocateBuildInfo& build_info)
975{
976 // The allocation of mesh entities is performed by the
977 // DynamicMeshCartesianBuilder class.
978 allocateCartesianMesh(this, build_info);
979}
980
981/*---------------------------------------------------------------------------*/
982/*---------------------------------------------------------------------------*/
983
984void DynamicMesh::
985serializeCells(ISerializer* buffer, Int32ConstArrayView cells_local_id)
986{
987 Trace::Setter mci(traceMng(), _className());
988 _checkDimension();
989 _checkConnectivity();
990 if (!itemFamilyNetwork() ||
991 !(itemFamilyNetwork() && itemFamilyNetwork()->isActivated()) ||
992 !IItemFamilyNetwork::plug_serializer) {
993 ScopedPtrT<IItemFamilySerializer> cell_serializer(m_cell_family->policyMng()->createSerializer());
994 buffer->setMode(ISerializer::ModeReserve);
995 cell_serializer->serializeItems(buffer, cells_local_id);
996 buffer->allocateBuffer();
998 cell_serializer->serializeItems(buffer, cells_local_id);
999 }
1000 else {
1001 _serializeItems(buffer, cells_local_id, m_cell_family);
1002 }
1003}
1004
1005/*---------------------------------------------------------------------------*/
1006/*---------------------------------------------------------------------------*/
1007
1008void DynamicMesh::
1009_serializeItems(ISerializer* buffer, Int32ConstArrayView item_local_ids, IItemFamily* item_family)
1010{
1011 // 1-Get item lids for family and downard dependencies.
1012 // Rk downard relations are not taken here => automatically added in addItems(ItemData) :
1013 // this will change. Todo add relations when addItems has been updated
1014 using FamilyLidMap = std::map<String, Int32UniqueArray>;
1015 FamilyLidMap serialized_items;
1016 serialized_items[item_family->name()] = item_local_ids;
1017 for (const auto& connectivity : mesh()->itemFamilyNetwork()->getChildDependencies(item_family)) {
1018 ENUMERATE_ITEM (item, item_family->view(item_local_ids)) {
1019 auto connectivity_accessor = ConnectivityItemVector{ connectivity };
1020 auto& connected_family_serialized_items = serialized_items[connectivity->targetFamily()->name()];
1021 connected_family_serialized_items.addRange(connectivity_accessor.connectedItems(ItemLocalId(item)).localIds());
1022 }
1023 }
1024 // 2-Serialize each family in the buffer. The order is important: use the family graph from leaves to root
1025 buffer->setMode(ISerializer::ModeReserve);
1026 _fillSerializer(buffer, serialized_items);
1027 buffer->allocateBuffer();
1028 buffer->setMode(ISerializer::ModePut);
1029 _fillSerializer(buffer, serialized_items);
1030}
1031
1032/*---------------------------------------------------------------------------*/
1033/*---------------------------------------------------------------------------*/
1034
1035void DynamicMesh::
1036_deserializeItems(ISerializer* buffer, Int32Array* item_local_ids, IItemFamily* item_family)
1037{
1038 ARCANE_UNUSED(item_family);
1039 buffer->setMode(ISerializer::ModeGet);
1040 mesh()->itemFamilyNetwork()->schedule([item_local_ids, buffer](IItemFamily* family) {
1041 auto family_serializer = std::unique_ptr<IItemFamilySerializer>{ family->policyMng()->createSerializer() }; // todo make_unique (not in 4.7.2...)
1042 family_serializer->deserializeItems(buffer, item_local_ids);
1043 },
1044 IItemFamilyNetwork::InverseTopologicalOrder);
1045 mesh()->itemFamilyNetwork()->schedule([item_local_ids, buffer](IItemFamily* family) {
1046 auto family_serializer = std::unique_ptr<IItemFamilySerializer>{ family->policyMng()->createSerializer() }; // todo make_unique (not in 4.7.2...)
1047 family_serializer->deserializeItemRelations(buffer, item_local_ids);
1048 },
1049 IItemFamilyNetwork::InverseTopologicalOrder);
1050}
1051
1052/*---------------------------------------------------------------------------*/
1053/*---------------------------------------------------------------------------*/
1054
1055void DynamicMesh::
1056_fillSerializer(ISerializer* buffer, std::map<String, Int32UniqueArray>& serialized_items)
1057{
1058 mesh()->itemFamilyNetwork()->schedule([&serialized_items, buffer](IItemFamily* family) {
1059 auto family_serializer = std::unique_ptr<IItemFamilySerializer>{ family->policyMng()->createSerializer() }; // todo make_unique (not in 4.7.2...)
1060 auto& serialized_items_local_ids = serialized_items[family->name()];
1061 family_serializer->serializeItems(buffer, serialized_items_local_ids);
1062 },
1063 IItemFamilyNetwork::InverseTopologicalOrder);
1064 mesh()->itemFamilyNetwork()->schedule([&serialized_items, buffer](IItemFamily* family) {
1065 auto family_serializer = std::unique_ptr<IItemFamilySerializer>{ family->policyMng()->createSerializer() }; // todo make_unique (not in 4.7.2...)
1066 auto& serialized_items_local_ids = serialized_items[family->name()];
1067 family_serializer->serializeItemRelations(buffer, serialized_items_local_ids);
1068 },
1069 IItemFamilyNetwork::InverseTopologicalOrder);
1070}
1071
1072/*---------------------------------------------------------------------------*/
1073/*---------------------------------------------------------------------------*/
1074
1075void DynamicMesh::
1076addParentCells(ItemVectorView& items)
1077{
1078 Trace::Setter mci(traceMng(), _className());
1079 _checkDimension();
1080 _checkConnectivity();
1081 m_mesh_builder->addParentCells(items);
1082}
1083/*---------------------------------------------------------------------------*/
1084/*---------------------------------------------------------------------------*/
1085
1087void DynamicMesh::
1088addHChildrenCells(Cell parent_cell, Integer nb_cell, Int64ConstArrayView cells_infos, Int32ArrayView cells)
1089{
1090 Trace::Setter mci(traceMng(), _className());
1091 _checkDimension();
1092 _checkConnectivity();
1093 bool allow_build_face = false /*(m_parallel_mng->commSize() == 1)*/;
1094 m_mesh_builder->addHChildrenCells(parent_cell, nb_cell, cells_infos, meshRank(), cells, allow_build_face);
1095}
1096
1097/*---------------------------------------------------------------------------*/
1098/*---------------------------------------------------------------------------*/
1099
1100void DynamicMesh::
1101addParentCellToCell(Cell child, Cell parent)
1102{
1103 Trace::Setter mci(traceMng(), _className());
1104 _checkDimension();
1105 _checkConnectivity();
1106
1107 m_cell_family->_addParentCellToCell(child, parent);
1108}
1109
1110/*---------------------------------------------------------------------------*/
1111/*---------------------------------------------------------------------------*/
1112
1113void DynamicMesh::
1114addChildCellToCell(Cell parent, Cell child)
1115{
1116 Trace::Setter mci(traceMng(), _className());
1117 _checkDimension();
1118 _checkConnectivity();
1119
1120 m_cell_family->_addChildCellToCell2(parent, child);
1121}
1122
1123/*---------------------------------------------------------------------------*/
1124/*---------------------------------------------------------------------------*/
1125
1126void DynamicMesh::
1127addParentFaceToFace(Face child, Face parent)
1128{
1129 Trace::Setter mci(traceMng(), _className());
1130 _checkDimension();
1131 _checkConnectivity();
1132
1133 m_face_family->_addParentFaceToFace(parent, child);
1134}
1135
1136/*---------------------------------------------------------------------------*/
1137/*---------------------------------------------------------------------------*/
1138
1139void DynamicMesh::
1140addChildFaceToFace(Face parent, Face child)
1141{
1142 Trace::Setter mci(traceMng(), _className());
1143 _checkDimension();
1144 _checkConnectivity();
1145
1146 m_face_family->_addChildFaceToFace(parent, child);
1147}
1148
1149/*---------------------------------------------------------------------------*/
1150/*---------------------------------------------------------------------------*/
1151
1152void DynamicMesh::
1153addParentNodeToNode(Node child, Node parent)
1154{
1155 Trace::Setter mci(traceMng(), _className());
1156 _checkDimension();
1157 _checkConnectivity();
1158
1159 m_node_family->_addParentNodeToNode(parent, child);
1160}
1161
1162/*---------------------------------------------------------------------------*/
1163/*---------------------------------------------------------------------------*/
1164
1165void DynamicMesh::
1166addChildNodeToNode(Node parent, Node child)
1167{
1168 Trace::Setter mci(traceMng(), _className());
1169 _checkDimension();
1170 _checkConnectivity();
1171
1172 m_node_family->_addChildNodeToNode(parent, child);
1173}
1174
1175/*---------------------------------------------------------------------------*/
1176/*---------------------------------------------------------------------------*/
1177
1178void DynamicMesh::
1179addFaces(Integer nb_face, Int64ConstArrayView face_infos, Int32ArrayView faces)
1180{
1181 _checkDimension();
1182 _checkConnectivity();
1183 Int32 rank = meshRank();
1184 if (m_use_mesh_item_family_dependencies)
1185 m_mesh_builder->addFaces3(nb_face, face_infos, rank, faces);
1186 else
1187 m_mesh_builder->addFaces(nb_face, face_infos, rank, faces);
1188}
1189
1190/*---------------------------------------------------------------------------*/
1191/*---------------------------------------------------------------------------*/
1192
1193void DynamicMesh::
1194addFaces(const MeshModifierAddFacesArgs& args)
1195{
1196 addFaces(args.nbFace(), args.faceInfos(), args.faceLocalIds());
1197}
1198
1199/*---------------------------------------------------------------------------*/
1200/*---------------------------------------------------------------------------*/
1201
1202void DynamicMesh::
1203addEdges(Integer nb_edge, Int64ConstArrayView edge_infos, Int32ArrayView edges)
1204{
1205 _checkDimension();
1206 _checkConnectivity();
1207 Int32 rank = meshRank();
1208 if (m_use_mesh_item_family_dependencies)
1209 m_mesh_builder->addEdges3(nb_edge, edge_infos, rank, edges);
1210 else
1211 m_mesh_builder->addEdges(nb_edge, edge_infos, rank, edges);
1212}
1213
1214/*---------------------------------------------------------------------------*/
1215/*---------------------------------------------------------------------------*/
1216
1217void DynamicMesh::
1218addNodes(Int64ConstArrayView nodes_uid, Int32ArrayView nodes)
1219{
1220 _checkDimension();
1221 _checkConnectivity();
1222 Int32 rank = meshRank();
1223 if (m_use_mesh_item_family_dependencies)
1224 m_mesh_builder->addNodes2(nodes_uid, rank, nodes);
1225 else
1226 m_mesh_builder->addNodes(nodes_uid, rank, nodes);
1227}
1228
1229/*---------------------------------------------------------------------------*/
1230/*---------------------------------------------------------------------------*/
1231
1232void DynamicMesh::
1233removeCells(Int32ConstArrayView cells_local_id, bool update_graph)
1234{
1235 ARCANE_UNUSED(update_graph);
1236 Trace::Setter mci(traceMng(), _className());
1237 if (m_use_mesh_item_family_dependencies)
1238 removeItems(m_cell_family, cells_local_id);
1239 else
1240 m_cell_family->internalRemoveItems(cells_local_id);
1241
1242 if (m_item_family_network) {
1243 m_item_family_network->removeConnectedDoFsFromCells(cells_local_id);
1244 }
1245}
1246
1247/*---------------------------------------------------------------------------*/
1248/*---------------------------------------------------------------------------*/
1249
1250void DynamicMesh::
1251removeItems(IItemFamily* item_family, Int32ConstArrayView cells_local_id)
1252{
1253 ARCANE_UNUSED(item_family);
1254 ARCANE_ASSERT((itemFamilyNetwork()), ("Cannot call DynamicMesh::removeItems if no ItemFamilyNetwork available"))
1255
1256 if (cells_local_id.empty())
1257 return;
1258
1259 // Create item info (to remove items)
1260 ItemDataList item_data_list;
1261 ItemData& cell_data = item_data_list.itemData(Integer(m_cell_family->itemKind()),
1262 cells_local_id.size(), cells_local_id.size(), Int32ArrayView(),
1263 m_cell_family, (IItemFamilyModifier*)(m_cell_family), m_parallel_mng->commRank());
1264 Integer i(0);
1265 for (auto local_id : cells_local_id) {
1266 // TODO Find a better place in ItemData to put removed item lids (with Int32...) .
1267 cell_data.itemInfos()[i++] = (Int64)local_id;
1268 }
1269 itemFamilyNetwork()->schedule([&item_data_list](IItemFamily* family) {
1270 // send the whole ItemDataList since removed items are to be added for child families
1271 family->removeItems2(item_data_list);
1272 },
1273 IItemFamilyNetwork::TopologicalOrder); // item destruction done from root to leaves
1274}
1275
1276/*---------------------------------------------------------------------------*/
1277/*---------------------------------------------------------------------------*/
1278
1279void DynamicMesh::
1280detachCells(Int32ConstArrayView cells_local_id)
1281{
1282 Trace::Setter mci(traceMng(), _className());
1283 if (m_use_mesh_item_family_dependencies)
1284 m_cell_family->detachCells2(cells_local_id);
1285 else {
1286 ItemInternalList cells = m_cell_family->itemsInternal();
1287 for (Integer i = 0, is = cells_local_id.size(); i < is; ++i)
1288 m_cell_family->detachCell(cells[cells_local_id[i]]);
1289 }
1290}
1291
1292/*---------------------------------------------------------------------------*/
1293/*---------------------------------------------------------------------------*/
1294
1295void DynamicMesh::
1296removeDetachedCells(Int32ConstArrayView cells_local_id)
1297{
1298 Trace::Setter mci(traceMng(), _className());
1299 if (m_use_mesh_item_family_dependencies)
1300 removeItems(m_cell_family, cells_local_id);
1301 else {
1302 ItemInternalList cells = m_cell_family->itemsInternal();
1303 for (Integer i = 0, is = cells_local_id.size(); i < is; ++i)
1304 m_cell_family->removeDetachedCell(cells[cells_local_id[i]]);
1305 }
1306}
1307
1308/*---------------------------------------------------------------------------*/
1309/*---------------------------------------------------------------------------*/
1310
1312void DynamicMesh::
1313flagCellToRefine(Int32ConstArrayView lids)
1314{
1315 Trace::Setter mci(traceMng(), _className());
1316 _checkAMR();
1317 m_mesh_refinement->flagCellToRefine(lids);
1318}
1319
1320/*---------------------------------------------------------------------------*/
1321/*---------------------------------------------------------------------------*/
1322
1323void DynamicMesh::
1324flagCellToCoarsen(Int32ConstArrayView lids)
1325{
1326 Trace::Setter mci(traceMng(), _className());
1327 _checkAMR();
1328 m_mesh_refinement->flagCellToCoarsen(lids);
1329}
1330
1331/*---------------------------------------------------------------------------*/
1332/*---------------------------------------------------------------------------*/
1333
1334void DynamicMesh::
1335refineItems()
1336{
1337 Trace::Setter mci(traceMng(), _className());
1338 _checkDimension();
1339 _checkConnectivity();
1340 _checkAMR();
1341 m_mesh_refinement->refineItems(true);
1342}
1343/*---------------------------------------------------------------------------*/
1344/*---------------------------------------------------------------------------*/
1345
1346void DynamicMesh::
1347coarsenItems()
1348{
1349 Trace::Setter mci(traceMng(), _className());
1350 _checkDimension();
1351 _checkConnectivity();
1352 _checkAMR();
1353 m_mesh_refinement->coarsenItems(true);
1354}
1355
1356/*---------------------------------------------------------------------------*/
1357/*---------------------------------------------------------------------------*/
1358
1359void DynamicMesh::
1360coarsenItemsV2(bool update_parent_flag)
1361{
1362 Trace::Setter mci(traceMng(), _className());
1363 _checkDimension();
1364 _checkConnectivity();
1365 _checkAMR();
1366 if (m_amr_type != eMeshAMRKind::Cell) {
1367 ARCANE_FATAL("This method is not compatible with Cartesian Mesh Patch AMR");
1368 }
1369 m_mesh_refinement->coarsenItemsV2(update_parent_flag);
1370}
1371
1372/*---------------------------------------------------------------------------*/
1373/*---------------------------------------------------------------------------*/
1374
1375bool DynamicMesh::
1376adapt()
1377{
1378 Trace::Setter mci(traceMng(), _className());
1379 _checkDimension();
1380 _checkConnectivity();
1381 _checkAMR();
1382 if (m_mesh_refinement->needUpdate())
1383 m_mesh_refinement->update();
1384 return m_mesh_refinement->refineAndCoarsenItems(true);
1385}
1386
1387/*---------------------------------------------------------------------------*/
1388/*---------------------------------------------------------------------------*/
1389
1390void DynamicMesh::
1391compact()
1392{
1393 _compactItems(false, true);
1394}
1395
1396/*---------------------------------------------------------------------------*/
1397/*---------------------------------------------------------------------------*/
1398
1399void DynamicMesh::
1400registerCallBack(IAMRTransportFunctor* f)
1401{
1402 Trace::Setter mci(traceMng(), _className());
1403 _checkAMR();
1404 m_mesh_refinement->registerCallBack(f);
1405}
1406/*---------------------------------------------------------------------------*/
1407/*---------------------------------------------------------------------------*/
1408
1409void DynamicMesh::
1410unRegisterCallBack(IAMRTransportFunctor* f)
1411{
1412 Trace::Setter mci(traceMng(), _className());
1413 _checkAMR();
1414 m_mesh_refinement->unRegisterCallBack(f);
1415}
1416
1417/*---------------------------------------------------------------------------*/
1418/*---------------------------------------------------------------------------*/
1419
1420void DynamicMesh::
1421_allocateCells2(DynamicMeshIncrementalBuilder* mib)
1422{
1423 Trace::Setter mci(traceMng(), _className());
1424
1425 _finalizeMeshChanged();
1426
1427 mib->printInfos();
1428
1429#ifdef ARCANE_DEBUG_DYNAMIC_MESH
1430 OCStringStream ostr;
1431 _printMesh(ostr());
1432 info() << ostr.str();
1433#endif
1434}
1435
1436/*---------------------------------------------------------------------------*/
1437/*---------------------------------------------------------------------------*/
1438
1439void DynamicMesh::
1440_writeMesh(const String& base_name)
1441{
1442 StringBuilder file_name(base_name);
1443 file_name += "-";
1444 IParallelMng* pm = m_parallel_mng;
1445 bool is_parallel = pm->isParallel();
1446 Int32 rank = meshRank();
1447 if (is_parallel) {
1448 file_name += subDomain()->commonVariables().globalIteration();
1449 file_name += "-";
1450 file_name += rank;
1451 }
1452 mesh_utils::writeMeshConnectivity(this, file_name.toString());
1453 //TODO ability to change the service name
1454 auto writer(ServiceBuilder<IMeshWriter>::createReference(subDomain(), "Lima"));
1455 if (writer.get()) {
1456 String mesh_file_name = file_name.toString() + ".mli";
1457 writer->writeMeshToFile(this, mesh_file_name);
1458 }
1459}
1460
1461/*---------------------------------------------------------------------------*/
1462/*---------------------------------------------------------------------------*/
1463
1464void DynamicMesh::
1465_printMesh(std::ostream& ostr)
1466{
1467 ostr << "----------- Mesh\n";
1468 ostr << " Nodes: " << nbNode() << '\n';
1469 ostr << " Edges: " << nbEdge() << '\n';
1470 ostr << " Faces: " << nbFace() << '\n';
1471 ostr << " Cells: " << nbCell() << '\n';
1472 mesh_utils::printItems(ostr, "Nodes", allNodes());
1473 mesh_utils::printItems(ostr, "Edges", allEdges());
1474 mesh_utils::printItems(ostr, "Faces", allFaces());
1475 mesh_utils::printItems(ostr, "Cells", allCells());
1476}
1477
1478/*---------------------------------------------------------------------------*/
1479/*---------------------------------------------------------------------------*/
1483void DynamicMesh::
1484_saveProperties()
1485{
1486 info(4) << "DynamicMesh::_saveProperties() name=" << name()
1487 << " nb-ghost=" << ghostLayerMng()->nbGhostLayer();
1488
1489 auto p = m_properties;
1490 p->setInt32("nb-ghostlayer", ghostLayerMng()->nbGhostLayer());
1491 p->setInt32("ghostlayer-builder-version", ghostLayerMng()->builderVersion());
1492 p->setInt32("part-info-part-rank", m_mesh_part_info.partRank());
1493 p->setInt32("part-info-nb-part", m_mesh_part_info.nbPart());
1494 p->setInt32("part-info-replication-rank", m_mesh_part_info.replicationRank());
1495 p->setInt32("part-info-nb-replication", m_mesh_part_info.nbReplication());
1496 p->setBool("has-itemsharedinfo-variables", true);
1497 p->setInt64("mesh-timestamp", m_timestamp);
1498 if (!m_do_not_save_need_compact)
1499 p->setBool("need-compact", m_need_compact);
1500}
1501
1502/*---------------------------------------------------------------------------*/
1503/*---------------------------------------------------------------------------*/
1507void DynamicMesh::
1508_loadProperties()
1509{
1510 auto p = m_properties;
1511
1512 info(4) << "DynamicMesh::_readProperties() name=" << name()
1513 << " mesh-version=" << p->getInt32WithDefault(PROPERTY_MESH_VERSION, -1);
1514
1515 {
1516 // Reloads info on the ghost layer manager.
1517 Int32 x = 0;
1518 if (p->get("nb-ghostlayer", x))
1519 ghostLayerMng()->setNbGhostLayer(x);
1520 if (p->get("ghostlayer-builder-version", x))
1521 ghostLayerMng()->setBuilderVersion(x);
1522 if (p->get("part-info-part-rank", x))
1523 m_mesh_part_info.setPartRank(x);
1524 if (p->get("part-info-nb-part", x))
1525 m_mesh_part_info.setNbPart(x);
1526 if (p->get("part-info-replication-rank", x))
1527 m_mesh_part_info.setReplicationRank(x);
1528 if (p->get("part-info-nb-replication", x))
1529 m_mesh_part_info.setNbReplication(x);
1530 if (!m_do_not_save_need_compact) {
1531 bool xb = false;
1532 if (p->get("need-compact", xb))
1533 m_need_compact = xb;
1534 }
1535 Int64 x2 = 0;
1536 if (p->get("mesh-timestamp", x2))
1537 m_timestamp = x2;
1538 }
1539}
1540
1541/*---------------------------------------------------------------------------*/
1542/*---------------------------------------------------------------------------*/
1546void DynamicMesh::
1547_prepareForDump()
1548{
1549 bool want_dump = m_properties->getBool(PROPERTY_DUMP);
1550 info(4) << "DynamicMesh::prepareForDump() name=" << name()
1551 << " need_compact?=" << m_need_compact
1552 << " want_dump?=" << want_dump
1553 << " timestamp=" << m_timestamp;
1554
1555 {
1557 m_mesh_events.eventObservable(t).notify(MeshEventArgs(this, t));
1558 }
1559
1560 // If the mesh is not saved, do nothing. This prevents compacting
1561 // and sorting the mesh, which is undesirable if the properties
1562 // 'sort' and 'compact' are set to 'false'.
1563 if (want_dump)
1565
1566 // Save properties. This must be done at the end because the call to
1567 // prepareForDumpReal() might modify these properties
1569
1570 {
1572 m_mesh_events.eventObservable(t).notify(MeshEventArgs(this, t));
1573 }
1574}
1575
1576/*---------------------------------------------------------------------------*/
1577/*---------------------------------------------------------------------------*/
1581void DynamicMesh::
1582_prepareForDumpReal()
1583{
1584 if (m_need_compact) {
1585 // For now, the entities must be sorted and compacted
1586 // before a save
1587 _compactItems(true, true);
1588 }
1589
1590 // Preparation of mesh/sub-mesh connections
1591 {
1592 if (m_parent_mesh) {
1593 ARCANE_ASSERT((m_parent_group != NULL), ("Unexpected NULL parent group"));
1594 m_parent_mesh_name = m_parent_mesh->name();
1595 m_parent_group_name = m_parent_group->name();
1596 }
1597 else {
1598 ARCANE_ASSERT((m_parent_group == NULL), ("Unexpected non-NULL parent group"));
1601 }
1602 const Integer n_sub_mesh = m_child_meshes.size();
1603 m_child_meshes_name.resize(n_sub_mesh);
1604 for (Integer i = 0; i < n_sub_mesh; ++i)
1605 m_child_meshes_name[i] = m_child_meshes[i]->name();
1606 }
1607
1608 // Save info on entity families
1609 {
1610 Integer nb_item_family = m_item_families.count();
1611 m_item_families_name.resize(nb_item_family);
1612 m_item_families_kind.resize(nb_item_family);
1613 Integer index = 0;
1614 for (IItemFamily* family : m_item_families) {
1615 m_item_families_kind[index] = family->itemKind();
1616 m_item_families_name[index] = family->name();
1617 ++index;
1618 }
1619 }
1620
1621 for (IItemFamily* family : m_item_families) {
1622 family->prepareForDump();
1623 }
1624
1625 if (m_tied_interface_need_prepare_dump) {
1626 m_tied_interface_mng->prepareTiedInterfacesForDump();
1627 m_tied_interface_need_prepare_dump = false;
1628 }
1629}
1630
1631/*---------------------------------------------------------------------------*/
1632/*---------------------------------------------------------------------------*/
1633
1634IItemFamily* DynamicMesh::
1635createItemFamily(eItemKind ik, const String& name)
1636{
1637 IItemFamily* xfamily = findItemFamily(ik, name, false, false);
1638 if (xfamily)
1639 ARCANE_FATAL("Attempting to create a family that already exists '{0}'", name);
1640
1641 debug() << "Creating the entities family "
1642 << " name=" << name
1643 << " kind=" << itemKindName(ik);
1644 ItemFamily* family = _createNewFamily(ik, name);
1645
1646 _addFamily(family);
1647 _buildAndInitFamily(family);
1648
1649 return family;
1650}
1651
1652/*---------------------------------------------------------------------------*/
1653/*---------------------------------------------------------------------------*/
1654
1655ItemFamily* DynamicMesh::
1656_createNewFamily(eItemKind kind, const String& name)
1657{
1658 switch (kind) {
1659 case IK_Node:
1660 return new NodeFamily(this, name);
1661 case IK_Edge:
1662 return new EdgeFamily(this, name);
1663 case IK_Face:
1664 return new FaceFamily(this, name);
1665 case IK_Cell:
1666 return new CellFamily(this, name);
1667 case IK_Particle:
1668 return new ParticleFamily(this, name);
1669 case IK_DoF:
1670 return new DoFFamily(this, name);
1671 case IK_Unknown:
1672 ARCANE_FATAL("Attempting to create an ItemFamily with an unknown item kind.");
1673 }
1674 ARCANE_FATAL("Invalid ItemKind");
1675}
1676
1677/*---------------------------------------------------------------------------*/
1678/*---------------------------------------------------------------------------*/
1679
1680IItemFamilyPolicyMng* DynamicMesh::
1681_createFamilyPolicyMng(ItemFamily* family)
1682{
1683 eItemKind kind = family->itemKind();
1684 switch (kind) {
1685 case IK_Node:
1686 return createNodeFamilyPolicyMng(family);
1687 case IK_Edge:
1688 return createEdgeFamilyPolicyMng(family);
1689 case IK_Face:
1690 return createFaceFamilyPolicyMng(family);
1691 case IK_Cell:
1692 return createCellFamilyPolicyMng(family);
1693 case IK_Particle:
1694 return createParticleFamilyPolicyMng(family);
1695 case IK_DoF:
1696 return createDoFFamilyPolicyMng(family);
1697 case IK_Unknown:
1698 ARCANE_FATAL("Attempting to create an ItemFamily with an unknown item kind.");
1699 }
1700 ARCANE_FATAL("Invalid ItemKind");
1701}
1702
1703/*---------------------------------------------------------------------------*/
1704/*---------------------------------------------------------------------------*/
1705
1706void DynamicMesh::
1707_buildAndInitFamily(IItemFamily* family)
1708{
1709 family->build();
1710 ItemFamily* true_family = ARCANE_CHECK_POINTER(dynamic_cast<ItemFamily*>(family));
1711 IItemFamilyPolicyMng* policy_mng = _createFamilyPolicyMng(true_family);
1712 true_family->setPolicyMng(policy_mng);
1713}
1714
1715/*---------------------------------------------------------------------------*/
1716/*---------------------------------------------------------------------------*/
1717
1718void DynamicMesh::
1719_addFamily(ItemFamily* family)
1720{
1721 m_item_families.add(family);
1722 m_true_item_families.add(family);
1723}
1724
1725/*---------------------------------------------------------------------------*/
1726/*---------------------------------------------------------------------------*/
1727
1728IItemFamily* DynamicMesh::
1729findItemFamily(eItemKind ik, const String& name, bool create_if_needed,
1730 bool register_modifier_if_created)
1731{
1732 for (IItemFamily* family : m_item_families)
1733 if (family->name() == name && family->itemKind() == ik)
1734 return family;
1735 if (create_if_needed) {
1736 IItemFamily* family = createItemFamily(ik, name);
1737 if (register_modifier_if_created) {
1738 IItemFamilyModifier* modifier = dynamic_cast<IItemFamilyModifier*>(family);
1739 if (modifier)
1740 m_family_modifiers.add(modifier);
1741 }
1742 return family;
1743 }
1744 return nullptr;
1745}
1746
1747/*---------------------------------------------------------------------------*/
1748/*---------------------------------------------------------------------------*/
1749
1750IItemFamily* DynamicMesh::
1751findItemFamily(const String& name, bool throw_exception)
1752{
1753 for (IItemFamily* family : m_item_families)
1754 if (family->name() == name)
1755 return family;
1756 if (throw_exception)
1757 ARCANE_FATAL("No family with name '{0}' exist", name);
1758 return nullptr;
1759}
1760
1761/*---------------------------------------------------------------------------*/
1762/*---------------------------------------------------------------------------*/
1763
1765findItemFamilyModifier(eItemKind ik, const String& name)
1766{
1767 IItemFamily* family = findItemFamily(ik, name, false, false);
1768 if (!family)
1769 return nullptr;
1770 for (IItemFamilyModifier* modifier : m_family_modifiers)
1771 if (modifier->family() == family)
1772 return modifier;
1773 return nullptr;
1774}
1775
1776/*---------------------------------------------------------------------------*/
1777/*---------------------------------------------------------------------------*/
1778
1779void DynamicMesh::
1780_exchangeItems(bool do_compact)
1781{
1782 String nb_exchange_str = platform::getEnvironmentVariable("ARCANE_NB_EXCHANGE");
1783 // It would be necessary to calculate the default value taking into account the number
1784 // of exchanged cells and the number of variables and their memory usage.
1785 // Be careful that all procs use the same value.
1786 // In practice, it is better not to exceed 3 or 4 exchanges because this
1787 // increases the time consumed and does not reduce memory enough.
1788 Integer nb_exchange = 1;
1789 if (!nb_exchange_str.null()) {
1790 bool is_bad = builtInGetValue(nb_exchange, nb_exchange_str);
1791 if (is_bad)
1792 nb_exchange = 1;
1793 }
1794 String exchange_version_str = platform::getEnvironmentVariable("ARCANE_MESH_EXCHANGE_VERSION");
1795 Integer exchange_version = 1;
1796 if (!exchange_version_str.null()) {
1797 builtInGetValue(exchange_version, exchange_version_str);
1798 }
1799
1800 info() << "DynamicMesh::_echangeItems() do_compact?=" << do_compact
1801 << " nb_exchange=" << nb_exchange << " version=" << exchange_version;
1802
1803 if (nb_exchange > 1) {
1804 _multipleExchangeItems(nb_exchange, exchange_version, do_compact);
1805 }
1806 else
1807 _exchangeItemsNew();
1808 // Currently, the exchangeItemsNew() method only takes into account
1809 // one layer of ghost cells. If we request more, we must
1810 // add them now. This call is not optimal but allows
1811 // for correctly processing all cases (I hope).
1812 if (ghostLayerMng()->nbGhostLayer() > 1 && !m_use_mesh_item_family_dependencies) // many ghost already handled in MeshExchange with ItemFamilyNetwork
1813 updateGhostLayers(true);
1814 String check_exchange = platform::getEnvironmentVariable("ARCANE_CHECK_EXCHANGE");
1815 if (!check_exchange.null()) {
1816 m_mesh_checker->checkGhostCells();
1817 pwarning() << "CHECKING SYNCHRONISATION !";
1818 m_mesh_checker->checkVariablesSynchronization();
1819 m_mesh_checker->checkItemGroupsSynchronization();
1820 }
1821 if (checkLevel() >= 2)
1822 m_mesh_checker->checkValidMesh();
1823 else if (checkLevel() >= 1)
1824 m_mesh_checker->checkValidConnectivity();
1825}
1826
1827/*---------------------------------------------------------------------------*/
1828/*---------------------------------------------------------------------------*/
1858void DynamicMesh::
1859_multipleExchangeItems(Integer nb_exchange, Integer version, bool do_compact)
1860{
1861 if (version < 1 || version > 2)
1862 ARCANE_FATAL("Invalid value '{0}' for version. Valid values are 1 or 2", version);
1863
1864 info() << "** ** MULTIPLE EXCHANGE ITEM version=" << version << " nb_exchange=" << nb_exchange;
1865 UniqueArray<UniqueArray<Int32>> cells_to_exchange_new_owner(nb_exchange);
1866 // We must store the uid because after load balancing the localIds will change
1867 UniqueArray<UniqueArray<Int64>> cells_to_exchange_uid(nb_exchange);
1868
1869 IItemFamily* cell_family = cellFamily();
1870 VariableItemInt32& cells_new_owner = cell_family->itemsNewOwner();
1871
1872 Integer nb_cell = ownCells().size();
1873 ENUMERATE_CELL (icell, ownCells()) {
1874 Cell cell = *icell;
1875 Int32 current_owner = cell.owner();
1876 Int32 new_owner = cells_new_owner[icell];
1877 if (current_owner == new_owner)
1878 continue;
1879 Integer phase = 0;
1880 if (version == 2)
1881 phase = (new_owner % nb_exchange);
1882 else if (version == 1)
1883 phase = icell.index() / nb_cell;
1884 cells_to_exchange_new_owner[phase].add(new_owner);
1885 cells_to_exchange_uid[phase].add(cell.uniqueId().asInt64());
1886 }
1887
1888 // Sets it as if the cell did not change owner to
1889 ENUMERATE_CELL (icell, ownCells()) {
1890 Cell cell = *icell;
1891 cells_new_owner[icell] = cell.owner();
1892 }
1893
1894 // From here, cells_new_owner is identical to cell.owner()
1895 // for each cell.
1896 Int32UniqueArray uids_to_lids;
1897 for (Integer i = 0; i < nb_exchange; ++i) {
1898 Int32ConstArrayView new_owners = cells_to_exchange_new_owner[i];
1899 Int64ConstArrayView new_uids = cells_to_exchange_uid[i];
1900 Integer nb_cell = new_uids.size();
1901 info() << "MultipleExchange current_exchange=" << i << " nb_cell=" << nb_cell;
1902 uids_to_lids.resize(nb_cell);
1903 cell_family->itemsUniqueIdToLocalId(uids_to_lids, new_uids);
1904 ItemInternalList cells = cell_family->itemsInternal();
1905 // For each cell in the current exchange part, sets the new_owner
1906 // to the correct value
1907 for (Integer z = 0; z < nb_cell; ++z)
1908 cells_new_owner[cells[uids_to_lids[z]]] = new_owners[z];
1909 cells_new_owner.synchronize();
1910 mesh()->utilities()->changeOwnersFromCells();
1911 _exchangeItemsNew();
1912 }
1913
1914 if (do_compact) {
1915 Timer::Action ts_action1(m_sub_domain, "CompactItems", true);
1916 bool do_sort = m_properties->getBool(PROPERTY_SORT);
1917 _compactItems(do_sort, true);
1918 }
1919}
1920
1921/*---------------------------------------------------------------------------*/
1922/*---------------------------------------------------------------------------*/
1923
1924void DynamicMesh::
1925exchangeItems()
1926{
1927 _exchangeItems(m_properties->getBool(PROPERTY_COMPACT));
1928}
1929
1930/*---------------------------------------------------------------------------*/
1931/*---------------------------------------------------------------------------*/
1932
1933void DynamicMesh::
1934clearItems()
1935{
1936 for (IItemFamily* family : m_item_families)
1937 family->clearItems();
1938 endUpdate();
1939}
1940
1941/*---------------------------------------------------------------------------*/
1942/*---------------------------------------------------------------------------*/
1943#if 0
1944class ItemsExchangeInfo2List
1945 : public UniqueArray<ItemsExchangeInfo2*>
1946{
1947public:
1948 ~ItemsExchangeInfo2List()
1949 {
1950 for( Integer i=0, is=size(); i<is; ++i ){
1951 ItemsExchangeInfo2* info = this->operator[](i);
1952 delete info;
1953 }
1954 clear();
1955 }
1956};
1957#endif
1958
1959/*---------------------------------------------------------------------------*/
1960/*---------------------------------------------------------------------------*/
1961
1962void DynamicMesh::
1963_exchangeItemsNew()
1964{
1965 // The algorithm used here is not recursive with submeshes.
1966 // All communications are grouped and the different levels of modifications
1967 // will be popped here. This implementation does not allow having
1968 // more than one submesh level per cell.
1969
1970 Trace::Setter mci(traceMng(), _className());
1971
1972 if (!m_is_dynamic)
1973 ARCANE_FATAL("property isDynamic() has to be 'true'");
1974
1975 m_need_compact = true;
1976
1977 if (arcane_debug_load_balancing) {
1978 // TODO: do this in the MeshExchanger and by family.
1979 // Checks that the variables are properly synchronized
1980 m_node_family->itemsNewOwner().checkIfSync(10);
1981 m_edge_family->itemsNewOwner().checkIfSync(10);
1982 m_face_family->itemsNewOwner().checkIfSync(10);
1983 m_cell_family->itemsNewOwner().checkIfSync(10);
1984 }
1985 // TODO: Check that everyone has the same families and in the same order.
1986
1987 // Cascades all meshes associated with this mesh
1988 typedef Collection<DynamicMesh*> DynamicMeshCollection;
1989 DynamicMeshCollection all_cascade_meshes = List<DynamicMesh*>();
1990 all_cascade_meshes.add(this);
1991 for (Integer i = 0; i < m_child_meshes.size(); ++i)
1992 all_cascade_meshes.add(m_child_meshes[i]);
1993
1994 IMeshExchanger* iexchanger = m_mesh_exchange_mng->beginExchange();
1995 MeshExchanger* mesh_exchanger = ARCANE_CHECK_POINTER(dynamic_cast<MeshExchanger*>(iexchanger));
1996
1997 // If there are no entities to exchange, the exchange stops immediately.
1998 if (mesh_exchanger->computeExchangeInfos()) {
1999 info() << "No load balance is performed";
2000 m_mesh_exchange_mng->endExchange();
2001 return;
2002 }
2003
2004 // Performs the info exchange
2005 mesh_exchanger->processExchange();
2006
2007 // Removes entities that should no longer be in our sub-domain.
2008 mesh_exchanger->removeNeededItems();
2009
2010 // Readjusts the groups by removing entities that are no longer in the mesh or by
2011 // invalidating the calculated groups.
2012 // TODO: make a method in the family that does this.
2013 {
2014 auto action = [](ItemGroup& group) {
2015 // (HP) TODO: 'if (group.internal()->hasComputeFunctor())' does not work simply, why ?
2016 // Formerly: if (group.isLocalToSubDomain() || group.isOwn())
2017 // Redundant with ItemFamily::notifyItemsOwnerChanged calculations
2018 if (group.internal()->hasComputeFunctor() || group.isLocalToSubDomain())
2019 group.invalidate();
2020 else
2021 group.internal()->removeSuppressedItems();
2022 };
2023 for (DynamicMesh* mesh : all_cascade_meshes) {
2024 meshvisitor::visitGroups(mesh, action);
2025 }
2026 }
2027
2028 // Removes potential ghost items remaining after updating the support group
2029 // which were marked by NeedRemove (which cleans up a potential inconsistent state of the
2030 // submesh relative to its parent)
2031 // This part is important because it is possible that updating the groups
2032 // is not enough to update the ghost parts of the submeshes
2033 // (unless a stronger constraint is placed on the group to also include all
2034 // ghost meshes of the submesh)
2035#if HEAD
2036 for (DynamicMesh* child_mesh : m_child_meshes)
2037 child_mesh->m_submesh_tools->removeDeadGhostCells();
2038#else
2039 for (Integer i_child_mesh = 0; i_child_mesh < m_child_meshes.size(); ++i_child_mesh)
2040 m_child_meshes[i_child_mesh]->m_submesh_tools->removeDeadGhostCells();
2041#endif
2042
2043 // Allocates the entities we received from other sub-domains.
2044 mesh_exchanger->allocateReceivedItems();
2045
2046 // We now resume a standard endUpdate cycle
2047 // but interleaving the submesh levels
2048 for (DynamicMesh* mesh : all_cascade_meshes)
2049 mesh->_internalEndUpdateInit(true);
2050
2051 mesh_exchanger->updateItemGroups();
2052
2053 // Recalculates synchronizers on groups.
2054 for (DynamicMesh* mesh : all_cascade_meshes)
2055 mesh->_computeGroupSynchronizeInfos();
2056
2057 // Updates the variable values of the received entities
2058 mesh_exchanger->updateVariables();
2059
2060 // Finalizes the modifications whose sorting and compaction
2061 for (DynamicMesh* mesh : all_cascade_meshes) {
2062 // Requests the display of info for the current mesh
2063 bool print_info = (mesh == this);
2064 mesh->_internalEndUpdateFinal(print_info);
2065 }
2066
2067 // Finalizes the exchanges
2068 // For now, this is only useful for TiedInterface but it
2069 // should be removed.
2070 mesh_exchanger->finalizeExchange();
2071
2072 // TODO: ensure this call in case of an exception.
2073 m_mesh_exchange_mng->endExchange();
2074
2075 // Now, the mesh is updated but the extraordinary ghost cells
2076 // have been potentially removed. We replace them in the mesh.
2077 // Non-optimized version. Ideally, extraordinary cells
2078 // should be managed in MeshExchange.
2079 // endUpdate() must be called in all cases to ensure
2080 // that the variables and groups are properly sized.
2081 if (m_extra_ghost_cells_builder->hasBuilder() || m_extra_ghost_particles_builder->hasBuilder())
2082 this->endUpdate(true, false);
2083 else
2084 this->endUpdate();
2085}
2086
2087/*---------------------------------------------------------------------------*/
2088/*---------------------------------------------------------------------------*/
2089
2090void DynamicMesh::
2091addExtraGhostCellsBuilder(IExtraGhostCellsBuilder* builder)
2092{
2093 m_extra_ghost_cells_builder->addExtraGhostCellsBuilder(builder);
2094}
2095
2096/*---------------------------------------------------------------------------*/
2097/*---------------------------------------------------------------------------*/
2098
2099void DynamicMesh::
2100removeExtraGhostCellsBuilder(IExtraGhostCellsBuilder* builder)
2101{
2102 m_extra_ghost_cells_builder->removeExtraGhostCellsBuilder(builder);
2103}
2104
2105/*---------------------------------------------------------------------------*/
2106/*---------------------------------------------------------------------------*/
2107
2108void DynamicMesh::
2109addExtraGhostParticlesBuilder(IExtraGhostParticlesBuilder* builder)
2110{
2111 m_extra_ghost_particles_builder->addExtraGhostParticlesBuilder(builder);
2112}
2113
2114/*---------------------------------------------------------------------------*/
2115/*---------------------------------------------------------------------------*/
2116
2117void DynamicMesh::
2118removeExtraGhostParticlesBuilder(IExtraGhostParticlesBuilder* builder)
2119{
2120 m_extra_ghost_particles_builder->removeExtraGhostParticlesBuilder(builder);
2121}
2122
2123/*---------------------------------------------------------------------------*/
2124/*---------------------------------------------------------------------------*/
2125
2126void DynamicMesh::
2127_computeExtraGhostCells()
2128{
2129 m_extra_ghost_cells_builder->computeExtraGhostCells();
2130}
2131
2132/*---------------------------------------------------------------------------*/
2133/*---------------------------------------------------------------------------*/
2134
2135void DynamicMesh::
2136_computeExtraGhostParticles()
2137{
2138 m_extra_ghost_particles_builder->computeExtraGhostParticles();
2139}
2140
2141/*---------------------------------------------------------------------------*/
2142/*---------------------------------------------------------------------------*/
2143
2144void DynamicMesh::
2145_removeGhostItems()
2146{
2147 const Int32 sid = meshRank();
2148
2149 // Removal of ghost cells.
2150 // We must use an intermediate array, because deleting
2151 // cells invalidates the iterators on 'cells_map'.
2152 UniqueArray<Int32> cells_to_remove;
2153 cells_to_remove.reserve(1000);
2154
2155 ItemInternalMap& cells_map = m_cell_family->itemsMap();
2156 cells_map.eachItem([&](Item cell) {
2157 if (cell.owner() != sid)
2158 cells_to_remove.add(cell.localId());
2159 });
2160
2161 info() << "Number of cells to remove: " << cells_to_remove.size();
2162 m_cell_family->removeCells(cells_to_remove);
2163
2164 // Readjusts the groups by removing entities that are no longer in the mesh
2165 _updateGroupsAfterRemove();
2166}
2167
2168/*---------------------------------------------------------------------------*/
2169/*---------------------------------------------------------------------------*/
2173void DynamicMesh::
2174_updateGroupsAfterRemove()
2175{
2176 auto action = [&](const ItemGroup& group) { group.itemFamily()->partialEndUpdateGroup(group); };
2177 meshvisitor::visitGroups(this, action);
2178}
2179
2180/*---------------------------------------------------------------------------*/
2181/*---------------------------------------------------------------------------*/
2182
2183void DynamicMesh::
2184updateGhostLayers()
2185{
2186 updateGhostLayers(true);
2187}
2188
2189/*---------------------------------------------------------------------------*/
2190/*---------------------------------------------------------------------------*/
2191
2192void DynamicMesh::
2193updateGhostLayers(bool remove_old_ghost)
2194{
2195 Trace::Setter mci(traceMng(), _className());
2196
2197 if (!m_is_dynamic)
2198 ARCANE_FATAL("property isDynamic() has to be 'true'");
2199 if (m_parent_mesh)
2200 ARCANE_FATAL("Cannot be called on submesh");
2201
2202 _internalUpdateGhost(true, remove_old_ghost);
2203 _internalEndUpdateInit(true);
2204 _synchronizeGroups();
2205 _computeGroupSynchronizeInfos();
2206 _internalEndUpdateResizeVariables();
2207 _synchronizeVariables();
2208 _internalEndUpdateFinal(true);
2209
2210 // Finalization of recursive submeshes
2211 for (Integer i = 0; i < m_child_meshes.size(); ++i) {
2212 m_child_meshes[i]->endUpdate(true, remove_old_ghost);
2213 }
2214}
2215/*---------------------------------------------------------------------------*/
2216/*---------------------------------------------------------------------------*/
2217
2218void DynamicMesh::
2219_removeGhostChildItems()
2220{
2221 const Int32 sid = meshRank();
2222
2223 // Removal of cells
2224 UniqueArray<Int32> cells_to_remove;
2225 cells_to_remove.reserve(1000);
2226
2227 ItemInternalMap& cells_map = m_cell_family->itemsMap();
2228 Integer max_level = 0;
2229 cells_map.eachItem([&](impl::ItemBase cell) {
2230 if ((cell.owner() != sid) && (cell.level() != 0))
2231 max_level = math::max(cell.level(), max_level);
2232 });
2233
2234 if (max_level == 0)
2235 return;
2236
2237 cells_map.eachItem([&](impl::ItemBase cell) {
2238 if ((cell.owner() != sid) && (cell.level() == max_level)) {
2239 cells_to_remove.add(cell.localId());
2240 }
2241 });
2242
2243 info() << "Number of cells to remove: " << cells_to_remove.size();
2244 m_cell_family->removeCells(cells_to_remove);
2245
2246 // Readjusts the groups by removing entities that are no longer in the mesh
2247 _updateGroupsAfterRemove();
2248}
2249
2250/*---------------------------------------------------------------------------*/
2251/*---------------------------------------------------------------------------*/
2252
2253void DynamicMesh::
2254_removeGhostChildItems2(Array<Int64>& cells_to_coarsen)
2255{
2256 const Int32 sid = meshRank();
2257
2258 cells_to_coarsen.reserve(1000);
2259
2260 // Removal of cells
2261 UniqueArray<Cell> cells_to_remove;
2262 cells_to_remove.reserve(1000);
2263
2264 ItemInternalMap& cells_map = m_cell_family->itemsMap();
2265 Integer counter = 0;
2266 cells_map.eachItem([&](Cell cell) {
2267 if (cell.owner() != sid)
2268 return;
2269 if (cell.hasFlags(ItemFlags::II_JustCoarsened)) {
2270 cells_to_coarsen.add(cell.uniqueId());
2271 for (Integer c = 0, cs = cell.nbHChildren(); c < cs; c++) {
2272 cells_to_remove.add(cell.hChild(c));
2273 counter++;
2274 }
2275 }
2276 });
2277
2278 if (counter == 0)
2279 return;
2280
2281 //info() << "Number of cells to remove: " << cells_to_remove.size();
2282 for (Integer i = 0, is = cells_to_remove.size(); i < is; ++i)
2283 m_cell_family->removeCell(cells_to_remove[i]);
2284
2285 // Readjust groups by removing entities that are no longer in the mesh
2286 _updateGroupsAfterRemove();
2287}
2288
2289/*---------------------------------------------------------------------------*/
2290/*---------------------------------------------------------------------------*/
2292void DynamicMesh::
2293updateGhostLayerFromParent(Array<Int64>& ghost_cell_to_refine_uid,
2294 Array<Int64>& ghost_cell_to_coarsen_uid, bool remove_old_ghost)
2295{
2296 Trace::Setter mci(traceMng(), _className());
2297 CHECKPERF(m_perf_counter.start(PerfCounter::UPGHOSTLAYER1));
2298
2299 m_need_compact = true;
2300 //Integer current_iteration = subDomain()->commonVariables().globalIteration();
2301 if (!m_is_dynamic)
2302 ARCANE_FATAL("Property isDynamic() has to be 'true'");
2303
2304 if (remove_old_ghost) {
2305 _removeGhostChildItems2(ghost_cell_to_coarsen_uid);
2306 }
2307
2308 // In case of refinement/coarsening, the orientation might be invalid at a point.
2309 m_face_family->setCheckOrientation(false);
2310
2311 m_mesh_builder->addGhostChildFromParent(ghost_cell_to_refine_uid);
2312 m_face_family->setCheckOrientation(true);
2313
2314 // From here, all mesh entities are known. It
2315 // is therefore possible to compact them if necessary
2316 m_mesh_builder->printStats();
2317 CHECKPERF(m_perf_counter.stop(PerfCounter::UPGHOSTLAYER1))
2318
2319 CHECKPERF(m_perf_counter.start(PerfCounter::UPGHOSTLAYER2))
2320 //_finalizeMeshChanged();
2321 {
2322 ++m_timestamp;
2323 for (IItemFamily* family : m_item_families)
2324 family->endUpdate();
2325 }
2326 CHECKPERF(m_perf_counter.stop(PerfCounter::UPGHOSTLAYER2))
2327
2328 // Reallocate mesh variables because their group has changed
2329 // TODO: this should be done for every family
2330 CHECKPERF(m_perf_counter.start(PerfCounter::UPGHOSTLAYER3))
2331 {
2332 IVariableMng* vm = m_sub_domain->variableMng();
2333 VariableCollection used_vars(vm->usedVariables());
2334 used_vars.each(std::mem_fn(&IVariable::resizeFromGroup));
2335 }
2336 CHECKPERF(m_perf_counter.stop(PerfCounter::UPGHOSTLAYER3))
2337
2338 // Recalculate the necessary information for the synchronization
2339 // of
2340 // entities
2341 //pm->computeSynchronizeInfos();
2342 CHECKPERF(m_perf_counter.start(PerfCounter::UPGHOSTLAYER4))
2344 _synchronizeGroupsAndVariables();
2345 CHECKPERF(m_perf_counter.stop(PerfCounter::UPGHOSTLAYER4))
2346
2347 //Loop of new refine ghost
2348 CHECKPERF(m_perf_counter.start(PerfCounter::UPGHOSTLAYER5))
2349 UniqueArray<Integer> ghost_cell_to_refine_lid(ghost_cell_to_refine_uid.size());
2350 m_cell_family->itemsUniqueIdToLocalId(ghost_cell_to_refine_lid, ghost_cell_to_refine_uid, true);
2351 ItemInternalList cells = m_cell_family->itemsInternal();
2352 for (Integer e = 0, i_size = ghost_cell_to_refine_lid.size(); e != i_size; ++e) {
2353 Cell i_hParent_cell(cells[ghost_cell_to_refine_lid[e]]);
2354 m_mesh_refinement->populateBackFrontCellsFromParentFaces(i_hParent_cell);
2355
2356 //need to populate also the new own cell connected to the new ghost
2357 Integer nb_face = i_hParent_cell.nbFace();
2358 Integer lid = i_hParent_cell.localId();
2359 for (Integer iface = 0; iface < nb_face; ++iface) {
2360 Face face = i_hParent_cell.face(iface);
2361 Integer nb_cell = face.nbCell();
2362 for (Integer icell = 0; icell < nb_cell; ++icell) {
2363 Cell cell = face.cell(icell);
2364 if ((cell.localId() != lid) && (cell.isOwn())) {
2366 m_face_family->familyTree(childs, cell, false);
2367 for (Integer i = 0, nchilds = childs.size(); i < nchilds; ++i) {
2368 ItemInternal* child = childs[i];
2369 if (child->isAncestor())
2370 m_mesh_refinement->populateBackFrontCellsFromParentFaces(child);
2371 }
2372 }
2373 }
2374 }
2375 }
2376 CHECKPERF(m_perf_counter.stop(PerfCounter::UPGHOSTLAYER5))
2377
2378 // Verify that the mesh conforms to the reference
2379 CHECKPERF(m_perf_counter.start(PerfCounter::UPGHOSTLAYER6))
2380 m_mesh_checker->checkMeshFromReferenceFile();
2381
2382 // Compact references to avoid gaps and take
2383 // advantage of cache effects.
2384 // NOTE: this is not theoretically necessary but currently is
2385 // because we do not save the #m_data_index of the ItemInternal.
2386 //_compactItemInternalReferences();
2387 bool do_compact = m_properties->getBool(PROPERTY_COMPACT);
2388 if (do_compact) {
2389 bool do_sort = m_properties->getBool(PROPERTY_SORT);
2390 _compactItems(do_sort, do_compact);
2391 }
2392 CHECKPERF(m_perf_counter.stop(PerfCounter::UPGHOSTLAYER6))
2393
2394 if (arcane_debug_load_balancing) {
2395 _writeMesh("update-ghost-layer-after");
2396 }
2397
2398 // Display the statistics of the new mesh
2399 {
2400 MeshStats ms(traceMng(), this, m_parallel_mng);
2401 ms.dumpStats();
2402 pinfo() << "Proc: " << meshRank()
2403 << " cellown=" << m_cell_family->allItems().own().size()
2404 << " cellloc=" << m_cell_family->allItems().size();
2405 }
2406
2408 CHECKPERF(m_perf_counter.start(PerfCounter::UPGHOSTLAYER7))
2410 m_mesh_checker->updateAMRFaceOrientation(ghost_cell_to_refine_uid);
2411
2412 if (m_mesh_checker->checkLevel() >= 1)
2413 m_mesh_checker->checkValidConnectivity();
2414 CHECKPERF(m_perf_counter.stop(PerfCounter::UPGHOSTLAYER7))
2415
2416#ifdef ACTIVATE_PERF_COUNTER
2417 m_perf_counter.printInfo(info().file());
2418#endif
2419}
2420
2421/*---------------------------------------------------------------------------*/
2422/*---------------------------------------------------------------------------*/
2423
2424void DynamicMesh::
2425_internalUpdateGhost(bool update_ghost_layer, bool remove_old_ghost)
2426{
2427 m_need_compact = true;
2428
2429 // Overrides behavior for submeshes
2430 if (parentMesh()) {
2431 if (update_ghost_layer)
2432 m_submesh_tools->updateGhostMesh();
2433 }
2434 else {
2435 if (update_ghost_layer) {
2436 if (remove_old_ghost) {
2437 _removeGhostItems();
2438 }
2439 // In case of refinement/coarsening, the orientation might be invalid at a point.
2440 m_face_family->setCheckOrientation(false);
2441 m_mesh_builder->addGhostLayers(false);
2442 m_face_family->setCheckOrientation(true);
2443 _computeExtraGhostCells();
2444 _computeExtraGhostParticles();
2445 }
2446 }
2447}
2448
2449/*---------------------------------------------------------------------------*/
2450/*---------------------------------------------------------------------------*/
2451
2452void DynamicMesh::
2453_internalEndUpdateInit(bool update_ghost_layer)
2454{
2455 // From here, all mesh entities are known. It
2456 // is therefore possible to compact them if necessary
2457 //m_mesh_builder->printStats();
2458
2459 //info() << "Finalize date=" << platform::getCurrentDateTime();
2460 _finalizeMeshChanged();
2461
2462 // Recalculate the necessary information for the synchronization
2463 // of
2464 // entities
2465 if (update_ghost_layer) {
2466 info() << "ComputeSyncInfos date=" << platform::getCurrentDateTime();
2467 _computeFamilySynchronizeInfos();
2468 }
2469}
2470
2471/*---------------------------------------------------------------------------*/
2472/*---------------------------------------------------------------------------*/
2473
2474void DynamicMesh::
2475_internalEndUpdateResizeVariables()
2476{
2477 // Reallocate mesh variables because their group has changed
2478 for (IItemFamily* family : m_item_families)
2479 family->_internalApi()->resizeVariables(true);
2480}
2481
2482/*---------------------------------------------------------------------------*/
2483/*---------------------------------------------------------------------------*/
2484
2485void DynamicMesh::
2486_internalEndUpdateFinal(bool print_stat)
2487{
2488 // Verify that the mesh conforms to the reference
2489 m_mesh_checker->checkMeshFromReferenceFile();
2490
2491 // Compact references to avoid gaps and take
2492 // advantage of cache effects.
2493 // NOTE: this is not theoretically necessary but currently is
2494 // because we do not save the #m_data_index of the ItemInternal.
2495 {
2496 //Timer::Action ts_action1(m_sub_domain,"CompactReferences",true);
2497 _compactItemInternalReferences(); // Utility to confirm
2498
2499 {
2500 bool do_compact = m_properties->getBool(PROPERTY_COMPACT);
2501 info(4) << "DynamicMesh::_internalEndUpdateFinal() compact?=" << do_compact << " sort?=" << m_properties->getBool(PROPERTY_SORT);
2502 if (do_compact) {
2503 bool do_sort = m_properties->getBool(PROPERTY_SORT);
2504 _compactItems(do_sort, do_compact);
2505 }
2506 }
2507 }
2508
2509 _notifyEndUpdateForFamilies();
2510
2511 // Display the statistics of the new mesh
2512 if (print_stat) {
2513 if (m_properties->getBool(PROPERTY_DISPLAY_STATS)) {
2514 MeshStats ms(traceMng(), this, m_parallel_mng);
2515 ms.dumpStats();
2516 }
2517 }
2518
2521 m_mesh_checker->updateAMRFaceOrientation();
2522
2523 if (m_mesh_checker->checkLevel() >= 1)
2524 m_mesh_checker->checkValidConnectivity();
2525}
2526
2527/*---------------------------------------------------------------------------*/
2528/*---------------------------------------------------------------------------*/
2529
2530void DynamicMesh::
2531_notifyEndUpdateForFamilies()
2532{
2533 for (IItemFamily* family : m_item_families)
2534 family->_internalApi()->notifyEndUpdateFromMesh();
2535}
2536
2537/*---------------------------------------------------------------------------*/
2538/*---------------------------------------------------------------------------*/
2539
2540void DynamicMesh::
2541endUpdate()
2542{
2543 endUpdate(false, false);
2544}
2545
2546/*---------------------------------------------------------------------------*/
2547/*---------------------------------------------------------------------------*/
2548
2549void DynamicMesh::
2550endUpdate(bool update_ghost_layer, bool remove_old_ghost)
2551{
2552 // The order of operations is as follows:
2553 // 1- Ghost layer update
2554 // 2- Mesh finalization (freezes items)
2555 // Calculate if requested (update_ghost_layer) the synchronizers on the families
2556 // 3- Synchronize groups (requires updated family synchronizers)
2557 // 4- Calculate if requested (update_ghost_layer) the synchronizers on the groups
2558 // 5- Resize variables (families and groups)
2559 // 6- Synchronize if requested (update_ghost_layer) the variables (families and groups)
2560 // 7- Finalization including: compaction, sorting (if enabled), statistics, and validity check
2561 // 8- Recursive calls to submeshes
2562
2563 Trace::Setter mci(traceMng(), _className());
2564 _internalUpdateGhost(update_ghost_layer, remove_old_ghost);
2565
2566 _internalEndUpdateInit(update_ghost_layer);
2567 if (update_ghost_layer) {
2568 _synchronizeGroups();
2569 _computeGroupSynchronizeInfos();
2570 }
2571 _internalEndUpdateResizeVariables();
2572 if (update_ghost_layer) {
2573 _synchronizeVariables();
2574 }
2575 _internalEndUpdateFinal(false);
2576
2577 // Recursive finalization of submeshes
2578 for (DynamicMesh* child_mesh : m_child_meshes)
2579 child_mesh->endUpdate(update_ghost_layer, remove_old_ghost);
2580}
2581
2582/*---------------------------------------------------------------------------*/
2583/*---------------------------------------------------------------------------*/
2584
2585void DynamicMesh::
2586synchronizeGroupsAndVariables()
2587{
2588 _synchronizeGroupsAndVariables();
2589 // Can be tested in the case where the parent group of a submesh
2590 // before calling the child meshes.
2591 // This might require an update of the child synchronizers
2592 for (DynamicMesh* child_mesh : m_child_meshes)
2593 child_mesh->synchronizeGroupsAndVariables();
2594}
2595
2596/*---------------------------------------------------------------------------*/
2597/*---------------------------------------------------------------------------*/
2598
2599void DynamicMesh::
2600_synchronizeGroupsAndVariables()
2601{
2602 _synchronizeGroups();
2603 _synchronizeVariables();
2604}
2605
2606/*---------------------------------------------------------------------------*/
2607/*---------------------------------------------------------------------------*/
2608
2609void DynamicMesh::
2610_synchronizeGroups()
2611{
2612 {
2613 ItemGroupsSynchronize igs(m_node_family);
2614 igs.synchronize();
2615 }
2616 {
2617 ItemGroupsSynchronize igs(m_edge_family);
2618 igs.synchronize();
2619 }
2620 {
2621 ItemGroupsSynchronize igs(m_face_family);
2622 igs.synchronize();
2623 }
2624 {
2625 ItemGroupsSynchronize igs(m_cell_family);
2626 igs.synchronize();
2627 }
2628 {
2629 for (IItemFamily* family : m_item_families) {
2630 if (family->itemKind() == IK_Particle) {
2631 IParticleFamily* pfamily = family->toParticleFamily();
2632 if (pfamily && pfamily->getEnableGhostItems()) {
2633 ItemGroupsSynchronize igs(family);
2634 igs.synchronize();
2635 }
2636 }
2637 }
2638 }
2639}
2640
2641/*---------------------------------------------------------------------------*/
2642/*---------------------------------------------------------------------------*/
2643
2644void DynamicMesh::
2645_synchronizeVariables()
2646{
2647 // We only synchronize variables on the items of the current mesh
2648 // - Graph items are not handled here (it was already removed from
2649 // the previous version of the code)
2650 // - Particles and those without kind (Unknown) are not subject to synchronization
2651 // Synchronization is factored here by a collection of variables with the same
2652 // synchronizer (even for synchronizers on groups != family)
2653 // To preserve a consistent synchronization order, an
2654 // auxiliary OrderedSyncList structure is used.
2655
2656 // Can we do this with a more compact structure?
2657 typedef UniqueArray<IVariableSynchronizer*> OrderedSyncList;
2658 typedef std::map<IVariableSynchronizer*, VariableCollection> SyncList;
2659 OrderedSyncList ordered_sync_list;
2660 SyncList sync_list;
2661
2662 VariableCollection used_vars(subDomain()->variableMng()->usedVariables());
2663 for (VariableCollection::Enumerator i_var(used_vars); ++i_var;) {
2664 IVariable* var = *i_var;
2665 switch (var->itemKind()) {
2666 case IK_Node:
2667 case IK_Edge:
2668 case IK_Face:
2669 case IK_Cell:
2670 case IK_DoF: {
2671 IVariableSynchronizer* synchronizer = 0;
2672 if (var->isPartial())
2673 synchronizer = var->itemGroup().synchronizer();
2674 else
2675 synchronizer = var->itemFamily()->allItemsSynchronizer();
2676 IMesh* sync_mesh = synchronizer->itemGroup().mesh();
2677 if (sync_mesh != this)
2678 continue; // we only synchronize on the current mesh
2679 std::pair<SyncList::iterator, bool> inserter = sync_list.insert(std::make_pair(synchronizer, VariableCollection()));
2680 if (inserter.second) { // new synchronizer
2681 ordered_sync_list.add(synchronizer);
2682 }
2683 VariableCollection& collection = inserter.first->second;
2684 collection.add(var);
2685 } break;
2686 case IK_Particle:
2687 case IK_Unknown:
2688 break;
2689 }
2690 }
2691
2692 for (Integer i_sync = 0; i_sync < ordered_sync_list.size(); ++i_sync) {
2693 IVariableSynchronizer* synchronizer = ordered_sync_list[i_sync];
2694 VariableCollection& collection = sync_list[synchronizer];
2695 synchronizer->synchronize(collection);
2696 }
2697}
2698
2699/*---------------------------------------------------------------------------*/
2700/*---------------------------------------------------------------------------*/
2701
2702void DynamicMesh::
2703_sortInternalReferences()
2704{
2705 // TODO: this specific call must be handled by NodeFamily.
2706 m_node_family->sortInternalReferences();
2707}
2708
2709/*---------------------------------------------------------------------------*/
2710/*---------------------------------------------------------------------------*/
2711
2712void DynamicMesh::
2713_finalizeMeshChanged()
2714{
2715 ++m_timestamp;
2716 for (IItemFamily* family : m_item_families) {
2717 debug() << "_finalizeMeshChanged on " << family->name() << " Family on Mesh " << name();
2718 family->endUpdate();
2719 }
2720
2721 bool do_sort = m_properties->getBool(PROPERTY_SORT);
2722 if (do_sort)
2723 _sortInternalReferences();
2724 m_tied_interface_need_prepare_dump = true;
2725}
2726
2727/*---------------------------------------------------------------------------*/
2728/*---------------------------------------------------------------------------*/
2729
2730void DynamicMesh::
2731_applyCompactPolicy(const String& timer_name,
2732 std::function<void(IItemFamilyCompactPolicy*)> functor)
2733{
2734 Timer::Action ts_action(m_sub_domain, timer_name);
2735 for (IItemFamily* family : m_item_families) {
2736 IItemFamilyCompactPolicy* c = family->policyMng()->compactPolicy();
2737 if (c)
2738 functor(c);
2739 }
2740}
2741
2742/*---------------------------------------------------------------------------*/
2743/*---------------------------------------------------------------------------*/
2744
2745void DynamicMesh::
2746_compactItemInternalReferences()
2747{
2748 _applyCompactPolicy("CompactConnectivityData", [&](IItemFamilyCompactPolicy* c) { c->compactConnectivityData(); });
2749}
2750
2751/*---------------------------------------------------------------------------*/
2752/*---------------------------------------------------------------------------*/
2753
2754void DynamicMesh::
2755_compactItems(bool do_sort, bool compact_variables_and_groups)
2756{
2757 if (do_sort)
2758 info(4) << "Compress and sort the mesh entities " << name() << ".";
2759 else
2760 info(4) << "Compress the mesh entities " << name() << ".";
2761
2762 IMeshCompacter* compacter = m_mesh_compact_mng->beginCompact();
2763
2764 try {
2765 compacter->setSorted(do_sort);
2766 compacter->_setCompactVariablesAndGroups(compact_variables_and_groups);
2767
2768 compacter->doAllActions();
2769 }
2770 catch (...) {
2771 m_mesh_compact_mng->endCompact();
2772 throw;
2773 }
2774 m_mesh_compact_mng->endCompact();
2775
2776 if (do_sort) {
2777 Timer::Action ts_action(m_sub_domain, "CompactItemSortReferences");
2778 // TODO: put this in the family policy (apparently only useful
2779 // for node families)
2780 _sortInternalReferences();
2781 }
2782
2783 m_need_compact = false;
2784
2785 // Consider compaction as a mesh evolution because this
2786 // changes the structures associated with the entities and their connectivities
2787 ++m_timestamp;
2788}
2789
2790/*---------------------------------------------------------------------------*/
2791/*---------------------------------------------------------------------------*/
2792
2793void DynamicMesh::
2794setEstimatedCells(Integer nb_cell0)
2795{
2796 Real factor = 1.0;
2797 if (m_parallel_mng->isParallel())
2798 factor = 1.2; // Considers 20% ghost entities.
2799 // The following estimations corresponding to an evaluation for a cube of side N=16
2800 Integer nb_node = Convert::toInteger(nb_cell0 * 1.2 * factor); // (N+1)^3/N^3 => 1.2
2801 Integer nb_edge = Convert::toInteger(nb_cell0 * 6.8 * factor); // 6*(N+1)^2*N/N^3 => 6.8
2802 Integer nb_face = Convert::toInteger(nb_cell0 * 3.4 * factor); // 3*N^2*(N+1)/N^3 => 3.19
2803 Integer nb_cell = Convert::toInteger(nb_cell0 * 1.0 * factor); // trivial => 1.0
2804 info() << "Estimating the number of entities:"
2805 << " Node=" << nb_node
2806 << " Edge=" << nb_edge
2807 << " Face=" << nb_face
2808 << " Cell=" << nb_cell;
2809 m_node_family->preAllocate(nb_node);
2810 m_edge_family->preAllocate(nb_edge);
2811 m_face_family->preAllocate(nb_face);
2812 m_cell_family->preAllocate(nb_cell);
2813}
2814
2815/*---------------------------------------------------------------------------*/
2816/*---------------------------------------------------------------------------*/
2820void DynamicMesh::
2821_readFromDump()
2822{
2824
2825 // Do nothing on a mesh that has not yet been allocated.
2826 if (m_mesh_dimension() < 0)
2827 return;
2828
2829 // Mesh/sub-mesh connection
2830 {
2831 IMeshMng* mm = meshMng();
2832 if (!m_parent_mesh_name.value().null()) {
2833 m_parent_mesh = mm->findMeshHandle(m_parent_mesh_name.value()).mesh();
2834 }
2835 if (!m_parent_group_name.value().null()) {
2836 ARCANE_ASSERT((m_parent_mesh != NULL), ("Unexpected NULL Mesh"));
2837 m_parent_group = m_parent_mesh->findGroup(m_parent_group_name.value()).internal();
2838 }
2839 const Integer n_sub_mesh = m_child_meshes_name.size();
2840 m_child_meshes.resize(n_sub_mesh);
2841 for (Integer i = 0; i < n_sub_mesh; ++i) {
2842 IMesh* child_mesh = mm->findMeshHandle(m_child_meshes_name[i]).mesh();
2843 DynamicMesh* dynamic_child_mesh = dynamic_cast<DynamicMesh*>(child_mesh);
2844 if (dynamic_child_mesh == 0)
2845 ARCANE_FATAL("Cannot associate sub mesh from a different concrete type");
2846 m_child_meshes[i] = dynamic_child_mesh;
2847 }
2848 }
2849
2850 {
2851 Integer nb_item_family = m_item_families_name.size();
2852 for (Integer i = 0; i < nb_item_family; ++i) {
2853 info(5) << "Found family: I=" << i
2854 << " name=" << m_item_families_name[i]
2855 << " kind=" << (eItemKind)m_item_families_kind[i];
2856 }
2857 }
2858
2859 // Relit les infos sur les familles d'entités
2860 {
2861 Integer nb_item_family = m_item_families_name.size();
2862 for (Integer i = 0; i < nb_item_family; ++i) {
2864 }
2865 }
2866
2867 // GG: Update of connectivity choices
2868 // This must be done here because the families might be created at the beginning of this
2869 // method and thus not account for connectivity.
2870 if (!m_is_sub_connectivity_set)
2871 _setSubConnectivity();
2872
2873 for (IItemFamily* family : m_item_families)
2874 family->readFromDump();
2875
2876 // After reading, the families must be notified of the potential
2877 // change in entities.
2878 _notifyEndUpdateForFamilies();
2879
2880 //TODO: should not be done here.
2881 m_item_internal_list.nodes = m_node_family->itemsInternal();
2882 m_item_internal_list.edges = m_edge_family->itemsInternal();
2883 m_item_internal_list.faces = m_face_family->itemsInternal();
2884 m_item_internal_list.cells = m_cell_family->itemsInternal();
2885 m_item_internal_list.mesh = this;
2886
2887 m_tied_interface_mng->readTiedInterfacesFromDump();
2888
2889 m_mesh_builder->readFromDump();
2890 //_writeMesh("after-read-dump-"+name());
2891}
2892
2893/*---------------------------------------------------------------------------*/
2894/*---------------------------------------------------------------------------*/
2895
2896bool DynamicMesh::
2897hasTiedInterface()
2898{
2899 return m_tied_interface_mng->hasTiedInterface();
2900}
2901
2902/*---------------------------------------------------------------------------*/
2903/*---------------------------------------------------------------------------*/
2904
2906tiedInterfaces()
2907{
2908 return m_tied_interface_mng->tiedInterfaces();
2909}
2910
2911/*---------------------------------------------------------------------------*/
2912/*---------------------------------------------------------------------------*/
2913
2915trueTiedInterfaces()
2916{
2917 return m_tied_interface_mng->trueTiedInterfaces();
2918}
2919
2920/*---------------------------------------------------------------------------*/
2921/*---------------------------------------------------------------------------*/
2922
2923void DynamicMesh::
2924computeTiedInterfaces(const XmlNode& mesh_node)
2925{
2926 m_tied_interface_mng->computeTiedInterfaces(mesh_node);
2927}
2928
2929/*---------------------------------------------------------------------------*/
2930/*---------------------------------------------------------------------------*/
2931
2932void DynamicMesh::
2933setDimension(Integer dim)
2934{
2935 _setDimension(dim);
2936 _checkConnectivity();
2937}
2938
2939/*---------------------------------------------------------------------------*/
2940/*---------------------------------------------------------------------------*/
2941
2942void DynamicMesh::
2943_setDimension(Integer dim)
2944{
2945 if (m_is_allocated)
2946 ARCANE_FATAL("DynamicMesh::setDimension(): mesh is already allocated");
2947 info() << "Mesh name=" << name() << " set dimension = " << dim;
2948 m_mesh_dimension = dim;
2949 const bool is_non_manifold = meshKind().isNonManifold();
2950 // Force the fact of not re-numbering faces and edges
2951 // in the case of a non-manifold mesh
2952 if (is_non_manifold) {
2953 info() << "Force no-renumbering of edge and face uid because we are using non manifold mesh";
2954 m_mesh_unique_id_mng->setFaceBuilderVersion(0);
2955 m_mesh_unique_id_mng->setEdgeBuilderVersion(0);
2956 }
2957 bool v = m_mesh_unique_id_mng->isUseNodeUniqueIdToGenerateEdgeAndFaceUniqueId();
2958 // If the mesh is non-manifold, then it is mandatory to use
2959 // generation from uniqueId() from nodes to guarantee
2960 // the consistency of the created entities.
2961 // This constraint may eventually be removed when this type
2962 // of mesh is no longer experimental.
2963 if (!v && is_non_manifold) {
2964 v = true;
2965 info() << "Force using edge and face uid generation from nodes because we are using non manifold mesh";
2966 }
2967 if (m_mesh_builder) {
2968 auto* adder = m_mesh_builder->oneMeshItemAdder();
2969 if (adder)
2970 adder->setUseNodeUniqueIdToGenerateEdgeAndFaceUniqueId(v);
2971 }
2972 // In 3D, with non-manifold meshes, it is mandatory to create edges.
2973 // They will be used instead of faces for 2D cells.
2974 if (dim == 3 && is_non_manifold) {
2975 Connectivity c(m_mesh_connectivity);
2976 if (!c.hasConnectivity(Connectivity::CT_HasEdge)) {
2977 c.enableConnectivity(Connectivity::CT_HasEdge);
2978 info() << "Force creating edges for 3D non-manifold mesh";
2979 }
2980 }
2981}
2982
2983/*---------------------------------------------------------------------------*/
2984/*---------------------------------------------------------------------------*/
2985
2986void DynamicMesh::
2987_checkDimension() const
2988{
2989 if (m_mesh_dimension() < 0)
2990 ARCANE_FATAL("dimension not set. setDimension() must be called before allocating cells");
2991}
2992
2993/*---------------------------------------------------------------------------*/
2994/*---------------------------------------------------------------------------*/
2995
2996void DynamicMesh::
2997_checkConnectivity()
2998{
2999 Connectivity c(m_mesh_connectivity);
3000 if (!c.isFrozen()) {
3001 c.freeze(this);
3002 debug() << "Mesh " << name() << " connectivity : " << Connectivity::Printer(m_mesh_connectivity());
3003 _setSubConnectivity();
3004 _updateItemFamilyDependencies(m_mesh_connectivity);
3005 }
3006}
3007
3008/*---------------------------------------------------------------------------*/
3009/*---------------------------------------------------------------------------*/
3010// AMR
3011void DynamicMesh::
3012_checkAMR() const
3013{
3014 if (!m_is_amr_activated)
3015 ARCANE_FATAL("DynamicMesh::_checkAMR(): amr activator not set.\t"
3016 "amr='true' must be set in the .arc file");
3017}
3018
3019/*---------------------------------------------------------------------------*/
3020/*---------------------------------------------------------------------------*/
3021
3022void DynamicMesh::
3023_setSubConnectivity()
3024{
3025 m_mesh_builder->setConnectivity(m_mesh_connectivity());
3026 m_node_family->setConnectivity(m_mesh_connectivity());
3027 m_edge_family->setConnectivity(m_mesh_connectivity());
3028 m_face_family->setConnectivity(m_mesh_connectivity());
3029 m_cell_family->setConnectivity(m_mesh_connectivity());
3030 m_is_sub_connectivity_set = true;
3031}
3032
3033/*---------------------------------------------------------------------------*/
3034/*---------------------------------------------------------------------------*/
3035
3036void DynamicMesh::
3037_writeCells(const String& filename)
3038{
3039 CellGroup cells(m_cell_family->allItems());
3040 std::ofstream ofile(filename.localstr());
3041 ENUMERATE_CELL (icell, cells) {
3042 Cell cell = *icell;
3043 ofile << "CELL: uid=" << cell.uniqueId() << " isown="
3044 << cell.isOwn() << " owner=" << cell.owner() << '\n';
3045 }
3046}
3047
3048/*---------------------------------------------------------------------------*/
3049/*---------------------------------------------------------------------------*/
3050
3051VariableNodeReal3& DynamicMesh::
3052nodesCoordinates()
3053{
3054 return m_node_family->nodesCoordinates();
3055}
3056
3057/*---------------------------------------------------------------------------*/
3058/*---------------------------------------------------------------------------*/
3059
3061sharedNodesCoordinates()
3062{
3063 if (parentMesh())
3065 else
3067}
3068
3069/*---------------------------------------------------------------------------*/
3070/*---------------------------------------------------------------------------*/
3071
3072void DynamicMesh::
3073_setOwnersFromCells()
3074{
3075 // We assume we know the new owners of the cells, which
3076 // are found in cells_owner. We must now determine the new owners of the nodes and
3077 // faces. Until we have an algorithm that better balances
3078 // the messages, we apply the following:
3079 // - each sub-domain is responsible for determining the new
3080 // owner of the nodes and faces belonging to it.
3081 // - for nodes and edges, the new owner is the new owner of the cell
3082 // connected to this node whose uniqueId() is the smallest.
3083 // - for faces, the new owner is the new owner
3084 // of the cell behind this face if it is an internal face, and of the connected cell if it is a boundary face.
3085 // - for dual nodes, the new owner is the new owner
3086 // of the cell connected to the dual element
3087 // - for links, the new owner is the new owner
3088 // of the cell connected to the first dual node, i.e., the owner
3089 // of the first dual node of the link
3090
3091 VariableItemInt32& nodes_owner(nodeFamily()->itemsNewOwner());
3092 VariableItemInt32& edges_owner(edgeFamily()->itemsNewOwner());
3093 VariableItemInt32& faces_owner(faceFamily()->itemsNewOwner());
3094
3095 const Integer sid = subDomain()->subDomainId();
3096
3097 // Owner assignment tool for items
3098 if (m_new_item_owner_builder == NULL)
3099 m_new_item_owner_builder = new NewItemOwnerBuilder();
3100
3101 // Determines the new owners of the nodes
3102 {
3103 ENUMERATE_NODE (i_node, ownNodes()) {
3104 Node node = *i_node;
3105 nodes_owner[node] = m_new_item_owner_builder->ownerOfItem(node);
3106 }
3107 nodes_owner.synchronize();
3108 }
3109
3110 ENUMERATE_NODE (i_node, allNodes()) {
3111 Node node = *i_node;
3112 node.mutableItemBase().setOwner(nodes_owner[node], sid);
3113 }
3114
3115 // Determines the new owners of the edges
3116 {
3117 ENUMERATE_EDGE (i_edge, ownEdges()) {
3118 Edge edge = *i_edge;
3119 edges_owner[edge] = m_new_item_owner_builder->ownerOfItem(edge);
3120 }
3121 edges_owner.synchronize();
3122 }
3123
3124 ENUMERATE_EDGE (i_edge, allEdges()) {
3125 Edge edge = *i_edge;
3126 edge.mutableItemBase().setOwner(edges_owner[edge], sid);
3127 }
3128
3129 // Determines the new owners of the faces
3130 {
3131 ENUMERATE_FACE (i_face, ownFaces()) {
3132 Face face = *i_face;
3133 faces_owner[face] = m_new_item_owner_builder->ownerOfItem(face);
3134 }
3135 faces_owner.synchronize();
3136 }
3137
3138 ENUMERATE_FACE (i_face, allFaces()) {
3139 Face face = *i_face;
3140 face.mutableItemBase().setOwner(faces_owner[face], sid);
3141 }
3142
3143 nodeFamily()->notifyItemsOwnerChanged();
3144 edgeFamily()->notifyItemsOwnerChanged();
3145 faceFamily()->notifyItemsOwnerChanged();
3146 _computeFamilySynchronizeInfos();
3147}
3148
3149/*---------------------------------------------------------------------------*/
3150/*---------------------------------------------------------------------------*/
3151
3152IMeshUtilities* DynamicMesh::
3153utilities()
3154{
3155 if (!m_mesh_utilities)
3156 m_mesh_utilities = new UnstructuredMeshUtilities(this);
3157 return m_mesh_utilities;
3158}
3159
3160/*---------------------------------------------------------------------------*/
3161/*---------------------------------------------------------------------------*/
3162
3163FaceGroup DynamicMesh::
3164outerFaces()
3165{
3166 return m_cell_family->allItems().outerFaceGroup();
3167}
3168
3170/*---------------------------------------------------------------------------*/
3171/*---------------------------------------------------------------------------*/
3172
3174CellGroup DynamicMesh::
3175allActiveCells()
3176{
3177 return m_cell_family->allItems().activeCellGroup();
3178}
3179/*---------------------------------------------------------------------------*/
3180/*---------------------------------------------------------------------------*/
3182CellGroup DynamicMesh::
3183ownActiveCells()
3184{
3185 return m_cell_family->allItems().ownActiveCellGroup();
3186}
3187/*---------------------------------------------------------------------------*/
3188/*---------------------------------------------------------------------------*/
3190CellGroup DynamicMesh::
3191allLevelCells(const Integer& level)
3192{
3193 return m_cell_family->allItems().levelCellGroup(level);
3194}
3195/*---------------------------------------------------------------------------*/
3196/*---------------------------------------------------------------------------*/
3198CellGroup DynamicMesh::
3199ownLevelCells(const Integer& level)
3200{
3201 return m_cell_family->allItems().ownLevelCellGroup(level);
3202}
3203/*---------------------------------------------------------------------------*/
3204/*---------------------------------------------------------------------------*/
3206FaceGroup DynamicMesh::
3207allActiveFaces()
3208{
3209 return m_cell_family->allItems().activeFaceGroup();
3210}
3211/*---------------------------------------------------------------------------*/
3212/*---------------------------------------------------------------------------*/
3214FaceGroup DynamicMesh::
3215ownActiveFaces()
3216{
3217 return m_cell_family->allItems().ownActiveFaceGroup();
3218}
3219/*---------------------------------------------------------------------------*/
3220/*---------------------------------------------------------------------------*/
3221
3222/*---------------------------------------------------------------------------*/
3223/*---------------------------------------------------------------------------*/
3225FaceGroup DynamicMesh::
3226innerActiveFaces()
3227{
3228 return m_cell_family->allItems().innerActiveFaceGroup();
3229}
3230/*---------------------------------------------------------------------------*/
3231/*---------------------------------------------------------------------------*/
3233FaceGroup DynamicMesh::
3234outerActiveFaces()
3235{
3236 return m_cell_family->allItems().outerActiveFaceGroup();
3237}
3238/*---------------------------------------------------------------------------*/
3239/*---------------------------------------------------------------------------*/
3240
3241/*---------------------------------------------------------------------------*/
3242/*---------------------------------------------------------------------------*/
3243
3244void DynamicMesh::
3245defineParentForBuild(IMesh* mesh, ItemGroup group)
3246{
3247 Trace::Setter mci(traceMng(), _className());
3248 if (!mesh)
3249 ARCANE_FATAL("Cannot set NULL parent mesh to mesh '{0}'", name());
3250
3251 if (mesh != group.mesh())
3252 ARCANE_FATAL("Cannot set inconsistant mesh/group parents to mesh '{0}'", name());
3253
3254 if (m_parent_mesh) {
3255 if (m_parent_mesh != mesh)
3256 ARCANE_FATAL("Mesh '{0}' already has parent mesh '{1}'", name(), m_parent_mesh->name());
3257 if (m_parent_group != group.internal())
3258 ARCANE_FATAL("Mesh '{0}' already has parent group '{1}'", name(), m_parent_group->name());
3259 }
3260
3261 m_parent_mesh = mesh;
3262 m_parent_group = group.internal();
3263
3264 Integer dimension_shift = 0;
3265 if (group.itemKind() == IK_Face) {
3266 dimension_shift = 1;
3267 }
3268 else if (group.itemKind() == IK_Cell) {
3269 dimension_shift = 0;
3270 }
3271 else {
3272 ARCANE_FATAL("Only SubMesh on FaceGroup or CellGoup is allowed");
3273 }
3274
3275 _setDimension(mesh->dimension() - dimension_shift);
3276
3277 for (IItemFamily* family : m_item_families) {
3278 const eItemKind kind = family->itemKind();
3279 // Uniquement sur les items constructifs d'un maillage
3280 if (kind == IK_Node || kind == IK_Edge || kind == IK_Face || kind == IK_Cell) {
3281 const eItemKind parent_kind = MeshToMeshTransposer::kindTranspose(kind, this, mesh);
3282 if (parent_kind != IK_Unknown) {
3283 family->setParentFamily(mesh->itemFamily(parent_kind));
3284 } // else : pas de transposition
3285 }
3286 else {
3287 // do nothing. Another idea ?
3288 }
3289 }
3290}
3291
3292/*---------------------------------------------------------------------------*/
3293/*---------------------------------------------------------------------------*/
3294
3296partitionConstraintMng()
3297{
3298 return m_partition_constraint_mng;
3299}
3300
3301/*---------------------------------------------------------------------------*/
3302/*---------------------------------------------------------------------------*/
3303
3304IMesh* DynamicMesh::
3305parentMesh() const
3306{
3307 return m_parent_mesh;
3308}
3309
3310/*---------------------------------------------------------------------------*/
3311/*---------------------------------------------------------------------------*/
3312
3313ItemGroup DynamicMesh::
3314parentGroup() const
3315{
3316 return ItemGroup(m_parent_group);
3317}
3318
3319/*---------------------------------------------------------------------------*/
3320/*---------------------------------------------------------------------------*/
3321
3322void DynamicMesh::
3323addChildMesh(IMesh* sub_mesh)
3324{
3325 DynamicMesh* dynamic_child_mesh = dynamic_cast<DynamicMesh*>(sub_mesh);
3326 if (!dynamic_child_mesh)
3327 ARCANE_FATAL("Cannot associate sub mesh from a different concrete type");
3328 for (Integer i = 0; i < m_child_meshes.size(); ++i)
3329 if (m_child_meshes[i] == dynamic_child_mesh)
3330 return;
3331 m_child_meshes.add(dynamic_child_mesh);
3332}
3333
3334/*---------------------------------------------------------------------------*/
3335/*---------------------------------------------------------------------------*/
3336
3337IMeshCollection DynamicMesh::
3338childMeshes() const
3339{
3340 IMeshCollection collection = List<IMesh*>();
3341 for (Integer i = 0; i < m_child_meshes.size(); ++i) {
3342 collection.add(m_child_meshes[i]);
3343 }
3344 return collection;
3345}
3346
3347/*---------------------------------------------------------------------------*/
3348/*---------------------------------------------------------------------------*/
3349
3350IMeshChecker* DynamicMesh::
3351checker() const
3352{
3353 return m_mesh_checker;
3354}
3355
3356/*---------------------------------------------------------------------------*/
3357/*---------------------------------------------------------------------------*/
3358
3359bool DynamicMesh::
3360isPrimaryMesh() const
3361{
3362 return (this->parentMesh() == nullptr);
3363}
3364
3365/*---------------------------------------------------------------------------*/
3366/*---------------------------------------------------------------------------*/
3367
3368IPrimaryMesh* DynamicMesh::
3369toPrimaryMesh()
3370{
3371 if (!isPrimaryMesh())
3372 throw BadCastException(A_FUNCINFO, "Mesh is not a primary mesh");
3373 return this;
3374}
3375
3376/*---------------------------------------------------------------------------*/
3377/*---------------------------------------------------------------------------*/
3378
3379Integer DynamicMesh::
3380nbNode()
3381{
3382 return m_node_family->nbItem();
3383}
3384Integer DynamicMesh::
3385nbEdge()
3386{
3387 return m_edge_family->nbItem();
3388}
3389Integer DynamicMesh::
3390nbFace()
3391{
3392 return m_face_family->nbItem();
3393}
3394Integer DynamicMesh::
3395nbCell()
3396{
3397 return m_cell_family->nbItem();
3398}
3399
3400IItemFamily* DynamicMesh::
3401nodeFamily()
3402{
3403 return m_node_family;
3404}
3405
3406IItemFamily* DynamicMesh::
3407edgeFamily()
3408{
3409 return m_edge_family;
3410}
3411
3412IItemFamily* DynamicMesh::
3413faceFamily()
3414{
3415 return m_face_family;
3416}
3417
3418IItemFamily* DynamicMesh::
3419cellFamily()
3420{
3421 return m_cell_family;
3422}
3423
3424DynamicMeshKindInfos::ItemInternalMap& DynamicMesh::
3425nodesMap()
3426{
3427 return m_node_family->itemsMap();
3428}
3429
3430DynamicMeshKindInfos::ItemInternalMap& DynamicMesh::
3431edgesMap()
3432{
3433 return m_edge_family->itemsMap();
3434}
3435
3436DynamicMeshKindInfos::ItemInternalMap& DynamicMesh::
3437facesMap()
3438{
3439 return m_face_family->itemsMap();
3440}
3441
3442DynamicMeshKindInfos::ItemInternalMap& DynamicMesh::
3443cellsMap()
3444{
3445 return m_cell_family->itemsMap();
3446}
3447
3448/*---------------------------------------------------------------------------*/
3449/*---------------------------------------------------------------------------*/
3450
3451void DynamicMesh::
3452mergeMeshes(ConstArrayView<IMesh*> meshes)
3453{
3454 UniqueArray<DynamicMesh*> true_meshes;
3455 for (IMesh* mesh : meshes) {
3456 DynamicMesh* true_mesh = ARCANE_CHECK_POINTER(dynamic_cast<DynamicMesh*>(mesh));
3457 true_meshes.add(true_mesh);
3458 }
3459 DynamicMeshMerger merger(this);
3460 merger.mergeMeshes(true_meshes);
3461}
3462
3463/*---------------------------------------------------------------------------*/
3464/*---------------------------------------------------------------------------*/
3465
3466void DynamicMesh::
3467_printConnectivityPolicy()
3468{
3469 info() << "Connectivity policy=" << (int)m_connectivity_policy;
3470
3471 if (m_connectivity_policy != InternalConnectivityPolicy::NewOnly)
3472 ARCANE_FATAL("Invalid value '{0}' for InternalConnectivityPolicy. Only '{1}' is allowed",
3473 (int)m_connectivity_policy, (int)InternalConnectivityPolicy::NewOnly);
3474}
3475
3476/*---------------------------------------------------------------------------*/
3477/*---------------------------------------------------------------------------*/
3478
3479void DynamicMesh::
3480setMeshPartInfo(const MeshPartInfo& mpi)
3481{
3482 m_mesh_part_info = mpi;
3483 // TODO: notify the families
3484}
3485
3486/*---------------------------------------------------------------------------*/
3487/*---------------------------------------------------------------------------*/
3488
3489void DynamicMesh::
3490_updateItemFamilyDependencies(VariableScalarInteger connectivity)
3491{
3492 if (!m_item_family_network)
3493 return;
3494 Connectivity c(connectivity);
3495 for (const auto& con : m_item_family_network->getConnectivities()) {
3496 if (c.hasConnectivity(c.kindsToConnectivity(con->sourceFamily()->itemKind(), con->targetFamily()->itemKind()))) {
3497 m_item_family_network->setIsStored(con);
3498 }
3499 }
3500}
3501
3502/*---------------------------------------------------------------------------*/
3503/*---------------------------------------------------------------------------*/
3504
3505IMeshInternal* DynamicMesh::
3506_internalApi()
3507{
3508 return m_internal_api.get();
3509}
3510
3511/*---------------------------------------------------------------------------*/
3512/*---------------------------------------------------------------------------*/
3513
3515_modifierInternalApi()
3516{
3517 return m_internal_api.get();
3518}
3519
3520/*---------------------------------------------------------------------------*/
3521/*---------------------------------------------------------------------------*/
3522
3523void DynamicMesh::
3524computeSynchronizeInfos()
3525{
3526 _computeSynchronizeInfos();
3527}
3528
3529/*---------------------------------------------------------------------------*/
3530/*---------------------------------------------------------------------------*/
3531
3532class ARCANE_MESH_EXPORT DynamicMeshFactoryBase
3533: public AbstractService
3534, public IMeshFactory
3535{
3536 public:
3537
3538 DynamicMeshFactoryBase(const ServiceBuildInfo& sbi, bool is_amr)
3539 : AbstractService(sbi)
3540 , m_is_amr(is_amr)
3541 {}
3542
3543 public:
3544
3545 void build() override {}
3546 IPrimaryMesh* createMesh(IMeshMng* mm, const MeshBuildInfo& build_info) override
3547 {
3548 MeshBuildInfo mbi(build_info);
3549 MeshKind mk(mbi.meshKind());
3550 // If AMR is requested but not indicated in MeshPart,
3551 // we add it.
3552 if (m_is_amr && mk.meshAMRKind() == eMeshAMRKind::None)
3553 mk.setMeshAMRKind(eMeshAMRKind::Cell);
3554 mbi.addMeshKind(mk);
3556 bool is_submesh = !mbi.parentGroup().null();
3557 if (is_submesh && m_is_amr)
3558 ARCANE_FATAL("Submesh cannot be refined with AMR.");
3559 return new DynamicMesh(sd, mbi, is_submesh);
3560 }
3561
3562 private:
3563
3564 bool m_is_amr;
3565};
3566
3567/*---------------------------------------------------------------------------*/
3568/*---------------------------------------------------------------------------*/
3569
3570class ARCANE_MESH_EXPORT DynamicMeshFactory
3571: public DynamicMeshFactoryBase
3572{
3573 public:
3574
3575 explicit DynamicMeshFactory(const ServiceBuildInfo& sbi)
3576 : DynamicMeshFactoryBase(sbi, false)
3577 {}
3578};
3579
3580/*---------------------------------------------------------------------------*/
3581/*---------------------------------------------------------------------------*/
3582
3583class ARCANE_MESH_EXPORT DynamicAMRMeshFactory
3584: public DynamicMeshFactoryBase
3585{
3586 public:
3587
3588 explicit DynamicAMRMeshFactory(const ServiceBuildInfo& sbi)
3589 : DynamicMeshFactoryBase(sbi, true)
3590 {}
3591};
3592
3593/*---------------------------------------------------------------------------*/
3594/*---------------------------------------------------------------------------*/
3595
3597 ServiceProperty("ArcaneDynamicMeshFactory", ST_Application),
3599
3601 ServiceProperty("ArcaneDynamicAMRMeshFactory", ST_Application),
3603
3604/*---------------------------------------------------------------------------*/
3605/*---------------------------------------------------------------------------*/
3606
3607} // End namespace Arcane::mesh
3608
3609/*---------------------------------------------------------------------------*/
3610/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL_IF(const,...)
Macro throwing a FatalErrorException if cond is true.
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
#define ENUMERATE_EDGE(name, group)
Generic enumerator for an edge group.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
void writeMeshConnectivity(IMesh *mesh, const String &file_name)
Writes the connectivity of the mesh mesh to the file file_name.
Definition MeshUtils.cc:829
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
Integer size() const
Number of elements in the vector.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
Base class for 1D data vectors.
ConstReferenceType operator[](Int64 i) const
Element at index i.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Exception when a conversion from one type to another is invalid.
Cell of a mesh.
Definition Item.h:1300
Face face(Int32 i) const
i-th face of the cell
Definition Item.h:1400
Int32 nbFace() const
Number of faces of the cell.
Definition Item.h:1397
Manages the retrieval of connectivity information.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
constexpr bool empty() const noexcept
true if the array is empty (size()==0)
Face of a cell.
Definition Item.h:1032
Cell cell(Int32 i) const
i-th cell of the face
Definition Item.h:1793
Int32 nbCell() const
Number of cells of the face (1 or 2).
Definition Item.h:1129
Interface of a part of a dataset.
virtual XmlNode rootElement()=0
Returns the root element.
Interface of a builder for "extraordinary" ghost cells.
Interface of a builder for "extraordinary" ghost cells.
Interface for modifying a family.
Interface of an entity family.
Definition IItemFamily.h:83
virtual ItemGroup findGroup(const String &name) const =0
Searches for a group.
virtual ItemInternalArrayView itemsInternal()=0
Internal array of entities.
virtual String name() const =0
Family name.
virtual ItemVectorView view(Int32ConstArrayView local_ids)=0
View on the entities.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converts an array of unique numbers to local numbers.
virtual VariableItemInt32 & itemsNewOwner()=0
Variable containing the number of the new subdomain owning the entity.
Interface for mesh verification methods.
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.
virtual MeshHandle * findMeshHandle(const String &name, bool throw_exception)=0
Searches for the mesh with name name.
Internal part of IMeshModifier.
Interface of a mesh partitioning constraint manager.
Interface of a class providing utility functions on meshes.
Interface of the parallelism manager for a subdomain.
virtual void allocateBuffer()=0
Allocates the serializer memory.
virtual void setMode(eMode new_mode)=0
Sets the current mode.
Interface of the subdomain manager.
Definition ISubDomain.h:75
Interface managing execution time statistics.
Definition ITimeStats.h:44
virtual void dumpTimeAndMemoryUsage(IParallelMng *pm)=0
Displays the current date and memory consumption.
virtual ISubDomain * internalSubDomain() const =0
Temporary internal function to retrieve the subdomain.
Variable manager interface.
virtual VariableCollection usedVariables()=0
List of used variables.
virtual IVariable * findMeshVariable(IMesh *mesh, const String &name)=0
Returns the mesh variable named name or 0 if no such name exists.
virtual IObservable * writeObservable()=0
Observable for variables being written.
virtual IVariableMngInternal * _internalApi()=0
Internal Arcane API.
virtual IObservable * readObservable()=0
Observable for variables being read.
Interface of a variable.
Definition IVariable.h:40
virtual bool initialize(const ItemGroup &group, const String &value)=0
Initializes the variable on a group.
virtual void resizeFromGroup()=0
Sets the number of elements for a mesh variable.
virtual bool isUsed() const =0
Usage state of the variable.
virtual IItemFamily * itemFamily() const =0
Associated entity family.
virtual String name() const =0
Variable name.
bool isAncestor() const
Mesh entity group.
Definition ItemGroup.h:51
ItemGroupImpl * internal() const
Returns the group implementation.
Definition ItemGroup.h:125
eItemKind itemKind() const
Group kind. This is the kind of its elements.
Definition ItemGroup.h:114
bool null() const
true means the group is the null group
Definition ItemGroup.h:75
IMesh * mesh() const
Mesh to which this group belongs (0 for the null group).
Definition ItemGroup.h:131
Internal structure of a mesh entity.
Index of an Item in a variable.
Definition ItemLocalId.h:42
Base class for a mesh element.
Definition Item.h:84
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
Int32 owner() const
Owner subdomain number of the entity.
Definition Item.h:252
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
constexpr bool isOwn() const
true if the entity belongs to the subdomain
Definition Item.h:267
Implementation of a collection of elements in vector form.
Parameters necessary for building a mesh.
const ItemGroup & parentGroup() const
Parent group in the case of a sub-mesh, null otherwise.
const MeshKind meshKind() const
Mesh characteristics.
MeshBuildInfo & addMeshKind(const MeshKind &v)
Sets the mesh characteristics.
Arguments for mesh events.
Definition MeshEvents.h:44
IMesh * mesh() const
Associated mesh.
Characteristics of a mesh.
Definition MeshKind.h:113
Arguments for IMeshModifier::addCells().
Arguments for IMeshModifier::addFaces().
Information about a partitioned mesh.
void dumpStats() override
Prints mesh information.
Definition MeshStats.cc:63
static eItemKind kindTranspose(eItemKind kindA, IMesh *meshA, IMesh *meshB)
Transpose the kind kindA of mesh meshA to the associated kind in meshB.
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
Node of a mesh.
Definition Item.h:598
Encapsulation of an automatically destructing pointer.
Definition ScopedPtr.h:44
Structure containing the information to create a service.
Service creation properties.
bool null() const
Returns true if the string is null.
Definition String.cc:306
Positions the name of the currently executing action.
Definition Timer.h:119
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
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage pinfo() const
Flow for a parallel information message.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
1D data vector with value semantics (STL style).
Function each(Function f)
Applies the functor f to all elements in the collection.
List of nodes of a DOM tree.
Definition XmlNodeList.h:36
Node of a DOM tree.
Definition XmlNode.h:51
XmlNodeList children(const String &name) const
Set of child nodes of this node having the name name.
Definition XmlNode.cc:102
bool null() const
True if the node is null.
Definition XmlNode.h:303
IPrimaryMesh * createMesh(IMeshMng *mm, const MeshBuildInfo &build_info) override
Creates a mesh with the information from build_info.
void build() override
Build-level construction of the service.
Information for mesh exchange between subdomains.
Implementation of a mesh.
Definition DynamicMesh.h:98
IPrimaryMesh * toPrimaryMesh() override
Returns the instance in the form of an IPrimaryMesh.
void computeSynchronizeInfos() override
Recalculates synchronization information.
IItemFamily * nodeFamily() override
Returns the node family.
IItemFamily * cellFamily() override
Returns the cell family.
void endAllocate() override
Indicates the end of cell allocation.
ITraceMng * traceMng() override
Associated message manager.
IParallelMng * parallelMng() override
Parallelism manager.
bool isPrimaryMesh() const override
Indicates if the instance is a primary mesh.
IMesh * mesh() override
Associated mesh.
VariableNodeReal3 & nodesCoordinates() override
Node coordinates.
IItemFamily * createItemFamily(eItemKind ik, const String &name) override
Create a particle family named name.
String name() const override
Mesh name.
IMeshMng * meshMng() const override
Associated mesh manager.
void _readFromDump()
Reloads the mesh from protected variables.
IMeshModifier * modifier() override
Associated modifier interface.
void clearItems() override
Deletes all entities of all families in this mesh.
void updateGhostLayers() override
ItemFamilyList m_item_families
List of entity family interfaces.
IGhostLayerMng * ghostLayerMng() const override
Associated ghost layer manager.
void endUpdate() override
Notifies the instance that mesh modification is finished.
void destroyGroups() override
Destroys all groups of all families.
void _saveProperties()
Saves properties before a dump.
IItemFamily * findItemFamily(eItemKind ik, const String &name, bool create_if_needed, bool register_modifier_if_created) override
Returns the family named name.
Properties * properties() override
Properties associated with this mesh.
CellGroup ownCells() override
Group of all domain-specific cells.
IItemFamilyNetwork * itemFamilyNetwork() override
Family network interface (connected families).
IMesh * parentMesh() const override
Access to the parent mesh.
void _loadProperties()
Reloads properties from a dump.
void checkValidMesh() override
Check for the validity of internal mesh structures (internal).
void _prepareForDump()
Prepares variables for a dump.
void _prepareForDumpReal()
Prepares variables for a dump.
ItemGroupList m_all_groups
List of entity groups.
MeshRefinement * m_mesh_refinement
AMR.
void addFaces(Integer nb_face, Int64ConstArrayView face_infos, Int32ArrayView faces) override
Adds faces.
Interface for the manager of incremental connectivities indexed on entities.
void executeExtend(const Int32ConstArrayView *new_items_info)
Execute the action associated with the extension.
Information for exchanging entities of a given family and their characteristics.
Manager for compacting families of a mesh.
Interface for the mesh exchange manager between subdomains.
Mesh partitioning constraint manager.
Implementation of unstructured mesh refinement adaptation algorithms.
Mesh uniqueId() numbering manager.
Variables containing the information of connectivities common to 1D, 2D, and 3D meshes.
VariableArrayString m_item_families_name
Names of entity families.
VariableArrayString m_child_meshes_name
Names of parent meshes.
VariableArrayInteger m_item_families_kind
Kind of entities in the families.
VariableScalarString m_parent_mesh_name
Name of the parent mesh.
VariableScalarString m_parent_group_name
Name of the parent group.
VariableScalarInteger m_mesh_dimension
Mesh dimension.
Implementation of the tied interface manager.
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
ItemGroupT< Face > FaceGroup
Group of faces.
Definition ItemTypes.h:179
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
VariableRefScalarT< Integer > VariableScalarInteger
Scalar variable of integer type.
String getEnvironmentVariable(const String &name)
Environment variable named name.
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
Collection< ItemGroup > ItemGroupCollection
Collection of mesh item groups.
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< ItemInternal * > ItemInternalList
Type of the internal list of entities.
Definition ItemTypes.h:466
@ 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:480
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:341
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
SharedMeshVariableScalarRefT< Node, Real3 > SharedVariableNodeReal3
Quantity at the node of coordinate type.
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.
const char * itemKindName(eItemKind kind)
Entity kind name.
Array< Int32 > Int32Array
Dynamic one-dimensional array of 32-bit integers.
Definition UtilsTypes.h:127
Collection< IMesh * > IMeshCollection
Collection of meshes.
InternalConnectivityPolicy
Connectivity usage policy.
Definition ItemTypes.h:517
@ NewOnly
Allocates only the new connectivities.
Definition ItemTypes.h:554
eMeshAMRKind
AMR mesh type.
Definition MeshKind.h:49
@ Patch
The mesh is AMR by patch.
Definition MeshKind.h:55
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
@ None
The mesh is not AMR.
Definition MeshKind.h:51
@ PatchCartesianMeshOnly
The mesh is AMR by Cartesian patch (rectangular).
Definition MeshKind.h:57
Collection< ITiedInterface * > TiedInterfaceCollection
Collection of tied interfaces.
std::int32_t Int32
Signed integer type of 32 bits.