18#ifndef LIBMESH_KOKKOS_VECTOR_OPS_H
19#define LIBMESH_KOKKOS_VECTOR_OPS_H
46#include "libmesh/kokkos_linalg_base.h"
48#include "libmesh/tensor_tools.h"
63template <
typename ResultVector =
void,
typename VectorLike>
66 -> std::conditional_t<std::is_void<ResultVector>::value,
70 using output_type = std::conditional_t<std::is_void<ResultVector>::value,
73 return materialize_vector<output_type>(v);
85template <
typename LeftVector,
typename RightVector>
89 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
90 left(component) = right(component);
96template <
typename VectorLike,
typename Scalar>
100 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
101 v(component) =
value;
107template <
typename LeftVector,
typename RightVector,
typename Scalar>
111 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
112 left(component) = left(component) + factor * right(component);
119template <
typename OutputVector,
typename InputVector,
typename TransformOp>
123 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
124 out(component) = op(in(component));
130template <
typename ResultVector,
typename VectorLike,
typename TransformOp>
144template <
typename LeftVector,
typename RightVector>
148 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
149 if (left(component) != right(component))
162template <
typename ValueType>
165 LIBMESH_DEVICE_INLINE
172template <
typename Scalar>
177 LIBMESH_DEVICE_INLINE
183 template <
typename ValueType>
184 LIBMESH_DEVICE_INLINE
191template <
typename Scalar>
196 LIBMESH_DEVICE_INLINE
202 template <
typename ValueType>
203 LIBMESH_DEVICE_INLINE
218template <
typename LeftVector,
typename RightVector>
220auto vector_dot(
const LeftVector & left,
const RightVector & right)
222 static_assert(is_vector_like_v<LeftVector>,
"vector_dot() requires a vector-like left input");
223 static_assert(is_vector_like_v<RightVector>,
"vector_dot() requires a vector-like right input");
228 sum_type sum = sum_type(0);
229 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
230 sum += left(component) * right(component);
240template <
typename ResultVector =
void,
typename VectorLike>
243 -> std::conditional_t<std::is_void<ResultVector>::value,
247 const auto length = v.norm();
248 libmesh_assert_not_equal_to(length,
static_cast<Real>(0.));
249 using output_type = std::conditional_t<std::is_void<ResultVector>::value,
252 return detail::transformed_vector<output_type>(v,
detail::divide_value<
decltype(length)>{length});
265template <
typename ResultVector =
void,
typename LeftVector,
typename RightVector>
268 -> std::conditional_t<std::is_void<ResultVector>::value,
272 using output_type = std::conditional_t<std::is_void<ResultVector>::value,
279 out(0) = left(1) * right(2) - left(2) * right(1);
280 out(1) = -left(0) * right(2) + left(2) * right(0);
281 out(2) = left(0) * right(1) - left(1) * right(0);
295template <
typename LeftVector,
typename M
iddleVector,
typename RightVector>
298 const MiddleVector & middle,
299 const RightVector & right)
302 return left(0) * (middle(1) * right(2) - middle(2) * right(1)) -
303 left(1) * (middle(0) * right(2) - middle(2) * right(0)) +
304 left(2) * (middle(0) * right(1) - middle(1) * right(0));
309 return value_type(0);
318template <
typename LeftVector,
typename RightVector>
322 const auto z = left(0) * right(1) - left(1) * right(0);
325 const auto x = left(1) * right(2) - left(2) * right(1);
326 const auto y = left(0) * right(2) - left(2) * right(0);
327 return x * x + y * y + z * z;
340template <
typename VectorA,
typename VectorB,
typename VectorC>
346 const auto norm01 = v01.norm();
347 const auto norm02 = v02.norm();
348 const auto norm03 = v03.norm();
349 const auto tan_half_angle =
354 norm01 * norm02 * norm03);
356 return Real(2) * atan(tan_half_angle);
365template <
typename LeftVector,
366 typename RightVector,
367 typename std::enable_if<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector>,
370auto contract(
const LeftVector & left,
const RightVector & right)
379template <
typename LeftVector,
typename RightVector>
381auto operator+=(LeftVector & left,
const RightVector & right)
382 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
383 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
386template <
typename LeftVector,
typename RightVector>
388auto operator-=(LeftVector & left,
const RightVector & right)
389 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
390 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
398template <
typename ViewType>
399template <
typename RightVector>
406template <
typename ViewType>
407template <
typename RightVector>
414template <
typename ViewType>
415template <
typename RightVector>
422template <
typename ViewType>
423template <
typename RightVector>
430template <
typename ViewType>
431template <
typename RightVector>
438template <
typename ViewType>
445template <
typename ViewType>
446template <
typename RightVector>
453template <
typename ViewType>
458 return sqrt(this->norm_sq());
461template <
typename ViewType>
468 norm_type sum = norm_type(0);
469 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
475template <
typename ViewType>
482 norm_type sum = norm_type(0);
483 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
484 sum += abs((*
this)(component));
489template <
typename ViewType>
493 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
500template <
typename ViewType>
507template <
typename ViewType>
508template <
typename RightVector>
527template <
typename VectorLike>
530 -> std::enable_if_t<is_vector_like_v<VectorLike> && is_vector_ref_v<VectorLike>,
533 return detail::transformed_vector<vector_semantic_type_t<VectorLike>>(
541template <
typename LeftVector,
typename RightVector>
543auto operator+(
const LeftVector & left,
const RightVector & right)
544 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
545 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
548 auto out = copy_vector<vector_semantic_type_t<LeftVector>>(left);
556template <
typename LeftVector,
typename RightVector>
558auto operator-(
const LeftVector & left,
const RightVector & right)
559 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
560 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
563 auto out = copy_vector<vector_semantic_type_t<LeftVector>>(left);
572template <
typename LeftVector,
573 typename RightVector,
574 typename std::enable_if<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
575 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
578auto operator*(
const LeftVector & left,
const RightVector & right)
587template <
typename Scalar,
589 typename std::enable_if<!is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar> &&
590 is_vector_like_v<VectorLike> && is_vector_ref_v<VectorLike>,
593auto operator*(
const Scalar & alpha,
const VectorLike & v)
598template <
typename VectorLike,
600 typename std::enable_if<is_vector_like_v<VectorLike> && is_vector_ref_v<VectorLike> &&
601 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
604auto operator*(
const VectorLike & v,
const Scalar & alpha)
606 return detail::transformed_vector<vector_semantic_type_t<VectorLike>>(
615template <
typename VectorLike,
617 typename std::enable_if<is_vector_like_v<VectorLike> && is_vector_ref_v<VectorLike> &&
618 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
621auto operator/(
const VectorLike & v,
const Scalar & alpha)
623 return detail::transformed_vector<vector_semantic_type_t<VectorLike>>(
634template <
typename LeftVector,
typename RightVector>
636auto operator==(
const LeftVector & left,
const RightVector & right)
637 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
638 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
648template <
typename LeftVector,
typename RightVector>
650auto operator!=(
const LeftVector & left,
const RightVector & right)
651 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
652 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
655 return !(left == right);
662template <
typename LeftVector,
typename RightVector>
665 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
666 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
676template <
typename LeftVector,
typename RightVector>
679 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector> &&
680 (is_vector_ref_v<LeftVector> || is_vector_ref_v<RightVector>),
690template <
typename LeftVector,
typename Scalar>
693 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_ref_v<LeftVector> &&
694 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
704template <
typename LeftVector,
typename Scalar>
707 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_ref_v<LeftVector> &&
708 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
LIBMESH_DEVICE_INLINE auto l1_norm() const
LIBMESH_DEVICE_INLINE auto norm() const
LIBMESH_DEVICE_INLINE auto cross(const RightVector &right) const
LIBMESH_DEVICE_INLINE void zero()
Sets every component of the referenced entry to zero.
LIBMESH_DEVICE_INLINE void add_scaled(const RightVector &right, const value_type &factor)
Adds factor times right to the referenced entry, in place.
LIBMESH_DEVICE_INLINE void add(const RightVector &right)
Adds right to the referenced entry, in place.
detail::vector_view_value_t< ViewType > value_type
LIBMESH_DEVICE_INLINE void subtract(const RightVector &right)
Subtracts right from the referenced entry, in place.
LIBMESH_DEVICE_INLINE void subtract_scaled(const RightVector &right, const value_type &factor)
Subtracts factor times right from the referenced entry, in place.
LIBMESH_DEVICE_INLINE auto norm_sq() const
LIBMESH_DEVICE_INLINE auto contract(const RightVector &right) const
LIBMESH_DEVICE_INLINE void assign(const RightVector &right)
Assigns right 's components to the referenced entry.
LIBMESH_DEVICE_INLINE auto unit() const
LIBMESH_DEVICE_INLINE bool is_zero() const
LIBMESH_DEVICE_INLINE void update_vector_components(LeftVector &left, const RightVector &right, const Scalar &factor)
Componentwise axpy-style update: left += factor * right.
LIBMESH_DEVICE_INLINE void assign_vector_components(LeftVector &left, const RightVector &right)
Componentwise copy: left = right.
LIBMESH_DEVICE_INLINE ResultVector transformed_vector(const VectorLike &v, const TransformOp &op)
typename std::remove_cv< typename std::remove_reference< T >::type >::type remove_cvref_t
Strips reference and const/volatile qualifiers from T, turning e.g.
LIBMESH_DEVICE_INLINE void fill_vector_components(VectorLike &v, const Scalar &value)
Sets every component of v to value.
LIBMESH_DEVICE_INLINE void transform_vector_components(OutputVector &out, const InputVector &in, const TransformOp &op)
Componentwise transform: out(i) = op(in(i)).
LIBMESH_DEVICE_INLINE bool vector_equal_impl(const LeftVector &left, const RightVector &right)
LIBMESH_DEVICE_INLINE auto operator*(const Scalar &alpha, const TensorLike &T_in)
LIBMESH_DEVICE_INLINE auto vector_triple_product(const LeftVector &left, const MiddleVector &middle, const RightVector &right)
LIBMESH_DEVICE_INLINE auto vector_unit(const VectorLike &v) -> std::conditional_t< std::is_void< ResultVector >::value, vector_semantic_type_t< VectorLike >, ResultVector >
LIBMESH_DEVICE_INLINE auto vector_dot(const LeftVector &left, const RightVector &right)
LIBMESH_DEVICE_INLINE auto operator/=(LeftTensor &left, const Scalar &alpha) -> std::enable_if_t< is_tensor_like_v< LeftTensor > &&is_tensor_ref_v< LeftTensor > &&!is_vector_like_v< Scalar > &&!is_tensor_like_v< Scalar >, LeftTensor & >
Divides left by alpha in place.
typename vector_traits< detail::remove_cvref_t< T > >::semantic_type vector_semantic_type_t
The owning libMesh type a vector-like T materializes to, with any cv/reference qualification on T str...
LIBMESH_DEVICE_INLINE auto operator+(const LeftTensor &left, const RightTensor &right) -> std::enable_if_t< is_tensor_like_v< LeftTensor > &&is_tensor_like_v< RightTensor > &&(is_tensor_ref_v< LeftTensor >||is_tensor_ref_v< RightTensor >), tensor_semantic_type_t< LeftTensor > >
LIBMESH_DEVICE_INLINE auto contract(const LeftTensor &left, const RightTensor &right)
LIBMESH_DEVICE_INLINE auto operator==(const LeftTensor &left, const RightTensor &right) -> std::enable_if_t< is_tensor_like_v< LeftTensor > &&is_tensor_like_v< RightTensor > &&(is_tensor_ref_v< LeftTensor >||is_tensor_ref_v< RightTensor >), bool >
LIBMESH_DEVICE_INLINE auto operator-(const TensorLike &T_in) -> std::enable_if_t< is_tensor_like_v< TensorLike > &&is_tensor_ref_v< TensorLike >, tensor_semantic_type_t< TensorLike > >
LIBMESH_DEVICE_INLINE auto operator!=(const LeftTensor &left, const RightTensor &right) -> std::enable_if_t< is_tensor_like_v< LeftTensor > &&is_tensor_like_v< RightTensor > &&(is_tensor_ref_v< LeftTensor >||is_tensor_ref_v< RightTensor >), bool >
LIBMESH_DEVICE_INLINE auto vector_cross(const LeftVector &left, const RightVector &right) -> std::conditional_t< std::is_void< ResultVector >::value, vector_semantic_type_t< LeftVector >, ResultVector >
LIBMESH_DEVICE_INLINE auto copy_vector(const VectorLike &v) -> std::conditional_t< std::is_void< ResultVector >::value, vector_semantic_type_t< VectorLike >, ResultVector >
LIBMESH_DEVICE_INLINE auto vector_solid_angle(const VectorA &v01, const VectorB &v02, const VectorC &v03)
LIBMESH_DEVICE_INLINE auto operator-=(LeftTensor &left, const RightTensor &right) -> std::enable_if_t< is_tensor_like_v< LeftTensor > &&is_tensor_like_v< RightTensor > &&(is_tensor_ref_v< LeftTensor >||is_tensor_ref_v< RightTensor >), LeftTensor & >
Subtracts right from left in place.
LIBMESH_DEVICE_INLINE auto operator/(const TensorLike &T_in, const Scalar &alpha) -> std::enable_if_t< is_tensor_like_v< TensorLike > &&is_tensor_ref_v< TensorLike > &&!is_vector_like_v< Scalar > &&!is_tensor_like_v< Scalar >, tensor_semantic_type_t< TensorLike > >
LIBMESH_DEVICE_INLINE auto operator+=(LeftTensor &left, const RightTensor &right) -> std::enable_if_t< is_tensor_like_v< LeftTensor > &&is_tensor_like_v< RightTensor > &&(is_tensor_ref_v< LeftTensor >||is_tensor_ref_v< RightTensor >), LeftTensor & >
Adds right to left in place; when left is a ref, the update writes through to the underlying storage.
LIBMESH_DEVICE_INLINE auto operator*=(LeftTensor &left, const Scalar &alpha) -> std::enable_if_t< is_tensor_like_v< LeftTensor > &&is_tensor_ref_v< LeftTensor > &&!is_vector_like_v< Scalar > &&!is_tensor_like_v< Scalar >, LeftTensor & >
Scales left by alpha in place.
LIBMESH_DEVICE_INLINE auto vector_cross_norm_sq(const LeftVector &left, const RightVector &right)
void libmesh_ignore(const Args &...)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
LIBMESH_DEVICE_INLINE auto operator()(const ValueType &value) const -> decltype(value/alpha)
LIBMESH_DEVICE_INLINE auto operator()(const Scalar &value) const -> decltype(value/alpha)
Componentwise transform functors, shared by the vector helpers here and the tensor helpers in kokkos_...
LIBMESH_DEVICE_INLINE auto operator()(const ValueType &value) const
LIBMESH_DEVICE_INLINE auto operator()(const Scalar &value) const -> decltype(value *alpha)
LIBMESH_DEVICE_INLINE auto operator()(const ValueType &value) const -> decltype(value *alpha)