Skip to main content
gamedev.net
🔒 Locked

Gravity

Started by rever Dec 15, 2005 at 6:12 PM 10 replies 2.2k views
Original Post
rever
rever
Hello, i was doing gravity simulation, and this is bascicly simulation of solar system, and the red object is the sun and the green one is the Haleys comet...problem is that the comet doesn;t follow it;s path and flies of when it gets close to the sun....does anyone know what is wrong with my gravity related calculations i am 90 % sure my mass and speed data is correct. MAIN: /* Changes in the program: Version 1: Creating the window done. Ploting a point on given (x,y) coordinats done. Animating a point to move by Vx*Dt Version 2: Added acceleration support. Forces have been added in order to find out the acceleration Class structure implemented. Point is not discribed using a structure. Version 3: Expension to animate in 2 dimension under the influence of 2 forces, in x, and y directions. Support for an array of points added. Gravitation forces are used to calculate the movemnet of the program An example system of 2 objects is models to show for both x and y forces. Version 4: Modeled earth-sun system. */ //Needed to create the windwo. #include #include #include #include #include #include //Class responsible for all physical calculataions, as well as drawing the point. #include "draw.h" using namespace std; //Limit the lines static const WORD MAX_CONSOLE_LINES = 1000; //This will redirected the output to a console. void RedirectIOToConsole(); //Window proc that will handle the paint and the quit messages. LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); //Timer procedure is used to make sure that the drawing is done a given number of times a second //The time for each redraw is constant here. There are 33.3 frames per second drawn void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime); //Global object defintion of the method to do the drawing. CDraw o_draw; //Main program function, we start here int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow){ //Declare a window class information structure. used to register the windows WNDCLASSEX wcWndCls; //message structure, used to in relaying the messages sent to the window MSG mMsg; //Initializing the window class structure. wcWndCls.cbSize = sizeof(wcWndCls); wcWndCls.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; wcWndCls.lpfnWndProc = WndProc; wcWndCls.cbClsExtra = 0; wcWndCls.cbWndExtra = 0; wcWndCls.hInstance = hInstance; wcWndCls.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcWndCls.hCursor = LoadCursor(NULL, IDC_ARROW); wcWndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wcWndCls.lpszMenuName = NULL; wcWndCls.lpszClassName = schAppName; wcWndCls.hIconSm = LoadIcon(hInstance, IDI_APPLICATION); //We register the window for use in subsequent class with createWindowEx RegisterClassEx(&wcWndCls); //Create the actual window.Name is declared in CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,schAppName,schAppName,WS_OVERLAPPEDWINDOW | WS_VISIBLE,CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL); //Create the timer to draw the window 33 times a second. SetTimer(NULL,0,0,(TIMERPROC)TimerProc); RedirectIOToConsole(); system("pause"); //Message loop while(GetMessage(&mMsg, NULL, 0, 0)){ TranslateMessage(&mMsg); DispatchMessage( &mMsg); } //Ending the program return static_cast(mMsg.wParam); } //Here we will process the messages sent LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg,WPARAM wParam, LPARAM lParam){ switch(Msg){ //Draw the window now case WM_PAINT: o_draw.Draw(); break; //time to shut down case WM_DESTROY: PostQuitMessage(WM_QUIT); break; //pass the rest of the messages to the default procedure. default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; } //This function is a callback functions, and it will be called evry 30 milliseconds. //At that time it will make sure that the window is redrawn void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime){ //Update the windwo //Do NOT erase the background. //Set last parameter to true to do jsut that. InvalidateRect(FindWindow(0,schAppName),NULL,false); } //We redirect all the output to console we can debug the program normally. void RedirectIOToConsole(){ int hConHandle; long lStdHandle; CONSOLE_SCREEN_BUFFER_INFO coninfo; FILE *fp; AllocConsole(); GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo); coninfo.dwSize.Y = MAX_CONSOLE_LINES; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize); lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); fp = _fdopen( hConHandle, "w" ); *stdout = *fp; setvbuf( stdout, NULL, _IONBF, 0 ); lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); fp = _fdopen( hConHandle, "r" ); *stdin = *fp; setvbuf( stdin, NULL, _IONBF, 0 ); lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); fp = _fdopen( hConHandle, "w" ); *stderr = *fp; setvbuf( stderr, NULL, _IONBF, 0 ); ios::sync_with_stdio(); } DRAW.H #ifndef DRAW_H_ #define DRAW_H_ //Regular header for all the windows stuff #include #include #include #include #include #include //to get rid of the std:: b4 the cout's. using namespace std; //Name of the application, inconsequential, used just for the class name of the window and the titel. static char schAppName[] = "Solar System Simulataion"; //Conversion to DIB color. #define COLOR(r, g ,b) ((DWORD) (((BYTE) (r) | ((WORD) (g) << 8)) |(((DWORD) (BYTE) (b)) << 16))) //structure that will be responsible for a single point. typedef struct gPOINT { double dPosX; double dPosY; double dVeloX; double dVeloY; double dMass; double dForceX; double dForceY; double dAccelX; double dAccelY; }; //Class to draw the point. class CDraw{ private: //array of 10 points(Solar System will be stored here) //For now only a few of them are used to make gPOINT point[11]; //Device context. Used to set pixesls HDC hDC; //Paint structure, used in Being/EndPaint functions. PAINTSTRUCT Ps; private: double Time(long double dTimeMs); double Velocity(double dLastVelocity,double dAcceleration,double DTime); double Acceleration(double dForce,double dMass); double ForceX(gPOINT point,gPOINT point2); double ForceY(gPOINT point,gPOINT point2); double Gravity(gPOINT point,gPOINT point2); double Pytheg(gPOINT point,gPOINT point2); int PositionX(double x); int PositionY(double y); void Point(gPOINT point,DWORD dwColor); public: CDraw(); ~CDraw(); void Draw(); }; #endif DRAW.CPP #include "draw.h" #include "math.h" //Scaling of the distance const double DistanceFactor=5.25e10; //Scaling of the time const double TimeFactor=1000000; bool first=true; double iTime=0; //Initialize 2 points givng them some values. CDraw::CDraw(){ ZeroMemory(point,sizeof(gPOINT)*11); //Set Sun's mass point[0].dMass=1.99e30; //Set comet's position in relation to earth. point[1].dPosX=5.25e12; //point[1].dPosX=2.67e12; point[1].dPosY=0; //Set the initial velocity for the comet. point[1].dVeloY=-896; point[1].dVeloX=0; //Set the mass of the conet. point[1].dMass=5.2e11; } //Deinitialize the points, giving them 0's CDraw::~CDraw(){ ZeroMemory(point,sizeof(gPOINT)*11); } //Do the drawing. //Time scal;ing is not done corrrectly, this is just a test void CDraw::Draw(){ hDC = BeginPaint(FindWindow(0,schAppName), &Ps); if(first)Point(point[1],COLOR(0,0,255)); point[1].dForceX=ForceX(point[1],point[0]); point[1].dForceY=ForceY(point[1],point[0]); cout<<"Force on the moon in x:"<=364){ cout<<"Time passed(d):"<<iTime/86400<<" "<<point[1].dPosX<<endl; Point(point[1],COLOR(0,0,255)); }*/ system("pause"); EndPaint(FindWindow(0,schAppName), &Ps ); } //Do the time scaling using Time factor double CDraw::Time(long double dTimeMs){ return (dTimeMs*TimeFactor); } //calculate the new velocity. newVelocity=oldVelocioty +AccelerationTime double CDraw::Velocity(double dLastVelocity,double dAcceleration,double dTime){ if(first){ first=false; return dLastVelocity+dAcceleration*0.5*dTime; } return dLastVelocity+dAcceleration*dTime; } //Do acceleration from f=ma double CDraw::Acceleration(double dForce,double dMass){ double a=dForce/dMass; return a; } //Calculate force in the X direction //Fx=forceGravity*changeinX/radius double CDraw::ForceX(gPOINT point,gPOINT point2){ double dForce=(Gravity(point,point2)*(-point.dPosX)/Pytheg(point,point2)); return dForce; } //Calculate force in the X direction //Fy=forceGravity*changeiny/radius double CDraw::ForceY(gPOINT point,gPOINT point2){ double dForce=(Gravity(point,point2)*(-point.dPosY)/Pytheg(point,point2)); return dForce; } //Gravity, Fg=Gmm/r^2 double CDraw::Gravity(gPOINT point,gPOINT point2){ return ((6.67e-11*point.dMass*point2.dMass)/pow(Pytheg(point,point2),2)); } //r^2=a^2+b^2 //r=sqrt(a^2+b^2) double CDraw::Pytheg(gPOINT point,gPOINT point2){ return sqrt(pow(point2.dPosX-point.dPosX,2)+pow(point2.dPosY-point.dPosY,2)); } //Convert to screen cords int CDraw::PositionX(double x){ double ret=((x/DistanceFactor)+320); // cout<<"x: "<<x<<"ret: "<<ret<<endl; return ret; } //Convert to screen coords int CDraw::PositionY(double y){ return ((y/DistanceFactor)+240); } //Do a 5 pixel method for a point. void CDraw::Point(gPOINT point,DWORD dwColor){ SetPixel(hDC,PositionX(point.dPosX), PositionY(point.dPosY),dwColor); SetPixel(hDC,PositionX(point.dPosX), PositionY(point.dPosY)-1,dwColor); SetPixel(hDC,PositionX(point.dPosX), PositionY(point.dPosY)+1,dwColor); SetPixel(hDC,PositionX(point.dPosX)+1,PositionY(point.dPosY),dwColor); SetPixel(hDC,PositionX(point.dPosX)-1,PositionY(point.dPosY),dwColor); } Thx
Zakwayda
Zakwayda
Whoa.

