SpECTRE  v2024.05.11
Tensor Expressions

Namespaces

namespace  tenex
 
namespace  ti
 Contains definitions for the available TensorIndexs to use in a TensorExpression
 

Classes

struct  tenex::AddSub< T1, T2, ArgsList1, ArgsList2, Sign >
 Defines the tensor expression representing the addition or subtraction of two tensor expressions. More...
 
struct  tenex::TensorContract< T, X, Symm, IndexList, ArgsList, NumContractedIndices >
 
struct  tenex::Divide< T1, T2, Args2 >
 Defines the tensor expression representing the quotient of one tensor expression divided by another tensor expression that evaluates to a rank 0 tensor. More...
 
struct  tenex::LhsTensorSymmAndIndices< RhsTensorIndexList, LhsTensorIndexList, RhsSymmetry, RhsTensorIndexTypeList, NumLhsIndices, NumRhsIndices, LhsIndexSequence >
 Determines and stores a LHS tensor's symmetry and index list from a RHS tensor expression and desired LHS index order. More...
 
struct  tenex::Negate< T >
 Defines the tensor expression representing the negation of a tensor expression. More...
 
struct  tenex::MarkAsNumberAsExpression
 Marks a class as being a NumberAsExpression<DataType> More...
 
struct  tenex::NumberAsExpression< DataType >
 Defines an expression representing a number. More...
 
struct  tenex::OuterProduct< T1, T2, IndexList1, IndexList2, ArgsList1, ArgsList2 >
 Defines the tensor expression representing the outer product of two tensor expressions. More...
 
struct  tenex::SquareRoot< T, Args >
 Defines the tensor expression representing the square root of a tensor expression that evaluates to a rank 0 tensor. More...
 
struct  tenex::TensorAsExpression< T, ArgsList >
 Defines an expression representing a Tensor. More...
 
struct  Expression
 Marks a class as being a TensorExpression. More...
 
struct  TensorExpression< Derived, DataType, Symm, tmpl::list< Indices... >, ArgsList< Args... > >
 The base class all tensor expression implementations derive from. More...
 
struct  TensorIndex< I, >
 Represents the geeric indices in a TensorExpression. More...
 
struct  tt::is_tensor_index< T >
 Check if a type T is a TensorIndex used in TensorExpressions. More...
 
struct  tenex::tensorindex_list_is_valid< TensorIndexList >
 Determine whether or not a given list of TensorIndexs is valid to be used with a tensor. More...
 
struct  tt::is_time_index< T >
 Check if a type T is a TensorIndex representing a concrete time index. More...
 
struct  MarkAsVectorImpl
 Marks a class as being a VectorImpl More...
 

Typedefs

template<typename TensorIndexList1 , typename TensorIndexList2 >
using tenex::generic_indices_at_same_positions = typename detail::generic_indices_at_same_positions_impl< TensorIndexList1, TensorIndexList2, tmpl::size< TensorIndexList1 >::value==tmpl::size< TensorIndexList2 >::value >::type
 Determine whether or not two lists of TensorIndexs contain the same generic indices at the same positions. More...
 
template<auto &... TensorIndices>
using make_tensorindex_list = typename tenex::detail::make_tensorindex_list_impl< TensorIndices... >::type
 Creates a TensorIndex type list from a list of TensorIndex objects. More...
 

Functions

template<typename T1 , typename T2 , typename X1 , typename X2 , typename Symm1 , typename Symm2 , typename IndexList1 , typename IndexList2 , typename Args1 , typename Args2 >
auto operator+ (const TensorExpression< T1, X1, Symm1, IndexList1, Args1 > &t1, const TensorExpression< T2, X2, Symm2, IndexList2, Args2 > &t2)
 
template<typename T1 , typename T2 , typename X1 , typename X2 , typename Symm1 , typename Symm2 , typename IndexList1 , typename IndexList2 , typename Args1 , typename Args2 >
auto operator- (const TensorExpression< T1, X1, Symm1, IndexList1, Args1 > &t1, const TensorExpression< T2, X2, Symm2, IndexList2, Args2 > &t2)
 
