DOLFINx 0.12.0.0
DOLFINx C++
Loading...
Searching...
No Matches
matrix_csr_impl.h
1// Copyright (C) 2021-2023 Garth N. Wells and Chris N. Richardson
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include <cassert>
10#include <concepts>
11#include <numeric>
12#include <span>
13#include <type_traits>
14#include <utility>
15#include <vector>
16
17namespace dolfinx::la
18{
19namespace impl
20{
22template <typename T>
23struct is_integral_constant : std::false_type
24{
25};
26template <std::integral U, U N>
27struct is_integral_constant<std::integral_constant<U, N>> : std::true_type
28{
29};
30
34template <typename T>
35concept BlockSizeArg = std::integral<std::remove_cvref_t<T>>
36 or is_integral_constant<std::remove_cvref_t<T>>::value;
38
68template <int BS0, int BS1, typename OP, typename U, typename V, typename W,
69 typename X, typename Y>
70void insert_csr(U&& data, const V& cols, const W& row_ptr, const X& x,
71 const Y& xrows, const Y& xcols, OP op,
72 [[maybe_unused]] typename Y::value_type num_rows)
73{
74 const std::size_t nc = xcols.size();
75 assert(x.size() == xrows.size() * xcols.size() * BS0 * BS1);
76 for (std::size_t r = 0; r < xrows.size(); ++r)
77 {
78 // Row index and current data row
79 auto row = xrows[r];
80 using T = typename X::value_type;
81 const T* xr = x.data() + r * nc * BS0 * BS1;
82
83#ifndef NDEBUG
84 if (row >= num_rows)
85 throw std::runtime_error("Local row out of range");
86#endif
87 // Columns indices for row
88 auto cit0 = std::next(cols.begin(), row_ptr[row]);
89 auto cit1 = std::next(cols.begin(), row_ptr[row + 1]);
90 for (std::size_t c = 0; c < nc; ++c)
91 {
92 // Find position of column index
93 auto it = std::lower_bound(cit0, cit1, xcols[c]);
94 if (it == cit1 or *it != xcols[c])
95 throw std::runtime_error("Entry not in sparsity");
96
97 std::size_t d = std::ranges::distance(cols.begin(), it);
98 std::size_t di = d * BS0 * BS1;
99 std::size_t xi = c * BS1;
100 assert(di < data.size());
101 for (int i = 0; i < BS0; ++i)
102 {
103 for (int j = 0; j < BS1; ++j)
104 op(data[di + j], xr[xi + j]);
105 di += BS1;
106 xi += nc * BS1;
107 }
108 }
109 }
110}
111
133template <int BS0, int BS1, typename OP, typename U, typename V, typename W,
134 typename X, typename Y>
135void insert_blocked_csr(U&& data, const V& cols, const W& row_ptr, const X& x,
136 const Y& xrows, const Y& xcols, OP op,
137 [[maybe_unused]] typename Y::value_type num_rows)
138{
139 const std::size_t nc = xcols.size();
140 assert(x.size() == xrows.size() * xcols.size() * BS0 * BS1);
141 for (std::size_t r = 0; r < xrows.size(); ++r)
142 {
143 // Row index and current data row
144 auto row = xrows[r] * BS0;
145#ifndef NDEBUG
146 if (row >= num_rows)
147 throw std::runtime_error("Local row out of range");
148#endif
149
150 for (int i = 0; i < BS0; ++i)
151 {
152 using T = typename X::value_type;
153 const T* xr = x.data() + (r * BS0 + i) * nc * BS1;
154
155 // Columns indices for row
156 auto cit0 = std::next(cols.begin(), row_ptr[row + i]);
157 auto cit1 = std::next(cols.begin(), row_ptr[row + i + 1]);
158 for (std::size_t c = 0; c < nc; ++c)
159 {
160 // Find position of column index
161 auto it = std::lower_bound(cit0, cit1, xcols[c] * BS1);
162 if (it == cit1 or *it != xcols[c] * BS1)
163 throw std::runtime_error("Entry not in sparsity");
164
165 std::size_t d = std::ranges::distance(cols.begin(), it);
166 assert(d < data.size());
167 std::size_t xi = c * BS1;
168 for (int j = 0; j < BS1; ++j)
169 op(data[d + j], xr[xi + j]);
170 }
171 }
172 }
173}
174
194template <typename OP, typename U, typename V, typename W, typename X,
195 typename Y>
196void insert_nonblocked_csr(U&& data, const V& cols, const W& row_ptr,
197 const X& x, const Y& xrows, const Y& xcols, OP op,
198 [[maybe_unused]] typename Y::value_type num_rows,
199 int bs0, int bs1)
200{
201 const std::size_t nc = xcols.size();
202 const int nbs = bs0 * bs1;
203
204 assert(x.size() == xrows.size() * xcols.size());
205 for (std::size_t r = 0; r < xrows.size(); ++r)
206 {
207 // Row index and current data row
208 auto rdiv = std::div(xrows[r], bs0);
209 using T = typename X::value_type;
210 const T* xr = x.data() + r * nc;
211
212#ifndef NDEBUG
213 if (rdiv.quot >= num_rows)
214 throw std::runtime_error("Local row out of range");
215#endif
216 // Columns indices for row
217 auto cit0 = std::next(cols.begin(), row_ptr[rdiv.quot]);
218 auto cit1 = std::next(cols.begin(), row_ptr[rdiv.quot + 1]);
219 for (std::size_t c = 0; c < nc; ++c)
220 {
221 // Find position of column index
222 auto cdiv = std::div(xcols[c], bs1);
223 auto it = std::lower_bound(cit0, cit1, cdiv.quot);
224 if (it == cit1 or *it != cdiv.quot)
225 throw std::runtime_error("Entry not in sparsity");
226
227 std::size_t d = std::ranges::distance(cols.begin(), it);
228 std::size_t di = d * nbs + rdiv.rem * bs1 + cdiv.rem;
229 assert(di < data.size());
230 op(data[di], xr[c]);
231 }
232 }
233}
234
260template <typename T>
261void spmv(std::span<const T> values, std::span<const std::int64_t> row_begin,
262 std::span<const std::int64_t> row_end,
263 std::span<const std::int32_t> indices, std::span<const T> x,
264 std::span<T> y, BlockSizeArg auto bs0, BlockSizeArg auto bs1)
265{
266 assert(row_begin.size() == row_end.size());
267 // Block layout: row-major within each block. The element at row-offset
268 // k0 (∈ [0, bs0)) and column-offset k1 (∈ [0, bs1)) of block entry j
269 // is stored at values[j * bs0 * bs1 + k0 * bs1 + k1].
270 for (decltype(+bs0) k0 = 0; k0 < bs0; ++k0)
271 {
272 for (std::size_t i = 0; i < row_begin.size(); i++)
273 {
274 T vi{0};
275 for (std::int64_t j = row_begin[i]; j < row_end[i]; j++)
276 {
277 for (decltype(+bs1) k1 = 0; k1 < bs1; ++k1)
278 {
279 vi += values[j * bs0 * bs1 + k0 * bs1 + k1]
280 * x[indices[j] * bs1 + k1];
281 }
282 }
283
284 y[i * bs0 + k0] += vi;
285 }
286 }
287}
288
320template <typename T>
321void spmvT(std::span<const T> values, std::span<const std::int64_t> row_begin,
322 std::span<const std::int64_t> row_end,
323 std::span<const std::int32_t> indices, std::span<const T> x,
324 std::span<T> y, BlockSizeArg auto bs0, BlockSizeArg auto bs1)
325{
326 assert(row_begin.size() == row_end.size());
327
328 // Block layout: row-major within each block.
329 for (decltype(+bs0) k0 = 0; k0 < bs0; ++k0)
330 {
331 for (std::size_t i = 0; i < row_begin.size(); i++)
332 {
333 const T xval = x[i * bs0 + k0];
334 for (std::int64_t j = row_begin[i]; j < row_end[i]; j++)
335 {
336 for (decltype(+bs1) k1 = 0; k1 < bs1; ++k1)
337 {
338 y[indices[j] * bs1 + k1]
339 += values[j * bs0 * bs1 + k0 * bs1 + k1] * xval;
340 }
341 }
342 }
343 }
344}
345
346} // namespace impl
347} // namespace dolfinx::la
Fetch the rows of B that correspond to the ghost columns of A.
Definition matmul.h:36
void insert_csr(U &&data, const V &cols, const W &row_ptr, const X &x, const Y &xrows, const Y &xcols, OP op, typename Y::value_type num_rows)
Incorporate data into a CSR matrix.
Definition matrix_csr_impl.h:70
void spmv(std::span< const T > values, std::span< const std::int64_t > row_begin, std::span< const std::int64_t > row_end, std::span< const std::int32_t > indices, std::span< const T > x, std::span< T > y, BlockSizeArg auto bs0, BlockSizeArg auto bs1)
Sparse matrix-vector product implementation.
Definition matrix_csr_impl.h:261
void insert_blocked_csr(U &&data, const V &cols, const W &row_ptr, const X &x, const Y &xrows, const Y &xcols, OP op, typename Y::value_type num_rows)
Incorporate blocked data with given block sizes into a non-blocked MatrixCSR.
Definition matrix_csr_impl.h:135
void insert_nonblocked_csr(U &&data, const V &cols, const W &row_ptr, const X &x, const Y &xrows, const Y &xcols, OP op, typename Y::value_type num_rows, int bs0, int bs1)
Incorporate non-blocked data into a blocked matrix (data block size=1).
Definition matrix_csr_impl.h:196
void spmvT(std::span< const T > values, std::span< const std::int64_t > row_begin, std::span< const std::int64_t > row_end, std::span< const std::int32_t > indices, std::span< const T > x, std::span< T > y, BlockSizeArg auto bs0, BlockSizeArg auto bs1)
Sparse matrix-vector transpose product implementation.
Definition matrix_csr_impl.h:321
Linear algebra interface.
Definition dolfinx_la.h:7