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
35struct ControlInformation;
36struct NonLinearSolverInformation;
37
38template <typename Derived>
40namespace Concepts {
41
48 template <typename T>
49 concept EigenType = std::is_base_of_v<Eigen::MatrixBase<std::decay_t<T>>, std::decay_t<T>>;
50
59 template <typename Basis>
60 concept FlatInterLeavedBasis = requires {
61 std::is_same_v<typename Basis::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::FlatInterleaved>;
62 };
63
64 namespace Impl {
65 template <template <typename, int, typename> class U, typename T>
66 struct LagrangeNodeHelper : std::false_type
67 {
68 };
69 template <template <typename, int, typename> class U, typename GV, int k, typename R>
70 struct LagrangeNodeHelper<U, U<GV, k, R>> : std::true_type
71 {
72 };
73
74 template <template <typename, int, typename> class U, typename T, int k>
75 struct LagrangeNodeHelperOfOrder : std::false_type
76 {
77 };
78 template <template <typename, int, typename> class U, typename GV, int k, typename R>
79 struct LagrangeNodeHelperOfOrder<U, U<GV, k, R>, k> : std::true_type
80 {
81 };
82 } // namespace Impl
83
91 template <typename N>
92 concept LagrangeNode = Impl::LagrangeNodeHelper<Dune::Functions::LagrangeNode, N>::value;
93
101 template <typename N, int order>
102 concept LagrangeNodeOfOrder = Impl::LagrangeNodeHelperOfOrder<Dune::Functions::LagrangeNode, N, order>::value;
103
112 template <typename B>
113 concept FlatLexicographicBasis = requires {
114 std::is_same_v<typename B::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::FlatLexicographic>;
115 };
116
125 template <typename B>
127
136 template <typename Basis>
137 concept BlockedInterLeavedBasis = requires {
138 std::is_same_v<typename Basis::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::BlockedInterleaved>;
139 };
140
149 template <typename B>
150 concept BlockedLexicographicBasis = requires {
151 std::is_same_v<typename B::PreBasis::IndexMergingStrategy, Dune::Functions::BasisFactory::BlockedLexicographic>;
152 };
153
159 template <typename DLB>
160 concept DuneLocalBasis = requires(DLB& duneLocalBasis) {
161 typename DLB::Traits::RangeType;
162 typename DLB::Traits::JacobianType;
163 DLB::Traits::dimDomain;
164 typename DLB::Traits::DomainType;
165
166 typename DLB::Traits::DomainFieldType;
167 typename DLB::Traits::RangeFieldType;
168
169 duneLocalBasis.evaluateFunction(std::declval<typename DLB::Traits::DomainType>(),
170 std::declval<std::vector<typename DLB::Traits::RangeType>&>());
171 duneLocalBasis.evaluateJacobian(std::declval<typename DLB::Traits::DomainType>(),
172 std::declval<std::vector<typename DLB::Traits::JacobianType>&>());
173 };
174
184 template <typename B>
186
194 template <typename PF, typename F, typename SA>
195 concept PathFollowingStrategy = requires(PF pft, F nop, SA args, typename F::Domain req) {
196 { pft(args) } -> std::same_as<void>;
197 { pft.initialPrediction(req, nop, args) } -> std::same_as<void>;
198 { pft.intermediatePrediction(req, nop, args) } -> std::same_as<void>;
199 };
200
209 template <typename ASS, typename NLSI, typename SA, typename DifferentiableFunction>
211 requires(ASS adaptiveStepSizing, NLSI info, SA args, DifferentiableFunction nop) {
212 { adaptiveStepSizing(info, args, nop) } -> std::same_as<void>;
213 { adaptiveStepSizing.targetIterations() } -> std::same_as<int>;
214 { adaptiveStepSizing.setTargetIterations(std::declval<int>()) } -> std::same_as<void>;
215 };
216
225 template <typename LS, typename M, typename V>
226 concept LinearSolverCheck = requires(LS linearSolver, M A, V vec) {
227 linearSolver.analyzePattern(A);
228 linearSolver.factorize(A);
229 linearSolver.solve(vec, vec);
230 };
231
239 template <typename NLS>
241 not(std::is_same_v<typename NLS::DifferentiableFunction::Domain, double> and
242 ((traits::isSpecializationTypeAndNonTypes<
243 Eigen::Matrix, typename NLS::DifferentiableFunction::Traits::template Range<1>>::value) or
244 (traits::isSpecializationTypeNonTypeAndType<
245 Eigen::SparseMatrix, typename NLS::DifferentiableFunction::Traits::template Range<1>>::value)));
246 };
247
255 template <typename L, typename R>
256 concept MultiplyAble = requires(L x, R y) { x* y; };
257
265 template <typename L, typename R>
266 concept AddAble = requires(L x, R y) { x + y; };
267
275 template <typename L, typename R>
276 concept SubstractAble = requires(L x, R y) { x - y; };
277
286 template <typename L, typename R>
287 concept MultiplyAssignAble = requires(L x, R y) { x *= y; };
288
297 template <typename L, typename R>
298 concept DivideAssignAble = requires(L x, R y) { x /= y; };
299
308 template <typename L, typename R>
309 concept AddAssignAble = requires(L x, R y) { x += y; };
310
319 template <typename L, typename R>
320 concept SubstractAssignAble = requires(L x, R y) { x -= y; };
321
329 template <typename L, typename R>
330 concept DivideAble = requires(L x, R y) { x / y; };
331
338 template <typename L>
339 concept NegateAble = requires(L x) { -x; };
340
347 template <typename L>
348 concept TransposeAble = requires(L x) { transpose(x); };
349
356 template <typename Op, typename... Args>
357 concept IsFunctorWithArgs = requires(Op op, Args... args) { op(args...); };
358
364 template <typename V>
365 concept EigenVector = static_cast<bool>(V::IsVectorAtCompileTime);
366
372 template <typename M>
373 concept EigenMatrix = traits::isSpecializationTypeAndNonTypes<Eigen::Matrix, M>::value;
374
380 template <typename M>
381 concept SparseEigenMatrix = traits::isSpecializationTypeNonTypeAndType<Eigen::SparseMatrix, M>::value;
382
388 template <typename M>
390
391#define MAKE_EIGEN_FIXED_VECTOR_CONCEPT(Size) \
392 template <typename V> \
393 concept EigenVector##Size = \
394 static_cast<bool>(V::IsVectorAtCompileTime) and static_cast<bool>(V::SizeAtCompileTime == Size);
395
402
403#define MAKE_EIGEN_FIXED_MATRIX_CONCEPT(Size1, Size2) \
404 template <typename M> \
405 concept EigenMatrix##Size1##Size2 = static_cast<bool>(std::remove_cvref_t<M>::RowsAtCompileTime == Size1) and \
406 static_cast<bool>(std::remove_cvref_t<M>::ColsAtCompileTime == Size2);
407
409
412
417
424
433
444
445#define MAKE_EIGEN_FIXED_MATRIX_OR_VOIGT_CONCEPT(Size1, Size2) \
446 template <typename M> \
447 concept EigenMatrixOrVoigtNotation##Size1 = EigenMatrix##Size1##Size1<M> or EigenVector##Size2<M>;
448
452
453 namespace Impl {
454 template <template <typename...> class MaterialToCheck, typename Material>
455 consteval bool isMaterial() {
456 if constexpr (traits::isSpecialization<MaterialToCheck, Material>::value)
457 return true;
458
459 if constexpr (Material::isReduced) {
460 if constexpr (traits::isSpecialization<MaterialToCheck, typename Material::Underlying>::value) {
461 return true;
462 } else {
463 return false;
464 }
465 } else
466 return false;
467 }
468 } // namespace Impl
469
482 template <template <typename...> class MaterialToCheck, typename Material>
483 concept IsMaterial = Impl::isMaterial<MaterialToCheck, Material>();
484
485 namespace Impl {
486 template <typename T>
487 concept ResultType = requires(T t) {
488 typename T::type; // The nested type 'type'
489 typename T::Vectorizer; // The nested type 'Vectorizer'
490 typename T::Matricizer; // The nested type 'Matricizer'
491 { toString(t) } -> std::same_as<std::string>; // The toString function
492 };
493 } // namespace Impl
494
504 template <template <typename, int, int> typename RT>
505 concept ResultType =
506 Impl::ResultType<RT<double, 1, 1>> or Impl::ResultType<RT<double, 1, 2>> or Impl::ResultType<RT<double, 1, 3>> or
507 Impl::ResultType<RT<double, 2, 3>> or Impl::ResultType<RT<double, 3, 3>>;
508
516 template <typename T>
517 concept FlatAssembler = requires(T t, const typename T::FERequirement& req,
518 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
519 { t.requirement() } -> std::convertible_to<typename T::FERequirement&>;
520 { t.affordanceCollection() } -> std::convertible_to<typename T::AffordanceCollectionType>;
521 { t.dBCOption() } -> std::convertible_to<DBCOption>;
522
523 { t.bind(req, affordance, dbcOption) } -> std::same_as<void>;
524 { t.bind(req) } -> std::same_as<void>;
525 { t.bind(affordance) } -> std::same_as<void>;
526 { t.bind(dbcOption) } -> std::same_as<void>;
527
528 { t.bound() } -> std::convertible_to<bool>;
529 { t.boundToRequirement() } -> std::convertible_to<bool>;
530 { t.boundToAffordanceCollection() } -> std::convertible_to<bool>;
531 { t.boundToDBCOption() } -> std::convertible_to<bool>;
532 { t.estimateOfConnectivity() } -> std::convertible_to<size_t>;
533
534 { t.createFullVector(std::declval<Eigen::Ref<const Eigen::VectorXd>>()) } -> std::convertible_to<Eigen::VectorXd>;
535 { t.constraintsBelow(std::declval<size_t>()) } -> std::convertible_to<size_t>;
536 { t.isConstrained(std::declval<size_t>()) } -> std::convertible_to<bool>;
537 { t.size() } -> std::convertible_to<size_t>;
538 { t.reducedSize() } -> std::convertible_to<size_t>;
539 };
540
547 template <typename T>
549 Concepts::FlatAssembler<T> and requires(T t, const typename T::FERequirement& req,
550 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
551 { t.scalar(req, affordance.scalarAffordance()) } -> std::convertible_to<const double&>;
552 { t.scalar() } -> std::convertible_to<const double&>;
553 };
554
561 template <typename T>
563 requires(T t, const typename T::FERequirement& req,
564 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
565 {
566 t.vector(req, affordance.vectorAffordance(), dbcOption)
567 } -> std::convertible_to<const Eigen::VectorXd&>;
568 { t.vector(dbcOption) } -> std::convertible_to<const Eigen::VectorXd&>;
569 { t.vector() } -> std::convertible_to<const Eigen::VectorXd&>;
570 };
571
578 template <typename T>
580 requires(T t, const typename T::FERequirement& req,
581 typename T::AffordanceCollectionType affordance, DBCOption dbcOption) {
582 { t.matrix(req, affordance.matrixAffordance(), dbcOption) };
583 { t.matrix(dbcOption) };
584 { t.matrix() };
585 };
586
587 // adapted from /dune/dune-vtk/dune/vtk/utility/concepts.hh
588 template <class DC>
589 concept DataCollector = requires(DC dc) {
590 typename DC::GridView;
591 { dc.update() } -> std::same_as<void>;
592 { dc.numPoints() } -> std::convertible_to<std::uint64_t>;
593 { dc.numCells() } -> std::convertible_to<std::uint64_t>;
594 { dc.gridView() } -> std::same_as<const typename DC::GridView&>;
595 };
596
597 template <class GV>
598 concept GridView = requires(GV g) {
599 typename GV::Grid;
600 GV::dimension;
601 GV::dimensionworld;
602
603 { g.grid() };
604 };
605
606 namespace Impl {
607 template <typename T>
608 struct is_dual : std::false_type
609 {
610 };
611
612 // Specialization for Dual<T, U>: this will be true for Dual types
613 template <typename T, typename U>
614 struct is_dual<autodiff::detail::Dual<T, U>> : std::true_type
615 {
616 };
617 } // namespace Impl
618
624 template <typename T>
625 concept AutodiffScalar = Impl::is_dual<T>::value;
626
632 template <typename T>
633 concept SmartPointer = traits::isSharedPtr<T>::value || traits::isUniquePtr<T>::value;
634
640 template <typename T>
642
648 template <typename S>
649 concept ControlRoutineState = requires(S s) {
650 typename S::Domain;
651
652 { s.information } -> std::same_as<const ControlInformation&>;
653 { s.loadStep } -> std::convertible_to<int>;
654 { s.stepSize } -> std::convertible_to<double>;
655 { s.domain } -> std::same_as<const typename S::Domain&>;
656 };
657
663 template <typename S>
664 concept NonLinearSolverState = requires(S s) {
665 typename S::Domain;
666 typename S::CorrectionType;
667
668 { s.information } -> std::same_as<const NonLinearSolverInformation&>;
669 { s.domain } -> std::same_as<const typename S::Domain&>;
670 { s.correction } -> std::same_as<const typename S::CorrectionType&>;
671 };
672
676 template <StrainTags tag>
679
683 template <StressTags tag>
685
686 namespace Formulations {
693 template <StrainTags T1, StressTags T2>
696
703 template <StrainTags T1, StressTags T2>
704 concept TwoPoint =
706 } // namespace Formulations
707
714 template <typename M>
715 concept Material = requires(M m, Eigen::Matrix3d C) {
716 M::strainTag;
717 M::stressTag;
718 M::tangentModuliTag;
719 M::derivativeFactor;
720 M::isReduced;
721
722 typename M::ScalarType;
723
724 { m.name() } -> std::convertible_to<std::string>;
725 { m.materialParameters() } -> std::same_as<typename M::MaterialParameters>;
726 { m.template storedEnergy<M::strainTag>(C) } -> std::same_as<typename M::ScalarType>;
727 { m.template stresses<M::strainTag>(C) };
728 { m.template tangentModuli<M::strainTag>(C) };
729 };
730
737 template <typename MAT>
739
746 template <typename ES>
747 concept EigenValueSolver = requires(ES es) {
748 typename ES::MatrixType;
749 typename ES::ScalarType;
750 { es.compute() } -> std::same_as<bool>;
751 { es.eigenvalues() } -> std::convertible_to<Eigen::VectorX<typename ES::ScalarType>>;
752 { es.eigenvectors() } -> std::convertible_to<Eigen::MatrixX<typename ES::ScalarType>>;
753 { es.nev() } -> std::convertible_to<int>;
754 };
755
756} // namespace Concepts
757
758namespace traits {
759#ifndef DOXYGEN
760
761 // Primary template: for non-pointer types.
762 template <typename T, bool = Concepts::PointerOrSmartPointer<T>>
763 struct MaybeDereference
764 {
765 using type = T;
766 };
767
768 // Specialization: for pointer (or smart pointer) types.
769 template <typename T>
770 struct MaybeDereference<T, true>
771 {
772 // We know T is pointer-like, so *std::declval<T&>() is well-formed.
773 using type = std::remove_reference_t<decltype(*std::declval<T&>())>;
774 };
775#endif
776
777 template <typename T>
778 using MaybeDereferencedType = typename MaybeDereference<T>::type;
779
780} // namespace traits
781
782} // 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:778
Definition: utils/concepts.hh:30
Concept to check if a type is derived from Eigen::MatrixBase.
Definition: utils/concepts.hh:49
Concept to check if a basis uses FlatInterleaved indexing strategy.
Definition: utils/concepts.hh:60
Concept to check if a node in a basis tree is a Lagrangian node.
Definition: utils/concepts.hh:92
Definition: utils/concepts.hh:102
Concept to check if a basis uses FlatLexicographic indexing strategy.
Definition: utils/concepts.hh:113
Concept to check if a basis uses FlatIndex indexing strategy.
Definition: utils/concepts.hh:126
Concept to check if a basis uses BlockedInterleaved indexing strategy.
Definition: utils/concepts.hh:137
Concept to check if a basis uses BlockedLexicographic indexing strategy.
Definition: utils/concepts.hh:150
Concept to check if a local basis is a duneLocalBasis.
Definition: utils/concepts.hh:160
Concept to check if a basis uses either BlockedLexicographic or BlockedInterleaved indexing strategy.
Definition: utils/concepts.hh:185
Concept defining the requirements for a path-following strategy.
Definition: utils/concepts.hh:195
Concept to check if a type implements all the needed functions to be an adaptive step sizing method.
Definition: utils/concepts.hh:210
Concept to check if a linear solver implements all the needed functions for given vector and matrix t...
Definition: utils/concepts.hh:226
Concept to check if a non-linear solver with its non-linear operator satisfies requirements for path ...
Definition: utils/concepts.hh:240
Concept defining the requirements for types that support multiplication.
Definition: utils/concepts.hh:256
Concept defining the requirements for types that support addition.
Definition: utils/concepts.hh:266
Concept defining the requirements for types that support subtraction.
Definition: utils/concepts.hh:276
Concept defining the requirements for types that support in-place multiplication.
Definition: utils/concepts.hh:287
Concept defining the requirements for types that support in-place division.
Definition: utils/concepts.hh:298
Concept defining the requirements for types that support in-place addition.
Definition: utils/concepts.hh:309
Concept defining the requirements for types that support in-place subtraction.
Definition: utils/concepts.hh:320
Concept defining the requirements for types that support division.
Definition: utils/concepts.hh:330
Concept defining the requirements for types that support negation.
Definition: utils/concepts.hh:339
Concept defining the requirements for types that support transposition.
Definition: utils/concepts.hh:348
Concept defining the requirements for functors with arguments.
Definition: utils/concepts.hh:357
Concept defining the requirements for Eigen vectors.
Definition: utils/concepts.hh:365
Concept defining the requirements for Eigen matrices. This also includes Eigen vectors.
Definition: utils/concepts.hh:373
Concept defining the requirements for sparse Eigen matrices.
Definition: utils/concepts.hh:381
Concept defining the requirements for sparse or dense Eigen matrices.
Definition: utils/concepts.hh:389
Concept defining the requirements for a material type.
Definition: utils/concepts.hh:483
A concept to check if a template type satisfies the ResultType requirements.
Definition: utils/concepts.hh:505
Concept representing the requirements for a FlatAssembler.A type T satisfies FlatAssembler if it prov...
Definition: utils/concepts.hh:517
Concept representing the requirements for a ScalarFlatAssembler.A type T satisfies ScalarFlatAssemble...
Definition: utils/concepts.hh:548
Concept representing the requirements for a VectorFlatAssembler.A type T satisfies VectorFlatAssemble...
Definition: utils/concepts.hh:562
Concept representing the requirements for a MatrixFlatAssembler.A type T satisfies MatrixFlatAssemble...
Definition: utils/concepts.hh:579
Definition: utils/concepts.hh:589
Definition: utils/concepts.hh:598
Concept to check if the underlying scalar type is a dual type.
Definition: utils/concepts.hh:625
Concept to check if the type is either a unique_ptr or a shared_ptr.
Definition: utils/concepts.hh:633
Definition: utils/concepts.hh:641
Concept to check if a type represents a control routine state.
Definition: utils/concepts.hh:649
Concept to check if a type represents a nonlinear solver state.
Definition: utils/concepts.hh:664
Returns true if a given straintag is related only to the reference configuration.
Definition: utils/concepts.hh:677
Returns true if a given stresstag is related only to the reference configuration.
Definition: utils/concepts.hh:684
Concept to check if the underlying strain and stress tag correspond to a total Lagrangian formulation...
Definition: utils/concepts.hh:694
Concept to check if the underlying strain and stress tag correspond to a two point formulation.
Definition: utils/concepts.hh:704
Concept representing a material interface.
Definition: utils/concepts.hh:715
Concepts defining the requirements for a material to be geometrically linear This is the case when th...
Definition: utils/concepts.hh:738
Concept representing an eigenvalue solver interface.
Definition: utils/concepts.hh:747
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:403
#define MAKE_EIGEN_FIXED_MATRIX_OR_VOIGT_CONCEPT(Size1, Size2)
Definition: utils/concepts.hh:445
#define MAKE_EIGEN_FIXED_VECTOR_CONCEPT(Size)
Definition: utils/concepts.hh:391