Skip to content

Commit

Permalink
update docs to reflect python 3.7+; update handling of coupled input …
Browse files Browse the repository at this point in the history
…variables; add Jupyter notebook tutorial
  • Loading branch information
thurber committed Jun 7, 2021
1 parent fb6d250 commit 7fc56f1
Show file tree
Hide file tree
Showing 6 changed files with 559 additions and 32 deletions.
36 changes: 10 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@

## getting started

Ensure you have Python >= 3.9 available (consider using a [virtual environment](https://github.com/pyenv/pyenv), see the docs [here](https://mosartwmpy.readthedocs.io/en/latest/virtualenv.html) for a brief tutorial), then install `mosartwmpy` with:
Ensure you have Python >= 3.7 available (consider using a [virtual environment](https://github.com/pyenv/pyenv), see the docs [here](https://mosartwmpy.readthedocs.io/en/latest/virtualenv.html) for a brief tutorial), then install `mosartwmpy` with:
```shell
pip install mosartwmpy
```

Alternatively, install via conda with:
```shell
conda install mosartwmpy
```

Download a sample input dataset spanning May 1981 by running the following and selecting option `1` for "tutorial". This will download and unpack the inputs to your current directory. Optionally specify a path to download and extract to instead of the current directory.

```shell
Expand Down Expand Up @@ -108,6 +113,10 @@ plt.show()

```

## model coupling

A common use case for `mosartwmpy` is to run coupled with output from the Community Land Model (CLM). To see an example of how to drive `mosartwmpy` with runoff from a coupled model, check out the [Jupyter notebook tutorial](https://github.com/IMMM-SFA/mosartwmpy/blob/main/notebooks/tutorial.ipynb)!

## model input

Several input files in NetCDF format are required to successfully run a simulation, which are not shipped with this repository due to their large size. The grid files, reservoir files, and a small range of runoff and demand input files can be obtained using the download utility by running `python -m mosartwmpy.download` and choosing option 1 for "sample_input". Currently, all input files are assumed to be at the same resolution (for the sample files this is 1/8 degree over the CONUS). Below is a summary of the various input files:
Expand Down Expand Up @@ -197,31 +206,6 @@ Several input files in NetCDF format are required to successfully run a simulati
</tbody>
</table>

Alternatively, certain model inputs can be set using the BMI interface. This can be useful for coupling `mosartwmpy` with other models. If setting an input that would typically be read from a file, be sure to disable the `read_from_file` configuration value for that input. For example:
```python
import numpy as np
from mosartwmpy import Model

mosart_wm = Model()
mosart_wm.initialize()

# get a list of model input variables
mosart_wm.get_input_var_names()

# disable the runoff read_from_file
mosart_wm.config['runoff.read_from_file'] = False

# set the runoff values manually (i.e. from another model's output)
surface_runoff = np.empty(mosart_wm.get_grid_size())
surface_runoff[:] = # <values from coupled model>
mosart_wm.set_value('surface_runoff_flux', surface_runoff)

# advance one timestep
mosart_wm.update()

# continue coupling...
```

## model output

By default, key model variables are output on a monthly basis at a daily averaged resolution to `./output/<simulation name>/<simulation name>_<year>_<month>.nc`. See the configuration file for examples of how to modify the outputs, and the `./mosartwmpy/state/state.py` file for state variable names.
Expand Down
22 changes: 17 additions & 5 deletions mosartwmpy/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,17 +161,23 @@ def initialize(self, config_file_path: str = None, grid: Grid = None, state: Sta
raise e

logging.debug(f'Initialization completed in {pretty_timer(timer() - t)}.')
logging.info(f'Done.')

def update(self) -> None:
t = timer()
step = datetime.fromtimestamp(self.get_current_time()).isoformat(" ")
# perform one timestep
logging.debug(f'Beginning timestep {step}...')
try:
# read runoff
if self.config.get('runoff.read_from_file', False):
# read runoff from file
logging.debug(f'Reading runoff input from file.')
load_runoff(self.state, self.grid, self.config, self.current_time)
else:
# convert provided runoff from mm/s to m3/s
self.state.hillslope_surface_runoff = 0.001 * self.grid.land_fraction * self.grid.area * self.state.hillslope_surface_runoff
self.state.hillslope_subsurface_runoff = 0.001 * self.grid.land_fraction * self.grid.area * self.state.hillslope_subsurface_runoff
self.state.hillslope_wetland_runoff = 0.001 * self.grid.land_fraction * self.grid.area * self.state.hillslope_wetland_runoff
# read demand
if self.config.get('water_management.enabled', False):
if self.config.get('water_management.demand.read_from_file', False):
Expand Down Expand Up @@ -206,10 +212,16 @@ def update(self) -> None:
except Exception as e:
logging.exception('Failed to write output or restart file; see below for stacktrace.')
raise e
# clear runoff input arrays
self.state.hillslope_surface_runoff[:] = 0
self.state.hillslope_subsurface_runoff[:] = 0
self.state.hillslope_wetland_runoff[:] = 0
if self.config.get('runoff.read_from_file', False):
# clear runoff input arrays
self.state.hillslope_surface_runoff[:] = 0
self.state.hillslope_subsurface_runoff[:] = 0
self.state.hillslope_wetland_runoff[:] = 0
else:
# convert back to mm/s
self.state.hillslope_surface_runoff = self.state.hillslope_surface_runoff * 1000.0 / self.grid.land_fraction / self.grid.area
self.state.hillslope_subsurface_runoff = self.state.hillslope_subsurface_runoff * 1000.0 / self.grid.land_fraction / self.grid.area
self.state.hillslope_wetland_runoff = self.state.hillslope_wetland_runoff * 1000.0 / self.grid.land_fraction / self.grid.area

def update_until(self, time: float) -> None:
# make sure that requested end time is after now
Expand Down
3 changes: 2 additions & 1 deletion mosartwmpy/utilities/download_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def initialize_logger(self):
# logger console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
console_handler.setFormatter(logging.Formatter(""))
logger.addHandler(console_handler)

@staticmethod
Expand Down Expand Up @@ -100,6 +100,7 @@ def fetch_zenodo(self):
with tqdm.wrapattr(
stream,
'write',
file=sys.stdout,
miniters=1,
desc=self.url,
total=int(r.headers.get('content-length', 0))
Expand Down
21 changes: 21 additions & 0 deletions notebooks/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
simulation:
name: tutorial
start_date: 1981-05-01
end_date: 1981-05-31

grid:
path: ./input/domains/mosart.nc
land:
path: ./input/domains/land.nc

runoff:
read_from_file: true
path: ./input/runoff/runoff_1981_05.nc

water_management:
enabled: true
demand:
read_from_file: true
path: ./input/demand/demand_1981_05.nc
reservoirs:
path: ./input/reservoirs/reservoirs.nc
22 changes: 22 additions & 0 deletions notebooks/config_with_restart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
simulation:
name: tutorial
restart_file: ./output/tutorial/restart_files/tutorial_restart_1981_05_15.nc
start_date: 1981-05-15
end_date: 1981-05-31

grid:
path: ./input/domains/mosart.nc
land:
path: ./input/domains/land.nc

runoff:
read_from_file: true
path: ./input/runoff/runoff_1981_05.nc

water_management:
enabled: true
demand:
read_from_file: true
path: ./input/demand/demand_1981_05.nc
reservoirs:
path: ./input/reservoirs/reservoirs.nc
487 changes: 487 additions & 0 deletions notebooks/tutorial.ipynb

Large diffs are not rendered by default.

0 comments on commit 7fc56f1

Please sign in to comment.