Here are a couple of suggestions that will greatly increase your chances of getting help. First, strip out all of the code except that which is directly relevant to the problem you're asking about. Second, put it in [ source ][ /source ] tags so that the formatting is preserved.
JohnBolton
JohnBolton
From what I can tell, you are using Euler integration and that generally sucks. On the other hand, it could just be a bug that is causing the problem. It's hard to tell.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
rever
rever
well, i like Eulers method, and the bug that u are talking about is kind of hard to find, so if anyone got a better idea of it, coudl they give me some ideas where to find it. AS for the source tags, sry about that, i could find a key that woudl do it for me and i didn;t know the command, here is slightly modified version:
draw.h#ifndef DRAW_H_#define DRAW_H_//Regular header for all the windows stuff#include <windows.h>#include <stdio.h>#include <fcntl.h>#include <io.h>#include <iostream>#include <fstream>//to get rid of the std:: b4 the cout's. using namespace std;//Name of the application, inconsequential, used just for the class name of the window and the titel.static char schAppName[] = "Solar System Simulataion";//Conversion to DIB color.#define COLOR(r, g ,b)  ((DWORD) (((BYTE) (r) | ((WORD) (g) << 8)) |(((DWORD) (BYTE) (b)) << 16)))//structure that will be responsible for a single point.typedef struct gPOINT {           double       dPosX;           double       dPosY;              double       dVeloX;           double       dVeloY;           double       dMass;           double       dForceX;           double       dForceY;           double       dAccelX;            double       dAccelY;     };//Class to draw the point. class CDraw{      private:              //array of 10 points(Solar System will be stored here)              //For now only a few of them are used to make               gPOINT       point[11];              //Device context. Used to set pixesls              HDC          hDC;              //Paint structure, used in Being/EndPaint functions.              PAINTSTRUCT  Ps;      private:              double Time(long double dTimeMs);              double Velocity(double dLastVelocity,double dAcceleration,double DTime);              double Acceleration(double dForce,double dMass);              double ForceX(gPOINT point,gPOINT point2);              double ForceY(gPOINT point,gPOINT point2);              double Gravity(gPOINT point,gPOINT point2);              double Pytheg(gPOINT point,gPOINT point2);              int PositionX(double x);              int PositionY(double y);              void   Point(gPOINT point,DWORD dwColor);      public:              CDraw();              ~CDraw();              void Draw();};#endif

