Page MenuHomec4science

grid_view.hh
No OneTemporary

File Metadata

Created
Wed, May 22, 05:36

grid_view.hh

/**
*
* @author Lucas Frérot <lucas.frerot@epfl.ch>
*
* @section LICENSE
*
* Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de
* Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des
* Solides)
*
* Tamaas is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Tamaas 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef __GRID_VIEW_HH__
#define __GRID_VIEW_HH__
/* -------------------------------------------------------------------------- */
#include "tamaas.hh"
#include "grid.hh"
#include <vector>
/* -------------------------------------------------------------------------- */
__BEGIN_TAMAAS__
/* -------------------------------------------------------------------------- */
/**
* @brief View type on grid
* /!\ iterators do not work on this type of grid
*/
template <template <typename, UInt> class Base,
typename T,
UInt base_dim,
UInt dim>
class GridView : public Base<T, dim> {
public:
/// Constructor
GridView(GridBase<T> & grid_base,
const std::vector<view::index> & multi_index);
/// Move constructor
GridView(GridView&& o) :
Base<T, dim>(std::forward<Base<T, dim>>(o)),
grid(std::exchange(o.grid, nullptr)),
indexes(std::move(o.indexes)) {}
/// Destructor
virtual ~GridView() = default;
public:
/// Compute strides and offset
void computeStrides() override;
/// Return view size
UInt dataSize() const override { return this->computeSize(); }
/// Delete resize
void resize(const std::array<UInt, dim> &) = delete;
/// Get a view only for the last component
GridView lastComponentView() const;
public:
/// Access operator (1D access is extremely slow)
template <typename... T1>
T & operator()(T1... args);
/// Const access operator (1D access is extremely slow)
template <typename... T1>
const T & operator()(T1... args) const;
protected:
Base<T, base_dim> * grid;
std::vector<view::index> indexes;
};
/* -------------------------------------------------------------------------- */
/* Template implementation */
/* -------------------------------------------------------------------------- */
template <template <typename, UInt> class Base,
typename T,
UInt base_dim,
UInt dim>
GridView<Base, T, base_dim, dim>::GridView(GridBase<T> & grid_base,
const std::vector<view::index> & multi_index):
Base<T, dim>(),
grid(nullptr),
indexes(multi_index)
{
static_assert(base_dim >= dim,
"view dimension must be >= than the base class");
// Checking view type
grid = dynamic_cast<Base<T, base_dim> *>(&grid_base);
if (!grid) TAMAAS_EXCEPTION("given base type is incompatible with view");
// Checking view integrity
if (multi_index.size() == base_dim) {
this->nb_components = grid->getNbComponents();
} else if (multi_index.size() == base_dim+1) {
this->nb_components = 1;
} else {
TAMAAS_EXCEPTION("Multi-index has wrong number of components");
}
UInt view_dim = 0;
for (auto & it : multi_index) {
if (it.i == -1) view_dim += 1;
}
if (view_dim != dim)
TAMAAS_EXCEPTION("Multi-index has the wrong number of free components");
if (indexes.size() == base_dim
&& this->nb_components == 1) indexes.push_back(view::blocked(0));
this->data.wrapMemory(grid->getInternalData(), grid->dataSize());
computeStrides();
}
/* -------------------------------------------------------------------------- */
template <template <typename, UInt> class Base,
typename T,
UInt base_dim,
UInt dim>
void GridView<Base, T, base_dim, dim>::computeStrides() {
/// Copying sizes with number of components in last position
auto stride_it = this->strides.begin();
auto size_it = this->n.begin();
auto grid_stride_it = grid->getStrides().begin();
auto grid_size_it = grid->sizes().begin();
for (auto & index : indexes) {
if (index.i == -1) {
*stride_it = *grid_stride_it;
*size_it = *grid_size_it;
++stride_it, ++size_it;
} else
this->offset += index.i * *grid_stride_it;
++grid_stride_it, ++grid_size_it;
}
}
/* -------------------------------------------------------------------------- */
template <template <typename, UInt> class Base,
typename T,
UInt base_dim,
UInt dim>
template <typename... T1>
T & GridView<Base, T, base_dim, dim>::operator()(T1... args) {
constexpr UInt nargs = sizeof...(args);
static_assert(nargs == 1 || nargs == dim || nargs == dim + 1,
"number of arguments in operator() does not match dimension");
if (nargs == 1) {
UInt index = UInt(args...);
std::array<UInt, dim+1> tuple = {0};
tuple[dim] = index % this->nb_components;
index -= tuple[dim];
index /= this->nb_components;
/// Computing tuple from index
for (UInt d = dim-1 ; d > 0 ; d--) {
tuple[d] = index % this->n[d];
index -= tuple[d];
index /= this->n[d];
}
tuple[0] = index;
return Base<T, dim>::operator()(tuple);
}
else {
return Base<T, dim>::operator()(args...);
}
}
/* -------------------------------------------------------------------------- */
template <template <typename, UInt> class Base,
typename T,
UInt base_dim,
UInt dim>
template <typename... T1>
const T & GridView<Base, T, base_dim, dim>::operator()(T1... args) const {
constexpr UInt nargs = sizeof...(args);
static_assert(nargs == 1 || nargs == dim || nargs == dim + 1,
"number of arguments in operator() does not match dimension");
if (nargs == 1) {
UInt index = UInt(args...);
std::array<UInt, dim+1> tuple = {0};
tuple[dim] = index % this->nb_components;
index -= tuple[dim];
index /= this->nb_components;
/// Computing tuple from index
for (UInt d = dim-1 ; d > 0 ; d--) {
tuple[d] = index % this->n[d];
index -= tuple[d];
index /= this->n[d];
}
tuple[0] = index;
return Base<T, dim>::operator()(tuple);
}
else {
return Base<T, dim>::operator()(args...);
}
}
/* -------------------------------------------------------------------------- */
template <template <typename, UInt> class Base,
typename T,
UInt base_dim,
UInt dim>
GridView<Base, T, base_dim, dim>
GridView<Base, T, base_dim, dim>::lastComponentView() const {
GridView<Base, T, base_dim, dim> tmp(*grid, indexes);
tmp.indexes.back() = view::blocked(this->nb_components-1);
tmp.computeStrides();
return tmp;
}
__END_TAMAAS__
#endif // __GRID_VIEW_HH__

Event Timeline