Столкновение частиц

Я пытаюсь написать код, который с учетом масс, скорости, смещения и радиусов N частиц в одномерном поле будет возвращать их позиции с небольшим шагом 0,03 с. Программа соответствует. Однако не выдает правильных значений.

#include <iostream>
#include <cmath>
#include <fstream>
#include <vector>


using namespace std;



struct particle {
    double x;   //position of particle
    double im;  //inverse mass
    double v;   //velocity of particle
    double r;   //radius of particle
};

void bonkers(vector<particle> &array, int NN, double t, double ddt, int T);
double time(vector<particle> &a, int NN, int &whichn);
void collision(particle &a, particle &b);
void position(particle &a, double ddt);

void position(particle &a, double ddt)//position of particles
{
    a.x += ddt * a.v; //position = t * velocity
}

void collision(particle &a, particle &b)//velocities after collision
{
    double realativeV = a.v - b.v;
    double af = a.im / (a.im + b.im);
    double bf = b.im / (a.im + b.im);
    a.v -= 2.0 * af * realativeV;
    b.v += 2.0 * bf * realativeV;
}

double time(vector<particle> &a, int NN, int &whichn)//Finds time of first collision.
{
    double dt = 1e100; //really large number
    for (int n = 0; n < NN - 1 ; n++) 
    {
        double RelativeV = a[n].v - a[n + 1].v;
        if (RelativeV > 0)//this means dt won't be 0, no negative times
        {
            double Collisiont = ((a[n + 1].x - a[n + 1].r) - (a[n].x + a[n].r))/ RelativeV;//gives time of collision
            //time of collision worked out as time when the distance between the two balls centre is equal to their combined radi
            if (Collisiont < dt)//finds smallest possible time of collision
            {
                dt = Collisiont; //returns time of first collision
                whichn = n; //gives which particles collide. Therefore which particles velocities need to change
            }
        }
    }
    return dt;
}

void bonkers(vector<particle> &array, int NN, double t, double ddt, int T)
{

    ofstream myfile;
    myfile.open("example.txt");//sends all information to file called example.txt
    int whichn = 0;
    double k;
    double l = 0;
    for (int i = 0; i <= T; i++)//set arbitrary number of collision i.e. T
    {
        k = t;//after every collision k reset to 0 as time function works from 0
        while( k <= time(array, NN, whichn) )
        {
            myfile << l; //prints the time
            k += ddt; //incriments time
            l += ddt; //increments time, but doesn't reset time so gives total time

            for (int n = 1; n < NN -1 ; n++)
            {
                position(array[n], ddt);//calculates new position
                myfile << "\t" << array[n].x;//prints the positions of all the particles at said time
            } 
            myfile << endl;
        }
        collision(array[whichn], array[whichn + 1]);//asings new velocities to the two particles which collided
    }
    myfile.close();

}

int main()
{
    int N; //number of balls
    double m; //mass of balls
    int T = 50; //number of collisions
    double t = 0.0; //starts from 0 time
    double ddt = 0.03; //invrements by 0.03 seconds each time

    cout << "Input number of balls" << endl;
    cin >> N;

    vector<particle> a(N + 2); //extra two for the two walls, wall1 at 0 and wall2 at 20

    for (int k = 1; k <= N; k++)
    {
        cout << "Input mass of ball " << k << endl;
        cin >> m;
        a[k].im = 1.0 / m;  //finds inverse mass
        cout << "Input position of ball " << k << " between 0 and 20" << endl;
        cin >> a[k].x;
        cout << "Input speed of ball " << k << endl;
        cin >> a[k].v;
        cout << "Input radius of ball " << k << endl;
        cin >> a[k].r;
    }

    //asign wall variables
    a[0].im = 0;    //infinte mass, so walls don't move
    a[0].r = 0;
    a[0].x = 0; //wall1 at 0
    a[0].v = 0;
    a[N + 1].im = 0;    
    a[N + 1].r = 0;
    a[N + 1].x = 20;    //wall2 at 20
    a[N + 1].v = 0;

    bonkers(a, N + 2, t, ddt, T);   
    return 0;
}

Существует очень очевидная проблема, когда у вас есть только один мяч. Радиусы, масса и скорость равны 1. Скорость мячей почему-то изменяется в положении 10.03 вместо того, чтобы отскакивать от стены в положении 20.

Я считаю, что проблема заключается в части кода функции «время». Эта проблема становится более очевидной, если в файле example.txt в функции bonkers вместо «l» выводится «k».

Спасибо большое :)


person Emily    schedule 02.12.2014    source источник
comment
Использовали ли вы отладчик и пошагово выполняли код? Если да, то в чем проблема? Если это в режиме реального времени, рассматривали ли вы возможность вывода значений на консоль или в файл журнала?   -  person Thomas Matthews    schedule 03.12.2014
comment
Может быть, вы также предоставите свои исходные переменные? В противном случае я не смогу воссоздать ваши результаты...   -  person arc_lupus    schedule 03.12.2014


Ответы (1)


Проблема в этой строке.

while( k <= time(array, NN, whichn) )

Вы пересчитываете время до столкновения в каждой итерации цикла while, а также увеличиваете прошедшее время, k, а затем сравниваете их. Время до события и прошедшее время сравнивать не имеет смысла. Вы можете либо рассчитать время до столкновения и увеличить время, k, пока не доберетесь туда, либо вы можете пересчитать время до столкновения и сравнить с 0 на каждой итерации.

person Praxeolitic    schedule 02.12.2014
comment
Без проблем. Еще несколько вещей, которые я заметил: вы передаете размер std::vector как отдельную переменную, но для этого было бы лучше использовать std::vector.size(). Использование const поможет повысить ясность вашего кода, особенно если вы изменяете переменные, передаваемые по ссылке, как в вашей функции time(). - person Praxeolitic; 03.12.2014