DirichletBC.hpp 3.42 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
13
14
#include <amdis/common/Concepts.hpp>
#include <amdis/utility/RangeType.hpp>
#include <amdis/utility/TreeData.hpp>
15
#include <amdis/utility/Visitor.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
44
45
46
47
    template <class BM, class Values,
      REQUIRES(Concepts::Functor<Values, Range(Domain)>) >
    DirichletBC(BM&& boundaryManager, BoundaryType id, Values&& values)
      : Super(std::forward<BM>(boundaryManager), id)
      , values_(std::forward<Values>(values))
    {}

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_(std::forward<Predicate>(predicate))
      , values_(std::forward<Values>(values))
54
    {}
55

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

63
64
65
    // fill \ref dirichletNodes_ with 1 or 0 whether DOF corresponds to the boundary or not.
    template <class RowBasis, class ColBasis>
    void init(RowBasis const& rowBasis, ColBasis 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
    template <class Matrix, class VectorX, class VectorB, class RowNode, class ColNode>
70
71
    void fillBoundaryCondition(Matrix& matrix, VectorX& solution, VectorB& rhs,
                               RowNode const& rowNode, ColNode const& colNode);
72

73
  private:
74
    Dune::Std::optional<std::function<bool(Domain)>> predicate_;
75
    std::function<Range(Domain)> values_;
76
    std::vector<bool> dirichletNodes_;
77
78
  };

79

80
  template <class Basis>
81
82
  struct DirichletData
  {
83
    using WorldVector = typename Basis::GridView::template Codim<0>::Geometry::GlobalCoordinate;
84

85
    template <class RowNode, class ColNode>
86
    using type = std::list< std::shared_ptr<DirichletBC<WorldVector, RangeType_t<RowNode>>> >;
87
88
  };

89
  template <class RowBasis, class ColBasis>
90
  using DirichletBCs = MatrixData<RowBasis, ColBasis, DirichletData<RowBasis>::template type>;
91

92
} // end namespace AMDiS
93
94

#include "DirichletBC.inc.hpp"