Discontinuous Galerkin Library
#include "dg/algorithm.h"
Loading...
Searching...
No Matches
Collaboration diagram for The tag dispatch system:

Topics

 All TensorTraits specialisations
 

Classes

struct  dg::AnyPolicyTag
 Execution Policy base class. More...
 
struct  dg::NoPolicyTag
 Indicate that a type does not have an execution policy. More...
 
struct  dg::AnyMatrixTag
 tensor_category base class More...
 
struct  dg::NotATensorTag
 Indicate that a type is not a tensor. More...
 
struct  dg::WhichType<... >
 
struct  dg::TensorTraits< Vector, Enable >
 The vector traits. More...
 

Typedefs

template<class T , class Tag = AnyScalarTag>
using dg::is_scalar = typename std::is_base_of<Tag, get_tensor_category<T>>::type
 Does a type have a tensor_category derived from Tag.
 
template<class T , class Tag = AnyVectorTag>
using dg::is_vector = typename std::is_base_of<Tag, get_tensor_category<T>>::type
 Does a type have a tensor_category derived from Tag.
 
template<class T , class Tag = AnyMatrixTag>
using dg::is_matrix = typename std::is_base_of<Tag, get_tensor_category<T>>::type
 Does a type have a tensor_category derived from Tag.
 
template<class T , class Tag = AnyPolicyTag>
using dg::has_policy = std::is_same<Tag, get_execution_policy<T>>
 Does a type have an execution_policy equal to Tag.
 
template<class Vector >
using dg::get_value_type = typename TensorTraits<std::decay_t<Vector>>::value_type
 
template<class Vector >
using dg::get_tensor_category = typename TensorTraits< std::decay_t<Vector>>::tensor_category
 
template<class Vector >
using dg::get_execution_policy = typename TensorTraits<std::decay_t<Vector>>::execution_policy
 

Variables

template<class T , class Tag = AnyScalarTag>
constexpr bool dg::is_scalar_v = is_scalar<T, Tag>::value
 Utility typedef.
 
template<class T , class Tag = AnyVectorTag>
constexpr bool dg::is_vector_v = is_vector<T, Tag>::value
 Utility typedef.
 
template<class T , class Tag = AnyMatrixTag>
constexpr bool dg::is_matrix_v = is_matrix<T, Tag>::value
 Utility typedef.
 
template<class T , class Tag = AnyPolicyTag>
constexpr bool dg::has_policy_v = has_policy<T, Tag>::value
 Utility typedef.
 

Detailed Description

The dg dispatch system

At the heart of the dispatch system lies the dg::TensorTraits class that specifies how a type T behaves in the respective functions though a tag system defined by the tensor_category tag and the execution_policy tag. Per default it looks like

template< class T, class Enable=void>
struct TensorTraits
{
using value_type = void;
using tensor_category = NotATensorTag;
using execution_policy = NoPolicyTag;
};
NoPolicyTag execution_policy
Definition tensor_traits.h:41
NotATensorTag tensor_category
Definition tensor_traits.h:40
void value_type
Definition tensor_traits.h:39

The values for tensor_category are either dg::NotATensorTag or (a class derived from) dg::AnyMatrixTag, while the values for execution_policy are either dg::NoPolicyTag or (a class derived from) dg::AnyPolicyTag. Any type T assumes the above default values for value_type, tensor_category and execution_policy unless a specialisation exists for that type (see All TensorTraits specialisations for a full list). We define the following nomenclature

When dispatching level 1 functions we distinguish between three classes of functions: trivially parallel (dg::blas1::subroutine and related dg::blas1 functions), global communication (dg::blas1::dot and dg::blas2::dot) and local communication (dg::blas2::symv).

The subroutine function

The execution of dg::blas1::subroutine with a Functor called routine (and all related dg::blas1 functions) is equivalent to the following:

  1. Assert the following prerequisites:
    1. All template parameter types must be either Scalars or Vectors and have an execution policy and a value type
    2. All Vectors and all execution policies must be mutually compatible
    3. All Vectors must contain the same number of elements (equal sizes)
    4. The number of template parameters must be equal to the number of parameters in the routine
    5. The value type of every template parameter must be convertible to the respective parameter type in the routine
  2. If all types are Scalars, apply the routine and return
  3. If at least one type is a Vector, then all Scalars are promoted to this type with the same size, communicator and execution policy
  4. Check the base class of the tensor_category:
    1. If dg::SharedVectorTag, check execution policy and dispatch to respective implementation (The implementation just loops over all elements in the vectors and applies the routine)
    2. If dg::MPIVectorTag, access the underlying data and recursively call dg::blas1::subroutine (and start again at 1)
    3. If dg::RecursiveVectorTag, loop over all elements and recursively call dg::blas1::subroutine for all elements (and start again at 1)

The dot function

The execution of dg::blas1::dot and dg::blas2::dot is equivalent to the following:

  1. Assert the following prerequisites:
    1. All template parameter types must be either Scalars or Vectors and have an execution policy and a value type
    2. All Vectors and all execution policies must be mutually compatible
    3. All Vectors must contain the same number of elements (equal sizes)
  2. If all types are Scalars, multiply and return
  3. If at least one type is a Vector, then all Scalars are promoted to this type with the same size, communicator and execution policy
  4. Check the base class of the tensor_category:
    1. If dg::SharedVectorTag, check execution policy and dispatch to respective implementation (The implementation multiplies and accumulates all elements in the vectors). Return the result.
    2. If dg::MPIVectorTag, assert that the vector MPI-communicators are congruent (same process group, different context) or ident (same process group, same context). Then, access the underlying data and recursively call dot (and start again at 1). Accumulate the result among participating processes and return.
    3. If dg::RecursiveVectorTag, loop over all elements and recursively call dot for all elements (and start again at 1). Accumulate the results and return.

The symv function

In the execution of the dg::blas2::symv (and its aliases dg::blas2::gemv and dg::apply) each matrix type has individual prerequisites and execution paths depending on its tensor_category. We can identify some general rules:

  1. If the tensor category is dg::NotATensorTag (any type has this tag by default unless it is overwritten by a specialization of dg::TensorTraits ) then the compiler assumes that the type is a functor type and immediately forwards all parameters to the operator() member and none of the following applies
  2. If the Matrix type has the dg::SelfMadeMatrixTag tensor category, then all parameters are immediately forwarded to the symv member function. No asserts are performed and none of the following applies.
  3. If the Matrix type is either a Scalar or a Vector and the remaining types do not have the dg::RecursiveVectorTag tensor category, then dg::blas2::symv is equivalent to dg::blas1::pointwiseDot
  4. The container template parameters must be Vectors or Scalars and must have compatible execution policies. Vectors must be compatible.
  5. If the tensor category of the Vectors is dg::RecursiveVectorTag and the tensor category of the Matrix is not, then the dg::blas2::symv is recursively called with the Matrix on all elements of the Vectors.

Typedef Documentation

◆ get_execution_policy

template<class Vector >
using dg::get_execution_policy = typename TensorTraits<std::decay_t<Vector>>::execution_policy

◆ get_tensor_category

template<class Vector >
using dg::get_tensor_category = typename TensorTraits< std::decay_t<Vector>>::tensor_category

◆ get_value_type

template<class Vector >
using dg::get_value_type = typename TensorTraits<std::decay_t<Vector>>::value_type

◆ has_policy

template<class T , class Tag = AnyPolicyTag>
using dg::has_policy = std::is_same<Tag, get_execution_policy<T>>

Does a type have an execution_policy equal to Tag.

See also
dg::has_policy_v

◆ is_matrix

template<class T , class Tag = AnyMatrixTag>
using dg::is_matrix = typename std::is_base_of<Tag, get_tensor_category<T>>::type

Does a type have a tensor_category derived from Tag.

See also
dg::is_matrix_v

◆ is_scalar

template<class T , class Tag = AnyScalarTag>
using dg::is_scalar = typename std::is_base_of<Tag, get_tensor_category<T>>::type

Does a type have a tensor_category derived from Tag.

See also
dg::is_scalar_v

◆ is_vector

template<class T , class Tag = AnyVectorTag>
using dg::is_vector = typename std::is_base_of<Tag, get_tensor_category<T>>::type

Does a type have a tensor_category derived from Tag.

See also
dg::is_vector_v

Variable Documentation

◆ has_policy_v

template<class T , class Tag = AnyPolicyTag>
bool dg::has_policy_v = has_policy<T, Tag>::value
constexpr

Utility typedef.

◆ is_matrix_v

template<class T , class Tag = AnyMatrixTag>
bool dg::is_matrix_v = is_matrix<T, Tag>::value
constexpr

Utility typedef.

◆ is_scalar_v

template<class T , class Tag = AnyScalarTag>
bool dg::is_scalar_v = is_scalar<T, Tag>::value
constexpr

Utility typedef.

◆ is_vector_v

template<class T , class Tag = AnyVectorTag>
bool dg::is_vector_v = is_vector<T, Tag>::value
constexpr

Utility typedef.