IgANet
IGAnets - Isogeometric Analysis Networks
Loading...
Searching...
No Matches
matrix.hpp
Go to the documentation of this file.
1
15#pragma once
16
17#include <iganet/core/core.hpp>
19
20namespace iganet::utils {
21
31 inline torch::Tensor to_sparseCsrTensor(const torch::Tensor& col_indices,
32 const torch::Tensor& values,
33 const torch::IntArrayRef& size) {
34
35 TORCH_CHECK(size.size() == 2,
36 "Sparse CSR matrix size must contain two entries");
37
38 TORCH_CHECK(col_indices.dim() == 2,
39 "col_indices must be a two-dimensional tensor");
40
41 TORCH_CHECK(values.sizes() == col_indices.sizes(),
42 "values and col_indices must have identical shapes");
43
44 TORCH_CHECK(
45 col_indices.scalar_type() == torch::kInt32 ||
46 col_indices.scalar_type() == torch::kInt64,
47 "col_indices must have dtype torch::kInt32 or torch::kInt64");
48
49 TORCH_CHECK(values.device() == col_indices.device(),
50 "values and col_indices must be on the same device");
51
52 const int64_t populated_rows = col_indices.size(0);
53 const int64_t entries_per_row = col_indices.size(1);
54 const int64_t matrix_rows = size[0];
55
56 TORCH_CHECK(
57 populated_rows <= matrix_rows,
58 "col_indices contains ", populated_rows,
59 " rows, but the requested matrix has only ", matrix_rows, " rows");
60
61 // CSR requires exactly matrix_rows + 1 row pointers.
62 auto crow_indices =
63 torch::arange(
64 populated_rows + 1,
65 col_indices.options())
66 * entries_per_row;
67
68 // Append empty trailing rows. Each empty row repeats the final
69 // accumulated number of nonzero entries.
70 const int64_t empty_rows = matrix_rows - populated_rows;
71
72 if (empty_rows > 0) {
73 auto padding = crow_indices[-1].repeat({empty_rows});
74 crow_indices = torch::cat({crow_indices, padding});
75 }
76
77 return torch::sparse_csr_tensor(crow_indices.flatten(),
78 col_indices.flatten(),
79 values.flatten(),
80 size,
81 values.options().layout(torch::kSparseCsr));
82 }
83
96 template<std::size_t N>
97 inline torch::Tensor to_sparseCsrTensor(const utils::TensorArray<N>& col_indices,
98 const std::array<int64_t, N>& nbasfuncs,
99 const torch::Tensor& values,
100 const torch::IntArrayRef& size) {
101
102 // Compute absolut column indices
103 torch::Tensor col_indices_;
104 if constexpr (N == 1)
105 col_indices_ = col_indices[0];
106 else if constexpr (N == 2)
107 col_indices_ = (col_indices[0].unsqueeze(2) +
108 nbasfuncs[0]*col_indices[1].unsqueeze(1))
109 .permute({0, 2, 1}).reshape({col_indices[0].size(0), -1});
110 else if constexpr (N == 3)
111 col_indices_ = (col_indices[0].unsqueeze(2).unsqueeze(3) +
112 nbasfuncs[0]*col_indices[1].unsqueeze(1).unsqueeze(3) +
113 nbasfuncs[0]*nbasfuncs[1]*col_indices[2].unsqueeze(1).unsqueeze(2))
114 .permute({0, 3, 2, 1}).reshape({col_indices[0].size(0), -1});
115 else
116 throw std::runtime_error("Invalid dimension");
117
118 return to_sparseCsrTensor(col_indices_, values, size);
119 }
120
138 template<std::size_t N>
139 inline torch::Tensor to_sparseCsrTensor(const utils::TensorArray<N>& knot_indices,
140 const std::array<short, N>& degrees,
141 const std::array<int64_t, N>& nbasfuncs,
142 const torch::Tensor& values,
143 const torch::IntArrayRef& size) {
144
145 // Apply offsets to indices
146 std::array<torch::Tensor, N> col_indices;
147 for (std::size_t i = 0; i < N; ++i) {
148 col_indices[i] =
149 (knot_indices[i].unsqueeze(0) +
150 torch::arange(-degrees[i],
151 1,
152 knot_indices[i].options()
153 ).unsqueeze(1)).t();
154 }
155
156 return to_sparseCsrTensor(col_indices, nbasfuncs, values, size);
157 }
158} // namespace iganet::utils
Core components.
Definition blocktensor.hpp:24
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:26
torch::Tensor to_sparseCsrTensor(const torch::Tensor &col_indices, const torch::Tensor &values, const torch::IntArrayRef &size)
Constructs a sparse-CSR matrix from the column indices, matrix values and the matrix size.
Definition matrix.hpp:31
TensorArray utility functions.