├── .gitignore ├── LICENSE ├── README ├── nrlmsise_00.py ├── nrlmsise_00_data.py ├── nrlmsise_00_header.py └── nrlmsise_00_test.py /.gitignore: -------------------------------------------------------------------------------- 1 | /lookat.txt 2 | /__pycache__ 3 | /test.py 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Joshua Milas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a port of the NRLMSISE-00 atmospheric model to python 2 | based of the c version from Dominik Brodowski http://www.brodo.de/english/pub/nrlmsise/ 3 | 4 | It is used the same way as the c version is 5 | 6 | C program runtime 7 | 0.031-0.033 seconds 8 | 9 | Python runtime 10 | 0.038-0.041 seconds 11 | 12 | It runs at almost comparable speeds after running a few times 13 | 14 | To use, make an input class, and output class, and a flag class. 15 | Set the input and flags with the appropriate settings, 16 | then call gtd7(input, flags, output) 17 | -------------------------------------------------------------------------------- /nrlmsise_00.py: -------------------------------------------------------------------------------- 1 | """ 2 | 12/19/2013 3 | Author: Joshua Milas 4 | Python Version: 3.3.2 5 | 6 | The NRLMSISE-00 model 2001 ported to python 7 | Based off of Dominik Brodowski 20100516 version available here 8 | http://www.brodo.de/english/pub/nrlmsise/ 9 | 10 | This is the main program that contains all the functions 11 | /* -------------------------------------------------------------------- */ 12 | /* --------- N R L M S I S E - 0 0 M O D E L 2 0 0 1 ---------- */ 13 | /* -------------------------------------------------------------------- */ 14 | 15 | /* This file is part of the NRLMSISE-00 C source code package - release 16 | * 20041227 17 | * 18 | * The NRLMSISE-00 model was developed by Mike Picone, Alan Hedin, and 19 | * Doug Drob. They also wrote a NRLMSISE-00 distribution package in 20 | * FORTRAN which is available at 21 | * http://uap-www.nrl.navy.mil/models_web/msis/msis_home.htm 22 | * 23 | * Dominik Brodowski implemented and maintains this C version. You can 24 | * reach him at mail@brodo.de. See the file "DOCUMENTATION" for details, 25 | * and check http://www.brodo.de/english/pub/nrlmsise/index.html for 26 | * updated releases of this package. 27 | */ 28 | """ 29 | 30 | 31 | from nrlmsise_00_header import * 32 | from math import * 33 | 34 | """ 35 | /* ------------------------------------------------------------------- */ 36 | /* ------------------------- SHARED VARIABLES ------------------------ */ 37 | /* ------------------------------------------------------------------- */ 38 | """ 39 | 40 | #/* PARMB */ 41 | gsurf = [0.0]; 42 | re = [0.0]; 43 | 44 | #/* GTS3C */ 45 | dd = 0.0; 46 | 47 | #/* DMIX */ 48 | dm04 = 0.0 49 | dm16 = 0.0 50 | dm28 = 0.0 51 | dm32 = 0.0 52 | dm40 = 0.0 53 | dm01 = 0.0 54 | dm14 = 0.0 55 | 56 | #/* MESO7 */ 57 | meso_tn1 = [0.0 for _ in range(5)]; 58 | meso_tn2 = [0.0 for _ in range(4)]; 59 | meso_tn3 = [0.0 for _ in range(5)]; 60 | meso_tgn1 = [0.0 for _ in range(2)]; 61 | meso_tgn2 = [0.0 for _ in range(2)]; 62 | meso_tgn3 = [0.0 for _ in range(2)]; 63 | 64 | #/* POWER7 */ 65 | #/* LOWER7 */ 66 | #Dont to need to do anyt of the externs, they are all here 67 | from nrlmsise_00_data import * 68 | 69 | 70 | #/* LPOLY */ 71 | dfa = 0.0 72 | plg = [[0.0 for _ in range(9)] for _ in range(4)]; 73 | ctloc = 0.0 74 | stloc = 0.0 75 | c2tloc = 0.0 76 | s2tloc = 0.0 77 | s3tloc = 0.0 78 | c3tloc = 0.0 79 | apdf = 0.0 80 | apt = [0.0 for _ in range(4)] 81 | 82 | 83 | #since rgas is used eerywehre usignthe same variable, ill make it glboal 84 | #rgas = 831.44621 85 | #rgas = 831.4 86 | """ 87 | /* ------------------------------------------------------------------- */ 88 | /* ------------------------------ TSELEC ----------------------------- */ 89 | /* ------------------------------------------------------------------- */ 90 | """ 91 | def tselec(flags): 92 | 93 | for i in range(24): 94 | if(i != 9): 95 | if(flags.switches[i]==1): 96 | flags.sw[i]=1 97 | else: 98 | flags.sw[i]=0 99 | 100 | if(flags.switches[i]>0): 101 | flags.swc[i]=1 102 | else: 103 | flags.swc[i]=0 104 | else: 105 | flags.sw[i]=flags.switches[i] 106 | flags.swc[i]=flags.switches[i] 107 | return 108 | 109 | 110 | """ 111 | /* ------------------------------------------------------------------- */ 112 | /* ------------------------------ GLATF ------------------------------ */ 113 | /* ------------------------------------------------------------------- */ 114 | """ 115 | def glatf(lat, gv, reff): 116 | dgtr = 1.74533E-2 117 | c2 = cos(2.0*dgtr*lat) 118 | 119 | #Need to return these since the c program wants pointers to these 120 | gv[0] = 980.616 * (1.0 - 0.0026373 * c2) 121 | reff[0] = 2.0 * (gv[0]) / (3.085462E-6 + 2.27E-9 * c2) * 1.0E-5 #The may-be troubled line 122 | return #gv, rref 123 | 124 | """ 125 | /* ------------------------------------------------------------------- */ 126 | /* ------------------------------ CCOR ------------------------------- */ 127 | /* ------------------------------------------------------------------- */ 128 | """ 129 | def ccor(alt, r, h1, zh): 130 | """ 131 | /* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS 132 | * ALT - altitude 133 | * R - target ratio 134 | * H1 - transition scale length 135 | * ZH - altitude of 1/2 R 136 | */ 137 | """ 138 | e = (alt - zh) / h1 139 | if(e>70): 140 | return exp(0) 141 | if (e<-70): 142 | return exp(r) 143 | ex = exp(e) 144 | e = r / (1.0 + ex) 145 | return exp(e) 146 | 147 | ''' 148 | /* ------------------------------------------------------------------- */ 149 | /* ------------------------------ CCOR ------------------------------- */ 150 | /* ------------------------------------------------------------------- */ 151 | ''' 152 | def ccor2(alt, r, h1, zh, h2): 153 | ''' 154 | /* CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS 155 | * ALT - altitude 156 | * R - target ratio 157 | * H1 - transition scale length 158 | * ZH - altitude of 1/2 R 159 | * H2 - transition scale length #2 ? 160 | */ 161 | ''' 162 | e1 = (alt - zh) / h1; 163 | e2 = (alt - zh) / h2; 164 | if ((e1 > 70) or (e2 > 70)): 165 | return exp(0) 166 | if ((e1 < -70) and (e2 < -70)): 167 | return exp(r) 168 | ex1 = exp(e1); 169 | ex2 = exp(e2); 170 | ccor2v = r / (1.0 + 0.5 * (ex1 + ex2)); 171 | return exp(ccor2v); 172 | 173 | 174 | 175 | """ 176 | /* ------------------------------------------------------------------- */ 177 | /* ------------------------------- SCALH ----------------------------- */ 178 | /* ------------------------------------------------------------------- */ 179 | """ 180 | def scalh(alt, xm, temp): 181 | #rgas = 831.44621 #maybe make this a global constant? 182 | rgas = 831.4 183 | g = gsurf[0] / (pow((1.0 + alt/re[0]),2.0)) 184 | g = rgas * temp / (g * xm) 185 | return g 186 | 187 | 188 | ''' 189 | /* ------------------------------------------------------------------- */ 190 | /* -------------------------------- DNET ----------------------------- */ 191 | /* ------------------------------------------------------------------- */ 192 | ''' 193 | def dnet(dd, dm, zhm, xmm, xm): 194 | ''' 195 | /* TURBOPAUSE CORRECTION FOR MSIS MODELS 196 | * Root mean density 197 | * DD - diffusive density 198 | * DM - full mixed density 199 | * ZHM - transition scale length 200 | * XMM - full mixed molecular weight 201 | * XM - species molecular weight 202 | * DNET - combined density 203 | */ 204 | ''' 205 | a = zhm / (xmm-xm) 206 | if( not((dm>0) and (dd>0))): 207 | print("dnet log error %e %e %e" % (dm, dd, xm)) 208 | if((dd==0) and (dm==0)): 209 | dd=1 210 | if(dm==0): 211 | return dd 212 | if(dd==0): 213 | return dm 214 | 215 | ylog = a * log(dm/dd) 216 | if(ylog < -10): 217 | return dd 218 | if(ylog>10): 219 | return dm 220 | a = dd*pow((1.0 + exp(ylog)),(1.0/a)) 221 | return a 222 | 223 | 224 | ''' 225 | /* ------------------------------------------------------------------- */ 226 | /* ------------------------------- SPLINI ---------------------------- */ 227 | /* ------------------------------------------------------------------- */ 228 | ''' 229 | def splini(xa, ya, y2a, n, x, y): 230 | ''' 231 | /* INTEGRATE CUBIC SPLINE FUNCTION FROM XA(1) TO X 232 | * XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X 233 | * Y2A: ARRAY OF SECOND DERIVATIVES 234 | * N: SIZE OF ARRAYS XA,YA,Y2A 235 | * X: ABSCISSA ENDPOINT FOR INTEGRATION 236 | * Y: OUTPUT VALUE 237 | */ 238 | ''' 239 | yi = 0 240 | klo = 0 241 | khi = 1 242 | while((x>xa[klo]) and (khi1): 281 | k=int((khi+klo)/2); 282 | if (xa[k]>x): 283 | khi = k 284 | else: 285 | klo = k 286 | h = xa[khi] - xa[klo]; 287 | if (h==0.0): 288 | print("bad XA input to splint") 289 | a = (xa[khi] - x)/h; 290 | b = (x - xa[klo])/h; 291 | yi = a * ya[klo] + b * ya[khi] + ((a*a*a - a) * y2a[klo] + (b*b*b - b) * y2a[khi]) * h * h/6.0; 292 | y[0] = yi #may not need this 293 | return #yi #or this 294 | 295 | 296 | ''' 297 | /* ------------------------------------------------------------------- */ 298 | /* ------------------------------- SPLINE ---------------------------- */ 299 | /* ------------------------------------------------------------------- */ 300 | ''' 301 | def spline(x, y, n, yp1, ypn, y2): 302 | ''' 303 | /* CALCULATE 2ND DERIVATIVES OF CUBIC SPLINE INTERP FUNCTION 304 | * ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL 305 | * X,Y: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X 306 | * N: SIZE OF ARRAYS X,Y 307 | * YP1,YPN: SPECIFIED DERIVATIVES AT X[0] AND X[N-1]; VALUES 308 | * >= 1E30 SIGNAL SIGNAL SECOND DERIVATIVE ZERO 309 | * Y2: OUTPUT ARRAY OF SECOND DERIVATIVES 310 | */ 311 | ''' 312 | u = [0.0 for _ in range(n)] #I think this is the same as malloc 313 | 314 | #no need for the out of memory 315 | 316 | if (yp1 > 0.99E30): 317 | y2[0] = 0 318 | u[0] = 0 319 | else: 320 | y2[0]=-0.5 321 | u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yp1) 322 | 323 | for i in range(1, n-1): 324 | sig = (x[i]-x[i-1])/(x[i+1] - x[i-1]) 325 | p = sig * y2[i-1] + 2.0 326 | y2[i] = (sig - 1.0) / p 327 | u[i] = (6.0 * ((y[i+1] - y[i])/(x[i+1] - x[i]) -(y[i] - y[i-1]) / (x[i] - x[i-1]))/(x[i+1] - x[i-1]) - sig * u[i-1])/p; 328 | 329 | if (ypn>0.99E30): 330 | qn = 0; 331 | un = 0 332 | else: 333 | qn = 0.5 334 | un = (3.0 / (x[n-1] - x[n-2])) * (ypn - (y[n-1] - y[n-2])/(x[n-1] - x[n-2])); 335 | 336 | y2[n-1] = (un - qn * u[n-2]) / (qn * y2[n-2] + 1.0); 337 | 338 | #it uses a for loop here, but its not something python can do (I dont think) 339 | k = n-2 340 | while(k >= 0): 341 | y2[k] = y2[k] * y2[k+1] + u[k] 342 | k -= 1 343 | #This for loop might work 344 | #for k in range(n-2, -1, -1): 345 | # y2[k] = y2[k] * y2[k+1] + u[k] 346 | #no need to free u here 347 | return 348 | 349 | 350 | ''' 351 | /* ------------------------------------------------------------------- */ 352 | /* ------------------------------- DENSM ----------------------------- */ 353 | /* ------------------------------------------------------------------- */ 354 | ''' 355 | def zeta(zz, zl): 356 | return ((zz-zl)*(re[0]+zl)/(re[0]+zz)) #re is the global variable 357 | 358 | def densm(alt, d0, xm, tz, mn3, zn3, tn3, tgn3, mn2, zn2, tn2, tgn2): 359 | ''' 360 | /* Calculate Temperature and Density Profiles for lower atmos. */ 361 | ''' 362 | xs = [0.0 for _ in range(10)] 363 | ys = [0.0 for _ in range(10)] 364 | y2out = [0.0 for _ in range(10)] 365 | rgas = 831.4 366 | #rgas = 831.44621 #maybe make this a global constant? 367 | densm_tmp=d0 368 | if (alt>zn2[0]): 369 | if(xm==0.0): 370 | return tz[0] 371 | else: 372 | return d0 373 | 374 | #/* STRATOSPHERE/MESOSPHERE TEMPERATURE */ 375 | if (alt>zn2[mn2-1]): 376 | z=alt 377 | else: 378 | z=zn2[mn2-1]; 379 | mn=mn2; 380 | z1=zn2[0]; 381 | z2=zn2[mn-1]; 382 | t1=tn2[0]; 383 | t2=tn2[mn-1]; 384 | zg = zeta(z, z1); 385 | zgdif = zeta(z2, z1); 386 | 387 | #/* set up spline nodes */ 388 | for k in range(mn): 389 | xs[k]=zeta(zn2[k],z1)/zgdif; 390 | ys[k]=1.0 / tn2[k]; 391 | yd1=-tgn2[0] / (t1*t1) * zgdif; 392 | yd2=-tgn2[1] / (t2*t2) * zgdif * (pow(((re[0]+z2)/(re[0]+z1)),2.0)); 393 | 394 | #/* calculate spline coefficients */ 395 | spline (xs, ys, mn, yd1, yd2, y2out); #No need to change this 396 | x = zg/zgdif; 397 | y = [0.0] 398 | splint (xs, ys, y2out, mn, x, y); 399 | 400 | #/* temperature at altitude */ 401 | tz[0] = 1.0 / y[0]; 402 | if (xm!=0.0): 403 | #/* calaculate stratosphere / mesospehere density */ 404 | glb = gsurf[0] / (pow((1.0 + z1/re[0]),2.0)); 405 | gamm = xm * glb * zgdif / rgas; 406 | 407 | #/* Integrate temperature profile */ 408 | yi = [0.0] 409 | splini(xs, ys, y2out, mn, x, yi); 410 | expl=gamm*yi[0]; 411 | if (expl>50.0): 412 | expl=50.0 413 | 414 | #/* Density at altitude */ 415 | densm_tmp = densm_tmp * (t1 / tz[0]) * exp(-expl); 416 | 417 | if (alt>zn3[0]): 418 | if (xm==0.0): 419 | return tz[0] 420 | else: 421 | return densm_tmp 422 | 423 | #/* troposhere / stratosphere temperature */ 424 | z = alt; 425 | mn = mn3; 426 | z1=zn3[0]; 427 | z2=zn3[mn-1]; 428 | t1=tn3[0]; 429 | t2=tn3[mn-1]; 430 | zg=zeta(z,z1); 431 | zgdif=zeta(z2,z1); 432 | 433 | 434 | 435 | #/* set up spline nodes */ 436 | for k in range(mn): 437 | xs[k] = zeta(zn3[k],z1) / zgdif; 438 | ys[k] = 1.0 / tn3[k]; 439 | 440 | yd1=-tgn3[0] / (t1*t1) * zgdif; 441 | yd2=-tgn3[1] / (t2*t2) * zgdif * (pow(((re[0]+z2)/(re[0]+z1)),2.0)); 442 | 443 | #/* calculate spline coefficients */ 444 | spline (xs, ys, mn, yd1, yd2, y2out); 445 | x = zg/zgdif; 446 | y = [0.0] 447 | splint (xs, ys, y2out, mn, x, y); 448 | 449 | #/* temperature at altitude */ 450 | tz[0] = 1.0 / y[0]; 451 | if (xm!=0.0): 452 | #/* calaculate tropospheric / stratosphere density */ 453 | glb = gsurf[0] / (pow((1.0 + z1/re[0]),2.0)); 454 | gamm = xm * glb * zgdif / rgas; 455 | 456 | #/* Integrate temperature profile */ 457 | yi = [0.0] 458 | splini(xs, ys, y2out, mn, x, yi); 459 | expl=gamm*yi[0]; 460 | if (expl>50.0): 461 | expl=50.0; 462 | 463 | #/* Density at altitude */ 464 | densm_tmp = densm_tmp * (t1 / tz[0]) * exp(-expl); 465 | 466 | if (xm==0.0): 467 | return tz[0]; 468 | else: 469 | return densm_tmp; 470 | return 471 | 472 | 473 | ''' 474 | /* ------------------------------------------------------------------- */ 475 | /* ------------------------------- DENSU ----------------------------- */ 476 | /* ------------------------------------------------------------------- */ 477 | ''' 478 | def densu(alt, dlb, tinf, tlb, xm, alpha, tz, zlb, s2, mn1, zn1, tn1, tgn1): 479 | ''' 480 | /* Calculate Temperature and Density Profiles for MSIS models 481 | * New lower thermo polynomial 482 | */ 483 | tz, zn1, tn1, and tgn1 are simulated pointers 484 | ''' 485 | rgas = 831.4 486 | #rgas = 831.44621 #maybe make this a global constant? 487 | densu_temp = 1.0 488 | 489 | xs = [0.0 for _ in range(5)] 490 | ys = [0.0 for _ in range(5)] 491 | y2out = [0.0 for _ in range(5)] 492 | 493 | #/* joining altitudes of Bates and spline */ 494 | za=zn1[0]; 495 | if (alt>za): 496 | z=alt; 497 | else: 498 | z=za; 499 | 500 | #/* geopotential altitude difference from ZLB */ 501 | zg2 = zeta(z, zlb); 502 | 503 | #/* Bates temperature */ 504 | tt = tinf - (tinf - tlb) * exp(-s2*zg2); 505 | ta = tt; 506 | tz[0] = tt 507 | densu_temp = tz[0] 508 | 509 | if (altzn1[mn1-1]): 516 | z=alt; 517 | else: 518 | z=zn1[mn1-1]; 519 | mn=mn1; 520 | z1=zn1[0]; 521 | z2=zn1[mn-1]; 522 | t1=tn1[0]; 523 | t2=tn1[mn-1]; 524 | #/* geopotental difference from z1 */ 525 | zg = zeta (z, z1); 526 | zgdif = zeta(z2, z1); 527 | #/* set up spline nodes */ 528 | for k in range(mn): 529 | xs[k] = zeta(zn1[k], z1) / zgdif; 530 | ys[k] = 1.0 / tn1[k]; 531 | 532 | #/* end node derivatives */ 533 | yd1 = -tgn1[0] / (t1*t1) * zgdif; 534 | yd2 = -tgn1[1] / (t2*t2) * zgdif * pow(((re[0]+z2)/(re[0]+z1)),2.0); 535 | #/* calculate spline coefficients */ 536 | spline (xs, ys, mn, yd1, yd2, y2out); 537 | x = zg / zgdif; 538 | y = [0.0] 539 | splint (xs, ys, y2out, mn, x, y); 540 | #/* temperature at altitude */ 541 | tz[0] = 1.0 / y[0]; 542 | densu_temp = tz[0]; 543 | 544 | if (xm==0): 545 | return densu_temp; 546 | 547 | #/* calculate density above za */ 548 | glb = gsurf[0] / pow((1.0 + zlb/re[0]),2.0); 549 | gamma = xm * glb / (s2 * rgas * tinf); 550 | expl = exp(-s2 * gamma * zg2); 551 | if (expl>50.0): 552 | expl=50.0; 553 | if (tt<=0): 554 | expl=50.0; 555 | 556 | #/* density at altitude */ 557 | densa = dlb * pow((tlb/tt),((1.0+alpha+gamma))) * expl; 558 | densu_temp=densa; 559 | if (alt>=za): 560 | return densu_temp; 561 | 562 | #/* calculate density below za */ 563 | glb = gsurf[0] / pow((1.0 + z1/re[0]),2.0); 564 | gamm = xm * glb * zgdif / rgas; 565 | 566 | #/* integrate spline temperatures */ 567 | yi = [0] 568 | splini (xs, ys, y2out, mn, x, yi); 569 | expl = gamm * yi[0]; 570 | if (expl>50.0): 571 | expl=50.0; 572 | if (tz[0]<=0): 573 | expl=50.0; 574 | 575 | #/* density at altitude */ 576 | densu_temp = densu_temp * pow ((t1 / tz[0]),(1.0 + alpha)) * exp(-expl); 577 | return densu_temp; 578 | 579 | 580 | ''' 581 | /* ------------------------------------------------------------------- */ 582 | /* ------------------------------- GLOBE7 ---------------------------- */ 583 | /* ------------------------------------------------------------------- */ 584 | ''' 585 | 586 | #/* 3hr Magnetic activity functions */ 587 | #/* Eq. A24d */ 588 | def g0(a, p): 589 | return (a - 4.0 + (p[25] - 1.0) * (a - 4.0 + (exp(-sqrt(p[24]*p[24]) * (a - 4.0)) - 1.0) / sqrt(p[24]*p[24]))); 590 | 591 | 592 | #/* Eq. A24c */ 593 | def sumex(ex): 594 | return (1.0 + (1.0 - pow(ex,19.0)) / (1.0 - ex) * pow(ex,0.5)); 595 | 596 | 597 | #/* Eq. A24a */ 598 | def sg0(ex, p, ap): 599 | return (g0(ap[1],p) + (g0(ap[2],p)*ex + g0(ap[3],p)*ex*ex + \ 600 | g0(ap[4],p)*pow(ex,3.0) + (g0(ap[5],p)*pow(ex,4.0) + \ 601 | g0(ap[6],p)*pow(ex,12.0))*(1.0-pow(ex,8.0))/(1.0-ex)))/sumex(ex); 602 | 603 | 604 | def globe7(p, Input, flags): 605 | ''' 606 | /* CALCULATE G(L) FUNCTION 607 | * Upper Thermosphere Parameters */ 608 | ''' 609 | t = [0 for _ in range(15)] #modified this, there was a for loop that did this 610 | sw9 = 1 611 | sr = 7.2722E-5; 612 | dgtr = 1.74533E-2; 613 | dr = 1.72142E-2; 614 | hr = 0.2618; 615 | 616 | tloc = Input.lst 617 | #for j in range(14): 618 | # t[j] = 0 619 | if(flags.sw[9] > 0): 620 | sw9 = 1 621 | elif(flags.sw[9] < 0): 622 | sw9 = -1 623 | xlong = Input.g_long 624 | 625 | #/* calculate legendre polynomials */ 626 | c = sin(Input.g_lat * dgtr); 627 | s = cos(Input.g_lat * dgtr); 628 | c2 = c*c; 629 | c4 = c2*c2; 630 | s2 = s*s; 631 | 632 | plg[0][1] = c; 633 | plg[0][2] = 0.5*(3.0*c2 -1.0); 634 | plg[0][3] = 0.5*(5.0*c*c2-3.0*c); 635 | plg[0][4] = (35.0*c4 - 30.0*c2 + 3.0)/8.0; 636 | plg[0][5] = (63.0*c2*c2*c - 70.0*c2*c + 15.0*c)/8.0; 637 | plg[0][6] = (11.0*c*plg[0][5] - 5.0*plg[0][4])/6.0; 638 | #/* plg[0][7] = (13.0*c*plg[0][6] - 6.0*plg[0][5])/7.0; */ 639 | plg[1][1] = s; 640 | plg[1][2] = 3.0*c*s; 641 | plg[1][3] = 1.5*(5.0*c2-1.0)*s; 642 | plg[1][4] = 2.5*(7.0*c2*c-3.0*c)*s; 643 | plg[1][5] = 1.875*(21.0*c4 - 14.0*c2 +1.0)*s; 644 | plg[1][6] = (11.0*c*plg[1][5]-6.0*plg[1][4])/5.0; 645 | #/* plg[1][7] = (13.0*c*plg[1][6]-7.0*plg[1][5])/6.0; */ 646 | #/* plg[1][8] = (15.0*c*plg[1][7]-8.0*plg[1][6])/7.0; */ 647 | plg[2][2] = 3.0*s2; 648 | plg[2][3] = 15.0*s2*c; 649 | plg[2][4] = 7.5*(7.0*c2 -1.0)*s2; 650 | plg[2][5] = 3.0*c*plg[2][4]-2.0*plg[2][3]; 651 | plg[2][6] =(11.0*c*plg[2][5]-7.0*plg[2][4])/4.0; 652 | plg[2][7] =(13.0*c*plg[2][6]-8.0*plg[2][5])/5.0; 653 | plg[3][3] = 15.0*s2*s; 654 | plg[3][4] = 105.0*s2*s*c; 655 | plg[3][5] =(9.0*c*plg[3][4]-7.*plg[3][3])/2.0; 656 | plg[3][6] =(11.0*c*plg[3][5]-8.*plg[3][4])/3.0; 657 | 658 | if( not (((flags.sw[7]==0) and (flags.sw[8]==0)) and (flags.sw[14] == 0))): 659 | global stloc 660 | stloc = sin(hr*tloc); 661 | global ctloc 662 | ctloc = cos(hr*tloc); 663 | global s2tloc 664 | s2tloc = sin(2.0*hr*tloc); 665 | global c2tloc 666 | c2tloc = cos(2.0*hr*tloc); 667 | global s3tloc 668 | s3tloc = sin(3.0*hr*tloc); 669 | global c3tloc 670 | c3tloc = cos(3.0*hr*tloc); 671 | 672 | cd32 = cos(dr*(Input.doy-p[31])); 673 | cd18 = cos(2.0*dr*(Input.doy-p[17])); 674 | cd14 = cos(dr*(Input.doy-p[13])); 675 | cd39 = cos(2.0*dr*(Input.doy-p[38])); 676 | p32=p[31]; 677 | p18=p[17]; 678 | p14=p[13]; 679 | p39=p[38]; 680 | 681 | #/* F10.7 EFFECT */ 682 | df = Input.f107 - Input.f107A; 683 | global dfa 684 | dfa = Input.f107A - 150.0; 685 | t[0] = p[19]*df*(1.0+p[59]*dfa) + p[20]*df*df + p[21]*dfa + p[29]*pow(dfa,2.0); 686 | f1 = 1.0 + (p[47]*dfa +p[19]*df+p[20]*df*df)*flags.swc[1]; 687 | f2 = 1.0 + (p[49]*dfa+p[19]*df+p[20]*df*df)*flags.swc[1]; 688 | 689 | #/* TIME INDEPENDENT */ 690 | t[1] = (p[1]*plg[0][2]+ p[2]*plg[0][4]+p[22]*plg[0][6]) + \ 691 | (p[14]*plg[0][2])*dfa*flags.swc[1] +p[26]*plg[0][1]; 692 | 693 | #/* SYMMETRICAL ANNUAL */ 694 | t[2] = p[18]*cd32; 695 | 696 | #/* SYMMETRICAL SEMIANNUAL */ 697 | t[3] = (p[15]+p[16]*plg[0][2])*cd18; 698 | 699 | #/* ASYMMETRICAL ANNUAL */ 700 | t[4] = f1*(p[9]*plg[0][1]+p[10]*plg[0][3])*cd14; 701 | 702 | #/* ASYMMETRICAL SEMIANNUAL */ 703 | t[5] = p[37]*plg[0][1]*cd39; 704 | 705 | #/* DIURNAL */ 706 | if (flags.sw[7]): 707 | t71 = (p[11]*plg[1][2])*cd14*flags.swc[5]; 708 | t72 = (p[12]*plg[1][2])*cd14*flags.swc[5]; 709 | t[6] = f2*((p[3]*plg[1][1] + p[4]*plg[1][3] + p[27]*plg[1][5] + t71) * \ 710 | ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + p[28]*plg[1][5] \ 711 | + t72)*stloc); 712 | 713 | 714 | #/* SEMIDIURNAL */ 715 | if (flags.sw[8]): 716 | t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags.swc[5]; 717 | t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags.swc[5]; 718 | t[7] = f2*((p[5]*plg[2][2]+ p[41]*plg[2][4] + t81)*c2tloc +(p[8]*plg[2][2] + p[42]*plg[2][4] + t82)*s2tloc); 719 | 720 | 721 | #/* TERDIURNAL */ 722 | if (flags.sw[14]): 723 | t[13] = f2 * ((p[39]*plg[3][3]+(p[93]*plg[3][4]+p[46]*plg[3][6])*cd14*flags.swc[5])* s3tloc +(p[40]*plg[3][3]+(p[94]*plg[3][4]+p[48]*plg[3][6])*cd14*flags.swc[5])* c3tloc); 724 | 725 | 726 | #/* magnetic activity based on daily ap */ 727 | if (flags.sw[9]==-1): 728 | ap = Input.ap_a; 729 | if (p[51]!=0): 730 | exp1 = exp(-10800.0*sqrt(p[51]*p[51])/(1.0+p[138]*(45.0-sqrt(Input.g_lat*Input.g_lat)))); 731 | if (exp1>0.99999): 732 | exp1=0.99999; 733 | if (p[24]<1.0E-4): 734 | p[24]=1.0E-4; 735 | apt[0]=sg0(exp1,p,ap.a); 736 | #/* apt[1]=sg2(exp1,p,ap->a); 737 | # apt[2]=sg0(exp2,p,ap->a); 738 | # apt[3]=sg2(exp2,p,ap->a); 739 | #*/ 740 | if (flags.sw[9]): 741 | t[8] = apt[0]*(p[50]+p[96]*plg[0][2]+p[54]*plg[0][4]+ \ 742 | (p[125]*plg[0][1]+p[126]*plg[0][3]+p[127]*plg[0][5])*cd14*flags.swc[5]+ \ 743 | (p[128]*plg[1][1]+p[129]*plg[1][3]+p[130]*plg[1][5])*flags.swc[7]* \ 744 | cos(hr*(tloc-p[131]))); 745 | 746 | 747 | else: 748 | apd=Input.ap-4.0; 749 | p44=p[43]; 750 | p45=p[44]; 751 | if (p44<0): 752 | p44 = 1.0E-5; 753 | global apdf 754 | apdf = apd + (p45-1.0)*(apd + (exp(-p44 * apd) - 1.0)/p44); 755 | if (flags.sw[9]): 756 | t[8]=apdf*(p[32]+p[45]*plg[0][2]+p[34]*plg[0][4]+ \ 757 | (p[100]*plg[0][1]+p[101]*plg[0][3]+p[102]*plg[0][5])*cd14*flags.swc[5]+ 758 | (p[121]*plg[1][1]+p[122]*plg[1][3]+p[123]*plg[1][5])*flags.swc[7]* 759 | cos(hr*(tloc-p[124]))); 760 | 761 | 762 | 763 | if ((flags.sw[10]) and (Input.g_long>-1000.0)): 764 | 765 | #/* longitudinal */ 766 | if (flags.sw[11]): 767 | t[10] = (1.0 + p[80]*dfa*flags.swc[1])* \ 768 | ((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ 769 | +p[103]*plg[1][1]+p[104]*plg[1][3]+p[105]*plg[1][5]\ 770 | +flags.swc[5]*(p[109]*plg[1][1]+p[110]*plg[1][3]+p[111]*plg[1][5])*cd14)* \ 771 | cos(dgtr*Input.g_long) \ 772 | +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ 773 | +p[106]*plg[1][1]+p[107]*plg[1][3]+p[108]*plg[1][5]\ 774 | +flags.swc[5]*(p[112]*plg[1][1]+p[113]*plg[1][3]+p[114]*plg[1][5])*cd14)* \ 775 | sin(dgtr*Input.g_long)); 776 | 777 | 778 | #/* ut and mixed ut, longitude */ 779 | if (flags.sw[12]): 780 | t[11]=(1.0+p[95]*plg[0][1])*(1.0+p[81]*dfa*flags.swc[1])*\ 781 | (1.0+p[119]*plg[0][1]*flags.swc[5]*cd14)*\ 782 | ((p[68]*plg[0][1]+p[69]*plg[0][3]+p[70]*plg[0][5])*\ 783 | cos(sr*(Input.sec-p[71]))); 784 | t[11]+=flags.swc[11]*\ 785 | (p[76]*plg[2][3]+p[77]*plg[2][5]+p[78]*plg[2][7])*\ 786 | cos(sr*(Input.sec-p[79])+2.0*dgtr*Input.g_long)*(1.0+p[137]*dfa*flags.swc[1]); 787 | 788 | 789 | #/* ut, longitude magnetic activity */ 790 | if (flags.sw[13]): 791 | if (flags.sw[9]==-1): 792 | if (p[51]): 793 | t[12]=apt[0]*flags.swc[11]*(1.+p[132]*plg[0][1])*\ 794 | ((p[52]*plg[1][2]+p[98]*plg[1][4]+p[67]*plg[1][6])*\ 795 | cos(dgtr*(Input.g_long-p[97])))\ 796 | +apt[0]*flags.swc[11]*flags.swc[5]*\ 797 | (p[133]*plg[1][1]+p[134]*plg[1][3]+p[135]*plg[1][5])*\ 798 | cd14*cos(dgtr*(Input.g_long-p[136])) \ 799 | +apt[0]*flags.swc[12]* \ 800 | (p[55]*plg[0][1]+p[56]*plg[0][3]+p[57]*plg[0][5])*\ 801 | cos(sr*(Input.sec-p[58])); 802 | 803 | else: 804 | t[12] = apdf*flags.swc[11]*(1.0+p[120]*plg[0][1])*\ 805 | ((p[60]*plg[1][2]+p[61]*plg[1][4]+p[62]*plg[1][6])*\ 806 | cos(dgtr*(Input.g_long-p[63])))\ 807 | +apdf*flags.swc[11]*flags.swc[5]* \ 808 | (p[115]*plg[1][1]+p[116]*plg[1][3]+p[117]*plg[1][5])* \ 809 | cd14*cos(dgtr*(Input.g_long-p[118])) \ 810 | + apdf*flags.swc[12]* \ 811 | (p[83]*plg[0][1]+p[84]*plg[0][3]+p[85]*plg[0][5])* \ 812 | cos(sr*(Input.sec-p[75])); 813 | 814 | 815 | 816 | 817 | #/* parms not used: 82, 89, 99, 139-149 */ 818 | tinf = p[30]; 819 | for i in range(14): 820 | tinf = tinf + abs(flags.sw[i+1])*t[i]; 821 | return tinf; 822 | 823 | 824 | ''' 825 | /* ------------------------------------------------------------------- */ 826 | /* ------------------------------- GLOB7S ---------------------------- */ 827 | /* ------------------------------------------------------------------- */ 828 | ''' 829 | def glob7s(p, Input, flags): 830 | ''' 831 | /* VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99 832 | */ 833 | ''' 834 | pset = 2.0 835 | t = [0.0 for _ in range(14)] 836 | dr=1.72142E-2; 837 | dgtr=1.74533E-2; 838 | 839 | #/* confirm parameter set */ 840 | if (p[99]==0): 841 | p[99]=pset; 842 | if (p[99]!=pset): 843 | printf("Wrong parameter set for glob7s\n"); 844 | return -1; 845 | 846 | #for j in range(14): #Already taken care of 847 | # t[j]=0.0; 848 | cd32 = cos(dr*(Input.doy-p[31])); 849 | cd18 = cos(2.0*dr*(Input.doy-p[17])); 850 | cd14 = cos(dr*(Input.doy-p[13])); 851 | cd39 = cos(2.0*dr*(Input.doy-p[38])); 852 | p32=p[31]; 853 | p18=p[17]; 854 | p14=p[13]; 855 | p39=p[38]; 856 | 857 | #/* F10.7 */ 858 | t[0] = p[21]*dfa; 859 | 860 | #/* time independent */ 861 | t[1]=p[1]*plg[0][2] + p[2]*plg[0][4] + p[22]*plg[0][6] + p[26]*plg[0][1] + p[14]*plg[0][3] + p[59]*plg[0][5]; 862 | 863 | #/* SYMMETRICAL ANNUAL */ 864 | t[2]=(p[18]+p[47]*plg[0][2]+p[29]*plg[0][4])*cd32; 865 | 866 | #/* SYMMETRICAL SEMIANNUAL */ 867 | t[3]=(p[15]+p[16]*plg[0][2]+p[30]*plg[0][4])*cd18; 868 | 869 | #/* ASYMMETRICAL ANNUAL */ 870 | t[4]=(p[9]*plg[0][1]+p[10]*plg[0][3]+p[20]*plg[0][5])*cd14; 871 | 872 | #/* ASYMMETRICAL SEMIANNUAL */ 873 | t[5]=(p[37]*plg[0][1])*cd39; 874 | 875 | #/* DIURNAL */ 876 | if (flags.sw[7]): 877 | t71 = p[11]*plg[1][2]*cd14*flags.swc[5]; 878 | t72 = p[12]*plg[1][2]*cd14*flags.swc[5]; 879 | t[6] = ((p[3]*plg[1][1] + p[4]*plg[1][3] + t71) * ctloc + (p[6]*plg[1][1] + p[7]*plg[1][3] + t72) * stloc) ; 880 | 881 | 882 | #/* SEMIDIURNAL */ 883 | if (flags.sw[8]): 884 | t81 = (p[23]*plg[2][3]+p[35]*plg[2][5])*cd14*flags.swc[5]; 885 | t82 = (p[33]*plg[2][3]+p[36]*plg[2][5])*cd14*flags.swc[5]; 886 | t[7] = ((p[5]*plg[2][2] + p[41]*plg[2][4] + t81) * c2tloc + (p[8]*plg[2][2] + p[42]*plg[2][4] + t82) * s2tloc); 887 | 888 | 889 | #/* TERDIURNAL */ 890 | if (flags.sw[14]): 891 | t[13] = p[39] * plg[3][3] * s3tloc + p[40] * plg[3][3] * c3tloc; 892 | 893 | 894 | #/* MAGNETIC ACTIVITY */ 895 | if (flags.sw[9]): 896 | if (flags.sw[9]==1): 897 | t[8] = apdf * (p[32] + p[45] * plg[0][2] * flags.swc[2]); 898 | if (flags.sw[9]==-1): 899 | t[8]=(p[50]*apt[0] + p[96]*plg[0][2] * apt[0]*flags.swc[2]); 900 | 901 | 902 | #/* LONGITUDINAL */ 903 | if ( not((flags.sw[10]==0) or (flags.sw[11]==0) or (Input.g_long<=-1000.0))): 904 | t[10] = (1.0 + plg[0][1]*(p[80]*flags.swc[5]*cos(dr*(Input.doy-p[81]))\ 905 | +p[85]*flags.swc[6]*cos(2.0*dr*(Input.doy-p[86])))\ 906 | +p[83]*flags.swc[3]*cos(dr*(Input.doy-p[84]))\ 907 | +p[87]*flags.swc[4]*cos(2.0*dr*(Input.doy-p[88])))\ 908 | *((p[64]*plg[1][2]+p[65]*plg[1][4]+p[66]*plg[1][6]\ 909 | +p[74]*plg[1][1]+p[75]*plg[1][3]+p[76]*plg[1][5]\ 910 | )*cos(dgtr*Input.g_long)\ 911 | +(p[90]*plg[1][2]+p[91]*plg[1][4]+p[92]*plg[1][6]\ 912 | +p[77]*plg[1][1]+p[78]*plg[1][3]+p[79]*plg[1][5]\ 913 | )*sin(dgtr*Input.g_long)); 914 | 915 | tt=0; 916 | for i in range(14): 917 | tt+=abs(flags.sw[i+1])*t[i]; 918 | return tt; 919 | 920 | 921 | ''' 922 | /* ------------------------------------------------------------------- */ 923 | /* ------------------------------- GTD7 ------------------------------ */ 924 | /* ------------------------------------------------------------------- */ 925 | ''' 926 | def gtd7(Input, flags, output): 927 | mn3 = 5 928 | zn3 = [32.5,20.0,15.0,10.0,0.0] 929 | mn2 = 4 930 | zn2 = [72.5,55.0,45.0,32.5] 931 | zmix = 62.5 932 | soutput = nrlmsise_output() 933 | 934 | tselec(flags); 935 | 936 | #/* Latitude variation of gravity (none for sw[2]=0) */ 937 | xlat=Input.g_lat; 938 | if (flags.sw[2]==0): 939 | xlat=45.0; 940 | glatf(xlat, gsurf, re); 941 | 942 | xmm = pdm[2][4]; 943 | 944 | #/* THERMOSPHERE / MESOSPHERE (above zn2[0]) */ 945 | if (Input.alt>zn2[0]): 946 | altt=Input.alt; 947 | else: 948 | altt=zn2[0]; 949 | 950 | tmp=Input.alt; 951 | Input.alt=altt; 952 | 953 | gts7(Input, flags, soutput); 954 | altt=Input.alt; 955 | Input.alt=tmp; 956 | if (flags.sw[0]): #/* metric adjustment */ 957 | dm28m= dm28*1.0E6; 958 | else: 959 | dm28m = dm28; 960 | output.t[0]=soutput.t[0]; 961 | output.t[1]=soutput.t[1]; 962 | if (Input.alt>=zn2[0]): 963 | for i in range(9): 964 | output.d[i]=soutput.d[i]; 965 | return 966 | 967 | 968 | #/* LOWER MESOSPHERE/UPPER STRATOSPHERE (between zn3[0] and zn2[0]) 969 | #* Temperature at nodes and gradients at end nodes 970 | #* Inverse temperature a linear function of spherical harmonics 971 | #*/ 972 | meso_tgn2[0]=meso_tgn1[1]; 973 | meso_tn2[0]=meso_tn1[4]; 974 | meso_tn2[1]=pma[0][0]*pavgm[0]/(1.0-flags.sw[20]*glob7s(pma[0], Input, flags)); 975 | meso_tn2[2]=pma[1][0]*pavgm[1]/(1.0-flags.sw[20]*glob7s(pma[1], Input, flags)); 976 | meso_tn2[3]=pma[2][0]*pavgm[2]/(1.0-flags.sw[20]*flags.sw[22]*glob7s(pma[2], Input, flags)); 977 | meso_tgn2[1]=pavgm[8]*pma[9][0]*(1.0+flags.sw[20]*flags.sw[22]*glob7s(pma[9], Input, flags))*meso_tn2[3]*meso_tn2[3]/(pow((pma[2][0]*pavgm[2]),2.0)); 978 | meso_tn3[0]=meso_tn2[3]; 979 | 980 | if (Input.altzmix): 997 | dmc = 1.0 - (zn2[0]-Input.alt)/(zn2[0] - zmix); 998 | dz28=soutput.d[2]; 999 | 1000 | #/**** N2 density ****/ 1001 | dmr=soutput.d[2] / dm28m - 1.0; 1002 | tz = [0.0] 1003 | output.d[2]=densm(Input.alt,dm28m,xmm, tz, mn3, zn3, meso_tn3, meso_tgn3, mn2, zn2, meso_tn2, meso_tgn2); 1004 | output.d[2]=output.d[2] * (1.0 + dmr*dmc); 1005 | 1006 | #/**** HE density ****/ 1007 | dmr = soutput.d[0] / (dz28 * pdm[0][1]) - 1.0; 1008 | output.d[0] = output.d[2] * pdm[0][1] * (1.0 + dmr*dmc); 1009 | 1010 | #/**** O density ****/ 1011 | output.d[1] = 0; 1012 | output.d[8] = 0; 1013 | 1014 | #/**** O2 density ****/ 1015 | dmr = soutput.d[3] / (dz28 * pdm[3][1]) - 1.0; 1016 | output.d[3] = output.d[2] * pdm[3][1] * (1.0 + dmr*dmc); 1017 | 1018 | #/**** AR density ***/ 1019 | dmr = soutput.d[4] / (dz28 * pdm[4][1]) - 1.0; 1020 | output.d[4] = output.d[2] * pdm[4][1] * (1.0 + dmr*dmc); 1021 | 1022 | #/**** Hydrogen density ****/ 1023 | output.d[6] = 0; 1024 | 1025 | #/**** Atomic nitrogen density ****/ 1026 | output.d[7] = 0; 1027 | 1028 | #/**** Total mass density */ 1029 | output.d[5] = 1.66E-24 * (4.0 * output.d[0] + 16.0 * output.d[1] + 28.0 * output.d[2] + 32.0 * output.d[3] + 40.0 * output.d[4] + output.d[6] + 14.0 * output.d[7]); 1030 | 1031 | if (flags.sw[0]): 1032 | output.d[5]=output.d[5]/1000; 1033 | 1034 | #/**** temperature at altitude ****/ 1035 | global dd 1036 | dd = densm(Input.alt, 1.0, 0, tz, mn3, zn3, meso_tn3, meso_tgn3, mn2, zn2, meso_tn2, meso_tgn2); 1037 | output.t[1]=tz[0]; 1038 | return 1039 | 1040 | 1041 | ''' 1042 | /* ------------------------------------------------------------------- */ 1043 | /* ------------------------------- GTD7D ----------------------------- */ 1044 | /* ------------------------------------------------------------------- */ 1045 | ''' 1046 | def gtd7d(Input, flags, output): 1047 | gtd7(Input, flags, output) 1048 | output.d[5] = 1.66E-24 * (4.0 * output.d[0] + 16.0 * output.d[1] + 28.0 * output.d[2] + 32.0 * output.d[3] + 40.0 * output.d[4] + output.d[6] + 14.0 * output.d[7] + 16.0 * output.d[8]); 1049 | if (flags.sw[0]): 1050 | output.d[5]=output.d[5]/1000; 1051 | return 1052 | 1053 | 1054 | ''' 1055 | /* ------------------------------------------------------------------- */ 1056 | /* -------------------------------- GHP7 ----------------------------- */ 1057 | /* ------------------------------------------------------------------- */ 1058 | ''' 1059 | def ghp7(Input, flags, output, press): 1060 | bm = 1.3806E-19; 1061 | rgas = 831.4; 1062 | #rgas = 831.44621 #maybe make this a global constant? 1063 | test = 0.00043; 1064 | ltest = 12; 1065 | 1066 | pl = log10(press) 1067 | 1068 | if (pl >= -5.0): 1069 | if (pl>2.5): 1070 | zi = 18.06 * (3.00 - pl); 1071 | elif ((pl>0.075) and (pl<=2.5)): 1072 | zi = 14.98 * (3.08 - pl); 1073 | elif ((pl>-1) and (pl<=0.075)): 1074 | zi = 17.80 * (2.72 - pl); 1075 | elif ((pl>-2) and (pl<=-1)): 1076 | zi = 14.28 * (3.64 - pl); 1077 | elif ((pl>-4) and (pl<=-2)): 1078 | zi = 12.72 * (4.32 -pl); 1079 | elif (pl<=-4): 1080 | zi = 25.3 * (0.11 - pl); 1081 | cl = Input.g_lat/90.0; 1082 | cl2 = cl*cl; 1083 | if (Input.doy<182): 1084 | cd = (1.0 - float(Input.doy)) / 91.25; 1085 | else: 1086 | cd = (float(Input.doy)) / 91.25 - 3.0; 1087 | ca = 0; 1088 | if ((pl > -1.11) and (pl<=-0.23)): 1089 | ca = 1.0; 1090 | if (pl > -0.23): 1091 | ca = (2.79 - pl) / (2.79 + 0.23); 1092 | if ((pl <= -1.11) and (pl>-3)): 1093 | ca = (-2.93 - pl)/(-2.93 + 1.11); 1094 | z = zi - 4.87 * cl * cd * ca - 1.64 * cl2 * ca + 0.31 * ca * cl; 1095 | else: 1096 | z = 22.0 * pow((pl + 4.0),2.0) + 110.0; 1097 | 1098 | #/* iteration loop */ 1099 | l = 0; 1100 | while(True): 1101 | l += 1; 1102 | Input.alt = z; 1103 | gtd7(Input, flags, output); 1104 | z = Input.alt; 1105 | xn = output.d[0] + output.d[1] + output.d[2] + output.d[3] + output.d[4] + output.d[6] + output.d[7]; 1106 | p = bm * xn * output.t[1]; 1107 | if (flags.sw[0]): 1108 | p = p*1.0E-6; 1109 | diff = pl - log10(p); 1110 | if (sqrt(diff*diff) 72.5 km! 1140 | */ 1141 | ''' 1142 | zn1 = [120.0, 110.0, 100.0, 90.0, 72.5] 1143 | mn1 = 5 1144 | dgtr=1.74533E-2; 1145 | dr=1.72142E-2; 1146 | alpha = [-0.38, 0.0, 0.0, 0.0, 0.17, 0.0, -0.38, 0.0, 0.0] 1147 | altl = [200.0, 300.0, 160.0, 250.0, 240.0, 450.0, 320.0, 450.0] 1148 | za = pdl[1][15]; 1149 | zn1[0] = za; 1150 | 1151 | for j in range(9): 1152 | output.d[j]=0; 1153 | 1154 | #/* TINF VARIATIONS NOT IMPORTANT BELOW ZA OR ZN1(1) */ 1155 | if (Input.alt>zn1[0]): 1156 | tinf = ptm[0]*pt[0] * \ 1157 | (1.0+flags.sw[16]*globe7(pt,Input,flags)); 1158 | else: 1159 | tinf = ptm[0]*pt[0]; 1160 | output.t[0]=tinf; 1161 | 1162 | #/* GRADIENT VARIATIONS NOT IMPORTANT BELOW ZN1(5) */ 1163 | if (Input.alt>zn1[4]): 1164 | g0 = ptm[3]*ps[0] * \ 1165 | (1.0+flags.sw[19]*globe7(ps,Input,flags)); 1166 | else: 1167 | g0 = ptm[3]*ps[0]; 1168 | tlb = ptm[1] * (1.0 + flags.sw[17]*globe7(pd[3],Input,flags))*pd[3][0]; 1169 | s = g0 / (tinf - tlb); 1170 | 1171 | #/* Lower thermosphere temp variations not significant for 1172 | # * density above 300 km */ 1173 | if (Input.alt<300.0): 1174 | meso_tn1[1]=ptm[6]*ptl[0][0]/(1.0-flags.sw[18]*glob7s(ptl[0], Input, flags)); 1175 | meso_tn1[2]=ptm[2]*ptl[1][0]/(1.0-flags.sw[18]*glob7s(ptl[1], Input, flags)); 1176 | meso_tn1[3]=ptm[7]*ptl[2][0]/(1.0-flags.sw[18]*glob7s(ptl[2], Input, flags)); 1177 | meso_tn1[4]=ptm[4]*ptl[3][0]/(1.0-flags.sw[18]*flags.sw[20]*glob7s(ptl[3], Input, flags)); 1178 | meso_tgn1[1]=ptm[8]*pma[8][0]*(1.0+flags.sw[18]*flags.sw[20]*glob7s(pma[8], Input, flags))*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); 1179 | else: 1180 | meso_tn1[1]=ptm[6]*ptl[0][0]; 1181 | meso_tn1[2]=ptm[2]*ptl[1][0]; 1182 | meso_tn1[3]=ptm[7]*ptl[2][0]; 1183 | meso_tn1[4]=ptm[4]*ptl[3][0]; 1184 | meso_tgn1[1]=ptm[8]*pma[8][0]*meso_tn1[4]*meso_tn1[4]/(pow((ptm[4]*ptl[3][0]),2.0)); 1185 | 1186 | 1187 | z0 = zn1[3]; 1188 | t0 = meso_tn1[3]; 1189 | tr12 = 1.0; 1190 | 1191 | #/* N2 variation factor at Zlb */ 1192 | g28=flags.sw[21]*globe7(pd[2], Input, flags); 1193 | 1194 | #/* VARIATION OF TURBOPAUSE HEIGHT */ 1195 | zhf=pdl[1][24]*(1.0+flags.sw[5]*pdl[0][24]*sin(dgtr*Input.g_lat)*cos(dr*(Input.doy-pt[13]))); 1196 | output.t[0]=tinf; 1197 | xmm = pdm[2][4]; 1198 | z = Input.alt; 1199 | 1200 | 1201 | #/**** N2 DENSITY ****/ 1202 | 1203 | #/* Diffusive density at Zlb */ 1204 | db28 = pdm[2][0]*exp(g28)*pd[2][0]; 1205 | #/* Diffusive density at Alt */ 1206 | RandomVariable = [output.t[1]] 1207 | output.d[2]=densu(z,db28,tinf,tlb,28.0,alpha[2],RandomVariable,ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); 1208 | output.t[1] = RandomVariable[0] 1209 | dd=output.d[2]; 1210 | #/* Turbopause */ 1211 | zh28=pdm[2][2]*zhf; 1212 | zhm28=pdm[2][3]*pdl[1][5]; 1213 | xmd=28.0-xmm; 1214 | #/* Mixed density at Zlb */ 1215 | tz = [0] 1216 | b28=densu(zh28,db28,tinf,tlb,xmd,(alpha[2]-1.0),tz,ptm[5],s,mn1, zn1,meso_tn1,meso_tgn1); 1217 | if ((flags.sw[15]) and (z<=altl[2])): 1218 | #/* Mixed density at Alt */ 1219 | global dm28 1220 | dm28=densu(z,b28,tinf,tlb,xmm,alpha[2],tz,ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); 1221 | #/* Net density at Alt */ 1222 | output.d[2]=dnet(output.d[2],dm28,zhm28,xmm,28.0); 1223 | 1224 | 1225 | 1226 | #/**** HE DENSITY ****/ 1227 | 1228 | #/* Density variation factor at Zlb */ 1229 | g4 = flags.sw[21]*globe7(pd[0], Input, flags); 1230 | #/* Diffusive density at Zlb */ 1231 | db04 = pdm[0][0]*exp(g4)*pd[0][0]; 1232 | #/* Diffusive density at Alt */ 1233 | RandomVariable = [output.t[1]] 1234 | output.d[0]=densu(z,db04,tinf,tlb, 4.,alpha[0],RandomVariable,ptm[5],s,mn1,zn1,meso_tn1,meso_tgn1); 1235 | output.t[1] = RandomVariable[0] 1236 | dd=output.d[0]; 1237 | if ((flags.sw[15]) and (z