def test_rcolum_qback(): if msise00 is not None: densd, tempd = rungtd1d(dtime, z, glat, glon, f107a, f107, [ap] * 7) """ VCD: Vertical Column Density """ sza = test_solzen() zcol, zvcd = glowfort.rcolum(sza, z * 1e5, densd.loc[:, ['O', 'O2', 'N2']].values.T, tempd.loc[:, 'Tn']) # FIXME these tests were numerically unstable (near infinity values) assert isclose(zcol[0, 0], 1e30) #see rcolum comments for sun below horizon 1e30 assert isclose(zvcd[2, 5], 5.97157e+28, rtol=1e-2) #TODO changes a bit between python 2 / 3 #%% skipping EPHOTO since we care about night time more for now znoint = test_snoemint() # zeros because nighttime photoi = zeros((nst, nmaj, jmax), dtype=float32, order='F') phono = zeros((nst, jmax), dtype=float32, order='F') glowfort.qback(zmaj=densd.loc[:, ['O', 'O2', 'N2']].values.T, zno=znoint, zvcd=zvcd, photoi=photoi, phono=phono) #arbitrary point check assert isclose(photoi[0, 0, 77], 1.38091e-18, rtol=1e-5) assert isclose(phono[0, 73], 0.0, rtol=1e-5) else: logging.warning('skipped rcolum qback due to missing external msise00')
def test_forecast(): t = datetime(2023, 3, 31, 12) altkm = 150. glat = 65. glon = -148. atmos = msise00.rungtd1d(t, altkm, glat, glon) assert atmos['He'].ndim == 4 assert atmos['He'].size == 1 dims = list(atmos.dims) assert ['alt_km', 'lat', 'lon', 'time'] == dims assert atmos['He'] == approx(4391892942848.0) assert atmos['O'] == approx(4572213877407744.0) assert atmos['N2'] == approx(3.699869941864858e+16) assert atmos['O2'] == approx(8123202106556416.0) assert atmos['Ar'] == approx(335927545167872.0) assert atmos['Total'] == approx(2.2950290556877917e-09) assert atmos['N'] == approx(2154773479424.0) assert atmos['AnomalousO'] == approx(8.750423680563095e-16) assert atmos.species == [ 'He', 'O', 'N2', 'O2', 'Ar', 'Total', 'H', 'N', 'AnomalousO' ] assert atmos['Tn'] == approx(666.9913330078125) assert atmos['Texo'] == approx(922.104736328125)
def test_gtd1d(): t = datetime(2013, 3, 31, 12) altkm = 150. glat = 65. glon = -148. atmos = msise00.rungtd1d(t, altkm, glat, glon) assert atmos['He'].ndim == 4 assert atmos['He'].size == 1 dims = list(atmos.dims) assert ['alt_km', 'lat', 'lon', 'time'] == dims assert atmos['He'] == approx(11908118740992.0) assert atmos['O'] == approx(1.306165589835776e+16) assert atmos['N2'] == approx(3.051389580214272e+16) assert atmos['O2'] == approx(2664322295660544.0) assert atmos['Ar'] == approx(67772830711808.0) assert atmos['Total'] == approx(1.9115256044699436e-09) assert atmos['N'] == approx(9171036536832.0) assert atmos['AnomalousO'] == approx(5.380620096337701e-15) assert atmos.species == [ 'He', 'O', 'N2', 'O2', 'Ar', 'Total', 'H', 'N', 'AnomalousO' ] assert atmos['Tn'] == approx(681.584167) assert atmos['Texo'] == approx(941.289246)
def reesiono(T: Union[str, datetime], altkm: np.ndarray, E: np.ndarray, glat: float, glon: float, isotropic: bool, verbose: bool, datfn: Path) -> xarray.DataArray: # other assertions covered inside modules assert isinstance(isotropic, bool) if abs(glat) < 45.: logging.error('This model was intended for auroral precipitation.') if isinstance(T, str): T = parse(T) time = np.atleast_1d(T) assert isinstance(time[0], datetime) # %% MSIS if isotropic: logging.debug('isotropic pitch angle flux') else: logging.debug('field-aligned pitch angle flux') Qt = xarray.DataArray(data=np.empty((time.size, altkm.size, E.size)), coords=[time, altkm, E], dims=['time', 'alt_km', 'energy']) # %% loop for t in time: iono = rungtd1d(t, altkm, glat, glon) Q = ionization_profile_from_flux(E, iono, isotropic, datfn, verbose) Qt.loc[t, ...] = Q return Qt
def test_snoemint(): if msise00 is not None: densd, tempd = rungtd1d(dtime, z, glat, glon, f107a, f107, [ap] * 7) # (nighttime background ionization) print(tempd) znoint = glowfort.snoemint(dtime.strftime('%Y%j'), glat, glon, f107, ap, z, tempd.loc[:, 'Tn']) assert_allclose(znoint[[28, 143]], (1.262170e+08, 3.029169e+01), rtol=1e-5) #arbitrary return znoint else: logging.warning( 'skipped test_snoemint() due to missing external msise00')
def makefig7(datfn: Path): """ Energy deposition (W Eqn A1) plots """ z = loadaltenergrid(80., 200)[0] iono = msise00.rungtd1d(tp, z, llp[0], llp[1], f107a=150., f107=150., ap=4., mass=48., # leave mass=48. ! tselecopts=np.array([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], float)) # NOTE kg m^-2 *10 = g cm^-2 rho = iono.loc[:, 'Total'] * 10. # mass density of atmosphere [g cm^-3] # eqn A1 Sergienko 1993 W = energy_deg(Eplot, isotropic, rho) fig7(W, z, Eplot)
def test_gtd1d(): t = datetime(2013, 3, 31, 12, tzinfo=UTC) altkm = 150. glat = 65. glon = -148. f107a = 100 f107 = 100 ap = 4 dens, temp = rungtd1d(t, altkm, glat, glon, f107a, f107, ap) assert_allclose(dens.values[0, :-1], [ 1.19930062e+13, 1.25792119e+16, 2.92461331e+16, 2.75184702e+15, 6.24779497e+13, 1.84406768e-09, 8.54530523e+11, 8.42101896e+12 ]) assert (dens.species.values == [ 'He', 'O', 'N2', 'O2', 'Ar', 'Total', 'H', 'N', 'AnomalousO' ]).all() assert_allclose(temp.values[0, :], [848.71148682, 645.71972656])
p.add_argument('-c', '--latlon', help='geodetic coordinates of simulation', default=(65, -147.5), type=float) p.add_argument('--f107', type=float, default=200.) p.add_argument('--f107a', type=float, default=200.) p.add_argument('--ap', type=int, default=4) p = p.parse_args() altkm = np.arange(p.alt[0], p.alt[1], p.alt[2]) dtime = parse(p.time) #%% IRI iono = runiri(dtime, altkm, p.latlon, p.f107, p.f107a, ap=p.ap) #%% MSIS dens, temp = rungtd1d(dtime, altkm, p.latlon[0], p.latlon[1], p.f107a, p.f107, p.ap) #%% IGRF Bx, By, Bz, B0 = runigrf12(dtime, isv=0, itype=1, alt=altkm, glat=p.latlon[0], glon=p.latlon[1])[:4] B0 = B0 / 1e9 #[T] #%% compute electron-neutral collison frequency """ Thrane & Piggot, The collision frequency in the E- and D-regions of the ionosphere, 1966, JATP. vm essentially matches Fig. 1 of this paper. This paper argues that Tn~Te in the D and E region ionosphere. """ T = iono.loc[:, 'Te']
from argparse import ArgumentParser p = ArgumentParser() p.add_argument('--alt',help='START STOP STEP altitude [km]',type=float,nargs=3,default=(50,150,1.)) p.add_argument('-t','--time',help='datetime of simulation',default='2012-07-21T12') p.add_argument('-c','--latlon',help='geodetic coordinates of simulation',default=(65,-147.5),type=float) p.add_argument('--f107',type=float,default=200.) p.add_argument('--f107a',type=float,default=200.) p.add_argument('--ap',type=int,default=4) p = p.parse_args() altkm = np.arange(p.alt[0], p.alt[1], p.alt[2]) dtime = parse(p.time) #%% IRI iono = runiri(dtime,altkm,p.latlon,p.f107, p.f107a, ap=p.ap) #%% MSIS dens,temp = rungtd1d(dtime, altkm, p.latlon[0], p.latlon[1], p.f107a, p.f107, p.ap) #%% IGRF Bx,By,Bz,B0 = runigrf12(dtime,isv=0,itype=1, alt=altkm, glat=p.latlon[0], glon=p.latlon[1])[:4] B0 = B0/1e9 #[T] #%% compute electron-neutral collison frequency """ Thrane & Piggot, The collision frequency in the E- and D-regions of the ionosphere, 1966, JATP. vm essentially matches Fig. 1 of this paper. This paper argues that Tn~Te in the D and E region ionosphere. """ T = iono.loc[:,'Te'] T[np.isnan(T)] = temp.loc[:,'Tn'] E = 3/2*kb_evK*T # [eV] # [Hz] monoenergetic electron-neutral collision freq