opm-simulators
AluGridCartesianIndexMapper.hpp
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
23 
24 #ifndef OPM_ALUGRID_CARTESIAN_INDEX_MAPPER_HPP
25 #define OPM_ALUGRID_CARTESIAN_INDEX_MAPPER_HPP
26 
27 #include <dune/alugrid/grid.hh>
28 #include <dune/alugrid/3d/gridview.hh>
29 #include <opm/grid/common/CartesianIndexMapper.hpp>
30 #include <dune/grid/common/datahandleif.hh>
31 #include <dune/grid/utility/persistentcontainer.hh>
32 
33 #include <array>
34 #include <cassert>
35 #include <cstddef>
36 #include <memory>
37 #include <stdexcept>
38 #include <vector>
39 
40 namespace Dune {
41 
46 //#if HAVE_MPI
47  template <>
48  class CartesianIndexMapper<Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming>>
49 {
50 public:
51 
52 #if HAVE_MPI
53  using Grid = Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridMPIComm>;
54 #else
55  using Grid = Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridNoComm>;
56 #endif //HAVE_MPI
57 
58  // data handle for communicating global ids during load balance and communication
59  template <class GridView>
60  class GlobalIndexDataHandle : public Dune::CommDataHandleIF<GlobalIndexDataHandle<GridView>, int>
61  {
62  // global id
63  class GlobalCellIndex
64  {
65  public:
66  GlobalCellIndex()
67  : idx_(-1)
68  {}
69 
70  GlobalCellIndex& operator=(const int index)
71  {
72  idx_ = index;
73  return *this;
74  }
75 
76  int index() const
77  { return idx_; }
78 
79  private:
80  int idx_;
81  };
82 
83  using GlobalIndexContainer = typename Dune::PersistentContainer<Grid, GlobalCellIndex>;
84 
85  public:
86  // constructor copying cartesian index to persistent container
87  GlobalIndexDataHandle(const GridView& gridView,
88  std::vector<int>& cartesianIndex)
89  : gridView_(gridView)
90  , globalIndex_(gridView.grid(), 0)
91  , cartesianIndex_(cartesianIndex)
92  {
93  globalIndex_.resize();
94  initialize();
95  }
96 
97  // constructor copying cartesian index to persistent container
98  GlobalIndexDataHandle(const GlobalIndexDataHandle& other) = delete ;
99 
100  // destrcutor writing load balanced cartesian index back to vector
101  ~GlobalIndexDataHandle()
102  { finalize(); }
103 
104  bool contains(int /* dim */, int codim) const
105  { return codim == 0; }
106 
107  bool fixedsize(int /* dim */, int /* codim */) const
108  { return true; }
109 
112  template<class MessageBufferImp, class EntityType>
113  void gather(MessageBufferImp& buff, const EntityType& element) const
114  {
115  int globalIdx = globalIndex_[element].index();
116  buff.write(globalIdx);
117  }
118 
121  template<class MessageBufferImp, class EntityType>
122  void scatter(MessageBufferImp& buff, const EntityType& element, std::size_t /* n */)
123  {
124  int globalIdx = -1;
125  buff.read(globalIdx);
126  if (globalIdx >= 0)
127  {
128  globalIndex_.resize();
129  globalIndex_[element] = globalIdx;
130  }
131  }
132 
135  template<class EntityType>
136  std::size_t size(const EntityType& /* en */) const
137  { return 1; }
138 
139  protected:
140  // initialize persistent container from given vector
141  void initialize()
142  {
143  auto idx = cartesianIndex_.begin();
144  auto it = gridView_.template begin<0>();
145  const auto& endIt = gridView_.template end<0>();
146 
147  for (; it != endIt; ++it, ++idx)
148  globalIndex_[*it] = *idx;
149  }
150 
151  // update vector from given persistent container
152  void finalize()
153  {
154  std::vector<int> newIndex ;
155  newIndex.reserve(gridView_.indexSet().size(0));
156 
157  auto it = gridView_.template begin<0>();
158  const auto& endIt = gridView_.template end<0>();
159  for (; it != endIt; ++it)
160  newIndex.push_back(globalIndex_[*it].index()) ;
161 
162  cartesianIndex_.swap(newIndex);
163  }
164 
165  GridView gridView_;
166  GlobalIndexContainer globalIndex_;
167  std::vector<int>& cartesianIndex_;
168  };
169 
170 public:
172  static constexpr int dimension = Grid::dimension ;
173 
175  CartesianIndexMapper(const Grid& grid,
176  const std::array<int, dimension>& cartDims,
177  const std::vector<int>& cartesianIndex)
178  : grid_(grid)
179  , cartesianDimensions_(cartDims)
180  , cartesianIndex_(cartesianIndex)
181  , cartesianSize_(computeCartesianSize())
182  {}
183 
185  const std::array<int, dimension>& cartesianDimensions() const
186  { return cartesianDimensions_; }
187 
189  int cartesianSize() const
190  { return cartesianSize_; }
191 
193  int compressedSize() const
194  { return cartesianIndex_.size(); }
195 
197  int cartesianIndex(const int compressedElementIndex) const
198  {
199  assert(compressedElementIndex < compressedSize());
200  return cartesianIndex_[compressedElementIndex];
201  }
202 
204  int cartesianIndex(const std::array<int, dimension>& coords) const
205  {
206  int cartIndex = coords[0];
207  int factor = cartesianDimensions()[0];
208  for (int i=1; i < dimension; ++i) {
209  cartIndex += coords[i] * factor;
210  factor *= cartesianDimensions()[i];
211  }
212 
213  return cartIndex;
214  }
215 
217  void cartesianCoordinate(const int compressedElementIndex, std::array<int, dimension>& coords) const
218  {
219  int gc = cartesianIndex(compressedElementIndex);
220  if constexpr (dimension == 3) {
221  coords[0] = gc % cartesianDimensions()[0];
222  gc /= cartesianDimensions()[0];
223  coords[1] = gc % cartesianDimensions()[1];
224  coords[2] = gc / cartesianDimensions()[1];
225  }
226  else if constexpr (dimension == 2) {
227  coords[0] = gc % cartesianDimensions()[0];
228  coords[1] = gc / cartesianDimensions()[0];
229  }
230  else if constexpr (dimension == 1)
231  coords[0] = gc ;
232  else
233  throw std::invalid_argument("cartesianCoordinate not implemented for dimension " + std::to_string(dimension));
234  }
235 
236  template <class GridView>
237  std::unique_ptr<GlobalIndexDataHandle<GridView> > dataHandle(const GridView& gridView)
238  {
239  using DataHandle = GlobalIndexDataHandle<GridView>;
240  assert(&grid_ == &gridView.grid());
241  return std::make_unique<DataHandle>(gridView, cartesianIndex_);
242  }
243 
244 protected:
245  int computeCartesianSize() const
246  {
247  int size = cartesianDimensions()[0];
248  for (int d=1; d<dimension; ++d)
249  size *= cartesianDimensions()[d];
250  return size ;
251  }
252 
253  const Grid& grid_;
254  const std::array<int, dimension> cartesianDimensions_;
255  std::vector<int> cartesianIndex_;
256  const int cartesianSize_ ;
257 };
258 
259 } // end namespace Dune
260 
261 #endif // OPM_ALUGRID_CARTESIAN_INDEX_MAPPER_HPP
int cartesianIndex(const int compressedElementIndex) const
return index of the cells in the logical Cartesian grid
Definition: AluGridCartesianIndexMapper.hpp:197
void scatter(MessageBufferImp &buff, const EntityType &element, std::size_t)
loop over all internal data handlers and call scatter for given entity
Definition: AluGridCartesianIndexMapper.hpp:122
int cartesianIndex(const std::array< int, dimension > &coords) const
return index of the cells in the logical Cartesian grid
Definition: AluGridCartesianIndexMapper.hpp:204
int compressedSize() const
return number of cells in the active grid
Definition: AluGridCartesianIndexMapper.hpp:193
Definition: fvbaseprimaryvariables.hh:161
void cartesianCoordinate(const int compressedElementIndex, std::array< int, dimension > &coords) const
return Cartesian coordinate, i.e.
Definition: AluGridCartesianIndexMapper.hpp:217
std::size_t size(const EntityType &) const
loop over all internal data handlers and return sum of data size of given entity
Definition: AluGridCartesianIndexMapper.hpp:136
const std::array< int, dimension > & cartesianDimensions() const
return Cartesian dimensions, i.e.
Definition: AluGridCartesianIndexMapper.hpp:185
void gather(MessageBufferImp &buff, const EntityType &element) const
loop over all internal data handlers and call gather for given entity
Definition: AluGridCartesianIndexMapper.hpp:113
int cartesianSize() const
return total number of cells in the logical Cartesian grid
Definition: AluGridCartesianIndexMapper.hpp:189
Definition: CollectDataOnIORank.hpp:49
CartesianIndexMapper(const Grid &grid, const std::array< int, dimension > &cartDims, const std::vector< int > &cartesianIndex)
constructor taking grid
Definition: AluGridCartesianIndexMapper.hpp:175