
Math & Physics Mathematical and physical problems of space flight and astronomy. 

Thread Tools 
05152018, 03:44 PM  #1 
Orbinaut

Yet another propagation problem (atmospheric drag mostly)
Hello! I’ve write a program for orbit propagation and choose numerical integration method rungekutta 4. I wrote only 2 perturbation effect: 2body and atmospheric drag. Here is the code of main cycle:
Code:
Satellite sat(QVector3D(7000,0,500), QVector3D(0,9,0),0.0025, 3725.0); QVector< QVector3D > satellite; double h = 1.0; QDateTime dt = QDateTime(QDate(1983,9,23),QTime(0,0,0,0)); for (int j = 0.0; j < 100; j++) { double Mjd_UTC = MJD(dt); // 32.184 – UTCTAI double Mjd_TT = Mjd_UTC + 32.184/86400.0; RK4step(h, sat, Mjd_TT); dt = dt.addDays(j); satellite.push_back(sat.loc); satellite.push_back(sat.vel); } Code:
void RK4step(const double& h, Satellite& y, const double &Mjd_TT) { QVector3D loc(y.loc); QVector3D vel(y.vel); QVector3D k1,k2,k3,k4, acceleration; // rotation matrix for satellite relative to Earth at time Mjd_TT // O.Montenbruck, E. Gill; Satellite Orbits  Models, Methods, and Applications QMatrix3x3 T = NutationMatrix(Mjd_TT) * PreccessionMatrix(MJD_J2000, Mjd_TT); k1 = partialStep(y, T, y.size, y.mass); k2 = partialStep(y + k1 * h/2, T, y.size, y.mass); k3 = partialStep(y + k2 * h/2, T, y.size, y.mass); k4 = partialStep(y + k3 * h, T, y.size, y.mass); acceleration += (k1 + (k2 + k3) * 2 + k4) / 6; y.vel += acceleration * h; y.loc += y.vel * h; } Code:
QVector3D partialStep(const Satellite &y, const QMatrix3x3 &T, const double& satSize, const double& satMass ) { QVector3D acceleration (0.0, 0.0, 0.0); double r = Magnitude(y.loc); // MU  Earth gravity = 398602 double temp = MU / (r * r * r); QVector3D acc2Body = y.loc * temp; double Cd = 2.2; QVector3D accFromAir = AccelDrag(0.0, y.loc, y.vel, T, satSize, satMass, Cd); acceleration = acc2Body + accFromAir; return acceleration; } Code:
QVector3D AccelDrag ( double Mjd_TT, const QVector3D &loc, const QVector3D &vel, const QMatrix3x3& T, double Area, double mass, double CD ) { // W3 – Earth rotation = 0.0000729211 rad/sec const QVector3D omega (0.0, 0.0, W3); double vel_abs, dens; QVector3D loc_tod, vel_tod; QVector3D vel_rel, acc_tod; QMatrix3x3 T_trp; // for converting to ICRF/EME2000 T_trp = T.transposed(); loc_tod = T * loc; vel_tod = T * vel; // velocity relative to Earth rotation vel_rel = vel_tod  QVector3D::crossProduct(omega, loc_tod); vel_abs = Magnitude2(vel_rel); // HarrisPriester atmospheric density model dens = Density_HP (Mjd_TT, loc_tod); // atmospheric acceleration acc_tod = 0.5*CD*(Area/mass)*dens*vel_abs*vel_rel; return T_trp * acc_tod; } I know that in matlab it’s dormanprince method but difference in values only +15, it’s okay for me.The problem is that with solo atmospheric drag satellite position change not quit correct, I guess. Following common sense satellite must go down sooner or later, but it fly away from Earth all the time position vector just increase. And I don’t find simple example to compare results with mine. May be I am not right and propagate with only atmospheric drag is incorrect? Or it's error in code? 
05152018, 05:31 PM  #2 
Orbiter Founder

What do you mean by incorrect? You are free to simulate whatever you like. And yes, adding drag should reduce the orbital energy and lead to a decaying orbit. If yours doesn't then there must be a bug.
Since you say your 2body propagation works, the problem is likely in your drag term. Did you try to debug if it produces reasonable results? For example, is the vector returned by AccelDrag approx. opposite your y.vel value, as expected? In the first instance, you can probably drop the second term in the calculation of your vel_rel value (i.e. nonrotating planet). It removes one potential source of error, and should still produce the expected result. Are you sure that your definition of matrix T is as intended (i.e. transforms from global to local planet system and not the other way round)? 
05152018, 10:48 PM  #3 
Orbinaut

Quote:
I see: for (int j = 0.0; j < 100; j++) { ... dt = dt.addDays(j); } but I think that you should do: for (int j = 0; j < 100; j++) { ... dt = dt.addDays(t_step); } where t_step is a small constant time step. 
05162018, 03:47 PM  #4 
Orbinaut

martins, i understand that i can simulate whatever i want, but under incorrect i mean that result will be not "good" for understanding theme. I am programmer not physicist, i need to understand how propagation work on simple example. With 2Body was simple but other perturbation effects are hard to calculate. I want understand them 1by1.
Vector returned by AccelDrag is opposite to my y.vel value, but power is E20 or E17. Values are too low and with my example where velocity is (0, 9, 0) after 2500 iteration it will be (1E14, 7.996... , 2E13). Functions for calculation matrix T i get from this book "O.Montenbruck, E. Gill; Satellite Orbits  Models, Methods, and Applications". May be they are not what i needed. In different sources all this coordinates systems call by different names, it's confusing for me. I even found atmospheric models (US standart and Russian GOST) which doesn't depend on time. And still same results! cristiapi, i try all variants even crazy ones to change years, but again values which i get too low. 
05182018, 02:30 PM  #5 
Orbinaut

martins, vector returned by AccelDrag is opposite to mine y.vel value but values are too small from E20 to E17. And their influence is small too. about matrix T i am not sure, but i take it from book "O.Montenbruck, E. Gill; Satellite Orbits  Models, Methods, and Applications", may be i miss something.
cristiapi, there is nothing change when i take another step, i even try years and get same results. 
05242018, 10:25 PM  #6 
Orbinaut

Quote:
If you use a low order integrator (like RK4) the step must be very small for a LEO satellite. 
05252018, 11:40 AM  #7 
Orbiter Founder

Quote:
Also, this seems to be at odds with your previous statement that your propagator works ok for the frictionless 2body case, and only has problems when including the atmospheric drag term. If the drag deceleration is in the correct direction, and negligibly small anyway, I don't see how it can lead to an increase in orbital energy. 
05252018, 12:18 PM  #8 
Orbinaut

Quote:

05292018, 05:15 PM  #9 
Orbinaut

martins, as I said don't have éxample to compare. But I try another propagator like this: https://www.mathworks.com/matlabcent...bitpropagator . I disable all perturbation effects except atmospheric drag, and I get same result as mine. So I came to conclusion that atmospheric drag hasn’t much affection on orbit alone.
cristiapi, i try them too. Also i try low orbit like 100 km, and with propagator I mention, and with mine  orbit rize. So i guess this thread can be closed, if someone have better explanation then me. And i realy will be glad to hear that i am not right and why. Anyway thanks martins and cristiapi. 
05292018, 07:59 PM  #10 
Orbinaut

Quote:
which shows the perigee, apogee and the mean radius vector (it includes the atmospheric drag). You should disable all the perturbations and transformations in your program to see if the basic integrator works as expected. Last edited by cristiapi; 05292018 at 08:01 PM. 
05302018, 03:19 PM  #11 
Orbinaut

Do you mean to check if my RK works? But why another propagator show same results? its rather confusing. Simpler integrator  euler method?

05302018, 08:24 PM  #12 
Orbinaut

Quote:
Did you check that your RK4 integrator works? EDIT: in other words write: QVector3D partialStep(const Satellite &y, const QMatrix3x3 &T, const double& satSize, const double& satMass ) { double r = Magnitude(y.loc); // MU  Earth gravity = 398602 double temp = MU / (r * r * r); return y.loc * temp; } Quote:
Quote:
Please, post the source code for the smallest step size you tried to use: for (int j = 0; j < 100; j++) { ... dt = ... } Last edited by cristiapi; 05312018 at 07:25 AM. 
05312018, 06:18 AM  #13 
Orbinaut

Quote:
Only if these things come out correct and you know the error rate, proceed to more complicated things. I will add a sideremark on the RK  when I tried different solver schemes a while ago, I had the impression RK is chiefly superior if you have (stiff) dissipative terms in the equation (like the equations for a parachute). In orbit, it didn't gain me measurably in terms of accuracy over a straightforward scheme, but it ran slower  so when making the timestep of the straightforward scheme smaller such that it ran as fast as RK, it actually had the higher accuracy. Sometimes brute force wins out... 
06012018, 03:44 PM  #14 
Orbinaut

Code:
QVector3D partialStep(const Satellite &y, const QMatrix3x3 &T, const double& satSize, const double& satMass, const double &Mjd_TT ) { double r = Magnitude2(y.loc); // MU  Earth gravity = 398602 double temp = MU / (r * r * r); QVector3D acceleration = y.loc * temp; return acceleration; } void RK4step(const double& h, Satellite& y, const double &Mjd_TT, const QMatrix3x3 &T) { QVector3D loc(y.loc); QVector3D vel(y.vel); QVector3D k1,k2,k3,k4, acceleration; k1 = partialStep(y, T, y.size, y.mass, Mjd_TT); k2 = partialStep(y + k1 * h/2, T, y.size, y.mass, Mjd_TT); k3 = partialStep(y + k2 * h/2, T, y.size, y.mass, Mjd_TT); k4 = partialStep(y + k3 * h, T, y.size, y.mass, Mjd_TT); acceleration += (k1 + (k2 + k3) * 2 + k4) / 6; y.vel += acceleration * h; y.loc += y.vel * h; } Void main(){ Satellite sat(QVector3D(7000.0, 0.0, 500.0), QVector3D(0.0, 9.0, 0.0), 62.5, 8000.0); QVector< QVector3D > satellite; double t = 0; double Mjd_UTC; double Mjd_TT; QVector <double> height; double h = 1; QDateTime dt = QDateTime(QDate(2002,4,24),QTime(0,0,0,0)); for (int j = 0.0; j < 100; j++, t+=60.0 ) { Mjd_UTC = MJD(dt); Mjd_TT = Mjd_UTC + (32.0 + 32.184)/86400.0; QMatrix3x3 T = NutationMatrix(Mjd_TT) * PreccessionMatrix(MJD_J2000, Mjd_TT); RK4step(h, sat, Mjd_TT, T); dt = dt.addSecs(t); height.push_back(Magnitude2(sat.loc)R3); satellite.push_back(sat.loc); satellite.push_back(sat.vel); } } With h = 0.1 height decrease from 639.6954180199783 to 638.8549766625807. 
06012018, 09:53 PM  #15 
Orbinaut

Does that code work? I read
k2 = partialStep(y + k1 * h/2, ... what does y + k1 * h/2 mean? y is a Satellite structure or class; are you adding a vector to a class? Also, is not clear to me the use of RK4step(h, sat, Mjd_TT, T); (which is good) and dt = dt.addSecs(t); it should be dt = dt.addSecs(h) (even if it seems that you don't use dt). The function RK4step() is wrong. You should update a system of 2 differential equations, while you do a mix of RK4 with an Euler step. Here's my tested code for RK4: Code:
void acc(VECTOR3 *y, VECTOR3 *f) { f[0] = y[1]; const double p= 1 / Vabs(y[0]); f[1]= y[0] * mu * p*p*p; } VECTOR3 k1[2], k2[2], k3[2], k4[2], yy[2]; acc(y , k1); for(int i= 0; i < 2; i++) yy[i]= y[i] + stp * .5 * k1[i]; acc(yy, k2); for(int i= 0; i < 2; i++) yy[i]= y[i] + stp * .5 * k2[i]; acc(yy, k3); for(int i= 0; i < 2; i++) yy[i]= y[i] + stp * k3[i]; acc(yy, k4); for(int i= 0; i < 2; i++) y[i] += stp/6 * (k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]); 

Tags 
atmospheric drag, c++, propagation 
Thread Tools  


Quick Links  Need Help? 