Operator.hpp 3.29 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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
#pragma once

#include <type_traits>

#include <dune/common/concept.hh>
#include <dune/functions/common/typeerasure.hh>

#include <amdis/LocalOperator.hpp>
#include <amdis/common/ConceptsBase.hpp>
#include <amdis/typetree/TreeContainerTrafo.hpp>

namespace AMDiS {
namespace Impl {

template <class GV, class LC, class C>
struct OperatorTraits
{
  using GridView = GV;
  using LocalContext = LC;
  using ElementContainer = C;
};

template <class Traits, class... Nodes>
struct OperatorDefinition
{
  using GridView = typename Traits::GridView;

  // Definition of the interface an Operator must fulfill
  struct Interface
  {
    virtual ~Interface() = default;
    virtual void update(GridView const&) = 0;
    virtual LocalOperator<Traits,Nodes...> asLocalOperator() const = 0;
  };

  // Templatized implementation of the interface
  template <class Impl>
  struct Model : public Impl
  {
    using Impl::Impl;
    void update(GridView const& gv) final { this->get().update(gv); }
    LocalOperator<Traits,Nodes...> asLocalOperator() const final {
      return localOperator(this->get()); }
  };

  // The Concept definition of an Operator
  struct Concept
  {
    using LOpConcept = typename LocalOperatorDefinition<Traits,Nodes...>::Concept;

    template <class Op>
    auto require(Op&& op) -> decltype
    (
      op.update(std::declval<GridView>()),
      Dune::Concept::requireConcept<LOpConcept>(localOperator(op))
    );
  };

  using Base = Dune::Functions::TypeErasureBase<Interface,Model>;
};

} // end namespace Impl


/**
 * \addtogroup operators
 * @{
 **/

/// \brief The base class for an operator to be used in an \ref Assembler.
/**
 * Type-erasure base class for grid-operators.
 *
 * \tparam Traits    Parameters for the Operator collected in a class.
 *                   See \ref Impl::OperatorTraits.
 * \tparam Nodes...  Basis-node (pair) the operator is associated to.
 **/
template <class Traits, class... Nodes>
class Operator
    : public Impl::OperatorDefinition<Traits,Nodes...>::Base
{
  using Definition = Impl::OperatorDefinition<Traits,Nodes...>;
  using Super = typename Definition::Base;

public:
  // The gridview the operator is associated to
  using GridView = typename Traits::GridView;

public:
  /// Constructor. Pass any type supporting the \ref OperatorInterface
  template <class Impl, Dune::disableCopyMove<Operator,Impl> = 0>
  Operator(Impl&& impl)
    : Super{FWD(impl)}
  {
    static_assert(Concepts::models<typename Definition::Concept(Impl)>,
      "Implementation does not model the Operator concept.");
  }

  /// Default Constructor.
  Operator() = default;

  /// Update the operator data on a \ref GridView
  void update(GridView const& gv)
  {
    this->asInterface().update(gv);
  }

  /// Transform an operator into a local-operator
  friend LocalOperator<Traits,Nodes...> localOperator(Operator const& op)
  {
    return op.asInterface().asLocalOperator();
  }
};

template <class LocalContext, class Op, class GV>
auto makeOperator(Op op, GV const& gridView)
{
  op.update(gridView);
  return op;
}

/// Transform an operator into a local operator and also containers of operators
/// into containers of local operators
template <class Container>
auto localOperators(Container const& c)
{
  return Recursive::apply([](auto const& op) { return localOperator(op); }, c);
}


} // end namespace AMDiS