162 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			162 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /* | ||
|  |  [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 |