template<typename T1 , typename T2 , typename... Args2>
auto operator/ (const TensorExpression< T1, typename T1::type, typename T1::symmetry, typename T1::index_list, typename T1::args_list > &t1, const TensorExpression< T2, typename T2::type, typename T2::symmetry, typename T2::index_list, tmpl::list< Args2... > > &t2)
 Returns the tensor expression representing the quotient of one tensor expression over another tensor expression that evaluates to a rank 0 tensor. More...
 
template<auto &... LhsTensorIndices, typename LhsDataType , typename LhsSymmetry , typename LhsIndexList , typename Derived , typename RhsDataType , typename RhsSymmetry , typename RhsIndexList , typename... RhsTensorIndices>
void tenex::evaluate (const gsl::not_null< Tensor< LhsDataType, LhsSymmetry, LhsIndexList > * > lhs_tensor, const TensorExpression< Derived, RhsDataType, RhsSymmetry, RhsIndexList, tmpl::list< RhsTensorIndices... > > &rhs_tensorexpression)
 Assign the result of a RHS tensor expression to a tensor with the LHS index order set in the template parameters. More...
 
template<auto &... LhsTensorIndices, typename RhsTE , Requires< std::is_base_of_v< Expression, RhsTE > > = nullptr>
auto tenex::evaluate (const RhsTE &rhs_tensorexpression)
 Assign the result of a RHS tensor expression to a tensor with the LHS index order set in the template parameters. More...
 
template<auto &... LhsTensorIndices, typename LhsDataType , typename RhsDataType , typename LhsSymmetry , typename LhsIndexList , typename Derived , typename RhsSymmetry , typename RhsIndexList , typename... RhsTensorIndices>
void tenex::update (const gsl::not_null< Tensor< LhsDataType, LhsSymmetry, LhsIndexList > * > lhs_tensor, const TensorExpression< Derived, RhsDataType, RhsSymmetry, RhsIndexList, tmpl::list< RhsTensorIndices... > > &rhs_tensorexpression)
 If the LHS tensor is used in the RHS expression, this should be used to assign a LHS tensor to the result of a RHS tensor expression that contains it. More...
 
template<typename T >
auto operator- (const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t)
 Returns the tensor expression representing the negation of a tensor expression. More...
 
template<typename T1 , typename T2 , typename ArgsList1 , typename ArgsList2 >
auto operator* (const TensorExpression< T1, typename T1::type, typename T1::symmetry, typename T1::index_list, ArgsList1 > &t1, const TensorExpression< T2, typename T2::type, typename T2::symmetry, typename T2::index_list, ArgsList2 > &t2)
 Returns the tensor expression representing the product of two tensor expressions. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args>
auto sqrt (const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t)
 Returns the tensor expression representing the square root of a tensor expression that evaluates to a rank 0 tensor. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator+ (const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t, const N number)
 Returns the tensor expression representing the sum of a tensor expression and a number. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator+ (const N number, const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t)
 Returns the tensor expression representing the sum of a tensor expression and a number. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator+ (const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t, const std::complex< N > &number)
 Returns the tensor expression representing the sum of a tensor expression and a number. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator+ (const std::complex< N > &number, const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t)
 Returns the tensor expression representing the sum of a tensor expression and a number. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator- (const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t, const N number)
 Returns the tensor expression representing the difference of a tensor expression and a number. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator- (const N number, const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t)
 Returns the tensor expression representing the difference of a tensor expression and a number. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator- (const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t, const std::complex< N > &number)
 Returns the tensor expression representing the difference of a tensor expression and a number. More...
 
template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator- (const std::complex< N > &number, const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &t)
 Returns the tensor expression representing the difference of a tensor expression and a number. More...
 
template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator/ (const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t, const N number)
 Returns the tensor expression representing the quotient of a tensor expression over a number. More...
 
template<typename T , typename N >
auto operator/ (const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t, const std::complex< N > &number)
 Returns the tensor expression representing the quotient of a tensor expression over a number. More...
 
template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator/ (const N number, const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t)
 Returns the tensor expression representing the quotient of a number over a tensor expression that evaluates to a rank 0 tensor. More...
 
