#pragma once #include #include #include #include namespace AMDiS { namespace Impl { template struct BoundaryConditionDefinition { // Definition of the interface a BoundaryCondition must fulfill struct Interface { virtual ~Interface() = default; virtual void init() = 0; virtual void apply(Mat&, Sol&, Rhs&) = 0; }; // Templatized implementation of the interface template struct Model : public Impl { using Impl::Impl; void init() final { this->get().init(); } void apply(Mat& A, Sol& x, Rhs& b) final { this->get().apply(A,x,b); } }; // The Concept definition of a BoundaryCondition struct Concept { template auto require(BC&& bc) -> decltype ( bc.init(), bc.apply(std::declval(), std::declval(), std::declval()) ); }; using Base = Dune::Functions::TypeErasureBase; }; } // end namespace Impl /// \brief Interface class for boundary conditions /** * Stores a boundary subset related to the boundary condition. See \ref BoundarySubset. * \relates DirichletBoundaryCondition * \relates PeriodicBoundaryCondition * \tparam Mat Matrix * \tparam Sol Vector of solution * \tparam Rhs Vector of rhs **/ template class BoundaryCondition : public Impl::BoundaryConditionDefinition::Base { using Definition = Impl::BoundaryConditionDefinition; using Super = typename Definition::Base; public: /// \brief Constructor. Pass any type supporting the \ref BoundaryConditionInterface template = 0> BoundaryCondition(Impl&& impl) : Super{FWD(impl)} { static_assert(Concepts::models, "Implementation does not model the BoundaryCondition concept."); } /// \brief Default Constructor. BoundaryCondition() = default; /// \brief Initialize the boundary condition. /** * This performs setup before starting the matrix and vector assembly independantly of the * matrix, rhs or solution. **/ void init() { this->asInterface().init(); } /// \brief Apply the boundary condition to matrix and vector. /** * This is called after the matrix `A` and rhs `b` are assembled. * Implementations may alter values or change the structure of `A`, `x` or `b`. **/ void apply(Mat& A, Sol& x, Rhs& b) { this->asInterface().apply(A,x,b); } }; } // end namespace AMDiS