version 0.4.1
utils/concepts.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2025 The Ikarus Developers ikarus@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
9#pragma once
10
11#include <concepts>
12#include <type_traits>
13#include <utility>
14#include <vector>
15
16#include <dune/functions/functionspacebases/basistags.hh>
17#include <dune/functions/functionspacebases/lagrangebasis.hh>
18
19#include <Eigen/Dense>
20#include <Eigen/Sparse>
21
22#include <autodiff/forward/dual/dual.hpp>
23
27
28namespace Eigen {
29template <typename Derived>
30struct EigenBase;
31}
32
33namespace Ikarus {
34
35template <typename Derived>
37namespace Concepts {
38
45 template <typename T>
46 concept EigenType = std::is_base_of_v<Eigen::MatrixBase<std::decay_t<T>>, std::decay_t<T>>;
47
56 template <typename Basis>
57 concept FlatInterLeavedBasis = requires {
58 std::is_same_v<typename Basis::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::FlatInterleaved>;
59 };
60
61 namespace Impl {
62 template <template <typename, int, typename> class U, typename T>
63 struct LagrangeNodeHelper : std::false_type
64 {
65 };
66 template <template <typename, int, typename> class U, typename GV, int k, typename R>
67 struct LagrangeNodeHelper<U, U<GV, k, R>> : std::true_type
68 {
69 };
70
71 template <template <typename, int, typename> class U, typename T, int k>
72 struct LagrangeNodeHelperOfOrder : std::false_type
73 {
74 };
75 template <template <typename, int, typename> class U, typename GV, int k, typename R>
76 struct LagrangeNodeHelperOfOrder<U, U<GV, k, R>, k> : std::true_type
77 {
78 };
79 } // namespace Impl
80
88 template <typename N>
89 concept LagrangeNode = Impl::LagrangeNodeHelper<Dune::Functions::LagrangeNode, N>::value;
90
98 template <typename N, int order>
99 concept LagrangeNodeOfOrder = Impl::LagrangeNodeHelperOfOrder<Dune::Functions::LagrangeNode, N, order>::value;
100
109 template <typename B>
110 concept FlatLexicographicBasis = requires {
111 std::is_same_v<typename B::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::FlatLexicographic>;
112 };
113
122 template <typename B>
124
133 template <typename Basis>
134 concept BlockedInterLeavedBasis = requires {
135 std::is_same_v<typename Basis::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::BlockedInterleaved>;
136 };
137
146 template <typename B>
147 concept BlockedLexicographicBasis = requires {
148 std::is_same_v<typename B::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::BlockedLexicographic>;
149 };
150
156 template <typename DLB>
157 concept DuneLocalBasis = requires(DLB& duneLocalBasis) {
158 typename DLB::Traits::RangeType;
159 typename DLB::Traits::JacobianType;
160 DLB::Traits::dimDomain;
161 typename DLB::Traits::DomainType;
162
163 typename DLB::Traits::DomainFieldType;
164 typename DLB::Traits::RangeFieldType;
165
166 duneLocalBasis.evaluateFunction(std::declval<typename DLB::Traits::DomainType>(),
167 std::declval<std::vector<typename DLB::Traits::RangeType>&>());
168 duneLocalBasis.evaluateJacobian(std::declval<typename DLB::Traits::DomainType>(),
169 std::declval<std::vector<typename DLB::Traits::JacobianType>&>());
170 };
171
181 template <typename B>
183
191 template <typename PF, typename F, typename SA>
192 concept PathFollowingStrategy = requires(PF pft, F nop, SA args, typename F::Domain req) {
193 { pft(args) } -> std::same_as<void>;
194 { pft.initialPrediction(req, nop, args) } -> std::same_as<void>;
195 { pft.intermediatePrediction(req, nop, args) } -> std::same_as<void>;
196 };
197
206 template <typename ASS, typename NLSI, typename SA, typename DifferentiableFunction>
208 requires(ASS adaptiveStepSizing, NLSI info, SA args, DifferentiableFunction nop) {
209 { adaptiveStepSizing(info, args, nop) } -> std::same_as<void>;
210 { adaptiveStepSizing.targetIterations() } -> std::same_as<int>;
211 { adaptiveStepSizing.setTargetIterations(std::declval<int>()) } -> std::same_as<void>;
212 };
213
222 template <typename LS, typename M, typename V>
223 concept LinearSolverCheck = requires(LS linearSolver, M A, V vec) {
224 linearSolver.analyzePattern(A);
225 linearSolver.factorize(A);
226 linearSolver.solve(vec, vec);
227 };
228
236 template <typename NLS>
238 not(std::is_same_v<typename NLS::DifferentiableFunction::Domain, double> and
239 ((traits::isSpecializationTypeAndNonTypes<
240 Eigen::Matrix, typename NLS::DifferentiableFunction::Traits::template Range<1>>::value) or
241 (traits::isSpecializationTypeNonTypeAndType<
242 Eigen::SparseMatrix, typename NLS::DifferentiableFunction::Traits::template Range<1>>::value)));
243 };
244
252 template <typename L, typename R>
253 concept MultiplyAble = requires(L x, R y) { x* y; };
254
262 template <typename L, typename R>
263 concept AddAble = requires(L x, R y) { x + y; };
264
272 template <typename L, typename R>
273 concept SubstractAble = requires(L x, R y) { x - y; };
274
283 template <typename L, typename R>
284 concept MultiplyAssignAble = requires(L x, R y) { x *= y; };
285
294 template <typename L, typename R>
295 concept DivideAssignAble = requires(L x, R y) { x /= y; };
296
305 template <typename L, typename R>
306 concept AddAssignAble = requires(L x, R y) { x += y; };
307
316 template <typename L, typename R>
317 concept SubstractAssignAble = requires(L x, R y) { x -= y; };
318
326 template <typename L, typename R>
327 concept DivideAble = requires(L x, R y) { x / y; };
328
335 template <typename L>
336 concept NegateAble = requires(L x) { -x; };
337
344 template <typename L>
345 concept TransposeAble = requires(L x) { transpose(x); };
346
353 template <typename Op, typename... Args>
354 concept IsFunctorWithArgs = requires(Op op, Args... args) { op(args...); };
355
361 template <typename V>
362 concept EigenVector = static_cast<bool>(V::IsVectorAtCompileTime);
363
369 template <typename M>
370 concept EigenMatrix = traits::isSpecializationTypeAndNonTypes<Eigen::Matrix, M>::value;
371
377 template <typename M>
378 concept SparseEigenMatrix = traits::isSpecializationTypeNonTypeAndType<Eigen::SparseMatrix, M>::value;
379
385 template <typename M>
387
388#define MAKE_EIGEN_FIXED_VECTOR_CONCEPT(Size) \
389 template <typename V> \
390 concept EigenVector##Size = \
391 static_cast<bool>(V::IsVectorAtCompileTime) and static_cast<bool>(V::SizeAtCompileTime == Size);
392
399
400#define MAKE_EIGEN_FIXED_MATRIX_CONCEPT(Size1, Size2) \
401 template <typename M> \
402 concept EigenMatrix##Size1##Size2 = static_cast<bool>(std::remove_cvref_t<M>::RowsAtCompileTime == Size1) and \
403 static_cast<bool>(std::remove_cvref_t<M>::ColsAtCompileTime == Size2);
404
406
409
414
421
430
441
442#define MAKE_EIGEN_FIXED_MATRIX_OR_VOIGT_CONCEPT(Size1, Size2) \
443 template <typename M> \
444 concept EigenMatrixOrVoigtNotation##Size1 = EigenMatrix##Size1##Size1<M> or EigenVector##Size2<M>;
445
449
450 namespace Impl {
451 template <template <typename...> class MaterialToCheck, typename Material>
452 consteval bool isMaterial() {
453 if constexpr (traits::isSpecialization<MaterialToCheck, Material>::value)
454 return true;
455
456 if constexpr (Material::isReduced) {
457 if constexpr (traits::isSpecialization<MaterialToCheck, typename Material::Underlying>::value) {
458 return true;
459 } else {
460 return false;
461 }
462 } else
463 return false;
464 }
465 } // namespace Impl
466
479 template <template <typename...> class MaterialToCheck, typename Material>
480 concept IsMaterial = Impl::isMaterial<MaterialToCheck, Material>();
481
482 namespace Impl {
483 template <typename T>
484 concept ResultType = requires(T t) {
485 typename T::type; // The nested type 'type'
486 typename T::Vectorizer; // The nested type 'Vectorizer'
487 typename T::Matricizer; // The nested type 'Matricizer'
488 { toString(t) } -> std::same_as<std::string>; // The toString function
489 };
490 } // namespace Impl
491
501 template <template <typename, int, int> typename RT>
502 concept ResultType =
503 Impl::ResultType<RT<double, 1, 1>> or Impl::ResultType<RT<double, 1, 2>> or Impl::ResultType<RT<double, 1, 3>> or
504 Impl::ResultType<RT<double, 2, 3>> or Impl::ResultType<RT<double, 3, 3>>;
505
513 template <typename T>
514 concept FlatAssembler = requires(T t, const typename T::FERequirement& req,
515 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
516 { t.requirement() } -> std::convertible_to<typename T::FERequirement&>;
517 { t.affordanceCollection() } -> std::convertible_to<typename T::AffordanceCollectionType>;
518 { t.dBCOption() } -> std::convertible_to<DBCOption>;
519
520 { t.bind(req, affordance, dbcOption) } -> std::same_as<void>;
521 { t.bind(req) } -> std::same_as<void>;
522 { t.bind(affordance) } -> std::same_as<void>;
523 { t.bind(dbcOption) } -> std::same_as<void>;
524
525 { t.bound() } -> std::convertible_to<bool>;
526 { t.boundToRequirement() } -> std::convertible_to<bool>;
527 { t.boundToAffordanceCollection() } -> std::convertible_to<bool>;
528 { t.boundToDBCOption() } -> std::convertible_to<bool>;
529 { t.estimateOfConnectivity() } -> std::convertible_to<size_t>;
530
531 { t.createFullVector(std::declval<Eigen::Ref<const Eigen::VectorXd>>()) } -> std::convertible_to<Eigen::VectorXd>;
532 { t.constraintsBelow(std::declval<size_t>()) } -> std::convertible_to<size_t>;
533 { t.isConstrained(std::declval<size_t>()) } -> std::convertible_to<bool>;
534 { t.size() } -> std::convertible_to<size_t>;
535 { t.reducedSize() } -> std::convertible_to<size_t>;
536 };
537
544 template <typename T>
546 Concepts::FlatAssembler<T> and requires(T t, const typename T::FERequirement& req,
547 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
548 { t.scalar(req, affordance.scalarAffordance()) } -> std::convertible_to<const double&>;
549 { t.scalar() } -> std::convertible_to<const double&>;
550 };
551
558 template <typename T>
560 requires(T t, const typename T::FERequirement& req,
561 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
562 {
563 t.vector(req, affordance.vectorAffordance(), dbcOption)
564 } -> std::convertible_to<const Eigen::VectorXd&>;
565 { t.vector(dbcOption) } -> std::convertible_to<const Eigen::VectorXd&>;
566 { t.vector() } -> std::convertible_to<const Eigen::VectorXd&>;
567 };
568
575 template <typename T>
577 requires(T t, const typename T::FERequirement& req,
578 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
579 { t.matrix(req, affordance.matrixAffordance(), dbcOption) };
580 { t.matrix(dbcOption) };
581 { t.matrix() };
582 };
583
584 // adapted from /dune/dune-vtk/dune/vtk/utility/concepts.hh
585 template <class DC>
586 concept DataCollector = requires(DC dc) {
587 typename DC::GridView;
588 { dc.update() } -> std::same_as<void>;
589 { dc.numPoints() } -> std::convertible_to<std::uint64_t>;
590 { dc.numCells() } -> std::convertible_to<std::uint64_t>;
591 { dc.gridView() } -> std::same_as<const typename DC::GridView&>;
592 };
593
594 template <class GV>
595 concept GridView = requires(GV g) {
596 typename GV::Grid;
597 GV::dimension;
598 GV::dimensionworld;
599
600 { g.grid() };
601 };
602
603 namespace Impl {
604 template <typename T>
605 struct is_dual : std::false_type
606 {
607 };
608
609 // Specialization for Dual<T, U>: this will be true for Dual types
610 template <typename T, typename U>
611 struct is_dual<autodiff::detail::Dual<T, U>> : std::true_type
612 {
613 };
614 } // namespace Impl
615
621 template <typename T>
622 concept AutodiffScalar = Impl::is_dual<T>::value;
623
629 template <typename T>
630 concept SmartPointer = traits::isSharedPtr<T>::value || traits::isUniquePtr<T>::value;
631
637 template <typename T>
639
640 template <typename S>
641 concept ControlRoutineState = requires(S s) {
642 typename S::Domain;
643
644 // { s.domain } -> std::convertible_to<const typename S::Domain>;
645 { s.loadStep } -> std::convertible_to<int>;
646 { s.stepSize } -> std::convertible_to<double>;
647 };
648
652 template <StrainTags tag>
655
659 template <StressTags tag>
661
662 namespace Formulations {
669 template <StrainTags T1, StressTags T2>
672
679 template <StrainTags T1, StressTags T2>
680 concept TwoPoint =
682 } // namespace Formulations
683
690 template <typename M>
691 concept Material = requires(M m, Eigen::Matrix3d C) {
692 M::strainTag;
693 M::stressTag;
694 M::tangentModuliTag;
695 M::derivativeFactor;
696 M::isReduced;
697
698 typename M::ScalarType;
699
700 { m.name() } -> std::convertible_to<std::string>;
701 { m.materialParameters() } -> std::same_as<typename M::MaterialParameters>;
702 { m.template storedEnergy<M::strainTag>(C) } -> std::same_as<typename M::ScalarType>;
703 { m.template stresses<M::strainTag>(C) };
704 { m.template tangentModuli<M::strainTag>(C) };
705 };
706
713 template <typename MAT>
715
722 template <typename ES>
723 concept EigenValueSolver = requires(ES es) {
724 typename ES::MatrixType;
725 typename ES::ScalarType;
726 { es.compute() } -> std::same_as<bool>;
727 { es.eigenvalues() } -> std::convertible_to<Eigen::VectorX<typename ES::ScalarType>>;
728 { es.eigenvectors() } -> std::convertible_to<Eigen::MatrixX<typename ES::ScalarType>>;
729 { es.nev() } -> std::convertible_to<int>;
730 };
731
732} // namespace Concepts
733
734namespace traits {
735#ifndef DOXYGEN
736
737 // Primary template: for non-pointer types.
738 template <typename T, bool = Concepts::PointerOrSmartPointer<T>>
739 struct MaybeDereference
740 {
741 using type = T;
742 };
743
744 // Specialization: for pointer (or smart pointer) types.
745 template <typename T>
746 struct MaybeDereference<T, true>
747 {
748 // We know T is pointer-like, so *std::declval<T&>() is well-formed.
749 using type = std::remove_reference_t<decltype(*std::declval<T&>())>;
750 };
751#endif
752
753 template <typename T>
754 using MaybeDereferencedType = typename MaybeDereference<T>::type;
755
756} // namespace traits
757
758} // namespace Ikarus
Contains stl-like type traits.
Definition of several material related enums.
Definition: assemblermanipulatorbuildingblocks.hh:22
DBCOption
Definition: dirichletbcenforcement.hh:8
auto transpose(const Eigen::EigenBase< Derived > &A)
constexpr std::string toString(DBCOption _e)
Definition: dirichletbcenforcement.hh:8
Definition: truncatedconjugategradient.hh:24
typename MaybeDereference< T >::type MaybeDereferencedType
Definition: utils/concepts.hh:754
Definition: utils/concepts.hh:30
Concept to check if a type is derived from Eigen::MatrixBase.
Definition: utils/concepts.hh:46
Concept to check if a basis uses FlatInterleaved indexing strategy.
Definition: utils/concepts.hh:57
Concept to check if a node in a basis tree is a Lagrangian node.
Definition: utils/concepts.hh:89
Definition: utils/concepts.hh:99
Concept to check if a basis uses FlatLexicographic indexing strategy.
Definition: utils/concepts.hh:110
Concept to check if a basis uses FlatIndex indexing strategy.
Definition: utils/concepts.hh:123
Concept to check if a basis uses BlockedInterleaved indexing strategy.
Definition: utils/concepts.hh:134
Concept to check if a basis uses BlockedLexicographic indexing strategy.
Definition: utils/concepts.hh:147
Concept to check if a local basis is a duneLocalBasis.
Definition: utils/concepts.hh:157
Concept to check if a basis uses either BlockedLexicographic or BlockedInterleaved indexing strategy.
Definition: utils/concepts.hh:182
Concept defining the requirements for a path-following strategy.
Definition: utils/concepts.hh:192
Concept to check if a type implements all the needed functions to be an adaptive step sizing method.
Definition: utils/concepts.hh:207
Concept to check if a linear solver implements all the needed functions for given vector and matrix t...
Definition: utils/concepts.hh:223
Concept to check if a non-linear solver with its non-linear operator satisfies requirements for path ...
Definition: utils/concepts.hh:237
Concept defining the requirements for types that support multiplication.
Definition: utils/concepts.hh:253
Concept defining the requirements for types that support addition.
Definition: utils/concepts.hh:263
Concept defining the requirements for types that support subtraction.
Definition: utils/concepts.hh:273
Concept defining the requirements for types that support in-place multiplication.
Definition: utils/concepts.hh:284
Concept defining the requirements for types that support in-place division.
Definition: utils/concepts.hh:295
Concept defining the requirements for types that support in-place addition.
Definition: utils/concepts.hh:306
Concept defining the requirements for types that support in-place subtraction.
Definition: utils/concepts.hh:317
Concept defining the requirements for types that support division.
Definition: utils/concepts.hh:327
Concept defining the requirements for types that support negation.
Definition: utils/concepts.hh:336
Concept defining the requirements for types that support transposition.
Definition: utils/concepts.hh:345
Concept defining the requirements for functors with arguments.
Definition: utils/concepts.hh:354
Concept defining the requirements for Eigen vectors.
Definition: utils/concepts.hh:362
Concept defining the requirements for Eigen matrices. This also includes Eigen vectors.
Definition: utils/concepts.hh:370
Concept defining the requirements for sparse Eigen matrices.
Definition: utils/concepts.hh:378
Concept defining the requirements for sparse or dense Eigen matrices.
Definition: utils/concepts.hh:386
Concept defining the requirements for a material type.
Definition: utils/concepts.hh:480
A concept to check if a template type satisfies the ResultType requirements.
Definition: utils/concepts.hh:502
Concept representing the requirements for a FlatAssembler.A type T satisfies FlatAssembler if it prov...
Definition: utils/concepts.hh:514
Concept representing the requirements for a ScalarFlatAssembler.A type T satisfies ScalarFlatAssemble...
Definition: utils/concepts.hh:545
Concept representing the requirements for a VectorFlatAssembler.A type T satisfies VectorFlatAssemble...
Definition: utils/concepts.hh:559
Concept representing the requirements for a MatrixFlatAssembler.A type T satisfies MatrixFlatAssemble...
Definition: utils/concepts.hh:576
Definition: utils/concepts.hh:586
Definition: utils/concepts.hh:595
Concept to check if the underlying scalar type is a dual type.
Definition: utils/concepts.hh:622
Concept to check if the type is either a unique_ptr or a shared_ptr.
Definition: utils/concepts.hh:630
Definition: utils/concepts.hh:638
Definition: utils/concepts.hh:641
Returns true if a given straintag is related only to the reference configuration.
Definition: utils/concepts.hh:653
Returns true if a given stresstag is related only to the reference configuration.
Definition: utils/concepts.hh:660
Concept to check if the underlying strain and stress tag correspond to a total Lagrangian formulation...
Definition: utils/concepts.hh:670
Concept to check if the underlying strain and stress tag correspond to a two point formulation.
Definition: utils/concepts.hh:680
Concept representing a material interface.
Definition: utils/concepts.hh:691
Concepts defining the requirements for a material to be geometrically linear This is the case when th...
Definition: utils/concepts.hh:714
Concept representing an eigenvalue solver interface.
Definition: utils/concepts.hh:723
Concept to check if a type is a pointer or nullptr_t.
Definition: traits.hh:30
#define MAKE_EIGEN_FIXED_MATRIX_CONCEPT(Size1, Size2)
Definition: utils/concepts.hh:400
#define MAKE_EIGEN_FIXED_MATRIX_OR_VOIGT_CONCEPT(Size1, Size2)
Definition: utils/concepts.hh:442
#define MAKE_EIGEN_FIXED_VECTOR_CONCEPT(Size)
Definition: utils/concepts.hh:388