Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xarray and other upgrades #75

Merged
merged 23 commits into from
Jul 8, 2019
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ before_install:
install:
- source activate test-environment
- python setup.py install
- make -C sami2py/fortran compile
script:
- nosetests -vs --with-coverage --cover-package=sami2py

Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,12 @@ a local install use the "--user" flag after "install".
python setup.py install
```

Additionally, you must make and install the fortran executables.
If something has gone wrong, you may be prompted to manually install the fortran executables.

```
make -C sami2py/fortran compile
```

Now you can run the sami2 executable (sami2py.x) from anywhere.


# Example

Expand Down
4 changes: 1 addition & 3 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ a local install use the "--user" flag after "install".
cd sami2py/
python setup.py install

Additionally, you must make and install the fortran executables.
If something has gone wrong, you may be prompted to manually install the fortran executables.

::

make -C sami2py/fortran compile

Now you can run the sami2 executable (sami2py.x) from anywhere.
33 changes: 33 additions & 0 deletions docs/sample_workflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,37 @@ Now load the resultant data:

ModelRun = sami2py.Model(tag='run_name', lon=0, year=2012, day=210)

The data is stored as `ModelRun.data`, which is an `xarray.Dataset`. Information about the run is stored as 'ModelRun.MetaData', which is a human-readable dictionary of the namelist.

The MetaData can be accessed directly via the dictionary, or through the __repr__. Typing

.. code:: python

ModelRun

yields

.. code:: python

Model Run Name = test
Day 256, 1999
Longitude = 256 deg
2 time steps from 0.1 to 0.1 UT
Ions Used: H+, O+, NO+, O2+, He+, N2+

Solar Activity
--------------
F10.7: 120.0 sfu
F10.7A: 120.0 sfu
ap: 0

Component Models Used
---------------------
Neutral Atmosphere: NRLMSISe-2000
Winds: HWM-14
Photoproduction: EUVAC
ExB Drifts: Fejer-Scherliess

No modifications to empirical models

Full description coming soon
33 changes: 8 additions & 25 deletions sami2py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,16 @@
# Full license can be found in License.md
# -----------------------------------------------------------------------------
"""
sami2py
-----------
sami2py - sami2py is another model of the ionosphere python style
=================================================================

Functions
---------------------------------------------------------------------------
run_model(year, day, lat=0, lon=0, alt=300,
f107=120, f107a=120, ap=0,
rmin=100, rmax=2000, gams=3, gamp=3, altmin=85.,
dthr=0.25, hrinit=0., hrpr=24., hrmax=48.,
dt0=30., maxstep=100000000, denmin=1.e-6,
nion1=1, nion2=7, mmass=48, h_scale=1, o_scale=1,
no_scale=1, o2_scale=1, he_scale=1, n2_scale=1, n_scale=1,
Tinf_scale=1, Tn_scale=1., euv_scale=1,
wind_scale=1, hwm_model=14,
fejer=True, ExB_drifts=np.zeros((10,2)), ve01=0., exb_scale=1,
alt_crit=150., cqe=7.e-14,
tag='test', clean=False, test=False)
Sami2py is a python module that runs the SAMI2 model, as well as archives,
loads and plots the resulting modeled values. SAMI2 is a model developed
by the Naval Research Laboratory to simulate the motions of plasma in a
2D ionospheric environment along a dipole magnetic field [Huba et al, 2000].
SAMI2 solves for the chemical and dynamical evolution of seven ion species
in this environment (H+, He+, N+, O+, N2+, NO+, and O2+).

Initializes a run of the SAMI2 model and archives the data.
---------------------------------------------------------------------------

Classes
---------------------------------------------------------------------------
model
Loads, reshapes, and holds SAMI2 output for a given model run
specified by the user.
---------------------------------------------------------------------------
"""
import logging
import sys
Expand Down
49 changes: 22 additions & 27 deletions sami2py/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import os
import subprocess
import numpy as np
from sami2py import fortran_dir
from sami2py import fortran_dir, __version__
from .utils import generate_path


Expand Down Expand Up @@ -252,8 +252,8 @@ def run_model(tag='model_run', lat=0, lon=0, alt=300, year=2018, day=1,
'wind_scale': wind_scale, 'hwm_model': hwm_model}

info['fejer'] = _generate_drift_info(fejer, ExB_drifts)
info['fmtout'] = _generate_format_info(fmtout)
info['outn'] = _generate_neutral_info(outn)
info['fmtout'] = _generate_fortran_bool(fmtout)
info['outn'] = _generate_fortran_bool(outn)
_generate_namelist(info)
archive_path = generate_path(tag, lon, year, day, test)
if not test:
Expand All @@ -268,36 +268,22 @@ def _generate_drift_info(fejer, ExB_drifts=None):
"""Generates the information regarding the ExB drifts used by the model.
This information is later stored in the namelist file for SAMI2
"""
if fejer:
drift_info = '.true.'
else:
drift_info = _generate_fortran_bool(fejer)
if not fejer:
if ExB_drifts.shape != (10, 2):
raise Exception('Invalid ExB drift shape! Must be 10x2 ndarray.')
drift_info = '.false.'
np.savetxt('exb.inp', ExB_drifts)
return drift_info


def _generate_format_info(fmtout):
"""Generates the namelist information needed to tell the SAMI2 model to
output the model results in formatted or unformatted data files
"""
if fmtout:
format_info = '.true.'
else:
format_info = '.false.'
return format_info


def _generate_neutral_info(outn):
"""Generates the namelist information needed to tell the SAMI2 model to
output the model results of neutral species and wind
def _generate_fortran_bool(pybool):
"""Generates a fortran bool as a string for the namelist generator
"""
if outn:
neutral_info = '.true.'
if pybool:
fbool = '.true.'
else:
neutral_info = '.false.'
return neutral_info
fbool = '.false.'
return fbool


def _generate_namelist(info):
Expand Down Expand Up @@ -380,6 +366,7 @@ def _archive_model(path, clean, fejer, fmtout, outn):
If False, then 'exb.inp' is also archived
"""
import shutil
import subprocess

if fmtout:
filelist = ['glonf.dat', 'glatf.dat', 'zaltf.dat',
Expand All @@ -392,19 +379,27 @@ def _archive_model(path, clean, fejer, fmtout, outn):
filelist = ['glonu.dat', 'glatu.dat', 'zaltu.dat',
'deniu.dat', 'vsiu.dat', 'tiu.dat', 'teu.dat',
'time.dat', 'sami2py-1.00.namelist']
if outn:
filelist.append('dennu.dat')
filelist.append('u4u.dat')

if os.path.isfile(filelist[0]):
try:
os.stat(path)
except FileNotFoundError:
os.makedirs(path)

hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'])
with open(os.path.join(path, 'version.txt'), 'w+') as f:
f.write('sami2py v' + __version__ + '\n')
f.write('short hash ' + hash.decode("utf-8"))

for list_file in filelist:
shutil.copyfile(list_file, path + list_file)
shutil.copyfile(list_file, os.path.join(path, list_file))
if clean:
for list_file in filelist[:-1]:
os.remove(list_file)
if not fejer:
shutil.copyfile('exb.inp', path + 'exb.inp')
shutil.copyfile('exb.inp', os.path.join(path, 'exb.inp'))
else:
print('No files to move!')
35 changes: 23 additions & 12 deletions sami2py/_core_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"""
from os import path
import numpy as np
import xarray as xr
from .utils import generate_path, get_unformatted_data


Expand Down Expand Up @@ -210,18 +211,27 @@ def _load_model(self):
te = get_unformatted_data(model_path, 'te',
dim0=dim0, dim1=dim1, reshape=True)

self.glat = np.reshape(glat, (nz, nf), order="F")
self.glon = np.reshape(glon, (nz, nf), order="F")
self.zalt = np.reshape(zalt, (nz, nf), order="F")
self.deni = np.reshape(deni, (nz, nf, ni, nt), order="F")
self.vsi = np.reshape(vsi, (nz, nf, ni, nt), order="F")
self.ti = np.reshape(ti, (nz, nf, ni, nt), order="F")
self.te = np.reshape(te, (nz, nf, nt), order="F")
glat = np.reshape(glat, (nz, nf), order="F")
glon = np.reshape(glon, (nz, nf), order="F")
zalt = np.reshape(zalt, (nz, nf), order="F")
deni = np.reshape(deni, (nz, nf, ni, nt), order="F")
vsi = np.reshape(vsi, (nz, nf, ni, nt), order="F")
ti = np.reshape(ti, (nz, nf, ni, nt), order="F")
te = np.reshape(te, (nz, nf, nt), order="F")
self.data = xr.Dataset({'deni': (['z', 'f', 'ion', 'ut'], deni),
'vsi': (['z', 'f', 'ion', 'ut'], vsi),
'ti': (['z', 'f', 'ion', 'ut'], ti),
'te': (['z', 'f', 'ut'], te),
'slt': (['ut'], self.slt)},
coords={'glat': (['z', 'f'], glat),
'glon': (['z', 'f'], glon),
'zalt': (['z', 'f'], zalt),
'ut': self.ut})
if self.outn:
self.denn = np.reshape(denn, (nz, nf, 7, nt), order="F")
self.u = np.reshape(u, (nz, nf, nt), order="F")
del denn, u
del glat, glon, zalt, deni, vsi, ti, te
denn = np.reshape(denn, (nz, nf, 7, nt), order="F")
self.data['denn'] = denn
u = np.reshape(u, (nz, nf, nt), order="F")
self.data['u'] = u

def _generate_metadata(self, namelist):
"""Reads the namelist and generates MetaData based on Parameters
Expand Down Expand Up @@ -345,7 +355,8 @@ def plot_lat_alt(self, time_step=0, species=1):
"""
import matplotlib.pyplot as plt

plt.pcolor(self.glat, self.zalt, self.deni[:, :, species, time_step])
plt.pcolor(self.data['glat'], self.data['zalt'],
self.data['deni'][:, :, species, time_step])
plt.xlabel('Geo Lat (deg)')
plt.ylabel('Altitude (km)')
plt.show()
20 changes: 10 additions & 10 deletions sami2py/fortran/exb.inp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
-2.256592115245508268e+01 -1.700658929016086063e+01
6.970157155494434598e+00 -1.785773092653965932e+01
7.715990594846469097e-01 -1.457794556537672204e+00
1.133009384321719537e+01 6.217447257350539047e+00
5.315180719049175551e+00 6.543500525980066485e+00
-4.754135936133724094e+00 7.493698025175492994e+00
-3.036451049580922046e+00 -1.789034697779917638e+00
-3.791099765373269648e+00 -8.665409647917849956e-01
2.083139968647748308e+00 -3.636326810220660732e+00
2.205828847907577828e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
0.000000000000000000e+00 0.000000000000000000e+00
10 changes: 8 additions & 2 deletions sami2py/fortran/sami2py-1.00.f
Original file line number Diff line number Diff line change
Expand Up @@ -2914,6 +2914,8 @@ subroutine sf1216 ( f,line,nfl )

subroutine open_u

include 'param-1.00.inc'
include 'com-1.00.inc'
! open output files (unformatted, except time.dat)

open ( unit=70, file='time.dat' ,form='formatted' )
Expand All @@ -2924,7 +2926,9 @@ subroutine open_u
! open ( unit=78, file='vnu.dat' ,form='unformatted' )
! open ( unit=90, file='vtu.dat' ,form='unformatted' )
! open ( unit=91, file='vru.dat' ,form='unformatted' )
! open ( unit=92, file='dennu.dat' ,form='unformatted' )
if (outn) then
open ( unit=92, file='dennu.dat' ,form='unformatted' )
endif
! open ( unit=93, file='vexbu.dat' ,form='unformatted' )

! diagnostic files (unformatted)
Expand All @@ -2935,7 +2939,9 @@ subroutine open_u
! open ( unit=84, file='u1u.dat' ,form='unformatted' )
! open ( unit=85, file='u2u.dat' ,form='unformatted' )
! open ( unit=86, file='u3u.dat' ,form='unformatted' )
! open ( unit=87, file='u4u.dat' ,form='unformatted' )
if (outn) then
open ( unit=87, file='u4u.dat' ,form='unformatted' )
endif
! open ( unit=88, file='u5u.dat' ,form='unformatted' )

return
Expand Down
12 changes: 6 additions & 6 deletions sami2py/fortran/sami2py-1.00.namelist
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
&go
fmtout = .true.,
maxstep = 100000000,
hrmax = 48.000000,
hrmax = 0.110000,
dt0 = 30.000000,
dthr = 0.250000,
hrpr = 24.000000,
dthr = 0.050000,
hrpr = 0.000000,
grad_in = 300.000000,
glat_in = 0.000000,
glon_in = 0.000000,
glon_in = 256.000000,
fejer = .true.,
rmin = 100.000000,
rmax = 2000.000000,
altmin = 85.000000,
fbar = 120.000000,
f10p7 = 120.000000,
ap = 0,
year = 2012,
day = 211,
year = 1958,
day = 30,
mmass = 48,
nion1 = 1,
nion2 = 7,
Expand Down
10 changes: 6 additions & 4 deletions sami2py/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ def setup(self):
if not os.path.exists(self.model_path):
os.makedirs(self.model_path)
self.filelist = ['glonf.dat', 'glatf.dat', 'zaltf.dat', 'denif.dat',
'vsif.dat', 'tif.dat', 'tef.dat', 'time.dat']
'dennf.dat', 'u4f.dat', 'vsif.dat', 'tif.dat',
'tef.dat', 'time.dat']
for filename in self.filelist:
open(os.path.join(fortran_dir, filename), 'w').close()

Expand All @@ -42,7 +43,7 @@ def teardown(self):
def test_run_model_namelist(self):
"""The test to ensure that the namelist file is generated properly
"""
sami2py.run_model(tag='test', year=2012, day=211, test=True,
sami2py.run_model(tag='test', lon=0, year=2012, day=211, test=True,
fmtout=self.format)
namelist_file = self.model_path + 'sami2py-1.00.namelist'
ref_namelist = os.path.join(test_data_dir, self.ref_file)
Expand All @@ -61,7 +62,7 @@ def test_run_model_dat_files(self):
"""Test to ensure that the dat files are copied properly
"""
sami2py.run_model(tag='test', lon=0, year=2012, day=211, test=True,
fmtout=self.format)
fmtout=self.format, outn=True)
if self.format:
fname = 'glonf.dat'
else:
Expand Down Expand Up @@ -123,7 +124,8 @@ def setup(self):
if not os.path.exists(self.model_path):
os.makedirs(self.model_path)
self.filelist = ['glonu.dat', 'glatu.dat', 'zaltu.dat', 'deniu.dat',
'vsiu.dat', 'tiu.dat', 'teu.dat', 'time.dat']
'dennu.dat', 'u4u.dat', 'vsiu.dat', 'tiu.dat',
'teu.dat', 'time.dat']
for filename in self.filelist:
open(os.path.join(fortran_dir, filename), 'w').close()

Expand Down
Loading