diff --git a/python/tamaas/nonlinear_solvers/__init__.py b/python/tamaas/nonlinear_solvers/__init__.py
index b10ba88..d30b39a 100644
--- a/python/tamaas/nonlinear_solvers/__init__.py
+++ b/python/tamaas/nonlinear_solvers/__init__.py
@@ -1,167 +1,171 @@
# -*- mode:python; coding: utf-8 -*-
#
# 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 .
"""Nonlinear solvers for plasticity problems.
Solvers in this module use :py:mod:`scipy.optimize` to solve the implicit
non-linear equation for plastic deformations with fixed contact pressures.
"""
from functools import wraps
from scipy.optimize import newton_krylov, root
from scipy.optimize.nonlin import NoConvergence
from .. import EPSolver, Logger, LogLevel, mpi
from .._tamaas import _tolerance_manager
from .._tamaas import _DFSANESolver as DFSANECXXSolver
__all__ = ['NLNoConvergence',
'DFSANESolver',
'DFSANECXXSolver',
'NewtonKrylovSolver',
'ToleranceManager']
class NLNoConvergence(Exception):
"""Convergence not reached exception."""
class ScipySolver(EPSolver):
"""Base class for solvers wrapping SciPy routines."""
def __init__(self, residual, model=None, callback=None):
"""Construct nonlinear solver with residual.
:param residual: plasticity residual object
:param model: Deprecated
:param callback: passed on to the Scipy solver
"""
super(ScipySolver, self).__init__(residual)
if mpi.size() > 1:
raise RuntimeError("Scipy solvers cannot be used with MPI; "
"DFSANECXXSolver can be used instead")
self.callback = callback
self._x = self.getStrainIncrement()
self._residual = self.getResidual()
self.options = {'ftol': 0, 'fatol': 1e-9}
def solve(self):
"""Solve R(δε) = 0 using a Scipy function."""
# For initial guess, compute the strain due to boundary tractions
# self._residual.computeResidual(self._x)
# self._x[...] = self._residual.getVector()
EPSolver.beforeSolve(self)
# Scipy root callback
def compute_residual(vec):
self._residual.computeResidual(vec)
return self._residual.getVector().copy()
# Solve
+ Logger().get(LogLevel.debug) << \
+ "Entering non-linear solve\n"
self._x[...] = self._scipy_solve(compute_residual)
+ Logger().get(LogLevel.debug) << \
+ "Non-linear solve returned"
# Computing displacements
self._residual.computeResidualDisplacement(self._x)
def reset(self):
"""Set solution vector to zero."""
self._x[...] = 0
def _scipy_solve(self, compute_residual):
"""Actually call the scipy solver.
:param compute_residual: function returning residual for given variable
"""
raise NotImplementedError()
class NewtonKrylovSolver(ScipySolver):
"""Solve using a finite-difference Newton-Krylov method."""
def _scipy_solve(self, compute_residual):
try:
return newton_krylov(compute_residual, self._x,
f_tol=self.tolerance,
verbose=True, callback=self.callback)
except NoConvergence:
raise NLNoConvergence("Newton-Krylov did not converge")
class DFSANESolver(ScipySolver):
"""Solve using a spectral residual jacobianless method.
See :doi:`10.1090/S0025-5718-06-01840-0` for details on method and
the relevant Scipy `documentation
`_ for
details on parameters.
"""
def _scipy_solve(self, compute_residual):
solution = root(compute_residual,
self._x,
method='df-sane',
options={'ftol': 0, 'fatol': self.tolerance},
callback=self.callback)
Logger().get(LogLevel.info) << \
"DF-SANE/Scipy: {} ({} iterations, {})".format(
solution.message,
solution.nit,
self.tolerance)
if not solution.success:
raise NLNoConvergence("DF-SANE/Scipy did not converge")
return solution.x.copy()
def ToleranceManager(start, end, rate):
"""Decorate solver to manage tolerance of non-linear solve step."""
def actual_decorator(cls):
orig_init = cls.__init__
orig_solve = cls.solve
orig_update_state = cls.updateState
@wraps(cls.__init__)
def __init__(obj, *args, **kwargs):
orig_init(obj, *args, **kwargs)
obj.setToleranceManager(_tolerance_manager(start, end, rate))
@wraps(cls.solve)
def new_solve(obj, *args, **kwargs):
ftol = obj.tolerance
ftol *= rate
obj.tolerance = max(ftol, end)
return orig_solve(obj, *args, **kwargs)
@wraps(cls.updateState)
def updateState(obj, *args, **kwargs):
obj.tolerance = start
return orig_update_state(obj, *args, **kwargs)
cls.__init__ = __init__
# cls.solve = new_solve
# cls.updateState = updateState
return cls
return actual_decorator
diff --git a/src/core/array.hh b/src/core/array.hh
index 5bc3124..c145d01 100644
--- a/src/core/array.hh
+++ b/src/core/array.hh
@@ -1,168 +1,179 @@
/*
* 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 ARRAY_HH
#define ARRAY_HH
/* -------------------------------------------------------------------------- */
#include "logger.hh"
+#include "span.hh"
#include "tamaas.hh"
#include
#include
#include
#include
/* -------------------------------------------------------------------------- */
namespace tamaas {
/// Generic storage class with wrapping capacities
template
struct Array final {
/// Default
Array() = default;
+
/// Empty array of given size
- Array(UInt size) : Array() { this->resize(size); }
+ Array(UInt size) : Array() { resize(size); }
+
/// Copy constructor (deep)
Array(const Array& v) : Array() {
- this->resize(v._size);
- thrust::copy_n(v._data, v._size, this->_data);
+ resize(v.size());
+ thrust::copy(v.view_.begin(), v.view_.end(), view_.begin());
}
+
/// Move constructor (transfers data ownership)
Array(Array&& v) noexcept : Array() {
- _data = std::exchange(v._data, nullptr);
- _size = std::exchange(v._size, 0);
- _reserved = std::exchange(v._reserved, 0);
- wrapped = std::exchange(v.wrapped, false);
+ view_ = std::exchange(v.view_, span{});
+ reserved_ = std::exchange(v.reserved_, 0);
+ wrapped_ = std::exchange(v.wrapped_, false);
}
+
/// Wrap array on data
- Array(T* data, UInt size) : Array() { this->wrap(data, size); }
+ Array(T* data, UInt size) noexcept : Array() { wrap(data, size); }
+
+ /// Wrap on span
+ Array(span view) noexcept : Array() { wrap(view); }
+
/// Destructor
~Array() {
- if (not wrapped)
- _alloc.deallocate(_data, _reserved);
+ if (not wrapped_)
+ alloc_.deallocate(view_);
}
/// Copy operator
Array& operator=(const Array& v) {
- this->wrapped = false;
- if (v.size() != this->size())
- this->resize(v.size());
- thrust::copy_n(v._data, _size, _data);
+ wrapped_ = false;
+ resize(v.size());
+ thrust::copy(v.view_.begin(), v.view_.end(), view_.begin());
return *this;
}
/// Move operator
Array& operator=(Array&& v) noexcept {
- if (this != &v) {
- if (not wrapped)
- _alloc.deallocate(_data, _reserved);
- _data = std::exchange(v._data, nullptr);
- _size = std::exchange(v._size, 0);
- _reserved = std::exchange(v._reserved, 0);
- wrapped = std::exchange(v.wrapped, false);
- }
+ if (this == &v)
+ return *this;
+
+ if (not wrapped_)
+ alloc_.deallocate(view_);
+ view_ = std::exchange(v.view_, span{});
+ reserved_ = std::exchange(v.reserved_, 0);
+ wrapped_ = std::exchange(v.wrapped_, false);
return *this;
}
- void wrap(const Array& other) { this->wrap(other._data, other._size); }
+ /// Wrap on view
+ Array& operator=(span v) noexcept { wrap(v); }
- /// Wrap a memory pointer
- void wrap(T* data, UInt size) {
- _data = data;
- _size = size;
- wrapped = true;
- _reserved = 0;
+ /// Wrap array
+ void wrap(const Array& other) noexcept { wrap(other.view_); }
+
+ /// Wrap view
+ void wrap(span view) noexcept {
+ view_ = view;
+ wrapped_ = true;
+ reserved_ = 0;
}
+ /// Wrap a memory pointer
+ void wrap(T* data, UInt size) noexcept { wrap(span{data, size}); }
+
/// Data pointer access (const)
- const T* data() const { return _data; }
+ const T* data() const { return view_.data(); }
+
/// Data pointer access (non-const)
- T* data() { return _data; }
+ T* data() { return view_.data(); }
/// Resize array
- void resize(UInt size, const T& value = T()) {
- if (wrapped)
+ void resize(UInt new_size, const T& value = T()) {
+ if (wrapped_)
TAMAAS_EXCEPTION("cannot resize wrapped array");
// Erase array
- if (size == 0) {
- _alloc.deallocate(_data, _reserved);
- _data = nullptr;
- _size = 0;
- _reserved = 0;
+ if (new_size == 0) {
+ alloc_.deallocate(view_);
+ view_ = span{};
+ reserved_ = 0;
return;
}
// Do nothing
- if (size == this->_size)
+ if (new_size == size())
return;
// Allocate new data
- _alloc.deallocate(_data, _reserved);
+ alloc_.deallocate(view_);
- _data = _alloc.allocate(size);
- _size = size;
- _reserved = size;
+ view_ = alloc_.allocate(new_size);
+ reserved_ = new_size;
- if (not wrapped)
- thrust::fill(_data, _data + size, value);
+ if (not wrapped_)
+ thrust::fill(view_.begin(), view_.end(), value);
}
/// Reserve storage space
void reserve(UInt size) {
- if (_reserved >= size)
+ if (reserved_ >= size)
return;
- auto new_data = _alloc.allocate(size);
- if (new_data != _data) {
- thrust::copy_n(_data, _size, new_data);
- _alloc.deallocate(_data, _reserved);
- _data = new_data;
- _reserved = size;
+ auto new_view = alloc_.allocate(size);
+
+ if (new_view.data() != view_.data()) {
+ thrust::copy(view_.begin(), view_.end(), new_view.begin());
+
+ alloc_.deallocate(view_);
+ view_ = {new_view.data(), view_.size()};
+ reserved_ = view_.size();
+ } else {
+ reserved_ = size;
}
}
/// Access operator
- inline T& operator[](UInt i) {
- TAMAAS_ASSERT(i < _size, "memory overflow");
- return _data[i];
- }
+ inline T& operator[](UInt i) { return view_[i]; }
/// Access operator (const)
- inline const T& operator[](UInt i) const {
- TAMAAS_ASSERT(i < _size, "memory overflow");
- return _data[i];
- }
+ inline const T& operator[](UInt i) const { return view_[i]; }
/// Get size of array
- inline UInt size() const { return _size; }
+ inline UInt size() const { return view_.size(); }
+
+ span view() const { return view_; }
private:
- T* _data = nullptr;
- UInt _size = 0;
- std::size_t _reserved = 0;
- bool wrapped = false;
- Allocator _alloc;
+ span view_;
+ typename span::size_type reserved_ = 0;
+ bool wrapped_ = false;
+ Allocator alloc_;
};
} // namespace tamaas
/* -------------------------------------------------------------------------- */
#endif /* ARRAY_HH */
diff --git a/src/core/cuda/unified_allocator.hh b/src/core/cuda/unified_allocator.hh
index 7630e9d..97f4983 100644
--- a/src/core/cuda/unified_allocator.hh
+++ b/src/core/cuda/unified_allocator.hh
@@ -1,51 +1,52 @@
/*
* 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 UNIFIED_ALLOCATOR_HH
#define UNIFIED_ALLOCATOR_HH
/* -------------------------------------------------------------------------- */
+#include "span.hh"
#include
#include
/* -------------------------------------------------------------------------- */
namespace tamaas {
/// Class allocating [unified
/// memory](http://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__MEMORY.html#group__CUDART__MEMORY_1gd228014f19cc0975ebe3e0dd2af6dd1b)
template
struct UnifiedAllocator {
/// Allocate memory
- static T* allocate(std::size_t n) {
+ static span allocate(typename span::size_type n) noexcept {
T* p = nullptr;
cudaMallocManaged(&p, n * sizeof(T));
return p;
}
/// Free memory
static void deallocate(T* p, __attribute__((unused)) std::size_t n) {
cudaFree(p);
}
};
} // namespace tamaas
#endif // UNIFIED_ALLOCATOR_HH
diff --git a/src/core/fftw/fftw_allocator.hh b/src/core/fftw/fftw_allocator.hh
index f0eab15..5d6f793 100644
--- a/src/core/fftw/fftw_allocator.hh
+++ b/src/core/fftw/fftw_allocator.hh
@@ -1,52 +1,52 @@
/*
* 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 FFTW_ALLOCATOR_HH
#define FFTW_ALLOCATOR_HH
/* -------------------------------------------------------------------------- */
+#include "span.hh"
#include
#include
/* -------------------------------------------------------------------------- */
namespace tamaas {
/// Class allocating
/// [SIMD](http://www.fftw.org/fftw3_doc/SIMD-alignment-and-fftw_005fmalloc.html#SIMD-alignment-and-fftw_005fmalloc)
/// aligned memory
template
struct FFTWAllocator {
/// Allocate memory
- static T* allocate(std::size_t n) noexcept {
+ static span allocate(typename span::size_type n) noexcept {
T* p = nullptr;
- p = (T*)fftw_malloc(sizeof(T) * n);
- return p;
+ p = static_cast(fftw_malloc(sizeof(T) * n));
+ span view{p, n};
+ return view;
}
/// Free memory
- static void deallocate(T* p, __attribute__((unused)) std::size_t n) noexcept {
- fftw_free(p);
- }
+ static void deallocate(span view) noexcept { fftw_free(view.data()); }
};
} // namespace tamaas
#endif // FFTW_ALLOCATOR_HH
diff --git a/src/core/grid.cpp b/src/core/grid.cpp
index 55f8204..8086e65 100644
--- a/src/core/grid.cpp
+++ b/src/core/grid.cpp
@@ -1,122 +1,100 @@
/*
* 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 "grid.hh"
#include "tamaas.hh"
#include
#include
#include
/* -------------------------------------------------------------------------- */
namespace tamaas {
/* -------------------------------------------------------------------------- */
template
Grid::Grid() : GridBase() {
this->n.fill(0);
this->strides.fill(1);
this->nb_components = 1;
}
/* -------------------------------------------------------------------------- */
-template
-Grid::Grid(const std::array& n, UInt nb_components,
- value_type* data)
- : GridBase() {
- this->n = n;
- this->nb_components = nb_components;
- UInt size = this->computeSize();
- this->data.wrap(data, size);
- this->computeStrides();
-}
-
-template
-Grid::Grid(const Grid& o)
- : GridBase(o), n(o.n), strides(o.strides) {}
-
-template
-Grid::Grid(Grid&& o) noexcept
- : GridBase(std::move(o)), n(std::move(o.n)),
- strides(std::move(o.strides)) {}
-
-/* -------------------------------------------------------------------------- */
-
template
void Grid::resize(const std::array& n) {
this->resize(n.begin(), n.end());
}
/* -------------------------------------------------------------------------- */
template
void Grid::resize(const std::vector& n) {
TAMAAS_ASSERT(n.size() == dim, "Shape vector not matching grid dimensions");
this->resize(n.begin(), n.end());
}
/* -------------------------------------------------------------------------- */
template
void Grid::resize(std::initializer_list n) {
TAMAAS_ASSERT(n.size() == dim,
"Shape initializer list not matching grid dimensions");
this->resize(std::begin(n), std::end(n));
}
/* -------------------------------------------------------------------------- */
template
void Grid::computeStrides() {
std::copy(n.begin() + 1, n.end(), strides.begin());
strides[dim] = 1;
strides[dim - 1] = this->nb_components;
std::partial_sum(strides.rbegin(), strides.rend(), strides.rbegin(),
std::multiplies());
}
/* -------------------------------------------------------------------------- */
template
void Grid::printself(std::ostream& str) const {
str << "Grid(" << dim << ", " << this->nb_components << ") {";
for (auto& val : *this) {
str << val << ", ";
}
str << "\b\b}";
}
/* -------------------------------------------------------------------------- */
/// Class instanciation
#define GRID_INSTANCIATE_TYPE(type) \
template class Grid; \
template class Grid; \
template class Grid
GRID_INSTANCIATE_TYPE(Real);
GRID_INSTANCIATE_TYPE(UInt);
GRID_INSTANCIATE_TYPE(Complex);
GRID_INSTANCIATE_TYPE(Int);
GRID_INSTANCIATE_TYPE(bool);
#undef GRID_INSTANCIATE_TYPE
} // namespace tamaas
diff --git a/src/core/grid.hh b/src/core/grid.hh
index 333fd01..4229715 100644
--- a/src/core/grid.hh
+++ b/src/core/grid.hh
@@ -1,233 +1,234 @@
/*
* 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
+ /// Constructor with shape from iterators
template
Grid(RandomAccessIterator begin, RandomAccessIterator end,
UInt nb_components);
+ /// Construct with shape from iterators on data view
template
- Grid(RandomAccessIterator begin, RandomAccessIterator end,
- UInt nb_components, value_type* data);
+ Grid(RandomAccessIterator begin, RandomAccessIterator end, UInt nb_components,
+ span 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);
+ Grid(const std::array& n, UInt nb_components,
+ span data)
+ : Grid(std::begin(n), std::end(n), nb_components, 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);
+ Grid(const Grid& o) : GridBase(), n(o.n), strides(o.strides) {}
/// Move constructor (transfers data ownership)
- Grid(Grid&& o) noexcept;
+ Grid(Grid&& o) noexcept
+ : GridBase(std::move(o)), n(std::move(o.n)),
+ strides(std::move(o.strides)) {}
/// 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) {
+ 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) {
+ 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);
- }
+ void wrap(Grid& other) { wrap(other, other.n); }
// Wrap memory
- void wrap(const Grid& other) {
- wrap(other, other.n);
- }
+ 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_base.hh b/src/core/grid_base.hh
index 5a7e2ac..fc96e29 100644
--- a/src/core/grid_base.hh
+++ b/src/core/grid_base.hh
@@ -1,342 +1,344 @@
/*
* 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_BASE_HH
#define GRID_BASE_HH
/* -------------------------------------------------------------------------- */
#include "array.hh"
#include "iterator.hh"
#include "loop.hh"
#include "mpi_interface.hh"
#include "static_types.hh"
#include "tamaas.hh"
#include
#include
#include
#include
/* -------------------------------------------------------------------------- */
namespace tamaas {
/**
* @brief Dimension agnostic grid with components stored per points
*/
template
class GridBase {
public:
/// Constructor by default
GridBase() = default;
/// Copy constructor
GridBase(const GridBase& o) { this->copy(o); }
/// Move constructor (transfers data ownership)
GridBase(GridBase&& o) noexcept
: data(std::move(o.data)),
nb_components(std::exchange(o.nb_components, 1)) {}
/// Initialize with size
explicit GridBase(UInt nb_points, UInt nb_components = 1) {
setNbComponents(nb_components);
this->resize(nb_points * nb_components);
}
/// Destructor
virtual ~GridBase() = default;
/* ------------------------------------------------------------------------ */
/* Iterator class */
/* ------------------------------------------------------------------------ */
using iterator = iterator_::iterator;
using const_iterator = iterator_::iterator;
using value_type = T;
using reference = value_type&;
/// Get grid dimension
virtual UInt getDimension() const { return 1; }
/// Get internal data pointer (const)
const T* getInternalData() const { return this->data.data(); }
/// Get internal data pointer (non-const)
T* getInternalData() { return this->data.data(); }
/// Get number of components
UInt getNbComponents() const { return nb_components; }
/// Set number of components
void setNbComponents(UInt n) { nb_components = n; }
/// Get total size
virtual UInt dataSize() const { return this->data.size(); }
/// Get global data size
UInt globalDataSize() const {
return mpi::allreduce(dataSize());
}
/// Get number of points
UInt getNbPoints() const {
return this->dataSize() / this->getNbComponents();
}
/// Get global number of points
UInt getGlobalNbPoints() const {
return this->globalDataSize() / this->getNbComponents();
}
/// Set components
void uniformSetComponents(const GridBase& vec);
/// Resize
void resize(UInt size) { this->data.resize(size); }
/// Reserve storage w/o changing data logic
void reserve(UInt size) { this->data.reserve(size); }
/* ------------------------------------------------------------------------ */
/* Iterator methods */
/* ------------------------------------------------------------------------ */
virtual iterator begin(UInt n = 1) {
return iterator(this->getInternalData(), n);
}
virtual iterator end(UInt n = 1) {
return iterator(this->getInternalData() + this->dataSize(), n);
}
virtual const_iterator begin(UInt n = 1) const {
return const_iterator(this->getInternalData(), n);
}
virtual const_iterator end(UInt n = 1) const {
return const_iterator(this->getInternalData() + this->dataSize(), n);
}
+ decltype(auto) view() const { return data.view(); }
+
/* ------------------------------------------------------------------------ */
/* Operators */
/* ------------------------------------------------------------------------ */
inline T& operator()(UInt i) { return this->data[i]; }
inline const T& operator()(UInt i) const { return this->data[i]; }
#define VEC_OPERATOR(op) \
template \
GridBase& operator op(const GridBase& other)
VEC_OPERATOR(+=);
VEC_OPERATOR(*=);
VEC_OPERATOR(-=);
VEC_OPERATOR(/=);
#undef VEC_OPERATOR
template
T dot(const GridBase& other) const;
#define SCALAR_OPERATOR(op) GridBase& operator op(const T& e)
SCALAR_OPERATOR(+=);
SCALAR_OPERATOR(*=);
SCALAR_OPERATOR(-=);
SCALAR_OPERATOR(/=);
SCALAR_OPERATOR(=);
#undef SCALAR_OPERATOR
/// Broadcast operators
#define BROADCAST_OPERATOR(op) \
template \
GridBase& operator op(const StaticArray& b)
BROADCAST_OPERATOR(+=);
BROADCAST_OPERATOR(-=);
BROADCAST_OPERATOR(*=);
BROADCAST_OPERATOR(/=);
BROADCAST_OPERATOR(=);
#undef BROADCAST_OPERATOR
/* ------------------------------------------------------------------------ */
/* Min/max */
/* ------------------------------------------------------------------------ */
T min() const;
T max() const;
T sum() const;
T mean() const { return sum() / static_cast(globalDataSize()); }
T var() const;
T l2norm() const { return std::sqrt(dot(*this)); }
/* ------------------------------------------------------------------------ */
/* Move/Copy */
/* ------------------------------------------------------------------------ */
GridBase& operator=(const GridBase& o) {
this->copy(o);
return *this;
}
GridBase& operator=(GridBase& o) {
this->copy(o);
return *this;
}
GridBase& operator=(GridBase&& o) noexcept {
this->move(std::move(o));
return *this;
}
template
void copy(const GridBase& other) {
if (other.dataSize() != this->dataSize())
this->resize(other.dataSize());
thrust::copy(other.begin(), other.end(), this->begin());
nb_components = other.nb_components;
}
template
void move(GridBase&& other) noexcept {
data = std::move(other.data);
nb_components = std::exchange(other.nb_components, 1);
}
GridBase& wrap(GridBase& o) {
data.wrap(o.data);
nb_components = o.nb_components;
return *this;
}
GridBase& wrap(const GridBase& o) {
data.wrap(o.data);
nb_components = o.nb_components;
return *this;
}
protected:
Array data;
UInt nb_components = 1;
};
/* -------------------------------------------------------------------------- */
template
void GridBase::uniformSetComponents(const GridBase& vec) {
if (vec.dataSize() != this->nb_components)
TAMAAS_EXCEPTION("Cannot set grid field with values of vector");
auto begin_it{begin()};
auto end_it{end()}; // silencing nvcc warnings
for (auto it = begin(); it < end_it; ++it) {
UInt i = it - begin_it;
*it = vec(i % this->nb_components);
}
}
/* --------------------------------------------------------------------------
*/
#define SCALAR_OPERATOR_IMPL(op) \
template \
inline GridBase& GridBase::operator op(const T& e) { \
Loop::loop([e] CUDA_LAMBDA(T& val) { val op e; }, *this); \
return *this; \
}
SCALAR_OPERATOR_IMPL(+=)
SCALAR_OPERATOR_IMPL(*=)
SCALAR_OPERATOR_IMPL(-=)
SCALAR_OPERATOR_IMPL(/=)
SCALAR_OPERATOR_IMPL(=)
#undef SCALAR_OPERATOR_IMPL
/* -------------------------------------------------------------------------- */
#define VEC_OPERATOR_IMPL(op) \
template \
template \
inline GridBase& GridBase::operator op(const GridBase& other) { \
TAMAAS_ASSERT(other.dataSize() == this->dataSize(), \
"surface size does not match"); \
Loop::loop([] CUDA_LAMBDA(T& x, const T1& y) { x op y; }, *this, other); \
return *this; \
}
VEC_OPERATOR_IMPL(+=)
VEC_OPERATOR_IMPL(-=)
VEC_OPERATOR_IMPL(*=)
VEC_OPERATOR_IMPL(/=)
#undef VEC_OPERATOR
/* -------------------------------------------------------------------------- */
#define BROADCAST_OPERATOR_IMPL(op) \
template \
template \
GridBase& GridBase::operator op(const StaticArray& b) { \
TAMAAS_ASSERT(this->dataSize() % size == 0, \
"Broadcast operator cannot broadcast" \
<< size << " on array of size " << this->dataSize()); \
Tensor::type, size> a(b); \
Loop::loop([a] CUDA_LAMBDA(VectorProxy g) { g op a; }, \
range>(*this)); \
return *this; \
}
BROADCAST_OPERATOR_IMPL(+=)
BROADCAST_OPERATOR_IMPL(-=)
BROADCAST_OPERATOR_IMPL(*=)
BROADCAST_OPERATOR_IMPL(/=)
BROADCAST_OPERATOR_IMPL(=)
#undef BROADCAST_OPERATOR_IMPL
/* -------------------------------------------------------------------------- */
template
inline T GridBase::min() const {
// const auto id = [] CUDA_LAMBDA (const T&x){return x;};
return Loop::reduce([] CUDA_LAMBDA(const T& x) { return x; },
*this);
}
/* -------------------------------------------------------------------------- */
template
inline T GridBase::max() const {
return Loop::reduce([] CUDA_LAMBDA(const T& x) { return x; },
*this);
}
/* -------------------------------------------------------------------------- */
template
inline T GridBase::sum() const {
return Loop::reduce([] CUDA_LAMBDA(const T& x) { return x; },
*this);
}
/* -------------------------------------------------------------------------- */
template
inline T GridBase::var() const {
const T mu = mean();
const T var = Loop::reduce(
[mu] CUDA_LAMBDA(const T& x) { return (x - mu) * (x - mu); }, *this);
return var / (globalDataSize() - 1);
}
/* -------------------------------------------------------------------------- */
template
template
T GridBase::dot(const GridBase& other) const {
return Loop::reduce(
[] CUDA_LAMBDA(const T& x, const T1& y) { return x * y; }, *this, other);
}
} // namespace tamaas
#endif // GRID_BASE_HH
diff --git a/src/core/grid_tmpl.hh b/src/core/grid_tmpl.hh
index 69aee35..499a661 100644
--- a/src/core/grid_tmpl.hh
+++ b/src/core/grid_tmpl.hh
@@ -1,171 +1,176 @@
/*
* 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)
+ UInt nb_components, span 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());
+
+ if (data.size() != computeSize())
+ TAMAAS_EXCEPTION("incompatible wrap span size");
+
+ this->data.wrap(data);
+ this->computeStrides();
}
/* -------------------------------------------------------------------------- */
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/core/cuda/unified_allocator.hh b/src/core/span.hh
similarity index 50%
copy from src/core/cuda/unified_allocator.hh
copy to src/core/span.hh
index 7630e9d..a4622de 100644
--- a/src/core/cuda/unified_allocator.hh
+++ b/src/core/span.hh
@@ -1,51 +1,71 @@
/*
* 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 UNIFIED_ALLOCATOR_HH
-#define UNIFIED_ALLOCATOR_HH
+#ifndef SPAN_HH
+#define SPAN_HH
/* -------------------------------------------------------------------------- */
-#include
-#include
+#include "tamaas.hh"
+#include
+#include
+#include
/* -------------------------------------------------------------------------- */
-
namespace tamaas {
-/// Class allocating [unified
-/// memory](http://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__MEMORY.html#group__CUDART__MEMORY_1gd228014f19cc0975ebe3e0dd2af6dd1b)
template
-struct UnifiedAllocator {
- /// Allocate memory
- static T* allocate(std::size_t n) {
- T* p = nullptr;
- cudaMallocManaged(&p, n * sizeof(T));
- return p;
+struct span {
+ using element_type = T;
+ using value_type = std::remove_cv_t;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using iterator = T*;
+ using reverse_iterator = std::reverse_iterator;
+
+ constexpr size_type size() const noexcept { return size_; }
+ constexpr pointer data() const noexcept { return data_; }
+
+ constexpr iterator begin() const noexcept { return data_; }
+ constexpr iterator end() const noexcept { return data_ + size_; }
+ constexpr iterator begin() noexcept { return data_; }
+ constexpr iterator end() noexcept { return data_ + size_; }
+
+ reference operator[](size_type idx) {
+ TAMAAS_ASSERT((idx < size_), "index out of span range");
+ return data_[idx];
}
- /// Free memory
- static void deallocate(T* p, __attribute__((unused)) std::size_t n) {
- cudaFree(p);
+ const_reference operator[](size_type idx) const {
+ TAMAAS_ASSERT((idx < size_), "index out of span range");
+ return data_[idx];
}
+
+ pointer data_ = nullptr;
+ size_type size_ = 0;
};
} // namespace tamaas
-#endif // UNIFIED_ALLOCATOR_HH
+/* -------------------------------------------------------------------------- */
+#endif
diff --git a/src/core/tamaas.hh b/src/core/tamaas.hh
index 1f15e61..836c0bf 100644
--- a/src/core/tamaas.hh
+++ b/src/core/tamaas.hh
@@ -1,199 +1,200 @@
/**
* @mainpage Tamaas - A high-performance periodic contact library
*
* @section Introduction
* Tamaas is a spectral-integral-equation based contact library. It is made
* with love to be fast and friendly!
*
* @author Lucas Frérot
* @author Guillaume Anciaux
* @author Valentine Rey
* @author Son Pham-Ba
* @author Jean-François Molinari
*
* @section License
*
* 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 TAMAAS_HH
#define TAMAAS_HH
/* -------------------------------------------------------------------------- */
#ifndef TAMAAS_USE_CUDA
#define TAMAAS_USE_FFTW
#endif
// Values for fftw backends
#define TAMAAS_FFTW_BACKEND_OMP 2
#define TAMAAS_FFTW_BACKEND_THREADS 2
#define TAMAAS_FFTW_BACKEND_NONE 3
// Values for thrust backends
#define TAMAAS_LOOP_BACKEND_OMP 1
#define TAMAAS_LOOP_BACKEND_TBB 2
#define TAMAAS_LOOP_BACKEND_CPP 3
#define TAMAAS_LOOP_BACKEND_CUDA 4
// Default loop backend is OpenMP
#ifndef TAMAAS_LOOP_BACKEND
#define TAMAAS_LOOP_BACKEND TAMAAS_LOOP_BACKEND_OMP
#endif
// Default FFTW backend is none
#ifndef TAMAAS_FFTW_BACKEND
#define TAMAAS_FFTW_BACKEND TAMAAS_FFTW_BACKEND_NONE
#endif
// If the thrust device hasn't been set, set OpenMP
#ifndef THRUST_DEVICE_SYSTEM
#define THRUST_DEVICE_SYSTEM THRUST_DEVICE_SYSTEM_OMP
#endif
+
+/// Convenience macros
+#define TAMAAS_DEBUG_MSG(mesg) \
+ __FILE__ << ':' << __LINE__ << ": " << mesg << '\n'
+#define TAMAAS_EXCEPTION(mesg) \
+ { \
+ std::stringstream sstr; \
+ sstr << TAMAAS_DEBUG_MSG("FATAL: " << mesg); \
+ throw ::tamaas::Exception(sstr.str()); \
+ }
+
+#define SURFACE_FATAL(mesg) TAMAAS_EXCEPTION(mesg)
+
+#if defined(TAMAAS_DEBUG)
+#define TAMAAS_ASSERT(cond, reason) \
+ do { \
+ if (not(cond)) { \
+ TAMAAS_EXCEPTION(#cond " assert failed: " << reason); \
+ } \
+ } while (0)
+#define TAMAAS_DEBUG_EXCEPTION(reason) TAMAAS_EXCEPTION(reason)
+#else
+#define TAMAAS_ASSERT(cond, reason)
+#define TAMAAS_DEBUG_EXCEPTION(reason)
+#endif
+
+#define TAMAAS_ACCESSOR(var, type, name) \
+ type& get##name() { return var; } \
+ void set##name(const type& new_var) { var = new_var; }
+
/* -------------------------------------------------------------------------- */
// Standard includes
#include
#include
#include
#include
#include
/* -------------------------------------------------------------------------- */
// Special thrust includes
#include
#include
#ifdef TAMAAS_USE_CUDA
#include "cuda/unified_allocator.hh"
#else
#include "fftw/fftw_allocator.hh"
#endif
/* -------------------------------------------------------------------------- */
namespace tamaas {
/* -------------------------------------------------------------------------- */
/// Cuda specific definitions
#define CUDA_LAMBDA __device__ __host__
#ifdef TAMAAS_USE_CUDA
template
using Allocator = UnifiedAllocator;
#else
template
using Allocator = FFTWAllocator;
#endif
/// Common types definitions
// If type macros have not been set, put default values
#ifndef TAMAAS_REAL_TYPE
#define TAMAAS_REAL_TYPE double
#endif
#ifndef TAMAAS_INT_TYPE
#define TAMAAS_INT_TYPE int
#endif
using Real = TAMAAS_REAL_TYPE; ///< default floating point type
using Int = TAMAAS_INT_TYPE; ///< default signed integer type
using UInt = std::make_unsigned_t; ///< default unsigned integer type
template