Commit 001f8176 authored by Praetorius, Simon's avatar Praetorius, Simon

navier stokes demo. Note: not yet working

parent 3c050d06
Pipeline #965 passed with stage
in 8 minutes and 25 seconds
...@@ -43,7 +43,6 @@ namespace AMDiS ...@@ -43,7 +43,6 @@ namespace AMDiS
void DirichletBC<WorldVector, Range>::finishImpl( void DirichletBC<WorldVector, Range>::finishImpl(
Matrix& matrix, VectorX& solution, VectorB& rhs, Matrix& matrix, VectorX& solution, VectorB& rhs,
RowBasis const& rowBasis, ColBasis const& colBasis, ValueCat) RowBasis const& rowBasis, ColBasis const& colBasis, ValueCat)
// Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag)
{ {
using Dune::Functions::interpolate; using Dune::Functions::interpolate;
......
...@@ -50,7 +50,7 @@ namespace AMDiS ...@@ -50,7 +50,7 @@ namespace AMDiS
private: // typedefs and static constants private: // typedefs and static constants
using GlobalBasis = typename Traits::GlobalBasis; using GlobalBasis = typename Traits::GlobalBasis;
using GridView = typename GlobalBasis::GridView; using GridView = typename GlobalBasis::GridView;
using Vector = DOFVectorConstView<GlobalBasis,TreePath>; using Vector = DOFVectorConstView<Traits,TreePath>;
using Range = typename Vector::Range; using Range = typename Vector::Range;
/// Dimension of the mesh /// Dimension of the mesh
...@@ -112,10 +112,10 @@ namespace AMDiS ...@@ -112,10 +112,10 @@ namespace AMDiS
}; };
template <class Traits, class GlobalBasis, class TreePath> template <class Traits, class TreePath>
std::shared_ptr<FileWriter<Traits,TreePath>> makeFileWriterPtr( std::shared_ptr<FileWriter<Traits,TreePath>> makeFileWriterPtr(
std::string baseName, std::string baseName,
DOFVectorConstView<GlobalBasis,TreePath> const& dofvector) DOFVectorConstView<Traits,TreePath> const& dofvector)
{ {
return std::make_shared<FileWriter<Traits,TreePath>>(baseName, dofvector); return std::make_shared<FileWriter<Traits,TreePath>>(baseName, dofvector);
} }
......
...@@ -56,6 +56,22 @@ namespace AMDiS ...@@ -56,6 +56,22 @@ namespace AMDiS
, order_(order) , order_(order)
{} {}
// Copy constructor
GridFunctionOperatorBase(GridFunctionOperatorBase const& that)
: gridFct_(that.gridFct_)
, localFct_(localFunction(gridFct_)) // recreate localFct_ on new gridFct_
, quadCreator_(that.quadCreator_)
, order_(that.order_)
{}
// Move constructor
GridFunctionOperatorBase(GridFunctionOperatorBase&& that)
: gridFct_(std::move(that.gridFct_))
, localFct_(localFunction(gridFct_)) // recreate localFct_ on new gridFct_
, quadCreator_(std::move(that.quadCreator_))
, order_(std::move(that.order_))
{}
/// \brief Binds operator to `element` and `geometry`. /// \brief Binds operator to `element` and `geometry`.
/** /**
* Binding an operator to the currently visited element in grid traversal. * Binding an operator to the currently visited element in grid traversal.
......
...@@ -21,7 +21,7 @@ namespace AMDiS ...@@ -21,7 +21,7 @@ namespace AMDiS
// specialization for intersections // specialization for intersections
template <class I> template <class I>
struct ContextImpl<I, Void_t<typename I::Entity>> struct ContextImpl<I, Void_t<decltype(std::declval<I>().inside())>>
{ {
using Entity = typename I::Entity; using Entity = typename I::Entity;
using Geometry = typename I::LocalGeometry; using Geometry = typename I::LocalGeometry;
......
...@@ -63,7 +63,7 @@ namespace AMDiS ...@@ -63,7 +63,7 @@ namespace AMDiS
using WorldVector = typename Element::Geometry::GlobalCoordinate; using WorldVector = typename Element::Geometry::GlobalCoordinate;
using SystemMatrix = DOFMatrix<GlobalBasis, GlobalBasis, double>; using SystemMatrix = DOFMatrix<GlobalBasis, GlobalBasis, double>;
using SystemVector = DOFVector<GlobalBasis, double>; using SystemVector = DOFVector<Traits, double>;
using LinearSolverType = LinearSolverInterface<typename SystemMatrix::BaseMatrix, typename SystemVector::BaseVector>; using LinearSolverType = LinearSolverInterface<typename SystemMatrix::BaseMatrix, typename SystemVector::BaseVector>;
......
...@@ -122,7 +122,7 @@ void ProblemStat<Traits>::createFileWriter() ...@@ -122,7 +122,7 @@ void ProblemStat<Traits>::createFileWriter()
if (!Parameters::get<std::string>(componentName + "->filename")) if (!Parameters::get<std::string>(componentName + "->filename"))
return; return;
auto writer = makeFileWriterPtr<Traits>(componentName, this->getSolution(treePath)); auto writer = makeFileWriterPtr(componentName, this->getSolution(treePath));
filewriter.push_back(std::move(writer)); filewriter.push_back(std::move(writer));
}); });
} }
...@@ -146,7 +146,7 @@ void ProblemStat<Traits>::addMatrixOperator( ...@@ -146,7 +146,7 @@ void ProblemStat<Traits>::addMatrixOperator(
auto j = child(globalBasis->localView().tree(), makeTreePath(col)); auto j = child(globalBasis->localView().tree(), makeTreePath(col));
auto op = makeGridOperator(preOp, globalBasis->gridView()); auto op = makeGridOperator(preOp, globalBasis->gridView());
auto localAssembler = makeLocalAssemblerPtr<Element>(op, i, j); auto localAssembler = makeLocalAssemblerPtr<Element>(std::move(op), i, j);
matrixOperators[i][j].element.push_back({localAssembler, factor, estFactor}); matrixOperators[i][j].element.push_back({localAssembler, factor, estFactor});
matrixOperators[i][j].changing = true; matrixOperators[i][j].changing = true;
...@@ -171,7 +171,7 @@ void ProblemStat<Traits>::addMatrixOperator( ...@@ -171,7 +171,7 @@ void ProblemStat<Traits>::addMatrixOperator(
using Intersection = typename GridView::Intersection; using Intersection = typename GridView::Intersection;
auto op = makeGridOperator(preOp, globalBasis->gridView()); auto op = makeGridOperator(preOp, globalBasis->gridView());
auto localAssembler = makeLocalAssemblerPtr<Intersection>(op, i, j); auto localAssembler = makeLocalAssemblerPtr<Intersection>(std::move(op), i, j);
matrixOperators[i][j].boundary.push_back({localAssembler, factor, estFactor, b}); matrixOperators[i][j].boundary.push_back({localAssembler, factor, estFactor, b});
matrixOperators[i][j].changing = true; matrixOperators[i][j].changing = true;
...@@ -191,7 +191,7 @@ void ProblemStat<Traits>::addVectorOperator( ...@@ -191,7 +191,7 @@ void ProblemStat<Traits>::addVectorOperator(
auto i = child(globalBasis->localView().tree(), makeTreePath(path)); auto i = child(globalBasis->localView().tree(), makeTreePath(path));
auto op = makeGridOperator(preOp, globalBasis->gridView()); auto op = makeGridOperator(preOp, globalBasis->gridView());
auto localAssembler = makeLocalAssemblerPtr<Element>(op, i); auto localAssembler = makeLocalAssemblerPtr<Element>(std::move(op), i);
rhsOperators[i].element.push_back({localAssembler, factor, estFactor}); rhsOperators[i].element.push_back({localAssembler, factor, estFactor});
rhsOperators[i].changing = true; rhsOperators[i].changing = true;
...@@ -213,7 +213,7 @@ void ProblemStat<Traits>::addVectorOperator( ...@@ -213,7 +213,7 @@ void ProblemStat<Traits>::addVectorOperator(
using Intersection = typename GridView::Intersection; using Intersection = typename GridView::Intersection;
auto op = makeGridOperator(preOp, globalBasis->gridView()); auto op = makeGridOperator(preOp, globalBasis->gridView());
auto localAssembler = makeLocalAssemblerPtr<Intersection>(op, i); auto localAssembler = makeLocalAssemblerPtr<Intersection>(std::move(op), i);
rhsOperators[i].boundary.push_back({localAssembler, factor, estFactor, b}); rhsOperators[i].boundary.push_back({localAssembler, factor, estFactor, b});
rhsOperators[i].changing = true; rhsOperators[i].changing = true;
......
...@@ -39,24 +39,22 @@ namespace AMDiS ...@@ -39,24 +39,22 @@ namespace AMDiS
return v /= factor; return v /= factor;
} }
// some arithmetic operations with FieldMatrix template <class T>
FieldVector<T,1> operator*(FieldVector<T,1> const& v, FieldVector<T,1> const& w)
template <class T, int N, int M>
FieldMatrix<T,N,M> operator+(FieldMatrix<T,N,M> A, FieldMatrix<T,N,M> const& B)
{ {
return A += B; return {v[0] * w[0]};
} }
template <class T, int N, int M> template <class T, int N>
FieldMatrix<T,N,M> operator-(FieldMatrix<T,N,M> A, FieldMatrix<T,N,M> const& B) FieldVector<T,N> operator*(FieldVector<T,1> const& factor, FieldVector<T,N> v)
{ {
return A -= B; return v *= factor[0];
} }
template <class T, int N, int M> template <class T, int N>
FieldVector<T,N> operator*(FieldMatrix<T,N,M> const& mat, FieldVector<T,M> const& vec) FieldVector<T,N> operator*(FieldVector<T,N> v, FieldVector<T,1> const& factor)
{ {
return Dune::FMatrixHelp::mult(mat, vec); return v *= factor[0];
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -84,6 +82,14 @@ namespace AMDiS ...@@ -84,6 +82,14 @@ namespace AMDiS
return vec1.dot(vec2); return vec1.dot(vec2);
} }
template <class T, int N, int M,
REQUIRES( N!=1 && M!=1 )>
auto operator*(FieldVector<T,N> v, FieldVector<T,M> const& w)
{
static_assert(M == N, "Requires vectors of the same type!");
return v.dot(w);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
namespace Impl namespace Impl
...@@ -350,6 +356,9 @@ namespace AMDiS ...@@ -350,6 +356,9 @@ namespace AMDiS
return sqrt(dot(DF[0], DF[0])); return sqrt(dot(DF[0], DF[0]));
} }
// ----------------------------------------------------------------------------
// some arithmetic operations with FieldMatrix
template <class T, int M, int N> template <class T, int M, int N>
FieldMatrix<T,N,M> trans(FieldMatrix<T, M, N> const& A) FieldMatrix<T,N,M> trans(FieldMatrix<T, M, N> const& A)
{ {
...@@ -362,6 +371,45 @@ namespace AMDiS ...@@ -362,6 +371,45 @@ namespace AMDiS
} }
template <class T, int M, int N>
FieldMatrix<T,M,N> operator*(T scalar, FieldMatrix<T, M, N> A)
{
return A *= scalar;
}
template <class T, int M, int N>
FieldMatrix<T,M,N> operator*(FieldMatrix<T, M, N> A, T scalar)
{
return A *= scalar;
}
template <class T, int M, int N>
FieldMatrix<T,M,N> operator/(FieldMatrix<T, M, N> A, T scalar)
{
return A /= scalar;
}
template <class T, int M, int N>
FieldMatrix<T,M,N> operator+(FieldMatrix<T, M, N> A, FieldMatrix<T, M, N> const& B)
{
return A += B;
}
template <class T, int M, int N>
FieldMatrix<T,M,N> operator-(FieldMatrix<T, M, N> A, FieldMatrix<T, M, N> const& B)
{
return A -= B;
}
template <class T, int N, int M>
FieldVector<T,N> operator*(FieldMatrix<T,N,M> const& mat, FieldVector<T,M> const& vec)
{
return Dune::FMatrixHelp::mult(mat, vec);
}
template <class T, int M, int N, int L> template <class T, int M, int N, int L>
FieldMatrix<T,M,N> multiplies(FieldMatrix<T, M, L> const& A, FieldMatrix<T, L, N> const& B) FieldMatrix<T,M,N> multiplies(FieldMatrix<T, M, L> const& A, FieldMatrix<T, L, N> const& B)
{ {
......
...@@ -80,4 +80,17 @@ namespace AMDiS ...@@ -80,4 +80,17 @@ namespace AMDiS
} // end namespace Category } // end namespace Category
template <class V>
constexpr bool isVector(V const&)
{
static_assert(Category::Vector<V>,"");
return Category::Vector<V>;
}
template <class V>
constexpr bool isNotVector(V const&)
{
static_assert(!Category::Vector<V>,"");
return !Category::Vector<V>;
}
} // end namespace AMDiS } // end namespace AMDiS
...@@ -20,13 +20,13 @@ namespace AMDiS ...@@ -20,13 +20,13 @@ namespace AMDiS
* @{ * @{
**/ **/
template <class GlobalBasisType, class TreePathType> template <class Traits, class TreePathType>
class DOFVectorConstView class DOFVectorConstView
{ {
public: public:
using GlobalBasis = GlobalBasisType; using GlobalBasis = typename Traits::GlobalBasis;
using TreePath = TreePathType; using TreePath = TreePathType;
using Vector = DOFVector<GlobalBasis>; using Vector = DOFVector<Traits>;
using Tree = typename GlobalBasis::LocalView::Tree; using Tree = typename GlobalBasis::LocalView::Tree;
using SubTree = typename Dune::TypeTree::ChildForTreePath<Tree, TreePath>; using SubTree = typename Dune::TypeTree::ChildForTreePath<Tree, TreePath>;
...@@ -38,7 +38,8 @@ namespace AMDiS ...@@ -38,7 +38,8 @@ namespace AMDiS
using Domain = typename EntitySet::GlobalCoordinate; using Domain = typename EntitySet::GlobalCoordinate;
using Range = RangeType_t<SubTree>; using Range = RangeType_t<SubTree>;
using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<Range(Domain)>; using RawSignature = typename Dune::Functions::SignatureTraits<Range(Domain)>::RawSignature;
using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>;
using DerivativeRange = typename DerivativeTraits::Range; using DerivativeRange = typename DerivativeTraits::Range;
using LocalDomain = typename EntitySet::LocalCoordinate; using LocalDomain = typename EntitySet::LocalCoordinate;
...@@ -177,6 +178,7 @@ namespace AMDiS ...@@ -177,6 +178,7 @@ namespace AMDiS
/// \brief Create a LocalFunction representing the gradient. \relates GradientLocalFunction /// \brief Create a LocalFunction representing the gradient. \relates GradientLocalFunction
friend GradientLocalFunction derivative(LocalFunction const& localFunction) friend GradientLocalFunction derivative(LocalFunction const& localFunction)
{ {
static_assert(isValidRange<DerivativeTraits>(),"Derivative of DOFVector not defined.");
return GradientLocalFunction{*localFunction.globalFunction_}; return GradientLocalFunction{*localFunction.globalFunction_};
} }
...@@ -207,7 +209,7 @@ namespace AMDiS ...@@ -207,7 +209,7 @@ namespace AMDiS
public: public:
/// Constructor. Stores a pointer to the dofVector and a copy of the treePath. /// Constructor. Stores a pointer to the dofVector and a copy of the treePath.
DOFVectorConstView(DOFVector<GlobalBasis> const& dofVector, TreePath const& treePath) DOFVectorConstView(DOFVector<Traits> const& dofVector, TreePath const& treePath)
: dofVector_(&dofVector) : dofVector_(&dofVector)
, treePath_(treePath) , treePath_(treePath)
, entitySet_(dofVector.getFeSpace().gridView()) , entitySet_(dofVector.getFeSpace().gridView())
...@@ -246,13 +248,13 @@ namespace AMDiS ...@@ -246,13 +248,13 @@ namespace AMDiS
} }
/// Return const coefficient vector /// Return const coefficient vector
DOFVector<GlobalBasis> const& coefficients() const DOFVector<Traits> const& coefficients() const
{ {
return *dofVector_; return *dofVector_;
} }
protected: protected:
DOFVector<GlobalBasis> const* dofVector_; DOFVector<Traits> const* dofVector_;
TreePath const treePath_; TreePath const treePath_;
EntitySet entitySet_; EntitySet entitySet_;
...@@ -261,18 +263,18 @@ namespace AMDiS ...@@ -261,18 +263,18 @@ namespace AMDiS
// A mutable version of DOFVectorView // A mutable version of DOFVectorView
template <class GlobalBasisType, class TreePathType> template <class Traits, class TreePathType>
class DOFVectorMutableView class DOFVectorMutableView
: public DOFVectorConstView<GlobalBasisType, TreePathType> : public DOFVectorConstView<Traits, TreePathType>
{ {
using Super = DOFVectorConstView<GlobalBasisType, TreePathType>; using Super = DOFVectorConstView<Traits, TreePathType>;
using GlobalBasis = GlobalBasisType; using GlobalBasis = typename Traits::GlobalBasis;
using TreePath = TreePathType; using TreePath = TreePathType;
public: public:
/// Constructor. Stores a pointer to the mutable `dofvector`. /// Constructor. Stores a pointer to the mutable `dofvector`.
DOFVectorMutableView(DOFVector<GlobalBasis>& dofVector, TreePath const& treePath) DOFVectorMutableView(DOFVector<Traits>& dofVector, TreePath const& treePath)
: Super(dofVector, treePath) : Super(dofVector, treePath)
, mutableDofVector_(&dofVector) , mutableDofVector_(&dofVector)
{} {}
...@@ -287,7 +289,7 @@ namespace AMDiS ...@@ -287,7 +289,7 @@ namespace AMDiS
auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), basis.gridView()); auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), basis.gridView());
DOFVector<GlobalBasis> tmp(basis, "tmp"); DOFVector<Traits> tmp(basis, "tmp");
Dune::Functions::interpolate(basis, treePath, tmp, std::forward<decltype(gridFct)>(gridFct)); Dune::Functions::interpolate(basis, treePath, tmp, std::forward<decltype(gridFct)>(gridFct));
// move data from temporary vector into stored DOFVector // move data from temporary vector into stored DOFVector
...@@ -296,13 +298,13 @@ namespace AMDiS ...@@ -296,13 +298,13 @@ namespace AMDiS
} }
/// Return the mutable DOFVector /// Return the mutable DOFVector
DOFVector<GlobalBasis>& coefficients() { return *mutableDofVector_; } DOFVector<Traits>& coefficients() { return *mutableDofVector_; }
/// Return the const DOFVector /// Return the const DOFVector
using Super::coefficients; using Super::coefficients;
protected: protected:
DOFVector<GlobalBasis>* mutableDofVector_; DOFVector<Traits>* mutableDofVector_;
}; };
/** @} **/ /** @} **/
...@@ -310,34 +312,34 @@ namespace AMDiS ...@@ -310,34 +312,34 @@ namespace AMDiS
#ifndef DOXYGEN #ifndef DOXYGEN
// A Generator for a const \ref DOFVectorView. // A Generator for a const \ref DOFVectorView.
template <class GlobalBasis, class TreePath> template <class Traits, class TreePath>
auto makeDOFVectorView(DOFVector<GlobalBasis> const& dofVector, TreePath const& treePath) auto makeDOFVectorView(DOFVector<Traits> const& dofVector, TreePath const& treePath)
{ {
return DOFVectorConstView<GlobalBasis, TreePath>{dofVector, treePath}; return DOFVectorConstView<Traits, TreePath>{dofVector, treePath};
} }
// A Generator for a mutable \ref DOFVectorView. // A Generator for a mutable \ref DOFVectorView.
template <class GlobalBasis, class TreePath> template <class Traits, class TreePath>
auto makeDOFVectorView(DOFVector<GlobalBasis>& dofVector, TreePath const& treePath) auto makeDOFVectorView(DOFVector<Traits>& dofVector, TreePath const& treePath)
{ {
return DOFVectorMutableView<GlobalBasis, TreePath>{dofVector, treePath}; return DOFVectorMutableView<Traits, TreePath>{dofVector, treePath};
} }
// A Generator for a const \ref DOFVectorView. // A Generator for a const \ref DOFVectorView.
template <class GlobalBasis> template <class Traits>
auto makeDOFVectorView(DOFVector<GlobalBasis> const& dofVector) auto makeDOFVectorView(DOFVector<Traits> const& dofVector)
{ {
auto treePath = Dune::TypeTree::hybridTreePath(); auto treePath = Dune::TypeTree::hybridTreePath();
return DOFVectorConstView<GlobalBasis, decltype(treePath)>{dofVector, treePath}; return DOFVectorConstView<Traits, decltype(treePath)>{dofVector, treePath};
} }
// A Generator for a mutable \ref DOFVectorView. // A Generator for a mutable \ref DOFVectorView.
template <class GlobalBasis> template <class Traits>
auto makeDOFVectorView(DOFVector<GlobalBasis>& dofVector) auto makeDOFVectorView(DOFVector<Traits>& dofVector)
{ {
auto treePath = Dune::TypeTree::hybridTreePath(); auto treePath = Dune::TypeTree::hybridTreePath();
return DOFVectorMutableView<GlobalBasis, decltype(treePath)>{dofVector, treePath}; return DOFVectorMutableView<Traits, decltype(treePath)>{dofVector, treePath};
} }
#endif #endif
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
namespace AMDiS { namespace AMDiS {
template <class GlobalBasis, class TreePath> template <class Traits, class TreePath>
typename DOFVectorConstView<GlobalBasis, TreePath>::Range DOFVectorConstView<GlobalBasis, TreePath>:: typename DOFVectorConstView<Traits, TreePath>::Range DOFVectorConstView<Traits, TreePath>::
LocalFunction::operator()(LocalDomain const& x) const LocalFunction::operator()(LocalDomain const& x) const
{ {
assert( bound_ ); assert( bound_ );
...@@ -58,8 +58,8 @@ LocalFunction::operator()(LocalDomain const& x) const ...@@ -58,8 +58,8 @@ LocalFunction::operator()(LocalDomain const& x) const
} }
template <class GlobalBasis, class TreePath> template <class Traits, class TreePath>
typename DOFVectorConstView<GlobalBasis, TreePath>::DerivativeRange DOFVectorConstView<GlobalBasis, TreePath>:: typename DOFVectorConstView<Traits, TreePath>::DerivativeRange DOFVectorConstView<Traits, TreePath>::
GradientLocalFunction::operator()(LocalDomain const& x) const GradientLocalFunction::operator()(LocalDomain const& x) const
{ {
assert( bound_ ); assert( bound_ );
......
...@@ -29,13 +29,16 @@ namespace AMDiS ...@@ -29,13 +29,16 @@ namespace AMDiS
using GridFctRange = typename GridFunction::Range; using GridFctRange = typename GridFunction::Range;
using GridFctDomain = typename GridFunction::Domain; using GridFctDomain = typename GridFunction::Domain;
using RawSignature = typename Dune::Functions::SignatureTraits<GridFctRange(GridFctDomain)>::RawSignature; using RawSignature = typename Dune::Functions::SignatureTraits<GridFctRange(GridFctDomain)>::RawSignature;
using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>;
using LocalFunction = std::decay_t<decltype(derivative(localFunction(std::declval<GridFunction>())))>; using LocalFunction = std::decay_t<decltype(derivative(localFunction(std::declval<GridFunction>())))>;
public: public:
/// The Range of the derivative of the GridFunction /// The Range of the derivative of the GridFunction
using Range = typename Dune::Functions::DefaultDerivativeTraits<RawSignature>::Range; using Range = typename DerivativeTraits::Range;
/// The domain of the GridFunction /// The domain of the GridFunction
using Domain = GridFctDomain; using Domain = GridFctDomain;
/// The EntitySet of the GridFunction /// The EntitySet of the GridFunction
using EntitySet = typename GridFunction::EntitySet; using EntitySet = typename GridFunction::EntitySet;
...@@ -43,7 +46,9 @@ namespace AMDiS ...@@ -43,7 +46,9 @@ namespace AMDiS
/// Constructor. Stores a copy of gridFct. /// Constructor. Stores a copy of gridFct.
explicit DerivativeGridFunction(GridFunction const& gridFct) explicit DerivativeGridFunction(GridFunction const& gridFct)
: gridFct_(gridFct) : gridFct_(gridFct)
{} {
static_assert(isValidRange<DerivativeTraits>(), "Derivative of GridFunction not defined");
}