mirror of
https://github.com/boostorg/odeint.git
synced 2025-05-11 13:34:09 +00:00
added overflow exception to other integrate funcs
following the previous additions for integrate_const now also integrate_n_steps and integrate_times support max_step overflow exceptions.
This commit is contained in:
parent
44576c3dab
commit
fa6a914f1a
@ -7,7 +7,7 @@
|
|||||||
[end_description]
|
[end_description]
|
||||||
|
|
||||||
Copyright 2011-2013 Karsten Ahnert
|
Copyright 2011-2013 Karsten Ahnert
|
||||||
Copyright 2011-2012 Mario Mulansky
|
Copyright 2011-2015 Mario Mulansky
|
||||||
Copyright 2012 Christoph Koke
|
Copyright 2012 Christoph Koke
|
||||||
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
integrate const implementation
|
integrate const implementation
|
||||||
[end_description]
|
[end_description]
|
||||||
|
|
||||||
Copyright 2012 Mario Mulansky
|
Copyright 2012-2015 Mario Mulansky
|
||||||
Copyright 2012 Christoph Koke
|
Copyright 2012 Christoph Koke
|
||||||
Copyright 2012 Karsten Ahnert
|
Copyright 2012 Karsten Ahnert
|
||||||
|
|
||||||
@ -92,8 +92,9 @@ size_t integrate_const(
|
|||||||
obs( start_state , time );
|
obs( start_state , time );
|
||||||
chk.reset(); // reset after each observation
|
chk.reset(); // reset after each observation
|
||||||
// integrate_adaptive_checked uses the given checker to throw if an overflow occurs
|
// integrate_adaptive_checked uses the given checker to throw if an overflow occurs
|
||||||
real_steps += detail::integrate_adaptive_checked( stepper , system , start_state , time , time+time_step , dt ,
|
real_steps += detail::integrate_adaptive_checked(stepper, system, start_state, time,
|
||||||
null_observer() , checker );
|
static_cast<Time>(time + time_step), dt,
|
||||||
|
null_observer(), checker);
|
||||||
// direct computation of the time avoids error propagation happening when using time += dt
|
// direct computation of the time avoids error propagation happening when using time += dt
|
||||||
// we need clumsy type analysis to get boost units working here
|
// we need clumsy type analysis to get boost units working here
|
||||||
step++;
|
step++;
|
||||||
|
@ -31,20 +31,20 @@ namespace odeint {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// forward declaration
|
// forward declaration
|
||||||
template< class Stepper , class System , class State , class Time , class Observer >
|
template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker >
|
||||||
size_t integrate_adaptive(
|
size_t integrate_adaptive_checked(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
Time &start_time , Time end_time , Time &dt ,
|
Time &start_time , Time end_time , Time &dt ,
|
||||||
Observer observer , controlled_stepper_tag
|
Observer observer , StepOverflowChecker checker
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/* basic version */
|
/* basic version */
|
||||||
template< class Stepper , class System , class State , class Time , class Observer>
|
template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker >
|
||||||
Time integrate_n_steps(
|
Time integrate_n_steps(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
Time start_time , Time dt , size_t num_of_steps ,
|
Time start_time , Time dt , size_t num_of_steps ,
|
||||||
Observer observer , stepper_tag )
|
Observer observer , StepOverflowChecker /* checker */ , stepper_tag )
|
||||||
{
|
{
|
||||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||||
@ -66,13 +66,14 @@ Time integrate_n_steps(
|
|||||||
|
|
||||||
|
|
||||||
/* controlled version */
|
/* controlled version */
|
||||||
template< class Stepper , class System , class State , class Time , class Observer>
|
template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker >
|
||||||
Time integrate_n_steps(
|
Time integrate_n_steps(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
Time start_time , Time dt , size_t num_of_steps ,
|
Time start_time , Time dt , size_t num_of_steps ,
|
||||||
Observer observer , controlled_stepper_tag )
|
Observer observer , StepOverflowChecker checker , controlled_stepper_tag )
|
||||||
{
|
{
|
||||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||||
|
typename odeint::unwrap_reference< StepOverflowChecker >::type &chk = checker;
|
||||||
|
|
||||||
Time time = start_time;
|
Time time = start_time;
|
||||||
Time time_step = dt;
|
Time time_step = dt;
|
||||||
@ -80,8 +81,10 @@ Time integrate_n_steps(
|
|||||||
for( size_t step = 0; step < num_of_steps ; ++step )
|
for( size_t step = 0; step < num_of_steps ; ++step )
|
||||||
{
|
{
|
||||||
obs( start_state , time );
|
obs( start_state , time );
|
||||||
detail::integrate_adaptive( stepper , system , start_state , time , static_cast<Time>(time+time_step) , dt ,
|
chk.reset(); // reset after each observation
|
||||||
null_observer() , controlled_stepper_tag() );
|
// integrate_adaptive_checked uses the given checker to throw if an overflow occurs
|
||||||
|
detail::integrate_adaptive_checked(stepper, system, start_state, time, static_cast<Time>(time + time_step), dt,
|
||||||
|
null_observer(), checker);
|
||||||
// direct computation of the time avoids error propagation happening when using time += dt
|
// direct computation of the time avoids error propagation happening when using time += dt
|
||||||
// we need clumsy type analysis to get boost units working here
|
// we need clumsy type analysis to get boost units working here
|
||||||
time = start_time + static_cast< typename unit_value_type<Time>::type >(step+1) * time_step;
|
time = start_time + static_cast< typename unit_value_type<Time>::type >(step+1) * time_step;
|
||||||
@ -93,14 +96,15 @@ Time integrate_n_steps(
|
|||||||
|
|
||||||
|
|
||||||
/* dense output version */
|
/* dense output version */
|
||||||
template< class Stepper , class System , class State , class Time , class Observer>
|
template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker >
|
||||||
Time integrate_n_steps(
|
Time integrate_n_steps(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
Time start_time , Time dt , size_t num_of_steps ,
|
Time start_time , Time dt , size_t num_of_steps ,
|
||||||
Observer observer , dense_output_stepper_tag )
|
Observer observer , StepOverflowChecker checker , dense_output_stepper_tag )
|
||||||
{
|
{
|
||||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||||
|
typename odeint::unwrap_reference< StepOverflowChecker >::type &chk = checker;
|
||||||
|
|
||||||
Time time = start_time;
|
Time time = start_time;
|
||||||
const Time end_time = start_time + static_cast< typename unit_value_type<Time>::type >(num_of_steps) * dt;
|
const Time end_time = start_time + static_cast< typename unit_value_type<Time>::type >(num_of_steps) * dt;
|
||||||
@ -115,6 +119,7 @@ Time integrate_n_steps(
|
|||||||
{
|
{
|
||||||
st.calc_state( time , start_state );
|
st.calc_state( time , start_state );
|
||||||
obs( start_state , time );
|
obs( start_state , time );
|
||||||
|
chk.reset(); // reset checker after every observer call
|
||||||
++step;
|
++step;
|
||||||
// direct computation of the time avoids error propagation happening when using time += dt
|
// direct computation of the time avoids error propagation happening when using time += dt
|
||||||
// we need clumsy type analysis to get boost units working here
|
// we need clumsy type analysis to get boost units working here
|
||||||
@ -127,14 +132,17 @@ Time integrate_n_steps(
|
|||||||
st.current_time_step() ) )
|
st.current_time_step() ) )
|
||||||
{
|
{
|
||||||
st.do_step( system );
|
st.do_step( system );
|
||||||
|
chk(); // potential check for too much work exception
|
||||||
}
|
}
|
||||||
else if( less_with_sign( st.current_time() , end_time , st.current_time_step() ) )
|
else if( less_with_sign( st.current_time() , end_time , st.current_time_step() ) )
|
||||||
{ // do the last step ending exactly on the end point
|
{ // do the last step ending exactly on the end point
|
||||||
st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) );
|
st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) );
|
||||||
st.do_step( system );
|
st.do_step( system );
|
||||||
|
chk();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure we really end exactly where we should end
|
||||||
while( st.current_time() < end_time )
|
while( st.current_time() < end_time )
|
||||||
{
|
{
|
||||||
if( less_with_sign( end_time ,
|
if( less_with_sign( end_time ,
|
||||||
@ -142,9 +150,10 @@ Time integrate_n_steps(
|
|||||||
st.current_time_step() ) )
|
st.current_time_step() ) )
|
||||||
st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) );
|
st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) );
|
||||||
st.do_step( system );
|
st.do_step( system );
|
||||||
|
chk();
|
||||||
}
|
}
|
||||||
|
|
||||||
// observation at end point, only if we ended exactly on the end-point (or above due to finite precision)
|
// observation at final point
|
||||||
obs( st.current_state() , end_time );
|
obs( st.current_state() , end_time );
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
Default integrate times implementation.
|
Default integrate times implementation.
|
||||||
[end_description]
|
[end_description]
|
||||||
|
|
||||||
Copyright 2011-2012 Mario Mulansky
|
Copyright 2011-2015 Mario Mulansky
|
||||||
Copyright 2012 Karsten Ahnert
|
Copyright 2012 Karsten Ahnert
|
||||||
Copyright 2012 Christoph Koke
|
Copyright 2012 Christoph Koke
|
||||||
|
|
||||||
@ -38,15 +38,16 @@ namespace detail {
|
|||||||
/*
|
/*
|
||||||
* integrate_times for simple stepper
|
* integrate_times for simple stepper
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
template<class Stepper, class System, class State, class TimeIterator, class Time, class Observer, class StepOverflowChecker>
|
||||||
size_t integrate_times(
|
size_t integrate_times(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
||||||
Observer observer , stepper_tag
|
Observer observer , StepOverflowChecker checker , stepper_tag
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||||
|
typename odeint::unwrap_reference< StepOverflowChecker >::type &chk = checker;
|
||||||
typedef typename unit_value_type<Time>::type time_type;
|
typedef typename unit_value_type<Time>::type time_type;
|
||||||
|
|
||||||
size_t steps = 0;
|
size_t steps = 0;
|
||||||
@ -55,12 +56,14 @@ size_t integrate_times(
|
|||||||
{
|
{
|
||||||
Time current_time = *start_time++;
|
Time current_time = *start_time++;
|
||||||
obs( start_state , current_time );
|
obs( start_state , current_time );
|
||||||
|
chk.reset(); // reset after each observer call
|
||||||
if( start_time == end_time )
|
if( start_time == end_time )
|
||||||
break;
|
break;
|
||||||
while( less_with_sign( current_time , static_cast<time_type>(*start_time) , current_dt ) )
|
while( less_with_sign( current_time , static_cast<time_type>(*start_time) , current_dt ) )
|
||||||
{
|
{
|
||||||
current_dt = min_abs( dt , *start_time - current_time );
|
current_dt = min_abs( dt , *start_time - current_time );
|
||||||
st.do_step( system , start_state , current_time , current_dt );
|
st.do_step( system , start_state , current_time , current_dt );
|
||||||
|
chk(); // check for potential too many steps exception
|
||||||
current_time += current_dt;
|
current_time += current_dt;
|
||||||
steps++;
|
steps++;
|
||||||
}
|
}
|
||||||
@ -71,17 +74,19 @@ size_t integrate_times(
|
|||||||
/*
|
/*
|
||||||
* integrate_times for controlled stepper
|
* integrate_times for controlled stepper
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer , class StepOverflowChecker >
|
||||||
size_t integrate_times(
|
size_t integrate_times(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
||||||
Observer observer , controlled_stepper_tag
|
Observer observer , StepOverflowChecker checker , controlled_stepper_tag
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||||
|
typename odeint::unwrap_reference< StepOverflowChecker >::type &chk = checker;
|
||||||
typedef typename unit_value_type<Time>::type time_type;
|
typedef typename unit_value_type<Time>::type time_type;
|
||||||
|
|
||||||
|
// ToDo: refactor this into a separate max_step_checker
|
||||||
const size_t max_attempts = 1000;
|
const size_t max_attempts = 1000;
|
||||||
const char *error_string = "Integrate adaptive : Maximal number of iterations reached. A step size could not be found.";
|
const char *error_string = "Integrate adaptive : Maximal number of iterations reached. A step size could not be found.";
|
||||||
size_t steps = 0;
|
size_t steps = 0;
|
||||||
@ -90,6 +95,7 @@ size_t integrate_times(
|
|||||||
size_t fail_steps = 0;
|
size_t fail_steps = 0;
|
||||||
Time current_time = *start_time++;
|
Time current_time = *start_time++;
|
||||||
obs( start_state , current_time );
|
obs( start_state , current_time );
|
||||||
|
chk.reset(); // reset after each observer call
|
||||||
if( start_time == end_time )
|
if( start_time == end_time )
|
||||||
break;
|
break;
|
||||||
while( less_with_sign( current_time , static_cast<time_type>(*start_time) , dt ) )
|
while( less_with_sign( current_time , static_cast<time_type>(*start_time) , dt ) )
|
||||||
@ -109,6 +115,8 @@ size_t integrate_times(
|
|||||||
++fail_steps;
|
++fail_steps;
|
||||||
dt = current_dt;
|
dt = current_dt;
|
||||||
}
|
}
|
||||||
|
chk(); // check for potential step overflow exception
|
||||||
|
// ToDo: The following should be part of another checker
|
||||||
if( fail_steps == max_attempts ) BOOST_THROW_EXCEPTION( std::overflow_error( error_string ));
|
if( fail_steps == max_attempts ) BOOST_THROW_EXCEPTION( std::overflow_error( error_string ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,15 +126,16 @@ size_t integrate_times(
|
|||||||
/*
|
/*
|
||||||
* integrate_times for dense output stepper
|
* integrate_times for dense output stepper
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer , class StepOverflowChecker >
|
||||||
size_t integrate_times(
|
size_t integrate_times(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
||||||
Observer observer , dense_output_stepper_tag
|
Observer observer , StepOverflowChecker checker , dense_output_stepper_tag
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||||
|
typename odeint::unwrap_reference< StepOverflowChecker >::type &chk = checker;
|
||||||
typedef typename unit_value_type<Time>::type time_type;
|
typedef typename unit_value_type<Time>::type time_type;
|
||||||
|
|
||||||
if( start_time == end_time )
|
if( start_time == end_time )
|
||||||
@ -138,6 +147,7 @@ size_t integrate_times(
|
|||||||
|
|
||||||
st.initialize( start_state , *start_time , dt );
|
st.initialize( start_state , *start_time , dt );
|
||||||
obs( start_state , *start_time++ );
|
obs( start_state , *start_time++ );
|
||||||
|
chk.reset(); // reset after each observer call
|
||||||
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
while( start_time != end_time )
|
while( start_time != end_time )
|
||||||
@ -146,6 +156,7 @@ size_t integrate_times(
|
|||||||
{
|
{
|
||||||
st.calc_state( *start_time , start_state );
|
st.calc_state( *start_time , start_state );
|
||||||
obs( start_state , *start_time );
|
obs( start_state , *start_time );
|
||||||
|
chk.reset(); // reset after each observer call
|
||||||
start_time++;
|
start_time++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,12 +166,14 @@ size_t integrate_times(
|
|||||||
st.current_time_step() ) )
|
st.current_time_step() ) )
|
||||||
{
|
{
|
||||||
st.do_step( system );
|
st.do_step( system );
|
||||||
|
chk(); // check for potential step overflow exception
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
else if( start_time != end_time )
|
else if( start_time != end_time )
|
||||||
{ // do the last step ending exactly on the end point
|
{ // do the last step ending exactly on the end point
|
||||||
st.initialize( st.current_state() , st.current_time() , last_time_point - st.current_time() );
|
st.initialize( st.current_state() , st.current_time() , last_time_point - st.current_time() );
|
||||||
st.do_step( system );
|
st.do_step( system );
|
||||||
|
chk(); // check for potential step overflow exception
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
|
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
|
||||||
#include <boost/numeric/odeint/integrate/null_observer.hpp>
|
#include <boost/numeric/odeint/integrate/null_observer.hpp>
|
||||||
|
#include <boost/numeric/odeint/integrate/null_checker.hpp>
|
||||||
#include <boost/numeric/odeint/integrate/detail/integrate_n_steps.hpp>
|
#include <boost/numeric/odeint/integrate/detail/integrate_n_steps.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -34,36 +35,58 @@ namespace odeint {
|
|||||||
*
|
*
|
||||||
* the two overloads are needed in order to solve the forwarding problem
|
* the two overloads are needed in order to solve the forwarding problem
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class Time , class Observer>
|
template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker >
|
||||||
Time integrate_n_steps(
|
Time integrate_n_steps(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
Time start_time , Time dt , size_t num_of_steps ,
|
Time start_time , Time dt , size_t num_of_steps ,
|
||||||
Observer observer )
|
Observer observer , StepOverflowChecker checker )
|
||||||
{
|
{
|
||||||
typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category;
|
typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category;
|
||||||
return detail::integrate_n_steps(
|
return detail::integrate_n_steps(
|
||||||
stepper , system , start_state ,
|
stepper , system , start_state ,
|
||||||
start_time , dt , num_of_steps ,
|
start_time , dt , num_of_steps ,
|
||||||
observer , stepper_category() );
|
observer , checker , stepper_category() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class Time , class Observer >
|
template< class Stepper , class System , class State , class Time , class Observer , class StepOverflowChecker >
|
||||||
Time integrate_n_steps(
|
Time integrate_n_steps(
|
||||||
Stepper stepper , System system , const State &start_state ,
|
Stepper stepper , System system , const State &start_state ,
|
||||||
Time start_time , Time dt , size_t num_of_steps ,
|
Time start_time , Time dt , size_t num_of_steps ,
|
||||||
Observer observer )
|
Observer observer , StepOverflowChecker checker )
|
||||||
{
|
{
|
||||||
typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category;
|
typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category;
|
||||||
return detail::integrate_n_steps(
|
return detail::integrate_n_steps(
|
||||||
stepper , system , start_state ,
|
stepper , system , start_state ,
|
||||||
start_time , dt , num_of_steps ,
|
start_time , dt , num_of_steps ,
|
||||||
observer , stepper_category() );
|
observer , checker , stepper_category() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The same function as above, but without checker.
|
||||||
|
*/
|
||||||
|
template< class Stepper , class System , class State , class Time , class Observer >
|
||||||
|
Time integrate_n_steps(
|
||||||
|
Stepper stepper , System system , State &start_state ,
|
||||||
|
Time start_time , Time dt , size_t num_of_steps , Observer observer )
|
||||||
|
{
|
||||||
|
return integrate_n_steps(stepper, system, start_state, start_time, dt, num_of_steps, observer, null_checker());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
||||||
|
*/
|
||||||
|
template< class Stepper , class System , class State , class Time , class Observer >
|
||||||
|
Time integrate_n_steps(
|
||||||
|
Stepper stepper , System system , const State &start_state ,
|
||||||
|
Time start_time , Time dt , size_t num_of_steps , Observer observer )
|
||||||
|
{
|
||||||
|
return integrate_n_steps(stepper, system, start_state, start_time, dt, num_of_steps, observer, null_checker());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief The same function as above, but without observer calls.
|
* \brief The same function as above, but without observer calls.
|
||||||
*/
|
*/
|
||||||
@ -72,7 +95,8 @@ Time integrate_n_steps(
|
|||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
Time start_time , Time dt , size_t num_of_steps )
|
Time start_time , Time dt , size_t num_of_steps )
|
||||||
{
|
{
|
||||||
return integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , null_observer() );
|
return integrate_n_steps(stepper, system, start_state, start_time, dt, num_of_steps, null_observer(),
|
||||||
|
null_checker());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +107,8 @@ Time integrate_n_steps(
|
|||||||
Stepper stepper , System system , const State &start_state ,
|
Stepper stepper , System system , const State &start_state ,
|
||||||
Time start_time , Time dt , size_t num_of_steps )
|
Time start_time , Time dt , size_t num_of_steps )
|
||||||
{
|
{
|
||||||
return integrate_n_steps( stepper , system , start_state , start_time , dt , num_of_steps , null_observer() );
|
return integrate_n_steps(stepper, system, start_state, start_time, dt, num_of_steps, null_observer(),
|
||||||
|
null_checker());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
|
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
|
||||||
#include <boost/numeric/odeint/integrate/null_observer.hpp>
|
#include <boost/numeric/odeint/integrate/null_observer.hpp>
|
||||||
|
#include <boost/numeric/odeint/integrate/null_checker.hpp>
|
||||||
#include <boost/numeric/odeint/integrate/detail/integrate_times.hpp>
|
#include <boost/numeric/odeint/integrate/detail/integrate_times.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -32,8 +33,72 @@ namespace odeint {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* \brief Integrates while calling the observer at the time points given by sequence [times_start, time_end)
|
||||||
* the two overloads are needed in order to solve the forwarding problem
|
* the two overloads are needed in order to solve the forwarding problem
|
||||||
*/
|
*/
|
||||||
|
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer , class StepOverflowChecker >
|
||||||
|
size_t integrate_times(
|
||||||
|
Stepper stepper , System system , State &start_state ,
|
||||||
|
TimeIterator times_start , TimeIterator times_end , Time dt ,
|
||||||
|
Observer observer , StepOverflowChecker checker )
|
||||||
|
{
|
||||||
|
typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category;
|
||||||
|
return detail::integrate_times(
|
||||||
|
stepper , system , start_state ,
|
||||||
|
times_start , times_end , dt ,
|
||||||
|
observer , checker , stepper_category() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
||||||
|
*/
|
||||||
|
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer , class StepOverflowChecker >
|
||||||
|
size_t integrate_times(
|
||||||
|
Stepper stepper , System system , const State &start_state ,
|
||||||
|
TimeIterator times_start , TimeIterator times_end , Time dt ,
|
||||||
|
Observer observer , StepOverflowChecker checker )
|
||||||
|
{
|
||||||
|
typedef typename odeint::unwrap_reference< Stepper >::type::stepper_category stepper_category;
|
||||||
|
return detail::integrate_times(
|
||||||
|
stepper , system , start_state ,
|
||||||
|
times_start , times_end , dt ,
|
||||||
|
observer , checker , stepper_category() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The same function as above, but with the observation times given as range.
|
||||||
|
*/
|
||||||
|
template< class Stepper , class System , class State , class TimeRange , class Time , class Observer , class StepOverflowChecker >
|
||||||
|
size_t integrate_times(
|
||||||
|
Stepper stepper , System system , State &start_state ,
|
||||||
|
const TimeRange × , Time dt ,
|
||||||
|
Observer observer , StepOverflowChecker checker )
|
||||||
|
{
|
||||||
|
return integrate_times(
|
||||||
|
stepper , system , start_state ,
|
||||||
|
boost::begin( times ) , boost::end( times ) , dt , observer , checker );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
||||||
|
*/
|
||||||
|
template< class Stepper , class System , class State , class TimeRange , class Time , class Observer , class StepOverflowChecker >
|
||||||
|
size_t integrate_times(
|
||||||
|
Stepper stepper , System system , const State &start_state ,
|
||||||
|
const TimeRange × , Time dt ,
|
||||||
|
Observer observer , StepOverflowChecker checker )
|
||||||
|
{
|
||||||
|
return integrate_times(
|
||||||
|
stepper , system , start_state ,
|
||||||
|
boost::begin( times ) , boost::end( times ) , dt , observer , checker );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The same functions as above, but without a StepOverflowChecker
|
||||||
|
*/
|
||||||
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
||||||
size_t integrate_times(
|
size_t integrate_times(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
@ -44,12 +109,12 @@ size_t integrate_times(
|
|||||||
return detail::integrate_times(
|
return detail::integrate_times(
|
||||||
stepper , system , start_state ,
|
stepper , system , start_state ,
|
||||||
times_start , times_end , dt ,
|
times_start , times_end , dt ,
|
||||||
observer , stepper_category() );
|
observer , null_checker() , stepper_category() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
||||||
size_t integrate_times(
|
size_t integrate_times(
|
||||||
Stepper stepper , System system , const State &start_state ,
|
Stepper stepper , System system , const State &start_state ,
|
||||||
@ -60,12 +125,12 @@ size_t integrate_times(
|
|||||||
return detail::integrate_times(
|
return detail::integrate_times(
|
||||||
stepper , system , start_state ,
|
stepper , system , start_state ,
|
||||||
times_start , times_end , dt ,
|
times_start , times_end , dt ,
|
||||||
observer , stepper_category() );
|
observer , null_checker() , stepper_category() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief The same function as above, but without observer calls.
|
* \brief The same function as above, but with the observation times given as range.
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class TimeRange , class Time , class Observer >
|
template< class Stepper , class System , class State , class TimeRange , class Time , class Observer >
|
||||||
size_t integrate_times(
|
size_t integrate_times(
|
||||||
Stepper stepper , System system , State &start_state ,
|
Stepper stepper , System system , State &start_state ,
|
||||||
@ -74,12 +139,12 @@ size_t integrate_times(
|
|||||||
{
|
{
|
||||||
return integrate_times(
|
return integrate_times(
|
||||||
stepper , system , start_state ,
|
stepper , system , start_state ,
|
||||||
boost::begin( times ) , boost::end( times ) , dt , observer );
|
boost::begin( times ) , boost::end( times ) , dt , observer , null_checker() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
* \brief Solves the forwarding problem, can be called with Boost.Range as start_state.
|
||||||
*/
|
*/
|
||||||
template< class Stepper , class System , class State , class TimeRange , class Time , class Observer >
|
template< class Stepper , class System , class State , class TimeRange , class Time , class Observer >
|
||||||
size_t integrate_times(
|
size_t integrate_times(
|
||||||
Stepper stepper , System system , const State &start_state ,
|
Stepper stepper , System system , const State &start_state ,
|
||||||
@ -88,12 +153,10 @@ size_t integrate_times(
|
|||||||
{
|
{
|
||||||
return integrate_times(
|
return integrate_times(
|
||||||
stepper , system , start_state ,
|
stepper , system , start_state ,
|
||||||
boost::begin( times ) , boost::end( times ) , dt , observer );
|
boost::begin( times ) , boost::end( times ) , dt , observer , null_checker() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********* DOXYGEN ***********/
|
/********* DOXYGEN ***********/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +45,9 @@ namespace odeint {
|
|||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Resets the max_step_checker by setting the internal counter to 0.
|
||||||
|
*/
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
m_steps = 0;
|
m_steps = 0;
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/iterator/counting_iterator.hpp>
|
||||||
|
|
||||||
#include <boost/numeric/odeint.hpp>
|
#include <boost/numeric/odeint.hpp>
|
||||||
|
|
||||||
|
|
||||||
@ -77,11 +79,10 @@ BOOST_AUTO_TEST_CASE( test_integrate_const )
|
|||||||
integrate_const(stepper_type(), lorenz, x, 0.0, 10.0, 1.0, null_observer());
|
integrate_const(stepper_type(), lorenz, x, 0.0, 10.0, 1.0, null_observer());
|
||||||
integrate_const(stepper_type(), lorenz, x, 0.0, 10.0, 1.0, null_observer(), null_checker());
|
integrate_const(stepper_type(), lorenz, x, 0.0, 10.0, 1.0, null_observer(), null_checker());
|
||||||
// no exceptions expected for normal steppers
|
// no exceptions expected for normal steppers
|
||||||
integrate_const(stepper_type(), lorenz, x, 0.0, 10.0, 1.0, null_observer(), max_step_checker());
|
integrate_const(stepper_type(), lorenz, x, 0.0, 10.0, 1.0, null_observer(), max_step_checker(10));
|
||||||
|
|
||||||
|
|
||||||
// check exceptions for controlled stepper
|
// check exceptions for controlled stepper
|
||||||
integrate_const(stepper_type(), lorenz, x, 0.0, 10.0, 1.0);
|
|
||||||
integrate_const(make_controlled<stepper_type>(1E-5, 1E-5), lorenz, x, 0.0, 10.0, 1.0);
|
integrate_const(make_controlled<stepper_type>(1E-5, 1E-5), lorenz, x, 0.0, 10.0, 1.0);
|
||||||
// very small error terms -> standard overflow threshold of 500 should fire an exception
|
// very small error terms -> standard overflow threshold of 500 should fire an exception
|
||||||
BOOST_CHECK_THROW(integrate_const(make_controlled<stepper_type>(1E-15, 1E-15), lorenz, x,
|
BOOST_CHECK_THROW(integrate_const(make_controlled<stepper_type>(1E-15, 1E-15), lorenz, x,
|
||||||
@ -105,4 +106,82 @@ BOOST_AUTO_TEST_CASE( test_integrate_const )
|
|||||||
std::overflow_error);
|
std::overflow_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( test_integrate_n_steps )
|
||||||
|
{
|
||||||
|
state_type x(3, 5.0);
|
||||||
|
std::vector<double> times;
|
||||||
|
|
||||||
|
// check the function signatures with normal stepper
|
||||||
|
integrate_n_steps(stepper_type(), lorenz, x, 0.0, 1.0, 10);
|
||||||
|
integrate_n_steps(stepper_type(), lorenz, x, 0.0, 1.0, 10, null_observer());
|
||||||
|
integrate_n_steps(stepper_type(), lorenz, x, 0.0, 1.0, 10, null_observer(), null_checker());
|
||||||
|
// no exceptions expected for normal steppers
|
||||||
|
integrate_n_steps(stepper_type(), lorenz, x, 0.0, 1.0, 10, null_observer(), max_step_checker(10));
|
||||||
|
|
||||||
|
|
||||||
|
// check exceptions for controlled stepper
|
||||||
|
integrate_n_steps(make_controlled<stepper_type>(1E-5, 1E-5), lorenz, x, 0.0, 1.0, 10);
|
||||||
|
// very small error terms -> standard overflow threshold of 500 should fire an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_n_steps(make_controlled<stepper_type>(1E-15, 1E-15), lorenz, x,
|
||||||
|
0.0, 1.0, 10, push_back_time(times), max_step_checker()),
|
||||||
|
std::overflow_error);
|
||||||
|
// small threshold of 10 -> larger error still gives an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_n_steps(make_controlled<stepper_type>(1E-5, 1E-5), lorenz, x,
|
||||||
|
0.0, 1.0, 10, push_back_time(times), max_step_checker(10)),
|
||||||
|
std::overflow_error);
|
||||||
|
|
||||||
|
// check exceptions for dense output stepper
|
||||||
|
integrate_n_steps(make_dense_output<stepper_type>(1E-5, 1E-5), lorenz, x, 0.0, 1.0, 10);
|
||||||
|
integrate_n_steps(make_dense_output<stepper_type>(1E-5, 1E-5), lorenz, x, 0.0, 1.0, 10, push_back_time(times));
|
||||||
|
// very small error terms -> standard overflow threshold of 500 should fire an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_n_steps(make_dense_output<stepper_type>(1E-15, 1E-15), lorenz, x,
|
||||||
|
0.0, 1.0, 10, push_back_time(times), max_step_checker()),
|
||||||
|
std::overflow_error);
|
||||||
|
// small threshold of 10 -> larger error still gives an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_n_steps(make_dense_output<stepper_type>(1E-5, 1E-5), lorenz, x,
|
||||||
|
0.0, 1.0, 10, push_back_time(times), max_step_checker(10)),
|
||||||
|
std::overflow_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( test_integrate_times )
|
||||||
|
{
|
||||||
|
state_type x(3, 5.0);
|
||||||
|
std::vector<double> times;
|
||||||
|
boost::counting_iterator<int> t0(0);
|
||||||
|
boost::counting_iterator<int> t1(10);
|
||||||
|
|
||||||
|
// check the function signatures with normal stepper
|
||||||
|
integrate_times(stepper_type(), lorenz, x, t0, t1, 1.0 , push_back_time(times));
|
||||||
|
integrate_times(stepper_type(), lorenz, x, t0, t1, 1.0 , push_back_time(times), null_checker());
|
||||||
|
// no exceptions expected for big enough step size
|
||||||
|
integrate_times(stepper_type(), lorenz, x, t0, t1, 1.0 , push_back_time(times), max_step_checker(10));
|
||||||
|
// if dt*max_steps < observer time difference we expect an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_times(stepper_type(), lorenz, x, t0, t1, 0.01, push_back_time(times),
|
||||||
|
max_step_checker(10)),
|
||||||
|
std::overflow_error);
|
||||||
|
|
||||||
|
// check exceptions for controlled stepper
|
||||||
|
// no exception if no checker is provided
|
||||||
|
integrate_times(make_controlled<stepper_type>(1E-5, 1E-5), lorenz, x, t0, t1, 1.0 , push_back_time(times));
|
||||||
|
// very small error terms -> standard overflow threshold of 500 should fire an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_times(make_controlled<stepper_type>(1E-15, 1E-15), lorenz, x,
|
||||||
|
t0, t1, 1.0 , push_back_time(times), max_step_checker()),
|
||||||
|
std::overflow_error);
|
||||||
|
// small threshold of 10 -> larger error still gives an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_times(make_controlled<stepper_type>(1E-5, 1E-5), lorenz, x,
|
||||||
|
t0, t1, 1.0 , push_back_time(times), max_step_checker(10)),
|
||||||
|
std::overflow_error);
|
||||||
|
|
||||||
|
// check exceptions for dense output stepper
|
||||||
|
integrate_times(make_dense_output<stepper_type>(1E-5, 1E-5), lorenz, x, t0, t1, 1.0 , push_back_time(times));
|
||||||
|
// very small error terms -> standard overflow threshold of 500 should fire an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_times(make_dense_output<stepper_type>(1E-15, 1E-15), lorenz, x,
|
||||||
|
t0, t1, 1.0 , push_back_time(times), max_step_checker()),
|
||||||
|
std::overflow_error);
|
||||||
|
// small threshold of 10 -> larger error still gives an exception
|
||||||
|
BOOST_CHECK_THROW(integrate_times(make_dense_output<stepper_type>(1E-5, 1E-5), lorenz, x,
|
||||||
|
t0, t1, 1.0 , push_back_time(times), max_step_checker(10)),
|
||||||
|
std::overflow_error);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
x
Reference in New Issue
Block a user