DOLFINx 0.8.0
DOLFINx C++ interface
Loading...
Searching...
No Matches
CoordinateElement.h
1// Copyright (C) 2018-2020 Garth N. Wells and Chris N. Richardson
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "ElementDofLayout.h"
10#include <algorithm>
11#include <array>
12#include <basix/element-families.h>
13#include <basix/mdspan.hpp>
14#include <cmath>
15#include <concepts>
16#include <cstdint>
17#include <dolfinx/common/math.h>
18#include <dolfinx/mesh/cell_types.h>
19#include <limits>
20#include <memory>
21#include <span>
22
23namespace basix
24{
25template <std::floating_point T>
27}
28
29namespace dolfinx::fem
30{
36template <std::floating_point T>
38{
39public:
42 explicit CoordinateElement(
43 std::shared_ptr<const basix::FiniteElement<T>> element);
44
51 basix::element::lagrange_variant type
52 = basix::element::lagrange_variant::unset);
53
55 virtual ~CoordinateElement() = default;
56
60
63 int degree() const;
64
71 int dim() const;
72
74 basix::element::lagrange_variant variant() const;
75
82 std::array<std::size_t, 4> tabulate_shape(std::size_t nd,
83 std::size_t num_points) const;
84
93 void tabulate(int nd, std::span<const T> X, std::array<std::size_t, 2> shape,
94 std::span<T> basis) const;
95
104 template <typename U, typename V, typename W>
105 static void compute_jacobian(const U& dphi, const V& cell_geometry, W&& J)
106 {
107 math::dot(cell_geometry, dphi, J, true);
108 }
109
113 template <typename U, typename V>
114 static void compute_jacobian_inverse(const U& J, V&& K)
115 {
116 int gdim = J.extent(0);
117 int tdim = K.extent(0);
118 if (gdim == tdim)
119 math::inv(J, K);
120 else
121 math::pinv(J, K);
122 }
123
129 template <typename U>
130 static double
131 compute_jacobian_determinant(const U& J, std::span<typename U::value_type> w)
132 {
133 static_assert(U::rank() == 2, "Must be rank 2");
134 if (J.extent(0) == J.extent(1))
135 return math::det(J);
136 else
137 {
138 assert(w.size() >= 2 * J.extent(0) * J.extent(1));
139 using X = typename U::element_type;
140 using mdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
141 X, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
142 mdspan2_t B(w.data(), J.extent(1), J.extent(0));
143 mdspan2_t BA(w.data() + J.extent(0) * J.extent(1), B.extent(0),
144 J.extent(1));
145 for (std::size_t i = 0; i < B.extent(0); ++i)
146 for (std::size_t j = 0; j < B.extent(1); ++j)
147 B(i, j) = J(j, i);
148
149 // Zero working memory of BA
150 std::fill_n(BA.data_handle(), BA.size(), 0);
151 math::dot(B, J, BA);
152 return std::sqrt(math::det(BA));
153 }
154 }
155
158
166 template <typename U, typename V, typename W>
167 static void push_forward(U&& x, const V& cell_geometry, const W& phi)
168 {
169 for (std::size_t i = 0; i < x.extent(0); ++i)
170 for (std::size_t j = 0; j < x.extent(1); ++j)
171 x(i, j) = 0;
172
173 // Compute x = phi * cell_geometry;
174 math::dot(phi, cell_geometry, x);
175 }
176
187 template <typename U, typename V, typename W>
188 static void pull_back_affine(U&& X, const V& K, const std::array<T, 3>& x0,
189 const W& x)
190 {
191 assert(X.extent(0) == x.extent(0));
192 assert(X.extent(1) == K.extent(0));
193 assert(x.extent(1) == K.extent(1));
194 for (std::size_t i = 0; i < X.extent(0); ++i)
195 for (std::size_t j = 0; j < X.extent(1); ++j)
196 X(i, j) = 0;
197
198 // Calculate X for each point
199 for (std::size_t p = 0; p < x.extent(0); ++p)
200 for (std::size_t i = 0; i < K.extent(0); ++i)
201 for (std::size_t j = 0; j < K.extent(1); ++j)
202 X(p, i) += K(i, j) * (x(p, j) - x0[j]);
203 }
204
206 template <typename X>
207 using mdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
208 X, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
209
222 mdspan2_t<const T> cell_geometry,
223 double tol = 1.0e-6, int maxit = 15) const;
224
226 void permute(std::span<std::int32_t> dofs, std::uint32_t cell_perm) const;
227
229 void permute_inv(std::span<std::int32_t> dofs, std::uint32_t cell_perm) const;
230
236 bool needs_dof_permutations() const;
237
240 bool is_affine() const noexcept { return _is_affine; }
241
242private:
243 // Flag denoting affine map
244 bool _is_affine;
245
246 // Basix Element
247 std::shared_ptr<const basix::FiniteElement<T>> _element;
248};
249} // namespace dolfinx::fem
Definition CoordinateElement.h:26
Definition CoordinateElement.h:38
ElementDofLayout create_dof_layout() const
Compute and return the dof layout.
Definition CoordinateElement.cpp:63
static void compute_jacobian(const U &dphi, const V &cell_geometry, W &&J)
Definition CoordinateElement.h:105
static void pull_back_affine(U &&X, const V &K, const std::array< T, 3 > &x0, const W &x)
Compute reference coordinates X for physical coordinates x for an affine map. For the affine case,...
Definition CoordinateElement.h:188
void tabulate(int nd, std::span< const T > X, std::array< std::size_t, 2 > shape, std::span< T > basis) const
Evaluate basis values and derivatives at set of points.
Definition CoordinateElement.cpp:54
CoordinateElement(std::shared_ptr< const basix::FiniteElement< T > > element)
Create a coordinate element from a Basix element.
Definition CoordinateElement.cpp:18
void permute_inv(std::span< std::int32_t > dofs, std::uint32_t cell_perm) const
Reverses a DOF permutation.
Definition CoordinateElement.cpp:171
basix::element::lagrange_variant variant() const
Variant of the element.
Definition CoordinateElement.cpp:201
mesh::CellType cell_shape() const
Cell shape.
Definition CoordinateElement.cpp:40
static void compute_jacobian_inverse(const U &J, V &&K)
Compute the inverse of the Jacobian.
Definition CoordinateElement.h:114
MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< X, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents< std::size_t, 2 > > mdspan2_t
mdspan typedef
Definition CoordinateElement.h:207
std::array< std::size_t, 4 > tabulate_shape(std::size_t nd, std::size_t num_points) const
Shape of array to fill when calling tabulate.
Definition CoordinateElement.cpp:47
int degree() const
The polynomial degree of the element.
Definition CoordinateElement.cpp:187
void permute(std::span< std::int32_t > dofs, std::uint32_t cell_perm) const
Permute a list of DOF numbers on a cell.
Definition CoordinateElement.cpp:163
int dim() const
The dimension of the coordinate element space.
Definition CoordinateElement.cpp:194
void pull_back_nonaffine(mdspan2_t< T > X, mdspan2_t< const T > x, mdspan2_t< const T > cell_geometry, double tol=1.0e-6, int maxit=15) const
Compute reference coordinates X for physical coordinates x for a non-affine map.
Definition CoordinateElement.cpp:71
virtual ~CoordinateElement()=default
Destructor.
bool is_affine() const noexcept
Definition CoordinateElement.h:240
static void push_forward(U &&x, const V &cell_geometry, const W &phi)
Compute physical coordinates x for points X in the reference configuration.
Definition CoordinateElement.h:167
static double compute_jacobian_determinant(const U &J, std::span< typename U::value_type > w)
Compute the determinant of the Jacobian.
Definition CoordinateElement.h:131
bool needs_dof_permutations() const
Indicates whether the geometry DOF numbers on each cell need permuting.
Definition CoordinateElement.cpp:179
Definition ElementDofLayout.h:30
Finite element method functionality.
Definition assemble_matrix_impl.h:26
CellType
Cell type identifier.
Definition cell_types.h:22