DOLFINx 0.12.0.0
DOLFINx C++
Loading...
Searching...
No Matches
FiniteElement.h
1// Copyright (C) 2020-2026 Garth N. Wells, Matthew W. Scroggs and Jørgen S.
2// Dokken
3//
4// This file is part of DOLFINx (https://www.fenicsproject.org)
5//
6// SPDX-License-Identifier: LGPL-3.0-or-later
7
8#pragma once
9
10#include "traits.h"
11#include <algorithm>
12#include <array>
13#include <basix/finite-element.h>
14#include <basix/maps.h>
15#include <cassert>
16#include <concepts>
17#include <cstddef>
18#include <cstdint>
19#include <dolfinx/mesh/cell_types.h>
20#include <dolfinx/mesh/permutationcomputation.h>
21#include <functional>
22#include <memory>
23#include <optional>
24#include <span>
25#include <stdexcept>
26#include <utility>
27#include <vector>
28
29namespace dolfinx::fem
30{
32enum class doftransform : std::uint8_t
33{
35 transpose = 1,
36 inverse = 2,
38};
39
40template <std::floating_point T>
41class FiniteElement;
42
77std::vector<std::size_t>
78compute_value_shape(basix::maps::type map_type,
79 std::span<const std::size_t> reference_value_shape,
80 std::size_t gdim);
81
84template <std::floating_point T>
86{
87 std::reference_wrapper<const basix::FiniteElement<T>>
93 std::optional<std::vector<std::size_t>> value_shape = std::nullopt;
94 bool symmetry = false;
96};
97
99template <typename U, typename V, typename W>
100BasixElementData(U element, V bs, W symmetry)
102
200template <std::floating_point T>
202{
203public:
205 using geometry_type = T;
206
218 std::size_t gdim,
219 const std::optional<std::vector<std::size_t>>& value_shape
220 = std::nullopt,
221 bool symmetric = false);
222
234 std::size_t gdim);
235
254 const std::vector<std::shared_ptr<const FiniteElement<geometry_type>>>&
255 elements);
256
266 FiniteElement(mesh::CellType cell_type, std::span<const geometry_type> points,
267 std::array<std::size_t, 2> pshape,
268 std::vector<std::size_t> value_shape = {},
269 bool symmetric = false);
270
272 FiniteElement(const FiniteElement& element) = delete;
273
275 FiniteElement(FiniteElement&& element) = default;
276
278 ~FiniteElement() = default;
279
281 FiniteElement& operator=(const FiniteElement& element) = delete;
282
284 FiniteElement& operator=(FiniteElement&& element) = default;
285
294 bool operator==(const FiniteElement& e) const;
295
300 bool operator!=(const FiniteElement& e) const;
301
303 mesh::CellType cell_type() const noexcept;
304
311 const std::string& signature() const noexcept;
312
320 int space_dimension() const noexcept;
321
333 int block_size() const noexcept;
334
347 int value_size() const;
348
366 std::span<const std::size_t> value_shape() const;
367
390 int physical_base_value_size() const;
391
407 int reference_value_size() const;
408
423 std::span<const std::size_t> reference_value_shape() const;
424
426 const std::vector<std::vector<std::vector<int>>>&
427 entity_dofs() const noexcept;
428
431 const std::vector<std::vector<std::vector<int>>>&
432 entity_closure_dofs() const noexcept;
433
440 bool symmetric() const;
441
454 void tabulate(std::span<geometry_type> values,
455 std::span<const geometry_type> X,
456 std::array<std::size_t, 2> shape, int order) const;
457
468 std::pair<std::vector<geometry_type>, std::array<std::size_t, 4>>
469 tabulate(std::span<const geometry_type> X, std::array<std::size_t, 2> shape,
470 int order) const;
471
474 int num_sub_elements() const noexcept;
475
483 bool is_mixed() const noexcept;
484
486 const std::vector<std::shared_ptr<const FiniteElement<geometry_type>>>&
487 sub_elements() const noexcept;
488
490 std::shared_ptr<const FiniteElement<geometry_type>>
491 extract_sub_element(const std::vector<int>& component) const;
492
495 const basix::FiniteElement<geometry_type>& basix_element() const;
496
498 basix::maps::type map_type() const;
499
506 bool interpolation_ident() const noexcept;
507
512 bool map_ident() const noexcept;
513
524 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>>
525 interpolation_points() const;
526
536 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>>
538
551 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>>
553
567 bool needs_dof_transformations() const noexcept;
568
582 bool depends_on_facet_orientations() const noexcept;
583
598 bool needs_dof_permutations() const noexcept;
599
639 template <typename U>
640 std::function<void(std::span<U>, std::span<const std::uint32_t>, std::int32_t,
641 int)>
642 dof_transformation_fn(doftransform ttype, bool scalar_element = false) const
643 {
645 return nullptr;
646
647 if (!_sub_elements.empty())
648 {
649 if (!_reference_value_shape) // Mixed element
650 {
651 std::vector<std::function<void(
652 std::span<U>, std::span<const std::uint32_t>, std::int32_t, int)>>
653 sub_element_fns;
654 std::vector<int> dims;
655 sub_element_fns.reserve(_sub_elements.size());
656 dims.reserve(_sub_elements.size());
657 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
658 {
659 sub_element_fns.push_back(
660 _sub_elements[i]->template dof_transformation_fn<U>(ttype));
661 dims.push_back(_sub_elements[i]->space_dimension());
662 }
663
664 return [dims = std::move(dims),
665 sub_element_fns = std::move(sub_element_fns)](
666 std::span<U> data, std::span<const std::uint32_t> cell_info,
667 std::int32_t cell, int block_size)
668 {
669 std::size_t offset = 0;
670 for (std::size_t e = 0; e < sub_element_fns.size(); ++e)
671 {
672 const std::size_t width = dims[e] * block_size;
673 if (sub_element_fns[e])
674 {
675 sub_element_fns[e](data.subspan(offset, width), cell_info, cell,
676 block_size);
677 }
678 offset += width;
679 }
680 };
681 }
682 else if (!scalar_element)
683 {
684 // Blocked element
685 std::function<void(std::span<U>, std::span<const std::uint32_t>,
686 std::int32_t, int)>
687 sub_fn
688 = _sub_elements.front()->template dof_transformation_fn<U>(ttype);
689 assert(sub_fn); // Consistent with needs_dof_transformations() above
690 const int ebs = _bs;
691 return [ebs, sub_fn = std::move(sub_fn)](
692 std::span<U> data, std::span<const std::uint32_t> cell_info,
693 std::int32_t cell, int data_block_size)
694 { sub_fn(data, cell_info, cell, ebs * data_block_size); };
695 }
696 }
697
698 switch (ttype)
699 {
701 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
702 std::int32_t cell, int block_size)
703 { Tt_inv_apply(data, cell_info[cell], block_size); };
705 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
706 std::int32_t cell, int block_size)
707 { Tt_apply(data, cell_info[cell], block_size); };
709 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
710 std::int32_t cell, int block_size)
711 { Tinv_apply(data, cell_info[cell], block_size); };
713 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
714 std::int32_t cell, int block_size)
715 { T_apply(data, cell_info[cell], block_size); };
716 default:
717 throw std::invalid_argument("Unknown transformation type");
718 }
719 }
720
744 template <typename U>
745 std::function<void(std::span<U>, std::span<const std::uint32_t>, std::int32_t,
746 int)>
748 bool scalar_element = false) const
749 {
751 return nullptr;
752 else if (!_sub_elements.empty())
753 {
754 if (!_reference_value_shape) // Mixed element
755 {
756 std::vector<std::function<void(
757 std::span<U>, std::span<const std::uint32_t>, std::int32_t, int)>>
758 sub_element_fns;
759 std::vector<int> dims;
760 sub_element_fns.reserve(_sub_elements.size());
761 dims.reserve(_sub_elements.size());
762 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
763 {
764 sub_element_fns.push_back(
765 _sub_elements[i]->template dof_transformation_right_fn<U>(ttype));
766 dims.push_back(_sub_elements[i]->space_dimension());
767 }
768
769 return [dims = std::move(dims),
770 sub_element_fns = std::move(sub_element_fns)](
771 std::span<U> data, std::span<const std::uint32_t> cell_info,
772 std::int32_t cell, int block_size)
773 {
774 // `data` is (block_size, ndofs), row-major. Sub-element `e`
775 // owns columns [offset, offset + dims[e]) of every row, so the
776 // rows are transformed one at a time.
777 const std::size_t ndofs = data.size() / block_size;
778 std::size_t offset = 0;
779 for (std::size_t e = 0; e < sub_element_fns.size(); ++e)
780 {
781 if (sub_element_fns[e])
782 {
783 for (int i = 0; i < block_size; ++i)
784 {
785 sub_element_fns[e](data.subspan(i * ndofs + offset, dims[e]),
786 cell_info, cell, 1);
787 }
788 }
789 offset += dims[e];
790 }
791 };
792 }
793 else if (!scalar_element)
794 {
795 // Blocked element
796 // The transformation from the left can be used here as blocked
797 // elements use xyzxyzxyz ordering, and so applying the DOF
798 // transformation from the right is equivalent to applying the DOF
799 // transformation from the left to data using xxxyyyzzz ordering
800 std::function<void(std::span<U>, std::span<const std::uint32_t>,
801 std::int32_t, int)>
802 sub_fn
803 = _sub_elements.front()->template dof_transformation_fn<U>(ttype);
804 assert(sub_fn); // Consistent with needs_dof_transformations() above
805 return [this, sub_fn = std::move(sub_fn)](
806 std::span<U> data, std::span<const std::uint32_t> cell_info,
807 std::int32_t cell, int data_block_size)
808 {
809 const int ebs = block_size();
810 const std::size_t dof_count = data.size() / data_block_size;
811 for (int block = 0; block < data_block_size; ++block)
812 {
813 sub_fn(data.subspan(block * dof_count, dof_count), cell_info, cell,
814 ebs);
815 }
816 };
817 }
818 }
819
820 switch (ttype)
821 {
823 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
824 std::int32_t cell, int n)
825 { Tt_inv_apply_right(data, cell_info[cell], n); };
827 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
828 std::int32_t cell, int n)
829 { Tt_apply_right(data, cell_info[cell], n); };
831 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
832 std::int32_t cell, int n)
833 { Tinv_apply_right(data, cell_info[cell], n); };
835 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
836 std::int32_t cell, int n)
837 { T_apply_right(data, cell_info[cell], n); };
838 default:
839 throw std::invalid_argument("Unknown transformation type");
840 }
841 }
842
879 template <typename U>
880 void T_apply(std::span<U> data, std::uint32_t cell_permutation, int n) const
881 {
882 assert(_element);
883 _element->T_apply(data, n, cell_permutation & ~_orientation_mask);
884 flip_reversed<false>(data, cell_permutation, n);
885 }
886
896 template <typename U>
897 void Tt_inv_apply(std::span<U> data, std::uint32_t cell_permutation,
898 int n) const
899 {
900 assert(_element);
901 _element->Tt_inv_apply(data, n, cell_permutation & ~_orientation_mask);
902 flip_reversed<false>(data, cell_permutation, n);
903 }
904
914 template <typename U>
915 void Tt_apply(std::span<U> data, std::uint32_t cell_permutation, int n) const
916 {
917 assert(_element);
918 _element->Tt_apply(data, n, cell_permutation & ~_orientation_mask);
919 flip_reversed<false>(data, cell_permutation, n);
920 }
921
930 template <typename U>
931 void Tinv_apply(std::span<U> data, std::uint32_t cell_permutation,
932 int n) const
933 {
934 assert(_element);
935 _element->Tinv_apply(data, n, cell_permutation & ~_orientation_mask);
936 flip_reversed<false>(data, cell_permutation, n);
937 }
938
947 template <typename U>
948 void T_apply_right(std::span<U> data, std::uint32_t cell_permutation,
949 int n) const
950 {
951 assert(_element);
952 _element->T_apply_right(data, n, cell_permutation & ~_orientation_mask);
953 flip_reversed<true>(data, cell_permutation, n);
954 }
955
965 template <typename U>
966 void Tinv_apply_right(std::span<U> data, std::uint32_t cell_permutation,
967 int n) const
968 {
969 assert(_element);
970 _element->Tinv_apply_right(data, n, cell_permutation & ~_orientation_mask);
971 flip_reversed<true>(data, cell_permutation, n);
972 }
973
983 template <typename U>
984 void Tt_apply_right(std::span<U> data, std::uint32_t cell_permutation,
985 int n) const
986 {
987 assert(_element);
988 _element->Tt_apply_right(data, n, cell_permutation & ~_orientation_mask);
989 flip_reversed<true>(data, cell_permutation, n);
990 }
991
1001 template <typename U>
1002 void Tt_inv_apply_right(std::span<U> data, std::uint32_t cell_permutation,
1003 int n) const
1004 {
1005 assert(_element);
1006 _element->Tt_inv_apply_right(data, n,
1007 cell_permutation & ~_orientation_mask);
1008 flip_reversed<true>(data, cell_permutation, n);
1009 }
1010
1027 void permute(std::span<std::int32_t> doflist,
1028 std::uint32_t cell_permutation) const;
1029
1046 void permute_inv(std::span<std::int32_t> doflist,
1047 std::uint32_t cell_permutation) const;
1048
1063 std::function<void(std::span<std::int32_t>, std::uint32_t)>
1064 dof_permutation_fn(bool inverse = false, bool scalar_element = false) const;
1065
1066private:
1067 // Negate data on each facet marked with mesh::reversed_facet_bit, if
1068 // the basis depends on the facet signs (see
1069 // mesh::Topology::create_facet_orientations). A sign is its own
1070 // inverse and transpose, so every DOF transformation applies it the
1071 // same way.
1072 //
1073 // `post` selects the layout: the right-applied transformations store
1074 // their data as `(n, num_dofs)`, the others as `(num_dofs, n)`.
1075 template <bool post, typename U>
1076 void flip_reversed(std::span<U> data, std::uint32_t cell_permutation,
1077 int n) const
1078 {
1079 if (!_depends_on_facet_orientations
1080 or !(cell_permutation & _orientation_mask)) [[likely]]
1081 {
1082 return;
1083 }
1084
1085 // The mask is non-zero only on a cell of dimension 2, whose facets
1086 // are its edges
1087 assert(mesh::cell_dim(_cell_type) == 2 and _entity_dofs.size() > 1);
1088 const std::vector<std::vector<int>>& facet_dofs = _entity_dofs[1];
1089
1090 assert(n > 0 and data.size() % n == 0);
1091 const std::size_t num_dofs = data.size() / n;
1092 for (std::size_t f = 0; f < facet_dofs.size(); ++f)
1093 {
1094 if (!(cell_permutation & mesh::reversed_facet_bit(f)))
1095 continue;
1096 for (int dof : facet_dofs[f])
1097 {
1098 for (int j = 0; j < n; ++j)
1099 {
1100 U& value = post ? data[j * num_dofs + dof] : data[dof * n + j];
1101 value = -value;
1102 }
1103 }
1104 }
1105 }
1106
1107 // Value shape in physical space. For blocked elements this is larger
1108 // than _reference_value_shape. For non-blocked elements it equals
1109 // _reference_value_shape, except for a Piola-mapped element on a
1110 // manifold, where the trailing axes have extent gdim rather than
1111 // tdim. For mixed elements, it is std::nullopt.
1112 std::optional<std::vector<std::size_t>> _value_shape;
1113
1114 // Block size for BlockedElements. This gives the number of DOFs
1115 // co-located at each dof 'point'.
1116 int _bs;
1117
1118 // Element cell shape
1119 mesh::CellType _cell_type;
1120
1121 // Element signature
1122 std::string _signature;
1123
1124 // Dimension of the finite element space (accounting for any blocking)
1125 int _space_dim;
1126
1127 // List of sub-elements (if any)
1128 std::vector<std::shared_ptr<const FiniteElement<geometry_type>>>
1129 _sub_elements;
1130
1131 // Value shape on the reference cell, i.e. the shape Basix tabulates
1132 // in, e.g. {} for a scalar, {3, 3} for a tensor in 3D. For a mixed
1133 // element it is std::nullopt, which is the sentinel used by
1134 // is_mixed() and the dof transformation functions.
1135 std::optional<std::vector<std::size_t>> _reference_value_shape;
1136
1137 // Basix Element (nullptr for mixed elements)
1138 std::unique_ptr<basix::FiniteElement<geometry_type>> _element;
1139
1140 // Indicate whether this element represents a symmetric 2-tensor
1141 bool _symmetric;
1142
1143 // Indicate whether the element needs permutations or transformations
1144 bool _needs_dof_permutations;
1145 bool _needs_dof_transformations;
1146
1147 // Indicate whether the basis depends on the facet signs
1148 bool _depends_on_facet_orientations;
1149
1150 // Bits of the cell permutation info holding facet signs for this
1151 // element's cell type, cleared before the info is passed to Basix
1152 std::uint32_t _orientation_mask = 0;
1153
1154 std::vector<std::vector<std::vector<int>>> _entity_dofs;
1155 std::vector<std::vector<std::vector<int>>> _entity_closure_dofs;
1156
1157 // Quadrature points of a quadrature element (0 dimensional array for
1158 // all elements except quadrature elements)
1159 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>> _points;
1160};
1161
1162} // namespace dolfinx::fem
Definition CoordinateElement.h:27
bool symmetric() const
Does the element represent a symmetric 2-tensor?
Definition FiniteElement.cpp:445
FiniteElement & operator=(const FiniteElement &element)=delete
Copy assignment.
const std::vector< std::shared_ptr< const FiniteElement< geometry_type > > > & sub_elements() const noexcept
Get subelements (if any).
Definition FiniteElement.cpp:491
void Tinv_apply(std::span< U > data, std::uint32_t cell_permutation, int n) const
Apply the inverse of the operator applied by T_apply().
Definition FiniteElement.h:931
std::span< const std::size_t > value_shape() const
Value shape of the finite element field in physical space.
Definition FiniteElement.cpp:383
std::pair< std::vector< geometry_type >, std::array< std::size_t, 2 > > create_interpolation_operator(const FiniteElement &from) const
Create a matrix that maps degrees of freedom from one element to this element (interpolation).
Definition FiniteElement.cpp:592
void T_apply(std::span< U > data, std::uint32_t cell_permutation, int n) const
Transform basis functions from the reference element ordering and orientation to the globally consist...
Definition FiniteElement.h:880
basix::maps::type map_type() const
Get the map type used by the element.
Definition FiniteElement.cpp:520
int space_dimension() const noexcept
Dimension of the finite element function space (the number of degrees-of-freedom for the element).
Definition FiniteElement.cpp:365
void tabulate(std::span< geometry_type > values, std::span< const geometry_type > X, std::array< std::size_t, 2 > shape, int order) const
Evaluate derivatives of the basis functions up to given order at points in the reference cell.
Definition FiniteElement.cpp:457
void Tt_inv_apply_right(std::span< U > data, std::uint32_t cell_permutation, int n) const
Right(post)-apply the transpose inverse of the operator applied by T_apply().
Definition FiniteElement.h:1002
FiniteElement & operator=(FiniteElement &&element)=default
Move assignment.
bool needs_dof_transformations() const noexcept
Check if DOF transformations are needed for this element.
Definition FiniteElement.cpp:637
FiniteElement(const FiniteElement &element)=delete
Copy constructor.
void Tt_inv_apply(std::span< U > data, std::uint32_t cell_permutation, int n) const
Apply the inverse transpose of the operator applied by T_apply().
Definition FiniteElement.h:897
std::pair< std::vector< geometry_type >, std::array< std::size_t, 2 > > interpolation_points() const
Points on the reference cell at which an expression needs to be evaluated in order to interpolate the...
Definition FiniteElement.cpp:560
std::shared_ptr< const FiniteElement< geometry_type > > extract_sub_element(const std::vector< int > &component) const
Extract sub finite element for component.
Definition FiniteElement.cpp:498
void T_apply_right(std::span< U > data, std::uint32_t cell_permutation, int n) const
Right(post)-apply the operator applied by T_apply().
Definition FiniteElement.h:948
bool needs_dof_permutations() const noexcept
Check if DOF permutations are needed for this element.
Definition FiniteElement.cpp:649
const std::string & signature() const noexcept
String identifying the finite element.
Definition FiniteElement.cpp:359
const std::vector< std::vector< std::vector< int > > > & entity_dofs() const noexcept
Local DOFs associated with each sub-entity of the cell.
Definition FiniteElement.cpp:432
bool is_mixed() const noexcept
Check if element is a mixed element.
Definition FiniteElement.cpp:484
FiniteElement(const basix::FiniteElement< geometry_type > &element, std::size_t gdim, const std::optional< std::vector< std::size_t > > &value_shape=std::nullopt, bool symmetric=false)
Create a finite element from a Basix finite element.
Definition FiniteElement.cpp:160
int reference_value_size() const
Value size of the base (non-blocked) finite element field on the reference cell.
Definition FiniteElement.cpp:410
int value_size() const
Value size of the finite element field in physical space.
Definition FiniteElement.cpp:371
std::function< void(std::span< U >, std::span< const std::uint32_t >, std::int32_t, int)> dof_transformation_fn(doftransform ttype, bool scalar_element=false) const
Return a function that applies a DOF transformation operator to some data (see T_apply()).
Definition FiniteElement.h:642
bool operator!=(const FiniteElement &e) const
Check if two elements are not equivalent.
Definition FiniteElement.cpp:347
~FiniteElement()=default
Destructor.
T geometry_type
Geometry type of the Mesh that the FunctionSpace is defined on.
Definition FiniteElement.h:205
bool depends_on_facet_orientations() const noexcept
Check if the basis changes sign on the facets whose two cells disagree on the normal (see mesh::Topol...
Definition FiniteElement.cpp:643
int physical_base_value_size() const
Number of physical components in one block of the finite element field.
Definition FiniteElement.cpp:392
const basix::FiniteElement< geometry_type > & basix_element() const
Return underlying Basix element (if it exists).
Definition FiniteElement.cpp:508
FiniteElement(FiniteElement &&element)=default
Move constructor.
int num_sub_elements() const noexcept
Number of sub elements (for a mixed or blocked element).
Definition FiniteElement.cpp:478
void Tt_apply(std::span< U > data, std::uint32_t cell_permutation, int n) const
Apply the transpose of the operator applied by T_apply().
Definition FiniteElement.h:915
const std::vector< std::vector< std::vector< int > > > & entity_closure_dofs() const noexcept
Local DOFs associated with the closure of each sub-entity of the cell.
Definition FiniteElement.cpp:439
std::pair< std::vector< geometry_type >, std::array< std::size_t, 2 > > interpolation_operator() const
Definition FiniteElement.cpp:579
int block_size() const noexcept
Block size of the finite element function space.
Definition FiniteElement.cpp:451
std::span< const std::size_t > reference_value_shape() const
Value shape of the base (non-blocked) finite element field on the reference cell.
Definition FiniteElement.cpp:422
void Tt_apply_right(std::span< U > data, std::uint32_t cell_permutation, int n) const
Right(post)-apply the transpose of the operator applied by T_apply().
Definition FiniteElement.h:984
std::function< void(std::span< U >, std::span< const std::uint32_t >, std::int32_t, int)> dof_transformation_right_fn(doftransform ttype, bool scalar_element=false) const
Return a function that applies DOF transformation to some transposed data (see T_apply_right()).
Definition FiniteElement.h:747
mesh::CellType cell_type() const noexcept
Cell shape that the element is defined on.
Definition FiniteElement.cpp:353
bool interpolation_ident() const noexcept
Definition FiniteElement.cpp:547
void Tinv_apply_right(std::span< U > data, std::uint32_t cell_permutation, int n) const
Right(post)-apply the inverse of the operator applied by T_apply().
Definition FiniteElement.h:966
bool operator==(const FiniteElement &e) const
Check if two elements are equivalent.
Definition FiniteElement.cpp:329
bool map_ident() const noexcept
Definition FiniteElement.cpp:533
Finite element method functionality.
Definition assemble_expression_impl.h:28
doftransform
DOF transformation type.
Definition FiniteElement.h:33
@ transpose
Transpose.
Definition FiniteElement.h:35
@ inverse_transpose
Transpose inverse.
Definition FiniteElement.h:37
@ inverse
Inverse.
Definition FiniteElement.h:36
@ standard
Standard.
Definition FiniteElement.h:34
std::vector< std::size_t > compute_value_shape(basix::maps::type map_type, std::span< const std::size_t > reference_value_shape, std::size_t gdim)
Value shape of a finite element field in physical space.
Definition FiniteElement.cpp:119
@ cell
Cell.
Definition Form.h:42
int cell_dim(CellType type)
Return topological dimension of cell type.
Definition cell_types.h:47
CellType
Cell type identifier.
Definition cell_types.h:24
constexpr std::uint32_t reversed_facet_bit(int f)
Bit of the cell permutation info that negates the degrees-of-freedom on facet f of a cell (see Topolo...
Definition permutationcomputation.h:28
Basix element holder.
Definition FiniteElement.h:86
std::optional< std::vector< std::size_t > > value_shape
Definition FiniteElement.h:93
bool symmetry
Definition FiniteElement.h:94
std::reference_wrapper< const basix::FiniteElement< T > > element
Definition FiniteElement.h:88