Basic arithmetic¶
Addition¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename std::enable_if_t<tmech::is_tensor_type<typename std::decay<_TensorLHS>::type>::value>* = nullptr, typename std::enable_if_t<tmech::is_tensor_type<typename std::decay<_TensorRHS>::type>::value>* = nullptr>
constexpr autooperator+(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ Addition of two tensors of same rank and dimension
.tmech::tensor<double, 3, 2> a,b,c; a.randn(); b.randn(); c = a + b;
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Right hand side tensor expression.
Subtraction¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename std::enable_if_t<tmech::is_tensor_type<typename std::decay<_TensorLHS>::type>::value>* = nullptr, typename std::enable_if_t<tmech::is_tensor_type<typename std::decay<_TensorRHS>::type>::value>* = nullptr>
constexpr autooperator-(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ Subtraction of two tensors of same rank and dimension.
.tmech::tensor<double, 3, 2> a,b,c; a.randn(); b.randn(); c = a - b;
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Right hand side tensor expression.
Single contraction¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename std::enable_if_t<tmech::is_tensor_type<typename std::decay<_TensorLHS>::type>::value>* = nullptr, typename std::enable_if_t<tmech::is_tensor_type<typename std::decay<_TensorRHS>::type>::value>* = nullptr>
constexpr autooperator*(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ Single contraction of two tensors. Assume that the left hand side tensor is of rank m and the right hand side tensor of rank n. The resulting tensor is of rank m+n-2. The most right index of the left hand side tensor is contracted with the most left index of the right hand tensor
.tmech::tensor<double, 3, 2> a,b,c; a.randn(); b.randn(); c = a * b;
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Right hand side tensor expression.
Scalar update¶
-
template<typename
_Scalar, typename_Tensor, typename, typename>
constexpr autooperator*(_Scalar &&__scalar, _Tensor &&__tensor)¶ Scalar update of a tensor
.tmech::tensor<double, 3, 2> a,b; a.randn(); b = 2.0*a;
- Template Parameters
_Tensor: Tensor object_Scalar: Scalar type. Must be a std::fundamental
- Parameters
__scalar: Scalar__tensor: Tensor expression.
-
template<typename
_Scalar, typename_Tensor, typename std::enable_if<std::is_fundamental<typename std::decay<_Scalar>::type>::value>::type* = nullptr, typename std::enable_if_t<tmech::is_tensor_type<typename std::decay<_Tensor>::type>::value>* = nullptr>
constexpr autooperator/(_Tensor &&__tensor, _Scalar &&__scalar)¶ Tensor division by a scalar
.tmech::tensor<double, 3, 2> a,b; a.randn(); b = a/2.0;
- Template Parameters
_Tensor: Tensor object_Scalar: Scalar type. Must be a std::fundamental
- Parameters
__scalar: Scalar__tensor: Tensor expression.
Basis rearrangement¶
General basis rearrangement¶
-
template<typename
_Sequence, typename_Tensor, typename, typename>
constexpr autotmech::basis_change(_Tensor &&__tensor)¶ General basis rearrangement. Controlled by template parameter _Sequence, which contains the new order of bases.
Self assignment//Basis 1,2,3,4 is swaped to 3,4,1,2. tmech::tensor<double, 3, 4> A, B; A.randn(); B = tmech::basis_change<tmech::sequence<3,4,1,2>>(A); B = tmech::basis_change<tmech::sequence<3,4,1,2>>(A+2*A);
//Basis 1,2,3,4 is swaped to 3,4,1,2. tmech::tensor<double, 3, 4> A; A.randn(); A = tmech::eval(tmech::basis_change<tmech::sequence<3,4,1,2>>(A)); A = tmech::eval(tmech::basis_change<tmech::sequence<3,4,1,2>>(A+2*A));
- Template Parameters
_Sequence: A tmech::sequence<>, which contains the new order of bases_Derived: Tensor object
- Parameters
__tensor: Tensor expression from which the basis rearrangement is to be formed
-
template<typename
_Sequence, typename_Tensor, typename, typename>
constexpr autotmech::basis_change(_Tensor &&__tensor) General basis rearrangement. Controlled by template parameter _Sequence, which contains the new order of bases.
Self assignment//Basis 1,2,3,4 is swaped to 3,4,1,2. tmech::tensor<double, 3, 4> A, B; A.randn(); B = tmech::basis_change<tmech::sequence<3,4,1,2>>(A); B = tmech::basis_change<tmech::sequence<3,4,1,2>>(A+2*A);
//Basis 1,2,3,4 is swaped to 3,4,1,2. tmech::tensor<double, 3, 4> A; A.randn(); A = tmech::eval(tmech::basis_change<tmech::sequence<3,4,1,2>>(A)); A = tmech::eval(tmech::basis_change<tmech::sequence<3,4,1,2>>(A+2*A));
- Template Parameters
_Sequence: A tmech::sequence<>, which contains the new order of bases_Derived: Tensor object
- Parameters
__tensor: Tensor expression from which the basis rearrangement is to be formed
Transposition¶
-
template<typename
_Tensor, typename>
constexpr autotmech::trans(_Tensor &&__tensor)¶ Wrapper function for transposition for a second-order tensor and major transposition of a fourth-order tensor.
The transpose of a second-order tensor in index notation
.\ The transpose of a fourth-order tensor in index notation
.
tmech::tensor<double,3,2> A, B; A.randn(); B = tmech::trans(A);
tmech::tensor<double,3,2> A; A.randn(); A = tmech::eval(tmech::trans(A));
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the transposition is to be formed.
Left basis transposition¶
-
template<typename
_Tensor, typename>
constexpr autotmech::transl(_Tensor &&__tensor)¶ Transposition of the left base a fourth-order tensor
.
tmech::tensor<double,3,4> A, B; A.randn(); B = tmech::transl(A);
tmech::tensor<double,3,4> A; A.randn(); A = tmech::eval(tmech::transl(A));
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the left transpose part is to be formed.
Outer product¶
General outer product¶
-
template<typename
_SequenceLHS, typename_SequenceRHS, typename_TensorLHS, typename_TensorRHS, typename, typename>
constexpr autotmech::outer_product(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ General outer product. Controlled by template parameters _SequenceLHS and _SequenceRHS. Bases contained in sequence _SequenceLHS are used for ordered element acces in __lhs tensor expression. Bases contained in sequence _SequenceRHS are used for ordered element acces in __rhs tensor expression. Both togther peform outer product.
using SeqL = tmech::sequence<1,2>; using SeqR = tmech::sequence<3,4>; //Bases 1,2 of the new tensor C //are given by a and bases 3,4 are //given by b. tmech::tensor<double, 3, 2> a, b; tmech::tensor<double, 3, 4> C; C = tmech::outer_product<SeqL, SeqR>(a,b);
- Template Parameters
_SequenceLHS: Left hand side sequence, which contains numbers of bases to peform the outer product._SequenceRHS: Right hand side sequence, which contains numbers of bases to peform the outer product._TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Reft hand side tensor expression.
Dyadic product¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename, typename>
constexpr autotmech::otimes(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ The dyadic product between a tensor object of order n and a tensor object of order m is a tensor of order m + n. The dyadic product between two first-order tensors is defined as
.tmech::tensor<double,3,2> A, B; tmech::tensor<double,3,4> C{tmech::otimes(A,B)}; tmech::tensor<double,3,6> D{tmech::otimes(C,B)}; tmech::tensor<double,3,8> E{tmech::otimes(C,C)};
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Reft hand side tensor expression.
Lower dyadic product¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename, typename>
constexpr autotmech::otimesl(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ The
product between two second-order tensors is defined as
.tmech::tensor<double,3,2> A, B; tmech::tensor<double,3,4> C{tmech::otimesl(A,B)};
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Reft hand side tensor expression.
Upper dyadic product¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename, typename>
constexpr autotmech::otimesu(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ The
product between two second-order tensors is defined as
.tmech::tensor<double,3,2> A, B; tmech::tensor<double,3,4> C{tmech::otimesu(A,B)};
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Reft hand side tensor expression.
Inner product¶
General inner product¶
-
template<typename
_SequenceLHS, typename_SequenceRHS, typename_TensorLHS, typename_TensorRHS, typename, typename>
constexpr autotmech::inner_product(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ General inner product. Controlled by template parameters _SequenceLHS and _SequenceRHS. Bases contained in sequence _SequenceLHS are contracted with bases contained in sequence _SequenceRHS.
using SeqL = tmech::sequence<3,4>; using SeqR = tmech::sequence<1,2>; //Double contraction of two 4th order tensors tmech::tensor<double, 3, 4> A, B, C; C = tmech::inner_product<SeqL, SeqR>(A,B); //Double contraction of a 4th and a 2th order tensor tmech::tensor<double, 3, 2> a, c; c = tmech::inner_product<SeqL, SeqR>(C,a);
- Template Parameters
_SequenceLHS: Left hand side sequence, which contains the numbers of bases used for contraction._SequenceRHS: Right hand side sequence, which contains the numbers of bases used for contraction._TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Reft hand side tensor expression.
Double contraction¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename, typename>
constexpr autotmech::dcontract(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ A double contraction between two tensors objects contracts the two most right and left indices. The result of a double contraction between a tensor of order n and a tensor of order m is a tensor of order m + n - 4.
tmech::tensor<double,3,4> A; tmech::tensor<double,3,2> B; A.randn(); B.randn(); auto c{tmech::dcontract(A,B)};
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Reft hand side tensor expression.
Fourth contraction¶
-
template<typename
_TensorLHS, typename_TensorRHS, typename, typename>
constexpr autotmech::ddcontract(_TensorLHS &&__tensor_lhs, _TensorRHS &&__tensor_rhs)¶ A fourth contraction between two tensors objects contracts the fourth most right and left indices. The result of a double contraction between a tensor of order n and a tensor of order m is a tensor of order m + n - 8.
tmech::tensor<double,3,4> A; tmech::tensor<double,3,2> B; A.randn(); B.randn(); auto c{tmech::ddcontract(A,B)};
- Template Parameters
_TensorLHS: Left hand side tensor object_TensorRHS: Right hand side tensor object
- Parameters
__tensor_lhs: Left hand side tensor expression.__tensor_rhs: Reft hand side tensor expression.
Invers of a tensor¶
Second order tensors and fourth order tensors with minior-symmetry¶
-
template<typename ...
_Sequences, typename_Tensor, typename>
constexpr autotmech::inv(_Tensor &&__tensor)¶ Inverse of a second- and a fourth-order tensor. The inverse of a second order tensor is defined by
, where
is the second order identity tensor.
tmech::tensor<double, 3, 2> A, B; A.randn(); B = tmech::inv(A);
The inverse of a fourth order tensor depends on the minior-symmetry. Using the following differentiation rule
yields a minior-symmetry in the first and in the second pair of indicies
and
, respectively. In this case the inverse is defined by
.
tmech::tensor<double, 3, 4> A, B; A.randn(); //the sequences are indicating the pairs of minior-symmetry B = tmech::inv<tmech::sequence<1,2>, tmech::sequence<3,4>>(A); // the rule above is the most used one, therefore the following is sufficient. // the correct indicies are set inside the function. B = tmech::inv(A);
Using the following differentiation rule
, yields a minior symmetry in the outer and in the inner pair of indicies
and
, respectively.
tmech::tensor<double, 3, 4> A, B; A.randn(); //the sequences are indicating the pairs of minior-symmetry B = tmech::inv<tmech::sequence<1,4>, tmech::sequence<2,3>>(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the inverse is to be formed.
Fully anisotropic tensors¶
-
template<typename ...
_Sequences, typename_Tensor, typename>
constexpr autotmech::invf(_Tensor &&__tensor)¶ Inverse of a second- and a full anisotropic fourth-order tensor. The inverse of a second order tensor is defined by
, where
is the second order identity tensor. In the case of a second oder tensor the ouput is the same as from the function inv.
tmech::tensor<double, 3, 2> A, B; A.randn(); B = tmech::invf(A); //or B = tmech::inv(A);
This function assumes, that a fourth order tensor has no minior-symmetry and is therefore fully anisotropic. In this case the inverse is defined by
.
tmech::tensor<double, 3, 4> A, B; A.randn(); B = tmech::invf<tmech::sequence<1,2,3,4>>(A); // the rule above is the most used one, therefore the following is sufficient. // the correct indicies are set inside the function. B = tmech::invf(A);
Using other kind of differentiation rules as
must be indicated, due to the internal storage scheme. For example using
.
tmech::tensor<double, 3, 4> A, B; A.randn(); B = tmech::invf<tmech::sequence<1,3,4,2>>(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the inverse is to be formed.
Volumetric and deviatoric parts¶
Volumetric part¶
-
template<typename
_Tensor, typename>
constexpr autotmech::vol(_Tensor &&__tensor)¶ Volumetric part of a second-order tensor
, where
is the dimension.
tmech::tensor<double,3,2> A, B; A.randn(); B = tmech::vol(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the volumetric part is to be formed.
Deviatoric part¶
-
template<typename
_Tensor, typename>
constexpr autotmech::dev(_Tensor &&__tensor)¶ Deviatoric part of a second-order tensor
.
tmech::tensor<double,3,2> A, B; A.randn(); B = tmech::dev(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the deviatoric part is to be formed.
Symmetric and skew-symmetric parts¶
Symmetric part¶
-
template<typename
_Tensor, typename>
constexpr autotmech::sym(_Tensor &&__tensor)¶ Symmetric part of a second-order tensor
.
tmech::tensor<double,3,2> A, B; A.randn(); B = tmech::sym(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the symmetric part is to be formed.
Skew-symmetric part¶
-
template<typename
_Tensor, typename>
constexpr autotmech::skew(_Tensor &&__tensor)¶ Skew-symmetric part of a second-order tensor
.
tmech::tensor<double, 3, 2> A, B; A.randn(); B = tmech::skew(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the skew-symmetric part is to be formed.
Isotropic tensor functions¶
General function¶
-
template<typename
_Function, typename_Tensor, typename>
constexpr autotmech::isotropic_tensor_function(_Tensor &&__tensor)¶ Isotropic tensor function of a symmetric second-order tensor.
struct sqrt{ template<typename T> static constexpr inline auto apply(T const& value){return std::sqrt(value);} template<typename T> static constexpr inline auto derivative(T const& value){return 1./(2.*std::sqrt(value));} }; tmech::tensor<double, 3, 2> A, B; A.randn(); B = tmech::isotropic_tensor_function<sqrt>(A);
- Template Parameters
_Function:_Tensor: Tensor object
- Parameters
__tensor: Tensor expression
Square root¶
-
template<typename
_Tensor, typename>
constexpr autotmech::sqrt(_Tensor &&__tensor)¶ Square root of a positive semi-definite symmetric second-order tensor
. The square is given by spectral decomposition
whereis the number of non repeated eigenvalues
and
is the corresponding eigenbase.
tmech::tensor<double, 3, 2> A, B; A = tmech::sym(tmech::randn<double,3,2>()); B = tmech::sqrt(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression
Exponential map¶
-
template<typename
_Tensor, typename>
constexpr autotmech::exp_sym(_Tensor &&__tensor)¶ Exponential map
of a positive semi-definite symmetric second-order tensor. The exponential map is given by spectral decomposition
whereis the number of non repeated eigenvalues
and
is the corresponding eigenbase.
tmech::tensor<double, 3, 2> A, B; A = tmech::sym(tmech::randn<double,3,2>()); B = tmech::exp_sym(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression
Logarithmic map¶
-
template<typename
_Tensor, typename>
constexpr autotmech::log(_Tensor &&__tensor)¶ Logarithmic map
of a positive semi-definite symmetric second-order tensor. The Logarithmic map is given by spectral decomposition
whereis the number of non repeated eigenvalues
and
is the corresponding eigenbase.
tmech::tensor<double, 3, 2> A, B; A = tmech::sym(tmech::randn<double,3,2>()); B = tmech::log(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression
Positive-negative decomposition¶
General method¶
-
template<typename
_Tensor, typename>
constexpr autotmech::positive_negative_decomposition(_Tensor &&__tensor)¶ Positive and negative decomposition
of a positive semi-definite symmetric second-order tensor is given by spectral decomposition
whereis the number of non repeated eigenvalues
and
is the corresponding eigenbase.
tmech::tensor<double, 3, 2> A, B; A = tmech::sym(tmech::randn<double,3,2>()); auto A_pos_neg = tmech::positive_negative_decomposition(A); auto A_pos = A_pos_neg.positive(); auto A_neg = A_pos_neg.negative();
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression
Only positive part¶
-
template<typename
_Tensor, typename>
constexpr autotmech::positive(_Tensor &&__tensor)¶ The positive part
of a positive semi-definite symmetric second-order tensor is given by spectral decomposition
whereis the number of non repeated eigenvalues
and
is the corresponding eigenbase.
If both partstmech::tensor<double, 3, 2> A, B; A = tmech::sym(tmech::randn<double,3,2>()); B = tmech::positive(A);
and
are needed use
positive_negative_decomposition().- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression
Only negative part¶
-
template<typename
_Tensor, typename>
constexpr autotmech::negative(_Tensor &&__tensor)¶ The negative part
of a positive semi-definite symmetric second-order tensor is given by spectral decomposition
whereis the number of non repeated eigenvalues
and
is the corresponding eigenbase.
If both partstmech::tensor<double, 3, 2> A, B; A = tmech::sym(tmech::randn<double,3,2>()); B = tmech::negative(A);
and
are needed use
positive_negative_decomposition().- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression
Eigen-decomposition¶
-
template<typename
_Tensor, typename>
constexpr autotmech::eigen_decomposition(_Tensor &&__tensor)¶ Eigendecomposition of a positive semi-definite symmetric second-order tensor
whereis the number of non repeated eigenvalues,
are the corresponding eigenvalues,
eigenvectors and
eigenbasen.
Using eigenbases to get the inverse
tmech::tensor<double, 3, 2> A, A_inv; A = tmech::sym(tmech::randn<double,3,2>()); auto A_eig = tmech::eigen_decomposition(A); const auto[eigenvalues, eigenbasis]{A_eig.decompose_eigenbasis()}; const auto idx{A_eig.non_repeated_eigenvalues_index()}; for(std::size_t i{0}; i<A_eig.number_non_repeated_eigenvalues(); ++i){ A_inv += (1.0/eigenvalues[idx[i]])*eigenbasis[idx[i]]; } std::cout<<std::boolalpha<<tmech::almost_equal(tmech::inv(A), A_inv, 5e-7)<<std::endl;
Using eigenvectors to get the inverse
tmech::tensor<double, 3, 2> A, A_inv; A = tmech::sym(tmech::randn<double,3,2>()); auto A_eig = tmech::eigen_decomposition(A); const auto[eigenvalues, eigenvectors]{A_eig.decompose()}; const auto idx{A_eig.non_repeated_eigenvalues_index()}; for(std::size_t i{0}; i<A_eig.number_non_repeated_eigenvalues(); ++i){ A_inv += (1.0/eigenvalues[idx[i]])*tmech::otimes(eigenvectors[idx[i]],eigenvectors[idx[i]]); } std::cout<<std::boolalpha<<tmech::almost_equal(tmech::inv(A), A_inv, 5e-7)<<std::endl;
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression, from which the eigen decomposition is to be computed.
Sign decomposition¶
-
template<typename
_Tensor, typename>
constexpr autotmech::sign(_Tensor &&__tensor, typename std::decay<_Tensor>::type::value_type __eps = 5e-7, std::size_t __max_iter = 10)¶ Sign tensor decomposition of a second-order tensor
The decomposition is based on a Newton iteration as describet here.which converges quadratically tofor any
having no pure imaginary eigenvalues.
tmech::tensor<double, 3, 2> A, B; A.randn(); B = tmech::sign(A);
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression from which the inverse is to be formed.__eps: Tolerance for Newton iteration__max_iter: Maximum of Newton iterations
Polar decomposition¶
-
template<typename
_Tensor, typename>
constexpr autotmech::polar_decomposition(_Tensor &&__tensor, bool const __newton_method, typename std::decay<_Tensor>::type::value_type const __tol, std::size_t const __max_steps)¶ Polar decomposition of a positive semi-definite symmetric second-order tensor
whereis an orthogonal tensor also knwon as the rotation tensor,
and
are symmetric tensors called the right and the left stretch tensor, respectively. This function provides two different method to determine
,
and
. The frist method uses spectral decomposition
.//use the spectral decomposition tmech::tensor<double, 3, 2> F; F.randn(); auto F_polar = tmech::polar_decomposition(F); F = F_polar.R()*F_polar.U(); F = F_polar.V()*F_polar.R();
The second one is based on a Newton iteration
//use the newton iteration tmech::tensor<double, 3, 2> F; F.randn(); auto F_polar = tmech::polar_decomposition(F, // tensor to decompose true, //use newton iteration 5e-7, // tolerance 5 // number of max steps ); F = F_polar.R()*F_polar.U(); F = F_polar.V()*F_polar.R();
The following derivatives are also important
explicit results are given here//use the spectral decomposition tmech::tensor<double, 3, 2> F; F.randn(); auto F_polar = tmech::polar_decomposition(F); auto dR = F_polar.R().derivative(); auto dU = F_polar.U().derivative(); auto dV = F_polar.V().derivative();
- Template Parameters
_Tensor: Tensor object
- Parameters
__tensor: Tensor expression, from which the polar decomposition is to be computed.__newton_method: True if Newton iteration should be used__tol: Tolerance for Newton iteration__max_steps: Maximum number of Newton iterations
Exponential map¶
-
template<typename
_Tensor, typename>
constexpr autotmech::exp(_Tensor &&__tensor)¶ Exponential map of a nonsymmetric second order tensor
.tmech::tensor<double, 3, 2> A{9.064107e-01, -4.649874e-01, 4.431378e-01, 1.557860e+00, 2.493285e-01, -3.458549e-01, 1.747649e+00, -3.824761e-01, -8.110930e-01}; tmech::tensor<double, 3, 2>Aexp{2.333496383103521e+00, -9.424245337660712e-01, 6.174107765089896e-01, 2.458154759604529e+00, 7.615487934000856e-01, 1.403592316302926e-01, 1.701192794766057e+00, -7.849258234991792e-01, 8.233614408596337e-01}; std::cout<<std::boolalpha <<tmech::almost_equal(Aexp, tmech::exp(A), 5e-7)<<std::endl; //check the derivative const auto func_exp = [](auto const& tensor){return tmech::exp(tensor);}; std::cout<<std::boolalpha <<tmech::almost_equal(tmech::num_diff_central<tmech::sequence<1,2,3,4>>(func_exp,A), tmech::exp(A).derivative(), 5e-7)<<std::endl;