File indexing completed on 2025-09-17 08:53:38
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Types.hh"
0010 #include "corecel/math/Algorithms.hh"
0011
0012 #include "Types.hh"
0013
0014 #include "detail/FieldUtils.hh"
0015
0016 namespace celeritas
0017 {
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 template<class EquationT>
0046 class RungeKuttaIntegrator
0047 {
0048 public:
0049
0050
0051 using result_type = FieldIntegration;
0052
0053
0054 public:
0055
0056 explicit CELER_FUNCTION RungeKuttaIntegrator(EquationT&& eq)
0057 : calc_rhs_(::celeritas::forward<EquationT>(eq))
0058 {
0059 }
0060
0061
0062 CELER_FUNCTION result_type operator()(real_type step,
0063 OdeState const& beg_state) const;
0064
0065 private:
0066
0067 CELER_FUNCTION auto do_step(real_type step,
0068 OdeState const& beg_state,
0069 OdeState const& end_slope) const -> OdeState;
0070
0071 private:
0072
0073 EquationT calc_rhs_;
0074 };
0075
0076
0077
0078
0079 template<class EquationT>
0080 CELER_FUNCTION
0081 RungeKuttaIntegrator(EquationT&&) -> RungeKuttaIntegrator<EquationT>;
0082
0083
0084
0085
0086
0087
0088
0089 template<class E>
0090 CELER_FUNCTION auto RungeKuttaIntegrator<E>::operator()(
0091 real_type step, OdeState const& beg_state) const -> result_type
0092 {
0093 using celeritas::axpy;
0094 real_type half_step = step / real_type(2);
0095 constexpr real_type fourth_order_correction = 1 / real_type(15);
0096
0097 result_type result;
0098 OdeState beg_slope = calc_rhs_(beg_state);
0099
0100
0101 result.mid_state = this->do_step(half_step, beg_state, beg_slope);
0102 result.end_state = this->do_step(
0103 half_step, result.mid_state, calc_rhs_(result.mid_state));
0104
0105
0106 OdeState yt = this->do_step(step, beg_state, beg_slope);
0107
0108
0109 result.err_state = result.end_state;
0110 axpy(real_type(-1), yt, &result.err_state);
0111
0112
0113 axpy(fourth_order_correction, result.err_state, &result.end_state);
0114
0115 return result;
0116 }
0117
0118
0119
0120
0121
0122 template<class E>
0123 CELER_FUNCTION auto
0124 RungeKuttaIntegrator<E>::do_step(real_type step,
0125 OdeState const& beg_state,
0126 OdeState const& beg_slope) const -> OdeState
0127 {
0128 using celeritas::axpy;
0129 real_type half_step = step / real_type(2);
0130 constexpr real_type sixth = 1 / real_type(6);
0131
0132
0133 OdeState mid_est = beg_state;
0134 axpy(half_step, beg_slope, &mid_est);
0135 OdeState mid_est_slope = calc_rhs_(mid_est);
0136
0137
0138 OdeState mid_state = beg_state;
0139 axpy(half_step, mid_est_slope, &mid_state);
0140 OdeState mid_slope = calc_rhs_(mid_state);
0141
0142
0143 OdeState end_est = beg_state;
0144 axpy(step, mid_slope, &end_est);
0145 OdeState end_slope = calc_rhs_(end_est);
0146
0147
0148 axpy(real_type(1), beg_slope, &end_slope);
0149 axpy(real_type(2), mid_slope, &end_slope);
0150 axpy(real_type(2), mid_est_slope, &end_slope);
0151
0152
0153 OdeState end_state = beg_state;
0154 axpy(sixth * step, end_slope, &end_state);
0155
0156 return end_state;
0157 }
0158
0159
0160 }