55using HostTag = backend::CpuTag;
71 bool m_indices_sorted;
76 void copy_indices_to_device(
const std::vector<size_t> &
sorted_indices) {
77 if constexpr (std::is_same_v<BackendTag, backend::CpuTag>) {
81#if defined(OpenPFC_ENABLE_CUDA)
82 else if constexpr (std::is_same_v<BackendTag, backend::CudaTag>) {
87 throw std::runtime_error(
"CUDA copy failed: " +
111 m_indices_sorted =
true;
118 m_indices_sorted =
true;
136 throw std::runtime_error(
"SparseVector: indices and data size mismatch");
142 m_indices_sorted =
true;
147 std::vector<std::pair<size_t, T>>
pairs;
148 pairs.reserve(m_size);
149 for (
size_t i = 0;
i < m_size; ++
i) {
153 [](
const auto &
a,
const auto &
b) { return a.first < b.first; });
163 m_indices_sorted =
true;
177 size_t size()
const {
return m_size; }
182 bool empty()
const {
return m_size == 0; }
204 void copy_data_to_device(
const std::vector<T> &
host_data) {
205 if constexpr (std::is_same_v<BackendTag, backend::CpuTag>) {
209#if defined(OpenPFC_ENABLE_CUDA)
210 else if constexpr (std::is_same_v<BackendTag, backend::CudaTag>) {
215 throw std::runtime_error(
"CUDA copy failed: " +
226template <
typename BackendTag,
typename T>
229 return std::is_same_v<BackendTag, backend::CpuTag>;
235namespace sparsevector {
238using HostTag = backend::CpuTag;
243template <
typename T,
typename BackendTag = backend::CpuTag>
244core::SparseVector<BackendTag, T> create(
size_t size) {
245 return core::SparseVector<BackendTag, T>(size);
251template <
typename T,
typename BackendTag = backend::CpuTag>
252core::SparseVector<BackendTag, T>
create(std::initializer_list<size_t> indices) {
253 return core::SparseVector<BackendTag, T>(std::vector<size_t>(indices));
259template <
typename T,
typename BackendTag = backend::CpuTag>
260core::SparseVector<BackendTag, T>
create(
const std::vector<size_t> &indices) {
261 return core::SparseVector<BackendTag, T>(indices);
267template <
typename T,
typename BackendTag = backend::CpuTag>
268core::SparseVector<BackendTag, T>
create(
const std::vector<size_t> &indices,
269 const std::vector<T> &data) {
270 return core::SparseVector<BackendTag, T>(indices, data);
276template <
typename BackendTag,
typename T>
277size_t get_size(
const core::SparseVector<BackendTag, T> &vec) {
287template <
typename BackendTag,
typename T>
288void set_index(core::SparseVector<BackendTag, T> &vec,
289 const std::vector<size_t> &indices) {
290 static_assert(std::is_same_v<BackendTag, backend::CpuTag>,
291 "set_index only available for CPU");
294 core::SparseVector<BackendTag, T> new_vec(indices);
295 vec = std::move(new_vec);
301template <
typename BackendTag,
typename T>
302void set_data(core::SparseVector<BackendTag, T> &vec,
const std::vector<T> &data) {
303 static_assert(std::is_same_v<BackendTag, backend::CpuTag>,
304 "set_data only available for CPU");
305 if (data.size() != vec.size()) {
306 throw std::runtime_error(
"set_data: size mismatch");
309 T *data_ptr = vec.data().data();
310 std::copy(data.begin(), data.end(), data_ptr);
316template <
typename BackendTag,
typename T>
317std::vector<size_t> get_index(
const core::SparseVector<BackendTag, T> &vec) {
318 static_assert(std::is_same_v<BackendTag, backend::CpuTag>,
319 "get_index only available for CPU");
320 std::vector<size_t> result(vec.size());
321 std::copy(vec.indices().data(), vec.indices().data() + vec.size(), result.begin());
328template <
typename BackendTag,
typename T>
329std::vector<T> get_data(
const core::SparseVector<BackendTag, T> &vec) {
330 static_assert(std::is_same_v<BackendTag, backend::CpuTag>,
331 "get_data only available for CPU");
332 std::vector<T> result(vec.size());
333 std::copy(vec.data().data(), vec.data().data() + vec.size(), result.begin());
340template <
typename BackendTag,
typename T>
341size_t get_index(
const core::SparseVector<BackendTag, T> &vec,
size_t i) {
342 static_assert(std::is_same_v<BackendTag, backend::CpuTag>,
343 "get_index only available for CPU");
344 return vec.indices().data()[i];
350template <
typename BackendTag,
typename T>
351T get_data(
const core::SparseVector<BackendTag, T> &vec,
size_t i) {
352 static_assert(std::is_same_v<BackendTag, backend::CpuTag>,
353 "get_data only available for CPU");
354 return vec.data().data()[i];
360template <
typename BackendTag,
typename T>
361std::pair<size_t, T> get_entry(
const core::SparseVector<BackendTag, T> &vec,
363 static_assert(std::is_same_v<BackendTag, backend::CpuTag>,
364 "get_entry only available for CPU");
365 return {vec.indices().data()[i], vec.data().data()[i]};
Sparse vector for indexed data views.
Definition sparse_vector.hpp:66
size_t size() const
Get number of entries.
Definition sparse_vector.hpp:177
bool empty() const
Check if empty.
Definition sparse_vector.hpp:182
SparseVector(const std::vector< size_t > &indices, const std::vector< T > &data)
Construct SparseVector with indices and initial data.
Definition sparse_vector.hpp:133
SparseVector(const std::vector< size_t > &indices)
Construct SparseVector with given indices.
Definition sparse_vector.hpp:106
const DataBuffer< BackendTag, size_t > & indices() const
Get indices buffer (read-only)
Definition sparse_vector.hpp:187
bool is_sorted() const
Check if indices are sorted.
Definition sparse_vector.hpp:198
SparseVector(size_t size)
Construct empty SparseVector.
Definition sparse_vector.hpp:99
DataBuffer< BackendTag, T > & data()
Get data buffer (read-write)
Definition sparse_vector.hpp:192
Backend-agnostic memory buffer with tag-based dispatch.
auto create(const World< T > &world, const heffte::box3d< int > &box)
Construct a new World object from an existing one and a box.
Definition decomposition.hpp:62
bool on_host(const SparseVector< BackendTag, T > &vec)
Check if SparseVector is on host.
Definition sparse_vector.hpp:227
Represents the global simulation domain (the "world").
Definition world.hpp:91