简体   繁体   English

计算 N 个物体之间的力矢量返回不正确的值?

[英]Calculating force vectors between N bodies returns incorrect values?

I'm trying to write a function that calculates the force vectors acting on a body from N bodies using F = GMm/r^2 (given the masses and initial positions in.txt files), and stores the values in a dynamically allocated array.我正在尝试编写一个 function,它使用 F = GMm/r^2(给定质量和初始位置 in.txt 文件)计算作用在 N 个物体上的力矢量,并将这些值存储在动态分配的数组中. I think the issue stems from the calculation of the radius (distance between 2 bodies), as the values returned are incorrect.我认为问题源于半径(两个物体之间的距离)的计算,因为返回的值不正确。 The position vectors in the initial_positions.txt file are in this format (without the headers): initial_positions.txt 文件中的 position 向量采用以下格式(不带标题):

pos_x pos_y pos_z
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6

The masses in the masses.txt file are in this format: masss.txt 文件中的质量是这样的格式:

1
2
3
4
5

So that the body with mass 1 has initial position (1, 2, 3), the body with mass 2 has initial position (4, 5, 6) etc.因此,质量为 1 的物体的初始值为 position (1, 2, 3),质量为 2 的物体的初始值为 position (4, 5, 6) 等。

My code to read in the files and calculate the force vectors:我读取文件并计算力矢量的代码:

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

int NumberOfBodies(void) //finds the number of bodies from masses.txt file.
    {
    char character;
    char previousCharacter;
    int numberOfBodies = 1;

    FILE *file = fopen("masses.txt", "r");

    if (file == NULL)
        {
        printf("\nUnable to access the 'masses.txt' file.\n");
        exit(1);
        }
    else
        {
        while ((character = fgetc(file)) != EOF)
            {
            if (character == '\n' && previousCharacter != '\n')
                {
                numberOfBodies++;
                }
            previousCharacter = character;
            }
        }

    fclose(file);

    return numberOfBodies;
    }

double *ReadMasses(int numberOfBodies) //reads masses.
    {
    int row;
    int line;
    double *masses = malloc(sizeof(double) * numberOfBodies);

    FILE *file = fopen("masses.txt", "r");

    if (file == NULL)
        {
        printf("\nUnable to access the 'masses.txt' file.\n");
        exit(1);
        }

    for (row = 0; row < numberOfBodies; row++)
        {
        line = fscanf(file, "%lf", &masses[row]);

        if (line == EOF)
            {
            break;
            }
        }

    fclose(file);

    return masses;
    }

double **ReadInitialPositions(int numberOfBodies) //reads initial positions.
    {
    int row;
    int scan;
    double **initialPositions = malloc(sizeof(double*) * numberOfBodies);

    for (row = 0; row < numberOfBodies; row++)
        {
        initialPositions[row] = malloc(sizeof(double) * 3); //hardcoded as we only consider x, y, and z components of position.
        }

    FILE *file = fopen("initial_positions.txt", "r");

    if (file == NULL)
        {
        printf("\nUnable to access the 'initial_positions.txt' file.\n");
        exit(1);
        }

    for (row = 0; row < numberOfBodies; row++)
        {
        scan = fscanf(file, "%lf %lf %lf", &initialPositions[row][0], &initialPositions[row][1], &initialPositions[row][2]);

        if (scan == EOF)
            {
            break;
            }
        }

    fclose(file);

    return initialPositions;
    }