draw.cpp#include "draw.h"#include "math.h"//Scaling of the distanceconst double DistanceFactor=5.25e10; //Scaling of the timeconst double TimeFactor=1000000;bool first=true;double iTime=0;//Initialize 2 points givng them some values.CDraw::CDraw(){     ZeroMemory(point,sizeof(gPOINT)*11);     //Set Sun's mass     point[0].dMass=1.99e30;     //Set comet's position in relation to earth.     point[1].dPosX=5.25e12;     //point[1].dPosX=2.67e12;     point[1].dPosY=0;     //Set the initial velocity for the comet.     point[1].dVeloY=-896;     point[1].dVeloX=0;     //Set the mass of the conet.      point[1].dMass=5.2e11;}//Deinitialize the points, giving them 0'sCDraw::~CDraw(){     ZeroMemory(point,sizeof(gPOINT)*11);}//Do the drawing.//Time scal;ing is not done corrrectly, this is just a testvoid CDraw::Draw(){     hDC = BeginPaint(FindWindow(0,schAppName), &Ps);                    if(first)Point(point[1],COLOR(0,0,255));                  point[1].dForceX=ForceX(point[1],point[0]);                  point[1].dForceY=ForceY(point[1],point[0]);                  cout<<"Force on the moon in x:"<<point[1].dForceX<<endl;                  cout<<"Force on the moon in y:"<<point[1].dForceY<<endl;                  point[1].dVeloX =Velocity(point[1].dVeloX,Acceleration(point[1].dForceX,point[1].dMass),Time(10));                  cout<<"Veolocity in the x direction:"<<point[1].dVeloX<<endl;                  //Position calculations in X                  point[1].dPosX=point[1].dPosX+point[1].dVeloX*Time(10);                   cout<<"Position in the x direction:"<<point[1].dPosX<<endl;                  //Velocity update in Y                  point[1].dVeloY=Velocity(point[1].dVeloY,Acceleration(point[1].dForceY,point[1].dMass),Time(10));                      cout<<"Veolocity in the y direction:"<<point[1].dVeloY<<endl;                  //Position calculations in Y                  point[1].dPosY+=point[1].dVeloY*Time(10);                       cout<<"Position in the y direction:"<<point[1].dPosY<<endl;                        Point(point[1],COLOR(0,255,0));                     Point(point[0],COLOR(255,0,0));                       iTime+=10*TimeFactor;                  cout<<"Acce:"<<sqrt(pow(Acceleration(point[1].dForceX,point[1].dMass),2)+pow(Acceleration(point[1].dForceY,point[1].dMass),2));                  //system("pause");                  cout<<"Time passed(d):"<<iTime/86400<<"Distance:"<<Pytheg(point[1],point[0])<<endl;                  cout<<"Total Energy:"<<0.5*point[1].dMass*pow(sqrt(pow(point[1].dVeloX,2)+pow(point[1].dVeloY,2)),2)-(6.67e-11*1.99e30*5.2e11)/Pytheg(point[1],point[0])<<endl;                  /*if(iTime/86400>=364){                      cout<<"Time passed(d):"<<iTime/86400<<"  "<<point[1].dPosX<<endl;                      Point(point[1],COLOR(0,0,255));                                    }*/                   system("pause");               EndPaint(FindWindow(0,schAppName), &Ps );}//Do the time scaling using Time factordouble CDraw::Time(long double dTimeMs){       return (dTimeMs*TimeFactor);}//calculate the new velocity. newVelocity=oldVelocioty +AccelerationTimedouble CDraw::Velocity(double dLastVelocity,double dAcceleration,double dTime){       if(first){                 first=false;                 return dLastVelocity+dAcceleration*0.5*dTime;       }       return dLastVelocity+dAcceleration*dTime;}//Do acceleration from f=madouble CDraw::Acceleration(double dForce,double dMass){       double a=dForce/dMass;       return a;}//Calculate force in the X direction//Fx=forceGravity*changeinX/radiusdouble CDraw::ForceX(gPOINT point,gPOINT point2){       double dForce=(Gravity(point,point2)*(-point.dPosX)/Pytheg(point,point2));       return dForce;} //Calculate force in the X direction//Fy=forceGravity*changeiny/radiusdouble CDraw::ForceY(gPOINT point,gPOINT point2){       double dForce=(Gravity(point,point2)*(-point.dPosY)/Pytheg(point,point2));       return dForce;}//Gravity, Fg=Gmm/r^2double CDraw::Gravity(gPOINT point,gPOINT point2){       return ((6.67e-11*point.dMass*point2.dMass)/pow(Pytheg(point,point2),2));}//r^2=a^2+b^2//r=sqrt(a^2+b^2)double CDraw::Pytheg(gPOINT point,gPOINT point2){       return sqrt(pow(point2.dPosX-point.dPosX,2)+pow(point2.dPosY-point.dPosY,2));}//Convert to screen cordsint CDraw::PositionX(double x){       double ret=((x/DistanceFactor)+320);      // cout<<"x: "<<x<<"ret: "<<ret<<endl;       return ret;}//Convert to screen coordsint CDraw::PositionY(double y){       return ((y/DistanceFactor)+240);       }//Do a 5 pixel method for a point.void  CDraw::Point(gPOINT point,DWORD dwColor){      SetPixel(hDC,PositionX(point.dPosX), PositionY(point.dPosY),dwColor);        SetPixel(hDC,PositionX(point.dPosX), PositionY(point.dPosY)-1,dwColor);       SetPixel(hDC,PositionX(point.dPosX), PositionY(point.dPosY)+1,dwColor);       SetPixel(hDC,PositionX(point.dPosX)+1,PositionY(point.dPosY),dwColor);           SetPixel(hDC,PositionX(point.dPosX)-1,PositionY(point.dPosY),dwColor);}
Zipster
Zipster
Where is your simulation actually performed? For best results you want a fixed timestep, however the word 'best' is loosely applied as Euler integration is probably the least accurate method and has a tendency to fly off the handle if you're not careful. Usually, this means you can destabilize the system by applying too much force at once. This would explain why the comet goes nuts when it's close to the sun, because of the intense gravitational force.

