opm-grid
Indexsets.hpp
1 //===========================================================================
2 //
3 // File: Indexsets.hpp
4 //
5 // Created: Fri May 29 23:30:01 2009
6 //
7 // Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
8 // Bård Skaflestad <bard.skaflestad@sintef.no>
9 //
10 // $Date$
11 //
12 // $Revision$
13 //
14 //===========================================================================
15 
16 /*
17 Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
18 Copyright 2009, 2010, 2022 Equinor ASA.
19 
20 This file is part of The Open Porous Media project (OPM).
21 
22 OPM is free software: you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation, either version 3 of the License, or
25 (at your option) any later version.
26 
27 OPM is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31 
32 You should have received a copy of the GNU General Public License
33 along with OPM. If not, see <http://www.gnu.org/licenses/>.
34 */
35 
36 #ifndef OPM_INDEXSETS_HEADER
37 #define OPM_INDEXSETS_HEADER
38 
39 #include <dune/geometry/type.hh>
40 #include <opm/grid/utility/ErrorMacros.hpp>
41 #include "Entity.hpp"
42 #include "GlobalIdMapping.hpp"
43 #include "Intersection.hpp"
44 
45 #include <cstdint>
46 #include <unordered_map>
47 #include <utility>
48 
49 namespace Dune
50 {
51  namespace cpgrid
52  {
56  class IndexSet
57  {
58  public:
61  typedef std::int64_t IndexType;
62 
63  static constexpr int dimension = 3;
64 
66  template <int cd>
67  using Codim = typename Impl::CodimTraits<cd>;
68 
71  typedef std::vector<GeometryType> Types;
72 
76  IndexSet() : IndexSet(0,0){}
77 
78  IndexSet(std::size_t numCells, std::size_t numPoints)
79  {
80  geom_types_[0].emplace_back(Dune::GeometryTypes::cube(3));
81  geom_types_[3].emplace_back(Dune::GeometryTypes::cube(0));
82  size_codim_map_[0] = numCells;
83  size_codim_map_[3] = numPoints;
84  }
85 
88  {}
89 
94  const Types& geomTypes(int codim) const
95  {
96  return geom_types_[codim];
97  }
98 
103  const Types& types(int codim) const
104  {
105  return geom_types_[codim];
106  }
107 
112  int size(GeometryType type) const
113  {
114  if (type.isCube()) {
115  return size(3 - type.dim()); // return grid_.size(type);
116  } else {
117  return 0;
118  }
119  }
120 
121 
126  int size(int codim) const
127  {
128  return size_codim_map_[codim]; //grid_.size(codim)
129  }
130 
131 
137  template<int cd>
139  {
140  return e.index();
141  }
142 
148  template<class EntityType>
149  IndexType index(const EntityType& e) const
150  {
151  return e.index();
152  }
153 
159  template <int cc>
160  IndexType subIndex(const cpgrid::Entity<0>& e, int i) const
161  {
162  return index(e.template subEntity<cc>(i));
163  }
164 
170  IndexType subIndex(const cpgrid::Entity<0>& e, int i, unsigned int cc) const;
171 
172 
173  template<int codim>
174  IndexType subIndex(const cpgrid::Entity<codim>& /* e */, int /* i */, unsigned int /* cc */) const
175  {
176  DUNE_THROW(NotImplemented, "subIndex not implemented for codim"
177  << codim << "entities.");
178  }
184  template <class EntityType>
185  bool contains(const EntityType& e) const
186  {
187  // return index(e) >= 0 && index(e) < grid_.size(EntityType::codimension); //EntityType::codimension == 0;
188  return index(e) >= 0 && index(e) < this->size(EntityType::codimension);
189  }
190 
191  private:
192  // const CpGridData& grid_;
193  Types geom_types_[4];
194  std::array<int,4> size_codim_map_{0,0,0,0};
195  };
196 
197 
198  class IdSet
199  {
200  friend class ReversePointGlobalIdSet;
201  friend class Dune::cpgrid::CpGridData;
202  //friend class Dune::cpgrid::LevelGlobalIdSet; Not needed due to repeated code in LevelGlobalIdSet (computeId_cell and computeId_point)
203  public:
204  typedef std::int64_t IdType;
205 
206  static constexpr int dimension = 3;
207 
209  template <int cd>
210  using Codim = typename Impl::CodimTraits<cd>;
211 
212  explicit IdSet(const CpGridData& grid)
213  : grid_(grid)
214  {
215  }
216 
217  template <int cd>
218  IdType id(const typename Codim<cd>::Entity& e) const
219  {
220  if constexpr (cd == 0)
221  return computeId_cell(e);
222  else if constexpr (cd == 3)
223  return computeId_point(e);
224  else
225  static_assert(AlwaysFalse<index_constant<cd>>::value,
226  "IdSet::id not implemented for codims other than 0, and 3.");
227  }
228 
229  template<class EntityType>
230  IdType id(const EntityType& e) const
231  {
232  return id<EntityType::codimension>(e);
233  }
234 
235  template<int codim>
236  IdType idLevelZero(const cpgrid::EntityRep<codim>& e) const
237  {
238  return computeId(e);
239  }
240 
241  template<int codim>
242  IdType idLevelZero(const Entity<codim>& e) const = delete;
243 
245  IdType id( const cpgrid::Intersection& intersection ) const
246  {
247  return intersection.id();
248  }
249 
250  template<int cc>
251  IdType subId(const cpgrid::Entity<0>& e, int i) const
252  {
253  return id(e.template subEntity<cc>(i));
254  }
255 
256  IdType subId(const cpgrid::Entity<0>& e, int i, int cc) const;
257 
258  private:
259 
260  template<class EntityType>
261  IdType computeId(const EntityType& e) const
262  {
263  IdType myId = 0;
264  for( int c=0; c<EntityType::codimension; ++c )
265  myId += grid_.indexSet().size( c );
266  return myId + e.index();
267  }
268 
269  const CpGridData& grid_;
270 
271  IdType computeId_cell(const cpgrid::Entity<0>& e) const
272  {
273  IdType myId = 0;
274  // Case: Leaf grid view is a mixed of coarse and fined cells.
275  if (grid_.levelData().size() > 1) {
276  const auto& gridIdx = grid_.getGridIdx();
277  // Level zero grid
278  if ( gridIdx == 0 ) {
279  return myId + e.index();
280  }
281  // Level 1, 2, ...., maxLevel refined grids
282  if ( (gridIdx>0) && (gridIdx < static_cast<int>(grid_.levelData().size() -1)) ) {
283  if ((e.level() != gridIdx)) { // cells equiv to pre-existing cells
284  return grid_.levelData()[e.level()]->localIdSet().id(e.getLevelElem());
285  }
286  else {
287  // Count (and add to myId) all the entities of all the codimensions (for CpGrid, only 0 and 3)
288  // from all the "previous" level grids.
289  for (int lowerLevel = 0; lowerLevel< gridIdx; ++lowerLevel) {
290  for( int c=0; c<4; ++c ) {
291  myId += grid_.levelData()[lowerLevel]->indexSet().size( c );
292  }
293  }
294  return myId + e.index();
295  }
296  }
297  else { // Leaf grid view (grid view with mixed coarse and refined cells).
298  assert( grid_.getGridIdx() == (static_cast<int>(grid_.levelData().size()) -1) );
299  // In this case, we search for the ids defined in previous levels
300  // (since each entities must keep its id along the entire hiearchy)
301  const std::array<int,2> level_levelIdx = grid_.leaf_to_level_cells_[e.index()];
302  const auto& levelEntity = cpgrid::Entity<0>(*(grid_.levelData()[level_levelIdx[0]]), level_levelIdx[1], true);
303  return grid_.levelData()[level_levelIdx[0]]->local_id_set_ ->id(levelEntity);
304  }
305  } // end-if-data_.size()>1
306  else { // Case: No LGRs / No refined level grids. Only level 0 grid (GLOBAL grid).
307  return myId + e.index();
308  }
309  }
310 
311  IdType computeId_point(const cpgrid::Entity<3>& e) const
312  {
313  IdType myId = 0;
314  // Case: Leaf grid view is a mixed of coarse and fined cells.
315  if (grid_.levelData().size() > 1) {
316  const auto& gridIdx = grid_.getGridIdx();
317  // Level zero grid
318  if ( gridIdx == 0 ) {
319  // Count all the entities of (all the levels) level 0 of all codimensions lower than 3 (for CpGrid, only codim = 0 cells).
320  for( int c=0; c<3; ++c ) {
321  myId += grid_.indexSet().size( c );
322  }
323  return myId + e.index();
324  }
325  // Level 1, 2, ...., maxLevel refined grids.
326  if ( (gridIdx>0) && (gridIdx < static_cast<int>(grid_.levelData().size() -1)) ) {
327  const auto& level_levelIdx = grid_.corner_history_[e.index()];
328  if(level_levelIdx[0] != -1) { // corner equiv to a pre-exisiting level corner
329  const auto& levelEntity = cpgrid::Entity<3>(*(grid_.levelData()[level_levelIdx[0]]), level_levelIdx[1], true);
330  return grid_.levelData()[level_levelIdx[0]]->localIdSet().id(levelEntity);
331  }
332  else {
333  // Count (and add to myId) all the entities of all the codimensions (for CpGrid, only 0 and 3)
334  // from all the "previous" level grids.
335  for (int lowerLevel = 0; lowerLevel< gridIdx; ++lowerLevel) {
336  for( int c=0; c<4; ++c ) {
337  myId += grid_.levelData()[lowerLevel]->indexSet().size( c );
338  }
339  }
340  // Count (and add to myId) all the entities of the refined level grid of codim < 3.
341  for( int c=0; c<3; ++c ) {
342  myId += grid_.indexSet().size( c );
343  }
344  return myId + e.index();
345  }
346  }
347  else { // Leaf grid view (grid view with mixed coarse and refined cells).
348  assert( grid_.getGridIdx() == (static_cast<int>(grid_.levelData().size()) -1) );
349  // In this case, we search for the ids defined in previous levels
350  // (since each entities must keep its id along the entire hiearchy)
351  const std::array<int,2> level_levelIdx = grid_.corner_history_[e.index()];
352  const auto& levelEntity = cpgrid::Entity<3>(*(grid_.levelData()[level_levelIdx[0]]), level_levelIdx[1], true);
353  return grid_.levelData()[level_levelIdx[0]]->local_id_set_ ->id(levelEntity);
354  }
355  } // end-if-data_.size()>1
356  else { // Case: No LGRs / No refined level grids. Only level 0 grid (GLOBAL grid).
357  for( int c=0; c<3; ++c ) {
358  myId += grid_.indexSet().size( c );
359  }
360  return myId + e.index();
361  }
362  }
363  };
364 
365 
367  {
368  friend class CpGridData;
369  friend class ReversePointGlobalIdSet;
370  public:
371  typedef std::int64_t IdType;
372 
373  static constexpr int dimension = 3;
374 
376  template <int cd>
377  using Codim = typename Impl::CodimTraits<cd>;
378 
379  void swap(std::vector<int>& cellMapping,
380  std::vector<int>& faceMapping,
381  std::vector<int>& pointMapping)
382  {
383  idSet_=nullptr;
384  GlobalIdMapping::swap(cellMapping,
385  faceMapping,
386  pointMapping);
387  }
388  LevelGlobalIdSet(std::shared_ptr<const IdSet> ids, const CpGridData* view)
389  : idSet_(std::move(ids)), view_(view)
390  {}
391  LevelGlobalIdSet()
392  : idSet_(), view_()
393  {}
394  template<int codim>
395  IdType id(const typename Codim<codim>::Entity& e) const
396  {
397  assert(view_ == e.pgrid_);
398  // We need to ask the local id set with the full entity
399  // as it needs to be able to determine the level and other
400  // things that are not available in EntityRep.
401  if(idSet_)
402  return idSet_->id(e);
403  else
404  // This a parallel grid and we need to use the mapping
405  // build from the ids of the sequential grid
406  return this->template getMapping<codim>()[e.index()];
407  }
408 
409  template<int codim>
410  IdType idLevelZero(const EntityRep<codim>& e) const
411  {
412  if(idSet_)
413  return idSet_->idLevelZero(e);
414  else
415  return this->template getMapping<codim>()[e.index()];
416  }
417 
418  template<int codim>
419  IdType idLevelZero(const Entity<codim>& e) const = delete;
420 
421  template<class EntityType>
422  IdType id(const EntityType& e) const
423  {
424  return id<EntityType::codimension>(e);
425  }
426 
427  template<int cc>
428  IdType subId(const cpgrid::Entity<0>& e, int i) const
429  {
430  assert(view_ == e.pgrid_);
431  return id(e.template subEntity<cc>(i));
432  }
433 
434  IdType subId(const cpgrid::Entity<0>& e, int i, int cc) const;
435 
436  template<int codim>
437  IdType getMaxCodimGlobalId() const
438  {
439  if(idSet_)
440  {
441  IdType max_codim_id = 0;
442  if (codim == 0) {
443  for (int elemIdx = 0; elemIdx < view_-> size(0); ++elemIdx) {
444  const auto& element= cpgrid::Entity<0>(*view_, elemIdx, true);
445  max_codim_id = std::max(max_codim_id, idSet_->id(element));
446  }
447  }
448  if (codim == 3) {
449  for (int pointIdx = 0; pointIdx < view_->size(3); ++pointIdx) {
450  const auto& point = cpgrid::Entity<3>(*view_, pointIdx, true);
451  max_codim_id = std::max(max_codim_id, idSet_->id(point));
452  }
453  }
454  return max_codim_id;
455  }
456  else {
457  // This a parallel grid and we need to use the mapping
458  // build from the ids of the sequential grid
459  const auto max_elem_codim =
460  std::ranges::max_element(this->template getMapping<codim>());
461  return *max_elem_codim;
462  }
463  }
464 
465  IdType getMaxGlobalId() const
466  {
467  // Ignore faces
468  return std::max(getMaxCodimGlobalId<0>(), getMaxCodimGlobalId<3>());
469  }
470 
471  private:
472  std::shared_ptr<const IdSet> idSet_;
473  const CpGridData* view_;
474  };
475 
483  {
484  public:
486  using IdType = typename LevelGlobalIdSet::IdType;
487 
488  static constexpr int dimension = 3;
489 
491  template <int cd>
492  using Codim = typename Impl::CodimTraits<cd>;
493 
494  explicit GlobalIdSet(const CpGridData& view);
495 
496  template<int codim>
497  IdType id(const typename Codim<codim>::Entity& e) const
498  {
499  return levelIdSet(e.pgrid_).id(e);
500  }
501 
502  template<class EntityType>
503  IdType id(const EntityType& e) const
504  {
505  return id<EntityType::codimension>(e);
506  }
507 
508  template <int cc>
509  IdType subId(const typename Codim<0>::Entity& e, int i) const
510  {
511  return levelIdSet(e.pgrid_).template subId<cc>(e, i);
512  }
513 
514  IdType subId(const typename Codim<0>::Entity& e, int i, int cc) const;
515 
516  void insertIdSet(const CpGridData& view);
517  private:
519  const LevelGlobalIdSet& levelIdSet(const CpGridData* const data) const
520  {
521  auto candidate = idSets_.find(data);
522  assert(candidate != idSets_.end());
523  return *candidate->second;
524  }
526  std::map<const CpGridData* const, std::shared_ptr<const LevelGlobalIdSet>> idSets_;
527  };
528 
530  {
531  public:
532  explicit ReversePointGlobalIdSet(const LevelGlobalIdSet& idSet)
533  {
534  if(idSet.idSet_)
535  {
536  grid_ = &(idSet.idSet_->grid_);
537  }
538  else
539  {
540  mapping_.reset(new std::unordered_map<int,int>);
541  int localId = 0;
542  for (const auto& globalId: idSet.template getMapping<3>())
543  (*mapping_)[globalId] = localId++;
544  }
545  }
546  int operator[](int i) const
547  {
548  if (mapping_)
549  {
550  return(*mapping_)[i];
551  }
552  else if (grid_)
553  {
554  return i - grid_->size(0) - grid_->size(1) - grid_->size(2);
555  }
556 
557  OPM_THROW(std::runtime_error, "No grid or mapping. Should not be here!");
558  }
559  void release()
560  {
561  mapping_.reset(nullptr);
562  }
563  private:
564  std::unique_ptr<std::unordered_map<int,int> > mapping_;
565  const CpGridData* grid_ = nullptr;
566  };
567 
568  } // namespace cpgrid
569 } // namespace Dune
570 
571 #endif // OPM_INDEXSETS_HEADER
int index() const
The (positive) index of an entity.
Definition: EntityRep.hpp:125
typename Impl::CodimTraits< cd > Codim
Export supported entity types.
Definition: Indexsets.hpp:492
const IndexSet & indexSet() const
Get the index set.
Definition: CpGridData.hpp:570
int size(int codim) const
Definition: Indexsets.hpp:126
IndexSet()
Definition: Indexsets.hpp:76
The namespace Dune is the main namespace for all Dune code.
Definition: CartesianIndexMapper.hpp:9
Definition: Indexsets.hpp:366
Definition: Indexsets.hpp:198
Definition: Intersection.hpp:329
Definition: Indexsets.hpp:529
Definition: Intersection.hpp:62
Definition: Entity.hpp:66
typename LevelGlobalIdSet::IdType IdType
The type of the id.
Definition: Indexsets.hpp:486
std::vector< GeometryType > Types
Definition: Indexsets.hpp:71
Struct that hods all the data needed to represent a Cpgrid.
Definition: CpGridData.hpp:117
typename Impl::CodimTraits< cd > Codim
Export supported entity types.
Definition: Indexsets.hpp:210
void swap(std::vector< int > &cellMapping, std::vector< int > &faceMapping, std::vector< int > &pointMapping)
Swap data for initialization.
Definition: GlobalIdMapping.hpp:38
IndexType subIndex(const cpgrid::Entity< 0 > &e, int i) const
Definition: Indexsets.hpp:160
const Types & geomTypes(int codim) const
Definition: Indexsets.hpp:94
std::int64_t IndexType
Definition: Indexsets.hpp:61
typename Impl::CodimTraits< cd > Codim
Export supported entity types.
Definition: Indexsets.hpp:377
IdType id(const cpgrid::Intersection &intersection) const
return id of intersection (here face number)
Definition: Indexsets.hpp:245
int size(GeometryType type) const
Definition: Indexsets.hpp:112
Class managing the mappings of local indices to global ids.
Definition: GlobalIdMapping.hpp:30
IndexType index(const EntityType &e) const
Definition: Indexsets.hpp:149
const Types & types(int codim) const
Definition: Indexsets.hpp:103
typename Impl::CodimTraits< cd > Codim
Export supported entity types.
Definition: Indexsets.hpp:67
The global id set for Dune.
Definition: Indexsets.hpp:482
IndexType index(const cpgrid::Entity< cd > &e) const
Definition: Indexsets.hpp:138
Represents an entity of a given codim, with positive or negative orientation.
Definition: CpGridData.hpp:96
Definition: Indexsets.hpp:56
bool contains(const EntityType &e) const
Definition: Indexsets.hpp:185
~IndexSet()
Destructor.
Definition: Indexsets.hpp:87