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.6.0
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 <dolfinx/mesh/cell_types.h>
12#include <functional>
13#include <memory>
14#include <span>
15#include <utility>
16#include <vector>
17
18struct ufcx_finite_element;
19
20namespace dolfinx::fem
21{
25{
26public:
29 explicit FiniteElement(const ufcx_finite_element& e);
30
34 FiniteElement(const basix::FiniteElement& element, int bs);
35
37 FiniteElement(const FiniteElement& element) = delete;
38
40 FiniteElement(FiniteElement&& element) = default;
41
43 virtual ~FiniteElement() = default;
44
46 FiniteElement& operator=(const FiniteElement& element) = delete;
47
49 FiniteElement& operator=(FiniteElement&& element) = default;
50
55 bool operator==(const FiniteElement& e) const;
56
61 bool operator!=(const FiniteElement& e) const;
62
69 std::string signature() const noexcept;
70
73 mesh::CellType cell_shape() const noexcept;
74
78 int space_dimension() const noexcept;
79
84 int block_size() const noexcept;
85
92 int value_size() const;
93
97 int reference_value_size() const;
98
101 std::span<const std::size_t> value_shape() const noexcept;
102
105 std::string family() const noexcept;
106
118 void tabulate(std::span<double> values, std::span<const double> X,
119 std::array<std::size_t, 2> shape, int order) const;
120
130 std::pair<std::vector<double>, std::array<std::size_t, 4>>
131 tabulate(std::span<const double> X, std::array<std::size_t, 2> shape,
132 int order) const;
133
136 int num_sub_elements() const noexcept;
137
142 bool is_mixed() const noexcept;
143
145 const std::vector<std::shared_ptr<const FiniteElement>>&
146 sub_elements() const noexcept;
147
149 std::shared_ptr<const FiniteElement>
150 extract_sub_element(const std::vector<int>& component) const;
151
153 const basix::FiniteElement& basix_element() const;
154
156 basix::maps::type map_type() const;
157
164 bool interpolation_ident() const noexcept;
165
169 bool map_ident() const noexcept;
170
181 std::pair<std::vector<double>, std::array<std::size_t, 2>>
182 interpolation_points() const;
183
193 std::pair<std::vector<double>, std::array<std::size_t, 2>>
195
208 std::pair<std::vector<double>, std::array<std::size_t, 2>>
210
224 bool needs_dof_transformations() const noexcept;
225
240 bool needs_dof_permutations() const noexcept;
241
259 template <typename T>
260 std::function<void(const std::span<T>&, const std::span<const std::uint32_t>&,
261 std::int32_t, int)>
262 get_dof_transformation_function(bool inverse = false, bool transpose = false,
263 bool scalar_element = false) const
264 {
266 {
267 // If no permutation needed, return function that does nothing
268 return [](const std::span<T>&, const std::span<const std::uint32_t>&,
269 std::int32_t, int)
270 {
271 // Do nothing
272 };
273 }
274
275 if (_sub_elements.size() != 0)
276 {
277 if (_bs == 1)
278 {
279 // Mixed element
280 std::vector<std::function<void(const std::span<T>&,
281 const std::span<const std::uint32_t>&,
282 std::int32_t, int)>>
283 sub_element_functions;
284 std::vector<int> dims;
285 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
286 {
287 sub_element_functions.push_back(
288 _sub_elements[i]->get_dof_transformation_function<T>(inverse,
289 transpose));
290 dims.push_back(_sub_elements[i]->space_dimension());
291 }
292
293 return [dims, sub_element_functions](
294 const std::span<T>& data,
295 const std::span<const std::uint32_t>& cell_info,
296 std::int32_t cell, int block_size)
297 {
298 std::size_t offset = 0;
299 for (std::size_t e = 0; e < sub_element_functions.size(); ++e)
300 {
301 const std::size_t width = dims[e] * block_size;
302 sub_element_functions[e](data.subspan(offset, width), cell_info,
304 offset += width;
305 }
306 };
307 }
308 else if (!scalar_element)
309 {
310 // Vector element
311 const std::function<void(const std::span<T>&,
312 const std::span<const std::uint32_t>&,
313 std::int32_t, int)>
314 sub_function = _sub_elements[0]->get_dof_transformation_function<T>(
315 inverse, transpose);
316 const int ebs = _bs;
317 return
318 [ebs, sub_function](const std::span<T>& data,
319 const std::span<const std::uint32_t>& cell_info,
320 std::int32_t cell, int data_block_size)
321 { sub_function(data, cell_info, cell, ebs * data_block_size); };
322 }
323 }
324 if (transpose)
325 {
326 if (inverse)
327 {
328 return [this](const std::span<T>& data,
329 const std::span<const std::uint32_t>& cell_info,
330 std::int32_t cell, int block_size)
331 {
333 block_size);
334 };
335 }
336 else
337 {
338 return [this](const std::span<T>& data,
339 const std::span<const std::uint32_t>& cell_info,
340 std::int32_t cell, int block_size) {
342 };
343 }
344 }
345 else
346 {
347 if (inverse)
348 {
349 return [this](const std::span<T>& data,
350 const std::span<const std::uint32_t>& cell_info,
351 std::int32_t cell, int block_size) {
353 };
354 }
355 else
356 {
357 return [this](const std::span<T>& data,
358 const std::span<const std::uint32_t>& cell_info,
359 std::int32_t cell, int block_size)
360 { apply_dof_transformation(data, cell_info[cell], block_size); };
361 }
362 }
363 }
364
383 template <typename T>
384 std::function<void(const std::span<T>&, const std::span<const std::uint32_t>&,
385 std::int32_t, int)>
387 bool transpose = false,
388 bool scalar_element
389 = false) const
390 {
392 {
393 // If no permutation needed, return function that does nothing
394 return [](const std::span<T>&, const std::span<const std::uint32_t>&,
395 std::int32_t, int)
396 {
397 // Do nothing
398 };
399 }
400 else if (_sub_elements.size() != 0)
401 {
402 if (_bs == 1)
403 {
404 // Mixed element
405 std::vector<std::function<void(const std::span<T>&,
406 const std::span<const std::uint32_t>&,
407 std::int32_t, int)>>
408 sub_element_functions;
409 for (std::size_t i = 0; i < _sub_elements.size(); ++i)
410 {
411 sub_element_functions.push_back(
412 _sub_elements[i]->get_dof_transformation_to_transpose_function<T>(
413 inverse, transpose));
414 }
415
416 return [this, sub_element_functions](
417 const std::span<T>& data,
418 const std::span<const std::uint32_t>& cell_info,
419 std::int32_t cell, int block_size)
420 {
421 std::size_t offset = 0;
422 for (std::size_t e = 0; e < sub_element_functions.size(); ++e)
423 {
424 sub_element_functions[e](data.subspan(offset, data.size() - offset),
425 cell_info, cell, block_size);
426 offset += _sub_elements[e]->space_dimension();
427 }
428 };
429 }
430 else if (!scalar_element)
431 {
432 // Vector element
433 const std::function<void(const std::span<T>&,
434 const std::span<const std::uint32_t>&,
435 std::int32_t, int)>
436 sub_function = _sub_elements[0]->get_dof_transformation_function<T>(
437 inverse, transpose);
438 return [this,
439 sub_function](const std::span<T>& data,
440 const std::span<const std::uint32_t>& cell_info,
441 std::int32_t cell, int data_block_size)
442 {
443 const int ebs = block_size();
444 const std::size_t dof_count = data.size() / data_block_size;
445 for (int block = 0; block < data_block_size; ++block)
446 {
447 sub_function(data.subspan(block * dof_count, dof_count), cell_info,
448 cell, ebs);
449 }
450 };
451 }
452 }
453
454 if (transpose)
455 {
456 if (inverse)
457 {
458 return [this](const std::span<T>& data,
459 const std::span<const std::uint32_t>& cell_info,
460 std::int32_t cell, int block_size)
461 {
463 data, cell_info[cell], block_size);
464 };
465 }
466 else
467 {
468 return [this](const std::span<T>& data,
469 const std::span<const std::uint32_t>& cell_info,
470 std::int32_t cell, int block_size)
471 {
473 block_size);
474 };
475 }
476 }
477 else
478 {
479 if (inverse)
480 {
481 return [this](const std::span<T>& data,
482 const std::span<const std::uint32_t>& cell_info,
483 std::int32_t cell, int block_size)
484 {
486 block_size);
487 };
488 }
489 else
490 {
491 return [this](const std::span<T>& data,
492 const std::span<const std::uint32_t>& cell_info,
493 std::int32_t cell, int block_size) {
495 block_size);
496 };
497 }
498 }
499 }
500
507 template <typename T>
508 void apply_dof_transformation(const std::span<T>& data,
509 std::uint32_t cell_permutation,
510 int block_size) const
511 {
512 assert(_element);
513 _element->apply_dof_transformation(data, block_size, cell_permutation);
514 }
515
524 template <typename T>
525 void
527 std::uint32_t cell_permutation,
528 int block_size) const
529 {
530 assert(_element);
531 _element->apply_inverse_transpose_dof_transformation(data, block_size,
532 cell_permutation);
533 }
534
542 template <typename T>
543 void apply_transpose_dof_transformation(const std::span<T>& data,
544 std::uint32_t cell_permutation,
545 int block_size) const
546 {
547 assert(_element);
548 _element->apply_transpose_dof_transformation(data, block_size,
549 cell_permutation);
550 }
551
559 template <typename T>
560 void apply_inverse_dof_transformation(const std::span<T>& data,
561 std::uint32_t cell_permutation,
562 int block_size) const
563 {
564 assert(_element);
565 _element->apply_inverse_dof_transformation(data, block_size,
566 cell_permutation);
567 }
568
575 template <typename T>
576 void apply_dof_transformation_to_transpose(const std::span<T>& data,
577 std::uint32_t cell_permutation,
578 int block_size) const
579 {
580 assert(_element);
581 _element->apply_dof_transformation_to_transpose(data, block_size,
582 cell_permutation);
583 }
584
591 template <typename T>
592 void
594 std::uint32_t cell_permutation,
595 int block_size) const
596 {
597 assert(_element);
598 _element->apply_inverse_dof_transformation_to_transpose(data, block_size,
599 cell_permutation);
600 }
601
608 template <typename T>
610 const std::span<T>& data, std::uint32_t cell_permutation,
611 int block_size) const
612 {
613 assert(_element);
614 _element->apply_transpose_dof_transformation_to_transpose(data, block_size,
615 cell_permutation);
616 }
617
624 template <typename T>
626 const std::span<T>& data, std::uint32_t cell_permutation,
627 int block_size) const
628 {
629 assert(_element);
630 _element->apply_inverse_transpose_dof_transformation_to_transpose(
631 data, block_size, cell_permutation);
632 }
633
638 void permute_dofs(const std::span<std::int32_t>& doflist,
639 std::uint32_t cell_permutation) const;
640
645 void unpermute_dofs(const std::span<std::int32_t>& doflist,
646 std::uint32_t cell_permutation) const;
647
659 std::function<void(const std::span<std::int32_t>&, std::uint32_t)>
660 get_dof_permutation_function(bool inverse = false,
661 bool scalar_element = false) const;
662
663private:
664 std::string _signature, _family;
665
666 mesh::CellType _cell_shape;
667
668 int _space_dim;
669
670 // List of sub-elements (if any)
671 std::vector<std::shared_ptr<const FiniteElement>> _sub_elements;
672
673 // Dimension of each value space
674 std::vector<std::size_t> _value_shape;
675
676 // Block size for VectorElements and TensorElements. This gives the
677 // number of DOFs co-located at each dof 'point'.
678 int _bs;
679
680 // Indicate whether the element needs permutations or transformations
681 bool _needs_dof_permutations;
682 bool _needs_dof_transformations;
683
684 // Basix Element (nullptr for mixed elements)
685 std::unique_ptr<basix::FiniteElement> _element;
686};
687} // namespace dolfinx::fem
Finite Element, containing the dof layout on a reference element, and various methods for evaluating ...
Definition: FiniteElement.h:25
FiniteElement & operator=(const FiniteElement &element)=delete
Copy assignment.
void apply_inverse_dof_transformation(const std::span< T > &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:560
std::string family() const noexcept
The finite element family.
Definition: FiniteElement.cpp:347
std::pair< std::vector< double >, 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:452
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:504
void apply_inverse_dof_transformation_to_transpose(const std::span< T > &data, std::uint32_t cell_permutation, int block_size) const
Apply inverse of DOF transformation to some transposed data.
Definition: FiniteElement.h:593
basix::maps::type map_type() const
Get the map type used by the element.
Definition: FiniteElement.cpp:403
int space_dimension() const noexcept
Dimension of the finite element function space (the number of degrees-of-freedom for the element)
Definition: FiniteElement.cpp:326
std::function< void(const std::span< T > &, 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:262
void apply_transpose_dof_transformation(const std::span< T > &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:543
std::function< void(const std::span< T > &, 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:386
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:494
FiniteElement(const FiniteElement &element)=delete
Copy constructor.
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:510
void apply_transpose_dof_transformation_to_transpose(const std::span< T > &data, std::uint32_t cell_permutation, int block_size) const
Apply transpose of transformation to some transposed data.
Definition: FiniteElement.h:609
std::string signature() const noexcept
String identifying the finite element.
Definition: FiniteElement.cpp:319
bool needs_dof_permutations() const noexcept
Check if DOF permutations are needed for this element.
Definition: FiniteElement.cpp:499
void apply_dof_transformation_to_transpose(const std::span< T > &data, std::uint32_t cell_permutation, int block_size) const
Apply DOF transformation to some transposed data.
Definition: FiniteElement.h:576
void apply_dof_transformation(const std::span< T > &data, std::uint32_t cell_permutation, int block_size) const
Apply DOF transformation to some data.
Definition: FiniteElement.h:508
std::pair< std::vector< double >, 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:440
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:370
std::pair< std::vector< double >, std::array< std::size_t, 2 > > interpolation_points() const
Points on the reference cell at which an expression need to be evaluated in order to interpolate the ...
Definition: FiniteElement.cpp:427
std::shared_ptr< const FiniteElement > extract_sub_element(const std::vector< int > &component) const
Extract sub finite element for component.
Definition: FiniteElement.cpp:382
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:334
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:328
virtual ~FiniteElement()=default
Destructor.
bool operator!=(const FiniteElement &e) const
Check if two elements are not equivalent.
Definition: FiniteElement.cpp:314
void tabulate(std::span< double > values, std::span< const double > 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:349
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:342
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:365
const basix::FiniteElement & basix_element() const
Return underlying basix element (if it exists)
Definition: FiniteElement.cpp:392
int block_size() const noexcept
Block size of the finite element function space. For VectorElements and TensorElements,...
Definition: FiniteElement.cpp:340
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:517
const std::vector< std::shared_ptr< const FiniteElement > > & sub_elements() const noexcept
Subelements (if any)
Definition: FiniteElement.cpp:376
bool interpolation_ident() const noexcept
Check if interpolation into the finite element space is an identity operation given the evaluation on...
Definition: FiniteElement.cpp:420
void apply_inverse_transpose_dof_transformation_to_transpose(const std::span< T > &data, std::uint32_t cell_permutation, int block_size) const
Apply inverse transpose transformation to some transposed data.
Definition: FiniteElement.h:625
void apply_inverse_transpose_dof_transformation(const std::span< T > &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:526
bool operator==(const FiniteElement &e) const
Check if two elements are equivalent.
Definition: FiniteElement.cpp:304
mesh::CellType cell_shape() const noexcept
Cell shape.
Definition: FiniteElement.cpp:321
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:414
Finite element method functionality.
Definition: assemble_matrix_impl.h:25
CellType
Cell type identifier.
Definition: cell_types.h:22