double **CalculateForces(int numberOfBodies, double *masses, double **initialPositions) //function  to calculate force vectors.
    {
    int row;
    int column;
    int currentBody = 0;
    double radius;
    double gravitationalConstant = 6.6743;
    double **forces = malloc(sizeof(double*) * numberOfBodies);

    for (row = 0; row < numberOfBodies; row++)
        {
        forces[row] = malloc(sizeof(double) * 3);
        }

    for (row = 0; row < numberOfBodies; row++)
        {
        for (column = 0; column < 3; column++)
            {
            if (row != currentBody)
                {
                radius = (initialPositions[row][column] - initialPositions[row][currentBody]); //I suspect the issue stems from this line.
                forces[row][column] = (gravitationalConstant * masses[row] * masses[currentBody]) / (radius * radius);
                currentBody++;
                }
            else
                {
                forces[row][column] = 0;
                currentBody++;
                }
            }
        }

    for (row = 0; row < numberOfBodies; row++)
        {
        for (column = 0; column < 3; column++)
            {
            printf(" %lf", forces[row][column]); //Prints force vectors.
            }
        printf(" \n");
        }

    return forces;
    }

int main(void)
    {
    int numberOfBodies;
    double *masses;
    double **initialPositions;

    numberOfBodies = NumberOfBodies();
    masses = ReadMasses(numberOfBodies);
    initialPositions = ReadInitialPositions(numberOfBodies);

    CalculateForces(numberOfBodies, masses, initialPositions);

    return 0;
    }

NumberOfBodies(), ReadMasses(), and ReadInitialPositions() all seem to be working as intended. NumberOfBodies()、ReadMasses() 和 ReadInitialPositions() 似乎都按预期工作。 Thanks in advance::)提前致谢::)

This has all the earmarks of code written without a firm grasp of the math.这具有在没有牢固掌握数学的情况下编写的代码的所有指定用途。 Try writing out the math first.尝试先写出数学。

GMm/r^2 gives the scalar force between two bodies. GMm/r^2 给出了两个物体之间的量力。 It acts along the direction vector between the bodies.它沿着物体之间的方向矢量起作用。 Consequently, the scalar must be split into its vector components.因此,必须将标量拆分为其矢量分量。 Splitting is just just multiplying by the direction vector scaled to unit length.分裂只是乘以缩放到单位长度的方向向量。

More to the point, if you are computing the force between bodies a and b, then更重要的是,如果你计算物体 a 和 b 之间的力,那么

Rab^2 = (xb - xa)^2 + (yb - ya)^2 + (zb - za)^ 2
Fab = ma mb / Rab^2

A unit vector from a to b has coordinates从 a 到 b 的单位向量具有坐标

Uabx = (xb - xa) / Rab
Uaby = (yb - ya) / Rab
Uabz = (zb - za) / Rab

Of course Rab = sqrt(Rab^2) computed above.当然是上面计算的 Rab = sqrt(Rab^2) 。

The three components of the force acting on a due to b are由于 b 作用在 a 上的力的三个分量是

Fabx = Uabx * Fab
Faby = Uaby * Fab
Fabz = Uabz * Fab

The force acting on b due to a is Fb = -Fa.由于 a 作用在 b 上的力为 Fb = -Fa。

Working this out as an algorithm:将其作为算法解决:

For each pair a,b of bodies
  Find r^2 the distance between a and b.
  Find Fab the scalar force between a and b.
  Find Ua the unit vector from a toward b.
  Find vector Fa by splitting Fab into three components using Ua.
  Add Fa into the total force acting on a.
  Add -Fa into the total force acting on b. 

A quick look at your code shows it can't be very close to correct.快速查看您的代码表明它不太接近正确。 Ex: it computes three different values of r for a pair of bodies.例如:它为一对物体计算三个不同的值 r。 There can be only one distance between two points in space!空间中两点之间只能有一个距离!

Hint: To get all pairs of integers (ignoring order) in [0..n-1] that don't include self-pairs like (1, 1), the standard pattern is loops that look like this:提示:要获取 [0..n-1] 中不包括自对(如 (1, 1))的所有整数对(忽略顺序),标准模式是如下所示的循环:

for (j = 1; j < n; j++)
  for (i = 0; i < j; i++)

This will iterate over ij pairs in the order (0, 1), (0, 2), (1, 2), (0, 3), (1, 3), (2, 3), ...这将按顺序迭代 ij 对 (0, 1), (0, 2), (1, 2), (0, 3), (1, 3), (2, 3), ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM