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

#include <functional>
4
#include <utility>
5
6
#include <vector>

7
8
9
#include <dune/common/concept.hh>
#include <dune/functions/functionspacebases/concepts.hh>
#include <dune/functions/functionspacebases/subspacebasis.hh>
10

11
#include <amdis/Boundary.hpp>
12
#include <amdis/BoundaryCondition.hpp>
13
#include <amdis/BoundarySubset.hpp>
14
#include <amdis/common/Concepts.hpp>
15
#include <amdis/common/TypeTraits.hpp>
16
#include <amdis/typetree/RangeType.hpp>
17
#include <amdis/typetree/TreePath.hpp>
18

19
20
namespace AMDiS
{
21
22
  /// Implements a boundary condition of Dirichlet-type.
  /**
23
   * By calling the methods \ref init and \ref finish before and after
24
   * assembling the system-matrix, respectively, dirichlet boundary conditions
25
   * can be applied to the matrix and system vector. Therefore, a predicate
26
   * functions indicates the DOFs where values should be enforced and a second
27
   * functor provided in the constructor is responsible for determining the
28
   * values to be set at the DOFs.
29
   *
30
   * In the \ref finish method the matrix is called with \ref apply
31
32
   * to erase the corresponding rows and columns for the DOF indices. This
   * application of boundary conditions can be symmetric if the matrix does
33
34
35
36
37
38
39
40
41
   * support this symmetric modification.
   *
   * \tparam Mat  Matrix
   * \tparam Sol  Vector of solution
   * \tparam Rhs  Vector of rhs
   * \tparam RB   Basis of the row FE space
   * \tparam RTP  Treepath to the row node this constraint applies to
   * \tparam CB   Basis of the column FE space
   * \tparam CTP  Treepath to the column node this constraint applies to
42
   **/
43
  template <class Mat, class Sol, class Rhs, class RB, class RTP, class CB, class CTP>
44
  class DirichletBC
45
      : public BoundaryCondition<Mat, Sol, Rhs>
46
  {
47
48
49
50
51
52
53
    using Super = BoundaryCondition<Mat, Sol, Rhs>;
    using RowSubBasis = Dune::Functions::SubspaceBasis<RB, RTP>;
    using ColSubBasis = Dune::Functions::SubspaceBasis<CB, CTP>;
    // We assume CB's GridView to be the same as RB's
    using Domain = typename RB::GridView::template Codim<0>::Geometry::GlobalCoordinate;
    using Intersection = typename RB::GridView::Intersection;
    using Range = RangeType_t<typename ColSubBasis::LocalView::Tree>;
54

55
  public:
56
57
58
59
60
61
62
63
    /// Constructor accepting subspacebases.
    template <class Values,
      REQUIRES(Concepts::Functor<Values, Range(Domain)>)>
    DirichletBC(RowSubBasis rowBasis, ColSubBasis colBasis,
                BoundarySubset<Intersection> boundarySubset, Values&& values)
      : rowBasis_(std::move(rowBasis))
      , colBasis_(std::move(colBasis))
      , boundarySubset_(std::move(boundarySubset))
64
      , values_(FWD(values))
65
66
    {}

67
68
    /// Constructor accepting global bases and treepaths.
    template <class Values,
69
      REQUIRES(Concepts::Functor<Values, Range(Domain)>)>
70
71
72
73
74
75
    DirichletBC(RB const& rowBasis, RTP const& rowTreePath,
                CB const& colBasis, CTP const& colTreePath,
                BoundarySubset<Intersection> boundarySubset, Values&& values)
      : DirichletBC(Dune::Functions::subspaceBasis(rowBasis, rowTreePath),
                    Dune::Functions::subspaceBasis(colBasis, colTreePath),
                    std::move(boundarySubset), FWD(values))
76
    {}
77

78
    // fill \ref dirichletNodes_ with 1 or 0 whether DOF corresponds to the boundary or not.
79
80
81
82
    /**
     * \see BoundaryCondition::init
     **/
    void init() override;
83

84
    /// \brief Apply dirichlet BC to matrix and vector
85
    /**
86
87
     * Add a unit-row to the matrix and optionally delete the corresponding matrix-column.
     * Uses a backend-specific implementation.
88
     **/
89
    void apply(Mat& matrix, Sol& solution, Rhs& rhs) override;
90

91
  private:
92
93
94
    RowSubBasis rowBasis_;
    ColSubBasis colBasis_;
    BoundarySubset<Intersection> boundarySubset_;
95
    std::function<Range(Domain)> values_;
96
    std::vector<bool> dirichletNodes_;
97
98
  };

99

100
101
102
103
104
105
  /// Make a DirichletBC from subspacebases
  template <class Mat, class Sol, class Rhs, class RB, class RTP, class CB, class CTP, class Values>
  auto makeDirichletBC(Dune::Functions::SubspaceBasis<RB, RTP> rowBasis,
                       Dune::Functions::SubspaceBasis<CB, CTP> colBasis,
                       BoundarySubset<typename RB::GridView::Intersection> boundarySubset,
                       Values&& values)
106
  {
107
108
109
110
111
112
    using BcType = DirichletBC<Mat, Sol, Rhs, RB, RTP, CB, CTP>;
    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 <class Mat, class Sol, class Rhs, class RB, class RTP, class CB, class CTP, class Values,
113
114
    REQUIRES(Concepts::GlobalBasis<RB>),
    REQUIRES(Concepts::GlobalBasis<CB>)>
115
116
117
118
119
120
121
122
123
124
125
126
  auto makeDirichletBC(RB const& rowBasis, RTP const& rowTreePath,
                       CB const& colBasis, CTP const& colTreePath,
                       BoundarySubset<typename RB::GridView::Intersection> boundarySubset,
                       Values&& values)
  {
    using BcType = DirichletBC<Mat, Sol, Rhs, RB, RTP, CB, CTP>;
    return BcType(rowBasis, rowTreePath, colBasis, colTreePath,
                  std::move(boundarySubset), FWD(values));
  }

  /// Make a DirichletBC from a global row- and colbasis
  template <class Mat, class Sol, class Rhs, class RB, class CB, class Values,
127
128
    REQUIRES(Concepts::GlobalBasis<RB>),
    REQUIRES(Concepts::GlobalBasis<CB>)>
129
130
131
132
  auto makeDirichletBC(RB const& rowBasis, CB const& colBasis,
                       BoundarySubset<typename RB::GridView::Intersection> boundarySubset,
                       Values&& values)
  {
133
    return makeDirichletBC<Mat, Sol, Rhs>(rowBasis, makeTreePath(), colBasis, makeTreePath(),
134
135
                                          std::move(boundarySubset), FWD(values));
  }
136

137
} // end namespace AMDiS
138
139

#include "DirichletBC.inc.hpp"