C++ C+中的龙格库塔4+;洛伦兹系统

C++ C+中的龙格库塔4+;洛伦兹系统,c++,numerical-methods,differential-equations,runge-kutta,C++,Numerical Methods,Differential Equations,Runge Kutta,有人能在我的代码中找到错误吗?它在特殊的点中工作正常,但公差不适合该方法。我的Errorstepper非常简单,所以我不认为它有什么问题。请帮忙 #include <math.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <time.h> #include <iostream> #include <string>

有人能在我的代码中找到错误吗?它在特殊的点中工作正常,但公差不适合该方法。我的Errorstepper非常简单,所以我不认为它有什么问题。请帮忙

#include <math.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <conio.h> 
#include <time.h> 
#include <iostream>
#include <string>
using namespace std;
const int q=10;
const double b=8/3;
double r;
double x,y,z;
struct delta
{
    double dx;
    double dy;
    double dz;
};

 double f1(double x , double y)
{
    return (q*(y-x));
}
double f2(double x,double y, double z)
{
    return ((-x)*z+r*x-y);
}
double f3(double x,double y,double z)
{
    return (x*y- b*z);
}
    delta calc(double x,double y,double z,double dh=0.1)
{
    double k1,k2,k3,k4,m1,m2,m3,m4,p1,p2,p3,p4,dx,dy,dz,a,b,c,h;

    h=dh;
    k1=h*f1(x,y);
    m1=h*f2(x,y,z);
    p1=h*f3(x,y,z);

    //h+=dh/2;
    k2=h*f1((x+k1/2.),(y+m1/2.));
    m2=h*f2((x+k1/2.) ,(y+m1/2.),(z+p1/2.));
    p2=h*f3((x+k1/2.),(y+m1/2.),(z+p1/2.));

//  h+=dh/2;
    k3=h*f1((x+k2/2.),(y+m2/2.));
    m3=h*f2((x+k2/2.),(y+m2/2.),(z+p2/2.));
    p3=h*f3((x+k2/2.),(y+m2/2.),(z+p2/2.));

//  h+=dh;
    k4=h*f1((x+k3),(y+m3));
    m4=h*f2((x+k3),(y+m3),(z+p3));
    p4=h*f3((x+k3),(y+m3),(z+p3));

    dx=(k1+2*k2+2*k3+k4)/6.;
    dy=(m1+2*m2+2*m3+m4)/6.;
    dz=(p1+2*p2+2*p3+p4)/6.;

    a=x+dx;
    b=y+dy;
    c=z+dz;
    delta add;

    add.dx=a;
    add.dy=b;
    add.dz=c;

    return add;

}
double Error(double x,double y ,double z, double h)
{
    double xi,e,a,b,c;
    delta end1=calc(x,y,z,h);
    xi=end1.dx;
    end1=calc(x,y,z,h/2);
    a=end1.dx;
    b=end1.dy;
    c=end1.dz;
    end1=calc(a,b,c,h/2);
    e=fabs((xi-end1.dx)/15);
    return e;

}
int main ()
{


    double dx,dy,dz,h,ei,xi,zi,yi,e,t=0,T=0.08,a,b,c,k=0,E,h1,e1,m,E1;
    int n=0;
    FILE *fff; 
    fff=fopen("data.txt","w"); 
    cout <<"x0=";
    cin>>x;
    cout<<"y0=";
    cin>>y;
    cout<<"z0=";
    cin>>z;
    cout<<"h=";
    cin>>h;
    cout<<"r=";
    cin>>r;
    cout<<"Time=";
    cin>>T;
    cout<<"Toleranse=";
    cin>>E;
    xi=x;
    double hmin=0.00005;
    if (E<=0.0000001) 
    hmin=hmin/100;
    else cout<<"ok"<<endl;

    E1=E/10;
do
    {


     e=Error(x,y,z,h);


while (e<E1 || e>E)
    {   
    if (e<E1)
        h+=hmin;
    else if (e>E)
        h-=hmin;
    else cout<<" ok"<<endl;
     e=Error(x,y,z,h);

    };/*
    while(e>E)
    {
    h=h/2;
     e=Error(x,y,z,h);
    };*/
    xi=x;
    yi=y;
    zi=z;
    ei=e;

    delta konec1=calc(x,y,z,h);

    x=end1.dx;
    y=end1.dy;
    z=end1.dz;

    t+=h;   
    k+=1;
//  cout<<"x="<<x<<" y= "<<y<<" z="<<z<<" Pogreshnost= "<<e<<" Time="<<t<<endl;
    fprintf(fff,"%lf, %lf, %lf, %.10lf  ,%lf ,%lf\n", x, y,z,e,t, h);               

}
while (t<=T);
fprintf(fff,"Step = %lf",T/k); 
fclose(fff);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
常数int q=10;
常数双b=8/3;
双r;
双x,y,z;
结构三角洲
{
双dx;
双dy;
双dz;
};
双f1(双x,双y)
{
收益率(q*(y-x));
}
双f2(双x,双y,双z)
{
返回((-x)*z+r*x-y);
}
双f3(双x、双y、双z)
{
返回(x*y-b*z);
}
增量计算(双x、双y、双z、双dh=0.1)
{
双k1、k2、k3、k4、m1、m2、m3、m4、p1、p2、p3、p4、dx、dy、dz、a、b、c、h;
h=dh;
k1=h*f1(x,y);
m1=h*f2(x,y,z);
p1=h*f3(x,y,z);
//h+=dh/2;
k2=h*f1((x+k1/2.),(y+m1/2.);
m2=h*f2((x+k1/2.),(y+m1/2.),(z+p1/2.);
p2=h*f3((x+k1/2.),(y+m1/2.),(z+p1/2.);
//h+=dh/2;
k3=h*f1((x+k2/2.),(y+m2/2.);
m3=h*f2((x+k2/2.),(y+m2/2.),(z+p2/2.);
p3=h*f3((x+k2/2.),(y+m2/2.),(z+p2/2.);
//h+=dh;
k4=h*f1((x+k3),(y+m3));
m4=h*f2((x+k3),(y+m3),(z+p3));
p4=h*f3((x+k3),(y+m3),(z+p3));
dx=(k1+2*k2+2*k3+k4)/6。;
dy=(m1+2*m2+2*m3+m4)/6。;
dz=(p1+2*p2+2*p3+p4)/6。;
a=x+dx;
b=y+dy;
c=z+dz;
增量加法;
加上.dx=a;
add.dy=b;
加上dz=c;
返回添加;
}
双误差(双x、双y、双z、双h)
{
双席,E,A,B,C;
delta end1=计算值(x,y,z,h);
xi=end1.dx;
end1=计算值(x,y,z,h/2);
a=end1.dx;
b=end1.dy;
c=end1.dz;
end1=计算值(a、b、c、h/2);
e=fabs((xi-end1.dx)/15);
返回e;
}
int main()
{
双DX,DY,DZ,H,EI,席,Zi,Yi,E,t=0,t=0.08,A,B,C,K=0,E,H1,E1,M,E1;
int n=0;
文件*fff;
fff=fopen(“data.txt”,“w”);
cout x;
库蒂;
库茨;
库思;
库特;
库特;
库特;
xi=x;
双hmin=0.00005;

如果(E你的错误步进器,看起来很简单,正在实现一些错误的想法

一般的假设是,最低阶的局部误差为
e=C·h^5
。因此,用一半的步长执行两个步骤会产生误差

e2=2·C·(h/2)^5=C·h^5/16=e/16. 
由于通过计算RK4步骤,我们只知道值
y1=y+e
y2=y+e2=y+e/16
,因此我们发现

y1-y2=15/16*e   or   e=16/15*(y1-y2)   and   e2=(y1-y2)/15.
假设局部误差均匀地、累加地转化为全局误差,则得到的全局误差为
e·(T/h)
。或者以不同的方式解释,
e/h
是局部错误密度,期望的全局错误
e
转化为平均错误密度
e/T
。因此,您必须将
e
e/T·h
进行比较,而不是与裸露的
e
进行比较。尤其是缺少因子
h
将导致不合适的step尺寸


整个步长计算在计算上也过于昂贵。由于已发现局部误差为
e=C·h^5
,且期望的局部误差为
e·h/T
,则可能的最佳步长
h1
(排除大的高阶效应)由

C·h1^4=E/T   or   h1 = h*(E/(e*T))^0.25.
这个公式比一个几千次迭代的循环要快得多,每个循环有3个RK4步。我们可以围绕这个公式进行检查,以确保新的步长确实存在局部错误,并且在伪概念C代码中,步长的变化不会太大

fac = 1.0;
do {
    h *= fac;
    y1 = /* RK4 step with h */;
    y2 = /* 2 RK4 steps with h/2 */;
    e = 16*norm(y1-y2)/15;
    fac = pow(E/(e*T), 0.25);
    fac = min(20, max(0.05, fac) );
} while( fac<0.5 or 2<fac ) 
// advance the integration
fac=1.0;
做{
h*=fac;
y1=/*RK4步进带h*/;
y2=/*2个RK4台阶,带h/2*/;
e=16*标准(y1-y2)/15;
fac=功率(E/(E*T),0.25);
fac=最小值(20,最大值(0.05,fac));

}尽管(FAC)你在使用调试器检查代码时观察到了什么?“有人能在我的代码中找到错误吗?”恕我直言,但我怀疑,除非有人会以某种方式得到补偿。你的输入是什么?你的输出是什么?预期的输出是什么?你是否试图缩小问题的范围?
e=fabs((xi-end1.dx)/15;
-这是什么?为什么是15?@AVK:因为15=2^4-1,请参见理查森外推法中的4阶方法。但它确实应该考虑整个状态向量。