template<typename T , typename N >
auto operator/ (const std::complex< N > &number, const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t)
 Returns the tensor expression representing the quotient of a number over a tensor expression that evaluates to a rank 0 tensor. More...
 
template<auto &... LhsTensorIndices, typename X , typename LhsSymmetry , typename LhsIndexList , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
void tenex::evaluate (const gsl::not_null< Tensor< X, LhsSymmetry, LhsIndexList > * > lhs_tensor, const N rhs_value)
 Assign a number to components of a tensor with the LHS index order set in the template parameters. More...
 
template<auto &... LhsTensorIndices, typename X , typename LhsSymmetry , typename LhsIndexList , typename N >
void tenex::evaluate (const gsl::not_null< Tensor< X, LhsSymmetry, LhsIndexList > * > lhs_tensor, const std::complex< N > &rhs_value)
 Assign a number to components of a tensor with the LHS index order set in the template parameters. More...
 
template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator* (const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t, const N number)
 Returns the tensor expression representing the product of a tensor expression and a number. More...
 
template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator* (const N number, const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t)
 Returns the tensor expression representing the product of a tensor expression and a number. More...
 
template<typename T , typename N >
auto operator* (const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t, const std::complex< N > &number)
 Returns the tensor expression representing the product of a tensor expression and a number. More...
 
template<typename T , typename N >
auto operator* (const std::complex< N > &number, const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &t)
 Returns the tensor expression representing the product of a tensor expression and a number. More...
 

Detailed Description

Tensor Expressions allow writing expressions of tensors in a way similar to what is used with pen and paper.

Tensor expressions are implemented using (smart) expression templates. This allows a domain specific language making expressions such as

auto T = evaluate<Indices::_a_t, Indices::_b_t>(F(Indices::_b,
Indices::_a));

possible.

Typedef Documentation

◆ generic_indices_at_same_positions

template<typename TensorIndexList1 , typename TensorIndexList2 >
using tenex::generic_indices_at_same_positions = typedef typename detail::generic_indices_at_same_positions_impl< TensorIndexList1, TensorIndexList2, tmpl::size<TensorIndexList1>::value == tmpl::size<TensorIndexList2>::value>::type

Determine whether or not two lists of TensorIndexs contain the same generic indices at the same positions.

Template Parameters
TensorIndexList1the first TensorIndex list
TensorIndexList2the second TensorIndex list

◆ make_tensorindex_list

template<auto &... TensorIndices>
using make_tensorindex_list = typename tenex::detail::make_tensorindex_list_impl<TensorIndices...>::type

Creates a TensorIndex type list from a list of TensorIndex objects.

Template Parameters
TensorIndiceslist of generic index objects, e.g. ti::a, ti::b

Function Documentation

◆ evaluate() [1/4]

template<auto &... LhsTensorIndices, typename LhsDataType , typename LhsSymmetry , typename LhsIndexList , typename Derived , typename RhsDataType , typename RhsSymmetry , typename RhsIndexList , typename... RhsTensorIndices>
void tenex::evaluate ( const gsl::not_null< Tensor< LhsDataType, LhsSymmetry, LhsIndexList > * >  lhs_tensor,
const TensorExpression< Derived, RhsDataType, RhsSymmetry, RhsIndexList, tmpl::list< RhsTensorIndices... > > &  rhs_tensorexpression 
)

Assign the result of a RHS tensor expression to a tensor with the LHS index order set in the template parameters.

Details

Uses the right hand side (RHS) TensorExpression's index ordering (RhsTE::args_list) and the desired left hand side (LHS) tensor's index ordering (LhsTensorIndices) to fill the provided LHS Tensor with that LHS index ordering. This can carry out the evaluation of a RHS tensor expression to a LHS tensor with the same index ordering, such as \(L_{ab} = R_{ab}\), or different ordering, such as \(L_{ba} = R_{ab}\).

The symmetry of the provided LHS Tensor need not match the symmetry determined from evaluating the RHS TensorExpression according to its order of operations. This allows one to specify LHS symmetries (via lhs_tensor) that may not be preserved by the RHS expression's order of operations, which depends on how the expression is written and implemented.

