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.
Discussion
This MR is an alternative to !1433. Both try to solve the same problem. It needs to be decided which design should be followed in Dune if we want to have tensor data strcutures.