42 #ifndef TPETRA_DETAILS_CRSUTILS_HPP
43 #define TPETRA_DETAILS_CRSUTILS_HPP
46 #include <type_traits>
48 #include "TpetraCore_config.h"
49 #include "Kokkos_Core.hpp"
50 #include "Kokkos_UnorderedMap.hpp"
63 template<
class ViewType>
65 uninitialized_view(
const std::string& name,
const size_t& size)
67 return ViewType (Kokkos::view_alloc(name, Kokkos::WithoutInitializing), size);
71 template<
class RowPtr,
class Indices,
class Padding>
77 const Padding& padding)
80 if (padding.size() == 0 || row_ptr_beg.size() == 0) {
86 auto num_row = row_ptr_beg.size() - 1;
87 auto policy = Kokkos::RangePolicy<typename Padding::execution_space>(0, num_row);
88 RowPtr entries_this_row(
"entries_this_row", num_row);
90 size_t additional_size_needed = 0;
91 Kokkos::parallel_reduce(
"Determine additional size needed", policy,
92 KOKKOS_LAMBDA(
const int i,
size_t& ladditional_size_needed) {
94 auto allocated_this_row = row_ptr_beg(i+1) - row_ptr_beg(i);
95 auto used_this_row = row_ptr_end(i) - row_ptr_beg(i);
96 auto free_this_row = allocated_this_row - used_this_row;
97 entries_this_row(i) = allocated_this_row;
99 auto k = padding.find(static_cast<typename Padding::key_type>(i));
100 if (padding.valid_at(k)) {
102 auto num_ent = padding.value_at(k);
103 auto n = (num_ent > free_this_row) ? num_ent - free_this_row : 0;
104 entries_this_row(i) += n;
105 ladditional_size_needed += n;
107 }, additional_size_needed);
109 if (additional_size_needed == 0)
return;
112 auto indices_new = uninitialized_view<Indices>(
"ind new", indices.size()+additional_size_needed);
118 auto this_row_beg = row_ptr_beg(0);
119 auto this_row_end = row_ptr_end(0);
120 using range = Kokkos::pair<typename RowPtr::value_type, typename RowPtr::value_type>;
121 for (
typename RowPtr::size_type i=0; i<num_row-1; i++) {
124 auto used_this_row = this_row_end - this_row_beg;
125 auto indices_old_subview =
126 subview(indices, range(this_row_beg, this_row_beg+used_this_row));
127 auto indices_new_subview =
128 subview(indices_new, range(row_ptr_beg(i), row_ptr_beg(i)+used_this_row));
131 using value_type =
typename Indices::non_const_value_type;
132 memcpy(indices_new_subview.data(), indices_old_subview.data(),
133 used_this_row *
sizeof(value_type));
139 this_row_beg = row_ptr_beg(i+1);
140 this_row_end = row_ptr_end(i+1);
142 auto used_next_row = row_ptr_end(i+1) - row_ptr_beg(i+1);
143 row_ptr_beg(i+1) = row_ptr_beg(i) + entries_this_row(i);
144 row_ptr_end(i+1) = row_ptr_beg(i+1) + used_next_row;
147 row_ptr_beg(num_row) = indices_new.size();
149 auto n = num_row - 1;
150 auto used_this_row = row_ptr_end(n) - row_ptr_beg(n);
151 auto indices_old_subview =
152 subview(indices, range(this_row_beg, this_row_beg+used_this_row));
153 auto indices_new_subview =
154 subview(indices_new, range(row_ptr_beg(n), row_ptr_beg(n)+used_this_row));
155 using value_type =
typename Indices::non_const_value_type;
156 memcpy(indices_new_subview.data(), indices_old_subview.data(),
157 used_this_row *
sizeof(value_type));
159 indices = indices_new;
163 template <
class Po
inters,
class InOutIndices,
class InIndices,
class IndexMap>
166 typename Pointers::value_type
const row,
167 Pointers
const& row_ptrs,
168 InOutIndices& cur_indices,
169 size_t& num_assigned,
170 InIndices
const& new_indices,
172 std::function<
void(
size_t const,
size_t const,
size_t const)> cb)
174 using offset_type =
typename std::decay<decltype (row_ptrs[0])>::type;
175 using ordinal_type =
typename std::decay<decltype (cur_indices[0])>::type;
177 if (new_indices.size() == 0) {
181 const offset_type start = row_ptrs[row];
182 offset_type end = start +
static_cast<offset_type
> (num_assigned);
183 const size_t num_avail = (row_ptrs[row + 1] < end) ?
size_t (0) :
184 row_ptrs[row + 1] - end;
185 const size_t num_new_indices =
static_cast<size_t> (new_indices.size ());
186 size_t num_inserted = 0;
188 for (
size_t k = 0; k < num_new_indices; ++k) {
189 const ordinal_type idx = std::forward<IndexMap>(map)(new_indices[k]);
190 offset_type row_offset = start;
191 for (; row_offset < end; ++row_offset) {
192 if (idx == cur_indices[row_offset]) {
197 if (row_offset == end) {
198 if (num_inserted >= num_avail) {
199 return Teuchos::OrdinalTraits<size_t>::invalid();
202 cur_indices[end++] = idx;
206 cb(k, start, row_offset - start);
209 num_assigned += num_inserted;
214 template <
class Po
inters,
class Indices1,
class Indices2,
class IndexMap,
class Callback>
217 typename Pointers::value_type
const row,
218 Pointers
const& row_ptrs,
219 Indices1
const& cur_indices,
220 Indices2
const& new_indices,
224 if (new_indices.size() == 0)
227 using ordinal =
typename Indices1::value_type;
228 auto invalid_ordinal = Teuchos::OrdinalTraits<ordinal>::invalid();
230 auto const start = row_ptrs[row];
231 auto const end = row_ptrs[row + 1];
232 size_t num_found = 0;
233 for (
size_t k = 0; k < new_indices.size(); k++)
235 auto row_offset = start;
236 auto idx = std::forward<IndexMap>(map)(new_indices[k]);
237 if (idx == invalid_ordinal)
239 for (; row_offset < end; row_offset++)
241 if (idx == cur_indices[row_offset])
243 std::forward<Callback>(cb)(k, start, row_offset - start);
275 template<
class RowPtr,
class Indices,
class Padding>
281 const Padding& padding)
283 using impl::pad_crs_arrays;
284 pad_crs_arrays<RowPtr, Indices, Padding>(rowPtrBeg, rowPtrEnd, indices, padding);
332 template <
class Po
inters,
class InOutIndices,
class InIndices>
335 typename Pointers::value_type
const row,
336 Pointers
const& rowPtrs,
337 InOutIndices& curIndices,
339 InIndices
const& newIndices,
340 std::function<
void(
const size_t,
const size_t,
const size_t)> cb =
341 std::function<
void(
const size_t,
const size_t,
const size_t)>())
343 static_assert(std::is_same<
typename std::remove_const<typename InOutIndices::value_type>::type,
344 typename std::remove_const<typename InIndices::value_type>::type>::value,
345 "Expected views to have same value type");
348 using ordinal =
typename InOutIndices::value_type;
349 auto numInserted = impl::insert_crs_indices(row, rowPtrs, curIndices,
350 numAssigned, newIndices, [](ordinal
const idx) {
return idx; }, cb);
354 template <
class Po
inters,
class InOutIndices,
class InIndices>
357 typename Pointers::value_type
const row,
358 Pointers
const& rowPtrs,
359 InOutIndices& curIndices,
361 InIndices
const& newIndices,
362 std::function<
typename InOutIndices::value_type(
const typename InIndices::value_type)> map,
363 std::function<
void(
const size_t,
const size_t,
const size_t)> cb =
364 std::function<
void(
const size_t,
const size_t,
const size_t)>())
366 auto numInserted = impl::insert_crs_indices(row, rowPtrs, curIndices,
367 numAssigned, newIndices, map, cb);
401 template <
class Po
inters,
class Indices1,
class Indices2,
class Callback>
404 typename Pointers::value_type
const row,
405 Pointers
const& rowPtrs,
406 Indices1
const& curIndices,
407 Indices2
const& newIndices,
410 static_assert(std::is_same<
typename std::remove_const<typename Indices1::value_type>::type,
411 typename std::remove_const<typename Indices2::value_type>::type>::value,
412 "Expected views to have same value type");
414 using ordinal =
typename Indices2::value_type;
415 auto numFound = impl::find_crs_indices(row, rowPtrs, curIndices, newIndices,
416 [=](ordinal ind){
return ind; }, cb);
420 template <
class Po
inters,
class Indices1,
class Indices2,
class IndexMap,
class Callback>
423 typename Pointers::value_type
const row,
424 Pointers
const& rowPtrs,
425 Indices1
const& curIndices,
426 Indices2
const& newIndices,
430 return impl::find_crs_indices(row, rowPtrs, curIndices, newIndices, map, cb);
436 #endif // TPETRA_DETAILS_CRSUTILS_HPP
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
size_t insertCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, InOutIndices &curIndices, size_t &numAssigned, InIndices const &newIndices, std::function< void(const size_t, const size_t, const size_t)> cb=std::function< void(const size_t, const size_t, const size_t)>())
Insert new indices in to current list of indices.
void padCrsArrays(RowPtr &rowPtrBeg, RowPtr &rowPtrEnd, Indices &indices, const Padding &padding)
Determine if the row pointers and indices arrays need to be resized to accommodate new entries...
size_t findCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, Indices1 const &curIndices, Indices2 const &newIndices, Callback &&cb)
Finds offsets in to current list of indices.