Discontinuous Galerkin Library
#include "dg/algorithm.h"
blas1.h
Go to the documentation of this file.
1#pragma once
2
3#include "backend/predicate.h"
9#include "backend/blas1_dispatch_scalar.h"
10#include "backend/blas1_dispatch_shared.h"
12#ifdef MPI_VERSION
13#include "backend/mpi_vector.h"
14#include "backend/blas1_dispatch_mpi.h"
15#endif
16#include "backend/blas1_dispatch_vector.h"
17#include "backend/blas1_dispatch_map.h"
18#include "subroutines.h"
19
25namespace dg{
26
35namespace blas1
36{
38template< class ContainerType, class BinarySubroutine, class Functor, class ContainerType0, class ...ContainerTypes>
39inline void evaluate( ContainerType& y, BinarySubroutine f, Functor g, const ContainerType0& x0, const ContainerTypes& ...xs);
41
44
86template< class ContainerType1, class ContainerType2>
87inline get_value_type<ContainerType1> dot( const ContainerType1& x, const ContainerType2& y)
88{
89 std::vector<int64_t> acc = dg::blas1::detail::doDot_superacc( x,y);
90 return exblas::cpu::Round(acc.data());
91}
92
137template< class ContainerType, class OutputType, class BinaryOp, class UnaryOp
138 = IDENTITY>
139inline OutputType reduce( const ContainerType& x, OutputType zero, BinaryOp
140 binary_op, UnaryOp unary_op = UnaryOp())
141{
142 //init must indeed have the same type as the values of Container since op must be associative
143 // The generalization would be a transform_reduce combining subroutine and reduce
144 return dg::blas1::detail::doReduce(
146 unary_op);
147}
148
163template<class ContainerTypeIn, class ContainerTypeOut>
164inline void copy( const ContainerTypeIn& source, ContainerTypeOut& target){
165 if( std::is_same<ContainerTypeIn, ContainerTypeOut>::value && &source==(const ContainerTypeIn*)&target)
166 return;
167 dg::blas1::subroutine( dg::equals(), source, target);
168}
169
184template< class ContainerType>
185inline void scal( ContainerType& x, get_value_type<ContainerType> alpha)
186{
187 if( alpha == get_value_type<ContainerType>(1))
188 return;
190}
191
206template< class ContainerType>
207inline void plus( ContainerType& x, get_value_type<ContainerType> alpha)
208{
209 if( alpha == get_value_type<ContainerType>(0))
210 return;
212}
213
230template< class ContainerType, class ContainerType1>
231inline void axpby( get_value_type<ContainerType> alpha, const ContainerType1& x, get_value_type<ContainerType> beta, ContainerType& y)
232{
233 using value_type = get_value_type<ContainerType>;
234 if( alpha == value_type(0) ) {
235 scal( y, beta);
236 return;
237 }
238 if( std::is_same<ContainerType, ContainerType1>::value && &x==(const ContainerType1*)&y){
239 dg::blas1::scal( y, (alpha+beta));
240 return;
241 }
243}
244
264template< class ContainerType, class ContainerType1, class ContainerType2>
265inline void axpbypgz( get_value_type<ContainerType> alpha, const ContainerType1& x, get_value_type<ContainerType> beta, const ContainerType2& y, get_value_type<ContainerType> gamma, ContainerType& z)
266{
267 using value_type = get_value_type<ContainerType>;
268 if( alpha == value_type(0) )
269 {
270 axpby( beta, y, gamma, z);
271 return;
272 }
273 else if( beta == value_type(0) )
274 {
275 axpby( alpha, x, gamma, z);
276 return;
277 }
278 if( std::is_same<ContainerType1, ContainerType2>::value && &x==(const ContainerType1*)&y){
279 dg::blas1::axpby( alpha+beta, x, gamma, z);
280 return;
281 }
282 else if( std::is_same<ContainerType1, ContainerType>::value && &x==(const ContainerType1*)&z){
283 dg::blas1::axpby( beta, y, alpha+gamma, z);
284 return;
285 }
286 else if( std::is_same<ContainerType2, ContainerType>::value && &y==(const ContainerType2*)&z){
287 dg::blas1::axpby( alpha, x, beta+gamma, z);
288 return;
289 }
291}
292
310template< class ContainerType, class ContainerType1, class ContainerType2>
311inline void axpby( get_value_type<ContainerType> alpha, const ContainerType1& x, get_value_type<ContainerType> beta, const ContainerType2& y, ContainerType& z)
312{
313 dg::blas1::evaluate( z , dg::equals(), dg::PairSum(), alpha, x, beta, y);
314}
315
335template< class ContainerType, class ContainerType1, class ContainerType2>
336inline void pointwiseDot( get_value_type<ContainerType> alpha, const ContainerType1& x1, const ContainerType2& x2, get_value_type<ContainerType> beta, ContainerType& y)
337{
338 if( alpha == get_value_type<ContainerType>(0) ) {
339 dg::blas1::scal(y, beta);
340 return;
341 }
342 //not sure this is necessary performance-wise, subroutine does allow aliases
343 if( std::is_same<ContainerType, ContainerType1>::value && &x1==(const ContainerType1*)&y){
345
346 return;
347 }
348 if( std::is_same<ContainerType, ContainerType2>::value && &x2==(const ContainerType2*)&y){
350
351 return;
352 }
354}
355
371template< class ContainerType, class ContainerType1, class ContainerType2>
372inline void pointwiseDot( const ContainerType1& x1, const ContainerType2& x2, ContainerType& y)
373{
375}
376
397template< class ContainerType, class ContainerType1, class ContainerType2, class ContainerType3>
398inline void pointwiseDot( get_value_type<ContainerType> alpha, const ContainerType1& x1, const ContainerType2& x2, const ContainerType3& x3, get_value_type<ContainerType> beta, ContainerType& y)
399{
400 if( alpha == get_value_type<ContainerType>(0) ) {
401 dg::blas1::scal(y, beta);
402 return;
403 }
405}
406
427template< class ContainerType, class ContainerType1, class ContainerType2>
428inline void pointwiseDivide( get_value_type<ContainerType> alpha, const ContainerType1& x1, const ContainerType2& x2, get_value_type<ContainerType> beta, ContainerType& y)
429{
430 if( alpha == get_value_type<ContainerType>(0) ) {
431 dg::blas1::scal(y, beta);
432 return;
433 }
434 if( std::is_same<ContainerType, ContainerType1>::value && &x1==(const ContainerType1*)&y){
436
437 return;
438 }
440}
441
459template< class ContainerType, class ContainerType1, class ContainerType2>
460inline void pointwiseDivide( const ContainerType1& x1, const ContainerType2& x2, ContainerType& y)
461{
463}
464
488template<class ContainerType, class ContainerType1, class ContainerType2, class ContainerType3, class ContainerType4>
489void pointwiseDot( get_value_type<ContainerType> alpha, const ContainerType1& x1, const ContainerType2& y1,
490 get_value_type<ContainerType> beta, const ContainerType3& x2, const ContainerType4& y2,
491 get_value_type<ContainerType> gamma, ContainerType & z)
492{
493 using value_type = get_value_type<ContainerType>;
494 if( alpha==value_type(0)){
495 pointwiseDot( beta, x2,y2, gamma, z);
496 return;
497 }
498 else if( beta==value_type(0)){
499 pointwiseDot( alpha, x1,y1, gamma, z);
500 return;
501 }
502 dg::blas1::subroutine( dg::PointwiseDot<get_value_type<ContainerType>>(alpha, beta, gamma), x1, y1, x2, y2, z );
503}
504
523template< class ContainerType, class ContainerType1, class UnaryOp>
524inline void transform( const ContainerType1& x, ContainerType& y, UnaryOp op )
525{
527}
528
555template< class ContainerType, class BinarySubroutine, class Functor, class ContainerType0, class ...ContainerTypes>
556inline void evaluate( ContainerType& y, BinarySubroutine f, Functor g, const ContainerType0& x0, const ContainerTypes& ...xs)
557{
559}
560
561
563namespace detail{
564
565template< class ContainerType1, class ContainerType2>
566inline std::vector<int64_t> doDot_superacc( const ContainerType1& x, const ContainerType2& y)
567{
568 static_assert( all_true<
569 dg::is_vector<ContainerType1>::value,
570 dg::is_vector<ContainerType2>::value>::value,
571 "All container types must have a vector data layout (AnyVector)!");
572 using vector_type = find_if_t<dg::is_not_scalar, ContainerType1, ContainerType1, ContainerType2>;
573 using tensor_category = get_tensor_category<vector_type>;
574 static_assert( all_true<
575 dg::is_scalar_or_same_base_category<ContainerType1, tensor_category>::value,
576 dg::is_scalar_or_same_base_category<ContainerType2, tensor_category>::value
577 >::value,
578 "All container types must be either Scalar or have compatible Vector categories (AnyVector or Same base class)!");
579 return doDot_superacc( x, y, tensor_category());
580}
581
582}//namespace detail
584
617template< class Subroutine, class ContainerType, class ...ContainerTypes>
618inline void subroutine( Subroutine f, ContainerType&& x, ContainerTypes&&... xs)
619{
620 static_assert( all_true<
621 dg::is_vector<ContainerType>::value,
622 dg::is_vector<ContainerTypes>::value...>::value,
623 "All container types must have a vector data layout (AnyVector)!");
624 using vector_type = find_if_t<dg::is_not_scalar, ContainerType, ContainerType, ContainerTypes...>;
625 using tensor_category = get_tensor_category<vector_type>;
626 static_assert( all_true<
627 dg::is_scalar_or_same_base_category<ContainerType, tensor_category>::value,
628 dg::is_scalar_or_same_base_category<ContainerTypes, tensor_category>::value...
629 >::value,
630 "All container types must be either Scalar or have compatible Vector categories (AnyVector or Same base class)!");
631 //using basic_tag_type = std::conditional_t< all_true< is_scalar<ContainerType>::value, is_scalar<ContainerTypes>::value... >::value, AnyScalarTag , AnyVectorTag >;
632 dg::blas1::detail::doSubroutine(tensor_category(), f, std::forward<ContainerType>(x), std::forward<ContainerTypes>(xs)...);
633}
634
636}//namespace blas1
637
664template<class from_ContainerType, class ContainerType, class ...Params>
665inline void assign( const from_ContainerType& from, ContainerType& to, Params&& ... ps)
666{
667 dg::detail::doAssign<from_ContainerType, ContainerType, Params...>( from, to, get_tensor_category<from_ContainerType>(), get_tensor_category<ContainerType>(), std::forward<Params>(ps)...);
668}
669
695template<class ContainerType, class from_ContainerType, class ...Params>
696inline ContainerType construct( const from_ContainerType& from, Params&& ... ps)
697{
698 return dg::detail::doConstruct<ContainerType, from_ContainerType, Params...>( from, get_tensor_category<ContainerType>(), get_tensor_category<from_ContainerType>(), std::forward<Params>(ps)...);
699}
700
701
702} //namespace dg
703
ContainerType construct(const from_ContainerType &from, Params &&... ps)
Generic way to construct an object of ContainerType given a from_ContainerType object and optional ad...
Definition: blas1.h:696
void assign(const from_ContainerType &from, ContainerType &to, Params &&... ps)
Generic way to assign the contents of a from_ContainerType object to a ContainerType object optionall...
Definition: blas1.h:665
static DG_DEVICE double zero(double x)
Definition: functions.h:29
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition: blas1.h:164
void plus(ContainerType &x, get_value_type< ContainerType > alpha)
Definition: blas1.h:207
void transform(const ContainerType1 &x, ContainerType &y, UnaryOp op)
Definition: blas1.h:524
void axpbypgz(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, const ContainerType2 &y, get_value_type< ContainerType > gamma, ContainerType &z)
Definition: blas1.h:265
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
Definition: blas1.h:231
OutputType reduce(const ContainerType &x, OutputType zero, BinaryOp binary_op, UnaryOp unary_op=UnaryOp())
Custom (transform) reduction
Definition: blas1.h:139
void subroutine(Subroutine f, ContainerType &&x, ContainerTypes &&... xs)
; Customizable and generic blas1 function
Definition: blas1.h:618
void scal(ContainerType &x, get_value_type< ContainerType > alpha)
Definition: blas1.h:185
void evaluate(ContainerType &y, BinarySubroutine f, Functor g, const ContainerType0 &x0, const ContainerTypes &...xs)
Definition: blas1.h:556
void pointwiseDivide(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
Definition: blas1.h:428
void pointwiseDot(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
Definition: blas1.h:336
get_value_type< ContainerType1 > dot(const ContainerType1 &x, const ContainerType2 &y)
Binary reproducible Euclidean dot product between two vectors
Definition: blas1.h:87
@ z
z direction
@ y
y direction
@ x
x direction
to
Switch for the Timeloop integrate function.
Definition: ode.h:17
typename TensorTraits< std::decay_t< Vector > >::tensor_category get_tensor_category
Definition: tensor_traits.h:40
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition: tensor_traits.h:38
static double Round(int64_t *accumulator)
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Definition: subroutines.h:245
Definition: subroutines.h:273
Definition: subroutines.h:259
Definition: subroutines.h:193
Definition: subroutines.h:11
Definition: subroutines.h:108
Definition: subroutines.h:231
Definition: subroutines.h:317
Definition: subroutines.h:289
Definition: subroutines.h:218
Definition: subroutines.h:72
Definition: subroutines.h:22