Fragen zu Runge-Kutta
-
Hallo,
ich trete mit folgendem Anliegen an euch heran: Ich will einen Ball simulieren, auf den Beschleunigungskräfte wirken und der dementsprechend seine Flugbahn verändert. Bisherige Versuche mit Euler scheiterten kläglich weshalb ich nun versucht habe, das Runge-Kutta verfahren vierter Ordnung zu implementieren. Allerdings hängt der Simulationsausgang immer noch zu einem großen Teil von der eingestellten Schrittweite ab, was ich komisch finde da bei mir maximal Differentialgleichungen zweiten Grades vorhanden sind.
Ich bitte euch daher, mal einen kurzen Blich auf das entsprechenden Codeschnipsel zu werfen und mir eure Meinungen dazu zu sagen. Orientiert habe ich mich bei der Implementierung an folgender Seite: http://mitarbeiter.fh-heilbronn.de/~spieth/homepages/vorlesung/RungeKutta.pdf. Auf Seite 5 ganz unten ist das Verfahren für ein Differentialgleichungssystem 2. Ordnung dargestellt.
Zum Code: Der größte Teil sollte eigentlich selbsterklärend sein, "ball" speichert jeweils Position und Geschwindigkeit des Balles zu Beginn des Integrationsschrittes, worauf aufbauend calcAcceleration jeweils die Beschleunigung für den nächsten Integrationsschritt mit der Schrittweite stepSize bestimmt. ballK1 bis ballK4 sind nur temporäre Variablen.
Hier der Code :
ballK1 = ball; ballK2 = ball; ballK3 = ball; ballK4 = ball; calcAcceleration(ballK1,stepSize); ballK1->setPos (ballK1->getVel() * stepSize); ballK1->setVel (ballK1->getAcc() * stepSize); ballK2->setVel (ball->getVel() + ballK1->getVel()/2); ballK2->setPos (ball->getPos() + ballK1->getPos()/2); calcAcceleration(ballK2,stepSize); ballK2->setPos (ballK2->getVel() * stepSize); ballK2->setVel (ballK2->getAcc() * stepSize); ballK3->setVel (ball->getVel() + ballK2->getVel()/2); ballK3->setPos (ball->getPos() + ballK2->getPos()/2); calcAcceleration(ballK3,stepSize); ballK3->setPos (ballK3->getVel() * stepSize); ballK3->setVel (ballK3->getAcc() * stepSize); ballK4->setVel (ball->getVel() + ballK3->getVel()); ballK4->setPos (ball->getPos() + ballK3->getPos()); calcAcceleration(ballK4,stepSize); ballK4->setPos (ballK4->getVel() * stepSize); ballK4->setVel (ballK4->getAcc() * stepSize); ball->setVel (ball->getVel() + (ballK1->getVel() + ballK2->getVel()*2 + ballK3->getVel()*2 + ballK4->getVel())/6); ball->setPos (ball->getPos() + (ballK1->getPos() + ballK2->getPos()*2 + ballK3->getPos()*2 + ballK4->getPos())/6);
Danke schon im Voraus,
nierth
-
Allerdings hängt der Simulationsausgang immer noch zu einem großen Teil von der eingestellten Schrittweite ab, was ich komisch finde da bei mir maximal Differentialgleichungen zweiten Grades vorhanden sind.
Sollte denn Runge-Kutta deine Differentialgleichung exakt loesen? Wenn nein, dann haengt das Ergebnis immer von der Schrittweite ab. Vielleicht hilft es ja den globalen Fehler zu bestimmen ... Auch kannst du mit den Ergenissen in gaengigen Implementierungen wie in Matlab vergleichen.
-
Genau, also
Runge Kutta 4. Ordnung heisst natürlich nicht,
dass der Fehler für DGLen < 4 Ordnung verschwindet. (du kannst sowieso jede gewöhnliche DGL auf nen System 1.Ordung umschreiben)
Sondern es bedeutet, dass der Fehler in diesem Fall O(h^4) ist.
-
hmm, habe das ganze mal mit Matlab verglichen, da stimmt alles. Was mich halt wundert, dass der Fehler bei Runge-Kutta wie bei Euler ungefähr gleich stark von der Schrittweite abhängt - genau DAS passiert in Matlab nicht, da liefert Euler wie erwartet bei zu großen Schrittweiten erwartungsgemäß katastrophale Ergebnisse, bei RK hingegen stimmt alles.
Daher nochmal meine Frage an euch: seht ihr irgendeinen offensichtlichen Fehler in der Implementierung?Im übrigen: was ist mit "genau lösen" gemeint?
-
ok, ich glaube ich habe den Fehler gefunden. Es liegt am Übergang zwischen zwei verschiedenen Schrittweiten und ist unamhängig vom Lösungsverfahren der Differentialgleichungen