Page MenuHomec4science

container_array.hh
No OneTemporary

File Metadata

Created
Wed, Jul 17, 17:06

container_array.hh

/**
* @file container_array.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Thu Jul 24 14:21:58 2014
*
* @brief This is the contiguous array-like container for LM
*
* @section LICENSE
*
* Copyright INRIA and CEA
*
* The LibMultiScale is a C++ parallel framework for the multiscale
* coupling methods dedicated to material simulations. This framework
* provides an API which makes it possible to program coupled simulations
* and integration of already existing codes.
*
* This Project was initiated in a collaboration between INRIA Futurs Bordeaux
* within ScAlApplix team and CEA/DPTA Ile de France.
* The project is now continued at the Ecole Polytechnique Fédérale de Lausanne
* within the LSMS/ENAC laboratory.
*
* This software is governed by the CeCILL-C license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL-C
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*
*/
#ifndef __LIBMULTISCALE_CONTAINER_ARRAY_HH__
#define __LIBMULTISCALE_CONTAINER_ARRAY_HH__
/* -------------------------------------------------------------------------- */
#include "container.hh"
#include <algorithm>
#include <vector>
template <typename Ref> class ReferenceManager;
/* -------------------------------------------------------------------------- */
#ifdef TRACE_ATOM
#include "lammps/ref_atom_lammps.hh"
#include "trace_atom.hh"
#endif
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/**
* Class ContainerArray<T>
* array implementation of a generic container
*/
/* -------------------------------------------------------------------------- */
template <class T> struct GetDim {
static constexpr UInt Dim = T::Dim;
inline UInt getDim() { return T::Dim; }
};
template <> struct GetDim<Real> {};
template <> struct GetDim<UInt> {};
/* -------------------------------------------------------------------------- */
template <typename T> class ContainerArrayIterator;
template <typename T> class ContainerArray;
template <typename T>
std::enable_if_t<!std::is_arithmetic<T>::value, UInt>
getContainerArrayDim([[gnu::unused]] ContainerArray<T> &cont) {
return T::Dim;
}
template <typename T>
std::enable_if_t<std::is_arithmetic<T>::value, UInt>
getContainerArrayDim(ContainerArray<T> &cont) {
return cont.cols();
}
/* -------------------------------------------------------------------------- */
template <class T>
class ContainerArray : public Container_base<T>, public GetDim<T> {
public:
using ContainerSubSet = ContainerArray<T>;
using iterator = ContainerArrayIterator<T>;
using EigenArray =
Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using value_type = T;
template <typename OtherDerived>
ContainerArray(const Eigen::EigenBase<OtherDerived> &other_array);
ContainerArray(EigenArray &&other_array);
ContainerArray(const LMID &id, UInt nrows = 0, UInt ncols = 1);
ContainerArray(UInt nrows = 0, UInt ncols = 1);
ContainerArray(ContainerArray &&);
ContainerArray(ContainerArray &);
template <typename OtherDerived>
ContainerArray &operator=(const Eigen::EigenBase<OtherDerived> &other);
ContainerArray &operator=(const ContainerArray &);
template <typename Other> decltype(auto) operator*(const Other &other) {
return (*_array) * other;
}
~ContainerArray();
auto array() { return *_array; };
auto matrix() { return _array->matrix(); };
auto matrix() const { return _array->matrix(); };
UInt getDim() { return getContainerArrayDim(*this); }
void setZero() { this->array_storage.setZero(); }
//! return an associated iterator
virtual iterator begin();
virtual iterator end();
//! sort items
virtual void sort() override;
//! search for a given item
virtual UInt search(T &el) override;
//! add a particular item
virtual void push_back(const T &el) override;
//! add a particular item
template <UInt Dim> void push_back(const Array1D<Dim> &el);
template <UInt Dim> void push_back(const Vector<Dim, T> &el);
template <UInt Dim> void push_back(const VectorView<Dim, T> el);
void push_back(const Eigen::Ref<const Eigen::ArrayXd> &el);
//! resize the container (by clearing the additional values)
virtual void resize(UInt nrows, UInt ncols = -1);
//! assign all values up to size to a single value
virtual void assign(UInt size, T val);
//! get an item from its index
inline T &get(UInt index) override;
//! get an item from its index
inline T &operator[](UInt index) override;
//! return the number of contained items
virtual UInt size() override;
//! return the number of columns in the array
UInt cols() const { return _array->cols(); };
//! return the number of columns in the array
UInt rows() const { return _array->rows(); };
//! return a row by its index
auto row(UInt row) { return _array->row(row); };
//! function that clear the container
virtual void clear();
//! return the element from its index
decltype(auto) operator()(UInt i) { return _array->row(i); };
T &operator()(UInt i, UInt j) { return _array->operator()(i, j); };
template <typename V> auto &operator+=(V &&v) {
*this->_array += v;
return *this;
}
//! access to raw pointer
T *data() { return array_storage.data(); }
//! shift access to raw pointer
auto shift(UInt index, UInt size) {
return Eigen::Map<EigenArray>(&array_storage(index, 0), size,
_array->cols());
}
decltype(auto) rowwise() { return _array->rowwise(); }
private:
EigenArray array_storage;
std::unique_ptr<Eigen::Map<EigenArray>> _array;
};
/* -------------------------------------------------------------------------- */
__END_LIBMULTISCALE__
#include "iterator_array.hh"
#include "reference_manager.hh"
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
template <typename T>
ContainerArray<T>::ContainerArray(const LMID &id, UInt nrows, UInt ncols)
: LMObject(id), Container_base<T>() {
DUMP("creating array: " << id << " : " << this << " : "
<< &(this->array_storage) << " : "
<< this->array_storage.data(),
DBG_INFO);
this->resize(nrows, ncols);
}
/* -------------------------------------------------------------------------- */
template <typename T>
ContainerArray<T>::ContainerArray(UInt nrows, UInt ncols)
: LMObject("anonymous"), Container_base<T>() {
DUMP("creating array: " << this->getID() << " : " << this << " : "
<< &(this->array_storage) << " : "
<< this->array_storage.data(),
DBG_INFO);
this->resize(nrows, ncols);
}
/* -------------------------------------------------------------------------- */
template <typename T>
template <typename OtherDerived>
ContainerArray<T>::ContainerArray(const Eigen::EigenBase<OtherDerived> &other)
: LMObject("anonymous"), Container_base<T>() {
DUMP("copying array: " << this->getID() << " : " << this, DBG_MESSAGE);
this->resize(other.rows(), other.cols());
this->array_storage = other;
_array = std::make_unique<Eigen::Map<EigenArray>>(array_storage.data(),
other.rows(), other.cols());
}
template <typename T>
ContainerArray<T>::ContainerArray(ContainerArray &&other)
: LMObject(other.getID()) {
this->array_storage = std::move(other.array_storage);
DUMP("move array: " << this->getID() << " : " << this << " : "
<< &(this->array_storage) << " : "
<< this->array_storage.data(),
DBG_INFO);
_array = std::make_unique<Eigen::Map<EigenArray>>(array_storage.data(),
other.rows(), other.cols());
}
/* -------------------------------------------------------------------------- */
template <typename T>
ContainerArray<T>::ContainerArray(ContainerArray &other)
: LMObject(other.getID()) {
DUMP("copying array: " << this->getID() << " : " << this, DBG_MESSAGE);
this->array_storage = other.array_storage;
_array = std::make_unique<Eigen::Map<EigenArray>>(array_storage.data(),
other.rows(), other.cols());
}
/* -------------------------------------------------------------------------- */
template <typename T>
ContainerArray<T> &ContainerArray<T>::operator=(const ContainerArray &other) {
this->array_storage = other.array_storage;
_array = std::make_unique<Eigen::Map<EigenArray>>(array_storage.data(),
other.rows(), other.cols());
return *this;
}
/* -------------------------------------------------------------------------- */
template <typename T>
template <typename OtherDerived>
ContainerArray<T> &ContainerArray<T>::
operator=(const Eigen::EigenBase<OtherDerived> &other) {
this->array_storage = other;
_array = std::make_unique<Eigen::Map<EigenArray>>(array_storage.data(),
other.rows(), other.cols());
return *this;
}
/* -------------------------------------------------------------------------- */
template <typename T> ContainerArray<T>::~ContainerArray() {
DUMP("destroy array: " << this->getID() << " : " << this << " : "
<< &(this->array_storage),
DBG_INFO);
clear();
if (this->hasRefManager()) {
this->getRefManager()->removeSubSet(this->getID());
}
}
/* ------------------------------------------------------------------------ */
template <class T> void ContainerArray<T>::sort() {
// std::sort(array.begin(),array.end());
LM_TOIMPLEMENT;
}
/* ------------------------------------------------------------------------ */
template <class T> inline UInt ContainerArray<T>::size() {
return _array->size();
}
/* ------------------------------------------------------------------------ */
template <class T> inline void ContainerArray<T>::clear() {
array_storage.resize(0, this->cols());
_array = std::make_unique<Eigen::Map<EigenArray>>(array_storage.data(), 0,
this->cols());
}
/* ------------------------------------------------------------------------ */
template <class T>
inline void ContainerArray<T>::resize(UInt nrows, UInt ncols) {
if (ncols == UInt(-1))
ncols = _array->cols();
if (_array && (_array->rows() > 0) && (_array->cols() != ncols))
LM_FATAL(this->getID()
<< ": cannot change the number of columns if the vector is full ("
<< nrows << " , " << ncols << " != " << _array->cols() << ")");
while (nrows > array_storage.rows()) {
array_storage.conservativeResize(1 + array_storage.rows() * 2, ncols);
}
_array = std::make_unique<Eigen::Map<EigenArray>>(array_storage.data(), nrows,
ncols);
}
/* ------------------------------------------------------------------------ */
template <class T> inline void ContainerArray<T>::assign(UInt size, T val) {
this->resize(size);
*_array = val;
}
/* ------------------------------------------------------------------------ */
template <class T>
inline void
ContainerArray<T>::push_back(const Eigen::Ref<const Eigen::ArrayXd> &el) {
auto row = _array->rows();
this->resize(row + 1);
_array->row(row) = el;
}
/* ------------------------------------------------------------------------ */
template <class T> inline void ContainerArray<T>::push_back(const T &el) {
if (_array->cols() > 1)
LM_FATAL("cannot add a single scalar with push_back in an array having "
"more than one column");
auto row = _array->rows();
this->resize(row + 1);
_array->row(row) = el;
}
/* ------------------------------------------------------------------------ */
template <class T>
template <UInt Dim>
inline void ContainerArray<T>::push_back(const Array1D<Dim> &arr) {
auto row = _array->rows();
this->resize(row + 1);
_array->row(row) = arr.transpose();
}
/* ------------------------------------------------------------------------ */
template <class T>
template <UInt Dim>
inline void ContainerArray<T>::push_back(const Vector<Dim, T> &arr) {
auto row = _array->rows();
this->resize(row + 1);
_array->row(row) = arr.transpose();
}
/* ------------------------------------------------------------------------ */
template <class T>
template <UInt Dim>
inline void ContainerArray<T>::push_back(const VectorView<Dim, T> arr) {
auto row = _array->rows();
this->resize(row + 1);
_array->row(row) = arr.transpose();
}
/* ------------------------------------------------------------------------ */
template <class T> inline T &ContainerArray<T>::get(UInt index) {
LM_ASSERT(index < size(), "out of range access : " << index << " over "
<< size() << " for "
<< this->getID());
using EigenArray1 = Eigen::Array<T, Eigen::Dynamic, 1u>;
Eigen::Map<EigenArray1> view(_array->data(), this->size());
return view(index);
}
/* ------------------------------------------------------------------------ */
template <class T> inline T &ContainerArray<T>::operator[](UInt index) {
LM_ASSERT(index < size(),
"out of range access : " << index << " over " << size());
return this->get(index);
}
/* ------------------------------------------------------------------------ */
template <class T> UInt ContainerArray<T>::search(T &el) {
for (UInt i = 0; i < size(); ++i) {
T &e = this->get(i);
if (el == e)
return i;
}
return UINT_MAX;
}
/* ------------------------------------------------------------------------ */
template <class T> auto ContainerArray<T>::begin() -> iterator {
return iterator(_array->data());
}
/* ------------------------------------------------------------------------ */
template <class T> auto ContainerArray<T>::end() -> iterator {
return iterator(_array->data() + this->size());
}
/* ------------------------------------------------------------------------ */
template <typename T> decltype(auto) operator/(Real val, ContainerArray<T> &c) {
return val / c.array();
}
/* ------------------------------------------------------------------------ */
template <typename T> decltype(auto) operator*(Real val, ContainerArray<T> &c) {
return val * c.array();
}
inline decltype(auto) operator-(ContainerArray<Real> &v) { return -v.array(); }
__END_LIBMULTISCALE__
#endif /* __LIBMULTISCALE_CONTAINER_ARRAY_HH__ */

Event Timeline