Basix 0.10.0.0

Home     Installation     Demos     C++ docs     Python docs

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 <cstdint>
11 #include <span>
12 #include <tuple>
13 #include <type_traits>
14 #include <vector>
15 
18 {
19 namespace impl
20 {
23 template <typename T, typename = void>
24 struct scalar_value_type
25 {
27  typedef T value_type;
28 };
30 template <typename T>
31 struct scalar_value_type<T, std::void_t<typename T::value_type>>
32 {
33  typedef typename T::value_type value_type;
34 };
36 template <typename T>
37 using scalar_value_type_t = typename scalar_value_type<T>::value_type;
38 } // namespace impl
39 
84 void prepare_permutation(std::span<std::size_t> perm);
85 
136 template <typename E>
137 void apply_permutation(std::span<const std::size_t> perm, std::span<E> data,
138  std::size_t offset = 0, std::size_t n = 1)
139 {
140  for (std::size_t i = 0; i < perm.size(); ++i)
141  for (std::size_t b = 0; b < n; ++b)
142  std::swap(data[n * (offset + i) + b], data[n * (offset + perm[i]) + b]);
143 }
144 
146 template <typename E>
147 void apply_permutation_mapped(std::span<const std::size_t> perm,
148  std::span<E> data, std::span<const int> emap,
149  std::size_t n = 1)
150 {
151  for (std::size_t i = 0; i < perm.size(); ++i)
152  for (std::size_t b = 0; b < n; ++b)
153  std::swap(data[n * emap[i] + b], data[n * emap[perm[i]] + b]);
154 }
155 
164 template <typename E>
165 void apply_inv_permutation_right(std::span<const std::size_t> perm,
166  std::span<E> data, std::size_t offset = 0,
167  std::size_t n = 1)
168 {
169  const std::size_t dim = perm.size();
170  const std::size_t data_size = (data.size() + (dim < n ? n - dim : 0)) / n;
171  for (std::size_t b = 0; b < n; ++b)
172  {
173  for (std::size_t i = 0; i < dim; ++i)
174  {
175  std::swap(data[data_size * b + offset + i],
176  data[data_size * b + offset + perm[i]]);
177  }
178  }
179 }
180 
197 template <std::floating_point T>
198 std::vector<std::size_t>
199 prepare_matrix(std::pair<std::vector<T>, std::array<std::size_t, 2>>& A)
200 {
201  return math::transpose_lu<T>(A);
202 }
203 
235 template <typename T, typename E>
237  std::span<const std::size_t> v_size_t,
238  MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
239  const T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
240  M,
241  std::span<E> data, std::size_t offset = 0, std::size_t n = 1)
242 {
243  using U = typename impl::scalar_value_type_t<E>;
244 
245  const std::size_t dim = v_size_t.size();
246  apply_permutation(v_size_t, data, offset, n);
247  for (std::size_t b = 0; b < n; ++b)
248  {
249  for (std::size_t i = 0; i < dim; ++i)
250  {
251  for (std::size_t j = i + 1; j < dim; ++j)
252  {
253  data[n * (offset + i) + b]
254  += static_cast<U>(M(i, j)) * data[n * (offset + j) + b];
255  }
256  }
257 
258  for (std::size_t i = 1; i <= dim; ++i)
259  {
260  data[n * (offset + dim - i) + b] *= static_cast<U>(M(dim - i, dim - i));
261  for (std::size_t j = 0; j < dim - i; ++j)
262  {
263  data[n * (offset + dim - i) + b]
264  += static_cast<U>(M(dim - i, j)) * data[n * (offset + j) + b];
265  }
266  }
267  }
268 }
269 
278 template <typename T, typename E>
280  std::span<const std::size_t> v_size_t,
281  MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
282  const T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
283  M,
284  std::span<E> data, std::size_t offset = 0, std::size_t n = 1)
285 {
286  using U = typename impl::scalar_value_type_t<E>;
287 
288  const std::size_t dim = v_size_t.size();
289  const std::size_t data_size = (data.size() + (dim < n ? n - dim : 0)) / n;
290  apply_inv_permutation_right(v_size_t, data, offset, n);
291  for (std::size_t b = 0; b < n; ++b)
292  {
293  for (std::size_t i = 0; i < dim; ++i)
294  {
295  for (std::size_t j = i + 1; j < dim; ++j)
296  {
297  data[data_size * b + offset + i]
298  += static_cast<U>(M(i, j)) * data[data_size * b + offset + j];
299  }
300  }
301  for (std::size_t i = 1; i <= dim; ++i)
302  {
303  data[data_size * b + offset + dim - i]
304  *= static_cast<U>(M(dim - i, dim - i));
305  for (std::size_t j = 0; j < dim - i; ++j)
306  {
307  data[data_size * b + offset + dim - i]
308  += static_cast<U>(M(dim - i, j)) * data[data_size * b + offset + j];
309  }
310  }
311  }
312 }
313 
314 } // namespace basix::precompute
Matrix and permutation pre-computation.
Definition: precompute.h:18
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:199
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:279
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:137
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:165
void prepare_permutation(std::span< std::size_t > perm)
Prepare a permutation.
Definition: precompute.cpp:10
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:236
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:147