Am Montag, 13. Mai 2022, finden Wartungsarbeiten am Gitlab-Server (Update auf neue Version statt). Der Dienst wird daher am Montag für einige Zeit nicht verfügbar sein.
On Monday, May 13th 2022, the Gitlab server will be updated. The service will therefore not be accessible for some time on Monday.

DataTransfer.hpp 6.16 KB
Newer Older
1
2
#pragma once

3
#include <map>
4
5
#include <memory>

6
7
#include <dune/grid/common/mcmgmapper.hh>

8
#include <amdis/Output.hpp>
9
#include <amdis/typetree/TreeContainer.hpp>
10
11
12

namespace AMDiS
{
13
14
15
16
17
  /**
   * \addtogroup Adaption
   * @{
   **/

18
  enum class DataTransferOperation {
19
20
    NO_OPERATION = 0,
    INTERPOLATE  = 1
21
  };
22
23


24
  /// \brief Interface for Containers allowing data transfer between grid changes.
25
26
27
28
29
30
31
  template <class Container>
  class DataTransferInterface
  {
  public:
    /// Virtual destructor
    virtual ~DataTransferInterface() = default;

32
33
34
    /// Clone method
    virtual std::unique_ptr<DataTransferInterface> clone() const = 0;

35
36
37
38
    /// Collect data that is needed before grid adaption
    virtual void preAdapt(Container const& container, bool mightCoarsen) = 0;

    /// Interpolate data to new grid after grid adaption
39
40
41
42
    virtual void adapt(Container& container) = 0;

    /// Perform cleanup after grid adaption
    virtual void postAdapt(Container& container) = 0;
43
44
45
  };


46
47
48
49
  /**
   * \brief Implementation of \ref DataTransferInterface that does not interpolate, but
   * just resizes the containers to the dimension of the basis
   **/
50
51
52
53
  template <class Container>
  class NoDataTransfer
      : public DataTransferInterface<Container>
  {
54
55
    using Interface = DataTransferInterface<Container>;

56
  public:
57
58
59
60
61
62
    std::unique_ptr<Interface> clone() const override
    {
      return std::make_unique<NoDataTransfer>();
    }

    void preAdapt(Container const&, bool) override {}
63

64
    void adapt(Container& container) override
65
    {
66
      container.resize();
67
    }
68
69

    void postAdapt(Container&) override {}
70
71
72
  };


73
74
75
76
77
78
79
80
  template <class Node, class Container, class Basis>
  class NodeDataTransfer;


  /** Data Transfer implementation for a single grid using interpolation
   *  Handles computations related to the geometric information of the grid and passes that to the
   *    underlying NodeDataTransfer classes
   */
81
  template <class Container, class Basis>
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  class DataTransfer
      : public DataTransferInterface<Container>
  {
    using LocalView = typename Basis::LocalView;
    using Tree = typename LocalView::Tree;
    using GridView = typename Basis::GridView;
    using Grid = typename GridView::Grid;

    using Element = typename GridView::template Codim<0>::Entity;
    using Geometry = typename Element::Geometry;
    using LocalCoordinate = typename Geometry::LocalCoordinate;
    using IdType = typename Grid::LocalIdSet::IdType;

    template <class Node>
    using NodeElementData = typename NodeDataTransfer<Node, Container, Basis>::NodeElementData;
97
    using ElementData = TreeContainer<NodeElementData,Tree,true>;
98

99
100
    using Interface = DataTransferInterface<Container>;

101
  public:
102
103
104
105
106
107
    DataTransfer(std::shared_ptr<Basis const> basis);

    std::unique_ptr<Interface> clone() const override
    {
      return std::make_unique<DataTransfer<Container, Basis>>(basis_);
    }
108
109
110
111
112
113
114
115
116

    /** Saves data contained in coeff in the PersistentContainer
     *  To be called after grid.preAdapt() and before grid.adapt()
     */
    void preAdapt(Container const& coeff, bool mightCoarsen) override;

    /** Unpacks data from the PersistentContainer
     *  To be called after grid.adapt() and before grid.postAdapt()
     */
117
    // [[expects: basis is updated in gridView]]
118
    // [[expects: comm is updated in basis]]
119
120
121
122
123
124
    void adapt(Container& coeff) override;

    /** Performs cleanup
     *  To be called after grid.postAdapt()
     */
    void postAdapt(Container& coeff) override;
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

  private:
    /// The global basis
    std::shared_ptr<Basis const> basis_;

    /// Container with data that persists during grid adaptation
    using PersistentContainer = std::map<IdType, ElementData>;
    PersistentContainer persistentContainer_;

    /// Map leaf entities to unique index
    using Mapper = Dune::LeafMultipleCodimMultipleGeomTypeMapper<Grid>;
    Mapper mapper_;

    /// Data transfer on a single basis node
    template <class Node>
    using NDT = NodeDataTransfer<Node, Container, Basis>;
141
    using NodeDataTransferContainer = TreeContainer<NDT,Tree,true>;
142
143
144
    NodeDataTransferContainer nodeDataTransfer_;
  };

145
146
147
148
149
150
151
152
153

  /// Factory to create DataTransfer objects based on the \ref DataTransferOperation
  template <class Container>
  class DataTransferFactory
  {
    using Interface = DataTransferInterface<Container>;

  public:
    template <class Basis>
154
    static std::unique_ptr<Interface> create(DataTransferOperation op, std::shared_ptr<Basis> basis)
155
156
157
    {
      switch (op)
      {
158
        case DataTransferOperation::NO_OPERATION:
159
          return std::make_unique<NoDataTransfer<Container>>();
160
        case DataTransferOperation::INTERPOLATE:
161
          return std::make_unique<DataTransfer<Container, Basis>>(std::move(basis));
162
163
164
165
166
167
168
        default:
          error_exit("Invalid data transfer\n");
          return nullptr; // avoid warnings
      }
    }
  };

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

  /** Wrapper class for (No)DataTransfer objects.
   *  This wrapper class may be used instead of a pointer type to DataTransferInterface. It wraps
   *  and redirects to the implementation, while providing deep copy and move functionality.
   *  A virtual clone() method in the interface and implementation classes is required to perform
   *  the deep copy of the implementation.
   */
  template <class Container>
  class DataTransferWrapper
  {
    using Interface = DataTransferInterface<Container>;
    using Factory = DataTransferFactory<Container>;
    using Self = DataTransferWrapper<Container>;

  public:
    template <class Basis>
    DataTransferWrapper(DataTransferOperation op, std::shared_ptr<Basis> basis)
      : impl_(std::move(Factory::create(op, basis)))
    {}

    DataTransferWrapper(Self const& that)
      : impl_(std::move(that.impl_->clone()))
    {}

    DataTransferWrapper(Self&& that) = default;

    Self& operator=(Self const& that)
    {
      impl_ = std::move(that.impl_->clone());
      return *this;
    }

    Self& operator=(Self&& that) = default;

    void preAdapt(Container const& c, bool b) { impl_->preAdapt(c, b); }

    void adapt(Container& c) { impl_->adapt(c); }

    void postAdapt(Container& c) { impl_->postAdapt(c); }

  private:
    std::unique_ptr<Interface> impl_;
  };

213
214
  /// @}

215
} // end namespace AMDiS
216
217

#include "DataTransfer.inc.hpp"