SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/OdeIntegration - OdeIntegration.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 7.7 % 13 1
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <algorithm>
       7              : #include <array>
       8              : #include <complex>
       9              : #include <cstddef>
      10              : 
      11              : #include "DataStructures/BoostMultiArray.hpp"
      12              : #include "DataStructures/ComplexDataVector.hpp"
      13              : #include "DataStructures/ComplexModalVector.hpp"
      14              : #include "DataStructures/DataVector.hpp"
      15              : #include "DataStructures/ModalVector.hpp"
      16              : #include "DataStructures/VectorImpl.hpp"
      17              : 
      18              : // Boost MultiArray is used internally in odeint, so odeint must be included
      19              : // later
      20              : #include <boost/numeric/odeint.hpp>
      21              : 
      22              : namespace detail {
      23              : struct vector_impl_algebra : boost::numeric::odeint::vector_space_algebra {
      24              :   template <typename VectorType>
      25              :   static double norm_inf(const VectorType& vector) {
      26              :     return max(abs(vector));
      27              :   }
      28              : };
      29              : 
      30              : struct vector_impl_array_algebra : boost::numeric::odeint::array_algebra {
      31              :   template <typename VectorType, size_t Size>
      32              :   static double norm_inf(const std::array<VectorType, Size>& vector_array) {
      33              :     return std::accumulate(
      34              :         vector_array.begin(), vector_array.end(), 0.0,
      35              :         [](const double maximum_so_far, const VectorType& element) {
      36              :           return std::max(maximum_so_far, max(abs(element)));
      37              :         });
      38              :   }
      39              : };
      40              : }  // namespace detail
      41              : 
      42              : namespace boost {
      43              : namespace numeric {
      44              : namespace odeint {
      45              : 
      46              : namespace detail {
      47              : template <typename V>
      48              : struct set_unit_value_impl<ComplexDataVector, V, void> {
      49              :   static void set_value(ComplexDataVector& t, const V& v) {  // NOLINT
      50              :     // this ensures that the blaze expression template resolve the result to a
      51              :     // complex vector
      52              :     t = std::complex<double>(1.0, 0.0) * v;
      53              :   }
      54              : };
      55              : template <typename V>
      56              : struct set_unit_value_impl<ComplexModalVector, V, void> {
      57              :   static void set_value(ComplexModalVector& t, const V& v) {  // NOLINT
      58              :     // this ensures that the blaze expression template resolve the result to a
      59              :     // complex vector
      60              :     t = std::complex<double>(1.0, 0.0) * v;
      61              :   }
      62              : };
      63              : }  // namespace detail
      64              : 
      65              : // In some integration contexts, boost requires the ability to resize the
      66              : // integration arguments in preparation for writing to output buffers passed by
      67              : // reference. These specializations make the resize work correctly with spectre
      68              : // vector types.
      69              : template <class VectorType1, class VectorType2>
      70            0 : struct resize_impl_sfinae<VectorType1, VectorType2,
      71              :                           typename boost::enable_if_c<
      72              :                               is_derived_of_vector_impl_v<VectorType1> and
      73              :                               is_derived_of_vector_impl_v<VectorType2>>::type> {
      74            0 :   static void resize(VectorType1& x1, const VectorType2& x2) {
      75              :     x1.destructive_resize(x2.size());
      76              :   }
      77              : };
      78              : 
      79              : template <class VectorType>
      80            0 : struct is_resizeable_sfinae<
      81              :     VectorType,
      82              :     typename boost::enable_if_c<is_derived_of_vector_impl_v<VectorType>>::type>
      83              :     :
      84              : #if BOOST_VERSION >= 108600
      85              :     std::true_type
      86              : #else
      87              :     boost::true_type
      88              : #endif
      89              : {
      90              : };
      91              : 
      92              : template <>
      93            0 : struct algebra_dispatcher<DataVector> {
      94            0 :   using algebra_type = ::detail::vector_impl_algebra;
      95              : };
      96              : 
      97              : template <>
      98            0 : struct algebra_dispatcher<ComplexDataVector> {
      99            0 :   using algebra_type = ::detail::vector_impl_algebra;
     100              : };
     101              : 
     102              : template <>
     103            0 : struct algebra_dispatcher<ModalVector> {
     104            0 :   using algebra_type = ::detail::vector_impl_algebra;
     105              : };
     106              : 
     107              : template <>
     108            0 : struct algebra_dispatcher<ComplexModalVector> {
     109            0 :   using algebra_type = ::detail::vector_impl_algebra;
     110              : };
     111              : 
     112              : template <size_t Size>
     113              : struct algebra_dispatcher<std::array<DataVector, Size>> {
     114              :   using algebra_type = ::detail::vector_impl_array_algebra;
     115              : };
     116              : 
     117              : template <size_t Size>
     118              : struct algebra_dispatcher<std::array<ComplexDataVector, Size>> {
     119              :   using algebra_type = ::detail::vector_impl_array_algebra;
     120              : };
     121              : 
     122              : template <size_t Size>
     123              : struct algebra_dispatcher<std::array<ModalVector, Size>> {
     124              :   using algebra_type = ::detail::vector_impl_array_algebra;
     125              : };
     126              : 
     127              : template <size_t Size>
     128              : struct algebra_dispatcher<std::array<ComplexModalVector, Size>> {
     129              :   using algebra_type = ::detail::vector_impl_array_algebra;
     130              : };
     131              : }  // namespace odeint
     132              : }  // namespace numeric
     133              : }  // namespace boost
     134              : 
     135              : /*!
     136              :  * \ingroup NumericalAlgorithmsGroup
     137              :  * \brief For ODE integration, we suggest using the boost libraries whenever
     138              :  * possible.
     139              :  *
     140              :  * \details Here we describe briefly the suggested setup to use a boost ODE
     141              :  * integrator in SpECTRE. The boost utilities have a number of more elaborate
     142              :  * features, including features that may result in simpler function calls than
     143              :  * the specific recipes below. For full documentation, see the Boost odeint
     144              :  * documentation:
     145              :  * https://www.boost.org/doc/libs/1_72_0/libs/numeric/odeint/doc/html/boost_numeric_odeint/
     146              :  *
     147              :  * The integration methods can be used largely as in the boost documentation. We
     148              :  * summarize the salient points necessary to get an example running. The main
     149              :  * steps in using a boost integrator are:
     150              :  * - define the system
     151              :  * - construct the stepper
     152              :  * - initialize (might be performed implicitly, depending on the stepper)
     153              :  * - perform steps
     154              :  * - (compute dense output, for dense-output steppers)
     155              :  *
     156              :  * For most cases the Dormand-Prince fifth order controlled, dense-output
     157              :  * stepper is recommended. That stepper is used in the section "SpECTRE vectors
     158              :  * or `std::array` thereof in boost integrators" below.
     159              :  *
     160              :  * #### Fundamental types or `std::array` thereof in fixed-step integrators
     161              :  *
     162              :  * Let us consider a simple oscillator system, which we'll declare as a lambda:
     163              :  *
     164              :  * \snippet Test_OdeIntegration.cpp explicit_fundamental_array_system
     165              :  *
     166              :  * Note that the first argument is a `const` lvalue reference to the state type,
     167              :  * `std::array<double, 2>`, the second argument is an lvalue reference for the
     168              :  * time derivatives that is written to by the system function, and the final
     169              :  * argument is the current time.
     170              :  *
     171              :  * The construction and initialization of the stepper is simple:
     172              :  *
     173              :  * \snippet Test_OdeIntegration.cpp explicit_fundamental_stepper_construction
     174              :  *
     175              :  * Finally, we can perform the steps and examine the output,
     176              :  *
     177              :  * \snippet Test_OdeIntegration.cpp explicit_fundamental_stepper_use
     178              :  *
     179              :  * #### Fundamental types or `std::array` thereof in Dense-output integrators
     180              :  *
     181              :  * The dense-output and controlled-step-size ODE integrators in boost comply
     182              :  * with a somewhat different interface, as significantly more state information
     183              :  * must be managed. The result is a somewhat simpler, but more opaque, interface
     184              :  * to the user code.
     185              :  *
     186              :  * Once again, we start by constructing the system we'd like to integrate,
     187              :  *
     188              :  * \snippet Test_OdeIntegration.cpp dense_output_fundamental_system
     189              :  *
     190              :  * The constructor for dense steppers takes optional arguments for tolerance,
     191              :  * and dense steppers need to be initialized.
     192              :  *
     193              :  * \snippet Test_OdeIntegration.cpp dense_output_fundamental_construction
     194              :  *
     195              :  * It is important to take note of the tolerance arguments, as the defaults are
     196              :  * `1.0e-6`, which is often looser than we want for calculations in SpECTRE.
     197              :  *
     198              :  * We then perform the step supplying the system function, and can retrieve the
     199              :  * dense output state with `calc_state`, which returns by reference by the
     200              :  * second argument.
     201              :  *
     202              :  * \snippet Test_OdeIntegration.cpp dense_output_fundamental_stepper_use
     203              :  *
     204              :  * #### SpECTRE vectors or `std::array` thereof in boost integrators
     205              :  *
     206              :  * The additional template specializations present in the `OdeIntegration.hpp`
     207              :  * file ensure that the boost ODE methods work transparently for SpECTRE vectors
     208              :  * as well. We'll run through a brief example to emphasize the functionality.
     209              :  *
     210              :  * \snippet Test_OdeIntegration.cpp dense_output_vector_stepper
     211              :  */
     212            1 : namespace OdeIntegration {}
        

Generated by: LCOV version 2.0-1