Skip to content
Snippets Groups Projects
Commit bd66a3a3 authored by Timo Koch's avatar Timo Koch
Browse files

new slides

parent 28203b71
No related branches found
No related tags found
1 merge request!270[properties][slides] Renew properties slides
Pipeline #47220 passed
...@@ -3,22 +3,40 @@ title: The DuMuX property system ...@@ -3,22 +3,40 @@ title: The DuMuX property system
subtitle: Flexible compile-time customization subtitle: Flexible compile-time customization
--- ---
# System Design # Property System Design
## Goals ## Goals
- Easy to change parts of the simulation - Change parts of the simulation
- Add a energy equation - e.g. add a energy equation
- Reuse specializations efficiently - Reuse specializations efficiently
- Test various discretization schemes for same application - e.g. test various discretization schemes for same application
- Group properties of the simulations - Group properties of the simulation
- Improves readability - Improves readability
- Efficiency (runtime and implementation time)
## Customization points
- Simulations have many possible customization points!
- fluid system, constitutive relations
- the type of the grid (incl. dimension)
- the terms in the equation
- discretization scheme
- details of the discretization scheme
- ...
## Challenges
- Simulations have many possible customization points
- This means many properties
- Composing and reusing properties while keeping flexibility is technically challenging
# A C++ solution # A C++ solution
## Template parameters ## Template parameters
- C++ supports _generic programming_ via __templates__ - C++ supports _generic programming_ via __templates__
- e.g. classes defined in terms of other types - e.g. classes parameterized in terms of other types
- concrete versions of templates are stamped out upon compilation - concrete versions of templates are defined by specifying concrete types
- the actual type has to be known at compilation time
- __Flexible__: implementation not restricted to _concrete types_ - __Flexible__: implementation not restricted to _concrete types_
- __Efficient__: decisions made at compile-time - __Efficient__: decisions made at compile-time
...@@ -32,20 +50,12 @@ An example - `std::vector` ...@@ -32,20 +50,12 @@ An example - `std::vector`
template<typename T, typename A = std::allocator<T>> template<typename T, typename A = std::allocator<T>>
class vector; class vector;
// Instantiation of a concrete vector - a vector of ints. // Instantiation of a concrete vector - a vector of ints.
// The compiler will define this concrete type for us, // The compiler will define this concrete type for us,
// using the definition of the class template. // using the definition of the class template.
std::vector<int> v; std::vector<int> v;
``` ```
## Template parameters
An example - `std::vector`
<img src="./img/template_example.png" width="800"/>
## Template specializations ## Template specializations
Template implementations can be specialized for concrete types Template implementations can be specialized for concrete types
...@@ -64,7 +74,23 @@ class MyVector<int> ...@@ -64,7 +74,23 @@ class MyVector<int>
}; };
``` ```
## Too many template parameters ## Templates in algorithms
Using class templates, we can write _generic_ algorithms
```cpp
template<typename T>
double two_norm(const MyVector<T>& v)
{
double norm = 0.0;
for (int i = 0; i < v.size(); ++i)
norm += v[i]*v[i];
return std::sqrt(norm);
}
```
## Challenge: Too many parameters
For some classes, providing all template parameters can be very cumbersome and error-prone. For some classes, providing all template parameters can be very cumbersome and error-prone.
...@@ -78,7 +104,7 @@ using GOF0 = Dune::GridOperator< ...@@ -78,7 +104,7 @@ using GOF0 = Dune::GridOperator<
``` ```
## Traits classes ## Technique 1: Traits classes
A usual way to group template parameters A usual way to group template parameters
...@@ -97,7 +123,7 @@ struct TwoPVolumeVariablesTraits ...@@ -97,7 +123,7 @@ struct TwoPVolumeVariablesTraits
}; };
``` ```
## Type traits ## Technique 2: Type traits
Why do we need the type? Why do we need the type?
...@@ -114,7 +140,7 @@ template<typename T, int size> ...@@ -114,7 +140,7 @@ template<typename T, int size>
struct ValueType<Dune::FieldVector<T, size>> { using type = T; }; struct ValueType<Dune::FieldVector<T, size>> { using type = T; };
``` ```
## Type traits ## Technique 2: Type traits
```cpp ```cpp
...@@ -125,7 +151,7 @@ class TwoPVolumeVariables ...@@ -125,7 +151,7 @@ class TwoPVolumeVariables
... ...
using FluidSystem = typename Traits::FluidSystem using FluidSystem = typename Traits::FluidSystem
... ...
``` ```
Usage: these VolumeVariables will work for various FluidSystems: Usage: these VolumeVariables will work for various FluidSystems:
...@@ -134,7 +160,7 @@ Usage: these VolumeVariables will work for various FluidSystems: ...@@ -134,7 +160,7 @@ Usage: these VolumeVariables will work for various FluidSystems:
Scalar mu = FluidSystem::viscosity(fluidState, paramCache, phaseIdx); Scalar mu = FluidSystem::viscosity(fluidState, paramCache, phaseIdx);
``` ```
## Inheriting from traits classes ## Challenge: Inheritance
Inheritance may lead to unexpected results Inheritance may lead to unexpected results
...@@ -153,8 +179,8 @@ struct MyDoubleTraits : public MyBaseTraits ...@@ -153,8 +179,8 @@ struct MyDoubleTraits : public MyBaseTraits
// this is a vector of ints! // this is a vector of ints!
typename MyDoubleTraits::Vector v{1.14142, 1.73205}; typename MyDoubleTraits::Vector v{1.14142, 1.73205};
``` ```
# The DuMuX Property System
# The DuMuX Property System
## Property System Design ## Property System Design
- Based on __C++ template specialization__ (_type traits_) - Based on __C++ template specialization__ (_type traits_)
...@@ -190,7 +216,7 @@ A simplified example to illustrate the idea ...@@ -190,7 +216,7 @@ A simplified example to illustrate the idea
```cpp ```cpp
template<class TypeTag> template<class TypeTag>
class GenericClass class GenericClass // e.g. LocalResidual
{ {
using PropA = typename Properties::PropTagA<TypeTag>::type; using PropA = typename Properties::PropTagA<TypeTag>::type;
using PropB = typename Properties::PropTagB<TypeTag>::type; using PropB = typename Properties::PropTagB<TypeTag>::type;
...@@ -232,8 +258,8 @@ struct Scalar<TypeTag, TTag::BaseTag> { using type = int; }; ...@@ -232,8 +258,8 @@ struct Scalar<TypeTag, TTag::BaseTag> { using type = int; };
// specialization of the Vector property for BaseTag // specialization of the Vector property for BaseTag
template<class TypeTag> template<class TypeTag>
struct Vector<TypeTag, TTag::BaseTag> { struct Vector<TypeTag, TTag::BaseTag> {
private: using Scalar = GetPropType<TypeTag, Properties::Scalar>; using Scalar = GetPropType<TypeTag, Properties::Scalar>;
public: using type = std::vector<Scalar>; using type = std::vector<Scalar>;
}; };
``` ```
...@@ -409,3 +435,64 @@ class Problem ...@@ -409,3 +435,64 @@ class Problem
* e.g. <span style="color:blue">TwoP, TwoPTwoC, TwoPNI</span> * e.g. <span style="color:blue">TwoP, TwoPTwoC, TwoPNI</span>
- By deriving your __type tag__ from those, your problem inherits all type information needed to set up the model at compile time! - By deriving your __type tag__ from those, your problem inherits all type information needed to set up the model at compile time!
- Example: see Exercise - Example: see Exercise
# Alternatives to properties
## Should I create new properties
- Not necessary for most problems
- Only when designing a complex class of models (e.g. porous medium flow models)
- When there is many customization points
## Alternative 1:
- Use a simple template argument
```cpp
template <bool useNeummanBoundaryConditions>
class Problem
{
...
if constexpr (useNeummanBoundaryConditions)
...
else
...
};
```
## Alternative 2:
C++ type traits
```cpp
template<class CouplingManager>
struct SupportsMultithreadedAssembly
: public std::false_type {}
```
## Alternative 2:
C++ type traits
```cpp
class MyCouplingManager { ... };
template<>
struct SupportsMultithreadedAssembly<MyCouplingManager>
: public std::true_type {}
```
## Alternative 2:
Generic algorithm
```cpp
template<class CouplingManager>
class Assembler {
void assemble() {
if (SupportsMultithreadedAssembly<CouplingManager>::value)
// assembly multi-threaded
else
// assembly single-threaded
}
};
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment