├── src └── msise00 │ ├── tests │ ├── __init__.py │ ├── ref1.nc │ ├── ref2.nc │ ├── ref3.nc │ ├── ref4.nc │ ├── ref5.nc │ ├── ref6.nc │ ├── msis_matlab.png │ ├── msise00_demo.gif │ ├── ccmc.log │ ├── test_grid.py │ ├── test_time_grid.py │ ├── test_module.py │ ├── test_point.py │ └── test_ccmc.py │ ├── __init__.py │ ├── worldgrid.py │ ├── CMakeLists.txt │ ├── timeutils.py │ ├── fortran │ ├── msise00_driver.f90 │ ├── msise00_data.f │ └── msise00_sub.f │ ├── __main__.py │ ├── base.py │ └── plots.py ├── MANIFEST.in ├── +msise00 ├── python-matlab │ ├── xarray2mat.m │ ├── msise00.m │ ├── xarrayind2vector.m │ └── plotmsis.m ├── private │ ├── fix_macos.m │ └── cmake.m ├── plottime.m ├── plotalt.m ├── msise00.m └── TestUnit.m ├── CMakeLists.txt ├── .flake8 ├── reference ├── test77gtd7.f ├── Makefile ├── physics_constants.f90 ├── utils_spline.f90 ├── nrlmsise00_driver.for ├── nrlmsise00_driver_ORIGINAL.for ├── testgtd7.f90 └── utils_constants.f90 ├── .editorconfig ├── Examples ├── AltitudeProfile.m ├── AltitudeProfile.py ├── Worldgrid.py ├── TimeProfile.py ├── TimeProfile.m └── suntest.py ├── .github └── workflows │ ├── publish-python-package.yml │ ├── ci.yml │ └── ci-matlab.yml ├── LICENSE.txt ├── pyproject.toml ├── .gitignore ├── .archive ├── msise00.m ├── f2py.py └── azure-pipelines.yml └── README.md /src/msise00/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # this file makes importlib.resources work 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft src/msise00/fortran 2 | include src/msise00/CMakeLists.txt 3 | -------------------------------------------------------------------------------- /src/msise00/tests/ref1.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/ref1.nc -------------------------------------------------------------------------------- /src/msise00/tests/ref2.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/ref2.nc -------------------------------------------------------------------------------- /src/msise00/tests/ref3.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/ref3.nc -------------------------------------------------------------------------------- /src/msise00/tests/ref4.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/ref4.nc -------------------------------------------------------------------------------- /src/msise00/tests/ref5.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/ref5.nc -------------------------------------------------------------------------------- /src/msise00/tests/ref6.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/ref6.nc -------------------------------------------------------------------------------- /+msise00/python-matlab/xarray2mat.m: -------------------------------------------------------------------------------- 1 | function M = xarray2mat(V) 2 | M = double(py.numpy.asfortranarray(V)); 3 | end -------------------------------------------------------------------------------- /src/msise00/tests/msis_matlab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/msis_matlab.png -------------------------------------------------------------------------------- /src/msise00/tests/msise00_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/space-physics/msise00/HEAD/src/msise00/tests/msise00_demo.gif -------------------------------------------------------------------------------- /src/msise00/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import run, rungtd1d 2 | from .timeutils import todatetime, todt64 3 | 4 | __version__ = "1.11.1" 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14...3.21) 2 | 3 | project(msise00 LANGUAGES Fortran) 4 | 5 | include(CTest) 6 | 7 | add_subdirectory(src/msise00) 8 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 132 3 | exclude = .git,__pycache__,.eggs/,doc/,docs/,build/,dist/,archive/,.archive/ 4 | per-file-ignores = 5 | __init__.py:F401 6 | -------------------------------------------------------------------------------- /reference/test77gtd7.f: -------------------------------------------------------------------------------- 1 | program test77gtd7 2 | implicit none 3 | 4 | 5 | real D(9), T(2) 6 | 7 | call GTD7(172,29000.,400.,60.,-70.,16.,150.,150.,4.,48,D,T) 8 | 9 | 10 | write (*,*) D,T 11 | stop 12 | end 13 | -------------------------------------------------------------------------------- /src/msise00/worldgrid.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import numpy as np 4 | 5 | 6 | def latlonworldgrid(latstep: float | int = 5, lonstep: float | int = 5) -> tuple: 7 | lat = np.arange(-90.0, 90 + latstep, latstep) 8 | lon = np.arange(-180.0, 180 + lonstep, lonstep) 9 | glon, glat = np.meshgrid(lon, lat) 10 | 11 | return glat, glon 12 | -------------------------------------------------------------------------------- /+msise00/python-matlab/msise00.m: -------------------------------------------------------------------------------- 1 | %% MSISE00 call MSISE-00 model 2 | % https://www.scivision.dev/matlab-python-user-module-import/ 3 | 4 | function atmos = msise00(time, alt_km, glat, glon) 5 | arguments 6 | time (1,1) datetime 7 | alt_km (1,:) {mustBePositive} 8 | glat (1,1) 9 | glon (1,1) 10 | end 11 | 12 | atmos = py.msise00.run(time, alt_km, glat, glon); 13 | 14 | end 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 2 9 | 10 | # Matches multiple files with brace expansion notation 11 | # Set default charset 12 | [*.{js,py}] 13 | charset = utf-8 14 | 15 | [*.py] 16 | indent_style = space 17 | indent_size = 4 18 | 19 | [Makefile] 20 | indent_style = tab 21 | -------------------------------------------------------------------------------- /Examples/AltitudeProfile.m: -------------------------------------------------------------------------------- 1 | % geographic WGS84 lat,lon,alt 2 | glat = 65.1; 3 | glon = -147.5; 4 | 5 | gi = struct; 6 | gi.f107s = 150; 7 | gi.f107 = 150; 8 | gi.Ap = 4; 9 | 10 | alt_km = 50:20:1000; 11 | time = datetime(2015,12,13,10,0,0); 12 | 13 | cwd = fileparts(mfilename('fullpath')); 14 | addpath(fullfile(cwd, '..')); 15 | 16 | for i = 1:length(alt_km) 17 | atmos(i) = msise00.msise00(time, glat, glon, gi, alt_km(i)); %#ok 18 | end 19 | 20 | msise00.plotalt(atmos, time, glat, glon); 21 | -------------------------------------------------------------------------------- /Examples/AltitudeProfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Example: 4 | Poker Flat Research Range altitude profile 5 | """ 6 | import numpy as np 7 | from datetime import datetime 8 | from matplotlib.pyplot import show 9 | 10 | import msise00.plots as msplots 11 | import msise00 12 | 13 | glat = 65.1 14 | glon = -147.5 15 | alt_km = np.arange(50, 1000, 20.0) 16 | time = datetime(2015, 12, 13, 10, 0, 0) 17 | 18 | atmos = msise00.run(time, alt_km, glat, glon) 19 | 20 | msplots.plotgtd(atmos) 21 | 22 | show() 23 | -------------------------------------------------------------------------------- /Examples/Worldgrid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Example: 4 | 5 | lat / lon grid at altitude example 6 | """ 7 | from datetime import datetime 8 | from matplotlib.pyplot import show 9 | 10 | import msise00.plots as msplots 11 | import msise00 12 | from msise00.worldgrid import latlonworldgrid 13 | 14 | glat, glon = latlonworldgrid(10.0, 20.0) 15 | alt_km = 200.0 16 | time = datetime(2015, 12, 13, 10, 0, 0) 17 | 18 | atmos = msise00.run(time, alt_km, glat, glon) 19 | 20 | msplots.plotgtd(atmos) 21 | 22 | show() 23 | -------------------------------------------------------------------------------- /Examples/TimeProfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Time profile example 4 | """ 5 | import numpy as np 6 | from datetime import datetime, timedelta 7 | from matplotlib.pyplot import show 8 | 9 | import msise00.plots as msplots 10 | import msise00 11 | 12 | glat = 65.1 13 | glon = -147.5 14 | alt_km = 200 15 | t0 = datetime(2015, 12, 13, 10, 0, 0) 16 | t1 = datetime(2015, 12, 14, 10, 0, 0) 17 | 18 | times = np.arange(t0, t1, timedelta(hours=1)) 19 | 20 | atmos = msise00.run(times, alt_km, glat, glon) 21 | 22 | msplots.plotgtd(atmos) 23 | 24 | show() 25 | -------------------------------------------------------------------------------- /+msise00/python-matlab/xarrayind2vector.m: -------------------------------------------------------------------------------- 1 | function I = xarrayind2vector(V, key) 2 | 3 | C = cell(V.indexes{key}.values.tolist); % might be numeric or cell array of strings 4 | 5 | if iscellstr(C) || (length(C) > 1 && isa(C{1}, 'py.str')) 6 | I = cellfun(@char, C, 'uniformoutput', false); 7 | elseif isa(C{1}, 'py.datetime.datetime') 8 | I = char(C{1}.isoformat()); 9 | elseif isa(C{1}, 'py.int') && C{1} > 1e12 10 | C = cellfun(@double,C)/1e9; 11 | I = datetime(C, 'convertfrom','posixtime'); 12 | else 13 | I = cell2mat(C); 14 | end % if 15 | 16 | end % function 17 | -------------------------------------------------------------------------------- /Examples/TimeProfile.m: -------------------------------------------------------------------------------- 1 | % geographic WGS84 lat,lon,alt 2 | function TimeProfile() 3 | 4 | glat = 65.1; 5 | glon = -147.5; 6 | 7 | gi = struct; 8 | gi.f107s = 150; 9 | gi.f107 = 150; 10 | gi.Ap = 4; 11 | 12 | alt_km = 200; 13 | t0 = datetime(2015, 12, 13, 10, 1, 2); 14 | t1 = datetime(2015, 12, 14, 10, 3, 4); 15 | 16 | cwd = fileparts(mfilename('fullpath')); 17 | addpath(fullfile(cwd, '..')); 18 | 19 | time = t0:seconds(3600):t1; 20 | 21 | for i = 1:length(time) 22 | atmos(i) = msise00.msise00(time(i), glat, glon, gi, alt_km); %#ok 23 | end 24 | 25 | msise00.plottime(atmos, time, glat, glon); 26 | 27 | end -------------------------------------------------------------------------------- /+msise00/private/fix_macos.m: -------------------------------------------------------------------------------- 1 | %% MacOS PATH workaround 2 | % Matlab does not seem to load .zshrc or otherwise pickup shell "export" like 3 | % Matlab on Linux or Windows does, so we apply these MacOS-specific workaround 4 | 5 | function fix_macos() 6 | 7 | if ~ismac 8 | return 9 | end 10 | 11 | sys_path = getenv("PATH"); 12 | needed_paths = ["/opt/homebrew/bin", "/usr/local/bin"]; 13 | for np = needed_paths 14 | if isfolder(np) 15 | if contains(sys_path, np) 16 | return 17 | else 18 | sys_path = np + pathsep + sys_path; 19 | break 20 | end 21 | end 22 | end 23 | 24 | setenv('PATH', sys_path) 25 | 26 | end -------------------------------------------------------------------------------- /+msise00/private/cmake.m: -------------------------------------------------------------------------------- 1 | function cmake(src_dir) 2 | % build program using CMake 3 | arguments 4 | src_dir (1,1) string 5 | end 6 | 7 | assert(isfolder(src_dir), "source directory not found: %s", src_dir) 8 | 9 | build_dir = fullfile(src_dir, "build"); 10 | 11 | fix_macos() 12 | 13 | assert(system("cmake --version") == 0, 'CMake not found') 14 | 15 | cmd = "cmake -B" + build_dir + " -S" + src_dir; 16 | if ispc && ~isenv("CMAKE_GENERATOR") 17 | cmd = cmd + ' -G "MinGW Makefiles"'; 18 | end 19 | 20 | assert(system(cmd) == 0, 'error building with CMake') 21 | 22 | cmd = "cmake --build " + build_dir; 23 | assert(system(cmd) == 0, 'error building with CMake') 24 | 25 | end 26 | -------------------------------------------------------------------------------- /.github/workflows/publish-python-package.yml: -------------------------------------------------------------------------------- 1 | # https://docs.pypi.org/trusted-publishers/using-a-publisher/ 2 | 3 | name: publish 4 | 5 | on: 6 | release: 7 | types: [published] 8 | 9 | jobs: 10 | release: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | environment: release 15 | 16 | permissions: 17 | id-token: write 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: Set up Python 23 | uses: actions/setup-python@v5 24 | with: 25 | python-version: '3.x' 26 | 27 | - name: Install builder 28 | run: pip install build 29 | 30 | - name: Build package 31 | run: python -m build 32 | 33 | - name: Publish package 34 | uses: pypa/gh-action-pypi-publish@release/v1 35 | -------------------------------------------------------------------------------- /reference/Makefile: -------------------------------------------------------------------------------- 1 | FC = gfortran 2 | FCFLAGS = -O3 -mtune=native -pedantic -Wall 3 | 4 | all: libnrlmsis.a testgtd7 5 | 6 | clean: 7 | $(RM) libnrlmsis.a $(LIBOBJS) 8 | 9 | LIBOBJS = physics_constants.o utils_spline.o physics_msis.o utils_constants.o 10 | 11 | %.o: %.f90 12 | $(FC) $(FCFLAGS) -c $< 13 | 14 | %.o: %.F90 15 | $(FC) $(CPPFLAGS) $(FCFLAGS) -c $< 16 | 17 | libnrlmsis.a: $(LIBOBJS) 18 | $(AR) $(ARFLAGS) $@ $(LIBOBJS) 19 | 20 | testgtd7: testgtd7.f90 libnrlmsis.a 21 | $(FC) $(FCFLAGS) $(LDFLAGS) -o $@ $< libnrlmsis.a 22 | 23 | utils_constants.o: utils_constants.f90 24 | physics_constants.o: physics_constants.f90 utils_constants.o 25 | utils_spline.o: utils_spline.f90 utils_constants.o 26 | physics_msis.o: physics_msis.f90 physics_constants.o physics_msis.o utils_constants.o 27 | -------------------------------------------------------------------------------- /+msise00/python-matlab/plotmsis.m: -------------------------------------------------------------------------------- 1 | function plotmsis(atmos) 2 | arguments 3 | atmos struct 4 | end 5 | 6 | species = cellfun(@char, cell(atmos.attrs{'species'}), 'uniformoutput', false); 7 | alt_km = xarrayind2vector(atmos, 'alt_km'); 8 | times = xarrayind2vector(atmos, 'time'); 9 | glat = xarrayind2vector(atmos, 'lat'); 10 | glon = xarrayind2vector(atmos, 'lon'); 11 | 12 | figure 13 | ax = axes('nextplot','add'); 14 | 15 | for i = 1:length(species) 16 | dens = xarray2mat(atmos{species{i}}); 17 | semilogx(ax, dens, alt_km, 'DisplayName', species{i}) 18 | end 19 | 20 | 21 | title(ax, {[times,' (',num2str(glat),', ', num2str(glon),')']}) 22 | xlabel(ax,'Density [m^-3]') 23 | ylabel(ax,'altitude [km]') 24 | 25 | set(ax,'xscale','log') 26 | xlim(ax,[1e6,1e20]) 27 | grid(ax,'on') 28 | legend('show') 29 | 30 | end 31 | -------------------------------------------------------------------------------- /+msise00/plottime.m: -------------------------------------------------------------------------------- 1 | function fig = plottime(atmos, times, glat, glon) 2 | arguments 3 | atmos struct 4 | times datetime 5 | glat (1,1) double 6 | glon (1,1) double 7 | end 8 | 9 | fig = figure(1); 10 | clf(fig) 11 | t = tiledlayout(fig, 2, 1); 12 | ax1 = nexttile(t); 13 | set(ax1, nextplot='add') 14 | 15 | semilogy(ax1, times, [atmos.nN2], DisplayName='N_{N_2}') 16 | semilogy(ax1, times, [atmos.nO2], DisplayName='N_{O_2}') 17 | 18 | title(ax1, string(times(1)) + " (" + string(glat) + "," + string(glon) + ")") 19 | ylabel(ax1, 'm^{-3}') 20 | 21 | legend(ax1,'show',location='southwest') 22 | 23 | %% smaller quantities 24 | ax = nexttile(t); 25 | set(ax, nextplot='add') 26 | semilogy(ax,times, [atmos.nAr], DisplayName='N_{Ar}') 27 | 28 | ylabel(ax, 'm^{-3}') 29 | xlabel(ax, 'time [UTC]') 30 | 31 | legend(ax,'show') 32 | end 33 | -------------------------------------------------------------------------------- /src/msise00/tests/ccmc.log: -------------------------------------------------------------------------------- 1 | NRLMSISE-00 model listing 2 | Input parameters 3 | year= 2001, month= 2, day= 2, hour= 8.06, 4 | Time_type = Universal 5 | Coordinate_type = Geographic 6 | latitude= 60.00, longitude= 290.00, height= 400.00 7 | Prof. parameters: start= 400.00 stop= 400.00 step= 50.00 8 | 9 | Optional parameters: F10.7(daily) =146.7; F10.7(3-month avg) =163.6666; ap(daily) = 7. 10 | 11 | Selected parameters are: 12 | 1 Height, km 13 | 2 O, cm-3 14 | 3 N2, cm-3 15 | 4 O2, cm-3 16 | 5 Mass_density, g/cm-3 17 | 6 Temperature_neutral, K 18 | 7 Temperature_exospheric, K 19 | 8 He, cm-3 20 | 9 Ar, cm-3 21 | 10 H, cm-3 22 | 11 N, cm-3 23 | 12 Anomalous_Oxygen, cm-3 24 | 25 | 1 2 3 4 5 6 7 8 9 10 11 12 26 | 400.0 9.118E+07 3.655E+06 8.660E+04 2.652E-15 917.8 918 6.763E+06 1.820E+02 1.126E+05 4.480E+05 3.263E+03 27 | -------------------------------------------------------------------------------- /src/msise00/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | 3 | project(msise00 LANGUAGES Fortran) 4 | 5 | enable_testing() 6 | 7 | add_library(msise00 OBJECT fortran/msise00_sub.f fortran/msise00_data.f) 8 | target_compile_options(msise00 PRIVATE $<$:-std=legacy>) 9 | set_target_properties(msise00 PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include) 10 | target_include_directories(msise00 INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/include) 11 | 12 | add_executable(msise00_driver fortran/msise00_driver.f90) 13 | set_target_properties(msise00_driver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}) 14 | target_link_libraries(msise00_driver PRIVATE msise00) 15 | 16 | install(TARGETS msise00_driver TYPE RUNTIME) 17 | 18 | add_test(NAME MSISdriver 19 | COMMAND $ 30 12 1 2 65 0 100 100 4 100) 20 | set_tests_properties(MSISdriver PROPERTIES 21 | TIMEOUT 15 22 | PASS_REGULAR_EXPRESSION "1027.3.*187.8") 23 | -------------------------------------------------------------------------------- /src/msise00/timeutils.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dateutil.parser import parse 4 | import numpy as np 5 | from datetime import datetime, date 6 | 7 | 8 | def todt64(time: str | datetime): 9 | dtime = np.atleast_1d(todatetime(time)) # type: ignore 10 | 11 | if dtime.size == 1: 12 | dtime = np.atleast_1d(np.datetime64(dtime[0], dtype="datetime64[us]")) # type: ignore 13 | # mypy bug 14 | elif dtime.size == 2: 15 | dtime = np.arange(dtime[0], dtime[1], dtype="datetime64[h]") 16 | else: 17 | pass 18 | 19 | return dtime 20 | 21 | 22 | def todatetime(time: str | datetime) -> datetime: 23 | 24 | if isinstance(time, str): 25 | dtime: datetime = parse(time) 26 | elif isinstance(time, datetime): 27 | dtime = time 28 | elif isinstance(time, np.datetime64): 29 | dtime = time.astype(datetime) 30 | else: 31 | raise TypeError(f"{type(time)} not allowed") 32 | 33 | if not isinstance(dtime, datetime) and isinstance(dtime, date): 34 | dtime = datetime.combine(dtime, datetime.min.time()) 35 | 36 | return dtime 37 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2025 SciVision, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Examples/suntest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | understanding sun apparent position over Earth in geodetic lat,lon 4 | """ 5 | from astropy.time import Time 6 | from astropy.coordinates import get_sun, AltAz, EarthLocation 7 | import astropy.units as u 8 | import numpy as np 9 | from matplotlib.pyplot import figure, show 10 | from pymap3d import aer2geodetic 11 | 12 | obslla = (0, 0, 0) 13 | 14 | midnight = Time("2015-01-01T00:00") 15 | delta_midnight = np.linspace(0, 365, 1000) * u.day 16 | time = midnight + delta_midnight 17 | 18 | obs = EarthLocation(lat=obslla[0], lon=obslla[1], height=obslla[2]) 19 | sun = get_sun(time=time) 20 | aaf = AltAz(obstime=time, location=obs) 21 | sloc = sun.transform_to(aaf) 22 | # %% 23 | time = time.to_datetime() 24 | 25 | fg = figure() 26 | ax = fg.subplots(2, 1, sharex=True) 27 | ax[0].plot(time, sloc.alt) 28 | ax[0].set_title("sun elevation") 29 | ax[0].set_ylabel("elevation [deg]") 30 | 31 | ax[1].plot(time, sloc.az) 32 | ax[1].set_title("sun azimuth") 33 | ax[1].set_ylabel("azimuth [deg]") 34 | ax[1].set_xlabel("time") 35 | 36 | fg.suptitle(f"sun over 1 year @ lat,lon,alt: {obslla}") 37 | 38 | # %% 39 | 40 | lat, lon, alt = aer2geodetic(sloc.az.value, sloc.alt.value, sloc.distance.value, *obslla) 41 | 42 | ax = figure().gca() 43 | ax.plot(time, lat) 44 | ax.set_title("subsolar latitude vs. time") 45 | ax.set_ylabel("latitude [deg]") 46 | ax.set_xlabel("time") 47 | 48 | show() 49 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.0.0", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "msise00" 7 | description = "Python API for Fortran MSISE-00 neutral atmosphere model." 8 | keywords = ["atmosphere", "geospace"] 9 | classifiers = [ 10 | "Development Status :: 5 - Production/Stable", 11 | "Environment :: Console", 12 | "Intended Audience :: Science/Research", 13 | "Operating System :: OS Independent", 14 | "Programming Language :: Fortran", 15 | "Programming Language :: Python :: 3", 16 | "Topic :: Scientific/Engineering :: Atmospheric Science" 17 | ] 18 | dependencies = ["python-dateutil", "numpy", "xarray", "geomagindices>=1.4.0"] 19 | dynamic = ["readme", "version"] 20 | requires-python = ">=3.9" 21 | 22 | [tool.setuptools.dynamic] 23 | readme = {file = ["README.md"], content-type = "text/markdown"} 24 | version = {attr = "msise00.__version__"} 25 | 26 | [project.optional-dependencies] 27 | tests = ["pytest", "netCDF4"] 28 | lint = [ 29 | "flake8", 30 | "flake8-bugbear", 31 | "flake8-builtins", 32 | "flake8-blind-except", 33 | "mypy", 34 | "types-python-dateutil" 35 | ] 36 | plot = [ 37 | "matplotlib", 38 | "astropy", 39 | "pymap3d" 40 | ] 41 | 42 | 43 | [tool.black] 44 | line-length = 100 45 | 46 | [tool.mypy] 47 | files = ["src/"] 48 | 49 | ignore_missing_imports = true 50 | allow_redefinition = true 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | msise00_driver 2 | 3 | *.m~ 4 | *.svg 5 | bin/ 6 | .mypy_cache/ 7 | .pytest_cache/ 8 | 9 | *.nc 10 | # Byte-compiled / optimized / DLL files 11 | __pycache__/ 12 | *.py[cod] 13 | 14 | # C extensions 15 | *.so 16 | 17 | # Distribution / packaging 18 | .Python 19 | env/ 20 | build/ 21 | develop-eggs/ 22 | dist/ 23 | downloads/ 24 | eggs/ 25 | .eggs/ 26 | lib/ 27 | lib64/ 28 | parts/ 29 | sdist/ 30 | var/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *,cover 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | 62 | # Sphinx documentation 63 | docs/_build/ 64 | 65 | # PyBuilder 66 | target/ 67 | 68 | # Compiled Object files 69 | *.slo 70 | *.lo 71 | *.o 72 | *.obj 73 | 74 | # Precompiled Headers 75 | *.gch 76 | *.pch 77 | 78 | # Compiled Dynamic libraries 79 | *.so 80 | *.dylib 81 | *.dll 82 | 83 | # Fortran module files 84 | *.mod 85 | 86 | # Compiled Static libraries 87 | *.lai 88 | *.la 89 | *.a 90 | *.lib 91 | 92 | # Executables 93 | *.exe 94 | *.out 95 | *.app 96 | -------------------------------------------------------------------------------- /+msise00/plotalt.m: -------------------------------------------------------------------------------- 1 | function hp = plotalt(atmos, times, glat, glon) 2 | arguments 3 | atmos struct 4 | times datetime 5 | glat (1,1) double 6 | glon (1,1) double 7 | end 8 | %% Density profiles 9 | hp = figure; 10 | sgtitle(hp, {string(times) + " deg. (" + string(glat) + ", " + string(glon) + ")"}) 11 | t = tiledlayout(hp, 1,2); 12 | ax = nexttile(t); 13 | set(ax, 'nextplot','add') 14 | 15 | altkm = [atmos.altkm]; 16 | 17 | semilogx(ax, [atmos.nHe], altkm, Displayname='N_{He}') 18 | semilogx(ax, [atmos.nO], altkm, Displayname='N_{O^+}') 19 | semilogx(ax, [atmos.nN2], altkm, Displayname='N_{N_2}') 20 | semilogx(ax, [atmos.nO2], altkm, Displayname='N_{O_2}') 21 | semilogx(ax, [atmos.nAr], altkm, Displayname='N_{Ar}') 22 | semilogx(ax, [atmos.nTotal], altkm, Displayname='N_{Total}') 23 | semilogx(ax, [atmos.nH], altkm, Displayname='N_H') 24 | semilogx(ax, [atmos.nN], altkm, Displayname='N_N') 25 | 26 | title(ax, 'Number Densities') 27 | xlabel(ax, 'Density [m^-3]') 28 | ylabel(ax, 'altitude [km]') 29 | xlim(ax, [1,1e17]) 30 | 31 | set(ax,'xscale','log') 32 | grid(ax, 'on') 33 | legend(ax, 'show',location='northeast') 34 | 35 | %% Temperature Profiles 36 | 37 | ax = nexttile(t); 38 | set(ax, 'nextplot','add') 39 | 40 | plot(ax, [atmos.Tn], altkm, Displayname='T_n') 41 | plot(ax, [atmos.Texo], altkm, Displayname='T_{exo}') 42 | 43 | title(ax, 'Temperature') 44 | xlabel(ax, 'Temperature [K]') 45 | ylabel(ax, 'altitude [km]') 46 | 47 | grid(ax, 'on') 48 | legend(ax, 'show',location='northwest') 49 | 50 | end 51 | -------------------------------------------------------------------------------- /+msise00/msise00.m: -------------------------------------------------------------------------------- 1 | function atmos = msise00(time, glat, glon, indices, altkm) 2 | %% run MSISe00 3 | arguments 4 | time (1,1) datetime 5 | glat (1,1) {mustBeNumeric,mustBeFinite} 6 | glon (1,1) {mustBeNumeric,mustBeFinite} 7 | indices (1,1) struct 8 | altkm (1,1) {mustBeNumeric,mustBeFinite,mustBeNonnegative} 9 | end 10 | %% binary MSISe00 11 | cwd = fileparts(mfilename('fullpath')); 12 | src_dir = fullfile(cwd, "../src/msise00"); 13 | 14 | exe = fullfile(src_dir, "msise00_driver"); 15 | if ispc, exe = exe + ".exe"; end 16 | 17 | if ~isfile(exe) 18 | cmake(src_dir) 19 | end 20 | 21 | doy = day(time, 'dayofyear'); 22 | hms = sprintf('%02d %02d %02d', hour(time), minute(time), second(time)); 23 | 24 | cmd = exe + " " + doy + " " + hms +... 25 | " " + num2str(glat) + " " + num2str(glon) + ... 26 | " " + num2str(indices.f107s) + " " + num2str(indices.f107) + " " + num2str(indices.Ap) + ... 27 | " " + num2str(altkm); 28 | 29 | [ret,dat] = system(cmd); 30 | if ret ~= 0 31 | error("msise00:runtimeError", "MSISE00 failure %s", dat) 32 | end 33 | 34 | D = cell2mat(textscan(dat, '%f', 'ReturnOnError', false)); 35 | if length(D)~=11 36 | disp(dat) 37 | error("unexpected output from MSISe00 using " + exe) 38 | end 39 | 40 | atmos = struct("altkm", altkm, "f107s", indices.f107s, "f107", indices.f107, "Ap", indices.Ap,... 41 | "nHe", D(1), "nO", D(2), "nN2", D(3), "nO2", D(4), "nAr", D(5), ... 42 | "nTotal", D(6), "nH", D(7), "nN", D(8), "nOanomalous", D(9), "Texo", D(10), "Tn", D(11)); 43 | 44 | end 45 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | env: 4 | CMAKE_BUILD_PARALLEL_LEVEL: 4 5 | CTEST_PARALLEL_LEVEL: 0 6 | CTEST_NO_TESTS_ACTION: error 7 | CMAKE_BUILD_TYPE: Release 8 | 9 | on: 10 | push: 11 | paths: 12 | - "**.py" 13 | - .github/workflows/ci.yml 14 | workflow_dispatch: 15 | 16 | # avoid wasted runs 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | 23 | unix: 24 | strategy: 25 | matrix: 26 | os: [ubuntu-latest, macos-latest] 27 | python-version: ["3.9", "3.13"] 28 | 29 | env: 30 | FC: gfortran-14 31 | 32 | runs-on: ${{ matrix.os }} 33 | 34 | steps: 35 | - uses: actions/checkout@v4 36 | - uses: actions/setup-python@v5 37 | with: 38 | python-version: ${{ matrix.python-version }} 39 | 40 | - run: pip install .[tests,lint] 41 | 42 | - run: flake8 43 | - run: mypy 44 | 45 | - run: pytest 46 | 47 | 48 | msys2: 49 | runs-on: windows-latest 50 | timeout-minutes: 10 51 | 52 | steps: 53 | - uses: msys2/setup-msys2@v2 54 | id: msys2 55 | with: 56 | update: true 57 | install: >- 58 | mingw-w64-ucrt-x86_64-gcc-fortran 59 | 60 | - name: Put MSYS2_MinGW64 on PATH 61 | run: echo "${{ steps.msys2.outputs.msys2-location }}/ucrt64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append 62 | 63 | - uses: actions/checkout@v4 64 | 65 | - run: pip install .[tests,lint] 66 | 67 | - run: pytest 68 | -------------------------------------------------------------------------------- /src/msise00/tests/test_grid.py: -------------------------------------------------------------------------------- 1 | """ 2 | regenerate data: 3 | 4 | python -m msise00 -w src/msise00/tests/ref3.nc -a 200 -gs 30 60 -t 2017-03-01T12 5 | """ 6 | 7 | import subprocess 8 | import pytest 9 | import sys 10 | import xarray 11 | import xarray.testing 12 | import importlib.resources 13 | 14 | import msise00 15 | import msise00.worldgrid 16 | 17 | altkm = 200.0 18 | time = "2017-03-01T12" 19 | 20 | 21 | def test_one_alt_one_time(): 22 | with importlib.resources.as_file(importlib.resources.files(__package__) / "ref3.nc") as fn: 23 | ref = xarray.open_dataset(fn) 24 | 25 | lat, lon = msise00.worldgrid.latlonworldgrid(30, 60) 26 | 27 | try: 28 | dat_mod = msise00.run(time, altkm, lat, lon).squeeze() 29 | except ConnectionError: 30 | pytest.skip("unable to download RecentIndices.txt") 31 | xarray.testing.assert_allclose(ref, dat_mod) 32 | 33 | 34 | def test_script(tmp_path): 35 | 36 | with importlib.resources.as_file(importlib.resources.files(__package__) / "ref3.nc") as fn: 37 | ref = xarray.open_dataset(fn) 38 | 39 | fn = tmp_path / "test.nc" 40 | cmd = [ 41 | sys.executable, 42 | "-m", 43 | "msise00", 44 | "-q", 45 | "-w", 46 | str(fn), 47 | "-a", 48 | str(altkm), 49 | "-t", 50 | time, 51 | "-gs", 52 | "30", 53 | "60", 54 | ] 55 | print(" ".join(cmd)) 56 | subprocess.check_call(cmd) 57 | 58 | dat = xarray.open_dataset(fn) 59 | xarray.testing.assert_allclose(ref, dat) 60 | -------------------------------------------------------------------------------- /src/msise00/tests/test_time_grid.py: -------------------------------------------------------------------------------- 1 | """ 2 | generate the reference data: 3 | 4 | python -m msise00 -w src/msise00/tests/ref4.nc -a 200 -gs 90 90 -t 2017-03-01T12 2017-03-01T13 5 | """ 6 | 7 | import importlib.resources 8 | import subprocess 9 | import pytest 10 | import sys 11 | import xarray 12 | import xarray.testing 13 | import msise00 14 | import msise00.worldgrid 15 | 16 | time = ["2017-03-01T12", "2017-03-01T13"] 17 | altkm = 200.0 18 | 19 | 20 | def test_multiple_time(): 21 | with importlib.resources.as_file(importlib.resources.files(__package__) / "ref4.nc") as fn: 22 | ref = xarray.open_dataset(fn) 23 | 24 | lat, lon = msise00.worldgrid.latlonworldgrid(90, 90) 25 | 26 | try: 27 | dat_mod = msise00.run(time, altkm, lat, lon).squeeze() 28 | except ConnectionError: 29 | pytest.skip("unable to download RecentIndices.txt") 30 | xarray.testing.assert_allclose(ref, dat_mod) 31 | 32 | 33 | def test_script(tmp_path): 34 | with importlib.resources.as_file(importlib.resources.files(__package__) / "ref4.nc") as fn: 35 | ref = xarray.open_dataset(fn) 36 | 37 | fn = tmp_path / "test.nc" 38 | cmd = [ 39 | sys.executable, 40 | "-m", 41 | "msise00", 42 | "-q", 43 | "-w", 44 | str(fn), 45 | "-gs", 46 | "90", 47 | "90", 48 | "-a", 49 | str(altkm), 50 | "-t", 51 | ] + time 52 | print(" ".join(cmd)) 53 | subprocess.check_call(cmd) 54 | 55 | dat = xarray.open_dataset(fn) 56 | xarray.testing.assert_allclose(ref, dat) 57 | -------------------------------------------------------------------------------- /.archive/msise00.m: -------------------------------------------------------------------------------- 1 | function msise00() 2 | % quick demo calling MSISE00 model from Matlab. 3 | % https://www.scivision.dev/matlab-python-user-module-import/ 4 | 5 | assert(~verLessThan('matlab', '8.4'), 'Matlab >= R2014b required') 6 | 7 | % geographic WGS84 lat,lon,alt 8 | glat = 65.1; 9 | glon = -147.5; 10 | alt_km = 10:10:1000; 11 | t = '2015-12-13T10'; 12 | 13 | 14 | atmos = py.msise00.run(t, alt_km, glat, glon); 15 | 16 | plotmsis(atmos) 17 | end 18 | 19 | function plotmsis(atmos) 20 | 21 | species = cellfun(@char, cell(atmos.attrs{'species'}), 'uniformoutput', false); 22 | alt_km = xarrayind2vector(atmos, 'alt_km'); 23 | times = xarrayind2vector(atmos, 'time'); 24 | glat = xarrayind2vector(atmos, 'lat'); 25 | glon = xarrayind2vector(atmos, 'lon'); 26 | 27 | figure(1), clf(1) 28 | ax = axes('nextplot','add'); 29 | 30 | for i = 1:size(species) 31 | dens = xarray2mat(atmos{species{i}}); 32 | semilogx(ax, dens, alt_km, 'DisplayName', species{i}) 33 | end 34 | 35 | set(ax,'xscale','log') 36 | title({[times,' (',num2str(glat),', ', num2str(glon),')']}) 37 | xlabel('Density [m^-3]') 38 | ylabel('altitude [km]') 39 | 40 | xlim([1e6,1e20]) 41 | grid('on') 42 | legend('show') 43 | 44 | end 45 | 46 | function V = xarray2mat(V) 47 | % convert xarray 2-D array to Matlab matrix 48 | 49 | 50 | V = V.values; 51 | S = V.shape; 52 | V = cell2mat(cell(V.ravel('F').tolist())); 53 | V = reshape(V,[int64(S{1}), int64(S{2})]); 54 | 55 | end 56 | 57 | function I = xarrayind2vector(V, key) 58 | 59 | C = cell(V.indexes{key}.values.tolist); % might be numeric or cell array of strings 60 | 61 | if iscellstr(C) || (length(C) > 1 && isa(C{1}, 'py.str')) 62 | I = cellfun(@char, C, 'uniformoutput', false); 63 | elseif isa(C{1}, 'py.datetime.datetime') 64 | I = char(C{1}.isoformat()); 65 | else 66 | I = cell2mat(C); 67 | end % if 68 | 69 | end % function -------------------------------------------------------------------------------- /src/msise00/tests/test_module.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | import pytest 3 | from pytest import approx 4 | 5 | import msise00 6 | 7 | 8 | def test_past(): 9 | t = datetime(2013, 3, 31, 12) 10 | altkm = 150.0 11 | glat = 65.0 12 | glon = -148.0 13 | 14 | try: 15 | atmos = msise00.run(t, altkm, glat, glon) 16 | except ConnectionError: 17 | pytest.skip("unable to download RecentIndices.txt") 18 | 19 | assert atmos["He"].ndim == 4 20 | assert atmos["He"].size == 1 21 | dims = list(atmos.dims) 22 | assert ["time", "alt_km", "lat", "lon"] == dims 23 | 24 | # daily resolution 25 | assert atmos["He"].item() == approx(1.2523275e13) 26 | assert atmos["O"].item() == approx(1.3222577e16) 27 | assert atmos["N2"].item() == approx(2.9318694e16) 28 | assert atmos["O2"].item() == approx(2.6164412e15) 29 | assert atmos["Ar"].item() == approx(5.9933693e13) 30 | assert atmos["Total"].item() == approx(1.8571854e-9) 31 | assert atmos["N"].item() == approx(9.1038102e12) 32 | assert atmos["AnomalousO"].item() == approx(4.503e-14) 33 | 34 | assert atmos["Tn"].item() == approx(655.79, abs=0.01) 35 | assert atmos["Texo"].item() == approx(875.18, abs=0.01) 36 | 37 | assert atmos.species == ["He", "O", "N2", "O2", "Ar", "Total", "H", "N", "AnomalousO"] 38 | 39 | 40 | def test_forecast(): 41 | t = datetime(2029, 3, 31, 12) 42 | altkm = 150.0 43 | glat = 65.0 44 | glon = -148.0 45 | 46 | atmos = msise00.run(t, altkm, glat, glon) 47 | 48 | assert atmos["He"].ndim == 4 49 | assert atmos["He"].size == 1 50 | dims = list(atmos.dims) 51 | assert ["time", "alt_km", "lat", "lon"] == dims 52 | 53 | assert atmos.species == ["He", "O", "N2", "O2", "Ar", "Total", "H", "N", "AnomalousO"] 54 | 55 | assert atmos["Tn"].item() == approx(616.09, abs=0.1) 56 | assert atmos["Texo"].item() == approx(769.82, abs=0.01) 57 | -------------------------------------------------------------------------------- /src/msise00/tests/test_point.py: -------------------------------------------------------------------------------- 1 | """ 2 | Regenerate test data: 3 | 4 | python -m msise00 -w src/msise00/tests/ref6.nc -a 200 -t 2017-03-01T12 -c 65.0 -148.0 5 | python -m msise00 -w src/msise00/tests/ref5.nc -a 100 -t 2017-03-01T12 -c 65.0 -148.0 6 | """ 7 | 8 | import importlib.resources 9 | import subprocess 10 | import pytest 11 | import sys 12 | from datetime import datetime 13 | 14 | import xarray 15 | import xarray.testing 16 | 17 | import msise00 18 | 19 | lat = 65.0 20 | lon = -148.0 21 | time = datetime(2017, 3, 1, 12) 22 | 23 | 24 | @pytest.mark.parametrize("altkm,reffn", [(100.0, "ref5.nc"), (200.0, "ref6.nc")]) 25 | def test_one_loc_one_time(altkm, reffn): 26 | with importlib.resources.as_file(importlib.resources.files(__package__) / reffn) as fn: 27 | ref = xarray.open_dataset(fn) 28 | 29 | ds = {"time": time, "Ap": 39, "Kp": 4.7, "f107": 79.3, "f107s": 74.989727, "Aps": 9.675052} 30 | 31 | dat = msise00.run(time, altkm, lat, lon, indices=ds).squeeze() 32 | 33 | assert dat.lat == ref.lat == lat 34 | assert dat.lon == ref.lon == lon 35 | assert dat.time == ref.time 36 | 37 | xarray.testing.assert_allclose(ref, dat, rtol=0.001) 38 | 39 | 40 | @pytest.mark.parametrize("altkm,reffn", [(100.0, "ref5.nc"), (200.0, "ref6.nc")]) 41 | def test_script(altkm, reffn, tmp_path): 42 | with importlib.resources.as_file(importlib.resources.files(__package__) / reffn) as fn: 43 | ref = xarray.open_dataset(fn) 44 | 45 | fn = tmp_path / "test.nc" 46 | cmd = [ 47 | sys.executable, 48 | "-m", 49 | "msise00", 50 | "-q", 51 | "-w", 52 | str(fn), 53 | "-a", 54 | str(altkm), 55 | "-t", 56 | str(time), 57 | "-c", 58 | str(lat), 59 | str(lon), 60 | ] 61 | print(" ".join(cmd)) 62 | subprocess.check_call(cmd) 63 | 64 | dat = xarray.open_dataset(fn) 65 | xarray.testing.assert_allclose(ref, dat, rtol=0.001) 66 | -------------------------------------------------------------------------------- /src/msise00/tests/test_ccmc.py: -------------------------------------------------------------------------------- 1 | """ 2 | compare with CCMC web service output 3 | """ 4 | 5 | from datetime import datetime 6 | import numpy as np 7 | from pytest import approx 8 | import importlib.resources 9 | 10 | import msise00 11 | 12 | 13 | def test_ccmc(): 14 | t = datetime(2001, 2, 2, 8, 0, 0) 15 | glat = 60.0 16 | glon = -70.0 17 | altkm = 400.0 18 | indices = {"f107s": 163.6666, "f107": 146.7, "Ap": 7} 19 | 20 | with importlib.resources.as_file(importlib.resources.files(__package__) / "ccmc.log") as fn: 21 | A = np.loadtxt(fn, skiprows=25) 22 | 23 | atmos = msise00.run(t, altkm, glat, glon, indices) 24 | assert atmos.f107s == approx(indices["f107s"]) 25 | assert atmos.f107 == approx(indices["f107"]) 26 | assert atmos.Ap == indices["Ap"] 27 | assert A[0] == approx(altkm) 28 | assert A[1] == approx(atmos["O"].item() / 1e6, rel=0.01) 29 | assert A[2] == approx(atmos["N2"].item() / 1e6, rel=0.01) 30 | assert A[3] == approx(atmos["O2"].item() / 1e6, rel=0.01) 31 | assert A[7] == approx(atmos["He"].item() / 1e6, rel=0.01) 32 | assert A[8] == approx(atmos["Ar"].item() / 1e6, rel=0.01) 33 | assert A[9] == approx(atmos["H"].item() / 1e6, rel=0.01) 34 | assert A[10] == approx(atmos["N"].item() / 1e6, rel=0.01) 35 | assert A[11] == approx(atmos["AnomalousO"].item() / 1e6, rel=0.01) 36 | 37 | assert A[5] == approx(atmos["Tn"].item(), rel=0.001) 38 | assert A[6] == approx(atmos["Texo"].item(), rel=0.001) 39 | 40 | 41 | def test_ccmc2(): 42 | t = datetime(2018, 5, 17, 21, 0, 0) 43 | glat = 55.0 44 | glon = 120.0 45 | altkm = 300.0 46 | indices = {"f107s": 72.6, "f107": 71.5, "Ap": 9.5} 47 | 48 | atmos = msise00.run(t, altkm, glat, glon, indices) 49 | 50 | assert 4.874e7 == approx(atmos["N2"].item() / 1e6, rel=0.01) 51 | assert 1.622e6 == approx(atmos["O2"].item() / 1e6, rel=0.01) 52 | 53 | assert 794.1 == approx(atmos["Tn"].item(), rel=0.01) 54 | assert 800.0 == approx(atmos["Texo"].item(), rel=0.01) 55 | -------------------------------------------------------------------------------- /src/msise00/fortran/msise00_driver.f90: -------------------------------------------------------------------------------- 1 | program msis_driver 2 | 3 | use, intrinsic:: iso_fortran_env, only: stderr=>error_unit 4 | use msise00_python, only : gtd7, meters 5 | 6 | implicit none 7 | 8 | ! ./msise00 172 8 0 0 60. -70. 150. 150. 4. 400 9 | 10 | integer :: doy ! day of year 11 | real :: utsec ! UTC second of day 12 | real :: alt_km ! altitude [km] 13 | real :: glat, glon ! geodetic latitude, longitude [deg] 14 | 15 | real :: lst ! local solar time 16 | real :: f107a 17 | real :: f107 18 | real :: Ap, Ap7(7) 19 | 20 | real :: hour, minute, second 21 | 22 | character(1000) :: argv 23 | 24 | ! output variables 25 | real :: Density(9) 26 | real :: Temperature(2) 27 | 28 | ! SW is as defined in NRL example 29 | real, parameter :: SW(25)=[1.,1.,1.,1.,1.,1.,1.,1.,-1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.] 30 | 31 | call meters(.true.) 32 | 33 | ! --- command line input 34 | if (command_argument_count() < 10) then 35 | write(stderr,*) 'need input parameters: DayOfYear hour minute second glat glon f107a f107 ap alt_km' 36 | stop 1 37 | endif 38 | 39 | call get_command_argument(1, argv) 40 | read(argv,'(i3)') doy 41 | 42 | call get_command_argument(2, argv) 43 | read(argv,*) hour 44 | 45 | call get_command_argument(3, argv) 46 | read(argv,*) minute 47 | 48 | call get_command_argument(4, argv) 49 | read(argv,*) second 50 | 51 | call get_command_argument(5, argv) 52 | read(argv,*) glat 53 | 54 | call get_command_argument(6, argv) 55 | read(argv,*) glon 56 | 57 | call get_command_argument(7, argv) 58 | read(argv,*) f107a 59 | 60 | call get_command_argument(8, argv) 61 | read(argv,*) f107 62 | 63 | call get_command_argument(9, argv) 64 | read(argv,*) Ap 65 | Ap7 = Ap 66 | 67 | call get_command_argument(10, argv) 68 | read(argv,*) alt_km 69 | 70 | 71 | ! --- execute program 72 | utsec = hour*3600. + minute*60. + second 73 | 74 | lst = utsec/3600. + glon/15. 75 | 76 | CALL GTD7(doy, utsec, alt_km, glat, glon, lst, f107a, f107, Ap7, 48, Density, Temperature) 77 | 78 | print '(9ES15.7)',Density 79 | print '(2F9.2)',Temperature 80 | 81 | end program 82 | -------------------------------------------------------------------------------- /.github/workflows/ci-matlab.yml: -------------------------------------------------------------------------------- 1 | name: matlab 2 | 3 | env: 4 | CTEST_NO_TESTS_ACTION: error 5 | CMAKE_BUILD_PARALLEL_LEVEL: 4 6 | CTEST_PARALLEL_LEVEL: 0 7 | 8 | on: 9 | push: 10 | paths: 11 | - "**.m" 12 | - "**.cmake" 13 | - "**/CMakeLists.txt" 14 | - ".github/workflows/ci-matlab.yml" 15 | workflow_dispatch: 16 | 17 | # avoid wasted runs 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | 24 | unix: 25 | 26 | strategy: 27 | matrix: 28 | os: [ubuntu-24.04, macos-latest] 29 | matlab: [R2024b] 30 | 31 | runs-on: ${{ matrix.os }} 32 | 33 | env: 34 | FC: gfortran-14 35 | 36 | steps: 37 | 38 | - name: Install MATLAB 39 | timeout-minutes: 10 40 | uses: matlab-actions/setup-matlab@v2 41 | with: 42 | release: ${{ matrix.matlab }} 43 | cache: true 44 | 45 | - uses: actions/checkout@v4 46 | 47 | - name: Lint task 48 | uses: matlab-actions/run-build@v2 49 | with: 50 | tasks: check 51 | 52 | - name: Test task 53 | uses: matlab-actions/run-build@v2 54 | with: 55 | tasks: test 56 | 57 | 58 | msys2: 59 | runs-on: windows-latest 60 | timeout-minutes: 10 61 | 62 | steps: 63 | - uses: msys2/setup-msys2@v2 64 | id: msys2 65 | with: 66 | update: true 67 | install: >- 68 | mingw-w64-ucrt-x86_64-gcc-fortran 69 | 70 | - name: Put MSYS2_MinGW64 on PATH 71 | run: echo "${{ steps.msys2.outputs.msys2-location }}/ucrt64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append 72 | 73 | - name: Install MATLAB 74 | timeout-minutes: 10 75 | uses: matlab-actions/setup-matlab@v2 76 | with: 77 | release: R2024b 78 | cache: true 79 | 80 | - uses: actions/checkout@v4 81 | 82 | - name: Lint task 83 | uses: matlab-actions/run-build@v2 84 | with: 85 | tasks: check 86 | 87 | - name: Test task 88 | uses: matlab-actions/run-build@v2 89 | with: 90 | tasks: test 91 | -------------------------------------------------------------------------------- /.archive/f2py.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import numpy as np 4 | import xarray 5 | from datetime import datetime 6 | 7 | 8 | def rungtd1d(time: datetime | str, altkm, glat: float, glon: float) -> xarray.Dataset: 9 | """ 10 | This is the "atomic" function looped by other functions 11 | """ 12 | time = todt64(time) 13 | # %% get solar parameters for date 14 | f107Ap = gi.getApF107(time, smoothdays=81) 15 | f107a = f107Ap["f107s"].item() 16 | f107 = f107Ap["f107"].item() 17 | Ap = f107Ap["Ap"].item() 18 | # %% dimensions 19 | altkm = np.atleast_1d(altkm) 20 | assert altkm.ndim == 1 21 | assert isinstance(glon, (int, float)) 22 | assert isinstance(glat, (int, float)) 23 | assert isinstance(time, np.datetime64) or ( 24 | time.size == 1 and isinstance(time[0], np.datetime64) 25 | ), "if you have multiple times, for loop over them" 26 | 27 | # don't check ap, too complicated 28 | assert isinstance(MASS, (float, int)) 29 | assert len(TSELECOPS) == 25 30 | # %% 31 | gtd7.tselec(TSELECOPS) # like the msis_driver example 32 | 33 | iyd, utsec, stl = datetime2gtd(time, glon) 34 | altkm = np.atleast_1d(altkm) 35 | 36 | gtd7.meters(1) # makes output in m^-3 and kg/m^-3 37 | # %% 38 | if isinstance(Ap, (float, int)): 39 | Ap = [Ap] * 7 # even if SW(9) == 1 due to f2py needs for array 40 | 41 | dens = np.empty((altkm.size, len(species))) 42 | temp = np.empty((altkm.size, len(ttypes))) 43 | for i, a in enumerate(altkm): 44 | dens[i, :], temp[i, :] = gtd7.gtd7(iyd, utsec, a, glat, glon, stl, f107a, f107, Ap, MASS) 45 | 46 | dsf = { 47 | k: (("time", "alt_km", "lat", "lon"), v[None, :, None, None]) 48 | for (k, v) in zip(species, dens.T) 49 | } 50 | dsf.update( 51 | { 52 | "Tn": (("time", "alt_km", "lat", "lon"), temp[:, 1][None, :, None, None]), 53 | "Texo": (("time", "alt_km", "lat", "lon"), temp[:, 0][None, :, None, None]), 54 | } 55 | ) 56 | 57 | atmos = xarray.Dataset( 58 | dsf, 59 | coords={"time": time.astype(datetime), "alt_km": altkm, "lat": [glat], "lon": [glon]}, 60 | attrs={"Ap": Ap, "f107": f107, "f107a": f107a, "species": species}, 61 | ) 62 | 63 | return atmos 64 | -------------------------------------------------------------------------------- /src/msise00/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Run MSISE00, save to NetCDF4 (HDF5) and/or plot. 4 | 5 | Example: 6 | Poker Flat Research Range altitude profile: 7 | 8 | MSISE00.py -t 2018-01-01 -c 65 -148 -a 0.2 9 | """ 10 | 11 | from pathlib import Path 12 | import numpy as np 13 | from argparse import ArgumentParser 14 | 15 | from .base import run 16 | from .worldgrid import latlonworldgrid 17 | 18 | 19 | p = ArgumentParser(description="calls MSISE-00 from Python, save to NetCDF4 and/or plot") 20 | p.add_argument("-t", "--time", help="time or times", nargs="+", required=True) 21 | p.add_argument( 22 | "-a", 23 | "--altkm", 24 | help="altitude (km). scalar, or (start,stop,step) or list of alts.", 25 | type=float, 26 | nargs="+", 27 | required=True, 28 | ) 29 | p.add_argument( 30 | "-c", 31 | "--latlon", 32 | help="geodetic latitude/longitude (deg)", 33 | metavar=("lat", "lon"), 34 | type=float, 35 | nargs=2, 36 | ) 37 | p.add_argument("-o", "--odir", help="directory to write plots to") 38 | p.add_argument("-w", help="NetCDF4 .nc filename to write") 39 | p.add_argument( 40 | "-gs", help="geographic grid spacing (lat, lon)", nargs=2, type=float, default=(10, 10) 41 | ) 42 | p.add_argument("-q", "--quiet", help="disable plotting", action="store_true") 43 | P = p.parse_args() 44 | 45 | # %% altitude 46 | if len(P.altkm) == 1: 47 | altkm = P.altkm[0] 48 | elif len(P.altkm) == 3: 49 | altkm = np.arange(*P.altkm) 50 | else: 51 | altkm = P.altkm 52 | # %% latlon 53 | if P.latlon is not None: 54 | glat, glon = P.latlon 55 | else: 56 | glat, glon = latlonworldgrid(*P.gs) 57 | # %% run 58 | atmos = run(P.time, altkm, glat, glon) 59 | 60 | if not atmos: 61 | raise ValueError(f"no/bad data for {P.time} alt: {altkm} km coord:{glat} {glon}") 62 | 63 | # %% save 64 | if P.w: 65 | ncfn = Path(P.w).expanduser() 66 | print("saving", ncfn) 67 | # NOTE: .squeeze() avoids ValueError: unsupported dtype for netCDF4 variable: datetime64[ns] 68 | atmos.squeeze().to_netcdf(ncfn) 69 | # %% plot 70 | if not P.quiet: 71 | try: 72 | from matplotlib.pyplot import show 73 | from .plots import plotgtd 74 | 75 | plotgtd(atmos, P.odir) 76 | show() 77 | except ImportError: 78 | print("skipped plotting") 79 | -------------------------------------------------------------------------------- /reference/physics_constants.f90: -------------------------------------------------------------------------------- 1 | module physics_constants 2 | 3 | use utils_constants 4 | 5 | public 6 | 7 | ! Basic physical constants of matter. The 10^-23 and 10^23 factors 8 | ! have been removed to ease calculations. 9 | 10 | ! Boltzman Constant - CODATA 2010 11 | real(8) , parameter :: boltzk = 1.380648813_r8 12 | ! Avogadro Constant - International Avogadro cohordination 2011 13 | real(8) , parameter :: navgdr = 6.0221407818_r8 14 | 15 | ! Gas constant in J/K/mol 16 | real(dp) , parameter :: rgasmol = boltzk*navgdr 17 | 18 | ! Molecular weight of water 19 | real(dp) , parameter :: watmolwgt = 18.01528_r8 ! g/mol 20 | ! Mean dry air molecular weight 21 | real(dp) , parameter :: airmolwgt = 28.96443_r8 ! g/mol 22 | ! Ratio of mean molecular weight of water to that of dry air 23 | real(dp) , parameter :: wgtfrac = watmolwgt/airmolwgt 24 | 25 | ! Gas constant for dry air in J/K/kg 26 | real(dp) , parameter :: rgas = (rgasmol/airmolwgt)*d_1000 27 | ! Gas constant for water in J/K/kg 28 | real(dp) , parameter :: rwat = (rgasmol/watmolwgt)*d_1000 29 | 30 | ! 0 C in Kelvin 31 | real(dp) , parameter :: tzero = 273.16_r8 32 | 33 | ! Standard Gravity (m/sec**2) 3rd CGPM 34 | real(dp) , parameter :: egrav = 9.80665_r8 35 | 36 | ! Earth radius in meters 37 | real(8) , parameter :: earthrad = 6.371229D+06 38 | real(8) , parameter :: erkm = earthrad/d_1000 39 | ! Angular velocity of rotation of Earth 40 | real(8) , parameter :: eomeg = 7.2921159D-05 41 | real(8) , parameter :: eomeg2 = d_2*eomeg 42 | 43 | ! Hydrostatic coefficient 44 | real(8) , parameter :: gmr = egrav*airmolwgt/rgasmol 45 | 46 | ! Specific heat at constant pressure for dry air J/kg/K 47 | real(dp) , parameter :: cpd = 1005.46_r8 48 | ! Specific heat at constant pressure for moist air J/kg/K 49 | real(dp) , parameter :: cpv = 1869.46_r8 50 | ! Specific heat of water at 15 Celsius J/kg/K 51 | real(dp) , parameter :: cpw = 4186.95_r8 52 | ! Specific heat of water at 0 Celsius J/kg/K 53 | real(dp) , parameter :: cpw0 = 4218.0_r8 54 | 55 | ! Derived 56 | real(dp) , parameter :: rgovrw = rgas/rwat 57 | real(dp) , parameter :: rwovrg = rwat/rgas 58 | real(dp) , parameter :: rgovcp = rgas/cpd 59 | real(dp) , parameter :: rgovg = rgas/egrav 60 | real(dp) , parameter :: govrg = egrav/rgas 61 | 62 | real(dp) , parameter :: regrav = d_1/egrav 63 | real(dp) , parameter :: rrgas = d_1/rgas 64 | real(dp) , parameter :: rcpd = d_1/cpd 65 | 66 | end module physics_constants 67 | -------------------------------------------------------------------------------- /+msise00/TestUnit.m: -------------------------------------------------------------------------------- 1 | classdef TestUnit < matlab.unittest.TestCase 2 | 3 | methods (Test) 4 | 5 | function test_ccmc(tc) 6 | time = datetime(2001,2,2,8,0,0); 7 | glat = 60; 8 | glon = -70; 9 | ind = struct(f107s=163.6666, f107=146.7, Ap=7); 10 | altkm = 400.; 11 | 12 | cwd = fileparts(mfilename('fullpath')); 13 | 14 | atmo = msise00.msise00(time, glat, glon, ind, altkm); 15 | %% read CCMC output 16 | ref_fn = fullfile(cwd, "../src/msise00/tests/ccmc.log"); 17 | fid = fopen(ref_fn); 18 | 19 | A = cell2mat(textscan(fid, '%f %f %f %f %f %f %f %f %f %f %f %f', 1, ... 20 | ReturnOnError=false, HeaderLines=25)); 21 | 22 | A(2:4) = A(2:4) * 1e6; % cm^-3 => m^-3 23 | A(5) = A(5) * 1000; % gram cm^-3 => kg m^-3 24 | A(8:end) = A(8:end) * 1e6; 25 | 26 | fclose(fid); 27 | 28 | %% compare 29 | tc.assertEqual(ind.f107, atmo.f107) 30 | tc.assertEqual(ind.f107s, atmo.f107s) 31 | tc.assertEqual(ind.Ap, atmo.Ap) 32 | 33 | tc.verifyEqual(A(1), atmo.altkm) 34 | tc.verifyEqual(A(2), atmo.nO, RelTol=0.01) 35 | tc.verifyEqual(A(3), atmo.nN2, RelTol=0.01) 36 | tc.verifyEqual(A(4), atmo.nO2, RelTol=0.01) 37 | tc.verifyEqual(A(5), atmo.nTotal, RelTol=0.01) 38 | tc.verifyEqual(A(6), atmo.Tn, RelTol=0.01) 39 | tc.verifyEqual(A(7), atmo.Texo, RelTol=0.01) 40 | tc.verifyEqual(A(8), atmo.nHe, RelTol=0.01) 41 | tc.verifyEqual(A(9), atmo.nAr, RelTol=0.01) 42 | tc.verifyEqual(A(10), atmo.nH, RelTol=0.01) 43 | tc.verifyEqual(A(11), atmo.nN, RelTol=0.01) 44 | tc.verifyEqual(A(12), atmo.nOanomalous, RelTol=0.01) 45 | 46 | end 47 | 48 | 49 | function test_ccmc2(tc) 50 | time = datetime(2018,5,17,21,0,0); 51 | glat = 55; 52 | glon = 120; 53 | ind = struct(f107s=72.6, f107=71.5, Ap=9.5); 54 | altkm = 300.; 55 | 56 | atmo = msise00.msise00(time, glat, glon, ind, altkm); 57 | 58 | tc.verifyEqual(4.874e7, atmo.nN2 / 1e6, RelTol=0.01) 59 | tc.verifyEqual(1.622e6, atmo.nO2 / 1e6, RelTol=0.01) 60 | 61 | tc.verifyEqual(794.1, atmo.Tn, RelTol=0.01) 62 | tc.verifyEqual(800, atmo.Texo, RelTol=0.01) 63 | 64 | end 65 | 66 | 67 | function test_plot_alt(tc) 68 | time = datetime(2018,5,17,21,0,0); 69 | glat = 55; 70 | glon = 120; 71 | ind = struct(f107s=72.6, f107=71.5, Ap=9.5); 72 | altkm = 300.; 73 | 74 | atmo = msise00.msise00(time, glat, glon, ind, altkm); 75 | 76 | hf = msise00.plotalt(atmo, time, glat, glon); 77 | 78 | tc.verifyClass(hf, "matlab.ui.Figure") 79 | 80 | close(hf) 81 | 82 | end 83 | 84 | function test_plot_time(tc) 85 | time = datetime(2018,5,17,21,0,0); 86 | glat = 55; 87 | glon = 120; 88 | ind = struct(f107s=72.6, f107=71.5, Ap=9.5); 89 | altkm = 300.; 90 | 91 | atmo = msise00.msise00(time, glat, glon, ind, altkm); 92 | 93 | hf= msise00.plottime(atmo, time, glat, glon); 94 | 95 | tc.verifyClass(hf, "matlab.ui.Figure") 96 | 97 | close(hf) 98 | 99 | end 100 | 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /.archive/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # wait with Octave till Github Action migrations which has Ubuntu 18.04 2 | variables: 3 | CI: true 4 | 5 | stages: 6 | 7 | - stage: SyntaxChecks 8 | jobs: 9 | 10 | - job: PEP8_MyPy_Python37 11 | pool: 12 | vmImage: ubuntu-latest 13 | steps: 14 | - task: UsePythonVersion@0 15 | inputs: 16 | versionSpec: '3.7' 17 | addToPath: true 18 | - script: pip install -e .[tests,lint] 19 | displayName: 'Dev install' 20 | - script: flake8 21 | displayName: PEP8 22 | - script: mypy . 23 | displayName: Type Check 24 | 25 | - stage: PackageTests 26 | jobs: 27 | 28 | - job: UbuntuInstall 29 | pool: 30 | vmImage: ubuntu-latest 31 | 32 | steps: 33 | - task: UsePythonVersion@0 34 | inputs: 35 | versionSpec: '3.6' 36 | addToPath: true 37 | - script: | 38 | sudo apt install -yq --no-install-recommends gfortran 39 | python setup.py install 40 | pip install msise00[tests] 41 | displayName: 'Install Prereqs' 42 | - script: | 43 | cd $HOME 44 | python -m pytest $(Build.SourcesDirectory)/tests -r a -v 45 | displayName: 'Build Python' 46 | - script: pytest -r a -v 47 | displayName: 'PyTest' 48 | 49 | - stage: IntegrationTests 50 | jobs: 51 | 52 | - job: Ubuntu 53 | pool: 54 | vmImage: ubuntu-latest 55 | 56 | steps: 57 | - task: UsePythonVersion@0 58 | inputs: 59 | versionSpec: '3.6' 60 | addToPath: true 61 | - script: sudo apt install -yq --no-install-recommends gfortran 62 | displayName: 'Install Prereqs' 63 | - script: pip install -e .[tests] 64 | displayName: 'Build Python' 65 | - script: pytest -r a -v 66 | displayName: 'PyTest' 67 | 68 | - job: MacOS 69 | pool: 70 | vmImage: macOS-latest 71 | 72 | steps: 73 | - task: UsePythonVersion@0 74 | inputs: 75 | versionSpec: '3.6' 76 | addToPath: true 77 | - script: brew install gcc 78 | displayName: 'Install Prereqs' 79 | - script: pip install -e .[tests] 80 | displayName: 'Build Python' 81 | - script: pytest -r a -v 82 | displayName: 'PyTest' 83 | 84 | - job: WindowsMinGW 85 | pool: 86 | vmImage: windows-latest 87 | 88 | steps: 89 | - task: UsePythonVersion@0 90 | inputs: 91 | versionSpec: '3.6' 92 | addToPath: true 93 | - script: cinst -y mingw 94 | displayName: 'Install Prereqs' 95 | - script: pip install -e .[tests] 96 | displayName: 'Build Python' 97 | - script: pytest -r a -v 98 | displayName: 'PyTest' 99 | 100 | 101 | - stage: CoverageTests 102 | 103 | jobs: 104 | - job: CoverageOctave 105 | pool: 106 | vmImage: ubuntu-latest 107 | steps: 108 | - task: UsePythonVersion@0 109 | inputs: 110 | versionSpec: '3.7' 111 | addToPath: true 112 | - script: sudo apt install -yq --no-install-recommends gfortran 113 | displayName: 'Install Prereqs' 114 | - script: pip install -e .[tests] 115 | displayName: 'Dev install' 116 | - script: pytest --junitxml=junit/test-results.xml --cov --cov-report=xml --cov-report=html 117 | displayName: Coverage 118 | 119 | - task: PublishTestResults@2 120 | condition: succeededOrFailed() 121 | inputs: 122 | testResultsFiles: '**/test-*.xml' 123 | testRunTitle: 'Publish test results for Python $(python.version)' 124 | # https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/python?view=azure-devops#publish-code-coverage-results 125 | - task: PublishCodeCoverageResults@1 126 | condition: succeeded() 127 | inputs: 128 | codeCoverageTool: Cobertura 129 | summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' 130 | reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov' 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MSISE-00 in Python and Matlab 2 | 3 | [![Zenodo DOI](https://zenodo.org/badge/32971905.svg)](https://zenodo.org/badge/latestdoi/32971905) 4 | [![python](https://github.com/space-physics/msise00/actions/workflows/ci.yml/badge.svg)](https://github.com/space-physics/msise00/actions/workflows/ci.yml) 5 | [![matlab](https://github.com/space-physics/msise00/actions/workflows/ci-matlab.yml/badge.svg)](https://github.com/space-physics/msise00/actions/workflows/ci-matlab.yml) 6 | [![PyPi Download stats](http://pepy.tech/badge/msise00)](http://pepy.tech/project/msise00) 7 | 8 | NRL MSISE-00 atmospheric model for Python. 9 | Also accessible via Matlab. 10 | Valid from altitude z = 0..1000 km. 11 | 12 | The plot immediately below shows a slice at 200km on a world-wide grid. 13 | The yellow ball represents the sun footprint on Earth. 14 | 15 | ![MSIS global time animation](./src/msise00/tests/msise00_demo.gif) 16 | 17 | This plot is from [Matlab](./src/msise00/tests/test_msise00_matlab.m) calling MSISE00: 18 | 19 | ![MSISE00 Matlab](./src/msise00/tests/msis_matlab.png) 20 | 21 | ## Units 22 | 23 | * Temperature: degrees Kelvin [K] 24 | * Density: particles per cubic meter [m^-3] 25 | * Mass density: kilograms per cubic meter [kg m^-3] 26 | 27 | ## Install 28 | 29 | This process is used for the Python and [Matlab](#matlab) access to MSIS. 30 | Any Fortran compiler should work. 31 | Fortran compiler may be installed by 32 | 33 | * MacOS / Homebrew: `brew install gcc` 34 | * Linux: `apt install gfortran` 35 | * [Windows](https://www.scivision.dev/install-msys2-windows) 36 | 37 | Get MSISE00 and install Python package: 38 | 39 | ```sh 40 | pip install msise00 41 | ``` 42 | 43 | or for the latest development code 44 | 45 | ```sh 46 | git clone https://github.com/space-physics/msise00 47 | 48 | pip install -e msise00 49 | ``` 50 | 51 | optionally check that MSIS is working via: 52 | 53 | ```sh 54 | pytest msise00 55 | ``` 56 | 57 | This Python module uses our build-on-run technique. 58 | The first time you use this Python module, you will see messages from the Meson build system. 59 | 60 | ## Examples 61 | 62 | MSISE00 can be used from the command line, as an imported module, and even from Matlab. 63 | 64 | ### import module 65 | 66 | ```python 67 | import msise00 68 | from datetime import datetime 69 | 70 | atmos = msise00.run(time=datetime(2013, 3, 31, 12), altkm=150., glat=65., glon=-148.) 71 | ``` 72 | 73 | atmos is an 74 | [xarray.Dataset](http://xarray.pydata.org/en/stable/generated/xarray.Dataset.html) 75 | containing all the simulation output values. 76 | `atmos` is 4-D: (time, altitude, lat, lon), and indexed like `atmos['N2']` 77 | 78 | ### Command Line 79 | 80 | Write NetCDF4 output (HDF5 compatible) with command line argument `-w filename.nc`. 81 | 82 | Simple examples under [Examples/](./Examples) 83 | 84 | * Altitude Profile at a single time: 85 | 86 | ```sh 87 | msise00 -t 2017-08-21T20:48 -c 40 -90 88 | ``` 89 | * Alt. profile time-range with hourly time step: 90 | 91 | ```sh 92 | msise00 -t 2017-08-21 2017-08-22 -c 40 -90 93 | ``` 94 | * Grid: time,lat,lon: generates the plots in the README: 95 | 96 | ```sh 97 | msise00 -t 2016-09-20 2016-09-21 98 | ``` 99 | * single time lat/lon can be plotted: 100 | 101 | ```sh 102 | msise00 -t 2017-01-02T12 103 | ``` 104 | 105 | ### Matlab 106 | 107 | Matlab use of MSISE00 is demonstrated in 108 | [Examples](./Examples/) 109 | 110 | MSISE00 will **automatically compile** "build on run" on first run from Matlab as with Python. 111 | 112 | Optionally, verify Matlab is working by from the top `msise00/` directory in Terminal 113 | 114 | ```sh 115 | buildtool test 116 | ``` 117 | 118 | ### Fortran 119 | 120 | Those wishing to use MSIS from a plain Fortran program can do from the top-level msise00/ directory: 121 | 122 | ```sh 123 | cmake -B build 124 | cmake --build build 125 | ``` 126 | 127 | optionally: 128 | 129 | ```sh 130 | ctest --test-dir build 131 | ``` 132 | 133 | ## Reference 134 | 135 | * Original fortran [code](https://ccmc.gsfc.nasa.gov/pub/modelweb/atmospheric/msis/) 136 | * 1200+ citations 2002 [paper](http://onlinelibrary.wiley.com/doi/10.1029/2002JA009430/pdf) 137 | -------------------------------------------------------------------------------- /reference/utils_spline.f90: -------------------------------------------------------------------------------- 1 | module utils_spline 2 | 3 | use utils_constants 4 | 5 | private 6 | 7 | public :: splini , spline , splint 8 | 9 | contains 10 | 11 | ! 12 | ! Calculate 2nd derivatives of cubic spline interp function 13 | ! Adapted from numerical recipes by press et al 14 | ! 15 | subroutine spline(x,y,yp1,ypn,y2) 16 | implicit none 17 | ! 18 | integer , parameter :: nmax = 100 19 | ! 20 | ! Arrays of tabulated function in ascending order by x with y = f(x) 21 | real(dp) , dimension(:) , intent(in) :: x , y 22 | ! Specified derivatives at x(1) and x(n) 23 | ! Values > 1E30 signals second derivative zero 24 | real(dp) , intent(in) :: yp1 , ypn 25 | ! Output array of second derivatives 26 | real(dp) , dimension(:) , intent(out) :: y2 27 | ! 28 | integer :: n , i , k 29 | real(dp) :: p , qn , sig , un 30 | real(dp) , dimension(nmax) :: u 31 | 32 | n = size(x,1) 33 | if ( yp1 > 0.99E30_r8 ) then 34 | y2(1) = d_0 35 | u(1) = d_0 36 | else 37 | y2(1) = -d_half 38 | u(1) = (d_3/(x(2)-x(1)))*((y(2)-y(1))/(x(2)-x(1))-yp1) 39 | end if 40 | do i = 2 , n - 1 41 | sig = (x(i)-x(i-1))/(x(i+1)-x(i-1)) 42 | p = sig*y2(i-1) + d_2 43 | y2(i) = (sig-d_1)/p 44 | u(i) = (d_6*((y(i+1)-y(i))/(x(i+1)-x(i))- & 45 | (y(i)-y(i-1))/(x(i)-x(i-1))) / & 46 | (x(i+1)-x(i-1))-sig*u(i-1))/p 47 | end do 48 | if ( ypn > .99E30_r8 ) then 49 | qn = d_0 50 | un = d_0 51 | else 52 | qn = d_half 53 | un = (d_3/(x(n)-x(n-1)))*(ypn-(y(n)-y(n-1))/(x(n)-x(n-1))) 54 | end if 55 | y2(n) = (un-qn*u(n-1))/(qn*y2(n-1)+d_1) 56 | do k = n - 1 , 1 , -1 57 | y2(k) = y2(k)*y2(k+1) + u(k) 58 | end do 59 | end subroutine spline 60 | ! 61 | ! Integrate cubic spline function from xa(1) to x 62 | ! 63 | subroutine splini(xa,ya,y2a,x,yi) 64 | implicit none 65 | ! 66 | ! Arrays of tabulated function in ascending order by xa with ya = f(xa) 67 | real(dp) , dimension(:) , intent(in) :: xa , ya 68 | ! Array of second derivatives 69 | real(dp) , dimension(:) , intent(in) :: y2a 70 | ! Ascissa endpoint of integration 71 | real(dp) , intent(in) :: x 72 | ! Output value 73 | real(dp) , intent(out) :: yi 74 | ! 75 | real(dp) :: a , a2 , b , b2 , h , xx 76 | integer :: n , khi , klo 77 | ! 78 | n = size(xa,1) 79 | yi = d_0 80 | klo = 1 81 | khi = 2 82 | do while ( x > xa(klo) .and. khi <= n ) 83 | xx = x 84 | if ( khi 1 ) 120 | k = (khi+klo)/2 121 | if ( xa(k)>x ) then 122 | khi = k 123 | else 124 | klo = k 125 | end if 126 | end do 127 | h = xa(khi) - xa(klo) 128 | if ( h==0 ) then 129 | y = 1.0E-30_r8 130 | return 131 | end if 132 | a = (xa(khi)-x)/h 133 | b = (x-xa(klo))/h 134 | y = a*ya(klo) + b*ya(khi) + ((a*a*a-a)*y2a(klo) + & 135 | (b*b*b-b)*y2a(khi))*h*h/d_6 136 | end subroutine splint 137 | 138 | end module utils_spline 139 | -------------------------------------------------------------------------------- /reference/nrlmsise00_driver.for: -------------------------------------------------------------------------------- 1 | C TEST DRIVER FOR GTD7 (ATMOSPHERIC MODEL) 2 | DIMENSION D(9,16),T(2,16),SW(25),APH(7) 3 | DIMENSION IDAY(15),UT(15),ALT(15),XLAT(15),XLONG(15),XLST(15), 4 | & F107A(15),F107(15),AP(15) 5 | COMMON/GTS3C/DL(16) 6 | COMMON/DATIME/ISDATE(3),ISTIME(2),NAME(2) 7 | DATA IDAY/172,81,13*172/ 8 | DATA UT/29000.,29000.,75000.,12*29000./ 9 | DATA ALT/400.,400.,1000.,100.,6*400.,0,10.,30.,50.,70./ 10 | DATA XLAT/4*60.,0.,10*60./ 11 | DATA XLONG/5*-70.,0.,9*-70./ 12 | DATA XLST/6*16.,4.,8*16./ 13 | DATA F107A/7*150.,70.,7*150./ 14 | DATA F107/8*150.,180.,6*150./ 15 | DATA AP/9*4.,40.,5*4./ 16 | DATA APH/7*100./,SW/8*1.,-1.,16*1./ 17 | DO I=1,15 18 | CALL GTD7(IDAY(I),UT(I),ALT(I),XLAT(I),XLONG(I),XLST(I), 19 | & F107A(I),F107(I),AP(I),48,D(1,I),T(1,I)) 20 | WRITE(6,100) (D(J,I),J=1,9),T(1,I),T(2,I),DL 21 | ENDDO 22 | CALL TSELEC(SW) 23 | I=16 24 | CALL GTD7(IDAY(1),UT(1),ALT(1),XLAT(1),XLONG(1),XLST(1), 25 | & F107A(1),F107(1),APH,48,D(1,I),T(1,I)) 26 | WRITE(6,100) (D(J,I),J=1,9),T(1,I),T(2,I),DL 27 | CALL GTD7(IDAY(1),UT(1),ALT(4),XLAT(1),XLONG(1),XLST(1), 28 | & F107A(1),F107(1),APH,48,D(1,I),T(1,I)) 29 | WRITE(6,100) (D(J,I),J=1,9),T(1,I),T(2,I),DL 30 | WRITE(6,300) NAME,ISDATE,ISTIME 31 | WRITE(6,200) (IDAY(I),I=1,5) 32 | WRITE(6,201) (UT(I),I=1,5) 33 | WRITE(6,202) (ALT(I),I=1,5) 34 | WRITE(6,203) (XLAT(I),I=1,5) 35 | WRITE(6,204) (XLONG(I),I=1,5) 36 | WRITE(6,205) (XLST(I),I=1,5) 37 | WRITE(6,206) (F107A(I),I=1,5) 38 | WRITE(6,207) (F107(I),I=1,5) 39 | WRITE(6,208) (AP(I),I=1,5) 40 | WRITE(6,210) (T(1,I),I=1,5) 41 | WRITE(6,211) (T(2,I),I=1,5) 42 | WRITE(6,212) (D(1,I),I=1,5) 43 | WRITE(6,213) (D(2,I),I=1,5) 44 | WRITE(6,214) (D(3,I),I=1,5) 45 | WRITE(6,215) (D(4,I),I=1,5) 46 | WRITE(6,216) (D(5,I),I=1,5) 47 | WRITE(6,217) (D(7,I),I=1,5) 48 | WRITE(6,219) (D(8,I),I=1,5) 49 | WRITE(6,220) (D(9,I),I=1,5) 50 | WRITE(6,218) (D(6,I),I=1,5) 51 | WRITE(6,200) (IDAY(I),I=6,10) 52 | WRITE(6,201) (UT(I),I=6,10) 53 | WRITE(6,202) (ALT(I),I=6,10) 54 | WRITE(6,203) (XLAT(I),I=6,10) 55 | WRITE(6,204) (XLONG(I),I=6,10) 56 | WRITE(6,205) (XLST(I),I=6,10) 57 | WRITE(6,206) (F107A(I),I=6,10) 58 | WRITE(6,207) (F107(I),I=6,10) 59 | WRITE(6,208) (AP(I),I=6,10) 60 | WRITE(6,210) (T(1,I),I=6,10) 61 | WRITE(6,211) (T(2,I),I=6,10) 62 | WRITE(6,212) (D(1,I),I=6,10) 63 | WRITE(6,213) (D(2,I),I=6,10) 64 | WRITE(6,214) (D(3,I),I=6,10) 65 | WRITE(6,215) (D(4,I),I=6,10) 66 | WRITE(6,216) (D(5,I),I=6,10) 67 | WRITE(6,217) (D(7,I),I=6,10) 68 | WRITE(6,219) (D(8,I),I=6,10) 69 | WRITE(6,220) (D(9,I),I=6,10) 70 | WRITE(6,218) (D(6,I),I=6,10) 71 | WRITE(6,200) (IDAY(I),I=11,15) 72 | WRITE(6,201) (UT(I),I=11,15) 73 | WRITE(6,202) (ALT(I),I=11,15) 74 | WRITE(6,203) (XLAT(I),I=11,15) 75 | WRITE(6,204) (XLONG(I),I=11,15) 76 | WRITE(6,205) (XLST(I),I=11,15) 77 | WRITE(6,206) (F107A(I),I=11,15) 78 | WRITE(6,207) (F107(I),I=11,15) 79 | WRITE(6,208) (AP(I),I=11,15) 80 | WRITE(6,210) (T(1,I),I=11,15) 81 | WRITE(6,211) (T(2,I),I=11,15) 82 | WRITE(6,212) (D(1,I),I=11,15) 83 | WRITE(6,213) (D(2,I),I=11,15) 84 | WRITE(6,214) (D(3,I),I=11,15) 85 | WRITE(6,215) (D(4,I),I=11,15) 86 | WRITE(6,216) (D(5,I),I=11,15) 87 | WRITE(6,217) (D(7,I),I=11,15) 88 | WRITE(6,219) (D(8,I),I=11,15) 89 | WRITE(6,220) (D(9,I),I=11,15) 90 | WRITE(6,218) (D(6,I),I=11,15) 91 | 100 FORMAT(1X,1P8E9.2/4X,1PE9.2,2E10.3/4X,8E9.2/4X,8E9.2/) 92 | 200 FORMAT(//' DAY ',5I12) 93 | 201 FORMAT(' UT ',5F12.0) 94 | 202 FORMAT(' ALT ',5F12.0) 95 | 203 FORMAT(' LAT ',5F12.0) 96 | 204 FORMAT(' LONG ',5F12.0) 97 | 205 FORMAT(' LST ',5F12.0) 98 | 206 FORMAT(' F107A',5F12.0) 99 | 207 FORMAT(' F107 ',5F12.0) 100 | 208 FORMAT(' AP ',5F12.0) 101 | 210 FORMAT(/' TINF ',5F12.2) 102 | 211 FORMAT(' TG ',5F12.2) 103 | 212 FORMAT(' HE ',1P5E12.3) 104 | 213 FORMAT(' O ',1P5E12.3) 105 | 214 FORMAT(' N2 ',1P5E12.3) 106 | 215 FORMAT(' O2 ',1P5E12.3) 107 | 216 FORMAT(' AR ',1P5E12.3) 108 | 217 FORMAT(' H ',1P5E12.3) 109 | 219 FORMAT(' N ',1P5E12.3) 110 | 220 FORMAT(' ANM O',1P5E12.3) 111 | 218 FORMAT(' RHO ',1P5E12.3) 112 | 300 FORMAT(1X,2A4,2X,3A4,2X,2A4) 113 | STOP 114 | END 115 | -------------------------------------------------------------------------------- /reference/nrlmsise00_driver_ORIGINAL.for: -------------------------------------------------------------------------------- 1 | C TEST DRIVER FOR GTD7 (ATMOSPHERIC MODEL) 2 | DIMENSION D(9,16),T(2,16),SW(25),APH(7) 3 | DIMENSION IDAY(15),UT(15),ALT(15),XLAT(15),XLONG(15),XLST(15), 4 | & F107A(15),F107(15),AP(15) 5 | COMMON/GTS3C/DL(16) 6 | COMMON/DATIME/ISDATE(3),ISTIME(2),NAME(2) 7 | DATA IDAY/172,81,13*172/ 8 | DATA UT/29000.,29000.,75000.,12*29000./ 9 | DATA ALT/400.,400.,1000.,100.,6*400.,0,10.,30.,50.,70./ 10 | DATA XLAT/4*60.,0.,10*60./ 11 | DATA XLONG/5*-70.,0.,9*-70./ 12 | DATA XLST/6*16.,4.,8*16./ 13 | DATA F107A/7*150.,70.,7*150./ 14 | DATA F107/8*150.,180.,6*150./ 15 | DATA AP/9*4.,40.,5*4./ 16 | DATA APH/7*100./,SW/8*1.,-1.,16*1./ 17 | DO I=1,15 18 | CALL GTD7(IDAY(I),UT(I),ALT(I),XLAT(I),XLONG(I),XLST(I), 19 | & F107A(I),F107(I),AP(I),48,D(1,I),T(1,I)) 20 | WRITE(6,100) (D(J,I),J=1,9),T(1,I),T(2,I),DL 21 | ENDDO 22 | CALL TSELEC(SW) 23 | I=16 24 | CALL GTD7(IDAY(1),UT(1),ALT(1),XLAT(1),XLONG(1),XLST(1), 25 | & F107A(1),F107(1),APH,48,D(1,I),T(1,I)) 26 | WRITE(6,100) (D(J,I),J=1,9),T(1,I),T(2,I),DL 27 | CALL GTD7(IDAY(1),UT(1),ALT(4),XLAT(1),XLONG(1),XLST(1), 28 | & F107A(1),F107(1),APH,48,D(1,I),T(1,I)) 29 | WRITE(6,100) (D(J,I),J=1,9),T(1,I),T(2,I),DL 30 | WRITE(6,300) NAME,ISDATE,ISTIME 31 | WRITE(6,200) (IDAY(I),I=1,5) 32 | WRITE(6,201) (UT(I),I=1,5) 33 | WRITE(6,202) (ALT(I),I=1,5) 34 | WRITE(6,203) (XLAT(I),I=1,5) 35 | WRITE(6,204) (XLONG(I),I=1,5) 36 | WRITE(6,205) (XLST(I),I=1,5) 37 | WRITE(6,206) (F107A(I),I=1,5) 38 | WRITE(6,207) (F107(I),I=1,5) 39 | WRITE(6,208) (AP(I),I=1,5) 40 | WRITE(6,210) (T(1,I),I=1,5) 41 | WRITE(6,211) (T(2,I),I=1,5) 42 | WRITE(6,212) (D(1,I),I=1,5) 43 | WRITE(6,213) (D(2,I),I=1,5) 44 | WRITE(6,214) (D(3,I),I=1,5) 45 | WRITE(6,215) (D(4,I),I=1,5) 46 | WRITE(6,216) (D(5,I),I=1,5) 47 | WRITE(6,217) (D(7,I),I=1,5) 48 | WRITE(6,219) (D(8,I),I=1,5) 49 | WRITE(6,220) (D(9,I),I=1,5) 50 | WRITE(6,218) (D(6,I),I=1,5) 51 | WRITE(6,200) (IDAY(I),I=6,10) 52 | WRITE(6,201) (UT(I),I=6,10) 53 | WRITE(6,202) (ALT(I),I=6,10) 54 | WRITE(6,203) (XLAT(I),I=6,10) 55 | WRITE(6,204) (XLONG(I),I=6,10) 56 | WRITE(6,205) (XLST(I),I=6,10) 57 | WRITE(6,206) (F107A(I),I=6,10) 58 | WRITE(6,207) (F107(I),I=6,10) 59 | WRITE(6,208) (AP(I),I=6,10) 60 | WRITE(6,210) (T(1,I),I=6,10) 61 | WRITE(6,211) (T(2,I),I=6,10) 62 | WRITE(6,212) (D(1,I),I=6,10) 63 | WRITE(6,213) (D(2,I),I=6,10) 64 | WRITE(6,214) (D(3,I),I=6,10) 65 | WRITE(6,215) (D(4,I),I=6,10) 66 | WRITE(6,216) (D(5,I),I=6,10) 67 | WRITE(6,217) (D(7,I),I=6,10) 68 | WRITE(6,219) (D(8,I),I=6,10) 69 | WRITE(6,220) (D(9,I),I=6,10) 70 | WRITE(6,218) (D(6,I),I=6,10) 71 | WRITE(6,200) (IDAY(I),I=11,15) 72 | WRITE(6,201) (UT(I),I=11,15) 73 | WRITE(6,202) (ALT(I),I=11,15) 74 | WRITE(6,203) (XLAT(I),I=11,15) 75 | WRITE(6,204) (XLONG(I),I=11,15) 76 | WRITE(6,205) (XLST(I),I=11,15) 77 | WRITE(6,206) (F107A(I),I=11,15) 78 | WRITE(6,207) (F107(I),I=11,15) 79 | WRITE(6,208) (AP(I),I=11,15) 80 | WRITE(6,210) (T(1,I),I=11,15) 81 | WRITE(6,211) (T(2,I),I=11,15) 82 | WRITE(6,212) (D(1,I),I=11,15) 83 | WRITE(6,213) (D(2,I),I=11,15) 84 | WRITE(6,214) (D(3,I),I=11,15) 85 | WRITE(6,215) (D(4,I),I=11,15) 86 | WRITE(6,216) (D(5,I),I=11,15) 87 | WRITE(6,217) (D(7,I),I=11,15) 88 | WRITE(6,219) (D(8,I),I=11,15) 89 | WRITE(6,220) (D(9,I),I=11,15) 90 | WRITE(6,218) (D(6,I),I=11,15) 91 | 100 FORMAT(1X,1P8E9.2/4X,1PE9.2,2E10.3/4X,8E9.2/4X,8E9.2/) 92 | 200 FORMAT(//' DAY ',5I12) 93 | 201 FORMAT(' UT ',5F12.0) 94 | 202 FORMAT(' ALT ',5F12.0) 95 | 203 FORMAT(' LAT ',5F12.0) 96 | 204 FORMAT(' LONG ',5F12.0) 97 | 205 FORMAT(' LST ',5F12.0) 98 | 206 FORMAT(' F107A',5F12.0) 99 | 207 FORMAT(' F107 ',5F12.0) 100 | 208 FORMAT(' AP ',5F12.0) 101 | 210 FORMAT(/' TINF ',5F12.2) 102 | 211 FORMAT(' TG ',5F12.2) 103 | 212 FORMAT(' HE ',1P5E12.3) 104 | 213 FORMAT(' O ',1P5E12.3) 105 | 214 FORMAT(' N2 ',1P5E12.3) 106 | 215 FORMAT(' O2 ',1P5E12.3) 107 | 216 FORMAT(' AR ',1P5E12.3) 108 | 217 FORMAT(' H ',1P5E12.3) 109 | 219 FORMAT(' N ',1P5E12.3) 110 | 220 FORMAT(' ANM O',1P5E12.3) 111 | 218 FORMAT(' RHO ',1P5E12.3) 112 | 300 FORMAT(1X,2A4,2X,3A4,2X,2A4) 113 | STOP 114 | END 115 | -------------------------------------------------------------------------------- /reference/testgtd7.f90: -------------------------------------------------------------------------------- 1 | program testgtd7 2 | use utils_constants 3 | use physics_msis 4 | implicit none 5 | ! 6 | real(dp) , dimension(15) :: alt , ap , f107 , f107a , ut , xlat , & 7 | & xlong , xlst 8 | real(dp) , dimension(7) :: aph 9 | real(dp) , dimension(9,16) :: d 10 | integer :: i , j 11 | integer , dimension(15) :: iday 12 | real(dp) , dimension(25) :: sw 13 | real(dp) , dimension(2,16) :: t 14 | ! 15 | ! TEST DRIVER FOR GTD7 (ATMOSPHERIC MODEL) 16 | data iday/172 , 81 , 13*172/ 17 | data ut/29000. , 29000. , 75000. , 12*29000./ 18 | data alt/400. , 400. , 1000. , 100. , 6*400. , 0 , 10. , 30. , & 19 | & 50. , 70./ 20 | data xlat/4*60. , 0. , 10*60./ 21 | data xlong/5* - 70. , 0. , 9* - 70./ 22 | data xlst/6*16. , 4. , 8*16./ 23 | data f107a/7*150. , 70. , 7*150./ 24 | data f107/8*150. , 180. , 6*150./ 25 | data ap/9*4. , 40. , 5*4./ 26 | data aph/7*100./ , sw/8*1. , -1. , 16*1./ 27 | do i = 1 , 15 28 | call gtd7(iday(i),ut(i),alt(i),xlat(i),xlong(i),xlst(i),f107a(i)& 29 | & ,f107(i),ap(i),48,d(:,i),t(:,i)) 30 | write (6,99001) (d(j,i),j=1,9) , t(1,i) , t(2,i) , & 31 | TLB,S,DB04,DB16,DB28,DB32,DB40,DB48,DB01,ZA,T0,Z0, & 32 | XG0,RL,DD,DB14 33 | end do 34 | call tselec(sw) 35 | i = 16 36 | call gtd7(iday(1),ut(1),alt(1),xlat(1),xlong(1),xlst(1),f107a(1), & 37 | & f107(1),aph,48,d(:,i),t(:,i)) 38 | write (6,99001) (d(j,i),j=1,9) , t(1,i) , t(2,i) , & 39 | TLB,S,DB04,DB16,DB28,DB32,DB40,DB48,DB01,ZA,T0,Z0, & 40 | XG0,RL,DD,DB14 41 | call gtd7(iday(1),ut(1),alt(4),xlat(1),xlong(1),xlst(1),f107a(1), & 42 | & f107(1),aph,48,d(:,i),t(:,i)) 43 | write (6,99001) (d(j,i),j=1,9) , t(1,i) , t(2,i) , & 44 | TLB,S,DB04,DB16,DB28,DB32,DB40,DB48,DB01,ZA,T0,Z0, & 45 | XG0,RL,DD,DB14 46 | write (6,99022) chname , isdate , istime 47 | write (6,99002) (iday(i),i=1,5) 48 | write (6,99003) (ut(i),i=1,5) 49 | write (6,99004) (alt(i),i=1,5) 50 | write (6,99005) (xlat(i),i=1,5) 51 | write (6,99006) (xlong(i),i=1,5) 52 | write (6,99007) (xlst(i),i=1,5) 53 | write (6,99008) (f107a(i),i=1,5) 54 | write (6,99009) (f107(i),i=1,5) 55 | write (6,99010) (ap(i),i=1,5) 56 | write (6,99011) (t(1,i),i=1,5) 57 | write (6,99012) (t(2,i),i=1,5) 58 | write (6,99013) (d(1,i),i=1,5) 59 | write (6,99014) (d(2,i),i=1,5) 60 | write (6,99015) (d(3,i),i=1,5) 61 | write (6,99016) (d(4,i),i=1,5) 62 | write (6,99017) (d(5,i),i=1,5) 63 | write (6,99018) (d(7,i),i=1,5) 64 | write (6,99019) (d(8,i),i=1,5) 65 | write (6,99020) (d(9,i),i=1,5) 66 | write (6,99021) (d(6,i),i=1,5) 67 | write (6,99002) (iday(i),i=6,10) 68 | write (6,99003) (ut(i),i=6,10) 69 | write (6,99004) (alt(i),i=6,10) 70 | write (6,99005) (xlat(i),i=6,10) 71 | write (6,99006) (xlong(i),i=6,10) 72 | write (6,99007) (xlst(i),i=6,10) 73 | write (6,99008) (f107a(i),i=6,10) 74 | write (6,99009) (f107(i),i=6,10) 75 | write (6,99010) (ap(i),i=6,10) 76 | write (6,99011) (t(1,i),i=6,10) 77 | write (6,99012) (t(2,i),i=6,10) 78 | write (6,99013) (d(1,i),i=6,10) 79 | write (6,99014) (d(2,i),i=6,10) 80 | write (6,99015) (d(3,i),i=6,10) 81 | write (6,99016) (d(4,i),i=6,10) 82 | write (6,99017) (d(5,i),i=6,10) 83 | write (6,99018) (d(7,i),i=6,10) 84 | write (6,99019) (d(8,i),i=6,10) 85 | write (6,99020) (d(9,i),i=6,10) 86 | write (6,99021) (d(6,i),i=6,10) 87 | write (6,99002) (iday(i),i=11,15) 88 | write (6,99003) (ut(i),i=11,15) 89 | write (6,99004) (alt(i),i=11,15) 90 | write (6,99005) (xlat(i),i=11,15) 91 | write (6,99006) (xlong(i),i=11,15) 92 | write (6,99007) (xlst(i),i=11,15) 93 | write (6,99008) (f107a(i),i=11,15) 94 | write (6,99009) (f107(i),i=11,15) 95 | write (6,99010) (ap(i),i=11,15) 96 | write (6,99011) (t(1,i),i=11,15) 97 | write (6,99012) (t(2,i),i=11,15) 98 | write (6,99013) (d(1,i),i=11,15) 99 | write (6,99014) (d(2,i),i=11,15) 100 | write (6,99015) (d(3,i),i=11,15) 101 | write (6,99016) (d(4,i),i=11,15) 102 | write (6,99017) (d(5,i),i=11,15) 103 | write (6,99018) (d(7,i),i=11,15) 104 | write (6,99019) (d(8,i),i=11,15) 105 | write (6,99020) (d(9,i),i=11,15) 106 | write (6,99021) (d(6,i),i=11,15) 107 | 99001 format (1x,1P8e9.2/4x,1pe9.2,2E10.3/4x,8E9.2/4x,8E9.2/) 108 | 99002 format (//' DAY ',5I12) 109 | 99003 format (' UT ',5F12.0) 110 | 99004 format (' ALT ',5F12.0) 111 | 99005 format (' LAT ',5F12.0) 112 | 99006 format (' LONG ',5F12.0) 113 | 99007 format (' LST ',5F12.0) 114 | 99008 format (' F107A',5F12.0) 115 | 99009 format (' F107 ',5F12.0) 116 | 99010 format (' AP ',5F12.0) 117 | 99011 format (/' TINF ',5F12.2) 118 | 99012 format (' TG ',5F12.2) 119 | 99013 format (' HE ',1P5e12.3) 120 | 99014 format (' O ',1P5e12.3) 121 | 99015 format (' N2 ',1P5e12.3) 122 | 99016 format (' O2 ',1P5e12.3) 123 | 99017 format (' AR ',1P5e12.3) 124 | 99018 format (' H ',1P5e12.3) 125 | 99019 format (' N ',1P5e12.3) 126 | 99020 format (' ANM O',1P5e12.3) 127 | 99021 format (' RHO ',1P5e12.3) 128 | 99022 format (1x,2A4,2x,3A4,2x,2A4) 129 | end program testgtd7 130 | -------------------------------------------------------------------------------- /reference/utils_constants.f90: -------------------------------------------------------------------------------- 1 | module utils_constants 2 | 3 | public 4 | 5 | ! Kind helpers 6 | integer , parameter :: dp = kind(1.0D0) 7 | integer , parameter :: sp = kind(1.0) 8 | integer , parameter :: r8 = kind(1.0D0) 9 | integer , parameter :: r4 = kind(1.0) 10 | integer , parameter :: shortint = 2 11 | integer , parameter :: normint = 4 12 | integer , parameter :: longint = 8 13 | 14 | ! Numbers 1-10 15 | real(dp) , parameter :: d_0 = 0.0_r8 16 | real(dp) , parameter :: d_1 = 1.0_r8 17 | real(dp) , parameter :: d_2 = 2.0_r8 18 | real(dp) , parameter :: d_3 = 3.0_r8 19 | real(dp) , parameter :: d_4 = 4.0_r8 20 | real(dp) , parameter :: d_5 = 5.0_r8 21 | real(dp) , parameter :: d_6 = 6.0_r8 22 | real(dp) , parameter :: d_7 = 7.0_r8 23 | real(dp) , parameter :: d_8 = 8.0_r8 24 | real(dp) , parameter :: d_9 = 9.0_r8 25 | real(dp) , parameter :: d_10 = 10.0_r8 26 | real(dp) , parameter :: d_16 = 16.0_r8 27 | real(dp) , parameter :: d_32 = 32.0_r8 28 | 29 | ! Simple Fractions 30 | real(dp) , parameter :: d_half = d_1/d_2 31 | 32 | real(dp) , parameter :: d_1q2 = d_1/d_2 33 | real(dp) , parameter :: d_3q2 = d_3/d_2 34 | real(dp) , parameter :: d_5q2 = d_5/d_2 35 | real(dp) , parameter :: d_7q2 = d_7/d_2 36 | real(dp) , parameter :: d_9q2 = d_9/d_2 37 | real(dp) , parameter :: d_1q3 = d_1/d_3 38 | real(dp) , parameter :: d_2q3 = d_2/d_3 39 | real(dp) , parameter :: d_4q3 = d_4/d_3 40 | real(dp) , parameter :: d_5q3 = d_5/d_3 41 | real(dp) , parameter :: d_1q4 = d_1/d_4 42 | real(dp) , parameter :: d_3q4 = d_3/d_4 43 | real(dp) , parameter :: d_5q4 = d_5/d_4 44 | real(dp) , parameter :: d_7q4 = d_7/d_4 45 | real(dp) , parameter :: d_1q5 = d_1/d_5 46 | real(dp) , parameter :: d_2q5 = d_2/d_5 47 | real(dp) , parameter :: d_3q5 = d_3/d_5 48 | real(dp) , parameter :: d_4q5 = d_4/d_5 49 | real(dp) , parameter :: d_6q5 = d_6/d_5 50 | real(dp) , parameter :: d_7q5 = d_7/d_5 51 | 52 | ! 100 and 1000 and their inverse 53 | real(dp) , parameter :: d_100 = 100.0_r8 54 | real(dp) , parameter :: d_1000 = 1000.0_r8 55 | real(dp) , parameter :: d_r100 = 0.01_r8 56 | real(dp) , parameter :: d_r1000 = 0.001_r8 57 | 58 | ! Power of 10 59 | real(dp) , parameter :: d_10E1 = 10.0_r8 60 | real(dp) , parameter :: d_10E2 = 100.0_r8 61 | real(dp) , parameter :: d_10E3 = 1000.0_r8 62 | real(dp) , parameter :: d_10E4 = 10000.0_r8 63 | real(dp) , parameter :: d_10E5 = 100000.0_r8 64 | real(dp) , parameter :: d_10E6 = 1000000.0_r8 65 | real(dp) , parameter :: d_10E7 = 10000000.0_r8 66 | real(dp) , parameter :: d_10E8 = 100000000.0_r8 67 | real(dp) , parameter :: d_10E9 = 1000000000.0_r8 68 | real(dp) , parameter :: d_10E10 = 10000000000.0_r8 69 | real(dp) , parameter :: d_10E11 = 100000000000.0_r8 70 | real(dp) , parameter :: d_10E12 = 1000000000000.0_r8 71 | real(dp) , parameter :: d_10E13 = 10000000000000.0_r8 72 | real(dp) , parameter :: d_10EM1 = 0.1_r8 73 | real(dp) , parameter :: d_10EM2 = 0.01_r8 74 | real(dp) , parameter :: d_10EM3 = 0.001_r8 75 | real(dp) , parameter :: d_10EM4 = 0.0001_r8 76 | real(dp) , parameter :: d_10EM5 = 0.00001_r8 77 | real(dp) , parameter :: d_10EM6 = 0.000001_r8 78 | real(dp) , parameter :: d_10EM7 = 0.0000001_r8 79 | real(dp) , parameter :: d_10EM8 = 0.00000001_r8 80 | real(dp) , parameter :: d_10EM9 = 0.000000001_r8 81 | real(dp) , parameter :: d_10EM10 = 0.0000000001_r8 82 | real(dp) , parameter :: d_10EM11 = 0.00000000001_r8 83 | real(dp) , parameter :: d_10EM12 = 0.000000000001_r8 84 | real(dp) , parameter :: d_10EM13 = 0.0000000000001_r8 85 | 86 | ! Time related constants 87 | real(dp) , parameter :: d_seconds_per_hour = 3600.0_r8 88 | real(sp) , parameter :: s_seconds_per_hour = 3600.0 89 | integer , parameter :: i_seconds_per_hour = 3600 90 | 91 | real(dp) , parameter :: d_seconds_per_minute = 60.0_r8 92 | real(sp) , parameter :: s_seconds_per_minute = 60.0 93 | integer , parameter :: i_seconds_per_minute = 60 94 | 95 | real(dp) , parameter :: d_minutes_per_hour = 60.0_r8 96 | real(sp) , parameter :: s_minutes_per_hour = 60.0 97 | integer , parameter :: i_minutes_per_hour = 60 98 | 99 | real(dp) , parameter :: d_hours_per_day = 24.0_r8 100 | real(sp) , parameter :: s_hours_per_day = 24.0 101 | integer , parameter :: i_hours_per_day = 24 102 | 103 | real(dp) , parameter :: d_minutes_per_day = 1440.0_r8 104 | real(sp) , parameter :: s_minutes_per_day = 1440.0 105 | integer , parameter :: i_minutes_per_day = 1440 106 | 107 | real(dp) , parameter :: d_seconds_per_day = 86400.0_r8 108 | real(sp) , parameter :: s_seconds_per_day = 86400.0 109 | integer , parameter :: i_seconds_per_day = 86400 110 | 111 | real(dp) , parameter :: d_months_per_year = 12.0_r8 112 | real(sp) , parameter :: s_months_per_year = 12.0 113 | integer , parameter :: i_months_per_year = 12 114 | 115 | ! Degrees helpers 116 | real(dp) , parameter :: d_000 = 0.0D0 117 | real(dp) , parameter :: d_045 = 45.0D0 118 | real(dp) , parameter :: d_090 = 90.0D0 119 | real(dp) , parameter :: d_180 = 180.0D0 120 | real(dp) , parameter :: d_360 = 360.0D0 121 | 122 | ! Trigonometric 123 | real(dp) , parameter :: mathpi = 3.1415926535897932384626433832795029_r8 124 | real(dp) , parameter :: invpi = d_1/mathpi 125 | real(dp) , parameter :: twopi = d_2*mathpi 126 | real(dp) , parameter :: halfpi = d_1q2*mathpi 127 | real(dp) , parameter :: deg2rad = mathpi/d_180 128 | real(dp) , parameter :: rad2deg = d_180/mathpi 129 | 130 | integer , parameter :: maxpath = 256 131 | 132 | end module utils_constants 133 | -------------------------------------------------------------------------------- /src/msise00/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | Call NRL MSISE-00 using f2py from Python 3 | 4 | Original fortran code from 5 | http://nssdcftp.gsfc.nasa.gov/models/atmospheric/msis/nrlmsise00/ 6 | """ 7 | 8 | from __future__ import annotations 9 | import typing as T 10 | import os 11 | import logging 12 | import importlib.resources 13 | from datetime import datetime, date 14 | import xarray 15 | import numpy as np 16 | import subprocess 17 | import shutil 18 | 19 | from .timeutils import todatetime 20 | 21 | import geomagindices as gi 22 | 23 | 24 | species = ["He", "O", "N2", "O2", "Ar", "Total", "H", "N", "AnomalousO"] 25 | ttypes = ["Texo", "Tn"] 26 | first = True 27 | 28 | 29 | def build(): 30 | """ 31 | attempt to build using CMake 32 | """ 33 | cmake = shutil.which("cmake") 34 | if not cmake: 35 | raise FileNotFoundError("CMake not available") 36 | 37 | with importlib.resources.as_file( 38 | importlib.resources.files(__package__) / "CMakeLists.txt" 39 | ) as f: 40 | s = f.parent 41 | b = s / "build" 42 | g = [] 43 | 44 | if os.name == "nt" and not os.environ.get("CMAKE_GENERATOR"): 45 | g = ["-G", "MinGW Makefiles"] 46 | 47 | subprocess.check_call([cmake, f"-S{s}", f"-B{b}"] + g) 48 | subprocess.check_call([cmake, "--build", str(b), "--parallel"]) 49 | 50 | 51 | def run( 52 | time: datetime, 53 | altkm, 54 | glat, 55 | glon, 56 | indices: dict[str, T.Any] | None = None, 57 | ): 58 | """ 59 | loops the rungtd1d function below. Figure it's easier to troubleshoot in Python than Fortran. 60 | """ 61 | glat = np.atleast_2d(glat) 62 | glon = np.atleast_2d(glon) # has to be here 63 | # %% altitude 1-D 64 | if glat.size == 1 and glon.size == 1 and isinstance(time, (str, date, datetime, np.datetime64)): 65 | atmos = rungtd1d(time, altkm, glat.squeeze()[()], glon.squeeze()[()], indices) 66 | # %% lat/lon grid at 1 altitude 67 | else: 68 | atmos = loopalt_gtd(time, glat, glon, altkm, indices) 69 | 70 | return atmos 71 | 72 | 73 | def loopalt_gtd( 74 | time: datetime, 75 | glat, 76 | glon, 77 | altkm, 78 | indices: dict[str, T.Any] | None = None, 79 | ): 80 | """ 81 | loop over location and time 82 | 83 | time: datetime or numpy.datetime64 or list of datetime or ndarray of datetime 84 | glat: float or 2-D ndarray 85 | glon: float or 2-D ndarray 86 | altkm: float or list or 1-D ndarray 87 | """ 88 | glat = np.atleast_2d(glat) 89 | glon = np.atleast_2d(glon) 90 | assert glat.ndim == glon.ndim == 2 91 | 92 | times = np.atleast_1d(time) # type: ignore 93 | assert times.ndim == 1 94 | 95 | atmos = xarray.Dataset() 96 | 97 | for t in times: 98 | print("computing", t) 99 | for i in range(glat.shape[0]): 100 | for j in range(glat.shape[1]): 101 | # atmos = xarray.concat((atmos, rungtd1d(t, altkm, glat[i,j], glon[i,j])), 102 | # data_vars='minimal',coords='minimal',dim='lon') 103 | atm = rungtd1d(t, altkm, glat[i, j], glon[i, j], indices) 104 | atmos = xarray.merge((atmos, atm)) 105 | 106 | atmos.attrs = atm.attrs 107 | 108 | return atmos 109 | 110 | 111 | def rungtd1d(time: datetime, altkm, glat, glon, indices: dict[str, T.Any] | None = None): 112 | """ 113 | This is the "atomic" function looped by other functions 114 | """ 115 | time = todatetime(time) 116 | # %% get solar parameters for date 117 | if not indices: 118 | indices = gi.get_indices(time, smoothdays=81).squeeze().to_dict() 119 | assert isinstance(indices, dict) 120 | # %% dimensions 121 | altkm = np.atleast_1d(altkm) 122 | if altkm.ndim != 1: 123 | raise ValueError("altitude read incorrectly") 124 | if not isinstance(glon, (int, float, np.int32, np.int64)): 125 | raise TypeError("single longitude only") 126 | if not isinstance(glat, (int, float, np.int32, np.int64)): 127 | raise TypeError("single latitude only") 128 | 129 | # %% 130 | doy = time.strftime("%j") 131 | altkm = np.atleast_1d(altkm) 132 | # %% 133 | dens = np.empty((altkm.size, len(species))) 134 | temp = np.empty((altkm.size, len(ttypes))) 135 | # %% build on run 136 | exe_name = "msise00_driver" 137 | if os.name == "nt": 138 | exe_name += ".exe" 139 | 140 | f107s = indices["f107s"] 141 | 142 | f107 = indices["f107"] 143 | 144 | Ap = indices["Ap"] 145 | 146 | exe = importlib.resources.files(__package__) / exe_name 147 | if not exe.is_file(): 148 | build() 149 | 150 | for i, a in enumerate(altkm): 151 | cmd = [ 152 | str(exe), 153 | doy, 154 | str(time.hour), 155 | str(time.minute), 156 | str(time.second), 157 | str(glat), 158 | str(glon), 159 | str(f107s), 160 | str(f107), 161 | str(Ap), 162 | str(a), 163 | ] 164 | 165 | logging.info(" ".join(cmd)) 166 | 167 | ret = subprocess.run(cmd, capture_output=True, text=True) 168 | if ret.returncode != 0: 169 | logging.error(ret.stderr) 170 | return xarray.Dataset() 171 | 172 | # different compilers throw in extra \n 173 | raw = list(map(float, ret.stdout.split())) 174 | if not len(raw) == 9 + 2: 175 | raise ValueError(ret) 176 | dens[i, :] = raw[:9] 177 | temp[i, :] = raw[9:] 178 | 179 | dsf = { 180 | k: (("time", "alt_km", "lat", "lon"), v[None, :, None, None]) 181 | for (k, v) in zip(species, dens.T) 182 | } 183 | dsf.update( 184 | { 185 | "Tn": (("time", "alt_km", "lat", "lon"), temp[:, 1][None, :, None, None]), 186 | "Texo": (("time", "alt_km", "lat", "lon"), temp[:, 0][None, :, None, None]), 187 | } 188 | ) 189 | 190 | atmos = xarray.Dataset( 191 | dsf, # type: ignore 192 | coords={"time": [time], "alt_km": altkm, "lat": [glat], "lon": [glon]}, 193 | attrs={ 194 | "species": species, 195 | "f107s": indices["f107s"], 196 | "f107": indices["f107"], 197 | "Ap": indices["Ap"], 198 | }, 199 | ) 200 | 201 | return atmos 202 | -------------------------------------------------------------------------------- /src/msise00/plots.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from pathlib import Path 3 | from datetime import datetime 4 | from matplotlib.pyplot import figure, close 5 | from matplotlib.ticker import ScalarFormatter 6 | 7 | try: 8 | from pymap3d import aer2geodetic 9 | except ImportError: 10 | aer2geodetic = None 11 | try: 12 | from astropy.time import Time 13 | from astropy.coordinates import get_sun, EarthLocation, AltAz 14 | except ImportError: 15 | Time = None 16 | 17 | sfmt = ScalarFormatter(useMathText=True) # for 10^3 instead of 1e3 18 | sfmt.set_powerlimits((-2, 2)) 19 | sfmt.set_scientific(True) 20 | sfmt.set_useOffset(False) 21 | 22 | 23 | def plotgtd(atmos, rodir: Path | None = None): 24 | # 25 | if rodir: 26 | rodir = Path(rodir).expanduser() 27 | 28 | atmos = atmos.squeeze() 29 | tmp = atmos["N2"] 30 | 31 | if tmp.ndim == 1: 32 | if "alt_km" in tmp.dims: 33 | plot1dalt(atmos) 34 | elif "time" in tmp.dims: 35 | plot1dtime(atmos) 36 | else: 37 | raise NotImplementedError( 38 | "didnt handle this plotting case yet. Should be straightforward." 39 | ) 40 | elif tmp.ndim == 2: 41 | if "lat" in tmp.dims and "lon" in tmp.dims: 42 | plot2dlatlon(atmos, rodir) 43 | elif "time" in tmp.dims: 44 | for t in atmos.time: 45 | plot1dalt(atmos.sel(time=t), rodir) 46 | else: 47 | raise NotImplementedError( 48 | "didnt handle this plotting case yet. Should be straightforward." 49 | ) 50 | elif tmp.ndim in (3, 4): # lat/lon grid vs. time 51 | plot4d(atmos, rodir) 52 | else: # single point 53 | print(atmos) 54 | 55 | 56 | def plot4d(atmos, rodir: Path | None = None): 57 | 58 | for t in atmos.time: 59 | if Time is not None and aer2geodetic is not None: 60 | time = Time(str(t.values)) 61 | obs = EarthLocation(0, 0) # geodetic lat,lon = 0,0 arbitrary 62 | sun = get_sun(time=time) 63 | aaf = AltAz(obstime=time, location=obs) 64 | sloc = sun.transform_to(aaf) 65 | slat, slon = aer2geodetic(sloc.az.value, sloc.alt.value, sloc.distance.value, 0, 0, 0)[ 66 | :2 67 | ] 68 | plot2dlatlon(atmos.sel(time=t), rodir, slat, slon) 69 | else: 70 | plot2dlatlon(atmos.sel(time=t), rodir) 71 | 72 | 73 | def plot2dlatlon( 74 | atmos, rodir: Path | None = None, slat: float | None = None, slon: float | None = None 75 | ): 76 | 77 | fg = figure(figsize=(8, 8)) 78 | ax = fg.subplots(4, 2, sharex=True).ravel() 79 | 80 | fg.suptitle( 81 | str(atmos.time.values.squeeze())[:-13] + f" alt.(km) {atmos.alt_km.item()}\n" 82 | f"Ap={atmos.Ap} F10.7={atmos.f107}" 83 | ) 84 | 85 | j = 0 86 | 87 | for s in atmos.species: 88 | if s == "Total": 89 | continue 90 | 91 | a = ax[j] 92 | 93 | hi = a.imshow( 94 | atmos[s].squeeze(), 95 | aspect="auto", 96 | interpolation="none", 97 | cmap="viridis", 98 | extent=(atmos.lon[0], atmos.lon[-1], atmos.lat[0], atmos.lat[-1]), 99 | ) 100 | 101 | fg.colorbar(hi, ax=a, format=sfmt) 102 | # %% sun icon moving 103 | if slat is not None and slon is not None: 104 | a.plot(slon, slat, linestyle="none", marker="o", markersize=5, color="w") 105 | 106 | a.set_title(f"Density: {s}") 107 | a.set_xlim(-180, 180) 108 | a.set_ylim(-90, 90) 109 | a.autoscale(False) 110 | j += 1 111 | 112 | for k in range(0, 6 + 2, 2): 113 | ax[k].set_ylabel("latitude (deg)") 114 | for k in (6, 7): 115 | ax[k].set_xlabel("longitude (deg)") 116 | 117 | if rodir: 118 | ofn = rodir / ( 119 | f"{atmos.alt_km.item():.1f}_" + str(atmos.time.values.squeeze())[:-13] + ".png" 120 | ) 121 | writeplot(fg, ofn) 122 | 123 | 124 | def plot1dalt(atmos, odir: Path | None = None): 125 | 126 | footer = f"\n({atmos.lat.item()},{atmos.lon.item()}) Ap {atmos.Ap} F10.7 {atmos.f107}" 127 | 128 | z = atmos.alt_km.values 129 | 130 | # %% number density 131 | fg = figure() 132 | ax = fg.gca() 133 | for s in atmos.species: 134 | if s == "Total": 135 | continue 136 | ax.semilogx(atmos[s].squeeze(), z, label=s) 137 | ax.legend(loc="best") 138 | ax.set_xlim(left=1e3) 139 | ax.set_ylabel("altitude [km]") 140 | ax.set_xlabel("density [m$^{-3}$]") 141 | ax.grid(True) 142 | ax.set_title("Number Density from MSISE-00" + footer) 143 | if odir: 144 | ofn = odir / ("number-density_" + str(atmos.time.values.squeeze())[:-13] + ".png") 145 | writeplot(fg, ofn) 146 | 147 | # %% total mass 148 | fg = figure() 149 | ax = fg.gca() 150 | ax.semilogx(atmos["Total"].squeeze(), z) 151 | ax.set_xlabel("Total Mass Density [kg m$^{-3}$]") 152 | ax.set_ylabel("altitude [km]") 153 | ax.grid(True) 154 | ax.set_title("Total Mass Density from MSISE-00" + footer) 155 | 156 | if odir: 157 | ofn = odir / ("total-density_" + str(atmos.time.values.squeeze())[:-13] + ".png") 158 | writeplot(fg, ofn) 159 | 160 | # %% temperature 161 | fg = figure() 162 | ax = fg.gca() 163 | ax.plot(atmos["Tn"].squeeze(), z) 164 | ax.set_xlabel("Temperature [K]") 165 | ax.set_ylabel("altitude [km]") 166 | ax.grid(True) 167 | ax.set_title("Temperature from MSISE-00" + footer) 168 | 169 | if odir: 170 | ofn = odir / ("temperature_" + str(atmos.time.values.squeeze())[:-13] + ".png") 171 | writeplot(fg, ofn) 172 | 173 | 174 | def plot1dtime(atmos, odir: Path | None = None): 175 | 176 | footer = f"\n({atmos.lat.item()},{atmos.lon.item()}) alt: {atmos.alt_km.item()} km, Ap {atmos.Ap} F10.7 {atmos.f107}" 177 | 178 | t = atmos.time.values.astype("datetime64[us]").astype(datetime) 179 | 180 | # %% number density 181 | fg = figure() 182 | ax = fg.gca() 183 | for s in atmos.species: 184 | if s == "Total": 185 | continue 186 | ax.plot(t, atmos[s].squeeze(), label=s) 187 | ax.legend(loc="best") 188 | ax.set_ylabel("density [m$^{-3}$]") 189 | ax.set_xlabel("time [UTC]") 190 | ax.grid(True) 191 | ax.set_title("Number Density from MSISE-00" + footer) 192 | if odir: 193 | ofn = odir / ("number-density_" + str(atmos.time.values.squeeze())[:-13] + ".png") 194 | writeplot(fg, ofn) 195 | 196 | # %% total mass 197 | fg = figure() 198 | ax = fg.gca() 199 | ax.plot(t, atmos["Total"].squeeze()) 200 | ax.set_ylabel("Total Mass Density [kg m$^{-3}$]") 201 | ax.set_xlabel("time [UTC]") 202 | ax.grid(True) 203 | ax.set_title("Total Mass Density from MSISE-00" + footer) 204 | 205 | if odir: 206 | ofn = odir / ("total-density_" + str(atmos.time.values.squeeze())[:-13] + ".png") 207 | writeplot(fg, ofn) 208 | 209 | # %% temperature 210 | fg = figure() 211 | ax = fg.gca() 212 | ax.plot(t, atmos["Tn"].squeeze()) 213 | ax.set_ylabel("Temperature [K]") 214 | ax.set_xlabel("time [UTC]") 215 | ax.grid(True) 216 | ax.set_title("Temperature from MSISE-00" + footer) 217 | 218 | if odir: 219 | ofn = odir / ("temperature_" + str(atmos.time.values.squeeze())[:-13] + ".png") 220 | writeplot(fg, ofn) 221 | 222 | 223 | def writeplot(fg, ofn: Path): 224 | print("writing", ofn) 225 | fg.savefig(ofn, dpi=100, bbox_inches="tight") 226 | close(fg) 227 | -------------------------------------------------------------------------------- /src/msise00/fortran/msise00_data.f: -------------------------------------------------------------------------------- 1 | module msise00_data 2 | 3 | private 4 | public :: parm7g, ptm, pdm, pavgm, imr 5 | 6 | C MSISE-00 01-FEB-02 7 | COMMON/PARM7g/PT1(50),PT2(50),PT3(50),PA1(50),PA2(50),PA3(50), 8 | $ PB1(50),PB2(50),PB3(50),PC1(50),PC2(50),PC3(50), 9 | $ PD1(50),PD2(50),PD3(50),PE1(50),PE2(50),PE3(50), 10 | $ PF1(50),PF2(50),PF3(50),PG1(50),PG2(50),PG3(50), 11 | $ PH1(50),PH2(50),PH3(50),PI1(50),PI2(50),PI3(50), 12 | $ PJ1(50),PJ2(50),PJ3(50),PK1(50),PL1(50),PL2(50), 13 | $ PM1(50),PM2(50),PN1(50),PN2(50),PO1(50),PO2(50), 14 | $ PP1(50),PP2(50),PQ1(50),PQ2(50),PR1(50),PR2(50), 15 | $ PS1(50),PS2(50),PU1(50),PU2(50),PV1(50),PV2(50), 16 | $ PW1(50),PW2(50),PX1(50),PX2(50),PY1(50),PY2(50), 17 | $ PZ1(50),PZ2(50),PAA1(50),PAA2(50) 18 | real :: PTM(10),PDM(10,8) 19 | real :: PAVGM(10) 20 | 21 | integer :: IMR = 0 22 | 23 | C TEMPERATURE 24 | DATA PT1/ 25 | * 9.86573E-01, 1.62228E-02, 1.55270E-02,-1.04323E-01,-3.75801E-03, 26 | * -1.18538E-03,-1.24043E-01, 4.56820E-03, 8.76018E-03,-1.36235E-01, 27 | * -3.52427E-02, 8.84181E-03,-5.92127E-03,-8.61650E+00, 0.00000E+00, 28 | * 1.28492E-02, 0.00000E+00, 1.30096E+02, 1.04567E-02, 1.65686E-03, 29 | * -5.53887E-06, 2.97810E-03, 0.00000E+00, 5.13122E-03, 8.66784E-02, 30 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.27026E-06, 31 | * 0.00000E+00, 6.74494E+00, 4.93933E-03, 2.21656E-03, 2.50802E-03, 32 | * 0.00000E+00, 0.00000E+00,-2.08841E-02,-1.79873E+00, 1.45103E-03, 33 | * 2.81769E-04,-1.44703E-03,-5.16394E-05, 8.47001E-02, 1.70147E-01, 34 | * 5.72562E-03, 5.07493E-05, 4.36148E-03, 1.17863E-04, 4.74364E-03/ 35 | DATA PT2/ 36 | * 6.61278E-03, 4.34292E-05, 1.44373E-03, 2.41470E-05, 2.84426E-03, 37 | * 8.56560E-04, 2.04028E-03, 0.00000E+00,-3.15994E+03,-2.46423E-03, 38 | * 1.13843E-03, 4.20512E-04, 0.00000E+00,-9.77214E+01, 6.77794E-03, 39 | * 5.27499E-03, 1.14936E-03, 0.00000E+00,-6.61311E-03,-1.84255E-02, 40 | * -1.96259E-02, 2.98618E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 41 | * 6.44574E+02, 8.84668E-04, 5.05066E-04, 0.00000E+00, 4.02881E+03, 42 | * -1.89503E-03, 0.00000E+00, 0.00000E+00, 8.21407E-04, 2.06780E-03, 43 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 44 | * -1.20410E-02,-3.63963E-03, 9.92070E-05,-1.15284E-04,-6.33059E-05, 45 | * -6.05545E-01, 8.34218E-03,-9.13036E+01, 3.71042E-04, 0.00000E+00/ 46 | DATA PT3/ 47 | * 4.19000E-04, 2.70928E-03, 3.31507E-03,-4.44508E-03,-4.96334E-03, 48 | * -1.60449E-03, 3.95119E-03, 2.48924E-03, 5.09815E-04, 4.05302E-03, 49 | * 2.24076E-03, 0.00000E+00, 6.84256E-03, 4.66354E-04, 0.00000E+00, 50 | * -3.68328E-04, 0.00000E+00, 0.00000E+00,-1.46870E+02, 0.00000E+00, 51 | * 0.00000E+00, 1.09501E-03, 4.65156E-04, 5.62583E-04, 3.21596E+00, 52 | * 6.43168E-04, 3.14860E-03, 3.40738E-03, 1.78481E-03, 9.62532E-04, 53 | * 5.58171E-04, 3.43731E+00,-2.33195E-01, 5.10289E-04, 0.00000E+00, 54 | * 0.00000E+00,-9.25347E+04, 0.00000E+00,-1.99639E-03, 0.00000E+00, 55 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 56 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 57 | C HE DENSITY 58 | DATA PA1/ 59 | * 1.09979E+00,-4.88060E-02,-1.97501E-01,-9.10280E-02,-6.96558E-03, 60 | * 2.42136E-02, 3.91333E-01,-7.20068E-03,-3.22718E-02, 1.41508E+00, 61 | * 1.68194E-01, 1.85282E-02, 1.09384E-01,-7.24282E+00, 0.00000E+00, 62 | * 2.96377E-01,-4.97210E-02, 1.04114E+02,-8.61108E-02,-7.29177E-04, 63 | * 1.48998E-06, 1.08629E-03, 0.00000E+00, 0.00000E+00, 8.31090E-02, 64 | * 1.12818E-01,-5.75005E-02,-1.29919E-02,-1.78849E-02,-2.86343E-06, 65 | * 0.00000E+00,-1.51187E+02,-6.65902E-03, 0.00000E+00,-2.02069E-03, 66 | * 0.00000E+00, 0.00000E+00, 4.32264E-02,-2.80444E+01,-3.26789E-03, 67 | * 2.47461E-03, 0.00000E+00, 0.00000E+00, 9.82100E-02, 1.22714E-01, 68 | * -3.96450E-02, 0.00000E+00,-2.76489E-03, 0.00000E+00, 1.87723E-03/ 69 | DATA PA2/ 70 | * -8.09813E-03, 4.34428E-05,-7.70932E-03, 0.00000E+00,-2.28894E-03, 71 | * -5.69070E-03,-5.22193E-03, 6.00692E-03,-7.80434E+03,-3.48336E-03, 72 | * -6.38362E-03,-1.82190E-03, 0.00000E+00,-7.58976E+01,-2.17875E-02, 73 | * -1.72524E-02,-9.06287E-03, 0.00000E+00, 2.44725E-02, 8.66040E-02, 74 | * 1.05712E-01, 3.02543E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 75 | * -6.01364E+03,-5.64668E-03,-2.54157E-03, 0.00000E+00, 3.15611E+02, 76 | * -5.69158E-03, 0.00000E+00, 0.00000E+00,-4.47216E-03,-4.49523E-03, 77 | * 4.64428E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 78 | * 4.51236E-02, 2.46520E-02, 6.17794E-03, 0.00000E+00, 0.00000E+00, 79 | * -3.62944E-01,-4.80022E-02,-7.57230E+01,-1.99656E-03, 0.00000E+00/ 80 | DATA PA3/ 81 | * -5.18780E-03,-1.73990E-02,-9.03485E-03, 7.48465E-03, 1.53267E-02, 82 | * 1.06296E-02, 1.18655E-02, 2.55569E-03, 1.69020E-03, 3.51936E-02, 83 | * -1.81242E-02, 0.00000E+00,-1.00529E-01,-5.10574E-03, 0.00000E+00, 84 | * 2.10228E-03, 0.00000E+00, 0.00000E+00,-1.73255E+02, 5.07833E-01, 85 | * -2.41408E-01, 8.75414E-03, 2.77527E-03,-8.90353E-05,-5.25148E+00, 86 | * -5.83899E-03,-2.09122E-02,-9.63530E-03, 9.77164E-03, 4.07051E-03, 87 | * 2.53555E-04,-5.52875E+00,-3.55993E-01,-2.49231E-03, 0.00000E+00, 88 | * 0.00000E+00, 2.86026E+01, 0.00000E+00, 3.42722E-04, 0.00000E+00, 89 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 90 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 91 | C O DENSITY 92 | DATA PB1/ 93 | * 1.02315E+00,-1.59710E-01,-1.06630E-01,-1.77074E-02,-4.42726E-03, 94 | * 3.44803E-02, 4.45613E-02,-3.33751E-02,-5.73598E-02, 3.50360E-01, 95 | * 6.33053E-02, 2.16221E-02, 5.42577E-02,-5.74193E+00, 0.00000E+00, 96 | * 1.90891E-01,-1.39194E-02, 1.01102E+02, 8.16363E-02, 1.33717E-04, 97 | * 6.54403E-06, 3.10295E-03, 0.00000E+00, 0.00000E+00, 5.38205E-02, 98 | * 1.23910E-01,-1.39831E-02, 0.00000E+00, 0.00000E+00,-3.95915E-06, 99 | * 0.00000E+00,-7.14651E-01,-5.01027E-03, 0.00000E+00,-3.24756E-03, 100 | * 0.00000E+00, 0.00000E+00, 4.42173E-02,-1.31598E+01,-3.15626E-03, 101 | * 1.24574E-03,-1.47626E-03,-1.55461E-03, 6.40682E-02, 1.34898E-01, 102 | * -2.42415E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.13666E-04/ 103 | DATA PB2/ 104 | * -5.40373E-03, 2.61635E-05,-3.33012E-03, 0.00000E+00,-3.08101E-03, 105 | * -2.42679E-03,-3.36086E-03, 0.00000E+00,-1.18979E+03,-5.04738E-02, 106 | * -2.61547E-03,-1.03132E-03, 1.91583E-04,-8.38132E+01,-1.40517E-02, 107 | * -1.14167E-02,-4.08012E-03, 1.73522E-04,-1.39644E-02,-6.64128E-02, 108 | * -6.85152E-02,-1.34414E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 109 | * 6.07916E+02,-4.12220E-03,-2.20996E-03, 0.00000E+00, 1.70277E+03, 110 | * -4.63015E-03, 0.00000E+00, 0.00000E+00,-2.25360E-03,-2.96204E-03, 111 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 112 | * 3.92786E-02, 1.31186E-02,-1.78086E-03, 0.00000E+00, 0.00000E+00, 113 | * -3.90083E-01,-2.84741E-02,-7.78400E+01,-1.02601E-03, 0.00000E+00/ 114 | DATA PB3/ 115 | * -7.26485E-04,-5.42181E-03,-5.59305E-03, 1.22825E-02, 1.23868E-02, 116 | * 6.68835E-03,-1.03303E-02,-9.51903E-03, 2.70021E-04,-2.57084E-02, 117 | * -1.32430E-02, 0.00000E+00,-3.81000E-02,-3.16810E-03, 0.00000E+00, 118 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 119 | * 0.00000E+00,-9.05762E-04,-2.14590E-03,-1.17824E-03, 3.66732E+00, 120 | * -3.79729E-04,-6.13966E-03,-5.09082E-03,-1.96332E-03,-3.08280E-03, 121 | * -9.75222E-04, 4.03315E+00,-2.52710E-01, 0.00000E+00, 0.00000E+00, 122 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 123 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 124 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 125 | C N2 DENSITY 126 | DATA PC1/ 127 | * 1.16112E+00, 0.00000E+00, 0.00000E+00, 3.33725E-02, 0.00000E+00, 128 | * 3.48637E-02,-5.44368E-03, 0.00000E+00,-6.73940E-02, 1.74754E-01, 129 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, 130 | * 1.26733E-01, 0.00000E+00, 1.03154E+02, 5.52075E-02, 0.00000E+00, 131 | * 0.00000E+00, 8.13525E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02, 132 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 133 | * 0.00000E+00,-2.50482E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 134 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.48894E-03, 135 | * 6.16053E-04,-5.79716E-04, 2.95482E-03, 8.47001E-02, 1.70147E-01, 136 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 137 | DATA PC2/ 138 | * 0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, 139 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 140 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 141 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 142 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 143 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 144 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 145 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 146 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 147 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 148 | DATA PC3/ 149 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 150 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 151 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 152 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 153 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 154 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 155 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 156 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 157 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 158 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 159 | C TLB 160 | DATA PD1/ 161 | * 9.44846E-01, 0.00000E+00, 0.00000E+00,-3.08617E-02, 0.00000E+00, 162 | * -2.44019E-02, 6.48607E-03, 0.00000E+00, 3.08181E-02, 4.59392E-02, 163 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, 164 | * 2.13260E-02, 0.00000E+00,-3.56958E+02, 0.00000E+00, 1.82278E-04, 165 | * 0.00000E+00, 3.07472E-04, 0.00000E+00, 0.00000E+00, 8.66784E-02, 166 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 167 | * 0.00000E+00, 0.00000E+00, 3.83054E-03, 0.00000E+00, 0.00000E+00, 168 | * -1.93065E-03,-1.45090E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 169 | * 0.00000E+00,-1.23493E-03, 1.36736E-03, 8.47001E-02, 1.70147E-01, 170 | * 3.71469E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 171 | DATA PD2/ 172 | * 5.10250E-03, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, 173 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 174 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 175 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 176 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 177 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 178 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 179 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 180 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 181 | * 0.00000E+00, 3.68756E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 182 | DATA PD3/ 183 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 184 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 185 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 186 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 187 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 188 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 189 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 190 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 191 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 192 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 193 | C O2 DENSITY 194 | DATA PE1/ 195 | * 1.35580E+00, 1.44816E-01, 0.00000E+00, 6.07767E-02, 0.00000E+00, 196 | * 2.94777E-02, 7.46900E-02, 0.00000E+00,-9.23822E-02, 8.57342E-02, 197 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.38636E+01, 0.00000E+00, 198 | * 7.71653E-02, 0.00000E+00, 8.18751E+01, 1.87736E-02, 0.00000E+00, 199 | * 0.00000E+00, 1.49667E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02, 200 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 201 | * 0.00000E+00,-3.67874E+02, 5.48158E-03, 0.00000E+00, 0.00000E+00, 202 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 203 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, 204 | * 1.22631E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 205 | DATA PE2/ 206 | * 8.17187E-03, 3.71617E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, 207 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 208 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.10826E-03, 209 | * -3.13640E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 210 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 211 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 212 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 213 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 214 | * -7.35742E-02,-5.00266E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 215 | * 0.00000E+00, 1.94965E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 216 | DATA PE3/ 217 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 218 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 219 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 220 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 221 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 222 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 223 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 224 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 225 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 226 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 227 | C AR DENSITY 228 | DATA PF1/ 229 | * 1.04761E+00, 2.00165E-01, 2.37697E-01, 3.68552E-02, 0.00000E+00, 230 | * 3.57202E-02,-2.14075E-01, 0.00000E+00,-1.08018E-01,-3.73981E-01, 231 | * 0.00000E+00, 3.10022E-02,-1.16305E-03,-2.07596E+01, 0.00000E+00, 232 | * 8.64502E-02, 0.00000E+00, 9.74908E+01, 5.16707E-02, 0.00000E+00, 233 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.66784E-02, 234 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 235 | * 0.00000E+00, 3.46193E+02, 1.34297E-02, 0.00000E+00, 0.00000E+00, 236 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.48509E-03, 237 | * -1.54689E-04, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, 238 | * 1.47753E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 239 | DATA PF2/ 240 | * 1.89320E-02, 3.68181E-05, 1.32570E-02, 0.00000E+00, 0.00000E+00, 241 | * 3.59719E-03, 7.44328E-03,-1.00023E-03,-6.50528E+03, 0.00000E+00, 242 | * 1.03485E-02,-1.00983E-03,-4.06916E-03,-6.60864E+01,-1.71533E-02, 243 | * 1.10605E-02, 1.20300E-02,-5.20034E-03, 0.00000E+00, 0.00000E+00, 244 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 245 | * -2.62769E+03, 7.13755E-03, 4.17999E-03, 0.00000E+00, 1.25910E+04, 246 | * 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.23595E-03, 4.60217E-03, 247 | * 5.71794E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 248 | * -3.18353E-02,-2.35526E-02,-1.36189E-02, 0.00000E+00, 0.00000E+00, 249 | * 0.00000E+00, 2.03522E-02,-6.67837E+01,-1.09724E-03, 0.00000E+00/ 250 | DATA PF3/ 251 | * -1.38821E-02, 1.60468E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 252 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.51574E-02, 253 | * -5.44470E-04, 0.00000E+00, 7.28224E-02, 6.59413E-02, 0.00000E+00, 254 | * -5.15692E-03, 0.00000E+00, 0.00000E+00,-3.70367E+03, 0.00000E+00, 255 | * 0.00000E+00, 1.36131E-02, 5.38153E-03, 0.00000E+00, 4.76285E+00, 256 | * -1.75677E-02, 2.26301E-02, 0.00000E+00, 1.76631E-02, 4.77162E-03, 257 | * 0.00000E+00, 5.39354E+00, 0.00000E+00,-7.51710E-03, 0.00000E+00, 258 | * 0.00000E+00,-8.82736E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 259 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 260 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 261 | C H DENSITY 262 | DATA PG1/ 263 | * 1.26376E+00,-2.14304E-01,-1.49984E-01, 2.30404E-01, 2.98237E-02, 264 | * 2.68673E-02, 2.96228E-01, 2.21900E-02,-2.07655E-02, 4.52506E-01, 265 | * 1.20105E-01, 3.24420E-02, 4.24816E-02,-9.14313E+00, 0.00000E+00, 266 | * 2.47178E-02,-2.88229E-02, 8.12805E+01, 5.10380E-02,-5.80611E-03, 267 | * 2.51236E-05,-1.24083E-02, 0.00000E+00, 0.00000E+00, 8.66784E-02, 268 | * 1.58727E-01,-3.48190E-02, 0.00000E+00, 0.00000E+00, 2.89885E-05, 269 | * 0.00000E+00, 1.53595E+02,-1.68604E-02, 0.00000E+00, 1.01015E-02, 270 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.84552E-04, 271 | * -1.22181E-03, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, 272 | * -1.04927E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.91313E-03/ 273 | DATA PG2/ 274 | * -2.30501E-02, 3.14758E-05, 0.00000E+00, 0.00000E+00, 1.26956E-02, 275 | * 8.35489E-03, 3.10513E-04, 0.00000E+00, 3.42119E+03,-2.45017E-03, 276 | * -4.27154E-04, 5.45152E-04, 1.89896E-03, 2.89121E+01,-6.49973E-03, 277 | * -1.93855E-02,-1.48492E-02, 0.00000E+00,-5.10576E-02, 7.87306E-02, 278 | * 9.51981E-02,-1.49422E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 279 | * 2.65503E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 280 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 6.37110E-03, 3.24789E-04, 281 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 282 | * 6.14274E-02, 1.00376E-02,-8.41083E-04, 0.00000E+00, 0.00000E+00, 283 | * 0.00000E+00,-1.27099E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 284 | DATA PG3/ 285 | * -3.94077E-03,-1.28601E-02,-7.97616E-03, 0.00000E+00, 0.00000E+00, 286 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 287 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 288 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 289 | * 0.00000E+00,-6.71465E-03,-1.69799E-03, 1.93772E-03, 3.81140E+00, 290 | * -7.79290E-03,-1.82589E-02,-1.25860E-02,-1.04311E-02,-3.02465E-03, 291 | * 2.43063E-03, 3.63237E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 292 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 293 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 294 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 295 | C N DENSITY 296 | DATA PH1/ 297 | * 7.09557E+01,-3.26740E-01, 0.00000E+00,-5.16829E-01,-1.71664E-03, 298 | * 9.09310E-02,-6.71500E-01,-1.47771E-01,-9.27471E-02,-2.30862E-01, 299 | * -1.56410E-01, 1.34455E-02,-1.19717E-01, 2.52151E+00, 0.00000E+00, 300 | * -2.41582E-01, 5.92939E-02, 4.39756E+00, 9.15280E-02, 4.41292E-03, 301 | * 0.00000E+00, 8.66807E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02, 302 | * 1.58727E-01, 9.74701E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 303 | * 0.00000E+00, 6.70217E+01,-1.31660E-03, 0.00000E+00,-1.65317E-02, 304 | * 0.00000E+00, 0.00000E+00, 8.50247E-02, 2.77428E+01, 4.98658E-03, 305 | * 6.15115E-03, 9.50156E-03,-2.12723E-02, 8.47001E-02, 1.70147E-01, 306 | * -2.38645E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.37380E-03/ 307 | DATA PH2/ 308 | * -8.41918E-03, 2.80145E-05, 7.12383E-03, 0.00000E+00,-1.66209E-02, 309 | * 1.03533E-04,-1.68898E-02, 0.00000E+00, 3.64526E+03, 0.00000E+00, 310 | * 6.54077E-03, 3.69130E-04, 9.94419E-04, 8.42803E+01,-1.16124E-02, 311 | * -7.74414E-03,-1.68844E-03, 1.42809E-03,-1.92955E-03, 1.17225E-01, 312 | * -2.41512E-02, 1.50521E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 313 | * 1.60261E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 314 | * 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.54403E-04,-1.87270E-02, 315 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 316 | * 2.76439E-02, 6.43207E-03,-3.54300E-02, 0.00000E+00, 0.00000E+00, 317 | * 0.00000E+00,-2.80221E-02, 8.11228E+01,-6.75255E-04, 0.00000E+00/ 318 | DATA PH3/ 319 | * -1.05162E-02,-3.48292E-03,-6.97321E-03, 0.00000E+00, 0.00000E+00, 320 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 321 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 322 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 323 | * 0.00000E+00,-1.45546E-03,-1.31970E-02,-3.57751E-03,-1.09021E+00, 324 | * -1.50181E-02,-7.12841E-03,-6.64590E-03,-3.52610E-03,-1.87773E-02, 325 | * -2.22432E-03,-3.93895E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 326 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 327 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 328 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 329 | C HOT O DENSITY 330 | DATA PI1/ 331 | * 6.04050E-02, 1.57034E+00, 2.99387E-02, 0.00000E+00, 0.00000E+00, 332 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.51018E+00, 333 | * 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.61650E+00, 1.26454E-02, 334 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 335 | * 0.00000E+00, 5.50878E-03, 0.00000E+00, 0.00000E+00, 8.66784E-02, 336 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 337 | * 0.00000E+00, 0.00000E+00, 6.23881E-02, 0.00000E+00, 0.00000E+00, 338 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 339 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 8.47001E-02, 1.70147E-01, 340 | * -9.45934E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 341 | DATA PI2/ 342 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 343 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 344 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 345 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 346 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 347 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 348 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 349 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 350 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 351 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 352 | DATA PI3/ 353 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 354 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 355 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 356 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 357 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 358 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 359 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 360 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 361 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 362 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 363 | C S PARAM 364 | DATA PJ1/ 365 | * 9.56827E-01, 6.20637E-02, 3.18433E-02, 0.00000E+00, 0.00000E+00, 366 | * 3.94900E-02, 0.00000E+00, 0.00000E+00,-9.24882E-03,-7.94023E-03, 367 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.74712E+02, 0.00000E+00, 368 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 369 | * 0.00000E+00, 2.74677E-03, 0.00000E+00, 1.54951E-02, 8.66784E-02, 370 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 371 | * 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.99007E-04, 0.00000E+00, 372 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 373 | * 0.00000E+00, 1.24362E-02,-5.28756E-03, 8.47001E-02, 1.70147E-01, 374 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 375 | DATA PJ2/ 376 | * 0.00000E+00, 2.47425E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, 377 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 378 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 379 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 380 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 381 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 382 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 383 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 384 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 385 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 386 | DATA PJ3/ 387 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 388 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 389 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 390 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 391 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 392 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 393 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 394 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 395 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 396 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 397 | C TURBO 398 | DATA PK1/ 399 | * 1.09930E+00, 3.90631E+00, 3.07165E+00, 9.86161E-01, 1.63536E+01, 400 | * 4.63830E+00, 1.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 401 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 402 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 403 | * 0.00000E+00, 0.00000E+00, 1.28840E+00, 3.10302E-02, 1.18339E-01, 404 | * 1.00000E+00, 7.00000E-01, 1.15020E+00, 3.44689E+00, 1.28840E+00, 405 | * 1.00000E+00, 1.08738E+00, 1.22947E+00, 1.10016E+00, 7.34129E-01, 406 | * 1.15241E+00, 2.22784E+00, 7.95046E-01, 4.01612E+00, 4.47749E+00, 407 | * 1.23435E+02,-7.60535E-02, 1.68986E-06, 7.44294E-01, 1.03604E+00, 408 | * 1.72783E+02, 1.15020E+00, 3.44689E+00,-7.46230E-01, 9.49154E-01/ 409 | C LOWER BOUNDARY 410 | DATA PTM/ 411 | L 1.04130E+03, 3.86000E+02, 1.95000E+02, 1.66728E+01, 2.13000E+02, 412 | L 1.20000E+02, 2.40000E+02, 1.87000E+02,-2.00000E+00, 0.00000E+00/ 413 | DATA PDM/ 414 | L 2.45600E+07, 6.71072E-06, 1.00000E+02, 0.00000E+00, 1.10000E+02, 415 | L 1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 416 | C 417 | L 8.59400E+10, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02, 418 | L 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00, 419 | C 420 | L 2.81000E+11, 0.00000E+00, 1.05000E+02, 2.80000E+01, 2.89500E+01, 421 | L 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 422 | C 423 | L 3.30000E+10, 2.68270E-01, 1.05000E+02, 1.00000E+00, 1.10000E+02, 424 | L 1.00000E+01, 1.10000E+02,-1.00000E+01, 0.00000E+00, 0.00000E+00, 425 | C 426 | L 1.33000E+09, 1.19615E-02, 1.05000E+02, 0.00000E+00, 1.10000E+02, 427 | L 1.00000E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 428 | C 429 | L 1.76100E+05, 1.00000E+00, 9.50000E+01,-8.00000E+00, 1.10000E+02, 430 | L 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00, 431 | C 432 | L 1.00000E+07, 1.00000E+00, 1.05000E+02,-8.00000E+00, 1.10000E+02, 433 | L 1.00000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 0.00000E+00, 434 | C 435 | L 1.00000E+06, 1.00000E+00, 1.05000E+02,-8.00000E+00, 5.50000E+02, 436 | L 7.60000E+01, 9.00000E+01, 2.00000E+00, 0.00000E+00, 4.00000E+03/ 437 | C TN1(2) 438 | DATA PL1/ 439 | * 1.00858E+00, 4.56011E-02,-2.22972E-02,-5.44388E-02, 5.23136E-04, 440 | * -1.88849E-02, 5.23707E-02,-9.43646E-03, 6.31707E-03,-7.80460E-02, 441 | * -4.88430E-02, 0.00000E+00, 0.00000E+00,-7.60250E+00, 0.00000E+00, 442 | * -1.44635E-02,-1.76843E-02,-1.21517E+02, 2.85647E-02, 0.00000E+00, 443 | * 0.00000E+00, 6.31792E-04, 0.00000E+00, 5.77197E-03, 8.66784E-02, 444 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 445 | * 0.00000E+00,-8.90272E+03, 3.30611E-03, 3.02172E-03, 0.00000E+00, 446 | * -2.13673E-03,-3.20910E-04, 0.00000E+00, 0.00000E+00, 2.76034E-03, 447 | * 2.82487E-03,-2.97592E-04,-4.21534E-03, 8.47001E-02, 1.70147E-01, 448 | * 8.96456E-03, 0.00000E+00,-1.08596E-02, 0.00000E+00, 0.00000E+00/ 449 | DATA PL2/ 450 | * 5.57917E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 451 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 452 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 453 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 454 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 455 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 456 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 457 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 458 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 459 | * 0.00000E+00, 9.65405E-03, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 460 | C TN1(3) 461 | DATA PM1/ 462 | * 9.39664E-01, 8.56514E-02,-6.79989E-03, 2.65929E-02,-4.74283E-03, 463 | * 1.21855E-02,-2.14905E-02, 6.49651E-03,-2.05477E-02,-4.24952E-02, 464 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.19148E+01, 0.00000E+00, 465 | * 1.18777E-02,-7.28230E-02,-8.15965E+01, 1.73887E-02, 0.00000E+00, 466 | * 0.00000E+00, 0.00000E+00,-1.44691E-02, 2.80259E-04, 8.66784E-02, 467 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 468 | * 0.00000E+00, 2.16584E+02, 3.18713E-03, 7.37479E-03, 0.00000E+00, 469 | * -2.55018E-03,-3.92806E-03, 0.00000E+00, 0.00000E+00,-2.89757E-03, 470 | * -1.33549E-03, 1.02661E-03, 3.53775E-04, 8.47001E-02, 1.70147E-01, 471 | * -9.17497E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 472 | DATA PM2/ 473 | * 3.56082E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 474 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 475 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 476 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 477 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 478 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 479 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 480 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 481 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 482 | * 0.00000E+00,-1.00902E-02, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 483 | C TN1(4) 484 | DATA PN1/ 485 | * 9.85982E-01,-4.55435E-02, 1.21106E-02, 2.04127E-02,-2.40836E-03, 486 | * 1.11383E-02,-4.51926E-02, 1.35074E-02,-6.54139E-03, 1.15275E-01, 487 | * 1.28247E-01, 0.00000E+00, 0.00000E+00,-5.30705E+00, 0.00000E+00, 488 | * -3.79332E-02,-6.24741E-02, 7.71062E-01, 2.96315E-02, 0.00000E+00, 489 | * 0.00000E+00, 0.00000E+00, 6.81051E-03,-4.34767E-03, 8.66784E-02, 490 | * 1.58727E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 491 | * 0.00000E+00, 1.07003E+01,-2.76907E-03, 4.32474E-04, 0.00000E+00, 492 | * 1.31497E-03,-6.47517E-04, 0.00000E+00,-2.20621E+01,-1.10804E-03, 493 | * -8.09338E-04, 4.18184E-04, 4.29650E-03, 8.47001E-02, 1.70147E-01, 494 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 495 | DATA PN2/ 496 | * -4.04337E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 497 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 498 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-9.52550E-04, 499 | * 8.56253E-04, 4.33114E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 500 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.21223E-03, 501 | * 2.38694E-04, 9.15245E-04, 1.28385E-03, 8.67668E-04,-5.61425E-06, 502 | * 1.04445E+00, 3.41112E+01, 0.00000E+00,-8.40704E-01,-2.39639E+02, 503 | * 7.06668E-01,-2.05873E+01,-3.63696E-01, 2.39245E+01, 0.00000E+00, 504 | * -1.06657E-03,-7.67292E-04, 1.54534E-04, 0.00000E+00, 0.00000E+00, 505 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 506 | C TN1(5) TN2(1) 507 | DATA PO1/ 508 | * 1.00320E+00, 3.83501E-02,-2.38983E-03, 2.83950E-03, 4.20956E-03, 509 | * 5.86619E-04, 2.19054E-02,-1.00946E-02,-3.50259E-03, 4.17392E-02, 510 | * -8.44404E-03, 0.00000E+00, 0.00000E+00, 4.96949E+00, 0.00000E+00, 511 | * -7.06478E-03,-1.46494E-02, 3.13258E+01,-1.86493E-03, 0.00000E+00, 512 | * -1.67499E-02, 0.00000E+00, 0.00000E+00, 5.12686E-04, 8.66784E-02, 513 | * 1.58727E-01,-4.64167E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 514 | * 4.37353E-03,-1.99069E+02, 0.00000E+00,-5.34884E-03, 0.00000E+00, 515 | * 1.62458E-03, 2.93016E-03, 2.67926E-03, 5.90449E+02, 0.00000E+00, 516 | * 0.00000E+00,-1.17266E-03,-3.58890E-04, 8.47001E-02, 1.70147E-01, 517 | * 0.00000E+00, 0.00000E+00, 1.38673E-02, 0.00000E+00, 0.00000E+00/ 518 | DATA PO2/ 519 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 520 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 521 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.60571E-03, 522 | * 6.28078E-04, 5.05469E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, 523 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.57829E-03, 524 | * -4.00855E-04, 5.04077E-05,-1.39001E-03,-2.33406E-03,-4.81197E-04, 525 | * 1.46758E+00, 6.20332E+00, 0.00000E+00, 3.66476E-01,-6.19760E+01, 526 | * 3.09198E-01,-1.98999E+01, 0.00000E+00,-3.29933E+02, 0.00000E+00, 527 | * -1.10080E-03,-9.39310E-05, 1.39638E-04, 0.00000E+00, 0.00000E+00, 528 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 529 | C TN2(2) 530 | DATA PP1/ 531 | * 9.81637E-01,-1.41317E-03, 3.87323E-02, 0.00000E+00, 0.00000E+00, 532 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.58707E-02, 533 | * -8.63658E-03, 0.00000E+00, 0.00000E+00,-2.02226E+00, 0.00000E+00, 534 | * -8.69424E-03,-1.91397E-02, 8.76779E+01, 4.52188E-03, 0.00000E+00, 535 | * 2.23760E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 536 | * 0.00000E+00,-7.07572E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 537 | * -4.11210E-03, 3.50060E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 538 | * 0.00000E+00, 0.00000E+00,-8.36657E-03, 1.61347E+01, 0.00000E+00, 539 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 540 | * 0.00000E+00, 0.00000E+00,-1.45130E-02, 0.00000E+00, 0.00000E+00/ 541 | DATA PP2/ 542 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 543 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 544 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.24152E-03, 545 | * 6.43365E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 546 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.33255E-03, 547 | * 2.42657E-03, 1.60666E-03,-1.85728E-03,-1.46874E-03,-4.79163E-06, 548 | * 1.22464E+00, 3.53510E+01, 0.00000E+00, 4.49223E-01,-4.77466E+01, 549 | * 4.70681E-01, 8.41861E+00,-2.88198E-01, 1.67854E+02, 0.00000E+00, 550 | * 7.11493E-04, 6.05601E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 551 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 552 | C TN2(3) 553 | DATA PQ1/ 554 | * 1.00422E+00,-7.11212E-03, 5.24480E-03, 0.00000E+00, 0.00000E+00, 555 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.28914E-02, 556 | * -2.41301E-02, 0.00000E+00, 0.00000E+00,-2.12219E+01,-1.03830E-02, 557 | * -3.28077E-03, 1.65727E-02, 1.68564E+00,-6.68154E-03, 0.00000E+00, 558 | * 1.45155E-02, 0.00000E+00, 8.42365E-03, 0.00000E+00, 0.00000E+00, 559 | * 0.00000E+00,-4.34645E-03, 0.00000E+00, 0.00000E+00, 2.16780E-02, 560 | * 0.00000E+00,-1.38459E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 561 | * 0.00000E+00, 0.00000E+00, 7.04573E-03,-4.73204E+01, 0.00000E+00, 562 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 563 | * 0.00000E+00, 0.00000E+00, 1.08767E-02, 0.00000E+00, 0.00000E+00/ 564 | DATA PQ2/ 565 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 566 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.08279E-03, 567 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.21769E-04, 568 | * -2.27387E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 569 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.26769E-03, 570 | * 3.16901E-03, 4.60316E-04,-1.01431E-04, 1.02131E-03, 9.96601E-04, 571 | * 1.25707E+00, 2.50114E+01, 0.00000E+00, 4.24472E-01,-2.77655E+01, 572 | * 3.44625E-01, 2.75412E+01, 0.00000E+00, 7.94251E+02, 0.00000E+00, 573 | * 2.45835E-03, 1.38871E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 574 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 575 | C TN2(4) TN3(1) 576 | DATA PR1/ 577 | * 1.01890E+00,-2.46603E-02, 1.00078E-02, 0.00000E+00, 0.00000E+00, 578 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-6.70977E-02, 579 | * -4.02286E-02, 0.00000E+00, 0.00000E+00,-2.29466E+01,-7.47019E-03, 580 | * 2.26580E-03, 2.63931E-02, 3.72625E+01,-6.39041E-03, 0.00000E+00, 581 | * 9.58383E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 582 | * 0.00000E+00,-1.85291E-03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 583 | * 0.00000E+00, 1.39717E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 584 | * 0.00000E+00, 0.00000E+00, 9.19771E-03,-3.69121E+02, 0.00000E+00, 585 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 586 | * 0.00000E+00, 0.00000E+00,-1.57067E-02, 0.00000E+00, 0.00000E+00/ 587 | DATA PR2/ 588 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 589 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.07265E-03, 590 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.92953E-03, 591 | * -2.77739E-03,-4.40092E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 592 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.47280E-03, 593 | * 2.95035E-04,-1.81246E-03, 2.81945E-03, 4.27296E-03, 9.78863E-04, 594 | * 1.40545E+00,-6.19173E+00, 0.00000E+00, 0.00000E+00,-7.93632E+01, 595 | * 4.44643E-01,-4.03085E+02, 0.00000E+00, 1.15603E+01, 0.00000E+00, 596 | * 2.25068E-03, 8.48557E-04,-2.98493E-04, 0.00000E+00, 0.00000E+00, 597 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 598 | C TN3(2) 599 | DATA PS1/ 600 | * 9.75801E-01, 3.80680E-02,-3.05198E-02, 0.00000E+00, 0.00000E+00, 601 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.85575E-02, 602 | * 5.04057E-02, 0.00000E+00, 0.00000E+00,-1.76046E+02, 1.44594E-02, 603 | * -1.48297E-03,-3.68560E-03, 3.02185E+01,-3.23338E-03, 0.00000E+00, 604 | * 1.53569E-02, 0.00000E+00,-1.15558E-02, 0.00000E+00, 0.00000E+00, 605 | * 0.00000E+00, 4.89620E-03, 0.00000E+00, 0.00000E+00,-1.00616E-02, 606 | * -8.21324E-03,-1.57757E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 607 | * 0.00000E+00, 0.00000E+00, 6.63564E-03, 4.58410E+01, 0.00000E+00, 608 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 609 | * 0.00000E+00, 0.00000E+00,-2.51280E-02, 0.00000E+00, 0.00000E+00/ 610 | DATA PS2/ 611 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 612 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 9.91215E-03, 613 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-8.73148E-04, 614 | * -1.29648E-03,-7.32026E-05, 0.00000E+00, 0.00000E+00, 0.00000E+00, 615 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.68110E-03, 616 | * -4.66003E-03,-1.31567E-03,-7.39390E-04, 6.32499E-04,-4.65588E-04, 617 | * -1.29785E+00,-1.57139E+02, 0.00000E+00, 2.58350E-01,-3.69453E+01, 618 | * 4.10672E-01, 9.78196E+00,-1.52064E-01,-3.85084E+03, 0.00000E+00, 619 | * -8.52706E-04,-1.40945E-03,-7.26786E-04, 0.00000E+00, 0.00000E+00, 620 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 621 | C TN3(3) 622 | DATA PU1/ 623 | * 9.60722E-01, 7.03757E-02,-3.00266E-02, 0.00000E+00, 0.00000E+00, 624 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.22671E-02, 625 | * 4.10423E-02, 0.00000E+00, 0.00000E+00,-1.63070E+02, 1.06073E-02, 626 | * 5.40747E-04, 7.79481E-03, 1.44908E+02, 1.51484E-04, 0.00000E+00, 627 | * 1.97547E-02, 0.00000E+00,-1.41844E-02, 0.00000E+00, 0.00000E+00, 628 | * 0.00000E+00, 5.77884E-03, 0.00000E+00, 0.00000E+00, 9.74319E-03, 629 | * 0.00000E+00,-2.88015E+03, 0.00000E+00, 0.00000E+00, 0.00000E+00, 630 | * 0.00000E+00, 0.00000E+00,-4.44902E-03,-2.92760E+01, 0.00000E+00, 631 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 632 | * 0.00000E+00, 0.00000E+00, 2.34419E-02, 0.00000E+00, 0.00000E+00/ 633 | DATA PU2/ 634 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 635 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.36685E-03, 636 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.65325E-04, 637 | * -5.50628E-04, 3.31465E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 638 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.06179E-03, 639 | * -3.08575E-03,-7.93589E-04,-1.08629E-04, 5.95511E-04,-9.05050E-04, 640 | * 1.18997E+00, 4.15924E+01, 0.00000E+00,-4.72064E-01,-9.47150E+02, 641 | * 3.98723E-01, 1.98304E+01, 0.00000E+00, 3.73219E+03, 0.00000E+00, 642 | * -1.50040E-03,-1.14933E-03,-1.56769E-04, 0.00000E+00, 0.00000E+00, 643 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 644 | C TN3(4) 645 | DATA PV1/ 646 | * 1.03123E+00,-7.05124E-02, 8.71615E-03, 0.00000E+00, 0.00000E+00, 647 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-3.82621E-02, 648 | * -9.80975E-03, 0.00000E+00, 0.00000E+00, 2.89286E+01, 9.57341E-03, 649 | * 0.00000E+00, 0.00000E+00, 8.66153E+01, 7.91938E-04, 0.00000E+00, 650 | * 0.00000E+00, 0.00000E+00, 4.68917E-03, 0.00000E+00, 0.00000E+00, 651 | * 0.00000E+00, 7.86638E-03, 0.00000E+00, 0.00000E+00, 9.90827E-03, 652 | * 0.00000E+00, 6.55573E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 653 | * 0.00000E+00, 0.00000E+00, 0.00000E+00,-4.00200E+01, 0.00000E+00, 654 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 655 | * 0.00000E+00, 0.00000E+00, 7.07457E-03, 0.00000E+00, 0.00000E+00/ 656 | DATA PV2/ 657 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 658 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.72268E-03, 659 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.04970E-04, 660 | * 1.21560E-03,-8.05579E-06, 0.00000E+00, 0.00000E+00, 0.00000E+00, 661 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.49941E-03, 662 | * -4.57256E-04,-1.59311E-04, 2.96481E-04,-1.77318E-03,-6.37918E-04, 663 | * 1.02395E+00, 1.28172E+01, 0.00000E+00, 1.49903E-01,-2.63818E+01, 664 | * 0.00000E+00, 4.70628E+01,-2.22139E-01, 4.82292E-02, 0.00000E+00, 665 | * -8.67075E-04,-5.86479E-04, 5.32462E-04, 0.00000E+00, 0.00000E+00, 666 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 667 | C TN3(5) SURFACE TEMP TSL 668 | DATA PW1/ 669 | * 1.00828E+00,-9.10404E-02,-2.26549E-02, 0.00000E+00, 0.00000E+00, 670 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-2.32420E-02, 671 | * -9.08925E-03, 0.00000E+00, 0.00000E+00, 3.36105E+01, 0.00000E+00, 672 | * 0.00000E+00, 0.00000E+00,-1.24957E+01,-5.87939E-03, 0.00000E+00, 673 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 674 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 675 | * 0.00000E+00, 2.79765E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 676 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.01237E+03, 0.00000E+00, 677 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 678 | * 0.00000E+00, 0.00000E+00,-1.75553E-02, 0.00000E+00, 0.00000E+00/ 679 | DATA PW2/ 680 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 681 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 682 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.29699E-03, 683 | * 1.26659E-03, 2.68402E-04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 684 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 1.17894E-03, 685 | * 1.48746E-03, 1.06478E-04, 1.34743E-04,-2.20939E-03,-6.23523E-04, 686 | * 6.36539E-01, 1.13621E+01, 0.00000E+00,-3.93777E-01, 2.38687E+03, 687 | * 0.00000E+00, 6.61865E+02,-1.21434E-01, 9.27608E+00, 0.00000E+00, 688 | * 1.68478E-04, 1.24892E-03, 1.71345E-03, 0.00000E+00, 0.00000E+00, 689 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 690 | C TGN3(2) SURFACE GRAD TSLG 691 | DATA PX1/ 692 | * 1.57293E+00,-6.78400E-01, 6.47500E-01, 0.00000E+00, 0.00000E+00, 693 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-7.62974E-02, 694 | * -3.60423E-01, 0.00000E+00, 0.00000E+00, 1.28358E+02, 0.00000E+00, 695 | * 0.00000E+00, 0.00000E+00, 4.68038E+01, 0.00000E+00, 0.00000E+00, 696 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 697 | * 0.00000E+00,-1.67898E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 698 | * 0.00000E+00, 2.90994E+04, 0.00000E+00, 0.00000E+00, 0.00000E+00, 699 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.15706E+01, 0.00000E+00, 700 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 701 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 702 | DATA PX2/ 703 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 704 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 705 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 706 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 707 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 708 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 709 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 710 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 711 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 712 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 713 | C TGN2(1) TGN1(2) 714 | DATA PY1/ 715 | * 8.60028E-01, 3.77052E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 716 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.17570E+00, 717 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 7.77757E-03, 0.00000E+00, 718 | * 0.00000E+00, 0.00000E+00, 1.01024E+02, 0.00000E+00, 0.00000E+00, 719 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 720 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 721 | * 0.00000E+00, 6.54251E+02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 722 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 723 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 724 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 725 | DATA PY2/ 726 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 727 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 728 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 729 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 730 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00,-1.56959E-02, 731 | * 1.91001E-02, 3.15971E-02, 1.00982E-02,-6.71565E-03, 2.57693E-03, 732 | * 1.38692E+00, 2.82132E-01, 0.00000E+00, 0.00000E+00, 3.81511E+02, 733 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 734 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 735 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 736 | C TGN3(1) TGN2(2) 737 | DATA PZ1/ 738 | * 1.06029E+00,-5.25231E-02, 3.73034E-01, 0.00000E+00, 0.00000E+00, 739 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.31072E-02, 740 | * -3.88409E-01, 0.00000E+00, 0.00000E+00,-1.65295E+02,-2.13801E-01, 741 | * -4.38916E-02,-3.22716E-01,-8.82393E+01, 1.18458E-01, 0.00000E+00, 742 | * -4.35863E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 743 | * 0.00000E+00,-1.19782E-01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 744 | * 0.00000E+00, 2.62229E+01, 0.00000E+00, 0.00000E+00, 0.00000E+00, 745 | * 0.00000E+00, 0.00000E+00, 0.00000E+00,-5.37443E+01, 0.00000E+00, 746 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 747 | * 0.00000E+00, 0.00000E+00,-4.55788E-01, 0.00000E+00, 0.00000E+00/ 748 | DATA PZ2/ 749 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 750 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 751 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 3.84009E-02, 752 | * 3.96733E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 753 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 5.05494E-02, 754 | * 7.39617E-02, 1.92200E-02,-8.46151E-03,-1.34244E-02, 1.96338E-02, 755 | * 1.50421E+00, 1.88368E+01, 0.00000E+00, 0.00000E+00,-5.13114E+01, 756 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 757 | * 5.11923E-02, 3.61225E-02, 0.00000E+00, 0.00000E+00, 0.00000E+00, 758 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 2.00000E+00/ 759 | C SEMIANNUAL MULT SAM 760 | DATA PAA1/ 761 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 762 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 763 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 764 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 765 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 766 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 767 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 768 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 769 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 770 | * 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00, 1.00000E+00/ 771 | DATA PAA2/ 772 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 773 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 774 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 775 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 776 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 777 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 778 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 779 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 780 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 781 | * 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00, 0.00000E+00/ 782 | C MIDDLE ATMOSPHERE AVERAGES 783 | DATA PAVGM/ 784 | M 2.61000E+02, 2.64000E+02, 2.29000E+02, 2.17000E+02, 2.17000E+02, 785 | M 2.23000E+02, 2.86760E+02,-2.93940E+00, 2.50000E+00, 0.00000E+00/ 786 | 787 | end module msise00_data 788 | -------------------------------------------------------------------------------- /src/msise00/fortran/msise00_sub.f: -------------------------------------------------------------------------------- 1 | module msise00_python 2 | C module to avoid link conflicts 3 | use, intrinsic :: iso_fortran_env, only : stderr=>error_unit 4 | use msise00_data, only : parm7g, ptm, pdm, pavgm, imr 5 | 6 | private 7 | public :: gtd7, tselec, meters 8 | 9 | contains 10 | 11 | SUBROUTINE GTD7(IYD,SEC,ALT,GLAT,GLONG,STL,F107A,F107,AP,MASS,D,T) 12 | C 13 | C NRLMSISE-00 14 | C ----------- 15 | C Neutral Atmosphere Empirical Model from the surface to lower 16 | C exosphere 17 | C 18 | C NEW FEATURES: 19 | C *Extensive satellite drag database used in model generation 20 | C *Revised O2 (and O) in lower thermosphere 21 | C *Additional nonlinear solar activity term 22 | C *"ANOMALOUS OXYGEN" NUMBER DENSITY, OUTPUT D(9) 23 | C At high altitudes (> 500 km), hot atomic oxygen or ionized 24 | C oxygen can become appreciable for some ranges of subroutine 25 | C inputs, thereby affecting drag on satellites and debris. We 26 | C group these species under the term "anomalous oxygen," since 27 | C their individual variations are not presently separable with 28 | C the drag data used to define this model component. 29 | C 30 | C SUBROUTINES FOR SPECIAL OUTPUTS: 31 | C 32 | C HIGH ALTITUDE DRAG: EFFECTIVE TOTAL MASS DENSITY 33 | C (SUBROUTINE GTD7D, OUTPUT D(6)) 34 | C For atmospheric drag calculations at altitudes above 500 km, 35 | C call SUBROUTINE GTD7D to compute the "effective total mass 36 | C density" by including contributions from "anomalous oxygen." 37 | C See "NOTES ON OUTPUT VARIABLES" below on D(6). 38 | C 39 | C PRESSURE GRID (SUBROUTINE GHP7) 40 | C See subroutine GHP7 to specify outputs at a pressure level 41 | C rather than at an altitude. 42 | C 43 | C OUTPUT IN M-3 and KG/M3: CALL METERS(.TRUE.) 44 | C 45 | C INPUT VARIABLES: 46 | C IYD - YEAR AND DAY AS YYDDD (day of year from 1 to 365 (or 366)) 47 | C (Year ignored in current model) 48 | C SEC - UT(SEC) 49 | C ALT - ALTITUDE(KM) 50 | C GLAT - GEODETIC LATITUDE(DEG) 51 | C GLONG - GEODETIC LONGITUDE(DEG) 52 | C STL - LOCAL APPARENT SOLAR TIME(HRS; see Note below) 53 | C F107A - 81 day AVERAGE OF F10.7 FLUX (centered on day DDD) 54 | C F107 - DAILY F10.7 FLUX FOR PREVIOUS DAY 55 | C AP - MAGNETIC INDEX(DAILY) OR WHEN SW(9)=-1. : 56 | C - ARRAY CONTAINING: 57 | C (1) DAILY AP 58 | C (2) 3 HR AP INDEX FOR CURRENT TIME 59 | C (3) 3 HR AP INDEX FOR 3 HRS BEFORE CURRENT TIME 60 | C (4) 3 HR AP INDEX FOR 6 HRS BEFORE CURRENT TIME 61 | C (5) 3 HR AP INDEX FOR 9 HRS BEFORE CURRENT TIME 62 | C (6) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 12 TO 33 HRS PRIOR 63 | C TO CURRENT TIME 64 | C (7) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 36 TO 57 HRS PRIOR 65 | C TO CURRENT TIME 66 | C MASS - MASS NUMBER (ONLY DENSITY FOR SELECTED GAS IS 67 | C CALCULATED. MASS 0 IS TEMPERATURE. MASS 48 FOR ALL. 68 | C MASS 17 IS Anomalous O ONLY.) 69 | C 70 | C NOTES ON INPUT VARIABLES: 71 | C UT, Local Time, and Longitude are used independently in the 72 | C model and are not of equal importance for every situation. 73 | C For the most physically realistic calculation these three 74 | C variables should be consistent (STL=SEC/3600+GLONG/15). 75 | C The Equation of Time departures from the above formula 76 | C for apparent local time can be included if available but 77 | C are of minor importance. 78 | c 79 | C F107 and F107A values used to generate the model correspond 80 | C to the 10.7 cm radio flux at the actual distance of the Earth 81 | C from the Sun rather than the radio flux at 1 AU. The following 82 | C site provides both classes of values: 83 | C ftp://ftp.ngdc.noaa.gov/STP/SOLAR_DATA/SOLAR_RADIO/FLUX/ 84 | C 85 | C F107, F107A, and AP effects are neither large nor well 86 | C established below 80 km and these parameters should be set to 87 | C 150., 150., and 4. respectively. 88 | C 89 | C OUTPUT VARIABLES: 90 | C D(1) - HE NUMBER DENSITY(CM-3) 91 | C D(2) - O NUMBER DENSITY(CM-3) 92 | C D(3) - N2 NUMBER DENSITY(CM-3) 93 | C D(4) - O2 NUMBER DENSITY(CM-3) 94 | C D(5) - AR NUMBER DENSITY(CM-3) 95 | C D(6) - TOTAL MASS DENSITY(GM/CM3) 96 | C D(7) - H NUMBER DENSITY(CM-3) 97 | C D(8) - N NUMBER DENSITY(CM-3) 98 | C D(9) - Anomalous oxygen NUMBER DENSITY(CM-3) 99 | C T(1) - EXOSPHERIC TEMPERATURE 100 | C T(2) - TEMPERATURE AT ALT 101 | C 102 | C NOTES ON OUTPUT VARIABLES: 103 | C TO GET OUTPUT IN M-3 and KG/M3: CALL METERS(.TRUE.) 104 | C 105 | C O, H, and N are set to zero below 72.5 km 106 | C 107 | C T(1), Exospheric temperature, is set to global average for 108 | C altitudes below 120 km. The 120 km gradient is left at global 109 | C average value for altitudes below 72 km. 110 | C 111 | C D(6), TOTAL MASS DENSITY, is NOT the same for subroutines GTD7 112 | C and GTD7D 113 | C 114 | C SUBROUTINE GTD7 -- D(6) is the sum of the mass densities of the 115 | C species labeled by indices 1-5 and 7-8 in output variable D. 116 | C This includes He, O, N2, O2, Ar, H, and N but does NOT include 117 | C anomalous oxygen (species index 9). 118 | C 119 | C SUBROUTINE GTD7D -- D(6) is the "effective total mass density 120 | C for drag" and is the sum of the mass densities of all species 121 | C in this model, INCLUDING anomalous oxygen. 122 | C 123 | C SWITCHES: The following is for test and special purposes: 124 | C 125 | C TO TURN ON AND OFF PARTICULAR VARIATIONS CALL TSELEC(SW), 126 | C WHERE SW IS A 25 ELEMENT ARRAY CONTAINING 0. FOR OFF, 1. 127 | C FOR ON, OR 2. FOR MAIN EFFECTS OFF BUT CROSS TERMS ON 128 | C FOR THE FOLLOWING VARIATIONS 129 | C 1 - F10.7 EFFECT ON MEAN 2 - TIME INDEPENDENT 130 | C 3 - SYMMETRICAL ANNUAL 4 - SYMMETRICAL SEMIANNUAL 131 | C 5 - ASYMMETRICAL ANNUAL 6 - ASYMMETRICAL SEMIANNUAL 132 | C 7 - DIURNAL 8 - SEMIDIURNAL 133 | C 9 - DAILY AP 10 - ALL UT/LONG EFFECTS 134 | C 11 - LONGITUDINAL 12 - UT AND MIXED UT/LONG 135 | C 13 - MIXED AP/UT/LONG 14 - TERDIURNAL 136 | C 15 - DEPARTURES FROM DIFFUSIVE EQUILIBRIUM 137 | C 16 - ALL TINF VAR 17 - ALL TLB VAR 138 | C 18 - ALL TN1 VAR 19 - ALL S VAR 139 | C 20 - ALL TN2 VAR 21 - ALL NLB VAR 140 | C 22 - ALL TN3 VAR 23 - TURBO SCALE HEIGHT VAR 141 | C 142 | C To get current values of SW: CALL TRETRV(SW) 143 | C 144 | Real,Intent(OUT):: D(9), T(2) 145 | Real,Intent(In) :: SEC,ALT,GLAT,GLONG,STL,F107A,F107,AP(7) 146 | Integer,Intent(IN)::IYD,MASS 147 | 148 | Real DS(9),TS(2) 149 | real ZN3(5),ZN2(4),SV(25) 150 | 151 | COMMON/GTS3C/TLB,S,DB04,DB16,DB28,DB32,DB40,DB48,DB01,ZA,T0,Z0 152 | & ,G0,RL,DD,DB14,TR12 153 | COMMON/MESO7/TN1(5),TN2(4),TN3(5),TGN1(2),TGN2(2),TGN3(2) 154 | 155 | COMMON/PARM7g/PT(150),PD(150,9),PS(150),PDL(25,2),PTL(100,4), 156 | $ PMA(100,10),SAM(100) 157 | 158 | COMMON/CSW/SW(25),ISW,SWC(25) 159 | COMMON/DMIX/DM04,DM16,DM28,DM32,DM40,DM01,DM14 160 | COMMON/PARMB/GSURF,RE 161 | COMMON/METSEL/IMR 162 | SAVE 163 | 164 | DATA MN3/5/,ZN3/32.5,20.,15.,10.,0./ 165 | DATA MN2/4/,ZN2/72.5,55.,45.,32.5/ 166 | DATA ZMIX/62.5/,ALAST/99999./,MSSL/-999/ 167 | DATA SV/25*1./ 168 | IF(ISW.NE.64999) CALL TSELEC(SV) 169 | C 170 | C Test for changed input 171 | V1=VTST7(IYD,SEC,GLAT,GLONG,STL,F107A,F107,AP,1) 172 | C Latitude variation of gravity (none for SW(2)=0) 173 | XLAT=GLAT 174 | IF(SW(2).EQ.0) XLAT=45. 175 | CALL GLATF(XLAT,GSURF,RE) 176 | C 177 | XMM=PDM(5,3) 178 | C 179 | C THERMOSPHERE/MESOSPHERE (above ZN2(1)) 180 | ALTT=MAX(ALT,ZN2(1)) 181 | MSS=MASS 182 | C Only calculate N2 in thermosphere if alt in mixed region 183 | IF(ALT.LT.ZMIX.AND.MASS.GT.0) MSS=28 184 | C Only calculate thermosphere if input parameters changed 185 | C or altitude above ZN2(1) in mesosphere 186 | IF(V1.EQ.1..OR.ALT.GT.ZN2(1).OR.ALAST.GT.ZN2(1).OR.MSS.NE.MSSL) 187 | $ THEN 188 | CALL GTS7(IYD,SEC,ALTT,GLAT,GLONG,STL,F107A,F107,AP,MSS,DS,TS) 189 | DM28M=DM28 190 | C metric adjustment 191 | IF(IMR.EQ.1) DM28M=DM28*1.E6 192 | MSSL=MSS 193 | ENDIF 194 | T(1)=TS(1) 195 | T(2)=TS(2) 196 | IF(ALT.GE.ZN2(1)) THEN 197 | DO 5 J=1,9 198 | D(J)=DS(J) 199 | 5 CONTINUE 200 | GOTO 10 201 | ENDIF 202 | C 203 | C LOWER MESOSPHERE/UPPER STRATOSPHERE [between ZN3(1) and ZN2(1)] 204 | C Temperature at nodes and gradients at end nodes 205 | C Inverse temperature a linear function of spherical harmonics 206 | C Only calculate nodes if input changed 207 | IF(V1.EQ.1..OR.ALAST.GE.ZN2(1)) THEN 208 | TGN2(1)=TGN1(2) 209 | TN2(1)=TN1(5) 210 | TN2(2)=PMA(1,1)*PAVGM(1)/(1.-SW(20)*GLOB7S(PMA(1,1))) 211 | TN2(3)=PMA(1,2)*PAVGM(2)/(1.-SW(20)*GLOB7S(PMA(1,2))) 212 | TN2(4)=PMA(1,3)*PAVGM(3)/(1.-SW(20)*SW(22)*GLOB7S(PMA(1,3))) 213 | TGN2(2)=PAVGM(9)*PMA(1,10)*(1.+SW(20)*SW(22)*GLOB7S(PMA(1,10))) 214 | $ *TN2(4)*TN2(4)/(PMA(1,3)*PAVGM(3))**2 215 | TN3(1)=TN2(4) 216 | ENDIF 217 | C Including ZN3(1) in the jump condition creates a model coverage gap at that exact altitude 218 | C IF(ALT.GE.ZN3(1)) GOTO 6 219 | IF(ALT.GT.ZN3(1)) GOTO 6 220 | C 221 | C LOWER STRATOSPHERE AND TROPOSPHERE [below ZN3(1)] 222 | C Temperature at nodes and gradients at end nodes 223 | C Inverse temperature a linear function of spherical harmonics 224 | C Only calculate nodes if input changed 225 | IF(V1.EQ.1..OR.ALAST.GE.ZN3(1)) THEN 226 | TGN3(1)=TGN2(2) 227 | TN3(2)=PMA(1,4)*PAVGM(4)/(1.-SW(22)*GLOB7S(PMA(1,4))) 228 | TN3(3)=PMA(1,5)*PAVGM(5)/(1.-SW(22)*GLOB7S(PMA(1,5))) 229 | TN3(4)=PMA(1,6)*PAVGM(6)/(1.-SW(22)*GLOB7S(PMA(1,6))) 230 | TN3(5)=PMA(1,7)*PAVGM(7)/(1.-SW(22)*GLOB7S(PMA(1,7))) 231 | TGN3(2)=PMA(1,8)*PAVGM(8)*(1.+SW(22)*GLOB7S(PMA(1,8))) 232 | $ *TN3(5)*TN3(5)/(PMA(1,7)*PAVGM(7))**2 233 | ENDIF 234 | 6 CONTINUE 235 | IF(MASS.EQ.0) GOTO 50 236 | C LINEAR TRANSITION TO FULL MIXING BELOW ZN2(1) 237 | DMC=0 238 | IF(ALT.GT.ZMIX) DMC=1.-(ZN2(1)-ALT)/(ZN2(1)-ZMIX) 239 | DZ28=DS(3) 240 | C ***** N2 DENSITY **** 241 | DMR=DS(3)/DM28M-1. 242 | D(3)=DENSM(ALT,DM28M,XMM,TZ,MN3,ZN3,TN3,TGN3,MN2,ZN2,TN2,TGN2) 243 | D(3)=D(3)*(1.+DMR*DMC) 244 | C ***** HE DENSITY **** 245 | D(1)=0 246 | IF(MASS.NE.4.AND.MASS.NE.48) GOTO 204 247 | DMR=DS(1)/(DZ28*PDM(2,1))-1. 248 | D(1)=D(3)*PDM(2,1)*(1.+DMR*DMC) 249 | 204 CONTINUE 250 | C **** O DENSITY **** 251 | D(2)=0 252 | D(9)=0 253 | 216 CONTINUE 254 | C ***** O2 DENSITY **** 255 | D(4)=0 256 | IF(MASS.NE.32.AND.MASS.NE.48) GOTO 232 257 | DMR=DS(4)/(DZ28*PDM(2,4))-1. 258 | D(4)=D(3)*PDM(2,4)*(1.+DMR*DMC) 259 | 232 CONTINUE 260 | C ***** AR DENSITY **** 261 | D(5)=0 262 | IF(MASS.NE.40.AND.MASS.NE.48) GOTO 240 263 | DMR=DS(5)/(DZ28*PDM(2,5))-1. 264 | D(5)=D(3)*PDM(2,5)*(1.+DMR*DMC) 265 | 240 CONTINUE 266 | C ***** HYDROGEN DENSITY **** 267 | D(7)=0 268 | C ***** ATOMIC NITROGEN DENSITY **** 269 | D(8)=0 270 | C 271 | C TOTAL MASS DENSITY 272 | C 273 | IF(MASS.EQ.48) THEN 274 | D(6) = 1.66E-24*(4.*D(1)+16.*D(2)+28.*D(3)+32.*D(4)+40.*D(5)+ 275 | & D(7)+14.*D(8)) 276 | IF(IMR.EQ.1) D(6)=D(6)/1000. 277 | ENDIF 278 | T(2)=TZ 279 | 10 CONTINUE 280 | GOTO 90 281 | 50 CONTINUE 282 | DD=DENSM(ALT,1.,0.,TZ,MN3,ZN3,TN3,TGN3,MN2,ZN2,TN2,TGN2) 283 | T(2)=TZ 284 | 90 CONTINUE 285 | ALAST=ALT 286 | RETURN 287 | END 288 | C----------------------------------------------------------------------- 289 | SUBROUTINE GTD7D(IYD,SEC,ALT,GLAT,GLONG,STL,F107A,F107,AP,MASS, 290 | $ D,T) 291 | C 292 | C NRLMSISE-00 293 | C ----------- 294 | C This subroutine provides Effective Total Mass Density for 295 | C output D(6) which includes contributions from "anomalous 296 | C oxygen" which can affect satellite drag above 500 km. This 297 | C subroutine is part of the distribution package for the 298 | C Neutral Atmosphere Empirical Model from the surface to lower 299 | C exosphere. See subroutine GTD7 for more extensive comments. 300 | C 301 | C INPUT VARIABLES: 302 | C IYD - YEAR AND DAY AS YYDDD (day of year from 1 to 365 (or 366)) 303 | C (Year ignored in current model) 304 | C SEC - UT(SEC) 305 | C ALT - ALTITUDE(KM) 306 | C GLAT - GEODETIC LATITUDE(DEG) 307 | C GLONG - GEODETIC LONGITUDE(DEG) 308 | C STL - LOCAL APPARENT SOLAR TIME(HRS; see Note below) 309 | C F107A - 81 day AVERAGE OF F10.7 FLUX (centered on day DDD) 310 | C F107 - DAILY F10.7 FLUX FOR PREVIOUS DAY 311 | C AP - MAGNETIC INDEX(DAILY) OR WHEN SW(9)=-1. : 312 | C - ARRAY CONTAINING: 313 | C (1) DAILY AP 314 | C (2) 3 HR AP INDEX FOR CURRENT TIME 315 | C (3) 3 HR AP INDEX FOR 3 HRS BEFORE CURRENT TIME 316 | C (4) 3 HR AP INDEX FOR 6 HRS BEFORE CURRENT TIME 317 | C (5) 3 HR AP INDEX FOR 9 HRS BEFORE CURRENT TIME 318 | C (6) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 12 TO 33 HRS PRIOR 319 | C TO CURRENT TIME 320 | C (7) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 36 TO 57 HRS PRIOR 321 | C TO CURRENT TIME 322 | C MASS - MASS NUMBER (ONLY DENSITY FOR SELECTED GAS IS 323 | C CALCULATED. MASS 0 IS TEMPERATURE. MASS 48 FOR ALL. 324 | C MASS 17 IS Anomalous O ONLY.) 325 | C 326 | C NOTES ON INPUT VARIABLES: 327 | C UT, Local Time, and Longitude are used independently in the 328 | C model and are not of equal importance for every situation. 329 | C For the most physically realistic calculation these three 330 | C variables should be consistent (STL=SEC/3600+GLONG/15). 331 | C The Equation of Time departures from the above formula 332 | C for apparent local time can be included if available but 333 | C are of minor importance. 334 | c 335 | C F107 and F107A values used to generate the model correspond 336 | C to the 10.7 cm radio flux at the actual distance of the Earth 337 | C from the Sun rather than the radio flux at 1 AU. 338 | C 339 | C OUTPUT VARIABLES: 340 | C D(1) - HE NUMBER DENSITY(CM-3) 341 | C D(2) - O NUMBER DENSITY(CM-3) 342 | C D(3) - N2 NUMBER DENSITY(CM-3) 343 | C D(4) - O2 NUMBER DENSITY(CM-3) 344 | C D(5) - AR NUMBER DENSITY(CM-3) 345 | C D(6) - TOTAL MASS DENSITY(GM/CM3) [includes anomalous oxygen] 346 | C D(7) - H NUMBER DENSITY(CM-3) 347 | C D(8) - N NUMBER DENSITY(CM-3) 348 | C D(9) - Anomalous oxygen NUMBER DENSITY(CM-3) 349 | C T(1) - EXOSPHERIC TEMPERATURE 350 | C T(2) - TEMPERATURE AT ALT 351 | C 352 | DIMENSION D(9),T(2),AP(7),DS(9),TS(2) 353 | COMMON/METSEL/IMR 354 | CALL GTD7(IYD,SEC,ALT,GLAT,GLONG,STL,F107A,F107,AP,MASS,D,T) 355 | C TOTAL MASS DENSITY 356 | C 357 | IF(MASS.EQ.48) THEN 358 | D(6) = 1.66E-24*(4.*D(1)+16.*D(2)+28.*D(3)+32.*D(4)+40.*D(5)+ 359 | & D(7)+14.*D(8)+16.*D(9)) 360 | IF(IMR.EQ.1) D(6)=D(6)/1000. 361 | ENDIF 362 | END SUBROUTINE GTD7D 363 | C----------------------------------------------------------------------- 364 | SUBROUTINE GHP7(IYD,SEC,ALT,GLAT,GLONG,STL,F107A,F107,AP, 365 | $ D,T,PRESS) 366 | C FIND ALTITUDE OF PRESSURE SURFACE (PRESS) FROM GTD7 367 | C INPUT: 368 | C IYD - YEAR AND DAY AS YYDDD 369 | C SEC - UT(SEC) 370 | C GLAT - GEODETIC LATITUDE(DEG) 371 | C GLONG - GEODETIC LONGITUDE(DEG) 372 | C STL - LOCAL APPARENT SOLAR TIME(HRS) 373 | C F107A - 3 MONTH AVERAGE OF F10.7 FLUX 374 | C F107 - DAILY F10.7 FLUX FOR PREVIOUS DAY 375 | C AP - MAGNETIC INDEX(DAILY) OR WHEN SW(9)=-1. : 376 | C - ARRAY CONTAINING: 377 | C (1) DAILY AP 378 | C (2) 3 HR AP INDEX FOR CURRENT TIME 379 | C (3) 3 HR AP INDEX FOR 3 HRS BEFORE CURRENT TIME 380 | C (4) 3 HR AP INDEX FOR 6 HRS BEFORE CURRENT TIME 381 | C (5) 3 HR AP INDEX FOR 9 HRS BEFORE CURRENT TIME 382 | C (6) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 12 TO 33 HRS PRIOR 383 | C TO CURRENT TIME 384 | C (7) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 36 TO 59 HRS PRIOR 385 | C TO CURRENT TIME 386 | C PRESS - PRESSURE LEVEL(MB) 387 | C OUTPUT: 388 | C ALT - ALTITUDE(KM) 389 | C D(1) - HE NUMBER DENSITY(CM-3) 390 | C D(2) - O NUMBER DENSITY(CM-3) 391 | C D(3) - N2 NUMBER DENSITY(CM-3) 392 | C D(4) - O2 NUMBER DENSITY(CM-3) 393 | C D(5) - AR NUMBER DENSITY(CM-3) 394 | C D(6) - TOTAL MASS DENSITY(GM/CM3) 395 | C D(7) - H NUMBER DENSITY(CM-3) 396 | C D(8) - N NUMBER DENSITY(CM-3) 397 | C D(9) - HOT O NUMBER DENSITY(CM-3) 398 | C T(1) - EXOSPHERIC TEMPERATURE 399 | C T(2) - TEMPERATURE AT ALT 400 | C 401 | COMMON/PARMB/GSURF,RE 402 | COMMON/METSEL/IMR 403 | DIMENSION D(9),T(2),AP(7) 404 | SAVE 405 | DATA BM/1.3806E-19/,RGAS/831.4/ 406 | DATA TEST/.00043/,LTEST/12/ 407 | PL=ALOG10(PRESS) 408 | C Initial altitude estimate 409 | IF(PL.GE.-5.) THEN 410 | IF(PL.GT.2.5) ZI=18.06*(3.00-PL) 411 | IF(PL.GT..75.AND.PL.LE.2.5) ZI=14.98*(3.08-PL) 412 | IF(PL.GT.-1..AND.PL.LE..75) ZI=17.8*(2.72-PL) 413 | IF(PL.GT.-2..AND.PL.LE.-1.) ZI=14.28*(3.64-PL) 414 | IF(PL.GT.-4..AND.PL.LE.-2.) ZI=12.72*(4.32-PL) 415 | IF(PL.LE.-4.) ZI=25.3*(.11-PL) 416 | IDAY=MOD(IYD,1000) 417 | CL=GLAT/90. 418 | CL2=CL*CL 419 | IF(IDAY.LT.182) CD=1.-IDAY/91.25 420 | IF(IDAY.GE.182) CD=IDAY/91.25-3. 421 | CA=0 422 | IF(PL.GT.-1.11.AND.PL.LE.-.23) CA=1.0 423 | IF(PL.GT.-.23) CA=(2.79-PL)/(2.79+.23) 424 | IF(PL.LE.-1.11.AND.PL.GT.-3.) CA=(-2.93-PL)/(-2.93+1.11) 425 | Z=ZI-4.87*CL*CD*CA-1.64*CL2*CA+.31*CA*CL 426 | ENDIF 427 | IF(PL.LT.-5.) Z=22.*(PL+4.)**2+110 428 | C ITERATION LOOP 429 | L=0 430 | 10 CONTINUE 431 | L=L+1 432 | CALL GTD7(IYD,SEC,Z,GLAT,GLONG,STL,F107A,F107,AP,48,D,T) 433 | XN=D(1)+D(2)+D(3)+D(4)+D(5)+D(7)+D(8) 434 | P=BM*XN*T(2) 435 | IF(IMR.EQ.1) P=P*1.E-6 436 | DIFF=PL-ALOG10(P) 437 | IF(ABS(DIFF).LT.TEST .OR. L.EQ.LTEST) GOTO 20 438 | XM=D(6)/XN/1.66E-24 439 | IF(IMR.EQ.1) XM = XM*1.E3 440 | G=GSURF/(1.+Z/RE)**2 441 | SH=RGAS*T(2)/(XM*G) 442 | C New altitude estimate using scale height 443 | IF(L.LT.6) THEN 444 | Z=Z-SH*DIFF*2.302 445 | ELSE 446 | Z=Z-SH*DIFF 447 | ENDIF 448 | GOTO 10 449 | 20 CONTINUE 450 | IF(L.EQ.LTEST) write(stderr,100) PRESS,DIFF 451 | 100 FORMAT(1X,29HGHP7 NOT CONVERGING FOR PRESS, 1PE12.2,E12.2) 452 | ALT=Z 453 | 454 | END SUBROUTINE GHP7 455 | C----------------------------------------------------------------------- 456 | SUBROUTINE GLATF(LAT,GV,REFF) 457 | C CALCULATE LATITUDE VARIABLE GRAVITY (GV) AND EFFECTIVE 458 | C RADIUS (REFF) 459 | REAL LAT 460 | SAVE 461 | DATA DGTR/1.74533E-2/ 462 | C2 = COS(2.*DGTR*LAT) 463 | GV = 980.616*(1.-.0026373*C2) 464 | REFF = 2.*GV/(3.085462E-6 + 2.27E-9*C2)*1.E-5 465 | END SUBROUTINE GLATF 466 | C----------------------------------------------------------------------- 467 | FUNCTION VTST7(IYD,SEC,GLAT,GLONG,STL,F107A,F107,AP,IC) 468 | C Test if geophysical variables or switches changed and save 469 | C Return 0 if unchanged and 1 if changed 470 | DIMENSION AP(7),IYDL(2),SECL(2),GLATL(2),GLL(2),STLL(2) 471 | DIMENSION FAL(2),FL(2),APL(7,2),SWL(25,2),SWCL(25,2) 472 | COMMON/CSW/SW(25),ISW,SWC(25) 473 | SAVE 474 | DATA IYDL/2*-999/,SECL/2*-999./,GLATL/2*-999./,GLL/2*-999./ 475 | DATA STLL/2*-999./,FAL/2*-999./,FL/2*-999./,APL/14*-999./ 476 | DATA SWL/50*-999./,SWCL/50*-999./ 477 | VTST7=0 478 | IF(IYD.NE.IYDL(IC)) GOTO 10 479 | IF(SEC.NE.SECL(IC)) GOTO 10 480 | IF(GLAT.NE.GLATL(IC)) GOTO 10 481 | IF(GLONG.NE.GLL(IC)) GOTO 10 482 | IF(STL.NE.STLL(IC)) GOTO 10 483 | IF(F107A.NE.FAL(IC)) GOTO 10 484 | IF(F107.NE.FL(IC)) GOTO 10 485 | DO 5 I=1,7 486 | IF(AP(I).NE.APL(I,IC)) GOTO 10 487 | 5 CONTINUE 488 | DO 7 I=1,25 489 | IF(SW(I).NE.SWL(I,IC)) GOTO 10 490 | IF(SWC(I).NE.SWCL(I,IC)) GOTO 10 491 | 7 CONTINUE 492 | GOTO 20 493 | 10 CONTINUE 494 | VTST7=1 495 | IYDL(IC)=IYD 496 | SECL(IC)=SEC 497 | GLATL(IC)=GLAT 498 | GLL(IC)=GLONG 499 | STLL(IC)=STL 500 | FAL(IC)=F107A 501 | FL(IC)=F107 502 | DO 15 I=1,7 503 | APL(I,IC)=AP(I) 504 | 15 CONTINUE 505 | DO 16 I=1,25 506 | SWL(I,IC)=SW(I) 507 | SWCL(I,IC)=SWC(I) 508 | 16 CONTINUE 509 | 20 CONTINUE 510 | END FUNCTION VTST7 511 | C----------------------------------------------------------------------- 512 | SUBROUTINE GTS7(IYD,SEC,ALT,GLAT,GLONG,STL,F107A,F107,AP,MASS,D,T) 513 | C 514 | C Thermospheric portion of NRLMSISE-00 515 | C See GTD7 for more extensive comments 516 | C 517 | C OUTPUT IN M-3 and KG/M3: CALL METERS(.TRUE.) 518 | C 519 | C INPUT VARIABLES: 520 | C IYD - YEAR AND DAY AS YYDDD (day of year from 1 to 365 (or 366)) 521 | C (Year ignored in current model) 522 | C SEC - UT(SEC) 523 | C ALT - ALTITUDE(KM) (>72.5 km) 524 | C GLAT - GEODETIC LATITUDE(DEG) 525 | C GLONG - GEODETIC LONGITUDE(DEG) 526 | C STL - LOCAL APPARENT SOLAR TIME(HRS; see Note below) 527 | C F107A - 81 day AVERAGE OF F10.7 FLUX (centered on day DDD) 528 | C F107 - DAILY F10.7 FLUX FOR PREVIOUS DAY 529 | C AP - MAGNETIC INDEX(DAILY) OR WHEN SW(9)=-1. : 530 | C - ARRAY CONTAINING: 531 | C (1) DAILY AP 532 | C (2) 3 HR AP INDEX FOR CURRENT TIME 533 | C (3) 3 HR AP INDEX FOR 3 HRS BEFORE CURRENT TIME 534 | C (4) 3 HR AP INDEX FOR 6 HRS BEFORE CURRENT TIME 535 | C (5) 3 HR AP INDEX FOR 9 HRS BEFORE CURRENT TIME 536 | C (6) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 12 TO 33 HRS PRIOR 537 | C TO CURRENT TIME 538 | C (7) AVERAGE OF EIGHT 3 HR AP INDICIES FROM 36 TO 57 HRS PRIOR 539 | C TO CURRENT TIME 540 | C MASS - MASS NUMBER (ONLY DENSITY FOR SELECTED GAS IS 541 | C CALCULATED. MASS 0 IS TEMPERATURE. MASS 48 FOR ALL. 542 | C MASS 17 IS Anomalous O ONLY.) 543 | C 544 | C NOTES ON INPUT VARIABLES: 545 | C UT, Local Time, and Longitude are used independently in the 546 | C model and are not of equal importance for every situation. 547 | C For the most physically realistic calculation these three 548 | C variables should be consistent (STL=SEC/3600+GLONG/15). 549 | C The Equation of Time departures from the above formula 550 | C for apparent local time can be included if available but 551 | C are of minor importance. 552 | c 553 | C F107 and F107A values used to generate the model correspond 554 | C to the 10.7 cm radio flux at the actual distance of the Earth 555 | C from the Sun rather than the radio flux at 1 AU. The following 556 | C site provides both classes of values: 557 | C ftp://ftp.ngdc.noaa.gov/STP/SOLAR_DATA/SOLAR_RADIO/FLUX/ 558 | C 559 | C F107, F107A, and AP effects are neither large nor well 560 | C established below 80 km and these parameters should be set to 561 | C 150., 150., and 4. respectively. 562 | C 563 | C OUTPUT VARIABLES: 564 | C D(1) - HE NUMBER DENSITY(CM-3) 565 | C D(2) - O NUMBER DENSITY(CM-3) 566 | C D(3) - N2 NUMBER DENSITY(CM-3) 567 | C D(4) - O2 NUMBER DENSITY(CM-3) 568 | C D(5) - AR NUMBER DENSITY(CM-3) 569 | C D(6) - TOTAL MASS DENSITY(GM/CM3) [Anomalous O NOT included] 570 | C D(7) - H NUMBER DENSITY(CM-3) 571 | C D(8) - N NUMBER DENSITY(CM-3) 572 | C D(9) - Anomalous oxygen NUMBER DENSITY(CM-3) 573 | C T(1) - EXOSPHERIC TEMPERATURE 574 | C T(2) - TEMPERATURE AT ALT 575 | C 576 | DIMENSION ZN1(5),ALPHA(9) 577 | COMMON/GTS3C/TLB,S,DB04,DB16,DB28,DB32,DB40,DB48,DB01,ZA,T0,Z0 578 | & ,G0,RL,DD,DB14,TR12 579 | COMMON/MESO7/TN1(5),TN2(4),TN3(5),TGN1(2),TGN2(2),TGN3(2) 580 | DIMENSION D(9),T(2),MT(11),AP(7),ALTL(8) 581 | 582 | COMMON/PARM7g/PT(150),PD(150,9),PS(150),PDL(25,2),PTL(100,4), 583 | $ PMA(100,10),SAM(100) 584 | COMMON/CSW/SW(25),ISW,SWC(25) 585 | COMMON/TTEST/TINFG,GB,ROUT,TT(15) 586 | COMMON/DMIX/DM04,DM16,DM28,DM32,DM40,DM01,DM14 587 | COMMON/METSEL/IMR 588 | SAVE 589 | DATA MT/48,0,4,16,28,32,40,1,49,14,17/ 590 | DATA ALTL/200.,300.,160.,250.,240.,450.,320.,450./ 591 | DATA MN1/5/,ZN1/120.,110.,100.,90.,72.5/ 592 | DATA DGTR/1.74533E-2/,DR/1.72142E-2/,ALAST/-999./ 593 | DATA ALPHA/-0.38,0.,0.,0.,0.17,0.,-0.38,0.,0./ 594 | C Test for changed input 595 | V2=VTST7(IYD,SEC,GLAT,GLONG,STL,F107A,F107,AP,2) 596 | C 597 | YRD=IYD 598 | ZA=PDL(16,2) 599 | ZN1(1)=ZA 600 | DO 2 J=1,9 601 | D(J)=0. 602 | 2 CONTINUE 603 | C TINF VARIATIONS NOT IMPORTANT BELOW ZA OR ZN1(1) 604 | IF(ALT.GT.ZN1(1)) THEN 605 | IF(V2.EQ.1..OR.ALAST.LE.ZN1(1)) TINF=PTM(1)*PT(1) 606 | $ *(1.+SW(16)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PT)) 607 | ELSE 608 | TINF=PTM(1)*PT(1) 609 | ENDIF 610 | T(1)=TINF 611 | C GRADIENT VARIATIONS NOT IMPORTANT BELOW ZN1(5) 612 | IF(ALT.GT.ZN1(5)) THEN 613 | IF(V2.EQ.1.OR.ALAST.LE.ZN1(5)) G0=PTM(4)*PS(1) 614 | $ *(1.+SW(19)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PS)) 615 | ELSE 616 | G0=PTM(4)*PS(1) 617 | ENDIF 618 | C Calculate these temperatures only if input changed 619 | IF(V2.EQ.1. .OR. ALT.LT.300.) 620 | $ TLB=PTM(2)*(1.+SW(17)*GLOBE7(YRD,SEC,GLAT,GLONG,STL, 621 | $ F107A,F107,AP,PD(1,4)))*PD(1,4) 622 | S=G0/(TINF-TLB) 623 | C Lower thermosphere temp variations not significant for 624 | C density above 300 km 625 | IF(ALT.LT.300.) THEN 626 | IF(V2.EQ.1..OR.ALAST.GE.300.) THEN 627 | TN1(2)=PTM(7)*PTL(1,1)/(1.-SW(18)*GLOB7S(PTL(1,1))) 628 | TN1(3)=PTM(3)*PTL(1,2)/(1.-SW(18)*GLOB7S(PTL(1,2))) 629 | TN1(4)=PTM(8)*PTL(1,3)/(1.-SW(18)*GLOB7S(PTL(1,3))) 630 | TN1(5)=PTM(5)*PTL(1,4)/(1.-SW(18)*SW(20)*GLOB7S(PTL(1,4))) 631 | TGN1(2)=PTM(9)*PMA(1,9)*(1.+SW(18)*SW(20)*GLOB7S(PMA(1,9))) 632 | $ *TN1(5)*TN1(5)/(PTM(5)*PTL(1,4))**2 633 | ENDIF 634 | ELSE 635 | TN1(2)=PTM(7)*PTL(1,1) 636 | TN1(3)=PTM(3)*PTL(1,2) 637 | TN1(4)=PTM(8)*PTL(1,3) 638 | TN1(5)=PTM(5)*PTL(1,4) 639 | TGN1(2)=PTM(9)*PMA(1,9) 640 | $ *TN1(5)*TN1(5)/(PTM(5)*PTL(1,4))**2 641 | ENDIF 642 | C 643 | Z0=ZN1(4) 644 | T0=TN1(4) 645 | TR12=1. 646 | C 647 | IF(MASS.EQ.0) GO TO 50 648 | C N2 variation factor at Zlb 649 | G28=SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107, 650 | & AP,PD(1,3)) 651 | DAY=AMOD(YRD,1000.) 652 | C VARIATION OF TURBOPAUSE HEIGHT 653 | ZHF=PDL(25,2) 654 | $ *(1.+SW(5)*PDL(25,1)*SIN(DGTR*GLAT)*COS(DR*(DAY-PT(14)))) 655 | YRD=IYD 656 | T(1)=TINF 657 | XMM=PDM(5,3) 658 | Z=ALT 659 | C 660 | DO 10 J = 1,11 661 | IF(MASS.EQ.MT(J)) GO TO 15 662 | 10 CONTINUE 663 | WRITE(6,100) MASS 664 | GO TO 90 665 | 15 IF(Z.GT.ALTL(6).AND.MASS.NE.28.AND.MASS.NE.48) GO TO 17 666 | C 667 | C **** N2 DENSITY **** 668 | C 669 | C Diffusive density at Zlb 670 | DB28 = PDM(1,3)*EXP(G28)*PD(1,3) 671 | C Diffusive density at Alt 672 | D(3)=DENSU(Z,DB28,TINF,TLB, 28.,ALPHA(3),T(2),PTM(6),S,MN1,ZN1, 673 | & TN1,TGN1) 674 | DD=D(3) 675 | C Turbopause 676 | ZH28=PDM(3,3)*ZHF 677 | ZHM28=PDM(4,3)*PDL(6,2) 678 | XMD=28.-XMM 679 | C Mixed density at Zlb 680 | B28=DENSU(ZH28,DB28,TINF,TLB,XMD,ALPHA(3)-1.,TZ,PTM(6),S,MN1, 681 | & ZN1,TN1,TGN1) 682 | IF(Z.GT.ALTL(3).OR.SW(15).EQ.0.) GO TO 17 683 | C Mixed density at Alt 684 | DM28=DENSU(Z,B28,TINF,TLB,XMM,ALPHA(3),TZ,PTM(6),S,MN1, 685 | & ZN1,TN1,TGN1) 686 | C Net density at Alt 687 | D(3)=DNET(D(3),DM28,ZHM28,XMM,28.) 688 | 17 CONTINUE 689 | GO TO (20,50,20,25,90,35,40,45,25,48,46), J 690 | 20 CONTINUE 691 | C 692 | C **** HE DENSITY **** 693 | C 694 | C Density variation factor at Zlb 695 | G4 = SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PD(1,1)) 696 | C Diffusive density at Zlb 697 | DB04 = PDM(1,1)*EXP(G4)*PD(1,1) 698 | C Diffusive density at Alt 699 | D(1)=DENSU(Z,DB04,TINF,TLB, 4.,ALPHA(1),T(2),PTM(6),S,MN1,ZN1, 700 | & TN1,TGN1) 701 | DD=D(1) 702 | IF(Z.GT.ALTL(1).OR.SW(15).EQ.0.) GO TO 24 703 | C Turbopause 704 | ZH04=PDM(3,1) 705 | C Mixed density at Zlb 706 | B04=DENSU(ZH04,DB04,TINF,TLB,4.-XMM,ALPHA(1)-1., 707 | $ T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 708 | C Mixed density at Alt 709 | DM04=DENSU(Z,B04,TINF,TLB,XMM,0.,T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 710 | ZHM04=ZHM28 711 | C Net density at Alt 712 | D(1)=DNET(D(1),DM04,ZHM04,XMM,4.) 713 | C Correction to specified mixing ratio at ground 714 | RL=ALOG(B28*PDM(2,1)/B04) 715 | ZC04=PDM(5,1)*PDL(1,2) 716 | HC04=PDM(6,1)*PDL(2,2) 717 | C Net density corrected at Alt 718 | D(1)=D(1)*CCOR(Z,RL,HC04,ZC04) 719 | 24 CONTINUE 720 | IF(MASS.NE.48) GO TO 90 721 | 25 CONTINUE 722 | C 723 | C **** O DENSITY **** 724 | C 725 | C Density variation factor at Zlb 726 | G16= SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PD(1,2)) 727 | C Diffusive density at Zlb 728 | DB16 = PDM(1,2)*EXP(G16)*PD(1,2) 729 | C Diffusive density at Alt 730 | D(2)=DENSU(Z,DB16,TINF,TLB, 16.,ALPHA(2),T(2),PTM(6),S,MN1, 731 | $ ZN1,TN1,TGN1) 732 | DD=D(2) 733 | IF(Z.GT.ALTL(2).OR.SW(15).EQ.0.) GO TO 34 734 | C Corrected from PDM(3,1) to PDM(3,2) 12/2/85 735 | C Turbopause 736 | ZH16=PDM(3,2) 737 | C Mixed density at Zlb 738 | B16=DENSU(ZH16,DB16,TINF,TLB,16-XMM,ALPHA(2)-1., 739 | $ T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 740 | C Mixed density at Alt 741 | DM16=DENSU(Z,B16,TINF,TLB,XMM,0.,T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 742 | ZHM16=ZHM28 743 | C Net density at Alt 744 | D(2)=DNET(D(2),DM16,ZHM16,XMM,16.) 745 | C 3/16/99 Change form to match O2 departure from diff equil near 150 746 | C km and add dependence on F10.7 747 | C RL=ALOG(B28*PDM(2,2)*ABS(PDL(17,2))/B16) 748 | RL=PDM(2,2)*PDL(17,2)*(1.+SW(1)*PDL(24,1)*(F107A-150.)) 749 | HC16=PDM(6,2)*PDL(4,2) 750 | ZC16=PDM(5,2)*PDL(3,2) 751 | HC216=PDM(6,2)*PDL(5,2) 752 | D(2)=D(2)*CCOR2(Z,RL,HC16,ZC16,HC216) 753 | C Chemistry correction 754 | HCC16=PDM(8,2)*PDL(14,2) 755 | ZCC16=PDM(7,2)*PDL(13,2) 756 | RC16=PDM(4,2)*PDL(15,2) 757 | C Net density corrected at Alt 758 | D(2)=D(2)*CCOR(Z,RC16,HCC16,ZCC16) 759 | 34 CONTINUE 760 | IF(MASS.NE.48.AND.MASS.NE.49) GO TO 90 761 | 35 CONTINUE 762 | C 763 | C **** O2 DENSITY **** 764 | C 765 | C Density variation factor at Zlb 766 | G32= SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PD(1,5)) 767 | C Diffusive density at Zlb 768 | DB32 = PDM(1,4)*EXP(G32)*PD(1,5) 769 | C Diffusive density at Alt 770 | D(4)=DENSU(Z,DB32,TINF,TLB, 32.,ALPHA(4),T(2),PTM(6),S,MN1, 771 | $ ZN1,TN1,TGN1) 772 | IF(MASS.EQ.49) THEN 773 | DD=DD+2.*D(4) 774 | ELSE 775 | DD=D(4) 776 | ENDIF 777 | IF(SW(15).EQ.0.) GO TO 39 778 | IF(Z.GT.ALTL(4)) GO TO 38 779 | C Turbopause 780 | ZH32=PDM(3,4) 781 | C Mixed density at Zlb 782 | B32=DENSU(ZH32,DB32,TINF,TLB,32.-XMM,ALPHA(4)-1., 783 | $ T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 784 | C Mixed density at Alt 785 | DM32=DENSU(Z,B32,TINF,TLB,XMM,0.,T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 786 | ZHM32=ZHM28 787 | C Net density at Alt 788 | D(4)=DNET(D(4),DM32,ZHM32,XMM,32.) 789 | C Correction to specified mixing ratio at ground 790 | RL=ALOG(B28*PDM(2,4)/B32) 791 | HC32=PDM(6,4)*PDL(8,2) 792 | ZC32=PDM(5,4)*PDL(7,2) 793 | D(4)=D(4)*CCOR(Z,RL,HC32,ZC32) 794 | 38 CONTINUE 795 | C Correction for general departure from diffusive equilibrium above Zlb 796 | HCC32=PDM(8,4)*PDL(23,2) 797 | HCC232=PDM(8,4)*PDL(23,1) 798 | ZCC32=PDM(7,4)*PDL(22,2) 799 | RC32=PDM(4,4)*PDL(24,2)*(1.+SW(1)*PDL(24,1)*(F107A-150.)) 800 | C Net density corrected at Alt 801 | D(4)=D(4)*CCOR2(Z,RC32,HCC32,ZCC32,HCC232) 802 | 39 CONTINUE 803 | IF(MASS.NE.48) GO TO 90 804 | 40 CONTINUE 805 | C 806 | C **** AR DENSITY **** 807 | C 808 | C Density variation factor at Zlb 809 | G40= SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PD(1,6)) 810 | C Diffusive density at Zlb 811 | DB40 = PDM(1,5)*EXP(G40)*PD(1,6) 812 | C Diffusive density at Alt 813 | D(5)=DENSU(Z,DB40,TINF,TLB, 40.,ALPHA(5),T(2),PTM(6),S,MN1, 814 | $ ZN1,TN1,TGN1) 815 | DD=D(5) 816 | IF(Z.GT.ALTL(5).OR.SW(15).EQ.0.) GO TO 44 817 | C Turbopause 818 | ZH40=PDM(3,5) 819 | C Mixed density at Zlb 820 | B40=DENSU(ZH40,DB40,TINF,TLB,40.-XMM,ALPHA(5)-1., 821 | $ T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 822 | C Mixed density at Alt 823 | DM40=DENSU(Z,B40,TINF,TLB,XMM,0.,T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 824 | ZHM40=ZHM28 825 | C Net density at Alt 826 | D(5)=DNET(D(5),DM40,ZHM40,XMM,40.) 827 | C Correction to specified mixing ratio at ground 828 | RL=ALOG(B28*PDM(2,5)/B40) 829 | HC40=PDM(6,5)*PDL(10,2) 830 | ZC40=PDM(5,5)*PDL(9,2) 831 | C Net density corrected at Alt 832 | D(5)=D(5)*CCOR(Z,RL,HC40,ZC40) 833 | 44 CONTINUE 834 | IF(MASS.NE.48) GO TO 90 835 | 45 CONTINUE 836 | C 837 | C **** HYDROGEN DENSITY **** 838 | C 839 | C Density variation factor at Zlb 840 | G1 = SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PD(1,7)) 841 | C Diffusive density at Zlb 842 | DB01 = PDM(1,6)*EXP(G1)*PD(1,7) 843 | C Diffusive density at Alt 844 | D(7)=DENSU(Z,DB01,TINF,TLB,1.,ALPHA(7),T(2),PTM(6),S,MN1, 845 | $ ZN1,TN1,TGN1) 846 | DD=D(7) 847 | IF(Z.GT.ALTL(7).OR.SW(15).EQ.0.) GO TO 47 848 | C Turbopause 849 | ZH01=PDM(3,6) 850 | C Mixed density at Zlb 851 | B01=DENSU(ZH01,DB01,TINF,TLB,1.-XMM,ALPHA(7)-1., 852 | $ T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 853 | C Mixed density at Alt 854 | DM01=DENSU(Z,B01,TINF,TLB,XMM,0.,T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 855 | ZHM01=ZHM28 856 | C Net density at Alt 857 | D(7)=DNET(D(7),DM01,ZHM01,XMM,1.) 858 | C Correction to specified mixing ratio at ground 859 | RL=ALOG(B28*PDM(2,6)*ABS(PDL(18,2))/B01) 860 | HC01=PDM(6,6)*PDL(12,2) 861 | ZC01=PDM(5,6)*PDL(11,2) 862 | D(7)=D(7)*CCOR(Z,RL,HC01,ZC01) 863 | C Chemistry correction 864 | HCC01=PDM(8,6)*PDL(20,2) 865 | ZCC01=PDM(7,6)*PDL(19,2) 866 | RC01=PDM(4,6)*PDL(21,2) 867 | C Net density corrected at Alt 868 | D(7)=D(7)*CCOR(Z,RC01,HCC01,ZCC01) 869 | 47 CONTINUE 870 | IF(MASS.NE.48) GO TO 90 871 | 48 CONTINUE 872 | C 873 | C **** ATOMIC NITROGEN DENSITY **** 874 | C 875 | C Density variation factor at Zlb 876 | G14 = SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PD(1,8)) 877 | C Diffusive density at Zlb 878 | DB14 = PDM(1,7)*EXP(G14)*PD(1,8) 879 | C Diffusive density at Alt 880 | D(8)=DENSU(Z,DB14,TINF,TLB,14.,ALPHA(8),T(2),PTM(6),S,MN1, 881 | $ ZN1,TN1,TGN1) 882 | DD=D(8) 883 | IF(Z.GT.ALTL(8).OR.SW(15).EQ.0.) GO TO 49 884 | C Turbopause 885 | ZH14=PDM(3,7) 886 | C Mixed density at Zlb 887 | B14=DENSU(ZH14,DB14,TINF,TLB,14.-XMM,ALPHA(8)-1., 888 | $ T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 889 | C Mixed density at Alt 890 | DM14=DENSU(Z,B14,TINF,TLB,XMM,0.,T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 891 | ZHM14=ZHM28 892 | C Net density at Alt 893 | D(8)=DNET(D(8),DM14,ZHM14,XMM,14.) 894 | C Correction to specified mixing ratio at ground 895 | RL=ALOG(B28*PDM(2,7)*ABS(PDL(3,1))/B14) 896 | HC14=PDM(6,7)*PDL(2,1) 897 | ZC14=PDM(5,7)*PDL(1,1) 898 | D(8)=D(8)*CCOR(Z,RL,HC14,ZC14) 899 | C Chemistry correction 900 | HCC14=PDM(8,7)*PDL(5,1) 901 | ZCC14=PDM(7,7)*PDL(4,1) 902 | RC14=PDM(4,7)*PDL(6,1) 903 | C Net density corrected at Alt 904 | D(8)=D(8)*CCOR(Z,RC14,HCC14,ZCC14) 905 | 49 CONTINUE 906 | IF(MASS.NE.48) GO TO 90 907 | 46 CONTINUE 908 | C 909 | C **** Anomalous OXYGEN DENSITY **** 910 | C 911 | G16H = SW(21)*GLOBE7(YRD,SEC,GLAT,GLONG,STL,F107A,F107,AP,PD(1,9)) 912 | DB16H = PDM(1,8)*EXP(G16H)*PD(1,9) 913 | THO=PDM(10,8)*PDL(7,1) 914 | DD=DENSU(Z,DB16H,THO,THO,16.,ALPHA(9),T2,PTM(6),S,MN1, 915 | $ ZN1,TN1,TGN1) 916 | ZSHT=PDM(6,8) 917 | ZMHO=PDM(5,8) 918 | ZSHO=SCALH(ZMHO,16.,THO) 919 | D(9)=DD*EXP(-ZSHT/ZSHO*(EXP(-(Z-ZMHO)/ZSHT)-1.)) 920 | IF(MASS.NE.48) GO TO 90 921 | C 922 | C TOTAL MASS DENSITY 923 | C 924 | D(6) = 1.66E-24*(4.*D(1)+16.*D(2)+28.*D(3)+32.*D(4)+40.*D(5)+ 925 | & D(7)+14.*D(8)) 926 | DB48=1.66E-24*(4.*DB04+16.*DB16+28.*DB28+32.*DB32+40.*DB40+DB01+ 927 | & 14.*DB14) 928 | GO TO 90 929 | C TEMPERATURE AT ALTITUDE 930 | 50 CONTINUE 931 | Z=ABS(ALT) 932 | DDUM = DENSU(Z,1., TINF,TLB,0.,0.,T(2),PTM(6),S,MN1,ZN1,TN1,TGN1) 933 | 90 CONTINUE 934 | C ADJUST DENSITIES FROM CGS TO KGM 935 | IF(IMR.EQ.1) THEN 936 | DO 95 I=1,9 937 | D(I)=D(I)*1.E6 938 | 95 CONTINUE 939 | D(6)=D(6)/1000. 940 | ENDIF 941 | ALAST=ALT 942 | RETURN 943 | 100 FORMAT(1X,'MASS', I5, ' NOT VALID') 944 | END Subroutine GTS7 945 | C----------------------------------------------------------------------- 946 | SUBROUTINE METERS(METER) 947 | implicit none (external) 948 | C Convert outputs to Kg & Meters if METER true 949 | logical,Intent(In) :: METER 950 | Integer IMR 951 | COMMON/METSEL/IMR 952 | SAVE 953 | IMR=0 954 | IF(METER) IMR=1 955 | END SUBROUTINE METERS 956 | C----------------------------------------------------------------------- 957 | FUNCTION SCALH(ALT,XM,TEMP) 958 | C Calculate scale height (km) 959 | COMMON/PARMB/GSURF,RE 960 | SAVE 961 | DATA RGAS/831.4/ 962 | G=GSURF/(1.+ALT/RE)**2 963 | SCALH=RGAS*TEMP/(G*XM) 964 | END FUNCTION SCALH 965 | C----------------------------------------------------------------------- 966 | FUNCTION GLOBE7(YRD,SEC,LAT,LONG,TLOC,F107A,F107,AP,P) 967 | C CALCULATE G(L) FUNCTION 968 | C Upper Thermosphere Parameters 969 | REAL LAT, LONG 970 | DIMENSION P(150),SV(25),AP(7) 971 | COMMON/TTEST/TINF,GB,ROUT,T(15) 972 | COMMON/CSW/SW(25),ISW,SWC(25) 973 | COMMON/LPOLY/PLG(9,4),CTLOC,STLOC,C2TLOC,S2TLOC,C3TLOC,S3TLOC, 974 | $ IYR,DAY,DF,DFA,APD,APDF,APT(4),XLONG 975 | SAVE 976 | DATA DGTR/1.74533E-2/,DR/1.72142E-2/, XL/1000./,TLL/1000./ 977 | DATA SW9/1./,DAYL/-1./,P14/-1000./,P18/-1000./,P32/-1000./ 978 | DATA HR/.2618/,SR/7.2722E-5/,SV/25*1./,NSW/14/,P39/-1000./ 979 | C 3hr Magnetic activity functions 980 | C Eq. A24d 981 | G0(A)=(A-4.+(P(26)-1.)*(A-4.+(EXP(-ABS(P(25))*(A-4.))-1.)/ABS(P(25 982 | *)))) 983 | C Eq. A24c 984 | SUMEX(EX)=1.+(1.-EX**19)/(1.-EX)*EX**(.5) 985 | C Eq. A24a 986 | SG0(EX)=(G0(AP(2))+(G0(AP(3))*EX+G0(AP(4))*EX*EX+G0(AP(5))*EX**3 987 | $ +(G0(AP(6))*EX**4+G0(AP(7))*EX**12)*(1.-EX**8)/(1.-EX)) 988 | $ )/SUMEX(EX) 989 | IF(ISW.NE.64999) CALL TSELEC(SV) 990 | DO 10 J=1,14 991 | T(J)=0 992 | 10 CONTINUE 993 | IF(SW(9).GT.0) SW9=1. 994 | IF(SW(9).LT.0) SW9=-1. 995 | IYR = YRD/1000. 996 | DAY = YRD - IYR*1000. 997 | XLONG=LONG 998 | C Eq. A22 (remainder of code) 999 | IF(XL.EQ.LAT) GO TO 15 1000 | C CALCULATE LEGENDRE POLYNOMIALS 1001 | C = SIN(LAT*DGTR) 1002 | S = COS(LAT*DGTR) 1003 | C2 = C*C 1004 | C4 = C2*C2 1005 | S2 = S*S 1006 | PLG(2,1) = C 1007 | PLG(3,1) = 0.5*(3.*C2 -1.) 1008 | PLG(4,1) = 0.5*(5.*C*C2-3.*C) 1009 | PLG(5,1) = (35.*C4 - 30.*C2 + 3.)/8. 1010 | PLG(6,1) = (63.*C2*C2*C - 70.*C2*C + 15.*C)/8. 1011 | PLG(7,1) = (11.*C*PLG(6,1) - 5.*PLG(5,1))/6. 1012 | C PLG(8,1) = (13.*C*PLG(7,1) - 6.*PLG(6,1))/7. 1013 | PLG(2,2) = S 1014 | PLG(3,2) = 3.*C*S 1015 | PLG(4,2) = 1.5*(5.*C2-1.)*S 1016 | PLG(5,2) = 2.5*(7.*C2*C-3.*C)*S 1017 | PLG(6,2) = 1.875*(21.*C4 - 14.*C2 +1.)*S 1018 | PLG(7,2) = (11.*C*PLG(6,2)-6.*PLG(5,2))/5. 1019 | C PLG(8,2) = (13.*C*PLG(7,2)-7.*PLG(6,2))/6. 1020 | C PLG(9,2) = (15.*C*PLG(8,2)-8.*PLG(7,2))/7. 1021 | PLG(3,3) = 3.*S2 1022 | PLG(4,3) = 15.*S2*C 1023 | PLG(5,3) = 7.5*(7.*C2 -1.)*S2 1024 | PLG(6,3) = 3.*C*PLG(5,3)-2.*PLG(4,3) 1025 | PLG(7,3)=(11.*C*PLG(6,3)-7.*PLG(5,3))/4. 1026 | PLG(8,3)=(13.*C*PLG(7,3)-8.*PLG(6,3))/5. 1027 | PLG(4,4) = 15.*S2*S 1028 | PLG(5,4) = 105.*S2*S*C 1029 | PLG(6,4)=(9.*C*PLG(5,4)-7.*PLG(4,4))/2. 1030 | PLG(7,4)=(11.*C*PLG(6,4)-8.*PLG(5,4))/3. 1031 | XL=LAT 1032 | 15 CONTINUE 1033 | IF(TLL.EQ.TLOC) GO TO 16 1034 | IF(SW(7).EQ.0.AND.SW(8).EQ.0.AND.SW(14).EQ.0) GOTO 16 1035 | STLOC = SIN(HR*TLOC) 1036 | CTLOC = COS(HR*TLOC) 1037 | S2TLOC = SIN(2.*HR*TLOC) 1038 | C2TLOC = COS(2.*HR*TLOC) 1039 | S3TLOC = SIN(3.*HR*TLOC) 1040 | C3TLOC = COS(3.*HR*TLOC) 1041 | TLL = TLOC 1042 | 16 CONTINUE 1043 | IF(DAY.NE.DAYL.OR.P(14).NE.P14) CD14=COS(DR*(DAY-P(14))) 1044 | IF(DAY.NE.DAYL.OR.P(18).NE.P18) CD18=COS(2.*DR*(DAY-P(18))) 1045 | IF(DAY.NE.DAYL.OR.P(32).NE.P32) CD32=COS(DR*(DAY-P(32))) 1046 | IF(DAY.NE.DAYL.OR.P(39).NE.P39) CD39=COS(2.*DR*(DAY-P(39))) 1047 | DAYL = DAY 1048 | P14 = P(14) 1049 | P18 = P(18) 1050 | P32 = P(32) 1051 | P39 = P(39) 1052 | C F10.7 EFFECT 1053 | DF = F107 - F107A 1054 | DFA=F107A-150. 1055 | T(1) = P(20)*DF*(1.+P(60)*DFA) + P(21)*DF*DF + P(22)*DFA 1056 | & + P(30)*DFA**2 1057 | F1 = 1. + (P(48)*DFA +P(20)*DF+P(21)*DF*DF)*SWC(1) 1058 | F2 = 1. + (P(50)*DFA+P(20)*DF+P(21)*DF*DF)*SWC(1) 1059 | C TIME INDEPENDENT 1060 | T(2) = 1061 | 1 (P(2)*PLG(3,1) + P(3)*PLG(5,1)+P(23)*PLG(7,1)) 1062 | & +(P(15)*PLG(3,1))*DFA*SWC(1) 1063 | 2 +P(27)*PLG(2,1) 1064 | C SYMMETRICAL ANNUAL 1065 | T(3) = 1066 | 1 (P(19) )*CD32 1067 | C SYMMETRICAL SEMIANNUAL 1068 | T(4) = 1069 | 1 (P(16)+P(17)*PLG(3,1))*CD18 1070 | C ASYMMETRICAL ANNUAL 1071 | T(5) = F1* 1072 | 1 (P(10)*PLG(2,1)+P(11)*PLG(4,1))*CD14 1073 | C ASYMMETRICAL SEMIANNUAL 1074 | T(6) = P(38)*PLG(2,1)*CD39 1075 | C DIURNAL 1076 | IF(SW(7).EQ.0) GOTO 200 1077 | T71 = (P(12)*PLG(3,2))*CD14*SWC(5) 1078 | T72 = (P(13)*PLG(3,2))*CD14*SWC(5) 1079 | T(7) = F2* 1080 | 1 ((P(4)*PLG(2,2) + P(5)*PLG(4,2) + P(28)*PLG(6,2) 1081 | 2 + T71)*CTLOC 1082 | 4 + (P(7)*PLG(2,2) + P(8)*PLG(4,2) +P(29)*PLG(6,2) 1083 | 5 + T72)*STLOC) 1084 | 200 CONTINUE 1085 | C SEMIDIURNAL 1086 | IF(SW(8).EQ.0) GOTO 210 1087 | T81 = (P(24)*PLG(4,3)+P(36)*PLG(6,3))*CD14*SWC(5) 1088 | T82 = (P(34)*PLG(4,3)+P(37)*PLG(6,3))*CD14*SWC(5) 1089 | T(8) = F2* 1090 | 1 ((P(6)*PLG(3,3) + P(42)*PLG(5,3) + T81)*C2TLOC 1091 | 3 +(P(9)*PLG(3,3) + P(43)*PLG(5,3) + T82)*S2TLOC) 1092 | 210 CONTINUE 1093 | C TERDIURNAL 1094 | IF(SW(14).EQ.0) GOTO 220 1095 | T(14) = F2* 1096 | 1 ((P(40)*PLG(4,4)+(P(94)*PLG(5,4)+P(47)*PLG(7,4))*CD14*SWC(5))* 1097 | $ S3TLOC 1098 | 2 +(P(41)*PLG(4,4)+(P(95)*PLG(5,4)+P(49)*PLG(7,4))*CD14*SWC(5))* 1099 | $ C3TLOC) 1100 | 220 CONTINUE 1101 | C MAGNETIC ACTIVITY BASED ON DAILY AP 1102 | 1103 | IF(SW9.EQ.-1.) GO TO 30 1104 | APD=(AP(1)-4.) 1105 | P44=P(44) 1106 | P45=P(45) 1107 | IF(P44.LT.0) P44=1.E-5 1108 | APDF = APD+(P45-1.)*(APD+(EXP(-P44 *APD)-1.)/P44) 1109 | IF(SW(9).EQ.0) GOTO 40 1110 | T(9)=APDF*(P(33)+P(46)*PLG(3,1)+P(35)*PLG(5,1)+ 1111 | $ (P(101)*PLG(2,1)+P(102)*PLG(4,1)+P(103)*PLG(6,1))*CD14*SWC(5)+ 1112 | $ (P(122)*PLG(2,2)+P(123)*PLG(4,2)+P(124)*PLG(6,2))*SWC(7)* 1113 | $ COS(HR*(TLOC-P(125)))) 1114 | GO TO 40 1115 | 30 CONTINUE 1116 | IF(P(52).EQ.0) GO TO 40 1117 | EXP1 = EXP(-10800.*ABS(P(52))/(1.+P(139)*(45.-ABS(LAT)))) 1118 | IF(EXP1.GT..99999) EXP1=.99999 1119 | IF(P(25).LT.1.E-4) P(25)=1.E-4 1120 | APT(1)=SG0(EXP1) 1121 | C APT(2)=SG2(EXP1) 1122 | c APT(3)=SG0(EXP2) 1123 | C APT(4)=SG2(EXP2) 1124 | IF(SW(9).EQ.0) GOTO 40 1125 | T(9) = APT(1)*(P(51)+P(97)*PLG(3,1)+P(55)*PLG(5,1)+ 1126 | $ (P(126)*PLG(2,1)+P(127)*PLG(4,1)+P(128)*PLG(6,1))*CD14*SWC(5)+ 1127 | $ (P(129)*PLG(2,2)+P(130)*PLG(4,2)+P(131)*PLG(6,2))*SWC(7)* 1128 | $ COS(HR*(TLOC-P(132)))) 1129 | 40 CONTINUE 1130 | IF(SW(10).EQ.0.OR.LONG.LE.-1000.) GO TO 49 1131 | C LONGITUDINAL 1132 | IF(SW(11).EQ.0) GOTO 230 1133 | T(11)= (1.+P(81)*DFA*SWC(1))* 1134 | $((P(65)*PLG(3,2)+P(66)*PLG(5,2)+P(67)*PLG(7,2) 1135 | $ +P(104)*PLG(2,2)+P(105)*PLG(4,2)+P(106)*PLG(6,2) 1136 | $ +SWC(5)*(P(110)*PLG(2,2)+P(111)*PLG(4,2)+P(112)*PLG(6,2))*CD14)* 1137 | $ COS(DGTR*LONG) 1138 | $ +(P(91)*PLG(3,2)+P(92)*PLG(5,2)+P(93)*PLG(7,2) 1139 | $ +P(107)*PLG(2,2)+P(108)*PLG(4,2)+P(109)*PLG(6,2) 1140 | $ +SWC(5)*(P(113)*PLG(2,2)+P(114)*PLG(4,2)+P(115)*PLG(6,2))*CD14)* 1141 | $ SIN(DGTR*LONG)) 1142 | 230 CONTINUE 1143 | C UT AND MIXED UT,LONGITUDE 1144 | IF(SW(12).EQ.0) GOTO 240 1145 | T(12)=(1.+P(96)*PLG(2,1))*(1.+P(82)*DFA*SWC(1))* 1146 | $(1.+P(120)*PLG(2,1)*SWC(5)*CD14)* 1147 | $((P(69)*PLG(2,1)+P(70)*PLG(4,1)+P(71)*PLG(6,1))* 1148 | $ COS(SR*(SEC-P(72)))) 1149 | T(12)=T(12)+SWC(11)* 1150 | $ (P(77)*PLG(4,3)+P(78)*PLG(6,3)+P(79)*PLG(8,3))* 1151 | $ COS(SR*(SEC-P(80))+2.*DGTR*LONG)*(1.+P(138)*DFA*SWC(1)) 1152 | 240 CONTINUE 1153 | C UT,LONGITUDE MAGNETIC ACTIVITY 1154 | IF(SW(13).EQ.0) GOTO 48 1155 | IF(SW9.EQ.-1.) GO TO 45 1156 | T(13)= APDF*SWC(11)*(1.+P(121)*PLG(2,1))* 1157 | $((P( 61)*PLG(3,2)+P( 62)*PLG(5,2)+P( 63)*PLG(7,2))* 1158 | $ COS(DGTR*(LONG-P( 64)))) 1159 | $ +APDF*SWC(11)*SWC(5)* 1160 | $ (P(116)*PLG(2,2)+P(117)*PLG(4,2)+P(118)*PLG(6,2))* 1161 | $ CD14*COS(DGTR*(LONG-P(119))) 1162 | $ + APDF*SWC(12)* 1163 | $ (P( 84)*PLG(2,1)+P( 85)*PLG(4,1)+P( 86)*PLG(6,1))* 1164 | $ COS(SR*(SEC-P( 76))) 1165 | GOTO 48 1166 | 45 CONTINUE 1167 | IF(P(52).EQ.0) GOTO 48 1168 | T(13)=APT(1)*SWC(11)*(1.+P(133)*PLG(2,1))* 1169 | $((P(53)*PLG(3,2)+P(99)*PLG(5,2)+P(68)*PLG(7,2))* 1170 | $ COS(DGTR*(LONG-P(98)))) 1171 | $ +APT(1)*SWC(11)*SWC(5)* 1172 | $ (P(134)*PLG(2,2)+P(135)*PLG(4,2)+P(136)*PLG(6,2))* 1173 | $ CD14*COS(DGTR*(LONG-P(137))) 1174 | $ +APT(1)*SWC(12)* 1175 | $ (P(56)*PLG(2,1)+P(57)*PLG(4,1)+P(58)*PLG(6,1))* 1176 | $ COS(SR*(SEC-P(59))) 1177 | 48 CONTINUE 1178 | C PARMS NOT USED: 83, 90,100,140-150 1179 | 49 CONTINUE 1180 | TINF=P(31) 1181 | DO 50 I = 1,NSW 1182 | 50 TINF = TINF + ABS(SW(I))*T(I) 1183 | GLOBE7 = TINF 1184 | RETURN 1185 | END 1186 | C----------------------------------------------------------------------- 1187 | SUBROUTINE TSELEC(SV) 1188 | C SET SWITCHES 1189 | C Output in COMMON/CSW/SW(25),ISW,SWC(25) 1190 | C SW FOR MAIN TERMS, SWC FOR CROSS TERMS 1191 | C 1192 | C TO TURN ON AND OFF PARTICULAR VARIATIONS CALL TSELEC(SV), 1193 | C WHERE SV IS A 25 ELEMENT ARRAY CONTAINING 0. FOR OFF, 1. 1194 | C FOR ON, OR 2. FOR MAIN EFFECTS OFF BUT CROSS TERMS ON 1195 | C 1196 | C To get current values of SW: CALL TRETRV(SW) 1197 | C 1198 | DIMENSION SV(25),SAV(25),SVV(25) 1199 | COMMON/CSW/SW(25),ISW,SWC(25) 1200 | SAVE 1201 | DO 100 I = 1,25 1202 | SAV(I)=SV(I) 1203 | SW(I)=AMOD(SV(I),2.) 1204 | IF(ABS(SV(I)).EQ.1.OR.ABS(SV(I)).EQ.2.) THEN 1205 | SWC(I)=1. 1206 | ELSE 1207 | SWC(I)=0. 1208 | ENDIF 1209 | 100 CONTINUE 1210 | ISW=64999 1211 | RETURN 1212 | ENTRY TRETRV(SVV) 1213 | DO 200 I=1,25 1214 | SVV(I)=SAV(I) 1215 | 200 CONTINUE 1216 | END 1217 | C----------------------------------------------------------------------- 1218 | FUNCTION GLOB7S(P) 1219 | C VERSION OF GLOBE FOR LOWER ATMOSPHERE 10/26/99 1220 | REAL LONG 1221 | COMMON/LPOLY/PLG(9,4),CTLOC,STLOC,C2TLOC,S2TLOC,C3TLOC,S3TLOC, 1222 | $ IYR,DAY,DF,DFA,APD,APDF,APT(4),LONG 1223 | COMMON/CSW/SW(25),ISW,SWC(25) 1224 | DIMENSION P(*),T(14) 1225 | SAVE 1226 | DATA DR/1.72142E-2/,DGTR/1.74533E-2/,PSET/2./ 1227 | DATA DAYL/-1./,P32,P18,P14,P39/4*-1000./ 1228 | C CONFIRM PARAMETER SET 1229 | IF(P(100).EQ.0) P(100)=PSET 1230 | IF(P(100).NE.PSET) THEN 1231 | write(stderr,900) PSET,P(100) 1232 | 900 FORMAT(1X,'WRONG PARAMETER SET FOR GLOB7S',3F10.1) 1233 | error stop 1234 | ENDIF 1235 | DO 10 J=1,14 1236 | T(J)=0. 1237 | 10 CONTINUE 1238 | IF(DAY.NE.DAYL.OR.P32.NE.P(32)) CD32=COS(DR*(DAY-P(32))) 1239 | IF(DAY.NE.DAYL.OR.P18.NE.P(18)) CD18=COS(2.*DR*(DAY-P(18))) 1240 | IF(DAY.NE.DAYL.OR.P14.NE.P(14)) CD14=COS(DR*(DAY-P(14))) 1241 | IF(DAY.NE.DAYL.OR.P39.NE.P(39)) CD39=COS(2.*DR*(DAY-P(39))) 1242 | DAYL=DAY 1243 | P32=P(32) 1244 | P18=P(18) 1245 | P14=P(14) 1246 | P39=P(39) 1247 | C 1248 | C F10.7 1249 | T(1)=P(22)*DFA 1250 | C TIME INDEPENDENT 1251 | T(2)=P(2)*PLG(3,1)+P(3)*PLG(5,1)+P(23)*PLG(7,1) 1252 | $ +P(27)*PLG(2,1)+P(15)*PLG(4,1)+P(60)*PLG(6,1) 1253 | C SYMMETRICAL ANNUAL 1254 | T(3)=(P(19)+P(48)*PLG(3,1)+P(30)*PLG(5,1))*CD32 1255 | C SYMMETRICAL SEMIANNUAL 1256 | T(4)=(P(16)+P(17)*PLG(3,1)+P(31)*PLG(5,1))*CD18 1257 | C ASYMMETRICAL ANNUAL 1258 | T(5)=(P(10)*PLG(2,1)+P(11)*PLG(4,1)+P(21)*PLG(6,1))*CD14 1259 | C ASYMMETRICAL SEMIANNUAL 1260 | T(6)=(P(38)*PLG(2,1))*CD39 1261 | C DIURNAL 1262 | IF(SW(7).EQ.0) GOTO 200 1263 | T71 = P(12)*PLG(3,2)*CD14*SWC(5) 1264 | T72 = P(13)*PLG(3,2)*CD14*SWC(5) 1265 | T(7) = 1266 | 1 ((P(4)*PLG(2,2) + P(5)*PLG(4,2) 1267 | 2 + T71)*CTLOC 1268 | 4 + (P(7)*PLG(2,2) + P(8)*PLG(4,2) 1269 | 5 + T72)*STLOC) 1270 | 200 CONTINUE 1271 | C SEMIDIURNAL 1272 | IF(SW(8).EQ.0) GOTO 210 1273 | T81 = (P(24)*PLG(4,3)+P(36)*PLG(6,3))*CD14*SWC(5) 1274 | T82 = (P(34)*PLG(4,3)+P(37)*PLG(6,3))*CD14*SWC(5) 1275 | T(8) = 1276 | 1 ((P(6)*PLG(3,3) + P(42)*PLG(5,3) + T81)*C2TLOC 1277 | 3 +(P(9)*PLG(3,3) + P(43)*PLG(5,3) + T82)*S2TLOC) 1278 | 210 CONTINUE 1279 | C TERDIURNAL 1280 | IF(SW(14).EQ.0) GOTO 220 1281 | T(14) = P(40)*PLG(4,4)*S3TLOC 1282 | $ +P(41)*PLG(4,4)*C3TLOC 1283 | 220 CONTINUE 1284 | C MAGNETIC ACTIVITY 1285 | IF(SW(9).EQ.0) GOTO 40 1286 | IF(SW(9).EQ.1) 1287 | $ T(9)=APDF*(P(33)+P(46)*PLG(3,1)*SWC(2)) 1288 | IF(SW(9).EQ.-1) 1289 | $ T(9)=(P(51)*APT(1)+P(97)*PLG(3,1)*APT(1)*SWC(2)) 1290 | 40 CONTINUE 1291 | IF(SW(10).EQ.0.OR.SW(11).EQ.0.OR.LONG.LE.-1000.) GO TO 49 1292 | C LONGITUDINAL 1293 | T(11)= (1.+PLG(2,1)*(P(81)*SWC(5)*COS(DR*(DAY-P(82))) 1294 | $ +P(86)*SWC(6)*COS(2.*DR*(DAY-P(87)))) 1295 | $ +P(84)*SWC(3)*COS(DR*(DAY-P(85))) 1296 | $ +P(88)*SWC(4)*COS(2.*DR*(DAY-P(89)))) 1297 | $ *((P(65)*PLG(3,2)+P(66)*PLG(5,2)+P(67)*PLG(7,2) 1298 | $ +P(75)*PLG(2,2)+P(76)*PLG(4,2)+P(77)*PLG(6,2) 1299 | $ )*COS(DGTR*LONG) 1300 | $ +(P(91)*PLG(3,2)+P(92)*PLG(5,2)+P(93)*PLG(7,2) 1301 | $ +P(78)*PLG(2,2)+P(79)*PLG(4,2)+P(80)*PLG(6,2) 1302 | $ )*SIN(DGTR*LONG)) 1303 | 49 CONTINUE 1304 | TT=0. 1305 | DO 50 I=1,14 1306 | 50 TT=TT+ABS(SW(I))*T(I) 1307 | GLOB7S=TT 1308 | RETURN 1309 | END 1310 | C-------------------------------------------------------------------- 1311 | FUNCTION DENSU(ALT,DLB,TINF,TLB,XM,ALPHA,TZ,ZLB,S2, 1312 | $ MN1,ZN1,TN1,TGN1) 1313 | C Calculate Temperature and Density Profiles for MSIS models 1314 | C New lower thermo polynomial 10/30/89 1315 | DIMENSION ZN1(MN1),TN1(MN1),TGN1(2),XS(5),YS(5),Y2OUT(5) 1316 | COMMON/PARMB/GSURF,RE 1317 | COMMON/LSQV/MP,II,JG,LT,QPB(50),IERR,IFUN,N,J,DV(60) 1318 | SAVE 1319 | DATA RGAS/831.4/ 1320 | ZETA(ZZ,ZL)=(ZZ-ZL)*(RE+ZL)/(RE+ZZ) 1321 | CCCCCCWRITE(6,*) 'DB',ALT,DLB,TINF,TLB,XM,ALPHA,ZLB,S2,MN1,ZN1,TN1 1322 | DENSU=1. 1323 | C Joining altitude of Bates and spline 1324 | ZA=ZN1(1) 1325 | Z=AMAX1(ALT,ZA) 1326 | C Geopotential altitude difference from ZLB 1327 | ZG2=ZETA(Z,ZLB) 1328 | C Bates temperature 1329 | TT=TINF-(TINF-TLB)*EXP(-S2*ZG2) 1330 | TA=TT 1331 | TZ=TT 1332 | DENSU=TZ 1333 | IF(ALT.GE.ZA) GO TO 10 1334 | C 1335 | C CALCULATE TEMPERATURE BELOW ZA 1336 | C Temperature gradient at ZA from Bates profile 1337 | DTA=(TINF-TA)*S2*((RE+ZLB)/(RE+ZA))**2 1338 | TGN1(1)=DTA 1339 | TN1(1)=TA 1340 | Z=AMAX1(ALT,ZN1(MN1)) 1341 | MN=MN1 1342 | Z1=ZN1(1) 1343 | Z2=ZN1(MN) 1344 | T1=TN1(1) 1345 | T2=TN1(MN) 1346 | C Geopotental difference from Z1 1347 | ZG=ZETA(Z,Z1) 1348 | ZGDIF=ZETA(Z2,Z1) 1349 | C Set up spline nodes 1350 | DO 20 K=1,MN 1351 | XS(K)=ZETA(ZN1(K),Z1)/ZGDIF 1352 | YS(K)=1./TN1(K) 1353 | 20 CONTINUE 1354 | C End node derivatives 1355 | YD1=-TGN1(1)/(T1*T1)*ZGDIF 1356 | YD2=-TGN1(2)/(T2*T2)*ZGDIF*((RE+Z2)/(RE+Z1))**2 1357 | C Calculate spline coefficients 1358 | CALL SPLINE(XS,YS,MN,YD1,YD2,Y2OUT) 1359 | X=ZG/ZGDIF 1360 | CALL SPLINT(XS,YS,Y2OUT,MN,X,Y) 1361 | C temperature at altitude 1362 | TZ=1./Y 1363 | DENSU=TZ 1364 | 10 IF(XM.EQ.0.) GO TO 50 1365 | C 1366 | C CALCULATE DENSITY ABOVE ZA 1367 | GLB=GSURF/(1.+ZLB/RE)**2 1368 | GAMMA=XM*GLB/(S2*RGAS*TINF) 1369 | EXPL=EXP(-S2*GAMMA*ZG2) 1370 | IF(EXPL.GT.50.OR.TT.LE.0.) THEN 1371 | EXPL=50. 1372 | ENDIF 1373 | C Density at altitude 1374 | DENSA=DLB*(TLB/TT)**(1.+ALPHA+GAMMA)*EXPL 1375 | DENSU=DENSA 1376 | IF(ALT.GE.ZA) GO TO 50 1377 | C 1378 | C CALCULATE DENSITY BELOW ZA 1379 | GLB=GSURF/(1.+Z1/RE)**2 1380 | GAMM=XM*GLB*ZGDIF/RGAS 1381 | C integrate spline temperatures 1382 | CALL SPLINI(XS,YS,Y2OUT,MN,X,YI) 1383 | EXPL=GAMM*YI 1384 | IF(EXPL.GT.50..OR.TZ.LE.0.) THEN 1385 | EXPL=50. 1386 | ENDIF 1387 | C Density at altitude 1388 | DENSU=DENSU*(T1/TZ)**(1.+ALPHA)*EXP(-EXPL) 1389 | 50 CONTINUE 1390 | RETURN 1391 | END 1392 | C-------------------------------------------------------------------- 1393 | FUNCTION DENSM(ALT,D0,XM,TZ,MN3,ZN3,TN3,TGN3,MN2,ZN2,TN2,TGN2) 1394 | C Calculate Temperature and Density Profiles for lower atmos. 1395 | DIMENSION ZN3(MN3),TN3(MN3),TGN3(2),XS(10),YS(10),Y2OUT(10) 1396 | DIMENSION ZN2(MN2),TN2(MN2),TGN2(2) 1397 | COMMON/PARMB/GSURF,RE 1398 | COMMON/FIT/TAF 1399 | COMMON/LSQV/MP,II,JG,LT,QPB(50),IERR,IFUN,N,J,DV(60) 1400 | SAVE 1401 | DATA RGAS/831.4/ 1402 | ZETA(ZZ,ZL)=(ZZ-ZL)*(RE+ZL)/(RE+ZZ) 1403 | DENSM=D0 1404 | IF(ALT.GT.ZN2(1)) GOTO 50 1405 | C STRATOSPHERE/MESOSPHERE TEMPERATURE 1406 | Z=AMAX1(ALT,ZN2(MN2)) 1407 | MN=MN2 1408 | Z1=ZN2(1) 1409 | Z2=ZN2(MN) 1410 | T1=TN2(1) 1411 | T2=TN2(MN) 1412 | ZG=ZETA(Z,Z1) 1413 | ZGDIF=ZETA(Z2,Z1) 1414 | C Set up spline nodes 1415 | DO 210 K=1,MN 1416 | XS(K)=ZETA(ZN2(K),Z1)/ZGDIF 1417 | YS(K)=1./TN2(K) 1418 | 210 CONTINUE 1419 | YD1=-TGN2(1)/(T1*T1)*ZGDIF 1420 | YD2=-TGN2(2)/(T2*T2)*ZGDIF*((RE+Z2)/(RE+Z1))**2 1421 | C Calculate spline coefficients 1422 | CALL SPLINE(XS,YS,MN,YD1,YD2,Y2OUT) 1423 | X=ZG/ZGDIF 1424 | CALL SPLINT(XS,YS,Y2OUT,MN,X,Y) 1425 | C Temperature at altitude 1426 | TZ=1./Y 1427 | IF(XM.EQ.0.) GO TO 20 1428 | C 1429 | C CALCULATE STRATOSPHERE/MESOSPHERE DENSITY 1430 | GLB=GSURF/(1.+Z1/RE)**2 1431 | GAMM=XM*GLB*ZGDIF/RGAS 1432 | C Integrate temperature profile 1433 | CALL SPLINI(XS,YS,Y2OUT,MN,X,YI) 1434 | EXPL=GAMM*YI 1435 | IF(EXPL.GT.50.) EXPL=50. 1436 | C Density at altitude 1437 | DENSM=DENSM*(T1/TZ)*EXP(-EXPL) 1438 | 20 CONTINUE 1439 | IF(ALT.GT.ZN3(1)) GOTO 50 1440 | C 1441 | C TROPOSPHERE/STRATOSPHERE TEMPERATURE 1442 | Z=ALT 1443 | MN=MN3 1444 | Z1=ZN3(1) 1445 | Z2=ZN3(MN) 1446 | T1=TN3(1) 1447 | T2=TN3(MN) 1448 | ZG=ZETA(Z,Z1) 1449 | ZGDIF=ZETA(Z2,Z1) 1450 | C Set up spline nodes 1451 | DO 220 K=1,MN 1452 | XS(K)=ZETA(ZN3(K),Z1)/ZGDIF 1453 | YS(K)=1./TN3(K) 1454 | 220 CONTINUE 1455 | YD1=-TGN3(1)/(T1*T1)*ZGDIF 1456 | YD2=-TGN3(2)/(T2*T2)*ZGDIF*((RE+Z2)/(RE+Z1))**2 1457 | C Calculate spline coefficients 1458 | CALL SPLINE(XS,YS,MN,YD1,YD2,Y2OUT) 1459 | X=ZG/ZGDIF 1460 | CALL SPLINT(XS,YS,Y2OUT,MN,X,Y) 1461 | C temperature at altitude 1462 | TZ=1./Y 1463 | IF(XM.EQ.0.) GO TO 30 1464 | C 1465 | C CALCULATE TROPOSPHERIC/STRATOSPHERE DENSITY 1466 | C 1467 | GLB=GSURF/(1.+Z1/RE)**2 1468 | GAMM=XM*GLB*ZGDIF/RGAS 1469 | C Integrate temperature profile 1470 | CALL SPLINI(XS,YS,Y2OUT,MN,X,YI) 1471 | EXPL=GAMM*YI 1472 | IF(EXPL.GT.50.) EXPL=50. 1473 | C Density at altitude 1474 | DENSM=DENSM*(T1/TZ)*EXP(-EXPL) 1475 | 30 CONTINUE 1476 | 50 CONTINUE 1477 | IF(XM.EQ.0) DENSM=TZ 1478 | RETURN 1479 | END 1480 | C----------------------------------------------------------------------- 1481 | SUBROUTINE SPLINE(X,Y,N,YP1,YPN,Y2) 1482 | C CALCULATE 2ND DERIVATIVES OF CUBIC SPLINE INTERP FUNCTION 1483 | C ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL 1484 | C X,Y: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X 1485 | C N: SIZE OF ARRAYS X,Y 1486 | C YP1,YPN: SPECIFIED DERIVATIVES AT X(1) AND X(N); VALUES 1487 | C >= 1E30 SIGNAL SIGNAL SECOND DERIVATIVE ZERO 1488 | C Y2: OUTPUT ARRAY OF SECOND DERIVATIVES 1489 | PARAMETER (NMAX=100) 1490 | DIMENSION X(N),Y(N),Y2(N),U(NMAX) 1491 | SAVE 1492 | IF(YP1.GT..99E30) THEN 1493 | Y2(1)=0 1494 | U(1)=0 1495 | ELSE 1496 | Y2(1)=-.5 1497 | U(1)=(3./(X(2)-X(1)))*((Y(2)-Y(1))/(X(2)-X(1))-YP1) 1498 | ENDIF 1499 | DO 11 I=2,N-1 1500 | SIG=(X(I)-X(I-1))/(X(I+1)-X(I-1)) 1501 | P=SIG*Y2(I-1)+2. 1502 | Y2(I)=(SIG-1.)/P 1503 | U(I)=(6.*((Y(I+1)-Y(I))/(X(I+1)-X(I))-(Y(I)-Y(I-1)) 1504 | $ /(X(I)-X(I-1)))/(X(I+1)-X(I-1))-SIG*U(I-1))/P 1505 | 11 CONTINUE 1506 | IF(YPN.GT..99E30) THEN 1507 | QN=0 1508 | UN=0 1509 | ELSE 1510 | QN=.5 1511 | UN=(3./(X(N)-X(N-1)))*(YPN-(Y(N)-Y(N-1))/(X(N)-X(N-1))) 1512 | ENDIF 1513 | Y2(N)=(UN-QN*U(N-1))/(QN*Y2(N-1)+1.) 1514 | DO 12 K=N-1,1,-1 1515 | Y2(K)=Y2(K)*Y2(K+1)+U(K) 1516 | 12 CONTINUE 1517 | RETURN 1518 | END 1519 | C----------------------------------------------------------------------- 1520 | SUBROUTINE SPLINT(XA,YA,Y2A,N,X,Y) 1521 | C CALCULATE CUBIC SPLINE INTERP VALUE 1522 | C ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL. 1523 | C XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X 1524 | C Y2A: ARRAY OF SECOND DERIVATIVES 1525 | C N: SIZE OF ARRAYS XA,YA,Y2A 1526 | C X: ABSCISSA FOR INTERPOLATION 1527 | C Y: OUTPUT VALUE 1528 | DIMENSION XA(N),YA(N),Y2A(N) 1529 | SAVE 1530 | KLO=1 1531 | KHI=N 1532 | 1 CONTINUE 1533 | IF(KHI-KLO.GT.1) THEN 1534 | K=(KHI+KLO)/2 1535 | IF(XA(K).GT.X) THEN 1536 | KHI=K 1537 | ELSE 1538 | KLO=K 1539 | ENDIF 1540 | GOTO 1 1541 | ENDIF 1542 | H=XA(KHI)-XA(KLO) 1543 | IF(H.EQ.0) write(stderr,*) 'BAD XA INPUT TO SPLINT' 1544 | A=(XA(KHI)-X)/H 1545 | B=(X-XA(KLO))/H 1546 | Y=A*YA(KLO)+B*YA(KHI)+ 1547 | $ ((A*A*A-A)*Y2A(KLO)+(B*B*B-B)*Y2A(KHI))*H*H/6. 1548 | RETURN 1549 | END 1550 | C----------------------------------------------------------------------- 1551 | SUBROUTINE SPLINI(XA,YA,Y2A,N,X,YI) 1552 | C INTEGRATE CUBIC SPLINE FUNCTION FROM XA(1) TO X 1553 | C XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X 1554 | C Y2A: ARRAY OF SECOND DERIVATIVES 1555 | C N: SIZE OF ARRAYS XA,YA,Y2A 1556 | C X: ABSCISSA ENDPOINT FOR INTEGRATION 1557 | C Y: OUTPUT VALUE 1558 | DIMENSION XA(N),YA(N),Y2A(N) 1559 | SAVE 1560 | YI=0 1561 | KLO=1 1562 | KHI=2 1563 | 1 CONTINUE 1564 | IF(X.GT.XA(KLO).AND.KHI.LE.N) THEN 1565 | XX=X 1566 | IF(KHI.LT.N) XX=AMIN1(X,XA(KHI)) 1567 | H=XA(KHI)-XA(KLO) 1568 | A=(XA(KHI)-XX)/H 1569 | B=(XX-XA(KLO))/H 1570 | A2=A*A 1571 | B2=B*B 1572 | YI=YI+((1.-A2)*YA(KLO)/2.+B2*YA(KHI)/2.+ 1573 | $ ((-(1.+A2*A2)/4.+A2/2.)*Y2A(KLO)+ 1574 | $ (B2*B2/4.-B2/2.)*Y2A(KHI))*H*H/6.)*H 1575 | KLO=KLO+1 1576 | KHI=KHI+1 1577 | GOTO 1 1578 | ENDIF 1579 | RETURN 1580 | END 1581 | C----------------------------------------------------------------------- 1582 | FUNCTION DNET(DD,DM,ZHM,XMM,XM) 1583 | C TURBOPAUSE CORRECTION FOR MSIS MODELS 1584 | C Root mean density 1585 | C 8/20/80 1586 | C DD - diffusive density 1587 | C DM - full mixed density 1588 | C ZHM - transition scale length 1589 | C XMM - full mixed molecular weight 1590 | C XM - species molecular weight 1591 | C DNET - combined density 1592 | SAVE 1593 | A=ZHM/(XMM-XM) 1594 | IF(DM.GT.0.AND.DD.GT.0) GOTO 5 1595 | WRITE(stderr,*) 'DNET LOG ERROR',DM,DD,XM 1596 | error stop 1597 | IF(DD.EQ.0.AND.DM.EQ.0) DD=1. 1598 | IF(DM.EQ.0) GOTO 10 1599 | IF(DD.EQ.0) GOTO 20 1600 | 5 CONTINUE 1601 | YLOG=A*ALOG(DM/DD) 1602 | IF(YLOG.LT.-10.) GO TO 10 1603 | IF(YLOG.GT.10.) GO TO 20 1604 | DNET=DD*(1.+EXP(YLOG))**(1/A) 1605 | GO TO 50 1606 | 10 CONTINUE 1607 | DNET=DD 1608 | GO TO 50 1609 | 20 CONTINUE 1610 | DNET=DM 1611 | GO TO 50 1612 | 50 CONTINUE 1613 | RETURN 1614 | END 1615 | C----------------------------------------------------------------------- 1616 | FUNCTION CCOR(ALT, R,H1,ZH) 1617 | C CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS 1618 | C ALT - altitude 1619 | C R - target ratio 1620 | C H1 - transition scale length 1621 | C ZH - altitude of 1/2 R 1622 | SAVE 1623 | E=(ALT-ZH)/H1 1624 | IF(E.GT.70.) GO TO 20 1625 | IF(E.LT.-70.) GO TO 10 1626 | EX=EXP(E) 1627 | CCOR=R/(1.+EX) 1628 | GO TO 50 1629 | 10 CCOR=R 1630 | GO TO 50 1631 | 20 CCOR=0. 1632 | GO TO 50 1633 | 50 CONTINUE 1634 | CCOR=EXP(CCOR) 1635 | RETURN 1636 | END 1637 | C----------------------------------------------------------------------- 1638 | FUNCTION CCOR2(ALT, R,H1,ZH,H2) 1639 | C O&O2 CHEMISTRY/DISSOCIATION CORRECTION FOR MSIS MODELS 1640 | E1=(ALT-ZH)/H1 1641 | E2=(ALT-ZH)/H2 1642 | IF(E1.GT.70. .OR. E2.GT.70.) GO TO 20 1643 | IF(E1.LT.-70. .AND. E2.LT.-70) GO TO 10 1644 | EX1=EXP(E1) 1645 | EX2=EXP(E2) 1646 | CCOR2=R/(1.+.5*(EX1+EX2)) 1647 | GO TO 50 1648 | 10 CCOR2=R 1649 | GO TO 50 1650 | 20 CCOR2=0. 1651 | GO TO 50 1652 | 50 CONTINUE 1653 | CCOR2=EXP(CCOR2) 1654 | RETURN 1655 | END 1656 | C----------------------------------------------------------------------- 1657 | end module msise00_python 1658 | --------------------------------------------------------------------------------