Commit 681e70ef by Praetorius, Simon

### Constraints improvements

parent 34c64903
 #pragma once #include #include #include #include #include namespace AMDiS #include #include namespace AMDiS { namespace Impl { template struct BoundaryConditionDefinition { /// \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 // Definition of the interface a BoundaryCondition must fulfill struct Interface { public: /// 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. **/ virtual ~Interface() = default; virtual void init() = 0; virtual void apply(Mat&, Sol&, Rhs&) = 0; }; /// \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. **/ virtual void apply(Mat& A, Sol& x, Rhs& b) = 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); } }; template struct BCData // The Concept definition of a BoundaryCondition struct Concept { template using type = std::list>>; template auto require(BC&& bc) -> decltype ( bc.init(), bc.apply(std::declval(), std::declval(), std::declval()) ); }; /// Container for storing shared pointers to boundary conditions indexed by their position in /// the basis tree, see \ref MatrixData. template using BoundaryConditions = TreeMatrix::template type, typename RB::LocalView::Tree, typename CB::LocalView::Tree>; 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
 ... ... @@ -32,22 +32,14 @@ namespace AMDiS * application of boundary conditions can be symmetric if the matrix does * support this symmetric modification. * * \tparam Mat Matrix * \tparam Sol Vector of solution * \tparam Rhs Vector of rhs * \tparam RowSubBasis SubspaceBasis of the row FE space * \tparam ColSubBasis SubspaceBasis of the column FE space * \tparam SubBasis SubspaceBasis of the solution FE space * \tparam ValueGridFct Type of the GridFunction representing the Dirichlet values. **/ template template class DirichletBC : public BoundaryCondition { using Super = BoundaryCondition; // We assume CB's GridView to be the same as RB's using GridView = typename RowSubBasis::GridView; using GridView = typename SubBasis::GridView; using Intersection = typename GridView::Intersection; using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate; ... ... @@ -57,78 +49,72 @@ namespace AMDiS /// Constructor accepting subspacebases. template )> DirichletBC(RowSubBasis rowBasis, ColSubBasis colBasis, BoundarySubset boundarySubset, Values&& values) : rowBasis_(std::move(rowBasis)) , colBasis_(std::move(colBasis)) DirichletBC(SubBasis basis, BoundarySubset boundarySubset, Values&& values) : basis_(std::move(basis)) , boundarySubset_(std::move(boundarySubset)) , values_(FWD(values)) {} /// Make a DirichletBC from a basis with treepath arguments template )> DirichletBC(Basis const& basis, TP const& treePath, BoundarySubset boundarySubset, Values&& values) : DirichletBC(Dune::Functions::subspaceBasis(basis, treePath), std::move(boundarySubset), FWD(values)) {} /// Make a DirichletBC from a global basis template )> DirichletBC(Basis const& basis, BoundarySubset boundarySubset, Values&& values) : DirichletBC(Dune::Functions::subspaceBasis(basis, makeTreePath()), std::move(boundarySubset), FWD(values)) {} /// Fill \ref dirichletNodes_ with 1 or 0 whether DOF corresponds to the /// boundary or not. /** * \see BoundaryCondition::init **/ void init() override; void init(); /// \brief Apply dirichlet BC to matrix and vector /** * Add a unit-row to the matrix and optionally delete the corresponding matrix-column. * Uses a backend-specific implementation. **/ void apply(Mat& matrix, Sol& solution, Rhs& rhs) override; template void apply(Mat& matrix, Sol& solution, Rhs& rhs); private: RowSubBasis rowBasis_; ColSubBasis colBasis_; SubBasis basis_; BoundarySubset boundarySubset_; ValueGridFct values_; std::vector dirichletNodes_; }; /// Make a DirichletBC from subspacebases template auto makeDirichletBC(Dune::Functions::SubspaceBasis rowBasis, Dune::Functions::SubspaceBasis colBasis, BoundarySubset boundarySubset, Values&& values) { using RowSubBasis = Dune::Functions::SubspaceBasis; using ColSubBasis = Dune::Functions::SubspaceBasis; using BcType = DirichletBC; return BcType(std::move(rowBasis), std::move(colBasis), std::move(boundarySubset), FWD(values)); } /// Make a DirichletBC from a row- and colbasis with treepath arguments template ), REQUIRES(Concepts::GlobalBasis)> auto makeDirichletBC(RB const& rowBasis, RTP const& rowTreePath, CB const& colBasis, CTP const& colTreePath, BoundarySubset boundarySubset, Values&& values) { return makeDirichletBC( Dune::Functions::subspaceBasis(rowBasis, rowTreePath), Dune::Functions::subspaceBasis(colBasis, colTreePath), std::move(boundarySubset), FWD(values)); } /// Make a DirichletBC from a global row- and colbasis template ), REQUIRES(Concepts::GlobalBasis)> auto makeDirichletBC(RB const& rowBasis, CB const& colBasis, BoundarySubset boundarySubset, Values&& values) { return makeDirichletBC( rowBasis, makeTreePath(), colBasis, makeTreePath(), std::move(boundarySubset), FWD(values)); } // deduction guides // Make a DirichletBC from subspacebases template DirichletBC(Dune::Functions::SubspaceBasis, BoundarySubset, Values const&) -> DirichletBC, Underlying_t>; // Make a DirichletBC from a basis with treepath arguments template )> DirichletBC(B const&, TP const&, BoundarySubset, Values const&) -> DirichletBC, Underlying_t>; // Make a DirichletBC from a global basis template )> DirichletBC(B const&, BoundarySubset, Values const&) -> DirichletBC, Underlying_t>; } // end namespace AMDiS ... ...
 ... ... @@ -8,50 +8,36 @@ #include namespace AMDiS { namespace Impl { /// Traverse all interior boundary DOFs and apply the functor f. /// The Functor must have the signature /// void(int, typename Basis::LocalView, typename Basis::GridView::Intersection) template void forEachInteriorBoundaryDOF(Basis const& basis, F&& f) template void DirichletBC:: init() { auto localView = basis.localView(); auto seDOFs = Dune::Functions::subEntityDOFs(basis); auto const& gridView = basis.gridView(); for (auto const& element : elements(gridView, typename BackendTraits::PartitionSet{})) { dirichletNodes_.assign(basis_.dimension(), false); auto localView = basis_.localView(); auto seDOFs = Dune::Functions::subEntityDOFs(basis_); auto const& gridView = basis_.gridView(); for (auto const& element : elements(gridView, typename BackendTraits::PartitionSet{})) { if (element.hasBoundaryIntersections()) { localView.bind(element); for(auto const& intersection: intersections(gridView, element)) if (intersection.boundary()) for(auto localIndex: seDOFs.bind(localView,intersection)) f(localIndex, localView, intersection); dirichletNodes_[localView.index(localIndex)] = dirichletNodes_[localView.index(localIndex)] || boundarySubset_(intersection); } } } } // end namespace Impl template void DirichletBC:: init() { using LV = typename CB::LocalView; dirichletNodes_.assign(colBasis_.dimension(), false); Impl::forEachInteriorBoundaryDOF(colBasis_, [&](int localIndex, LV const& localView, Intersection const& intersection) { dirichletNodes_[localView.index(localIndex)] = dirichletNodes_[localView.index(localIndex)] || boundarySubset_(intersection); }); } template void DirichletBC:: template template void DirichletBC:: apply(Mat& matrix, Sol& solution, Rhs& rhs) { AMDiS::interpolate(colBasis_, solution, values_, tag::defaulted{}, tag::defaulted{}, dirichletNodes_); AMDiS::interpolate(basis_, solution, values_, tag::defaulted{}, tag::defaulted{}, dirichletNodes_); dirichletBC(matrix, solution, rhs, dirichletNodes_); } ... ...
 ... ... @@ -57,11 +57,9 @@ namespace AMDiS * \tparam Basis RowBasis, must be the same as ColBasis * \tparam TP Treepath to the node this constraint applies to **/ template template class PeriodicBC : public BoundaryCondition { using Super = BoundaryCondition; using SubspaceBasis = Dune::Functions::SubspaceBasis; public: ... ... @@ -85,7 +83,7 @@ namespace AMDiS * true for all DOFs on the periodic boundary. Furthermode associations() is initialized and * contains the index of the DOF associated to a DOF on the periodic boundary. **/ void init() override; void init(); /// Move matrix rows (and columns) of dependant DOFs to the corresponding master DOFs /** ... ... @@ -93,7 +91,8 @@ namespace AMDiS * columns) of dependant DOFs to unit-rows[columns] with entries of -1 at master DOF indices. * Uses a backend-specific implementation. **/ void apply(Mat& matrix, Sol& solution, Rhs& rhs) override; template void apply(Mat& matrix, Sol& solution, Rhs& rhs); /// Return the map of DOF associations auto const& associations() const ... ... @@ -134,35 +133,35 @@ namespace AMDiS /// Make a PeriodicBC from a subspacebasis template template auto makePeriodicBC(Dune::Functions::SubspaceBasis basis, BoundarySubset boundarySubset, Impl::FaceTrafo trafo) { using BcType = PeriodicBC; using BcType = PeriodicBC; return BcType(std::move(basis), std::move(boundarySubset), std::move(trafo)); } /// Make a PeriodicBC from a global basis and treepath template )> auto makePeriodicBC(B const& basis, TP const& tp, BoundarySubset boundarySubset, Impl::FaceTrafo trafo) { return makePeriodicBC(Dune::Functions::subspaceBasis(basis, tp), std::move(boundarySubset), std::move(trafo)); return makePeriodicBC(Dune::Functions::subspaceBasis(basis, tp), std::move(boundarySubset), std::move(trafo)); } /// Make a PeriodicBC from a global basis template )> auto makePeriodicBC(B const& basis, BoundarySubset boundarySubset, Impl::FaceTrafo trafo) { return makePeriodicBC(basis, makeTreePath(), std::move(boundarySubset), std::move(trafo)); return makePeriodicBC(basis, makeTreePath(), std::move(boundarySubset), std::move(trafo)); } } // end namespace AMDiS ... ...
 ... ... @@ -14,8 +14,8 @@ namespace AMDiS { template void PeriodicBC:: template void PeriodicBC:: init() { if (!bool(hasConnectedIntersections_)) { ... ... @@ -41,8 +41,8 @@ init() } template void PeriodicBC:: template void PeriodicBC:: initAssociations() { using std::sqrt; ... ... @@ -124,8 +124,8 @@ namespace Impl } template void PeriodicBC:: template void PeriodicBC:: initAssociations2() { using std::sqrt; ... ... @@ -191,9 +191,9 @@ initAssociations2() } template template template auto PeriodicBC:: auto PeriodicBC:: coords(Node const& tree, std::vector const& localIndices) const { std::vector dofCoords(localIndices.size()); ... ... @@ -231,8 +231,9 @@ coords(Node const& tree, std::vector const& localIndices) const } template void PeriodicBC:: template template void PeriodicBC:: apply(Mat& matrix, Sol& solution, Rhs& rhs) { periodicBC(matrix, solution, rhs, periodicNodes_, associations_); ... ...
 ... ... @@ -305,6 +305,10 @@ namespace AMDiS void addPeriodicBC(BoundaryType id, WorldMatrix const& A, WorldVector const& b); /** @} */ void addConstraint(BoundaryCondition constraint) { constraints_.push_back(constraint); } public: ... ... @@ -497,7 +501,8 @@ namespace AMDiS void initGlobalBasis(); private: protected: /// Name of this problem. std::string name_; ... ... @@ -539,8 +544,8 @@ namespace AMDiS /// for each node in the basis tree, indexed by [to_string(treePath)][element index] std::map> estimates_; private: // some internal data-structures BoundaryConditions boundaryConditions_; /// List of constraints to apply to matrix, solution and rhs std::list> constraints_; }; ... ...