Just to make sure the integration itself it correct, per-step Euler integration should look like this:
// Calculate accelerationVector3D acceleration = (gravitationalPullFromSun + otherForces) / mass;// Calculate dV (change in velocity) and dX (change in position)Vector3D dV = acceleration * deltaTime;Vector3D dX = velocity * deltaTime;// Update velocity and positionvelocity += dV;position += dX;
someusername
someusername
I totally agree with Zipster. The fixed timestep is very important if you want accuracy. You may want to consider starting a new thread to run asynchronous physics simulations independently of your main loop. This will assure that whenever you will need to draw your objects, the correct number of simulations will already have been performed for the given time. People also avoid to use Euler integration for accuracy issues. Maybe you want to consider an alternative method. the Runge-Kutta methods seems to be quite popular...

And a question.
Quote:

//Initialize 2 points givng them some values.
CDraw::CDraw(){
ZeroMemory(point,sizeof(gPOINT)*11);
//Set Sun's mass
point[0].dMass=1.99e30;
//Set comet's position in relation to earth.
point[1].dPosX=5.25e12;
//point[1].dPosX=2.67e12;
point[1].dPosY=0;
//Set the initial velocity for the comet.
point[1].dVeloY=-896;
point[1].dVeloX=0;
//Set the mass of the conet.
point[1].dMass=5.2e11;
}


