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

Partial preprocessor implementation #52

Merged
merged 15 commits into from
Jun 9, 2020
Merged
22 changes: 12 additions & 10 deletions docs/source/guides/10min.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,33 @@ Use pyDeltaRCM in ten minutes!
You can get a model running with three simple lines of code.
First, we instantiate the main :obj:`~pyDeltaRCM.deltaRCM_driver.pyDeltaRCM` model object.

.. code::
.. doctest::

>>> import pyDeltaRCM

>>> delta = pyDeltaRCM.deltaRCM_driver.pyDeltaRCM()
>>> delta = pyDeltaRCM.DeltaModel()

Next, since this is just a simple demo, we will run for a few short timesteps.
The delta model is run forward with a call to the :meth:`~pyDeltaRCM.deltaRCM_driver.pyDeltaRCM.update()` method of the delta model.
So we loop a few times and then finalize the model:
The delta model is run forward with a call to the :meth:`~pyDeltaRCM.DeltaModel.update()` method of the delta model.
So we loop the update function, and then finalize the model:

.. code::
.. doctest::

>>> for _t in range(0, 1):
>>> delta.update()
>>> for _ in range(0, 2):
... delta.update()

>>> delta.finalize()

That's it! You ran the pyDeltaRCM model for one timestep.
That's it! You ran the pyDeltaRCM model for two timesteps.

We can visualize the delta bed elevation, though it's not very exciting after only one timestep...
We can visualize the delta bed elevation, though it's not very exciting after only two timestep...

.. code::

>>> import matplotlib.pyplot as plt

>>> fig, ax = plt.subplots()
>>> ax.imshow(delta.bed_elevation, vmax=-4.5)
>>> ax.imshow(delta.bed_elevation, vmax=-4)
>>> plt.show()

.. plot:: 10min/model_run_visual.py
62 changes: 40 additions & 22 deletions docs/source/guides/userguide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,59 +16,75 @@ Inside this file you can specify parameters for your run, with each parameter on
.. code-block:: yaml

S0: 0.005
seed: 42

then a :obj:`~pyDeltaRCM.deltaRCM_driver.pyDeltaRCM` model instance initialized with this file specified as ``input_file`` will have a slope of 0.005.
then a :obj:`~pyDeltaRCM.DeltaModel` model instance initialized with this file specified as ``input_file`` will have a slope of 0.005, and will use a random seed of 42.
Multiple parameters can be specified line by line.

Default values are substituted for any parameter not explicitly given in the ``input_file`` ``.yml`` file.
Default values of the YAML configuration are listed in the :doc:`../reference/deltaRCM_driver/yaml_defaults`.
Default values of the YAML configuration are listed in the :doc:`../reference/model/yaml_defaults`.


===================
Starting model runs
===================

There are three ways to interact with the pyDeltaRCM model.
Two methods are part of the "high-level" model API, and these approaches each consist of a single line of code.
The third method is to create a model instance via the "low-level" model API and manually handle timestepping and model finalization.
There are two API levels at which you can interact with the pyDeltaRCM model.
There is a "high-level" model API, which takes as argument a YAML configuration file, and will compose a list of jobs as indicated in the YAML file; the setup can be configured to automatically execute the job list, as well.
The "low-level" API consists of creating a model instance from a YAML configuration file and manually handling the timestepping, or optionally, augmenting operations of the model to implement new features.


High-level model API
====================

The high-level API is accessed via either a shell prompt or python script, and is invoked directly if a YAML configuration file includes the ``timesteps`` variable.

.. note::
To use the high-level API, the configuration YAML file must contain the ``timesteps`` variable.

Bash API
--------

For example, to invoke a model run from the bash prompt using the YAML file ``model_configuration.yml`` which looks like:
For the following high-level API demonstrations, consider a YAML input file named ``model_configuration.yml`` which looks like:

.. code-block:: yaml

Length: 5000
Width: 2000
timesteps: 500

we would simply invoke at the bash prompt:

Command line API
----------------

To invoke a model run from the command line using the YAML file ``model_configuration.yml`` defined above,
we would simply call:

.. code:: bash

python -m pyDeltaRCM --config model_configuration.yml
pyDeltaRCM --config model_configuration.yml

or equivalently:

.. code:: bash

run_pyDeltaRCM --config model_configuration.yml
python -m pyDeltaRCM --config model_configuration.yml

These invokations will run the pyDeltaRCM :obj:`preprocessor <pyDeltaRCM.preprocessor.PreprocessorCLI>` with the parameters specified in the ``model_configuration.yml`` file.
If the YAML configuration indicates multiple jobs (:ref:`via matrix expansion or ensemble specification <configuring_multiple_jobs>`), the jobs will each be run automatically by calling :obj:`~pyDeltaRCM.DeltaModel.update` on the model 500 times.

These invokations will run the pyDeltaRCM with the parameters specified in the ``model_configuration.yml`` file, and automatically :obj:`~pyDeltaRCM.deltaRCM_driver.pyDeltaRCM.update` the model 500 times.


Python API
----------

Alternatively, calling the ``run_model`` method from a python script, with the :meth:`input file <pyDeltaRCM.deltaRCM_driver.pyDeltaRCM.__init__>` parameter specified as the same ``model_configuration.yml`` file above, would run the pyDeltaRCM model, and automatically :obj:`~pyDeltaRCM.deltaRCM_driver.pyDeltaRCM.update` the model 500 times.
The Python high-level API is accessed via the :obj:`~pyDeltaRCM.Preprocessor` object.
First, the `Preprocessor` is instantiated with a YAML configuration file (e.g., ``model_configuration.yml``):

.. code::

>>> pp = preprocessor.Preprocessor(p)

which returns an object containing the list of jobs to run.
Jobs are then run with:

.. code::

>>> pp.run_jobs()



Expand All @@ -79,20 +95,22 @@ iinteract with the model by creating your own script, and manipulating model out

.. code::

delta = pyDeltaRCM(input_file='model_configuration.yml')
>>> delta = DeltaModel(input_file='model_configuration.yml')

for time in range(0,1):
delta.update()
>>> for _ in range(0, 1):
... delta.update()

delta.finalize()
>>> delta.finalize()

However, you can also inspect/modify the :obj:`~pyDeltaRCM.deltaRCM_driver.pyDeltaRCM.update` method, and change the order or add operations as desired.
However, you can also inspect/modify the :obj:`~pyDeltaRCM.DeltaModel.update` method, and change the order of operations, or add operations, as desired.


=============================
Advanced model configurations
=============================

.. _configuring_multiple_jobs:

Configuring multiple model runs from a single YAML file
==============================================================

Expand Down
8 changes: 4 additions & 4 deletions docs/source/pyplots/10min/model_run_visual.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import sys
import os
sys.path.append(os.path.realpath(os.getcwd() + "/../../../../"))
# sys.path.append(os.path.realpath(os.getcwd() + "/../../../../"))

import matplotlib.pyplot as plt

import pyDeltaRCM


delta = pyDeltaRCM.pyDeltaRCM()
delta = pyDeltaRCM.DeltaModel()

for _t in range(0, 1):
for _t in range(0, 2):
delta.update()

delta.finalize()


fig, ax = plt.subplots()
ax.imshow(delta.bed_elevation, vmax=-4.5)
ax.imshow(delta.bed_elevation, vmax=-4)
plt.show()
26 changes: 0 additions & 26 deletions docs/source/reference/deltaRCM_driver/index.rst

This file was deleted.

3 changes: 2 additions & 1 deletion docs/source/reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ methods.
.. toctree::
:maxdepth: 2

deltaRCM_driver/index
model/index
deltaRCM_tools/index
init_tools/index
water_tools/index
sed_tools/index
shared_tools/index
preprocessor/index


References
Expand Down
27 changes: 27 additions & 0 deletions docs/source/reference/model/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.. api.model:

*****
model
*****

This is the main model code.

This class is defined in ``pyDeltaRCM.model``.


.. currentmodule:: pyDeltaRCM.model

.. autosummary::
:toctree: ../../_autosummary

DeltaModel



Model configuration reference
=============================

.. toctree::
:maxdepth: 1

yaml_defaults
18 changes: 18 additions & 0 deletions docs/source/reference/preprocessor/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.. api.preprocessor:

*********************************
Preprocessor
*********************************

The high-level API is principally defined in ``pyDeltaRCM.preprocessor``.


.. currentmodule:: pyDeltaRCM.preprocessor

.. autosummary::
:toctree: ../../_autosummary

PreprocessorCLI
Preprocessor
preprocessor_wrapper
BasePreprocessor
6 changes: 3 additions & 3 deletions pyDeltaRCM/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .deltaRCM_tools import Tools
from .deltaRCM_driver import pyDeltaRCM
from .model import DeltaModel
from .preprocessor import Preprocessor
from .bmi_delta import BmiDelta
from .shared_tools import _get_version

__all__ = ['Tools', 'pyDeltaRCM', 'BmiDelta']
__all__ = ['DeltaModel', 'Preprocessor', 'BmiDelta']
__version__ = _get_version()
4 changes: 2 additions & 2 deletions pyDeltaRCM/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pyDeltaRCM import command_line
from . import preprocessor

if __name__ == '__main__':
command_line.run_model()
preprocessor.preprocessor_wrapper()
4 changes: 2 additions & 2 deletions pyDeltaRCM/bmi_delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
from basic_modeling_interface import Bmi

from .deltaRCM_driver import pyDeltaRCM
from .model import DeltaModel

"""Basic Model Interface implementation for pyDeltaRCM."""

Expand Down Expand Up @@ -178,7 +178,7 @@ def initialize(self, filename = 'deltaRCM.yaml'):
yaml.dump(input_file_vars, inbetweenYAML)
inbetweenYAML.close()

self._delta = pyDeltaRCM(input_file = tmpFile)
self._delta = DeltaModel(input_file = tmpFile)

self._values = {
'channel_exit_water_flow__speed': self._delta.u0,
Expand Down
33 changes: 0 additions & 33 deletions pyDeltaRCM/command_line.py

This file was deleted.

3 changes: 0 additions & 3 deletions pyDeltaRCM/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,3 @@ coeff_U_ero_sand:
alpha:
type: ['float', 'int']
default: 0.1
timesteps:
type: ['float', 'int']
default: 10
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we remove the notion of a default timestepping?

3 changes: 3 additions & 0 deletions pyDeltaRCM/deltaRCM_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ def output_strata(self):
self.strata_eta = self.strata_eta[:, :self.strata_counter]

shape = self.strata_eta.shape
if shape[0] < 1:
raise RuntimeError('Stratigraphy are empty! '
'Are you sure you ran the model with `update()`?')

total_strata_age = self.output_netcdf.createDimension(
'total_strata_age',
Expand Down
3 changes: 2 additions & 1 deletion pyDeltaRCM/init_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ def create_other_variables(self):

self.diffusion_multiplier = (self.dt / self.N_crossdiff * self.alpha
* 0.5 / self.dx**2)
# self.prefix

# output directory config
self.prefix = self.out_dir

if self.out_dir[-1] != '/':
Expand Down
Loading