Beispiel #1
0
def demosuncor(T, glat, glon, alt_m):
    # %% Solar location with GLOW
    yd, utsec = datetime2yeardoy(T)[:2]
    solar = xarray.DataArray(np.empty((T.size, 2, 4)),
                             dims=['time', 'algorithm', 'coord'],
                             coords={
                                 'time': T,
                                 'algorithm': ['glow', 'astropy'],
                                 'coord': ['dec', 'ra', 'gst', 'sza']
                             })
    tic = time()
    for d, s, t in zip(yd, utsec, T):
        solar.loc[t, 'glow',
                  ['dec', 'ra', 'gst']] = glowfort.sun_angles.suncor(d, s)
    fortsec = time() - tic
    solar.loc[:, 'glow', ['dec', 'ra', 'gst']] = np.degrees(
        solar.loc[:, 'glow', ['dec', 'ra', 'gst']])
    # %% solar location with AstroPy
    tic = time()
    sza, sun, sunobs = solarzenithangle(T, glat, glon, alt_m)
    pysec = time() - tic
    solar.loc[:, 'astropy', 'dec'] = sun.dec.degree
    solar.loc[:, 'astropy', 'ra'] = sun.ra.degree
    solar.loc[:, 'astropy',
              'gst'] = sunobs.obstime.sidereal_time('apparent',
                                                    'greenwich').degree
    solar.loc[:, 'astropy', 'sza'] = sza

    print(
        f'in seconds, fortran time: {fortsec:.3f}   python time: {pysec:.3f} ')

    return solar
Beispiel #2
0
def demosolzen(t: datetime, glat: float, glon: float):
    """demo the solar zenith angle calclation vs AstroPy"""
    # %% SZA with glow
    yd, utsec = datetime2yeardoy(dtime)

    sza_glow = np.empty_like(dtime, dtype=float)
    for j, (d, s) in enumerate(zip(yd, utsec)):
        sza_glow[j] = glowfort.sun_angles.solzen(d, s, glat, glon)

    return sza_glow
def test_yearint():

    for t in T:
        yd, utsec = sd.datetime2yeardoy(t)

        utsec2 = sd.datetime2utsec(t)

        if isinstance(t, datetime.datetime):
            assert sd.yeardoy2datetime(yd, utsec) == t
        elif isinstance(t, np.datetime64):
            assert sd.yeardoy2datetime(yd, utsec) == t.astype(datetime.datetime)
        elif isinstance(t, str):
            assert sd.yeardoy2datetime(yd, utsec) == parse(t)
        else:
            assert sd.yeardoy2datetime(yd, utsec).date() == t

        assert utsec == utsec2
    # %% array
    y, s = sd.datetime2yeardoy(Tdt)
    assert (sd.yeardoy2datetime(y, s) == T[0]).all()
Beispiel #4
0
def runglowaurora(params: dict, z_km: np.ndarray = None) -> xarray.Dataset:
    """ Runs Fortran GLOW program and collects results in friendly arrays with metadata. """
    # %% (-2) check/process user inputs
    assert isinstance(params['flux'], (float, int, np.ndarray))
    assert isinstance(params['E0'], (float, int))
    assert isinstance(params['t0'], (datetime, str))
    assert isinstance(params['glat'], (float, int))
    assert isinstance(params['glon'], (float, int))
    # %% (-1) if no manual f10.7 and ap, autoload by date
    if not 'f107a' in params or params['f107a'] is None:
        if getApF107 is None:
            raise ImportError(GRIDERR)
        f107Ap = getApF107(params['t0'])
        params['f107a'] = params['f107p'] = f107Ap['f107s'].item()
        params['f107'] = f107Ap['f107'].item()
        params['Ap'] = (f107Ap['Ap'].item(), ) * 7

# %% flux grid / date
    eflux = np.atleast_1d(params['flux'])

    yeardoy, utsec = datetime2yeardoy(params['t0'])[:2]
    # %% (0) define altitude grid [km]

    # FIXME: dynamic grid
    z_km = np.array(
        list(range(80, 110, 1)) + [110., 111.5, 113., 114.5] +
        list(range(116, 136, 2)) +
        [137., 140., 144., 148., 153., 158., 164., 170] + list(
            chain(range(176, 204, 7), range(205, 253, 8), range(254, 299, 9),
                  range(300, 650, 10))))

    if z_km is None:
        if glowalt is not None:
            z_km = glowalt()
        else:
            raise ImportError(GRIDERR)


