Page MenuHomec4science

grid.hh
No OneTemporary

File Metadata

Created
Fri, May 3, 09:12
/*
* SPDX-License-Indentifier: AGPL-3.0-or-later
*
* Copyright (©) 2016-2022 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef GRID_HH
#define GRID_HH
/* -------------------------------------------------------------------------- */
#include "grid_base.hh"
#include "tamaas.hh"
#include <array>
#include <numeric>
#include <utility>
#include <vector>
/* -------------------------------------------------------------------------- */
namespace tamaas {
/**
* @brief Multi-dimensional & multi-component array class
*
* This class is a container for multi-component data stored on a multi-
* dimensional grid.
*
* The access function is the parenthesis operator. For a grid of dimension d,
* the operator takes d+1 arguments: the first d arguments are the position on
* the grid and the last one is the component of the stored data.
*
* It is also possible to use the access operator with only one argument, it is
* then considering the grid as a flat array, accessing the given cell of the
* array.
*/
template <typename T, UInt dim>
class Grid : public GridBase<T> {
template <typename... D>
using is_valid_index = fold_trait<std::is_integral, D...>;
public:
/* ------------------------------------------------------------------------ */
/* Types */
/* ------------------------------------------------------------------------ */
using value_type = T;
using reference = value_type&;
static constexpr UInt dimension = dim;
/* ------------------------------------------------------------------------ */
/* Constructors */
/* ------------------------------------------------------------------------ */
public:
/// Constructor by default (empty array)
Grid();
/// Constructor from iterators
template <typename RandomAccessIterator>
Grid(RandomAccessIterator begin, RandomAccessIterator end,
UInt nb_components);
/// Constructor
Grid(const std::array<UInt, dim>& n, UInt nb_components)
: Grid(std::begin(n), std::end(n), nb_components) {}
/// Wrap on given data
Grid(const std::array<UInt, dim>& n, UInt nb_components, value_type* data);
/// Constructor with vectors
Grid(const std::vector<UInt>& n, UInt nb_components)
: Grid(std::begin(n), std::end(n), nb_components) {}
/// Constructor with initializer list
Grid(const std::initializer_list<UInt>& n, UInt nb_components)
: Grid(std::begin(n), std::end(n), nb_components) {}
/// Copy constructor
Grid(const Grid& o);
/// Move constructor (transfers data ownership)
Grid(Grid&& o) noexcept;
/// Destructor
~Grid() override = default;
private:
/// Init from standard container
template <typename Container>
void init(const Container& n, UInt nb_components);
public:
/* ------------------------------------------------------------------------ */
/* Common operations */
/* ------------------------------------------------------------------------ */
/// Resize array
void resize(const std::array<UInt, dim>& n);
/// Resize array (from std::vector)
void resize(const std::vector<UInt>& n);
/// Resize array (from initializer list)
void resize(std::initializer_list<UInt> n);
/// Resize array (from iterators)
template <typename ForwardIt>
void resize(ForwardIt begin, ForwardIt end);
/// Compute size
inline UInt computeSize() const;
/// Get grid dimension
inline UInt getDimension() const override { return dim; }
/// Compute strides
void computeStrides();
/// Print
virtual void printself(std::ostream& str) const;
/// Get sizes
const std::array<UInt, dim>& sizes() const { return n; }
/// Get strides
const std::array<UInt, dim + 1>& getStrides() const { return this->strides; }
/* ------------------------------------------------------------------------ */
/* Access operators (these cannot be moved outside the class) */
/* ------------------------------------------------------------------------ */
/// Variadic access operator (non-const)
template <typename... T1>
inline std::enable_if_t<is_valid_index<T1...>::value, T&>
operator()(T1... args) {
/// Checking access integrity
constexpr UInt nargs = sizeof...(T1);
static_assert(nargs == dim + 1 || nargs == 1 || nargs == dim,
"number of arguments in operator() does not match dimension");
constexpr UInt start = (nargs == 1) ? dim : 0;
UInt offset = unpackOffset(0, start, args...);
return this->data[offset];
}
/// Variadic access operator
template <typename... T1>
inline std::enable_if_t<is_valid_index<T1...>::value, const T&>
operator()(T1... args) const {
/// Checking access integrity
constexpr UInt nargs = sizeof...(T1);
static_assert(nargs == dim + 1 || nargs == 1 || nargs == dim,
"number of arguments in operator() does not match dimension");
constexpr UInt start = (nargs == 1) ? dim : 0;
UInt offset = unpackOffset(0, start, args...);
return this->data[offset];
}
/// Tuple index access operator
template <std::size_t tdim>
inline T& operator()(std::array<UInt, tdim> tuple);
template <std::size_t tdim>
inline const T& operator()(std::array<UInt, tdim> tuple) const;
private:
/// Unpacking the arguments of variadic ()
template <typename... T1>
inline UInt unpackOffset(UInt offset, UInt index_pos, UInt index,
T1... rest) const;
/// End case for recursion
template <typename... T1>
inline UInt unpackOffset(UInt offset, UInt index_pos, UInt index) const;
/// Computing offset for a tuple index
template <std::size_t tdim>
inline UInt computeOffset(std::array<UInt, tdim> tuple) const;
/* ------------------------------------------------------------------------ */
/* Move/Copy operators */
/* ------------------------------------------------------------------------ */
public:
using GridBase<T>::operator=;
// = operator
Grid& operator=(const Grid& other);
// = operator (move)
Grid& operator=(Grid&& other) noexcept;
// Copy data from another grid
template <typename T1>
void copy(const Grid<T1, dim>& other);
// Move data from another grid
template <typename T1>
void move(Grid<T1, dim>&& other) noexcept;
// Wrap memory (non-const)
void wrap(Grid& other) {
GridBase<T>::wrap(other);
std::copy(other.n.begin(), other.n.end(), n.begin());
this->computeStrides();
}
// Wrap memory
void wrap(const Grid& other) {
GridBase<T>::wrap(other);
std::copy(other.n.begin(), other.n.end(), n.begin());
this->computeStrides();
}
/* ------------------------------------------------------------------------ */
/* Member variables */
/* ------------------------------------------------------------------------ */
protected:
std::array<UInt, dim> n; ///< shape of grid: size per dimension
std::array<UInt, dim + 1> strides; ///< strides for access
};
} // namespace tamaas
/* -------------------------------------------------------------------------- */
/* Inline/template function definitions */
/* -------------------------------------------------------------------------- */
#include "grid_tmpl.hh"
/* -------------------------------------------------------------------------- */
#endif // GRID_HH

Event Timeline