14#include "arcane/utils/HashTableMap.h"
15#include "arcane/utils/ITraceMng.h"
16#include "arcane/utils/CheckedConvert.h"
17#include "arcane/utils/ValueConvert.h"
19#include "arcane/core/parallel/BitonicSortT.H"
21#include "arcane/core/IParallelExchanger.h"
22#include "arcane/core/ISerializeMessage.h"
23#include "arcane/core/SerializeBuffer.h"
24#include "arcane/core/ISerializer.h"
25#include "arcane/core/ItemPrinter.h"
26#include "arcane/core/Timer.h"
27#include "arcane/core/IGhostLayerMng.h"
28#include "arcane/core/IItemFamilyPolicyMng.h"
29#include "arcane/core/IItemFamilySerializer.h"
30#include "arcane/core/ParallelMngUtils.h"
32#include "arcane/mesh/DynamicMesh.h"
33#include "arcane/mesh/DynamicMeshIncrementalBuilder.h"
58 using ItemInternalMap = DynamicMeshKindInfos::ItemInternalMap;
75 bool m_is_verbose =
false;
76 bool m_is_allocate =
false;
78 bool m_use_optimized_node_layer =
true;
79 bool m_use_only_minimal_cell_uid =
true;
85 void _sendAndReceiveCells(SubDomainItemMap& cells_to_send);
98, m_mesh(mesh_builder->
mesh())
99, m_mesh_builder(mesh_builder)
100, m_parallel_mng(m_mesh->parallelMng())
101, m_is_allocate(is_allocate)
105 Int32 vv = v.value();
106 m_use_optimized_node_layer = (vv == 1 || vv == 3);
107 m_use_only_minimal_cell_uid = (v == 2 || vv == 3);
110 m_is_verbose = (v.value() != 0);
117void GhostLayerBuilder2::
140 using BasicType =
Int64;
141 static constexpr Int64 nbBasicTypeSize() {
return 3; }
147 Int32 message_size = messageSize(values);
149 auto* ptr =
reinterpret_cast<const Int64*
>(fsi_base);
155 Int32 message_size = messageSize(values);
157 auto* ptr =
reinterpret_cast<Int64*
>(fsi_base);
164 Int64 message_size_i64 = values.
size() * nbBasicTypeSize();
165 Int32 message_size = CheckedConvert::toInteger(message_size_i64);
171 if ((message_size % nbBasicTypeSize()) != 0)
172 ARCANE_FATAL(
"Message size '{0}' is not a multiple of basic size '{1}'", message_size, nbBasicTypeSize());
173 Int32 nb_element = message_size / nbBasicTypeSize();
183 size_t h1 = std::hash<Int64>{}(a.node_uid);
184 size_t h2 = std::hash<Int64>{}(a.cell_uid);
185 size_t h3 = std::hash<Int32>{}(a.cell_owner);
191 return (a.node_uid == b.node_uid && a.cell_uid == b.cell_uid && a.cell_owner == b.cell_owner);
196 Int64 node_uid = NULL_ITEM_UNIQUE_ID;
197 Int64 cell_uid = NULL_ITEM_UNIQUE_ID;
198 Int32 cell_owner = -1;
213 Int64 k1_node_uid = k1.node_uid;
214 Int64 k2_node_uid = k2.node_uid;
215 if (k1_node_uid < k2_node_uid)
217 if (k1_node_uid > k2_node_uid)
220 Int64 k1_cell_uid = k1.cell_uid;
221 Int64 k2_cell_uid = k2.cell_uid;
222 if (k1_cell_uid < k2_cell_uid)
224 if (k1_cell_uid > k2_cell_uid)
227 return (k1.cell_owner < k2.cell_owner);
232 auto buf_view = BoundaryNodeInfo::asBasicBuffer(values);
233 return pm->send(buf_view, rank,
false);
238 auto buf_view = BoundaryNodeInfo::asBasicBuffer(values);
239 return pm->
recv(buf_view, rank,
false);
244 return BoundaryNodeInfo::messageSize(values);
250 bni.node_uid = INT64_MAX;
251 bni.cell_uid = INT64_MAX;
258 return bni.node_uid != INT64_MAX;
303 Integer nb_ghost_layer = m_mesh->ghostLayerMng()->nbGhostLayer();
304 info() <<
"** GHOST LAYER BUILDER V" << m_version <<
" with sort (nb_ghost_layer=" << nb_ghost_layer <<
")";
313 if (nb_ghost_layer == 0)
317 const bool is_non_manifold = m_mesh->meshKind().isNonManifold();
318 if (is_non_manifold && (m_version != 3))
319 ARCANE_FATAL(
"Only version 3 of ghostlayer builder is supported for non manifold meshes");
321 ItemInternalMap& cells_map = m_mesh->cellsMap();
322 ItemInternalMap& nodes_map = m_mesh->nodesMap();
324 Integer boundary_nodes_uid_count = 0;
328 if (m_version == 3) {
335 warning() <<
"Invalid call to addGhostLayers() with version 3 because mesh "
336 <<
" already has '" << nb_ghost <<
"' ghost cells. The computed ghost cells"
337 <<
" may be wrong. Use version 4 of ghost layer builder if you want to handle this case";
343 if (m_version >= 4) {
346 if (node_layer[node.
localId()] == 1)
347 ++boundary_nodes_uid_count;
356 node_layer[node.
localId()] = 1;
357 ++boundary_nodes_uid_count;
362 info() <<
"NB BOUNDARY NODE=" << boundary_nodes_uid_count;
364 for (
Integer current_layer = 1; current_layer <= nb_ghost_layer; ++current_layer) {
366 info() <<
"Processing layer " << current_layer;
369 if (m_version >= 4 && cell.
owner() != my_rank)
373 if (cell_layer[cell_lid] != (-1))
375 bool is_current_layer =
false;
377 Integer layer = node_layer[inode_local_id];
379 if (layer == current_layer) {
380 is_current_layer =
true;
384 if (is_current_layer) {
385 cell_layer[cell_lid] = current_layer;
389 Integer layer = node_layer[inode_local_id];
392 node_layer[inode_local_id] = current_layer + 1;
404 if (m_use_optimized_node_layer) {
408 Int32 layer = node_layer[lid];
410 node_layer[lid] = nb_ghost_layer + 1;
414 info() <<
"Mark remaining nodes nb=" << nb_no_layer;
417 for (
Integer i = 1; i <= nb_ghost_layer; ++i)
418 _addGhostLayer(i, node_layer);
440 ItemInternalMap& faces_map = m_mesh->facesMap();
453 inode.mutableItemBase().addFlags(shared_and_boundary_flags);
454 node_layer[inode.localId()] = 1;
457 iedge.mutableItemBase().addFlags(shared_and_boundary_flags);
460 _markBoundaryNodesFromEdges(node_layer);
466void GhostLayerBuilder2::
469 info() <<
"Processing ghost layer " << current_layer
470 <<
" node_layer_size=" << node_layer.
size();
479 bool is_verbose = m_is_verbose;
484 Int64 nb_added_for_different_rank = 0;
485 Int64 nb_added_for_in_layer = 0;
493 const bool do_only_minimal_uid = m_use_only_minimal_cell_uid;
504 Int32 node_lid = node.localId();
506 if (cell.
owner() != my_rank) {
508 ++nb_added_for_different_rank;
511 Integer layer = node_layer[node_lid];
512 do_it = layer <= current_layer;
514 ++nb_added_for_in_layer;
517 Int32 node_lid = node.localId();
518 if (do_only_minimal_uid) {
519 Int64 current_uid = node_cell_uids[node_lid];
520 if ((current_uid == NULL_ITEM_UNIQUE_ID) || cell_uid < current_uid) {
521 node_cell_uids[node_lid] = cell_uid;
523 info() <<
"AddNode node_uid=" << node.uniqueId() <<
" cell=" << cell_uid;
526 info() <<
"AddNode node_uid=" << node.uniqueId() <<
" cell=" << cell_uid <<
" not done current=" << current_uid;
529 Int64 node_uid = node.uniqueId();
531 nci.node_uid = node_uid;
532 nci.cell_uid = cell_uid;
533 nci.cell_owner = my_rank;
534 boundary_node_list.
add(nci);
536 info() <<
"AddNode node_uid=" << node.uniqueId() <<
" cell=" << cell_uid;
542 if (do_only_minimal_uid) {
544 Int32 lid = node.localId();
545 Int64 cell_uid = node_cell_uids[lid];
546 if (cell_uid != NULL_ITEM_UNIQUE_ID) {
547 Int64 node_uid = node.uniqueId();
549 nci.node_uid = node_uid;
550 nci.cell_uid = cell_uid;
551 nci.cell_owner = my_rank;
552 boundary_node_list.
add(nci);
557 info() <<
"NB BOUNDARY NODE LIST=" << boundary_node_list.
size()
558 <<
" nb_added_for_different_rank=" << nb_added_for_different_rank
559 <<
" nb_added_for_in_layer=" << nb_added_for_in_layer
560 <<
" do_only_minimal=" << do_only_minimal_uid;
563 SharedArray<BoundaryNodeInfo> all_boundary_node_info = boundary_node_list;
565 UniqueArray<BoundaryNodeToSendInfo> node_list_to_send;
567 ConstArrayView<BoundaryNodeInfo> all_bni = all_boundary_node_info;
569 for (
Integer i = 0; i < bi_n; ++i) {
573 Int64 node_uid = bni.node_uid;
575 for (; last_i < bi_n; ++last_i)
576 if (all_bni[last_i].node_uid != node_uid)
578 Integer nb_same_node = (last_i - i);
580 info() <<
"NB_SAME_NODE uid=" << node_uid <<
" n=" << nb_same_node <<
" last_i=" << last_i;
584 Int32 owner = bni.cell_owner;
585 bool has_ghost =
false;
586 for (
Integer z = 0; z < nb_same_node; ++z)
587 if (all_bni[i + z].cell_owner != owner) {
594 si.m_nb_cell = nb_same_node;
595 node_list_to_send.add(si);
597 info() <<
"Add ghost uid=" << node_uid <<
" index=" << i <<
" nb_same_node=" << nb_same_node;
605 ConstArrayView<BoundaryNodeInfo> all_bni = all_boundary_node_info;
606 Integer nb_node_to_send = node_list_to_send.size();
607 std::set<Int32> ranks_done;
608 for (
Integer i = 0; i < nb_node_to_send; ++i) {
609 Integer index = node_list_to_send[i].m_index;
610 Integer nb_cell = node_list_to_send[i].m_nb_cell;
614 for (
Integer kz = 0; kz < nb_cell; ++kz) {
615 Int32 krank = all_bni[index + kz].cell_owner;
616 if (ranks_done.find(krank) == ranks_done.end()) {
617 ranks_done.insert(krank);
623 nb_info_to_send[krank] += (nb_cell * 2) + 2;
630 for (
Integer i = 0; i < nb_rank; ++i) {
631 Integer nb_to_send = nb_info_to_send[i];
633 info() <<
"NB_TO_SEND rank=" << i <<
" n=" << nb_to_send;
639 for (
Integer i = 0; i < nb_rank; ++i) {
640 nb_info_to_send_indexes[i] = total_nb_to_send;
641 total_nb_to_send += nb_info_to_send[i];
643 info() <<
"TOTAL_NB_TO_SEND=" << total_nb_to_send;
645 UniqueArray<Int64> resend_infos(total_nb_to_send);
647 ConstArrayView<BoundaryNodeInfo> all_bni = all_boundary_node_info;
648 Integer nb_node_to_send = node_list_to_send.size();
649 std::set<Int32> ranks_done;
650 for (
Integer i = 0; i < nb_node_to_send; ++i) {
651 Integer node_index = node_list_to_send[i].m_index;
652 Integer nb_cell = node_list_to_send[i].m_nb_cell;
653 Int64 node_uid = all_bni[node_index].node_uid;
657 for (
Integer kz = 0; kz < nb_cell; ++kz) {
658 Int32 krank = all_bni[node_index + kz].cell_owner;
659 if (ranks_done.find(krank) == ranks_done.end()) {
660 ranks_done.insert(krank);
661 Integer send_index = nb_info_to_send_indexes[krank];
662 resend_infos[send_index] = node_uid;
664 resend_infos[send_index] = nb_cell;
666 for (
Integer zz = 0; zz < nb_cell; ++zz) {
667 resend_infos[send_index] = all_bni[node_index + zz].cell_uid;
669 resend_infos[send_index] = all_bni[node_index + zz].cell_owner;
672 nb_info_to_send_indexes[krank] = send_index;
680 Timer::SimplePrinter sp(
traceMng(),
"Sending size with AllToAll");
681 pm->allToAll(nb_info_to_send, nb_info_to_recv, 1);
685 for (
Integer i = 0; i < nb_rank; ++i)
686 info() <<
"NB_TO_RECV: I=" << i <<
" n=" << nb_info_to_recv[i];
689 for (
Integer i = 0; i < nb_rank; ++i)
690 total_nb_to_recv += nb_info_to_recv[i];
697 UniqueArray<Int64> recv_infos;
704 Int32 total_send = 0;
705 Int32 total_recv = 0;
706 for (
Integer i = 0; i < nb_rank; ++i) {
707 send_counts[i] = (
Int32)(nb_info_to_send[i] * vsize);
708 recv_counts[i] = (
Int32)(nb_info_to_recv[i] * vsize);
709 send_indexes[i] = total_send;
710 recv_indexes[i] = total_recv;
711 total_send += send_counts[i];
712 total_recv += recv_counts[i];
714 recv_infos.resize(total_nb_to_recv);
719 info() <<
"BUF_SIZES: send=" << send_buf.size() <<
" recv=" << recv_buf.size();
721 Timer::SimplePrinter sp(
traceMng(),
"Send values with AllToAll");
722 pm->allToAllVariable(send_buf, send_counts, send_indexes, recv_buf, recv_counts, recv_indexes);
726 SubDomainItemMap cells_to_send(50,
true);
735 UniqueArray<Int32> my_cells;
736 SharedArray<Int32> ranks_to_send;
737 std::set<Int32> ranks_done;
738 while (index < total_nb_to_recv) {
739 Int64 node_uid = recv_infos[index];
741 Int64 nb_cell = recv_infos[index];
743 Node current_node(nodes_map.
findItem(node_uid));
745 info() <<
"NODE uid=" << node_uid <<
" nb_cell=" << nb_cell <<
" idx=" << (index - 2);
747 ranks_to_send.clear();
749 for (
Integer kk = 0; kk < nb_cell; ++kk) {
750 Int64 cell_uid = recv_infos[index];
752 Int32 cell_owner = CheckedConvert::toInt32(recv_infos[index]);
754 if (kk == 0 && current_layer == 1 && m_is_allocate)
760 info() <<
" CELL=" << cell_uid <<
" owner=" << cell_owner;
761 if (cell_owner == my_rank) {
762 impl::ItemBase dcell = cells_map.
tryFind(cell_uid);
764 ARCANE_FATAL(
"Internal error: cell uid={0} is not in our mesh", cell_uid);
765 if (do_only_minimal_uid) {
767 for (CellLocalId c : current_node.cellIds())
771 my_cells.add(dcell.localId());
774 if (ranks_done.find(cell_owner) == ranks_done.end()) {
775 ranks_to_send.add(cell_owner);
776 ranks_done.insert(cell_owner);
782 info() <<
"CELLS TO SEND: node_uid=" << node_uid
783 <<
" nb_rank=" << ranks_to_send.size()
784 <<
" nb_cell=" << my_cells.size();
785 info(4) <<
"CELLS TO SEND: node_uid=" << node_uid
786 <<
" rank=" << ranks_to_send
787 <<
" cell=" << my_cells;
790 for (
Integer zrank = 0, zn = ranks_to_send.size(); zrank < zn; ++zrank) {
791 Int32 send_rank = ranks_to_send[zrank];
792 SubDomainItemMap::Data* d = cells_to_send.lookupAdd(send_rank);
794 for (
Integer zid = 0, zid_size = my_cells.size(); zid < zid_size; ++zid) {
796 c.add(my_cells[zid]);
802 info() <<
"GHOST V3 SERIALIZE CELLS";
803 _sendAndReceiveCells(cells_to_send);
821 bool is_verbose = m_is_verbose;
824 boundary_node_sorter.setNeedIndexAndRank(
false);
828 boundary_node_sorter.
sort(boundary_node_list);
834 for (
Integer i = 0; i < n; ++i) {
836 info() <<
"NODES_KEY i=" << i
837 <<
" node=" << bni.node_uid
838 <<
" cell=" << bni.cell_uid
839 <<
" rank=" << bni.cell_owner;
858 Integer begin_own_list_index = 0;
859 if (n != 0 && my_rank != 0) {
860 if (BoundaryNodeBitonicSortTraits::isValid(all_bni[0])) {
861 Int64 node_uid = all_bni[0].node_uid;
862 for (
Integer i = 0; i < n; ++i) {
863 if (all_bni[i].node_uid != node_uid) {
864 begin_own_list_index = i;
868 end_node_list.
add(all_bni[i]);
872 info() <<
"BEGIN_OWN_LIST_INDEX=" << begin_own_list_index <<
" end_node_list_size=" << end_node_list.
size();
874 for (
Integer k = 0, kn = end_node_list.
size(); k < kn; ++k)
875 info() <<
" SEND node_uid=" << end_node_list[k].node_uid
876 <<
" cell_uid=" << end_node_list[k].cell_uid;
883 Integer send_message_size = BoundaryNodeBitonicSortTraits::messageSize(end_node_list);
886 if (my_rank != (nb_rank - 1)) {
892 info() <<
"Send size=" << send_message_size <<
" Recv size=" << recv_message_size;
896 if (recv_message_size != 0) {
897 Int32 nb_element = BoundaryNodeInfo::nbElement(recv_message_size);
898 end_node_list_recv.
resize(nb_element);
899 requests.
add(BoundaryNodeBitonicSortTraits::recv(pm, my_rank + 1, end_node_list_recv));
901 if (send_message_size != 0)
902 requests.
add(BoundaryNodeBitonicSortTraits::send(pm, my_rank - 1, end_node_list));
906 boundary_node_list.
clear();
907 boundary_node_list.
addRange(all_bni.
subConstView(begin_own_list_index, n - begin_own_list_index));
908 boundary_node_list.
addRange(end_node_list_recv);
915void GhostLayerBuilder2::
916_sendAndReceiveCells(SubDomainItemMap& cells_to_send)
920 const bool is_verbose = m_is_verbose;
923 for (SubDomainItemMap::Enumerator i_map(cells_to_send); ++i_map;) {
924 Int32 sd = i_map.data()->key();
930 std::sort(std::begin(items), std::end(items));
931 auto new_end = std::unique(std::begin(items), std::end(items));
932 items.
resize(CheckedConvert::toInteger(new_end - std::begin(items)));
934 info(4) <<
"CELLS TO SEND SD=" << sd <<
" Items=" << items;
936 info(4) <<
"CELLS TO SEND SD=" << sd <<
" nb=" << items.size();
937 exchanger->addSender(sd);
939 exchanger->initializeCommunicationsMessages();
940 for (
Integer i = 0, ns = exchanger->nbSender(); i < ns; ++i) {
941 ISerializeMessage* sm = exchanger->messageToSend(i);
942 Int32 rank = sm->destination().value();
943 ISerializer* s = sm->serializer();
947 exchanger->processExchange();
948 info(4) <<
"END EXCHANGE CELLS";
949 for (
Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
950 ISerializeMessage* sm = exchanger->messageToReceive(i);
951 ISerializer* s = sm->serializer();
954 m_mesh_builder->printStats();
971 ItemInternalMap& faces_map = m_mesh->facesMap();
977 bool is_sub_domain_boundary_face =
false;
979 is_sub_domain_boundary_face =
true;
983 is_sub_domain_boundary_face =
true;
985 if (is_sub_domain_boundary_face) {
988 inode.mutableItemBase().addFlags(shared_and_boundary_flags);
990 iedge.mutableItemBase().addFlags(shared_and_boundary_flags);
993 _markBoundaryNodesFromEdges(node_layer);
999void GhostLayerBuilder2::
1003 if (!is_non_manifold)
1008 info() <<
"Mark boundary nodes from edges for non-manifold mesh";
1018 Int32 nb_dim2_cell = 0;
1019 Int32 nb_own_dim2_cell = 0;
1024 if (cell.
owner() == my_rank)
1028 if (nb_dim2_cell == nb_cell && nb_own_dim2_cell == 1) {
1030 for (Item inode : edge.
nodes()) {
1031 inode.mutableItemBase().addFlags(shared_and_boundary_flags);
1032 node_layer[inode.localId()] = 1;
1042_buildGhostLayerNewVersion(
DynamicMesh* mesh,
bool is_allocate,
Int32 version)
1045 glb.addGhostLayers();
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the start of the view.
Base class for 1D data vectors.
void addRange(ConstReferenceType val, Int64 n)
Adds n elements of value val to the end of the array.
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.
Constant view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
constexpr ConstArrayView< T > subConstView(Integer abegin, Integer asize) const noexcept
Sub-view (constant) starting from element abegin and containing asize elements.
Template class for converting a type.
CellConnectedListViewType cells() const
List of edge cells.
Int32 nbCell() const
Number of cells connected to the edge.
Cell cell(Int32 i) const
i-th cell of the face
Int32 nbCell() const
Number of cells of the face (1 or 2).
EdgeConnectedListViewType edges() const
List of edges of the face.
Hash table for associative arrays.
virtual Int32 maxLocalId() const =0
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Blocks while waiting for the rvalues requests to complete.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
MutableItemBase toMutable()
Mutable interface of this entity.
Int32 flags() const
Flags of the entity.
@ II_Shared
The entity is shared by another subdomain.
@ II_SubDomainBoundary
The entity is at the boundary of two subdomains.
@ II_Boundary
The entity is on the boundary.
Internal structure of a mesh entity.
Utility class for printing information about an entity.
Int16 dimension() const
Dimension of the element (<0 if unknown).
NodeConnectedListViewType nodes() const
List of nodes of the entity.
NodeLocalIdView nodeIds() const
List of nodes of the entity.
Base class for a mesh element.
const ItemTypeInfo * typeInfo() const
Information about the entity type.
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Int32 owner() const
Owner subdomain number of the entity.
ItemUniqueId uniqueId() const
Unique identifier across all domains.
constexpr bool isOwn() const
true if the entity belongs to the subdomain
impl::ItemBase itemBase() const
Internal part of the entity.
bool isNonManifold() const
True if the mesh structure is eMeshCellDimensionKind::NonManifold.
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
void addFlags(Int32 added_flags)
Adds the flags added_flags to those of the entity.
Parallel bitonic sort algorithm.
ConstArrayView< KeyType > keys() const override
After a sort, returns the list of elements on this rank.
void sort(ConstArrayView< KeyType > keys) override
Parallelly sorts the elements of keys on all ranks.
1D vector of data with reference semantics.
Displays the time elapsed between the call to the constructor and the destructor.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
TraceMessage warning() const
Flow for a warning message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Construction of a mesh incrementally.
Implementation of a mesh.
IItemFamily * nodeFamily() override
Returns the node family.
IParallelMng * parallelMng() override
Parallelism manager.
void serializeCells(ISerializer *buffer, Int32ConstArrayView cells_local_id) override
const MeshKind meshKind() const override
Mesh characteristics.
Functor for sorting BoundaryNodeInfo via bitonic sort.
Structure containing boundary node information.
Construction of ghost layers.
void _sortBoundaryNodeList(Array< BoundaryNodeInfo > &boundary_node_list)
Parallel sorting of the list of boundary node information.
void _markBoundaryItems(ArrayView< Int32 > node_layer)
Marks the entities at the edge of the sub-domain.
GhostLayerBuilder2(DynamicMeshIncrementalBuilder *mesh_builder, bool is_allocate, Int32 version)
Constructs an instance for the mesh mesh.
void addGhostLayers()
Adds ghost cell layers.
void _markBoundaryNodes(ArrayView< Int32 > node_layer)
Determines the boundary nodes.
Associative array of ItemInternal.
impl::ItemBase findItem(Int64 uid) const
Returns the unique ID entity uid.
void eachItem(const Lambda &lambda)
Template function to iterate over the instance's entities.
impl::ItemBase tryFind(Int64 key) const
Returns the entity associated with key if found, or the null entity otherwise.
Ref< IParallelExchanger > createExchangerRef(IParallelMng *pm)
Returns an interface to transfer messages between ranks.
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
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.
ArrayView< Integer > IntegerArrayView
C equivalent of a 1D array of integers.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Array< Int32 > Int32Array
Dynamic one-dimensional array of 32-bit integers.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
std::int32_t Int32
Signed integer type of 32 bits.