Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : #include <limits> 9 : 10 : #include "DataStructures/Tensor/Expressions/DataTypeSupport.hpp" 11 : #include "DataStructures/Tensor/Expressions/TensorExpression.hpp" 12 : #include "Utilities/ForceInline.hpp" 13 : #include "Utilities/TMPL.hpp" 14 : 15 : namespace tenex { 16 : /// \ingroup TensorExpressionsGroup 17 : /// \brief Marks a class as being a `NumberAsExpression<DataType>` 18 : /// 19 : /// \details 20 : /// The empty base class provides a simple means for checking if a type is a 21 : /// `NumberAsExpression<DataType>`. 22 1 : struct MarkAsNumberAsExpression {}; 23 : 24 : /// \ingroup TensorExpressionsGroup 25 : /// \brief Defines an expression representing a number 26 : /// 27 : /// \details 28 : /// For details on aliases and members defined in this class, as well as general 29 : /// `TensorExpression` terminology used in its members' documentation, see 30 : /// documentation for `TensorExpression`. 31 : template <typename DataType> 32 1 : struct NumberAsExpression 33 : : public TensorExpression<NumberAsExpression<DataType>, DataType, 34 : tmpl::list<>, tmpl::list<>, tmpl::list<>>, 35 : MarkAsNumberAsExpression { 36 : static_assert(detail::is_supported_number_datatype_v<DataType>, 37 : "TensorExpressions currently only support numeric terms whose " 38 : "type is double or std::complex<double>. It is possible to add " 39 : "support for more numeric types."); 40 : 41 : // === Index properties === 42 : /// The type of the data being stored in the result of the expression 43 1 : using type = DataType; 44 : /// The list of \ref SpacetimeIndex "TensorIndexType"s of the result of the 45 : /// expression 46 1 : using symmetry = tmpl::list<>; 47 : /// The list of \ref SpacetimeIndex "TensorIndexType"s of the result of the 48 : /// expression 49 1 : using index_list = tmpl::list<>; 50 : /// The list of generic `TensorIndex`s of the result of the expression 51 1 : using args_list = tmpl::list<>; 52 : /// The number of tensor indices in the result of the expression 53 1 : static constexpr auto num_tensor_indices = 0; 54 : 55 : // === Expression subtree properties === 56 : /// The number of arithmetic tensor operations done in the subtree for the 57 : /// left operand, which is 0 because this is a leaf expression 58 1 : static constexpr size_t num_ops_left_child = 0; 59 : /// The number of arithmetic tensor operations done in the subtree for the 60 : /// right operand, which is 0 because this is a leaf expression 61 1 : static constexpr size_t num_ops_right_child = 0; 62 : /// The total number of arithmetic tensor operations done in this expression's 63 : /// whole subtree, which is 0 because this is a leaf expression 64 1 : static constexpr size_t num_ops_subtree = 0; 65 : /// The height of this expression's node in the expression tree relative to 66 : /// the closest `TensorAsExpression` leaf in its subtree. Because this 67 : /// expression type is leaf, the height for this type is set to the maximum 68 : /// `size_t` value to encode a sense of maximal height. 69 1 : static constexpr size_t height_relative_to_closest_tensor_leaf_in_subtree = 70 : std::numeric_limits<size_t>::max(); 71 : 72 : // === Properties for splitting up subexpressions along the primary path === 73 : // These definitions only have meaning if this expression actually ends up 74 : // being along the primary path that is taken when evaluating the whole tree. 75 : // See documentation for `TensorExpression` for more details. 76 : /// If on the primary path, whether or not the expression is an ending point 77 : /// of a leg 78 1 : static constexpr bool is_primary_end = true; 79 : /// If on the primary path, this is the remaining number of arithmetic tensor 80 : /// operations that need to be done in the subtree of the child along the 81 : /// primary path, given that we will have already computed the whole subtree 82 : /// at the next lowest leg's starting point. This is just 0 because this 83 : /// expression is a leaf. 84 1 : static constexpr size_t num_ops_to_evaluate_primary_left_child = 0; 85 : /// If on the primary path, this is the remaining number of arithmetic tensor 86 : /// operations that need to be done in the right operand's subtree. This is 87 : /// just 0 because this expression is a leaf. 88 1 : static constexpr size_t num_ops_to_evaluate_primary_right_child = 0; 89 : /// If on the primary path, this is the remaining number of arithmetic tensor 90 : /// operations that need to be done for this expression's subtree, given that 91 : /// we will have already computed the subtree at the next lowest leg's 92 : /// starting point. This is just 0 because this expression is a leaf. 93 1 : static constexpr size_t num_ops_to_evaluate_primary_subtree = 0; 94 : /// If on the primary path, whether or not the expression is a starting point 95 : /// of a leg 96 1 : static constexpr bool is_primary_start = false; 97 : /// If on the primary path, whether or not the expression's child along the 98 : /// primary path is a subtree that contains a starting point of a leg along 99 : /// the primary path. This is always falls because this expression is a leaf. 100 1 : static constexpr bool primary_child_subtree_contains_primary_start = false; 101 : /// If on the primary path, whether or not this subtree contains a starting 102 : /// point of a leg along the primary path 103 1 : static constexpr bool primary_subtree_contains_primary_start = 104 : is_primary_start; 105 : 106 0 : NumberAsExpression(const type& number) : number_(number) {} 107 0 : ~NumberAsExpression() override = default; 108 : 109 : // This expression does not represent a tensor, nor does it have any children, 110 : // so we should never need to assert that the LHS `Tensor` is not equal to the 111 : // number stored by this expression 112 : template <typename LhsTensor> 113 0 : void assert_lhs_tensor_not_in_rhs_expression( 114 : const gsl::not_null<LhsTensor*>) const = delete; 115 : // This expression does not represent a tensor, nor does it have any children, 116 : // so we should never need to assert that instances of the LHS Tensor in this 117 : // expression's subtree have the same generic index order 118 : template <typename LhsTensorIndices, typename LhsTensor> 119 0 : void assert_lhs_tensorindices_same_in_rhs( 120 : const gsl::not_null<LhsTensor*> lhs_tensor) const = delete; 121 : // This expression is a non-`Tensor` leaf, so we should never try to get the 122 : // size of a `Tensor` component from this expression. 123 0 : size_t get_rhs_tensor_component_size() const = delete; 124 : 125 : /// \brief Returns the number represented by the expression 126 : /// 127 : /// \return the number represented by this expression 128 : SPECTRE_ALWAYS_INLINE type 129 1 : get(const std::array<size_t, num_tensor_indices>& /*multi_index*/) const { 130 : return number_; 131 : } 132 : 133 : /// \brief Returns the number represented by the expression 134 : /// 135 : /// \return the number represented by this expression 136 : template <typename ResultType> 137 1 : SPECTRE_ALWAYS_INLINE type get_primary( 138 : const ResultType& /*result_component*/, 139 : const std::array<size_t, num_tensor_indices>& /*multi_index*/) const { 140 : return number_; 141 : } 142 : 143 : // This expression is a leaf and therefore will never be the start of a leg 144 : // to evaluate in a split tree, which is enforced by 145 : // `is_primary_start == false`. Therefore, this function should never be 146 : // called on this expression type. 147 : template <typename ResultType> 148 0 : void evaluate_primary_subtree( 149 : ResultType&, 150 : const std::array<size_t, num_tensor_indices>&) const = delete; 151 : 152 : private: 153 : /// Number represented by this expression 154 1 : type number_; 155 : }; 156 : } // namespace tenex