SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/LinearSolver - InnerProduct.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 66.7 % 9 6
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            1 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : ///\file
       5              : /// Defines an inner product for the linear solver
       6              : 
       7              : #pragma once
       8              : 
       9              : #include <array>
      10              : 
      11              : #include "DataStructures/Variables.hpp"
      12              : #include "Utilities/Blas.hpp"
      13              : #include "Utilities/EqualWithinRoundoff.hpp"
      14              : #include "Utilities/ErrorHandling/Assert.hpp"
      15              : #include "Utilities/ForceInline.hpp"
      16              : 
      17              : namespace LinearSolver {
      18              : 
      19              : /// \ingroup LinearSolverGroup
      20              : /// Implementations of LinearSolver::inner_product.
      21            1 : namespace InnerProductImpls {
      22              : 
      23              : /// The inner product between any types that have a `dot` product
      24              : template <typename Lhs, typename Rhs>
      25            1 : struct InnerProductImpl {
      26            0 :   static auto apply(const Lhs& lhs, const Rhs& rhs) {
      27              :     return dot(conj(lhs), rhs);
      28              :   }
      29              : };
      30              : 
      31              : /// The inner product between `Variables`
      32              : template <typename LhsTagsList, typename RhsTagsList>
      33            1 : struct InnerProductImpl<Variables<LhsTagsList>, Variables<RhsTagsList>> {
      34            0 :   using ValueType = typename Variables<LhsTagsList>::value_type;
      35            0 :   static ValueType apply(const Variables<LhsTagsList>& lhs,
      36              :                          const Variables<RhsTagsList>& rhs) {
      37              :     const auto size = lhs.size();
      38              :     ASSERT(size == rhs.size(),
      39              :            "The Variables must be of the same size to take an inner product");
      40              :     if constexpr (std::is_same_v<ValueType, std::complex<double>>) {
      41              :       return zdotc_(size, lhs.data(), 1, rhs.data(), 1);
      42              :     } else {
      43              :       return ddot_(size, lhs.data(), 1, rhs.data(), 1);
      44              :     }
      45              :   }
      46              : };
      47              : 
      48              : }  // namespace InnerProductImpls
      49              : 
      50              : /*!
      51              :  * \ingroup LinearSolverGroup
      52              :  * \brief The local part of the Euclidean inner product on the vector space
      53              :  * w.r.t. which the addition and scalar multiplication of both `Lhs` and `Rhs`
      54              :  * is defined.
      55              :  *
      56              :  * \details The linear solver works under the following assumptions:
      57              :  * - The data represented by \p lhs and \p rhs can each be interpreted as the
      58              :  * local chunk of a vector of the same vector space \f$V\f$. _Local_ means there
      59              :  * are vectors \f$q, p\in V\f$ such that \p lhs and \p rhs represent the
      60              :  * components of these vectors w.r.t. a subset \f$B_i\f$ of a basis
      61              :  * \f$B\subset V\f$.
      62              :  * - The `*` and `+` operators of `Lhs` and `Rhs` implement the scalar
      63              :  * multiplication and addition in the vector space _locally_, i.e. restricted to
      64              :  * \f$B_i\f$ in the above sense.
      65              :  * - The inner product is the local part \f$\langle p,q\rangle|_{B_i}\f$ of the
      66              :  * standard Euclidean dot product in the vector space so that globally it is
      67              :  * \f$\langle p,q\rangle=\sum_{i}\langle p,q\rangle|_{B_i}\f$ for
      68              :  * \f$B=\mathop{\dot{\bigcup}}_i B_i\f$.
      69              :  *
      70              :  * In practice this means that the full vectors \f$p\f$ and \f$q\f$ can be
      71              :  * distributed on many elements, where each only holds local chunks \p lhs and
      72              :  * \p rhs of the components. Scalar multiplication and addition can be performed
      73              :  * locally as expected, but computing the full inner product requires a global
      74              :  * reduction over all elements that sums their local `inner_product`s.
      75              :  */
      76              : template <typename Lhs, typename Rhs>
      77            1 : SPECTRE_ALWAYS_INLINE auto inner_product(const Lhs& lhs, const Rhs& rhs) {
      78              :   return InnerProductImpls::InnerProductImpl<Lhs, Rhs>::apply(lhs, rhs);
      79              : }
      80              : 
      81              : /*!
      82              :  * \ingroup LinearSolverGroup
      83              :  * \brief The local part of the Euclidean inner product of a vector with itself.
      84              :  *
      85              :  * \see LinearSolver::inner_product for details on the inner product. This
      86              :  * function just returns the inner product of a vector with itself, and ensures
      87              :  * that the result is real.
      88              :  */
      89              : template <typename T>
      90            1 : SPECTRE_ALWAYS_INLINE double magnitude_square(const T& vector) {
      91              :   auto result =
      92              :       InnerProductImpls::InnerProductImpl<T, T>::apply(vector, vector);
      93              :   if constexpr (std::is_same_v<std::decay_t<decltype(result)>,
      94              :                                std::complex<double>>) {
      95              :     ASSERT(equal_within_roundoff(imag(result), 0.0, 1e-14, abs(result)),
      96              :            "The magnitude squared is not real: " << result);
      97              :     return real(result);
      98              :   } else {
      99              :     return result;
     100              :   }
     101              : }
     102              : 
     103              : }  // namespace LinearSolver
        

Generated by: LCOV version 2.0-1