mirror of
https://github.com/boostorg/odeint.git
synced 2025-05-11 05:24:01 +00:00
add max_dt support to generation functions + test
generate function now support additional max_dt parameter for setting the set size limit. Added a test case to check limiter behavior for controlled and dense out integration.
This commit is contained in:
parent
a006cb51fa
commit
6825d7af8b
@ -93,17 +93,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
time_type decrease_step(const time_type dt, const value_type error, const int error_order) const
|
time_type decrease_step(time_type dt, const value_type error, const int error_order) const
|
||||||
{
|
{
|
||||||
BOOST_USING_STD_MIN();
|
BOOST_USING_STD_MIN();
|
||||||
BOOST_USING_STD_MAX();
|
BOOST_USING_STD_MAX();
|
||||||
using std::pow;
|
using std::pow;
|
||||||
|
|
||||||
return dt * max
|
dt *= max
|
||||||
BOOST_PREVENT_MACRO_SUBSTITUTION(
|
BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||||
static_cast<value_type>( static_cast<value_type>(9) / static_cast<value_type>(10) *
|
static_cast<value_type>( static_cast<value_type>(9) / static_cast<value_type>(10) *
|
||||||
pow(error, static_cast<value_type>(-1) / (error_order - 1))),
|
pow(error, static_cast<value_type>(-1) / (error_order - 1))),
|
||||||
static_cast<value_type>( static_cast<value_type>(1) / static_cast<value_type> (5)));
|
static_cast<value_type>( static_cast<value_type>(1) / static_cast<value_type> (5)));
|
||||||
|
if(m_max_dt != static_cast<time_type >(0))
|
||||||
|
// limit to maximal stepsize even when decreasing
|
||||||
|
dt = detail::min_abs(dt, m_max_dt);
|
||||||
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_type increase_step(time_type dt, value_type error, const int stepper_order) const
|
time_type increase_step(time_type dt, value_type error, const int stepper_order) const
|
||||||
@ -113,8 +117,7 @@ public:
|
|||||||
using std::pow;
|
using std::pow;
|
||||||
|
|
||||||
// adjust the size if dt is smaller than max_dt (providede max_dt is not zero)
|
// adjust the size if dt is smaller than max_dt (providede max_dt is not zero)
|
||||||
if(error < 0.5 && (m_max_dt == static_cast<time_type >(0) ||
|
if(error < 0.5)
|
||||||
detail::less_with_sign(dt, m_max_dt, dt)))
|
|
||||||
{
|
{
|
||||||
// error should be > 0
|
// error should be > 0
|
||||||
error = max BOOST_PREVENT_MACRO_SUBSTITUTION (
|
error = max BOOST_PREVENT_MACRO_SUBSTITUTION (
|
||||||
@ -124,12 +127,22 @@ public:
|
|||||||
//error too small - increase dt and keep the evolution and limit scaling factor to 5.0
|
//error too small - increase dt and keep the evolution and limit scaling factor to 5.0
|
||||||
dt *= static_cast<value_type>(9)/static_cast<value_type>(10) *
|
dt *= static_cast<value_type>(9)/static_cast<value_type>(10) *
|
||||||
pow(error, static_cast<value_type>(-1) / stepper_order);
|
pow(error, static_cast<value_type>(-1) / stepper_order);
|
||||||
// limit to maximal stepsize
|
if(m_max_dt != static_cast<time_type >(0))
|
||||||
dt = detail::max_abs(dt, m_max_dt);
|
// limit to maximal stepsize
|
||||||
|
dt = detail::min_abs(dt, m_max_dt);
|
||||||
}
|
}
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_step_size_limit(const time_type dt)
|
||||||
|
{
|
||||||
|
if(m_max_dt != static_cast<time_type >(0))
|
||||||
|
return detail::less_eq_with_sign(dt, m_max_dt, dt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_type get_max_dt() { return m_max_dt; }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -380,6 +393,12 @@ public:
|
|||||||
template< class System , class StateIn , class DerivIn , class StateOut >
|
template< class System , class StateIn , class DerivIn , class StateOut >
|
||||||
controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , time_type &dt )
|
controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt , time_type &t , StateOut &out , time_type &dt )
|
||||||
{
|
{
|
||||||
|
if( !m_error_checker.check_step_size_limit(dt) )
|
||||||
|
{
|
||||||
|
// given dt was above step size limit - adjust and return fail;
|
||||||
|
dt = m_error_checker.get_max_dt();
|
||||||
|
return fail;
|
||||||
|
}
|
||||||
|
|
||||||
m_xerr_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_xerr_impl< StateIn > , detail::ref( *this ) , detail::_1 ) );
|
m_xerr_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_xerr_impl< StateIn > , detail::ref( *this ) , detail::_1 ) );
|
||||||
|
|
||||||
@ -710,10 +729,12 @@ public:
|
|||||||
controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt_in , time_type &t ,
|
controlled_step_result try_step( System system , const StateIn &in , const DerivIn &dxdt_in , time_type &t ,
|
||||||
StateOut &out , DerivOut &dxdt_out , time_type &dt )
|
StateOut &out , DerivOut &dxdt_out , time_type &dt )
|
||||||
{
|
{
|
||||||
BOOST_USING_STD_MIN();
|
if( !m_error_checker.check_step_size_limit(dt) )
|
||||||
BOOST_USING_STD_MAX();
|
{
|
||||||
|
// given dt was above step size limit - adjust and return fail;
|
||||||
using std::pow;
|
dt = m_error_checker.get_max_dt();
|
||||||
|
return fail;
|
||||||
|
}
|
||||||
|
|
||||||
m_xerr_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_xerr_impl< StateIn > , detail::ref( *this ) , detail::_1 ) );
|
m_xerr_resizer.adjust_size( in , detail::bind( &controlled_runge_kutta::template resize_m_xerr_impl< StateIn > , detail::ref( *this ) , detail::_1 ) );
|
||||||
|
|
||||||
|
@ -35,16 +35,21 @@ struct controller_factory< Stepper , controlled_runge_kutta< Stepper > >
|
|||||||
typedef controlled_runge_kutta< stepper_type > controller_type;
|
typedef controlled_runge_kutta< stepper_type > controller_type;
|
||||||
typedef typename controller_type::error_checker_type error_checker_type;
|
typedef typename controller_type::error_checker_type error_checker_type;
|
||||||
typedef typename stepper_type::value_type value_type;
|
typedef typename stepper_type::value_type value_type;
|
||||||
|
typedef typename stepper_type::value_type time_type;
|
||||||
|
|
||||||
controller_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper )
|
controller_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper )
|
||||||
{
|
{
|
||||||
return controller_type( error_checker_type( abs_error , rel_error ) , stepper );
|
return controller_type( error_checker_type( abs_error , rel_error ) , stepper );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controller_type operator()( value_type abs_error , value_type rel_error ,
|
||||||
|
time_type max_dt, const stepper_type &stepper )
|
||||||
|
{
|
||||||
|
return controller_type( error_checker_type( abs_error , rel_error , 1, 1, max_dt) , stepper );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // odeint
|
} // odeint
|
||||||
} // numeric
|
} // numeric
|
||||||
} // boost
|
} // boost
|
||||||
|
@ -34,12 +34,21 @@ struct dense_output_factory< Stepper , dense_output_runge_kutta< controlled_rung
|
|||||||
typedef controlled_runge_kutta< stepper_type > controller_type;
|
typedef controlled_runge_kutta< stepper_type > controller_type;
|
||||||
typedef typename controller_type::error_checker_type error_checker_type;
|
typedef typename controller_type::error_checker_type error_checker_type;
|
||||||
typedef typename stepper_type::value_type value_type;
|
typedef typename stepper_type::value_type value_type;
|
||||||
|
typedef typename stepper_type::time_type time_type;
|
||||||
typedef dense_output_runge_kutta< controller_type > dense_output_type;
|
typedef dense_output_runge_kutta< controller_type > dense_output_type;
|
||||||
|
|
||||||
dense_output_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper )
|
dense_output_type operator()( value_type abs_error , value_type rel_error , const stepper_type &stepper )
|
||||||
{
|
{
|
||||||
return dense_output_type( controller_type( error_checker_type( abs_error , rel_error ) , stepper ) );
|
return dense_output_type( controller_type( error_checker_type( abs_error , rel_error ) , stepper ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dense_output_type operator()( value_type abs_error , value_type rel_error ,
|
||||||
|
time_type max_dt , const stepper_type &stepper )
|
||||||
|
{
|
||||||
|
return dense_output_type(
|
||||||
|
controller_type( error_checker_type( abs_error , rel_error , 1, 1, max_dt) ,
|
||||||
|
stepper ) );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,15 @@ struct controller_factory
|
|||||||
{
|
{
|
||||||
return Controller( abs_error , rel_error , stepper );
|
return Controller( abs_error , rel_error , stepper );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Controller operator()(
|
||||||
|
typename Stepper::value_type abs_error ,
|
||||||
|
typename Stepper::value_type rel_error ,
|
||||||
|
typename Stepper::time_type max_dt ,
|
||||||
|
const Stepper &stepper )
|
||||||
|
{
|
||||||
|
return Controller( abs_error , rel_error , max_dt, stepper );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -72,6 +81,19 @@ typename result_of::make_controlled< Stepper >::type make_controlled(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< class Stepper >
|
||||||
|
typename result_of::make_controlled< Stepper >::type make_controlled(
|
||||||
|
typename Stepper::value_type abs_error ,
|
||||||
|
typename Stepper::value_type rel_error ,
|
||||||
|
typename Stepper::time_type max_dt ,
|
||||||
|
const Stepper & stepper = Stepper() )
|
||||||
|
{
|
||||||
|
typedef Stepper stepper_type;
|
||||||
|
typedef typename result_of::make_controlled< stepper_type >::type controller_type;
|
||||||
|
typedef controller_factory< stepper_type , controller_type > factory_type;
|
||||||
|
factory_type factory;
|
||||||
|
return factory( abs_error , rel_error , max_dt, stepper );
|
||||||
|
}
|
||||||
|
|
||||||
} // odeint
|
} // odeint
|
||||||
} // numeric
|
} // numeric
|
||||||
|
@ -39,6 +39,15 @@ struct dense_output_factory
|
|||||||
{
|
{
|
||||||
return DenseOutput( abs_error , rel_error , stepper );
|
return DenseOutput( abs_error , rel_error , stepper );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DenseOutput operator()(
|
||||||
|
typename Stepper::value_type abs_error ,
|
||||||
|
typename Stepper::value_type rel_error ,
|
||||||
|
typename Stepper::time_type max_dt ,
|
||||||
|
const Stepper &stepper )
|
||||||
|
{
|
||||||
|
return DenseOutput( abs_error , rel_error , max_dt , stepper );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -68,6 +77,19 @@ typename result_of::make_dense_output< Stepper >::type make_dense_output(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< class Stepper >
|
||||||
|
typename result_of::make_dense_output< Stepper >::type make_dense_output(
|
||||||
|
typename Stepper::value_type abs_error ,
|
||||||
|
typename Stepper::value_type rel_error ,
|
||||||
|
typename Stepper::time_type max_dt ,
|
||||||
|
const Stepper &stepper = Stepper() )
|
||||||
|
{
|
||||||
|
typedef Stepper stepper_type;
|
||||||
|
typedef typename result_of::make_dense_output< stepper_type >::type dense_output_type;
|
||||||
|
typedef dense_output_factory< stepper_type , dense_output_type > factory_type;
|
||||||
|
factory_type factory;
|
||||||
|
return factory( abs_error , rel_error , max_dt, stepper );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // odeint
|
} // odeint
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
Helper function to compare times taking into account the sign of dt
|
Helper function to compare times taking into account the sign of dt
|
||||||
[end_description]
|
[end_description]
|
||||||
|
|
||||||
Copyright 2012-2013 Mario Mulansky
|
Copyright 2012-2015 Mario Mulansky
|
||||||
Copyright 2012 Karsten Ahnert
|
Copyright 2012 Karsten Ahnert
|
||||||
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
@ -78,6 +78,7 @@ test-suite "odeint"
|
|||||||
[ run n_step_time_iterator.cpp ]
|
[ run n_step_time_iterator.cpp ]
|
||||||
[ run times_iterator.cpp ]
|
[ run times_iterator.cpp ]
|
||||||
[ run times_time_iterator.cpp ]
|
[ run times_time_iterator.cpp ]
|
||||||
|
[ run step_size_limitation.cpp ]
|
||||||
[ compile unwrap_boost_reference.cpp ]
|
[ compile unwrap_boost_reference.cpp ]
|
||||||
[ compile unwrap_reference.cpp : <cxxflags>-std=c++0x : unwrap_reference_C++11 ]
|
[ compile unwrap_reference.cpp : <cxxflags>-std=c++0x : unwrap_reference_C++11 ]
|
||||||
[ compile-fail unwrap_reference.cpp : <cxxflags>-std=c++98 : unwrap_reference_C++98 ]
|
[ compile-fail unwrap_reference.cpp : <cxxflags>-std=c++98 : unwrap_reference_C++98 ]
|
||||||
|
179
test/step_size_limitation.cpp
Normal file
179
test/step_size_limitation.cpp
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
[auto_generated]
|
||||||
|
libs/numeric/odeint/test/step_size_limitation.cpp
|
||||||
|
|
||||||
|
[begin_description]
|
||||||
|
Tests the step size limitation functionality
|
||||||
|
[end_description]
|
||||||
|
|
||||||
|
Copyright 2015 Mario Mulansky
|
||||||
|
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or
|
||||||
|
copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BOOST_TEST_MODULE odeint_integrate_times
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/numeric/odeint.hpp>
|
||||||
|
|
||||||
|
using namespace boost::unit_test;
|
||||||
|
using namespace boost::numeric::odeint;
|
||||||
|
|
||||||
|
typedef double value_type;
|
||||||
|
typedef std::vector< value_type > state_type;
|
||||||
|
|
||||||
|
|
||||||
|
void lorenz( const state_type &x , state_type &dxdt , const value_type t )
|
||||||
|
{
|
||||||
|
BOOST_CHECK( t >= 0.0 );
|
||||||
|
|
||||||
|
const value_type sigma( 10.0 );
|
||||||
|
const value_type R( 28.0 );
|
||||||
|
const value_type b( value_type( 8.0 ) / value_type( 3.0 ) );
|
||||||
|
|
||||||
|
dxdt[0] = sigma * ( x[1] - x[0] );
|
||||||
|
dxdt[1] = R * x[0] - x[1] - x[0] * x[2];
|
||||||
|
dxdt[2] = -b * x[2] + x[0] * x[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct push_back_time
|
||||||
|
{
|
||||||
|
std::vector< double >& m_times;
|
||||||
|
|
||||||
|
push_back_time( std::vector< double > × )
|
||||||
|
: m_times( times ) { }
|
||||||
|
|
||||||
|
void operator()( const state_type &x , double t )
|
||||||
|
{
|
||||||
|
m_times.push_back( t );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE( step_size_limitation_test )
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( test_error_checker )
|
||||||
|
{
|
||||||
|
// first use checker without step size limitation
|
||||||
|
default_error_checker<double, double, range_algebra, default_operations> checker;
|
||||||
|
const double dt = 0.1;
|
||||||
|
double dt_new = checker.decrease_step(dt, 1.5, 2);
|
||||||
|
BOOST_CHECK(dt_new < dt*2.0/3.0);
|
||||||
|
|
||||||
|
dt_new = checker.increase_step(dt, 0.8, 1);
|
||||||
|
// for errors > 0.5 no increase is performed
|
||||||
|
BOOST_CHECK(dt_new == dt);
|
||||||
|
|
||||||
|
dt_new = checker.increase_step(dt, 0.4, 1);
|
||||||
|
// smaller errors should lead to step size increase
|
||||||
|
std::cout << dt_new << std::endl;
|
||||||
|
BOOST_CHECK(dt_new > dt);
|
||||||
|
|
||||||
|
|
||||||
|
// now test with step size limitation max_dt = 0.1
|
||||||
|
default_error_checker<double, double, range_algebra, default_operations>
|
||||||
|
limited_checker(1E-6, 1E-6, 1, 1, dt);
|
||||||
|
|
||||||
|
dt_new = limited_checker.decrease_step(dt, 1.5, 2);
|
||||||
|
// decreasing works as before
|
||||||
|
BOOST_CHECK(dt_new < dt*2.0/3.0);
|
||||||
|
|
||||||
|
dt_new = limited_checker.decrease_step(2*dt, 1.1, 2);
|
||||||
|
// decreasing a large step size should give max_dt
|
||||||
|
BOOST_CHECK(dt_new == dt);
|
||||||
|
|
||||||
|
dt_new = limited_checker.increase_step(dt, 0.8, 1);
|
||||||
|
// for errors > 0.5 no increase is performed, still valid
|
||||||
|
BOOST_CHECK(dt_new == dt);
|
||||||
|
|
||||||
|
dt_new = limited_checker.increase_step(dt, 0.4, 1);
|
||||||
|
// but even for smaller errors, we should at most get 0.1
|
||||||
|
BOOST_CHECK(dt_new == dt);
|
||||||
|
|
||||||
|
dt_new = limited_checker.increase_step(0.9*dt, 0.1, 1);
|
||||||
|
std::cout << dt_new << std::endl;
|
||||||
|
// check that we don't increase beyond max_dt
|
||||||
|
BOOST_CHECK(dt_new == dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( test_controlled )
|
||||||
|
{
|
||||||
|
state_type x( 3 );
|
||||||
|
x[0] = x[1] = x[2] = 10.0;
|
||||||
|
const double max_dt = 0.01;
|
||||||
|
|
||||||
|
std::vector<double> times;
|
||||||
|
|
||||||
|
integrate_adaptive(make_controlled(1E-2, 1E-2, max_dt, runge_kutta_dopri5<state_type>()),
|
||||||
|
lorenz, x, 0.0, 1.0, max_dt, push_back_time(times));
|
||||||
|
// check that dt remains at exactly max_dt
|
||||||
|
for( size_t i=0 ; i<times.size() ; ++i )
|
||||||
|
// check if observer was called at times 0,1,2,...
|
||||||
|
BOOST_CHECK_SMALL( times[i] - static_cast<double>(i)*max_dt , 1E-15);
|
||||||
|
times.clear();
|
||||||
|
|
||||||
|
// this should also work when we provide some bigger initial dt
|
||||||
|
integrate_adaptive(make_controlled(1E-2, 1E-2, max_dt, runge_kutta_dopri5<state_type>()),
|
||||||
|
lorenz, x, 0.0, 1.0, 0.1, push_back_time(times));
|
||||||
|
// check that dt remains at exactly max_dt
|
||||||
|
for( size_t i=0 ; i<times.size() ; ++i )
|
||||||
|
// check if observer was called at times 0,1,2,...
|
||||||
|
BOOST_CHECK_SMALL( times[i] - static_cast<double>(i)*max_dt , 1E-15);
|
||||||
|
times.clear();
|
||||||
|
|
||||||
|
// check this behavior with cash karp
|
||||||
|
integrate_adaptive(make_controlled(1E-2, 1E-2, max_dt, runge_kutta_cash_karp54<state_type>()),
|
||||||
|
lorenz, x, 0.0, 1.0, max_dt, push_back_time(times));
|
||||||
|
// check that dt remains at exactly max_dt
|
||||||
|
for( size_t i=0 ; i<times.size() ; ++i )
|
||||||
|
// check if observer was called at times 0,1,2,...
|
||||||
|
BOOST_CHECK_SMALL( times[i] - static_cast<double>(i)*max_dt , 1E-15);
|
||||||
|
times.clear();
|
||||||
|
|
||||||
|
// this should also work when we provide some bigger initial dt
|
||||||
|
integrate_adaptive(make_controlled(1E-2, 1E-2, max_dt, runge_kutta_cash_karp54<state_type>()),
|
||||||
|
lorenz, x, 0.0, 1.0, 0.1, push_back_time(times));
|
||||||
|
// check that dt remains at exactly max_dt
|
||||||
|
for( size_t i=0 ; i<times.size() ; ++i )
|
||||||
|
// check if observer was called at times 0,1,2,...
|
||||||
|
BOOST_CHECK_SMALL( times[i] - static_cast<double>(i)*max_dt , 1E-15);
|
||||||
|
times.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( test_dense_out )
|
||||||
|
{
|
||||||
|
state_type x( 3 );
|
||||||
|
x[0] = x[1] = x[2] = 10.0;
|
||||||
|
const double max_dt = 0.01;
|
||||||
|
|
||||||
|
std::vector<double> times;
|
||||||
|
|
||||||
|
integrate_adaptive(make_dense_output(1E-2, 1E-2, max_dt, runge_kutta_dopri5<state_type>()),
|
||||||
|
lorenz, x, 0.0, 1.0, max_dt, push_back_time(times));
|
||||||
|
// check that dt remains at exactly max_dt
|
||||||
|
for( size_t i=0 ; i<times.size() ; ++i )
|
||||||
|
// check if observer was called at times 0,1,2,...
|
||||||
|
BOOST_CHECK_SMALL( times[i] - static_cast<double>(i)*max_dt , 1E-15);
|
||||||
|
times.clear();
|
||||||
|
|
||||||
|
// this should also work when we provide some bigger initial dt
|
||||||
|
integrate_adaptive(make_dense_output(1E-2, 1E-2, max_dt, runge_kutta_dopri5<state_type>()),
|
||||||
|
lorenz, x, 0.0, 1.0, 0.1, push_back_time(times));
|
||||||
|
// check that dt remains at exactly max_dt
|
||||||
|
for( size_t i=0 ; i<times.size() ; ++i )
|
||||||
|
// check if observer was called at times 0,1,2,...
|
||||||
|
BOOST_CHECK_SMALL( times[i] - static_cast<double>(i)*max_dt , 1E-15);
|
||||||
|
times.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
x
Reference in New Issue
Block a user