# %% (1) setup flux at top of ionosphere
    ener, dE = glowfort.egrid()

    if eflux.size == 1:
        logging.info(
            'generating maxwellian input differential number flux spectrum')
        # maxwellian input PhiTop at top of ionosphere
        phitop = glowfort.maxt(eflux,
                               params['E0'],
                               ener,
                               dE,
                               itail=0,
                               fmono=0,
                               emono=0)
    elif eflux.size > 1:  # eigenprofile generation, one non-zero bin at a time
        logging.info('running in eigenprofile mode')
        # FIXME should we interpolate instead? Maybe not, as long as we're consistent ref. Semeter 2006
        e0ind = find_nearest(ener, params['e0'])[0]
        phitop = np.zeros_like(ener)
        phitop[e0ind] = ener[e0ind]  # value in glow grid closest to zett grid
    else:
        return ValueError(
            'I do not understand your electron flux input. Should be scalar or vector'
        )

    phi = np.stack((ener, dE, phitop), 1)  # Nalt x 3
    assert phi.shape[1] == 3
    # %% (2) msis,iri,glow model
    glowfort.glowbasic(
        yeardoy,
        utsec,
        params['glat'],
        params['glon'] % 360,
        params['f107a'],
        params['f107'],
        params['f107p'],
        params['Ap'],
        z_km,
        pyphi=phi,
        pyverbose=False,
    )
    # %% (3) collect outputs

    lamb = [
        3371, 4278, 5200, 5577, 6300, 7320, 10400, 3466, 7774, 8446, 3726,
        'LBH', 1356, 1493, 1304
    ]  # same for ZETA and ZCETA
    ions = [
        'nO+(2P)', 'nO+(2D)', 'nO+(4S)', 'nN+', 'nN2+', 'nO2+', 'nNO+', 'nO',
        'nO2', 'nN2', 'nNO'
    ]
    neut = ['O', 'O2', 'N2']

    sim = xarray.Dataset()
    # %%  array of volume emission rates at each altitude; cm-3 s-1:
    sim['zeta'] = xarray.DataArray(glowfort.cglow.zeta.T,
                                   dims=['z_km', 'wavelength_nm'],
                                   coords={
                                       'z_km': z_km,
                                       'wavelength_nm': lamb
                                   })
    # %% array of contributions to each v.e.r at each alt; cm-3 s-1   Nalt x Nwavelength x Nprocess
    sim['zceta'] = xarray.DataArray(
        glowfort.cglow.zceta.T,  # See Glow.txt.
        dims=['z_km', 'wavelength_nm', 'process'],
        coords={
            'z_km': z_km,
            'wavelength_nm': lamb,
            'process': range(glowfort.cglow.zceta.T.shape[2])
        })
    # %% electron impact ionization rates calculated by ETRANS; cm-3 s-1
    sim['sion'] = xarray.DataArray(glowfort.cglow.sion.T,
                                   dims=['z_km', 'neutral_species'],
                                   coords={
                                       'z_km': z_km,
                                       'neutral_species': neut
                                   })
    # %% total photoionization rate at each altitude, cm-3 s-1
    sim['tpi'] = xarray.DataArray(glowfort.cglow.tpi,
                                  dims=['z_km'],
                                  coords={'z_km': z_km})
    # %% total electron impact ionization rate at each altitude, cm-3 s-1
    sim['tei'] = xarray.DataArray(glowfort.cglow.tei,
                                  dims=['z_km'],
                                  coords={'z_km': z_km})
    # %% PESPEC photoelectron production rate at energy, altitude; cm-3 s-1
    sim['pespec'] = xarray.DataArray(glowfort.cglow.pespec.T,
                                     dims=['z_km', 'eV'],
                                     coords={
                                         'z_km': z_km,
                                         'eV': ener
                                     })

    #    sim['photIon'] = xarray.DataArray(np.hstack((photI[:,None],ImpI[:,None],ecalc[:,None],ion)),
    #                               dims=['z_km','type'],
    #                               coords={'z_km':z_km,
    #                                'type':['photoIoniz','eImpactIoniz','ne']+products})
    #
    #    sim['isr'] = xarray.DataArray(isr,
    #                          dims=['z_km','param'],
    #                          coords={'z_km':z_km,'param':['ne','Te','Ti']})
    #
    #    sim['phitop'] = xarray.DataArray(phi[:,2],
    #                           dims=['eV'],
    #                           coords={'eV':phi[:,0]})
    #
    sim.attrs['sza'] = np.degrees(glowfort.cglow.sza)
    #
    #    sim['tez'] = xarray.DataArray(glowfort.cglow.tez,
    #                           dims=['z_km'], coords={'z_km':z_km})

    # %% production and loss rates
    #    prate = prate.T; lrate=lrate.T #fortran to C ordering 2x170x20, only first 12 columns are used
    #
    #    #column labels by inspection of fortran/gchem.f staring after "DO 150 I=1,JMAX" (thanks Stan!)
    #    sim['prates'] = xarray.DataArray(prate[1,:,:12], #columns 12:20 are identically zero
    #                      dims=['z_km','reaction'],
    #                      coords={'z_km':z_km,
    #                              'reaction':['O+(2P)','O+(2D)','O+(4S)','N+','N2+','O2+','NO+',
    #                                 'N2(A)','N(2P)','N(2D)','O(1S)','O(1D)']}
    #                    )
    #
    #    sim['lrates'] = xarray.DataArray(lrate[1,:,:12], #columns 12:20 are identically zero
    #                      dims=['z_km','reaction'],
    #                      coords={'z_km':z_km,
    #                        'reaction':['O+(2P)','O+(2D)','O+(4S)','N+','N2+','O2+','NO+',
    #                                 'N2(A)','N(2P)','N(2D)','O(1S)','O(1D)']}
    #                    )
    #
    #    sim['sion'] = xarray.DataArray(glowfort.cglow.sion,
    #                         dims=['gas','z_km'],
    #                         coords={'gas':['O','O2','N2'],
    #                                 'z_km':z_km})

    return sim