How did you find the initial velocity and position for your objects in the simulation? If you want to model the comet's orbit as accurately as possible, the first thing you have to be sure about, is that the initial velocity and position (for the given time instant) are as accurate as possible.
The physics simulation merely tries to approximate a value of an unknown function (the actual position with respect to time) from its second and first derivative. (acceleration and velocity)
However, when you integrate numerically, you need initial values for the unknown derivatives and the function, to begin with. The fact that you start integrating with the second derivative, means that you should provide two initial conditions, one for the first derivative and one for the actual function. (velocity and position) E.g. you can't find a line from its direction only. There are infinite lines with that direction. You'll have to know one point through which it passes.
If your selection of initial conditions is arbitrary or erroneous in any way, the only thing you can be sure of, is that you won't get the orbit you were expecting.
rever
rever
thx for the reaplies, but i don;t get the stuff about time....i am using a time step of 10 seconds with a time factor of 100000 which basicly speed up the simulations,i am not running from the system clock to do this.
Also the initial position and velocity i am 90 % sure are corrrect.
can you elaborate on the time stuff? and also, i will get rid of Eulers method as soon as i get it working correctly:D
btw, is there an example source of something that does graivty calcualtions aka, somethign like solar system, or just somethign that shows gravity between 2 object over time ....somethign like i have but that works so i can go from there.
grhodes_at_work
grhodes_at_work
Rever,

When doing numerical simulation, to get good reliable results, you really should consider learning what the time stepping is all about, and why you cannot get good results by simply picking whatever time step you want. It seems you're willing to learn, and that is admirable!

There a few resources you can start with. The info might not seem immediately relevant, but it is.

David Baraff and Michael Kaff articles on physics

The first two articles you should start with are "Differential Equation Basics" and "Energy Functions and Stiffness."
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
rever
rever
thx alot man,i will read over that stuff tonight and then post here tomorrow again to either complete the topic or try to get more info on it.
my question is....if i slow down the simulation time, will that allow for time steping to be improved?
say from liek 10000000 to something like 1000, becuase it is more precise that way , it will take more time but it should still work better rite?

well i am off to read the articles.
Thx

[EDIT]
Scratch my last question.....i just sloed down the program and now it works!!!!!!!!! Holy Fuck guys!!!!! Thx Alot.
i would have never figured somethign like that woudl ahve such a drastic effect on the program.

Well i am of to read this stuff.....this stuff is extremely interesting!
Thx again, and if anyone got any resource related to physics on the net(like the ones above) could u post some links here?
I got a Resnick and Hallday (not sure about the names) physics textbook, it is great, but i want to get some more diffrent topic like above as well.
rever
rever
Thx alot for the link. I read the first few articles and the stuff explains alot of problems that i had with Eulers method. With the decreased time intervals the simulations became actually realistic and no longer do i get the spin-off effect or the effect where Euler's method breaks down and object fly of in random direction:D.

A/w i was trying to implement the Runge Kutta method for the system, and i started with the force calculations. But i am not sure what the 4 step method for Runge Kutta actually does.
[Question 1]
Could somebody please give me some ideas on how to apply it to the gravity/orbiting situation i have?Or maybe a simpler motion situation, a quadratic or something like that so i can understand how it works?
Because i understand the idea of the four step method but i can;t grasp on how to apply it.
[Question 2]
Is there a way to do error calculations for Euler's method?
I looked on google and found this:
http://math.fullerton.edu/mathews/n2003/Euler'sMethodMod.html
I am having a little trouble understanding how a forumla like that can be applicable to a situation such as mine. Both of these question are related since they have similar forme and i don;t understand the application of the equation f(x0,t0). How can that be applied to my situtation? I can see how u can do it but what is the Ck term in the formula?

Rite now i am thinking that if i combine all the equations in my program into a single function that is passed parameters of the lsat position and time, then that is what the f(x0,t0) is talking about. The whole step in Eulers method/ Runge Kutta method is used in both methods, and not parts of each step like force in x direction force in y etc.
Am i rite or no?
Thx alot in advance.

[Edited by - rever on December 17, 2005 12:13:58 PM]
someusername
someusername
Quote:

[Question 2]
Is there a way to do error calculations for Euler's method?

It is only possible to find bounds for the error, if you also have a symbolic expression for the function you are integrating. like f(x)=2x+1.
E.g. if you were sampling cos(x) at sample points with distance == 2pi, you would always read the same value. It would be impossible to approximate its integral (sin(x)) by adding "constant*dt". If you don't know it was sin(x) in the first place, you can't make any assumptions about the error whatsoever.

The whole concept behind numeric integration is that you can find the next value of a function at a sample point, by taking its value at the previous point and "moving" an infitesimal distance away to the direction of its tangent there.

It's trivial to prove that when the slope of the functions tangent increases, the tangent is under the graph, and vice-versa. This depicts how, -when moving along the tangent at x(i-1)- the farther away you move from x(i), the farther away you end up from the actual value F(i), thus introducing errors to the integral.
This error is directly proportional to a specific quantity, which is the ability of the slope of the tangent of the function's graph to change, quickly enough for your finite sampling to pick up. This quantity is the first derivative of the integrand, and the second derivative of the integral.

When your comet gets too close to the sun, it's not the fact the its acceleration becomes too high, that causes the problem with euler integration. It's that it changes too fast for your finite sampling to keep track of.
There is no way to predict the error because you cannot know how it has behaved until you read the integrand's value again.

Something similar also holds for music in common audio CDs. One of the reasons that the sampling rate is 44KHz, is that the highest frequency that can be reproduced at that rate is 22KHz, which is enough, since it's very close to maximum audible frequency for the human ear.
The problem with your simulation is that it tries to reproduce values changing so fast, without having the capacity to do so, because of the poor sampling frequency. If your simulation runs at 100Hz, then the data you can recreate will consist of frequencies at most 50Hz, or .5 cycles/time step. This means that if an object's acceleration could switch values from a local minimum to a local maximum, faster than (time step)/2, [which in fact gets down to the absolute value of its derivative becoming higher than 2*abs(local_max - local_min)/time_step) ] then you would be leaving a very considerable quantity out of the final integral, thus accumulating significant error per time step.

edit:
I just read my post again, and found a mistake I made.
Quote:

This error is directly proportional to a specific quantity, which is the ability of the slope of the tangent of the function's graph to change, quickly enough for your finite sampling to pick up. This quantity is the first derivative of the integrand, and the second derivative of the integral.

It's not the first derivative of the integrand, it's how fast it changes, thus the second derivative.

Quote:

This means that if an object's acceleration could switch values from a local minimum to a local maximum, faster than (time step)/2, [which in fact gets down to [...]

It's obviously not the actual values that cause the problem, it's the fact that its first derivative can have two consecutive roots very close to each other, which gets down to the second derivative switching from a local maximum to a root and then to a local minimum (or the opposite) very fast for the simulation to pick up.

Anyway... I just thought I'd fix these, before I was spending someone's time for nothing

[Edited by - someusername on December 19, 2005 4:24:06 AM]
rever
rever
thx alot for that, i think i get it know ani am already trying to transform my program to use the Katta method.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.