Draft: Add FieldTensor and DynamicTensor containers based on mdarray and a TensorSpan based of mdspan
Summary
This MR brings the dune interface to mdarray and mdspan, by providing a CRTP base class DenseTensor
(similar to DenseMatrix
and DenseVector
) and derived classes DynamicTensor
and FieldTensor
. Additionally, the MR provides a TensorSpan
, i.e. an mdspan-like class with DenseTensor
interface.
Motivation
The Std::mdarray
and Std::mdspan
classes are based on the corresponding std c++ library proposals and implementations. Those are pure container-adapters and container-views. They can be used like they are, but do not provide the usual Dune interfaces as found in DynamicMatrix
and FieldMatrix
, for example. This MR provides these datastructures in the regular Dune::
namespace, to be used by Dune algorithms.
Limitations and Design Decisions
The DynamicTensor
is not (yet) a replacement for DynamicMatrix
and DynamicVector
, but goes in this direction. The FieldTensor
is (unlike the FieldXYZ
classes) not meant to be a container for field types only, but a container for "arbitrary" types (that still have to fulfill some requirements).
Currently the interface provided by DenseTensor
is very minimal. It essentially just provides the nested for rank-2 tensors the operator[i][j][...]
operator,rows()
and cols()
Member functions, and the exists(i0,i1...)
method. Especially, there are no arithmetic operators yet implemented.
A rank-0 tensor behaves like a scalar, i.e., it can be compared against a scalar, and it can be converted implicitly into a scalar. The other dune-ish scalar-specialization is not implemented (i.e. tensors with all extents 1 are not considered a scalar).
DynamicTensor
The DynamicTensor
is a multi-dimensional container with dynamic extents:
template <class Value, std::size_t rank>
class DynamicTensor;
The extents are given in the constructor, plus an optional default value for the entries:
DynamicTensor<double,2> matrix1(10,10);
DynamicTensor<double,2> matrix2(10,10, 42.0);
using E = std::dextents<int,2>;
DynamicTensor<double,2> matrix3(E{2,2}, {{1.0, 2.0}, {3.0,4.0}});
FieldTensor
The FieldTensor
is a multi-dimensional container with static extents:
template <class Value, int... extents>
class FieldTensor;
The extents are given as template parameters, thus don't need to be specified in the constructor. An optional default value for the entries is possible:
FieldTensor<double,10,10> matrix1;
FieldTensor<double,10,10> matrix2(42.0);
FieldTensor<double,2,2> matrix3{{1.0, 1.0}, {3.0, 4.0}}; // constructor with nested initializer list
matrix3[std::array{0,1}] = 42.0; // bracket operator access with array of indices
matrix3(1,0) = 7.0; // round bracket operator
assert(matrix3.cols() == 2); // provide special functions for matrices
assert(matrix3[0].size() == 2); // the operator[] return sub-mdspans
Both containers provide also constructors that take the Std::extents<...>
object as first argument and additionally a constructor with nested initializer lists.