Basix 0.8.0

Home     Installation     Demos     C++ docs     Python docs

Loading...
Searching...
No Matches
precompute.h
1// Copyright (c) 2020 Matthew Scroggs
2// FEniCS Project
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include "math.h"
8#include "mdspan.hpp"
9#include <concepts>
10#include <span>
11#include <tuple>
12#include <type_traits>
13#include <vector>
14
17{
18namespace impl
19{
22template <typename T, typename = void>
23struct scalar_value_type
24{
26 typedef T value_type;
27};
29template <typename T>
30struct scalar_value_type<T, std::void_t<typename T::value_type>>
31{
32 typedef typename T::value_type value_type;
33};
35template <typename T>
36using scalar_value_type_t = typename scalar_value_type<T>::value_type;
37} // namespace impl
38
88void prepare_permutation(std::span<std::size_t> perm);
89
143template <typename E>
144void apply_permutation(std::span<const std::size_t> perm, std::span<E> data,
145 std::size_t offset = 0, std::size_t n = 1)
146{
147 for (std::size_t i = 0; i < perm.size(); ++i)
148 for (std::size_t b = 0; b < n; ++b)
149 std::swap(data[n * (offset + i) + b], data[n * (offset + perm[i]) + b]);
150}
151
153template <typename E>
154void apply_permutation_mapped(std::span<const std::size_t> perm,
155 std::span<E> data, std::span<const int> emap,
156 std::size_t n = 1)
157{
158 for (std::size_t i = 0; i < perm.size(); ++i)
159 for (std::size_t b = 0; b < n; ++b)
160 std::swap(data[n * emap[i] + b], data[n * emap[perm[i]] + b]);
161}
162
171template <typename E>
172void apply_inv_permutation_right(std::span<const std::size_t> perm,
173 std::span<E> data, std::size_t offset = 0,
174 std::size_t n = 1)
175{
176 const std::size_t dim = perm.size();
177 const std::size_t data_size = (data.size() + (dim < n ? n - dim : 0)) / n;
178 for (std::size_t b = 0; b < n; ++b)
179 {
180 for (std::size_t i = 0; i < dim; ++i)
181 {
182 std::swap(data[data_size * b + offset + i],
183 data[data_size * b + offset + perm[i]]);
184 }
185 }
186}
187
204template <std::floating_point T>
205std::vector<std::size_t>
206prepare_matrix(std::pair<std::vector<T>, std::array<std::size_t, 2>>& A)
207{
208 return math::transpose_lu<T>(A);
209}
210
242template <typename T, typename E>
244 std::span<const std::size_t> v_size_t,
245 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
246 const T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
247 M,
248 std::span<E> data, std::size_t offset = 0, std::size_t n = 1)
249{
250 using U = typename impl::scalar_value_type_t<E>;
251
252 const std::size_t dim = v_size_t.size();
253 apply_permutation(v_size_t, data, offset, n);
254 for (std::size_t b = 0; b < n; ++b)
255 {
256 for (std::size_t i = 0; i < dim; ++i)
257 {
258 for (std::size_t j = i + 1; j < dim; ++j)
259 {
260 data[n * (offset + i) + b]
261 += static_cast<U>(M(i, j)) * data[n * (offset + j) + b];
262 }
263 }
264 for (std::size_t i = 1; i <= dim; ++i)
265 {
266 data[n * (offset + dim - i) + b] *= static_cast<U>(M(dim - i, dim - i));
267 for (std::size_t j = 0; j < dim - i; ++j)
268 {
269 data[n * (offset + dim - i) + b]
270 += static_cast<U>(M(dim - i, j)) * data[n * (offset + j) + b];
271 }
272 }
273 }
274}
275
284template <typename T, typename E>
286 std::span<const std::size_t> v_size_t,
287 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
288 const T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
289 M,
290 std::span<E> data, std::size_t offset = 0, std::size_t n = 1)
291{
292 using U = typename impl::scalar_value_type_t<E>;
293
294 const std::size_t dim = v_size_t.size();
295 const std::size_t data_size = (data.size() + (dim < n ? n - dim : 0)) / n;
296 apply_inv_permutation_right(v_size_t, data, offset, n);
297 for (std::size_t b = 0; b < n; ++b)
298 {
299 for (std::size_t i = 0; i < dim; ++i)
300 {
301 for (std::size_t j = i + 1; j < dim; ++j)
302 {
303 data[data_size * b + offset + i]
304 += static_cast<U>(M(i, j)) * data[data_size * b + offset + j];
305 }
306 }
307 for (std::size_t i = 1; i <= dim; ++i)
308 {
309 data[data_size * b + offset + dim - i]
310 *= static_cast<U>(M(dim - i, dim - i));
311 for (std::size_t j = 0; j < dim - i; ++j)
312 {
313 data[data_size * b + offset + dim - i]
314 += static_cast<U>(M(dim - i, j)) * data[data_size * b + offset + j];
315 }
316 }
317 }
318}
319
320} // namespace basix::precompute
Matrix and permutation pre-computation.
Definition: precompute.h:17
void apply_tranpose_matrix_right(std::span< const std::size_t > v_size_t, MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< const T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents< std::size_t, 2 > > M, std::span< E > data, std::size_t offset=0, std::size_t n=1)
Apply a (precomputed) matrix to some transposed data.
Definition: precompute.h:285
std::vector< std::size_t > prepare_matrix(std::pair< std::vector< T >, std::array< std::size_t, 2 > > &A)
Prepare a square matrix.
Definition: precompute.h:206
void apply_permutation(std::span< const std::size_t > perm, std::span< E > data, std::size_t offset=0, std::size_t n=1)
Apply a (precomputed) permutation .
Definition: precompute.h:144
void apply_inv_permutation_right(std::span< const std::size_t > perm, std::span< E > data, std::size_t offset=0, std::size_t n=1)
Apply a (precomputed) permutation to some transposed data.
Definition: precompute.h:172
void prepare_permutation(std::span< std::size_t > perm)
Prepare a permutation.
Definition: precompute.cpp:10
void apply_permutation_mapped(std::span< const std::size_t > perm, std::span< E > data, std::span< const int > emap, std::size_t n=1)
Permutation of mapped data.
Definition: precompute.h:154
void apply_matrix(std::span< const std::size_t > v_size_t, MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< const T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents< std::size_t, 2 > > M, std::span< E > data, std::size_t offset=0, std::size_t n=1)
Apply a (precomputed) matrix.
Definition: precompute.h:243