Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 停止与推力使用的odeint集成_C++_Thrust_Differential Equations_Odeint - Fatal编程技术网

C++ 停止与推力使用的odeint集成

C++ 停止与推力使用的odeint集成,c++,thrust,differential-equations,odeint,C++,Thrust,Differential Equations,Odeint,我试图将ODE系统与odeint库集成在一起,并在一组点上并行推进(这意味着相同的ODE具有许多不同的初始条件)。我特别使用了自适应步长算法runge_kutta_dopri5。 在某些情况下,该算法会失败,从而减小步长,并极大地减慢整个积分过程 如果某个测试失败,是否有办法仅对集合中的某些点停止集成过程 在我的特殊情况下,因为我在积分一个重力问题,我想在点靠近吸引子时停止积分,所以距离小于某个极限 在串行计算中,我认为这可以通过使用步进器的自定义while循环来实现。请尝试使用step功能,如

我试图将ODE系统与odeint库集成在一起,并在一组点上并行推进(这意味着相同的ODE具有许多不同的初始条件)。我特别使用了自适应步长算法runge_kutta_dopri5。 在某些情况下,该算法会失败,从而减小步长,并极大地减慢整个积分过程

如果某个测试失败,是否有办法仅对集合中的某些点停止集成过程

在我的特殊情况下,因为我在积分一个重力问题,我想在点靠近吸引子时停止积分,所以距离小于某个极限

在串行计算中,我认为这可以通过使用
步进器的自定义while循环来实现。请尝试使用step
功能,如后面的想法所示

如何在具有推力的并行计算中实现这一点


谢谢。

如前所述,这个问题没有直接的解决方案

一种可能的解决方案是提供

  • ODE已停止的ints报告向量。因此,如果这个向量的第i个元素为零,则表示第i个ODE仍在运行
  • runge_kutta_dopri5中的自定义错误检查器,如果当前系统已停止,则将错误设置为0。因此,可以避免此错误影响步长控制机制,至少不会对步长控制产生负面影响。请参见下面的草图,了解如何实现这一点
  • 检查集成是否停止的函数。原则上,这可以放在观察者身上
  • 自定义错误检查器的草图可以是(从默认错误检查器复制):

    您可以在观察者内部调用此函数,并且需要将is_stopped传递给观察者


    我们还有一个实验性的分支,其中步长控制直接在GPU上运行,并分别控制每个ODE。这是非常强大和高性能的。不幸的是,此功能无法轻松集成到主分支中,因为需要在odeint的方法中添加大量的
    \uuuuu设备\uuuuuuuuuuu主机\uuuuuuuuu
    说明符。如果您愿意,您可以查看odeint存储库中的cuda_控制的_步进器分支和/或给我留言以获取进一步的说明。

    我认为这是一个很难在具有推力的GPU上实现的问题


    我曾经做过一个类似的模拟,我必须对同一个系统的许多初始条件进行积分,但每次积分都会在不同的步骤后停止。不仅仅是微小的变化,还有数量级的变化,比如1000到10^6步之间。我使用在48个内核上运行的OpenMP编写了一个并行化程序。对于OpenMP并行化,我所做的非常简单:只要一个初始条件完成,下一个条件就会开始。只要轨迹的总数远大于并行线程,这是相当有效的。原则上,您也可以通过这种方式在GPU上实现它。一旦一条轨迹完成,就用一个新的初始条件替换它。当然,你必须做一些簿记,特别是如果你的系统是依赖于时间的。但总的来说,我认为这可能有效。

    你说的“一组点”是什么意思?你有一个大的常微分方程,它由许多小的常微分方程组成,具有不同的参数或初始条件吗?在这种情况下,仅在单独的部分上停止积分并不容易。是的,我必须从许多不同的初始条件开始执行相同的积分。好的,这不是很容易解决的。我很快会尝试绘制一个解决方案。也许你可以抛出一个异常来保证整个计算。这听起来比我的解决方案要简单一些。谢谢,我认为这是正确的方法,我也有一个在OpenMP上实现它的想法,但是我如何在GPU上实现它呢?我认为使用odeint我可以尝试的最近的事情是使用cuda_控制的_步进器分支。。。还有其他方法吗?这应该很容易与推力一起工作。你有两个设备向量,一个是当前在GPU上运行的,另一个应该运行的。如果当前运行的某个IC停止,只需将新IC复制到此位置并继续集成。如果没有更多已调度的IC,只需从设备_向量中删除此初始条件。对于这种方法,您应该使用always_resizer,因为在集成过程中,整个ODE的长度可能会发生变化。谢谢,我尝试了您的解决方案,它是有效的(如果我在第9行用
    custom
    替换
    default
    ),并且我的程序速度快了大约2倍!但我希望有一个程序,正如@mariomulansky所说:“只要一个初始条件完成,下一个条件就会开始”。不幸的是,到目前为止,我认为在odeint中并行化并不是这样做的。我看了cuda_控制的_步进机分支,很快我就会试试。
    class custom_error_checker
    {
    public:
    
        typedef double value_type;
        typedef thrust_algebra algebra_type;
        typedef thrust_operations operations_type;
    
        default_error_checker(
                const thrust::device_vector< int > &is_stopped ,
                value_type eps_abs = static_cast< value_type >( 1.0e-6 ) ,
                value_type eps_rel = static_cast< value_type >( 1.0e-6 ) ,
                value_type a_x = static_cast< value_type >( 1 ) ,
                value_type a_dxdt = static_cast< value_type >( 1 ) )
        : m_is_stopped( is_stopped ) ,
          m_eps_abs( eps_abs ) , m_eps_rel( eps_rel ) ,
          m_a_x( a_x ) , m_a_dxdt( a_dxdt )
        { }
    
    
        template< class State , class Deriv , class Err , class Time >
        value_type error( const State &x_old ,
                          const Deriv &dxdt_old ,
                          Err &x_err , Time dt ) const
        {
            return error( algebra_type() , x_old , dxdt_old , x_err , dt );
        }
    
        template< class State , class Deriv , class Err , class Time >
        value_type error( algebra_type &algebra ,
                          const State &x_old ,
                          const Deriv &dxdt_old ,
                          Err &x_err , Time dt ) const
        {
            // this overwrites x_err !
            algebra.for_each3( x_err , x_old , dxdt_old ,
                typename operations_type::template rel_error< value_type >(
                    m_eps_abs , m_eps_rel , m_a_x ,
                    m_a_dxdt * get_unit_value( dt ) ) );
    
            thrust::replace_if( x_err.begin() ,
                                x_err.end() ,
                                m_is_stopped.begin() ,
                                thrust::identity< double >()
                                0.0 );
    
            value_type res = algebra.reduce( x_err ,
                    typename operations_type::template maximum< value_type >() ,
                        static_cast< value_type >( 0 ) );
            return res;
        }
    
    private:
    
        thrust::device_vector< int > m_is_stopped;
        value_type m_eps_abs;
        value_type m_eps_rel;
        value_type m_a_x;
        value_type m_a_dxdt;
    };
    
    typedef runge_kutta_dopri5< double , state_type , double , state_type ,
        thrust_algebra , thrust_operation > stepper;
    typedef controlled_runge_kutta< stepper ,
        custom_error_checker > controlled_stepper ;
    typedef dense_output_runge_kutta< controlled_stepper > dense_output_stepper;
    
    thrust::device_vector< int > is_stopped;
    // initialize an is_finished
    dense_output_stepper s(
        controlled_stepper(
            custom_controller( is_stopped , ... )));
    
    void check_finish_status(
        const state_type &x ,
        thrust::device_vector< int > &is_stopped );