Loading [MathJax]/extensions/TeX/newcommand.js
 deal.II version GIT relicensing-2669-g1eff4de72e 2025-02-20 01:30:00+00:00
\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}} \newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=} \newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]} \newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
Public Types | Related Symbols | List of all members
ProductType< T, U > Struct Template Reference

#include <deal.II/base/template_constraints.h>

Public Types

using type = typename internal::ProductTypeImpl< std::decay_t< T >, std::decay_t< U > >::type
 

Related Symbols

(Note that these are not member symbols.)

template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, std::complex< U > >::typeoperator* (const std::complex< T > &left, const std::complex< U > &right)
 
template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, std::complex< U > >::typeoperator/ (const std::complex< T > &left, const std::complex< U > &right)
 
template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, U >::typeoperator* (const std::complex< T > &left, const U &right)
 
template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, U >::typeoperator/ (const std::complex< T > &left, const U &right)
 
template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< T, std::complex< U > >::typeoperator* (const T &left, const std::complex< U > &right)
 
template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< T, std::complex< U > >::typeoperator/ (const T &left, const std::complex< U > &right)
 

Detailed Description

template<typename T, typename U>
struct ProductType< T, U >

A class with a local alias that represents the type that results from the product of two variables of type T and U. In other words, we would like to infer the type of the product variable in code like this:

T t;
U u;
auto product = t*u;

The local alias of this structure represents the type the variable product would have.

Where is this useful

The purpose of this class is principally to represent the type one needs to use to represent the values or gradients of finite element fields at quadrature points. For example, assume you are storing the values U_j of unknowns in a Vector<float>, then evaluating u_h(x_q) = \sum_j U_j \varphi_j(x_q) at quadrature points results in values u_h(x_q) that need to be stored as double variables because the U_j are float values and the \varphi_j(x_q) are computed as double values, and the product are then double values. On the other hand, if you store your unknowns U_j as std::complex<double> values and you try to evaluate \nabla u_h(x_q) = \sum_j U_j \nabla\varphi_j(x_q) at quadrature points, then the gradients \nabla u_h(x_q) need to be stored as objects of type Tensor<1,dim,std::complex<double>> because that's what you get when you multiply a complex number by a Tensor<1,dim> (the type used to represent the gradient of shape functions of scalar finite elements).

Likewise, if you are using a vector valued element (with dim components) and the U_j are stored as double variables, then u_h(x_q) = \sum_j U_j \varphi_j(x_q) needs to have type Tensor<1,dim> (because the shape functions have type Tensor<1,dim>). Finally, if you store the U_j as objects of type std::complex<double> and you have a vector valued element, then the gradients \nabla u_h(x_q) = \sum_j U_j \nabla\varphi_j(x_q) will result in objects of type Tensor<2,dim,std::complex<double> >.

In all of these cases, this type is used to identify which type needs to be used for the result of computing the product of unknowns and the values, gradients, or other properties of shape functions.

Definition at line 459 of file template_constraints.h.

Member Typedef Documentation

◆ type

template<typename T , typename U >
using ProductType< T, U >::type = typename internal::ProductTypeImpl<std::decay_t<T>, std::decay_t<U> >::type

Definition at line 461 of file template_constraints.h.

Friends And Related Symbol Documentation

◆ operator*() [1/3]

template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, std::complex< U > >::type > operator* ( const std::complex< T > &  left,
const std::complex< U > &  right 
)
related

Provide an operator* that operates on mixed complex floating point types. Annoyingly, the standard library does not provide such an operator.

Note
Because the C++ standard does not provide for mixed-precision complex operators, code such as the following does not compile:
double factor = 3.141;
std::complex<float> x(1,2); // =1+2i
auto z = factor*x; // error
Because this does not compile, writing mixed-precision complex linear algebra libraries is not easily possible without much additional work that requires explicit casts. For example, one would have to write the code above as follows:
double factor = 1.0;
std::complex<float> x(1,2); // =1+2i
auto z = static_cast<P>(factor) * static_cast<P>(x);
typename internal::ProductTypeImpl< std::decay_t< T >, std::decay_t< U > >::type type
This makes much code unreadable. As a consequence, we define the necessary overloaded multiplication and division operators for mixed complex arithmetic (in namespace dealii) to make the code above compile without the extra casts.

Definition at line 70 of file complex_overloads.h.

◆ operator/() [1/3]

template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, std::complex< U > >::type > operator/ ( const std::complex< T > &  left,
const std::complex< U > &  right 
)
related

Provide an operator/ that operates on mixed complex floating point types. Annoyingly, the standard library does not provide such an operator.

