Новый день, новая проблема...
Я сделал это так, как сказал Эрик, и создал метод ускорения!
Это выглядит так:
static Vector2 AccelerationOfTheMoon(Vector2 position)
{
double Mm = 7.349 * Math.Pow(10, 22);
double MagnitudeOfForce()
{
double MagF = position.LengthSquared();
return MagF;
}
Vector2 ForceAsVector()
{
return position.NegativeUnitVector() * MagnitudeOfForce();
}
Vector2 acceleration = ForceAsVector() / Mm;
}
На мой взгляд, мой метод, который называется AccelerationOfTheMoon, получает вектор 2 с позицией. Теперь я хочу работать с этим вектором, поэтому я создал другой метод, который должен возвращать мою величину в виде скаляра (двойного). Для этого я создал метод для вычисления величины вектора и возведения его в квадрат. Когда я вызываю свой MagnitudeOfForce-Method внутри моего ForceAsVector-Method, я пытаюсь умножить отрицательный единичный вектор на скаляр и вернуть его как Vector2.
Может быть, мне ужасно плохо, но я изо всех сил пытаюсь понять все, что сделал Эрик, и все еще нуждаюсь в вашей помощи!
Благодарю.
Вы допустили две очевидные ошибки и неудачный выбор алгоритма.
Во-первых, вы смоделировали положение Луны как одно число, а не как вектор в трехмерном пространстве, поэтому вы моделируете здесь простое гармоническое движение, как пружину, ограниченную одним измерением, а не орбиту. Начните с моделирования позиций и скоростей как трехмерных векторов, а не двойников.
Во-вторых, вы сделали знак гравитационной силы положительным, так что она является отталкивающей силой между двумя телами, а не притягивающей. Знак силы должен быть в направлении земли.
В-третьих, ваша реализация алгоритма Эйлера кажется правильной, но Эйлер - плохой выбор для численного решения орбитальных задач, потому что он не является консервативным; Вы можете легко попасть в ситуации, когда Луна набирает или теряет немного импульса, и это складывает и разрушает вашу красивую эллиптическую орбиту.
Поскольку орбита Луны гамильтонова, используйте симплектический алгоритм; это разработано, чтобы моделировать консервативные системы.
https://en.wikipedia.org/wiki/Symplectic_integrator
Этот подход, а также ваш эйлеровский подход, в основном направлены на поиск векторов состояний:
https://en.wikipedia.org/wiki/Orbital_state_vectors
Однако для вашей простой системы из двух тел существуют более простые методы. Если вы хотите сделать симуляцию, подобную космической программе Kerbal, в которой только ваша орбита влияет на вашу орбиту, а планеты с несколькими лунами "на рельсах", вам не нужно моделировать систему на каждую единицу времени разработать последовательность векторов состояний; Вы можете вычислить их непосредственно, учитывая кеплеровские элементы:
https://en.wikipedia.org/wiki/Orbital_elements
Мы знаем шесть элементов Луны с высокой степенью точности; из них вы можете вычислить положение в 3-пространстве Луны в любое время, опять же, предполагая, что ничто не мешает его орбите. (В действительности, лунная орбита изменяется солнцем, фактом, что земля не сфера, потоками, и так далее.)
ОБНОВИТЬ:
Прежде всего, так как это для курсовой работы, вы должны указать все ваши источники, и это включает в себя получение помощи из Интернета. Ваши инструкторы должны знать, какую работу вы выполняете и какую работу вы выполняли для вас.
Вы спросили, как сделать эту работу в двух измерениях; это кажется неправильным, но что угодно, делайте то, что говорит курсовая работа.
Правило, которое я хотел бы научить большему количеству начинающих, - это создать тип, метод или переменную, которая решит вашу проблему. В этом случае мы хотим представить поведение комплексного значения, поэтому оно должно быть типом, а этот тип должен быть типом значения. Типы значений struct
в С#. Итак, давайте сделаем это.
struct Vector2
{
double X { get; }
double Y { get; }
public Vector2(double x, double y)
{
this.X = x;
this.Y = y;
}
Обратите внимание, что векторы неизменны, как и числа. Вы никогда не мутируете вектор. Когда вам нужен новый вектор, вы создаете новый.
Какие операции нам нужно выполнить с векторами? Сложение векторов, скалярное умножение и скалярное деление - просто причудливое умножение. Позвольте реализовать те:
public static Vector2 operator +(Vector2 a, Vector2 b) =>
new Vector2(a.X + b.X, a.Y + b.Y);
public static Vector2 operator -(Vector2 a, Vector2 b) =>
new Vector2(a.X - b.X, a.Y - b.Y);
public static Vector2 operator *(Vector2 a, double b) =>
new Vector2(a.X * b, a.Y * b);
public static Vector2 operator /(Vector2 a, double b) =>
a * (1.0 / b);
Мы можем сделать умножение и в другом порядке, поэтому давайте реализуем это:
public static Vector2 operator *(double b, Vector2 a) =>
a * b;
Сделать вектор отрицательным - это то же самое, что умножить его на -1:
public static Vector2 operator -(Vector2 a) => a * -1.0;
И чтобы помочь нам отладить:
public override string ToString() => $"({this.X},{this.Y})";
}
И мы закончили с векторами.
Мы пытаемся смоделировать эволюцию параметров орбитального состояния, поэтому снова сделаем тип. Каковы параметры состояния? Положение и скорость:
struct State
{
Vector2 Position { get; }
Vector2 Velocity { get; }
public State(Vector2 position, Vector2 velocity)
{
this.Position = position;
this.Velocity = velocity;
}
Теперь перейдем к основному алгоритму. Что у нас есть? состояние и ускорение. Что мы хотим? Новое государство. Сделай метод:
public State Euler(Vector2 acceleration, double step)
{
Vector2 newVelocity = this.Velocity + acceleration * step;
Vector2 newPosition = this.Position + this.Velocity * step;
return new State(newPosition, newVelocity);
}
}
Супер. Что осталось? Нам нужно отработать ускорение. Сделай метод:
static Vector2 AccelerationOfTheMoon(Vector2 position)
{
// You do this. Acceleration is force divided by mass,
// force is a vector, mass is a scalar. What is the force
// given the position? DO NOT MAKE A SIGN MISTAKE AGAIN.
}
И теперь у вас есть все необходимые детали. Начиная с исходного состояния, вы можете повторно вызывать AccelerationOfTheMoon, чтобы получить новое ускорение, а затем вызывать Euler, чтобы получить новое состояние, и повторить.
Как новичок, внимательно изучите эти приемы. Обратите внимание на то, что я сделал: я создал типы для представления концептов и методы для представления операций над этими концепциями. Как только вы это сделаете, программа станет чрезвычайно понятной для чтения.
Подумайте, как бы вы расширили эту программу, используя эти методы; мы создали жестко запрограммированный метод AccelerationOfTheMoon
, но что, если мы хотим вычислить ускорения нескольких тел? Опять же, создайте тип для представления Body
; тело характеризуется State
и массой. Что, если мы хотим решить проблему n-тела? Наше вычисление ускорения должно было бы принять другие тела в качестве параметра. И так далее.
Если бы кто-то мог помочь, это было бы очень признательно.
Я сделал это так, как сказал Эрик, но борюсь с методом AcclerationOfTheMoon.
Я хотел бы вычислить величину Силы Гравитации, умножить ее на Единицу-Вектор Положения, чтобы получить Силу Гравитации в качестве вектора для моего начального состояния.
Единственное, с чем я сейчас борюсь, это синтаксис в этом методе, я не могу найти подходящий метод для расчета моей величины и вектора единицы. Помощь очень ценится, а также объяснить как можно больше, я хочу узнать!