DirichletBC.hpp 3.4 KB
Newer Older
1 2 3
#pragma once

#include <functional>
4
#include <list>
5
#include <memory>
6 7
#include <vector>

8
#include <dune/common/std/optional.hh>
9

10
#include <amdis/Boundary.hpp>
11
#include <amdis/BoundaryCondition.hpp>
12
#include <amdis/common/Concepts.hpp>
13
#include <amdis/typetree/RangeType.hpp>
14
#include <amdis/typetree/Traversal.hpp>
15
#include <amdis/typetree/TreeData.hpp>
16

17 18
namespace AMDiS
{
19 20
  /// Implements a boundary condition of Dirichlet-type.
  /**
21
   * By calling the methods \ref init() and \ref finish before and after
22
   * assembling the system-matrix, respectively, dirichlet boundary conditions
23
   * can be applied to the matrix and system vector. Therefore, a predicate
24
   * functions indicates the DOFs where values should be enforced and a second
25
   * functor provided in the constructor is responsible for determining the
26
   * values to be set at the DOFs.
27 28 29 30
   *
   * In the \ref finish method the matrix is called with \ref applyDirichletBC
   * to erase the corresponding rows and columns for the DOF indices. This
   * application of boundary conditions can be symmetric if the matrix does
31 32 33
   * support this symmetric modification. As a result, this method returns a list
   * of columns values, that should be subtracted from the rhs.
   **/
34
  template <class Domain, class Range = double>
35
  class DirichletBC
36
      : public BoundaryCondition
37
  {
38 39
    using Super = BoundaryCondition;

40
  public:
41 42 43
    template <class BM, class Values,
      REQUIRES(Concepts::Functor<Values, Range(Domain)>) >
    DirichletBC(BM&& boundaryManager, BoundaryType id, Values&& values)
44 45
      : Super(FWD(boundaryManager), id)
      , values_(FWD(values))
46 47
    {}

48
    template <class Predicate, class Values,
49 50
      REQUIRES(Concepts::Functor<Predicate, bool(Domain)>),
      REQUIRES(Concepts::Functor<Values, Range(Domain)>)>
51
    DirichletBC(Predicate&& predicate, Values&& values)
52 53
      : predicate_(FWD(predicate))
      , values_(FWD(values))
54
    {}
55

56 57
    template <class IS>
    bool onBoundary(IS const& intersection) const
58
    {
59 60
      return predicate_ ? (*predicate_)(intersection.geometry().center())
                        : Super::onBoundary(intersection);
61 62
    }

63
    // fill \ref dirichletNodes_ with 1 or 0 whether DOF corresponds to the boundary or not.
64 65
    template <class RB, class CB>
    void init(RB const& rowBasis, CB const& colBasis);
66

67 68
    /// \brief Apply dirichlet BC to matrix and vector, i.e., add a unit-row
    /// to the matrix and optionally delete the corresponding matrix-column.
69 70 71 72 73 74 75 76 77
    /**
     * \tparam Mat  Matrix
     * \tparam Sol  Vector of solution
     * \tparam Rhs  Vector of rhs
     * \tparam RN   RowNode
     * \tparam CN   ColNode
     **/
    template <class Mat, class Sol, class Rhs, class RN, class CN>
    void fillBoundaryCondition(Mat& matrix, Sol& solution, Rhs& rhs, RN const& rowNode, CN const& colNode);
78

79
  private:
80
    Dune::Std::optional<std::function<bool(Domain)>> predicate_;
81
    std::function<Range(Domain)> values_;
82
    std::vector<bool> dirichletNodes_;
83 84
  };

85

86
  template <class Basis>
87 88
  struct DirichletData
  {
89
    using WorldVector = typename Basis::GridView::template Codim<0>::Geometry::GlobalCoordinate;
90

91 92
    template <class RN, class CN>
    using type = std::list< std::shared_ptr<DirichletBC<WorldVector, RangeType_t<RN>>> >;
93 94
  };

95
  template <class RowBasis, class ColBasis>
96
  using DirichletBCs = MatrixData<RowBasis, ColBasis, DirichletData<RowBasis>::template type>;
97

98
} // end namespace AMDiS
99 100

#include "DirichletBC.inc.hpp"