diff --git a/src/core/fftransform.hh b/src/core/fftransform.hh index 586d0f7..e9d6148 100644 --- a/src/core/fftransform.hh +++ b/src/core/fftransform.hh @@ -1,115 +1,119 @@ /** * * @author Lucas Frérot * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef FFTRANSFORM_HH #define FFTRANSFORM_HH /* -------------------------------------------------------------------------- */ #include "tamaas.hh" #include "grid.hh" #include "grid_hermitian.hh" #include "types.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ template class FFTransform { public: /// Constructor FFTransform(Grid & real, GridHermitian & spectral); /// Destructor virtual ~FFTransform(); public: /// Perform FFT virtual void forwardTransform() = 0; /// Perform IFFT virtual void backwardTransform() = 0; /// Normalize the real surface after backward transform virtual void normalize(); public: /// Fill a grid with modevectors: boolean if grid has hermitian dimensions template - static void computeFrequencies(Grid & freq); + static Grid computeFrequencies(const std::array & sizes); protected: Grid & real; GridHermitian & spectral; }; /* -------------------------------------------------------------------------- */ template template -void FFTransform::computeFrequencies(Grid & freq) { +Grid +FFTransform::computeFrequencies(const std::array & sizes) { // If hermitian is true, we suppose the dimensions of freq are // reduced based on hermitian symetry and that it has dim components - auto n = freq.sizes(); + auto & n = sizes; + Grid freq(n, dim); #pragma omp parallel for for (auto it = freq.begin(dim) ; it < freq.end(dim) ; ++it) { VectorProxy wavevector(&(*it), dim); UInt index = freq.getNbPoints() - (freq.end(dim) - it); - std::array tuple = {0}; + std::array tuple = {{0}}; /// Computing tuple from index for (UInt d = dim-1 ; d > 0 ; d--) { tuple[d] = index % n[d]; index -= tuple[d]; index /= n[d]; } tuple[0] = index; UInt dmax = dim; if (hermitian) { dmax = dim - 1; wavevector(dim-1) = tuple[dim-1]; } for (UInt d = 0 ; d < dmax ; d++) { T td = tuple[d]; T nd = n[d]; T q = (tuple[d] <= n[d]/2) ? td : td-nd; wavevector(d) = q; } } + + return freq; } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ /* -------------------------------------------------------------------------- */ #endif // FFTRANSFORM_HH diff --git a/src/core/grid.hh b/src/core/grid.hh index 869ab05..fc26beb 100644 --- a/src/core/grid.hh +++ b/src/core/grid.hh @@ -1,218 +1,218 @@ /** * * @author Lucas Frérot * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_HH__ #define __GRID_HH__ /* -------------------------------------------------------------------------- */ #include "tamaas.hh" #include "grid_base.hh" #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_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 class Grid: public GridBase { public: /* -------------------------------------------------------------------------- */ /* Types */ /* -------------------------------------------------------------------------- */ typedef T value_type; static constexpr UInt dimension = dim; /* -------------------------------------------------------------------------- */ /* Constructors */ /* -------------------------------------------------------------------------- */ public: /// Constructor by default (empty array) Grid(); /// Constructor Grid(const std::array & n, UInt nb_components); /// Constructor with vectors Grid(const std::vector & n, UInt nb_components); /// Constructor with initializer list Grid(const std::initializer_list & n, UInt nb_components); /// Copy constructor Grid(const Grid & o); /// Move constructor (transfers data ownership) Grid(Grid&& o); private: /// Init from standard container template void init(const Container & n, UInt nb_components); public: /* -------------------------------------------------------------------------- */ /* Common operations */ /* -------------------------------------------------------------------------- */ /// Resize array void resize(const std::array & n); /// Compute size - inline UInt computeSize() const; + inline UInt computeSize() const override; /// Compute strides virtual void computeStrides(); /// Print virtual void printself(std::ostream & str) const; /// Get sizes const std::array & sizes() const {return n;} /// Get strides const std::array & getStrides() const {return this->strides;} /* -------------------------------------------------------------------------- */ /* Access operators */ /* -------------------------------------------------------------------------- */ /// Variadic access operator (non-const) template inline T & operator()(T1... args); /// Variadic access operator template inline const T & operator()(T1... args) const; /// Tuple index access operator inline T & operator()(std::array tuple); inline const T & operator()(std::array tuple) const; private: /// Unpacking the arguments of variadic () template inline UInt unpackOffset(UInt offset, UInt index_pos, UInt index, T1... rest) const; /// End case for recursion template inline UInt unpackOffset(UInt offset, UInt index_pos, UInt index) const; /// Computing offset for a tuple index inline UInt computeOffset(std::array tuple) const; /* -------------------------------------------------------------------------- */ /* Arithmetic operators */ /* -------------------------------------------------------------------------- */ public: #define GRID_VEC_OPERATOR(op) \ template \ Grid & operator op(const Grid & other) \ GRID_VEC_OPERATOR(+=); GRID_VEC_OPERATOR(*=); GRID_VEC_OPERATOR(-=); GRID_VEC_OPERATOR(/=); #undef GRID_VEC_OPERATOR #define GRID_SCALAR_OPERATOR(op) \ Grid & operator op(const T & e) \ GRID_SCALAR_OPERATOR(+=); GRID_SCALAR_OPERATOR(*=); GRID_SCALAR_OPERATOR(-=); GRID_SCALAR_OPERATOR(/=); GRID_SCALAR_OPERATOR(=); #undef GRID_SCALAR_OPERATOR /* -------------------------------------------------------------------------- */ /* Move/Copy operators */ /* -------------------------------------------------------------------------- */ // = operator Grid & operator=(const Grid & other); // = operator (not const input, otherwise gcc is confused) Grid & operator=(Grid & other); // = operator (move) Grid & operator=(Grid && other); // Copy data from another grid template void copy(const Grid & other); // Move data from another grid template void move(Grid && other); /* -------------------------------------------------------------------------- */ /* Iterators */ /* -------------------------------------------------------------------------- */ public: using iterator = typename GridBase::iterator; using const_iterator = typename GridBase::const_iterator; public: iterator begin(UInt n = 1) override { return iterator(this->getInternalData()+this->offset, 0, n); } iterator end(UInt n = 1) override { return iterator(this->getInternalData()+this->offset, this->dataSize(), n); } const_iterator begin(UInt n = 1) const override { return const_iterator(this->getInternalData()+this->offset, 0, n); } const_iterator end(UInt n = 1) const override { return const_iterator(this->getInternalData()+this->offset, this->dataSize(), n); } /* -------------------------------------------------------------------------- */ /* Member variables */ /* -------------------------------------------------------------------------- */ protected: std::array n; std::array strides; }; __END_TAMAAS__ /* -------------------------------------------------------------------------- */ /* Inline/template function definitions */ /* -------------------------------------------------------------------------- */ #include "grid_tmpl.hh" /* -------------------------------------------------------------------------- */ #endif // __GRID_HH__ diff --git a/src/core/grid_hermitian.hh b/src/core/grid_hermitian.hh index 0d6752e..e78d0c2 100644 --- a/src/core/grid_hermitian.hh +++ b/src/core/grid_hermitian.hh @@ -1,180 +1,180 @@ /** * * @author Lucas Frérot * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_HERMITIAN_HH__ #define __GRID_HERMITIAN_HH__ /* -------------------------------------------------------------------------- */ #include "tamaas.hh" #include "grid.hh" #include #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ static std::complex dummy; /** * @brief Multi-dimensional, multi-component herimitian array * * This class represents an array of hermitian data, meaning it has dimensions * of: n1 * n2 * n3 * ... * (nx / 2 + 1) * * However, it acts as a fully dimensioned array, returning a dummy reference * for data outside its real dimension, allowing one to write full (and * inefficient) loops without really worrying about the reduced dimension. * * It would however be better to just use the true dimensions of the surface * for all intents and purposes, as it saves computation time. */ template class GridHermitian : public Grid, dim> { public: typedef std::complex value_type; /* -------------------------------------------------------------------------- */ /* Constructors */ /* -------------------------------------------------------------------------- */ public: GridHermitian() = default; GridHermitian(const GridHermitian & o) = default; GridHermitian(GridHermitian && o) = default; using Grid::Grid; using Grid, dim>::operator=; /* -------------------------------------------------------------------------- */ /* Access operators */ /* -------------------------------------------------------------------------- */ template inline std::complex & operator()(T1... args); template inline const std::complex & operator()(T1... args) const; static std::array hermitianDimensions(const std::array & n) { std::array hn(n); hn[dim-1] /= 2; hn[dim-1] += 1; return hn; } private: template inline void packTuple(UInt * t, UInt i, T1... args) const; template inline void packTuple(UInt * t, UInt i) const; }; /* -------------------------------------------------------------------------- */ /* Inline function definitions */ /* -------------------------------------------------------------------------- */ template template inline void GridHermitian::packTuple(UInt * t, UInt i, T1... args) const { *t = i; packTuple(t+1, args...); } template template inline void GridHermitian::packTuple(UInt * t, UInt i) const { *t = i; } template template inline std::complex & GridHermitian::operator()(T1... args) { TAMAAS_ASSERT(sizeof...(T1) == dim + 1 || sizeof...(T1) == 1, "operator() does not match dimension"); if (sizeof...(T1) == 1 && dim != 1) { UInt tuple[1] = {0}; packTuple(tuple, args...); if (tuple[0] >= this->data.size()) { TAMAAS_DEBUG_EXCEPTION("out of bonds access on hermitian surface"); dummy = std::complex(0,0); return dummy; } else return this->Grid, dim>::operator()(args...); } - std::array tuple = {0}; + std::array tuple = {{0}}; packTuple(tuple.data(), args...); // reverse tuple if necessary if (tuple[dim-1] >= this->n[dim-1]) { for (UInt i = 0 ; i < dim ; i++) { if (tuple[i] && i != dim-1) tuple[i] = this->n[i]-tuple[i]; else if (tuple[i] && i == dim-1) tuple[i] = 2*(this->n[i]-1) - tuple[i]; } dummy = std::conj(this->Grid, dim>::operator()(tuple)); return dummy; } else { return this->Grid, dim>::operator()(tuple); } } template template inline const std::complex & GridHermitian::operator()(T1... args) const { TAMAAS_ASSERT(sizeof...(T1) == dim + 1 || sizeof...(T1) == 1, "operator() does not match dimension"); if (sizeof...(T1) == 1 && dim != 1) { UInt tuple[1] = {0}; packTuple(tuple, args...); if (tuple[0] >= this->data.size()) { TAMAAS_DEBUG_EXCEPTION("out of bonds access on hermitian surface"); dummy = std::complex(0,0); return dummy; } else return this->Grid, dim>::operator()(args...); } std::array tuple = {0}; packTuple(tuple.data(), args...); // reverse tuple if necessary if (tuple[dim-1] >= this->n[dim-1]) { for (UInt i = 0 ; i < dim ; i++) { if (tuple[i] && i != dim-1) tuple[i] = this->n[i]-tuple[i]; else if (tuple[i] && i == dim-1) tuple[i] = 2*(this->n[i]-1) - tuple[i]; } dummy = std::conj(this->Grid, dim>::operator()(tuple)); return dummy; } else { return this->Grid, dim>::operator()(tuple); } } __END_TAMAAS__ #endif // __GRID_HERMITIAN_HH__ diff --git a/src/core/grid_tmpl.hh b/src/core/grid_tmpl.hh index c27c14b..3e09b20 100644 --- a/src/core/grid_tmpl.hh +++ b/src/core/grid_tmpl.hh @@ -1,200 +1,200 @@ /** * * @author Lucas Frérot * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_TMPL_HH__ #define __GRID_TMPL_HH__ /* -------------------------------------------------------------------------- */ #include "tamaas.hh" #include "grid.hh" __BEGIN_TAMAAS__ template template void Grid::init(const T1 & n, UInt nb_components) { std::copy(n.begin(), n.end(), this->n.begin()); this->nb_components = nb_components; this->resize(this->n); } /* -------------------------------------------------------------------------- */ template inline UInt Grid::computeSize() const { UInt size = 1; for (UInt i = 0 ; i < dim ; i++) size *= n[i]; size *= this->nb_components; return size; } /* -------------------------------------------------------------------------- */ template template inline UInt Grid::unpackOffset(UInt offset, UInt index_pos, UInt index, T1... rest) const { offset += index * strides[index_pos]; return unpackOffset(offset, index_pos+1, rest...); // tail-rec bb } template template inline UInt Grid::unpackOffset(UInt offset, UInt index_pos, UInt index) const { return offset + index * strides[index_pos]; } template template inline T & Grid::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(this->offset, start, args...); return this->data[offset]; } template template inline const T & Grid::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(this->offset, start, args...); return this->data[offset]; } /* -------------------------------------------------------------------------- */ template inline UInt Grid::computeOffset(std::array tuple) const { UInt offset = this->offset; for (UInt i = 0 ; i < dim+1 ; i++) { offset += tuple[i] * strides[i]; } return offset; } template inline T & Grid::operator()(std::array tuple) { UInt offset = computeOffset(tuple); return this->data[offset]; } template inline const T & Grid::operator()(std::array tuple) const { UInt offset = computeOffset(tuple); return this->data[offset]; } /* -------------------------------------------------------------------------- */ #define GRID_VEC_OPERATOR_IMPL(op) \ template \ template \ inline Grid & Grid::operator op(const Grid & other) { \ TAMAAS_ASSERT(other.computeSize() == this->computeSize(), \ "surface size does not match"); \ auto begin_it = this->begin(), end_it = this->end(); \ - auto other_begin = other.begin(); \ - _Pragma("omp parallel for") \ + auto other_begin = other.begin(), other_it = other.begin(); \ + _Pragma("omp parallel for firstprivate(other_it)") \ for (auto it = begin() ; it < end_it ; ++it) { \ - auto other_it = other_begin; \ + other_it = other_begin; \ other_it += it - begin_it; \ *it op *other_it; \ } \ return *this; \ } \ GRID_VEC_OPERATOR_IMPL(+=); GRID_VEC_OPERATOR_IMPL(-=); GRID_VEC_OPERATOR_IMPL(*=); GRID_VEC_OPERATOR_IMPL(/=); #undef GRID_VEC_OPERATOR /* -------------------------------------------------------------------------- */ template Grid & Grid::operator=(const Grid & other) { this->copy(other); return *this; } template Grid & Grid::operator=(Grid & other) { this->copy(other); return *this; } template Grid & Grid::operator=(Grid && other) { this->move(std::forward>(other)); return *this; } /* -------------------------------------------------------------------------- */ template template void Grid::copy(const Grid & other) { GridBase::copy(other); this->n = other.n; this->strides = other.strides; } template template void Grid::move(Grid && other) { GridBase::move(std::forward>(other)); this->n = std::move(other.n); this->strides = std::move(other.strides); } /* -------------------------------------------------------------------------- */ /* Stream operator */ /* -------------------------------------------------------------------------- */ template inline std::ostream & operator<<(std::ostream & stream, const Grid & _this) { _this.printself(stream); return stream; } __END_TAMAAS__ /* -------------------------------------------------------------------------- */ #endif // __GRID_TMPL_HH__ diff --git a/src/core/grid_view.hh b/src/core/grid_view.hh index 702a6e6..7d80aaa 100644 --- a/src/core/grid_view.hh +++ b/src/core/grid_view.hh @@ -1,240 +1,265 @@ /** * * @author Lucas Frérot * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __GRID_VIEW_HH__ #define __GRID_VIEW_HH__ /* -------------------------------------------------------------------------- */ #include "tamaas.hh" #include "grid.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ /** * @brief View type on grid * /!\ iterators do not work on this type of grid + * */ template