所以我想用C程序实现月球绕地球的路径。
我的问题是您知道月球在Apogee和Perigee的速度和位置。
因此,我开始从Apogee解决它,但是我无法弄清楚如何将第二速度和位置添加为“初始值”。我用if
进行了尝试,但结果之间没有任何区别。任何帮助表示赞赏!
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef void (*ode)(double* p, double t, double* k, double* dk);
void euler(ode f, double *p, double t, double* k, double h, int n, int N)
{
double kn[N];
double dk[N];
double Rp = - 3.633 * pow(10,8); // x position at Perigee
for(int i = 0; i < n; i++)
{
f(p, 0, k, dk);
for (int j = 0; j < N; j++)
{
if (k[0] == Rp) // this is the "if" I mentioned in my comment
// x coordinate at Perigee
{
k[1] = 0; // y coordinate at Perigee
k[2] = 0; // x velocity component at Perigee
k[3] = 1076; // y velocity component at Perigee
}
kn[j] = k[j] + h * dk[j];
printf("%f ", kn[j]);
k[j] = kn[j];
}
printf("\n");
}
}
void gravity_equation(double* p, double t, double* k, double* dk)
{
// Earth is at the (0, 0)
double G = p[0]; // Gravitational constant
double m = p[1]; // Earth mass
double x = k[0]; // x coordinate at Apogee
double y = k[1]; // y coordinate at Apogee
double Vx = k[2]; // x velocity component at Apogee
double Vy = k[3]; // y velocity component at Apogee
dk[0] = Vx;
dk[1] = Vy;
dk[2] = (- G * m * x) / pow(sqrt((x * x)+(y * y)),3);
dk[3] = (- G * m * y) / pow(sqrt((x * x)+(y * y)),3);
}
void run_gravity_equation()
{
int N = 4; // how many equations there are
double initial_values[N];
initial_values[0] = 4.055*pow(10,8); // x position at Apogee
initial_values[1] = 0; // y position at Apogee
initial_values[2] = 0; // x velocity component at Apogee
initial_values[3] = (-1) * 964; //y velocity component at Perigee
int p = 2; // how many parameters there are
double parameters[p];
parameters[0] = 6.67384 * pow(10, -11); // Gravitational constant
parameters[1] = 5.9736 * pow(10, 24); // Earth mass
double h = 3600; // step size
int n = 3000; // the number of steps
euler(&gravity_equation, parameters, 0, initial_values, h, n, N);
}
int main()
{
run_gravity_equation();
return 0;
}
答案 0 :(得分:2)
您的界面是
euler(odefun, params, t0, y0, h, n, N)
其中
N = dimension of state space
n = number of steps to perform
h = step size
t0, y0 = initial time and value
此过程的预期功能似乎是在数组y0
内返回更新后的值。没有理由插入一些hack来迫使状态具有一些初始条件。初始条件作为参数传递。就像您在void run_gravity_equation()
中所做的一样。集成例程应该与物理模型的细节无关。
您极不可能在第二次在k[0] == Rp
中达到相同的值。您可以做的是检查Vx
中的符号变化,即k[1]
以查找极端x
坐标的点或线段。
尝试进一步解释您的描述,您想要做的是解决一个边值问题,其中x(0)=4.055e8
,x'(0)=0
,y'(0)=-964
和x(T)=-3.633e8
,{{1 }}。这具有解决单次或多次射击的边值问题的高级任务,此外,其上限是可变的。
您可能希望使用 Kepler定律进一步了解该问题的参数,以便您可以通过正向集成来解决它。 第一项开普勒定律的开普勒椭圆具有以下公式(按x'(T)=0
的Apogee缩放,phi=0
的Perigee缩放)
phi=pi
这样
r = R/(1-E*cos(phi))
给出
R/(1-E)=4.055e8 and R/(1+E)=3.633e8,
此外,角速度由第二开普勒定律
给出R=3.633*(1+E)=4.055*(1-E)
==> E = (4.055-3.633)/(4.055+3.633) = 0.054891,
R = 3.633e8*(1+0.05489) = 3.8324e8
给出Apogee(phi'*r^2 = const. = sqrt(R*G*m)
)上的切线速度
r=R/(1-E)
和近地点(y'(0)=phi'*r = sqrt(R*G*m)*(1-E)/R = 963.9438
)
r=R/(1+E)
确实可以重现您在代码中使用的常量。
开普勒椭圆的面积是最小直径和最大直径乘积的-y'(T)=phi'*r = sqrt(R*G*m)*(1+E)/R = 1075.9130
倍。最小的直径可以在pi/4
处找到,最大的是远地点和近地点半径之和,因此面积为
cos(phi)=E
同时,它是整个pi*R/sqrt(1-E^2)*(R/(1+E)+R/(1-E))/2= pi*R^2/(1-E^2)^1.5
期间0.5*phi*r^2
的积分,因此等于
2*T
这是第三开普勒定律。这样可以将半周期计算为
sqrt(R*G*m)*T
对于T = pi/sqrt(G*m)*(R/(1-E^2))^1.5 = 1185821
,应该在h = 3600
和n=329
(n=330
)之间达到一半。与n=329.395
和Euler步骤的集成提供了scipy.integrate.odeint
的下表:
h=3600
与 n [ x[n], y[n] ] for odeint/lsode for Euler
328 [ -4.05469444e+08, 4.83941626e+06] [ -4.28090166e+08, 3.81898023e+07]
329 [ -4.05497554e+08, 1.36933874e+06] [ -4.28507841e+08, 3.48454695e+07]
330 [ -4.05494242e+08, -2.10084488e+06] [ -4.28897657e+08, 3.14986514e+07]
,h=36
n=32939..32940
对于Euler方法而言,该方法稍微接近一点,但效果却好得多。