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
|