Note
Because the C++ standard does not provide for mixed-precision complex operators, code such as the following does not compile:
double factor = 3.141;
std::complex<float> x(1,2); // =1+2i
auto z = factor*x; // error
Because this does not compile, writing mixed-precision complex linear algebra libraries is not easily possible without much additional work that requires explicit casts. For example, one would have to write the code above as follows:
double factor = 1.0;
std::complex<float> x(1,2); // =1+2i
auto z = static_cast<P>(factor) * static_cast<P>(x);
This makes much code unreadable. As a consequence, we define the necessary overloaded multiplication and division operators for mixed complex arithmetic (in namespace dealii) to make the code above compile without the extra casts.

Definition at line 111 of file complex_overloads.h.

◆ operator*() [2/3]

template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, U >::type > operator* ( const std::complex< T > &  left,
const U &  right 
)
related

Provide an operator* for a scalar multiplication of a complex floating point type with a different real floating point type. Annoyingly, the standard library does not provide such an operator.

Note
Because the C++ standard does not provide for mixed-precision complex operators, code such as the following does not compile:
double factor = 3.141;
std::complex<float> x(1,2); // =1+2i
auto z = factor*x; // error
Because this does not compile, writing mixed-precision complex linear algebra libraries is not easily possible without much additional work that requires explicit casts. For example, one would have to write the code above as follows:
double factor = 1.0;
std::complex<float> x(1,2); // =1+2i
auto z = static_cast<P>(factor) * static_cast<P>(x);
This makes much code unreadable. As a consequence, we define the necessary overloaded multiplication and division operators for mixed complex arithmetic (in namespace dealii) to make the code above compile without the extra casts.

Definition at line 151 of file complex_overloads.h.

◆ operator/() [2/3]

template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< std::complex< T >, U >::type > operator/ ( const std::complex< T > &  left,
const U &  right 
)
related

Provide an operator/ for a scalar division of a complex floating point type with a different real floating point type. Annoyingly, the standard library does not provide such an operator.

Note
Because the C++ standard does not provide for mixed-precision complex operators, code such as the following does not compile:
double factor = 3.141;
std::complex<float> x(1,2); // =1+2i
auto z = factor*x; // error
Because this does not compile, writing mixed-precision complex linear algebra libraries is not easily possible without much additional work that requires explicit casts. For example, one would have to write the code above as follows:
double factor = 1.0;
std::complex<float> x(1,2); // =1+2i
auto z = static_cast<P>(factor) * static_cast<P>(x);
This makes much code unreadable. As a consequence, we define the necessary overloaded multiplication and division operators for mixed complex arithmetic (in namespace dealii) to make the code above compile without the extra casts.

Definition at line 190 of file complex_overloads.h.

◆ operator*() [3/3]

template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< T, std::complex< U > >::type > operator* ( const T &  left,
const std::complex< U > &  right 
)
related

Provide an operator* for a scalar multiplication of a real floating point type with a different complex floating point type. Annoyingly, the standard library does not provide such an operator.

Note
Because the C++ standard does not provide for mixed-precision complex operators, code such as the following does not compile:
double factor = 3.141;
std::complex<float> x(1,2); // =1+2i
auto z = factor*x; // error
Because this does not compile, writing mixed-precision complex linear algebra libraries is not easily possible without much additional work that requires explicit casts. For example, one would have to write the code above as follows:
double factor = 1.0;
std::complex<float> x(1,2); // =1+2i
auto z = static_cast<P>(factor) * static_cast<P>(x);
This makes much code unreadable. As a consequence, we define the necessary overloaded multiplication and division operators for mixed complex arithmetic (in namespace dealii) to make the code above compile without the extra casts.

Definition at line 229 of file complex_overloads.h.

◆ operator/() [3/3]

template<typename T , typename U >
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U > &&!std::is_same_v< T, U >, typename ProductType< T, std::complex< U > >::type > operator/ ( const T &  left,
const std::complex< U > &  right 
)
related

Provide an operator/ for a scalar division of a real floating point type with a different complex floating point type. Annoyingly, the standard library does not provide such an operator.

Note
Because the C++ standard does not provide for mixed-precision complex operators, code such as the following does not compile:
double factor = 3.141;
std::complex<float> x(1,2); // =1+2i
auto z = factor*x; // error
Because this does not compile, writing mixed-precision complex linear algebra libraries is not easily possible without much additional work that requires explicit casts. For example, one would have to write the code above as follows:
double factor = 1.0;
std::complex<float> x(1,2); // =1+2i
auto z = static_cast<P>(factor) * static_cast<P>(x);
This makes much code unreadable. As a consequence, we define the necessary overloaded multiplication and division operators for mixed complex arithmetic (in namespace dealii) to make the code above compile without the extra casts.

Definition at line 268 of file complex_overloads.h.


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