The LHS Tensor cannot be part of the RHS expression, e.g. evaluate(make_not_null(&L), L() + R());, because the LHS Tensor will generally not be computed correctly when the RHS TensorExpression is split up and the LHS tensor components are computed by accumulating the result of subtrees (see the section on splitting in the documentation for the TensorExpression class). If you need to use the LHS Tensor on the RHS, use tenex::update instead.

Example usage

Given Tensors R, S, T, G, and H, we can compute the LHS tensor \(L\) in the equation \(L_{a} = R_{ab} S^{b} + G_{a} - H_{ba}{}^{b} T\) by doing:

result_tensor_type actual_result_tensor_filled{};
tenex::evaluate<ti::a>(
make_not_null(&actual_result_tensor_filled),
R(ti::a, ti::b) * S(ti::B) + G(ti::a) - H(ti::b, ti::a, ti::B) * T());
Note
LhsTensorIndices must be passed by reference because non-type template parameters cannot be class types until C++20.
Template Parameters
LhsTensorIndicesthe TensorIndexs of the Tensor on the LHS of the tensor expression, e.g. ti::a, ti::b, ti::c
Parameters
lhs_tensorpointer to the resultant LHS Tensor to fill
rhs_tensorexpressionthe RHS TensorExpression to be evaluated

◆ evaluate() [2/4]

template<auto &... LhsTensorIndices, typename X , typename LhsSymmetry , typename LhsIndexList , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
void tenex::evaluate ( const gsl::not_null< Tensor< X, LhsSymmetry, LhsIndexList > * >  lhs_tensor,
const N  rhs_value 
)

Assign a number to components of a tensor with the LHS index order set in the template parameters.

Details

Example usage:

tnsr::iab<DataType, 3, Frame::Inertial> L_tensor(used_for_size);
make_not_null(&L_tensor);
// \f$L_{itt} = 8.2\f$
tenex::evaluate<ti::i, ti::t, ti::t>(L, 8.2);
// \f$L_{itj} = 2.2\f$
tenex::evaluate<ti::i, ti::t, ti::j>(L, 2.2);
// \f$L_{ijt} = -1.9\f$
tenex::evaluate<ti::i, ti::j, ti::t>(L, -1.9);
// \f$L_{ijk} = -0.5\f$
tenex::evaluate<ti::i, ti::j, ti::k>(L, -0.5);
Definition: ContractFirstNIndices.hpp:16
Require a pointer to not be a nullptr
Definition: Gsl.hpp:183
Note
The components of the LHS Tensor passed in must already be sized because there is no way to infer component size from the RHS
LhsTensorIndices must be passed by reference because non-type template parameters cannot be class types until C++20.
Template Parameters
LhsTensorIndicesthe TensorIndexs of the Tensor on the LHS of the tensor expression, e.g. ti::a, ti::b, ti::c
Parameters
lhs_tensorpointer to the resultant LHS Tensor to fill
rhs_valuethe RHS value to assign

◆ evaluate() [3/4]

template<auto &... LhsTensorIndices, typename X , typename LhsSymmetry , typename LhsIndexList , typename N >
void tenex::evaluate ( const gsl::not_null< Tensor< X, LhsSymmetry, LhsIndexList > * >  lhs_tensor,
const std::complex< N > &  rhs_value 
)

Assign a number to components of a tensor with the LHS index order set in the template parameters.

Details

Example usage:

tnsr::iab<DataType, 3, Frame::Inertial> L_tensor(used_for_size);
make_not_null(&L_tensor);
// \f$L_{itt} = 8.2\f$
tenex::evaluate<ti::i, ti::t, ti::t>(L, 8.2);
// \f$L_{itj} = 2.2\f$
tenex::evaluate<ti::i, ti::t, ti::j>(L, 2.2);
// \f$L_{ijt} = -1.9\f$
tenex::evaluate<ti::i, ti::j, ti::t>(L, -1.9);
// \f$L_{ijk} = -0.5\f$
tenex::evaluate<ti::i, ti::j, ti::k>(L, -0.5);
Note
The components of the LHS Tensor passed in must already be sized because there is no way to infer component size from the RHS
LhsTensorIndices must be passed by reference because non-type template parameters cannot be class types until C++20.
Template Parameters
LhsTensorIndicesthe TensorIndexs of the Tensor on the LHS of the tensor expression, e.g. ti::a, ti::b, ti::c
Parameters
lhs_tensorpointer to the resultant LHS Tensor to fill
rhs_valuethe RHS value to assign