Beispiel #5
0
def rundayglow(time, glat, glon, f107a, f107, f107p, ap, conj=True):
    '''
    Run GLOW for no auroral input, to simulate Dayglow.

    conj = whether to account for photoelectrons from conjugate hemisphere

    After running, extra variables can be found in glowfort.cglow. Unfortunately
    you have to dig into the Fortran code to see what they mean.
    '''

    # %% (-2) check/process user inputs
    assert isinstance(time, (datetime, str))
    assert isinstance(glat, (float, int))
    assert isinstance(glon, (float, int))

    # %% flux grid / date

    yd, utsec = datetime2yeardoy(time)[:2]
    # %% (0) define altitude grid [km]
    # z = glowalt()
    z = np.concatenate(
        (range(30, 110, 1), np.logspace(np.log10(110), np.log10(1200), 90)))

    # %% (1) setup external flux at top of ionosphere. Set it to zero. Photoelectron flux from
    #       conjugate hemisphere will be calculated internally, if conj=True.
    ener, dE = glowfort.egrid()
    phitop = np.zeros_like(ener)
    phi = np.hstack((ener[:, None], dE[:, None], phitop[:, None]))

    # %% (2) msis,iri,glow model
    iconj = int(conj)  # convert boolean to int for passing to Fortran.
    ion, ecalc, photI, ImpI, isr, UV = glowfort.dayglow(
        z, yd, utsec, glat, glon % 360, f107a, f107, f107p, ap, phi, iconj)

    # %% handle the outputs including common blocks
    zeta = glowfort.cglow.zeta.T  # columns 11:20 are identically zero

    lamb = [
        3371., 4278., 5200., 5577., 6300., 7320., 10400., 3466., 7774., 8446.,
        3726., 1356., 1304., 1027., 989., 1900.
    ]
    products = [
        'nO+(2P)', 'nO+(2D)', 'nO+(4S)', 'nN+', 'nN2+', 'nO2+', 'nNO+', 'nO',
        'nO2', 'nN2', 'nNO'
    ]

    sim = xarray.Dataset()

    sim['ver'] = xarray.DataArray(np.concatenate((zeta[:, :11], UV.T), axis=1),
                                  dims=['z_km', 'wavelength_nm'],
                                  coords={
                                      'z_km': z,
                                      'wavelength_nm': lamb
                                  })

    sim['photIon'] = xarray.DataArray(
        dims=['z_km', 'type'],
        coords={
            'z_km': z,
            'type': ['photoIoniz', 'eImpactIoniz', 'ne'] + products
        },
        data=np.hstack((photI[:, None], ImpI[:, None], ecalc[:, None], ion)))

    sim['isr'] = xarray.DataArray(dims=['z_km', 'param'],
                                  coords={
                                      'z_km': z,
                                      'param': ['ne', 'Te', 'Ti']
                                  },
                                  data=isr)

    sim['phitop'] = xarray.DataArray(dims=['eV'],
                                     coords={'eV': phi[:, 0]},
                                     data=phi[:, 2])

    sim['zceta'] = xarray.DataArray(
        dims=['z_km', 'wavelength_nm', 'type'],
        coords={
            'z_km': z,
            'wavelength_nm': lamb[:11]
        },
        data=glowfort.cglow.zceta.T[:, :11, :]
    )  # Nalt x Nwavelengths  xNproductionEmissions

    sim.attrs['sza'] = np.degrees(glowfort.cglow.sza)

    sim['tez'] = xarray.DataArray(dims=['z_km'],
                                  coords={'z_km': z},
                                  data=glowfort.cglow.tez)

    sim['sion'] = xarray.DataArray(dims=['gas', 'z_km'],
                                   coords={
                                       'gas': ['O', 'O2', 'N2'],
                                       'z_km': z
                                   },
                                   data=glowfort.cglow.sion)

    return sim
Beispiel #6
0
jmax = 170  # glow.h

eflux = 1.
e0 = 1e3
maxind = 112
glat = 70
glon = 0  # like aurora.in
ap = 4
f107 = 100
f107a = 100
nmaj = 3
nst = 6
dtime = datetime(1999, 12, 21)
#
yd, utsec = datetime2yeardoy(dtime)[:2]


def test_pythonglow():
    params = {'t0': '2013-04-14T15:54',
              'glat': 65,
              'glon': -148,
              'flux': 1,
              'E0': 1000,
              'makeplot': [],
              'zlim': None,
              'plotformat': [],
              }

    sim = glowiono.runglowaurora(params)