Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/dolfinx/v0.9.0/cpp/doxygen/de/d83/FiniteElement_8h_source.html
DOLFINx 0.7.3
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 <array>
10#include <basix/finite-element.h>
11#include <concepts>
12#include <dolfinx/mesh/cell_types.h>
13#include <functional>
14#include <memory>
15#include <span>
16#include <utility>
17#include <vector>
18
19struct ufcx_finite_element;
20
21namespace dolfinx::fem
22{
25template <std::floating_point T>
27{
28public:
31 explicit FiniteElement(const ufcx_finite_element& e);
32
41 const std::vector<std::size_t>& value_shape);
42
44 FiniteElement(const FiniteElement& element) = delete;
45
47 FiniteElement(FiniteElement&& element) = default;
48
50 virtual ~FiniteElement() = default;
51
53 FiniteElement& operator=(const FiniteElement& element) = delete;
54
56 FiniteElement& operator=(FiniteElement&& element) = default;
57
62 bool operator==(const FiniteElement& e) const;
63
68 bool operator!=(const FiniteElement& e) const;
69
76 std::string signature() const noexcept;
77
80 mesh::CellType cell_shape() const noexcept;
81
85 int space_dimension() const noexcept;
86
91 int block_size() const noexcept;
92
99 int value_size() const;
100
104 int reference_value_size() const;
105
108 std::span<const std::size_t> value_shape() const noexcept;
109
112 std::string family() const noexcept;
113
125 void tabulate(std::span<T> values, std::span<const T> X,
126 std::array<std::size_t, 2> shape, int order) const;
127
137 std::pair<std::vector<T>, std::array<std::size_t, 4>>
138 tabulate(std::span<const T> X, std::array<std::size_t, 2> shape,
139 int order) const;
140
143 int num_sub_elements() const noexcept;
144
149 bool is_mixed() const noexcept;
150
152 const std::vector<std::shared_ptr<const FiniteElement<T>>>&
153 sub_elements() const noexcept;
154
156 std::shared_ptr<const FiniteElement<T>>
157 extract_sub_element(const std::vector<int>& component) const;
158
160 const basix::FiniteElement<T>& basix_element() const;
161
163 basix::maps::type map_type() const;
164
171 bool interpolation_ident() const noexcept;
172
177 bool map_ident() const noexcept;
178
189 std::pair<std::vector<T>, std::array<std::size_t, 2>>
190 interpolation_points() const;
191
201 std::pair<std::vector<T>, std::array<std::size_t, 2>>
203
216 std::pair<std::vector<T>, std::array<std::size_t, 2>>
218
232 bool needs_dof_transformations() const noexcept;
233
248 bool needs_dof_permutations() const noexcept;
249
267 template <typename U>
268 std::function<void(const std::span<U>&, const std::span<const std::uint32_t>&,
269 std::int32_t, int)>
270 get_dof_transformation_function(bool inverse = false, bool transpose = false,
271 bool scalar_element = false) const
272 {
274 {
275 // If no permutation needed, return function that does nothing
276 return [](const std::span<U>&, const std::span<const std::uint32_t>&,
277 std::int32_t, int)
278 {
279 // Do nothing
280 };
281 }
282
283 if (_sub_elements.size() != 0)
284 {
285 if (_bs == 1)
286 {
287 // Mixed element
288 std::vector<std::function<void(const std::span<U>&,
289 const std::span<const std::uint32_t>&,
290 std::int32_t, int)>>
291 sub_element_functions;
292 std::vector<int> dims;
293 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
294 {
295 sub_element_functions.push_back(
296 _sub_elements[i]->template get_dof_transformation_function<U>(
297 inverse, transpose));
298 dims.push_back(_sub_elements[i]->space_dimension());
299 }
300
301 return [dims, sub_element_functions](
302 const std::span<U>& data,
303 const std::span<const std::uint32_t>& cell_info,
304 std::int32_t cell, int block_size)
305 {
306 std::size_t offset = 0;
307 for (std::size_t e = 0; e < sub_element_functions.size(); ++e)
308 {
309 const std::size_t width = dims[e] * block_size;
310 sub_element_functions[e](data.subspan(offset, width), cell_info,
312 offset += width;
313 }
314 };
315 }
316 else if (!scalar_element)
317 {
318 // Vector element
319 const std::function<void(const std::span<U>&,
320 const std::span<const std::uint32_t>&,
321 std::int32_t, int)>
322 sub_function
323 = _sub_elements[0]->template get_dof_transformation_function<U>(
324 inverse, transpose);
325 const int ebs = _bs;
326 return
327 [ebs, sub_function](const std::span<U>& data,
328 const std::span<const std::uint32_t>& cell_info,
329 std::int32_t cell, int data_block_size)
330 { sub_function(data, cell_info, cell, ebs * data_block_size); };
331 }
332 }
333 if (transpose)
334 {
335 if (inverse)
336 {
337 return [this](const std::span<U>& data,
338 const std::span<const std::uint32_t>& cell_info,
339 std::int32_t cell, int block_size)
340 {
342 block_size);
343 };
344 }
345 else
346 {
347 return [this](const std::span<U>& data,
348 const std::span<const std::uint32_t>& cell_info,
349 std::int32_t cell, int block_size) {
351 };
352 }
353 }
354 else
355 {
356 if (inverse)
357 {
358 return [this](const std::span<U>& data,
359 const std::span<const std::uint32_t>& cell_info,
360 std::int32_t cell, int block_size) {
362 };
363 }
364 else
365 {
366 return [this](const std::span<U>& data,
367 const std::span<const std::uint32_t>& cell_info,
368 std::int32_t cell, int block_size)
369 { apply_dof_transformation(data, cell_info[cell], block_size); };
370 }
371 }
372 }
373
392 template <typename U>
393 std::function<void(const std::span<U>&, const std::span<const std::uint32_t>&,
394 std::int32_t, int)>
396 bool transpose = false,
397 bool scalar_element
398 = false) const
399 {
401 {
402 // If no permutation needed, return function that does nothing
403 return [](const std::span<U>&, const std::span<const std::uint32_t>&,
404 std::int32_t, int)
405 {
406 // Do nothing
407 };
408 }
409 else if (_sub_elements.size() != 0)
410 {
411 if (_bs == 1)
412 {
413 // Mixed element
414 std::vector<std::function<void(const std::span<U>&,
415 const std::span<const std::uint32_t>&,
416 std::int32_t, int)>>
417 sub_element_functions;
418 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
419 {
420 sub_element_functions.push_back(
421 _sub_elements[i]
422 ->template get_dof_transformation_to_transpose_function<U>(
423 inverse, transpose));
424 }
425
426 return [this, sub_element_functions](
427 const std::span<U>& data,
428 const std::span<const std::uint32_t>& cell_info,
429 std::int32_t cell, int block_size)
430 {
431 std::size_t offset = 0;
432 for (std::size_t e = 0; e < sub_element_functions.size(); ++e)
433 {
434 sub_element_functions[e](data.subspan(offset, data.size() - offset),
435 cell_info, cell, block_size);
436 offset += _sub_elements[e]->space_dimension();
437 }
438 };
439 }
440 else if (!scalar_element)
441 {
442 // Vector element
443 const std::function<void(const std::span<U>&,
444 const std::span<const std::uint32_t>&,
445 std::int32_t, int)>
446 sub_function
447 = _sub_elements[0]->template get_dof_transformation_function<U>(
448 inverse, transpose);
449 return [this,
450 sub_function](const std::span<U>& data,
451 const std::span<const std::uint32_t>& cell_info,
452 std::int32_t cell, int data_block_size)
453 {
454 const int ebs = block_size();
455 const std::size_t dof_count = data.size() / data_block_size;
456 for (int block = 0; block < data_block_size; ++block)
457 {
458 sub_function(data.subspan(block * dof_count, dof_count), cell_info,
459 cell, ebs);
460 }
461 };
462 }
463 }
464
465 if (transpose)
466 {
467 if (inverse)
468 {
469 return [this](const std::span<U>& data,
470 const std::span<const std::uint32_t>& cell_info,
471 std::int32_t cell, int block_size)
472 {
474 data, cell_info[cell], block_size);
475 };
476 }
477 else
478 {
479 return [this](const std::span<U>& data,
480 const std::span<const std::uint32_t>& cell_info,
481 std::int32_t cell, int block_size)
482 {
484 block_size);
485 };
486 }
487 }
488 else
489 {
490 if (inverse)
491 {
492 return [this](const std::span<U>& data,
493 const std::span<const std::uint32_t>& cell_info,
494 std::int32_t cell, int block_size)
495 {
497 block_size);
498 };
499 }
500 else
501 {
502 return [this](const std::span<U>& data,
503 const std::span<const std::uint32_t>& cell_info,
504 std::int32_t cell, int block_size) {
506 block_size);
507 };
508 }
509 }
510 }
511
518 template <typename U>
519 void apply_dof_transformation(const std::span<U>& data,
520 std::uint32_t cell_permutation,
521 int block_size) const
522 {
523 assert(_element);
524 _element->apply_dof_transformation(data, block_size, cell_permutation);
525 }
526
535 template <typename U>
536 void
538 std::uint32_t cell_permutation,
539 int block_size) const
540 {
541 assert(_element);
542 _element->apply_inverse_transpose_dof_transformation(data, block_size,
543 cell_permutation);
544 }
545
553 template <typename U>
554 void apply_transpose_dof_transformation(const std::span<U>& data,
555 std::uint32_t cell_permutation,
556 int block_size) const
557 {
558 assert(_element);
559 _element->apply_transpose_dof_transformation(data, block_size,
560 cell_permutation);
561 }
562
570 template <typename U>
571 void apply_inverse_dof_transformation(const std::span<U>& data,
572 std::uint32_t cell_permutation,
573 int block_size) const
574 {
575 assert(_element);
576 _element->apply_inverse_dof_transformation(data, block_size,
577 cell_permutation);
578 }
579
586 template <typename U>
587 void apply_dof_transformation_to_transpose(const std::span<U>& data,
588 std::uint32_t cell_permutation,
589 int block_size) const
590 {
591 assert(_element);
592 _element->apply_dof_transformation_to_transpose(data, block_size,
593 cell_permutation);
594 }
595
602 template <typename U>
603 void
605 std::uint32_t cell_permutation,
606 int block_size) const
607 {
608 assert(_element);
609 _element->apply_inverse_dof_transformation_to_transpose(data, block_size,
610 cell_permutation);
611 }
612
619 template <typename U>
621 const std::span<U>& data, std::uint32_t cell_permutation,
622 int block_size) const
623 {
624 assert(_element);
625 _element->apply_transpose_dof_transformation_to_transpose(data, block_size,
626 cell_permutation);
627 }
628
635 template <typename U>
637 const std::span<U>& data, std::uint32_t cell_permutation,
638 int block_size) const
639 {
640 assert(_element);
641 _element->apply_inverse_transpose_dof_transformation_to_transpose(
642 data, block_size, cell_permutation);
643 }
644
649 void permute_dofs(const std::span<std::int32_t>& doflist,
650 std::uint32_t cell_permutation) const;
651
656 void unpermute_dofs(const std::span<std::int32_t>& doflist,
657 std::uint32_t cell_permutation) const;
658
670 std::function<void(const std::span<std::int32_t>&, std::uint32_t)>
671 get_dof_permutation_function(bool inverse = false,
672 bool scalar_element = false) const;
673
674private:
675 std::string _signature, _family;
676
677 mesh::CellType _cell_shape;
678
679 int _space_dim;
680
681 // List of sub-elements (if any)
682 std::vector<std::shared_ptr<const FiniteElement<T>>> _sub_elements;
683
684 // Dimension of each value space
685 std::vector<std::size_t> _value_shape;
686
687 // Block size for BlockedElements. This gives the
688 // number of DOFs co-located at each dof 'point'.
689 int _bs;
690
691 // Indicate whether the element needs permutations or transformations
692 bool _needs_dof_permutations;
693 bool _needs_dof_transformations;
694
695 // Basix Element (nullptr for mixed elements)
696 std::unique_ptr<basix::FiniteElement<T>> _element;
697};
698} // 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:27
FiniteElement & operator=(const FiniteElement &element)=delete
Copy assignment.
std::string family() const noexcept
The finite element family.
Definition FiniteElement.cpp:388
const std::vector< std::shared_ptr< const FiniteElement< T > > > & sub_elements() const noexcept
Subelements (if any)
Definition FiniteElement.cpp:425
void permute_dofs(const std::span< std::int32_t > &doflist, std::uint32_t cell_permutation) const
Permute the DOFs of the element.
Definition FiniteElement.cpp:563
std::pair< std::vector< T >, 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:508
void apply_dof_transformation(const std::span< U > &data, std::uint32_t cell_permutation, int block_size) const
Apply DOF transformation to some data.
Definition FiniteElement.h:519
basix::maps::type map_type() const
Get the map type used by the element.
Definition FiniteElement.cpp:454
int space_dimension() const noexcept
Dimension of the finite element function space (the number of degrees-of-freedom for the element)
Definition FiniteElement.cpp:356
void apply_transpose_dof_transformation_to_transpose(const std::span< U > &data, std::uint32_t cell_permutation, int block_size) const
Apply transpose of transformation to some transposed data.
Definition FiniteElement.h:620
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:551
FiniteElement(const FiniteElement &element)=delete
Copy constructor.
void apply_inverse_dof_transformation_to_transpose(const 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:604
std::pair< std::vector< T >, 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:481
void unpermute_dofs(const std::span< std::int32_t > &doflist, std::uint32_t cell_permutation) const
Unpermute the DOFs of the element.
Definition FiniteElement.cpp:570
std::shared_ptr< const FiniteElement< T > > extract_sub_element(const std::vector< int > &component) const
Extract sub finite element for component.
Definition FiniteElement.cpp:432
std::string signature() const noexcept
String identifying the finite element.
Definition FiniteElement.cpp:344
bool needs_dof_permutations() const noexcept
Check if DOF permutations are needed for this element.
Definition FiniteElement.cpp:557
bool is_mixed() const noexcept
Check if element is a mixed element, i.e. composed of two or more elements of different types....
Definition FiniteElement.cpp:418
void apply_inverse_dof_transformation(const 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:571
void tabulate(std::span< T > values, std::span< const T > 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:394
void apply_inverse_transpose_dof_transformation(const 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:537
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:369
int 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:362
void apply_transpose_dof_transformation(const 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:554
virtual ~FiniteElement()=default
Destructor.
bool operator!=(const FiniteElement &e) const
Check if two elements are not equivalent.
Definition FiniteElement.cpp:338
void apply_dof_transformation_to_transpose(const std::span< U > &data, std::uint32_t cell_permutation, int block_size) const
Apply DOF transformation to some transposed data.
Definition FiniteElement.h:587
std::function< void(const std::span< U > &, const std::span< const std::uint32_t > &, std::int32_t, int)> get_dof_transformation_to_transpose_function(bool inverse=false, bool transpose=false, bool scalar_element=false) const
Return a function that applies DOF transformation to some transposed data.
Definition FiniteElement.h:395
const basix::FiniteElement< T > & basix_element() const
Return underlying basix element (if it exists)
Definition FiniteElement.cpp:442
std::span< const std::size_t > value_shape() const noexcept
Shape of the value space. The rank is the size of the value_shape.
Definition FiniteElement.cpp:382
void apply_inverse_transpose_dof_transformation_to_transpose(const std::span< U > &data, std::uint32_t cell_permutation, int block_size) const
Apply inverse transpose transformation to some transposed data.
Definition FiniteElement.h:636
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:412
std::pair< std::vector< T >, 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:495
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:376
std::function< void(const 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.
Definition FiniteElement.cpp:578
std::function< void(const std::span< U > &, const std::span< const std::uint32_t > &, std::int32_t, int)> get_dof_transformation_function(bool inverse=false, bool transpose=false, bool scalar_element=false) const
Return a function that applies DOF transformation to some data.
Definition FiniteElement.h:270
bool interpolation_ident() const noexcept
Check if interpolation into the finite element space is an identity operation given the evaluation on...
Definition FiniteElement.cpp:473
bool operator==(const FiniteElement &e) const
Check if two elements are equivalent.
Definition FiniteElement.cpp:326
mesh::CellType cell_shape() const noexcept
Cell shape.
Definition FiniteElement.cpp:350
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:466
Finite element method functionality.
Definition assemble_matrix_impl.h:25
CellType
Cell type identifier.
Definition cell_types.h:22