◆ evaluate() [4/4]

template<auto &... LhsTensorIndices, typename RhsTE , Requires< std::is_base_of_v< Expression, RhsTE > > = nullptr>
auto tenex::evaluate ( const RhsTE &  rhs_tensorexpression)

Assign the result of a RHS tensor expression to a tensor with the LHS index order set in the template parameters.

Details

Uses the right hand side (RHS) TensorExpression's index ordering (RhsTE::args_list) and the desired left hand side (LHS) tensor's index ordering (LhsTensorIndices) to construct a LHS Tensor with that LHS index ordering. This can carry out the evaluation of a RHS tensor expression to a LHS tensor with the same index ordering, such as \(L_{ab} = R_{ab}\), or different ordering, such as \(L_{ba} = R_{ab}\).

The symmetry of the returned LHS Tensor depends on the order of operations in the RHS TensorExpression, i.e. how the expression is written. If you would like to specify the symmetry of the LHS Tensor instead of it being determined by the order of operations in the RHS expression, please use the other tenex::evaluate overload that takes an empty LHS Tensor as its first argument.

Example usage

Given Tensors R, S, T, G, and H, we can compute the LHS tensor \(L\) in the equation \(L_{a} = R_{ab} S^{b} + G_{a} - H_{ba}{}^{b} T\) by doing:

result_tensor_type actual_result_tensor_returned = tenex::evaluate<ti::a>(
R(ti::a, ti::b) * S(ti::B) + G(ti::a) - H(ti::b, ti::a, ti::B) * T());
Note
If a generic spatial index is used for a spacetime index in the RHS tensor, its corresponding index in the LHS tensor type will be a spatial index with the same valence, frame, and number of spatial dimensions. If a concrete time index is used for a spacetime index in the RHS tensor, the index will not appear in the LHS tensor (i.e. there will NOT be a corresponding LHS index where only the time index of that index has been computed and its spatial indices are empty).
Note
LhsTensorIndices must be passed by reference because non-type template parameters cannot be class types until C++20.
Template Parameters
LhsTensorIndicesthe TensorIndexs of the Tensor on the LHS of the tensor expression, e.g. ti::a, ti::b, ti::c
Parameters
rhs_tensorexpressionthe RHS TensorExpression to be evaluated

Returns: the resultant LHS Tensor with index order specified by LhsTensorIndices

◆ operator*() [1/5]

template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator* ( const N  number,
const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t 
)

Returns the tensor expression representing the product of a tensor expression and a number.

Parameters
tthe tensor expression operand of the product
numberthe numeric operand of the product

Returns: the tensor expression representing the product of the tensor expression and the number

◆ operator*() [2/5]

template<typename T , typename N >
auto operator* ( const std::complex< N > &  number,
const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t 
)

Returns the tensor expression representing the product of a tensor expression and a number.

Parameters
tthe tensor expression operand of the product
numberthe numeric operand of the product

Returns: the tensor expression representing the product of the tensor expression and the number

◆ operator*() [3/5]

template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator* ( const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t,
const N  number 
)

Returns the tensor expression representing the product of a tensor expression and a number.

Parameters
tthe tensor expression operand of the product
numberthe numeric operand of the product

Returns: the tensor expression representing the product of the tensor expression and the number

◆ operator*() [4/5]

template<typename T , typename N >
auto operator* ( const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t,
const std::complex< N > &  number 
)

Returns the tensor expression representing the product of a tensor expression and a number.

Parameters
tthe tensor expression operand of the product
numberthe numeric operand of the product

Returns: the tensor expression representing the product of the tensor expression and the number

◆ operator*() [5/5]

template<typename T1 , typename T2 , typename ArgsList1 , typename ArgsList2 >
auto operator* ( const TensorExpression< T1, typename T1::type, typename T1::symmetry, typename T1::index_list, ArgsList1 > &  t1,
const TensorExpression< T2, typename T2::type, typename T2::symmetry, typename T2::index_list, ArgsList2 > &  t2 
)

