SpECTRE Documentation Coverage Report
Current view: top level - __w/spectre/spectre/docs/DevGuide - Variables.md Hit Total Coverage
Commit: f8ea4a52db6a7b766b531a9ef6054857b7453f1d Lines: 0 1 0.0 %
Date: 2024-05-03 17:20:07
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : \cond NEVER
       2             : Distributed under the MIT License.
       3             : See LICENSE.txt for details.
       4             : \endcond
       5             : # Using Variables in SpECTRE {#variables_foundations}
       6             : 
       7             : # What is a Variables and Why Use Them?
       8             : Variables are a data structure that hold a contiguous memory block with Tensors
       9             : pointing to it. Variables temporaries allow you to declare temporary tensors and
      10             : scalars so that you can do all allocations needed for a computation at one time.
      11             : Since physical memory is shared between CPU cores, processes can't allocate in
      12             : parallel since they might try to allocate to the same chunk of memory. As more
      13             : CPU cores are used, this becomes a bottleneck, slowing down or stopping other
      14             : processes while memory is being allocated. Using a Variables to allocate all
      15             : memory needed at once can improve efficiency allowing the computation to
      16             : operate smoothly and uninterrupted.
      17             : 
      18             : # Defining a Variables of Temporary Tags
      19             : To define a Variables, you'll need the TempTensor and Variables headers
      20             : ```cpp
      21             : #include "DataStructures/Tags/TempTensor.hpp"
      22             : #include "DataStructures/Variables.hpp"
      23             : ```
      24             : this will give you access to temporary Scalars and Tensors we'll need to
      25             : allocate. You can define a Variables that allocates one Scalar with something
      26             : like this:
      27             : ```cpp
      28             : Variables<tmpl::list<::Tags::TempScalar<0>>>
      29             : temp_buffer{get<0,0>(spatial_metric).size()};
      30             : ```
      31             : Here, the Variables we've defined `temp_buffer` provides a tmpl::list with a
      32             : TempScalar inside as the template argument, this will allocate a single
      33             : temporary scalar. The size and DataType of the TempScalar is deduced by what's
      34             : inside the {}, you can provide any tensor or std::array with the correct size
      35             : needed. Now, to use the allocation you've made, you can do:
      36             : ```cpp
      37             : auto& useful_scalar = get<::Tags::TempScalar<0>>(temp_buffer);
      38             : ```
      39             : 
      40             : # Real Use Example
      41             : Now that we've got the basics, using them to allocate multiple Scalars and
      42             : Tensors is quite easy. For instance, let's say I need to allocate 2 scalars,
      43             : a spatial vector and 2 lower rank 2 tensors for my function.
      44             : ```cpp
      45             : Variables<tmpl::list<::Tags::TempScalar<0>, ::Tags::TempScalar<1>,
      46             : ::Tags::TempI<0, 3, Frame::Inertial>, ::Tags::Tempij<0, 3, Frame::Inertial>,
      47             : ::Tags::Tempij<1, 3, Frame::Inertial>>>
      48             : temp_buffer{get<0,0>(spatial_metric).size()};
      49             : ```
      50             : Here, when we allocate for the same type of scalar or tensor (rank 2 lower) the
      51             : way we distinguish multiple allocations is through the number within the <>.
      52             : Now, to use each individual allocation, we can do something like:
      53             : ```cpp
      54             : auto& cool_scalar1 = get<::Tags::TempScalar<0>>(temp_buffer);
      55             : auto& cool_scalar2 = get<::Tags::TempScalar<1>>(temp_buffer);
      56             : auto& cool_tensor1 = get<::Tags::Tempij<0, 3, Frame::Inertial>>(temp_buffer);
      57             : auto& cool_tensor2 = get<::Tags::Tempij<1, 3, Frame::Inertial>>(temp_buffer);
      58             : ```
      59             : 
      60             : # Tips
      61             : In the interest of reducing memory allocations, there a certain scenarios where
      62             : you can resuse old allocations that are no longer useful to your computation.
      63             : 
      64             : To see this, let's say that you're trying to make two unit vectors. You might
      65             : start by saying you'll need two different vectors (rank 1 upper tensors) and 2
      66             : different scalars as the magnitude of each vector.
      67             : The way we'd allocate for this is by doing:
      68             : ```cpp
      69             : Variables<tmpl::list<::Tags::TempScalar<0>, ::Tags::TempScalar<1>,
      70             : ::Tags::TempI<0, 3, Frame::Inertial>, ::Tags::TempI<1, 3, Frame::Inertial>>>
      71             : temp_buffer{get<0,0>(spatial_metric).size()};
      72             : ```
      73             : However, doing this allocates more memory than we actually need. Once we finish
      74             : calculating the first unit vector, the memory we've allocated for the scalar
      75             : magnitude of the first vector will just sit there unused. We can reuse the
      76             : allocation for the TempScalar<0> and use it when calculating the second unit
      77             : vector without having to allocate another TempScalar. Now, allocating an extra
      78             : scalar is not very expensive, but when using tensors, the memory required really
      79             : adds up, so this is just another way to help make SpECTRE a bit more efficient.

Generated by: LCOV version 1.14