Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.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++ n维系统的模块化Runge-kutta四阶方法的实现_C++_Header Files_Numerical Methods_Runge Kutta - Fatal编程技术网

C++ n维系统的模块化Runge-kutta四阶方法的实现

C++ n维系统的模块化Runge-kutta四阶方法的实现,c++,header-files,numerical-methods,runge-kutta,C++,Header Files,Numerical Methods,Runge Kutta,我想把我的龙格库塔四阶码模块化。我不希望每次使用代码时都要编写和声明代码,但是在.hpp和.cpp文件中声明代码,以便分别使用它。但是我有一些问题。通常我想解一个n维方程组。为此,我使用了两个函数:一个用于方程组,另一个用于龙格-库塔法,如下所示: double F(double t, double x[], int eq) { // System equations if (eq == 0) { return (x[1]); } else if (eq ==

我想把我的龙格库塔四阶码模块化。我不希望每次使用代码时都要编写和声明代码,但是在.hpp和.cpp文件中声明代码,以便分别使用它。但是我有一些问题。通常我想解一个n维方程组。为此,我使用了两个函数:一个用于方程组,另一个用于龙格-库塔法,如下所示:

double F(double t, double x[], int eq)
{
    // System equations
    if      (eq == 0) { return (x[1]); }
    else if (eq == 1) { return (gama * sin(OMEGA*t) - zeta * x[1] - alpha * x[0] - beta * pow(x[0], 3) - chi * x[2]); }
    else if (eq == 2) { return (-kappa * x[1] - phi * x[2]); }
    else { return 0; }
}

使用向量函数,其中向量算法取自特征值3

#include <eigen3/Eigen/Dense>
using namespace Eigen;
#包括
使用名称空间特征;
与问题中讨论的相同部分的

VectorXd Func(常数双t,常数向量xd&x)
{//求解简谐振子的方程
矢量3d-dxdt;
dxdt[0]=x[1];
dxdt[1]=gama*sin(ω*t)-zeta*x[1]-alpha*x[0]-beta*pow(x[0],3)-chi*x[2];
dxdt[2]=-kappa*x[1]-phi*x[2];
返回dxdt;
}
矩阵XXD RK4(向量xd Func(双t,常量向量xd&y),常量Ref&y0,双t,双h,整数步长)
{
矩阵y(y0.rows(),步数);
矢量xd k1,k2,k3,k4;
y、 col(0)=y0;

对于(It i=1;II高度怀疑代码是RK4方法的代码。您只得到订单1方法,而不是预期的订单4方法。测试它,用不同大小的已知解决方案计算非标量测试问题的错误。您正在使用C++。您是否想过将ODE系统实现为导出维度的类。n和ODE函数(通过某些接口或基类)这个振荡器是一个圆耦合系统。你也验证了方法的顺序吗?正如我所说,这个方法仍然是1阶的,并且在第一步之后,数组将被填充1阶正确的值,所以如果步长足够小,仍然可以得到视觉上正确的结果。对于一些有大量样板的C++代码。看看答案,或者是一个更简单的实现,通过一些巧妙的指针处理,您可以在循环中压缩RK4的各个阶段,使用系数数组
c={0,0.5,0.5,1};
b={1,2,2,1};
来同时计算导数并更新下一个状态向量。
double F(double t, std::vector<double> x, int eq)
{
    // System Equations
    if (eq == 0) { return (x[1]); }
    else if (eq == 1) { return (gama * sin(OMEGA*t) - zeta * x[1] - alpha * x[0] - beta * pow(x[0], 3) - chi * x[2]); }
    else if (eq == 2) { return (-kappa * x[1] - phi * x[2]); }
    else { return 0; }
}

double rk4(double &t, std::vector<double> &x, double step, const int dim)
{
    std::vector<double> x_temp1(dim), x_temp2(dim), x_temp3(dim);
    std::vector<double> k1(dim), k2(dim), k3(dim), k4(dim);

    int j;

    for (j = 0; j < dim; j++) {
        x_temp1[j] = x[j] + 0.5*(k1[j] = step * F(t, x, j));
    }
    for (j = 0; j < dim; j++) {
        x_temp2[j] = x[j] + 0.5*(k2[j] = step * F(t + 0.5 * step, x_temp1, j));
    }
    for (j = 0; j < dim; j++) {
        x_temp3[j] = x[j] + (k3[j] = step * F(t + 0.5 * step, x_temp2, j));
    }
    for (j = 0; j < dim; j++) {
        k4[j] = step * F(t + step, x_temp3, j);
    }

    for (j = 0; j < dim; j++) {
        x[j] += (k1[j] + 2 * k2[j] + 2 * k3[j] + k4[j]) / 6.0;
    }

    t += step;

    for (j = 0; j < dim; j++) {
        return x[j];
    }
}

vector                 array

2.434 s   |        |   0.859 s
2.443 s   |        |   0.845 s
2.314 s   |        |   0.883 s
2.418 s   |        |   0.884 s
2.505 s   |        |   0.852 s
2.428 s   |        |   0.923 s
2.097 s   |        |   0.814 s
2.266 s   |        |   0.922 s
2.133 s   |        |   0.954 s
2.266 s   |        |   0.868 s
_______                _______
average = 2.330 s      average = 0.880 s
#include <eigen3/Eigen/Dense>
using namespace Eigen;
VectorXd Func(const double t, const VectorXd& x)
{ // equations for solving simple harmonic oscillator
    Vector3d dxdt;
    dxdt[0] = x[1];
    dxdt[1] = gama * sin(OMEGA*t) - zeta * x[1] - alpha * x[0] - beta * pow(x[0], 3) - chi * x[2]; 
    dxdt[2] = -kappa * x[1] - phi * x[2]; 
    return dxdt;
}

MatrixXd RK4(VectorXd Func(double t, const VectorXd& y), const Ref<const VectorXd>& y0, double t, double h, int step_num)
{
    MatrixXd y(y0.rows(), step_num );
    VectorXd k1, k2, k3, k4;
    y.col(0) = y0;

    for (int i=1; i<step_num; i++){
        k1 = Func(t, y.col(i-1));
        k2 = Func(t+0.5*h, y.col(i-1)+0.5*h*k1);
        k3 = Func(t+0.5*h, y.col(i-1)+0.5*h*k2);
        k4 = Func(t+h, y.col(i-1)+h*k3);
        y.col(i) = y.col(i-1) + (k1 + 2*k2 + 2*k3 + k4)*h/6;
        t = t+h;
    }
    return y.transpose();
}