Returns the tensor expression representing the product of two tensor expressions.

Details

If the two operands have N pairs of indices that need to be contracted, the returned expression will be an OuterProduct expression nested inside N TensorContract expressions. This represents computing the inner product of the outer product of the two operands. If the operands do not have any indices to be contracted, the returned expression will be an OuterProduct.

The two arguments are expressions that contain the two operands of the product, where the types of the operands are T1 and T2.

Template Parameters
T1the derived TensorExpression type of the first operand of the product
T2the derived TensorExpression type of the second operand of the product
ArgsList1the TensorIndexs of the first operand
ArgsList2the TensorIndexs of the second operand
Parameters
t1first operand expression of the product
t2the second operand expression of the product

Returns: the tensor expression representing the product of two tensor expressions

◆ operator+() [1/4]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator+ ( const N  number,
const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t 
)

Returns the tensor expression representing the sum of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the sum
numberthe numeric operand of the sum

Returns: the tensor expression representing the sum of the tensor expression and the number

◆ operator+() [2/4]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator+ ( const std::complex< N > &  number,
const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t 
)

Returns the tensor expression representing the sum of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the sum
numberthe numeric operand of the sum

Returns: the tensor expression representing the sum of the tensor expression and the number

◆ operator+() [3/4]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator+ ( const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t,
const N  number 
)

Returns the tensor expression representing the sum of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the sum
numberthe numeric operand of the sum

Returns: the tensor expression representing the sum of the tensor expression and the number

◆ operator+() [4/4]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator+ ( const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t,
const std::complex< N > &  number 
)

Returns the tensor expression representing the sum of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the sum
numberthe numeric operand of the sum

Returns: the tensor expression representing the sum of the tensor expression and the number

◆ operator-() [1/5]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator- ( const N  number,
const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t 
)

Returns the tensor expression representing the difference of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the difference
numberthe numeric operand of the difference

Returns: the tensor expression representing the difference of the tensor expression and the number

◆ operator-() [2/5]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator- ( const std::complex< N > &  number,
const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t 
)

Returns the tensor expression representing the difference of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the difference
numberthe numeric operand of the difference

Returns: the tensor expression representing the difference of the tensor expression and the number

◆ operator-() [3/5]

template<typename T >
auto operator- ( const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t)

Returns the tensor expression representing the negation of a tensor expression.

Parameters
tthe tensor expression

Returns: the tensor expression representing the negation of t

◆ operator-() [4/5]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator- ( const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t,
const N  number 
)

Returns the tensor expression representing the difference of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the difference
numberthe numeric operand of the difference

Returns: the tensor expression representing the difference of the tensor expression and the number

◆ operator-() [5/5]

template<typename T , typename X , typename Symm , typename IndexList , typename... Args, typename N >
auto operator- ( const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t,
const std::complex< N > &  number 
)

Returns the tensor expression representing the difference of a tensor expression and a number.

Details

The tensor expression operand must represent an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that the tensor expression operand could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t)
Parameters
tthe tensor expression operand of the difference
numberthe numeric operand of the difference

Returns: the tensor expression representing the difference of the tensor expression and the number

◆ operator/() [1/5]

template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator/ ( const N  number,
const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t 
)

Returns the tensor expression representing the quotient of a number over a tensor expression that evaluates to a rank 0 tensor.

Parameters
numberthe numeric numerator of the quotient
tthe tensor expression denominator of the quotient

Returns: the tensor expression representing the quotient of the number over the tensor expression

◆ operator/() [2/5]

template<typename T , typename N >
auto operator/ ( const std::complex< N > &  number,
const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t 
)

Returns the tensor expression representing the quotient of a number over a tensor expression that evaluates to a rank 0 tensor.

Parameters
numberthe numeric numerator of the quotient
tthe tensor expression denominator of the quotient

Returns: the tensor expression representing the quotient of the number over the tensor expression

◆ operator/() [3/5]

template<typename T , typename N , Requires< std::is_arithmetic_v< N > > = nullptr>
auto operator/ ( const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t,
const N  number 
)

