Basix
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
50template <typename O, typename P, typename Q, typename R>
51void 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
61template <typename O, typename P, typename Q, typename R>
62void 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
81template <typename O, typename P, typename Q, typename R>
82void 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
103template <typename O, typename P, typename Q, typename R>
104void 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), K.extent(0), K.extent(0));
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
131template <typename O, typename P, typename Q, typename R>
132void 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 &, double, const R &K)
Double covariant Piola map.
Definition maps.h:104
type
Map type.
Definition maps.h:40