14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/ArgumentException.h"
16#include "arcane/utils/CheckedConvert.h"
18#include "arcane/mesh/DynamicMesh.h"
19#include "arcane/mesh/FaceUniqueIdBuilder.h"
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/Timer.h"
24#include "arcane/parallel/BitonicSortT.H"
99 bool m_is_verbose =
false;
143 static const Int64 BITS_CELL_UID = 39;
144 static const Int64 BITS_RANK = 20;
145 static const Int64 BITS_INDEX = 5;
146 static const Int64 ONE_INT64 = 1;
147 static const Int64 MASK_CELL_UID = (ONE_INT64 << BITS_CELL_UID) - 1;
148 static const Int64 MASK_RANK = ((ONE_INT64 << BITS_RANK) - 1) << BITS_CELL_UID;
149 static const Int64 MASK_INDEX = ((ONE_INT64 << BITS_INDEX) - 1) << (BITS_CELL_UID + BITS_RANK);
155 setValue(NULL_ITEM_UNIQUE_ID, -1, -1);
160 bool isMaxValue()
const
162 Int64 max_id = (MASK_CELL_UID - 1);
163 return cellUid() == max_id;
168 Int64 max_id = (MASK_CELL_UID - 1);
169 setValue(max_id, -1, -1);
174 Int64 v_fli = face_local_index + 1;
175 Int64 v_rank = _rank + 1;
176 Int64 v_uid = cell_uid + 1;
177 m_value = v_fli << (BITS_CELL_UID + BITS_RANK);
178 m_value += v_rank << (BITS_CELL_UID);
180 if (cellUid() != cell_uid)
181 ARCANE_FATAL(
"Bad uid expected='{0}' computed='{1}' v={2}", cell_uid, cellUid(), m_value);
183 ARCANE_FATAL(
"Bad rank expected='{0}' computed='{1}'", _rank, rank());
184 if (faceLocalIndex() != face_local_index)
185 ARCANE_FATAL(
"Bad local_index expected='{0}' computed='{1}'", face_local_index, faceLocalIndex());
187 Int64 cellUid()
const {
return (m_value & MASK_CELL_UID) - 1; }
188 Int32 rank()
const {
return CheckedConvert::toInt32(((m_value & MASK_RANK) >> BITS_CELL_UID) - 1); }
189 Int32 faceLocalIndex()
const {
return CheckedConvert::toInt32(((m_value & MASK_INDEX) >> (BITS_CELL_UID + BITS_RANK)) - 1); }
191 bool isValid()
const {
return cellUid() != NULL_ITEM_UNIQUE_ID; }
209 : m_cell_uid(NULL_ITEM_UNIQUE_ID)
211 , m_face_local_index(-1)
216 bool isMaxValue()
const
218 Int64 max_id = INT64_MAX;
219 return cellUid() == max_id;
224 Int64 max_id = INT64_MAX;
225 setValue(max_id, -1, -1);
229 m_cell_uid = cell_uid;
231 m_face_local_index = face_local_index;
233 Int64 cellUid()
const {
return m_cell_uid; }
234 Int32 rank()
const {
return m_rank; }
235 Int32 faceLocalIndex()
const {
return m_face_local_index; }
236 bool isValid()
const {
return m_cell_uid != NULL_ITEM_UNIQUE_ID; }
242 Int32 m_face_local_index;
258 : m_node0_uid(NULL_ITEM_UNIQUE_ID)
259 , m_node1_uid(NULL_ITEM_UNIQUE_ID)
260 , m_node2_uid(NULL_ITEM_UNIQUE_ID)
261 , m_cell_uid(NULL_ITEM_UNIQUE_ID)
263 , m_face_local_index(-1)
265 bool hasSameNodes(
const BoundaryFaceInfo& fsi)
const
267 return fsi.m_node0_uid == m_node0_uid && fsi.m_node1_uid == m_node1_uid && fsi.m_node2_uid == m_node2_uid;
269 void setNodes(
Face face)
287 Int32 m_face_local_index;
305 AnyFaceInfo() =
default;
311 m_cell0.setValue(uid, rank, face_local_index);
315 m_cell1.setValue(uid, rank, face_local_index);
320 CellFaceInfo m_cell0;
321 CellFaceInfo m_cell1;
339 Int32 m_face_local_index_and_owner_rank;
340 Int32 m_index_in_rank_list;
360 if (k1.m_node0_uid < k2.m_node0_uid)
362 if (k1.m_node0_uid > k2.m_node0_uid)
366 if (k1.m_node1_uid < k2.m_node1_uid)
368 if (k1.m_node1_uid > k2.m_node1_uid)
372 if (k1.m_node2_uid < k2.m_node2_uid)
374 if (k1.m_node2_uid > k2.m_node2_uid)
378 return (k1.m_cell_uid < k2.m_cell_uid);
398 fsi.m_cell_uid = INT64_MAX;
399 fsi.m_rank = INT32_MAX;
400 fsi.m_node0_uid = INT64_MAX;
401 fsi.m_node1_uid = INT64_MAX;
402 fsi.m_node2_uid = INT64_MAX;
407 return fsi.m_cell_uid != INT64_MAX;
431 Int64 k1_cell0_uid = k1.m_cell0.cellUid();
432 Int64 k2_cell0_uid = k2.m_cell0.cellUid();
433 if (k1_cell0_uid < k2_cell0_uid)
435 if (k1_cell0_uid > k2_cell0_uid)
438 Int64 k1_face0_local_index = k1.m_cell0.faceLocalIndex();
439 Int64 k2_face0_local_index = k2.m_cell0.faceLocalIndex();
440 if (k1_face0_local_index < k2_face0_local_index)
442 if (k1_face0_local_index > k2_face0_local_index)
445 return (k1.m_cell1.cellUid() < k2.m_cell1.cellUid());
465 csi.m_cell0.setMaxValue();
466 csi.m_cell1.setMaxValue();
472 return !csi.m_cell0.isMaxValue();
483 bool operator()(
const Item& i1,
const Item& i2)
const
499, m_parallel_mng(
mesh->parallelMng())
514 if (m_parallel_mng->isParallel())
528 info() <<
"Compute FacesUniqueId() Sequential V3";
531 Int64 face_unique_id_counter = 0;
547 for (
Integer i = 0; i < nb_cell; ++i) {
548 Cell cell = cells[i];
550 if (face.uniqueId() == NULL_ITEM_UNIQUE_ID) {
551 face.mutableItemBase().setUniqueId(face_unique_id_counter);
552 ++face_unique_id_counter;
569 bool is_verbose = m_is_verbose;
573 info() <<
"Compute FacesUniqueId() V3 using parallel sort";
595 bool is_last_already_done =
false;
596 for (
Integer i = 0; i < n; ++i) {
598 Int64 cell_uid0 = fsi.m_cell_uid;
599 bool is_inside =
false;
603 is_inside = ((i + 1) != n && fsi.hasSameNodes(all_fsi[i + 1]));
604 if (is_last_already_done) {
605 is_last_already_done =
false;
611 Int64 cell_uid1 = next_fsi.m_cell_uid;
612 if (cell_uid0 < cell_uid1) {
613 csi.setCell0(cell_uid0, fsi.m_rank, fsi.m_face_local_index);
614 csi.setCell1(cell_uid1, next_fsi.m_rank, next_fsi.m_face_local_index);
617 csi.setCell0(cell_uid1, next_fsi.m_rank, next_fsi.m_face_local_index);
618 csi.setCell1(cell_uid0, fsi.m_rank, fsi.m_face_local_index);
620 is_last_already_done =
true;
623 csi.setCell0(cell_uid0, fsi.m_rank, fsi.m_face_local_index);
625 all_face_list.
add(csi);
628 info() <<
"FACES_KEY i=" << i
629 <<
" n0=" << fsi.m_node0_uid
630 <<
" n1=" << fsi.m_node1_uid
631 <<
" n2=" << fsi.m_node2_uid
632 <<
" cell=" << fsi.m_cell_uid
633 <<
" rank=" << fsi.m_rank
634 <<
" li=" << fsi.m_face_local_index
635 <<
" in=" << is_inside;
644 for (
Integer z = 0; z < cell_nb_face; ++z) {
650 Cell next_cell = (cell0 == cell) ? cell1 : cell0;
653 if (cell_uid < next_cell_uid) {
655 csi.m_cell0.setValue(cell_uid, my_rank, z);
657 csi.m_cell1.setValue(next_cell_uid, my_rank, -1);
658 all_face_list.
add(csi);
665 for (
Integer i = 0; i < n; ++i) {
667 info() <<
"CELL_TO_SORT i=" << i
668 <<
" cell0=" << csi.m_cell0.cellUid()
669 <<
" lidx0=" << csi.m_cell0.faceLocalIndex()
670 <<
" cell1=" << csi.m_cell1.cellUid();
676 all_face_sorter.setNeedIndexAndRank(
false);
678 all_face_sorter.
sort(all_face_list);
680 info() <<
"END_ALL_FACE_SORTER time=" << (
Real)(sort_end_time - sort_begin_time);
682 _resendCellsAndComputeFacesUniqueId(all_face_sorter.
keys());
696 bool is_verbose = m_is_verbose;
700 boundary_face_sorter.setNeedIndexAndRank(
false);
703 boundary_faces_info.
clear();
710 fsi.m_rank = my_rank;
716 if (cell.
face(z) == face) {
717 face_local_index = z;
720 fsi.m_face_local_index = face_local_index;
721 boundary_faces_info.
add(fsi);
727 for (
Integer i = 0; i < n; ++i) {
729 info() <<
"KEY i=" << i
730 <<
" n0=" << fsi.m_node0_uid
731 <<
" n1=" << fsi.m_node1_uid
732 <<
" n2=" << fsi.m_node2_uid
733 <<
" cell=" << fsi.m_cell_uid
734 <<
" rank=" << fsi.m_rank
735 <<
" li=" << fsi.m_face_local_index;
740 boundary_face_sorter.
sort(boundary_faces_info);
742 info() <<
"END_BOUNDARY_FACE_SORT time=" << (
Real)(sort_end_time - sort_begin_time);
748 for (
Integer i = 0; i < n; ++i) {
750 info() <<
" AFTER KEY i=" << i
751 <<
" n0=" << bfi.m_node0_uid
752 <<
" n1=" << bfi.m_node1_uid
753 <<
" n2=" << bfi.m_node2_uid
754 <<
" cell=" << bfi.m_cell_uid
755 <<
" rank=" << bfi.m_rank
756 <<
" li=" << bfi.m_face_local_index;
765 Integer begin_own_list_index = 0;
766 if (n != 0 && my_rank != 0) {
767 if (BoundaryFaceBitonicSortTraits::isValid(all_bfi[0])) {
768 Int64 node0_uid = all_bfi[0].m_node0_uid;
769 for (
Integer i = 0; i < n; ++i) {
770 if (all_bfi[i].m_node0_uid != node0_uid) {
771 begin_own_list_index = i;
775 end_face_list.
add(all_bfi[i]);
779 info() <<
"BEGIN_OWN_LIST_INDEX=" << begin_own_list_index;
781 for (
Integer k = 0, kn = end_face_list.
size(); k < kn; ++k)
782 info() <<
" SEND n0=" << end_face_list[k].m_node0_uid
783 <<
" n1=" << end_face_list[k].m_node1_uid
784 <<
" n2=" << end_face_list[k].m_node2_uid;
791 Integer send_message_size = BoundaryFaceBitonicSortTraits::messageSize(end_face_list);
796 if (my_rank != (nb_rank - 1)) {
806 if (recv_message_size != 0) {
808 end_face_list_recv.
resize(message_size);
809 requests.
add(BoundaryFaceBitonicSortTraits::recv(pm, my_rank + 1, end_face_list_recv));
811 if (send_message_size != 0)
812 requests.
add(BoundaryFaceBitonicSortTraits::send(pm, my_rank - 1, end_face_list));
816 boundary_faces_info.
clear();
817 boundary_faces_info.
addRange(all_bfi.
subConstView(begin_own_list_index, n - begin_own_list_index));
818 boundary_faces_info.
addRange(end_face_list_recv);
825void FaceUniqueIdBuilder2::
831 bool is_verbose = m_is_verbose;
838 for (
Integer i = 0; i < nb_computed_face; ++i) {
839 const AnyFaceInfo& csi = all_csi[i];
840 info() <<
"CELLS_KEY i=" << i
841 <<
" cell0=" << csi.m_cell0.cellUid()
842 <<
" lidx0=" << csi.m_cell0.faceLocalIndex()
843 <<
" cell1=" << csi.m_cell1.cellUid()
844 <<
" lidx1=" << csi.m_cell1.faceLocalIndex()
845 <<
" rank0=" << csi.m_cell0.rank()
846 <<
" rank1=" << csi.m_cell1.rank();
854 for (
Integer i = 0; i < nb_computed_face; ++i) {
855 const AnyFaceInfo& csi = all_csi[i];
856 Int32 rank0 = csi.m_cell0.rank();
857 Int32 rank1 = csi.m_cell1.rank();
859 ++nb_info_to_send[rank0];
862 if (csi.m_cell1.isValid() && rank1 != rank0)
863 ++nb_info_to_send[rank1];
878 for (
Integer i = 0; i < nb_rank; ++i) {
879 Int64 next = all_first_face_uid[i];
880 all_first_face_uid[i] = to_add;
887 for (
Integer i = 0; i < nb_rank; ++i) {
888 nb_info_to_send_indexes[i] = total_nb_to_send;
889 total_nb_to_send += nb_info_to_send[i];
891 info() <<
"TOTAL_NB_TO_SEND=" << total_nb_to_send;
893 UniqueArray<ResendCellInfo> resend_infos(total_nb_to_send);
895 for (
Integer i = 0; i < nb_computed_face; ++i) {
897 Int32 rank0 = csi.m_cell0.rank();
898 Int32 rank1 = csi.m_cell1.rank();
900 ResendCellInfo& rci0 = resend_infos[nb_info_to_send_indexes[rank0]];
901 rci0.m_cell_uid = csi.m_cell0.cellUid();
902 rci0.m_face_local_index_and_owner_rank = (csi.m_cell0.faceLocalIndex() * nb_rank) + rank0;
903 rci0.m_index_in_rank_list = i;
904 ++nb_info_to_send_indexes[rank0];
906 if (csi.m_cell1.isValid() && rank1 != rank0) {
907 ResendCellInfo& rci1 = resend_infos[nb_info_to_send_indexes[rank1]];
908 rci1.m_cell_uid = csi.m_cell1.cellUid();
910 rci1.m_face_local_index_and_owner_rank = (csi.m_cell1.faceLocalIndex() * nb_rank) + rank0;
911 rci1.m_index_in_rank_list = i;
912 ++nb_info_to_send_indexes[rank1];
919 info() <<
"TOTAL_NB_COMPUTED_FACE=" << total_nb_computed_face;
923 for (
Integer i = 0; i < nb_rank; ++i)
924 info() <<
"NB_TO_SEND: I=" << i <<
" n=" << nb_info_to_send[i];
928 Timer::SimplePrinter sp(
traceMng(),
"Sending size with AllToAll");
929 pm->allToAll(nb_info_to_send, nb_info_to_recv, 1);
933 for (
Integer i = 0; i < nb_rank; ++i)
934 info() <<
"NB_TO_RECV: I=" << i <<
" n=" << nb_info_to_recv[i];
937 for (
Integer i = 0; i < nb_rank; ++i)
938 total_nb_to_recv += nb_info_to_recv[i];
944 UniqueArray<ResendCellInfo> recv_infos;
951 Int32 total_send = 0;
952 Int32 total_recv = 0;
953 for (
Integer i = 0; i < nb_rank; ++i) {
954 send_counts[i] = (
Int32)(nb_info_to_send[i] * vsize);
955 recv_counts[i] = (
Int32)(nb_info_to_recv[i] * vsize);
956 send_indexes[i] = total_send;
957 recv_indexes[i] = total_recv;
958 total_send += send_counts[i];
959 total_recv += recv_counts[i];
961 recv_infos.resize(total_nb_to_recv);
966 info() <<
"BUF_SIZES: send=" << send_buf.size() <<
" recv=" << recv_buf.size();
968 Timer::SimplePrinter sp(
traceMng(),
"Send values with AllToAll");
969 pm->allToAllVariable(send_buf, send_counts, send_indexes, recv_buf, recv_counts, recv_indexes);
978 for (
Int32 rank = 0; rank < nb_rank; ++rank) {
979 for (
Integer z = 0, zs = nb_info_to_recv[rank]; z < zs; ++z) {
983 Int64 cell_uid = rci.m_cell_uid;
984 Int32 full_local_index = rci.m_face_local_index_and_owner_rank;
985 Int32 face_local_index = full_local_index / nb_rank;
986 Int32 owner_rank = full_local_index % nb_rank;
987 Int64 face_uid = all_first_face_uid[rank] + rci.m_index_in_rank_list;
988 info() <<
"RECV index=" << index <<
" uid=" << cell_uid
989 <<
" local_idx=" << full_local_index
990 <<
" face_local_idx=" << face_local_index
991 <<
" owner_rank=" << owner_rank
992 <<
" rank_idx=" << rci.m_index_in_rank_list
994 <<
" first_face_uid=" << all_first_face_uid[rank]
995 <<
" computed_uid=" << face_uid;
1003 for (
Int32 i = 0; i < nb_rank; ++i) {
1005 for (
Integer z = 0, zs = nb_info_to_recv[i]; z < zs; ++z) {
1009 Int64 cell_uid = rci.m_cell_uid;
1010 Int32 full_local_index = rci.m_face_local_index_and_owner_rank;
1011 Int32 face_local_index = full_local_index / nb_rank;
1012 Int32 owner_rank = full_local_index % nb_rank;
1016 ARCANE_FATAL(
"Can not find cell data for '{0}'", cell_uid);
1017 Face face = cell.face(face_local_index);
1018 Int64 face_uid = all_first_face_uid[rank] + rci.m_index_in_rank_list;
1019 face.mutableItemBase().setUniqueId(face_uid);
1020 face.mutableItemBase().setOwner(owner_rank, my_rank);
1037 info() <<
"Compute FacesUniqueId() V5 (experimental)";
1047 nodes_uid.
resize(nb_node);
1051 nodes_uid[index] = node.uniqueId();
1059 Int32 new_rank = my_rank;
1060 if (is_parallel && face.
nbCell() == 1)
1061 new_rank = A_NULL_RANK;
1092 if (face_uid == NULL_ITEM_UNIQUE_ID) {
1098 ARCANE_FATAL(
"Internal error in face uniqueId computation: nb_invalid={0}", nb_error);
1108 f.computeFacesUniqueIdAndOwnerVersion3();
1115_computeFaceUniqueIdVersion5(DynamicMesh*
mesh)
1117 FaceUniqueIdBuilder2 f(
mesh);
1118 f.computeFacesUniqueIdAndOwnerVersion5();
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Int64 generateHashUniqueId(SmallSpan< const Int64 > nodes_unique_id)
Generates a unique identifier from a list of node identifiers.
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.
constexpr Integer size() const noexcept
Returns the size of the array.
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.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
FaceConnectedListViewType faces() const
List of faces of the cell.
Face face(Int32 i) const
i-th face of the cell
Int32 nbFace() const
Number of faces of the cell.
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.
Cell cell(Int32 i) const
i-th cell of the face
Int32 nbCell() const
Number of cells of the face (1 or 2).
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 allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Performs an all-gather operation across all processors. This is a collective operation....
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.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
Node node(Int32 i) const
i-th node of the entity
NodeConnectedListViewType nodes() const
List of nodes of the entity.
Int32 nbNode() const
Number of nodes of the entity.
Base class for a mesh element.
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
ItemUniqueId uniqueId() const
Unique identifier across all domains.
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
void unsetUniqueId()
Nullifies the uniqueId to the value NULL_ITEM_UNIQUE_ID.
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.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Implementation of a mesh.
Functor for sorting AnyFaceInfo using bitonic sort.
Info for managing faces of sub-domains.
Functor for sorting BoundaryFaceInfo via bitonic sort.
Info for managing boundary faces of sub-domains.
Stores info about a face of a cell.
Stores info about a face of a cell.
Construction of the uniqueId() for faces.
void _checkFacesUniqueId()
Checks that all faces have a valid uid.
void _unsetFacesUniqueId()
Invalidates the uids to ensure they are all positioned.
void _computeAndSortBoundaryFaces(Array< BoundaryFaceInfo > &boundary_faces_info)
Determines the list of boundary faces for each subdomain and sorts them across all procs.
void _computeParallel()
Calculates the unique IDs of each face in parallel.
void computeFacesUniqueIdAndOwnerVersion3()
Calculates the unique IDs of each face in parallel.
void _computeSequential()
Calculates the unique IDs of each face sequentially.
FaceUniqueIdBuilder2(DynamicMesh *mesh)
Constructs an instance for the mesh mesh.
void computeFacesUniqueIdAndOwnerVersion5()
Calculates uniqueId() via a hash generated by the uniqueId() of the nodes.
Associative array of ItemInternal.
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.
Int32 count() const
Number of elements in the table.
@ ReduceSum
Sum of values.
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
ArrayView< Byte > ByteArrayView
C equivalent of a 1D array of characters.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
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.
double Real
Type representing a real number.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
unsigned char Byte
Type of a byte.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
@ Cell
The mesh is AMR by cell.
std::int32_t Int32
Signed integer type of 32 bits.