Returns the tensor expression representing the quotient of a tensor expression over a number.

Note
The implementation instead uses the operation, t * (1.0 / number)
Parameters
tthe tensor expression operand of the quotient
numberthe numeric operand of the quotient

Returns: the tensor expression representing the quotient of the tensor expression over the number

◆ operator/() [4/5]

template<typename T , typename N >
auto operator/ ( const TensorExpression< T, typename T::type, typename T::symmetry, typename T::index_list, typename T::args_list > &  t,
const std::complex< N > &  number 
)

Returns the tensor expression representing the quotient of a tensor expression over a number.

Note
The implementation instead uses the operation, t * (1.0 / number)
Parameters
tthe tensor expression operand of the quotient
numberthe numeric operand of the quotient

Returns: the tensor expression representing the quotient of the tensor expression over the number

◆ operator/() [5/5]

template<typename T1 , typename T2 , typename... Args2>
auto operator/ ( const TensorExpression< T1, typename T1::type, typename T1::symmetry, typename T1::index_list, typename T1::args_list > &  t1,
const TensorExpression< T2, typename T2::type, typename T2::symmetry, typename T2::index_list, tmpl::list< Args2... > > &  t2 
)

Returns the tensor expression representing the quotient of one tensor expression over another tensor expression that evaluates to a rank 0 tensor.

Details

t2 must be an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that t2 could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t) + 1.0
Parameters
t1the tensor expression numerator
t2the rank 0 tensor expression denominator

◆ sqrt()

template<typename T , typename X , typename Symm , typename IndexList , typename... Args>
auto sqrt ( const TensorExpression< T, X, Symm, IndexList, tmpl::list< Args... > > &  t)

Returns the tensor expression representing the square root of a tensor expression that evaluates to a rank 0 tensor.

Details

t must be an expression that, when evaluated, would be a rank 0 tensor. For example, if R and S are Tensors, here is a non-exhaustive list of some of the acceptable forms that t could take:

  • R()
  • R(ti::A, ti::a)
  • (R(ti::A, ti::B) * S(ti::a, ti::b))
  • R(ti::t, ti::t) + 1.0
Parameters
tthe tensor expression of which to take the square root

◆ update()

template<auto &... LhsTensorIndices, typename LhsDataType , typename RhsDataType , typename LhsSymmetry , typename LhsIndexList , typename Derived , typename RhsSymmetry , typename RhsIndexList , typename... RhsTensorIndices>
void tenex::update ( const gsl::not_null< Tensor< LhsDataType, LhsSymmetry, LhsIndexList > * >  lhs_tensor,
const TensorExpression< Derived, RhsDataType, RhsSymmetry, RhsIndexList, tmpl::list< RhsTensorIndices... > > &  rhs_tensorexpression 
)

If the LHS tensor is used in the RHS expression, this should be used to assign a LHS tensor to the result of a RHS tensor expression that contains it.

Details

See documentation for tenex::evaluate for basic functionality.

tenex::update differs from tenex::evaluate in that tenex::update should be used when some LHS Tensor has been partially computed, and now we would like to update it with a RHS expression that contains it. In other words, this should be used when we would like to emulate assignment operations like LHS +=, LHS -=, LHS *=, etc.

One important difference to note with tenex::update is that it cannot split up the RHS expression and evaluate subtrees, while tenex::evaluate can (see TensorExpression documentation). From benchmarking, it was found that the runtime of DataVector expressions scales poorly as we increase the number of operations. For this reason, when the data type held by the tensors in the expression is DataVector, it's best to avoid passing RHS expressions with a large number of operations (e.g. an inner product that sums over many terms).

Example usage

In implementing a large equation with many operations, we can manually break up the equation and evaluate different subexpressions at a time by making one initial call to tenex::evaluate followed by any number of calls to tenex::update that use the LHS tensor in the RHS expression and will compute the rest of the equation:

