JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++

FGMSIS.h

00001 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00002  
00003  Header:       FGMSIS.h
00004  Description:  MSIS-00 Atmosphere
00005  Author:       David Culp
00006  Date started: 12/14/03
00007  
00008  ------------- Copyright (C) 2003  David P. Culp (davidculp2@comcast.net) ------
00009  
00010  This program is free software; you can redistribute it and/or modify it under
00011  the terms of the GNU Lesser General Public License as published by the Free Software
00012  Foundation; either version 2 of the License, or (at your option) any later
00013  version.
00014  
00015  This program is distributed in the hope that it will be useful, but WITHOUT
00016  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00018  details.
00019  
00020  You should have received a copy of the GNU Lesser General Public License along with
00021  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00022  Place - Suite 330, Boston, MA  02111-1307, USA.
00023  
00024  Further information about the GNU Lesser General Public License can also be found on
00025  the world wide web at http://www.gnu.org.
00026  
00027 HISTORY
00028 --------------------------------------------------------------------------------
00029 12/14/03   DPC   Created
00030 01/11/04   DPC   Derive from FGAtmosphere
00031  
00032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00033 SENTRY
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00035 
00036 #ifndef FGMSIS_H
00037 #define FGMSIS_H
00038 
00039 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00040 INCLUDES
00041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00042 
00043 #include "models/FGAtmosphere.h"
00044 #include "FGFDMExec.h"
00045 
00046 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00047 DEFINITIONS
00048 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00049 
00050 #define ID_MSIS "$Id: FGMSIS.h,v 1.9 2011/05/20 03:18:36 jberndt Exp $"
00051 
00052 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00053 FORWARD DECLARATIONS
00054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00055 
00056 namespace JSBSim {
00057 
00058 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00059 CLASS DOCUMENTATION
00060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00061 
00081 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00082 STRUCT DECLARATIONS
00083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00084 
00085 struct nrlmsise_flags {
00086   int switches[24];
00087   double sw[24];
00088   double swc[24];
00089 };
00090 /*   
00091  *   Switches: to turn on and off particular variations use these switches.
00092  *   0 is off, 1 is on, and 2 is main effects off but cross terms on.
00093  *
00094  *   Standard values are 0 for switch 0 and 1 for switches 1 to 23. The 
00095  *   array "switches" needs to be set accordingly by the calling program. 
00096  *   The arrays sw and swc are set internally.
00097  *
00098  *   switches[i]:
00099  *    i - explanation
00100  *   -----------------
00101  *    0 - output in centimeters instead of meters
00102  *    1 - F10.7 effect on mean
00103  *    2 - time independent
00104  *    3 - symmetrical annual
00105  *    4 - symmetrical semiannual
00106  *    5 - asymmetrical annual
00107  *    6 - asymmetrical semiannual
00108  *    7 - diurnal
00109  *    8 - semidiurnal
00110  *    9 - daily ap [when this is set to -1 (!) the pointer
00111  *                  ap_a in struct nrlmsise_input must
00112  *                  point to a struct ap_array]
00113  *   10 - all UT/long effects
00114  *   11 - longitudinal
00115  *   12 - UT and mixed UT/long
00116  *   13 - mixed AP/UT/LONG
00117  *   14 - terdiurnal
00118  *   15 - departures from diffusive equilibrium
00119  *   16 - all TINF var
00120  *   17 - all TLB var
00121  *   18 - all TN1 var
00122  *   19 - all S var
00123  *   20 - all TN2 var
00124  *   21 - all NLB var
00125  *   22 - all TN3 var
00126  *   23 - turbo scale height var
00127  */
00128 
00129 struct ap_array {
00130   double a[7];   
00131 };
00132 /* Array containing the following magnetic values:
00133  *   0 : daily AP
00134  *   1 : 3 hr AP index for current time
00135  *   2 : 3 hr AP index for 3 hrs before current time
00136  *   3 : 3 hr AP index for 6 hrs before current time
00137  *   4 : 3 hr AP index for 9 hrs before current time
00138  *   5 : Average of eight 3 hr AP indicies from 12 to 33 hrs 
00139  *           prior to current time
00140  *   6 : Average of eight 3 hr AP indicies from 36 to 57 hrs 
00141  *           prior to current time 
00142  */
00143 
00144 
00145 struct nrlmsise_input {
00146   int year;      /* year, currently ignored                           */
00147   int doy;       /* day of year                                       */
00148   double sec;    /* seconds in day (UT)                               */
00149   double alt;    /* altitude in kilometers                            */
00150   double g_lat;  /* geodetic latitude                                 */
00151   double g_long; /* geodetic longitude                                */
00152   double lst;    /* local apparent solar time (hours), see note below */
00153   double f107A;  /* 81 day average of F10.7 flux (centered on DOY)    */
00154   double f107;   /* daily F10.7 flux for previous day                 */
00155   double ap;     /* magnetic index(daily)                             */
00156   struct ap_array *ap_a; /* see above */
00157 };
00158 /*
00159  *   NOTES ON INPUT VARIABLES: 
00160  *      UT, Local Time, and Longitude are used independently in the
00161  *      model and are not of equal importance for every situation.  
00162  *      For the most physically realistic calculation these three
00163  *      variables should be consistent (lst=sec/3600 + g_long/15).
00164  *      The Equation of Time departures from the above formula
00165  *      for apparent local time can be included if available but
00166  *      are of minor importance.
00167  *
00168  *      f107 and f107A values used to generate the model correspond
00169  *      to the 10.7 cm radio flux at the actual distance of the Earth
00170  *      from the Sun rather than the radio flux at 1 AU. The following
00171  *      site provides both classes of values:
00172  *      ftp://ftp.ngdc.noaa.gov/STP/SOLAR_DATA/SOLAR_RADIO/FLUX/
00173  *
00174  *      f107, f107A, and ap effects are neither large nor well
00175  *      established below 80 km and these parameters should be set to
00176  *      150., 150., and 4. respectively.
00177  */
00178 
00179 
00180 
00181 /* ------------------------------------------------------------------- */
00182 /* ------------------------------ OUTPUT ----------------------------- */
00183 /* ------------------------------------------------------------------- */
00184 
00185 struct nrlmsise_output {
00186   double d[9];   /* densities    */
00187   double t[2];   /* temperatures */
00188 };
00189 /* 
00190  *   OUTPUT VARIABLES:
00191  *      d[0] - HE NUMBER DENSITY(CM-3)
00192  *      d[1] - O NUMBER DENSITY(CM-3)
00193  *      d[2] - N2 NUMBER DENSITY(CM-3)
00194  *      d[3] - O2 NUMBER DENSITY(CM-3)
00195  *      d[4] - AR NUMBER DENSITY(CM-3)                       
00196  *      d[5] - TOTAL MASS DENSITY(GM/CM3) [includes d[8] in td7d]
00197  *      d[6] - H NUMBER DENSITY(CM-3)
00198  *      d[7] - N NUMBER DENSITY(CM-3)
00199  *      d[8] - Anomalous oxygen NUMBER DENSITY(CM-3)
00200  *      t[0] - EXOSPHERIC TEMPERATURE
00201  *      t[1] - TEMPERATURE AT ALT
00202  * 
00203  *
00204  *      O, H, and N are set to zero below 72.5 km
00205  *
00206  *      t[0], Exospheric temperature, is set to global average for
00207  *      altitudes below 120 km. The 120 km gradient is left at global
00208  *      average value for altitudes below 72 km.
00209  *
00210  *      d[5], TOTAL MASS DENSITY, is NOT the same for subroutines GTD7 
00211  *      and GTD7D
00212  *
00213  *        SUBROUTINE GTD7 -- d[5] is the sum of the mass densities of the
00214  *        species labeled by indices 0-4 and 6-7 in output variable d.
00215  *        This includes He, O, N2, O2, Ar, H, and N but does NOT include
00216  *        anomalous oxygen (species index 8).
00217  *
00218  *        SUBROUTINE GTD7D -- d[5] is the "effective total mass density
00219  *        for drag" and is the sum of the mass densities of all species
00220  *        in this model, INCLUDING anomalous oxygen.
00221  */
00222 
00223 
00224 
00225 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00226 CLASS DECLARATION
00227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00228 
00229 class MSIS : public FGAtmosphere
00230 {
00231 public:
00232 
00234   MSIS(FGFDMExec*);
00236   ~MSIS();
00244   bool Run(bool Holding);
00245 
00246   bool InitModel(void);
00247 
00249   void UseExternal(void);
00250 
00251 private:
00252 
00253   void Calculate(int day,      // day of year (1 to 366) 
00254                  double sec,   // seconds in day (0.0 to 86400.0)
00255                  double alt,   // altitude, feet
00256                  double lat,   // geodetic latitude, degrees
00257                  double lon    // geodetic longitude, degrees
00258                 );
00259 
00260   void Debug(int from);
00261 
00262   nrlmsise_flags flags;
00263   nrlmsise_input input;
00264   nrlmsise_output output;
00265   ap_array aph;
00266 
00267   /* PARMB */
00268   double gsurf;
00269   double re;
00270 
00271   /* GTS3C */
00272   double dd;
00273 
00274   /* DMIX */
00275   double dm04, dm16, dm28, dm32, dm40, dm01, dm14;
00276 
00277   /* MESO7 */
00278   double meso_tn1[5];
00279   double meso_tn2[4];
00280   double meso_tn3[5];
00281   double meso_tgn1[2];
00282   double meso_tgn2[2];
00283   double meso_tgn3[2];
00284 
00285   /* LPOLY */
00286   double dfa;
00287   double plg[4][9];
00288   double ctloc, stloc;
00289   double c2tloc, s2tloc;
00290   double s3tloc, c3tloc;
00291   double apdf, apt[4];
00292 
00293   void tselec(struct nrlmsise_flags *flags);
00294   void glatf(double lat, double *gv, double *reff);
00295   double ccor(double alt, double r, double h1, double zh);
00296   double ccor2(double alt, double r, double h1, double zh, double h2);
00297   double scalh(double alt, double xm, double temp);
00298   double dnet(double dd, double dm, double zhm, double xmm, double xm);
00299   void splini(double *xa, double *ya, double *y2a, int n, double x, double *y);
00300   void splint(double *xa, double *ya, double *y2a, int n, double x, double *y);
00301   void spline(double *x, double *y, int n, double yp1, double ypn, double *y2);
00302   double zeta(double zz, double zl);
00303   double densm(double alt, double d0, double xm, double *tz, int mn3, double *zn3,
00304                double *tn3, double *tgn3, int mn2, double *zn2, double *tn2,
00305                double *tgn2);
00306   double densu(double alt, double dlb, double tinf, double tlb, double xm, 
00307                double alpha, double *tz, double zlb, double s2, int mn1, 
00308                double *zn1, double *tn1, double *tgn1);
00309   double g0(double a, double *p);
00310   double sumex(double ex);
00311   double sg0(double ex, double *p, double *ap);
00312   double globe7(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
00313   double glob7s(double *p, nrlmsise_input *input, nrlmsise_flags *flags);
00314 
00315 // GTD7
00316 // Neutral Atmosphere Empirical Model from the surface to lower exosphere.
00317   void gtd7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output);
00318 
00319 // GTD7D 
00320 // This subroutine provides Effective Total Mass Density for output
00321 // d[5] which includes contributions from "anomalous oxygen" which can
00322 // affect satellite drag above 500 km. See the section "output" for
00323 // additional details.
00324   void gtd7d(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); 
00325 
00326 // GHP7
00327 // To specify outputs at a pressure level (press) rather than at
00328 // an altitude.
00329   void ghp7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output, double press);
00330 
00331 // GTS7
00332 // Thermospheric portion of NRLMSISE-00
00333   void gts7(nrlmsise_input *input, nrlmsise_flags *flags, nrlmsise_output *output); 
00334 
00335 };
00336 
00337 } // namespace JSBSim
00338 
00339 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00340 #endif
00341