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;
478 bool is_verbose = m_is_verbose;
483 Int64 nb_added_for_different_rank = 0;
484 Int64 nb_added_for_in_layer = 0;
492 const bool do_only_minimal_uid = m_use_only_minimal_cell_uid;
497 if (m_version >= 4 && cell.
owner() != my_rank)
501 Int32 node_lid = node.localId();
503 if (cell.
owner() != my_rank) {
505 ++nb_added_for_different_rank;
508 Integer layer = node_layer[node_lid];
509 do_it = layer <= current_layer;
511 ++nb_added_for_in_layer;
514 Int32 node_lid = node.localId();
515 if (do_only_minimal_uid) {
516 Int64 current_uid = node_cell_uids[node_lid];
517 if ((current_uid == NULL_ITEM_UNIQUE_ID) || cell_uid < current_uid) {
518 node_cell_uids[node_lid] = cell_uid;
520 info() <<
"AddNode node_uid=" << node.uniqueId() <<
" cell=" << cell_uid;
523 info() <<
"AddNode node_uid=" << node.uniqueId() <<
" cell=" << cell_uid <<
" not done current=" << current_uid;
526 Int64 node_uid = node.uniqueId();
528 nci.node_uid = node_uid;
529 nci.cell_uid = cell_uid;
530 nci.cell_owner = my_rank;
531 boundary_node_list.
add(nci);
533 info() <<
"AddNode node_uid=" << node.uniqueId() <<
" cell=" << cell_uid;
539 if (do_only_minimal_uid) {
541 Int32 lid = node.localId();
542 Int64 cell_uid = node_cell_uids[lid];
543 if (cell_uid != NULL_ITEM_UNIQUE_ID) {
544 Int64 node_uid = node.uniqueId();
546 nci.node_uid = node_uid;
547 nci.cell_uid = cell_uid;
548 nci.cell_owner = my_rank;
549 boundary_node_list.
add(nci);
554 info() <<
"NB BOUNDARY NODE LIST=" << boundary_node_list.
size()
555 <<
" nb_added_for_different_rank=" << nb_added_for_different_rank
556 <<
" nb_added_for_in_layer=" << nb_added_for_in_layer
557 <<
" do_only_minimal=" << do_only_minimal_uid;
560 SharedArray<BoundaryNodeInfo> all_boundary_node_info = boundary_node_list;
562 UniqueArray<BoundaryNodeToSendInfo> node_list_to_send;
564 ConstArrayView<BoundaryNodeInfo> all_bni = all_boundary_node_info;
566 for (
Integer i = 0; i < bi_n; ++i) {
570 Int64 node_uid = bni.node_uid;
572 for (; last_i < bi_n; ++last_i)
573 if (all_bni[last_i].node_uid != node_uid)
575 Integer nb_same_node = (last_i - i);
577 info() <<
"NB_SAME_NODE uid=" << node_uid <<
" n=" << nb_same_node <<
" last_i=" << last_i;
581 Int32 owner = bni.cell_owner;
582 bool has_ghost =
false;
583 for (
Integer z = 0; z < nb_same_node; ++z)
584 if (all_bni[i + z].cell_owner != owner) {
591 si.m_nb_cell = nb_same_node;
592 node_list_to_send.add(si);
594 info() <<
"Add ghost uid=" << node_uid <<
" index=" << i <<
" nb_same_node=" << nb_same_node;
602 ConstArrayView<BoundaryNodeInfo> all_bni = all_boundary_node_info;
603 Integer nb_node_to_send = node_list_to_send.size();
604 std::set<Int32> ranks_done;
605 for (
Integer i = 0; i < nb_node_to_send; ++i) {
606 Integer index = node_list_to_send[i].m_index;
607 Integer nb_cell = node_list_to_send[i].m_nb_cell;
611 for (
Integer kz = 0; kz < nb_cell; ++kz) {
612 Int32 krank = all_bni[index + kz].cell_owner;
613 if (ranks_done.find(krank) == ranks_done.end()) {
614 ranks_done.insert(krank);
620 nb_info_to_send[krank] += (nb_cell * 2) + 2;
627 for (
Integer i = 0; i < nb_rank; ++i) {
628 Integer nb_to_send = nb_info_to_send[i];
630 info() <<
"NB_TO_SEND rank=" << i <<
" n=" << nb_to_send;
636 for (
Integer i = 0; i < nb_rank; ++i) {
637 nb_info_to_send_indexes[i] = total_nb_to_send;
638 total_nb_to_send += nb_info_to_send[i];
640 info() <<
"TOTAL_NB_TO_SEND=" << total_nb_to_send;
642 UniqueArray<Int64> resend_infos(total_nb_to_send);
644 ConstArrayView<BoundaryNodeInfo> all_bni = all_boundary_node_info;
645 Integer nb_node_to_send = node_list_to_send.size();
646 std::set<Int32> ranks_done;
647 for (
Integer i = 0; i < nb_node_to_send; ++i) {
648 Integer node_index = node_list_to_send[i].m_index;
649 Integer nb_cell = node_list_to_send[i].m_nb_cell;
650 Int64 node_uid = all_bni[node_index].node_uid;
654 for (
Integer kz = 0; kz < nb_cell; ++kz) {
655 Int32 krank = all_bni[node_index + kz].cell_owner;
656 if (ranks_done.find(krank) == ranks_done.end()) {
657 ranks_done.insert(krank);
658 Integer send_index = nb_info_to_send_indexes[krank];
659 resend_infos[send_index] = node_uid;
661 resend_infos[send_index] = nb_cell;
663 for (
Integer zz = 0; zz < nb_cell; ++zz) {
664 resend_infos[send_index] = all_bni[node_index + zz].cell_uid;
666 resend_infos[send_index] = all_bni[node_index + zz].cell_owner;
669 nb_info_to_send_indexes[krank] = send_index;
677 Timer::SimplePrinter sp(
traceMng(),
"Sending size with AllToAll");
678 pm->allToAll(nb_info_to_send, nb_info_to_recv, 1);
682 for (
Integer i = 0; i < nb_rank; ++i)
683 info() <<
"NB_TO_RECV: I=" << i <<
" n=" << nb_info_to_recv[i];
686 for (
Integer i = 0; i < nb_rank; ++i)
687 total_nb_to_recv += nb_info_to_recv[i];
694 UniqueArray<Int64> recv_infos;
701 Int32 total_send = 0;
702 Int32 total_recv = 0;
703 for (
Integer i = 0; i < nb_rank; ++i) {
704 send_counts[i] = (
Int32)(nb_info_to_send[i] * vsize);
705 recv_counts[i] = (
Int32)(nb_info_to_recv[i] * vsize);
706 send_indexes[i] = total_send;
707 recv_indexes[i] = total_recv;
708 total_send += send_counts[i];
709 total_recv += recv_counts[i];
711 recv_infos.resize(total_nb_to_recv);
716 info() <<
"BUF_SIZES: send=" << send_buf.size() <<
" recv=" << recv_buf.size();
718 Timer::SimplePrinter sp(
traceMng(),
"Send values with AllToAll");
719 pm->allToAllVariable(send_buf, send_counts, send_indexes, recv_buf, recv_counts, recv_indexes);
723 SubDomainItemMap cells_to_send(50,
true);
732 UniqueArray<Int32> my_cells;
733 SharedArray<Int32> ranks_to_send;
734 std::set<Int32> ranks_done;
735 while (index < total_nb_to_recv) {
736 Int64 node_uid = recv_infos[index];
738 Int64 nb_cell = recv_infos[index];
740 Node current_node(nodes_map.
findItem(node_uid));
742 info() <<
"NODE uid=" << node_uid <<
" nb_cell=" << nb_cell <<
" idx=" << (index - 2);
744 ranks_to_send.clear();
746 for (
Integer kk = 0; kk < nb_cell; ++kk) {
747 Int64 cell_uid = recv_infos[index];
749 Int32 cell_owner = CheckedConvert::toInt32(recv_infos[index]);
751 if (kk == 0 && current_layer == 1 && m_is_allocate)
757 info() <<
" CELL=" << cell_uid <<
" owner=" << cell_owner;
758 if (cell_owner == my_rank) {
759 impl::ItemBase dcell = cells_map.
tryFind(cell_uid);
761 ARCANE_FATAL(
"Internal error: cell uid={0} is not in our mesh", cell_uid);
762 if (do_only_minimal_uid) {
764 for (CellLocalId c : current_node.cellIds())
768 my_cells.add(dcell.localId());
771 if (ranks_done.find(cell_owner) == ranks_done.end()) {
772 ranks_to_send.add(cell_owner);
773 ranks_done.insert(cell_owner);
779 info() <<
"CELLS TO SEND: node_uid=" << node_uid
780 <<
" nb_rank=" << ranks_to_send.size()
781 <<
" nb_cell=" << my_cells.size();
782 info(4) <<
"CELLS TO SEND: node_uid=" << node_uid
783 <<
" rank=" << ranks_to_send
784 <<
" cell=" << my_cells;
787 for (
Integer zrank = 0, zn = ranks_to_send.size(); zrank < zn; ++zrank) {
788 Int32 send_rank = ranks_to_send[zrank];
789 SubDomainItemMap::Data* d = cells_to_send.lookupAdd(send_rank);
791 for (
Integer zid = 0, zid_size = my_cells.size(); zid < zid_size; ++zid) {
793 c.add(my_cells[zid]);
799 info() <<
"GHOST V3 SERIALIZE CELLS";
800 _sendAndReceiveCells(cells_to_send);
818 bool is_verbose = m_is_verbose;
821 boundary_node_sorter.setNeedIndexAndRank(
false);
825 boundary_node_sorter.
sort(boundary_node_list);
831 for (
Integer i = 0; i < n; ++i) {
833 info() <<
"NODES_KEY i=" << i
834 <<
" node=" << bni.node_uid
835 <<
" cell=" << bni.cell_uid
836 <<
" rank=" << bni.cell_owner;
855 Integer begin_own_list_index = 0;
856 if (n != 0 && my_rank != 0) {
857 if (BoundaryNodeBitonicSortTraits::isValid(all_bni[0])) {
858 Int64 node_uid = all_bni[0].node_uid;
859 for (
Integer i = 0; i < n; ++i) {
860 if (all_bni[i].node_uid != node_uid) {
861 begin_own_list_index = i;
865 end_node_list.
add(all_bni[i]);
869 info() <<
"BEGIN_OWN_LIST_INDEX=" << begin_own_list_index <<
" end_node_list_size=" << end_node_list.
size();
871 for (
Integer k = 0, kn = end_node_list.
size(); k < kn; ++k)
872 info() <<
" SEND node_uid=" << end_node_list[k].node_uid
873 <<
" cell_uid=" << end_node_list[k].cell_uid;
880 Integer send_message_size = BoundaryNodeBitonicSortTraits::messageSize(end_node_list);
883 if (my_rank != (nb_rank - 1)) {
889 info() <<
"Send size=" << send_message_size <<
" Recv size=" << recv_message_size;
893 if (recv_message_size != 0) {
894 Int32 nb_element = BoundaryNodeInfo::nbElement(recv_message_size);
895 end_node_list_recv.
resize(nb_element);
896 requests.
add(BoundaryNodeBitonicSortTraits::recv(pm, my_rank + 1, end_node_list_recv));
898 if (send_message_size != 0)
899 requests.
add(BoundaryNodeBitonicSortTraits::send(pm, my_rank - 1, end_node_list));
903 boundary_node_list.
clear();
904 boundary_node_list.
addRange(all_bni.
subConstView(begin_own_list_index, n - begin_own_list_index));
905 boundary_node_list.
addRange(end_node_list_recv);
912void GhostLayerBuilder2::
913_sendAndReceiveCells(SubDomainItemMap& cells_to_send)
917 const bool is_verbose = m_is_verbose;
920 for (SubDomainItemMap::Enumerator i_map(cells_to_send); ++i_map;) {
921 Int32 sd = i_map.data()->key();
927 std::sort(std::begin(items), std::end(items));
928 auto new_end = std::unique(std::begin(items), std::end(items));
929 items.
resize(CheckedConvert::toInteger(new_end - std::begin(items)));
931 info(4) <<
"CELLS TO SEND SD=" << sd <<
" Items=" << items;
933 info(4) <<
"CELLS TO SEND SD=" << sd <<
" nb=" << items.size();
934 exchanger->addSender(sd);
936 exchanger->initializeCommunicationsMessages();
937 for (
Integer i = 0, ns = exchanger->nbSender(); i < ns; ++i) {
938 ISerializeMessage* sm = exchanger->messageToSend(i);
939 Int32 rank = sm->destination().value();
940 ISerializer* s = sm->serializer();
944 exchanger->processExchange();
945 info(4) <<
"END EXCHANGE CELLS";
946 for (
Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
947 ISerializeMessage* sm = exchanger->messageToReceive(i);
948 ISerializer* s = sm->serializer();
951 m_mesh_builder->printStats();
968 ItemInternalMap& faces_map = m_mesh->facesMap();
974 bool is_sub_domain_boundary_face =
false;
976 is_sub_domain_boundary_face =
true;
980 is_sub_domain_boundary_face =
true;
982 if (is_sub_domain_boundary_face) {
985 inode.mutableItemBase().addFlags(shared_and_boundary_flags);
987 iedge.mutableItemBase().addFlags(shared_and_boundary_flags);
990 _markBoundaryNodesFromEdges(node_layer);
996void GhostLayerBuilder2::
1000 if (!is_non_manifold)
1005 info() <<
"Mark boundary nodes from edges for non-manifold mesh";
1015 Int32 nb_dim2_cell = 0;
1016 Int32 nb_own_dim2_cell = 0;
1021 if (cell.
owner() == my_rank)
1025 if (nb_dim2_cell == nb_cell && nb_own_dim2_cell == 1) {
1027 for (Item inode : edge.
nodes()) {
1028 inode.mutableItemBase().addFlags(shared_and_boundary_flags);
1029 node_layer[inode.localId()] = 1;
1039_buildGhostLayerNewVersion(
DynamicMesh* mesh,
bool is_allocate,
Int32 version)
1042 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.