整理
This commit is contained in:
70
include/boost/numeric/odeint/integrate/detail/functors.hpp
Normal file
70
include/boost/numeric/odeint/integrate/detail/functors.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
[auto_generated]
|
||||
boost/numeric/odeint/integrate/detail/functors.hpp
|
||||
|
||||
[begin_description]
|
||||
some functors for the iterator based integrate routines
|
||||
[end_description]
|
||||
|
||||
Copyright 2009-2013 Karsten Ahnert
|
||||
Copyright 2009-2013 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)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED
|
||||
#define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace odeint {
|
||||
namespace detail {
|
||||
|
||||
|
||||
template< class Observer >
|
||||
struct obs_caller {
|
||||
|
||||
size_t &m_n;
|
||||
Observer m_obs;
|
||||
|
||||
obs_caller( size_t &m , Observer &obs ) : m_n(m) , m_obs( obs ) {}
|
||||
|
||||
template< class State , class Time >
|
||||
void operator()( std::pair< const State & , const Time & > x )
|
||||
{
|
||||
typedef typename odeint::unwrap_reference< Observer >::type observer_type;
|
||||
observer_type &obs = m_obs;
|
||||
obs( x.first , x.second );
|
||||
m_n++;
|
||||
}
|
||||
};
|
||||
|
||||
template< class Observer , class Time >
|
||||
struct obs_caller_time {
|
||||
|
||||
Time &m_t;
|
||||
Observer m_obs;
|
||||
|
||||
obs_caller_time( Time &t , Observer &obs ) : m_t(t) , m_obs( obs ) {}
|
||||
|
||||
template< class State >
|
||||
void operator()( std::pair< const State & , const Time & > x )
|
||||
{
|
||||
typedef typename odeint::unwrap_reference< Observer >::type observer_type;
|
||||
observer_type &obs = m_obs;
|
||||
obs( x.first , x.second );
|
||||
m_t = x.second;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace odeint
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_FUNCTORS_HPP_INCLUDED
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
[auto_generated]
|
||||
boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp
|
||||
|
||||
[begin_description]
|
||||
Default Integrate adaptive implementation.
|
||||
[end_description]
|
||||
|
||||
Copyright 2011-2013 Karsten Ahnert
|
||||
Copyright 2011-2015 Mario Mulansky
|
||||
Copyright 2012 Christoph Koke
|
||||
|
||||
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)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED
|
||||
#define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
|
||||
#include <boost/numeric/odeint/stepper/controlled_step_result.hpp>
|
||||
#include <boost/numeric/odeint/integrate/max_step_checker.hpp>
|
||||
#include <boost/numeric/odeint/integrate/detail/integrate_const.hpp>
|
||||
#include <boost/numeric/odeint/util/bind.hpp>
|
||||
#include <boost/numeric/odeint/util/unwrap_reference.hpp>
|
||||
#include <boost/numeric/odeint/util/copy.hpp>
|
||||
|
||||
#include <boost/numeric/odeint/util/detail/less_with_sign.hpp>
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace odeint {
|
||||
namespace detail {
|
||||
|
||||
// forward declaration
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_const(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time start_time , Time end_time , Time dt ,
|
||||
Observer observer , stepper_tag );
|
||||
|
||||
/*
|
||||
* integrate_adaptive for simple stepper is basically an integrate_const + some last step
|
||||
*/
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_adaptive(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time start_time , Time end_time , Time dt ,
|
||||
Observer observer , stepper_tag
|
||||
)
|
||||
{
|
||||
size_t steps = detail::integrate_const( stepper , system , start_state , start_time ,
|
||||
end_time , dt , observer , stepper_tag() );
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
Time end = start_time + dt*steps;
|
||||
if( less_with_sign( end , end_time , dt ) )
|
||||
{ //make a last step to end exactly at end_time
|
||||
st.do_step( system , start_state , end , end_time - end );
|
||||
steps++;
|
||||
obs( start_state , end_time );
|
||||
}
|
||||
return steps;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* integrate adaptive for controlled stepper
|
||||
*/
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_adaptive(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time &start_time , Time end_time , Time &dt ,
|
||||
Observer observer , controlled_stepper_tag
|
||||
)
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails
|
||||
size_t count = 0;
|
||||
while( less_with_sign( start_time , end_time , dt ) )
|
||||
{
|
||||
obs( start_state , start_time );
|
||||
if( less_with_sign( end_time , static_cast<Time>(start_time + dt) , dt ) )
|
||||
{
|
||||
dt = end_time - start_time;
|
||||
}
|
||||
|
||||
controlled_step_result res;
|
||||
do
|
||||
{
|
||||
res = st.try_step( system , start_state , start_time , dt );
|
||||
fail_checker(); // check number of failed steps
|
||||
}
|
||||
while( res == fail );
|
||||
fail_checker.reset(); // if we reach here, the step was successful -> reset fail checker
|
||||
|
||||
++count;
|
||||
}
|
||||
obs( start_state , start_time );
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* integrate adaptive for dense output steppers
|
||||
*
|
||||
* step size control is used if the stepper supports it
|
||||
*/
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_adaptive(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time start_time , Time end_time , Time dt ,
|
||||
Observer observer , dense_output_stepper_tag )
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
size_t count = 0;
|
||||
st.initialize( start_state , start_time , dt );
|
||||
|
||||
while( less_with_sign( st.current_time() , end_time , st.current_time_step() ) )
|
||||
{
|
||||
while( less_eq_with_sign( static_cast<Time>(st.current_time() + st.current_time_step()) ,
|
||||
end_time ,
|
||||
st.current_time_step() ) )
|
||||
{ //make sure we don't go beyond the end_time
|
||||
obs( st.current_state() , st.current_time() );
|
||||
st.do_step( system );
|
||||
++count;
|
||||
}
|
||||
// calculate time step to arrive exactly at end time
|
||||
st.initialize( st.current_state() , st.current_time() , static_cast<Time>(end_time - st.current_time()) );
|
||||
}
|
||||
obs( st.current_state() , st.current_time() );
|
||||
// overwrite start_state with the final point
|
||||
boost::numeric::odeint::copy( st.current_state() , start_state );
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace odeint
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
[auto_generated]
|
||||
boost/numeric/odeint/integrate/detail/integrate_const.hpp
|
||||
|
||||
[begin_description]
|
||||
integrate const implementation
|
||||
[end_description]
|
||||
|
||||
Copyright 2012-2015 Mario Mulansky
|
||||
Copyright 2012 Christoph Koke
|
||||
Copyright 2012 Karsten Ahnert
|
||||
|
||||
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)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_CONST_HPP_INCLUDED
|
||||
#define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_CONST_HPP_INCLUDED
|
||||
|
||||
#include <boost/numeric/odeint/util/unwrap_reference.hpp>
|
||||
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
|
||||
#include <boost/numeric/odeint/util/unit_helper.hpp>
|
||||
#include <boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp>
|
||||
|
||||
#include <boost/numeric/odeint/util/detail/less_with_sign.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace odeint {
|
||||
namespace detail {
|
||||
|
||||
// forward declaration
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_adaptive(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time &start_time , Time end_time , Time &dt ,
|
||||
Observer observer , controlled_stepper_tag
|
||||
);
|
||||
|
||||
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_const(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time start_time , Time end_time , Time dt ,
|
||||
Observer observer , stepper_tag
|
||||
)
|
||||
{
|
||||
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
Time time = start_time;
|
||||
int step = 0;
|
||||
// cast time+dt explicitely in case of expression templates (e.g. multiprecision)
|
||||
while( less_eq_with_sign( static_cast<Time>(time+dt) , end_time , dt ) )
|
||||
{
|
||||
obs( start_state , time );
|
||||
st.do_step( system , start_state , 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
|
||||
++step;
|
||||
time = start_time + static_cast< typename unit_value_type<Time>::type >(step) * dt;
|
||||
}
|
||||
obs( start_state , time );
|
||||
|
||||
return step;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_const(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time start_time , Time end_time , Time dt ,
|
||||
Observer observer , controlled_stepper_tag
|
||||
)
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
|
||||
Time time = start_time;
|
||||
const Time time_step = dt;
|
||||
int real_steps = 0;
|
||||
int step = 0;
|
||||
|
||||
while( less_eq_with_sign( static_cast<Time>(time+time_step) , end_time , dt ) )
|
||||
{
|
||||
obs( start_state , time );
|
||||
// integrate_adaptive_checked uses the given checker to throw if an overflow occurs
|
||||
real_steps += detail::integrate_adaptive(stepper, system, start_state, time,
|
||||
static_cast<Time>(time + time_step), dt,
|
||||
null_observer(), controlled_stepper_tag());
|
||||
// direct computation of the time avoids error propagation happening when using time += dt
|
||||
// we need clumsy type analysis to get boost units working here
|
||||
step++;
|
||||
time = start_time + static_cast< typename unit_value_type<Time>::type >(step) * time_step;
|
||||
}
|
||||
obs( start_state , time );
|
||||
|
||||
return real_steps;
|
||||
}
|
||||
|
||||
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_const(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time start_time , Time end_time , Time dt ,
|
||||
Observer observer , dense_output_stepper_tag
|
||||
)
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
Time time = start_time;
|
||||
|
||||
st.initialize( start_state , time , dt );
|
||||
obs( start_state , time );
|
||||
time += dt;
|
||||
|
||||
int obs_step( 1 );
|
||||
int real_step( 0 );
|
||||
|
||||
while( less_eq_with_sign( static_cast<Time>(time+dt) , end_time , dt ) )
|
||||
{
|
||||
while( less_eq_with_sign( time , st.current_time() , dt ) )
|
||||
{
|
||||
st.calc_state( time , start_state );
|
||||
obs( start_state , time );
|
||||
++obs_step;
|
||||
// direct computation of the time avoids error propagation happening when using time += dt
|
||||
// we need clumsy type analysis to get boost units working here
|
||||
time = start_time + static_cast< typename unit_value_type<Time>::type >(obs_step) * dt;
|
||||
}
|
||||
// we have not reached the end, do another real step
|
||||
if( less_with_sign( static_cast<Time>(st.current_time()+st.current_time_step()) ,
|
||||
end_time ,
|
||||
st.current_time_step() ) )
|
||||
{
|
||||
while( less_eq_with_sign( st.current_time() , time , dt ) )
|
||||
{
|
||||
st.do_step( system );
|
||||
++real_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
|
||||
st.initialize( st.current_state() , st.current_time() , end_time - st.current_time() );
|
||||
st.do_step( system );
|
||||
++real_step;
|
||||
}
|
||||
|
||||
}
|
||||
// last observation, if we are still in observation interval
|
||||
// might happen due to finite precision problems when computing the the time
|
||||
if( less_eq_with_sign( time , end_time , dt ) )
|
||||
{
|
||||
st.calc_state( time , start_state );
|
||||
obs( start_state , time );
|
||||
}
|
||||
|
||||
return real_step;
|
||||
}
|
||||
|
||||
|
||||
} } } }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
[auto_generated]
|
||||
boost/numeric/odeint/integrate/detail/integrate_n_steps.hpp
|
||||
|
||||
[begin_description]
|
||||
integrate steps implementation
|
||||
[end_description]
|
||||
|
||||
Copyright 2012-2015 Mario Mulansky
|
||||
Copyright 2012 Christoph Koke
|
||||
Copyright 2012 Karsten Ahnert
|
||||
|
||||
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)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED
|
||||
#define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED
|
||||
|
||||
#include <boost/numeric/odeint/util/unwrap_reference.hpp>
|
||||
#include <boost/numeric/odeint/stepper/stepper_categories.hpp>
|
||||
#include <boost/numeric/odeint/integrate/detail/integrate_adaptive.hpp>
|
||||
#include <boost/numeric/odeint/util/unit_helper.hpp>
|
||||
|
||||
#include <boost/numeric/odeint/util/detail/less_with_sign.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace odeint {
|
||||
namespace detail {
|
||||
|
||||
// forward declaration
|
||||
template< class Stepper , class System , class State , class Time , class Observer >
|
||||
size_t integrate_adaptive_checked(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
Time &start_time , Time end_time , Time &dt ,
|
||||
Observer observer, controlled_stepper_tag
|
||||
);
|
||||
|
||||
|
||||
/* basic version */
|
||||
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 , stepper_tag )
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
Time time = start_time;
|
||||
|
||||
for( size_t step = 0; step < num_of_steps ; ++step )
|
||||
{
|
||||
obs( start_state , time );
|
||||
st.do_step( system , start_state , 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
|
||||
time = start_time + static_cast< typename unit_value_type<Time>::type >( step+1 ) * dt;
|
||||
}
|
||||
obs( start_state , time );
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
/* controlled version */
|
||||
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 , controlled_stepper_tag )
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
|
||||
Time time = start_time;
|
||||
Time time_step = dt;
|
||||
|
||||
for( size_t step = 0; step < num_of_steps ; ++step )
|
||||
{
|
||||
obs( start_state , time );
|
||||
// integrate_adaptive_checked uses the given checker to throw if an overflow occurs
|
||||
detail::integrate_adaptive(stepper, system, start_state, time, static_cast<Time>(time + time_step), dt,
|
||||
null_observer(), controlled_stepper_tag());
|
||||
// direct computation of the time avoids error propagation happening when using time += dt
|
||||
// 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;
|
||||
}
|
||||
obs( start_state , time );
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
/* dense output version */
|
||||
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 , dense_output_stepper_tag )
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
Time time = start_time;
|
||||
const Time end_time = start_time + static_cast< typename unit_value_type<Time>::type >(num_of_steps) * dt;
|
||||
|
||||
st.initialize( start_state , time , dt );
|
||||
|
||||
size_t step = 0;
|
||||
|
||||
while( step < num_of_steps )
|
||||
{
|
||||
while( less_with_sign( time , st.current_time() , st.current_time_step() ) )
|
||||
{
|
||||
st.calc_state( time , start_state );
|
||||
obs( start_state , time );
|
||||
++step;
|
||||
// direct computation of the time avoids error propagation happening when using time += dt
|
||||
// we need clumsy type analysis to get boost units working here
|
||||
time = start_time + static_cast< typename unit_value_type<Time>::type >(step) * dt;
|
||||
}
|
||||
|
||||
// we have not reached the end, do another real step
|
||||
if( less_with_sign( static_cast<Time>(st.current_time()+st.current_time_step()) ,
|
||||
end_time ,
|
||||
st.current_time_step() ) )
|
||||
{
|
||||
st.do_step( system );
|
||||
}
|
||||
else if( less_with_sign( st.current_time() , end_time , st.current_time_step() ) )
|
||||
{ // 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.do_step( system );
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we really end exactly where we should end
|
||||
while( st.current_time() < end_time )
|
||||
{
|
||||
if( less_with_sign( end_time ,
|
||||
static_cast<Time>(st.current_time()+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.do_step( system );
|
||||
}
|
||||
|
||||
// observation at final point
|
||||
obs( st.current_state() , end_time );
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_N_STEPS_HPP_INCLUDED */
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
[auto_generated]
|
||||
boost/numeric/odeint/integrate/detail/integrate_times.hpp
|
||||
|
||||
[begin_description]
|
||||
Default integrate times implementation.
|
||||
[end_description]
|
||||
|
||||
Copyright 2011-2015 Mario Mulansky
|
||||
Copyright 2012 Karsten Ahnert
|
||||
Copyright 2012 Christoph Koke
|
||||
|
||||
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)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_TIMES_HPP_INCLUDED
|
||||
#define BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_TIMES_HPP_INCLUDED
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/numeric/odeint/util/unwrap_reference.hpp>
|
||||
#include <boost/numeric/odeint/stepper/controlled_step_result.hpp>
|
||||
#include <boost/numeric/odeint/util/detail/less_with_sign.hpp>
|
||||
#include <boost/numeric/odeint/integrate/max_step_checker.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace numeric {
|
||||
namespace odeint {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* integrate_times for simple stepper
|
||||
*/
|
||||
template<class Stepper, class System, class State, class TimeIterator, class Time, class Observer>
|
||||
size_t integrate_times(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
||||
Observer observer , stepper_tag
|
||||
)
|
||||
{
|
||||
typedef typename odeint::unwrap_reference< Stepper >::type stepper_type;
|
||||
typedef typename odeint::unwrap_reference< Observer >::type observer_type;
|
||||
|
||||
stepper_type &st = stepper;
|
||||
observer_type &obs = observer;
|
||||
typedef typename unit_value_type<Time>::type time_type;
|
||||
|
||||
size_t steps = 0;
|
||||
Time current_dt = dt;
|
||||
while( true )
|
||||
{
|
||||
Time current_time = *start_time++;
|
||||
obs( start_state , current_time );
|
||||
if( start_time == end_time )
|
||||
break;
|
||||
while( less_with_sign( current_time , static_cast<time_type>(*start_time) , current_dt ) )
|
||||
{
|
||||
current_dt = min_abs( dt , *start_time - current_time );
|
||||
st.do_step( system , start_state , current_time , current_dt );
|
||||
current_time += current_dt;
|
||||
steps++;
|
||||
}
|
||||
}
|
||||
return steps;
|
||||
}
|
||||
|
||||
/*
|
||||
* integrate_times for controlled stepper
|
||||
*/
|
||||
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
||||
size_t integrate_times(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
||||
Observer observer , controlled_stepper_tag
|
||||
)
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
typedef typename unit_value_type<Time>::type time_type;
|
||||
|
||||
failed_step_checker fail_checker; // to throw a runtime_error if step size adjustment fails
|
||||
size_t steps = 0;
|
||||
while( true )
|
||||
{
|
||||
Time current_time = *start_time++;
|
||||
obs( start_state , current_time );
|
||||
if( start_time == end_time )
|
||||
break;
|
||||
while( less_with_sign( current_time , static_cast<time_type>(*start_time) , dt ) )
|
||||
{
|
||||
// adjust stepsize to end up exactly at the observation point
|
||||
Time current_dt = min_abs( dt , *start_time - current_time );
|
||||
if( st.try_step( system , start_state , current_time , current_dt ) == success )
|
||||
{
|
||||
++steps;
|
||||
// successful step -> reset the fail counter, see #173
|
||||
fail_checker.reset();
|
||||
// continue with the original step size if dt was reduced due to observation
|
||||
dt = max_abs( dt , current_dt );
|
||||
}
|
||||
else
|
||||
{
|
||||
fail_checker(); // check for possible overflow of failed steps in step size adjustment
|
||||
dt = current_dt;
|
||||
}
|
||||
}
|
||||
}
|
||||
return steps;
|
||||
}
|
||||
|
||||
/*
|
||||
* integrate_times for dense output stepper
|
||||
*/
|
||||
template< class Stepper , class System , class State , class TimeIterator , class Time , class Observer >
|
||||
size_t integrate_times(
|
||||
Stepper stepper , System system , State &start_state ,
|
||||
TimeIterator start_time , TimeIterator end_time , Time dt ,
|
||||
Observer observer , dense_output_stepper_tag
|
||||
)
|
||||
{
|
||||
typename odeint::unwrap_reference< Observer >::type &obs = observer;
|
||||
typename odeint::unwrap_reference< Stepper >::type &st = stepper;
|
||||
|
||||
typedef typename unit_value_type<Time>::type time_type;
|
||||
|
||||
if( start_time == end_time )
|
||||
return 0;
|
||||
|
||||
TimeIterator last_time_iterator = end_time;
|
||||
--last_time_iterator;
|
||||
Time last_time_point = static_cast<time_type>(*last_time_iterator);
|
||||
|
||||
st.initialize( start_state , *start_time , dt );
|
||||
obs( start_state , *start_time++ );
|
||||
|
||||
size_t count = 0;
|
||||
while( start_time != end_time )
|
||||
{
|
||||
while( ( start_time != end_time ) && less_eq_with_sign( static_cast<time_type>(*start_time) , st.current_time() , st.current_time_step() ) )
|
||||
{
|
||||
st.calc_state( *start_time , start_state );
|
||||
obs( start_state , *start_time );
|
||||
start_time++;
|
||||
}
|
||||
|
||||
// we have not reached the end, do another real step
|
||||
if( less_eq_with_sign( st.current_time() + st.current_time_step() ,
|
||||
last_time_point ,
|
||||
st.current_time_step() ) )
|
||||
{
|
||||
st.do_step( system );
|
||||
++count;
|
||||
}
|
||||
else if( start_time != end_time )
|
||||
{ // 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.do_step( system );
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace odeint
|
||||
} // namespace numeric
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_NUMERIC_ODEINT_INTEGRATE_DETAIL_INTEGRATE_ADAPTIVE_HPP_INCLUDED
|
||||
Reference in New Issue
Block a user