LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
lagr_fe.h
1#ifndef LF_FE
2#define LF_FE
3/***************************************************************************
4 * LehrFEM++ - A simple C++ finite element libray for teaching
5 * Developed from 2018 at the Seminar of Applied Mathematics of ETH Zurich,
6 * lead developers Dr. R. Casagrande and Prof. R. Hiptmair
7 ***************************************************************************/
8
17#include <lf/assemble/dofhandler.h>
18#include <lf/fe/fe_point.h>
19#include <lf/fe/scalar_reference_finite_element.h>
20
21#include <iostream>
22#include <typeinfo>
23
24namespace lf::uscalfe {
37
56template <typename SCALAR>
59 public:
61 FeLagrangeO1Tria(FeLagrangeO1Tria&&) noexcept = default;
62 FeLagrangeO1Tria& operator=(const FeLagrangeO1Tria&) = default;
63 FeLagrangeO1Tria& operator=(FeLagrangeO1Tria&&) noexcept = default;
64 FeLagrangeO1Tria() = default;
65 ~FeLagrangeO1Tria() override = default;
66
67 [[nodiscard]] base::RefEl RefEl() const override {
68 return base::RefEl::kTria();
69 }
70
71 [[nodiscard]] unsigned Degree() const override { return 1; }
72
76 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 3; }
77
78 // clang-format off
83 // clang-format on
84 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
85 LF_ASSERT_MSG(codim <= 2, "Illegal codim " << codim);
86 return (codim == 2) ? 1 : 0;
87 }
88 // clang-format off
93 // clang-format on
95 dim_t codim, sub_idx_t subidx) const override {
96 LF_ASSERT_MSG(codim <= 2, "Illegal codim " << codim);
97 LF_ASSERT_MSG((codim == 2 && subidx < 3) || (codim == 1 && subidx < 3) ||
98 (codim == 0 && subidx == 0),
99 "codim/subidx out of range.");
100 return (codim == 2) ? 1 : 0;
101 }
102
103 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
104 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
105 LF_ASSERT_MSG(refcoords.rows() == 2,
106 "Reference coordinates must be 2-vectors");
107 const size_type n_pts(refcoords.cols());
108 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(
109 3, refcoords.cols());
110 result.row(0) = Eigen::RowVectorXd::Ones(refcoords.cols()) -
111 refcoords.row(0) - refcoords.row(1);
112 result.block(1, 0, 2, refcoords.cols()) = refcoords;
113 return result;
114 }
115
116 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
118 const Eigen::MatrixXd& refcoords) const override {
119 LF_ASSERT_MSG(refcoords.rows() == 2,
120 "Reference coordinates must be 2-vectors");
121 const size_type n_pts(refcoords.cols());
122
123 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(
124 3, 2 * refcoords.cols());
125 result.row(0) = Eigen::RowVectorXd::Constant(2 * n_pts, -1);
126 result.row(1) = Eigen::RowVector2d(1., 0.).replicate(1, n_pts);
127 result.row(2) = Eigen::RowVector2d(0., 1.).replicate(1, n_pts);
128 return result;
129 }
130
134 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
135 return RefEl().NodeCoords();
136 }
137
141 [[nodiscard]] size_type NumEvaluationNodes() const override {
142 return RefEl().NumNodes();
143 }
144};
145
163template <typename SCALAR>
165 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
166 public:
168 FeLagrangeO1Quad(FeLagrangeO1Quad&&) noexcept = default;
169 FeLagrangeO1Quad& operator=(const FeLagrangeO1Quad&) = default;
170 FeLagrangeO1Quad& operator=(FeLagrangeO1Quad&&) noexcept = default;
171 FeLagrangeO1Quad() = default;
172 ~FeLagrangeO1Quad() override = default;
173
174 [[nodiscard]] base::RefEl RefEl() const override {
175 return base::RefEl::kQuad();
176 }
177
178 [[nodiscard]] unsigned Degree() const override { return 1; }
179
183 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 4; }
184
185 // clang-format off
190 // clang-format on
191 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
192 return (codim == 2) ? 1 : 0;
193 }
194
195 // clang-format off
200 // clang-format on
202 dim_t codim, sub_idx_t subidx) const override {
203 LF_ASSERT_MSG((codim == 2 && subidx < 4) || (codim == 1 && subidx < 4) ||
204 (codim == 0 && subidx == 0),
205 "codim/subidx out of range.");
206 return (codim == 2) ? 1 : 0;
207 }
208
209 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
210 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
211 LF_ASSERT_MSG(refcoords.rows() == 2,
212 "Reference coordinates must be 2-vectors");
213
214 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(
215 4, refcoords.cols());
216
217 result.row(0) =
218 ((1 - refcoords.row(0).array()) * (1 - refcoords.row(1).array()))
219 .matrix();
220 result.row(1) =
221 ((refcoords.row(0).array()) * (1 - refcoords.row(1).array())).matrix();
222 result.row(2) =
223 ((refcoords.row(0).array()) * (refcoords.row(1).array())).matrix();
224 result.row(3) =
225 ((1 - refcoords.row(0).array()) * (refcoords.row(1).array())).matrix();
226
227 return result;
228 }
229
230 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
232 const Eigen::MatrixXd& refcoords) const override {
233 LF_ASSERT_MSG(refcoords.rows() == 2,
234 "Reference coordinates must be 2-vectors");
235 size_type n_pts(refcoords.cols());
236
237 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(4, 2 * n_pts);
238
239 // reshape the result matrix into a 8xn_pts matrix
240 Eigen::Map<Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic>,
241 Eigen::AutoAlign>
242 temp(&result(0, 0), 8, n_pts);
243 temp.row(0) = refcoords.row(1).array() - 1.0;
244 temp.row(1) = 1.0 - refcoords.row(1).array();
245 temp.row(2) = refcoords.row(1).array();
246 temp.row(3) = -refcoords.row(1).array();
247 temp.row(4) = refcoords.row(0).array() - 1.0;
248 temp.row(5) = -refcoords.row(0).array();
249 temp.row(6) = refcoords.row(0).array();
250 temp.row(7) = 1.0 - refcoords.row(0).array();
251
252 return result;
253 }
254
255 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
256 return RefEl().NodeCoords();
257 }
258
259 [[nodiscard]] size_type NumEvaluationNodes() const override {
260 return RefEl().NumNodes();
261 }
262};
263
282template <typename SCALAR>
284 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
285 public:
288 FeLagrangeO1Segment& operator=(const FeLagrangeO1Segment&) = default;
289 FeLagrangeO1Segment& operator=(FeLagrangeO1Segment&&) noexcept = default;
291 ~FeLagrangeO1Segment() override = default;
292
293 [[nodiscard]] base::RefEl RefEl() const override {
294 return base::RefEl::kSegment();
295 }
296
297 [[nodiscard]] unsigned Degree() const override { return 1; }
298
302 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 2; }
303
304 // clang-format off
308 // clang-format on
309 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
310 LF_ASSERT_MSG(codim <= 1, "Illegal codim " << codim);
311 return (codim == 1) ? 1 : 0;
312 }
313
314 // clang-format off
318 // clang-format on
320 dim_t codim, sub_idx_t subidx) const override {
321 LF_ASSERT_MSG(codim <= 1, "Illegal codim " << codim);
322 LF_ASSERT_MSG((codim == 1 && subidx < 2) || (codim == 0 && subidx == 0),
323 "codim/subidx out of range.");
324 return (codim == 1) ? 1 : 0;
325 }
326
327 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
328 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
329 LF_ASSERT_MSG(refcoords.rows() == 1,
330 "Reference coordinates must be 1-vectors");
331 const size_type n_pts(refcoords.cols());
332
333 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(
334 2, refcoords.cols());
335 result.row(0) = Eigen::RowVectorXd::Constant(1, n_pts, 1.0) - refcoords;
336 result.row(1) = refcoords;
337
338 return result;
339 }
340
341 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
343 const Eigen::MatrixXd& refcoords) const override {
344 LF_ASSERT_MSG(refcoords.rows() == 1,
345 "Reference coordinates must be 1-vectors");
346 const size_type n_pts(refcoords.cols());
347
348 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(
349 2, refcoords.cols());
350 result.row(0) = Eigen::MatrixXd::Constant(1, n_pts, -1.0);
351 result.row(1) = Eigen::MatrixXd::Constant(1, n_pts, 1.0);
352
353 return result;
354 }
355
359 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
360 return RefEl().NodeCoords();
361 }
362
366 [[nodiscard]] size_type NumEvaluationNodes() const override {
367 return RefEl().NumNodes();
368 }
369};
370
398template <typename SCALAR>
400 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
401 public:
403 FeLagrangeO2Tria(FeLagrangeO2Tria&&) noexcept = default;
404 FeLagrangeO2Tria& operator=(const FeLagrangeO2Tria&) = default;
405 FeLagrangeO2Tria& operator=(FeLagrangeO2Tria&&) noexcept = default;
406 FeLagrangeO2Tria() = default;
407 ~FeLagrangeO2Tria() override = default;
408
411 [[nodiscard]] base::RefEl RefEl() const override {
412 return base::RefEl::kTria();
413 }
414
418 [[nodiscard]] unsigned Degree() const override { return 2; }
419
425 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 6; }
426
433 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
434 LF_ASSERT_MSG(codim <= 2, "Illegal codim" << codim);
435 return (codim == 0) ? 0 : 1;
436 }
437
445 dim_t codim, sub_idx_t /*subidx*/) const override {
446 LF_ASSERT_MSG(codim <= 2, "Illegal codim" << codim);
447 return (codim == 0) ? 0 : 1;
448 }
449
457 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
458 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
459 LF_ASSERT_MSG(refcoords.rows() == 2,
460 "Reference coordinates must be 2-vectors");
461 // Number of evaluation points
462 const size_type n_pts(refcoords.cols());
463 // Result returned in 6 x P matrix
464 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(6, n_pts);
465 // Convert to array type for componentwise operations
466 auto x0 = refcoords.row(0).array();
467 auto x1 = refcoords.row(1).array();
468 // Compound evaluation of formulas for reference shape functions
469 result.row(0) = (2.0 * (1 - x0 - x1) * (0.5 - x0 - x1)).matrix();
470 result.row(1) = (2.0 * x0 * (x0 - 0.5)).matrix();
471 result.row(2) = (2.0 * x1 * (x1 - 0.5)).matrix();
472 result.row(3) = (4.0 * (1 - x0 - x1) * x0).matrix();
473 result.row(4) = (4.0 * x0 * x1).matrix();
474 result.row(5) = (4.0 * (1 - x0 - x1) * x1).matrix();
475 return result;
476 }
477
484 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
486 const Eigen::MatrixXd& refcoords) const override {
487 LF_ASSERT_MSG(refcoords.rows() == 2,
488 "Reference coordinates must be 2-vectors");
489 // Number of evaluation points
490 const size_type n_pts(refcoords.cols());
491 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(6, 2 * n_pts);
492 // reshape into a 12xn_pts matrix.
493 Eigen::Map<Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic>,
494 Eigen::AutoAlign>
495 temp(result.data(), 12, n_pts);
496 // Convert to array type for componentwise operations
497 auto x0 = refcoords.row(0).array();
498 auto x1 = refcoords.row(1).array();
499 // d/dx_0 for all reference shape functions
500 temp.row(0) = -3.0 + 4.0 * x0 + 4.0 * x1;
501 temp.row(1) = 4.0 * x0 - 1.0;
502 temp.row(2) = 0.0;
503 temp.row(3) = 4 - 0 - 8.0 * x0 - 4.0 * x1;
504 temp.row(4) = 4.0 * x1;
505 temp.row(5) = -4.0 * x1;
506 // d/dx_1 for the reference shape functions
507 temp.row(6) = -3.0 + 4.0 * x0 + 4.0 * x1;
508 temp.row(7) = 0.0;
509 temp.row(8) = 4.0 * x1 - 1.0;
510 temp.row(9) = -4 * x0;
511 temp.row(10) = 4.0 * x0;
512 temp.row(11) = 4.0 - 8.0 * x1 - 4.0 * x0;
513 return result;
514 }
515
528 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
529 // clang-format off
530 Eigen::Matrix<double, 2,6> nodes;
531 // Reference coordinates of evaluation nodes in the columns of a 2 x 6 - matrix.
532 nodes << 0.0, 1.0, 0.0, 0.5, 0.5, 0.0,
533 0.0, 0.0, 1.0, 0.0, 0.5, 0.5;
534 // clang-format on
535 return nodes;
536 }
537
542 [[nodiscard]] size_type NumEvaluationNodes() const override {
543 return NumRefShapeFunctions();
544 }
545};
546
561template <typename SCALAR>
563 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
564 public:
567 FeLagrangeO2Segment& operator=(const FeLagrangeO2Segment&) = default;
568 FeLagrangeO2Segment& operator=(FeLagrangeO2Segment&&) noexcept = default;
570 ~FeLagrangeO2Segment() override = default;
571
572 [[nodiscard]] base::RefEl RefEl() const override {
573 return base::RefEl::kSegment();
574 }
575
578 [[nodiscard]] unsigned Degree() const override { return 2; }
579
585 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 3; }
586
595 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
596 LF_ASSERT_MSG(codim <= 1, "Illegal codim " << codim);
597 return 1;
598 }
599
606 dim_t codim, sub_idx_t /*subidx*/) const override {
607 LF_ASSERT_MSG(codim <= 1, "Illegal codim " << codim);
608 return 1;
609 }
610
625 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
626 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
627 LF_ASSERT_MSG(refcoords.rows() == 1,
628 "Reference coordinates must be 1-vectors");
629 const size_type n_pts(refcoords.cols());
630 // Matrix for returning values of local shape functions
631 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(3, n_pts);
632 // Convert into an array type for componentwise operations
633 auto x = refcoords.row(0).array();
634 // local shape functions belonging to the endpoints
635 result.row(0) = 2.0 * (1.0 - x) * (0.5 - x);
636 result.row(1) = 2.0 * x * (x - 0.5);
637 // local shape function sitting at midpoint (belonging to segment)
638 result.row(2) = 4.0 * (1.0 - x) * x;
639 return result;
640 }
641
651 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
653 const Eigen::MatrixXd& refcoords) const override {
654 LF_ASSERT_MSG(refcoords.rows() == 1,
655 "Reference coordinates must be 1-vectors");
656 const size_type n_pts(refcoords.cols());
657 // Matrix for returning the derivatives of the local shape functions
658 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(3, n_pts);
659 // Convert to array for componentwise operations
660 auto x = refcoords.row(0).array();
661 // LSF at endpoints
662 result.row(0) = (4.0 * x - 3.0).matrix();
663 result.row(1) = (4.0 * x - 1.0).matrix();
664 // LSF at midpoint:
665 result.row(2) = (4.0 - 8.0 * x).matrix();
666 return result;
667 }
668
672 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
673 Eigen::Matrix<double, 1, 3> nodes;
674 // Reference coordinates of the three evaluation nodes
675 nodes << 0.0, 1.0, 0.5;
676 return nodes;
677 }
678
682 [[nodiscard]] size_type NumEvaluationNodes() const override {
683 return NumRefShapeFunctions();
684 }
685};
686
711template <typename SCALAR>
713 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
714 public:
716 FeLagrangeO2Quad(FeLagrangeO2Quad&&) noexcept = default;
717 FeLagrangeO2Quad& operator=(const FeLagrangeO2Quad&) = default;
718 FeLagrangeO2Quad& operator=(FeLagrangeO2Quad&&) noexcept = default;
719 FeLagrangeO2Quad() = default;
720 ~FeLagrangeO2Quad() override = default;
721
723 [[nodiscard]] base::RefEl RefEl() const override {
724 return base::RefEl::kQuad();
725 }
726
729 [[nodiscard]] unsigned Degree() const override { return 2; }
730
737 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 9; }
738
744 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
745 LF_ASSERT_MSG(codim <= 2, "Illegal codim" << codim);
746 return 1;
747 }
748
756 dim_t codim, sub_idx_t /*subidx*/) const override {
757 LF_ASSERT_MSG(codim <= 2, "Illegal codim" << codim);
758 return 1;
759 }
760
778 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
779 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
780 LF_ASSERT_MSG(refcoords.rows() == 2,
781 "Reference coordinates must be 2-vectors");
782 // Number of evaluation points
783 const size_type n_pts(refcoords.cols());
784 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(9, n_pts);
785
786 // evaluate "segment" shape functions (b^j and b^l)
787 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x0_eval =
788 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(0))).array();
789 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x1_eval =
790 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(1))).array();
791
792 // Evaluate basis functions using the tensor product structure
793 for (int i = 0; i < 9; ++i) {
794 result.row(i) = (segment_x0_eval.row(ksegment_to_quad_mapping_(i, 0)) *
795 segment_x1_eval.row(ksegment_to_quad_mapping_(i, 1)))
796 .matrix();
797 }
798 return result;
799 }
800
810 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
812 const Eigen::MatrixXd& refcoords) const override {
813 LF_ASSERT_MSG(refcoords.rows() == 2,
814 "Reference coordinates must be 2-vectors");
815
816 const size_type n_pts(refcoords.cols());
817 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(9, 2 * n_pts);
818
819 // reshape into a 18xn_pts matrix.
820 Eigen::Map<Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic>,
821 Eigen::AutoAlign>
822 temp(&result(0, 0), 18, n_pts);
823
824 // evaluate "segment" shape functions (b^j and b^l)
825 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x0_eval =
826 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(0))).array();
827 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x1_eval =
828 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(1))).array();
829
830 // evaluate derivatives of "segment" shape functions (b^j and
831 // b^l)
832 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x0_grad =
833 (krsf_segment_.GradientsReferenceShapeFunctions(refcoords.row(0)))
834 .array();
835 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x1_grad =
836 (krsf_segment_.GradientsReferenceShapeFunctions(refcoords.row(1)))
837 .array();
838
839 // evaluate gradients using the product rule and
840 // the tensor product structure of the basis functions.
841 for (int i = 0; i < 9; ++i) {
842 // d/dx
843 temp.row(i) = (segment_x0_grad.row(ksegment_to_quad_mapping_(i, 0)) *
844 segment_x1_eval.row(ksegment_to_quad_mapping_(i, 1)))
845 .matrix();
846 // d/dy
847 temp.row(i + 9) = (segment_x1_grad.row(ksegment_to_quad_mapping_(i, 1)) *
848 segment_x0_eval.row(ksegment_to_quad_mapping_(i, 0)))
849 .matrix();
850 }
851 return result;
852 }
853
863 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
864 Eigen::Matrix<double, 2, 9> nodes;
865
866 // clang-format off
867 nodes << 0.0, 1.0, 1.0, 0.0, 0.5, 1.0, 0.5, 0.0, 0.5,
868 0.0, 0.0, 1.0, 1.0, 0.0, 0.5, 1.0, 0.5, 0.5;
869 // clang-format on
870 return nodes;
871 }
872
877 [[nodiscard]] size_type NumEvaluationNodes() const override {
878 return NumRefShapeFunctions();
879 }
880
881 private:
886
904 const static Eigen::Matrix<int, 9, 2> ksegment_to_quad_mapping_;
905};
906
907template <typename SCALAR>
910
911template <typename SCALAR>
912const Eigen::Matrix<int, 9, 2>
914 // clang-format off
915 (Eigen::Matrix<int,9,2>() << 0, 0,
916 1, 0,
917 1, 1,
918 0, 1,
919 2, 0,
920 1, 2,
921 2, 1,
922 0, 2,
923 2, 2).finished();
924// clang-format on
925
943template <typename SCALAR>
945 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
946 public:
948 FeLagrangeO3Tria(FeLagrangeO3Tria&&) noexcept = default;
949 FeLagrangeO3Tria& operator=(const FeLagrangeO3Tria&) = default;
950 FeLagrangeO3Tria& operator=(FeLagrangeO3Tria&&) noexcept = default;
951 FeLagrangeO3Tria() = default;
952 ~FeLagrangeO3Tria() override = default;
953
954 [[nodiscard]] base::RefEl RefEl() const override {
955 return base::RefEl::kTria();
956 }
957
961 [[nodiscard]] unsigned Degree() const override { return 3; }
962
968 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 10; }
969
970 // clang-format off
977 // clang-format on
978 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
979 LF_ASSERT_MSG(codim <= 2, "Illegal codim" << codim);
980 return (codim == 1) ? 2 : 1;
981 }
982
983 // clang-format off
990 // clang-format on
992 dim_t codim, sub_idx_t subidx) const override {
993 LF_ASSERT_MSG(codim <= 2, "Illegal codim" << codim);
994 LF_ASSERT_MSG((codim == 2 && subidx < 3) || (codim == 1 && subidx < 3) ||
995 (codim == 0 && subidx == 0),
996 "codim/subidx out of range.");
997 return (codim == 1) ? 2 : 1;
998 }
999
1008 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
1009 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
1010 LF_ASSERT_MSG(refcoords.rows() == 2,
1011 "Reference coordinates must be 2-vectors");
1012 // number of points for which evaluation is desired
1013 const size_type n_pts(refcoords.cols());
1014 // Matrix for returning the values of the reference shape functions at the
1015 // specified nodes. Each row corresponds to a reference shape function
1016 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(10, n_pts);
1017
1018 // evaluation of the barycentric coordinate functions
1019 Eigen::Array<double, 1, Eigen::Dynamic> lambda0 =
1020 1 - refcoords.row(0).array() - refcoords.row(1).array();
1021 Eigen::Array<double, 1, Eigen::Dynamic> lambda1 = refcoords.row(0).array();
1022 Eigen::Array<double, 1, Eigen::Dynamic> lambda2 = refcoords.row(1).array();
1023
1024 // evaluation of the shape functions
1025 // The LSF associated with vertices
1026 result.row(0) = 4.5 * lambda0 * (lambda0 - 1 / 3.0) * (lambda0 - 2 / 3.0);
1027 result.row(1) = 4.5 * lambda1 * (lambda1 - 1 / 3.0) * (lambda1 - 2 / 3.0);
1028 result.row(2) = 4.5 * lambda2 * (lambda2 - 1 / 3.0) * (lambda2 - 2 / 3.0);
1029 // Six LSF are attached to edges
1030 result.row(3) = 13.5 * lambda0 * lambda1 * (lambda0 - 1 / 3.0);
1031 result.row(4) = 13.5 * lambda0 * lambda1 * (lambda1 - 1 / 3.0);
1032 result.row(5) = 13.5 * lambda1 * lambda2 * (lambda1 - 1 / 3.0);
1033 result.row(6) = 13.5 * lambda1 * lambda2 * (lambda2 - 1 / 3.0);
1034 result.row(7) = 13.5 * lambda2 * lambda0 * (lambda2 - 1 / 3.0);
1035 result.row(8) = 13.5 * lambda2 * lambda0 * (lambda0 - 1 / 3.0);
1036 // LSF associated with the cell: cubic bubble function
1037 result.row(9) = 27.0 * lambda0 * lambda1 * lambda2;
1038
1039 return result;
1040 }
1041
1049 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
1051 const Eigen::MatrixXd& refcoords) const override {
1052 LF_ASSERT_MSG(refcoords.rows() == 2,
1053 "Reference coordinates must be 2-vectors");
1054
1055 const size_type n_pts(refcoords.cols());
1056 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(10, 2 * n_pts);
1057
1058 // reshape into a 20xn_pts matrix.
1059 Eigen::Map<Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic>,
1060 Eigen::AutoAlign>
1061 temp(&result(0, 0), 20, n_pts);
1062
1063 // evaulate barycentric coordinate functions:
1064 Eigen::Array<double, 1, Eigen::Dynamic> l0 =
1065 1 - refcoords.row(0).array() - refcoords.row(1).array();
1066 auto l1 = refcoords.row(0).array();
1067 auto l2 = refcoords.row(1).array();
1068
1069 // vertex-associated LSF: numbers 0,1,2
1070 temp.row(0) = -4.5 * ((l0 - 1 / 3.0) * (l0 - 2 / 3.0) +
1071 l0 * (l0 - 2 / 3.0) + l0 * (l0 - 1 / 3.0));
1072 temp.row(10) = -4.5 * ((l0 - 1 / 3.0) * (l0 - 2 / 3.0) +
1073 l0 * (l0 - 2 / 3.0) + l0 * (l0 - 1 / 3.0));
1074 temp.row(1) = 4.5 * ((l1 - 1 / 3.0) * (l1 - 2 / 3.0) + l1 * (l1 - 2 / 3.0) +
1075 l1 * (l1 - 1 / 3.0));
1076 temp.row(11) = 0.0;
1077 temp.row(2) = 0.0;
1078 temp.row(12) = 4.5 * ((l2 - 1 / 3.0) * (l2 - 2 / 3.0) +
1079 l2 * (l2 - 2 / 3.0) + l2 * (l2 - 1 / 3.0));
1080 // edge-associated basis functions
1081 temp.row(3) = 13.5 * (-l1 * (l0 - 1 / 3.0) + l0 * (l0 - 1 / 3.0) - l0 * l1);
1082 temp.row(13) = -13.5 * (l1 * (l0 - 1 / 3.0) + l0 * l1);
1083 temp.row(4) = 13.5 * (-l1 * (l1 - 1 / 3.0) + l0 * (l1 - 1 / 3.0) + l0 * l1);
1084 temp.row(14) = -13.5 * l1 * (l1 - 1 / 3.0);
1085 temp.row(5) = 13.5 * (l2 * (l1 - 1 / 3.0) + l1 * l2);
1086 temp.row(15) = 13.5 * (l1 * (l1 - 1 / 3.0));
1087 temp.row(6) = 13.5 * (l2 * (l2 - 1 / 3.0));
1088 temp.row(16) = 13.5 * (l1 * (l2 - 1 / 3.0) + l1 * l2);
1089 temp.row(7) = -13.5 * l2 * (l2 - 1 / 3.0);
1090 temp.row(17) = 13.5 * (l0 * (l2 - 1 / 3.0) - l2 * (l2 - 1 / 3.0) + l0 * l2);
1091 temp.row(8) = -13.5 * (l2 * (l0 - 1 / 3.0) + l2 * l0);
1092 temp.row(18) = 13.5 * (l0 * (l0 - 1 / 3.0) - l2 * (l0 - 1 / 3.0) - l2 * l0);
1093 // cell-associated LSF
1094 temp.row(9) = 27.0 * (-l1 * l2 + l0 * l2);
1095 temp.row(19) = 27.0 * (-l1 * l2 + l0 * l1);
1096
1097 return result;
1098 }
1099
1112 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
1113 Eigen::Matrix<double, 2, 10> nodes;
1114 Eigen::Matrix<double, 2, 3> vertices;
1115 Eigen::Matrix<double, 2, 6> edges;
1116 Eigen::Matrix<double, 2, 1> center;
1117
1118 // clang-format off
1119 vertices << 0.0, 1.0, 0.0,
1120 0.0, 0.0, 1.0;
1121 edges << 1.0, 2.0, 2.0, 1.0, 0.0, 0.0,
1122 0.0, 0.0, 1.0, 2.0, 2.0, 1.0;
1123 center << 1.0 / 3.0,
1124 1.0 / 3.0;
1125 // clang-format on
1126 edges *= 1.0 / 3.0;
1127 nodes << vertices, edges, center;
1128
1129 return nodes;
1130 }
1134 [[nodiscard]] size_type NumEvaluationNodes() const override {
1135 return NumRefShapeFunctions();
1136 }
1137};
1138
1151template <typename SCALAR>
1153 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
1154 public:
1157 FeLagrangeO3Segment& operator=(const FeLagrangeO3Segment&) = default;
1158 FeLagrangeO3Segment& operator=(FeLagrangeO3Segment&&) noexcept = default;
1160 ~FeLagrangeO3Segment() override = default;
1161
1162 [[nodiscard]] base::RefEl RefEl() const override {
1163 return base::RefEl::kSegment();
1164 }
1165
1166 [[nodiscard]] unsigned Degree() const override { return 3; }
1167
1168 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 4; }
1169
1170 // clang-format off
1175 // clang-format on
1176 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
1177 LF_ASSERT_MSG(codim <= 1, "Illegal codim " << codim);
1178 return (codim == 0) ? 2 : 1;
1179 }
1180
1181 // clang-format off
1186 // clang-format on
1188 dim_t codim, sub_idx_t subidx) const override {
1189 LF_ASSERT_MSG(codim <= 1, "Illegal codim " << codim);
1190 LF_ASSERT_MSG((codim == 1 && subidx < 2) || (codim == 0 && subidx == 0),
1191 "codim/subidx out of range.");
1192 return (codim == 0) ? 2 : 1;
1193 }
1194
1195 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
1196 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
1197 LF_ASSERT_MSG(refcoords.rows() == 1,
1198 "Reference coordinates must be 1-vectors");
1199 const size_type n_pts(refcoords.cols());
1200
1201 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(4, n_pts);
1202
1203 auto x = refcoords.row(0).array();
1204
1205 // endpoints
1206 result.row(0) = 4.5 * (1.0 - x) * (1.0 / 3.0 - x) * (2.0 / 3.0 - x);
1207 result.row(1) = 4.5 * x * (x - 1.0 / 3.0) * (x - 2.0 / 3.0);
1208
1209 // interior
1210 result.row(2) = 13.5 * x * (1 - x) * (2.0 / 3.0 - x);
1211 result.row(3) = 13.5 * x * (1 - x) * (x - 1.0 / 3.0);
1212
1213 return result;
1214 }
1215
1216 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
1218 const Eigen::MatrixXd& refcoords) const override {
1219 LF_ASSERT_MSG(refcoords.rows() == 1,
1220 "Reference coordinates must be 1-vectors");
1221 const size_type n_pts(refcoords.cols());
1222
1223 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(4, n_pts);
1224
1225 auto x = refcoords.row(0).array();
1226
1227 // endpoints
1228 result.row(0) = -13.5 * x * x + 18.0 * x - 5.5;
1229 result.row(1) = 13.5 * x * x - 9.0 * x + 1.0;
1230 // interior
1231 result.row(2) = 40.5 * x * x - 45 * x + 9;
1232 result.row(3) = -40.5 * x * x + 36 * x - 4.5;
1233
1234 return result;
1235 }
1236
1237 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
1238 Eigen::Matrix<double, 1, 4> nodes;
1239 nodes << 0.0, 1.0, 1.0 / 3.0, 2.0 / 3.0;
1240 return nodes;
1241 }
1242
1246 [[nodiscard]] size_type NumEvaluationNodes() const override {
1247 return NumRefShapeFunctions();
1248 }
1249};
1250
1275template <typename SCALAR>
1277 : public lf::fe::ScalarReferenceFiniteElement<SCALAR> {
1278 public:
1280 FeLagrangeO3Quad(FeLagrangeO3Quad&&) noexcept = default;
1281 FeLagrangeO3Quad& operator=(const FeLagrangeO3Quad&) = default;
1282 FeLagrangeO3Quad& operator=(FeLagrangeO3Quad&&) noexcept = default;
1283 FeLagrangeO3Quad() = default;
1284 ~FeLagrangeO3Quad() override = default;
1285
1286 [[nodiscard]] base::RefEl RefEl() const override {
1287 return base::RefEl::kQuad();
1288 }
1289
1290 [[nodiscard]] unsigned Degree() const override { return 3; }
1291
1292 [[nodiscard]] size_type NumRefShapeFunctions() const override { return 16; }
1293
1294 // clang-format off
1299 // clang-format on
1300 [[nodiscard]] size_type NumRefShapeFunctions(dim_t codim) const override {
1301 switch (codim) {
1302 case 0:
1303 return 4;
1304 case 1:
1305 return 2;
1306 case 2:
1307 return 1;
1308 default:
1309 LF_ASSERT_MSG(false, "Illegal codim" << codim);
1310 }
1311 return 0;
1312 }
1313
1314 // clang-format off
1319 // clang-format on
1321 dim_t codim, sub_idx_t subidx) const override {
1322 LF_ASSERT_MSG((codim == 2 && subidx < 4) || (codim == 1 && subidx < 4) ||
1323 (codim == 0 && subidx == 0),
1324 "codim/subidx out of range.");
1325 return NumRefShapeFunctions(codim);
1326 }
1327
1328 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
1329 EvalReferenceShapeFunctions(const Eigen::MatrixXd& refcoords) const override {
1330 LF_ASSERT_MSG(refcoords.rows() == 2,
1331 "Reference coordinates must be 2-vectors");
1332
1333 const size_type n_pts(refcoords.cols());
1334 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(
1335 16, refcoords.cols());
1336
1337 // evaluate "segment" shape functions (b^j and b^l)
1338 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x0_eval =
1339 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(0))).array();
1340 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x1_eval =
1341 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(1))).array();
1342
1343 // Evaluate basis functions using the tensor product structure
1344 for (int i = 0; i < 16; ++i) {
1345 result.row(i) = (segment_x0_eval.row(ksegment_to_quad_mapping_(i, 0)) *
1346 segment_x1_eval.row(ksegment_to_quad_mapping_(i, 1)))
1347 .matrix();
1348 }
1349 return result;
1350 }
1351
1352 [[nodiscard]] Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
1354 const Eigen::MatrixXd& refcoords) const override {
1355 LF_ASSERT_MSG(refcoords.rows() == 2,
1356 "Reference coordinates must be 2-vectors");
1357
1358 const size_type n_pts(refcoords.cols());
1359 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> result(16, 2 * n_pts);
1360
1361 // reshape into a 32xn_pts matrix.
1362 Eigen::Map<Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic>,
1363 Eigen::AutoAlign>
1364 temp(&result(0, 0), 32, n_pts);
1365
1366 // evaluate "segment" shape functions (b^j and b^l)
1367 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x0_eval =
1368 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(0))).array();
1369 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x1_eval =
1370 (krsf_segment_.EvalReferenceShapeFunctions(refcoords.row(1))).array();
1371
1372 // evaluate derivatives of "segment" shape functions (b^j and
1373 // b^l)
1374 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x0_grad =
1375 (krsf_segment_.GradientsReferenceShapeFunctions(refcoords.row(0)))
1376 .array();
1377 Eigen::Array<SCALAR, Eigen::Dynamic, Eigen::Dynamic> segment_x1_grad =
1378 (krsf_segment_.GradientsReferenceShapeFunctions(refcoords.row(1)))
1379 .array();
1380
1381 // evaluate gradients using the product rule and
1382 // the tensor product structure of the basis functions.
1383 for (int i = 0; i < 16; ++i) {
1384 // d/dx
1385 temp.row(i) = (segment_x0_grad.row(ksegment_to_quad_mapping_(i, 0)) *
1386 segment_x1_eval.row(ksegment_to_quad_mapping_(i, 1)))
1387 .matrix();
1388 // d/dy
1389 temp.row(i + 16) = (segment_x1_grad.row(ksegment_to_quad_mapping_(i, 1)) *
1390 segment_x0_eval.row(ksegment_to_quad_mapping_(i, 0)))
1391 .matrix();
1392 }
1393
1394 return result;
1395 }
1396
1397 [[nodiscard]] Eigen::MatrixXd EvaluationNodes() const override {
1398 Eigen::Matrix<double, 2, 16> nodes;
1399
1400 Eigen::Matrix<double, 2, 4> vertices;
1401 Eigen::Matrix<double, 2, 8> midpoints;
1402 Eigen::Matrix<double, 2, 4> interior;
1403
1404 // clang-format off
1405 vertices << 0.0, 1.0, 1.0, 0.0,
1406 0.0, 0.0, 1.0, 1.0;
1407 midpoints << 1.0, 2.0, 3.0, 3.0, 2.0, 1.0, 0.0, 0.0,
1408 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 2.0, 1.0;
1409 interior << 1.0, 2.0, 2.0, 1.0,
1410 1.0, 1.0, 2.0, 2.0;
1411 // clang-format on
1412 midpoints *= 1.0 / 3.0;
1413 interior *= 1.0 / 3.0;
1414
1415 nodes << vertices, midpoints, interior;
1416
1417 return nodes;
1418 }
1419
1423 [[nodiscard]] size_type NumEvaluationNodes() const override {
1424 return NumRefShapeFunctions();
1425 }
1426
1427 private:
1432
1450 const static Eigen::Matrix<int, 16, 2> ksegment_to_quad_mapping_;
1451};
1452
1453template <typename SCALAR>
1456
1457template <typename SCALAR>
1458const Eigen::Matrix<int, 16, 2>
1460 // clang-format off
1461 (Eigen::Matrix<int,16,2>() << 0, 0,
1462 1, 0,
1463 1, 1,
1464 0, 1,
1465 2, 0,
1466 3, 0,
1467 1, 2,
1468 1, 3,
1469 3, 1,
1470 2, 1,
1471 0, 3,
1472 0, 2,
1473 2, 2,
1474 3, 2,
1475 3, 3,
1476 2, 3).finished();
1477// clang-format on
1478
1479} // namespace lf::uscalfe
1480
1481#endif
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
Definition: ref_el.h:150
const Eigen::MatrixXd & NodeCoords() const
Get the coordinates of the nodes of this reference element.
Definition: ref_el.h:238
static constexpr RefEl kTria()
Returns the reference triangle.
Definition: ref_el.h:158
constexpr size_type NumNodes() const
The number of nodes of this reference element.
Definition: ref_el.h:210
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
Definition: ref_el.h:166
Interface class for parametric scalar valued finite elements.
Linear Lagrange finite element on the quadrilateral reference element.
Definition: lagr_fe.h:165
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:174
FeLagrangeO1Quad(const FeLagrangeO1Quad &)=default
size_type NumRefShapeFunctions() const override
The local shape functions: four bilinear basis functions.
Definition: lagr_fe.h:183
size_type NumRefShapeFunctions(dim_t codim) const override
Exactly one shape function attached to each node, none to other sub-entities.
Definition: lagr_fe.h:191
size_type NumEvaluationNodes() const override
Tell the number of evaluation (interpolation) nodes.
Definition: lagr_fe.h:259
FeLagrangeO1Quad(FeLagrangeO1Quad &&) noexcept=default
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t subidx) const override
Exactly one shape function attached to each node, none to other sub-entities.
Definition: lagr_fe.h:201
Eigen::MatrixXd EvaluationNodes() const override
Returns reference coordinates of "evaluation nodes" for evaluation of parametric degrees of freedom,...
Definition: lagr_fe.h:255
unsigned Degree() const override
Request the maximal polynomial degree of the basis functions in this finite element.
Definition: lagr_fe.h:178
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Computation of the gradients of all reference shape functions in a number of points.
Definition: lagr_fe.h:231
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Evaluation of all reference shape functions in a number of points.
Definition: lagr_fe.h:210
Linear Lagrange finite element on a line segment.
Definition: lagr_fe.h:284
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t subidx) const override
All shape functions attached to nodes.
Definition: lagr_fe.h:319
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:293
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Evaluation of all reference shape functions in a number of points.
Definition: lagr_fe.h:328
size_type NumEvaluationNodes() const override
Two evaluation nodes.
Definition: lagr_fe.h:366
FeLagrangeO1Segment(const FeLagrangeO1Segment &)=default
size_type NumRefShapeFunctions(dim_t codim) const override
All shape functions attached to nodes.
Definition: lagr_fe.h:309
unsigned Degree() const override
Request the maximal polynomial degree of the basis functions in this finite element.
Definition: lagr_fe.h:297
Eigen::MatrixXd EvaluationNodes() const override
Evalutation nodes are just the vertices of the segment.
Definition: lagr_fe.h:359
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Computation of the gradients of all reference shape functions in a number of points.
Definition: lagr_fe.h:342
FeLagrangeO1Segment(FeLagrangeO1Segment &&) noexcept=default
size_type NumRefShapeFunctions() const override
The local shape functions: barycentric coordinate functions.
Definition: lagr_fe.h:302
Linear Lagrange finite element on triangular reference element.
Definition: lagr_fe.h:58
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t subidx) const override
Exactly one shape function attached to each node, none to other sub-entities.
Definition: lagr_fe.h:94
size_type NumRefShapeFunctions(dim_t codim) const override
Exactly one shape function attached to each node, none to other sub-entities.
Definition: lagr_fe.h:84
size_type NumEvaluationNodes() const override
Three evaluation nodes.
Definition: lagr_fe.h:141
Eigen::MatrixXd EvaluationNodes() const override
Evalutation nodes are just the vertices of the triangle.
Definition: lagr_fe.h:134
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Computation of the gradients of all reference shape functions in a number of points.
Definition: lagr_fe.h:117
size_type NumRefShapeFunctions() const override
The local shape functions: barycentric coordinate functions.
Definition: lagr_fe.h:76
unsigned Degree() const override
Request the maximal polynomial degree of the basis functions in this finite element.
Definition: lagr_fe.h:71
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Evaluation of all reference shape functions in a number of points.
Definition: lagr_fe.h:104
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:67
FeLagrangeO1Tria(FeLagrangeO1Tria &&) noexcept=default
FeLagrangeO1Tria(const FeLagrangeO1Tria &)=default
Quadratic Lagrangian finite element on a quadrilateral reference element.
Definition: lagr_fe.h:713
unsigned Degree() const override
Quadratic Lagrangian finite elements sport polynomials of degree 2.
Definition: lagr_fe.h:729
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Point evaluation of reference local shape functions in unit square.
Definition: lagr_fe.h:779
static const FeLagrangeO2Segment< SCALAR > krsf_segment_
Definition: lagr_fe.h:885
FeLagrangeO2Quad(const FeLagrangeO2Quad &)=default
FeLagrangeO2Quad(FeLagrangeO2Quad &&) noexcept=default
size_type NumEvaluationNodes() const override
Nine evaluation nodes, same as the number of local shape functions.
Definition: lagr_fe.h:877
Eigen::MatrixXd EvaluationNodes() const override
Evaluation nodes are the vertices, the midpoints of the edges and the center of the quadrilateral.
Definition: lagr_fe.h:863
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t) const override
One shape function is attached to each node and each edge of the quadrilateral. One interior shape fu...
Definition: lagr_fe.h:755
size_type NumRefShapeFunctions(dim_t codim) const override
One shape function is attached to each node and edge of the quadrilateral. One interior shape functio...
Definition: lagr_fe.h:744
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Point evaluation of gradient of reference shape functions for quadratic Lagrangian finite elements on...
Definition: lagr_fe.h:811
size_type NumRefShapeFunctions() const override
Nine local shape functions are associated with a quadrilateral cell.
Definition: lagr_fe.h:737
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:723
static const Eigen::Matrix< int, 9, 2 > ksegment_to_quad_mapping_
Definition: lagr_fe.h:904
Quadratic Lagrangian finite element on a line segment.
Definition: lagr_fe.h:563
size_type NumEvaluationNodes() const override
Three evaluation nodes, same number as local shape functions.
Definition: lagr_fe.h:682
size_type NumRefShapeFunctions() const override
Three local shape functions are associated with an edge.
Definition: lagr_fe.h:585
FeLagrangeO2Segment(FeLagrangeO2Segment &&) noexcept=default
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t) const override
One shape function attached to each node and one interior shape function.
Definition: lagr_fe.h:605
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Evaluation of shape functions on reference segment (unit interval)
Definition: lagr_fe.h:626
FeLagrangeO2Segment(const FeLagrangeO2Segment &)=default
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:572
Eigen::MatrixXd EvaluationNodes() const override
Evaluation nodes are the endpoints of the segment and its midpoint.
Definition: lagr_fe.h:672
unsigned Degree() const override
Quadratic Lagrangian finite element rely on polynomials of degree 2.
Definition: lagr_fe.h:578
size_type NumRefShapeFunctions(dim_t codim) const override
One shape function attached to each node and one interior shape function.
Definition: lagr_fe.h:595
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Evaluation of derivatives of local shape function on reference interval.
Definition: lagr_fe.h:652
Quadratic Lagrangian finite element on a triangular reference element.
Definition: lagr_fe.h:400
FeLagrangeO2Tria(const FeLagrangeO2Tria &)=default
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Point evaluation of reference shape functions.
Definition: lagr_fe.h:458
size_type NumEvaluationNodes() const override
Six evaluation nodes, the same number as local shape functions.
Definition: lagr_fe.h:542
Eigen::MatrixXd EvaluationNodes() const override
Evaluation nodes are the three vertices of the triangle and the three midpoints of its edges.
Definition: lagr_fe.h:528
size_type NumRefShapeFunctions() const override
Six local shape functions are associated with a triangular cell in the case of quadratic Lagrangian f...
Definition: lagr_fe.h:425
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:411
FeLagrangeO2Tria(FeLagrangeO2Tria &&) noexcept=default
unsigned Degree() const override
Quadratic Lagrangian finite elements rely on polynomials of degree 2.
Definition: lagr_fe.h:418
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t) const override
One shape function attached to each node and one to each edge of the triangle. There are no interior ...
Definition: lagr_fe.h:444
size_type NumRefShapeFunctions(dim_t codim) const override
One shape function attached to each node and one to each edge of the triangle. There are no interior ...
Definition: lagr_fe.h:433
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Point evaluations of gradients of reference shape functions.
Definition: lagr_fe.h:485
Cubic Lagrangian finite element on a quadrilateral reference element.
Definition: lagr_fe.h:1277
FeLagrangeO3Quad(const FeLagrangeO3Quad &)=default
Eigen::MatrixXd EvaluationNodes() const override
Returns reference coordinates of "evaluation nodes" for evaluation of parametric degrees of freedom,...
Definition: lagr_fe.h:1397
size_type NumEvaluationNodes() const override
Sixteen evaluation nodes.
Definition: lagr_fe.h:1423
size_type NumRefShapeFunctions(dim_t codim) const override
One shape function attached to each node and two to each edge of the quadrilateral....
Definition: lagr_fe.h:1300
static const FeLagrangeO3Segment< SCALAR > krsf_segment_
Definition: lagr_fe.h:1431
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t subidx) const override
One shape function attached to each node and two to each edge of the quadrilateral....
Definition: lagr_fe.h:1320
size_type NumRefShapeFunctions() const override
Total number of reference shape functions associated with the reference cell.
Definition: lagr_fe.h:1292
unsigned Degree() const override
Request the maximal polynomial degree of the basis functions in this finite element.
Definition: lagr_fe.h:1290
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Computation of the gradients of all reference shape functions in a number of points.
Definition: lagr_fe.h:1353
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Evaluation of all reference shape functions in a number of points.
Definition: lagr_fe.h:1329
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:1286
static const Eigen::Matrix< int, 16, 2 > ksegment_to_quad_mapping_
Definition: lagr_fe.h:1450
FeLagrangeO3Quad(FeLagrangeO3Quad &&) noexcept=default
Cubic Lagrangian finite element on a line segment.
Definition: lagr_fe.h:1153
size_type NumRefShapeFunctions() const override
Total number of reference shape functions associated with the reference cell.
Definition: lagr_fe.h:1168
unsigned Degree() const override
Request the maximal polynomial degree of the basis functions in this finite element.
Definition: lagr_fe.h:1166
FeLagrangeO3Segment(const FeLagrangeO3Segment &)=default
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t subidx) const override
One shape function attached to each node and two interior shape functions.
Definition: lagr_fe.h:1187
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Evaluation of all reference shape functions in a number of points.
Definition: lagr_fe.h:1196
Eigen::MatrixXd EvaluationNodes() const override
Returns reference coordinates of "evaluation nodes" for evaluation of parametric degrees of freedom,...
Definition: lagr_fe.h:1237
FeLagrangeO3Segment(FeLagrangeO3Segment &&) noexcept=default
size_type NumEvaluationNodes() const override
Four evaluation nodes.
Definition: lagr_fe.h:1246
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Computation of the gradients of all reference shape functions in a number of points.
Definition: lagr_fe.h:1217
size_type NumRefShapeFunctions(dim_t codim) const override
One shape function attached to each node and two interior shape functions.
Definition: lagr_fe.h:1176
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:1162
Cubic Lagrangian finite elment on a triangular reference element.
Definition: lagr_fe.h:945
FeLagrangeO3Tria(const FeLagrangeO3Tria &)=default
size_type NumRefShapeFunctions(dim_t codim, sub_idx_t subidx) const override
One shape function attached to each node and two to each edge of the triangle. There is one interior ...
Definition: lagr_fe.h:991
size_type NumRefShapeFunctions(dim_t codim) const override
One shape function attached to each node and two to each edge of the triangle. There is one interior ...
Definition: lagr_fe.h:978
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > GradientsReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Point evaluations of gradients of reference shape functions.
Definition: lagr_fe.h:1050
FeLagrangeO3Tria(FeLagrangeO3Tria &&) noexcept=default
unsigned Degree() const override
Quadratic Lagrangian finite elements rely on polynomials of degree 3.
Definition: lagr_fe.h:961
size_type NumEvaluationNodes() const override
Ten evaluation nodes.
Definition: lagr_fe.h:1134
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > EvalReferenceShapeFunctions(const Eigen::MatrixXd &refcoords) const override
Point evaluation of reference shape functions.
Definition: lagr_fe.h:1009
base::RefEl RefEl() const override
Tells the type of reference cell underlying the parametric finite element.
Definition: lagr_fe.h:954
size_type NumRefShapeFunctions() const override
Ten local shape functions are associated with a triangular cell in the case of cubic Lagrangian finit...
Definition: lagr_fe.h:968
Eigen::MatrixXd EvaluationNodes() const override
Evaluation nodes are the three vertices of the triangle, two equispaced interio nodes for each edge,...
Definition: lagr_fe.h:1112
unsigned int sub_idx_t
type for local indices of sub-entities
Definition: base.h:32
lf::base::size_type size_type
lf::base::glb_idx_t glb_idx_t
Eigen::Index gdof_idx_t
Eigen::Index ldof_idx_t
lf::base::dim_t dim_t
Collects data structures and algorithms designed for scalar finite element methods primarily meant fo...
lf::base::sub_idx_t sub_idx_t
Definition: lagr_fe.h:36
lf::assemble::glb_idx_t glb_idx_t
Definition: lagr_fe.h:34
lf::assemble::dim_t dim_t
Definition: lagr_fe.h:32
lf::assemble::ldof_idx_t ldof_idx_t
Definition: lagr_fe.h:28
lf::assemble::size_type size_type
Definition: lagr_fe.h:30
lf::assemble::gdof_idx_t gdof_idx_t
Definition: lagr_fe.h:26