我正在尝试做一个任务,我必须为限制的3体引力问题编写一个模拟,有两个固定质量和一个测试质量。我已经给出了我需要使用的方程式,但要么我没有正确理解它们,要么我没有正确实现。我会非常感激有人可以帮助我朝着正确的方向前进。
我获得的信息如下:
http://www.flickr.com/photos/91029993@N07/8269806430/in/photostream
基本上我一直试图测试单个质量,但是我的程序给了我测试质量运动的直线,在很短的时间内看起来好像程序运行正常然后它没有'随着你越来越高的工作。 (见图像,这些输入为1 0.4 0.5 0 -1)
http://www.flickr.com/photos/91029993@N07/8268764897/in/photostream
我最初非常忠实地编写了我的程序,给出了如下公式:
#include<stdlib.h>
#include<stdio.h>
#include <math.h>
int main (int argc, char* argv[])
{
double dt=0.005, x[20000],y[20000],xv,yv,ax[20000],ay[20000],mneg,mpos,time;
int n;
FILE* output=fopen("proj1.out", "w");
sscanf(argv[1], "%lf", &mneg);
sscanf(argv[2], "%lf", &mpos);
sscanf(argv[3], "%lf", &x[0]);
sscanf(argv[4], "%lf", &y[0]);
sscanf(argv[5], "%lf", &xv);
sscanf(argv[6], "%lf", &yv);
x[1]=x[0]+(xv*dt);
y[1]=y[0]+(yv*dt);
for(n=1;n<150;n++)
{
ax[n]= (-mneg*(x[n]+1)/(pow((sqrt(pow((x[n]+1),2))),3))) -(mpos*(x[n]-1)/(pow((sqrt(pow((x[n]-1),2))),3)));
ay[n]= (-mneg*(y[n])/(pow(y[n],3))) -(mpos*(y[n])/(pow(y[n],3)));
x[n+1]=((2*x[n])-x[n-1] +(dt*dt*ax[n]));
y[n+1]=((2*y[n])-y[n-1]+(dt*dt*ay[n]));
fprintf(output, "%lf %lf\n",x[n-1], y[n-1]);
}
return(0);
}
然后我按照这里给出的建议尝试了一种新方法:Simulate the gravitational pull of a star?,所以我现在有:
#include<stdlib.h>
#include<stdio.h>
#include <math.h>
int main (int argc, char* argv[])
{
double dt=0.005, x[20000],y[20000],xv,yv,ax[20000],ay[20000],mneg,time,r,a;
int n;
FILE* output=fopen("proj1.out", "w");
sscanf(argv[1], "%lf", &mneg);
sscanf(argv[2], "%lf", &x[0]);
sscanf(argv[3], "%lf", &y[0]);
sscanf(argv[4], "%lf", &xv);
sscanf(argv[5], "%lf", &yv);
x[1]=x[0]+(xv*dt);
y[1]=y[0]+(yv*dt);
for(n=1;n<150;n++)
{
r=sqrt(pow((x[n]+1),2)+pow(y[n],2));
a=mneg/(r*r);
ax[n]=a*((x[n]+1)/r);
ay[n]=a*((y[n])/r);
x[n+1]=((2*x[n])-x[n-1] +(dt*dt*ax[n]));
y[n+1]=((2*y[n])-y[n-1]+(dt*dt*ay[n]));
fprintf(output, "%lf %lf\n",x[n-1], y[n-1]);
}
return(0);
}
然而,这并没有给我任何更好的结果。
我真的不知道从哪里开始,我想我正在使用这个方法,但我无法看到实际编程中的任何问题,所以我真的不知道发生了什么,所以任何建议或指针在正确的方向将非常感激!
答案 0 :(得分:1)
您没有将方程式正确地转换为代码,特别是测试质量与固定质量之间距离的表达式。计算加速度的正确方法是:
double dxm = x[n] + 1.0;
double dxp = x[n] - 1.0;
double dy = y[n];
double denom_minus_inv = pow(dxm*dxm + dy*dy, -1.5);
double denom_plus_inv = pow(dxp*dxp + dy*dy, -1.5);
ax[n] = -mneg*dxn*denom_minus_inv - mpos*dxp*denom_plus_inv;
ay[n] = -mneg*dy*denom_minus_inv - mpos*dy*denom_plus_inv;
请使用临时变量来存储中间表达式 - 不要将它们全部放在一个复杂的表达式中。现代编译器在优化代码时非常擅长消除冗余临时表达式。上面的代码使用了乘法通常比除法快一点的事实以及1.0/pow(sqrt(x), 3.0) == pow(x, -1.5)
。
我建议您使用velocity Verlet替换Verlet集成商。它明确地存储粒子速度,允许您在每一步计算系统的总能量(动能和势能之和)。它应该在整个运行过程中保持几乎相同(给出或采取舍入和离散化错误)。如果它偏离狂野,那么你就知道你没有正确计算你的力量。