8#include <kernel/adjacency/dynamic_graph.hpp>
9#include <kernel/global/alg_dof_parti.hpp>
10#include <kernel/global/filter.hpp>
11#include <kernel/global/matrix.hpp>
12#include <kernel/lafem/null_matrix.hpp>
13#include <kernel/lafem/sparse_matrix_csr.hpp>
14#include <kernel/lafem/sparse_matrix_bcsr.hpp>
15#include <kernel/lafem/saddle_point_matrix.hpp>
16#include <kernel/lafem/tuple_matrix.hpp>
17#include <kernel/lafem/unit_filter.hpp>
18#include <kernel/lafem/unit_filter_blocked.hpp>
19#include <kernel/lafem/mean_filter.hpp>
20#include <kernel/lafem/mean_filter_blocked.hpp>
21#include <kernel/lafem/none_filter.hpp>
22#include <kernel/lafem/slip_filter.hpp>
23#include <kernel/lafem/filter_chain.hpp>
24#include <kernel/lafem/filter_sequence.hpp>
25#include <kernel/lafem/tuple_filter.hpp>
26#include <kernel/global/mean_filter.hpp>
27#include <kernel/lafem/matrix_mirror.hpp>
39 template<
typename Matrix_>
43 template<
typename Matrix_>
47 template<
typename Filter_>
131 template<
typename LocalMatrix_,
typename LocalFilter_,
typename Mirror_>
175 typedef Intern::ADPMatAux<LocalMatrixType> ADPMatAuxType;
176 typedef Intern::ADPFilAux<LocalFilterType> ADPFilAuxType;
198 std::vector<BufferMatrixType> _owner_bufs;
202 std::vector<OwnerMirrorType> _owner_data_mirs;
243 std::shared_ptr<AlgDofPartiType> adp) :
262 if(this->_alg_dof_parti)
263 r += this->_alg_dof_parti->bytes();
264 if(this->_owned_graph)
265 r += this->_owned_graph->bytes();
266 for(
const auto& x : this->_donee_bufs)
268 for(
const auto& x : this->_owner_bufs)
270 for(
const auto& x : this->_donee_data_mirs)
272 for(
const auto& x : this->_owner_data_mirs)
294 return this->_alg_dof_parti->get_num_owned_dofs();
300 return this->_alg_dof_parti->get_num_global_dofs();
306 return this->_alg_dof_parti->get_global_dof_offset();
312 return this->_alg_dof_parti->get_num_owned_dofs();
318 return this->_alg_dof_parti->get_num_owned_dofs();
324 return this->_alg_dof_parti->get_num_global_dofs();
342 XASSERT(this->_alg_dof_parti !=
nullptr);
343 return this->_alg_dof_parti->get_comm();
356 template<
typename DTV_>
359 XASSERT(this->_alg_dof_parti !=
nullptr);
360 this->_alg_dof_parti->upload_vector(val, vector);
374 template<
typename DTV_>
377 XASSERT(this->_alg_dof_parti !=
nullptr);
378 this->_alg_dof_parti->download_vector(val, vector);
401 template<
typename DTX_,
typename RPT_,
typename CIT_>
402 void apply(DTX_* vec_r,
const DTX_* vec_x,
const DTX_* val_a,
const RPT_* row_ptr,
const CIT_* col_idx)
const
404 XASSERTM(!this->_alg_dof_parti->get_all_global_dof_counts().empty(),
405 "You did not ask to assemble the required AlgDofParti allgather data");
408 std::vector<DTX_> vec_full(this->_alg_dof_parti->get_num_global_dofs());
410 this->_alg_dof_parti->get_num_owned_dofs(),
412 this->_alg_dof_parti->get_all_global_dof_counts().data(),
413 this->_alg_dof_parti->get_all_global_dof_offsets().data());
416 LAFEM::Arch::Apply::csr_generic(vec_r, DTX_(1), vec_full.data(), DTX_(0), vec_r, val_a, col_idx, row_ptr,
429 if(this->_alg_dof_parti ==
nullptr)
431 this->_alg_dof_parti = std::make_shared<AlgDofPartiType>();
432 this->_alg_dof_parti->assemble_by_gate(*this->_global_matrix.
get_row_gate());
464 template<
typename RPT_,
typename CIT_>
469 XASSERT(this->_owned_graph !=
nullptr);
472 static constexpr std::uint64_t max_rpt = 1ull << (8*
sizeof(RPT_) - 1);
473 static constexpr std::uint64_t max_cit = 1ull << (8*
sizeof(CIT_) - 1);
479 const Index* dom_ptr = this->_owned_graph->get_domain_ptr();
480 const Index* img_idx = this->_owned_graph->get_image_idx();
482 const Index n = this->_owned_graph->get_num_nodes_domain();
483 FEAT_PRAGMA_OMP(parallel
for)
484 for(
Index i = 0u; i <= n; ++i)
486 ASSERTM(std::uint64_t(dom_ptr[i]) < max_rpt,
"row-pointer exceeds RPT_ type range!");
487 row_ptr[i] = RPT_(dom_ptr[i]);
490 const Index m = this->_owned_graph->get_num_indices();
491 FEAT_PRAGMA_OMP(parallel
for)
492 for(
Index j = 0; j < m; ++j)
494 ASSERTM(std::uint64_t(img_idx[j]) < max_cit,
"column-index exceeds CIT_ type range!");
495 col_idx[j] = CIT_(img_idx[j]);
500 this->_owned_graph.reset();
520 template<
typename DTA_,
typename RPT_,
typename CIT_>
549 template<
typename DTA_,
typename RPT_,
typename CIT_>
552 XASSERT(this->_alg_dof_parti !=
nullptr);
561 memset(val, 0,
sizeof(DTA_)*this->_num_owned_non_zeros);
569 std::vector<BufferVectorType> donee_vbufs(num_neigh_donee);
570 std::vector<BufferVectorType> owner_vbufs(num_neigh_owner);
573 for(
Index i(0); i < num_neigh_donee; ++i)
584 for(
Index i(0); i < num_neigh_owner; ++i)
591 this->_owner_data_mirs.at(i).gather_owner_data(buf, matrix);
598 this->_owned_data_mir.upload_owned_data(val, matrix);
601 for(std::size_t idx(0u); recv_reqs.
wait_any(idx); )
635 template<
typename DTV_>
652 template<
typename DTV_>
678 template<
typename DTA_,
typename RPT_,
typename CIT_>
689 const IndexType* row_idx = this->_unit_filter_rows.
get_indices();
693 for(
Index i = 0; i < n; ++i)
695 const Index row = row_off + row_idx[i];
696 RPT_ j = row_ptr[row_idx[i]];
697 const RPT_ j_end = row_ptr[row_idx[i]+1];
698 for(; j < j_end; ++j)
700 val[j] = DTA_(row ==
Index(col_idx[j]) ? 1 : 0);
717 const Index num_global_dofs)
720 Index num_buf_rows = ADPMatAuxType::calc_mat_buf_num_rows(local_matrix, row_mirror);
723 std::vector<IndexType> aux_row(std::size_t(num_buf_rows+1u),
IndexType(0));
726 ADPMatAuxType::calc_mat_buf_row_nze(aux_row.data(), local_matrix, row_mirror);
729 feat_omp_ex_scan(std::size_t(num_buf_rows+1u), aux_row.data(), aux_row.data());
738 for(
Index i = 0u; i <= num_buf_rows; ++i)
739 buf_row_ptr[i] = aux_row[i];
743 ADPMatAuxType::gather_mat_buf_col_idx(aux_row.data(), buf_col_idx, local_matrix, row_mirror, global_dof_idx);
746 for(
Index i = 0u; i < num_buf_rows; ++i)
748 std::sort(&buf_col_idx[buf_row_ptr[i]], &buf_col_idx[buf_row_ptr[i+1]]);
771 _owner_bufs.resize(num_neigh_owner);
775 for(
Index i(0); i < num_neigh_owner; ++i)
797 std::vector<std::array<Index,4>> send_dims(num_neigh_owner);
798 std::vector<std::array<Index,4>> recv_dims(num_neigh_donee);
801 for(
Index i(0); i < num_neigh_donee; ++i)
807 for(
Index i(0); i < num_neigh_owner; ++i)
821 for(
Index i(0); i < num_neigh_donee; ++i)
824 Index nrows = recv_dims.at(i)[0];
825 Index ncols = recv_dims.at(i)[1];
826 Index nepnz = recv_dims.at(i)[2];
827 Index nnze = recv_dims.at(i)[3];
834 for(
Index i(0); i < num_neigh_donee; ++i)
836 recv_reqs[i] = comm.
irecv(this->_donee_bufs.at(i).row_ptr(),
837 this->_donee_bufs.at(i).rows()+std::size_t(1), adp.
get_donee_rank(i));
844 for(
Index i(0); i < num_neigh_owner; ++i)
846 send_reqs[i] = comm.
isend(this->_owner_bufs.at(i).row_ptr(),
847 this->_owner_bufs.at(i).rows()+std::size_t(1), adp.
get_owner_rank(i));
854 for(
Index i(0); i < num_neigh_donee; ++i)
856 recv_reqs[i] = comm.
irecv(this->_donee_bufs.at(i).col_ind(),
864 for(
Index i(0); i < num_neigh_owner; ++i)
866 send_reqs[i] = comm.
isend(this->_owner_bufs.at(i).col_ind(),
899 ADPMatAuxType::gather_owned_struct(dynamic_graph, this->_global_matrix.
local(),
904 for(
Index ineigh(0); ineigh < num_neigh_donee; ++ineigh)
911 const Index num_idx = mir.num_indices();
912 const IndexType* mir_idx = mir.indices();
917 for(
Index i(0); i < num_idx; ++i)
923 for(
IndexType j(buf_ptr[i]); j < buf_ptr[i + 1]; ++j)
926 dynamic_graph.
insert(row, buf_idx[j]);
937 dynamic_graph.
clear();
962 for(
Index i(0); i < buf_rows; ++i)
966 Index k = row_ptr[row_idx[i]];
967 const Index k_end = row_ptr[row_idx[i] + 1];
970 while((j < j_end) && (k < k_end))
972 if(buf_idx[j] < col_idx[k])
974 else if(buf_idx[j] > col_idx[k])
1000 this->_donee_data_mirs.resize(this->_donee_bufs.size());
1001 for(
Index i(0); i < this->_donee_bufs.size(); ++i)
1006 this->_owner_data_mirs.resize(this->_owner_bufs.size());
1007 for(
Index i(0); i < this->_owner_bufs.size(); ++i)
1008 this->_owner_data_mirs.at(i).asm_neighbor_owner_data_mir(this->_global_matrix.
local(),
1013 this->_owned_data_mir.asm_owned_data_mir(this->_global_matrix.
local(), *this->_owned_graph,
1020 template<
typename DTA_>
1029 for(
Index i(0); i < n; ++i)
1031 adp_val[mir_idx[i]] += DTA_(buf_val[i]);
1045 template<
typename DT_,
typename IT_>
1046 class ADPDOMM<LAFEM::SparseMatrixCSR<DT_, IT_>>
1051 Index num_indices()
const
1056 Index buf_size()
const
1058 return _buf_mir.
size();
1061 Index loc_size()
const
1063 return _loc_mir.
size();
1070 const IT_* buf_idx = _buf_mir.
indices();
1071 const IT_* loc_idx = _loc_mir.
indices();
1093 Index asm_neighbor_owner_data_mir(
1094 const LAFEM::SparseMatrixCSR<DT_, IT_>& local_matrix,
1095 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1096 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
1097 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx,
1101 const IT_* row_idx = row_mirror.indices();
1102 const IT_* row_ptr = local_matrix.row_ptr();
1103 const IT_* col_idx = local_matrix.col_ind();
1104 const IT_* buf_ptr = buffer.row_ptr();
1105 const IT_* buf_idx = buffer.col_ind();
1106 const IT_* glob_dof_idx = global_dof_idx.elements();
1107 const Index row_mir_num_idx = row_mirror.num_indices();
1110 Index data_mir_num_idx = 0u;
1111 for(Index i = 0; i < row_mir_num_idx; ++i)
1112 data_mir_num_idx += row_ptr[row_idx[i]+1u] - row_ptr[row_idx[i]];
1114 XASSERT(data_mir_num_idx <= buffer.used_elements());
1117 std::vector<std::pair<IT_, IT_>> aux_data_mir;
1118 aux_data_mir.reserve(data_mir_num_idx);
1121 std::vector<IT_> loc_it;
1122 loc_it.reserve(local_matrix.columns());
1125 auto sort_rel_loc = [&glob_dof_idx, &col_idx] (IT_ a, IT_ b)
1127 return glob_dof_idx[col_idx[a]] < glob_dof_idx[col_idx[b]];
1131 for(Index i(0); i < row_mir_num_idx; ++i)
1134 IT_ j = buf_ptr[row_offset + i];
1135 const IT_ j_end = buf_ptr[row_offset + i + 1];
1136 const IT_ k_beg = row_ptr[row_idx[i]];
1137 const IT_ k_end = row_ptr[row_idx[i] + 1];
1139 for(IT_ k = k_beg; k < k_end; ++k)
1140 loc_it.push_back(k);
1141 std::sort(loc_it.begin(), loc_it.end(), sort_rel_loc);
1143 auto kit = loc_it.begin();
1146 while((j < j_end) && (kit != loc_it.end()))
1148 if(buf_idx[j] < glob_dof_idx[col_idx[*kit]])
1150 else if(buf_idx[j] > glob_dof_idx[col_idx[*kit]])
1154 aux_data_mir.push_back(std::make_pair(j, *kit));
1163 this->_buf_mir = LAFEM::VectorMirror<DT_, IT_>(buffer.used_elements(), num_idx);
1164 this->_loc_mir = LAFEM::VectorMirror<DT_, IT_>(
1165 local_matrix.template used_elements<LAFEM::Perspective::pod>(), num_idx);
1167 IT_* bm_idx = this->_buf_mir.
indices();
1168 IT_* lm_idx = this->_loc_mir.
indices();
1169 for(Index i = 0; i < num_idx; ++i)
1171 bm_idx[i] = aux_data_mir[i].first;
1172 lm_idx[i] = aux_data_mir[i].second;
1175 return row_mir_num_idx;
1191 Index asm_owned_data_mir(
1192 const LAFEM::SparseMatrixCSR<DT_, IT_>& local_matrix,
1193 const Adjacency::Graph& owned_graph,
1194 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1195 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx,
1199 const Index* own_row_ptr = owned_graph.get_domain_ptr();
1200 const Index* own_col_idx = owned_graph.get_image_idx();
1201 const IT_* loc_row_ptr = local_matrix.row_ptr();
1202 const IT_* loc_col_idx = local_matrix.col_ind();
1205 std::vector<std::pair<IT_, IT_>> aux_data_mir;
1206 aux_data_mir.reserve(owned_graph.get_num_indices());
1208 const Index num_owned_dofs = row_mirror.num_indices();
1209 const IT_* loc_dof_idx = row_mirror.indices();
1210 const IT_* glob_dof_idx = global_dof_idx.elements();
1215 std::deque<IT_> row_it;
1218 auto sort_rel = [&glob_dof_idx, &loc_col_idx] (IT_ a, IT_ b)
1220 return glob_dof_idx[loc_col_idx[a]] < glob_dof_idx[loc_col_idx[b]];
1224 for(Index own_dof(0); own_dof < num_owned_dofs; ++own_dof)
1226 const IT_ k_beg = loc_row_ptr[loc_dof_idx[own_dof]];
1227 const IT_ k_end = loc_row_ptr[loc_dof_idx[own_dof] + 1];
1229 for(IT_ k = k_beg; k < k_end; ++k)
1230 row_it.push_back(k);
1231 std::sort(row_it.begin(), row_it.end(), sort_rel);
1234 IT_ j = IT_(own_row_ptr[row_offset + own_dof]);
1235 const IT_ j_end = IT_(own_row_ptr[row_offset + own_dof + 1]);
1236 auto kit = row_it.begin();
1239 while((j < j_end) && (kit != row_it.end()))
1241 if(own_col_idx[j] < glob_dof_idx[loc_col_idx[*kit]])
1243 else if(own_col_idx[j] > glob_dof_idx[loc_col_idx[*kit]])
1247 aux_data_mir.push_back(std::make_pair(j, *kit));
1256 this->_buf_mir = LAFEM::VectorMirror<DT_, IT_>(local_matrix.used_elements(), num_idx);
1257 this->_loc_mir = LAFEM::VectorMirror<DT_, IT_>(local_matrix.used_elements(), num_idx);
1259 IT_* bm_idx = this->_buf_mir.
indices();
1260 IT_* lm_idx = this->_loc_mir.
indices();
1261 for(Index i = 0; i < num_idx; ++i)
1263 bm_idx[i] = aux_data_mir[i].first;
1264 lm_idx[i] = aux_data_mir[i].second;
1267 return num_owned_dofs;
1270 template<
typename DTA_>
1271 void upload_owned_data(DTA_* adp_val,
const LAFEM::SparseMatrixCSR<DT_, IT_>& local_matrix)
const
1273 const DT_* loc_val = local_matrix.val();
1274 const IT_* adp_idx = _buf_mir.
indices();
1275 const IT_* loc_idx = _loc_mir.
indices();
1278 for(Index i = 0; i < n; ++i)
1280 ASSERT(loc_idx[i] < local_matrix.used_elements());
1281 adp_val[adp_idx[i]] = DTA_(loc_val[loc_idx[i]]);
1297 void gather_owner_data(LAFEM::DenseVector<DT_, IT_>& buffer,
const LAFEM::SparseMatrixCSR<DT_, IT_>& local_matrix)
const
1299 DT_* buf_val = buffer.elements();
1300 const DT_* loc_val = local_matrix.val();
1301 const IT_* buf_idx = this->_buf_mir.
indices();
1302 const IT_* loc_idx = this->_loc_mir.
indices();
1305 for(Index i = 0; i < n; ++i)
1307 ASSERT(buf_idx[i] < buffer.size());
1308 ASSERT(loc_idx[i] < local_matrix.used_elements());
1309 buf_val[buf_idx[i]] = loc_val[loc_idx[i]];
1317 template<
typename DT_,
typename IT_,
int bh_,
int bw_>
1318 class ADPDOMM<LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>>
1321 LAFEM::VectorMirror<DT_, IT_> _buf_mir, _loc_mir;
1323 Index num_indices()
const
1325 return _buf_mir.num_indices();
1328 Index buf_size()
const
1330 return _buf_mir.size();
1333 Index loc_size()
const
1335 return _loc_mir.size();
1341 XASSERT(_buf_mir.num_indices() == _loc_mir.num_indices());
1342 const IT_* buf_idx = _buf_mir.indices();
1343 const IT_* loc_idx = _loc_mir.indices();
1344 for(Index i = 0; i < _buf_mir.num_indices(); ++i)
1346 return "[" + s +
"]*" +
stringify(_buf_mir.num_indices());
1349 Index asm_neighbor_owner_data_mir(
1350 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& local_matrix,
1351 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1352 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
1353 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>& global_dof_idx,
1357 const IT_* row_idx = row_mirror.indices();
1358 const IT_* row_ptr = local_matrix.row_ptr();
1359 const IT_* col_idx = local_matrix.col_ind();
1360 const IT_* buf_ptr = buffer.row_ptr();
1361 const IT_* buf_idx = buffer.col_ind();
1362 const auto* glob_dof_idx = global_dof_idx.elements();
1363 const Index row_mir_num_idx = row_mirror.num_indices();
1366 Index data_mir_num_idx = 0u;
1367 for(Index i = 0; i < row_mir_num_idx; ++i)
1368 data_mir_num_idx += row_ptr[row_idx[i]+1u] - row_ptr[row_idx[i]];
1369 data_mir_num_idx *=
Index(bh_*bw_);
1371 XASSERT(data_mir_num_idx <= buffer.used_elements());
1374 std::vector<std::pair<IT_, IT_>> aux_data_mir;
1375 aux_data_mir.reserve(data_mir_num_idx);
1378 std::vector<IT_> loc_it;
1379 loc_it.reserve(local_matrix.columns() * std::size_t(bh_*bw_));
1382 auto sort_rel_loc = [&glob_dof_idx, &col_idx] (IT_ a, IT_ b)
1384 return glob_dof_idx[col_idx[a]][0] < glob_dof_idx[col_idx[b]][0];
1388 for(Index i(0); i < row_mir_num_idx; ++i)
1390 const IT_ k_beg = row_ptr[row_idx[i]];
1391 const IT_ k_end = row_ptr[row_idx[i] + 1];
1393 for(IT_ k = k_beg; k < k_end; ++k)
1394 loc_it.push_back(k);
1395 std::sort(loc_it.begin(), loc_it.end(), sort_rel_loc);
1398 for(
int bi = 0; bi < bh_; ++bi)
1401 IT_ j = buf_ptr[row_offset + i*IT_(bh_) + IT_(bi)];
1402 const IT_ j_end = buf_ptr[row_offset + i*IT_(bh_) + IT_(bi) + 1];
1404 auto kit = loc_it.begin();
1407 while((j < j_end) && (kit != loc_it.end()))
1409 if(buf_idx[j] < glob_dof_idx[col_idx[*kit]][0])
1411 else if(buf_idx[j] > glob_dof_idx[col_idx[*kit]][0])
1416 for(
int bj = 0; bj < bw_; ++bj)
1418 aux_data_mir.push_back(std::make_pair(j, (*kit)*IT_(bh_*bw_) + IT_(bi*bw_) + IT_(bj)));
1429 this->_buf_mir = LAFEM::VectorMirror<DT_, IT_>(buffer.used_elements(), num_idx);
1430 this->_loc_mir = LAFEM::VectorMirror<DT_, IT_>(
1431 local_matrix.template used_elements<LAFEM::Perspective::pod>(), num_idx);
1433 IT_* bm_idx = this->_buf_mir.indices();
1434 IT_* lm_idx = this->_loc_mir.indices();
1435 for(Index i = 0; i < num_idx; ++i)
1437 bm_idx[i] = aux_data_mir[i].first;
1438 lm_idx[i] = aux_data_mir[i].second;
1441 return row_mir_num_idx *
Index(bh_);
1444 Index asm_neighbor_owner_data_mir(
1445 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, 1>& local_matrix,
1446 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1447 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
1448 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx,
1452 const IT_* row_idx = row_mirror.indices();
1453 const IT_* row_ptr = local_matrix.row_ptr();
1454 const IT_* col_idx = local_matrix.col_ind();
1455 const IT_* buf_ptr = buffer.row_ptr();
1456 const IT_* buf_idx = buffer.col_ind();
1457 const IT_* glob_dof_idx = global_dof_idx.elements();
1458 const Index row_mir_num_idx = row_mirror.num_indices();
1461 Index data_mir_num_idx = 0u;
1462 for(Index i = 0; i < row_mir_num_idx; ++i)
1463 data_mir_num_idx += row_ptr[row_idx[i]+1u] - row_ptr[row_idx[i]];
1464 data_mir_num_idx *=
Index(bh_);
1466 XASSERT(data_mir_num_idx <= buffer.used_elements());
1469 std::vector<std::pair<IT_, IT_>> aux_data_mir;
1470 aux_data_mir.reserve(data_mir_num_idx);
1473 std::vector<IT_> loc_it;
1474 loc_it.reserve(local_matrix.columns() * std::size_t(bh_));
1477 auto sort_rel_loc = [&glob_dof_idx, &col_idx] (IT_ a, IT_ b)
1479 return glob_dof_idx[col_idx[a]] < glob_dof_idx[col_idx[b]];
1483 for(Index i(0); i < row_mir_num_idx; ++i)
1485 const IT_ k_beg = row_ptr[row_idx[i]];
1486 const IT_ k_end = row_ptr[row_idx[i] + 1];
1488 for(IT_ k = k_beg; k < k_end; ++k)
1489 loc_it.push_back(k);
1490 std::sort(loc_it.begin(), loc_it.end(), sort_rel_loc);
1493 for(
int bi = 0; bi < bh_; ++bi)
1496 IT_ j = buf_ptr[row_offset + i*IT_(bh_) + IT_(bi)];
1497 const IT_ j_end = buf_ptr[row_offset + i*IT_(bh_) + IT_(bi) + 1];
1498 auto kit = loc_it.begin();
1501 while((j < j_end) && (kit != loc_it.end()))
1503 if(buf_idx[j] < glob_dof_idx[col_idx[*kit]])
1505 else if(buf_idx[j] > glob_dof_idx[col_idx[*kit]])
1510 aux_data_mir.push_back(std::make_pair(j, (*kit)*IT_(bh_) + IT_(bi)));
1520 this->_buf_mir = LAFEM::VectorMirror<DT_, IT_>(buffer.used_elements(), num_idx);
1521 this->_loc_mir = LAFEM::VectorMirror<DT_, IT_>(
1522 local_matrix.template used_elements<LAFEM::Perspective::pod>(), num_idx);
1524 IT_* bm_idx = this->_buf_mir.indices();
1525 IT_* lm_idx = this->_loc_mir.indices();
1526 for(Index i = 0; i < num_idx; ++i)
1528 bm_idx[i] = aux_data_mir[i].first;
1529 lm_idx[i] = aux_data_mir[i].second;
1532 return row_mir_num_idx *
Index(bh_);
1535 Index asm_owned_data_mir(
1536 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& local_matrix,
1537 const Adjacency::Graph& owned_graph,
1538 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1539 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>& global_dof_idx,
1543 const Index* own_row_ptr = owned_graph.get_domain_ptr();
1544 const Index* own_col_idx = owned_graph.get_image_idx();
1545 const IT_* loc_row_ptr = local_matrix.row_ptr();
1546 const IT_* loc_col_idx = local_matrix.col_ind();
1549 std::vector<std::pair<IT_, IT_>> aux_data_mir;
1550 aux_data_mir.reserve(owned_graph.get_num_indices() * std::size_t(bh_*bw_));
1552 const Index num_owned_dofs = row_mirror.num_indices();
1553 const IT_* loc_dof_idx = row_mirror.indices();
1554 const auto* glob_dof_idx = global_dof_idx.elements();
1559 std::deque<IT_> row_it;
1562 auto sort_rel = [&glob_dof_idx, &loc_col_idx] (IT_ a, IT_ b)
1564 return glob_dof_idx[loc_col_idx[a]][0] < glob_dof_idx[loc_col_idx[b]][0];
1568 for(Index own_dof(0); own_dof < num_owned_dofs; ++own_dof)
1570 const IT_ k_beg = loc_row_ptr[loc_dof_idx[own_dof]];
1571 const IT_ k_end = loc_row_ptr[loc_dof_idx[own_dof] + 1];
1573 for(IT_ k = k_beg; k < k_end; ++k)
1574 row_it.push_back(k);
1575 std::sort(row_it.begin(), row_it.end(), sort_rel);
1578 for(
int bi = 0; bi < bh_; ++bi)
1580 IT_ j = IT_(own_row_ptr[row_offset + own_dof*IT_(bh_) + IT_(bi)]);
1581 const IT_ j_end = IT_(own_row_ptr[row_offset + own_dof*IT_(bh_) + IT_(bi) + 1]);
1582 auto kit = row_it.begin();
1585 while((j < j_end) && (kit != row_it.end()))
1587 if(own_col_idx[j] < glob_dof_idx[loc_col_idx[*kit]][0])
1589 else if(own_col_idx[j] > glob_dof_idx[loc_col_idx[*kit]][0])
1594 for(
int bj = 0; bj < bw_; ++bj)
1596 aux_data_mir.push_back(std::make_pair(j, (*kit)*IT_(bh_*bw_) + IT_(bi*bw_) + IT_(bj)));
1607 this->_buf_mir = LAFEM::VectorMirror<DT_, IT_>(owned_graph.get_num_indices(), num_idx);
1608 this->_loc_mir = LAFEM::VectorMirror<DT_, IT_>(
1609 local_matrix.template used_elements<LAFEM::Perspective::pod>(), num_idx);
1611 IT_* bm_idx = this->_buf_mir.indices();
1612 IT_* lm_idx = this->_loc_mir.indices();
1613 for(Index i = 0; i < num_idx; ++i)
1615 bm_idx[i] = aux_data_mir[i].first;
1616 lm_idx[i] = aux_data_mir[i].second;
1619 return num_owned_dofs *
Index(bh_);
1622 Index asm_owned_data_mir(
1623 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, 1>& local_matrix,
1624 const Adjacency::Graph& owned_graph,
1625 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1626 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx,
1630 const Index* own_row_ptr = owned_graph.get_domain_ptr();
1631 const Index* own_col_idx = owned_graph.get_image_idx();
1632 const IT_* loc_row_ptr = local_matrix.row_ptr();
1633 const IT_* loc_col_idx = local_matrix.col_ind();
1636 std::vector<std::pair<IT_, IT_>> aux_data_mir;
1637 aux_data_mir.reserve(owned_graph.get_num_indices() * std::size_t(bh_));
1639 const Index num_owned_dofs = row_mirror.num_indices();
1640 const IT_* loc_dof_idx = row_mirror.indices();
1641 const IT_* glob_dof_idx = global_dof_idx.elements();
1646 std::deque<IT_> row_it;
1649 auto sort_rel = [&glob_dof_idx, &loc_col_idx] (IT_ a, IT_ b)
1651 return glob_dof_idx[loc_col_idx[a]] < glob_dof_idx[loc_col_idx[b]];
1655 for(Index own_dof(0); own_dof < num_owned_dofs; ++own_dof)
1657 const IT_ k_beg = loc_row_ptr[loc_dof_idx[own_dof]];
1658 const IT_ k_end = loc_row_ptr[loc_dof_idx[own_dof] + 1];
1660 for(IT_ k = k_beg; k < k_end; ++k)
1661 row_it.push_back(k);
1662 std::sort(row_it.begin(), row_it.end(), sort_rel);
1665 for(
int bi = 0; bi < bh_; ++bi)
1667 IT_ j = IT_(own_row_ptr[row_offset + own_dof*IT_(bh_) + IT_(bi)]);
1668 const IT_ j_end = IT_(own_row_ptr[row_offset + own_dof*IT_(bh_) + IT_(bi) + 1]);
1669 auto kit = row_it.begin();
1672 while((j < j_end) && (kit != row_it.end()))
1674 if(own_col_idx[j] < glob_dof_idx[loc_col_idx[*kit]])
1676 else if(own_col_idx[j] > glob_dof_idx[loc_col_idx[*kit]])
1681 aux_data_mir.push_back(std::make_pair(j, (*kit)*IT_(bh_) + IT_(bi)));
1691 this->_buf_mir = LAFEM::VectorMirror<DT_, IT_>(owned_graph.get_num_indices(), num_idx);
1692 this->_loc_mir = LAFEM::VectorMirror<DT_, IT_>(
1693 local_matrix.template used_elements<LAFEM::Perspective::pod>(), num_idx);
1695 IT_* bm_idx = this->_buf_mir.indices();
1696 IT_* lm_idx = this->_loc_mir.indices();
1697 for(Index i = 0; i < num_idx; ++i)
1699 bm_idx[i] = aux_data_mir[i].first;
1700 lm_idx[i] = aux_data_mir[i].second;
1703 return num_owned_dofs *
Index(bh_);
1706 template<
typename DTA_>
1707 void upload_owned_data(DTA_* adp_val,
const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& local_matrix)
const
1709 const DT_* loc_val = local_matrix.template val<LAFEM::Perspective::pod>();
1710 const IT_* adp_idx = _buf_mir.indices();
1711 const IT_* loc_idx = _loc_mir.indices();
1712 XASSERT(_buf_mir.num_indices() == _loc_mir.num_indices());
1713 Index n = _buf_mir.num_indices();
1714 for(Index i = 0; i < n; ++i)
1716 ASSERT(loc_idx[i] < local_matrix.template used_elements<LAFEM::Perspective::pod>());
1717 adp_val[adp_idx[i]] = DTA_(loc_val[loc_idx[i]]);
1721 void gather_owner_data(
1722 LAFEM::DenseVector<DT_, IT_>& buffer,
1723 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& local_matrix)
const
1725 DT_* buf_val = buffer.elements();
1726 const DT_* loc_val = local_matrix.template val<LAFEM::Perspective::pod>();
1727 const IT_* buf_idx = this->_buf_mir.indices();
1728 const IT_* loc_idx = this->_loc_mir.indices();
1729 XASSERT(this->_buf_mir.num_indices() == this->_loc_mir.num_indices());
1730 Index n = this->_buf_mir.num_indices();
1731 for(Index i = 0; i < n; ++i)
1733 ASSERT(buf_idx[i] < buffer.size());
1734 ASSERT(loc_idx[i] < local_matrix.template used_elements<LAFEM::Perspective::pod>());
1735 buf_val[buf_idx[i]] = loc_val[loc_idx[i]];
1743 template<
typename DT_,
typename IT_,
int bh_,
int bw_>
1744 class ADPDOMM<LAFEM::NullMatrix<DT_, IT_, bh_, bw_>>
1747 Index num_indices()
const
1752 Index buf_size()
const
1757 Index loc_size()
const
1767 Index asm_neighbor_owner_data_mir(
1768 const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&,
1769 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1770 const LAFEM::MatrixMirrorBuffer<DT_, IT_>&,
1771 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>&,
1774 return row_mirror.num_indices() *
Index(bh_);
1777 Index asm_neighbor_owner_data_mir(
1778 const LAFEM::NullMatrix<DT_, IT_, bh_, 1>&,
1779 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1780 const LAFEM::MatrixMirrorBuffer<DT_, IT_>&,
1781 const LAFEM::DenseVector<IT_, IT_>&,
1784 return row_mirror.num_indices() *
Index(bh_);
1787 Index asm_owned_data_mir(
1788 const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&,
1789 const Adjacency::Graph&,
1790 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1791 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>&,
1794 return row_mirror.num_indices() *
Index(bh_);
1797 Index asm_owned_data_mir(
1798 const LAFEM::NullMatrix<DT_, IT_, bh_, 1>&,
1799 const Adjacency::Graph&,
1800 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
1801 const LAFEM::DenseVector<IT_, IT_>&,
1804 return row_mirror.num_indices() *
Index(bh_);
1807 template<
typename DTA_>
1808 void upload_owned_data(DTA_*,
const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&)
const
1812 void gather_owner_data(
1813 LAFEM::DenseVector<DT_, IT_>&,
1814 const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&)
const
1821 template<
typename FirstMatrix_,
typename... RestMatrix_>
1822 class ADPDOMM<LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>>
1825 typedef typename FirstMatrix_::DataType DT_;
1826 typedef typename FirstMatrix_::IndexType IT_;
1828 ADPDOMM<FirstMatrix_> first;
1829 ADPDOMM<LAFEM::TupleMatrixRow<RestMatrix_...>>
rest;
1831 Index num_indices()
const
1833 return first.num_indices() +
rest.num_indices();
1836 Index buf_size()
const
1838 return first.buf_size() +
rest.buf_size();
1841 Index loc_size()
const
1843 return first.loc_size() +
rest.loc_size();
1846 String dump_raw()
const
1848 return first.dump() +
"," +
rest.dump_raw();
1853 return "[" + dump_raw() +
"]";
1857 typename RowMirror_,
1858 typename FirstIdxVec_,
typename... RestIdxVec_>
1859 Index asm_neighbor_owner_data_mir(
1860 const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix,
1861 const RowMirror_& row_mirror,
1862 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
1863 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
1866 Index n1 = first.asm_neighbor_owner_data_mir(local_matrix.first(), row_mirror, buffer, global_dof_idx.first(), row_offset);
1867 Index n2 =
rest.asm_neighbor_owner_data_mir(local_matrix.rest(), row_mirror, buffer, global_dof_idx.rest(), row_offset);
1873 typename RowMirror_,
1874 typename FirstIdxVec_,
typename... RestIdxVec_>
1875 Index asm_owned_data_mir(
1876 const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix,
1877 const Adjacency::Graph& owned_graph,
1878 const RowMirror_& row_mirror,
1879 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
1882 Index n1 = first.asm_owned_data_mir(local_matrix.first(), owned_graph, row_mirror, global_dof_idx.first(), row_offset);
1883 Index n2 =
rest.asm_owned_data_mir(local_matrix.rest(), owned_graph, row_mirror, global_dof_idx.rest(), row_offset);
1888 template<
typename DTA_>
1889 void upload_owned_data(DTA_* adp_val,
const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix)
const
1891 first.upload_owned_data(adp_val, local_matrix.first());
1892 rest.upload_owned_data(adp_val, local_matrix.rest());
1895 void gather_owner_data(
1896 LAFEM::DenseVector<DT_, IT_>& buffer,
1897 const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix)
const
1899 first.gather_owner_data(buffer, local_matrix.first());
1900 rest.gather_owner_data(buffer, local_matrix.rest());
1906 template<
typename FirstMatrix_>
1907 class ADPDOMM<LAFEM::TupleMatrixRow<FirstMatrix_>>
1910 typedef typename FirstMatrix_::DataType DT_;
1911 typedef typename FirstMatrix_::IndexType IT_;
1913 ADPDOMM<FirstMatrix_> first;
1915 Index num_indices()
const
1917 return first.num_indices();
1920 Index buf_size()
const
1922 return first.buf_size();
1925 Index loc_size()
const
1927 return first.loc_size();
1930 String dump_raw()
const
1932 return first.dump();
1937 return "[" + dump_raw() +
"]";
1941 typename RowMirror_,
1942 typename FirstIdxVec_>
1943 Index asm_neighbor_owner_data_mir(
1944 const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix,
1945 const RowMirror_& row_mirror,
1946 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
1947 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx,
1950 return first.asm_neighbor_owner_data_mir(local_matrix.first(), row_mirror, buffer, global_dof_idx.first(), row_offset);
1954 typename RowMirror_,
1955 typename FirstIdxVec_>
1956 Index asm_owned_data_mir(
1957 const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix,
1958 const Adjacency::Graph& owned_graph,
1959 const RowMirror_& row_mirror,
1960 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx,
1963 return first.asm_owned_data_mir(local_matrix.first(), owned_graph, row_mirror, global_dof_idx.first(), row_offset);
1966 template<
typename DTA_>
1967 void upload_owned_data(DTA_* adp_val,
const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix)
const
1969 first.upload_owned_data(adp_val, local_matrix.first());
1972 void gather_owner_data(
1973 LAFEM::DenseVector<DT_, IT_>& buffer,
1974 const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix)
const
1976 first.gather_owner_data(buffer, local_matrix.first());
1982 template<
typename FirstMatRow_,
typename... RestMatRow_>
1983 class ADPDOMM<LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>>
1986 typedef typename FirstMatRow_::DataType DT_;
1987 typedef typename FirstMatRow_::IndexType IT_;
1989 ADPDOMM<FirstMatRow_> first;
1990 ADPDOMM<LAFEM::TupleMatrix<RestMatRow_...>>
rest;
1992 Index num_indices()
const
1994 return first.num_indices() +
rest.num_indices();
1997 Index buf_size()
const
1999 return first.buf_size() +
rest.buf_size();
2002 Index loc_size()
const
2004 return first.loc_size() +
rest.loc_size();
2007 String dump_raw()
const
2009 return first.dump() +
"," +
rest.dump_raw();
2014 return "[" + dump_raw() +
"]";
2018 typename FirstRowMir_,
typename... RestRowMir_,
2019 typename FirstIdxVec_,
typename... RestIdxVec_>
2020 Index asm_neighbor_owner_data_mir(
2021 const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix,
2022 const LAFEM::TupleMirror<FirstRowMir_, RestRowMir_...>& row_mirror,
2023 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
2024 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
2027 Index n1 = first.asm_neighbor_owner_data_mir(local_matrix.first(), row_mirror.first(), buffer, global_dof_idx, row_offset);
2028 Index n2 =
rest.asm_neighbor_owner_data_mir(local_matrix.rest(), row_mirror.rest(), buffer, global_dof_idx, row_offset + n1);
2033 typename FirstRowMir_,
typename... RestRowMir_,
2034 typename FirstIdxVec_,
typename... RestIdxVec_>
2035 Index asm_owned_data_mir(
2036 const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix,
2037 const Adjacency::Graph& owned_graph,
2038 const LAFEM::TupleMirror<FirstRowMir_, RestRowMir_...>& row_mirror,
2039 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
2042 Index n1 = first.asm_owned_data_mir(local_matrix.first(), owned_graph, row_mirror.first(), global_dof_idx, row_offset);
2043 Index n2 =
rest.asm_owned_data_mir(local_matrix.rest(), owned_graph, row_mirror.rest(), global_dof_idx, row_offset + n1);
2047 template<
typename DTA_>
2048 void upload_owned_data(DTA_* adp_val,
const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix)
const
2050 first.upload_owned_data(adp_val, local_matrix.first());
2051 rest.upload_owned_data(adp_val, local_matrix.rest());
2054 void gather_owner_data(
2055 LAFEM::DenseVector<DT_, IT_>& buffer,
2056 const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix)
const
2058 first.gather_owner_data(buffer, local_matrix.first());
2059 rest.gather_owner_data(buffer, local_matrix.rest());
2065 template<
typename FirstMatRow_>
2066 class ADPDOMM<LAFEM::TupleMatrix<FirstMatRow_>>
2069 typedef typename FirstMatRow_::DataType DT_;
2070 typedef typename FirstMatRow_::IndexType IT_;
2072 ADPDOMM<FirstMatRow_> first;
2074 Index num_indices()
const
2076 return first.num_indices();
2079 Index buf_size()
const
2081 return first.buf_size();
2084 Index loc_size()
const
2086 return first.loc_size();
2089 String dump_raw()
const
2091 return first.dump();
2096 return "[" + dump_raw() +
"]";
2100 typename FirstRowMir_,
2101 typename FirstIdxVec_,
typename... RestIdxVec_>
2102 Index asm_neighbor_owner_data_mir(
2103 const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix,
2104 const LAFEM::TupleMirror<FirstRowMir_>& row_mirror,
2105 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
2106 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
2109 return first.asm_neighbor_owner_data_mir(local_matrix.first(), row_mirror.first(), buffer, global_dof_idx, row_offset);
2113 typename FirstRowMir_,
2114 typename FirstIdxVec_,
typename... RestIdxVec_>
2115 Index asm_owned_data_mir(
2116 const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix,
2117 const Adjacency::Graph& owned_graph,
2118 const LAFEM::TupleMirror<FirstRowMir_>& row_mirror,
2119 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
2122 return first.asm_owned_data_mir(local_matrix.first(), owned_graph, row_mirror.first(), global_dof_idx, row_offset);
2125 template<
typename DTA_>
2126 void upload_owned_data(DTA_* adp_val,
const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix)
const
2128 first.upload_owned_data(adp_val, local_matrix.first());
2131 void gather_owner_data(
2132 LAFEM::DenseVector<DT_, IT_>& buffer,
2133 const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix)
const
2135 first.gather_owner_data(buffer, local_matrix.first());
2141 template<
typename MatrixA_,
typename MatrixB_,
typename MatrixD_>
2142 class ADPDOMM<LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>>
2145 typedef typename MatrixA_::DataType DT_;
2146 typedef typename MatrixA_::IndexType IT_;
2148 ADPDOMM<MatrixA_> block_a;
2149 ADPDOMM<MatrixB_> block_b;
2150 ADPDOMM<MatrixD_> block_d;
2152 Index num_indices()
const
2154 return block_a.num_indices() + block_b.num_indices() + block_d.num_indices();
2157 Index buf_size()
const
2159 return block_a.buf_size() + block_b.buf_size() + block_d.buf_size();
2162 Index loc_size()
const
2164 return block_a.loc_size() + block_b.loc_size() + block_d.loc_size();
2169 return "[[" + block_a.dump() +
"," + block_b.dump() +
"],[" + block_d.dump() +
",0]";
2173 typename MirrorV_,
typename MirrorP_,
2174 typename IdxVecV_,
typename IdxVecP_>
2175 Index asm_neighbor_owner_data_mir(
2176 const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix,
2177 const LAFEM::TupleMirror<MirrorV_, MirrorP_>& row_mirror,
2178 const LAFEM::MatrixMirrorBuffer<DT_, IT_>& buffer,
2179 const LAFEM::TupleVector<IdxVecV_, IdxVecP_>& global_dof_idx,
2182 Index na = block_a.asm_neighbor_owner_data_mir(local_matrix.block_a(), row_mirror.template at<0>(), buffer, global_dof_idx.template at<0>(), row_offset);
2183 Index nb = block_b.asm_neighbor_owner_data_mir(local_matrix.block_b(), row_mirror.template at<0>(), buffer, global_dof_idx.template at<1>(), row_offset);
2185 Index nd = block_d.asm_neighbor_owner_data_mir(local_matrix.block_d(), row_mirror.template at<1>(), buffer, global_dof_idx.template at<0>(), row_offset + na);
2190 typename MirrorV_,
typename MirrorP_,
2191 typename IdxVecV_,
typename IdxVecP_>
2192 Index asm_owned_data_mir(
2193 const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix,
2194 const Adjacency::Graph& owned_graph,
2195 const LAFEM::TupleMirror<MirrorV_, MirrorP_>& row_mirror,
2196 const LAFEM::TupleVector<IdxVecV_, IdxVecP_>& global_dof_idx,
2199 Index na = block_a.asm_owned_data_mir(local_matrix.block_a(), owned_graph, row_mirror.template at<0>(), global_dof_idx.template at<0>(), row_offset);
2200 Index nb = block_b.asm_owned_data_mir(local_matrix.block_b(), owned_graph, row_mirror.template at<0>(), global_dof_idx.template at<1>(), row_offset);
2202 Index nd = block_d.asm_owned_data_mir(local_matrix.block_d(), owned_graph, row_mirror.template at<1>(), global_dof_idx.template at<0>(), row_offset + na);
2206 template<
typename DTA_>
2207 void upload_owned_data(DTA_* adp_val,
const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix)
const
2209 block_a.upload_owned_data(adp_val, local_matrix.block_a());
2210 block_b.upload_owned_data(adp_val, local_matrix.block_b());
2211 block_d.upload_owned_data(adp_val, local_matrix.block_d());
2214 void gather_owner_data(
2215 LAFEM::DenseVector<DT_, IT_>& buffer,
2216 const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix)
const
2218 block_a.gather_owner_data(buffer, local_matrix.block_a());
2219 block_b.gather_owner_data(buffer, local_matrix.block_b());
2220 block_d.gather_owner_data(buffer, local_matrix.block_d());
2226 template<
typename DT_,
typename IT_>
2227 class ADPMatAux<LAFEM::SparseMatrixCSR<DT_, IT_>>
2230 static Index calc_mat_buf_num_rows(
2231 const LAFEM::SparseMatrixCSR<DT_, IT_>& DOXY(local_matrix),
2232 const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2234 return row_mirror.num_indices();
2237 static Index calc_mat_buf_row_nze(
2239 const LAFEM::SparseMatrixCSR<DT_, IT_>& local_matrix,
2240 const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2242 const Index num_idx = row_mirror.num_indices();
2243 const IT_* mir_idx = row_mirror.indices();
2244 const IT_* row_ptr = local_matrix.row_ptr();
2246 for(Index i(0); i < num_idx; ++i)
2248 buf_row_nze[i] += (row_ptr[mir_idx[i]+1] - row_ptr[mir_idx[i]]);
2254 static Index gather_mat_buf_col_idx(
2257 const LAFEM::SparseMatrixCSR<DT_, IT_>& local_matrix,
2258 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2259 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx)
2261 const Index num_idx = row_mirror.num_indices();
2262 const IT_* mir_idx = row_mirror.indices();
2263 const IT_* row_ptr = local_matrix.row_ptr();
2264 const IT_* col_idx = local_matrix.col_ind();
2265 const IT_* glob_dof_idx = global_dof_idx.elements();
2267 for(Index i(0); i < num_idx; ++i)
2270 IT_& k = aux_row_ptr[i];
2271 const IT_ row = mir_idx[i];
2274 for(IT_ j(row_ptr[row]); j < row_ptr[row+1]; ++j, ++k)
2275 buf_col_idx[k] = glob_dof_idx[col_idx[j]];
2281 static Index gather_owned_struct(
2282 Adjacency::DynamicGraph& graph,
2283 const LAFEM::SparseMatrixCSR<DT_, IT_>& local_matrix,
2284 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2285 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx,
2286 const Index row_offset)
2288 const Index num_rows = row_mirror.num_indices();
2289 const IT_* loc_row_ptr = local_matrix.row_ptr();
2290 const IT_* loc_col_idx = local_matrix.col_ind();
2291 const IT_* row_mir_idx = row_mirror.indices();
2292 const IT_* glob_dof_idx = global_dof_idx.elements();
2294 for(Index i(0); i < num_rows; ++i)
2296 const IT_ lrow = row_mir_idx[i];
2297 for(IT_ j(loc_row_ptr[lrow]); j < loc_row_ptr[lrow + 1]; ++j)
2299 graph.insert(row_offset + i,
Index(glob_dof_idx[loc_col_idx[j]]));
2308 template<
typename DT_,
typename IT_,
int bh_,
int bw_>
2309 class ADPMatAux<LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>>
2312 static Index calc_mat_buf_num_rows(
2313 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& DOXY(local_matrix),
2314 const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2316 return row_mirror.num_indices() *
Index(bh_);
2319 static Index calc_mat_buf_row_nze(
2321 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& local_matrix,
2322 const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2324 const Index num_idx = row_mirror.num_indices();
2325 const IT_* mir_idx = row_mirror.indices();
2326 const IT_* row_ptr = local_matrix.row_ptr();
2328 for(Index i(0), j(0); i < num_idx; ++i)
2330 IT_ nn = IT_(bw_) * (row_ptr[mir_idx[i]+1] - row_ptr[mir_idx[i]]);
2331 for(
int k(0); k < bh_; ++k, ++j)
2332 buf_row_nze[j] += nn;
2335 return num_idx *
Index(bh_);
2338 static Index gather_mat_buf_col_idx(
2341 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& local_matrix,
2342 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2343 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>& global_dof_idx)
2345 const Index num_idx = row_mirror.num_indices();
2346 const IT_* mir_idx = row_mirror.indices();
2347 const IT_* row_ptr = local_matrix.row_ptr();
2348 const IT_* col_idx = local_matrix.col_ind();
2349 const auto* glob_dof_idx = global_dof_idx.elements();
2351 for(Index i(0); i < num_idx; ++i)
2353 const IT_ row = mir_idx[i];
2356 for(
int bi(0); bi < bh_; ++bi)
2359 IT_& k = aux_row_ptr[i*IT_(bh_) + IT_(bi)];
2362 for(IT_ j(row_ptr[row]); j < row_ptr[row+1]; ++j)
2365 for(
int bj(0); bj < bw_; ++bj, ++k)
2367 buf_col_idx[k] = glob_dof_idx[col_idx[j]][bj];
2373 return num_idx *
Index(bh_);
2376 static Index gather_mat_buf_col_idx(
2379 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, 1>& local_matrix,
2380 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2381 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx)
2383 const Index num_idx = row_mirror.num_indices();
2384 const IT_* mir_idx = row_mirror.indices();
2385 const IT_* row_ptr = local_matrix.row_ptr();
2386 const IT_* col_idx = local_matrix.col_ind();
2387 const auto* glob_dof_idx = global_dof_idx.elements();
2389 for(Index i(0); i < num_idx; ++i)
2391 const IT_ row = mir_idx[i];
2394 for(
int bi(0); bi < bh_; ++bi)
2397 IT_& k = aux_row_ptr[i*IT_(bh_) + IT_(bi)];
2400 for(IT_ j(row_ptr[row]); j < row_ptr[row+1]; ++j, ++k)
2402 buf_col_idx[k] = glob_dof_idx[col_idx[j]];
2407 return num_idx *
Index(bh_);
2410 static Index gather_owned_struct(
2411 Adjacency::DynamicGraph& graph,
2412 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, bw_>& local_matrix,
2413 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2414 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>& global_dof_idx,
2415 const Index row_offset)
2417 const Index num_rows = row_mirror.num_indices();
2418 const IT_* loc_row_ptr = local_matrix.row_ptr();
2419 const IT_* loc_col_idx = local_matrix.col_ind();
2420 const IT_* row_mir_idx = row_mirror.indices();
2421 const auto* glob_dof_idx = global_dof_idx.elements();
2423 for(Index i(0); i < num_rows; ++i)
2425 const Index lrow = row_mir_idx[i];
2426 for(IT_ j(loc_row_ptr[lrow]); j < loc_row_ptr[lrow + 1]; ++j)
2428 const auto& gci = glob_dof_idx[loc_col_idx[j]];
2429 for(
int bi = 0; bi < bh_; ++bi)
2431 for(
int bj = 0; bj < bw_; ++bj)
2438 return num_rows *
Index(bh_);
2441 static Index gather_owned_struct(
2442 Adjacency::DynamicGraph& graph,
2443 const LAFEM::SparseMatrixBCSR<DT_, IT_, bh_, 1>& local_matrix,
2444 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2445 const LAFEM::DenseVector<IT_, IT_>& global_dof_idx,
2446 const Index row_offset)
2448 const Index num_rows = row_mirror.num_indices();
2449 const IT_* loc_row_ptr = local_matrix.row_ptr();
2450 const IT_* loc_col_idx = local_matrix.col_ind();
2451 const IT_* row_mir_idx = row_mirror.indices();
2452 const IT_* glob_dof_idx = global_dof_idx.elements();
2454 for(Index i(0); i < num_rows; ++i)
2456 const Index lrow = row_mir_idx[i];
2457 for(IT_ j(loc_row_ptr[lrow]); j < loc_row_ptr[lrow + 1]; ++j)
2459 const IT_ gci = glob_dof_idx[loc_col_idx[j]];
2460 for(
int bi = 0; bi < bh_; ++bi)
2466 return num_rows *
Index(bh_);
2472 template<
typename DT_,
typename IT_,
int bh_,
int bw_>
2473 class ADPMatAux<LAFEM::NullMatrix<DT_, IT_, bh_, bw_>>
2476 static Index calc_mat_buf_num_rows(
2477 const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&,
2478 const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2480 return row_mirror.num_indices() *
Index(bh_);
2483 static Index calc_mat_buf_row_nze(
2485 const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&,
2486 const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2488 return row_mirror.num_indices() *
Index(bh_);
2491 static Index gather_mat_buf_col_idx(
2494 const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&,
2495 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2496 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>&)
2498 return row_mirror.num_indices() *
Index(bh_);
2501 static Index gather_mat_buf_col_idx(
2504 const LAFEM::NullMatrix<DT_, IT_, bh_, 1>&,
2505 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2506 const LAFEM::DenseVector<IT_, IT_>&)
2508 return row_mirror.num_indices() *
Index(bh_);
2511 static Index gather_owned_struct(
2512 Adjacency::DynamicGraph&,
2513 const LAFEM::NullMatrix<DT_, IT_, bh_, bw_>&,
2514 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2515 const LAFEM::DenseVectorBlocked<IT_, IT_, bw_>&,
2518 return row_mirror.num_indices() *
Index(bh_);
2521 static Index gather_owned_struct(
2522 Adjacency::DynamicGraph&,
2523 const LAFEM::NullMatrix<DT_, IT_, bh_, 1>&,
2524 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2525 const LAFEM::DenseVector<IT_, IT_>&,
2528 return row_mirror.num_indices() *
Index(bh_);
2534 template<
typename FirstMatrix_,
typename... RestMatrix_>
2535 class ADPMatAux<LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>>
2538 typedef typename FirstMatrix_::IndexType IT_;
2539 typedef ADPMatAux<FirstMatrix_> ADPMatAuxFirst;
2540 typedef ADPMatAux<LAFEM::TupleMatrixRow<RestMatrix_...>> ADPMatAuxRest;
2542 template<
typename RowMirror_>
2543 static Index calc_mat_buf_num_rows(
2544 const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix,
2545 const RowMirror_& row_mirror)
2547 Index n1 = ADPMatAuxFirst::calc_mat_buf_num_rows(local_matrix.first(), row_mirror);
2548 Index n2 = ADPMatAuxRest::calc_mat_buf_num_rows(local_matrix.rest(), row_mirror);
2553 template<
typename RowMirror_>
2554 static Index calc_mat_buf_row_nze(
2556 const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix,
2557 const RowMirror_& row_mirror)
2559 Index n1 = ADPMatAuxFirst::calc_mat_buf_row_nze(buf_row_nze, local_matrix.first(), row_mirror);
2560 Index n2 = ADPMatAuxRest::calc_mat_buf_row_nze(buf_row_nze, local_matrix.rest(), row_mirror);
2566 typename RowMirror_,
2567 typename FirstIdxVec_,
typename... RestIdxVec_>
2568 static Index gather_mat_buf_col_idx(
2571 const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix,
2572 const RowMirror_& row_mirror,
2573 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx)
2575 Index n1 = ADPMatAuxFirst::gather_mat_buf_col_idx(aux_row_ptr, buf_col_idx, local_matrix.first(), row_mirror, global_dof_idx.first());
2576 Index n2 = ADPMatAuxRest::gather_mat_buf_col_idx(aux_row_ptr, buf_col_idx, local_matrix.rest(), row_mirror, global_dof_idx.rest());
2582 typename RowMirror_,
2583 typename FirstIdxVec_,
typename... RestIdxVec_>
2584 static Index gather_owned_struct(
2585 Adjacency::DynamicGraph& graph,
2586 const LAFEM::TupleMatrixRow<FirstMatrix_, RestMatrix_...>& local_matrix,
2587 const RowMirror_& row_mirror,
2588 const LAFEM::TupleVector<FirstIdxVec_, RestIdxVec_...>& global_dof_idx,
2589 const Index row_offset)
2591 Index n1 = ADPMatAuxFirst::gather_owned_struct(graph, local_matrix.first(), row_mirror, global_dof_idx.first(), row_offset);
2592 Index n2 = ADPMatAuxRest::gather_owned_struct(graph, local_matrix.rest(), row_mirror, global_dof_idx.rest(), row_offset);
2600 template<
typename FirstMatrix_>
2601 class ADPMatAux<LAFEM::TupleMatrixRow<FirstMatrix_>>
2604 typedef typename FirstMatrix_::IndexType IT_;
2605 typedef ADPMatAux<FirstMatrix_> ADPMatAuxFirst;
2607 template<
typename RowMirror_>
2608 static Index calc_mat_buf_num_rows(
2609 const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix,
2610 const RowMirror_& row_mirror)
2612 return ADPMatAuxFirst::calc_mat_buf_num_rows(local_matrix.first(), row_mirror);
2615 template<
typename RowMirror_>
2616 static Index calc_mat_buf_row_nze(
2618 const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix,
2619 const RowMirror_& row_mirror)
2621 return ADPMatAuxFirst::calc_mat_buf_row_nze(buf_row_nze, local_matrix.first(), row_mirror);
2625 typename RowMirror_,
2626 typename FirstIdxVec_>
2627 static Index gather_mat_buf_col_idx(
2630 const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix,
2631 const RowMirror_& row_mirror,
2632 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx)
2634 return ADPMatAuxFirst::gather_mat_buf_col_idx(aux_row_ptr, buf_col_idx, local_matrix.first(), row_mirror, global_dof_idx.first());
2638 typename RowMirror_,
2639 typename FirstIdxVec_>
2640 static Index gather_owned_struct(
2641 Adjacency::DynamicGraph& graph,
2642 const LAFEM::TupleMatrixRow<FirstMatrix_>& local_matrix,
2643 const RowMirror_& row_mirror,
2644 const LAFEM::TupleVector<FirstIdxVec_>& global_dof_idx,
2645 const Index row_offset)
2647 return ADPMatAuxFirst::gather_owned_struct(graph, local_matrix.first(), row_mirror, global_dof_idx.first(), row_offset);
2653 template<
typename FirstMatRow_,
typename... RestMatRow_>
2654 class ADPMatAux<LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>>
2657 typedef typename FirstMatRow_::IndexType IT_;
2658 typedef ADPMatAux<FirstMatRow_> ADPMatAuxFirst;
2659 typedef ADPMatAux<LAFEM::TupleMatrix<RestMatRow_...>> ADPMatAuxRest;
2661 template<
typename FirstMirror_,
typename... RestMirror_>
2662 static Index calc_mat_buf_num_rows(
2663 const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix,
2664 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& row_mirror)
2666 Index n1 = ADPMatAuxFirst::calc_mat_buf_num_rows(local_matrix.first(), row_mirror.first());
2667 Index n2 = ADPMatAuxRest::calc_mat_buf_num_rows(local_matrix.rest(), row_mirror.rest());
2671 template<
typename FirstMirror_,
typename... RestMirror_>
2672 static Index calc_mat_buf_row_nze(
2674 const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix,
2675 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& row_mirror)
2677 Index n1 = ADPMatAuxFirst::calc_mat_buf_row_nze(buf_row_nze, local_matrix.first(), row_mirror.first());
2678 Index n2 = ADPMatAuxRest::calc_mat_buf_row_nze(&buf_row_nze[n1], local_matrix.rest(), row_mirror.rest());
2683 typename FirstMirror_,
typename... RestMirror_,
2684 typename IndexVector_>
2685 static Index gather_mat_buf_col_idx(
2688 const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix,
2689 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& row_mirror,
2690 const IndexVector_& global_dof_idx)
2692 Index n1 = ADPMatAuxFirst::gather_mat_buf_col_idx(aux_row_ptr, buf_col_idx, local_matrix.first(), row_mirror.first(), global_dof_idx);
2693 Index n2 = ADPMatAuxRest::gather_mat_buf_col_idx(&aux_row_ptr[n1], buf_col_idx, local_matrix.rest(), row_mirror.rest(), global_dof_idx);
2698 typename FirstMirror_,
typename... RestMirror_,
2699 typename IndexVector_>
2700 static Index gather_owned_struct(
2701 Adjacency::DynamicGraph& graph,
2702 const LAFEM::TupleMatrix<FirstMatRow_, RestMatRow_...>& local_matrix,
2703 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& row_mirror,
2704 const IndexVector_& global_dof_idx,
2705 const Index row_offset)
2707 Index n1 = ADPMatAuxFirst::gather_owned_struct(graph, local_matrix.first(), row_mirror.first(), global_dof_idx, row_offset);
2708 Index n2 = ADPMatAuxRest::gather_owned_struct(graph, local_matrix.rest(), row_mirror.rest(), global_dof_idx, row_offset + n1);
2715 template<
typename FirstMatRow_>
2716 class ADPMatAux<LAFEM::TupleMatrix<FirstMatRow_>>
2719 typedef typename FirstMatRow_::IndexType IT_;
2720 typedef ADPMatAux<FirstMatRow_> ADPMatAuxFirst;
2722 template<
typename FirstMirror_>
2723 static Index calc_mat_buf_num_rows(
2724 const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix,
2725 const LAFEM::TupleMirror<FirstMirror_>& row_mirror)
2727 return ADPMatAuxFirst::calc_mat_buf_num_rows(local_matrix.first(), row_mirror.first());
2730 template<
typename FirstMirror_>
2731 static Index calc_mat_buf_row_nze(
2733 const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix,
2734 const LAFEM::TupleMirror<FirstMirror_>& row_mirror)
2736 return ADPMatAuxFirst::calc_mat_buf_row_nze(buf_row_nze, local_matrix.first(), row_mirror.first());
2740 typename FirstMirror_,
2741 typename IndexVector_>
2742 static Index gather_mat_buf_col_idx(
2745 const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix,
2746 const LAFEM::TupleMirror<FirstMirror_>& row_mirror,
2747 const IndexVector_& global_dof_idx)
2749 return ADPMatAuxFirst::gather_mat_buf_col_idx(aux_row_ptr, buf_col_idx, local_matrix.first(), row_mirror.first(), global_dof_idx);
2753 typename FirstMirror_,
2754 typename IndexVector_>
2755 static Index gather_owned_struct(
2756 Adjacency::DynamicGraph& graph,
2757 const LAFEM::TupleMatrix<FirstMatRow_>& local_matrix,
2758 const LAFEM::TupleMirror<FirstMirror_>& row_mirror,
2759 const IndexVector_& global_dof_idx,
2760 const Index row_offset)
2762 return ADPMatAuxFirst::gather_owned_struct(graph, local_matrix.first(), row_mirror.first(), global_dof_idx, row_offset);
2768 template<
typename MatrixA_,
typename MatrixB_,
typename MatrixD_>
2769 class ADPMatAux<LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>>
2772 typedef typename MatrixA_::IndexType IT_;
2773 typedef ADPMatAux<MatrixA_> ADPMatAuxA;
2774 typedef ADPMatAux<MatrixB_> ADPMatAuxB;
2775 typedef ADPMatAux<MatrixD_> ADPMatAuxD;
2777 template<
typename MirrorV_,
typename MirrorP_>
2778 static Index calc_mat_buf_num_rows(
2779 const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix,
2780 const LAFEM::TupleMirror<MirrorV_, MirrorP_>& row_mirror)
2782 Index n1 = ADPMatAuxB::calc_mat_buf_num_rows(local_matrix.block_b(), row_mirror.template at<0>());
2783 Index n2 = ADPMatAuxD::calc_mat_buf_num_rows(local_matrix.block_d(), row_mirror.template at<1>());
2787 template<
typename MirrorV_,
typename MirrorP_>
2788 static Index calc_mat_buf_row_nze(
2790 const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix,
2791 const LAFEM::TupleMirror<MirrorV_, MirrorP_>& row_mirror)
2793 Index na = ADPMatAuxA::calc_mat_buf_row_nze(buf_row_nze, local_matrix.block_a(), row_mirror.template at<0>());
2794 Index nb = ADPMatAuxB::calc_mat_buf_row_nze(buf_row_nze, local_matrix.block_b(), row_mirror.template at<0>());
2796 Index nd = ADPMatAuxD::calc_mat_buf_row_nze(&buf_row_nze[na], local_matrix.block_d(), row_mirror.template at<1>());
2806 typename MirrorV_,
typename MirrorP_,
2807 typename IdxVecV_,
typename IdxVecP_>
2808 static Index gather_mat_buf_col_idx(
2811 const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix,
2812 const LAFEM::TupleMirror<MirrorV_, MirrorP_>& row_mirror,
2813 const LAFEM::TupleVector<IdxVecV_, IdxVecP_>& global_dof_idx)
2815 Index na = ADPMatAuxA::gather_mat_buf_col_idx(aux_row_ptr, buf_col_idx, local_matrix.block_a(), row_mirror.template at<0>(), global_dof_idx.template at<0>());
2816 Index nb = ADPMatAuxB::gather_mat_buf_col_idx(aux_row_ptr, buf_col_idx, local_matrix.block_b(), row_mirror.template at<0>(), global_dof_idx.template at<1>());
2818 Index nd = ADPMatAuxD::gather_mat_buf_col_idx(&aux_row_ptr[na], buf_col_idx, local_matrix.block_d(), row_mirror.template at<1>(), global_dof_idx.template at<0>());
2829 typename MirrorV_,
typename MirrorP_,
2830 typename IdxVecV_,
typename IdxVecP_>
2831 static Index gather_owned_struct(
2832 Adjacency::DynamicGraph& graph,
2833 const LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>& local_matrix,
2834 const LAFEM::TupleMirror<MirrorV_, MirrorP_>& row_mirror,
2835 const LAFEM::TupleVector<IdxVecV_, IdxVecP_>& global_dof_idx,
2836 const Index row_offset)
2838 Index na = ADPMatAuxA::gather_owned_struct(graph, local_matrix.block_a(), row_mirror.template at<0>(), global_dof_idx.template at<0>(), row_offset);
2839 Index nb = ADPMatAuxB::gather_owned_struct(graph, local_matrix.block_b(), row_mirror.template at<0>(), global_dof_idx.template at<1>(), row_offset);
2841 Index nd = ADPMatAuxD::gather_owned_struct(graph, local_matrix.block_d(), row_mirror.template at<1>(), global_dof_idx.template at<0>(), row_offset + na);
2845 const auto* p_dof_idx = global_dof_idx.template at<1>().elements();
2846 for(Index i = 0u; i < nd; ++i)
2847 graph.insert(na + i, p_dof_idx[i]);
2858 template<
typename DT_,
typename IT_>
2859 class ADPFilAux<LAFEM::NoneFilter<DT_, IT_>>
2862 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2864 return row_mirror.num_indices();
2867 static Index upload_filter(
2868 LAFEM::UnitFilter<DT_, IT_>& DOXY(unit_rows),
2869 const LAFEM::NoneFilter<DT_, IT_>& DOXY(filter),
2870 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2871 Index DOXY(row_offset))
2874 return row_count(row_mirror);
2880 template<
typename DT_,
typename IT_,
int bs_>
2881 class ADPFilAux<LAFEM::NoneFilterBlocked<DT_, IT_, bs_>>
2884 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2886 return row_mirror.num_indices() *
Index(bs_);
2889 static Index upload_filter(
2890 LAFEM::UnitFilter<DT_, IT_>& DOXY(unit_rows),
2891 const LAFEM::NoneFilterBlocked<DT_, IT_, bs_>& DOXY(filter),
2892 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2893 Index DOXY(row_offset))
2896 return row_count(row_mirror);
2902 template<
typename DT_,
typename IT_>
2903 class ADPFilAux<LAFEM::UnitFilter<DT_, IT_>>
2906 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2908 return row_mirror.num_indices();
2911 static Index upload_filter(
2912 LAFEM::UnitFilter<DT_, IT_>& unit_rows,
2913 const LAFEM::UnitFilter<DT_, IT_>& filter,
2914 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2917 if(filter.used_elements() <=
Index(0))
2918 return row_count(row_mirror);
2920 const IT_* fil_idx = filter.get_indices();
2921 const IT_* mir_idx = row_mirror.indices();
2922 const Index num_fil = filter.used_elements();
2923 const Index num_mir = row_mirror.num_indices();
2925 Index i = 0u, j = 0u;
2926 while((i < num_fil) && (j < num_mir))
2928 if(fil_idx[i] <
Index(mir_idx[j]))
2930 else if(fil_idx[i] >
Index(mir_idx[j]))
2934 unit_rows.add(IT_(row_offset + j), DT_(0));
2940 return row_count(row_mirror);
2946 template<
typename DT_,
typename IT_,
int bs_>
2947 class ADPFilAux<LAFEM::UnitFilterBlocked<DT_, IT_, bs_>>
2950 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
2952 return row_mirror.num_indices() *
Index(bs_);
2955 static Index upload_filter(
2956 LAFEM::UnitFilter<DT_, IT_>& unit_rows,
2957 const LAFEM::UnitFilterBlocked<DT_, IT_, bs_>& filter,
2958 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
2961 if(filter.used_elements() <=
Index(0))
2962 return row_count(row_mirror);
2964 const bool ignore_nans = filter.get_ignore_nans();
2965 const auto* fil_val = filter.get_values();
2966 const IT_* fil_idx = filter.get_indices();
2967 const IT_* mir_idx = row_mirror.indices();
2968 const Index num_fil = filter.used_elements();
2969 const Index num_mir = row_mirror.num_indices();
2971 Index i = 0u, j = 0u;
2972 while((i < num_fil) && (j < num_mir))
2974 if(fil_idx[i] <
Index(mir_idx[j]))
2976 else if(fil_idx[i] >
Index(mir_idx[j]))
2981 for(
int k = 0; k < bs_; ++k)
2983 if(!ignore_nans || !Math::isnan(fil_val[i][k]))
2984 unit_rows.add(IT_(row_offset + j*
Index(bs_) +
Index(k)), DT_(0));
2990 return row_count(row_mirror);
2996 template<
typename DT_,
typename IT_>
2997 class ADPFilAux<LAFEM::MeanFilter<DT_, IT_>>
3000 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3002 return row_mirror.num_indices();
3005 static Index upload_filter(
3006 LAFEM::UnitFilter<DT_, IT_>& DOXY(unit_rows),
3007 const LAFEM::MeanFilter<DT_, IT_>& filter,
3008 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
3009 Index DOXY(row_offset))
3011 XASSERTM(filter.empty(),
"AlgDofParti does not support LAFEM::MeanFilter yet!");
3012 return row_count(row_mirror);
3018 template<
typename DT_,
typename IT_,
int bs_>
3019 class ADPFilAux<LAFEM::MeanFilterBlocked<DT_, IT_, bs_>>
3022 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3024 return row_mirror.num_indices() *
Index(bs_);
3027 static Index upload_filter(
3028 LAFEM::UnitFilter<DT_, IT_>& DOXY(unit_rows),
3029 const LAFEM::MeanFilterBlocked<DT_, IT_, bs_>& filter,
3030 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
3031 Index DOXY(row_offset))
3033 XASSERTM(filter.empty(),
"AlgDofParti does not support LAFEM::MeanFilterBlocked yet!");
3034 return row_count(row_mirror);
3040 template<
typename DT_,
typename IT_>
3041 class ADPFilAux<Global::MeanFilter<DT_, IT_>>
3044 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3046 return row_mirror.num_indices();
3049 static Index upload_filter(
3050 LAFEM::UnitFilter<DT_, IT_>& DOXY(unit_rows),
3051 const Global::MeanFilter<DT_, IT_>& filter,
3052 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
3053 Index DOXY(row_offset))
3055 XASSERTM(filter.empty(),
"AlgDofParti does not support Global::MeanFilter yet!");
3056 return row_count(row_mirror);
3062 template<
typename DT_,
typename IT_,
int bs_>
3063 class ADPFilAux<LAFEM::SlipFilter<DT_, IT_, bs_>>
3066 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3068 return row_mirror.num_indices() *
Index(bs_);
3071 static Index upload_filter(
3072 LAFEM::UnitFilter<DT_, IT_>& DOXY(unit_rows),
3073 const LAFEM::SlipFilter<DT_, IT_, bs_>& filter,
3074 const LAFEM::VectorMirror<DT_, IT_>& row_mirror,
3075 Index DOXY(row_offset))
3077 XASSERTM(filter.empty(),
"AlgDofParti does not support LAFEM::SlipFilter yet!");
3078 return row_count(row_mirror);
3084 template<
typename FirstFilter_,
typename... RestFilter_>
3085 class ADPFilAux<LAFEM::FilterChain<FirstFilter_, RestFilter_...>>
3088 typedef typename FirstFilter_::DataType DT_;
3089 typedef typename FirstFilter_::IndexType IT_;
3090 typedef ADPFilAux<FirstFilter_> ADPFilAuxFirst;
3091 typedef ADPFilAux<LAFEM::FilterChain<RestFilter_...>> ADPFilAuxRest;
3093 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3095 Index n1 = ADPFilAuxFirst::row_count(row_mirror);
3096 Index n2 = ADPFilAuxRest::row_count(row_mirror);
3101 template<
typename RowMirror_>
3102 static Index upload_filter(
3103 LAFEM::UnitFilter<DT_, IT_>& unit_rows,
3104 const LAFEM::FilterChain<FirstFilter_, RestFilter_...>& filter,
3105 const RowMirror_& row_mirror,
3108 Index n1 = ADPFilAuxFirst::upload_filter(unit_rows, filter.first(), row_mirror, row_offset);
3109 Index n2 = ADPFilAuxRest::upload_filter(unit_rows, filter.rest(), row_mirror, row_offset);
3117 template<
typename FirstFilter_>
3118 class ADPFilAux<LAFEM::FilterChain<FirstFilter_>>
3121 typedef typename FirstFilter_::DataType DT_;
3122 typedef typename FirstFilter_::IndexType IT_;
3123 typedef ADPFilAux<FirstFilter_> ADPFilAuxFirst;
3125 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3127 return ADPFilAuxFirst::row_count(row_mirror);
3130 template<
typename RowMirror_>
3131 static Index upload_filter(
3132 LAFEM::UnitFilter<DT_, IT_>& unit_rows,
3133 const LAFEM::FilterChain<FirstFilter_>& filter,
3134 const RowMirror_& row_mirror,
3137 return ADPFilAuxFirst::upload_filter(unit_rows, filter.first(), row_mirror, row_offset);
3143 template<
typename SubFilter_>
3144 class ADPFilAux<LAFEM::FilterSequence<SubFilter_>>
3147 typedef typename SubFilter_::DataType DT_;
3148 typedef typename SubFilter_::IndexType IT_;
3149 typedef ADPFilAux<SubFilter_> ADPFilAuxSub;
3151 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3153 return ADPFilAuxSub::row_count(row_mirror);
3156 template<
typename RowMirror_>
3157 static Index upload_filter(
3158 LAFEM::UnitFilter<DT_, IT_>& unit_rows,
3159 const LAFEM::FilterSequence<SubFilter_>& filter,
3160 const RowMirror_& row_mirror,
3163 for(
const auto& x : filter)
3165 ADPFilAuxSub::upload_filter(unit_rows, x.second, row_mirror, row_offset);
3167 return row_count(row_mirror);
3173 template<
typename FirstFilter_,
typename... RestFilter_>
3174 class ADPFilAux<LAFEM::TupleFilter<FirstFilter_, RestFilter_...>>
3177 typedef typename FirstFilter_::DataType DT_;
3178 typedef typename FirstFilter_::IndexType IT_;
3179 typedef ADPFilAux<FirstFilter_> ADPFilAuxFirst;
3180 typedef ADPFilAux<LAFEM::TupleFilter<RestFilter_...>> ADPFilAuxRest;
3182 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3184 Index n1 = ADPFilAuxFirst::row_count(row_mirror);
3185 Index n2 = ADPFilAuxRest::row_count(row_mirror);
3189 template<
typename FirstMirror_,
typename... RestMirror_>
3190 static Index upload_filter(
3191 LAFEM::UnitFilter<DT_, IT_>& unit_rows,
3192 const LAFEM::TupleFilter<FirstFilter_, RestFilter_...>& filter,
3193 const LAFEM::TupleMirror<FirstMirror_, RestMirror_...>& row_mirror,
3196 Index n1 = ADPFilAuxFirst::upload_filter(unit_rows, filter.first(), row_mirror.first(), row_offset);
3197 Index n2 = ADPFilAuxRest::upload_filter(unit_rows, filter.rest(), row_mirror.rest(), row_offset + n1);
3204 template<
typename FirstFilter_>
3205 class ADPFilAux<LAFEM::TupleFilter<FirstFilter_>>
3208 typedef typename FirstFilter_::DataType DT_;
3209 typedef typename FirstFilter_::IndexType IT_;
3210 typedef ADPFilAux<FirstFilter_> ADPFilAuxFirst;
3212 static Index row_count(
const LAFEM::VectorMirror<DT_, IT_>& row_mirror)
3214 return ADPFilAuxFirst::row_count(row_mirror);
3217 template<
typename FirstMirror_>
3218 static Index upload_filter(
3219 LAFEM::UnitFilter<DT_, IT_>& unit_rows,
3220 const LAFEM::TupleFilter<FirstFilter_>& filter,
3221 const LAFEM::TupleMirror<FirstMirror_>& row_mirror,
3224 return ADPFilAuxFirst::upload_filter(unit_rows, filter.first(), row_mirror.first(), row_offset);
#define ASSERT(expr)
Debug-Assertion macro definition.
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Dynamic Adjacency Graph implementation.
void clear()
Clears the graph.
bool insert(Index domain_node, Index image_node)
Inserts a new adjacency entry to the graph.
Index get_num_indices() const
Returns the total number of indices.
Adjacency Graph implementation.
Index * get_domain_ptr()
Returns the domain pointer array.
Index * get_image_idx()
Returns the image node index array.
Index get_num_indices() const
Returns the total number indices.
void allreduce(const void *sendbuf, void *recvbuf, std::size_t count, const Datatype &datatype, const Operation &op) const
Blocking All-Reduce.
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.
void allgatherv(const void *sendbuf, std::size_t sendcount, const Datatype &sendtype, void *recvbuf, const int *recvcounts, const int *displs, 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.
int get_donee_rank(Index i) const
Returns an donee neighbor rank.
const OwnedMirrorType & get_owned_mirror() const
Returns the Mirror of the owned DOFs.
const OwnerMirrorType & get_owner_mirror(Index i) const
Returns an owner neighbor mirror.
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.
int get_owner_rank(Index i) const
Returns an owner neighbor rank.
Index get_num_owner_neighbors() const
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
Algebraic DOF partitioning linear system conversion class.
Index get_adp_vector_size() const
Index _num_owned_non_zeros
number of non-zero entries owned by this process
void filter_vec_cor(DTV_ *vec_cor)
Applies the ADP filter onto an ADP correction vector.
void filter_vec_def(DTV_ *vec_def)
Applies the ADP filter onto an ADP defect vector.
std::shared_ptr< Adjacency::Graph > _owned_graph
adjacency graph containing the owned matrix structure
std::size_t bytes() const
Index get_num_global_nonzeros() const
void upload_matrix_numeric(DTA_ *val, const RPT_ *row_ptr, const CIT_ *col_idx)
Uploads the data value array of the ADP CSR system matrix.
AlgDofPartiSystem(const GlobalMatrixType &matrix, const GlobalFilterType &filter)
Constructor.
LocalMatrix_ LocalMatrixType
the local matrix type
Index get_adp_matrix_nzes() const
LAFEM::MatrixMirrorBuffer< DataType, IndexType > BufferMatrixType
the buffer matrix type used for communication
const GlobalFilterType & _global_filter
the global filter that we want to convert
LAFEM::VectorMirror< DataType, IndexType > DoneeMirrorType
donee neighbor mirror type
LAFEM::DenseVector< DataType, IndexType > BufferVectorType
the buffer vector type used for communication
LAFEM::SparseMatrixCSR< DataType, IndexType > OwnedMatrixType
the matrix type used for the internal storage of our owned matrix rows
void upload_filter(const LocalFilterType &filter)
Uploads the values of the given filter to the ADP system.
std::shared_ptr< AlgDofPartiType > _alg_dof_parti
the algebraic dof-partitioning
Global::AlgDofParti< LocalVectorType, MirrorType > AlgDofPartiType
the algebraic DOF partitioning
Index get_adp_matrix_rows() const
Index get_adp_matrix_cols() const
void upload_vector(DTV_ *val, const LocalVectorType &vector)
Uploads the ADP vector values to the given array.
Mirror_ MirrorType
the vector mirror type
Index get_global_dof_offset() const
AlgDofPartiSystem & operator=(const AlgDofPartiSystem &)=delete
no copy, no problems
void init_symbolic()
Performs the symbolic initialization.
void apply(DTX_ *vec_r, const DTX_ *vec_x, const DTX_ *val_a, const RPT_ *row_ptr, const CIT_ *col_idx) const
Performs a global matrix-vector product with this matrix.
static void _asm_neighbor_donee_data_mir(DoneeMirrorType &data_mirror, const Adjacency::Graph &owned_graph, const DoneeMirrorType &mirror, const BufferMatrixType &buffer)
Auxiliary function: assembles a data-mirror for a donee-neighbor.
const GlobalMatrixType & _global_matrix
the global matrix that we want to convert
void _assemble_data_mirrors()
Assembles the data-mirrors for all owner- and donee-neighbors.
const Dist::Comm * get_comm() const
void download_vector(LocalVectorType &vector, const DTV_ *val)
Downloads the ADP vector values from the given array.
Index get_num_global_dofs() const
LocalMatrixType::VectorTypeR LocalVectorType
the local vector type
static BufferMatrixType _asm_mat_buf(const LocalMatrixType &local_matrix, const MirrorType &row_mirror, const IndexVectorType &global_dof_idx, const Index num_global_dofs)
Assembles a matrix buffer for a given row mirror.
Global::Filter< LocalFilterType, MirrorType > GlobalFilterType
the global filter type
std::shared_ptr< AlgDofPartiType > get_alg_dof_parti()
Returns the algebraic dof partitioning that is used internally.
std::vector< DoneeMirrorType > _donee_data_mirs
the data array mirrors for our donee and owner neighbors
LocalMatrix_::DataType DataType
our data type
void _assemble_buffers()
Assembles the owner and donee matrix buffers.
void _assemble_structure()
Assembles the matrix structure of the algebraic-DOF-partitioned matrix.
Index get_num_owned_dofs() const
LAFEM::UnitFilter< DataType, IndexType > _unit_filter_rows
indices of all unit-filtered matrix rows; we store this as a mirror
LocalMatrix_::IndexType IndexType
our index type
void filter_matrix(DTA_ *val, const RPT_ *row_ptr, const CIT_ *col_idx)
Applies the ADP filter onto an ADP matrix.
OwnerMirrorType _owned_data_mir
the data array mirror for this process
LocalFilter_ LocalFilterType
the local filter type
Index _num_global_non_zeros
number of non-zero entries in total
AlgDofPartiType::IndexVectorType IndexVectorType
auxiliary index vector type
static void _scatter_donee_data(DTA_ *adp_val, const BufferVectorType &buffer, const DoneeMirrorType &data_mirror)
Scatters the values of a donee-neighbor buffer-vector into a local matrix.
AlgDofPartiSystem(const AlgDofPartiSystem &)=delete
no copy, no problems
std::vector< BufferMatrixType > _donee_bufs
the matrix buffers for our donee and owner neighbors; both buffers use global DOF indices
void upload_matrix_numeric(DTA_ *val, const RPT_ *row_ptr, const CIT_ *col_idx, const LocalMatrixType &matrix)
Copies the matrix entry values from the input matrix into this algebraic-dof-partitioned matrix.
void upload_matrix_symbolic(RPT_ *row_ptr, CIT_ *col_idx, bool keep_graph=false)
Uploads the row-pointer and column-index arrays of the ADP CSR system matrix.
void upload_filter()
Uploads the values of the system filter to the ADP system.
Intern::ADPDOMM< LocalMatrixType > OwnerMirrorType
owner neighbor mirror type
AlgDofPartiSystem(const GlobalMatrixType &matrix, const GlobalFilterType &filter, std::shared_ptr< AlgDofPartiType > adp)
Constructor.
Global::Matrix< LocalMatrixType, MirrorType, MirrorType > GlobalMatrixType
the global matrix type
Global Filter wrapper class template.
Global Matrix wrapper class template.
const GateRowType * get_row_gate() const
Returns a const pointer to the internal row gate of the matrix.
LocalMatrix_ & local()
Returns a reference to the internal local LAFEM matrix object.
Index size() const
Returns the containers size.
Dense data vector class template.
DT_ * elements()
Get a pointer to the data array.
Matrix Mirror Buffer class template.
Index columns() const
Retrieve matrix column count.
IT_ * row_ptr()
Retrieve row start index array.
IT_ * col_ind()
Retrieve column indices array.
Index entries_per_nonzero() const
Retrieve entries per non zero element count.
Index used_elements() const
Retrieve non zero element count.
Index rows() const
Retrieve matrix row count.
Unit Filter class template.
Index used_elements() const
std::size_t bytes() const
Returns the total amount of bytes allocated.
Handles vector prolongation, restriction and serialization.
IT_ * indices()
Get a pointer to the non zero indices array.
Index num_indices() const
Returns the number of indices in the mirror.
@ as_is
Render-As-Is mode.
const Operation op_sum(MPI_SUM)
Operation wrapper for MPI_SUM.
@ rest
restriction (multigrid)
void feat_omp_ex_scan(std::size_t n, const T_ x[], T_ y[])
Computes an OpenMP-parallel exclusive scan a.k.a. a prefix sum of an array, i.e.
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.