SpECTRE  v2024.09.29
evolution::dg::AtomicInboxBoundaryData< Dim > Struct Template Reference

Holds the data in the different directions for the nodegroup DgElementArray implementation. More...

#include <AtomicInboxBoundaryData.hpp>

Public Types

using stored_type = evolution::dg::BoundaryData< Dim >
 

Public Member Functions

 AtomicInboxBoundaryData (const AtomicInboxBoundaryData &)=delete
 
AtomicInboxBoundaryDataoperator= (const AtomicInboxBoundaryData &)=delete
 
 AtomicInboxBoundaryData (AtomicInboxBoundaryData &&rhs) noexcept
 
AtomicInboxBoundaryDataoperator= (AtomicInboxBoundaryData &&) noexcept=delete
 
void pup (PUP::er &p)
 

Static Public Member Functions

static size_t index (const DirectionalId< Dim > &directional_id)
 

Public Attributes

std::array< Parallel::StaticSpscQueue< std::tuple<::TimeStepId, stored_type, DirectionalId< Dim > >, 20 >, maximum_number_of_neighbors(Dim)> boundary_data_in_directions {}
 
std::atomic_uint message_count {}
 
std::atomic_uint number_of_neighbors {}
 

Detailed Description

template<size_t Dim>
struct evolution::dg::AtomicInboxBoundaryData< Dim >

Holds the data in the different directions for the nodegroup DgElementArray implementation.

The reason for this class is to reduce contention between cores and to allow the use of a Single-Producer-Single-Consumer (SPSC) queue instead of an MPMC queue. This has significant performance improvements since it drastically reduces contention.

The uint message counter is used to count how many neighbors have contributed for the next time. This is used to delay calling perform_algorithm() in order to reduce the number of messages we send through the runtime system. The number_of_neighbors is used to track the number of expected messages. Note that some additional logic is needed also for supporting local time stepping, since not every message entry "counts" since it depends on the time level of neighboring elements.

Warning
Only AtomicInboxBoundaryData with zero messages can be move constructed. A non-zero number of neighbors is allowed. This is necessary in order to be able to serialize a std::unordered_map<Key,AtomicInboxBoundaryData>.

Member Function Documentation

◆ index()

template<size_t Dim>
static size_t evolution::dg::AtomicInboxBoundaryData< Dim >::index ( const DirectionalId< Dim > &  directional_id)
static

Computes the 1d index into the boundary_data_in_directions array for a specific directional_id that has been re-oriented using the OrientationMap to be put in the same block frame as the element that is receiving the data (i.e. that whose inbox this is being inserted into).

The hash is computed as

\begin{align} 2^D d + 2^{D-1} s + e \end{align}

where \(D\) is the number of spatial dimensions, \(d\) is the logical dimension of the direction to the neighbor from the element whose inbox this is, \(s\) is the side in the logical dimension \(d\) with a value of 1 for upper and 0 for lower, and \(e\) is a hash of the index of the SegmentId's of the neighbor's ElementId for the dimensions other than \(d\). In particular: for \(d=1\), \(e\) is 0 (1) if the SegmentId index along the face is even (odd); and for \(d = 3\) \(e\) is 0 (1, 2, 3) if the SegmentId indices along the face are both even (lower dim odd, higher dim odd, both dims odd). The element segment hash is computed as the logical and of the SegmentID's index in that direction, left shifted by which direction on the face it is.


The documentation for this struct was generated from the following file: