2012-02-23 1 views
1

J'ai regardé autour en ligne pendant quelques temps maintenant pour des méthodes d'intégration pour un moteur de physique que j'essaye de coder pour le plaisir (dois aimer le nerdiness là: P). J'ai trouvé la méthode d'Euler, RK4, et Verlet (ainsi que la version corrigée dans le temps). J'ai aussi essayé de trouver certaines de mes méthodes. Je me demandais si vous en connaissiez d'autres que vous trouviez intuitifs ou utiles. Merci. EDIT: Merci pour toute votre aide jusqu'à maintenant. En ce qui concerne la clarification: peut-être que je veux dire l'intégration numérique. Étonnamment, dans toutes mes recherches, je n'ai pas trouvé autant que le NOM technique pour ce que j'essaie de faire! Peut-être décrivant mon problème spécifique rendra ma question plus claire. Disons que je veux simuler une balle se déplaçant à travers un champ gravitationnel circulaire (ou sphérique une fois que j'implémente 3d). Cette bille rencontrera des vecteurs de force qui peuvent être utilisés pour calculer un vecteur d'accélération correspondant au point où se trouve la bille sur cette coche spécifique. De votre classe de physique, vous savez que la vitesse = accélération * temps mais mon problème est que la balle est techniquement sur ce point pendant un instant, représenté mathématiquement dans le calcul par dt. Évidemment, je ne peux pas utiliser un nombre infinitésimal en C++ donc je dois approximer la solution en utilisant des méthodes d'intégration instantanée (un terme que j'ai entendu dans certaines lectures mais je peux me tromper complètement) ou ce que vous pensez s'appelle intégration numérique. juste donc j'ai changé le titre).Quels sont les bons algorithmes d'intégration numérique pour un moteur physique?

Voici mon (succès) tentative de mise en œuvre de la méthode d'Euler de l'intégration numérique:

//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 
    } 

Parce que l'accélération est constante et cette différence est en fait résoluble (pourquoi je l'utilise pour tester, la solution est position = temps^2, ceci est assez précis mais si vous le compliquez un peu, par exemple en faisant varier l'accélération dans le temps, l'algorithme perd de sa précision très rapidement, encore une fois merci

+3

Qu'entendez-vous par "intégration instantanée"? Voulez-vous dire "intégration numérique?" –

+0

Je pense que l'auteur signifie "intégration numérique des équations différentielles ordinaires". La méthode de Runge-Kutta est plutôt bonne. – lapk

+0

@Nicol Bolas J'ai fait de mon mieux pour clarifier pour vous les gars. – AnalyticalInsanity

Répondre

2

algorithmes pour l'intégration numérique des ODE Voir this Wikipedia article pour un overvi ew. Les algorithmes qui conviennent dépendent fortement des propriétés de l'ODE que vous essayez de résoudre. La méthode d'Euler donne rarement de bons résultats, dans la mesure où vous avez souvent besoin d'un très petit pas pour obtenir une bonne approximation de la solution (mais cela est très facile à mettre en œuvre, donc bon pour un premier essai). Il existe des variantes comme la méthode d'Euler rétrograde qui peut faire un peu mieux.

Les Runge-Kutta methods sont une large classe de méthodes qui incluent la méthode d'Euler. Au fur et à mesure que vous augmentez l'ordre de la méthode, vous avez généralement besoin de moins de pas de temps pour atteindre la même précision, mais l'exécution des calculs à chaque étape devient de plus en plus coûteuse - RK4 est utilisé très souvent.

En pratique, adaptive step size des techniques sont généralement utilisées pour contrôler le pas de temps pour atteindre une précision désirée.

Il existe de nombreuses implémentations de solveurs ODE, pour lesquelles les gens ont beaucoup travaillé. Bien qu'il soit intéressant de savoir comment ils fonctionnent, ces solveurs peuvent être compliqués, donc si vous n'êtes pas t satisfait des résultats que vous obtenez de vos propres tentatives, il pourrait être une meilleure idée de regarder dans les routines existantes, telles que those in the GNU Scientific Library.

2

Vous avez une équation différentielle de second ordre (ODE) x '' = f (x, x ', t). x peut être un vecteur et x 'et x' 'sont les dérivées première et seconde par rapport au temps. Dans votre cas, x est la position, x 'est la vitesse et x' 'est l'accélération.Habituellement, on transforme ce second ordre ODE dans un premier ODE en introduisant X = x, Y = x » et on obtient

X '= Y Y' = f (X, Y)

vous pouvez utiliser les schémas classiques pour résoudre ODE comme Runge-Kutta, Dormand-Prince, Adams-Bashforth, ...

Beaucoup de ces méthodes sont implémentées dans odeint qui est assez facile à utiliser.

Questions connexes