四阶龙格库塔:行星轨道微分方程的积分

计算科学 数值分析 龙格库塔 一体化
2021-12-27 00:09:36

我应该积分微分方程rθ为了模拟轨道运动。我用的微分方程r是二阶并且θ是第一顺序。最终目标是绘制图表r(t),θ(t),我可能会在 python 中使用 matplotlib。我想知道是否有事先了解轨道和 Runge-Kutta 的人可以让我知道我的代码哪里出错了?它编译没有错误,但没有返回我期望的值。这是我的代码,其中包含描述地球轨道的参数:

#include <stdio.h>
#include <math.h> 
#define N 3         /* number of first order equations */
#define dist 0.00001        /* stepsize in t*/
#define MAX 1       /* max for t */
#define MAXTHETA 2*M_PI

FILE *output;           /* internal filename */

void runge4(double x, double y[], double step);
double f(double x, double y[], int i);


int main()
{
double t, y[N];
int j;

void runge4(double x, double y[], double step); /* Runge-Kutta function */

double f(double x, double y[], int i);      /* function for derivatives */

output=fopen("kepler.rtf", "w");                   /* external filename */

y[0]= 1.02343552273569;                                       /* initial position */
y[1]= 6.18068911;                                       /* initial velocity */
y[2] = 0;                                               /* initial angle */

fprintf(output, "0\t%f\t%f\n", y[0], y[2]); /* prints time and position */

for (j=1; j*dist<=MAX ;j++)         /* time loop */
{
    t=j*dist;
    runge4(t, y, dist);

    fprintf(output, "%f\t%f\t%f\n", t, y[0], y[2]); /* prints time, position, theta */
}

fclose(output);
}

void runge4(double x, double y[], double step)
{
double h=step/2.0,          /* the midpoint */
    t1[N], t2[N], t3[N],        /* temporary storage arrays */
    k1[N], k2[N], k3[N],k4[N];  /* for Runge-Kutta */
int i;

for (i=0;i<N;i++) t1[i]=y[i]+0.5*(k1[i]=step*f(x, y, i));
for (i=0;i<N;i++) t2[i]=y[i]+0.5*(k2[i]=step*f(x+h, t1, i));
for (i=0;i<N;i++) t3[i]=y[i]+    (k3[i]=step*f(x+h, t2, i));
for (i=0;i<N;i++) k4[i]=        step*f(x+step, t3, i);

for (i=0;i<N;i++) y[i]+=(k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0;
}

double f(double x, double y[], int i)
{
    double k = 39.4784176044, m = 0.000003003, h = 0.00000300299, l = 0.0000188781;
    if (i==0) return(y[1]);         /* derivative of first equation (dr/dt)*/
    if (i==1) return((-k/(m*y[0]*y[0])) + (l*l)/(m*y[0]*y[0]*y[0])); /* derivative of second equation (d^2r/dt^2) */
    else return(h/(y[0]*y[0])); /* derivative of theta (d(theta)/dt) */
}

我用于位置的二阶微分方程,r, 是:

r¨=kmr2+l2mr3

参数在哪里l是角动量和k是引力常数乘以行星运行的物体的质量,在这种情况下是太阳。我用于的一阶微分方程θ是:

θ˙=hr2

h=l(m1m2m1+m2)1

在哪里m1m2是系统中两个物体的质量,方程中的质量项为h是减少的质量。所有参数的单位都是 AU、年和太阳质量。如果有人能指出我正确的方向,那就太棒了。

1个回答

正如所有评论员已经指出的那样:您的 ODE 有问题。

  • 为什么只有m为了r¨然后m1m2为了θ˙?
  • 为什么没有涉及的方程θ¨?
  • 为什么是l一个参数,人们实际上会期望一些动态的东西,比如rθ˙2对于角动量?
  • 为什么kmr2,人们期望的地方kmr2为了万有引力?

您显然希望使用极坐标在 2D 中模拟地球和太阳的天体力学(即经典的二体问题)。

具有动能的拉格朗日算子开始(参见此处以获得很好的推导,但不考虑数值解)m12(r˙2+r2θ˙2)和势能km1m2r,我们通过推导得到以下运动方程(欧拉-拉格朗日方程):

r¨=rθ˙2km2r2
θ¨=2r˙θ˙r

在哪里m2是太阳质量,即m2=1在太阳质量单位。

如果我然后在几个地方修改你的(抱歉但很丑)代码......

...
#define N 4         /* number of first order equations */
...
*/
    y[1]= 0.;                                       /* initial velocity */
    y[2] = 0;                                               /* initial angle */
    y[3] = 2*M_PI;                                          /* angular velocity */
...
        if(j % 100 == 0)
            fprintf(output, "%f\t%f\t%f\t%f\t%f\n", t, y[0], y[1], y[2], y[3]); /* only output every 100th point and output full y */
...
    switch(i) {
    case 0:
        return(y[1]);         /* derivative of first equation (dr/dt)*/
        break;;
    case 1:
        return((-k/(y[0]*y[0])) + y[0]*y[3]*y[3]); /* derivative of second equation (d^2r/dt^2) */
        break;;
    case 2:
        return(y[3]);       /* derivative of first equation (dtheta/dt)*/
        break;;
    case 3:
        return(-2.0*y[1]*y[3]/y[0]);        /* derivative of second equation (d^2theta /dt^2) */
        break;;
    }

然后我得到了一个很好的时间整合θ不断增加和r在其初始值附近摇摆不定。

在此处输入图像描述

换句话说,您的 RK4 代码似乎可以正常工作。

最后一句话:如果您使用时间步长(将其提高到 1e-3),您会注意到角速度丢失了:它不会返回到其初始值2π但较小的值。这是其他(辛)积分器更好地工作的地方,因为它们可以保存能量,因此对于这些周期性运动更稳定,请参阅@cpraveen 的评论。