Basix 0.10.0.0

Home     Installation     Demos     C++ docs     Python docs

maps.h
1 // Copyright (c) 2021-2022 Matthew Scroggs and Garth N. Wells
2 // FEniCS Project
3 // SPDX-License-Identifier: MIT
4 
5 #pragma once
6 
7 #include "mdspan.hpp"
8 #include "types.h"
9 #include <algorithm>
10 #include <stdexcept>
11 #include <type_traits>
12 
14 namespace basix::maps
15 {
16 
17 namespace impl
18 {
21 template <typename T, typename = void>
22 struct scalar_value_type
23 {
25  typedef T value_type;
26 };
28 template <typename T>
29 struct scalar_value_type<T, std::void_t<typename T::value_type>>
30 {
31  typedef typename T::value_type value_type;
32 };
34 template <typename T>
35 using scalar_value_type_t = typename scalar_value_type<T>::value_type;
36 } // namespace impl
37 
39 enum class type
40 {
41  identity = 0,
42  L2Piola = 1,
43  covariantPiola = 2,
44  contravariantPiola = 3,
45  doubleCovariantPiola = 4,
46  doubleContravariantPiola = 5,
47 };
48 
50 template <typename O, typename P, typename Q, typename R>
51 void l2_piola(O&& r, const P& U, const Q& /*J*/, double detJ, const R& /*K*/)
52 {
53  assert(U.extent(0) == r.extent(0));
54  assert(U.extent(1) == r.extent(1));
55  for (std::size_t i = 0; i < U.extent(0); ++i)
56  for (std::size_t j = 0; j < U.extent(1); ++j)
57  r(i, j) = U(i, j) / detJ;
58 }
59 
61 template <typename O, typename P, typename Q, typename R>
62 void covariant_piola(O&& r, const P& U, const Q& /*J*/, double /*detJ*/,
63  const R& K)
64 {
65  using T = typename std::decay_t<O>::value_type;
66  using Z = typename impl::scalar_value_type_t<T>;
67  for (std::size_t p = 0; p < U.extent(0); ++p)
68  {
69  // r_p = K^T U_p, where p indicates the p-th row
70  for (std::size_t i = 0; i < r.extent(1); ++i)
71  {
72  T acc = 0;
73  for (std::size_t k = 0; k < K.extent(0); ++k)
74  acc += static_cast<Z>(K(k, i)) * U(p, k);
75  r(p, i) = acc;
76  }
77  }
78 }
79 
81 template <typename O, typename P, typename Q, typename R>
82 void contravariant_piola(O&& r, const P& U, const Q& J, double detJ,
83  const R& /*K*/)
84 {
85  using T = typename std::decay_t<O>::value_type;
86  using Z = typename impl::scalar_value_type_t<T>;
87  for (std::size_t p = 0; p < U.extent(0); ++p)
88  {
89  for (std::size_t i = 0; i < r.extent(1); ++i)
90  {
91  T acc = 0;
92  for (std::size_t k = 0; k < J.extent(1); ++k)
93  acc += static_cast<Z>(J(i, k)) * U(p, k);
94  r(p, i) = acc;
95  }
96  }
97 
98  std::transform(r.data_handle(), r.data_handle() + r.size(), r.data_handle(),
99  [detJ](auto ri) { return ri / static_cast<Z>(detJ); });
100 }
101 
103 template <typename O, typename P, typename Q, typename R>
104 void double_covariant_piola(O&& r, const P& U, const Q& J, double /*detJ*/,
105  const R& K)
106 {
107  using T = typename std::decay_t<O>::value_type;
108  using Z = typename impl::scalar_value_type_t<T>;
109  for (std::size_t p = 0; p < U.extent(0); ++p)
110  {
111  md::mdspan<const T, md::dextents<std::size_t, 2>> _U(
112  U.data_handle() + p * U.extent(1), J.extent(1), J.extent(1));
113  md::mdspan<T, md::dextents<std::size_t, 2>> _r(
114  r.data_handle() + p * r.extent(1), K.extent(1), K.extent(1));
115  // _r = K^T _U K
116  for (std::size_t i = 0; i < _r.extent(0); ++i)
117  {
118  for (std::size_t j = 0; j < _r.extent(1); ++j)
119  {
120  T acc = 0;
121  for (std::size_t k = 0; k < K.extent(0); ++k)
122  for (std::size_t l = 0; l < _U.extent(1); ++l)
123  acc += static_cast<Z>(K(k, i)) * _U(k, l) * static_cast<Z>(K(l, j));
124  _r(i, j) = acc;
125  }
126  }
127  }
128 }
129 
131 template <typename O, typename P, typename Q, typename R>
132 void double_contravariant_piola(O&& r, const P& U, const Q& J, double detJ,
133  const R& /*K*/)
134 {
135  using T = typename std::decay_t<O>::value_type;
136  using Z = typename impl::scalar_value_type_t<T>;
137  for (std::size_t p = 0; p < U.extent(0); ++p)
138  {
139  md::mdspan<const T, md::dextents<std::size_t, 2>> _U(
140  U.data_handle() + p * U.extent(1), J.extent(1), J.extent(1));
141  md::mdspan<T, md::dextents<std::size_t, 2>> _r(
142  r.data_handle() + p * r.extent(1), J.extent(0), J.extent(0));
143 
144  // _r = J U J^T
145  for (std::size_t i = 0; i < _r.extent(0); ++i)
146  {
147  for (std::size_t j = 0; j < _r.extent(1); ++j)
148  {
149  T acc = 0;
150  for (std::size_t k = 0; k < J.extent(1); ++k)
151  for (std::size_t l = 0; l < _U.extent(1); ++l)
152  acc += static_cast<Z>(J(i, k)) * _U(k, l) * static_cast<Z>(J(j, l));
153  _r(i, j) = acc;
154  }
155  }
156  }
157 
158  std::transform(r.data_handle(), r.data_handle() + r.size(), r.data_handle(),
159  [detJ](auto ri) { return ri / static_cast<Z>(detJ * detJ); });
160 }
161 
162 } // namespace basix::maps
Information about finite element maps.
Definition: maps.h:15
void l2_piola(O &&r, const P &U, const Q &, double detJ, const R &)
L2 Piola map.
Definition: maps.h:51
void covariant_piola(O &&r, const P &U, const Q &, double, const R &K)
Covariant Piola map.
Definition: maps.h:62
void contravariant_piola(O &&r, const P &U, const Q &J, double detJ, const R &)
Contravariant Piola map.
Definition: maps.h:82
void double_contravariant_piola(O &&r, const P &U, const Q &J, double detJ, const R &)
Double contravariant Piola map.
Definition: maps.h:132
void double_covariant_piola(O &&r, const P &U, const Q &J, double, const R &K)
Double covariant Piola map.
Definition: maps.h:104
type
Map type.
Definition: maps.h:40