opm-simulators/ebos/alucartesianindexmapper.hh
Andreas Lauser cd681c6445 ebos: make its core headers self sufficient
this is part of the release maintainance. in this context "core
headers" means the ones which do not include the well model headers,
and only those which are concerned with non-exotic functionality,
e.g., the PolyhedralGrid and ALUGrid vanguards are not changed.
2019-03-26 13:17:54 +01:00

254 lines
8.1 KiB
C++

// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \copydoc Ewoms::AluCartesianIndexMapper
*/
#ifndef EWOMS_ALU_CARTESIAN_INDEX_MAPPER_HH
#define EWOMS_ALU_CARTESIAN_INDEX_MAPPER_HH
#include <dune/grid/common/datahandleif.hh>
#include <dune/grid/utility/persistentcontainer.hh>
#include <array>
#include <memory>
#include <exception>
#include <vector>
#include <cassert>
namespace Ewoms {
/*!
* \brief Interface class to access the logical Cartesian grid as used in industry
* standard simulator decks.
*/
template <class Grid>
class AluCartesianIndexMapper
{
public:
// data handle for communicating global ids during load balance and communication
template <class GridView>
class GlobalIndexDataHandle : public Dune::CommDataHandleIF<GlobalIndexDataHandle<GridView>, int>
{
// global id
class GlobalCellIndex
{
public:
GlobalCellIndex()
: idx_(-1)
{}
GlobalCellIndex& operator=(const int index)
{
idx_ = index;
return *this;
}
int index() const
{ return idx_; }
private:
int idx_;
};
typedef typename Dune::PersistentContainer<Grid, GlobalCellIndex> GlobalIndexContainer;
public:
// constructor copying cartesian index to persistent container
GlobalIndexDataHandle(const GridView& gridView,
std::vector<int>& cartesianIndex)
: gridView_(gridView)
, globalIndex_(gridView.grid(), 0)
, cartesianIndex_(cartesianIndex)
{
globalIndex_.resize();
initialize();
}
// constructor copying cartesian index to persistent container
GlobalIndexDataHandle(const GlobalIndexDataHandle& other) = delete ;
// destrcutor writing load balanced cartesian index back to vector
~GlobalIndexDataHandle()
{ finalize(); }
bool contains(int dim, int codim) const
{ return codim == 0; }
bool fixedsize(int dim, int codim) const
{ return true; }
//! \brief loop over all internal data handlers and call gather for
//! given entity
template<class MessageBufferImp, class EntityType>
void gather(MessageBufferImp& buff, const EntityType& element) const
{
int globalIdx = globalIndex_[element].index();
buff.write(globalIdx);
}
//! \brief loop over all internal data handlers and call scatter for
//! given entity
template<class MessageBufferImp, class EntityType>
void scatter(MessageBufferImp& buff, const EntityType& element, size_t n)
{
int globalIdx = -1;
buff.read(globalIdx);
if (globalIdx >= 0)
{
globalIndex_.resize();
globalIndex_[element] = globalIdx;
}
}
//! \brief loop over all internal data handlers and return sum of data
//! size of given entity
template<class EntityType>
size_t size(const EntityType& en) const
{ return 1; }
protected:
// initialize persistent container from given vector
void initialize()
{
auto idx = cartesianIndex_.begin();
auto it = gridView_.template begin<0>();
const auto& endIt = gridView_.template end<0>();
for (; it != endIt; ++it, ++idx)
globalIndex_[*it] = *idx;
}
// update vector from given persistent container
void finalize()
{
std::vector<int> newIndex ;
newIndex.reserve(gridView_.indexSet().size(0));
auto it = gridView_.template begin<0>();
const auto& endIt = gridView_.template end<0>();
for (; it != endIt; ++it)
newIndex.push_back(globalIndex_[*it].index()) ;
cartesianIndex_.swap(newIndex);
}
GridView gridView_;
GlobalIndexContainer globalIndex_;
std::vector<int>& cartesianIndex_;
};
public:
/** \brief dimension of the grid */
static const int dimension = Grid::dimension ;
/** \brief constructor taking grid */
AluCartesianIndexMapper(const Grid& grid,
const std::array<int, dimension>& cartDims,
const std::vector<int>& cartesianIndex)
: grid_(grid)
, cartesianDimensions_(cartDims)
, cartesianIndex_(cartesianIndex)
, cartesianSize_(computeCartesianSize())
{}
/** \brief return Cartesian dimensions, i.e. number of cells in each direction */
const std::array<int, dimension>& cartesianDimensions() const
{ return cartesianDimensions_; }
/** \brief return total number of cells in the logical Cartesian grid */
int cartesianSize() const
{ return cartesianSize_; }
/** \brief return number of cells in the active grid */
int compressedSize() const
{ return cartesianIndex_.size(); }
/** \brief return index of the cells in the logical Cartesian grid */
int cartesianIndex(const int compressedElementIndex) const
{
assert(compressedElementIndex < compressedSize());
return cartesianIndex_[compressedElementIndex];
}
/** \brief return index of the cells in the logical Cartesian grid */
int cartesianIndex(const std::array<int, dimension>& coords) const
{
int cartIndex = coords[0];
int factor = cartesianDimensions()[0];
for (int i=1; i < dimension; ++i) {
cartIndex += coords[i] * factor;
factor *= cartesianDimensions()[i];
}
return cartIndex;
}
/** \brief return Cartesian coordinate, i.e. IJK, for a given cell */
void cartesianCoordinate(const int compressedElementIndex, std::array<int, dimension>& coords) const
{
int gc = cartesianIndex(compressedElementIndex);
if (dimension == 3) {
coords[0] = gc % cartesianDimensions()[0];
gc /= cartesianDimensions()[0];
coords[1] = gc % cartesianDimensions()[1];
coords[2] = gc / cartesianDimensions()[1];
}
else if (dimension == 2) {
coords[0] = gc % cartesianDimensions()[0];
coords[1] = gc / cartesianDimensions()[0];
}
else if (dimension == 1)
coords[0] = gc ;
else
throw std::invalid_argument("cartesianCoordinate not implemented for dimension " + std::to_string(dimension));
}
template <class GridView>
std::unique_ptr<GlobalIndexDataHandle<GridView> > dataHandle(const GridView& gridView)
{
typedef GlobalIndexDataHandle<GridView> DataHandle ;
assert(&grid_ == &gridView.grid());
return std::unique_ptr<DataHandle>(new DataHandle(gridView, cartesianIndex_));
}
protected:
int computeCartesianSize() const
{
int size = cartesianDimensions()[0];
for (int d=1; d<dimension; ++d)
size *= cartesianDimensions()[d];
return size ;
}
const Grid& grid_;
const std::array<int, dimension> cartesianDimensions_;
std::vector<int> cartesianIndex_;
const int cartesianSize_ ;
};
} // end namespace Ewoms
#endif