18#ifndef LIBMESH_KOKKOS_TENSOR_OPS_H
19#define LIBMESH_KOKKOS_TENSOR_OPS_H
47#include "libmesh/kokkos_linalg_base.h"
48#include "libmesh/kokkos_vector_ops.h"
50#include "libmesh/tensor_tools.h"
63template <
typename ResultTensor>
70 for (
unsigned int i = 0; i <
dim; ++i)
82template <
typename ResultTensor =
void,
typename TensorLike>
85 -> std::conditional_t<std::is_void<ResultTensor>::value,
89 using output_type = std::conditional_t<std::is_void<ResultTensor>::value,
92 return materialize_tensor<output_type>(T_in);
106template <
typename TensorLike>
108typename TensorLike::value_type
111 static_assert(is_tensor_like_v<TensorLike>,
112 "detail::leading_determinant() requires a tensor-like input");
121 return T_in(0, 0) * T_in(1, 1) -
122 T_in(0, 1) * T_in(1, 0);
125 const auto a00 = T_in(0, 0);
126 const auto a01 = T_in(0, 1);
127 const auto a02 = T_in(0, 2);
128 const auto a10 = T_in(1, 0);
129 const auto a11 = T_in(1, 1);
130 const auto a12 = T_in(1, 2);
131 const auto a20 = T_in(2, 0);
132 const auto a21 = T_in(2, 1);
133 const auto a22 = T_in(2, 2);
135 return a00 * (a11 * a22 - a12 * a21) -
136 a01 * (a10 * a22 - a12 * a20) +
137 a02 * (a10 * a21 - a11 * a20);
149template <
typename ResultTensor,
typename LeftVector,
typename RightVector>
151ResultTensor
outer_product(
const LeftVector & left,
const RightVector & right)
156 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
157 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
168template <
typename ResultTensor,
typename TensorLike>
170ResultTensor
inverse(
const TensorLike & T_in,
const unsigned int dim = LIBMESH_DIM)
172 static_assert(is_tensor_like_v<TensorLike>,
"detail::inverse() requires a tensor-like input");
182 using value_type =
typename ResultTensor::value_type;
183 out(0, 0) = value_type(1) / T_in(0, 0);
191 out(0, 0) = T_in(1, 1) /
det;
192 out(0, 1) = -T_in(0, 1) /
det;
193 out(1, 0) = -T_in(1, 0) /
det;
194 out(1, 1) = T_in(0, 0) /
det;
199 const auto a00 = T_in(0, 0);
200 const auto a01 = T_in(0, 1);
201 const auto a02 = T_in(0, 2);
202 const auto a10 = T_in(1, 0);
203 const auto a11 = T_in(1, 1);
204 const auto a12 = T_in(1, 2);
205 const auto a20 = T_in(2, 0);
206 const auto a21 = T_in(2, 1);
207 const auto a22 = T_in(2, 2);
209 out(0, 0) = (a11 * a22 - a12 * a21) /
det;
210 out(0, 1) = (a02 * a21 - a01 * a22) /
det;
211 out(0, 2) = (a01 * a12 - a02 * a11) /
det;
212 out(1, 0) = (a12 * a20 - a10 * a22) /
det;
213 out(1, 1) = (a00 * a22 - a02 * a20) /
det;
214 out(1, 2) = (a02 * a10 - a00 * a12) /
det;
215 out(2, 0) = (a10 * a21 - a11 * a20) /
det;
216 out(2, 1) = (a01 * a20 - a00 * a21) /
det;
217 out(2, 2) = (a00 * a11 - a01 * a10) /
det;
228template <
typename ResultTensor,
typename TensorLike>
235 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
236 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
248template <
typename ResultTensor,
typename LeftTensor,
typename RightTensor>
255 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
256 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
258 auto value = left(
row, 0) * right(0, col);
259 for (
unsigned int k = 1; k < LIBMESH_DIM; ++k)
260 value += left(
row, k) * right(k, col);
270template <
typename ResultVector,
typename TensorLike>
272ResultVector
row(
const TensorLike & T_in,
const unsigned int row_index)
277 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
278 out(col) = T_in(row_index, col);
287template <
typename ResultVector,
typename TensorLike>
289ResultVector
column(
const TensorLike & T_in,
const unsigned int col_index)
294 for (
unsigned int row_index = 0; row_index < LIBMESH_DIM; ++row_index)
295 out(row_index) = T_in(row_index, col_index);
306template <
typename ResultVector,
typename TensorLike,
typename VectorLike>
313 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
316 for (
unsigned int col = 1; col < LIBMESH_DIM; ++col)
328template <
typename ResultVector,
typename VectorLike,
typename TensorLike>
335 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
337 auto value = v(0) * T_in(0, col);
338 for (
unsigned int row = 1;
row < LIBMESH_DIM; ++
row)
349template <
typename LeftTensor,
typename RightTensor>
353 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
354 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
355 left(
row, col) = right(
row, col);
361template <
typename TensorLike,
typename Scalar>
365 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
366 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
373template <
typename LeftTensor,
typename RightTensor,
typename Scalar>
377 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
378 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
379 left(
row, col) = left(
row, col) + factor * right(
row, col);
386template <
typename OutputTensor,
typename InputTensor,
typename TransformOp>
390 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
391 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
398template <
typename ResultTensor,
typename TensorLike,
typename TransformOp>
412template <
typename LeftTensor,
typename RightTensor>
416 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
417 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
418 if (left(
row, col) != right(
row, col))
430template <
typename LeftTensor,
typename RightTensor>
434 static_assert(is_tensor_like_v<LeftTensor>,
"tensor_contract() requires a tensor-like left input");
435 static_assert(is_tensor_like_v<RightTensor>,
"tensor_contract() requires a tensor-like right input");
440 sum_type sum = sum_type(0);
441 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
442 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
443 sum += left(
row, col) * right(
row, col);
452template <
typename TensorLike>
456 static_assert(is_tensor_like_v<TensorLike>,
"tensor_trace() requires a tensor-like input");
459 trace_type sum = trace_type(0);
460 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
474template <
typename LeftTensor,
475 typename RightTensor,
476 typename std::enable_if<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor>,
479auto contract(
const LeftTensor & left,
const RightTensor & right)
490template <
typename ResultTensor =
void,
typename LeftVector,
typename RightVector>
493 -> std::enable_if_t<is_vector_like_v<LeftVector> && is_vector_like_v<RightVector>,
494 std::conditional_t<std::is_void<ResultTensor>::value,
498 using output_type = std::conditional_t<std::is_void<ResultTensor>::value,
501 return detail::outer_product<output_type>(left, right);
508template <
typename ResultTensor =
void,
typename TensorLike>
511 -> std::enable_if_t<is_tensor_like_v<TensorLike>,
512 std::conditional_t<std::is_void<ResultTensor>::value,
516 using output_type = std::conditional_t<std::is_void<ResultTensor>::value,
519 return detail::transpose<output_type>(T_in);
527template <
typename TensorLike>
529auto det(
const TensorLike & T_in)
530 -> std::enable_if_t<is_tensor_like_v<TensorLike>,
decltype(T_in.det())>
539template <
typename ResultTensor =
void,
typename TensorLike>
541auto inverse(
const TensorLike & T_in,
const unsigned int dim = LIBMESH_DIM)
542 -> std::enable_if_t<is_tensor_like_v<TensorLike>,
543 std::conditional_t<std::is_void<ResultTensor>::value,
547 using output_type = std::conditional_t<std::is_void<ResultTensor>::value,
550 return detail::inverse<output_type>(T_in,
dim);
558template <
typename ResultVector =
void,
typename TensorLike>
560auto row(
const TensorLike & T_in,
const unsigned int i)
561 -> std::enable_if_t<is_tensor_like_v<TensorLike>,
562 std::conditional_t<std::is_void<ResultVector>::value,
566 using output_type = std::conditional_t<std::is_void<ResultVector>::value,
569 return detail::row<output_type>(T_in, i);
576template <
typename ResultVector =
void,
typename TensorLike>
578auto column(
const TensorLike & T_in,
const unsigned int i)
579 -> std::enable_if_t<is_tensor_like_v<TensorLike>,
580 std::conditional_t<std::is_void<ResultVector>::value,
584 using output_type = std::conditional_t<std::is_void<ResultVector>::value,
587 return detail::column<output_type>(T_in, i);
593template <
typename LeftTensor,
typename RightTensor>
595auto operator+=(LeftTensor & left,
const RightTensor & right)
596 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
597 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
600template <
typename LeftTensor,
typename RightTensor>
602auto operator-=(LeftTensor & left,
const RightTensor & right)
603 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
604 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
612template <
typename ViewType>
613template <
typename RightTensor>
620template <
typename ViewType>
621template <
typename RightTensor>
628template <
typename ViewType>
629template <
typename RightTensor>
636template <
typename ViewType>
637template <
typename RightTensor>
644template <
typename ViewType>
645template <
typename RightTensor>
652template <
typename ViewType>
659template <
typename ViewType>
660template <
typename RightTensor>
667template <
typename ViewType>
672 return sqrt(this->norm_sq());
675template <
typename ViewType>
682 norm_type sum = norm_type(0);
683 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
684 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
690template <
typename ViewType>
694 for (
unsigned int row = 0;
row < LIBMESH_DIM; ++
row)
695 for (
unsigned int col = 0; col < LIBMESH_DIM; ++col)
702template <
typename ViewType>
709template <
typename ViewType>
716template <
typename ViewType>
723template <
typename ViewType>
730template <
typename ViewType>
731template <
typename VectorLike,
typename ResultVector>
735 const auto solution =
736 detail::multiply_tensor_vector<vector_semantic_type_t<ResultVector>>(this->
inverse(),
b);
737 for (
unsigned int component = 0; component < LIBMESH_DIM; ++component)
738 x(component) = solution(component);
741template <
typename ViewType>
748template <
typename ViewType>
755template <
typename ViewType>
756template <
typename VectorLike>
775template <
typename TensorLike>
778 -> std::enable_if_t<is_tensor_like_v<TensorLike> && is_tensor_ref_v<TensorLike>,
781 return detail::transformed_tensor<tensor_semantic_type_t<TensorLike>>(
789template <
typename LeftTensor,
typename RightTensor>
791auto operator+(
const LeftTensor & left,
const RightTensor & right)
792 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
793 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
796 auto out = copy_tensor<tensor_semantic_type_t<LeftTensor>>(left);
805template <
typename LeftTensor,
typename RightTensor>
807auto operator-(
const LeftTensor & left,
const RightTensor & right)
808 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
809 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
812 auto out = copy_tensor<tensor_semantic_type_t<LeftTensor>>(left);
821template <
typename Scalar,
823 typename std::enable_if<!is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar> &&
824 is_tensor_like_v<TensorLike> && is_tensor_ref_v<TensorLike>,
827auto operator*(
const Scalar & alpha,
const TensorLike & T_in)
832template <
typename TensorLike,
834 typename std::enable_if<is_tensor_like_v<TensorLike> && is_tensor_ref_v<TensorLike> &&
835 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
838auto operator*(
const TensorLike & T_in,
const Scalar & alpha)
840 return detail::transformed_tensor<tensor_semantic_type_t<TensorLike>>(
849template <
typename TensorLike,
typename Scalar>
851auto operator/(
const TensorLike & T_in,
const Scalar & alpha)
852 -> std::enable_if_t<is_tensor_like_v<TensorLike> && is_tensor_ref_v<TensorLike> &&
853 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
856 return detail::transformed_tensor<tensor_semantic_type_t<TensorLike>>(
865template <
typename LeftTensor,
866 typename RightTensor,
867 typename std::enable_if<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
868 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
871auto operator*(
const LeftTensor & left,
const RightTensor & right)
873 return detail::multiply_tensors<tensor_semantic_type_t<LeftTensor>>(left, right);
879template <
typename TensorLike,
881 typename std::enable_if<is_tensor_like_v<TensorLike> && is_vector_like_v<VectorLike> &&
882 (is_tensor_ref_v<TensorLike> || is_vector_ref_v<VectorLike>),
885auto operator*(
const TensorLike & T_in,
const VectorLike & v)
887 return detail::multiply_tensor_vector<vector_semantic_type_t<VectorLike>>(T_in, v);
894template <
typename VectorLike,
896 typename std::enable_if<is_vector_like_v<VectorLike> && is_tensor_like_v<TensorLike> &&
897 (is_vector_ref_v<VectorLike> || is_tensor_ref_v<TensorLike>),
900auto operator*(
const VectorLike & v,
const TensorLike & T_in)
902 return detail::multiply_vector_tensor<vector_semantic_type_t<VectorLike>>(v, T_in);
913template <
typename LeftTensor,
typename RightTensor>
915auto operator==(
const LeftTensor & left,
const RightTensor & right)
916 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
917 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
927template <
typename LeftTensor,
typename RightTensor>
929auto operator!=(
const LeftTensor & left,
const RightTensor & right)
930 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
931 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
934 return !(left == right);
941template <
typename LeftTensor,
typename RightTensor>
944 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
945 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
955template <
typename LeftTensor,
typename RightTensor>
958 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_like_v<RightTensor> &&
959 (is_tensor_ref_v<LeftTensor> || is_tensor_ref_v<RightTensor>),
969template <
typename LeftTensor,
typename Scalar>
972 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_ref_v<LeftTensor> &&
973 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
983template <
typename LeftTensor,
typename Scalar>
986 -> std::enable_if_t<is_tensor_like_v<LeftTensor> && is_tensor_ref_v<LeftTensor> &&
987 !is_vector_like_v<Scalar> && !is_tensor_like_v<Scalar>,
LIBMESH_DEVICE_INLINE auto left_multiply(const VectorLike &v) const
LIBMESH_DEVICE_INLINE void add(const RightTensor &right)
Adds right to the referenced entry, in place.
LIBMESH_DEVICE_INLINE auto transpose() const
LIBMESH_DEVICE_INLINE void zero()
Sets every component of the referenced entry to zero.
LIBMESH_DEVICE_INLINE void subtract_scaled(const RightTensor &right, const value_type &factor)
Subtracts factor times right from the referenced entry, in place.
LIBMESH_DEVICE_INLINE void solve(const VectorLike &b, ResultVector &x) const
Solves the linear system (*this)x = b for x, via the explicit inverse.
LIBMESH_DEVICE_INLINE auto norm() const
LIBMESH_DEVICE_INLINE void add_scaled(const RightTensor &right, const value_type &factor)
Adds factor times right to the referenced entry, in place.
LIBMESH_DEVICE_INLINE auto norm_sq() const
LIBMESH_DEVICE_INLINE void subtract(const RightTensor &right)
Subtracts right from the referenced entry, in place.
LIBMESH_DEVICE_INLINE auto tr() const
LIBMESH_DEVICE_INLINE void assign(const RightTensor &right)
Assigns right 's components to the referenced entry.
LIBMESH_DEVICE_INLINE auto row(const unsigned int i) const
detail::tensor_view_value_t< ViewType > value_type
LIBMESH_DEVICE_INLINE auto contract(const RightTensor &right) const
LIBMESH_DEVICE_INLINE auto inverse(const unsigned int dim=LIBMESH_DIM) const
LIBMESH_DEVICE_INLINE auto det(const unsigned int dim=LIBMESH_DIM) const
LIBMESH_DEVICE_INLINE auto column(const unsigned int i) const
LIBMESH_DEVICE_INLINE bool is_zero() const
This class defines a tensor in LIBMESH_DIM dimensional space of type T.
This class defines a vector in LIBMESH_DIM dimensional space of type T.
LIBMESH_DEVICE_INLINE bool tensor_equal_impl(const LeftTensor &left, const RightTensor &right)
LIBMESH_DEVICE_INLINE void fill_tensor_components(TensorLike &T_in, const Scalar &value)
Sets every component of T_in to value.
LIBMESH_DEVICE_INLINE void transform_tensor_components(OutputTensor &out, const InputTensor &in, const TransformOp &op)
Componentwise transform: out(i,j) = op(in(i,j)).
LIBMESH_DEVICE_INLINE ResultTensor transformed_tensor(const TensorLike &T_in, const TransformOp &op)
LIBMESH_DEVICE_INLINE auto tensor_trace(const TensorLike &T_in)
LIBMESH_DEVICE_INLINE ResultTensor transpose(const TensorLike &T_in)
LIBMESH_DEVICE_INLINE ResultTensor inverse(const TensorLike &T_in, const unsigned int dim=LIBMESH_DIM)
LIBMESH_DEVICE_INLINE void assign_tensor_components(LeftTensor &left, const RightTensor &right)
Componentwise copy: left = right.
LIBMESH_DEVICE_INLINE ResultTensor outer_product(const LeftVector &left, const RightVector &right)
LIBMESH_DEVICE_INLINE void update_tensor_components(LeftTensor &left, const RightTensor &right, const Scalar &factor)
Componentwise axpy-style update: left += factor * right.
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 ResultVector column(const TensorLike &T_in, const unsigned int col_index)
LIBMESH_DEVICE_INLINE ResultVector row(const TensorLike &T_in, const unsigned int row_index)
LIBMESH_DEVICE_INLINE ResultVector multiply_vector_tensor(const VectorLike &v, const TensorLike &T_in)
LIBMESH_DEVICE_INLINE auto tensor_contract(const LeftTensor &left, const RightTensor &right)
LIBMESH_DEVICE_INLINE ResultVector multiply_tensor_vector(const TensorLike &T_in, const VectorLike &v)
LIBMESH_DEVICE_INLINE ResultTensor multiply_tensors(const LeftTensor &left, const RightTensor &right)
LIBMESH_DEVICE_INLINE TensorLike::value_type leading_determinant(const TensorLike &T_in, const unsigned int dim=LIBMESH_DIM)
LIBMESH_DEVICE_INLINE auto operator*(const Scalar &alpha, const TensorLike &T_in)
LIBMESH_DEVICE_INLINE auto inverse(const TensorLike &T_in, const unsigned int dim=LIBMESH_DIM) -> std::enable_if_t< is_tensor_like_v< TensorLike >, std::conditional_t< std::is_void< ResultTensor >::value, tensor_semantic_type_t< TensorLike >, ResultTensor > >
typename tensor_traits< detail::remove_cvref_t< T > >::semantic_type tensor_semantic_type_t
The owning libMesh type a tensor-like T materializes to, with any cv/reference qualification on T str...
LIBMESH_DEVICE_INLINE auto copy_tensor(const TensorLike &T_in) -> std::conditional_t< std::is_void< ResultTensor >::value, tensor_semantic_type_t< TensorLike >, ResultTensor >
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.
LIBMESH_DEVICE_INLINE auto column(const TensorLike &T_in, const unsigned int i) -> std::enable_if_t< is_tensor_like_v< TensorLike >, std::conditional_t< std::is_void< ResultVector >::value, libMesh::TypeVector< typename TensorLike::value_type >, ResultVector > >
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 ResultTensor tensor_identity(const unsigned int dim=LIBMESH_DIM)
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 row(const TensorLike &T_in, const unsigned int i) -> std::enable_if_t< is_tensor_like_v< TensorLike >, std::conditional_t< std::is_void< ResultVector >::value, libMesh::TypeVector< typename TensorLike::value_type >, ResultVector > >
LIBMESH_DEVICE_INLINE auto transpose(const TensorLike &T_in) -> std::enable_if_t< is_tensor_like_v< TensorLike >, std::conditional_t< std::is_void< ResultTensor >::value, tensor_semantic_type_t< TensorLike >, ResultTensor > >
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 outer_product(const LeftVector &left, const RightVector &right) -> std::enable_if_t< is_vector_like_v< LeftVector > &&is_vector_like_v< RightVector >, std::conditional_t< std::is_void< ResultTensor >::value, libMesh::TypeTensor< typename LeftVector::value_type >, ResultTensor > >
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 det(const TensorLike &T_in) -> std::enable_if_t< is_tensor_like_v< TensorLike >, decltype(T_in.det())>
void libmesh_ignore(const Args &...)
LIBMESH_DEVICE_INLINE T libmesh_conj(T a)
Componentwise transform functors, shared by the vector helpers here and the tensor helpers in kokkos_...