Operator.hpp 3.28 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
#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)
{
127
  return Recursive::map([](auto const& op) { return localOperator(op); }, c);
128
129
130
131
}


} // end namespace AMDiS