簡體   English   中英

C中的N體模擬

[英]N body simulation in C

我正在嘗試編寫代碼來使用 Runge Kutta 4 積分算法解決 n 體問題。 我正在使用質量均勻分布在 0 和 1 之間的兩個物體測試代碼,位置分布遵循與 1/r^2 成正比的密度定律,速度分布為麥克斯韋-玻爾茲曼分布。 我嘗試將系統集成為不同的 tmax,但我得到了圖中的軌道,但我無法弄清楚問題所在。 任何幫助,將不勝感激。

這是代碼:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct {
    double x, y, z;
}vector;

double *masse;
vector *pos, *vel, *forza;



int main(int argc, char** argv){
    double epsilon, dt, tmax,t;
    double dx, dy, dz, dist, invdist, invdist3;
    int N, i, l, m, n, s, j;
    double a, b;
    vector *k1, *k2, *k3, *k4, *w1, *w2, *w3, *w4, *pos1, *vel1;
    if(argc!=5) {
        fprintf(stdout,"Il programma prende in input il softening, il passo d'integrazione, il tempo massimo d'integrazione e il numero di corpi del sistema\n", argv[0]);
        exit(1);
    }

    epsilon=strtod(argv[1],NULL);
    dt=strtod(argv[2],NULL);
    tmax=strtod(argv[3],NULL);
    N=strtod(argv[4],NULL);

    FILE* fp=fopen("Cond_ini.out", "r");
    if(fp==NULL){
        perror("Errore: file non trovato\n");
        exit(1);
    }

    masse=(double*)malloc(N*sizeof(double));
    pos=(vector*)malloc(N*sizeof(vector));
    vel=(vector*)malloc(N*sizeof(vector));
    forza=(vector*)malloc(N*sizeof(vector));
    k1=(vector*)malloc(N*sizeof(vector));
    k2=(vector*)malloc(N*sizeof(vector));
    k3=(vector*)malloc(N*sizeof(vector));
    k4=(vector*)malloc(N*sizeof(vector));
    w1=(vector*)malloc(N*sizeof(vector));
    w2=(vector*)malloc(N*sizeof(vector));
    w3=(vector*)malloc(N*sizeof(vector));
    w4=(vector*)malloc(N*sizeof(vector));
    pos1=(vector*)malloc(N*sizeof(vector));
    vel1=(vector*)malloc(N*sizeof(vector));





    for(i=0;i<N;i++){
        fscanf(fp,"%lf %lf %lf %lf %lf %lf %lf", &masse[i], &pos[i].x, &pos[i].y, &pos[i].z, &vel[i].x, &vel[i].y, &vel[i].z);
    }
    fclose(fp);

    printf("Condizioni iniziali:\n");
    for(l=0;l<N;l++){
        printf("%lf %lf %lf %lf %lf %lf %lf\n", masse[l], pos[l].x, pos[l].y, pos[l].z, vel[l].x, vel[l].y, vel[l].z);
    }

    for(t=0;t<tmax;t+=dt){
        for(m=0;m<N;m++){
            for(n=0;n<N;n++){
                if(m!=n){

                    k1[n].x=dt*vel[n].x;
                    k1[n].y=dt*vel[n].y;
                    k1[n].z=dt*vel[n].z;

                    dx=pos[n].x-pos[m].x;
                    dy=pos[n].y-pos[m].y;
                    dz=pos[n].z-pos[m].z;
                    dist=(dx*dx)+(dy*dy)+(dz*dz)+(epsilon*epsilon);
                    invdist=(1/sqrt(dist));
                    invdist3=(invdist*invdist*invdist);
                    forza[n].x=dx*invdist3*masse[n];
                    forza[n].y=dy*invdist3*masse[n];
                    forza[n].z=dz*invdist3*masse[n];

                    w1[n].x=dt*forza[n].x;
                    w1[n].y=dt*forza[n].y;
                    w1[n].z=dt*forza[n].z;

                    pos1[n].x=pos[n].x+(0.5*k1[n].x);
                    pos1[n].y=pos[n].y+(0.5*k1[n].y);
                    pos1[n].z=pos[n].z+(0.5*k1[n].z);
                    vel1[n].x=vel[n].x+(0.5*w1[n].x);
                    vel1[n].y=vel[n].y+(0.5*w1[n].y);
                    vel1[n].z=vel[n].z+(0.5*w1[n].z);

                    k2[n].x=dt*(vel[n].x+(0.5*w1[n].x));
                    k2[n].y=dt*(vel[n].y+(0.5*w1[n].y));
                    k2[n].z=dt*(vel[n].z+(0.5*w1[n].z));

                    dx=pos1[n].x-pos[m].x;
                    dy=pos1[n].y-pos[m].y;
                    dz=pos1[n].z-pos[m].z;
                    dist=(dx*dx)+(dy*dy)+(dz*dz)+(epsilon*epsilon);
                    invdist=(1/sqrt(dist));
                    invdist3=(invdist*invdist*invdist);
                    forza[n].x=dx*invdist3*masse[n];
                    forza[n].y=dy*invdist3*masse[n];
                    forza[n].z=dz*invdist3*masse[n];

                    w2[n].x=dt*forza[n].x;
                    w2[n].y=dt*forza[n].y;
                    w2[n].z=dt*forza[n].z;

                    pos1[n].x=pos[n].x+(0.5*k2[n].x);
                    pos1[n].y=pos[n].y+(0.5*k2[n].y);
                    pos1[n].z=pos[n].z+(0.5*k2[n].z);
                    vel1[n].x=vel[n].x+(0.5*w2[n].x);
                    vel1[n].y=vel[n].y+(0.5*w2[n].y);
                    vel1[n].z=vel[n].z+(0.5*w2[n].z);

                    k3[n].x=dt*(vel[n].x+(0.5*w2[n].x));
                    k3[n].y=dt*(vel[n].y+(0.5*w2[n].y));
                    k3[n].z=dt*(vel[n].z+(0.5*w2[n].z));

                    dx=pos1[n].x-pos[m].x;
                    dy=pos1[n].y-pos[m].y;
                    dz=pos1[n].z-pos[m].z;
                    dist=(dx*dx)+(dy*dy)+(dz*dz)+(epsilon*epsilon);
                    invdist=(1/sqrt(dist));
                    invdist3=(invdist*invdist*invdist);
                    forza[n].x=dx*invdist3*masse[n];
                    forza[n].y=dy*invdist3*masse[n];
                    forza[n].z=dy*invdist3*masse[n];

                    w3[n].x=dt*forza[n].x;
                    w3[n].y=dt*forza[n].y;
                    w3[n].z=dt*forza[n].z;

                    pos1[n].x=pos[n].x+(k3[n].x);
                    pos1[n].y=pos[n].y+(k3[n].y);
                    pos1[n].z=pos[n].z+(k3[n].z);
                    vel1[n].x=vel[n].x+(w3[n].x);
                    vel1[n].y=vel[n].y+(w3[n].y);
                    vel1[n].z=vel[n].z+(w3[n].z);


                    k4[n].x=dt*(vel[n].x+w3[n].x);
                    k4[n].y=dt*(vel[n].y+w3[n].y);
                    k4[n].z=dt*(vel[n].z+w3[n].z);

                    dx=pos1[n].x-pos[m].x;
                    dy=pos1[n].y-pos[m].y;
                    dz=pos1[n].z-pos[m].z;
                    dist=(dx*dx)+(dy*dy)+(dz*dz)+(epsilon*epsilon);
                    invdist=(1/sqrt(dist));
                    invdist3=(invdist*invdist*invdist);
                    forza[n].x=dx*invdist3*masse[n];
                    forza[n].y=dy*invdist3*masse[n];
                    forza[n].z=dy*invdist3*masse[n];

                    w4[n].x=dt*forza[n].x;
                    w4[n].y=dt*forza[n].y;
                    w4[n].z=dt*forza[n].z;

                    a=k1[n].x+(2*k2[n].x)+(2*k3[n].x)+k4[n].x;
                    a=a/6;
                    pos1[n].x=pos[n].x+a;
                    a=k1[n].y+(2*k2[n].y)+(2*k3[n].y)+k4[n].y;
                    a=a/6;
                    pos1[n].y=pos[n].y+a;
                    a=k1[n].z+(2*k2[n].z)+(2*k3[n].z)+k4[n].z;
                    a=a/6;
                    pos1[n].z=pos[n].z+a;
                    b=w1[n].x+(2*w2[n].x)+(2*w3[n].x)+w4[n].x;
                    b=b/6;
                    vel1[n].x=vel[n].x+a;
                    b=w1[n].y+(2*w2[n].y)+(2*w3[n].y)+w4[n].y;
                    b=b/6;
                    vel1[n].y=vel[n].y+a;
                    b=w1[n].z+(2*w2[n].z)+(2*w3[n].z)+w4[n].z;
                    b=b/6;
                    vel1[n].z=vel[n].z+a;
                }
            }
            for(j=0;j<N;j++) {
                forza[j].x=0;
                forza[j].y=0;
                forza[j].z=0;
            }
        }
        for(i=0;i<N;i++){
            pos[i].x=pos1[i].x;
            pos[i].y=pos1[i].y;
            pos[i].z=pos1[i].z;
            vel[i].x=vel1[i].x;
            vel[i].y=vel1[i].y;
            vel[i].z=vel1[i].z;
            printf("%lf %lf %lf %lf %lf %lf %lf\n", t, pos[i].x, pos[i].y, pos[i].z, vel[i].x, vel[i].y, vel[i].z);
            /*forza[i].x=0;
            forza[i].y=0;
            forza[i].z=0;*/
        }
    }
}

這是不同 tmax 下的軌道圖:

tmax=5 tmax=2 tmax=3

在查看您的代碼時,您的第一個錯誤是算法錯誤。 循環的順序必須是時間步長,然后是 RK4 階段,然后是星體相互作用項/力的總和。 這尤其意味着您需要為 Runge-Kutta 方法的每個階段單獨和重新計算交互作用。

制作一個單獨的過程來從位置數組填充力數組以避免復制粘貼編輯錯誤可能是有意義的。

對於此類有據可查的測試問題,請參閱 IVP 測試套件的 Pleiades 系統https://archimede.dm.uniba.it/~testset/testsetivpsolvers/?page_id=26

參見還有如何使用函數更新 C++ 類成員? 在那里我發布了在這個測試問題上實現這些原則/更正的代碼,用於使用 Verlet 方法(和 C++)進行模擬。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM