2012-02-23 2 views
1

Я искал в Интернете какое-то время для методов интеграции в физический движок, который я пытаюсь запрограммировать для развлечения (нужно любить некрасивость там: P). Я нашел метод Эйлера, RK4 и Verlet (а также исправленную по времени версию). Я также пытался придумать некоторые из моих собственных методов. Мне было интересно, знаете ли вы о других, которые вы нашли интуитивно понятными или полезными. Благодарю.Каковы некоторые хорошие алгоритмы для численного интегрирования для физического движка?

EDIT: Спасибо за вашу помощь. Что касается уточнения: возможно, я имею в виду цифровую интеграцию. Удивительно, но во всех моих исследованиях я не нашел столько, сколько технического ИМЯ за то, что я пытаюсь сделать! Возможно, описание моей конкретной проблемы сделает мой вопрос более ясным. Позволяет сказать, что я хочу имитировать шар, движущийся через круговое (или сферическое, когда я реализую 3d) гравитационное поле. Этот шар столкнется с векторами силы, которые могут быть использованы для вычисления соответствующего вектора ускорения для точки, в которой шар находится на этом конкретном тике. Из вашего класса физики вы знаете, что скорость = время ускорения *, но моя проблема заключается в том, что шар технически находится на этой точке только мгновенно, математически представленный в исчислении на dt. Очевидно, что я не могу использовать бесконечно малое число в C++, поэтому я должен аппроксимировать решение с помощью методов мгновенной интеграции (термин, который я слышал в некоторых чтениях, но я мог быть совершенно не прав) или то, что вы считаете численной интеграцией (вы, вероятно, так что я изменил название).

Вот моя (успешная) попытка реализации метода Эйлера численного интегрирования:

//For console output. Note: I know I could just put "using namespace std;" but I hate doing that. 
    #include <iostream> 
    using std::cout; 
    using std::system; 
    using std::endl; 

    //Program entry 
    int main (void) 
    { 
     //Variable decleration; 
     double time = 0; 
     double position = 0; 
     double velocity = 0; 
     double acceleration = 2; 
     double dt = 0.000001; //Here is the "instantanious" change in time I was talking about. 
     double count = 0; //I use count to make sure I am only displaying the data at whole numbers. 

     //Each irritation of this loop is one tick 
     while (true) 
     { 

      //This next bit is a simplified form of Euler's method. It is what I want to "upgrade" 
      velocity += acceleration * dt; 
      position += velocity * dt; 

      if (count == 1/dt) //"count == 1/dt" will only return true if time is a whole number. 
      { 

       //Simple output to console 
       cout << "Time: " << time << endl; 
       cout << "Position: " << position << endl; 
       cout << "------------------" << endl; 
       system ("pause"); 

       count = 0; //To reset the counter. 

      } 

      //Update the counters "count" and "time" 
      count++; 
      time += dt; 

     } 
     return 1; //Program exit 
    } 

Поскольку ускорение постоянно и эта разница на самом деле решаемая (почему я использую его, чтобы проверить, раствор position = time^2, это довольно точно, но если вы сделаете это немного сложнее, например, за счет ускорения с течением времени, алгоритм теряет точность очень быстро. Опять же, спасибо!

+3

Что вы подразумеваете под «мгновенной интеграцией»? Вы имеете в виду «цифровую интеграцию»? –

+0

Я думаю, автор означает «числовое интегрирование обыкновенных дифференциальных уравнений». Метод Рунге-Кутты довольно хорош. – lapk

+0

@ Никол Болас Я сделал все возможное, чтобы разъяснить вам, ребята. – AnalyticalInsanity

ответ

2

Есть много разных алгоритмы для численного интегрирования ОДУ. См. this Wikipedia article для переопределения РЭБ. Какие алгоритмы подходят, сильно зависит от свойств ODE, которые вы пытаетесь решить. Метод Эйлера редко работает хорошо, поскольку вам часто требуется очень небольшой размер шага для достижения хорошего приближения к решению (но его очень легко реализовать, поэтому это может быть полезно для первой попытки). Существуют такие варианты, как обратный метод Эйлера, который может немного улучшить.

Runge-Kutta methods - это широкий класс методов, которые включают метод Эйлера. Когда вы увеличиваете порядок метода, вам обычно требуется меньше шагов времени для достижения такой же точности, но выполнение вычислений на каждом временном шаге становится все более дорогостоящим - RK4 используется очень часто, поскольку он имеет тенденцию к хорошему балансу.

На практике методы adaptive step size обычно используются для управления шагом времени для достижения желаемой точности.

Существует много существующих реализаций решателей ODE, к которым люди приложили много усилий - хотя хорошо, что вы заинтересованы в том, чтобы знать, как они работают, эти решатели могут стать довольно сложными, поэтому, t удовлетворены результатами, полученными вами от ваших собственных попыток, может быть лучше рассмотреть существующие подпрограммы, такие как those in the GNU Scientific Library.

2

У вас есть дифференциальное уравнение второго порядка (ODE) x '' = f (x, x », т). x может быть вектором, а x 'и x' 'являются первой и второй производной по времени. В вашем случае x - это положение, x '- скорость, а x - ускорение.Обычно один преобразует этот второй ОДУ порядка в первом ОДУ путем введения X = X, Y = X»и вы получите

X '= Y Y' = F (X, Y),

Затем вы можете использовать классические схемы для решения ODE, такие как Runge-Kutta, Dormand-Prince, Adams-Bashforth, ...

Многие из этих методов реализованы в odeint, который довольно прост в использовании.

 Смежные вопросы

  • Нет связанных вопросов^_^