8#include <kernel/global/gate.hpp>
9#include <kernel/global/vector.hpp>
10#include <kernel/lafem/dense_vector.hpp>
11#include <kernel/lafem/vector_mirror.hpp>
12#include <kernel/lafem/tuple_mirror.hpp>
13#include <kernel/util/omp_util.hpp>
24 template<
typename IdxVector_>
190 template<
typename LocalVector_,
typename Mirror_>
200 typedef typename LocalVectorType::DataType
DataType;
210 typedef typename LocalVectorType::template ContainerTypeByDI<IndexType, IndexType>
IndexVectorType;
320 r += x.second.bytes();
322 r += x.second.bytes();
380 return Index(this->_owner_mirrors.size());
386 return Index(this->_donee_mirrors.size());
400 return this->_owner_ranks.at(i);
414 return this->_donee_ranks.at(i);
431 return this->_owner_mirrors.at(i);
448 return this->_donee_mirrors.at(i);
462 XASSERTM(!this->_all_global_dof_offset.empty(),
"You did not ask to assemble the global dof offsets");
477 XASSERTM(!this->_all_global_dof_counts.empty(),
"You did not ask to assemble the global dof counts");
495 XASSERTM(yes_i_really_want_to_do_this,
"You probably don't want to do this!");
499 "allgather assembly not possible for more than a billion DOFs!");
501 std::size_t num_ranks = std::size_t(this->_comm->
size());
507 this->_all_global_dof_offset.resize(num_ranks, 0);
508 this->_all_global_dof_counts.resize(num_ranks, 0);
511 this->_comm->
allgather(&my_off, 1, this->_all_global_dof_offset.data(), 1);
512 this->_comm->
allgather(&my_nod, 1, this->_all_global_dof_counts.data(), 1);
530 XASSERTM(this->_comm !=
nullptr,
"need a communicator here!");
536 const int my_rank = comm.
rank();
537 const std::vector<int>& neighbor_ranks = gate.
_ranks;
543 this->_local_dof_count = vec_tmpl.template size<LAFEM::Perspective::pod>();
544 this->_extra_local_dof_count = extra_local;
545 this->_extra_shared_dof_count = extra_shared;
556 ADPAuxType::alloc_idx_vector(dof_owners, vec_tmpl,
IndexType(my_rank));
559 for(std::size_t i(0); i < neighbor_ranks.size(); ++i)
563 if(neighbor_ranks.at(i) < my_rank)
568 ADPAuxType::update_owners(
IndexType(neighbor_ranks.at(i)), dof_owners, gate.
get_mirrors().at(i));
574 this->_owned_dof_count = ADPAuxType::build_owned_mirror(
IndexType(my_rank), this->_owned_mirror, dof_owners);
583 const bool is_last_process = (this->_comm->
rank()+1 == this->_comm->
size());
588 XASSERTM(this->_owned_dof_count >
Index(0),
"this process has no DOFs!");
601 ADPAuxType::alloc_idx_vector(own_dof_idx, vec_tmpl, ~
IndexType(0));
602 ADPAuxType::build_owned_dofs(
IndexType(my_rank), own_dof_idx, dof_owners, 0u);
605 for(std::size_t i(0); i < neighbor_ranks.size(); ++i)
608 const int neighbor_rank = neighbor_ranks.at(i);
616 if(neighbor_rank < my_rank)
625 if(ADPAuxType::build_owner_mirror(
IndexType(neighbor_rank), owner_mirror, halo_mirror, dof_owners) >
Index(0))
642 Index num_donee_dofs = ADPAuxType::count_donee_dofs(halo_mirror, own_dof_idx);
643 if(num_donee_dofs >
Index(0))
647 ADPAuxType::build_donee_mirror(donee_mirror, halo_mirror, own_dof_idx, 0u);
665 ADPAuxType::alloc_idx_vector(this->_global_dof_idx, vec_tmpl, ~
IndexType(0));
669 ADPAuxType::init_global_dof_idx(this->_global_dof_idx, this->_owned_mirror, this->_global_dof_offset);
679 std::vector<std::vector<IndexType>> recv_bufs(num_neigh_owner);
680 for(
Index i(0); i < num_neigh_owner; ++i)
682 const std::size_t num_idx =
_owner_mirrors.at(i).buffer_size(vec_tmpl);
683 recv_bufs.at(i).resize(num_idx, ~
IndexType(0));
691 std::vector<std::vector<IndexType>> send_bufs(num_neigh_donee);
692 for(
Index i(0); i < num_neigh_donee; ++i)
698 send_bufs.at(i).resize(num_idx, ~
IndexType(0));
699 _get_donee_dofs(send_bufs.at(i),
_donee_mirrors.at(i), this->_global_dof_offset);
704 for(std::size_t i(0u); recv_reqs.
wait_any(i); )
708 ADPAuxType::set_owner_dofs(this->_global_dof_idx, recv_bufs.at(i),
_owner_mirrors.at(i), 0u);
715 std::vector<Index> local_num;
716 ADPAuxType::get_local_dof_count(local_num, this->_global_dof_idx, this->_owned_mirror);
719 std::vector<Index> global_num(local_num.size());
723 std::vector<Index> global_first(local_num.size());
727 std::deque<Index> loc_off, loc_num, glob_first, glob_num;
728 for(
Index i(0), off(0); i <
Index(local_num.size()); ++i)
730 loc_off.push_back(off);
731 loc_num.push_back(local_num[i]);
732 glob_num.push_back(global_num[i]);
733 glob_first.push_back(global_first[i]);
738 this->_block_information = ADPAuxType::build_block_info(this->_global_dof_idx, this->_global_dof_offset,
739 glob_first, glob_num, loc_off, loc_num);
742 template<
typename DT2_>
743 void upload_vector(DT2_* owned_dofs,
const LocalVectorType& local_vector,
744 const DataType* extra_local =
nullptr,
const DataType* extra_shared =
nullptr)
const
747 ADPAuxType::gather(owned_dofs, local_vector, this->_owned_mirror);
750 if(this->_extra_local_dof_count >
Index(0))
752 XASSERT(extra_local !=
nullptr);
755 dst[i] = DT2_(extra_local[i]);
759 if(this->_extra_shared_dof_count >
Index(0))
761 XASSERT(extra_shared !=
nullptr);
762 if(this->_comm->
rank() + 1 == this->_comm->size())
766 dst[i] = DT2_(extra_shared[i]);
771 template<
typename DT2_>
772 void download_vector(
const DT2_* owned_dofs,
LocalVectorType& local_vector,
776 XASSERT(this->_comm !=
nullptr);
779 const std::size_t num_neigh_owner = this->_owner_mirrors.size();
780 const std::size_t num_neigh_donee = this->_donee_mirrors.size();
789 Dist::RequestVector recv_reqs(num_neigh_owner);
790 std::vector<BufferVectorType> recv_bufs(num_neigh_owner);
791 for(std::size_t i(0); i < num_neigh_owner; ++i)
795 recv_bufs.at(i) = this->_owner_mirrors.at(i).create_buffer(local_vector);
797 recv_reqs[i] = this->_comm->
irecv(recv_bufs.at(i).elements(), recv_bufs.at(i).size(), this->_owner_ranks.at(i));
802 Dist::RequestVector send_reqs(num_neigh_donee);
803 std::vector<BufferVectorType> send_bufs(num_neigh_donee);
804 for(
Index i(0); i < num_neigh_donee; ++i)
810 _gather(send_bufs.at(i), owned_dofs, mir);
812 send_reqs[i] = this->_comm->
isend(send_bufs.at(i).elements(), send_bufs.at(i).size(), this->_donee_ranks.at(i));
816 local_vector.format();
819 ADPAuxType::scatter(owned_dofs, local_vector, this->_owned_mirror);
822 for(std::size_t idx(0u); recv_reqs.wait_any(idx); )
825 ADPAuxType::scatter(recv_bufs.at(idx).elements(), local_vector, this->_owner_mirrors.at(idx));
832 send_reqs.wait_all();
835 if(this->_extra_local_dof_count >
Index(0))
837 XASSERT(extra_local !=
nullptr);
844 if(this->_extra_shared_dof_count >
Index(0))
846 XASSERT(extra_shared !=
nullptr);
849 if(this->_comm->
rank() + 1 == this->_comm->size())
857 this->_comm->
bcast(extra_shared, std::size_t(this->_extra_shared_dof_count), this->_comm->
size() - 1);
862 static Index _get_donee_dofs(std::vector<IndexType>& send_buf,
863 const LAFEM::VectorMirror<DataType, IndexType>& donee_mir,
Index offset)
865 const Index num_idx = donee_mir.num_indices();
866 const IndexType* mir_idx = donee_mir.indices();
867 for(
Index j(0); j < num_idx; ++j)
868 send_buf[j] =
IndexType(offset) + mir_idx[j];
873 template<
typename DT2_>
874 static Index _gather(
875 LAFEM::DenseVector<DataType, IndexType>& buffer,
877 const LAFEM::VectorMirror<DataType, IndexType>& mirror)
879 const Index n = mirror.num_indices();
882 for(
Index i = 0u; i < n; ++i)
897 template<
typename IT_>
898 class ADPAux<LAFEM::DenseVector<IT_, IT_>>
901 template<
typename DT_>
902 static Index get_local_dof_count(std::vector<Index>& v,
903 const LAFEM::DenseVector<IT_, IT_>& DOXY(global_dof_idx),
904 const LAFEM::VectorMirror<DT_, IT_>& owned_mirror)
906 v.push_back(owned_mirror.num_indices());
910 static String build_block_info(
911 const LAFEM::DenseVector<IT_, IT_>& DOXY(global_dof_idx), Index global_offset,
912 std::deque<Index>& global_first, std::deque<Index>& global_num,
913 std::deque<Index>& local_offset, std::deque<Index>& local_num)
915 String s =
"<Scalar";
916 s +=
" gc=\"" +
stringify(global_num.front()) +
"\"";
917 s +=
" gf=\"" +
stringify(global_first.front()) +
"\"";
918 s +=
" go=\"" +
stringify(global_offset + local_offset.front()) +
"\"";
919 s +=
" lc=\"" +
stringify(local_num.front()) +
"\"";
920 s +=
" lo=\"" +
stringify(local_offset.front()) +
"\"";
923 global_num.pop_front();
924 local_offset.pop_front();
925 local_num.pop_front();
929 template<
typename DT_>
930 static void alloc_idx_vector(LAFEM::DenseVector<IT_, IT_>& idx_vec,
931 const LAFEM::DenseVector<DT_, IT_>& tmpl_vec, IT_ value)
933 idx_vec = LAFEM::DenseVector<IT_, IT_>(tmpl_vec.size(), value);
936 template<
typename DT_>
937 static void update_owners(
const IT_ neighbor_rank,
938 LAFEM::DenseVector<IT_, IT_>& dof_owners,
939 const LAFEM::VectorMirror<DT_, IT_>& mirror)
941 const Index num_indices = mirror.num_indices();
942 const IT_* mir_idx = mirror.indices();
943 IT_* dof_own = dof_owners.elements();
944 for(Index j(0); j < num_indices; ++j)
946 IT_& dof_owner = dof_own[mir_idx[j]];
947 if(neighbor_rank < dof_owner)
948 dof_owner = neighbor_rank;
952 static Index build_owned_dofs(
const IT_ my_rank,
953 LAFEM::DenseVector<IT_, IT_>& owned_dofs,
954 const LAFEM::DenseVector<IT_, IT_>& dof_owners, Index offset)
956 const Index n = dof_owners.size();
957 const IT_* dof_own = dof_owners.elements();
958 IT_* own_idx = owned_dofs.elements();
961 for(Index i = 0; i < n; ++i)
963 if(dof_own[i] == my_rank)
964 own_idx[i] = IT_(offset + k++);
970 template<
typename DT_>
971 static Index build_owned_mirror(
const IT_ owner_rank,
972 LAFEM::VectorMirror<DT_, IT_>& owner_mirror,
973 const LAFEM::DenseVector<IT_, IT_>& dof_owners)
976 const Index n = dof_owners.size();
977 const IT_* dof_own = dof_owners.elements();
978 Index num_owned = 0u;
979 for(Index i = 0; i < n; ++i)
981 if(dof_own[i] == owner_rank)
986 owner_mirror = LAFEM::VectorMirror<DT_, IT_>(n, num_owned);
987 IT_* mir_idx = owner_mirror.indices();
990 for(Index i = 0, k = 0; i < n; ++i)
992 if(dof_own[i] == owner_rank)
994 mir_idx[k++] = IT_(i);
1001 template<
typename DT_>
1002 static Index build_owner_mirror(
const IT_ neighbor_rank,
1003 LAFEM::VectorMirror<DT_, IT_>& owner_mirror,
1004 const LAFEM::VectorMirror<DT_, IT_>& halo_mirror,
1005 const LAFEM::DenseVector<IT_, IT_>& dof_owners)
1008 const Index n = halo_mirror.num_indices();
1009 const IT_* halo_idx = halo_mirror.indices();
1010 const IT_* dof_own = dof_owners.elements();
1013 Index num_owner = 0u;
1014 for(Index i = 0; i < n; ++i)
1016 if(dof_own[halo_idx[i]] == neighbor_rank)
1021 owner_mirror = LAFEM::VectorMirror<DT_, IT_>(dof_owners.size(), num_owner);
1023 if(num_owner <=
Index(0))
1027 IT_* own_idx = owner_mirror.indices();
1028 for(IT_ i = 0, k = 0; i < n; ++i)
1030 if(dof_own[halo_idx[i]] == neighbor_rank)
1032 own_idx[k++] = halo_idx[i];
1039 template<
typename DT_>
1040 static Index count_donee_dofs(
1041 const LAFEM::VectorMirror<DT_, IT_>& halo_mirror,
1042 const LAFEM::DenseVector<IT_, IT_>& own_dof_idx)
1045 const Index n = halo_mirror.num_indices();
1046 const IT_* halo_idx = halo_mirror.indices();
1047 const IT_* own_idx = own_dof_idx.elements();
1050 Index num_donee = 0u;
1051 for(Index i = 0; i < n; ++i)
1053 if(own_idx[halo_idx[i]] != ~IT_(0))
1060 template<
typename DT_>
1061 static Index build_donee_mirror(
1062 LAFEM::VectorMirror<DT_, IT_>& donee_mirror,
1063 const LAFEM::VectorMirror<DT_, IT_>& halo_mirror,
1064 const LAFEM::DenseVector<IT_, IT_>& own_dof_idx, Index offset)
1067 const Index n = halo_mirror.num_indices();
1068 const IT_* halo_idx = halo_mirror.indices();
1069 const IT_* own_idx = own_dof_idx.elements();
1070 IT_* donee_idx = donee_mirror.indices();
1074 for(Index i = 0; i < n; ++i)
1076 if(own_idx[halo_idx[i]] != ~IT_(0))
1078 donee_idx[offset + k++] = own_idx[halo_idx[i]];
1085 template<
typename DT_>
1086 static Index init_global_dof_idx(
1087 LAFEM::DenseVector<IT_, IT_>& global_dof_idx,
1088 const LAFEM::VectorMirror<DT_, IT_>& owned_mirror, Index offset)
1090 IT_* g_dof_idx = global_dof_idx.elements();
1091 const IT_* own_idx = owned_mirror.indices();
1092 const Index n = owned_mirror.num_indices();
1093 for(Index i = 0; i < n; ++i)
1094 g_dof_idx[own_idx[i]] = IT_(offset + i);
1098 template<
typename DT_>
1099 static Index set_owner_dofs(
1100 LAFEM::DenseVector<IT_, IT_>& glob_dof_idx,
1101 const std::vector<IT_>& recv_buf,
1102 const LAFEM::VectorMirror<DT_, IT_>& mirror, Index offset)
1104 const Index num_indices = mirror.num_indices();
1105 const IT_* mir_idx = mirror.indices();
1106 IT_* g_dof_idx = glob_dof_idx.elements();
1107 for(Index j(0); j < num_indices; ++j)
1108 g_dof_idx[mir_idx[j]] = recv_buf[offset + j];
1112 template<
typename DT_,
typename DT2_>
1113 static Index gather(DT2_* buf,
1114 const LAFEM::DenseVector<DT_, IT_>& vector,
1115 const LAFEM::VectorMirror<DT_, IT_>& mirror)
1117 XASSERT(mirror.size() == vector.size());
1118 const Index n = mirror.num_indices();
1119 const IT_* idx = mirror.indices();
1120 const DT_* val = vector.elements();
1121 for(Index i = 0u; i < n; ++i)
1122 buf[i] = DT2_(val[idx[i]]);
1126 template<
typename DT_,
typename DT2_>
1127 static Index scatter(
const DT2_* buf,
1128 LAFEM::DenseVector<DT_, IT_>& vector,
1129 const LAFEM::VectorMirror<DT_, IT_>& mirror)
1131 XASSERT(mirror.size() == vector.size());
1132 const Index n = mirror.num_indices();
1133 const IT_* idx = mirror.indices();
1134 DT_* val = vector.elements();
1135 for(Index i = 0u; i < n; ++i)
1136 val[idx[i]] = DT_(buf[i]);
1143 template<
typename IT_,
int bs_>
1144 class ADPAux<LAFEM::DenseVectorBlocked<IT_, IT_, bs_>>
1147 template<
typename DT_>
1148 static Index get_local_dof_count(std::vector<Index>& v,
1149 const LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& DOXY(global_dof_idx),
1150 const LAFEM::VectorMirror<DT_, IT_>& owned_mirror)
1152 v.push_back(owned_mirror.num_indices() *
Index(bs_));
1156 static String build_block_info(
1157 const LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& DOXY(global_dof_idx), Index global_offset,
1158 std::deque<Index>& global_first, std::deque<Index>& global_num,
1159 std::deque<Index>& local_offset, std::deque<Index>& local_num)
1161 String s =
"<Blocked";
1163 s +=
" gc=\"" +
stringify(global_num.front()) +
"\"";
1164 s +=
" gf=\"" +
stringify(global_first.front()) +
"\"";
1165 s +=
" go=\"" +
stringify(global_offset + local_offset.front()) +
"\"";
1166 s +=
" lc=\"" +
stringify(local_num.front()) +
"\"";
1167 s +=
" lo=\"" +
stringify(local_offset.front()) +
"\"";
1170 global_num.pop_front();
1171 local_offset.pop_front();
1172 local_num.pop_front();
1176 template<
typename DT_>
1177 static void alloc_idx_vector(LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& idx_vec,
1178 const LAFEM::DenseVectorBlocked<DT_, IT_, bs_>& tmpl_vec, IT_ value)
1180 idx_vec = LAFEM::DenseVectorBlocked<IT_, IT_, bs_>(tmpl_vec.size(), value);
1183 template<
typename DT_>
1184 static void update_owners(
const IT_ neighbor_rank,
1185 LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& dof_owners,
1186 const LAFEM::VectorMirror<DT_, IT_>& mirror)
1188 const Index num_indices = mirror.num_indices();
1189 const IT_* mir_idx = mirror.indices();
1190 auto* dof_own = dof_owners.elements();
1191 for(Index j(0); j < num_indices; ++j)
1193 auto& dof_owner = dof_own[mir_idx[j]];
1194 if(neighbor_rank < dof_owner[0])
1196 for(
int k = 0; k < bs_; ++k)
1197 dof_owner[k] = neighbor_rank;
1202 static Index build_owned_dofs(
const IT_ my_rank,
1203 LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& owned_dofs,
1204 const LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& dof_owners, Index offset)
1206 const Index n = dof_owners.size();
1207 const auto* dof_own = dof_owners.elements();
1208 auto* own_idx = owned_dofs.elements();
1211 for(Index i = 0; i < n; ++i)
1213 if(dof_own[i][0] == my_rank)
1215 for(
int j = 0; j < bs_; ++j)
1216 own_idx[i][j] = IT_(offset + k++);
1223 template<
typename DT_>
1224 static Index build_owned_mirror(
const IT_ owner_rank,
1225 LAFEM::VectorMirror<DT_, IT_>& owner_mirror,
1226 const LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& dof_owners)
1229 const Index n = dof_owners.size();
1230 const auto* dof_own = dof_owners.elements();
1231 Index num_owned = 0u;
1232 for(Index i = 0; i < n; ++i)
1234 if(dof_own[i][0] == owner_rank)
1239 owner_mirror = LAFEM::VectorMirror<DT_, IT_>(n, num_owned);
1240 IT_* mir_idx = owner_mirror.indices();
1243 for(Index i = 0, k = 0; i < n; ++i)
1245 if(dof_own[i][0] == owner_rank)
1247 mir_idx[k++] = IT_(i);
1251 return num_owned *
Index(bs_);
1254 template<
typename DT_>
1255 static Index build_owner_mirror(
const IT_ neighbor_rank,
1256 LAFEM::VectorMirror<DT_, IT_>& owner_mirror,
1257 const LAFEM::VectorMirror<DT_, IT_>& halo_mirror,
1258 const LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& dof_owners)
1261 const Index n = halo_mirror.num_indices();
1262 const IT_* halo_idx = halo_mirror.indices();
1263 const auto* dof_own = dof_owners.elements();
1266 Index num_owner = 0u;
1267 for(Index i = 0; i < n; ++i)
1269 if(dof_own[halo_idx[i]][0] == neighbor_rank)
1274 owner_mirror = LAFEM::VectorMirror<DT_, IT_>(dof_owners.size(), num_owner);
1276 if(num_owner <=
Index(0))
1280 IT_* own_idx = owner_mirror.indices();
1281 for(IT_ i = 0, k = 0; i < n; ++i)
1283 if(dof_own[halo_idx[i]][0] == neighbor_rank)
1285 own_idx[k++] = halo_idx[i];
1289 return num_owner *
Index(bs_);
1292 template<
typename DT_>
1293 static Index count_donee_dofs(
1294 const LAFEM::VectorMirror<DT_, IT_>& halo_mirror,
1295 const LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& own_dof_idx)
1298 const Index n = halo_mirror.num_indices();
1299 const IT_* halo_idx = halo_mirror.indices();
1300 const auto* own_idx = own_dof_idx.elements();
1303 Index num_donee = 0u;
1304 for(Index i = 0; i < n; ++i)
1306 if(own_idx[halo_idx[i]][0] != ~IT_(0))
1307 num_donee +=
Index(bs_);
1313 template<
typename DT_>
1314 static Index build_donee_mirror(
1315 LAFEM::VectorMirror<DT_, IT_>& donee_mirror,
1316 const LAFEM::VectorMirror<DT_, IT_>& halo_mirror,
1317 const LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& own_dof_idx, Index offset)
1320 const Index n = halo_mirror.num_indices();
1321 const IT_* halo_idx = halo_mirror.indices();
1322 const auto* own_idx = own_dof_idx.elements();
1323 IT_* donee_idx = donee_mirror.indices();
1327 for(Index i = 0; i < n; ++i)
1329 if(own_idx[halo_idx[i]][0] != ~IT_(0))
1331 for(
int j = 0; j < bs_; ++j)
1332 donee_idx[offset + k++] = own_idx[halo_idx[i]][j];
1339 template<
typename DT_>
1340 static Index init_global_dof_idx(
1341 LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& global_dof_idx,
1342 const LAFEM::VectorMirror<DT_, IT_>& owned_mirror, Index offset)
1344 auto* g_dof_idx = global_dof_idx.elements();
1345 const IT_* own_idx = owned_mirror.indices();
1346 const Index n = owned_mirror.num_indices();
1347 for(Index i = 0; i < n; ++i)
1349 for(
int j = 0; j < bs_; ++j)
1350 g_dof_idx[own_idx[i]][j] = IT_(offset + i*
Index(bs_) +
Index(j));
1352 return n *
Index(bs_);
1355 template<
typename DT_>
1356 static Index set_owner_dofs(
1357 LAFEM::DenseVectorBlocked<IT_, IT_, bs_>& glob_dof_idx,
1358 const std::vector<IT_>& recv_buf,
1359 const LAFEM::VectorMirror<DT_, IT_>& mirror, Index offset)
1361 const Index num_indices = mirror.num_indices();
1362 const IT_* mir_idx = mirror.indices();
1363 auto* g_dof_idx = glob_dof_idx.elements();
1364 for(Index i(0); i < num_indices; ++i)
1366 for(
int j = 0; j < bs_; ++j)
1367 g_dof_idx[mir_idx[i]][j] = recv_buf[offset + i*IT_(bs_) + IT_(j)];
1369 return num_indices *
Index(bs_);
1372 template<
typename DT_,
typename DT2_>
1373 static Index gather(DT2_* buf,
1374 const LAFEM::DenseVectorBlocked<DT_, IT_, bs_>& vector,
1375 const LAFEM::VectorMirror<DT_, IT_>& mirror)
1377 XASSERT(mirror.size() == vector.size());
1378 const Index n = mirror.num_indices();
1379 const IT_* idx = mirror.indices();
1380 const auto* val = vector.elements();
1381 for(Index i = 0u, k = 0u; i < n; ++i)
1383 for(
int j = 0; j < bs_; ++j, ++k)
1384 buf[k] = DT2_(val[idx[i]][j]);
1386 return n *
Index(bs_);
1389 template<
typename DT_,
typename DT2_>
1390 static Index scatter(
const DT2_* buf,
1391 LAFEM::DenseVectorBlocked<DT_, IT_, bs_>& vector,
1392 const LAFEM::VectorMirror<DT_, IT_>& mirror)
1394 XASSERT(mirror.size() == vector.size());
1395 const Index n = mirror.num_indices();
1396 const IT_* idx = mirror.indices();
1397 auto* val = vector.elements();
1398 for(Index i = 0u, k = 0u; i < n; ++i)
1400 for(
int j = 0; j < bs_; ++j, ++k)
1401 val[idx[i]][j] = DT_(buf[k]);
1403 return n *
Index(bs_);
1409 template<
typename FirstIdxVec_,
typename... RestIdxVec_>
1410 class ADPAux<LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>>
1413 typedef typename FirstIdxVec_::IndexType IT_;
1414 typedef ADPAux<FirstIdxVec_> ADPAuxFirst;
1415 typedef ADPAux<LAFEM::TupleVector<RestIdxVec_...>> ADPAuxRest;
1417 template<
typename FirstMirror_,
typename... RestMirror_>
1418 static Index get_local_dof_count_raw(std::vector<Index>& v,
1419 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
1420 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& owned_mirror)
1422 Index n1 = ADPAuxFirst::get_local_dof_count(v, global_dof_idx.first(), owned_mirror.first());
1423 Index n2 = ADPAuxRest::get_local_dof_count_raw(v, global_dof_idx.rest(), owned_mirror.rest());
1428 typename FirstMirror_,
typename... RestMirror_>
1429 static Index get_local_dof_count(std::vector<Index>& v,
1430 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
1431 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& owned_mirror)
1433 v.push_back(get_local_dof_count_raw(v, global_dof_idx, owned_mirror));
1437 static String build_block_info_raw(
1438 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx, Index global_offset,
1439 std::deque<Index>& global_first, std::deque<Index>& global_num,
1440 std::deque<Index>& local_offset, std::deque<Index>& local_num)
1442 String s = ADPAuxFirst::build_block_info(global_dof_idx.first(), global_offset, global_first, global_num, local_offset, local_num);
1444 s += ADPAuxRest::build_block_info_raw(global_dof_idx.rest(), global_offset, global_first, global_num, local_offset, local_num);
1448 static String build_block_info(
1449 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx, Index global_offset,
1450 std::deque<Index>& global_first, std::deque<Index>& global_num,
1451 std::deque<Index>& local_offset, std::deque<Index>& local_num)
1455 String slo =
stringify(local_offset.front());
1456 String sgo =
stringify(global_offset + local_offset.front());
1457 String sraw = build_block_info_raw(global_dof_idx, global_offset, global_first, global_num, local_offset, local_num);
1458 String s =
"<Tuple";
1461 s +=
" gc=\"" +
stringify(global_num.front()) +
"\"";
1462 s +=
" gf=\"" +
stringify(global_first.front()) +
"\"";
1463 s +=
" go=\"" + sgo +
"\"";
1464 s +=
" lc=\"" +
stringify(local_num.front()) +
"\"";
1465 s +=
" lo=\"" + slo +
"\">\n";
1469 global_num.pop_front();
1470 local_offset.pop_front();
1471 local_num.pop_front();
1475 template<
typename FirstTmplVector_,
typename... RestTmplVector_>
1476 static void alloc_idx_vector(LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& idx_vec,
1477 const LAFEM::TupleVector<FirstTmplVector_, RestTmplVector_...>& tmpl_vec, IT_ value)
1479 ADPAuxFirst::alloc_idx_vector(idx_vec.first(), tmpl_vec.first(), value);
1480 ADPAuxRest::alloc_idx_vector(idx_vec.rest(), tmpl_vec.rest(), value);
1483 template<
typename FirstMirror_,
typename... RestMirror_>
1484 static void update_owners(
const IT_ neighbor_rank,
1485 LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& dof_owners,
1486 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& mirror)
1488 ADPAuxFirst::update_owners(neighbor_rank, dof_owners.first(), mirror.first());
1489 ADPAuxRest::update_owners(neighbor_rank, dof_owners.rest(), mirror.rest());
1492 static Index build_owned_dofs(
const IT_ my_rank,
1493 LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& owned_dofs,
1494 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& dof_owners, Index offset)
1496 Index n1 = ADPAuxFirst::build_owned_dofs(my_rank, owned_dofs.first(), dof_owners.first(), offset);
1497 Index n2 = ADPAuxRest::build_owned_dofs(my_rank, owned_dofs.rest(), dof_owners.rest(), offset + n1);
1501 template<
typename FirstMirror_,
typename... RestMirror_>
1502 static Index build_owned_mirror(
const IT_ owner_rank,
1503 LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& owner_mirror,
1504 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& dof_owners)
1506 Index n1 = ADPAuxFirst::build_owned_mirror(owner_rank, owner_mirror.first(), dof_owners.first());
1507 Index n2 = ADPAuxRest::build_owned_mirror(owner_rank, owner_mirror.rest(), dof_owners.rest());
1511 template<
typename FirstMirror_,
typename... RestMirror_>
1512 static Index build_owner_mirror(
const IT_ neighbor_rank,
1513 LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& owner_mirror,
1514 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& halo_mirror,
1515 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& dof_owners)
1517 Index n1 = ADPAuxFirst::build_owner_mirror(neighbor_rank, owner_mirror.first(), halo_mirror.first(), dof_owners.first());
1518 Index n2 = ADPAuxRest::build_owner_mirror(neighbor_rank, owner_mirror.rest(), halo_mirror.rest(), dof_owners.rest());
1522 template<
typename FirstMirror_,
typename... RestMirror_>
1523 static Index count_donee_dofs(
1524 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& halo_mirror,
1525 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& own_dof_idx)
1527 Index n1 = ADPAuxFirst::count_donee_dofs(halo_mirror.first(), own_dof_idx.first());
1528 Index n2 = ADPAuxRest::count_donee_dofs(halo_mirror.rest(), own_dof_idx.rest());
1532 template<
typename DT_,
typename FirstMirror_,
typename... RestMirror_>
1533 static Index build_donee_mirror(
1534 LAFEM::VectorMirror<DT_, IT_>& donee_mirror,
1535 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& halo_mirror,
1536 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& own_dof_idx, Index offset)
1538 Index n1 = ADPAuxFirst::build_donee_mirror(donee_mirror, halo_mirror.first(), own_dof_idx.first(), offset);
1539 Index n2 = ADPAuxRest::build_donee_mirror(donee_mirror, halo_mirror.rest(), own_dof_idx.rest(), offset + n1);
1543 template<
typename FirstMirror_,
typename... RestMirror_>
1544 static Index init_global_dof_idx(
1545 LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
1546 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& owned_mirror, Index offset)
1548 Index n1 = ADPAuxFirst::init_global_dof_idx(global_dof_idx.first(), owned_mirror.first(), offset);
1549 Index n2 = ADPAuxRest::init_global_dof_idx(global_dof_idx.rest(), owned_mirror.rest(), offset + n1);
1553 template<
typename FirstMirror_,
typename... RestMirror_>
1554 static Index set_owner_dofs(
1555 LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& glob_dof_idx,
1556 const std::vector<IT_>& recv_buf,
1557 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& mirror, Index offset)
1559 Index n1 = ADPAuxFirst::set_owner_dofs(glob_dof_idx.first(), recv_buf, mirror.first(), offset);
1560 Index n2 = ADPAuxRest::set_owner_dofs(glob_dof_idx.rest(), recv_buf, mirror.rest(), offset + n1);
1564 template<
typename DT2_,
1565 typename FirstVector_,
typename... RestVector_,
1566 typename FirstMirror_,
typename... RestMirror_>
1567 static Index gather(DT2_* buf,
1568 const LAFEM::TupleVector<FirstVector_, RestVector_...>& vector,
1569 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& mirror)
1571 Index n1 = ADPAuxFirst::gather(buf, vector.first(), mirror.first());
1572 Index n2 = ADPAuxRest::gather(&buf[n1], vector.rest(), mirror.rest());
1576 template<
typename DT2_,
1577 typename FirstVector_,
typename... RestVector_,
1578 typename FirstMirror_,
typename... RestMirror_>
1579 static Index scatter(
const DT2_* buf,
1580 LAFEM::TupleVector<FirstVector_, RestVector_...>& vector,
1581 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& mirror)
1583 Index n1 = ADPAuxFirst::scatter(buf, vector.first(), mirror.first());
1584 Index n2 = ADPAuxRest::scatter(&buf[n1], vector.rest(), mirror.rest());
1591 template<
typename FirstIdxVec_>
1592 class ADPAux<LAFEM::TupleVector<FirstIdxVec_>>
1595 typedef typename FirstIdxVec_::IndexType IT_;
1596 typedef ADPAux<FirstIdxVec_> ADPAuxFirst;
1598 template<
typename FirstMirror_>
1599 static Index get_local_dof_count_raw(std::vector<Index>& v,
1600 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx,
1601 const LAFEM::TupleMirror<FirstMirror_>& owned_mirror)
1603 return ADPAuxFirst::get_local_dof_count(v, global_dof_idx.first(), owned_mirror.first());
1606 template<
typename FirstMirror_>
1607 static Index get_local_dof_count(std::vector<Index>& v,
1608 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx,
1609 const LAFEM::TupleMirror<FirstMirror_>& owned_mirror)
1611 v.push_back(get_local_dof_count_raw(v, global_dof_idx, owned_mirror));
1615 static String build_block_info_raw(
1616 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx, Index global_offset,
1617 std::deque<Index>& global_first, std::deque<Index>& global_num,
1618 std::deque<Index>& local_offset, std::deque<Index>& local_num)
1620 return ADPAuxFirst::build_block_info(global_dof_idx.first(), global_offset, global_first, global_num, local_offset, local_num);
1623 static String build_block_info(
1624 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx, Index global_offset,
1625 std::deque<Index>& global_first, std::deque<Index>& global_num,
1626 std::deque<Index>& local_offset, std::deque<Index>& local_num)
1630 String slo =
stringify(local_offset.front());
1631 String sgo =
stringify(global_offset + local_offset.front());
1632 String sraw = build_block_info_raw(global_dof_idx, global_offset, global_first, global_num, local_offset, local_num);
1633 String s =
"<Tuple";
1636 s +=
" gc=\"" +
stringify(global_num.front()) +
"\"";
1637 s +=
" gf=\"" +
stringify(global_first.front()) +
"\"";
1638 s +=
" go=\"" + sgo +
"\"";
1639 s +=
" lc=\"" +
stringify(local_num.front()) +
"\"";
1640 s +=
" lo=\"" + slo +
"\">\n";
1644 global_num.pop_front();
1645 local_offset.pop_front();
1646 local_num.pop_front();
1650 template<
typename FirstTmplVector_>
1651 static void alloc_idx_vector(LAFEM::TupleVector<FirstIdxVec_>& idx_vec,
1652 const LAFEM::TupleVector<FirstTmplVector_>& tmpl_vec, IT_ value)
1654 ADPAuxFirst::alloc_idx_vector(idx_vec.first(), tmpl_vec.first(), value);
1657 template<
typename FirstMirror_>
1658 static void update_owners(
const IT_ neighbor_rank,
1659 LAFEM::TupleVector<FirstIdxVec_>& dof_owners,
1660 const LAFEM::TupleMirror<FirstMirror_>& mirror)
1662 ADPAuxFirst::update_owners(neighbor_rank, dof_owners.first(), mirror.first());
1665 static Index build_owned_dofs(
const IT_ my_rank,
1666 LAFEM::TupleVector<FirstIdxVec_>& owned_dofs,
1667 const LAFEM::TupleVector<FirstIdxVec_>& dof_owners, Index offset)
1669 return ADPAuxFirst::build_owned_dofs(my_rank, owned_dofs.first(), dof_owners.first(), offset);
1672 template<
typename FirstMirror_>
1673 static Index build_owned_mirror(
const IT_ owner_rank,
1674 LAFEM::TupleMirror<FirstMirror_>& owner_mirror,
1675 const LAFEM::TupleVector<FirstIdxVec_>& dof_owners)
1677 return ADPAuxFirst::build_owned_mirror(owner_rank, owner_mirror.first(), dof_owners.first());
1680 template<
typename FirstMirror_>
1681 static Index build_owner_mirror(
const IT_ neighbor_rank,
1682 LAFEM::TupleMirror<FirstMirror_>& owner_mirror,
1683 const LAFEM::TupleMirror<FirstMirror_>& halo_mirror,
1684 const LAFEM::TupleVector<FirstIdxVec_>& dof_owners)
1686 return ADPAuxFirst::build_owner_mirror(neighbor_rank, owner_mirror.first(), halo_mirror.first(), dof_owners.first());
1689 template<
typename FirstMirror_>
1690 static Index count_donee_dofs(
1691 const LAFEM::TupleMirror<FirstMirror_>& halo_mirror,
1692 const LAFEM::TupleVector<FirstIdxVec_>& own_dof_idx)
1694 return ADPAuxFirst::count_donee_dofs(halo_mirror.first(), own_dof_idx.first());
1697 template<
typename DT_,
typename FirstMirror_>
1698 static Index build_donee_mirror(
1699 LAFEM::VectorMirror<DT_, IT_>& donee_mirror,
1700 const LAFEM::TupleMirror<FirstMirror_>& halo_mirror,
1701 const LAFEM::TupleVector<FirstIdxVec_>& own_dof_idx, Index offset)
1703 return ADPAuxFirst::build_donee_mirror(donee_mirror, halo_mirror.first(), own_dof_idx.first(), offset);
1706 template<
typename FirstMirror_>
1707 static Index init_global_dof_idx(
1708 LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx,
1709 const LAFEM::TupleMirror<FirstMirror_>& owned_mirror, Index offset)
1711 return ADPAuxFirst::init_global_dof_idx(global_dof_idx.first(), owned_mirror.first(), offset);
1714 template<
typename FirstMirror_>
1715 static Index set_owner_dofs(
1716 LAFEM::TupleVector<FirstIdxVec_>& glob_dof_idx,
1717 const std::vector<IT_>& recv_buf,
1718 const LAFEM::TupleMirror<FirstMirror_>& mirror, Index offset)
1720 return ADPAuxFirst::set_owner_dofs(glob_dof_idx.first(), recv_buf, mirror.first(), offset);
1723 template<
typename DT2_,
typename FirstVector_,
typename FirstMirror_>
1724 static Index gather(DT2_* buf,
1725 const LAFEM::TupleVector<FirstVector_>& vector,
1726 const LAFEM::TupleMirror<FirstMirror_>& mirror)
1728 return ADPAuxFirst::gather(buf, vector.first(), mirror.first());
1731 template<
typename DT2_,
typename FirstVector_,
typename FirstMirror_>
1732 static Index scatter(
const DT2_* buf,
1733 LAFEM::TupleVector<FirstVector_>& vector,
1734 const LAFEM::TupleMirror<FirstMirror_>& mirror)
1736 return ADPAuxFirst::scatter(buf, vector.first(), mirror.first());
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
void bcast(void *buffer, std::size_t count, const Datatype &datatype, int root) const
Blocking broadcast.
void allreduce(const void *sendbuf, void *recvbuf, std::size_t count, const Datatype &datatype, const Operation &op) const
Blocking All-Reduce.
int size() const
Returns the size of this communicator.
void exscan(const void *sendbuf, void *recvbuf, std::size_t count, const Datatype &datatype, const Operation &op) const
Blocking Exclusive Scan.
Request irecv(void *buffer, std::size_t count, const Datatype &datatype, int source, int tag=0) const
Nonblocking Receive.
Request isend(const void *buffer, std::size_t count, const Datatype &datatype, int dest, int tag=0) const
Nonblocking Send.
int rank() const
Returns the rank of this process in this communicator.
void allgather(const void *sendbuf, std::size_t sendcount, const Datatype &sendtype, void *recvbuf, std::size_t recvcount, const Datatype &recvtype) const
Blocking gather-to-all.
Communication Request vector class.
bool wait_any(std::size_t &idx, Status &status)
Blocks until one of the active requests has been fulfilled.
void wait_all()
Blocks until all active requests are fulfilled.
Algebraic DOF Partitioning implementation.
LAFEM::DenseVector< DataType, IndexType > BufferVectorType
the type for buffers used by our mirrors
Index _extra_shared_dof_count
number of extra shared dofs; must be equal on all processes
Mirror_ MirrorType
the vector mirror type
String get_block_information() const
Returns the block information of the algebraic dof partitioning as an XML string.
Index _local_dof_count
number of local dofs of this process
void clear()
Resets the whole object.
const std::vector< int > & get_all_global_dof_offsets() const
Returns the all-global-dof-offsets vector.
MirrorType OwnerMirrorType
type of mirror for neighbor owner local dof indices
int get_donee_rank(Index i) const
Returns an donee neighbor rank.
Index get_num_local_dofs() const
Index _extra_local_dof_count
number of extra local dofs; may be different for each process
void assemble_by_gate(const GateType &gate, Index extra_local=0u, Index extra_shared=0u)
Assembles the AlgDofParti object from a given Global::Gate.
std::vector< DoneeMirrorType > _donee_mirrors
rank/mirror-pair of DOF-donee processes
Index _global_dof_offset
global dof offset of this process
Global::Vector< LocalVectorType, MirrorType > GlobalVectorType
the global vector type
LocalVector_ LocalVectorType
the local vector type
Index _global_dof_count
global dof count over all processes
std::vector< int > _owner_ranks
ranks of DOF-owner neighbor processes
Index get_global_dof_offset() const
AlgDofParti()
default constructor
std::vector< int > _all_global_dof_offset
global DOF offsets of all processes,
MirrorType _owned_mirror
mirror for this process's owned DOFs
const std::vector< int > & get_all_global_dof_counts() const
Returns the all-global-dof-counts vector.
void assemble_allgather(bool yes_i_really_want_to_do_this=false)
Assembles the required data for the AlgDofPartiSystem::apply() function.
std::vector< int > _all_global_dof_counts
global DOF counts of all processes,
MirrorType OwnedMirrorType
type of mirror for owned local dof indices
Intern::ADPAux< IndexVectorType > ADPAuxType
auxiliary helper class type
const OwnedMirrorType & get_owned_mirror() const
Returns the Mirror of the owned DOFs.
Index _extra_dof_offset
offset of first extra DOF
const OwnerMirrorType & get_owner_mirror(Index i) const
Returns an owner neighbor mirror.
virtual ~AlgDofParti()=default
virtual destructor
LocalVectorType::template ContainerTypeByDI< IndexType, IndexType > IndexVectorType
the index vector type, this one is required for internal computations
const IndexVectorType & get_global_dof_indices() const
Returns the global-dof-indices array.
std::vector< int > _donee_ranks
ranks of DOF-donee neighbor processes
LocalVectorType::DataType DataType
our data type
AlgDofParti(const AlgDofParti &)=delete
no copy, no problems
Index _owned_dof_count
number of owned dofs of this process
int get_owner_rank(Index i) const
Returns an owner neighbor rank.
String _block_information
a string containing the block information in XML format
std::size_t bytes() const
const Dist::Comm * get_comm() const
Index get_num_owner_neighbors() const
LAFEM::VectorMirror< DataType, IndexType > DoneeMirrorType
type of mirror for neighbor donee owned dof indices
Index get_num_donee_neighbors() const
const DoneeMirrorType & get_donee_mirror(Index i) const
Returns a donee neighbor mirror.
Index get_num_global_dofs() const
Index get_num_owned_dofs() const
Global::Gate< LocalVectorType, MirrorType > GateType
the global gate type
IndexVectorType _global_dof_idx
global dof indices for each local dof
const Dist::Comm * _comm
our communicator
LocalVectorType::IndexType IndexType
our index type
AlgDofParti & operator=(const AlgDofParti &)=delete
no copy, no problems
std::vector< OwnerMirrorType > _owner_mirrors
rank/mirror-pair of DOF-owner processes
Global gate implementation.
const Dist::Comm * get_comm() const
Returns a const pointer to the underlying communicator.
const LocalVector_ & get_freqs() const
Returns a const reference to the frequencies vector.
const std::vector< Mirror_ > & get_mirrors() const
Returns a const reference to the neighbor mirrors vector.
std::vector< int > _ranks
communication ranks
Global vector wrapper class template.
Dense data vector class template.
Handles vector prolongation, restriction and serialization.
String class implementation.
void pop_front()
Removes the first character from the string.
const Operation op_sum(MPI_SUM)
Operation wrapper for MPI_SUM.
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.