diff --git a/src/core/grid.hh b/src/core/grid.hh
index 75db563..333fd01 100644
--- a/src/core/grid.hh
+++ b/src/core/grid.hh
@@ -1,230 +1,233 @@
/*
* 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)
* Copyright (©) 2020-2022 Lucas Frérot
*
* 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 .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef GRID_HH
#define GRID_HH
/* -------------------------------------------------------------------------- */
#include "grid_base.hh"
#include "tamaas.hh"
#include
#include
#include
#include
/* -------------------------------------------------------------------------- */
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
class Grid : public GridBase {
template
using is_valid_index = fold_trait;
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
Grid(RandomAccessIterator begin, RandomAccessIterator end,
UInt nb_components);
+ template
+ Grid(RandomAccessIterator begin, RandomAccessIterator end,
+ UInt nb_components, value_type* data);
/// Constructor
Grid(const std::array& n, UInt nb_components)
: Grid(std::begin(n), std::end(n), nb_components) {}
/// Wrap on given data
Grid(const std::array& n, UInt nb_components, value_type* data);
/// Constructor with vectors
Grid(const std::vector& n, UInt nb_components)
: Grid(std::begin(n), std::end(n), nb_components) {}
/// Constructor with initializer list
Grid(const std::initializer_list& 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
void init(const Container& n, UInt nb_components);
public:
/* ------------------------------------------------------------------------ */
/* Common operations */
/* ------------------------------------------------------------------------ */
/// Resize array
void resize(const std::array& n);
/// Resize array (from std::vector)
void resize(const std::vector& n);
/// Resize array (from initializer list)
void resize(std::initializer_list n);
/// Resize array (from iterators)
template
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& sizes() const { return n; }
/// Get strides
const std::array& getStrides() const { return this->strides; }
/* ------------------------------------------------------------------------ */
/* Access operators (these cannot be moved outside the class) */
/* ------------------------------------------------------------------------ */
/// Variadic access operator (non-const)
template
inline std::enable_if_t::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
inline std::enable_if_t::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
inline T& operator()(std::array tuple);
template
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
template
inline UInt computeOffset(std::array tuple) const;
/* ------------------------------------------------------------------------ */
/* Move/Copy operators */
/* ------------------------------------------------------------------------ */
public:
using GridBase::operator=;
// = operator
Grid& operator=(const Grid& other);
// = operator (move)
Grid& operator=(Grid&& other) noexcept;
// Copy data from another grid
template
void copy(const Grid& other);
// Move data from another grid
template
void move(Grid&& other) noexcept;
template
void wrap(GridBase & other, Container&& n) {
GridBase::wrap(other);
std::copy(n.begin(), n.end(), this->n.begin());
this->computeStrides();
}
template
void wrap(const GridBase & other, Container&& n) {
GridBase::wrap(other);
std::copy(n.begin(), n.end(), this->n.begin());
this->computeStrides();
}
// Wrap memory (non-const)
void wrap(Grid& other) {
wrap(other, other.n);
}
// Wrap memory
void wrap(const Grid& other) {
wrap(other, other.n);
}
/* ------------------------------------------------------------------------ */
/* Member variables */
/* ------------------------------------------------------------------------ */
protected:
std::array n; ///< shape of grid: size per dimension
std::array strides; ///< strides for access
};
} // namespace tamaas
/* -------------------------------------------------------------------------- */
/* Inline/template function definitions */
/* -------------------------------------------------------------------------- */
#include "grid_tmpl.hh"
/* -------------------------------------------------------------------------- */
#endif // GRID_HH
diff --git a/src/core/grid_tmpl.hh b/src/core/grid_tmpl.hh
index 12293b7..69aee35 100644
--- a/src/core/grid_tmpl.hh
+++ b/src/core/grid_tmpl.hh
@@ -1,153 +1,171 @@
/*
* 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)
* Copyright (©) 2020-2022 Lucas Frérot
*
* 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 .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef GRID_TMPL_HH
#define GRID_TMPL_HH
/* -------------------------------------------------------------------------- */
#include "grid.hh"
#include "tamaas.hh"
namespace tamaas {
template
template
Grid::Grid(RandomAccessIterator begin, RandomAccessIterator end,
UInt nb_components)
: GridBase() {
if (end - begin != dim) {
TAMAAS_EXCEPTION("Provided sizes (" << end - begin
<< ") for grid do not match dimension ("
<< dim << ")");
}
this->nb_components = nb_components;
this->resize(begin, end);
}
/* -------------------------------------------------------------------------- */
+template
+template
+Grid::Grid(RandomAccessIterator begin, RandomAccessIterator end,
+ UInt nb_components, value_type* data)
+ : GridBase() {
+ if (end - begin != dim) {
+ TAMAAS_EXCEPTION("Provided sizes (" << end - begin
+ << ") for grid do not match dimension ("
+ << dim << ")");
+ }
+
+ std::copy(begin, end, this->n.begin());
+ this->nb_components = nb_components;
+ this->data.wrap(data, this->computeSize());
+}
+
+/* -------------------------------------------------------------------------- */
+
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
void Grid::resize(ForwardIt begin, ForwardIt end) {
std::copy(begin, end, this->n.begin());
UInt size = this->computeSize();
GridBase::resize(size);
this->computeStrides();
}
/* -------------------------------------------------------------------------- */
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 UInt Grid::computeOffset(std::array tuple) const {
static_assert(tdim == dim or tdim == dim + 1, "Tuple dimension is invalid");
return std::inner_product(tuple.begin(), tuple.end(), strides.begin(), 0);
}
template
template
inline T& Grid::operator()(std::array tuple) {
UInt offset = computeOffset(tuple);
return this->data[offset];
}
template
template
inline const T& Grid::operator()(std::array tuple) const {
UInt offset = computeOffset(tuple);
return this->data[offset];
}
/* -------------------------------------------------------------------------- */
template
Grid& Grid::operator=(const Grid& other) {
this->copy(other);
return *this;
}
template
Grid& Grid::operator=(Grid&& other) noexcept {
this->move(std::move(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) noexcept {
GridBase::move(std::move(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;
}
} // namespace tamaas
/* -------------------------------------------------------------------------- */
#endif // GRID_TMPL_HH
diff --git a/src/model/kelvin.cpp b/src/model/kelvin.cpp
index fdf2bad..a286c6d 100644
--- a/src/model/kelvin.cpp
+++ b/src/model/kelvin.cpp
@@ -1,161 +1,161 @@
/*
* 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)
* Copyright (©) 2020-2022 Lucas Frérot
*
* 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 .
*
*/
/* -------------------------------------------------------------------------- */
#include "kelvin.hh"
#include "logger.hh"
/* -------------------------------------------------------------------------- */
namespace tamaas {
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Constructors */
/* -------------------------------------------------------------------------- */
template
Kelvin::Kelvin(Model* model) : VolumePotential(model) {
setIntegrationMethod(integration_method::linear, 1e-12);
}
template
void Kelvin::setIntegrationMethod(integration_method method,
Real cutoff) {
this->method = method;
this->cutoff = cutoff;
Logger logger;
if (this->method == integration_method::linear) {
logger.get(LogLevel::debug)
<< TAMAAS_DEBUG_MSG("Setting linear integration method");
this->initialize(dtrait::template source_components,
dtrait::template out_components,
this->model->getDiscretization()[0]);
}
else {
logger.get(LogLevel::debug) << TAMAAS_DEBUG_MSG(
"Setting cutoff integration method (cutoff " << this->cutoff << ')');
this->initialize(dtrait::template source_components,
dtrait::template out_components, 1);
}
auto max_q = Loop::reduce(
[] CUDA_LAMBDA(VectorProxy qv) {
return qv.l2norm();
},
range>(
this->wavevectors));
if (this->method == integration_method::linear and
not std::isfinite(std::exp(max_q * this->model->getSystemSize()[0])))
logger.get(LogLevel::warning)
<< "Probable overflow of integral computation (consider "
"changing integration method to integration_method::cutoff or "
"compiling with real_type='long double')\n";
}
/* -------------------------------------------------------------------------- */
/* Operator implementation */
/* -------------------------------------------------------------------------- */
template
void Kelvin::applyIf(GridBase& source,
GridBase& out,
filter_t pred) const {
KelvinInfluence kelvin(this->model->getShearModulus(),
this->model->getPoissonRatio());
parent::transformSource(source, pred);
// Reset buffer values
for (auto&& layer : this->out_buffer)
layer = 0;
if (method == integration_method::linear) {
linearIntegral(out, kelvin);
} else {
cutoffIntegral(out, kelvin);
}
}
template
void Kelvin::linearIntegral(GridBase& out,
KelvinInfluence& kelvin) const {
detail::KelvinHelper helper;
helper.applyIntegral(this->source_buffer, this->out_buffer, this->wavevectors,
this->model->getSystemSize().front(), kelvin);
helper.applyFreeTerm(this->source_buffer, this->out_buffer, kelvin);
helper.makeFundamentalGreatAgain(this->out_buffer);
parent::transformOutput(
[](auto&& out_buffer, auto layer) ->
typename parent::BufferType& { return out_buffer[layer]; },
out);
}
template
void Kelvin::cutoffIntegral(GridBase& out,
KelvinInfluence& kelvin) const {
detail::KelvinHelper helper;
auto func = [&](auto&& out_buffer,
auto layer) -> typename parent::BufferType& {
auto&& out = out_buffer.front();
out = 0;
helper.applyIntegral(this->source_buffer, out, layer, this->wavevectors,
this->model->getSystemSize().front(), cutoff, kelvin);
helper.applyFreeTerm(this->source_buffer[layer], out, kelvin);
helper.makeFundamentalGreatAgain(out);
return out;
};
parent::transformOutput(func, out);
}
/* -------------------------------------------------------------------------- */
template
std::pair Kelvin::matvecShape() const {
const auto N = (*this->model)["displacement"].getGlobalNbPoints();
return std::make_pair(dtrait::template out_components * N,
dtrait::template source_components * N);
}
/* -------------------------------------------------------------------------- */
template
GridBase Kelvin::matvec(GridBase& X) const {
const auto dim = trait::dimension;
- Grid x;
- Grid y{this->model->getDiscretization(),
- dtrait::template out_components};
- X.setNbComponents(dtrait::template source_components);
- x.wrap(X, this->model->getDiscretization());
+ const auto shape = this->model->getDiscretization();
+ Grid x{shape.begin(), shape.end(),
+ dtrait::template source_components,
+ X.getInternalData()},
+ y{shape, dtrait::template out_components};
this->apply(x, y);
return y;
}
/* -------------------------------------------------------------------------- */
/* Template instanciation */
/* -------------------------------------------------------------------------- */
template class Kelvin;
template class Kelvin;
template class Kelvin;
/* -------------------------------------------------------------------------- */
} // namespace tamaas