Basix 0.12.0.dev0
Loading...
Searching...
No Matches
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
14namespace basix::maps
15{
16
17namespace impl
18{
21template <typename T, typename = void>
22struct scalar_value_type
23{
25 typedef T value_type;
26};
28template <typename T>
29struct scalar_value_type<T, std::void_t<typename T::value_type>>
30{
31 typedef typename T::value_type value_type;
32};
34template <typename T>
35using scalar_value_type_t = typename scalar_value_type<T>::value_type;
36} // namespace impl
37
39enum class type
40{
41 identity = 0,
42 L2Piola = 1,
43 covariantPiola = 2,
44 contravariantPiola = 3,
45 doubleCovariantPiola = 4,
46 doubleContravariantPiola = 5,
47};
48
56template <typename O, typename P, typename Q, typename R>
57void l2_piola(O&& r, const P& U, const Q& /*J*/, double detJ, const R& /*K*/)
58{
59 assert(U.extent(0) == r.extent(0));
60 assert(U.extent(1) == r.extent(1));
61 for (std::size_t i = 0; i < U.extent(0); ++i)
62 for (std::size_t j = 0; j < U.extent(1); ++j)
63 r(i, j) = U(i, j) / detJ;
64}
65
73template <typename O, typename P, typename Q, typename R>
74void covariant_piola(O&& r, const P& U, const Q& /*J*/, double /*detJ*/,
75 const R& K)
76{
77 using T = typename std::decay_t<O>::value_type;
78 using Z = typename impl::scalar_value_type_t<T>;
79 for (std::size_t p = 0; p < U.extent(0); ++p)
80 {
81 // r_p = K^T U_p, where p indicates the p-th row
82 for (std::size_t i = 0; i < r.extent(1); ++i)
83 {
84 T acc = 0;
85 for (std::size_t k = 0; k < K.extent(0); ++k)
86 acc += static_cast<Z>(K(k, i)) * U(p, k);
87 r(p, i) = acc;
88 }
89 }
90}
91
100template <typename O, typename P, typename Q, typename R>
101void contravariant_piola(O&& r, const P& U, const Q& J, double detJ,
102 const R& /*K*/)
103{
104 using T = typename std::decay_t<O>::value_type;
105 using Z = typename impl::scalar_value_type_t<T>;
106 for (std::size_t p = 0; p < U.extent(0); ++p)
107 {
108 for (std::size_t i = 0; i < r.extent(1); ++i)
109 {
110 T acc = 0;
111 for (std::size_t k = 0; k < J.extent(1); ++k)
112 acc += static_cast<Z>(J(i, k)) * U(p, k);
113 r(p, i) = acc;
114 }
115 }
116
117 std::transform(r.data_handle(), r.data_handle() + r.size(), r.data_handle(),
118 [detJ](auto ri) { return ri / static_cast<Z>(detJ); });
119}
120
128template <typename O, typename P, typename Q, typename R>
129void double_covariant_piola(O&& r, const P& U, const Q& /*J*/, double /*detJ*/,
130 const R& K)
131{
132 using T = typename std::decay_t<O>::value_type;
133 using Z = typename impl::scalar_value_type_t<T>;
134 for (std::size_t p = 0; p < U.extent(0); ++p)
135 {
136 md::mdspan<const T, md::dextents<std::size_t, 2>> _U(
137 U.data_handle() + p * U.extent(1), K.extent(0), K.extent(0));
138 md::mdspan<T, md::dextents<std::size_t, 2>> _r(
139 r.data_handle() + p * r.extent(1), K.extent(1), K.extent(1));
140 // _r = K^T _U K
141 for (std::size_t i = 0; i < _r.extent(0); ++i)
142 {
143 for (std::size_t j = 0; j < _r.extent(1); ++j)
144 {
145 T acc = 0;
146 for (std::size_t k = 0; k < K.extent(0); ++k)
147 for (std::size_t l = 0; l < _U.extent(1); ++l)
148 acc += static_cast<Z>(K(k, i)) * _U(k, l) * static_cast<Z>(K(l, j));
149 _r(i, j) = acc;
150 }
151 }
152 }
153}
154
163template <typename O, typename P, typename Q, typename R>
164void double_contravariant_piola(O&& r, const P& U, const Q& J, double detJ,
165 const R& /*K*/)
166{
167 using T = typename std::decay_t<O>::value_type;
168 using Z = typename impl::scalar_value_type_t<T>;
169 for (std::size_t p = 0; p < U.extent(0); ++p)
170 {
171 md::mdspan<const T, md::dextents<std::size_t, 2>> _U(
172 U.data_handle() + p * U.extent(1), J.extent(1), J.extent(1));
173 md::mdspan<T, md::dextents<std::size_t, 2>> _r(
174 r.data_handle() + p * r.extent(1), J.extent(0), J.extent(0));
175
176 // _r = J U J^T
177 for (std::size_t i = 0; i < _r.extent(0); ++i)
178 {
179 for (std::size_t j = 0; j < _r.extent(1); ++j)
180 {
181 T acc = 0;
182 for (std::size_t k = 0; k < J.extent(1); ++k)
183 for (std::size_t l = 0; l < _U.extent(1); ++l)
184 acc += static_cast<Z>(J(i, k)) * _U(k, l) * static_cast<Z>(J(j, l));
185 _r(i, j) = acc;
186 }
187 }
188 }
189
190 std::transform(r.data_handle(), r.data_handle() + r.size(), r.data_handle(),
191 [detJ](auto ri) { return ri / static_cast<Z>(detJ * detJ); });
192}
193
194} // namespace basix::maps
A finite element.
Definition finite-element.h:138
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:57
void covariant_piola(O &&r, const P &U, const Q &, double, const R &K)
Covariant Piola map.
Definition maps.h:74
void contravariant_piola(O &&r, const P &U, const Q &J, double detJ, const R &)
Contravariant Piola map.
Definition maps.h:101
void double_contravariant_piola(O &&r, const P &U, const Q &J, double detJ, const R &)
Double contravariant Piola map.
Definition maps.h:164
void double_covariant_piola(O &&r, const P &U, const Q &, double, const R &K)
Double covariant Piola map.
Definition maps.h:129
type
Map type.
Definition maps.h:40