构建模板化ODE解算器

Building a templated ODE solver

本文关键字:ODE 建模 构建      更新时间:2023-10-16

我正试图用以下函数声明实现一个模板化的ODE求解器:

template<class ODEFunction,class StopCondition=decltype(continue_always<ODEFunction>)> 
bool euler_fwd(ODEFunction& f,typename State<ODEFunction>::type& x_0
    ,double t_0,double dt,size_t N_iter
    ,StopCondition& cond=continue_always<ODEFunction>);

完整来源:

/*From SO answer*/
template<class F>
struct State;
template <class R, class... A> 
struct State<R (*)(A...)>
    {
    typedef R type;
    };
/*End from SO answer*/

/**Default stop condition. Always return 0 to continue operation.
*/
template<class ODEFunction>
bool continue_always(const typename State<ODEFunction>::type& x_0,double t_0)
    {return 0;}
/**Euler forward solver
*/
template<class ODEFunction,class StopCondition=decltype(continue_always<ODEFunction>)> 
bool euler_fwd(ODEFunction& f,typename State<ODEFunction>::type& x_0
    ,double t_0,double dt,size_t N_iter
    ,StopCondition& cond=continue_always<ODEFunction>)
    {
    size_t k=0;
    while(N_iter)
        {
        if(cond(x_0,t_0))
           {return 1;}
        x_0+=dt*f(x_0,k*dt);
        --N_iter;
        ++k;
        }
    return 0;
    }

尝试用一个简单的函数调用euler_fwd

double f(double x,double t)
    {return x;}

GCC省略continue_always谓词,编写

错误:无效使用不完整的类型"struct State"bool continue_always(const typename状态::type&x_0,双t_0)

test.cpp:18:47:错误:对'euler_fwd(double(&)(double,double),double&,双&,双&,size_t&)'

编辑:

如果我尝试跳过cond:的默认参数的使用

euler_fwd(testfunc,x_0,t_0,dt,N,continue_always<decltype(testfunc)>);

我仍然收到错误

test.cpp:18:97:注意:无法从重载函数"continue_always"解析地址

与其尝试操作函数类型(fcond的类型),为什么不将状态作为模板参数呢?

#include <cstdlib> // for size_t
#include <functional>
template<class R>
bool continue_always(const R& x_0,double t_0)
{return 0;}
template<class R> 
bool euler_fwd(std::function<R(const R &)> f,R& x_0
  ,double t_0,double dt,size_t N_iter
  ,std::function<bool(const R&, double)> cond=continue_always<R>)
{
  size_t k=0;
  while(N_iter)
  {
    if(cond(x_0,t_0))
      {return 1;}
    x_0+=dt*f(x_0,k*dt);
    --N_iter;
    ++k;
  }
  return 0;
}