Tensor definitions supporting several GMat models.
- Getting started: this readme.
- Documentation: https://tdegeus.github.io/GMatTensor
This library is free to use under the MIT license. Any additions are very much appreciated, in terms of suggested functionality, code, documentation, testimonials, word-of-mouth advertisement, etc. Bug reports or feature requests can be filed on GitHub. As always, the code comes with no guarantee. None of the developers can be held responsible for possible mistakes.
Download: .zip file | .tar.gz file.
(c - MIT) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GMatTensor
This library implements for a Cartesian coordinate frame in 2d or in 3d:
- Second (
I2
) and fourth (I4
) order null tensors:- 0ik =
02
ij Ajk - 0ij =
04
ijkl Alk
- 0ik =
- Second (
I2
) and fourth (I4
) order unit tensors:- Aik =
I2
ij Ajk - Aij =
I4
ijkl Alk
- Aik =
- Fourth order projection tensors: symmetric, deviatoric, right- and left-transposed:
- tr(A) =
I2
ij Aji - dev(A) =
I4d
ijkl Alk - sym(A) =
I4s
ijkl Alk - transpose(A) =
I4rt
ijkl Alk
- tr(A) =
For convenience also find:
- Second (
I2
) and fourth (I4
) order random tensors, with each component drawn from a normal distribution.
In addition it provides an Array<rank>
of unit tensors.
Suppose that the array is rank three, with shape (R, S, T), then the output is:
- Second order tensors: (R, S, T, d, d), with
d
the number of dimensions (2 or 3). - Fourth order tensors: (R, S, T, d, d, d, d).
E.g.
auto A = GMatTensor::Array<3>({4, 5, 6}).O2();
auto A = GMatTensor::Array<3>({4, 5, 6}).O4();
auto A = GMatTensor::Array<3>({4, 5, 6}).I2();
auto A = GMatTensor::Array<3>({4, 5, 6}).I4();
auto A = GMatTensor::Array<3>({4, 5, 6}).II();
auto A = GMatTensor::Array<3>({4, 5, 6}).I4d();
auto A = GMatTensor::Array<3>({4, 5, 6}).I4s();
auto A = GMatTensor::Array<3>({4, 5, 6}).I4rt();
auto A = GMatTensor::Array<3>({4, 5, 6}).I4lt();
Given that the arrays are row-major, the tensors or each array component are thus stored contiguously in the memory. This is heavily used to expose all operations below to nd-arrays of tensors. In particular, all operations are available on raw pointers to a tensor, or for nd-arrays of (x)tensors (include a 'plain' tensor with array rank 0).
- Input: 2nd-order tensor (e.g.
(R, S, T, d, d)
). Returns: scalar (e.g.(R, S, T)
).- tr(A) =
Trace(A)
- tr(A) / d =
Hydrostatic(A)
- det(A) =
Det(A)
- Aij Bji = A : B =
A2_ddot_B2(A, B)
- Aij Bji = A : B =
A2s_ddot_B2s(A, B)
(both tensors assumed symmetric, no assertion). - dev(A)ij dev(A)ji =
Norm_deviatoric(A)
- tr(A) =
- Input: 2nd-order tensor (e.g.
(R, S, T, d, d)
). Returns: 2nd-order tensor (e.g.(R, S, T, d, d)
).- dev(A) =
A
-Hydrostatic(A)
*I2
- dev(A) =
Deviatoric(A)
- sym(A) =
Sym(A)
- A-1 =
Inv(A)
- log(A) =
Logs(A)
(tensor assumed symmetric, no assertion). - Cik Aij Akj = A . AT
=
A2_dot_A2T(A, B)
- Cik Aij Bjk = A . B =
A2_dot_B2(A, B)
- Cij Aijkl Blk = A : B =
A4_ddot_B2(A, B)
- dev(A) =
- Input: 2nd-order tensor (e.g.
(R, S, T, d, d)
) or 4th-order tensor (e.g.(R, S, T, d, d, d)
). Returns: 4th-order tensor (e.g.(R, S, T, d, d, d)
).- Cijkl Aij Bkl = A * B =
A2_dyadic_B2(A, B)
- Cijkm Aijkl Blm = A . B =
A4_dot_B2(A, B)
- Cijkl Aij Bkl = A * B =
Note that the output has:
- In the case of an input tensor
(d, d)
the output can be a rank-zero matrix. To get a scalar do e.g.Hydrostatic(A)()
.
Furthermore note that:
- Functions whose name starts with a capital letter allocate and return their output.
- Functions whose name starts with a small letter require their output as final input parameter(s), which is changed in-place.
A semi-public API exists that is mostly aimed to support GMat implementation. These involve pure-tensor operations based the input (and the output) as a pointer, using the following storage convention:
- Cartesian2d: (xx, xy, yx, yy).
- Cartesian3d: (xx, xy, xz, yx, yy, yz, zx, zy, zz).
This part of the API does not support arrays of tensors. In addition to the pointer equivalent (or in fact core) of the above function, the following functions are available:
Hydrostatic_deviatoric
: Return the hydrostatic part of a tensor, and write the deviatoric part to a pointer.A4_ddot_B4_ddot_C4
: A : B : CA2_dot_B2_dot_C2T
: A . B . CTeigs
: Compute the eigen values and eigen vectors for a symmetric 2nd order tensor (no assertion on symmetry).from_eigs
: The reverse operation fromeigs
, for a symmetric 2nd order tensor (no assertion on symmetry).
The code is a C++ header-only library (see installation notes), but a Python module is also provided (see installation notes). The interfaces are identical except:
- All xtensor objects (
xt::xtensor<...>
) are NumPy arrays in Python. Overloading based on rank is also available in Python. - The Python module cannot change output objects in-place: only functions whose name starts with a capital letter are included, see below.
- All
::
in C++ are.
in Python.
conda install -c conda-forge gmattensor
# Download GMatTensor
git checkout https://github.com/tdegeus/GMatTensor.git
cd GMatTensor
# Install headers, CMake and pkg-config support
cmake -Bbuild .
cd build
make install
conda install -c conda-forge python-gmattensor
Note that xsimd and hardware optimisation are not enabled. To enable them you have to compile on your system, as is discussed next.
You need xtensor, xtensor-python and optionally xsimd as prerequisites. In addition scikit-build is needed to control the build from Python. The easiest is to use conda to get the prerequisites:
conda install -c conda-forge xtensor-python conda install -c conda-forge xsimd conda install -c conda-forge scikit-buildIf you then compile and install with the same environment you should be good to go. Otherwise, a bit of manual labour might be needed to treat the dependencies.
# Download GMatTensor
git checkout https://github.com/tdegeus/GMatTensor.git
cd GMatTensor
# Only if you want to use hardware optization:
export CMAKE_ARGS="-DUSE_SIMD=1"
# Compile and install the Python module
# (-vv can be omitted as is controls just the verbosity)
python setup.py install --build-type Release -vv
# OR, Compile and install the Python module with hardware optimisation
# (with scikit-build CMake options can just be added as command-line arguments)
python setup.py install --build-type Release -DUSE_SIMDD=1 -vv
Using GMatTensor your CMakeLists.txt
can be as follows
cmake_minimum_required(VERSION 3.1)
project(example)
find_package(GMatTensor REQUIRED)
add_executable(example example.cpp)
target_link_libraries(example PRIVATE GMatTensor)
The following targets are available:
-
GMatTensor
Includes GMatTensor and the xtensor dependency. -
GMatTensor::assert
Enables assertions by definingGMATTENSOR_ENABLE_ASSERT
. -
GMatTensor::debug
Enables all assertions by definingGMATTENSOR_ENABLE_ASSERT
andXTENSOR_ENABLE_ASSERT
. -
GMatTensor::compiler_warings
Enables compiler warnings (generic).
It is advised to think about compiler optimisation and enabling xsimd.
Using CMake this can be done using the xtensor::optimize
and xtensor::use_xsimd
targets.
The above example then becomes:
cmake_minimum_required(VERSION 3.1)
project(example)
find_package(GMatTensor REQUIRED)
find_package(xtensor REQUIRED)
find_package(xsimd REQUIRED)
add_executable(example example.cpp)
target_link_libraries(example PRIVATE GMatTensor xtensor::optimize xtensor::use_xsimd)
See the documentation of xtensor concerning optimisation.
Presuming that the compiler is c++
, compile using:
c++ -I/path/to/GMatTensor/include ...
Note that you have to take care of the xtensor dependency, the C++ version, optimisation, enabling xsimd, ...
Presuming that the compiler is c++
, compile using:
c++ `pkg-config --cflags GMatTensor` ...
Note that you have to take care of the xtensor dependency, the C++ version, optimization, enabling xsimd, ...
- Extra functions to get version information
- [python] Array: unit tensors -> properties
- Updating Catch2
- Type alias
xt::xtensor
: allows full API to usext::pytensor
(#44) - [BREAKING CHANGE] Python:
shape*
: function -> property (#44) - [BREAKING CHANGE] Remove view_tensor* (re-rolls #41) (#44)
- [docs] Adding update script
- [BREAKING CHANGE] Moving "allocate" to public namespace (#42)
- Array of tensors: returning underlying shape/size (#43)
- Array: adding function to 'view' a tensor (rank 2 or 4) (#41)
- auto-format (#40)
- [Python] Adding 0d array
- Switching to scikit-build (#37)
- Allow xsimd from setup.py using
CMAKE_ARGS
(#36)
- Adding cross-compilation features (#35)
- Updating doxystyle
- Removing xtensor-python work-around
- Bugfix: type recognition for xtensor-fixed.
- Using xtensor-python to speed-up Python API, and to allow in-place output.
- [CI] Using micromamba for efficiency.
- [CI] Fixing typos
- [docs] Minor updates
- [docs] Using dark-style documentation
- [CMake] Simplifying implementation
- [Python] Reducing deps
- Minor reorganization
- [docs] Adding doxygen docs published on GitHub pages.
- [docs] Minor readme updates.
- [CMake] Small tweaks.
- [CMake] Relaxing C++17 requirement.
- Using setuptools_scm for versioning.
- Extending tests.
- Added
Sym
. - Added
A2_dot_B2
to Cartesian2d. - API change: all functions that return output, including scalars, now start with a capital letter.
- Updated readme.
- Adding "logs".
- Unit tensors: now all using pointer API.
- Porting all public APIs to array of tensors.
- Pointer API: less aggressive templating.
- API change: Renaming "equivalent_deviatioric" -> "norm_deviatoric".
- Introducing null tensors
GMatTensor::Cartesian3d::O2
andGMatTensor::Cartesian3d::O4
(also for Cartesian2d). - Adding several new tensor operations / products.
- Adding more public xtensor interface for tensor products. The aim is mostly to allow the user to be quick and dirty, e.g. when testing.
- Formatting tests with the latter new API.
- Relaxing assumption on symmetry for dev(A) : dev(A).
- Adding symmetric only function
A2s_ddot_B2s
to pointer API.
Pointer API
- Making pointer explicit (template
T
->T*
). - Adding zero and unit tensors.
- Add dyadic product between two second order tensors.
- Adding stride members to
Array
.
- Improved sub-classing support
Transfer from other libraries.