7#ifndef DUNE_FUFEM_FORMS_TENSORS_HH
8#define DUNE_FUFEM_FORMS_TENSORS_HH
23namespace Dune::Fufem::Forms::Impl::Tensor {
40 template<
class T, std::
size_t k>
45 static decltype(
auto) resolveIndices(
auto&& t)
50 static decltype(
auto) resolveIndices(
auto&& t,
const auto& i0,
const auto&... i)
52 return resolveIndices(t[i0], i...);
55 template<
class I, I... i>
58 return resolveIndices(t, i...);
74 decltype(
auto)
operator()(
const auto&... i)
const
76 return resolveIndices(t_, i...);
80 template<
class T, std::
size_t k>
87 template<
class T, std::
size_t k>
95 using value_type =
typename T::value_type;
106 template<
class I0,
class... I>
108 decltype(
auto)
operator()(
const I0& i0,
const I&... i)
const
113 template<
class I0,
class I1,
class... I>
115 decltype(
auto)
operator()(
const I0& i0,
const I1& i1,
const I&... i)
const
121 template<
class T, std::
size_t k>
128 template<
class T, std::
size_t k>
135 using value_type =
typename RawT::value_type;
146 template<
class I0,
class... I>
148 decltype(
auto)
operator()(
const I0& i0,
const I&... i)
const
153 template<
class I0,
class I1,
class... I>
155 decltype(
auto)
operator()(
const I0& i0,
const I1& i1,
const I&... i)
const
161 template<
class T, std::
size_t k>
167 template<
class Value>
172 using value_type = Value;
179 RankZeroTensor(Value value)
184 friend void sparseForEach(
const RankZeroTensor& tensor, F&& f)
189 template<
class Outer>
190 friend auto compose(
const Outer& outer,
const RankZeroTensor& inner)
192 return Dune::Fufem::Forms::Impl::Tensor::RankZeroTensor(outer(inner()));
210 template<
class Value>
216 template<std::
size_t r,
class Value,
class ForEach>
234 friend void sparseForEach(
const SparseTensor& tensor, F&& f)
239 template<
class Outer>
240 friend auto compose(
const Outer& outer,
const SparseTensor& inner)
243 return Dune::Fufem::Forms::Impl::Tensor::SparseTensor(
245 [outer, innerForEach=inner.forEach_](
auto&& f) {
246 innerForEach([&](const auto& y_i, auto... i) {
265 template<std::
size_t r,
class Value,
class ForEach>
266 struct IsTensor<SparseTensor<r, Value, ForEach>> :
public std::true_type
269 template<std::
size_t r,
class Value,
class ForEach>
275 template<
class Product,
class T0,
class T1>
276 class SparseProductTensor
287 SparseProductTensor(Product product, T0 t0, T1 t1)
294 friend void sparseForEach(
const SparseProductTensor& tensor, F&& f)
297 if constexpr(T0::rank() == 0)
298 sparseForEach(tensor.t1_, [&](
const auto& x1_j,
auto... j) {
299 f(tensor.product_(tensor.t0_(), x1_j), j...);
301 else if constexpr(T1::rank() == 0)
302 sparseForEach(tensor.t0_, [&](
const auto& x0_i,
auto... i) {
303 f(tensor.product_(x0_i, tensor.t1_()), i...);
305 else if constexpr((T0::rank() == 2) and (T1::rank() == 2))
306 sparseForEach(tensor.t0_, [&](
const auto& x0_i,
auto i0,
auto i1) {
307 sparseForEach(tensor.t1_, [&](const auto& x1_j, auto j0, auto j1) {
308 f(tensor.product_(x0_i, x1_j), i0, j0, i1, j1);
313 template<
class Outer>
314 friend auto compose(
const Outer& outer,
const SparseProductTensor& inner)
317 return Dune::Fufem::Forms::Impl::Tensor::SparseProductTensor(
318 [outer, innerProduct=inner.product()](
const auto&... args) { return outer(innerProduct(args...)); },
326 return t0_.nnz() * t1_.nnz();
335 template<std::
size_t k>
340 else if constexpr(k==1)
350 template<
class Product,
class T0,
class T1>
351 struct IsTensor<SparseProductTensor<Product, T0, T1>> :
public std::true_type
354 template<
class Product,
class T0,
class T1>
355 struct IsLazyTensor<SparseProductTensor<Product, T0, T1>> :
public std::true_type
360 template<
class Product,
class X,
class Y>
361 requires (IsTensor<X>::value and IsTensor<Y>::value)
362 auto interleavedOuterProduct(Product product,
const X& x,
const Y& y)
365 if constexpr((X::rank() == 0) and (Y::rank() == 0))
366 return RankZeroTensor(
product(x(), y()));
368 return SparseProductTensor(product, x, y);
373 template<
class K, std::
size_t rank,
class Value,
class ForEach,
class Y>
376 and IsTensor<Y>::value
377 and (rank == Y::rank())
379 void axpy(
const K&
alpha,
const SparseTensor<rank, Value, ForEach>& x, Y& y)
381 sparseForEach(x, [&](
const auto& xi,
auto...i) {
386 template<
class K,
class Product,
class T0,
class T1,
class Y>
389 and IsTensor<Y>::value
390 and (SparseProductTensor<Product, T0, T1>::rank() == Y::rank())
392 void axpy(
const K&
alpha,
const SparseProductTensor<Product, T0, T1>& x, Y& y)
398 if constexpr(T0::rank() == 0)
399 sparseForEach(x.factor(_1), [&](
const auto& x1_j,
auto... j) {
402 else if constexpr(T1::rank() == 0)
403 sparseForEach(x.factor(_0), [&](
const auto& x0_i,
auto... i) {
406 else if constexpr((T0::rank() == 2) and (T1::rank() == 2))
407 sparseForEach(x.factor(_0), [&](
const auto& x0_i,
auto i0,
auto i1) {
408 auto x0_i_alpha = mult(x0_i,alpha);
409 sparseForEach(x.factor(_1), [&](const auto& x1_j, auto j0, auto j1) {
410 y(i0, j0, i1, j1) += Dune::Fufem::asNumber(x.product()(x0_i_alpha, x1_j));
414 static_assert((T0::rank() == 2) and (T1::rank() == 2));
void axpy(const Ta &a, const type &y)
auto operator()(T &&t) -> decltype(this->apply(t, std::index_sequence_for< Args... >{})) const
constexpr void forEach(Range &&range, F &&f)
constexpr T & resolveRef(T &gf) noexcept
virtual void operator()()=0
const T & asNumber(const T &t)
Forward given value as number.
Definition asnumber.hh:23