result_tensor_type actual_result_tensor_filled{};
tenex::evaluate<ti::a, ti::b>(
make_not_null(&actual_result_tensor_filled),
-spacetime_deriv_gauge_function(ti::a, ti::b) -
spacetime_deriv_gauge_function(ti::b, ti::a) -
0.5 * pi_two_normals() * pi(ti::a, ti::b) +
gamma0() *
(normal_spacetime_one_form(ti::a) * gauge_constraint(ti::b) +
normal_spacetime_one_form(ti::b) * gauge_constraint(ti::a)) -
gamma0() * spacetime_metric(ti::a, ti::b) *
normal_dot_gauge_constraint() +
2.0 * christoffel_second_kind(ti::C, ti::a, ti::b) *
gauge_function(ti::c) -
2.0 * pi(ti::a, ti::c) * pi_2_up(ti::b, ti::C));
tenex::update<ti::a, ti::b>(
make_not_null(&actual_result_tensor_filled),
actual_result_tensor_filled(ti::a, ti::b) +
2.0 * phi_1_up(ti::I, ti::a, ti::c) * phi_3_up(ti::i, ti::b, ti::C));
tenex::update<ti::a, ti::b>(
make_not_null(&actual_result_tensor_filled),
actual_result_tensor_filled(ti::a, ti::b) -
2.0 * christoffel_first_kind_3_up(ti::a, ti::d, ti::C) *
christoffel_first_kind_3_up(ti::b, ti::c, ti::D));
tenex::update<ti::a, ti::b>(
make_not_null(&actual_result_tensor_filled),
actual_result_tensor_filled(ti::a, ti::b) -
pi_one_normal(ti::j) * phi_1_up(ti::J, ti::a, ti::b));
tenex::update<ti::a, ti::b>(make_not_null(&actual_result_tensor_filled),
actual_result_tensor_filled(ti::a, ti::b) -
inverse_spatial_metric(ti::J, ti::K) *
d_phi(ti::j, ti::k, ti::a, ti::b));
tenex::update<ti::a, ti::b>(
make_not_null(&actual_result_tensor_filled),
actual_result_tensor_filled(ti::a, ti::b) * lapse() +
gamma1gamma2() * shift_dot_three_index_constraint(ti::a, ti::b) +
shift(ti::J) * d_pi(ti::j, ti::a, ti::b));
void spacetime_metric(gsl::not_null< tnsr::aa< DataType, Dim, Frame > * > spacetime_metric, const Scalar< DataType > &lapse, const tnsr::I< DataType, Dim, Frame > &shift, const tnsr::ii< DataType, Dim, Frame > &spatial_metric)
Computes the spacetime metric from the spatial metric, lapse, and shift.
void pi(gsl::not_null< tnsr::aa< DataType, SpatialDim, Frame > * > pi, const Scalar< DataType > &lapse, const Scalar< DataType > &dt_lapse, const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::I< DataType, SpatialDim, Frame > &dt_shift, const tnsr::ii< DataType, SpatialDim, Frame > &spatial_metric, const tnsr::ii< DataType, SpatialDim, Frame > &dt_spatial_metric, const tnsr::iaa< DataType, SpatialDim, Frame > &phi)
Computes the conjugate momentum of the spacetime metric .
tnsr::I< DataType, SpatialDim, Frame > shift(const tnsr::aa< DataType, SpatialDim, Frame > &spacetime_metric, const tnsr::II< DataType, SpatialDim, Frame > &inverse_spatial_metric)
Compute shift from spacetime metric and inverse spatial metric.
void christoffel_second_kind(const gsl::not_null< tnsr::Abb< DataType, SpatialDim, Frame, Index > * > christoffel, const tnsr::abb< DataType, SpatialDim, Frame, Index > &d_metric, const tnsr::AA< DataType, SpatialDim, Frame, Index > &inverse_metric)
Computes Christoffel symbol of the second kind from derivative of metric and the inverse metric.
Scalar< DataType > lapse(const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::aa< DataType, SpatialDim, Frame > &spacetime_metric)
Compute lapse from shift and spacetime metric.
Note
LhsTensorIndices must be passed by reference because non-type template parameters cannot be class types until C++20.
Template Parameters
LhsTensorIndicesthe TensorIndexs of the Tensor on the LHS of the tensor expression, e.g. ti_a, ti_b, ti_c
Parameters
lhs_tensorpointer to the resultant LHS Tensor to fill
rhs_tensorexpressionthe RHS TensorExpression to be evaluated