この微分方程式を解くように求められました。
(x,y,vx,vy)'=(vx,vy,vy,-vx)
2*pi
ピリオド付きの円運動を返す必要があります。私は機能を実装しました:
class FunzioneBase
{
public:
virtual VettoreLineare Eval(double t, const VettoreLineare& v) const = 0;
};
class Circonferenza: public FunzioneBase
{
private:
double _alpha;
public:
Circonferenza(double alpha) { _alpha = alpha; };
void SetAlpha(double alpha) { _alpha = alpha; };
virtual VettoreLineare Eval(double t, const VettoreLineare& v) const;
};
VettoreLineare Circonferenza::Eval(double t, const VettoreLineare& v) const
{
VettoreLineare y(4);
if (v.GetN() != 4)
{
std::cout << "errore" << std::endl;
return 0;
};
y.SetComponent(0, v.GetComponent(2));
y.SetComponent(1, v.GetComponent(3));
y.SetComponent(2, pow(pow(v.GetComponent(0), 2.) + pow(v.GetComponent(1), 2.), _alpha) * v.GetComponent(3));
y.SetComponent(3, - pow(pow(v.GetComponent(0), 2.) + pow(v.GetComponent(1), 2.), _alpha)) * v.GetComponent(2));
return y;
};
に_alpha
等しい場所0
。さて、これはオイラーの方法で問題なく機能します。この ODE を に対して積分すると2 * pi * 10
、初期条件 が与えられ、(1, 0, 0, -1)
ある精度で、予想どおり、位置がの範囲内で に0.003
匹敵することがわかります。しかし、同じ ODE を次のように実装されたルンゲ・クッタの方法 (精度で数秒) と統合すると、次のようになります。(1, 0)
1 ± 0.1
0.003
2 * pi * 10
class EqDifferenzialeBase
{
public:
virtual VettoreLineare Passo (double t, VettoreLineare& x, double h, FunzioneBase* f) const = 0;
};
class Runge_Kutta: public EqDifferenzialeBase
{
public:
virtual VettoreLineare Passo(double t, VettoreLineare& v, double h, FunzioneBase* f) const;
};
VettoreLineare Runge_Kutta::Passo(double t, VettoreLineare& v, double h, FunzioneBase* _f) const
{
VettoreLineare k1 = _f->Eval(t, v);
VettoreLineare k2 = _f->Eval(t + h / 2., v + k1 *(h / 2.));
VettoreLineare k3 = _f->Eval(t + h / 2., v + k2 * (h / 2.));
VettoreLineare k4 = _f->Eval(t + h, v + k3 * h);
VettoreLineare y = v + (k1 + k2 * 2. + k3 * 2. + k4) * (h / 6.);
return y;
}
プログラムは、4 次のルンゲ クッタ法で、理論的には精度が必要な場合に、およそ にx
等しい位置を返します。確認したところ、Runge_Kutta の周期はほぼ 4 倍になっているように見えます (経過中に からに到達するため) が、その理由がわかりません。これは私のメインの内容です:0.39
1E-6
2 * pi
x
1
0.48
VettoreLineare DatiIniziali (4);
Circonferenza* myCirc = new Circonferenza(0);
DatiIniziali.SetComponent(0, 1.);
DatiIniziali.SetComponent(1, 0.);
DatiIniziali.SetComponent(2, 0.);
DatiIniziali.SetComponent(3, -1.);
double passo = 0.003;
Runge_Kutta myKutta;
for(int i = 0; i <= 2. * M_PI / passo; i++)
{
DatiIniziali = myKutta.Passo(0, DatiIniziali, passo, myCirc);
cout << DatiIniziali.GetComponent(0) << endl;
};
cout << 1 - DatiIniziali.GetComponent(0) << endl;
前もって感謝します。