File indexing completed on 2025-01-18 09:42:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAPTIVE_ADAMS_COEFFICIENTS_HPP_INCLUDED
0016 #define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_ADAPTIVE_ADAMS_COEFFICIENTS_HPP_INCLUDED
0017
0018 #include <boost/numeric/odeint/stepper/detail/rotating_buffer.hpp>
0019
0020 #include <boost/numeric/odeint/util/state_wrapper.hpp>
0021 #include <boost/numeric/odeint/util/is_resizeable.hpp>
0022 #include <boost/numeric/odeint/util/resizer.hpp>
0023
0024 #include <boost/numeric/odeint/util/unwrap_reference.hpp>
0025 #include <boost/numeric/odeint/util/bind.hpp>
0026
0027 #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
0028 #include <boost/numeric/odeint/algebra/operations_dispatcher.hpp>
0029
0030 #include <boost/array.hpp>
0031
0032 namespace boost {
0033 namespace numeric {
0034 namespace odeint {
0035 namespace detail {
0036
0037 template<
0038 size_t Steps,
0039 class Deriv,
0040 class Value = double,
0041 class Time = double,
0042 class Algebra = typename algebra_dispatcher< Deriv >::algebra_type,
0043 class Operations = typename operations_dispatcher< Deriv >::operations_type,
0044 class Resizer = initially_resizer
0045 >
0046 class adaptive_adams_coefficients
0047 {
0048 public:
0049 static const size_t steps = Steps;
0050
0051 typedef unsigned short order_type;
0052 static const order_type order_value = steps;
0053
0054 typedef Value value_type;
0055 typedef Deriv deriv_type;
0056 typedef Time time_type;
0057
0058 typedef state_wrapper< deriv_type > wrapped_deriv_type;
0059 typedef rotating_buffer< time_type , steps+1 > time_storage_type;
0060
0061 typedef Algebra algebra_type;
0062 typedef Operations operations_type;
0063 typedef Resizer resizer_type;
0064
0065 typedef adaptive_adams_coefficients< Steps , Deriv , Value , Time , Algebra , Operations , Resizer > aac_type;
0066
0067 adaptive_adams_coefficients( const algebra_type &algebra = algebra_type())
0068 :m_eo(1), m_steps_init(1), beta(), phi(), m_ns(0), m_time_storage(),
0069 m_algebra(algebra),
0070 m_phi_resizer()
0071 {
0072 for (size_t i=0; i<order_value+2; ++i)
0073 {
0074 c[i] = 1.0/(i+1);
0075 c[c_size+i] = 1.0/((i+1)*(i+2));
0076 }
0077
0078 g[0] = c[0];
0079 g[1] = c[c_size];
0080
0081 beta[0][0] = 1;
0082 beta[1][0] = 1;
0083
0084 gs[0] = 1.0;
0085 gs[1] = -1.0/2;
0086 gs[2] = -1.0/12;
0087 gs[3] = -1.0/24;
0088 gs[4] = -19.0/720;
0089 gs[5] = -3.0/160;
0090 gs[6] = -863.0/60480;
0091 gs[7] = -275.0/24192;
0092 gs[8] = -33953.0/3628800;
0093 gs[9] = 35.0/4436;
0094 gs[10] = 40.0/5891;
0095 gs[11] = 37.0/6250;
0096 gs[12] = 25.0/4771;
0097 gs[13] = 40.0/8547;
0098 };
0099
0100 void predict(time_type t, time_type dt)
0101 {
0102 using std::abs;
0103
0104 m_time_storage[0] = t;
0105
0106 if (abs(m_time_storage[0] - m_time_storage[1] - dt) > 1e-16 || m_eo >= m_ns)
0107 {
0108 m_ns = 0;
0109 }
0110 else if (m_ns < order_value + 2)
0111 {
0112 m_ns++;
0113 }
0114
0115 for(size_t i=1+m_ns; i<m_eo+1 && i<m_steps_init; ++i)
0116 {
0117 time_type diff = m_time_storage[0] - m_time_storage[i];
0118 beta[0][i] = beta[0][i-1]*(m_time_storage[0] + dt - m_time_storage[i-1])/diff;
0119 }
0120
0121 for(size_t i=2+m_ns; i<m_eo+2 && i<m_steps_init+1; ++i)
0122 {
0123 time_type diff = m_time_storage[0] + dt - m_time_storage[i-1];
0124 for(size_t j=0; j<m_eo+1-i+1; ++j)
0125 {
0126 c[c_size*i+j] = c[c_size*(i-1)+j] - c[c_size*(i-1)+j+1]*dt/diff;
0127 }
0128
0129 g[i] = c[c_size*i];
0130 }
0131 };
0132
0133 void do_step(const deriv_type &dxdt, const int o = 0)
0134 {
0135 m_phi_resizer.adjust_size( dxdt , detail::bind( &aac_type::template resize_phi_impl< deriv_type > , detail::ref( *this ) , detail::_1 ) );
0136
0137 phi[o][0].m_v = dxdt;
0138
0139 for(size_t i=1; i<m_eo+3 && i<m_steps_init+2 && i<order_value+2; ++i)
0140 {
0141 if (o == 0)
0142 {
0143 this->m_algebra.for_each3(phi[o][i].m_v, phi[o][i-1].m_v, phi[o+1][i-1].m_v,
0144 typename Operations::template scale_sum2<value_type, value_type>(1.0, -beta[o][i-1]));
0145 }
0146 else
0147 {
0148 this->m_algebra.for_each2(phi[o][i].m_v, phi[o][i-1].m_v,
0149 typename Operations::template scale_sum1<value_type>(1.0));
0150 }
0151 }
0152 };
0153
0154 void confirm()
0155 {
0156 beta.rotate();
0157 phi.rotate();
0158 m_time_storage.rotate();
0159
0160 if(m_steps_init < order_value+1)
0161 {
0162 ++m_steps_init;
0163 }
0164 };
0165
0166 void reset() { m_eo = 1; m_steps_init = 1; };
0167
0168 size_t m_eo;
0169 size_t m_steps_init;
0170
0171 rotating_buffer<boost::array<value_type, order_value+1>, 2> beta;
0172 rotating_buffer<boost::array<wrapped_deriv_type, order_value+2>, 3> phi;
0173 boost::array<value_type, order_value + 2> g;
0174 boost::array<value_type, 14> gs;
0175
0176 private:
0177 template< class StateType >
0178 bool resize_phi_impl( const StateType &x )
0179 {
0180 bool resized( false );
0181
0182 for(size_t i=0; i<(order_value + 2); ++i)
0183 {
0184 resized |= adjust_size_by_resizeability( phi[0][i], x, typename is_resizeable<deriv_type>::type() );
0185 resized |= adjust_size_by_resizeability( phi[1][i], x, typename is_resizeable<deriv_type>::type() );
0186 resized |= adjust_size_by_resizeability( phi[2][i], x, typename is_resizeable<deriv_type>::type() );
0187 }
0188 return resized;
0189 };
0190
0191 size_t m_ns;
0192
0193 time_storage_type m_time_storage;
0194 static const size_t c_size = order_value + 2;
0195 boost::array<value_type, c_size*c_size> c;
0196
0197 algebra_type m_algebra;
0198
0199 resizer_type m_phi_resizer;
0200 };
0201
0202 }
0203 }
0204 }
0205 }
0206
0207 #endif