Tensor.hpp
Go to the documentation of this file.
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 /// \file
5 /// Defines classes for Tensor
6 
7 #pragma once
8 
9 #include <cstddef>
10 
11 #include "DataStructures/ComplexDataVector.hpp"
12 #include "DataStructures/ComplexModalVector.hpp"
13 #include "DataStructures/DataVector.hpp"
14 #include "DataStructures/ModalVector.hpp"
15 #include "DataStructures/SpinWeighted.hpp"
21 #include "ErrorHandling/Error.hpp"
22 #include "Parallel/PupStlCpp11.hpp"
24 #include "Utilities/Gsl.hpp"
25 #include "Utilities/MakeArray.hpp"
27 #include "Utilities/PrettyType.hpp"
28 #include "Utilities/Requires.hpp"
29 #include "Utilities/StdHelpers.hpp"
30 #include "Utilities/TMPL.hpp"
31 #include "Utilities/TypeTraits.hpp"
32 
33 /// \cond
34 template <typename X, typename Symm = Symmetry<>,
35  typename IndexList = index_list<>>
36 class Tensor;
37 /// \endcond
38 
39 namespace Tensor_detail {
40 template <typename T, typename = void>
41 struct is_tensor : std::false_type {};
42 template <typename X, typename Symm, typename IndexList>
43 struct is_tensor<Tensor<X, Symm, IndexList>> : std::true_type {};
44 } // namespace Tensor_detail
45 
46 /*!
47  * \ingroup TensorGroup
48  * \brief Represents an object with multiple components
49  *
50  * \details
51  * Tensor is a container that represents indexable geometric objects. Each index
52  * has its own dimension, valence, and frame and must be either spatial or
53  * spacetime. Note that the dimension passed to `SpatialIndex` and
54  * `SpacetimeIndex` is always the spatial dimension of the index. Tensors with
55  * symmetric indices are stored only once and must be of the same
56  * type. A list of available type aliases can be found in the ::tnsr namespace
57  * where the adopted conventions are:
58  *
59  * 1. Upper case for contravariant or upper indices, lower case for covariant or
60  * lower indices.
61  *
62  * 2. `a, b, c, d` are used for spacetime indices while `i, j, k, l` are used
63  * for spatial indices.
64  *
65  * 3. `::Scalar` is not inside the `::tnsr` namespace but is used to represent
66  * a scalar with no indices.
67  *
68  * \example
69  * \snippet Test_Tensor.cpp scalar
70  * \snippet Test_Tensor.cpp spatial_vector
71  * \snippet Test_Tensor.cpp spacetime_vector
72  * \snippet Test_Tensor.cpp rank_3_122
73  *
74  * \tparam X the type held
75  * \tparam Symm the ::Symmetry of the indices
76  * \tparam IndexList a typelist of \ref SpacetimeIndex "TensorIndexType"'s
77  */
78 template <typename X, typename Symm, template <typename...> class IndexList,
79  typename... Indices>
80 class Tensor<X, Symm, IndexList<Indices...>> {
81  static_assert(sizeof...(Indices) < 5,
82  "If you are sure you need rank 5 or higher Tensor's please "
83  "file an issue on GitHub or discuss with a core developer of "
84  "SpECTRE.");
85  static_assert(
87  cpp17::is_same_v<X, double> or
88  cpp17::is_same_v<X, ComplexDataVector> or
89  cpp17::is_same_v<X, ComplexModalVector> or
90  cpp17::is_same_v<X, DataVector> or cpp17::is_same_v<X, ModalVector> or
91  is_spin_weighted_of_v<ComplexDataVector, X> or
92  is_spin_weighted_of_v<ComplexModalVector, X>,
93  "Only a Tensor<std::complex<double>>, Tensor<double>, "
94  "Tensor<ComplexDataVector>, Tensor<ComplexModalVector>, "
95  "Tensor<DataVector>, Tensor<ModalVector>, "
96  "Tensor<SpinWeighted<ComplexDataVector, N>>, "
97  "or Tensor<SpinWeighted<ComplexModalVector, N>> is currently "
98  "allowed. While other types are technically possible it is not "
99  "clear that Tensor is the correct container for them. Please "
100  "seek advice on the topic by discussing with the SpECTRE developers.");
101  /// The Tensor_detail::Structure for the particular tensor index structure
102  ///
103  /// Each tensor index structure, e.g. \f$T_{ab}\f$, \f$T_a{}^b\f$ or
104  /// \f$T^{ab}\f$ has its own Tensor_detail::TensorStructure that holds
105  /// information about how the data is stored, what the multiplicity of the
106  /// stored indices are, the number of (independent) components, etc.
107  using structure = Tensor_detail::Structure<Symm, Indices...>;
108 
109  public:
110  /// The type of the sequence that holds the data
111  using storage_type =
113  /// The type that is stored by the Tensor
114  using type = X;
115  /// Typelist of the symmetry of the Tensor
116  ///
117  /// \details
118  /// For a rank-3 tensor symmetric in the last two indices,
119  /// \f$T_{a(bc)}\f$, the ::Symmetry is `<2, 1, 1>`. For a non-symmetric rank-2
120  /// tensor the ::Symmetry is `<2, 1>`.
121  using symmetry = Symm;
122  /// Typelist of the \ref SpacetimeIndex "TensorIndexType"'s that the
123  /// Tensor has
124  using index_list = tmpl::list<Indices...>;
125  /// The type of the TensorExpression that would represent this Tensor in a
126  /// tensor expression.
127  template <typename ArgsList>
128  using TE = TensorExpression<Tensor<X, Symm, tmpl::list<Indices...>>, X, Symm,
129  tmpl::list<Indices...>, ArgsList>;
130 
131  Tensor() = default;
132  ~Tensor() = default;
133  Tensor(const Tensor&) = default;
134  Tensor(Tensor&&) noexcept = default;
135  Tensor& operator=(const Tensor&) = default;
136  Tensor& operator=(Tensor&&) noexcept = default;
137 
138  /// \cond HIDDEN_SYMBOLS
139  /// Constructor from a TensorExpression.
140  ///
141  /// \tparam LhsIndices the indices on the LHS of the tensor expression
142  /// \tparam T the type of the TensorExpression
143  /// \param tensor_expression the tensor expression being evaluated
144  template <typename... LhsIndices, typename T,
145  Requires<std::is_base_of<Expression, T>::value> = nullptr>
146  Tensor(const T& tensor_expression,
147  tmpl::list<LhsIndices...> /*meta*/) noexcept {
148  static_assert(
149  sizeof...(LhsIndices) == sizeof...(Indices),
150  "When calling evaluate<...>(...) you must pass the same "
151  "number of indices as template parameters as there are free "
152  "indices on the resulting tensor. For example, auto F = "
153  "evaluate<_a_t, _b_t>(G); if G has 2 free indices and you want "
154  "the LHS of the equation to be F_{ab} rather than F_{ba}.");
155  for (size_t i = 0; i < size(); ++i) {
156  gsl::at(data_, i) = tensor_expression.template get<LhsIndices...>(
157  structure::get_canonical_tensor_index(i));
158  }
159  }
160  /// \endcond
161 
162  /// Initialize a vector or scalar from an array
163  ///
164  /// \example
165  /// \snippet Test_Tensor.cpp init_vector
166  /// \param data the values of the individual components of the Vector
167  template <size_t NumberOfIndices = sizeof...(Indices),
168  Requires<(NumberOfIndices <= 1)> = nullptr>
169  explicit Tensor(storage_type data) noexcept;
170 
171  /// Constructor that passes "args" to constructor of X and initializes each
172  /// component to be the same
173  template <typename... Args,
175  Tensor<X, Symm, IndexList<Indices...>>,
176  std::decay_t<Args>>...> and
177  sizeof...(Args) == 1) and
178  cpp17::is_constructible_v<X, Args...>> = nullptr>
179  explicit Tensor(Args&&... args) noexcept;
180 
181  using value_type = typename storage_type::value_type;
182  using reference = typename storage_type::reference;
183  using const_reference = typename storage_type::const_reference;
184  using iterator = typename storage_type::iterator;
185  using const_iterator = typename storage_type::const_iterator;
186  using pointer = typename storage_type::pointer;
187  using const_pointer = typename storage_type::const_pointer;
188  using reverse_iterator = typename storage_type::reverse_iterator;
189  using const_reverse_iterator = typename storage_type::const_reverse_iterator;
190 
191  iterator begin() noexcept { return data_.begin(); }
192  const_iterator begin() const noexcept { return data_.begin(); }
193  const_iterator cbegin() const noexcept { return data_.begin(); }
194 
195  iterator end() noexcept { return data_.end(); }
196  const_iterator end() const noexcept { return data_.end(); }
197  const_iterator cend() const noexcept { return data_.end(); }
198 
199  reverse_iterator rbegin() noexcept { return data_.rbegin(); }
200  const_reverse_iterator rbegin() const noexcept { return data_.rbegin(); }
201  const_reverse_iterator crbegin() const noexcept { return data_.rbegin(); }
202 
203  reverse_iterator rend() noexcept { return data_.rend(); }
204  const_reverse_iterator rend() const noexcept { return data_.rend(); }
205  const_reverse_iterator crend() const noexcept { return data_.rend(); }
206 
207  // @{
208  /// Get data entry using an array representing a tensor index
209  ///
210  /// \details
211  /// Let \f$T_{abc}\f$ be a Tensor.
212  /// Then `get({{0, 2, 1}})` returns the \f$T_{0 2 1}\f$ component.
213  /// \param tensor_index the index at which to get the data
214  template <typename T>
215  SPECTRE_ALWAYS_INLINE constexpr reference get(
216  const std::array<T, sizeof...(Indices)>& tensor_index) noexcept {
217  return gsl::at(data_, structure::get_storage_index(tensor_index));
218  }
219  template <typename T>
220  SPECTRE_ALWAYS_INLINE constexpr const_reference get(
221  const std::array<T, sizeof...(Indices)>& tensor_index) const noexcept {
222  return gsl::at(data_, structure::get_storage_index(tensor_index));
223  }
224  // @}
225  // @{
226  /// Get data entry using a list of integers representing a tensor index
227  ///
228  /// \details
229  /// Let \f$T_{abc}\f$ be a Tensor.
230  /// Then `get(0, 2, 1)` returns the \f$T_{0 2 1}\f$ component.
231  /// \param n the index at which to get the data
232  template <typename... N>
233  constexpr reference get(N... n) noexcept {
234  static_assert(
235  sizeof...(Indices) == sizeof...(N),
236  "the number of tensor indices specified must match the rank of "
237  "the tensor");
238  return gsl::at(data_, structure::get_storage_index(n...));
239  }
240  template <typename... N>
241  constexpr const_reference get(N... n) const noexcept {
242  static_assert(
243  sizeof...(Indices) == sizeof...(N),
244  "the number of tensor indices specified must match the rank of "
245  "the tensor");
246  return gsl::at(data_, structure::get_storage_index(n...));
247  }
248  // @}
249 
250  // @{
251  /// Retrieve the index `N...` by computing the storage index at compile time
252  // clang-tidy: redundant declaration (bug in clang-tidy)
253  template <int... N, typename... Args>
254  friend SPECTRE_ALWAYS_INLINE constexpr typename Tensor<Args...>::reference
255  get(Tensor<Args...>& t) noexcept; // NOLINT
256  // clang-tidy: redundant declaration (bug in clang-tidy)
257  template <int... N, typename... Args>
258  friend SPECTRE_ALWAYS_INLINE constexpr
259  typename Tensor<Args...>::const_reference
260  get(const Tensor<Args...>& t) noexcept; // NOLINT
261  // @}
262 
263  // @{
264  /// Retrieve a TensorExpression object with the index structure passed in
265  template <typename... N,
267  tmpl::is_set<N...>::value> = nullptr>
268  SPECTRE_ALWAYS_INLINE constexpr TE<tmpl::list<N...>> operator()(
269  N... /*meta*/) const noexcept {
270  return TE<tmpl::list<N...>>(*this);
271  }
272 
273  template <typename... N,
275  not tmpl::is_set<N...>::value> = nullptr>
276  SPECTRE_ALWAYS_INLINE constexpr auto operator()(N... /*meta*/) const noexcept
277  -> decltype(
279  TE, replace_indices<tmpl::list<N...>, repeated<tmpl::list<N...>>>,
280  tmpl::int32_t<0>,
281  tmpl::size<repeated<tmpl::list<N...>>>>::apply(*this)) {
282  using args_list = tmpl::list<N...>;
283  using repeated_args_list = repeated<args_list>;
285  TE, replace_indices<args_list, repeated_args_list>, tmpl::int32_t<0>,
286  tmpl::size<repeated_args_list>>::apply(*this);
287  }
288  // @}
289 
290  // @{
291  /// Return i'th component of storage vector
292  constexpr reference operator[](const size_t storage_index) noexcept {
293  return gsl::at(data_, storage_index);
294  }
295  constexpr const_reference operator[](const size_t storage_index) const
296  noexcept {
297  return gsl::at(data_, storage_index);
298  }
299  // @}
300 
301  /// Return the number of independent components of the Tensor
302  ///
303  /// \details
304  /// Returns the number of independent components of the Tensor taking into
305  /// account symmetries. For example, let \f$T_{ab}\f$ be a n-dimensional
306  /// rank-2 symmetric tensor, then the number of independent components is
307  /// \f$n(n+1)/2\f$.
308  SPECTRE_ALWAYS_INLINE static constexpr size_t size() noexcept {
309  return structure::size();
310  }
311 
312  /// Returns the rank of the Tensor
313  ///
314  /// \details
315  /// The rank of a tensor is the number of indices it has. For example, the
316  /// tensor \f$v^a\f$ is rank-1, the tensor \f$\phi\f$ is rank-0, and the
317  /// tensor \f$T_{abc}\f$ is rank-3.
318  SPECTRE_ALWAYS_INLINE static constexpr size_t rank() noexcept {
319  return sizeof...(Indices);
320  }
321 
322  // @{
323  /// Given an iterator or storage index, get the canonical tensor index.
324  /// For scalars this is defined to be std::array<int, 1>{{0}}
325  SPECTRE_ALWAYS_INLINE constexpr std::array<size_t, sizeof...(Indices)>
326  get_tensor_index(const const_iterator& iter) const noexcept {
327  return structure::get_canonical_tensor_index(
328  static_cast<size_t>(iter - begin()));
329  }
330  SPECTRE_ALWAYS_INLINE static constexpr std::array<size_t, sizeof...(Indices)>
331  get_tensor_index(const size_t storage_index) noexcept {
332  return structure::get_canonical_tensor_index(storage_index);
333  }
334  // @}
335 
336  // @{
337  /// Get the storage index of the tensor index. Should only be used when
338  /// optimizing code in which computing the storage index is a bottleneck.
339  template <typename... N>
340  SPECTRE_ALWAYS_INLINE static constexpr size_t get_storage_index(
341  const N... args) noexcept {
342  return structure::get_storage_index(args...);
343  }
344  template <typename I>
345  SPECTRE_ALWAYS_INLINE static constexpr size_t get_storage_index(
346  const std::array<I, sizeof...(Indices)>& tensor_index) noexcept {
347  return structure::get_storage_index(tensor_index);
348  }
349  // @}
350 
351  // @{
352  /// Given an iterator or storage index, get the multiplicity of an index
353  ///
354  /// \see TensorMetafunctions::compute_multiplicity
356  const iterator& iter) const noexcept {
357  return structure::multiplicity(static_cast<size_t>(iter - begin()));
358  }
359  SPECTRE_ALWAYS_INLINE static constexpr size_t multiplicity(
360  const size_t storage_index) noexcept {
361  return structure::multiplicity(storage_index);
362  }
363  // @}
364 
365  // @{
366  /// Get dimensionality of i'th tensor index
367  ///
368  /// \snippet Test_Tensor.cpp index_dim
369  /// \see ::index_dim
370  SPECTRE_ALWAYS_INLINE static constexpr size_t index_dim(
371  const size_t i) noexcept {
372  static_assert(sizeof...(Indices),
373  "A scalar does not have any indices from which you can "
374  "retrieve the dimensionality.");
375  return gsl::at(structure::dims(), i);
376  }
377  // @}
378 
379  //@{
380  /// Return an array corresponding to the ::Symmetry of the Tensor
381  SPECTRE_ALWAYS_INLINE static constexpr std::array<int, sizeof...(Indices)>
382  symmetries() noexcept {
383  return structure::symmetries();
384  }
385  //@}
386 
387  //@{
388  /// Return array of the ::IndexType's (spatial or spacetime)
389  SPECTRE_ALWAYS_INLINE static constexpr std::array<IndexType,
390  sizeof...(Indices)>
391  index_types() noexcept {
392  return structure::index_types();
393  }
394  //@}
395 
396  //@{
397  /// Return array of dimensionality of each index
398  ///
399  /// \snippet Test_Tensor.cpp index_dim
400  /// \see index_dim ::index_dim
401  SPECTRE_ALWAYS_INLINE static constexpr std::array<size_t, sizeof...(Indices)>
402  index_dims() noexcept {
403  return structure::dims();
404  }
405  //@}
406 
407  //@{
408  /// Return array of the valence of each index (::UpLo)
409  SPECTRE_ALWAYS_INLINE static constexpr std::array<UpLo, sizeof...(Indices)>
410  index_valences() noexcept {
411  return structure::index_valences();
412  }
413  //@}
414 
415  //@{
416  /// Returns std::tuple of the ::Frame of each index
417  SPECTRE_ALWAYS_INLINE static constexpr auto index_frames() noexcept {
418  return Tensor_detail::Structure<Symm, Indices...>::index_frames();
419  }
420  //@}
421 
422  //@{
423  /// Given a tensor index, get the canonical label associated with the
424  /// canonical \ref SpacetimeIndex "TensorIndexType"
425  template <typename T = int>
427  const std::array<T, rank()>& tensor_index = std::array<T, rank()>{},
428  const std::array<std::string, rank()>& axis_labels =
429  make_array<rank()>(std::string(""))) noexcept {
430  return structure::component_name(tensor_index, axis_labels);
431  }
432  //@}
433 
434  /// Copy tensor data into an `std::vector<X>` along with the
435  /// component names into a `std::vector<std::string>`
436  /// \requires `std::is_same<X, DataVector>::%value` is true
437  std::pair<std::vector<std::string>, std::vector<X>> get_vector_of_data() const
438  noexcept;
439 
440  /// \cond HIDDEN_SYMBOLS
441  /// Serialization function used by Charm++
442  void pup(PUP::er& p) noexcept { // NOLINT
443  p | data_;
444  }
445  /// \endcond
446 
447  private:
448  // clang-tidy: redundant declaration
449  /// \cond
450  template <int I, class... Ts>
451  friend SPECTRE_ALWAYS_INLINE constexpr size_t index_dim( // NOLINT
452  const Tensor<Ts...>& /*t*/) noexcept;
453  /// \endcond
454 
455  storage_type data_;
456 };
457 
458 // ================================================================
459 // Template Definitions - Variadic templates must be in header
460 // ================================================================
461 
462 template <typename X, typename Symm, template <typename...> class IndexList,
463  typename... Indices>
464 template <size_t NumberOfIndices, Requires<(NumberOfIndices <= 1)>>
465 Tensor<X, Symm, IndexList<Indices...>>::Tensor(storage_type data) noexcept
466  : data_(std::move(data)) {}
467 
468 // The cpp17::disjunction is used to prevent the compiler from matching this
469 // function when it should select the move constructor.
470 template <typename X, typename Symm, template <typename...> class IndexList,
471  typename... Indices>
472 template <typename... Args,
474  std::is_same<Tensor<X, Symm, IndexList<Indices...>>,
475  std::decay_t<Args>>...> and
476  sizeof...(Args) == 1) and
477  cpp17::is_constructible_v<X, Args...>>>
478 Tensor<X, Symm, IndexList<Indices...>>::Tensor(Args&&... args) noexcept
479  : data_(make_array<size(), X>(std::forward<Args>(args)...)) {}
480 
481 template <typename X, typename Symm, template <typename...> class IndexList,
482  typename... Indices>
484 Tensor<X, Symm, IndexList<Indices...>>::get_vector_of_data() const noexcept {
485  std::vector<value_type> serialized_tensor(size());
486  std::vector<std::string> component_names(size());
487  for (size_t i = 0; i < data_.size(); ++i) {
488  component_names[i] = component_name(get_tensor_index(i));
489  serialized_tensor[i] = gsl::at(data_, i);
490  }
491  return std::make_pair(component_names, serialized_tensor);
492 }
493 
494 template <int... N, typename... Args>
495 SPECTRE_ALWAYS_INLINE constexpr typename Tensor<Args...>::reference get(
496  Tensor<Args...>& t) noexcept {
497  static_assert(Tensor<Args...>::rank() == sizeof...(N),
498  "the number of tensor indices specified must match the rank "
499  "of the tensor");
500  return gsl::at(
501  t.data_, Tensor<Args...>::structure::template get_storage_index<N...>());
502 }
503 
504 template <int... N, typename... Args>
505 SPECTRE_ALWAYS_INLINE constexpr typename Tensor<Args...>::const_reference get(
506  const Tensor<Args...>& t) noexcept {
507  static_assert(Tensor<Args...>::rank() == sizeof...(N),
508  "the number of tensor indices specified must match the rank "
509  "of the tensor");
510  return gsl::at(
511  t.data_, Tensor<Args...>::structure::template get_storage_index<N...>());
512 }
513 
514 template <typename X, typename Symm, template <typename...> class IndexList,
515  typename... Indices>
516 bool operator==(const Tensor<X, Symm, IndexList<Indices...>>& lhs,
517  const Tensor<X, Symm, IndexList<Indices...>>& rhs) noexcept {
518  return std::equal(lhs.begin(), lhs.end(), rhs.begin());
519 }
520 template <typename X, typename Symm, template <typename...> class IndexList,
521  typename... Indices>
522 bool operator!=(const Tensor<X, Symm, IndexList<Indices...>>& lhs,
523  const Tensor<X, Symm, IndexList<Indices...>>& rhs) noexcept {
524  return not(lhs == rhs);
525 }
526 
527 /// \ingroup TensorGroup
528 /// Get dimensionality of i'th tensor index
529 ///
530 /// \snippet Test_Tensor.cpp index_dim
531 template <int I, class... Ts>
533  const Tensor<Ts...>& /*t*/) noexcept {
534  return Tensor<Ts...>::structure::template dim<I>();
535 }
536 
537 // We place the stream operators in the header file so they do not need to be
538 // explicitly instantiated.
539 template <typename X, typename Symm, template <typename...> class IndexList,
540  typename... Indices>
541 std::ostream& operator<<(
542  std::ostream& os,
543  const Tensor<X, Symm, IndexList<Indices...>>& x) noexcept {
544  static_assert(tt::is_streamable_v<decltype(os), X>,
545  "operator<< is not defined for the type you are trying to "
546  "stream in Tensor");
547  for (size_t i = 0; i < x.size() - 1; ++i) {
548  os << "T" << x.get_tensor_index(i) << "=" << x[i]
549  << "\n";
550  }
551  size_t i = x.size() - 1;
552  os << "T" << x.get_tensor_index(i) << "=" << x[i];
553  return os;
554 }
555 
556 namespace MakeWithValueImpls {
557 template <typename... Structure>
558 struct MakeWithValueImpl<Tensor<DataVector, Structure...>, DataVector> {
559  /// \brief Returns a Tensor whose DataVectors are the same size as `input`,
560  /// with each element equal to `value`.
561  static SPECTRE_ALWAYS_INLINE Tensor<DataVector, Structure...> apply(
562  const DataVector& input, const double value) noexcept {
563  return Tensor<DataVector, Structure...>(input.size(), value);
564  }
565 };
566 
567 template <typename... Structure>
568 struct MakeWithValueImpl<DataVector, Tensor<DataVector, Structure...>> {
569  /// \brief Returns a DataVector with the same size as the DataVectors of
570  /// `input`, with each element equal to `value`.
572  apply(const Tensor<DataVector, Structure...>& input,
573  const double value) noexcept {
574  return DataVector(input.begin()->size(), value);
575  }
576 };
577 
578 template <typename... StructureOut, typename... StructureIn>
579 struct MakeWithValueImpl<Tensor<DataVector, StructureOut...>,
580  Tensor<DataVector, StructureIn...>> {
581  /// \brief Returns a Tensor whose DataVectors are the same size as the
582  /// DataVectors of `input`, with each element equal to `value`.
583  static SPECTRE_ALWAYS_INLINE Tensor<DataVector, StructureOut...> apply(
584  const Tensor<DataVector, StructureIn...>& input,
585  const double value) noexcept {
586  return Tensor<DataVector, StructureOut...>(input.begin()->size(), value);
587  }
588 };
589 
590 template <typename... Structure>
591 struct MakeWithValueImpl<Tensor<double, Structure...>, double> {
592  /// \brief Returns a Tensor whose elements are set equal to `value` (`input`
593  /// is ignored).
594  static SPECTRE_ALWAYS_INLINE Tensor<double, Structure...> apply(
595  const double& /*input*/, const double value) noexcept {
596  return Tensor<double, Structure...>(value);
597  }
598 };
599 
600 template <typename... Structure>
601 struct MakeWithValueImpl<double, Tensor<double, Structure...>> {
602  /// \brief Returns a double initialized to `value` (`input` is ignored)
604  const Tensor<double, Structure...>& /*input*/,
605  const double value) noexcept {
606  return value;
607  }
608 };
609 
610 template <typename... StructureOut, typename... StructureIn>
611 struct MakeWithValueImpl<Tensor<double, StructureOut...>,
612  Tensor<double, StructureIn...>> {
613  /// \brief Returns a Tensor whose elements are set equal to `value` (`input`
614  /// is ignored).
615  static SPECTRE_ALWAYS_INLINE Tensor<double, StructureOut...> apply(
616  const Tensor<double, StructureIn...>& /*input*/,
617  const double value) noexcept {
618  return Tensor<double, StructureOut...>(value);
619  }
620 };
621 } // namespace MakeWithValueImpls
Implementations of make_with_value.
Definition: DenseVector.hpp:61
tmpl::list< Indices... > index_list
Typelist of the TensorIndexType&#39;s that the Tensor has.
Definition: Tensor.hpp:124
static constexpr size_t size() noexcept
Return the number of independent components of the Tensor.
Definition: Tensor.hpp:308
Defines helper functions for the standard library.
constexpr bool disjunction_v
Definition: TypeTraits.hpp:156
constexpr TE< tmpl::list< N... > > operator()(N...) const noexcept
Retrieve a TensorExpression object with the index structure passed in.
Definition: Tensor.hpp:268
static constexpr size_t get_storage_index(const N... args) noexcept
Get the storage index of the tensor index. Should only be used when optimizing code in which computin...
Definition: Tensor.hpp:340
Definition: IndexType.hpp:146
Definition: Digraph.hpp:11
static constexpr size_t multiplicity(const size_t storage_index) noexcept
Given an iterator or storage index, get the multiplicity of an index.
Definition: Tensor.hpp:359
static constexpr auto index_frames() noexcept
Returns std::tuple of the Frame of each index.
Definition: Tensor.hpp:417
static Tensor< double, Structure... > apply(const double &, const double value) noexcept
Returns a Tensor whose elements are set equal to value (input is ignored).
Definition: Tensor.hpp:594
static DataVector apply(const Tensor< DataVector, Structure... > &input, const double value) noexcept
Returns a DataVector with the same size as the DataVectors of input, with each element equal to value...
Definition: Tensor.hpp:572
Defines function make_array.
static constexpr size_t index_dim(const size_t i) noexcept
Get dimensionality of i&#39;th tensor index.
Definition: Tensor.hpp:370
static constexpr std::array< size_t, sizeof...(Indices)> index_dims() noexcept
Return array of dimensionality of each index.
Definition: Tensor.hpp:402
Marks a class as being a TensorExpression.
Definition: TensorExpression.hpp:271
static std::string component_name(const std::array< T, rank()> &tensor_index=std::array< T, rank()>{}, const std::array< std::string, rank()> &axis_labels=make_array< rank()>(std::string(""))) noexcept
Given a tensor index, get the canonical label associated with the canonical TensorIndexType.
Definition: Tensor.hpp:426
Defines the type alias Requires.
constexpr size_t multiplicity(const iterator &iter) const noexcept
Given an iterator or storage index, get the multiplicity of an index.
Definition: Tensor.hpp:355
constexpr size_t index_dim(const Tensor< Ts... > &) noexcept
Get dimensionality of i&#39;th tensor index.
Definition: Tensor.hpp:532
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args)
Apply the function f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1595
tmpl::fold< List, tmpl::list<>, detail::repeated_helper< tmpl::pin< List >, tmpl::_state, tmpl::_element > > repeated
Definition: TensorExpression.hpp:231
Definition: MakeWithValue.hpp:20
Defines class TensorStructure<Symmetry, Indices...>
constexpr std::array< size_t, sizeof...(Indices)> get_tensor_index(const const_iterator &iter) const noexcept
Given an iterator or storage index, get the canonical tensor index. For scalars this is defined to be...
Definition: Tensor.hpp:326
constexpr auto operator()(N...) const noexcept -> decltype(TensorExpressions::fully_contracted< TE, replace_indices< tmpl::list< N... >, repeated< tmpl::list< N... >>>, tmpl::int32_t< 0 >, tmpl::size< repeated< tmpl::list< N... >>>>::apply(*this))
Retrieve a TensorExpression object with the index structure passed in.
Definition: Tensor.hpp:276
static Tensor< DataVector, StructureOut... > apply(const Tensor< DataVector, StructureIn... > &input, const double value) noexcept
Returns a Tensor whose DataVectors are the same size as the DataVectors of input, with each element e...
Definition: Tensor.hpp:583
static constexpr std::array< IndexType, sizeof...(Indices)> index_types() noexcept
Return array of the IndexType&#39;s (spatial or spacetime)
Definition: Tensor.hpp:391
static constexpr std::array< int, sizeof...(Indices)> symmetries() noexcept
Return an array corresponding to the Symmetry of the Tensor.
Definition: Tensor.hpp:382
constexpr const_reference operator[](const size_t storage_index) const noexcept
Return i&#39;th component of storage vector.
Definition: Tensor.hpp:295
#define SPECTRE_ALWAYS_INLINE
Always inline a function. Only use this if you benchmarked the code.
Definition: ForceInline.hpp:20
X type
The type that is stored by the Tensor.
Definition: Tensor.hpp:114
Defines class.
constexpr std::array< T, Size > make_array(Args &&... args) noexcept(noexcept(MakeArray_detail::MakeArray< Size==0 >::template apply< T >(std::make_index_sequence<(Size==0 ? Size :Size - 1)>{}, std::forward< Args >(args)...)))
Create a std::array<T, Size>{{T(args...), T(args...), ...}}
Definition: MakeArray.hpp:68
constexpr bool is_same_v
Variable template for is_same.
Definition: TypeTraits.hpp:221
PUP routines for new C+11 STL containers and other standard library objects Charm does not provide im...
Defines Expression Templates for contracting tensor indices on a single Tensor.
constexpr bool is_streamable_v
Definition: TypeTraits.hpp:1039
static constexpr size_t rank() noexcept
Returns the rank of the Tensor.
Definition: Tensor.hpp:318
static constexpr size_t get_storage_index(const std::array< I, sizeof...(Indices)> &tensor_index) noexcept
Get the storage index of the tensor index. Should only be used when optimizing code in which computin...
Definition: Tensor.hpp:345
Definition: AddSubtract.hpp:28
Defines macro to always inline a function.
detail::fully_contract_helper< TE, ReplacedArgList, I, TotalContracted > fully_contracted
Represents a fully contracted Tensor.
Definition: Contract.hpp:225
Defines a list of useful type aliases for tensors.
T size(T... args)
constexpr reference operator[](const size_t storage_index) noexcept
Return i&#39;th component of storage vector.
Definition: Tensor.hpp:292
Contains a pretty_type library to write types in a "pretty" format.
Symm symmetry
Typelist of the symmetry of the Tensor.
Definition: Tensor.hpp:121
Stores a collection of function values.
Definition: DataVector.hpp:46
Wraps the template metaprogramming library used (brigand)
Defines functions and classes from the GSL.
IndexType
Indicates whether the TensorIndexType is Spatial or Spacetime.
Definition: IndexType.hpp:133
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t ...
Definition: Requires.hpp:67
C++ STL code present in C++17.
Definition: Array.hpp:16
Defines macro ERROR.
Defines type traits, some of which are future STL type_traits header.
UpLo
Whether a TensorIndexType is covariant or contravariant.
Definition: IndexType.hpp:20
static constexpr std::array< UpLo, sizeof...(Indices)> index_valences() noexcept
Return array of the valence of each index (UpLo)
Definition: Tensor.hpp:410
TensorExpression< Tensor< X, Symm, tmpl::list< Indices... > >, X, Symm, tmpl::list< Indices... >, ArgsList > TE
The type of the TensorExpression that would represent this Tensor in a tensor expression.
Definition: Tensor.hpp:129
static double apply(const Tensor< double, Structure... > &, const double value) noexcept
Returns a double initialized to value (input is ignored)
Definition: Tensor.hpp:603
static Tensor< DataVector, Structure... > apply(const DataVector &input, const double value) noexcept
Returns a Tensor whose DataVectors are the same size as input, with each element equal to value...
Definition: Tensor.hpp:561
Defines make_with_value.
Defines classes representing tensor indices.
constexpr T & at(std::array< T, N > &arr, Size index)
Retrieve a entry from a container, with checks in Debug mode that the index being retrieved is valid...
Definition: Gsl.hpp:124
static Tensor< double, StructureOut... > apply(const Tensor< double, StructureIn... > &, const double value) noexcept
Returns a Tensor whose elements are set equal to value (input is ignored).
Definition: Tensor.hpp:615
static constexpr std::array< size_t, sizeof...(Indices)> get_tensor_index(const size_t storage_index) noexcept
Given an iterator or storage index, get the canonical tensor index. For scalars this is defined to be...
Definition: Tensor.hpp:331