diff --git a/python/wrap/test_features.cpp b/python/wrap/test_features.cpp
index bf06da0..87f5e8d 100644
--- a/python/wrap/test_features.cpp
+++ b/python/wrap/test_features.cpp
@@ -1,105 +1,120 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
+#include "boussinesq.hh"
+#include "eigenvalues.hh"
+#include "isotropic_hardening.hh"
#include "kelvin.hh"
#include "mindlin.hh"
-#include "boussinesq.hh"
#include "model.hh"
#include "model_type.hh"
#include "volume_potential.hh"
-#include "isotropic_hardening.hh"
#include "wrap.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_TAMAAS__
namespace wrap {
+using namespace py::literals;
+
template class KOp, model_type type,
UInt tensor_order>
void wrapKOp(const std::string& basename, py::module& mod) {
constexpr UInt dim = model_type_traits::dimension;
std::stringstream str;
str << basename << tensor_order;
py::class_>(mod, str.str().c_str())
.def(py::init())
.def("apply",
[](const KOp& engine, Grid& in,
Grid& out) { engine.apply(in, out); });
}
template
void wrapIsotropicHardening(py::module& mod) {
constexpr UInt dim = model_type_traits::dimension;
py::class_>(mod, "IsotropicHardening")
.def(py::init())
.def_property("h", &IsotropicHardening::getHardeningModulus,
&IsotropicHardening::setHardeningModulus)
.def_property("sigma_0", &IsotropicHardening::getYieldStress,
&IsotropicHardening::setYieldStress)
.def("computeStress",
[](IsotropicHardening& iso, Grid& stress,
const Grid& strain,
const Grid& strain_increment) {
- iso.template computeStress(stress, strain, strain_increment);
+ iso.template computeStress(stress, strain,
+ strain_increment);
})
.def("computeStressUpdate",
[](IsotropicHardening& iso, Grid& stress,
const Grid& strain,
const Grid& strain_increment) {
iso.template computeStress(stress, strain, strain_increment);
})
.def("computePlasticIncrement",
[](IsotropicHardening& iso, Grid& stress,
const Grid& strain,
const Grid& strain_increment) {
- iso.template computePlasticIncrement(stress, strain, strain_increment);
+ iso.template computePlasticIncrement(stress, strain,
+ strain_increment);
})
.def("computePlasticIncrementUpdate",
[](IsotropicHardening& iso, Grid& stress,
const Grid& strain,
const Grid& strain_increment) {
- iso.template computePlasticIncrement(stress, strain, strain_increment);
+ iso.template computePlasticIncrement(stress, strain,
+ strain_increment);
});
- // .def("getPlasticStrain", &IsotropicHardening::getPlasticStrain);
+ // .def("getPlasticStrain", &IsotropicHardening::getPlasticStrain);
+}
+
+void wrapEigenvalues(py::module& mod) {
+ mod.def("eigenvalues",
+ [](model_type type, Grid& eigs, const Grid& field) {
+ eigenvalues(type, eigs, field);
+ },
+ "model_type"_a, "eigenvalues_out"_a, "field"_a);
}
/// Wrap temporary features for testing
void wrapTestFeatures(py::module& mod) {
auto test_module = mod.def_submodule("_test_features");
test_module.doc() =
"Module for testing new features.\n"
"DISCLAIMER: this API is subject to frequent and unannounced changes "
"and should **not** be relied upon!";
// wrapKOp("Kelvin_", test_module);
// wrapKOp("Kelvin_", test_module);
// wrapKOp("Kelvin_", test_module);
// wrapKOp("Mindlin_", test_module);
// wrapKOp("Mindlin_", test_module);
// wrapKOp("Boussinesq_", test_module);
// wrapKOp("Boussinesq_", test_module);
wrapIsotropicHardening(test_module);
+ wrapEigenvalues(test_module);
}
-}
+} // namespace wrap
__END_TAMAAS__
diff --git a/src/SConscript b/src/SConscript
index 58f2321..41b88ce 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -1,158 +1,159 @@
# -*- coding: utf-8 -*-
# @file
# @section LICENSE
#
# Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
import os
Import('main_env')
def prepend(path, list):
return [os.path.join(path, x) for x in list]
env = main_env.Clone()
# Core
core_list = """
fft_plan_manager.cpp
fftransform.cpp
fftransform_fftw.cpp
grid.cpp
grid_hermitian.cpp
statistics.cpp
surface.cpp
tamaas.cpp
legacy_types.cpp
loop.cpp
+eigenvalues.cpp
""".split()
core_list = prepend('core', core_list)
if not main_env['strip_info']:
core_list.append('tamaas_info.cpp')
# Lib roughcontact
generator_list = """
surface_generator.cpp
surface_generator_filter.cpp
surface_generator_filter_fft.cpp
surface_generator_random_phase.cpp
isopowerlaw.cpp
regularized_powerlaw.cpp
""".split()
generator_list = prepend('surface', generator_list)
# Lib PERCOLATION
percolation_list = """
flood_fill.cpp
""".split()
percolation_list = prepend('percolation', percolation_list)
# BEM PERCOLATION
bem_list = """
bem_kato.cpp
bem_polonski.cpp
bem_gigi.cpp
bem_gigipol.cpp
bem_penalty.cpp
bem_uzawa.cpp
bem_fft_base.cpp
bem_functional.cpp
bem_meta_functional.cpp
elastic_energy_functional.cpp
exponential_adhesion_functional.cpp
squared_exponential_adhesion_functional.cpp
maugis_adhesion_functional.cpp
complimentary_term_functional.cpp
bem_grid.cpp
bem_grid_polonski.cpp
bem_grid_kato.cpp
bem_grid_teboulle.cpp
bem_grid_condat.cpp
""".split()
bem_list = prepend('bem', bem_list)
# Model
model_list = """
model.cpp
model_factory.cpp
model_type.cpp
model_template.cpp
be_engine.cpp
westergaard.cpp
elastic_functional.cpp
meta_functional.cpp
adhesion_functional.cpp
volume_potential.cpp
kelvin.cpp
mindlin.cpp
boussinesq.cpp
elasto_plastic/isotropic_hardening.cpp
elasto_plastic/elasto_plastic_model.cpp
elasto_plastic/residual.cpp
integration/element.cpp
""".split()
model_list = prepend('model', model_list)
# Solvers
solvers_list = """
contact_solver.cpp
polonsky_keer_rey.cpp
kato.cpp
beck_teboulle.cpp
condat.cpp
polonsky_keer_tan.cpp
ep_solver.cpp
epic.cpp
""".split()
solvers_list = prepend('solvers', solvers_list)
# GPU API
gpu_list = """
fftransform_cufft.cpp
""".split()
gpu_list = prepend('gpu', gpu_list)
# Assembling total list
rough_contact_list = \
core_list + generator_list + percolation_list + model_list + solvers_list
# For some reason collapse OMP loops don't compile on intel
if env['CXX'] != 'icpc':
rough_contact_list += bem_list
# Adding GPU if needed
if env['backend'] == 'cuda':
rough_contact_list += gpu_list
# Generating dependency files
# env.AppendUnique(CXXFLAGS=['-MMD'])
# for file_name in rough_contact_list:
# obj = file_name.replace('.cpp', '.os')
# dep_file_name = file_name.replace('.cpp', '.d')
# env.SideEffect(dep_file_name, obj)
# env.ParseDepends(dep_file_name)
# Adding extra warnings for Tamaas base lib
env.AppendUnique(CXXFLAGS=['-Wextra'])
libTamaas = env.SharedLibrary('Tamaas', rough_contact_list)
Export('libTamaas')
diff --git a/src/core/eigenvalues.cpp b/src/core/eigenvalues.cpp
new file mode 100644
index 0000000..2d55c79
--- /dev/null
+++ b/src/core/eigenvalues.cpp
@@ -0,0 +1,47 @@
+/**
+ * @file
+ * @section LICENSE
+ *
+ * Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#include "eigenvalues.hh"
+
+namespace tamaas {
+void eigenvalues(model_type /*type*/, GridBase& eigs,
+ const GridBase& field) {
+ /*
+ #define EIG_CASE(_, __, type) \
+ case type: { \
+ constexpr UInt dim = model_type_traits::dimension; \
+ const auto& f = dynamic_cast&>(field); \
+ auto& e = dynamic_cast&>(eigs); \
+ eigenvalues(e, f); \
+ break; \
+ }
+
+ switch (type) { BOOST_PP_SEQ_FOR_EACH(EIG_CASE, ~, TAMAAS_MODEL_TYPES); }
+ //*/
+
+ constexpr UInt dim = 3;
+ const auto& f = dynamic_cast&>(field);
+ auto& e = dynamic_cast&>(eigs);
+ eigenvalues(e, f);
+}
+
+} // namespace tamaas
diff --git a/src/core/eigenvalues.hh b/src/core/eigenvalues.hh
new file mode 100644
index 0000000..fd464fc
--- /dev/null
+++ b/src/core/eigenvalues.hh
@@ -0,0 +1,49 @@
+/**
+ * @file
+ * @section LICENSE
+ *
+ * Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#ifndef EIGENVALUES_HH
+#define EIGENVALUES_HH
+/* -------------------------------------------------------------------------- */
+#include "eigenvalues.hh"
+#include "grid.hh"
+#include "loop.hh"
+#include "model_type.hh"
+#include "ranges.hh"
+#include "static_types.hh"
+#include
+
+namespace tamaas {
+
+/// Compute eigenvalues of a symmetric matrix field
+template
+void eigenvalues(Grid& eigs, const Grid& field) {
+ Loop::loop([](auto eig, auto f) { eig = eigenvalues(f); },
+ range>(eigs),
+ range>(field));
+}
+
+void eigenvalues(model_type type, GridBase& eigs,
+ const GridBase& field);
+
+} // namespace tamaas
+
+#endif /* EIGENVALUES_HH */
diff --git a/src/core/static_types.hh b/src/core/static_types.hh
index bb10325..8fce747 100644
--- a/src/core/static_types.hh
+++ b/src/core/static_types.hh
@@ -1,750 +1,750 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef __STATIC_TYPES_HH__
#define __STATIC_TYPES_HH__
/* -------------------------------------------------------------------------- */
#include "tamaas.hh"
#include
namespace tamaas {
/* -------------------------------------------------------------------------- */
namespace detail {
template
struct product_tail_rec : product_tail_rec {};
template
struct product_tail_rec : std::integral_constant {};
template
struct get_rec : get_rec {};
template
struct get_rec<0, n, ns...> : std::integral_constant {};
} // namespace detail
template
struct product : detail::product_tail_rec<1, ns...> {};
template
struct get : detail::get_rec {};
template
struct is_arithmetic : std::is_arithmetic {};
template
struct is_arithmetic> : std::true_type {};
template
struct voigt_size;
template <>
struct voigt_size<3> : std::integral_constant {};
template <>
struct voigt_size<2> : std::integral_constant {};
template <>
struct voigt_size<1> : std::integral_constant {};
/* -------------------------------------------------------------------------- */
/**
* @brief Static Array
*
* This class is meant to be a small and fast object for intermediate
* calculations, possibly on wrapped memory belonging to a grid. Support type
* show be either a pointer or a C array. It should not contain any virtual
* method.
*/
template
class StaticArray {
static_assert(std::is_array::value ||
std::is_pointer::value,
"the support type of StaticArray should be either a pointer or "
"a C-array");
using T = DataType;
using T_bare = typename std::remove_cv_t;
public:
using value_type = T;
static constexpr UInt size = _size;
public:
/// Access operator
__device__ __host__ T& operator()(UInt i) {
// TAMAAS_ASSERT(i < n, "Access out of bounds");
return _mem[i];
}
/// Access operator
__device__ __host__ const T& operator()(UInt i) const {
// TAMAAS_ASSERT(i < n, "Access out of bounds");
return _mem[i];
}
/// Scalar product
template
__device__ __host__ T_bare dot(const StaticArray& o) const {
decltype(T_bare(0) * DT(0)) res = 0;
for (UInt i = 0; i < size; ++i)
res += (*this)(i)*o(i);
return res;
}
/// L2 norm squared
__device__ __host__ T_bare l2squared() const { return this->dot(*this); }
/// L2 norm
__device__ __host__ T_bare l2norm() const { return std::sqrt(l2squared()); }
/// Sum of all elements
__device__ __host__ T_bare sum() const {
T_bare res = 0;
for (UInt i = 0; i < size; ++i)
res += (*this)(i);
return res;
}
#define VECTOR_OP(op) \
template \
__device__ __host__ void operator op(const StaticArray& o) { \
for (UInt i = 0; i < size; ++i) \
(*this)(i) op o(i); \
}
VECTOR_OP(+=)
VECTOR_OP(-=)
VECTOR_OP(*=)
VECTOR_OP(/=)
#undef VECTOR_OP
#define SCALAR_OP(op) \
template \
__device__ __host__ std::enable_if_t::value, StaticArray&> \
operator op(const T1& x) { \
for (UInt i = 0; i < size; ++i) \
(*this)(i) op x; \
return *this; \
}
SCALAR_OP(+=)
SCALAR_OP(-=)
SCALAR_OP(*=)
SCALAR_OP(/=)
SCALAR_OP(=)
#undef SCALAR_OP
/// Overriding the implicit copy operator
__device__ __host__ StaticArray& operator=(const StaticArray& o) {
return this->copy(o);
}
template
__device__ __host__ void operator=(const StaticArray& o) {
this->copy(o);
}
template
__device__ __host__ StaticArray& copy(const StaticArray& o) {
for (UInt i = 0; i < size; ++i)
(*this)(i) = o(i);
return *this;
}
T* begin() { return _mem; }
const T* begin() const { return _mem; }
T* end() { return _mem + size; }
const T* end() const { return _mem + size; }
private:
template
using valid_size_t = std::enable_if_t<(size > 0), U>;
public:
valid_size_t front() { return *_mem; }
valid_size_t front() const { return *_mem; }
valid_size_t back() { return _mem[size - 1]; }
valid_size_t back() const { return _mem[size - 1]; }
protected:
SupportType _mem;
};
/**
* @brief Static Tensor
*
* This class implements a multi-dimensional tensor behavior.
*/
template
class StaticTensor
: public StaticArray::value> {
using parent = StaticArray::value>;
using T = DataType;
public:
static constexpr UInt dim = sizeof...(dims);
using parent::operator=;
private:
template
__device__ __host__ static UInt unpackOffset(UInt offset, UInt index,
Idx... rest) {
constexpr UInt size = sizeof...(rest);
offset += index;
offset *= get::value;
return unpackOffset(offset, rest...);
}
template
__device__ __host__ static UInt unpackOffset(UInt offset, UInt index) {
return offset + index;
}
public:
template
__device__ __host__ const T& operator()(Idx... idx) const {
return parent::operator()(unpackOffset(0, idx...));
}
template
__device__ __host__ T& operator()(Idx... idx) {
return parent::operator()(unpackOffset(0, idx...));
}
};
/* -------------------------------------------------------------------------- */
/* Common Static Types */
/* -------------------------------------------------------------------------- */
// Forward declaration
template
class StaticVector;
template
class StaticSymMatrix;
/* -------------------------------------------------------------------------- */
template
class StaticMatrix : public StaticTensor {
using T = DataType;
using T_bare = typename std::remove_cv_t;
public:
using StaticTensor::operator=;
// /// Initialize from a symmetric matrix
template
__device__ __host__ std::enable_if_t
fromSymmetric(const StaticSymMatrix& o);
/// Outer product of two vectors
template
__device__ __host__ void outer(const StaticVector& a,
const StaticVector& b);
template
__device__ __host__ void mul(const StaticMatrix& a,
const StaticMatrix& b) {
(*this) = T(0);
for (UInt i = 0; i < n; ++i)
for (UInt j = 0; j < m; ++j)
for (UInt k = 0; k < l; ++k)
(*this)(i, j) += a(i, k) * b(k, j);
}
__device__ __host__ std::enable_if_t trace() const {
T_bare res{0};
for (UInt i = 0; i < n; ++i)
res += (*this)(i, i);
return res;
}
template
__device__ __host__ std::enable_if_t
deviatoric(const StaticMatrix& mat, Real factor = n) {
auto norm_trace = mat.trace() / factor;
for (UInt i = 0; i < n; ++i)
for (UInt j = 0; j < m; ++j)
(*this)(i, j) = mat(i, j) - (i == j) * norm_trace;
}
};
/* -------------------------------------------------------------------------- */
/// Vector class with size determined at compile-time
template
class StaticVector : public StaticTensor {
using T = std::remove_cv_t;
public:
using StaticTensor::operator=;
/// Matrix-vector product
template
__device__ __host__ void mul(const StaticMatrix& mat,
const StaticVector& vec) {
*this = T(0);
for (UInt i = 0; i < n; ++i)
for (UInt j = 0; j < m; ++j)
(*this)(i) +=
((transpose) ? mat(j, i) : mat(i, j)) * vec(j); // can be optimized
}
};
/* -------------------------------------------------------------------------- */
/// Symmetric matrix in Voigt notation
template
class StaticSymMatrix
: public StaticVector::value> {
using parent = StaticVector::value>;
using T = std::remove_cv_t;
private:
template
__device__ __host__ void sym_binary(const StaticMatrix& m,
BinOp&& op) {
for (UInt i = 0; i < n; ++i)
op((*this)(i), m(i, i));
const auto a = 0.5 * std::sqrt(2);
for (UInt j = n - 1, b = n; j > 0; --j)
for (int i = j - 1; i >= 0; --i)
op((*this)(b++), a * (m(i, j) + m(j, i)));
}
public:
/// Copy values from matrix and symmetrize
template
__device__ __host__ void symmetrize(const StaticMatrix& m) {
sym_binary(m, [](auto&& v, auto&& w) { v = w; });
}
/// Add values from symmetrized matrix
template
__device__ __host__ void operator+=(const StaticMatrix& m) {
sym_binary(m, [](auto&& v, auto&& w) { v += w; });
}
__device__ __host__ auto trace() const {
std::remove_cv_t res = 0;
for (UInt i = 0; i < n; ++i)
res += (*this)(i);
return res;
}
template
__device__ __host__ void deviatoric(const StaticSymMatrix& m,
Real factor = n) {
auto tr = m.trace() / factor;
for (UInt i = 0; i < n; ++i)
(*this)(i) = m(i) - tr;
for (UInt i = n; i < voigt_size::value; ++i)
(*this)(i) = m(i);
}
using parent::operator+=;
using parent::operator=;
};
/* -------------------------------------------------------------------------- */
// Implementation of constructor from symmetric matrix
template
template
__device__ __host__ std::enable_if_t
StaticMatrix::fromSymmetric(
const StaticSymMatrix& o) {
for (UInt i = 0; i < n; ++i)
(*this)(i, i) = o(i);
// We use Mendel notation for the vector representation
const auto a = 1. / std::sqrt(2);
for (UInt j = n - 1, b = n; j > 0; --j)
for (int i = j - 1; i >= 0; --i)
(*this)(i, j) = (*this)(j, i) = a * o(b++);
}
// Implementation of outer product
template
template
__device__ __host__ void StaticMatrix::outer(
const StaticVector& a, const StaticVector& b) {
for (UInt i = 0; i < n; ++i)
for (UInt j = 0; j < m; ++j)
(*this)(i, j) = a(i) * b(j);
}
/* -------------------------------------------------------------------------- */
/* On the stack static types */
/* -------------------------------------------------------------------------- */
template class StaticParent,
UInt... dims>
struct static_size_helper : product {};
template
struct static_size_helper : voigt_size {};
template class StaticParent, typename T,
UInt... dims>
class Tensor
: public StaticParent<
T, T[static_size_helper::value], dims...> {
static constexpr UInt size = static_size_helper::value;
using parent = StaticParent;
public:
using parent::operator=;
using parent::copy;
/// Default constructor
__device__ __host__ Tensor() = default;
/// Construct with default value
__device__ __host__ Tensor(T val) { *this = val; }
/// Construct from array
__device__ __host__ Tensor(const std::array& arr) {
// we use size to ensure static loop unrolling
for (UInt i = 0; i < size; ++i)
this->_mem[i] = arr[i];
}
/// Copy from array
__device__ __host__ Tensor& operator=(const std::array& arr) {
// we use size to ensure static loop unrolling
for (UInt i = 0; i < size; ++i)
(*this)(i) = arr[i];
}
/// Construct by copy from static tensor
template
__device__ __host__ Tensor(const StaticParent& o) {
this->copy(o);
}
};
template
using Matrix = Tensor;
template
using SymMatrix = Tensor;
template
using Vector = Tensor;
/* -------------------------------------------------------------------------- */
/* Proxy Static Types */
/* -------------------------------------------------------------------------- */
/// Proxy type for tensor
template class StaticParent, typename T,
UInt... dims>
class TensorProxy : public StaticParent {
using parent = StaticParent;
public:
/// Explicit construction from data location
__device__ __host__ explicit TensorProxy(T* spot) { this->_mem = spot; }
/// Explicit construction from lvalue-reference
__device__ __host__ explicit TensorProxy(T& spot) : TensorProxy(&spot) {}
/// Construction from static tensor
template
__device__ __host__
TensorProxy(StaticParent& o)
: TensorProxy(o.begin()) {}
using parent::operator=;
public:
using stack_type = Tensor;
};
template
using MatrixProxy = TensorProxy;
template
using SymMatrixProxy = TensorProxy;
template
using VectorProxy = TensorProxy;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Arithmetic operators creating temporaries */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Simple operators */
/* -------------------------------------------------------------------------- */
template
__device__ __host__ Vector
operator+(const StaticVector& a,
const StaticVector& b) {
Vector res(a);
res += b;
return res;
}
template
__device__ __host__ Vector
operator-(const StaticVector& a,
const StaticVector& b) {
Vector res(a);
res -= b;
return res;
}
template
__device__ __host__ Vector
operator-(const StaticVector& a) {
Vector res(a);
res *= -1;
return res;
}
template
__device__ __host__ Matrix
operator+(const StaticMatrix& a,
const StaticMatrix& b) {
Matrix res(a);
res += b;
return res;
}
template
__device__ __host__ Matrix
operator-(const StaticMatrix& a,
const StaticMatrix& b) {
Matrix res(a);
res -= b;
return res;
}
template
__device__ __host__ Matrix
operator-(const StaticMatrix& a) {
Matrix res(a);
res *= -1;
return res;
}
template
__device__ __host__ SymMatrix
operator+(const StaticSymMatrix& a,
const StaticSymMatrix& b) {
SymMatrix res(a);
res += b;
return res;
}
template
__device__ __host__ SymMatrix
operator-(const StaticSymMatrix& a,
const StaticSymMatrix& b) {
SymMatrix res(a);
res -= b;
return res;
}
template
__device__ __host__ SymMatrix
operator-(const StaticSymMatrix& a) {
SymMatrix res(a);
res *= -1;
return res;
}
template ::value>>
Vector operator*(const StaticVector& a,
const T& b) {
Vector res{a};
res *= b;
return res;
}
// symmetry
template ::value>>
Vector operator*(const T& b,
const StaticVector& a) {
return a * b;
}
template ::value>>
Matrix
operator*(const StaticMatrix& a, const T& b) {
Matrix res{a};
res *= b;
return res;
}
// symmetry
template ::value, void>>
Matrix
operator*(const T& b, const StaticMatrix& a) {
return a * b;
}
template ::value>>
SymMatrix
operator*(const StaticSymMatrix& a, const T& b) {
SymMatrix res{a};
res *= b;
return res;
}
// symmetry
template