Assembler.hpp 3.95 KB
Newer Older
1
2
#pragma once

3
4
5
6
7
8
9
10
11
12
13
14
#include <functional>
#include <memory>
#include <type_traits>

#include <dune/common/shared_ptr.hh>
#include <dune/geometry/quadraturerules.hh>

#include <amdis/ContextGeometry.hpp>
#include <amdis/AssemblerInterface.hpp>
#include <amdis/common/Concepts.hpp>
#include <amdis/typetree/FiniteElementType.hpp>

15
16
namespace AMDiS
{
17
18
19
20
  /// Implementation of interface \ref AssemblerBase
  template <class LocalContext, class Operator, class... Nodes>
  class Assembler
      : public AssemblerInterface<LocalContext, Nodes...>
21
  {
22
    using Super = AssemblerInterface<LocalContext, Nodes...>;
23

24
  private:
25

26
27
28
    using Element = typename Super::Element;
    using Geometry = typename Super::Geometry;
    using ElementMatrixVector = typename Super::ElementMatrixVector;
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  public:

    /// Constructor. Stores a copy of operator `op`.
    explicit Assembler(Operator const& op)
      : op_(Dune::wrap_or_move(op))
    {}

    /// Constructor. Stores a copy of operator `op`.
    explicit Assembler(Operator&& op)
      : op_(Dune::wrap_or_move(std::move(op)))
    {}

    /// Constructor. Stores the reference to the operator.
    explicit Assembler(std::reference_wrapper<Operator> op)
      : op_(Dune::wrap_or_move(op.get()))
    {}
46

47
48
49
50
51
52
    /// \brief Implementation of \ref AssemblerInterface::bind.
    /**
     * Binds the operator `op_` to the `element` and `geometry` and
     * stores point to the `element` and `geometry`.
     **/
    void bind(Element const& element, Geometry const& geometry) final
53
    {
54
55
56
      element_ = &element;
      geometry_ = &geometry;
      op_->bind(element, geometry);
57
    }
58

59
60
61
62
63
64
65
66
67
68
69
    /// \brief Implementation of \ref AssemblerBase::unbind
    /**
     * Unbinds the operator `op_` and sets \ref element_ and \ref geometry_
     * to nullptr.
     **/
    void unbind() final
    {
      op_->unbind();
      geometry_ = nullptr;
      element_ = nullptr;
    }
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    /// Implementation of \ref AssemblerBase::assemble
    /**
     * Stores geometry and localGeometry and calls
     * \ref calculateElementVector or \ref calculateElementMatrix on the
     * vector or matrix operator, respectively.
     **/
    void assemble(LocalContext const& localContext,
                  Nodes const&... nodes,
                  ElementMatrixVector& elementMatrixVector) final
    {
      ContextGeometry<LocalContext> context{localContext, element(), geometry()};
      assembleImpl(context, nodes..., elementMatrixVector);
    }


#ifndef DOXYGEN

  protected: // implementation detail

    // matrix assembling
    template <class Context, class RowNode, class ColNode, class ElementMatrix>
    void assembleImpl(Context const& context,
                      RowNode const& rowNode, ColNode const& colNode,
                      ElementMatrix& elementMatrix)
    {
      op_->calculateElementMatrix(context, rowNode, colNode, elementMatrix);
    }

    // vector assembling
    template <class Context, class Node, class ElementVector>
    void assembleImpl(Context const& context,
                      Node const& node,
                      ElementVector& elementVector)
    {
      op_->calculateElementVector(context, node, elementVector);
    }

#endif // DOXYGEN

  public:

    /// return the bound entity (of codim 0)
    Element const& element() const
    {
      assert( element_ );
      return *element_;
    }

    /// return the geometry of the bound element
    Geometry const& geometry() const
    {
      assert( geometry_ );
      return *geometry_;
    }


  private:

    /// the stored operator, implementing \ref GridFunctionOperatorBase
    std::shared_ptr<Operator> op_;

    Element const* element_ = nullptr;
    Geometry const* geometry_ = nullptr;
  };
135
136


137
138
139
  /// Generate a \ref Assembler on a given `LocalContext` (element or intersection)
  template <class LocalContext, class Operator, class... Nodes>
  auto makeAssembler(Operator&& op, Nodes const&...)
140
  {
141
    return Assembler<LocalContext, Underlying_t<Operator>, Nodes...>{std::forward<Operator>(op)};
142
143
  }

144
} // end namespace AMDiS