Гравитация и много частиц

1

У меня много частиц в космосе.

Каждая частица знает свое положение в пространстве, а также некоторые вещи, такие как масса, скорость и ускорение.

public class Particle
{
    float mass;
    float velocity;
    float acceleration;
}

У меня есть класс, который контролирует гравитацию. Этот класс имеет List всех Particles. Я могу рассчитать силу тяжести двух частиц, используя приведенную ниже формулу.

F1 = F2 = G*M1*M2/d^2

Как рассчитать это, когда у меня есть 5 частиц в моем списке? В будущем их будет больше.

Элемент 0 с 1, Элемент 1 с 2, Элемент 2 с 3, Элемент 3 с 4 и Элемент 4 с 0? (Это не кажется хорошей идеей).

Теги:
physics

3 ответа

1
Лучший ответ

Это должно быть хорошей отправной точкой:

namespace SO.NBody
{
    public class Particle
    {
        public double mass;
        public double[] position;
        public double[] velocity;
        public double[] acceleration;

        public Particle(double mass)
        {
            this.mass=mass;
            this.position=new double[Simulation.DOF];
            this.velocity=new double[Simulation.DOF];
            this.acceleration=new double[Simulation.DOF];
        }
    }

    public class Simulation
    {
        // Degrees of Freedom, Planar Simulation = 2, Spatial Simulation = 3
        public static int DOF=2;
        // Set Universal Gravity as Needed here
        public const double G=100;

        public Simulation()
        {
            Bodies=new List<Particle>();
            Time=0;
        }
        public List<Particle> Bodies { get; private set; }
        public double Time { get; set; }

        public void CalculateAllAccelerations()
        {
            for (int i=0; i<Bodies.Count; i++)
            {
                Bodies[i].acceleration=new double[DOF];
                for (int j=0; j<i; j++)
                {
                    // Find relative position, which is needed for
                    //   a) Distance
                    //   b) Direction
                    double[] step=new double[DOF];
                    double distance=0;
                    for (int k=0; k<DOF; k++)
                    {
                        step[k]=Bodies[i].position[k]-Bodies[j].position[k];
                        // distance is |x^2+y^2+..|
                        distance+=step[k]*step[k];
                    }
                    distance=Math.Sqrt(distance);
                    // Law of gravity
                    double force=G*Bodies[i].mass*Bodies[j].mass/(distance*distance);
                    // direction vector from [j] to [i]
                    double[] direction=new double[DOF];
                    for (int k=0; k<DOF; k++)
                    {
                        direction[k]=step[k]/distance;
                    }
                    // Add equal and opposite acceleration components
                    for (int k=0; k<DOF; k++)
                    {
                        Bodies[i].acceleration[k]-=direction[k]*(force/Bodies[i].mass);
                        Bodies[j].acceleration[k]+=direction[k]*(force/Bodies[j].mass);
                    }
                }
            }

        }

        public void UpdatePositions(double time_step)
        {
            CalculateAllAccelerations();
            // Use symplectic integration
            for (int i=0; i<Bodies.Count; i++)
            {
                for (int k=0; k<DOF; k++)
                {
                    Bodies[i].velocity[k]+=time_step*Bodies[i].acceleration[k];
                    Bodies[i].position[k]+=time_step*Bodies[i].velocity[k];
                }
            }
            Time+=time_step;
        }

        public void RunSimulation(double end_time, int steps)
        {
            double h=(end_time-Time)/steps;
            while (Time<end_time)
            {
                // Trim last step if needed so the sim ends when specified
                if (Time+h>end_time) { h=end_time-Time; }
                UpdatePositions(h);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var world=new Simulation();
            var sun=new Particle(1000);
            var p1=new Particle(1.15)
            {
                position=new double[] { 100, 0 },
                velocity = new double[] { 0, 10 }
            };
            var p2=new Particle(1.05)
            {
                position=new double[] { 120, 0 },
                velocity=new double[] { 0, 6 }
            };
            // ...

            world.Bodies.Add(sun);
            world.Bodies.Add(p1);
            world.Bodies.Add(p2);
            //...

            // Run for t=10.0, with 100 steps
            world.RunSimulation(10.0, 100);
        }
    }
}
  • 0
    Метод Эйлера как интегратор будет постепенно увеличивать энергию системы, пока что-то не достигнет скорости убегания. Нужно использовать симплектический интегратор, такой как метод Верлета, который использовал Ньютон, или метод более высокого порядка. См stackoverflow.com/a/23671054/3088138 и jsfiddle.net/4XVPH (не совсем правильно инициализирован, центр масс не остается в центре экрана). И сравните с оригинальной реализацией, поставленной с вопросом.
  • 0
    Да, я очень хорошо это знаю. Это обсуждение выходит за рамки первоначального вопроса. Как я уже сказал, это отправная точка, а не окончательное решение.
Показать ещё 3 комментария
1

На каждой временной отметке в вашей симуляции вычисляйте полную векторную силу на каждой частице и перемещайте эту частицу с ускорением, равным полной силе, деленной на массу частицы.

Чтобы найти полную силу на каждой частице, вычислите гравитационные силы между частицей и каждой из других частиц и добавьте все это. Обратите внимание, что когда вы вычисляете каждую силу, это должна быть векторная сила, то есть сила с величиной, как в вашем уравнении, и направление к другой частице. (То есть, используйте эту версию закона тяготения Ньютона: http://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation#Vector_form)

Наряду с силой все здесь должно быть сделано с использованием векторов: положение, скорость, ускорение и сила, все как векторы. Массы - ваши единственные скаляры, как вы описали проблему. (То есть в вашем классе Particle масса может быть плавающей, но скорость и ускорение должны быть векторами с компонентами x, y и z).

0

На самом деле закон гравитации применяется только к двум объектам. Это было как общее исследование Земли и Объекта в космосе или на поверхности.

https://en.wikipedia.org/wiki/Newton's_law_of_universal_gravitation

Здесь, если у вас есть 5 масс, вы можете сделать одну массовую неподвижную или относительную. Который был бы M1 затем проверял бы все массы по отношению к ним, обнаруживая каждую гравитацию. Может быть, здесь вам понадобится какой-то цикл foreach.

Работать с 5 телами в космосе сложно даже от мистера Ньютона, поэтому он дал вам уравнение для двух тел. Они взаимосвязаны друг с другом. Вы можете использовать эти 2 тела и проверить плотность тела каждого тела. Отнесите их друг другу, потому что изначально они не связаны.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню