DOLFINx
DOLFINx C++ interface
Loading...
Searching...
No Matches
FiniteElement.h
1// Copyright (C) 2020-2021 Garth N. Wells and Matthew W. Scroggs
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 "traits.h"
10#include <array>
11#include <basix/finite-element.h>
12#include <concepts>
13#include <cstdint>
14#include <dolfinx/mesh/cell_types.h>
15#include <functional>
16#include <memory>
17#include <span>
18#include <utility>
19#include <vector>
20
21struct ufcx_finite_element;
22
23namespace dolfinx::fem
24{
27template <std::floating_point T>
29{
30public:
32 enum class doftransform
33 {
34 standard = 0,
35 transpose = 1,
36 inverse = 2,
37 inverse_transpose = 3,
38 };
39
41 using geometry_type = T;
42
45 explicit FiniteElement(const ufcx_finite_element& e);
46
51 const std::size_t block_size);
52
54 FiniteElement(const FiniteElement& element) = delete;
55
57 FiniteElement(FiniteElement&& element) = default;
58
60 ~FiniteElement() = default;
61
63 FiniteElement& operator=(const FiniteElement& element) = delete;
64
66 FiniteElement& operator=(FiniteElement&& element) = default;
67
72 bool operator==(const FiniteElement& e) const;
73
78 bool operator!=(const FiniteElement& e) const;
79
86 std::string signature() const noexcept;
87
90 mesh::CellType cell_shape() const noexcept;
91
95 int space_dimension() const noexcept;
96
101 int block_size() const noexcept;
102
106 int reference_value_size() const;
107
109 std::span<const std::size_t> reference_value_shape() const;
110
122 void tabulate(std::span<geometry_type> values,
123 std::span<const geometry_type> X,
124 std::array<std::size_t, 2> shape, int order) const;
125
135 std::pair<std::vector<geometry_type>, std::array<std::size_t, 4>>
136 tabulate(std::span<const geometry_type> X, std::array<std::size_t, 2> shape,
137 int order) const;
138
141 int num_sub_elements() const noexcept;
142
150 bool is_mixed() const noexcept;
151
153 const std::vector<std::shared_ptr<const FiniteElement<geometry_type>>>&
154 sub_elements() const noexcept;
155
157 std::shared_ptr<const FiniteElement<geometry_type>>
158 extract_sub_element(const std::vector<int>& component) const;
159
161 const basix::FiniteElement<geometry_type>& basix_element() const;
162
164 basix::maps::type map_type() const;
165
172 bool interpolation_ident() const noexcept;
173
178 bool map_ident() const noexcept;
179
190 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>>
191 interpolation_points() const;
192
202 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>>
204
217 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>>
219
233 bool needs_dof_transformations() const noexcept;
234
249 bool needs_dof_permutations() const noexcept;
250
265 template <typename U>
266 std::function<void(std::span<U>, std::span<const std::uint32_t>, std::int32_t,
267 int)>
269 = doftransform::standard,
270 bool scalar_element = false) const
271 {
273 {
274 // If no permutation needed, return function that does nothing
275 return [](std::span<U>, std::span<const std::uint32_t>, std::int32_t, int)
276 {
277 // Do nothing
278 };
279 }
280
281 if (_sub_elements.size() != 0)
282 {
283 if (_is_mixed)
284 {
285 // Mixed element
286 std::vector<std::function<void(
287 std::span<U>, std::span<const std::uint32_t>, std::int32_t, int)>>
288 sub_element_functions;
289 std::vector<int> dims;
290 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
291 {
292 sub_element_functions.push_back(
293 _sub_elements[i]->template get_pre_dof_transformation_function<U>(
294 ttype));
295 dims.push_back(_sub_elements[i]->space_dimension());
296 }
297
298 return [dims, sub_element_functions](
299 std::span<U> data, std::span<const std::uint32_t> cell_info,
300 std::int32_t cell, int block_size)
301 {
302 std::size_t offset = 0;
303 for (std::size_t e = 0; e < sub_element_functions.size(); ++e)
304 {
305 const std::size_t width = dims[e] * block_size;
306 sub_element_functions[e](data.subspan(offset, width), cell_info,
308 offset += width;
309 }
310 };
311 }
312 else if (!scalar_element)
313 {
314 // Vector element
315 const std::function<void(std::span<U>, std::span<const std::uint32_t>,
316 std::int32_t, int)>
317 sub_function
318 = _sub_elements[0]->template get_pre_dof_transformation_function<U>(
319 ttype);
320 const int ebs = _bs;
321 return [ebs, sub_function](std::span<U> data,
322 std::span<const std::uint32_t> cell_info,
323 std::int32_t cell, int data_block_size)
324 { sub_function(data, cell_info, cell, ebs * data_block_size); };
325 }
326 }
327 switch (ttype)
328 {
329 case doftransform::inverse_transpose:
330 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
331 std::int32_t cell, int block_size)
332 {
334 block_size);
335 };
336 case doftransform::transpose:
337 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
338 std::int32_t cell, int block_size) {
340 block_size);
341 };
342 case doftransform::inverse:
343 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
344 std::int32_t cell, int block_size) {
346 };
347 case doftransform::standard:
348 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
349 std::int32_t cell, int block_size)
350 { pre_apply_dof_transformation(data, cell_info[cell], block_size); };
351 default:
352 throw std::runtime_error("Unknown transformation type");
353 }
354 }
370 template <typename U>
371 std::function<void(std::span<U>, std::span<const std::uint32_t>, std::int32_t,
372 int)>
374 = doftransform::standard,
375 bool scalar_element = false) const
376 {
378 {
379 // If no permutation needed, return function that does nothing
380 return [](std::span<U>, std::span<const std::uint32_t>, std::int32_t, int)
381 {
382 // Do nothing
383 };
384 }
385 else if (_sub_elements.size() != 0)
386 {
387 if (_is_mixed)
388 {
389 // Mixed element
390 std::vector<std::function<void(
391 std::span<U>, std::span<const std::uint32_t>, std::int32_t, int)>>
392 sub_element_functions;
393 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
394 {
395 sub_element_functions.push_back(
396 _sub_elements[i]
397 ->template get_post_dof_transformation_function<U>(ttype));
398 }
399
400 return [this, sub_element_functions](
401 std::span<U> data, std::span<const std::uint32_t> cell_info,
402 std::int32_t cell, int block_size)
403 {
404 std::size_t offset = 0;
405 for (std::size_t e = 0; e < sub_element_functions.size(); ++e)
406 {
407 sub_element_functions[e](data.subspan(offset, data.size() - offset),
408 cell_info, cell, block_size);
409 offset += _sub_elements[e]->space_dimension();
410 }
411 };
412 }
413 else if (!scalar_element)
414 {
415 // Vector element
416 const std::function<void(std::span<U>, std::span<const std::uint32_t>,
417 std::int32_t, int)>
418 sub_function
419 = _sub_elements[0]->template get_pre_dof_transformation_function<U>(
420 ttype);
421 return [this, sub_function](std::span<U> data,
422 std::span<const std::uint32_t> cell_info,
423 std::int32_t cell, int data_block_size)
424 {
425 const int ebs = block_size();
426 const std::size_t dof_count = data.size() / data_block_size;
427 for (int block = 0; block < data_block_size; ++block)
428 {
429 sub_function(data.subspan(block * dof_count, dof_count), cell_info,
430 cell, ebs);
431 }
432 };
433 }
434 }
435
436 switch (ttype)
437 {
438 case doftransform::inverse_transpose:
439 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
440 std::int32_t cell, int block_size)
441 {
443 block_size);
444 };
445 case doftransform::transpose:
446 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
447 std::int32_t cell, int block_size) {
449 block_size);
450 };
451 case doftransform::inverse:
452 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
453 std::int32_t cell, int block_size) {
455 block_size);
456 };
457 case doftransform::standard:
458 return [this](std::span<U> data, std::span<const std::uint32_t> cell_info,
459 std::int32_t cell, int block_size)
460 { post_apply_dof_transformation(data, cell_info[cell], block_size); };
461 default:
462 throw std::runtime_error("Unknown transformation type");
463 }
464 }
465
472 template <typename U>
473 void pre_apply_dof_transformation(std::span<U> data,
474 std::uint32_t cell_permutation,
475 int block_size) const
476 {
477 assert(_element);
478 _element->pre_apply_dof_transformation(data, block_size, cell_permutation);
479 }
480
489 template <typename U>
491 std::span<U> data, std::uint32_t cell_permutation, int block_size) const
492 {
493 assert(_element);
494 _element->pre_apply_inverse_transpose_dof_transformation(data, block_size,
495 cell_permutation);
496 }
497
505 template <typename U>
507 std::uint32_t cell_permutation,
508 int block_size) const
509 {
510 assert(_element);
511 _element->pre_apply_transpose_dof_transformation(data, block_size,
512 cell_permutation);
513 }
514
522 template <typename U>
524 std::uint32_t cell_permutation,
525 int block_size) const
526 {
527 assert(_element);
528 _element->pre_apply_inverse_dof_transformation(data, block_size,
529 cell_permutation);
530 }
531
538 template <typename U>
539 void post_apply_dof_transformation(std::span<U> data,
540 std::uint32_t cell_permutation,
541 int block_size) const
542 {
543 assert(_element);
544 _element->post_apply_dof_transformation(data, block_size, cell_permutation);
545 }
546
553 template <typename U>
555 std::uint32_t cell_permutation,
556 int block_size) const
557 {
558 assert(_element);
559 _element->post_apply_inverse_dof_transformation(data, block_size,
560 cell_permutation);
561 }
562
569 template <typename U>
571 std::uint32_t cell_permutation,
572 int block_size) const
573 {
574 assert(_element);
575 _element->post_apply_transpose_dof_transformation(data, block_size,
576 cell_permutation);
577 }
578
585 template <typename U>
587 std::span<U> data, std::uint32_t cell_permutation, int block_size) const
588 {
589 assert(_element);
590 _element->post_apply_inverse_transpose_dof_transformation(data, block_size,
591 cell_permutation);
592 }
593
598 void permute_dofs(std::span<std::int32_t> doflist,
599 std::uint32_t cell_permutation) const;
600
605 void unpermute_dofs(std::span<std::int32_t> doflist,
606 std::uint32_t cell_permutation) const;
607
619 std::function<void(std::span<std::int32_t>, std::uint32_t)>
620 get_dof_permutation_function(bool inverse = false,
621 bool scalar_element = false) const;
622
623private:
624 std::string _signature;
625
626 mesh::CellType _cell_shape;
627
628 int _space_dim;
629
630 // List of sub-elements (if any)
631 std::vector<std::shared_ptr<const FiniteElement<geometry_type>>>
632 _sub_elements;
633
634 // Dimension of each value space
635 std::vector<std::size_t> _reference_value_shape;
636
637 // Block size for BlockedElements. This gives the
638 // number of DOFs co-located at each dof 'point'.
639 int _bs;
640
641 // Indicate whether this is a mixed element
642 bool _is_mixed;
643
644 // Indicate whether the element needs permutations or transformations
645 bool _needs_dof_permutations;
646 bool _needs_dof_transformations;
647
648 // Basix Element (nullptr for mixed elements)
649 std::unique_ptr<basix::FiniteElement<geometry_type>> _element;
650
651 // Quadrature points of a quadrature element (0 dimensional array for
652 // all elements except quadrature elements)
653 std::pair<std::vector<geometry_type>, std::array<std::size_t, 2>> _points;
654};
655} // namespace dolfinx::fem
Definition CoordinateElement.h:26
Finite Element, containing the dof layout on a reference element, and various methods for evaluating ...
Definition FiniteElement.h:29
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:424
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:514
basix::maps::type map_type() const
Get the map type used by the element.
Definition FiniteElement.cpp:453
void post_apply_inverse_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply inverse of DOF transformation to some transposed data.
Definition FiniteElement.h:554
int space_dimension() const noexcept
Dimension of the finite element function space (the number of degrees-of-freedom for the element)
Definition FiniteElement.cpp:368
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:393
void post_apply_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply DOF transformation to some transposed data.
Definition FiniteElement.h:539
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:557
FiniteElement(const FiniteElement &element)=delete
Copy constructor.
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:485
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:431
std::string signature() const noexcept
String identifying the finite element.
Definition FiniteElement.cpp:356
std::function< void(std::span< std::int32_t >, std::uint32_t)> get_dof_permutation_function(bool inverse=false, bool scalar_element=false) const
Return a function that applies DOF permutation to some data.
bool needs_dof_permutations() const noexcept
Check if DOF permutations are needed for this element.
Definition FiniteElement.cpp:563
void pre_apply_transpose_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply transpose transformation to some data. For VectorElements, this applies the transformations for...
Definition FiniteElement.h:506
bool is_mixed() const noexcept
Check if element is a mixed element.
Definition FiniteElement.cpp:417
int reference_value_size() const
The value size, e.g. 1 for a scalar function, 2 for a 2D vector, 9 for a second-order tensor in 3D,...
Definition FiniteElement.cpp:380
doftransform
DOF transformation type.
Definition FiniteElement.h:33
void pre_apply_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply DOF transformation to some data.
Definition FiniteElement.h:473
void post_apply_transpose_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply transpose of transformation to some transposed data.
Definition FiniteElement.h:570
bool operator!=(const FiniteElement &e) const
Check if two elements are not equivalent.
Definition FiniteElement.cpp:350
~FiniteElement()=default
Destructor.
T geometry_type
Geometry type of the Mesh that the FunctionSpace is defined on.
Definition FiniteElement.h:41
const basix::FiniteElement< geometry_type > & basix_element() const
Return underlying basix element (if it exists)
Definition FiniteElement.cpp:441
void pre_apply_inverse_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply inverse transformation to some data. For VectorElements, this applies the transformations for t...
Definition FiniteElement.h:523
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:411
std::function< void(std::span< U >, std::span< const std::uint32_t >, std::int32_t, int)> get_post_dof_transformation_function(doftransform ttype=doftransform::standard, bool scalar_element=false) const
Return a function that applies DOF transformation to some transposed data.
Definition FiniteElement.h:373
std::pair< std::vector< geometry_type >, std::array< std::size_t, 2 > > interpolation_operator() const
Interpolation operator (matrix) Pi that maps a function evaluated at the points provided by FiniteEle...
Definition FiniteElement.cpp:501
int block_size() const noexcept
Block size of the finite element function space. For BlockedElements, this is the number of DOFs colo...
Definition FiniteElement.cpp:387
std::span< const std::size_t > reference_value_shape() const
The reference value shape.
Definition FiniteElement.cpp:374
void pre_apply_inverse_transpose_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply inverse transpose transformation to some data. For VectorElements, this applies the transformat...
Definition FiniteElement.h:490
bool interpolation_ident() const noexcept
Check if interpolation into the finite element space is an identity operation given the evaluation on...
Definition FiniteElement.cpp:475
void unpermute_dofs(std::span< std::int32_t > doflist, std::uint32_t cell_permutation) const
Unpermute the DOFs of the element.
Definition FiniteElement.cpp:576
void post_apply_inverse_transpose_dof_transformation(std::span< U > data, std::uint32_t cell_permutation, int block_size) const
Apply inverse transpose transformation to some transposed data.
Definition FiniteElement.h:586
void permute_dofs(std::span< std::int32_t > doflist, std::uint32_t cell_permutation) const
Permute the DOFs of the element.
Definition FiniteElement.cpp:569
std::function< void(std::span< U >, std::span< const std::uint32_t >, std::int32_t, int)> get_pre_dof_transformation_function(doftransform ttype=doftransform::standard, bool scalar_element=false) const
Return a function that applies DOF transformation to some data.
Definition FiniteElement.h:268
bool operator==(const FiniteElement &e) const
Check if two elements are equivalent.
Definition FiniteElement.cpp:338
mesh::CellType cell_shape() const noexcept
Cell shape.
Definition FiniteElement.cpp:362
bool map_ident() const noexcept
Check if the push forward/pull back map from the values on reference to the values on a physical cell...
Definition FiniteElement.cpp:465
Finite element method functionality.
Definition assemble_matrix_impl.h:26
CellType
Cell type identifier.
Definition cell_types.h:22