├── .github
└── workflows
│ ├── build.yml
│ └── deploy.yml
├── .gitignore
├── CODE_OF_CONDUCT.rst
├── LICENSE
├── MANIFEST.in
├── README.rst
├── assets
├── private
│ ├── liang_2015_fig1fig2.png
│ ├── liang_2015_fig5.png
│ └── pyDeltaRCM_logo.svg
└── symbol.svg
├── docs
├── Makefile
├── make.bat
└── source
│ ├── .nojekyll
│ ├── _resources
│ ├── checkpoint.yaml
│ ├── checkpoint
│ │ └── checkpoint.npz
│ └── joss
│ │ ├── figures
│ │ ├── figures.py
│ │ ├── pyDeltaRCM_20210810-151130.log
│ │ └── timeseries.png
│ │ ├── paper.bib
│ │ └── paper.md
│ ├── _static
│ └── style.css
│ ├── _templates
│ └── page.html
│ ├── conf.py
│ ├── examples
│ ├── basic_runs.rst
│ ├── custom_class_preprocessor.rst
│ ├── custom_saving.rst
│ ├── custom_yaml.rst
│ ├── index.rst
│ ├── modelzoo.rst
│ ├── overwrite_topo_diffusion.rst
│ ├── resume_from_checkpoint.rst
│ ├── simple_example.ipynb
│ ├── slight_slope.rst
│ ├── subsidence_region.rst
│ ├── updating_boundary_conditions.rst
│ ├── variable_bedload.rst
│ └── variable_velocity.rst
│ ├── guides
│ ├── 10min.rst
│ ├── advanced_configuration_guide.inc
│ ├── developer_guide.rst
│ ├── getting_started.rst
│ ├── subsidence_guide.inc
│ └── user_guide.rst
│ ├── index.rst
│ ├── info
│ ├── hydrodynamics.rst
│ ├── index.rst
│ ├── initialization.rst
│ ├── modeltime.rst
│ ├── morphodynamics.rst
│ ├── outputfile.rst
│ └── yamlparameters.rst
│ ├── meta
│ ├── citing.rst
│ ├── conduct.rst
│ ├── contributing.rst
│ ├── installing.rst
│ ├── license.rst
│ └── usedby.rst
│ ├── pyplots
│ ├── debug_tools
│ │ └── debug_demo.py
│ ├── guides
│ │ ├── 10min_demo.py
│ │ ├── cover.py
│ │ └── output_file.py
│ ├── init_tools
│ │ ├── domain_basin_inlet_depth.py
│ │ ├── domain_inlet_geometry.py
│ │ ├── domain_parameters.py
│ │ └── domain_size_compare.py
│ ├── modeltime
│ │ ├── _base.py
│ │ ├── four_year_condensed_plot.py
│ │ ├── four_year_plot.py
│ │ └── one_year_plot.py
│ ├── sed_tools
│ │ ├── _initial_bed_state.py
│ │ ├── route_all_mud_parcels.py
│ │ ├── route_all_sand_parcels.py
│ │ ├── sediment_weights_examples.py
│ │ └── topo_diffusion.py
│ └── water_tools
│ │ ├── _accumulate_free_surface_walks.py
│ │ ├── _check_for_loops.py
│ │ ├── _smooth_free_surface.py
│ │ ├── compute_free_surface_inputs.py
│ │ ├── compute_free_surface_outputs.py
│ │ ├── flooding_correction.py
│ │ ├── run_water_iteration.py
│ │ └── water_weights_examples.py
│ └── reference
│ ├── debug_tools
│ └── index.rst
│ ├── hook_tools
│ └── index.rst
│ ├── index.rst
│ ├── init_tools
│ └── index.rst
│ ├── iteration_tools
│ └── index.rst
│ ├── model
│ ├── index.rst
│ ├── model_hooks.rst
│ └── yaml_defaults.rst
│ ├── preprocessor
│ └── index.rst
│ ├── sed_tools
│ └── index.rst
│ ├── shared_tools
│ └── index.rst
│ └── water_tools
│ └── index.rst
├── pyDeltaRCM
├── __init__.py
├── __main__.py
├── _version.py
├── debug_tools.py
├── default.yml
├── hook_tools.py
├── init_tools.py
├── iteration_tools.py
├── model.py
├── preprocessor.py
├── sed_tools.py
├── shared_tools.py
└── water_tools.py
├── pyproject.toml
├── requirements-docs.txt
├── requirements-test.txt
├── requirements.txt
├── strat_preprocess.py
└── tests
├── __init__.py
├── imgs_baseline
├── test_plot_domain_cell_type.png
├── test_plot_domain_cell_type_list_index.png
├── test_plot_domain_cell_type_list_mix_tuple_index.png
├── test_plot_domain_cell_type_list_tuple.png
├── test_plot_domain_cell_type_multiple_diff_args.png
├── test_plot_domain_cell_type_multiple_diff_kwargs.png
├── test_plot_domain_cell_type_multiple_index_calls.png
├── test_plot_domain_cell_type_no_grid.png
├── test_plot_domain_cell_type_single_index.png
├── test_plot_domain_cell_type_single_tuple.png
├── test_plot_domain_velocity.png
├── test_plot_domain_withlabel.png
├── test_plot_iwalk.png
├── test_plot_multiple_subplots.png
├── test_show_line_pts_Nx2_array.png
└── test_show_line_set_points.png
├── integration
├── __init__.py
├── test_checkpointing.py
├── test_cli.py
├── test_consistent_outputs.py
└── test_timing_triggers.py
├── test_debug_tools.py
├── test_init_tools.py
├── test_iteration_tools.py
├── test_logging.py
├── test_model.py
├── test_preprocessor.py
├── test_sed_tools.py
├── test_shared_tools.py
├── test_water_tools.py
└── utilities.py
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # This workflow installs and tests pyDeltaRCM on mulitple python versions and operating systems.
2 |
3 | name: build
4 |
5 | on:
6 | push:
7 | pull_request:
8 | schedule:
9 | - cron: '0 0 1 * *' # run workflow at 12AM on first day of every month
10 |
11 | jobs:
12 |
13 | test:
14 | runs-on: ${{ matrix.os }}
15 | strategy:
16 | fail-fast: false
17 | matrix:
18 | os: [ubuntu-latest, macos-latest, windows-latest]
19 | python-version: ['3.11', '3.12', '3.13']
20 | steps:
21 | - name: Checkout code
22 | uses: actions/checkout@v4
23 | - name: Set up Python ${{ matrix.python-version }}
24 | uses: actions/setup-python@v5
25 | with:
26 | python-version: ${{ matrix.python-version }}
27 | - name: Install dependencies
28 | run: |
29 | python -m pip install --upgrade pip
30 | pip install setuptools
31 | pip install -r requirements-test.txt
32 | pip install -r requirements.txt
33 | - name: Install pyDeltaRCM
34 | run: |
35 | pip install .
36 | - name: Test with pytest
37 | run: |
38 | python -m pytest --mpl --mpl-baseline-path=tests/imgs_baseline
39 |
40 |
41 | coverage:
42 | runs-on: ${{ matrix.os }}
43 | strategy:
44 | fail-fast: false
45 | matrix:
46 | os: [ubuntu-latest, macos-latest, windows-latest]
47 | env:
48 | OS: ${{ matrix.os }}
49 | PYTHON: '3.13'
50 | steps:
51 | - name: Checkout code
52 | uses: actions/checkout@v4
53 | - name: Set up Python ${{ env.PYTHON }}
54 | uses: actions/setup-python@v5
55 | with:
56 | python-version: ${{ env.PYTHON }}
57 | - name: Install dependencies
58 | run: |
59 | python -m pip install --upgrade pip
60 | pip install setuptools
61 | pip install pytest pytest-cov pytest-mpl coveralls
62 | pip install -r requirements.txt
63 | - name: Install pyDeltaRCM
64 | run: |
65 | pip install .
66 | - name: Disable jitted for coverage
67 | run: |
68 | echo "DISABLE_JIT: 1" > .numba_config.yaml
69 | - name: Test with pytest
70 | run: |
71 | python -m pytest --ignore=tests/integration/ --cov=pyDeltaRCM/ --cov-report=xml --mpl --mpl-baseline-path=tests/imgs_baseline
72 | - name: Upload coverage to Codecov
73 | uses: codecov/codecov-action@v5
74 | with:
75 | token: ${{ secrets.CODECOV_TOKEN }}
76 | file: ./coverage.xml
77 | env_vars: OS
78 | name: codecov-umbrella
79 | fail_ci_if_error: false
80 |
81 |
82 | docs:
83 | runs-on: ubuntu-latest
84 | steps:
85 | - name: Checkout code
86 | uses: actions/checkout@v4
87 | with:
88 | persist-credentials: false
89 | - name: Set up Python
90 | uses: actions/setup-python@v5
91 | with:
92 | python-version: '3.13'
93 | - name: Install dependencies
94 | run: |
95 | python -m pip install --upgrade pip
96 | pip install setuptools
97 | pip install -r requirements.txt
98 | pip install -r requirements-docs.txt
99 | sudo apt update -y && sudo apt install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended dvipng
100 | - name: Install pyDeltaRCM
101 | run: |
102 | pip install .
103 | - name: Build and test documentation
104 | run: |
105 | (cd docs && make docs)
106 | - name: Upload log file
107 | uses: actions/upload-artifact@v4
108 | if: ${{ failure() }}
109 | with:
110 | name: log-file
111 | path: docs/deltaRCM_Output/*.log
112 | - name: Debug
113 | run: |
114 | echo $REF
115 | echo $EVENT_NAME
116 | echo ${{ github.event_name == 'push' }}
117 | echo ${{ github.ref == 'refs/heads/develop' }}
118 | echo ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
119 | - name: Deploy to GitHub Pages
120 | uses: JamesIves/github-pages-deploy-action@v4
121 | if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
122 | with:
123 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
124 | EVENT_NAME: ${{ github.event_name }}
125 | REF: ${{ github.ref }}
126 | BRANCH: gh-pages
127 | FOLDER: docs/build/html
128 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | # This workflows will upload a Python Package using Twine when a release is created
2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
3 |
4 | name: deploy
5 |
6 | on:
7 | release:
8 | types: [created]
9 |
10 | jobs:
11 | deploy:
12 |
13 | # package runs on all os, so just upload from one for any
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Set up Python
19 | uses: actions/setup-python@v2
20 | with:
21 | python-version: '3.13'
22 | - name: Install dependencies
23 | run: |
24 | python -m pip install --upgrade pip
25 | pip install setuptools wheel twine build
26 | pip install -r requirements.txt
27 | - name: Build
28 | shell: bash
29 | run: |
30 | python -m build
31 | twine upload dist/*
32 | - name: Publish
33 | uses: pypa/gh-action-pypi-publish@release/v1
34 | with:
35 | repository-url: https://upload.pypi.org/legacy/
36 | skip-existing: true
37 | print-hash: true
38 | verify-metadata: false
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | deltaRCM_Output/
2 |
3 | ### a standard OSX .gitignore ###
4 |
5 | # General
6 | .DS_Store
7 | .AppleDouble
8 | .LSOverride
9 |
10 | # Icon must end with two \r
11 | Icon
12 |
13 | # Thumbnails
14 | ._*
15 |
16 | # Files that might appear in the root of a volume
17 | .DocumentRevisions-V100
18 | .fseventsd
19 | .Spotlight-V100
20 | .TemporaryItems
21 | .Trashes
22 | .VolumeIcon.icns
23 | .com.apple.timemachine.donotpresent
24 |
25 | # Directories potentially created on remote AFP share
26 | .AppleDB
27 | .AppleDesktop
28 | Network Trash Folder
29 | Temporary Items
30 | .apdisk
31 |
32 | #################
33 |
34 | # Byte-compiled / optimized / DLL files
35 | __pycache__/
36 | *.py[cod]
37 | *$py.class
38 |
39 | # C extensions
40 | *.so
41 |
42 | # Distribution / packaging
43 | .Python
44 | env/
45 | build/
46 | develop-eggs/
47 | dist/
48 | downloads/
49 | eggs/
50 | .eggs/
51 | lib/
52 | lib64/
53 | parts/
54 | sdist/
55 | var/
56 | *.egg-info/
57 | .installed.cfg
58 | *.egg
59 |
60 | # PyInstaller
61 | # Usually these files are written by a python script from a template
62 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
63 | *.manifest
64 | *.spec
65 |
66 | # Installer logs
67 | pip-log.txt
68 | pip-delete-this-directory.txt
69 |
70 | # Unit test / coverage reports
71 | htmlcov/
72 | .tox/
73 | .coverage
74 | .coverage.*
75 | .cache
76 | nosetests.xml
77 | coverage.xml
78 | *,cover
79 | .hypothesis/
80 | .pytest_cache
81 |
82 | # Translations
83 | *.mo
84 | *.pot
85 |
86 | # Django stuff:
87 | *.log
88 |
89 | # Sphinx documentation
90 | docs/_build/
91 | docs/source/_autosummary/
92 |
93 | # PyBuilder
94 | target/
95 |
96 | #Ipython Notebook
97 | .ipynb_checkpoints
98 |
99 | # SublimeText docs
100 | *.sublime-*
101 |
102 | # VSCode settings directory
103 | .vscode/
104 |
105 | # temp folder
106 | temp/
107 |
108 | # joss paper resources
109 | docs/source/_resources/joss
110 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.rst:
--------------------------------------------------------------------------------
1 | ***************
2 | Code of Conduct
3 | ***************
4 |
5 | Our Pledge
6 | ----------
7 |
8 | In the interest of fostering an open and welcoming environment, we as
9 | contributors and maintainers pledge to making participation in our project and
10 | our community a harassment-free experience for everyone, regardless of age, body
11 | size, disability, ethnicity, gender identity and expression, level of experience,
12 | nationality, personal appearance, race, religion, or sexual identity and
13 | orientation.
14 |
15 |
16 | Our Standards
17 | -------------
18 |
19 | Examples of behavior that contributes to creating a positive environment
20 | include:
21 |
22 | * Using welcoming and inclusive language
23 | * Being respectful of differing viewpoints and experiences
24 | * Gracefully accepting constructive criticism
25 | * Focusing on what is best for the community
26 | * Showing empathy towards other community members
27 |
28 |
29 | Examples of unacceptable behavior by participants include:
30 |
31 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
32 | * Trolling, insulting/derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
35 | * Other conduct which could reasonably be considered inappropriate in a professional setting
36 |
37 |
38 | Our Responsibilities
39 | --------------------
40 |
41 | Project maintainers are responsible for clarifying the standards of acceptable
42 | behavior and are expected to take appropriate and fair corrective action in
43 | response to any instances of unacceptable behavior.
44 |
45 | Project maintainers have the right and responsibility to remove, edit, or
46 | reject comments, commits, code, wiki edits, issues, and other contributions
47 | that are not aligned to this Code of Conduct, or to ban temporarily or
48 | permanently any contributor for other behaviors that they deem inappropriate,
49 | threatening, offensive, or harmful.
50 |
51 | Scope
52 | -----
53 |
54 | This Code of Conduct applies both within project spaces and in public spaces
55 | when an individual is representing the project or its community. Examples of
56 | representing a project or community include using an official project e-mail
57 | address, posting via an official social media account, or acting as an appointed
58 | representative at an online or offline event. Representation of a project may be
59 | further defined and clarified by project maintainers.
60 |
61 | Enforcement
62 | -----------
63 |
64 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
65 | reported by contacting the project team at the issue tracker. All
66 | complaints will be reviewed and investigated and will result in a response that
67 | is deemed necessary and appropriate to the circumstances. The project team is
68 | obligated to maintain confidentiality with regard to the reporter of an incident.
69 | Further details of specific enforcement policies may be posted separately.
70 |
71 | Project maintainers who do not follow or enforce the Code of Conduct in good
72 | faith may face temporary or permanent repercussions as determined by other
73 | members of the project's leadership.
74 |
75 | Attribution
76 | -----------
77 |
78 | This Code of Conduct is adapted from the `Contributor Covenant `_, `version 1.4 `_,
79 | available at https://www.contributor-covenant.org/version/1/4/.
80 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Mariela Perignon
4 | Copyright (c) 2020 The DeltaRCM Team
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include pyDeltaRCM *.yml
2 | exclude *.yml
3 | recursive-include tests/ *.py *.png
4 | recursive-include docs/source/ *
5 | recursive-exclude docs/source/_autosummary *
6 | recursive-exclude docs/source/_resources/joss *
7 | global-exclude *.nc *.log
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | **************
2 | pyDeltaRCM
3 | **************
4 |
5 | .. image:: https://badge.fury.io/py/pyDeltaRCM.svg
6 | :target: https://badge.fury.io/py/pyDeltaRCM
7 |
8 | .. image:: https://joss.theoj.org/papers/10.21105/joss.03398/status.svg
9 | :target: https://doi.org/10.21105/joss.03398
10 |
11 | .. image:: https://github.com/DeltaRCM/pyDeltaRCM/actions/workflows/build.yml/badge.svg
12 | :target: https://github.com/DeltaRCM/pyDeltaRCM/actions
13 |
14 | .. image:: https://codecov.io/gh/DeltaRCM/pyDeltaRCM/branch/develop/graph/badge.svg
15 | :target: https://codecov.io/gh/DeltaRCM/pyDeltaRCM
16 |
17 | .. image:: https://app.codacy.com/project/badge/Grade/1c137d0227914741a9ba09f0b00a49a7
18 | :target: https://app.codacy.com/gh/DeltaRCM/pyDeltaRCM/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade
19 |
20 |
21 |
22 |
23 | *pyDeltaRCM* is a computationally efficient, free and open source, and easy-to-customize numerical delta model based on the original DeltaRCM model design (`Matlab deltaRCM `_ model by Man Liang; `Liang et al., 2015 `_).
24 | *pyDeltaRCM* delivers improved model stability and capabilities, infrastructure to support exploration with minimal boilerplate code, and establishes an approach to extending model capabilities that ensures reproducible and comparable studies.
25 |
26 |
27 | .. figure:: https://deltarcm.org/pyDeltaRCM/_images/cover.png
28 |
29 | Weighted random walks for 20 water parcels, in a *pyDeltaRCM* model run with default parameters.
30 |
31 |
32 | Documentation
33 | #############
34 |
35 | `Find the complete documentation here `_.
36 |
37 | Documentation includes an `installation guide `_, a thorough `guide for users `_, detailed `API documentation for developers `_, a `plethora of examples `_ to use and develop pyDeltaRCM in novel scientific experiments, and more!
38 |
39 |
40 | Installation
41 | ############
42 |
43 | See our complete `installation guide `_, especially if you are a developer planning to modify or contribute code (`developer installation guide `_), or if you are new to managing Python `venv` or `conda` environments.
44 |
45 | For a quick installation into an existing Python 3.x environment:
46 |
47 | .. code:: console
48 |
49 | $ pip install pyDeltaRCM
50 |
51 |
52 | Executing the model
53 | ###################
54 |
55 | We recommend you check out our `pyDeltaRCM in 10 minutes tutorial `_, which is part of our documentation.
56 |
57 | Beyond that brief tutorial, we have a comprehensive `User Documentation `_ and `Developer Documentation `_ to check out.
58 |
59 |
60 | Citing pyDeltaRCM
61 | #################
62 |
63 | When citing *pyDeltaRCM*, please cite the `JOSS paper `_:
64 |
65 | Moodie et al., (2021). pyDeltaRCM: a flexible numerical delta model. Journal of Open Source Software, 6(64), 3398, https://doi.org/10.21105/joss.03398
66 |
67 | If you use BibTeX, you can add *pyDeltaRCM* to your `.bib` file using the following code:
68 |
69 | .. code:: console
70 |
71 | @article{Moodie2021,
72 | doi = {10.21105/joss.03398},
73 | url = {https://doi.org/10.21105/joss.03398},
74 | year = {2021},
75 | publisher = {The Open Journal},
76 | volume = {6},
77 | number = {64},
78 | pages = {3398},
79 | author = {Andrew J. Moodie and Jayaram Hariharan and Eric Barefoot and Paola Passalacqua},
80 | title = {*pyDeltaRCM*: a flexible numerical delta model},
81 | journal = {Journal of Open Source Software}
82 | }
83 |
84 |
85 | Additional notes
86 | ################
87 |
88 | This repository no longer includes the `Basic Model Interface (BMI) `_ wrapper to the DeltaRCM model.
89 | *pyDeltaRCM* maintains BMI compatibility through another repository (`the BMI_pyDeltaRCM model `_).
90 |
--------------------------------------------------------------------------------
/assets/private/liang_2015_fig1fig2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/assets/private/liang_2015_fig1fig2.png
--------------------------------------------------------------------------------
/assets/private/liang_2015_fig5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/assets/private/liang_2015_fig5.png
--------------------------------------------------------------------------------
/assets/private/pyDeltaRCM_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
74 |
--------------------------------------------------------------------------------
/assets/symbol.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help docs Makefile
16 |
17 |
18 | docs: test clean html
19 |
20 |
21 | clean :
22 | rm -rf source/api/
23 | rm -rf source/_autosummary/
24 | rm -rf ./build/
25 |
26 |
27 | test : clean
28 | @$(SPHINXBUILD) -b doctest "$(SOURCEDIR)" "$(BUILDDIR)" -E
29 | @$(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)" -E
30 |
31 |
32 | # Catch-all target: route all unknown targets to Sphinx using the new
33 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
34 | %: Makefile
35 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
36 |
37 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/source/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/docs/source/.nojekyll
--------------------------------------------------------------------------------
/docs/source/_resources/checkpoint.yaml:
--------------------------------------------------------------------------------
1 | out_dir: 'checkpoint'
2 | seed: 451220118313
3 | save_checkpoint: True
4 | timesteps: 2000
5 |
--------------------------------------------------------------------------------
/docs/source/_resources/checkpoint/checkpoint.npz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/docs/source/_resources/checkpoint/checkpoint.npz
--------------------------------------------------------------------------------
/docs/source/_resources/joss/figures/figures.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | import matplotlib
4 |
5 | import os
6 | import sys
7 |
8 | import pyDeltaRCM
9 | from pyDeltaRCM.shared_tools import sec_in_day, day_in_yr
10 |
11 | import netCDF4 as nc
12 | from typing import List
13 |
14 | # everything relative to this file
15 | _dir: str = os.path.realpath(os.path.dirname(__file__))
16 |
17 |
18 | if __name__ == '__main__':
19 |
20 | # get script input argument
21 | _arg: List[str] = sys.argv
22 | if len(_arg) == 3:
23 | _input_flag: str = sys.argv[1].strip('-')
24 | elif len(_arg) == 2:
25 | _input_flag: str = sys.argv[1].strip('-')
26 | else:
27 | raise ValueError('No arguments supplied.')
28 |
29 | # parameter choices for scaling
30 | If: float = 10 / day_in_yr # intermittency factor for year-scaling
31 |
32 | # if running the computation
33 | if _input_flag == 'compute':
34 |
35 | _mdl = pyDeltaRCM.DeltaModel(
36 | out_dir=_dir,
37 | seed=10151919, # JOSS, A1Z26 encoded
38 | save_eta_grids=True,
39 | save_dt=sec_in_day)
40 |
41 | for i in range(4000):
42 | _mdl.update()
43 |
44 | # finalize
45 | _mdl.finalize()
46 |
47 | # if running the plotting
48 | elif _input_flag == 'plot':
49 |
50 | # set up attributes needed for plotting
51 | H_SL, h, n = 0, 4, 0.3 # sea level, basin depth, surf relief
52 | blues = matplotlib.cm.get_cmap('Blues_r', 64)
53 | greens = matplotlib.cm.get_cmap('YlGn_r', 64)
54 | combined = np.vstack((blues(np.linspace(0.1, 0.7, 5)),
55 | greens(np.linspace(0.2, 0.8, 5))))
56 | cmap = matplotlib.colors.ListedColormap(combined, name='delta')
57 | bounds = np.hstack(
58 | (np.linspace(H_SL-h, H_SL-(n/2), 5),
59 | np.linspace(H_SL, H_SL+n, 6)))
60 | norm = matplotlib.colors.BoundaryNorm(bounds, len(bounds)-1)
61 |
62 | data = nc.Dataset(os.path.join(_dir, 'pyDeltaRCM_output.nc'))
63 |
64 | nt = 4
65 | ts = np.linspace(0, data['eta'].shape[0]-1,
66 | num=nt, dtype=int) # linearly interpolate ts
67 |
68 | # make the timeseries plot
69 | fig, ax = plt.subplots(1, nt, figsize=(11, 2), dpi=300)
70 | for i, t in enumerate(ts):
71 | ax[i].imshow(data['eta'][t, :, :], cmap=cmap, norm=norm)
72 | _time = pyDeltaRCM.shared_tools.scale_model_time(
73 | data['time'][t], If=If, units='years')
74 | ax[i].set_title(' '.join((
75 | str(np.round(_time, 1)),
76 | 'years')))
77 | ax[i].axes.get_xaxis().set_ticks([])
78 | ax[i].axes.get_yaxis().set_ticks([])
79 |
80 | # plt.show()
81 | plt.tight_layout()
82 | plt.savefig(os.path.join(_dir, 'timeseries.png'), transparent=True)
83 |
84 | # otherwise
85 | else:
86 | raise ValueError('Invalid argument supplied.')
87 |
--------------------------------------------------------------------------------
/docs/source/_resources/joss/figures/timeseries.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/docs/source/_resources/joss/figures/timeseries.png
--------------------------------------------------------------------------------
/docs/source/_resources/joss/paper.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '*pyDeltaRCM*: a flexible numerical delta model'
3 | tags:
4 | - Python
5 | - sedimentology
6 | - deltas
7 | - stratigraphy
8 | authors:
9 | - name: Andrew J. Moodie
10 | orcid: 0000-0002-6745-036X
11 | affiliation: "1"
12 | - name: Jayaram Hariharan
13 | orcid: 0000-0002-1343-193X
14 | affiliation: "1"
15 | - name: Eric Barefoot
16 | orcid: 0000-0001-5770-2116
17 | affiliation: "2"
18 | - name: Paola Passalacqua
19 | affiliation: "1"
20 | orcid: 0000-0002-4763-7231
21 | affiliations:
22 | - name: Department of Civil, Architectural, and Environmental Engineering, University of Texas at Austin, Austin, TX, USA
23 | index: 1
24 | - name: Department of Earth, Environmental and Planetary Sciences, Rice University, Houston, TX, USA
25 | index: 2
26 | date: 08 June 2021
27 | bibliography: paper.bib
28 | ---
29 |
30 | # Summary
31 |
32 | River deltas provide many societal benefits, and sustainability of these landforms may be impacted by human modification and global climate change.
33 | Reduced-complexity numerical delta models incorporate limited physical processes, allowing researchers to assess the spatiotemporal evolution of landscape response to individual processes and environmental forcings.
34 | Isolating individual processes is useful to understand, for example, shifting delta morphology due to sea-level rise, changing vegetal cover, or flooding intensity.
35 | As a result, many numerical delta models have been proposed in the literature, and results from these studies are difficult to compare because of various design and implementation choices.
36 | *pyDeltaRCM* (`v2.0`) delivers a computationally efficient and easy-to-customize implementation of the DeltaRCM numerical model [@liang_reduced_1_2015], enabling comparison and reproducibility in studies of delta change due to various environmental forcings.
37 |
38 |
39 | # Statement of need
40 |
41 | River deltas are societally important landforms because they provide arable land, deep inland ports, and are home to hundreds of millions of people globally [@edmonds_coastal_2020].
42 | Existing at the interface between landmasses and water bodies, deltas are impacted by a multitude of processes arising in both of these domains.
43 | For example, changes in sediment input to the delta modulate the rate at which new land is built; similarly, rising water levels in the downstream basin create flooded land.
44 | In addition to natural processes, human landscape modification renders deltaic environments more sensitive to global climate change into the future [@paola_natural_2011].
45 | Demand to understand natural delta processes, and how these processes will respond to various environmental forcings, has led to a proliferation of numerical delta models in the literature [@overeem_three_2005].
46 |
47 | The DeltaRCM delta model [@liang_reduced_1_2015] has gained popularity among geomorphologists due to an attractive balance of computational cost, realism, and interpretability [@larsen_appropriate_2016].
48 | For example, studies have employed the DeltaRCM design to examine delta morphology and dynamism response to sea-level rise and regional subsidence [@liang_quantifying_2016; @liang_how_2016], as well as extended model design to simulate delta evolution with vegetation [@lauzon_comparing_2018] and ice and permafrost [@lauzon_ice_2019; @piliouras_unraveling_2021].
49 | However, comparison among these studies is difficult, owing to disparate code bases, various implementation choices, lack of version control, and proprietary software dependencies.
50 |
51 |
52 | # Background
53 |
54 | Here, version 2.0 of *pyDeltaRCM* is introduced; *pyDeltaRCM* is a computationally efficient, free and open source, and easy-to-customize numerical delta model based on the original DeltaRCM design.
55 | The original DeltaRCM framework is inspired by well-understood physical phenomena, and models mass movement as a probabilistic weighted random-walk process coupled with a set of hierarchical rules; the model is extensively described in @liang_reduced_1_2015 and @liang_reduced_2_2015.
56 |
57 | This same framework is the basis for *pyDeltaRCM* v2.0, with a few modifications selected only to resolve known numerical instabilities, improve computational efficiency, and support reproducible simulations.
58 | *PyDeltaRCM* depends only on common Python packages `numpy` [@harris2020], `matplotlib` [@hunter2007], `scipy` [@virtanen2020], `netCDF4`, `pyyaml`, and `numba` [@lam_numba_2015].
59 |
60 | 
61 |
62 |
63 | # Flexible and easy to use
64 |
65 | *pyDeltaRCM* is an object-oriented package, providing the central model class `DeltaModel`.
66 | By creating custom model behavior as subclasses of `DeltaModel`, researchers can easily add, subtract, and modify model components without altering code that is not pertinent to the science objective.
67 | Importantly, separating custom code from core model code makes clear how different studies can be compared.
68 | The *pyDeltaRCM* documentation provides several examples for how to implement custom model behavior on top of the core `DeltaModel` object.
69 |
70 | *pyDeltaRCM* also provides infrastructure to accelerate scientific exploration, such as the ability to configure multiple simulations from a single file.
71 | Additionally, a preprocessor orchestrates `parallel` simulations for multi-core systems (optionally), and implements several tools to support simulations exploring a parameter space.
72 | For example, `matrix` expansion converts lists of parameters into an n-dimensional set of simulations.
73 | Similarly, replicate simulations can be created via an `ensemble` specification.
74 |
75 | Reproducibility and computational efficiency were important priorities in *pyDeltaRCM* development.
76 | For example, to-disk logging records all parameters, system-level and version data, and random-seed information to ensure that all runs can be recreated.
77 | Additionally, "checkpoint" infrastructure has been added to the model, which records simulation progress during computation and can later resume model runs for further simulation.
78 | Finally, *pyDeltaRCM* uses `numba` for computational optimization [@lam_numba_2015], and does not depend on any proprietary software.
79 |
80 | *pyDeltaRCM* component units and integrations are thoroughly documented and tested.
81 | Component-level documentation describes implementation notes, whereas narratives in "Guide" and "Example" documentation describes high-level model design and best practices for model use and development.
82 | *pyDeltaRCM* also couples with other numerical models via the CSDMS Basic Model Interface 2.0 [@hutton_basic_2020; @BMI_pyDeltaRCM].
83 |
84 |
85 | # Acknowledgments
86 |
87 | We gratefully acknowledge Rebecca Lauzon and Mariela Perignon for developing an implementation of *DeltaRCM* in Python that was the basis for *pyDeltaRCM*.
88 | We also thank the National Science Foundation for supporting us in developing this software, by way of a Postdoctoral Fellowship to A.M. (EAR 1952772) and a grant to J.H. and P.P. (EAR 1719670).
89 |
90 |
91 | # References
--------------------------------------------------------------------------------
/docs/source/_static/style.css:
--------------------------------------------------------------------------------
1 | @import url("default.css"); /* make sure to sync this with the base theme's css filename */
2 |
3 | /*:root {
4 | --main-bg-color: DarkGreen;
5 | --url-color: Brown;
6 | --url-color-hover: Coral;
7 | --sidebar-box-bg-color: DarkOrange;
8 | --sidebar-border-color: Black;
9 | }*/
10 |
11 | :root {
12 | --main-bg-color: #f2f2f2;
13 | --h1-color: #93776C;
14 | --hplus-color: black;
15 | --url-color: #D8925D;
16 | --url-color-hover: #9BAF9B;
17 | --sidebar-box-bg-color: #B3CF89;
18 | --sidebar-border-color: Black;
19 | --footer-bg-color: #B3CF89;
20 | }
21 |
22 |
23 | body {
24 | background-color: var(--main-bg-color);
25 | }
26 |
27 | h1 {
28 | margin: 0;
29 | padding: 0.7em 0 0.3em 0;
30 | font-size: 1.5em;
31 | color: var(--h1-color);
32 | }
33 |
34 | div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
35 | color: var(--hplus-color)!important;
36 | }
37 |
38 | a {
39 | color: var(--url-color);
40 | text-decoration: none;
41 | }
42 |
43 | a:hover {
44 | color: var(--url-color-hover);
45 | }
46 |
47 | a code {
48 | border: 0;
49 | color: var(--url-color);
50 | }
51 |
52 | a code:hover {
53 | color: var(--url-color-hover);
54 | }
55 |
56 | a.headerlink {
57 | color: PeachPuff!important;
58 | font-size: 1em;
59 | margin-left: 6px;
60 | padding: 0 4px 0 4px;
61 | text-decoration: none!important;
62 | }
63 |
64 | div.related ul li a {
65 | margin: 0;
66 | padding: 0 5px 0 5px;
67 | line-height: 1.75em;
68 | color: var(--url-color);
69 | }
70 |
71 | div.related ul li a:hover {
72 | color: var(--url-color-hover);
73 | }
74 |
75 | div.sphinxsidebar h3, div.sphinxsidebar h4 {
76 | color: white;
77 | border: 1px solid var(--sidebar-border-color);
78 | background-color: var(--sidebar-box-bg-color);
79 | }
80 |
81 | div.sphinxsidebar input {
82 | border: 1px solid var(--sidebar-border-color);
83 | }
84 |
85 | pre {
86 | font-family: 'Consolas', 'Deja Vu Sans Mono',
87 | 'Bitstream Vera Sans Mono', monospace;
88 | font-size: 0.95em;
89 | letter-spacing: 0.015em;
90 | line-height: 120%;
91 | padding: 0.5em;
92 | border: 1px solid #ccc;
93 | background-color: #eaece5;
94 | }
95 |
96 | pre span gp {
97 | color: red;
98 | }
99 |
100 | div.footer {
101 | background-color: var(--footer-bg-color);
102 | color: #969696;
103 | padding: 3px 8px 3px 0;
104 | clear: both;
105 | font-size: 0.8em;
106 | text-align: right;
107 | }
108 |
109 | div.footer a {
110 | color: #969696;
111 | text-decoration: underline;
112 | }
--------------------------------------------------------------------------------
/docs/source/_templates/page.html:
--------------------------------------------------------------------------------
1 | {% extends "!page.html" %}
2 |
3 | {% set css_files = css_files + ["_static/style.css"] %}
4 |
5 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 |
16 | import pyDeltaRCM
17 |
18 | # -- Project information -----------------------------------------------------
19 |
20 | project = 'pyDeltaRCM'
21 | copyright = '2020, The DeltaRCM Team'
22 | author = 'The DeltaRCM Team'
23 |
24 | # The full version, including alpha/beta/rc tags
25 | release = pyDeltaRCM.__version__
26 | version = pyDeltaRCM.__version__
27 |
28 |
29 | # -- General configuration ---------------------------------------------------
30 |
31 | # Add any Sphinx extension module names here, as strings. They can be
32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
33 | # ones.
34 | extensions = ['sphinx.ext.autodoc',
35 | 'sphinx.ext.doctest',
36 | 'sphinx.ext.autosummary',
37 | 'sphinx.ext.napoleon',
38 | 'sphinx.ext.graphviz',
39 | 'sphinx.ext.mathjax',
40 | 'sphinx.ext.githubpages',
41 | 'matplotlib.sphinxext.plot_directive',
42 | 'sphinx.ext.todo']
43 |
44 | # Add any paths that contain templates here, relative to this directory.
45 | templates_path = ['_templates']
46 |
47 | # toggle todo items
48 | todo_include_todos = True
49 |
50 | # List of patterns, relative to source directory, that match files and
51 | # directories to ignore when looking for source files.
52 | # This pattern also affects html_static_path and html_extra_path.
53 | exclude_patterns = []
54 |
55 | # Napoleon settings
56 | napoleon_google_docstring = False
57 | napoleon_numpy_docstring = True
58 | napoleon_include_init_with_doc = False
59 | napoleon_include_private_with_doc = False
60 | napoleon_include_special_with_doc = True
61 | napoleon_use_admonition_for_examples = False
62 | napoleon_use_admonition_for_notes = False
63 | napoleon_use_admonition_for_references = False
64 | napoleon_use_ivar = False
65 | napoleon_use_param = True
66 | napoleon_use_rtype = True
67 |
68 | # Autosummary / Automodapi settings
69 | autosummary_generate = True
70 | automodapi_inheritance_diagram = False
71 | autodoc_default_options = {'members': True, 'inherited-members': False,
72 | 'private-members': True}
73 |
74 | # doctest
75 | doctest_global_setup = '''
76 | import pyDeltaRCM
77 | import numpy as np
78 | from matplotlib import pyplot as plt
79 | '''
80 | doctest_test_doctest_blocks = '' # empty string disables testing all code in any docstring
81 |
82 | ## mpl plots
83 | plot_basedir = 'pyplots'
84 | plot_html_show_source_link = False
85 | plot_formats = ['png', ('hires.png', 300)]
86 | plot_pre_code = '''
87 | import numpy as np
88 | from matplotlib import pyplot as plt
89 | import pyDeltaRCM
90 | '''
91 |
92 |
93 | # img math
94 | # imgmath_latex_preamble = '\\usepackage{fouriernc}' # newtxsf, mathptmx
95 |
96 | # -- Options for HTML output -------------------------------------------------
97 |
98 | # The theme to use for HTML and HTML Help pages. See the documentation for
99 | # a list of builtin themes.
100 | #
101 | html_theme = 'sphinxdoc'
102 |
103 | # Add any paths that contain custom static files (such as style sheets) here,
104 | # relative to this directory. They are copied after the builtin static files,
105 | # so a file named "default.css" will overwrite the builtin "default.css".
106 | html_static_path = ['_static']
107 | # html_static_path = []
108 |
109 | # -- Options for linkcheck -------------------------------------------
110 |
111 | # Some DOI links throw 403 errors but when checked they work fine
112 | linkcheck_ignore = [
113 | r'https://doi.org/10.1029/2021GL095053',
114 | r'https://doi.org/10.1029/2018GL079405',
115 | r'https://doi.org/10.1029/2022JF006762',
116 | r'https://doi.org/10.1086/626637'
117 | ]
--------------------------------------------------------------------------------
/docs/source/examples/basic_runs.rst:
--------------------------------------------------------------------------------
1 | Basic script to run the model
2 | =============================
3 |
4 | .. plot::
5 | :context: reset
6 |
7 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
8 | delta = pyDeltaRCM.DeltaModel(
9 | out_dir=output_dir,
10 | resume_checkpoint='../_resources/checkpoint')
11 | delta.finalize()
12 |
13 |
14 | .. code::
15 |
16 | delta = pyDeltaRCM.DeltaModel()
17 |
18 | for _t in range(0, 1000):
19 | delta.update()
20 |
21 | delta.finalize()
22 |
23 | .. plot::
24 | :context:
25 | :include-source:
26 |
27 | fig, ax = plt.subplots()
28 | ax.imshow(delta.eta)
29 | plt.show()
30 |
--------------------------------------------------------------------------------
/docs/source/examples/custom_class_preprocessor.rst:
--------------------------------------------------------------------------------
1 | Using custom classes with the Preprocessor
2 | ==========================================
3 |
4 | Here, we set up three jobs to run as an ensemble of a single custom class.
5 |
6 |
7 | .. plot::
8 | :context: reset
9 | :include-source:
10 |
11 | >>> import numpy as np
12 | >>> import matplotlib.pyplot as plt
13 |
14 | >>> import pyDeltaRCM
15 |
16 | >>> class CustomRandomModel(pyDeltaRCM.DeltaModel):
17 | ... """
18 | ... A subclass of DeltaModel that runs fast for this example.
19 | ...
20 | ... Just for the sake of this example, we are implementing a
21 | ... custom class that runs very quickly. We override the
22 | ... `solve_water_and_sediment_timestep` method of the model to
23 | ... simply add random gaussian blobs to the surface on each step.
24 | ... """
25 | ... def __init__(self, input_file=None, **kwargs):
26 | ...
27 | ... # inherit base DeltaModel methods
28 | ... super().__init__(input_file, **kwargs)
29 | ...
30 | ... self.noise_patch = int(25)
31 | ... self.noise_size = 5 # x y scale
32 | ... self.noise_scale = 200 # z scale
33 | ... self._half_ns = self.noise_patch // 2
34 | ... self.noise_x, self.noise_y = np.meshgrid(
35 | ... np.linspace(-self._half_ns, self._half_ns, num=self.noise_patch),
36 | ... np.linspace(-self._half_ns, self._half_ns, num=self.noise_patch))
37 | ...
38 | ... def solve_water_and_sediment_timestep(self):
39 | ... """Overwrite method for documentation demonstration.
40 | ...
41 | ... This method now simply adds random gaussian noise on each step.
42 | ... """
43 | ... # get a random x and y value
44 | ... # important: use get_random_uniform for reproducibility!
45 | ... x, y, z = [pyDeltaRCM.shared_tools.get_random_uniform(1) for _ in range(3)]
46 | ...
47 | ... # rescale to fit inside domain
48 | ... x = int(x * (self.L - self.noise_patch))
49 | ... y = int(y * (self.W - self.noise_patch))
50 | ...
51 | ... # generate the blob
52 | ... sx = sy = self.noise_size
53 | ... exp = np.exp(-((self.noise_x)**2. / (2. * sx**2.) + (self.noise_y)**2. / (2. * sy**2.)))
54 | ... blob = (1. / (2. * np.pi * sx * sy) * exp * self.noise_scale)
55 | ...
56 | ... # place into domain
57 | ... self.eta[x:x+self.noise_patch, y:y+self.noise_patch] += blob
58 |
59 |
60 | Then, we pass this custom subclass to the :obj:`~pyDeltaRCM.preprocessor.Preprocessor.run_jobs` method.
61 |
62 | .. plot::
63 | :context:
64 |
65 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
66 | param_dict = dict(
67 | out_dir=output_dir,
68 | ensemble=3,
69 | timesteps=50
70 | )
71 |
72 | # let the preprocessor set up the jobs for you from checkpoint
73 | pp = pyDeltaRCM.Preprocessor(
74 | param_dict)
75 |
76 | # run the jobs
77 | pp.run_jobs(DeltaModel=CustomRandomModel)
78 |
79 | .. code::
80 |
81 | >>> # set up dictionary for parameters and create a `Preprocessor`
82 | >>> param_dict = dict(
83 | ... ensemble=3,
84 | ... timesteps=50
85 | ... )
86 |
87 | >>> # preprocessor set up the jobs
88 | >>> pp = pyDeltaRCM.Preprocessor(
89 | ... param_dict)
90 |
91 | >>> # run the jobs with custom class!
92 | >>> pp.run_jobs(DeltaModel=CustomRandomModel)
93 |
94 | .. plot::
95 | :context:
96 | :include-source:
97 |
98 | >>> fig, ax = plt.subplots(
99 | ... 1, len(pp.job_list),
100 | ... figsize=(12, 4.8))
101 | >>> for i in range(len(pp.job_list)):
102 | ... ax[i].imshow(pp.job_list[i].deltamodel.eta)
103 | >>> plt.tight_layout()
104 | >>> plt.show()
105 |
--------------------------------------------------------------------------------
/docs/source/examples/custom_saving.rst:
--------------------------------------------------------------------------------
1 | Saving custom fields to the output file
2 | =======================================
3 |
4 | Given the flexibility of the pyDeltaRCM model to modifications via hooks and subclassing, it is necessary that the variables saved to the output netCDF file are similarly customizable.
5 | Fortunately, the use of subclasses and hooks itself enables flexible setting of gridded variables to be saved as figures, as well as customization of the fields saved to the netCDF file as both variables, and as metadata.
6 |
7 | To customize the figures and variables that are saved, the hook ``hook_init_output_file`` should be used to subclass the pyDeltaRCM model.
8 |
9 | When adding a model attribute to the key-value pairs of grids to save as figures, the key indicates the name of the figure file that will be saved, and the value-pair can be a string representing the model attribute to be plotted, or a combination of model attributes, such as ``self.eta * self.depth``.
10 | For example, ``self._save_fig_list['active_layer'] = ['active_layer']`` will properly indicate that figures of the active layer should be saved.
11 |
12 | .. important::
13 |
14 | The built-in, on-the-fly, figure saving as the model runs is only supported for gridded variables with the shape ``L x W`` matching the model domain.
15 | Trying to set up figures to save that are not variables of that shape will result in an error.
16 |
17 | When adding variables or metadata to be initialized and subsequently saved in the output netCDF, the key-value pair relationship is as follows.
18 | The key added to ``self._save_var_list`` is the name of the variable as it will be recorded in the netCDF file, this *does not* have to correspond to the name of an attribute in the model.
19 | To add a variable to the metadata, a key must be added to ``self._save_var_list['meta']``.
20 | The expected value for a given key is a list containing strings indicating the model attribute to be saved, its units, the variable type, and lastly the variable dimensions (e.g., ``['active_layer', 'fraction', 'f4', ('time', 'x', 'y')]`` for the active layer).
21 |
22 | .. important::
23 |
24 | The dimensions of the custom variable being specified must match *exactly* with one of the three standard dimensions: `x`, `y`, `time`.
25 | Use of an invalid dimension will result in an error.
26 |
27 | An example of using the hook and creating a model subclass to customize the figures, gridded variables, and metadata being saved is provided below.
28 |
29 | .. doctest::
30 |
31 | >>> import pyDeltaRCM
32 |
33 | >>> class CustomSaveModel(pyDeltaRCM.DeltaModel):
34 | ... """A subclass of DeltaModel to save custom figures and variables.
35 | ...
36 | ... This subclass modifies the list of variables and figures used to
37 | ... initialize the netCDF file and save figures and grids before the
38 | ... output file is setup and initial conditions are plotted.
39 | ... """
40 | ... def __init__(self, input_file=None, **kwargs):
41 | ...
42 | ... # inherit base DeltaModel methods
43 | ... super().__init__(input_file, **kwargs)
44 | ...
45 | ... def hook_init_output_file(self):
46 | ... """Add non-standard grids, figures and metadata to be saved."""
47 | ... # save a figure of the active layer each save_dt
48 | ... self._save_fig_list['active_layer'] = ['active_layer']
49 | ...
50 | ... # save the active layer grid each save_dt w/ a short name
51 | ... self._save_var_list['actlay'] = ['active_layer', 'fraction',
52 | ... 'f4', ('time',
53 | ... 'x', 'y')]
54 | ...
55 | ... # save number of water parcels w/ a long name
56 | ... self._save_var_list['meta']['water_parcels'] = ['Np_water',
57 | ... 'parcels',
58 | ... 'i8', ()]
59 |
60 | Next, we instantiate the model class.
61 |
62 | .. code::
63 |
64 | >>> mdl = CustomSaveModel()
65 |
66 |
67 | .. doctest::
68 | :hide:
69 |
70 | >>> with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
71 | ... mdl = CustomSaveModel(out_dir=output_dir)
72 |
73 |
74 | This subclass has added the active layer as a figure and a grid to be saved, as well as the number of water parcels as metadata to be saved.
75 | For simplicity we will just check that the appropriate parameters were added to the save figure and save variable lists, however please feel free to give this example a try on your local machine and examine the output figures and netCDF file.
76 |
77 | .. doctest::
78 |
79 | >>> 'active_layer' in mdl._save_fig_list
80 | True
81 |
82 | >>> print(mdl._save_fig_list)
83 | {'active_layer': ['active_layer']}
84 |
85 | >>> print(mdl._save_var_list)
86 | {'meta': {'water_parcels': ['Np_water', 'parcels', 'i8', ()]}, 'actlay': ['active_layer', 'fraction', 'f4', ('time', 'x', 'y')]}
87 |
--------------------------------------------------------------------------------
/docs/source/examples/custom_yaml.rst:
--------------------------------------------------------------------------------
1 | Defining custom YAML parameters
2 | ===============================
3 |
4 | .. currentmodule:: pyDeltaRCM.hook_tools
5 |
6 | Custom subclasses for the standard ``DeltaModel`` may require additional or custom parameters not listed in the :doc:`/reference/model/yaml_defaults`.
7 | By using the hook, :obj:`~hook_tools.hook_import_files`, it is straightforward to define custom YAML parameters along with expected types and default values for your subclassed model.
8 |
9 | The following subclass model demonstrates this by defining a custom boolean parameter (could be used to toggle some custom functionality on/off), and a custom numeric parameter (could be required for the custom function).
10 |
11 | .. doctest::
12 |
13 | >>> import pyDeltaRCM
14 |
15 | >>> class CustomParamsModel(pyDeltaRCM.DeltaModel):
16 | ... """A subclass of DeltaModel with custom YAML parameters.
17 | ...
18 | ... This subclass defines custom YAML parameters, their expected types
19 | ... and default values.
20 | ... """
21 | ... def __init__(self, input_file=None, **kwargs):
22 | ...
23 | ... # inherit base DeltaModel methods
24 | ... super().__init__(input_file, **kwargs)
25 | ...
26 | ... def hook_import_files(self):
27 | ... """Define the custom YAML parameters."""
28 | ... # custom boolean parameter
29 | ... self.subclass_parameters['custom_bool'] = {
30 | ... 'type': 'bool', 'default': False
31 | ... }
32 | ...
33 | ... # custom numeric parameter
34 | ... self.subclass_parameters['custom_number'] = {
35 | ... 'type': ['int', 'float'], 'default': 0
36 | ... }
37 |
38 | If the subclass model is loaded with a YAML configuration file that does not explicitly define these custom parameters, then the default values will be assigned as model attributes.
39 |
40 | .. code::
41 |
42 | >>> defaults = CustomParamsModel()
43 |
44 | .. doctest::
45 | :hide:
46 |
47 | >>> with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
48 | ... defaults = CustomParamsModel(out_dir=output_dir)
49 |
50 | .. doctest::
51 |
52 | >>> print(defaults.custom_bool)
53 | False
54 |
55 | >>> print(defaults.custom_number)
56 | 0
57 |
58 | .. note::
59 |
60 | Since custom YAML parameters have expected types, ``TypeErrors`` are raised if the custom parameter type provided in the YAML does not agree with what is expected as defined in the subclass.
61 |
62 |
63 | Once the custom parameters have been defined in the subclassed model they can be treated just like the default model parameters, and can be specified in the YAML or as keyword arguments (``**kwargs``).
64 |
65 | .. code::
66 |
67 | >>> customized = CustomParamsModel(custom_bool=True, custom_number=15.3)
68 |
69 |
70 | .. doctest::
71 | :hide:
72 |
73 | >>> with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
74 | ... customized = CustomParamsModel(out_dir=output_dir,
75 | ... custom_bool=True,
76 | ... custom_number=15.3)
77 |
78 | .. doctest::
79 |
80 | >>> print(customized.custom_bool)
81 | True
82 |
83 | >>> print(customized.custom_number)
84 | 15.3
85 |
--------------------------------------------------------------------------------
/docs/source/examples/index.rst:
--------------------------------------------------------------------------------
1 | =============================================
2 | Examples of using and working with pyDeltaRCM
3 | =============================================
4 |
5 | Running the model
6 | -----------------
7 |
8 | .. toctree::
9 | :maxdepth: 1
10 |
11 | basic_runs
12 | resume_from_checkpoint
13 |
14 |
15 | Modifying initial conditions
16 | ----------------------------
17 |
18 | .. toctree::
19 | :maxdepth: 1
20 |
21 | slight_slope
22 |
23 |
24 | Modifying boundary conditions
25 | -----------------------------
26 |
27 | .. toctree::
28 | :maxdepth: 1
29 |
30 | updating_boundary_conditions
31 | subsidence_region
32 | variable_bedload
33 | variable_velocity
34 |
35 |
36 | Modifying internal computations
37 | -------------------------------
38 |
39 | .. toctree::
40 | :maxdepth: 1
41 |
42 | overwrite_topo_diffusion
43 |
44 |
45 | Modifying Model Input/Output
46 | ----------------------------
47 |
48 | .. toctree::
49 | :maxdepth: 1
50 |
51 | custom_yaml
52 | custom_saving
53 |
54 |
55 | Working with the Preprocessor
56 | -----------------------------
57 |
58 | .. toctree::
59 | :maxdepth: 1
60 |
61 | custom_class_preprocessor
62 |
--------------------------------------------------------------------------------
/docs/source/examples/modelzoo.rst:
--------------------------------------------------------------------------------
1 | Customized Applications of *pyDeltaRCM*
2 | =======================================
3 |
4 | Below is a "model zoo" containing a list with links to customized subclasses
5 | of the *pyDeltaRCM* found "in the wild". If you have a implemented a custom
6 | subclass of the model and would like us to highlight it here please reach out
7 | or open a pull request!
8 |
9 | VegetationModel
10 | ---------------
11 | Link: `VegetationModel `_
12 |
13 | This implementation of the *pyDeltaRCM* model is based off of the "DeltaRCM
14 | Vegetation" model presented in `Lauzon and Murray (2018) `_.
15 |
16 | MississippiFaultsModel
17 | ----------------------
18 | Link: `MississippiFaultsModel `_
19 |
20 | This implementation of the *pyDeltaRCM* model is used in the paper
21 | `Moodie and Passalacqua (2021) `_ to
22 | simulate a Mississippi River-like delta.
23 |
24 | SelengaModel
25 | ------------
26 | Link: `SelengaModel `_
27 |
28 | This implementation of the *pyDeltaRCM* model is used in the paper
29 | `Moodie and Passalacqua (2021) `_ to
30 | simulate a Selenga River-like delta.
31 |
32 | VariableSLRModel
33 | ----------------
34 | Link: `VariableSLRModel `_
35 |
36 | This implementation of the *pyDeltaRCM* model is used in the paper
37 | `Hariharan et al (2022) `_ to simulate
38 | variable sea level rise scenarios.
--------------------------------------------------------------------------------
/docs/source/examples/overwrite_topo_diffusion.rst:
--------------------------------------------------------------------------------
1 | Changing topographic diffusion to represent tree throw
2 | ======================================================
3 |
4 | Here, we demonstrate how to overwrite an existing method of the `DeltaModel` to achieve custom behavior during model runtime.
5 |
6 | .. note::
7 |
8 | This example demonstrates several best-practices, including using yaml parameters specifications, custom figure and grid saving setup, and using :obj:`~pyDeltaRCM.shared_tools.get_random_uniform` for random number generation.
9 |
10 | In implementing custom model subclasses, it is common to want to change runtime behavior of the model.
11 | This can often be achieved by using hooks alone, but sometimes a combination of hooks and overwriting existing methods is necessary.
12 |
13 | In this example, we calculate a diffusion multiplier to represent tree throw.
14 | In this super simple and **likely way over-exaggerated** representation of this process, we assume:
15 |
16 | * there are trees everywhere the elevation of a cell has been above `self.dry_depth` for 10 consecutive timesteps
17 | * there is a probability threshold of tree throw occurring anywhere trees exist
18 | * tree throw makes the diffusion multiplier for that cell on that timestep really big!
19 |
20 | .. important::
21 |
22 | There are all kinds of problems with the assumptions in this example. Don't read into it too much. It's an example to show how to modify code, not how to represent tree throw.
23 |
24 | .. plot::
25 | :context: reset
26 | :include-source:
27 |
28 | class TreeThrowModel(pyDeltaRCM.DeltaModel):
29 | """Implementation of tree throw.
30 | """
31 |
32 | def __init__(self, input_file=None, **kwargs):
33 |
34 | # inherit from base model
35 | super().__init__(input_file, **kwargs)
36 | self.hook_after_create_domain()
37 |
38 | def hook_import_files(self):
39 | """Define the custom YAML parameters."""
40 | # whether to run vegetation
41 | self.subclass_parameters['tree_throw'] = {
42 | 'type': 'bool', 'default': False
43 | }
44 |
45 | # tree throw multiplier
46 | self.subclass_parameters['p_tt_mult'] = {
47 | 'type': ['int', 'float'], 'default': 100
48 | }
49 |
50 | # tree throw establish timesteps
51 | self.subclass_parameters['p_tt_iter'] = {
52 | 'type': ['int', 'float'], 'default': 10
53 | }
54 |
55 | # tree throw prob threshold
56 | self.subclass_parameters['p_tt_prob'] = {
57 | 'type': ['int', 'float'], 'default': 0.2
58 | }
59 |
60 | def hook_init_output_file(self):
61 | """Add non-standard grids, figures and metadata to be saved."""
62 | # save a figure of the active layer each save_dt
63 | self._save_fig_list['tree'] = ['tree']
64 |
65 | # save the active layer grid each save_dt w/ a short name
66 | self._save_var_list['tree'] = ['tree', 'boolean',
67 | 'i4', ('time',
68 | 'x', 'y')]
69 |
70 | def hook_after_create_domain(self):
71 | """Add fields to the model for all tree parameterizations.
72 | """
73 | self.tree = np.zeros(self.depth.shape, dtype=np.int64)
74 | self.dry_count = np.zeros(self.depth.shape, dtype=np.int64)
75 |
76 | self.tree_multiplier = np.ones_like(self.depth)
77 |
78 | def hook_after_route_sediment(self):
79 | """Apply vegetation growth/death rules.
80 | """
81 | # determine cells dry and increment counter
82 | _where_dry = (self.depth < self.dry_depth)
83 | self.dry_count[~_where_dry] = 0 # any wet gets reset
84 | self.dry_count[_where_dry] += 1 # any dry gets incremented
85 |
86 | # if tree_throw is on, run the tree placing routine
87 | if self.tree_throw:
88 |
89 | # trees die anywhere wet
90 | self.tree[~_where_dry] = int(0)
91 |
92 | # trees go anywhere dry for more than threshold
93 | _where_above_thresh = (self.dry_count >= self.p_tt_iter)
94 |
95 | self.tree[_where_above_thresh] = int(1)
96 |
97 | # determine the multiplier field
98 | _rand = np.array([get_random_uniform(1) for i in np.arange(self.depth.size)]).reshape(self.depth.shape)
99 | _thrown = np.logical_and((_rand < self.p_tt_prob), self.tree)
100 |
101 | # ignore the strip of land
102 | _thrown[self.cell_type == -2] = 0
103 |
104 | # set to ones everywhere, then overwrite with multiplier
105 | self.tree_multiplier[:] = 1
106 | self.tree_multiplier[_thrown] = self.p_tt_mult
107 |
108 | def topo_diffusion(self):
109 | """Overwrite with new behavior.
110 |
111 | This method is very similar to the base DeltaModel code, but we add an
112 | additional multiplier to represent tree throw.
113 | """
114 | for _ in range(self.N_crossdiff):
115 |
116 | a = ndimage.convolve(self.eta, self.kernel1, mode='constant')
117 | b = ndimage.convolve(self.qs, self.kernel2, mode='constant')
118 | c = ndimage.convolve(self.qs * self.eta, self.kernel2,
119 | mode='constant')
120 |
121 | self.cf = (self.tree_multiplier * self.diffusion_multiplier *
122 | (self.qs * a - self.eta * b + c))
123 |
124 | self.cf[self.cell_type == -2] = 0
125 | self.cf[0, :] = 0
126 |
127 | self.eta += self.cf
128 |
129 | And the model is then instantiated with:
130 |
131 | .. plot::
132 | :context:
133 |
134 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
135 | mdl = TreeThrowModel(
136 | out_dir=output_dir,
137 | tree_throw=True)
138 |
139 | .. code:: python
140 |
141 | mdl = TreeThrowModel(
142 | tree_throw=True)
143 |
144 | We don't actually run this model at all in this example.
145 | Let's plot the ``.tree`` field just to see that the subclass was instantiated correctly.
146 |
147 | .. plot::
148 | :context:
149 | :include-source:
150 |
151 | fig, ax = plt.subplots()
152 | im = ax.imshow(mdl.tree)
153 | plt.colorbar(im, ax=ax, shrink=0.5)
154 | plt.show()
155 |
--------------------------------------------------------------------------------
/docs/source/examples/simple_example.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "70c593eb-e479-4b4c-ad52-2d578bfad177",
6 | "metadata": {
7 | "tags": []
8 | },
9 | "source": [
10 | "# Simple model run example\n",
11 | "\n",
12 | "This Jupyter Notebook shows how to configure and run a model simulation, and how to examine the model outputs.\n",
13 | "\n",
14 | "This document supplements the [10-minute tutorial](https://deltarcm.org/pyDeltaRCM/guides/10min.html) and [User Guide](https://deltarcm.org/pyDeltaRCM/guides/user_guide.html), but is not a complete guide to the model."
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "id": "ac5919f8-0779-4ac1-b728-bb6c1361ef82",
21 | "metadata": {},
22 | "outputs": [],
23 | "source": [
24 | "import pyDeltaRCM"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "d2d7db35-4f4b-4111-8269-e40478378ac8",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "import os\n",
35 | "import numpy as np\n",
36 | "import netCDF4\n",
37 | "import matplotlib.pyplot as plt"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "id": "7121c3ca-4c8b-4d5e-9642-b76b35f68a72",
43 | "metadata": {},
44 | "source": [
45 | "First, we will configure a YAML file to input to the model."
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "id": "169fd14b-3d16-4569-a91f-0523dbbad30d",
52 | "metadata": {},
53 | "outputs": [],
54 | "source": [
55 | "%%writefile eg_config.yaml\n",
56 | "\n",
57 | "f_bedload: 0.25\n",
58 | "h0: 2\n",
59 | "u0: 1.1\n",
60 | "save_eta_figs: True\n",
61 | "save_eta_grids: True\n",
62 | "save_velocity_grids: True\n",
63 | "save_dt: 250000"
64 | ]
65 | },
66 | {
67 | "cell_type": "markdown",
68 | "id": "46e6dd75-bd65-4dc3-81a1-29369eb87c6f",
69 | "metadata": {},
70 | "source": [
71 | "In the following cell, we instantiate the model with the yaml file we just created, run the model for 1000 steps, and finalize.\n",
72 | "\n",
73 | "**WARNING** executing the run will likely take 30-40 minutes."
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "id": "a87a3c1d-60bf-4916-b531-1ded37d89050",
80 | "metadata": {},
81 | "outputs": [],
82 | "source": [
83 | "mdl = pyDeltaRCM.DeltaModel('eg_config.yaml')\n",
84 | "\n",
85 | "for _ in range(0, 1000):\n",
86 | " mdl.update()\n",
87 | "\n",
88 | "mdl.finalize()"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "id": "57bb6af2-d7a4-4f0a-88b1-d6f29594aa02",
94 | "metadata": {},
95 | "source": [
96 | "With the model completed, we can see the final state:"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "id": "a86fd13d-ffb7-4c31-85c7-be3bd4533001",
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "fig, ax = plt.subplots()\n",
107 | "ax.imshow(mdl.eta, cmap='cividis')\n",
108 | "plt.show()"
109 | ]
110 | },
111 | {
112 | "cell_type": "markdown",
113 | "id": "a2488676-78da-4387-b933-4a237da2ca9f",
114 | "metadata": {},
115 | "source": [
116 | "We can also access the history of the run in the output NetCDF4 file."
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": null,
122 | "id": "7e02e59a-f615-4f58-b100-208d466f2df8",
123 | "metadata": {},
124 | "outputs": [],
125 | "source": [
126 | "data = netCDF4.Dataset(os.path.join('deltaRCM_Output', 'pyDeltaRCM_output.nc')) # this is the default location for the output file"
127 | ]
128 | },
129 | {
130 | "cell_type": "code",
131 | "execution_count": null,
132 | "id": "32b652fa-6158-412d-a4e8-d0fcdc41c31f",
133 | "metadata": {},
134 | "outputs": [],
135 | "source": [
136 | "nt = 3\n",
137 | "ts = np.linspace(0, data['eta'].shape[0]-1,\n",
138 | " num=nt, dtype=int) # linearly interpolate ts\n",
139 | "\n",
140 | "# make the timeseries plot\n",
141 | "fig, ax = plt.subplots(1, nt, figsize=(11, 2), dpi=300)\n",
142 | "for i, t in enumerate(ts):\n",
143 | " ax[i].imshow(data['eta'][t, :, :], cmap='cividis')\n",
144 | " ax[i].axes.get_xaxis().set_ticks([])\n",
145 | " ax[i].axes.get_yaxis().set_ticks([])\n",
146 | "\n",
147 | "plt.tight_layout()\n",
148 | "plt.show()"
149 | ]
150 | }
151 | ],
152 | "metadata": {
153 | "kernelspec": {
154 | "display_name": "Python 3 (ipykernel)",
155 | "language": "python",
156 | "name": "python3"
157 | },
158 | "language_info": {
159 | "codemirror_mode": {
160 | "name": "ipython",
161 | "version": 3
162 | },
163 | "file_extension": ".py",
164 | "mimetype": "text/x-python",
165 | "name": "python",
166 | "nbconvert_exporter": "python",
167 | "pygments_lexer": "ipython3",
168 | "version": "3.9.5"
169 | }
170 | },
171 | "nbformat": 4,
172 | "nbformat_minor": 5
173 | }
174 |
--------------------------------------------------------------------------------
/docs/source/examples/slight_slope.rst:
--------------------------------------------------------------------------------
1 | Slightly sloping basin
2 | ======================
3 |
4 | Consider the case where we are a researcher seeking to explore the effects of a receiving basin that is sloped perpendicular to the channel outlet.
5 | This researcher asks: does this sloped basin cause channels to steer towards the deeper water, where compensation is higher?
6 |
7 | The researcher can easily use subclassing and model hooks to achieve the desired effect.
8 | Recall that anything added to the end of the the subclass' `__init__` method will be called during instantiation of the subclass.
9 |
10 | .. plot::
11 | :context: reset
12 | :include-source:
13 |
14 | class SlightSlopeModel(pyDeltaRCM.DeltaModel):
15 | """A subclass of DeltaModel with sloping basin.
16 |
17 | This subclass simply modifies the basin geometry
18 | before any computation has occurred.
19 | """
20 | def __init__(self, input_file=None, **kwargs):
21 |
22 | # inherit base DeltaModel methods
23 | super().__init__(input_file, **kwargs)
24 |
25 | # modify the basin
26 | slope = 0.0005 # cross basin slope
27 | eta_line = slope * np.arange(0, self.Width,
28 | step=self.dx)
29 | eta_grid = np.tile(eta_line, (self.L - self.L0, 1))
30 | eta_grid = eta_grid - ((slope * self.Width)/2) # center at inlet
31 | self.eta[self.L0:, :] += eta_grid
32 |
33 | Next, we instantiate the model class.
34 |
35 | .. code::
36 |
37 | mdl = SlightSlopeModel()
38 |
39 |
40 | .. plot::
41 | :context:
42 |
43 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
44 | mdl = SlightSlopeModel(out_dir=output_dir)
45 |
46 |
47 | And finally, make a plot of the initial condition using the :obj:`~pyDeltaRCM.debug_tools.debug_tools.show_attribute` method.
48 |
49 | .. plot::
50 | :context:
51 | :include-source:
52 |
53 | fig, ax = plt.subplots()
54 | mdl.show_attribute('eta', grid=False)
55 | plt.show()
56 |
57 | You can try this out for yourself, and even complete the model run.
58 | Are the channels steered by the basin slope?
59 |
60 | .. important::
61 |
62 | In this example, we did not take care to update the model `stage` or `depth` fields. In this simple case it works out fine, because after a single timestep, the fields are correctly computed relative to the modified bed. However, take caution when modifying `DeltaModel` fields directly, and be sure to change *all* relevant fields too.
63 |
--------------------------------------------------------------------------------
/docs/source/examples/subsidence_region.rst:
--------------------------------------------------------------------------------
1 | Constraining subsidence to part of the domain
2 | =============================================
3 |
4 | One case that has been explored in the literature with the DeltaRCM model is the case of subsidence limited to one region of the model domain [1]_.
5 | This model configuration can be readily achieved with model subclassing.
6 |
7 | Setting up the custom subclass
8 | ------------------------------
9 |
10 | .. plot::
11 | :context: reset
12 | :include-source:
13 |
14 | class ConstrainedSubsidenceModel(pyDeltaRCM.DeltaModel):
15 | """A simple subclass of DeltaModel with subsidence region constrained.
16 |
17 | This subclass *overwrites* the `init_subsidence` method to
18 | constrain subsidence to only one region of the model domain.
19 | """
20 | def __init__(self, input_file=None, **kwargs):
21 |
22 | # inherit base DeltaModel methods
23 | super().__init__(input_file, **kwargs)
24 |
25 | def init_subsidence(self):
26 | """Initialize subsidence pattern constrained to a tighter region.
27 |
28 | Uses theta1 and theta2 to set the angular bounds for the
29 | subsiding region. theta1 and theta2 are set in relation to the
30 | inlet orientation. The inlet channel is at an angle of 0, if
31 | theta1 is -pi/3 radians, this means that the angle to the left of
32 | the inlet that will be included in the subsiding region is 30
33 | degrees. theta2 defines the right angular bounds for the subsiding
34 | region in a similar fashion.
35 | """
36 | _msg = 'Initializing custom subsidence field'
37 | self.log_info(_msg, verbosity=1)
38 |
39 | if self._toggle_subsidence:
40 |
41 | theta1 = -(np.pi / 3)
42 | theta2 = 0
43 |
44 | R1 = 0.3 * self.L # radial limits (fractions of L)
45 | R2 = 0.8 * self.L
46 |
47 | Rloc = np.sqrt((self.y - self.L0)**2 + (self.x - self.W / 2.)**2)
48 |
49 | thetaloc = np.zeros((self.L, self.W))
50 | thetaloc[self.y > self.L0 - 1] = np.arctan(
51 | (self.x[self.y > self.L0 - 1] - self.W / 2.)
52 | / (self.y[self.y > self.L0 - 1] - self.L0 + 1))
53 | self.subsidence_mask = ((R1 <= Rloc) & (Rloc <= R2) &
54 | (theta1 <= thetaloc) &
55 | (thetaloc <= theta2))
56 | self.subsidence_mask[:self.L0, :] = False
57 |
58 | self.sigma = self.subsidence_mask * self.subsidence_rate * self.dt
59 |
60 |
61 | Now, initialize the model and look at the field.
62 | Note that the colorscale depicts the magnitude of subsidence in the model *per timestep* (`sigma`, which has units meters).
63 |
64 | .. code:: python
65 |
66 | mdl = ConstrainedSubsidenceModel(toggle_subsidence=True)
67 |
68 | .. plot::
69 | :context:
70 |
71 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
72 | mdl = ConstrainedSubsidenceModel(toggle_subsidence=True,
73 | out_dir=output_dir)
74 |
75 | .. plot::
76 | :context:
77 | :include-source:
78 |
79 | fig, ax = plt.subplots()
80 | mdl.show_attribute('sigma', grid=False)
81 | plt.show()
82 |
83 |
84 | Using the custom subclass with the preprocessor
85 | -----------------------------------------------
86 |
87 | We can configure a :obj:`Preprocessor` to handle a set of custom runs in conjunction with out custom `pyDeltaRCM` model subclass.
88 | For example, in [1]_, the authors explore the impact of subsidence at various rates: 3 mm/yr, 6 mm/yr, 10 mm/yr, 25 mm/yr, 50 mm/yr, and 100 mm/yr.
89 | We can scale these rates, assuming a model :doc:`intermittency factor ` of 0.019, representing 7 of 365 days of flooding per year, by using the convenience function :obj:`~pyDeltaRCM.preprocessor.scale_relative_sea_level_rise_rate`:
90 |
91 | .. plot::
92 | :context: close-figs
93 | :include-source:
94 |
95 | from pyDeltaRCM.preprocessor import scale_relative_sea_level_rise_rate
96 |
97 | subsidence_mmyr = np.array([3, 6, 10, 25, 50, 100])
98 | subsidence_scaled = scale_relative_sea_level_rise_rate(subsidence_mmyr, If=0.019)
99 |
100 | Now, we use :ref:`matrix expansion ` to set up the runs with a preprocessor.
101 | For example, in a Python script, following the definition of the subclass above, define a dictionary with a `matrix` key and supply to the `Preprocessor`:
102 |
103 | .. plot::
104 | :context:
105 | :include-source:
106 |
107 | # add a matrix with subsidence to the dict
108 | param_dict = {}
109 | param_dict['matrix'] = {'subsidence_rate': subsidence_scaled}
110 |
111 | # add other configurations
112 | param_dict.update(
113 | {'out_dir': 'liang_2016_reproduce',
114 | 'toggle_subsidence': True,
115 | 'parallel': 3}) # we can take advantage of parallel jobs
116 |
117 | .. code::
118 |
119 | # create the preprocessor
120 | pp = pyDeltaRCM.Preprocessor(
121 | param_dict,
122 | timesteps=10000)
123 |
124 | And finally run the jobs by specifying the model subclass as the class to use when instantiating the jobs with the preprocessor.
125 |
126 | .. below, we overwrite the above, to make sure we only run for one timestep
127 | .. plot::
128 | :context:
129 |
130 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
131 | param_dict['out_dir'] = output_dir
132 | pp = pyDeltaRCM.Preprocessor(
133 | param_dict,
134 | parallel=False,
135 | timesteps=1)
136 | pp.run_jobs(DeltaModel=ConstrainedSubsidenceModel)
137 |
138 | .. code:: python
139 |
140 | # run the jobs
141 | pp.run_jobs(DeltaModel=ConstrainedSubsidenceModel)
142 |
143 | We can check whether the runs were set up, as expected:
144 |
145 | .. plot::
146 | :context:
147 | :include-source:
148 |
149 | from matplotlib.colors import Normalize
150 |
151 | fig, ax = plt.subplots(2, 3, sharex=True, sharey=True, figsize=(10, 4))
152 | norm = Normalize(vmin=3, vmax=100)
153 |
154 | for i, job in enumerate(pp.job_list):
155 | # first convert the field to a rate
156 | subsidence_rate_field = (job.deltamodel.sigma / job.deltamodel.dt)
157 |
158 | # now convert to mm/yr
159 | subsidence_rate_field = (subsidence_rate_field * 1000 *
160 | pyDeltaRCM.shared_tools._scale_factor(If=0.019, units='years'))
161 |
162 | # and display
163 | im = ax.flat[i].imshow(subsidence_rate_field, norm=norm)
164 |
165 | fig.colorbar(im, ax=ax.ravel().tolist())
166 | plt.show()
167 |
168 |
169 | .. [1] Liang, M., Kim, W., and Passalacqua, P. (2016), How much subsidence is
170 | enough to change the morphology of river deltas?, Geophysical Research Letters, 43, 10,266--10,276, doi:10.1002/2016GL070519.
171 |
--------------------------------------------------------------------------------
/docs/source/examples/updating_boundary_conditions.rst:
--------------------------------------------------------------------------------
1 | Updating model boundary conditions
2 | ==================================
3 |
4 | In implementing custom model subclasses, it is common to want to change boundary conditions throughout the model run (see :doc:`variable_bedload`, :doc:`variable_velocity`).
5 | In some situations, we want to change a single variable, and see the effect of changing *only this variable*, in essence, pushing the model out of a dynamic equilibrium.
6 | Another possibility is that we would want to change the boundary conditions of the inlet, *but maintain the dynamic equilibrium*.
7 |
8 | Let's create a `DeltaModel` class to demonstrate.
9 |
10 | .. code::
11 |
12 | mdl = DeltaModel()
13 |
14 |
15 | .. doctest::
16 | :hide:
17 |
18 | >>> with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
19 | ... mdl = pyDeltaRCM.DeltaModel(out_dir=output_dir)
20 |
21 | Now, we can see that by the default settings, after initialization, the model flow velocity is 1.0 m/s, flow depth is 5 m, and so the unit water discharge is 5 m2/s.
22 |
23 | .. doctest::
24 |
25 | >>> mdl.u0
26 | 1.0
27 | >>> mdl.h0
28 | 5.0
29 | >>> mdl.qw0
30 | 5.0
31 |
32 | If after some number of model iterations, we wanted to change the inlet flow velocity to be 2.0 m/s, we could simply set this value directly.
33 |
34 | .. doctest::
35 |
36 | >>> mdl.u0 = 2.0
37 |
38 | But, now the model has been thrown out of equilibrium, where the unit water discharge no longer matches the product of the flow depth and flow velocity.
39 |
40 | .. doctest::
41 |
42 | >>> mdl.u0
43 | 2.0
44 | >>> mdl.h0
45 | 5.0
46 | >>> mdl.qw0
47 | 5.0
48 |
49 | To remedy this, we need to use the :obj:`~pyDeltaRCM.init_tools.init_tools.create_boundary_conditions` method, which will reinitialize a number of fields, based on the current value of the inlet flow velocity.
50 |
51 | .. doctest::
52 |
53 | >>> mdl.create_boundary_conditions()
54 | >>> mdl.qw0
55 | 10.0
56 |
57 | .. important::
58 |
59 | You are responsible for ensuring that boundary conditions are updated in the appropriate manner after changing certain model parameters. **You need to call the method to reinitialize boundary conditions yourself!**
60 |
--------------------------------------------------------------------------------
/docs/source/examples/variable_bedload.rst:
--------------------------------------------------------------------------------
1 | Time-varying bedload
2 | ====================
3 |
4 | The following example demonstrates how to configure a subclassing model with a time-varying parameter.
5 | In this example, the time-varying behavior arises by managing two "switches", ``self._changed`` and ``self._changed_back``, which change the state of the :obj:`f_bedload` parameters at a predetermined time in the mode sequence.
6 |
7 | The following codes produce two runs (using `matrix` expansion from the Preprocessor), which has a baseline `f_bedload` value of either ``0.3`` or ``0.7``, and for a period in the middle of the run, the `f_bedload` values are mirrored by ``self.f_bedload = (1 - self.f_bedload)``, i.e., briefly switching the bedload values.
8 |
9 |
10 | .. plot::
11 | :context: reset
12 | :include-source:
13 |
14 | class VariableBedloadModel(pyDeltaRCM.DeltaModel):
15 |
16 | def __init__(self, input_file=None, **kwargs):
17 |
18 | super().__init__(input_file, **kwargs)
19 |
20 | self._changed = False
21 | self._changed_back = False
22 |
23 | def hook_solve_water_and_sediment_timestep(self):
24 | """Change the state depending on the _time.
25 | """
26 | # check if the state has been changed, and time to change it
27 | if (not self._changed) and (self._time > 459909090):
28 | self.f_bedload = (1 - self.f_bedload)
29 | self._changed = True
30 |
31 | _msg = 'Bedload changed to {f_bedload}'.format(
32 | f_bedload=self.f_bedload)
33 | self.log_info(_msg, verbosity=0)
34 |
35 | # check if the state has been changed back, and time to change it back
36 | if (not self._changed_back) and (self._time > 714545454):
37 | self.f_bedload = (1 - self.f_bedload)
38 | self._changed_back = True
39 |
40 | _msg = 'Bedload changed back to {f_bedload}'.format(
41 | f_bedload=self.f_bedload)
42 | self.log_info(_msg, verbosity=0)
43 |
44 |
45 | .. rubric:: Checking on the state-change effect
46 |
47 | To demonstrate how this works, let's loop through time and check the model state.
48 | Here, we will change the model time value directly, so that we can verify that the model is working as intended, but you should never do this in practice.
49 |
50 | .. plot::
51 | :context:
52 |
53 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
54 | mdl_muddy = VariableBedloadModel(f_bedload=0.3,
55 | out_dir=output_dir)
56 | mdl_sandy = VariableBedloadModel(f_bedload=0.7,
57 | out_dir=output_dir)
58 |
59 | .. code:: python
60 |
61 | mdl_muddy = VariableBedloadModel(f_bedload=0.3)
62 | mdl_sandy = VariableBedloadModel(f_bedload=0.7)
63 |
64 | .. important::
65 |
66 | You should never modify the model time via ``self._time`` directly when working with the model.
67 |
68 |
69 | .. plot::
70 | :context:
71 | :include-source:
72 |
73 | # create a figure
74 | fig, ax = plt.subplots()
75 |
76 | # set the "simulation" range
77 | _times = np.linspace(0, 1e9, num=100)
78 | fb_mdl_muddy = np.zeros_like(_times)
79 | fb_mdl_sandy = np.zeros_like(_times)
80 |
81 | # loop through time, change the model time and grab f_bedload values
82 | for i, _time in enumerate(_times):
83 | # change the model time directly
84 | mdl_muddy._time = _time # you should never do this
85 | mdl_sandy._time = _time # you should never do this
86 |
87 | # run the hooked method
88 | mdl_muddy.hook_solve_water_and_sediment_timestep()
89 | mdl_sandy.hook_solve_water_and_sediment_timestep()
90 |
91 | # grab the state of the `f_bedload` parameter
92 | fb_mdl_muddy[i] = mdl_muddy.f_bedload # get the value
93 | fb_mdl_sandy[i] = mdl_sandy.f_bedload # get the value
94 |
95 | # add it to the plot
96 | ax.plot(_times, fb_mdl_muddy, '-', c='saddlebrown', lw=2, label='muddy')
97 | ax.plot(_times, fb_mdl_sandy, '--', c='goldenrod', lw=2, label='sandy')
98 | ax.legend()
99 |
100 | # clean up
101 | ax.set_ylim(0, 1)
102 | ax.set_ylabel('f_bedload')
103 | ax.set_xlabel('model time (s)')
104 |
105 | plt.show()
106 |
107 |
108 | .. rubric:: Running the model for real
109 |
110 | Given a yaml file (``variable_bedload.yaml``):
111 |
112 | .. code:: yaml
113 |
114 | Length: 5000.
115 | Width: 10000.
116 | dx: 50
117 | N0_meters: 500
118 | C0_percent: 0.05
119 | SLR: 1.5e-8
120 | h0: 2
121 | u0: 1.1
122 | coeff_U_dep_mud: 0.5
123 | parallel: True
124 |
125 | matrix:
126 | f_bedload:
127 | - 0.3
128 | - 0.7
129 |
130 |
131 | and a script to run the code:
132 |
133 | .. code:: python
134 |
135 | if __name__ == '__main__':
136 |
137 | # base yaml configuration
138 | base_yaml = 'variable_bedload.yaml'
139 |
140 | pp = pyDeltaRCM.Preprocessor(
141 | base_yaml,
142 | timesteps=12000)
143 |
144 | # run the jobs
145 | pp.run_jobs(DeltaModel=VariableBedloadModel)
146 |
147 |
--------------------------------------------------------------------------------
/docs/source/examples/variable_velocity.rst:
--------------------------------------------------------------------------------
1 | Time-varying inlet velocity
2 | ===========================
3 |
4 | It is straightforward to create models with time-varying boundary conditions.
5 | In this example, we set up an array of values to use for the inlet flow velocity, depending on the time of the model (i.e., a timeseries).
6 |
7 | In implementation, because we don't know the timestep of the model before creating it, we interpolate the actual inlet flow velocity from the boundary condition timeseries.
8 |
9 |
10 | Define the boundary condition
11 | -----------------------------
12 |
13 | First, let's set up the boundary condition array we want to use.
14 | We'll set this up in a function, so that it can be called from the model subclass, as well as here for plotting.
15 |
16 | .. plot::
17 | :context: reset
18 | :include-source:
19 |
20 | def create_velocity_array(end_time, a=1, b=5e4, h=3.2, k=2):
21 | """Create velocity timeseries.
22 | """
23 | _time = np.linspace(0, end_time, num=1000)
24 |
25 | _velocity = a * np.sin((_time - h)/b) + k
26 | return _time, _velocity
27 |
28 | The function we define takes the `end_time` of the model run, as well as some shape parameters, and computes according to:
29 |
30 | .. math::
31 |
32 | y = a \sin \left( \frac{ \left( t - h \right) }{ b } \right) + k
33 |
34 | where :math:`t` is the time array in seconds.
35 | We can inspect the result of this function, as it will be called in the model subclass below.
36 |
37 | .. plot::
38 | :context:
39 | :include-source:
40 |
41 | end_time = 86400 * 100
42 | _time_array, _velocity_array = create_velocity_array(
43 | end_time)
44 |
45 | # make a plot of the boundary condition
46 | fig, ax = plt.subplots()
47 | ax.plot(_time_array, _velocity_array)
48 | ax.set_xlabel('time (seconds)')
49 | ax.set_ylabel('inlet velocity (meters/second)')
50 | plt.show()
51 |
52 |
53 | Define the model subclass
54 | -------------------------
55 |
56 | We define a model subclass to handle the changing boundary condition:
57 |
58 | .. plot::
59 | :context: close-figs
60 | :include-source:
61 |
62 | class ChangingVelocityModel(pyDeltaRCM.DeltaModel):
63 | """Model with changing flow velocity.
64 |
65 | Create a model that changes the inlet flow velocity throughout the run.
66 | In this example, the velocity is changed on each timestep, and the value
67 | it is set to is interpolated from a **predetermined timeseries** of
68 | velocities.
69 | """
70 | def __init__(self, input_file=None, end_time=86400, **kwargs):
71 |
72 | # inherit from the base model
73 | super().__init__(input_file, **kwargs)
74 |
75 | # set up the attributes for interpolation
76 | self._time_array, self._velocity_array = create_velocity_array(
77 | end_time) # use default shape parameters for the array
78 |
79 | def hook_solve_water_and_sediment_timestep(self):
80 | """Change the velocity."""
81 |
82 | # find the new velocity and set it to the model
83 | self.u0 = np.interp(self._time, self._time_array, self._velocity_array)
84 |
85 | # update other boundary conditions using u0
86 | self.create_boundary_conditions()
87 |
88 | # log the new value
89 | _msg = 'Changed velocity value to {u0}'.format(
90 | u0=self.u0)
91 | self.log_info(_msg, verbosity=0)
92 |
93 |
94 | and then simply run with:
95 |
96 | .. plot::
97 | :context:
98 |
99 | # we create the model here, just to be sure it works (for good docs)
100 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
101 | mdl = ChangingVelocityModel(
102 | end_time=86400*100,
103 | out_dir=output_dir)
104 |
105 | .. code::
106 |
107 | mdl = ChangingVelocityModel(end_time=end_time)
108 |
109 | while mdl.time < end_time:
110 | mdl.update()
111 |
112 |
113 | .. note::
114 |
115 | For information on updating boundary conditions after changing certain model parameters see :doc:`updating_boundary_conditions`.
116 |
--------------------------------------------------------------------------------
/docs/source/guides/10min.rst:
--------------------------------------------------------------------------------
1 | ******************
2 | 10-minute tutorial
3 | ******************
4 |
5 | Use pyDeltaRCM in ten minutes!
6 | This simple guide will show you the absolute basics of getting a `pyDeltaRCM` model running, and give you some direction on where to go from there.
7 |
8 | .. important::
9 |
10 | If you haven't already, be sure to follow the :doc:`installation guide ` to get *pyDeltaRCM* set up properly on your computer.
11 |
12 |
13 | A default model
14 | ---------------
15 |
16 | You can get a model running with five simple lines of Python code. Note that you can run *pyDeltaRCM* in either a standalone script or part of an interactive session.
17 | First, we instantiate the main :obj:`~pyDeltaRCM.DeltaModel` model object.
18 |
19 | .. code:: python
20 |
21 | >>> import pyDeltaRCM
22 |
23 | >>> default_delta = pyDeltaRCM.DeltaModel()
24 |
25 | Instantiating the :obj:`~pyDeltaRCM.model.DeltaModel()` without any arguments will use a set of :doc:`default parameters <../reference/model/yaml_defaults>` to configure the model run.
26 | The default options are a reasonable set for exploring some controls of the model, and would work perfectly well for a simple demonstration here.
27 |
28 | The delta model is run forward with a call to the :meth:`~pyDeltaRCM.DeltaModel.update()` method.
29 | So, we simply create a `for` loop, and call the `update` function, and then wrap everything up with a call to :meth:`~pyDeltaRCM.DeltaModel.finalize` the model:
30 |
31 | .. code:: python
32 |
33 | >>> for _ in range(0, 5):
34 | ... default_delta.update()
35 |
36 | >>> default_delta.finalize()
37 |
38 | .. note::
39 |
40 | Additional calls to update the model can be called up until the model is finalized.
41 |
42 | That's it! You ran the pyDeltaRCM model for five timesteps, with just five lines of code.
43 |
44 | We can visualize the delta bed elevation, though it's not very exciting after only five timesteps...
45 |
46 | .. code:: python
47 |
48 | >>> import matplotlib.pyplot as plt
49 |
50 | >>> fig, ax = plt.subplots()
51 | >>> ax.imshow(default_delta.bed_elevation, vmax=-3)
52 | >>> plt.show()
53 |
54 | .. plot:: guides/10min_demo.py
55 |
56 |
57 | The model with set parameters
58 | -----------------------------
59 |
60 | To run a simulation with a non-default set of parameters, we use a configuration file written in the YAML markup language named `10min_tutorial.yaml`.
61 | The markup file allows us to specify model boundary conditions and input and output settings, where anything set in the file will override the :doc:`default parameters <../reference/model/yaml_defaults>` for the model, and anything *not* specified will take the default value.
62 |
63 | .. important::
64 |
65 | The best practice for model configurations is to create a YAML file with only the settings you want to change specified.
66 |
67 | The YAML configuration file is central to managing *pyDeltaRCM* simulations, so we did not create this file for you; you will need to create the YAML file yourself.
68 | To create the YAML file, open up your favorite plain-text editing application (e.g., gedit, notepad).
69 | YAML syntax is pretty simple for basic configurations, essentially amounting to each line representing a parameter-value pair, separated by a colon.
70 | For this example, let's specify three simulation controls: where we want the output file to be placed via the `out_dir` parameter, we will ensure that our simulation is easily reproducible by setting the random `seed` parameter, and we can examine what is the effect of a high fraction of bedload with the `f_bedload` parameter.
71 | Enter the following in your text editor, and save the file as ``10min_tutorial.yaml``, making sure to place the file in a location accessible to your interpreter.
72 |
73 | .. code:: yaml
74 |
75 | out_dir: '10min_tutorial'
76 | seed: 451220118313
77 | f_bedload: 0.9
78 |
79 |
80 | Now, we can create a second instance of the :obj:`~pyDeltaRCM.model.DeltaModel()`, this time using the input yaml file.
81 |
82 | .. code::
83 |
84 | >>> second_delta = pyDeltaRCM.DeltaModel(input_file='10min_tutorial.yaml')
85 |
86 | and repeat the same `for` loop operation as above:
87 |
88 | .. code:: python
89 |
90 | >>> for _ in range(0, 5):
91 | ... second_delta.update()
92 |
93 | >>> second_delta.finalize()
94 |
95 |
96 | Resources
97 | ---------
98 |
99 | Consider reading through the :doc:`User Guide ` as a first action, and determine how to set up the model to complete your experiment, including tutorials and examples for customizing the model to achieve any arbitrary behavior you need!
100 |
101 | * :doc:`user_guide`
102 | * :doc:`/reference/model/index`
103 |
--------------------------------------------------------------------------------
/docs/source/guides/getting_started.rst:
--------------------------------------------------------------------------------
1 | .. _getting_started:
2 |
3 | ===============
4 | Getting Started
5 | ===============
6 |
7 |
8 | It's easy to get started using *pyDeltaRCM*.
9 | We recommend starting out with the 10-minute learn-by-example lesson:
10 |
11 | .. toctree::
12 | :maxdepth: 3
13 |
14 | 10min
15 |
16 |
17 | Return to the main index :ref:`user_documentation` to see all the other documentation available to help you get started.
18 |
19 | Some other helpful resources:
20 |
21 | * An example `Jupyter Notebook `_ that shows a complete model runs and quick analysis of output file.
22 | * A comprehensive :doc:`user_guide` on how to use and experiment with the model
23 |
24 |
25 | And when you're ready to start developing, check out the :doc:`developer_guide` and the complete model :doc:`API documentation `.
26 |
--------------------------------------------------------------------------------
/docs/source/guides/subsidence_guide.inc:
--------------------------------------------------------------------------------
1 | =======================
2 | Working with subsidence
3 | =======================
4 |
5 | What is subsidence anyway? Subsidence is basically the downward vertical
6 | movement of the ground. There are many direct and indirect causes of subsidence,
7 | check out the `Wikipedia page `_
8 | to get an overview.
9 |
10 | Turning on Subsidence in pyDeltaRCM
11 | ===================================
12 |
13 | To configure a pyDeltaRCM model with subsidence, the yaml parameter,
14 | ``toggle_subsidence`` must be set to ``True``.
15 |
16 | Controlling Subsidence Behavior
17 | ===============================
18 |
19 | Two yaml parameters are provided to give users some basic control over
20 | subsidence behavior. The first is ``start_subsidence``, which defines *when*
21 | subsidence begins in the model run. This parameter is set in terms of seconds,
22 | and is set to begin on the step *following* the time step that brings the
23 | model to ``time >= start_subsidence``. The second subsidence parameter is the
24 | ``subsidence_rate`` yaml parameter. This parameter defines the rate at which
25 | the basin will subside in meters per second. The default subsiding region is
26 | the entire delta basin with the exception of the inlet cells and the land cells
27 | along boundary.
28 |
29 | If, for example we wanted the basin to begin to subside after 2000 seconds
30 | with a rate of 2e-10 m/s, we would write our yaml file with the following
31 | parameters:
32 |
33 | .. code:: yaml
34 |
35 | toggle_subsidence: True
36 | start_subsidence: 2000
37 | subsidence_rate: 2e-10
38 |
39 | Advanced Subsidence Configurations
40 | ==================================
41 |
42 | Subsidence behavior can be easily modified by :ref:`creating a subclass ` and overwriting the :obj:`~pyDeltaRCM.init_tools.init_tools.init_subsidence` or :obj:`~pyDeltaRCM.iteration_tools.iteration_tools.apply_subsidence` methods, or even more simply the relevant model hooks.
43 |
44 | An example of using subclassing to create a model setup with subsidence confined to only part of the model domain is included in the documentation:
45 |
46 | * :doc:`/examples/subsidence_region`
47 |
48 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. pyDeltaRCM documentation master file
2 |
3 | Welcome to the PyDeltaRCM documentation
4 | #########################################
5 |
6 | *pyDeltaRCM* is a computationally efficient, free and open source, and easy-to-customize numerical delta model based on the original DeltaRCM model design (`Matlab DeltaRCM `_ model by Man Liang).
7 | *pyDeltaRCM* delivers improved model stability and capabilities, infrastructure to support exploration with minimal boilerplate code, and establishes an approach to extending model capabilities that ensures reproducible and comparable studies.
8 |
9 | .. plot:: guides/cover.py
10 |
11 | The weighted random walk of 20 water parcels in a *pyDeltaRCM* model run with default parameters.
12 |
13 |
14 | Project information
15 | ###################
16 |
17 | .. image:: https://badge.fury.io/gh/DeltaRCM%2FpyDeltaRCM.svg
18 | :target: https://github.com/DeltaRCM/pyDeltaRCM/releases
19 |
20 | .. image:: https://badge.fury.io/py/pyDeltaRCM.svg
21 | :target: https://badge.fury.io/py/pyDeltaRCM
22 |
23 | .. image:: https://img.shields.io/static/v1?label=GitHub&logo=github&message=source&color=brightgreen
24 | :target: https://github.com/DeltaRCM/pyDeltaRCM
25 |
26 | .. image:: https://joss.theoj.org/papers/10.21105/joss.03398/status.svg
27 | :target: https://joss.theoj.org/papers/10.21105/joss.03398
28 |
29 | .. toctree::
30 | :maxdepth: 1
31 |
32 | meta/installing
33 | meta/contributing
34 | meta/license
35 | meta/conduct
36 | meta/citing
37 | meta/usedby
38 |
39 |
40 | .. _user_documentation:
41 |
42 | User documentation
43 | ##################
44 |
45 | .. toctree::
46 | :maxdepth: 2
47 |
48 | guides/getting_started
49 | guides/user_guide
50 | info/index
51 | examples/index
52 | examples/modelzoo
53 |
54 |
55 |
56 | Developer documentation
57 | #######################
58 |
59 | .. image:: https://badge.fury.io/py/pyDeltaRCM.svg
60 | :target: https://badge.fury.io/py/pyDeltaRCM
61 |
62 | .. image:: https://github.com/DeltaRCM/pyDeltaRCM/actions/workflows/build.yml/badge.svg
63 | :target: https://github.com/DeltaRCM/pyDeltaRCM/actions
64 |
65 | .. image:: https://codecov.io/gh/DeltaRCM/pyDeltaRCM/branch/develop/graph/badge.svg
66 | :target: https://codecov.io/gh/DeltaRCM/pyDeltaRCM
67 |
68 | .. image:: https://app.codacy.com/project/badge/Grade/1c137d0227914741a9ba09f0b00a49a7
69 | :target: https://app.codacy.com/gh/DeltaRCM/pyDeltaRCM/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade
70 |
71 | .. toctree::
72 | :maxdepth: 3
73 |
74 | guides/developer_guide
75 | reference/index
76 |
--------------------------------------------------------------------------------
/docs/source/info/index.rst:
--------------------------------------------------------------------------------
1 | .. model_info:
2 |
3 | =================
4 | Model Information
5 | =================
6 |
7 | This section provides background information about the pyDeltaRCM model itself.
8 | What are the model variables and parameters?
9 | What do they mean?
10 | How does the model simulate hydrodynamics?
11 | How is morphodynamics handled?
12 | All of these questions and more are answered here!
13 |
14 | .. toctree::
15 | :maxdepth: 1
16 |
17 | initialization
18 | yamlparameters
19 | modeltime
20 | hydrodynamics
21 | morphodynamics
22 | outputfile
23 | ../reference/model/model_hooks
24 |
--------------------------------------------------------------------------------
/docs/source/info/initialization.rst:
--------------------------------------------------------------------------------
1 | **************
2 | Initialization
3 | **************
4 |
5 | .. currentmodule:: pyDeltaRCM.init_tools
6 |
7 | There are many built-in parameters for setting up pyDeltaRCM runs.
8 |
9 |
10 | Domain configuration
11 | ====================
12 |
13 | The domain configuration is controlled by a series of input configuration parameters.
14 | Conceptually, we can consider the domain of pyDeltaRCM to be made up of an *inlet* along the top edge of the model domain and bounded by a strip of land, and the *basin*.
15 |
16 | .. plot:: init_tools/domain_parameters.py
17 |
18 | By default, the basin and inlet are both flat and have the same depth. However these characteristics can be controlled by a variety of input parameters explained below.
19 | Moreover, any complex initial geometry can be configured by the use of hooks; see an example here :doc:`../examples/slight_slope`.
20 |
21 | Domain size
22 | -----------
23 |
24 | The domain size is controlled by the `Length` and `Width` YAML parameters.
25 |
26 | .. plot:: init_tools/domain_size_compare.py
27 |
28 | .. hint::
29 |
30 | The size of the computational domain is determined by the size of the smallest size of the domain. The value for `Width` should almost always be 2 times `Length` to minimize unecessary calcualtions outside the valid computational domain.
31 |
32 | Importantly, the number of cells in the domain is then a function of the domain size in meters and the grid spacing :obj:`dx`.
33 | Because the number of grid cells is inverse nonlinearly related to the grid spacing (:math:`numcells = 1/dx^2`), the model runtime is sensitive to the choice of `dx` relative to `Length` and `Width`.
34 |
35 |
36 | Basin depth and inlet depth
37 | ---------------------------
38 |
39 | Inlet depth is controlled by :obj:`h0`.
40 | If no argument is given in the configuration for the parameter :obj:`hb`, then the basin depth is determined to be the same as the inlet depth.
41 | However, these depths can be controlled independently.
42 |
43 | .. plot:: init_tools/domain_basin_inlet_depth.py
44 |
45 |
46 | Inlet width and length
47 | ----------------------
48 |
49 | The inlet length and width are controlled by an inlet length parameter :obj:`L0_meters` and an inlet width parameter :obj:`N0_meters`.
50 | In implementation, the input length and width are rounded to the nearest grid location (a function of :obj:`dx`).
51 |
52 | .. plot:: init_tools/domain_inlet_geometry.py
53 |
54 |
55 |
56 | Input water and sediment
57 | ========================
58 |
59 | The input flow velocity is determined by :obj:`u0`.
60 |
61 | The input water discharge is thus fully constrained by the inlet geometry and the inlet flow velocity as:
62 |
63 | .. math::
64 | Q_{w0} = h_0 \times N_0 \times u_0
65 |
66 | .. hint::
67 | Keep in mind that :math:`N_0` is specified in meters as :obj:`N0_meters` in the input configuration. Ditto for the inlet length (:obj:`L0_meters`).
68 |
69 |
70 | Input sediment discharge is then determined by a **percentage concentration** of sediment in the flow :obj:`C0_percent`.
71 |
72 | .. math::
73 | Q_{s0} = Q_{w0} \times (C_{0percent}/100)
74 |
75 | The volume of each parcel of water to be routed is then determined by the total water discharge divided by the number of parcels :obj:`Np_water`.
76 | The volume of each parcel of sediment to be routed is then determined by the total sediment discharge divided by the number of parcels :obj:`Np_sed`.
77 |
78 | The number of sand and mud parcels are then determined as `Np_sed` times :obj:`f_bedload` and `Np_sed` times (1-:obj:`f_bedload`), respectively.
79 |
--------------------------------------------------------------------------------
/docs/source/info/modeltime.rst:
--------------------------------------------------------------------------------
1 | ******************
2 | Time in pyDeltaRCM
3 | ******************
4 |
5 | Time in the pyDeltaRCM model is simulated in units of seconds.
6 | The duration of a timestep is determined during model initialization to maintain numerical stability; the calculation is based on model domain and configuration parameters.
7 | The model is then iterated timestep by timestep, until an end-run condition is reached
8 |
9 | .. note::
10 |
11 | If you are using the :ref:`high-level API `, the model run end condition is that the elapsed model time is *equal to or greater than* the specified input time. As a result, the model run duration is unlikely to exactly match the input time specification, because the model timestep is unlikely to be a factor of the specified time.
12 |
13 | Please keep this in mind when evaluating model results, and especially when comparing between different model runs.
14 |
15 | Over the duration of the model, the water discharge (and thus sediment discharge) are assumed to be at bankfull.
16 | This assumption is based on the concept of geomorphic work [WM60]_ and the strongly nonlinear relationship between water discharge and sediment transport.
17 | To summarize the basis of this assumption, a very small proportion of sediment is in motion when discharge is at or near a low-flow "base flow" condition, relative to the amount of sediment in motion during flood conditions.
18 | So while flooding only occurs for a small fraction of total time, most of the time-integrated sediment transport occurs during this fraction of time, and the remainder of time is deemed negligible in comparison.
19 |
20 | For example, in the contrived river-delta hydrograph shown below, the discharge fluctuates around a base-flow condition for most of the year, with the exception of a 50 day period when a flood event occurs (from "start event" to "end event").
21 | For 25 days of the flood event, the discharge is high enough to exceed the bankfull discharge ("flooding duration").
22 |
23 | .. plot:: modeltime/one_year_plot.py
24 |
25 | A numerical model could simulate every day of this hydrograph, but this would require substantial computing power.
26 | To accelerate the computation time of models, we assume that the only important period of time is when the river is at-or-above bankfull discharge, and we collapse the hydrograph to a single value: the bankfull discharge.
27 | The choice of bankfull discharge for the single-value discharge assumption is a matter of convenience, in that this is readily estimated from field data or measurements.
28 |
29 | The duration of time represented by the single-value discharge assumption is also determined by the hydrograph.
30 | We arrive at the so-called *intermittency factor* (:math:`I_f`) by finding the fraction of unit-time per unit-time when the river is in flood.
31 | For this example, the intermittency factor scales between days and years as
32 |
33 | .. math::
34 |
35 | \frac{25~\textrm{days}}{365.25~\textrm{days}} \approx 0.07 \equiv I_f
36 |
37 | The intermittency factor thus gives a relationship to scale pyDeltaRCM model time (which is always computed in units of seconds elapsed) from seconds to years.
38 | For example, for a model run that has elapsed :math:`4.32 \times 10^8` seconds and an assumed intermittency factor of 0.07:
39 |
40 | .. math::
41 |
42 | \frac{\textrm{seconds~elapsed}}{I_f} = \frac{4.32 \times 10^8~\textrm{seconds}}{0.07} = 6.17 \times 10^9~\textrm{seconds} \approx 196~\textrm{years}
43 |
44 | .. note:: A convenience function is supplied with the low-level API for these time conversions: :obj:`~pyDeltaRCM.shared_tools.scale_model_time`.
45 |
46 | Applying the intermittency assumption to a four year model simulation reveals the computational advantage of this approach.
47 | A simulation of every day in the simulation duration would require 1460 days of simulated time (:math:`1.26 \times 10^8` seconds).
48 |
49 | .. plot:: modeltime/four_year_plot.py
50 |
51 | In contrast, by condensing the simulated time down to a bankfull discharge only, the intermittency assumption allows us to simulate the same "four year" period in just under 59 days of simulated time (:math:`5.08 \times 10^6` seconds).
52 |
53 |
54 | See also
55 | --------
56 |
57 | * :obj:`~pyDeltaRCM.preprocessor.scale_relative_sea_level_rise_rate`
58 | * :obj:`~pyDeltaRCM.shared_tools.scale_model_time`
59 |
60 |
61 | References
62 | ----------
63 |
64 | .. [WM60] Wolman, M. G., & Miller, J. P. (1960). Magnitude and frequency of forces in geomorphic processes. The Journal of Geology, 68(1), 54–74. https://doi.org/10.1086/626637
--------------------------------------------------------------------------------
/docs/source/info/outputfile.rst:
--------------------------------------------------------------------------------
1 | =================
2 | Model Output File
3 | =================
4 |
5 | If configured to save any output data, model outputs are saved using the `netCDF4 `_ file format.
6 |
7 |
8 | Gridded Variables
9 | =================
10 |
11 | In any given run, the saving parameters "save__grids" control whether or
12 | not that 2-D grid variable (e.g. velocity) is saved to the netCDF4 file. In
13 | the netCDF4 file, a 3-D array with the dimensions `time` :math:`\times`
14 | `x` :math:`\times` `y` is created for each 2-D grid variable that is set to
15 | be saved. Note that `x` is the *downstream* coordinate, rather than the
16 | Cartesian `x` when displaying the grid. The appropriate units for all
17 | variables are stored: for example "meters per second" for the *velocity*
18 | grid.
19 |
20 | .. note::
21 |
22 | The format of the output netCDF file coordinate changed in `v2.1.0`. The
23 | old format is documented
24 | in :attr:`~pyDeltaRCM.model.DeltaModel.legacy_netcdf`, and that input
25 | parameter `legacy_netcdf` can be used to create on output netcdf file with
26 | the old coordinate configuration.
27 |
28 |
29 | Grid Coordinates
30 | ================
31 |
32 | Grid coordinates are specified in the variables `time`, `x`, and `y` in the output netCDF4 file.
33 | These arrays are 1D arrays, which specify the location of each cell in the domain in *dimensional* coordinates (e.g., meters).
34 | In the downstream direction, the distance of each cell from the inlet boundary is specified in `x` in meters.
35 | Similarly, the cross-domain distance is specified in `y` in meters.
36 | Lastly, the `time` variable is stored as a 1D array with model `time` in seconds.
37 |
38 |
39 | Model Metadata
40 | ==============
41 |
42 | In addition to the grid coordinates, model metadata is saved as a group of
43 | 1-D arrays (vectors) and 0-D arrays (floats and integers). The values that are
44 | saved as metadata are the following:
45 |
46 | - Length of the land surface: `L0`
47 | - Width of the inlet channel: `N0`
48 | - Center of the domain: `CTR`
49 | - Length of cell faces: `dx`
50 | - Depth of inlet channel: `h0`
51 | - Sea level: `H_SL`
52 | - Bedload fraction: `f_bedload`
53 | - Sediment concentration: `C0_percent`
54 | - Characteristic Velocity: `u0`
55 | - If subsidence is enabled:
56 | - Subsidence start time: `start_subsidence`
57 | - Subsidence rate: `sigma`
58 |
59 |
60 | Working with Model Outputs
61 | ==========================
62 |
63 | The resulting netCDF4 output file can be read using any netCDF4-compatible
64 | library. These libraries range from the
65 | `netCDF4 Python package `_ itself,
66 | to higher-level libraries such as
67 | `xarray `_. For deltas, and specifically
68 | *pyDeltaRCM*, there is also a package under development called
69 | `DeltaMetrics `_,
70 | that is being designed to help post-process and analyze *pyDeltaRCM* outputs.
71 |
72 |
73 | Here, we show how to read the output NetCDF file with Python package ``netCDF4``.
74 |
75 | .. code::
76 |
77 | import netCDF4 as nc
78 |
79 | data = nc.Dataset('pyDeltaRCM_output.nc') # the output file path!
80 |
81 | This `data` object is a `Dataset` object that can be sliced the same was as a `numpy` array.
82 | For example, we can slice the final bed elevation and velocity of a model run:
83 |
84 | .. code::
85 |
86 | final_bed_elevation = data['eta'][-1, :, :]
87 | final_velocity = data['velocity'][-1, :, :]
88 |
89 | These slices look like this, if we were to plot them.
90 |
91 | .. plot:: guides/output_file.py
92 |
--------------------------------------------------------------------------------
/docs/source/info/yamlparameters.rst:
--------------------------------------------------------------------------------
1 | ***************
2 | YAML Parameters
3 | ***************
4 |
5 | Configurable model parameters are listed in the
6 | :doc:`../reference/model/yaml_defaults`.
7 | Links to the API documentation for different types of YAML Parameters are
8 | provided below. The YAML parameters are sorted by "type", for example,
9 | :ref:`model-domain-parameters` are those parameters which control the
10 | definition of the pyDeltaRCM model domain.
11 |
12 | .. hint::
13 |
14 | View the complete list of default values and expected types
15 | here: :doc:`../reference/model/yaml_defaults`.
16 |
17 |
18 | Model Settings
19 | ==============
20 |
21 | :attr:`pyDeltaRCM.model.DeltaModel.out_dir`
22 |
23 | :attr:`pyDeltaRCM.model.DeltaModel.verbose`
24 |
25 |
26 | .. _model-domain-parameters:
27 |
28 | Model Domain Parameters
29 | =======================
30 |
31 | :attr:`pyDeltaRCM.model.DeltaModel.Length`
32 |
33 | :attr:`pyDeltaRCM.model.DeltaModel.Width`
34 |
35 | :attr:`pyDeltaRCM.model.DeltaModel.dx`
36 |
37 | :attr:`pyDeltaRCM.model.DeltaModel.L0_meters`
38 |
39 | :attr:`pyDeltaRCM.model.DeltaModel.N0_meters`
40 |
41 | :attr:`pyDeltaRCM.model.DeltaModel.S0`
42 |
43 | :attr:`pyDeltaRCM.model.DeltaModel.u0`
44 |
45 | :attr:`pyDeltaRCM.model.DeltaModel.h0`
46 |
47 | :attr:`pyDeltaRCM.model.DeltaModel.hb`
48 |
49 | :attr:`pyDeltaRCM.model.DeltaModel.H_SL`
50 |
51 | :attr:`pyDeltaRCM.model.DeltaModel.seed`
52 |
53 | :attr:`pyDeltaRCM.model.DeltaModel.SLR`
54 |
55 | :attr:`pyDeltaRCM.model.DeltaModel.f_bedload`
56 |
57 | :attr:`pyDeltaRCM.model.DeltaModel.C0_percent`
58 |
59 | :attr:`pyDeltaRCM.model.DeltaModel.active_layer_thickness`
60 |
61 | :attr:`pyDeltaRCM.model.DeltaModel.toggle_subsidence`
62 |
63 | :attr:`pyDeltaRCM.model.DeltaModel.subsidence_rate`
64 |
65 | :attr:`pyDeltaRCM.model.DeltaModel.start_subsidence`
66 |
67 |
68 | Reduced-Complexity Routing Parameters
69 | =====================================
70 |
71 | :attr:`pyDeltaRCM.model.DeltaModel.Np_water`
72 |
73 | :attr:`pyDeltaRCM.model.DeltaModel.Np_sed`
74 |
75 | :attr:`pyDeltaRCM.model.DeltaModel.omega_sfc`
76 |
77 | :attr:`pyDeltaRCM.model.DeltaModel.omega_flow`
78 |
79 | :attr:`pyDeltaRCM.model.DeltaModel.Nsmooth`
80 |
81 | :attr:`pyDeltaRCM.model.DeltaModel.Csmooth`
82 |
83 | :attr:`pyDeltaRCM.model.DeltaModel.theta_water`
84 |
85 | :attr:`pyDeltaRCM.model.DeltaModel.coeff_theta_sand`
86 |
87 | :attr:`pyDeltaRCM.model.DeltaModel.coeff_theta_mud`
88 |
89 | :attr:`pyDeltaRCM.model.DeltaModel.beta`
90 |
91 | :attr:`pyDeltaRCM.model.DeltaModel.sed_lag`
92 |
93 | :attr:`pyDeltaRCM.model.DeltaModel.coeff_U_dep_mud`
94 |
95 | :attr:`pyDeltaRCM.model.DeltaModel.coeff_U_ero_mud`
96 |
97 | :attr:`pyDeltaRCM.model.DeltaModel.coeff_U_ero_sand`
98 |
99 | :attr:`pyDeltaRCM.model.DeltaModel.alpha`
100 |
101 | :attr:`pyDeltaRCM.model.DeltaModel.itermax`
102 |
103 | :attr:`pyDeltaRCM.model.DeltaModel.stepmax`
104 |
105 |
106 | Output Settings
107 | ===============
108 |
109 | :attr:`pyDeltaRCM.model.DeltaModel.save_eta_figs`
110 |
111 | :attr:`pyDeltaRCM.model.DeltaModel.save_stage_figs`
112 |
113 | :attr:`pyDeltaRCM.model.DeltaModel.save_depth_figs`
114 |
115 | :attr:`pyDeltaRCM.model.DeltaModel.save_discharge_figs`
116 |
117 | :attr:`pyDeltaRCM.model.DeltaModel.save_velocity_figs`
118 |
119 | :attr:`pyDeltaRCM.model.DeltaModel.save_sedflux_figs`
120 |
121 | :attr:`pyDeltaRCM.model.DeltaModel.save_sandfrac_figs`
122 |
123 | :attr:`pyDeltaRCM.model.DeltaModel.save_figs_sequential`
124 |
125 | :attr:`pyDeltaRCM.model.DeltaModel.save_eta_grids`
126 |
127 | :attr:`pyDeltaRCM.model.DeltaModel.save_stage_grids`
128 |
129 | :attr:`pyDeltaRCM.model.DeltaModel.save_depth_grids`
130 |
131 | :attr:`pyDeltaRCM.model.DeltaModel.save_discharge_grids`
132 |
133 | :attr:`pyDeltaRCM.model.DeltaModel.save_velocity_grids`
134 |
135 | :attr:`pyDeltaRCM.model.DeltaModel.save_sedflux_grids`
136 |
137 | :attr:`pyDeltaRCM.model.DeltaModel.save_sandfrac_grids`
138 |
139 | :attr:`pyDeltaRCM.model.DeltaModel.save_discharge_components`
140 |
141 | :attr:`pyDeltaRCM.model.DeltaModel.save_velocity_components`
142 |
143 | :attr:`pyDeltaRCM.model.DeltaModel.save_dt`
144 |
145 | :attr:`pyDeltaRCM.model.DeltaModel.checkpoint_dt`
146 |
147 | :attr:`pyDeltaRCM.model.DeltaModel.save_checkpoint`
148 |
149 | :attr:`pyDeltaRCM.model.DeltaModel.resume_checkpoint`
150 |
151 | :attr:`pyDeltaRCM.model.DeltaModel.clobber_netcdf`
152 |
153 | :attr:`pyDeltaRCM.model.DeltaModel.legacy_netcdf`
154 |
--------------------------------------------------------------------------------
/docs/source/meta/citing.rst:
--------------------------------------------------------------------------------
1 | *******************
2 | Citing *pyDeltaRCM*
3 | *******************
4 |
5 | When citing *pyDeltaRCM*, please cite the `JOSS paper `_:
6 |
7 | Moodie et al., (2021). pyDeltaRCM: a flexible numerical delta model. Journal of Open Source Software, 6(64), 3398, https://doi.org/10.21105/joss.03398
8 |
9 | If you use BibTeX, you can add *pyDeltaRCM* to your `.bib` file using the following code:
10 |
11 | .. code:: console
12 |
13 | @article{Moodie2021,
14 | doi = {10.21105/joss.03398},
15 | url = {https://doi.org/10.21105/joss.03398},
16 | year = {2021},
17 | publisher = {The Open Journal},
18 | volume = {6},
19 | number = {64},
20 | pages = {3398},
21 | author = {Andrew J. Moodie and Jayaram Hariharan and Eric Barefoot and Paola Passalacqua},
22 | title = {*pyDeltaRCM*: a flexible numerical delta model},
23 | journal = {Journal of Open Source Software}
24 | }
25 |
--------------------------------------------------------------------------------
/docs/source/meta/conduct.rst:
--------------------------------------------------------------------------------
1 |
2 | .. include:: ../../../CODE_OF_CONDUCT.rst
3 |
--------------------------------------------------------------------------------
/docs/source/meta/contributing.rst:
--------------------------------------------------------------------------------
1 | ************
2 | Contributing
3 | ************
4 |
5 | To contribute to this project, you must follow our :doc:`Code of Conduct ` at all times.
6 | If you are not familiar with our code of conduct policy, take a minute to read the policy before starting with your first contribution.
7 |
8 |
9 | How to contribute
10 | -----------------
11 |
12 | We welcome contributions of many types, including but not limited to:
13 |
14 | * bug fixes
15 | * improvements to documentation
16 | * new features
17 | * additional examples for using and developing *pyDeltaRCM*
18 |
19 | If you are interested in contributing, please submit a pull request or get in touch with the development team via the `Github issue tracker `_.
20 |
21 |
22 | Issues and questions
23 | --------------------
24 |
25 | If you have identified a bug within the code, but aren't sure how to (or don't want to) fix it, we invite you to open an issue on our `Github issue tracker `_.
26 | Please explain the problem as fully as possible, including any system information that may be relevant.
27 |
28 | You can also ask any questions about the software or ask for help on the `Github issue tracker `_.
29 | We will try our best to help you how we can!
30 |
--------------------------------------------------------------------------------
/docs/source/meta/installing.rst:
--------------------------------------------------------------------------------
1 | ************
2 | Installing
3 | ************
4 |
5 | We recommend installing *pyDeltaRCM* in a virtual environment.
6 | That said, *pyDeltaRCM* depends on a small number of packages (:ref:`list of dependencies `), many of which are likely already in a Python user/developer's regular use, so it's probably safe to install *pyDeltaRCM* in your base environment, too.
7 |
8 |
9 | Installing
10 | ==========
11 |
12 | We describe installation flavors for both users and developers below.
13 |
14 | .. hint::
15 |
16 | If you are looking to make any modifications to the model source code, you should follow the developer instructions.
17 |
18 | We suggest using the Anaconda Python distribution, which you can obtain via `the project website `_.
19 |
20 | Before proceeding, you may wish to create a virtual environment for the *pyDeltaRCM* project.
21 | With Anaconda on Linux:
22 |
23 | .. code:: console
24 |
25 | $ conda create -n deltarcm python=3
26 | $ conda activate deltarcm
27 |
28 | For more informtaion, see `this guide `_ for help on creating and activating a virtual environment with Anaconda on other platforms.
29 | See `this helpful guide `_ for creating virtual environments with `venv` if you do not use Anaconda.
30 |
31 |
32 | User installation
33 | -----------------
34 |
35 | For a user installation, simply install from the pypi package repository:
36 |
37 | .. code:: console
38 |
39 | $ pip install pyDeltaRCM
40 |
41 | .. note::
42 |
43 | You may need to `first install `_ `pip`.
44 |
45 |
46 | .. _dev-install:
47 |
48 | Developer installation
49 | ----------------------
50 |
51 | For a developer installation, you should first fork the repository on Github.
52 | This will allow you to submit suggestions and contribute to *pyDeltaRCM*.
53 |
54 | .. note::
55 |
56 | You do not *need* to create a fork if your are just testing, but it may save you time and headache down the road. If you choose not to, just use the main repository url below (https://github.com/DeltaRCM/pyDeltaRCM).
57 |
58 | First, you will need to `install git `_ if you do not already have it.
59 | Then, download or clone your fork of the project:
60 |
61 | .. code:: console
62 |
63 | $ git clone https://github.com//pyDeltaRCM.git
64 |
65 | Then, with current working directory as the root of the repository (e.g., ``cd pyDeltaRCM``), run the following commands:
66 |
67 | .. code:: console
68 |
69 | $ pip install -r requirements.txt
70 | $ pip install -r requirements-docs.txt
71 | $ pip install -r requirements-test.txt
72 | $ pip install -e .
73 |
74 | To check installation, run the complete test suite with:
75 |
76 | .. code:: console
77 |
78 | $ pytest --mpl --mpl-baseline-path=tests/imgs_baseline
79 |
80 | Finally, add the `upstream` repository to your `remote` repository list:
81 |
82 | .. code:: console
83 |
84 | $ git remote add upstream https://github.com/DeltaRCM/pyDeltaRCM.git
85 |
86 | You can build a local copy of the documentation with:
87 |
88 | .. code:: console
89 |
90 | $ (cd docs && make html)
91 |
92 |
93 | Next steps
94 | ==========
95 |
96 | Consider reading through the :doc:`10-minute tutorial ` or the :doc:`User Guide ` to help get you started using *pyDeltaRCM*.
97 |
98 |
99 | .. _dependencies-list:
100 |
101 | Dependencies
102 | ============
103 |
104 | .. literalinclude:: ../../../requirements.txt
105 | :linenos:
106 |
--------------------------------------------------------------------------------
/docs/source/meta/license.rst:
--------------------------------------------------------------------------------
1 | ************
2 | License
3 | ************
4 |
5 | This project is licensed under the MIT License - see the `full license `_ file for details.
6 | It is provided without warranty or guaranteed support.
7 |
--------------------------------------------------------------------------------
/docs/source/meta/usedby.rst:
--------------------------------------------------------------------------------
1 | *******
2 | Used By
3 | *******
4 |
5 | Below are papers, presentations, and other material that use *pyDeltaRCM*.
6 |
7 | Papers
8 | ------
9 | .. copied from "Chicago" style within Google Scholar
10 |
11 | [1] Moodie, Andrew J., and Paola Passalacqua. "When Does Faulting‐Induced Subsidence Drive Distributary Network Reorganization?." Geophysical Research Letters 48, no. 22 (2021): e2021GL095053.
12 |
13 | [2] Hariharan, Jayaram, Paola Passalacqua, Zhongyuan Xu, Holly A. Michael, Elisabeth Steel, Austin Chadwick, Chris Paola, and Andrew J. Moodie. "Modeling the Dynamic Response of River Deltas to Sea‐Level Rise Acceleration." Journal of Geophysical Research: Earth Surface 127, no. 9 (2022): e2022JF006762.
14 |
15 |
16 | Presentations
17 | -------------
18 |
19 |
20 |
21 | Other
22 | -----
23 |
24 | [1] Hariharan, Jayaram. "Exploring *pyDeltaRCM*: A Collection of Numerical Experiments." Zenodo v0.1 (2022), https://zenodo.org/records/7315646.
--------------------------------------------------------------------------------
/docs/source/pyplots/debug_tools/debug_demo.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 |
3 | import pyDeltaRCM
4 |
5 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
6 | delta = pyDeltaRCM.DeltaModel(out_dir=output_dir)
7 |
8 | delta.show_attribute('cell_type', grid=False)
9 | delta.show_attribute('cell_type', grid=False)
10 | delta.show_ind([3378, 9145, 11568, 514, 13558])
11 | delta.show_ind((42, 94), 'bs')
12 | delta.show_ind([(41, 8), (42, 10)], 'g^')
13 | plt.show()
14 |
--------------------------------------------------------------------------------
/docs/source/pyplots/guides/10min_demo.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 |
3 | import pyDeltaRCM
4 |
5 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
6 | delta = pyDeltaRCM.DeltaModel(out_dir=output_dir)
7 |
8 | for _t in range(0, 5):
9 | delta.update()
10 |
11 | delta.finalize()
12 |
13 |
14 | fig, ax = plt.subplots()
15 | ax.imshow(delta.bed_elevation, vmax=-3)
16 | plt.show()
17 |
--------------------------------------------------------------------------------
/docs/source/pyplots/guides/cover.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | import pyDeltaRCM
8 |
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 20
15 | cm = matplotlib.colormaps['tab10']
16 |
17 |
18 | # init delta model
19 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
20 |
21 | delta = pyDeltaRCM.DeltaModel(
22 | out_dir=output_dir,
23 | resume_checkpoint='../../_resources/checkpoint')
24 |
25 |
26 | _shp = delta.eta.shape
27 |
28 |
29 | # manually call only the necessary paths
30 | delta.init_water_iteration()
31 | delta.run_water_iteration()
32 |
33 |
34 | # define a function to fill in the walks of given idx
35 | def _plot_idxs_walks_to_step(delta_inds, _step, _idxs, _ax) -> None:
36 | for i in range(len(_idxs)):
37 | iidx = _idxs[i]
38 | walk = delta_inds[iidx, :]
39 | walk = walk[:_step]
40 | pyDeltaRCM.debug_tools.plot_line(
41 | walk, shape=_shp, color='r', alpha=0.5,
42 | nozeros=True)
43 | yend, xend = pyDeltaRCM.shared_tools.custom_unravel(
44 | walk[-1], _shp)
45 | _ax.plot(xend, yend,
46 | marker='o', ms=3, color='r', alpha=0.5)
47 |
48 |
49 | # declare the idxs to use:
50 | np.random.seed(0) # make it reproducible
51 | idxs = np.random.randint(low=0, high=delta._Np_water, size=n)
52 | ps = 100
53 |
54 | # set up axis
55 | fig, ax = plt.subplots(figsize=(6, 3))
56 | vmin, vmax = delta.eta.min(), delta.eta.max()
57 |
58 | # fill in axis2
59 | ax.imshow(
60 | delta.eta, vmin=vmin, vmax=vmax, cmap='cividis')
61 | ax.set_xticks([])
62 | ax.set_yticks([])
63 | _plot_idxs_walks_to_step(
64 | delta.free_surf_walk_inds, _step=ps, _idxs=idxs, _ax=ax)
65 |
66 | plt.tight_layout()
67 | plt.show()
68 |
--------------------------------------------------------------------------------
/docs/source/pyplots/guides/output_file.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | import pyDeltaRCM
8 |
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 20
15 | cm = matplotlib.colormaps['tab10']
16 |
17 |
18 | # init delta model
19 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
20 |
21 | delta = pyDeltaRCM.DeltaModel(
22 | out_dir=output_dir,
23 | resume_checkpoint='../../_resources/checkpoint')
24 |
25 |
26 | _shp = delta.eta.shape
27 |
28 | # set up axis
29 | fig, ax = plt.subplots(1, 2, figsize=(6, 3))
30 | vmin, vmax = delta.eta.min(), delta.eta.max()
31 |
32 | # fill in axis
33 | ax[0].imshow(
34 | delta.eta, vmin=vmin, vmax=vmax, cmap='cividis')
35 | ax[0].set_xticks([])
36 | ax[0].set_yticks([])
37 | ax[0].set_title('bed elevation')
38 |
39 | ax[1].imshow(
40 | delta.uw, cmap='plasma')
41 | ax[1].set_xticks([])
42 | ax[1].set_yticks([])
43 | ax[1].set_title('velocity')
44 |
45 | plt.tight_layout()
46 | plt.show()
47 |
--------------------------------------------------------------------------------
/docs/source/pyplots/init_tools/domain_basin_inlet_depth.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 |
9 | # filter out the warning raised about no netcdf being found
10 | warnings.filterwarnings("ignore", category=UserWarning)
11 |
12 |
13 | n = 1
14 | cm = matplotlib.colormaps.get_cmap("tab10")
15 |
16 | param_dict = {"timesteps": 0}
17 | _matrix = {"h0": [2, 5], "hb": [2, 5]}
18 | param_dict["matrix"] = _matrix
19 | param_dict["L0_meters"] = 500
20 | param_dict["N0_meters"] = 500
21 |
22 | # init delta models with preprocessor
23 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
24 | param_dict.update({"out_dir": output_dir})
25 |
26 | pp = pyDeltaRCM.preprocessor.Preprocessor(param_dict)
27 |
28 | pp.run_jobs()
29 |
30 |
31 | fig, ax = plt.subplots(
32 | 2, 2, figsize=(6, 4), subplot_kw=dict(aspect="equal"), sharex=True, sharey=True
33 | )
34 |
35 | ax = ax.ravel()
36 | for i in range(4):
37 | ax[i].imshow(
38 | pp.job_list[i].deltamodel.eta,
39 | interpolation="none",
40 | extent=[
41 | 0,
42 | pp.job_list[i].deltamodel.Width,
43 | pp.job_list[i].deltamodel.Length,
44 | 0,
45 | ],
46 | )
47 | ax[i].text(
48 | 0.05,
49 | 0.05,
50 | f"h0: {pp.job_list[i].deltamodel.h0}\nhb: {pp.job_list[i].deltamodel.hb}",
51 | ha="left",
52 | va="bottom",
53 | color="white",
54 | fontsize=8,
55 | transform=ax[i].transAxes,
56 | )
57 |
58 | for i, axi in enumerate(ax.ravel()):
59 | axi.tick_params(labelsize=7)
60 | if i % 2 == 0:
61 | axi.set_ylabel("Length", fontsize=8)
62 | if i > 2:
63 | axi.set_xlabel("Width", fontsize=8)
64 |
65 | plt.tight_layout()
66 | plt.show()
67 |
--------------------------------------------------------------------------------
/docs/source/pyplots/init_tools/domain_inlet_geometry.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 |
9 | # filter out the warning raised about no netcdf being found
10 | warnings.filterwarnings("ignore", category=UserWarning)
11 |
12 |
13 | n = 1
14 | cm = matplotlib.colormaps.get_cmap("tab10")
15 |
16 | param_dict = {"timesteps": 0}
17 | _matrix = {"L0_meters": [200, 500, 1000], "N0_meters": [200, 500, 1000]}
18 | param_dict["matrix"] = _matrix
19 |
20 | # init delta models with preprocessor
21 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
22 | param_dict.update({"out_dir": output_dir})
23 |
24 | pp = pyDeltaRCM.preprocessor.Preprocessor(param_dict)
25 |
26 | pp.run_jobs()
27 |
28 |
29 | fig, ax = plt.subplots(
30 | 3, 3, figsize=(9, 5), subplot_kw=dict(aspect="equal"), sharex=True, sharey=True
31 | )
32 |
33 | ax = ax.ravel()
34 | for i in range(9):
35 | ax[i].imshow(
36 | pp.job_list[i].deltamodel.eta,
37 | interpolation="none",
38 | extent=[
39 | 0,
40 | pp.job_list[i].deltamodel.Width,
41 | pp.job_list[i].deltamodel.Length,
42 | 0,
43 | ],
44 | )
45 | ax[i].text(
46 | 0.05,
47 | 0.05,
48 | f"L0_meters: {pp.job_list[i].deltamodel.L0_meters}\nN0_meters: {pp.job_list[i].deltamodel.N0_meters}",
49 | ha="left",
50 | va="bottom",
51 | color="white",
52 | fontsize=8,
53 | transform=ax[i].transAxes,
54 | )
55 |
56 | for i, axi in enumerate(ax.ravel()):
57 | axi.tick_params(labelsize=7)
58 | if i % 3 == 0:
59 | axi.set_ylabel("Length", fontsize=8)
60 | if i > 6:
61 | axi.set_xlabel("Width", fontsize=8)
62 |
63 | plt.tight_layout()
64 | plt.show()
65 |
--------------------------------------------------------------------------------
/docs/source/pyplots/init_tools/domain_parameters.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 | # this creates a large plot showing a bunch of the basin parameters
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 1
15 | cm = matplotlib.colormaps.get_cmap("tab10")
16 |
17 | param_dict = {"timesteps": 0}
18 | # _matrix = {"Length": [2500, 5000, 10000]}
19 | # param_dict["matrix"] = _matrix
20 | LENGTH = 2000
21 | WIDTH = 4000
22 | param_dict["Length"] = LENGTH
23 | param_dict["Width"] = WIDTH
24 |
25 | # init delta model
26 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
27 | param_dict["out_dir"] = output_dir
28 | delta = pyDeltaRCM.DeltaModel(**param_dict)
29 |
30 | fig, ax = plt.subplots(
31 | figsize=(6, 3.5),
32 | subplot_kw=dict(aspect="equal"),
33 | )
34 |
35 |
36 | ax.imshow(delta.eta, interpolation="none", extent=[0, delta.Width, delta.Length, 0])
37 |
38 | # computational edge
39 | ax.contour(
40 | delta.X[1:, 1:],
41 | delta.Y[1:, 1:],
42 | delta.cell_type,
43 | levels=[-1],
44 | colors="white",
45 | linewidths=[1],
46 | linestyles=["-"],
47 | )
48 | ax.annotate(
49 | "computational\ndomain edge:\n Length, Width",
50 | (0.2 * WIDTH, 0.8 * LENGTH),
51 | (0.25 * WIDTH + delta.dx, 0.75 * LENGTH - delta.dx),
52 | fontsize=8,
53 | color="white",
54 | arrowprops=dict(arrowstyle="-", color="white"),
55 | )
56 |
57 | # inlet
58 | inlet_x = (delta.CTR + 1) * delta.dx
59 | inlet_y = (delta.L0 - 2) * delta.dx
60 | ax.annotate(
61 | "inlet geometry:\n h0, N0_meters, L0_meters",
62 | (inlet_x, inlet_y), # point
63 | (inlet_x - (10 * delta.dx), inlet_y + (10 * delta.dx)), # label
64 | fontsize=8,
65 | color="white",
66 | textcoords="data",
67 | arrowprops=dict(arrowstyle="-", color="white"),
68 | )
69 |
70 | # basin depth
71 | ax.annotate(
72 | "basin depth:\n hb",
73 | (0.75 * WIDTH, 0.45 * LENGTH),
74 | (0.65 * WIDTH, 0.6 * LENGTH),
75 | fontsize=8,
76 | color="white",
77 | arrowprops=dict(arrowstyle="-", color="white"),
78 | )
79 |
80 | ax.set_ylabel("Length", fontsize=8)
81 |
82 | ax.tick_params(labelsize=7)
83 | ax.set_xlabel("Width", fontsize=8)
84 |
85 | plt.tight_layout()
86 | plt.show()
87 |
--------------------------------------------------------------------------------
/docs/source/pyplots/init_tools/domain_size_compare.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 |
9 | # filter out the warning raised about no netcdf being found
10 | warnings.filterwarnings("ignore", category=UserWarning)
11 |
12 |
13 | n = 1
14 | cm = matplotlib.colormaps.get_cmap("tab10")
15 |
16 | param_dict = {"timesteps": 0}
17 | _matrix = {"Length": [2500, 5000, 10000]}
18 | param_dict["matrix"] = _matrix
19 |
20 | # init delta models with preprocessor
21 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
22 | param_dict.update({"out_dir": output_dir})
23 |
24 | pp = pyDeltaRCM.preprocessor.Preprocessor(param_dict)
25 |
26 | pp.run_jobs()
27 |
28 |
29 | fig, ax = plt.subplots(
30 | 1,
31 | 3,
32 | figsize=(9, 3.5),
33 | subplot_kw=dict(aspect="equal"),
34 | gridspec_kw=dict(width_ratios=[1, 1, 1]),
35 | )
36 |
37 | for i in range(3):
38 | ax[i].imshow(
39 | pp.job_list[i].deltamodel.eta,
40 | interpolation="none",
41 | extent=[
42 | 0,
43 | pp.job_list[i].deltamodel.Width,
44 | pp.job_list[i].deltamodel.Length,
45 | 0,
46 | ],
47 | )
48 | ax[i].contour(
49 | pp.job_list[i].deltamodel.X[1:, 1:],
50 | pp.job_list[i].deltamodel.Y[1:, 1:],
51 | pp.job_list[i].deltamodel.cell_type,
52 | levels=[-1],
53 | colors="white",
54 | linewidths=[1],
55 | linestyles=["-"],
56 | )
57 |
58 | ax[2].annotate(
59 | "computational\ndomain edge",
60 | (2000, 4000),
61 | (200, 6400),
62 | fontsize=8,
63 | color="white",
64 | arrowprops=dict(arrowstyle="-", color="white"),
65 | )
66 |
67 | ax[0].set_ylabel("Length", fontsize=8)
68 |
69 | for axi in ax.ravel():
70 | axi.tick_params(labelsize=7)
71 | axi.set_xlabel("Width", fontsize=8)
72 |
73 | plt.tight_layout()
74 | plt.show()
75 |
--------------------------------------------------------------------------------
/docs/source/pyplots/modeltime/_base.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | time = np.arange(365)
4 | hydrograph = np.ones((len(time),)) + \
5 | (np.random.uniform(size=(len(time),)) / 10)
6 | hydrograph[100:150] = 2 + np.sin(np.arange(15, 65) / 15)
7 | flood = hydrograph >= 2.5
8 |
--------------------------------------------------------------------------------
/docs/source/pyplots/modeltime/four_year_condensed_plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 |
4 |
5 | import _base
6 |
7 |
8 | fig, ax = plt.subplots(figsize=(8, 2))
9 | plt.subplots_adjust(top=0.7)
10 |
11 | nflood = np.sum(_base.flood)
12 | day = 0
13 | for i in range(4):
14 | ax.axvline(x=day, color='k', ls='-')
15 | ax.fill_between(day + np.arange(nflood + 1), np.zeros((nflood + 1,)),
16 | 4 * np.ones((nflood + 1,)),
17 | alpha=0.4, edgecolor='none')
18 | ax.plot(day + np.arange(nflood + 1), 2.5 * np.ones((nflood + 1),))
19 | day += nflood
20 |
21 | ax.axvline(x=day, color='k', ls='-')
22 | ax.set_ylim(0.9, 3.1)
23 | ax.set_xlim(0 - 10, 365 * 4 + 10)
24 | ax.set_yticks([])
25 | ax.set_xlabel(r'time $\rightarrow$')
26 | ax.set_yticks([1.05, 2.5])
27 | ax.set_yticklabels(['base flow', 'bankfull flow'])
28 |
29 | plt.show()
30 |
--------------------------------------------------------------------------------
/docs/source/pyplots/modeltime/four_year_plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 |
4 |
5 | import _base
6 |
7 |
8 | fig, ax = plt.subplots(2, 1, figsize=(8, 4), sharex=True)
9 | # plt.subplots_adjust(top=0.7)
10 |
11 |
12 | day = 0
13 | for i in range(4):
14 | ax[0].axvline(x=day, color='k', ls='-')
15 | ax[0].fill_between(day + np.arange(365), np.zeros((len(_base.time),)),
16 | 4 * np.ones((len(_base.time),)),
17 | where=_base.flood, alpha=0.4, edgecolor='none')
18 | ax[0].plot(day + np.arange(365), _base.hydrograph)
19 | ax[0].text(day + 220, 2.6, 'year ' + str(i))
20 | day += 365
21 |
22 | ax[0].axvline(x=day, color='k', ls='-')
23 | ax[0].set_ylim(0.9, 3.1)
24 | ax[0].set_xlim(0 - 10, day + 10)
25 | ax[0].set_xlabel(r'time $\rightarrow$')
26 | ax[0].set_yticks([1.05, 2.5])
27 | ax[0].set_yticklabels(['base flow', 'bankfull flow'])
28 |
29 |
30 | nflood = np.sum(_base.flood)
31 | day = 0
32 | for i in range(4):
33 | ax[1].axvline(x=day, color='k', ls='-')
34 | ax[1].fill_between(day + np.arange(nflood + 1), np.zeros((nflood + 1,)),
35 | 4 * np.ones((nflood + 1,)),
36 | alpha=0.4, edgecolor='none')
37 | ax[1].plot(day + np.arange(nflood + 1), 2.5 * np.ones((nflood + 1),))
38 | day += nflood
39 |
40 | ax[1].axvline(x=day, color='k', ls='-')
41 | ax[1].set_ylim(0.9, 3.1)
42 | ax[1].set_xlim(0 - 10, 365 * 4 + 10)
43 | ax[1].set_yticks([])
44 | ax[1].set_xlabel(r'time $\rightarrow$')
45 | ax[1].set_yticks([1.05, 2.5])
46 | ax[1].set_yticklabels(['base flow', 'bankfull flow'])
47 |
48 |
49 | plt.show()
50 |
--------------------------------------------------------------------------------
/docs/source/pyplots/modeltime/one_year_plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 |
4 | import _base
5 | from typing import Dict
6 |
7 | fig, ax = plt.subplots()
8 | plt.subplots_adjust(left=0.2)
9 | ax.plot(_base.time, _base.hydrograph)
10 | ax.axhline(y=2.5, color='k', ls='--')
11 | ax.fill_between(np.arange(365), 2.5 * np.ones((len(_base.time),)),
12 | _base.hydrograph, where=_base.flood, alpha=0.4)
13 | ax.set_yticks([1.05, 2.5])
14 | ax.set_yticklabels(['base flow', 'bankfull flow'])
15 | ax.set_xlabel('calendar day')
16 | ax.set_ylim(0.9, 3.1)
17 |
18 | bbox: Dict[str, str] = dict(boxstyle="round", fc="0.8")
19 | _cs0 = "angle,angleA=-10,angleB=-60,rad=10"
20 | ax.annotate('start event', xy=(95, 1.1), xytext=(0, 1.4),
21 | bbox=bbox, arrowprops=dict(arrowstyle="->", connectionstyle=_cs0))
22 | _cs1 = "angle,angleA=10,angleB=60,rad=10"
23 | ax.annotate('end event', xy=(150, 1.1), xytext=(170, 1.4),
24 | bbox=bbox, arrowprops=dict(arrowstyle="->", connectionstyle=_cs1))
25 | _cs2 = "angle,angleA=-10,angleB=60,rad=10"
26 | ax.annotate('flooding duration', xy=(110, 2.7), xytext=(150, 2.7),
27 | bbox=bbox, arrowprops=dict(arrowstyle="->", connectionstyle=_cs2))
28 |
29 | plt.show()
30 |
--------------------------------------------------------------------------------
/docs/source/pyplots/sed_tools/_initial_bed_state.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import numpy as np
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 | # filter out the warning raised about no netcdf being found
9 | warnings.filterwarnings("ignore", category=UserWarning)
10 |
11 |
12 | # init delta model
13 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
14 | delta = pyDeltaRCM.DeltaModel(
15 | out_dir=output_dir,
16 | resume_checkpoint='../../_resources/checkpoint')
17 |
18 | _shp = delta.eta.shape
19 |
20 | # set up axis
21 | fig, ax = plt.subplots()
22 |
23 | # fill in axis2
24 | pyDeltaRCM.debug_tools.plot_domain(
25 | delta.eta, ax=ax, grid=False, cmap='cividis')
26 | ax.set_title('intial bed elevation (m)')
27 |
28 |
29 | plt.tight_layout()
30 | plt.show()
31 |
--------------------------------------------------------------------------------
/docs/source/pyplots/sed_tools/route_all_mud_parcels.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import numpy as np
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 | # filter out the warning raised about no netcdf being found
9 | warnings.filterwarnings("ignore", category=UserWarning)
10 |
11 |
12 | # init delta model
13 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
14 | delta = pyDeltaRCM.DeltaModel(
15 | out_dir=output_dir,
16 | resume_checkpoint='../../_resources/checkpoint')
17 |
18 | _shp = delta.eta.shape
19 |
20 | _eta_before = np.copy(delta.eta)
21 |
22 | delta.route_all_mud_parcels()
23 |
24 | _eta_after = np.copy(delta.eta)
25 |
26 |
27 | # set up axis
28 | fig, ax = plt.subplots()
29 |
30 | # fill in axis2
31 | _diff = _eta_after - _eta_before
32 | pyDeltaRCM.debug_tools.plot_domain(
33 | _diff, ax=ax, grid=False, cmap='RdBu',
34 | vmin=-0.1, vmax=0.1)
35 | ax.set_title('bed elevation change (m) \n due to mud parcels')
36 |
37 |
38 | plt.tight_layout()
39 | plt.show()
40 |
--------------------------------------------------------------------------------
/docs/source/pyplots/sed_tools/route_all_sand_parcels.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import numpy as np
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 | # filter out the warning raised about no netcdf being found
9 | warnings.filterwarnings("ignore", category=UserWarning)
10 |
11 |
12 | # init delta model
13 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
14 | delta = pyDeltaRCM.DeltaModel(
15 | out_dir=output_dir,
16 | resume_checkpoint='../../_resources/checkpoint')
17 |
18 | _shp = delta.eta.shape
19 |
20 | _eta_before = np.copy(delta.eta)
21 |
22 | delta.route_all_sand_parcels()
23 |
24 | _eta_after = np.copy(delta.eta)
25 |
26 |
27 | # set up axis
28 | fig, ax = plt.subplots()
29 |
30 | # fill in axis2
31 | _diff = _eta_after - _eta_before
32 | pyDeltaRCM.debug_tools.plot_domain(
33 | _diff, ax=ax, grid=False, cmap='RdBu',
34 | vmin=-0.1, vmax=0.1)
35 | ax.set_title('bed elevation change (m) \n due to sand parcels')
36 |
37 |
38 | plt.tight_layout()
39 | plt.show()
40 |
--------------------------------------------------------------------------------
/docs/source/pyplots/sed_tools/sediment_weights_examples.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | import pyDeltaRCM
8 |
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 10
15 | cm = matplotlib.colormaps['tab10']
16 |
17 |
18 | class SedimentWeightingCalculator(pyDeltaRCM.DeltaModel):
19 |
20 | def __init__(self, input_file=None, **kwargs) -> None:
21 |
22 | # inherit from base model
23 | super().__init__(input_file, **kwargs)
24 |
25 | def get_sediment_weight_array(self) -> None:
26 | sand_weights = np.zeros((self.L, self.W, 9))
27 | mud_weights = np.zeros((self.L, self.W, 9))
28 |
29 | for i in range(self.L):
30 | for j in range(self.W):
31 | stage_nbrs = self.pad_stage[i:i + 3, j:j + 3]
32 | depth_nbrs = self.pad_depth[i:i + 3, j:j + 3]
33 | ct_nbrs = self.pad_cell_type[i:i + 3, j:j + 3]
34 |
35 | _, weight_int = pyDeltaRCM.shared_tools.get_weight_sfc_int(
36 | self.stage[i, j], stage_nbrs.ravel(),
37 | self.qx[i, j], self.qy[i, j], self.ivec_flat,
38 | self.jvec_flat, self.distances_flat)
39 |
40 | try:
41 | sand_weights[i, j] = pyDeltaRCM.sed_tools._get_weight_at_cell_sediment(
42 | (i, j), weight_int, depth_nbrs.ravel(), ct_nbrs.ravel(),
43 | self.dry_depth, self.theta_sand, self.distances_flat)
44 |
45 | mud_weights[i, j] = pyDeltaRCM.sed_tools._get_weight_at_cell_sediment(
46 | (i, j), weight_int, depth_nbrs.ravel(), ct_nbrs.ravel(),
47 | self.dry_depth, self.theta_mud, self.distances_flat)
48 | except Exception:
49 | sand_weights[i, j] = np.nan
50 | mud_weights[i, j] = np.nan
51 |
52 | self.sand_weights = sand_weights
53 | self.mud_weights = mud_weights
54 |
55 |
56 | # init delta model
57 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
58 | delta = SedimentWeightingCalculator(
59 | out_dir=output_dir,
60 | resume_checkpoint='../../_resources/checkpoint')
61 |
62 | delta.init_water_iteration()
63 | delta.run_water_iteration()
64 | delta.compute_free_surface()
65 | delta.finalize_free_surface()
66 |
67 | delta.get_sediment_weight_array()
68 |
69 | _shp = delta.eta.shape
70 |
71 |
72 | # manually call only the necessary paths
73 | delta.init_water_iteration()
74 | delta.run_water_iteration()
75 |
76 |
77 | NPLOT = 5
78 | hdr: int = NPLOT // 2
79 |
80 | # fig, ax = plt.subplots()
81 | fig = plt.figure(figsize=(6, 9))
82 | gs = fig.add_gridspec(
83 | nrows=NPLOT+hdr, ncols=5,
84 | left=0.05, right=0.95, top=0.95, bottom=0.05,
85 | wspace=0.01, hspace=0.2)
86 |
87 | hdr_ax = fig.add_subplot(gs[:hdr, :])
88 | pyDeltaRCM.debug_tools.plot_domain(
89 | delta.eta, ax=hdr_ax, grid=False, cmap='cividis', vmin=-3, vmax=0.5)
90 | hdr_ax.set_xticks([])
91 | hdr_ax.set_yticks([])
92 | hdr_ax.set_xlim(0, delta.W // 2)
93 | hdr_ax.set_ylim(delta.L // 2, 0)
94 |
95 |
96 | def plot_pxpy_weights(pxpy, i):
97 |
98 | px, py = pxpy
99 |
100 | hdr_ax.text(py, px, str(i-hdr),
101 | fontsize=9, color='white',
102 | ha='center', va='center')
103 |
104 | __ax_list = []
105 |
106 | def _make_single_axis(i, j, values, **kwargs):
107 | __ax = fig.add_subplot(gs[i, j])
108 | __ax.set_xticks([])
109 | __ax.set_yticks([])
110 | __ax.imshow(values, **kwargs)
111 | for _i in range(3):
112 | for _j in range(3):
113 | __ax.text(
114 | _j, _i, str(np.round(values[_i, _j], 2)),
115 | ha='center', va='center', fontsize=8)
116 | return __ax
117 |
118 | # grab the data from the fields and put it into axis
119 | _eta_data = delta.eta[px-1:px+2, py-1:py+2]
120 | _eta_ax = _make_single_axis(
121 | i, 0, _eta_data, cmap='cividis', vmin=-3, vmax=0.5)
122 | __ax_list.append(_eta_ax)
123 |
124 | _dpth_data = delta.depth[px-1:px+2, py-1:py+2]
125 | _dpth_ax = _make_single_axis(
126 | i, 1, _dpth_data, cmap='Blues', vmin=0, vmax=5)
127 | __ax_list.append(_dpth_ax)
128 |
129 | _vel_data = delta.uw[px-1:px+2, py-1:py+2]
130 | _vel_ax = _make_single_axis(
131 | i, 2, _vel_data, cmap='plasma', vmin=0, vmax=1.5)
132 | __ax_list.append(_vel_ax)
133 |
134 | _sandwght_data = delta.sand_weights[px, py, :].reshape((3, 3))
135 | _sandwght_ax = _make_single_axis(
136 | i, 3, _sandwght_data, cmap='YlGn', vmin=0, vmax=1)
137 | __ax_list.append(_sandwght_ax)
138 |
139 | _mudwght_data = delta.mud_weights[px, py, :].reshape((3, 3))
140 | _mudwght_ax = _make_single_axis(
141 | i, 4, _mudwght_data, cmap='YlGn', vmin=0, vmax=1)
142 | __ax_list.append(_mudwght_ax)
143 |
144 | return __ax_list
145 |
146 |
147 | # define the example location set
148 | _ex_set = [(10, 94), (20, 78), (38, 72), (22, 87), (47, 43)]
149 |
150 |
151 | # plot the points
152 | ax0 = plot_pxpy_weights(_ex_set[0], hdr+0)
153 | ax1 = plot_pxpy_weights(_ex_set[1], hdr+1)
154 | ax2 = plot_pxpy_weights(_ex_set[2], hdr+2)
155 | ax3 = plot_pxpy_weights(_ex_set[3], hdr+3)
156 | ax4 = plot_pxpy_weights(_ex_set[4], hdr+4)
157 |
158 |
159 | # labels
160 | for a, axx in enumerate([ax0, ax1, ax2, ax3, ax4]):
161 | axx[0].set_ylabel(str(a), rotation=0, labelpad=10,
162 | ha='center', va='center')
163 |
164 | albls = ['bed elevation\n(eta)', 'depth',
165 | 'velocity\n(uw)', 'sand weights', 'mud weights']
166 | for a, (axx, albl) in enumerate(zip(ax4, albls)):
167 | axx.set_xlabel(albl)
168 |
169 | # show
170 | plt.show()
171 |
--------------------------------------------------------------------------------
/docs/source/pyplots/sed_tools/topo_diffusion.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import numpy as np
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 | # filter out the warning raised about no netcdf being found
9 | warnings.filterwarnings("ignore", category=UserWarning)
10 |
11 |
12 | # init delta model
13 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
14 | delta = pyDeltaRCM.DeltaModel(
15 | out_dir=output_dir,
16 | resume_checkpoint='../../_resources/checkpoint')
17 |
18 | _shp = delta.eta.shape
19 |
20 | delta.route_all_sand_parcels()
21 |
22 | _eta_before = np.copy(delta.eta)
23 | delta.topo_diffusion()
24 | _eta_after = np.copy(delta.eta)
25 |
26 | # set up axis
27 | fig, ax = plt.subplots(1, 3, sharex=True, sharey=True, figsize=(12, 4))
28 |
29 | # fill in axis0
30 | pyDeltaRCM.debug_tools.plot_domain(
31 | _eta_before, ax=ax[0], grid=False, cmap='cividis', vmin=-6)
32 | ax[0].set_title('bed elevation before \n topographic diffusion')
33 |
34 | # fill in axis1
35 | pyDeltaRCM.debug_tools.plot_domain(
36 | _eta_after, ax=ax[1], grid=False, cmap='cividis', vmin=-6)
37 | ax[1].set_title('bed elevation before \n topographic diffusion')
38 |
39 |
40 | # fill in axis2
41 | _diff = _eta_after - _eta_before
42 | pyDeltaRCM.debug_tools.plot_domain(
43 | _diff, ax=ax[2], grid=False, cmap='RdBu',
44 | vmin=-0.1, vmax=0.1)
45 | ax[2].set_title('difference (after - before)')
46 |
47 |
48 | plt.tight_layout()
49 | plt.show()
50 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/_accumulate_free_surface_walks.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | import pyDeltaRCM
8 |
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 1
15 | cm = matplotlib.colormaps['tab10']
16 |
17 |
18 | # init delta model
19 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
20 | delta = pyDeltaRCM.DeltaModel(
21 | out_dir=output_dir,
22 | resume_checkpoint='../../_resources/checkpoint')
23 | _shp = delta.eta.shape
24 |
25 |
26 | delta.init_water_iteration()
27 | delta.run_water_iteration()
28 |
29 |
30 | # define a function to fill in the walks of given idx
31 | def _plot_idxs_walks_to_step(delta_inds, _step, _idxs, _ax) -> None:
32 | for i in range(len(_idxs)):
33 | walk = delta_inds[_idxs[i], :]
34 | walk = walk[:_step]
35 | # print(walk)
36 | pyDeltaRCM.debug_tools.plot_line(
37 | walk, shape=_shp, color='c',
38 | multiline=True, nozeros=True)
39 | yend, xend = pyDeltaRCM.shared_tools.custom_unravel(walk[-1], _shp)
40 | _ax.plot(xend, yend,
41 | marker='o', ms=3, color='c')
42 |
43 |
44 | # declare the idxs to use:
45 | idxs = np.random.randint(low=0, high=delta._Np_water, size=n)
46 | pidx = 85
47 |
48 |
49 | # set up axis
50 | # fig, ax = plt.subplots(1, 4, figsize=(10, 5))
51 | fig = plt.figure()
52 | gs = fig.add_gridspec(
53 | 2, 2,
54 | wspace=0.3,
55 | left=0.1, right=0.9)
56 |
57 |
58 | # fill in axis0
59 | ax0 = fig.add_subplot(gs[0, 0])
60 | pyDeltaRCM.debug_tools.plot_domain(
61 | delta.eta, ax=ax0, grid=False, cmap='cividis')
62 | _plot_idxs_walks_to_step(
63 | delta.free_surf_walk_inds, _step=pidx, _idxs=idxs, _ax=ax0)
64 | ax0.set_title('bed elevation')
65 |
66 |
67 | # fill in axis0
68 | ax1 = fig.add_subplot(gs[0, 1])
69 | pyDeltaRCM.debug_tools.plot_domain(
70 | delta.stage, ax=ax1, grid=False)
71 | _plot_idxs_walks_to_step(delta.free_surf_walk_inds, _step=pidx, _idxs=idxs, _ax=ax1)
72 | ax1.set_title('water surface (stage)')
73 |
74 |
75 | ax2 = fig.add_subplot(gs[1, :])
76 | ax2.axhline(y=0, xmin=0, xmax=pidx+1, ls='--', color='0.6')
77 | for i in range(n):
78 | walk = delta.free_surf_walk_inds[idxs[i], :]
79 | walk = walk[:pidx]
80 |
81 | ax2.plot(delta.eta.flat[walk], 'k-')
82 | ax2.plot(delta.stage.flat[walk], '-', color=cm(i))
83 |
84 | ax2.set_ylabel('elevation')
85 | ax2.set_xlabel('steps along parcel path')
86 |
87 | plt.show()
88 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/_check_for_loops.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import numpy as np
4 | import matplotlib
5 | import matplotlib.pyplot as plt
6 | from matplotlib.patches import Rectangle
7 |
8 | import pyDeltaRCM
9 | from pyDeltaRCM import water_tools
10 |
11 |
12 | # filter out the warning raised about no netcdf being found
13 | warnings.filterwarnings("ignore", category=UserWarning)
14 |
15 |
16 | n = 10
17 | cm = matplotlib.colormaps['tab10']
18 |
19 |
20 | # init delta model
21 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
22 | delta = pyDeltaRCM.DeltaModel(
23 | out_dir=output_dir,
24 | resume_checkpoint='../../_resources/checkpoint')
25 | _shp = delta.eta.shape
26 |
27 |
28 | # determine the index to plot at
29 | pidx = 40
30 | Npts = 5
31 | jidx = np.random.randint(0, delta._Np_water, Npts)
32 |
33 | # run an interation from the checkpoint
34 | delta.init_water_iteration()
35 | delta.run_water_iteration()
36 |
37 | # here, we recreate some steps of each iteration, in order to set up the
38 | # arrays needed to display the action of _check_for_loops
39 | #
40 | # 1. extract the water walks
41 | current_inds = delta.free_surf_walk_inds[:, pidx-1]
42 | #
43 | # 2. use water weights and random pick to determine d8 direction
44 | water_weights_flat = delta.water_weights.reshape(-1, 9)
45 | new_direction = water_tools._choose_next_directions(
46 | current_inds, water_weights_flat)
47 | new_direction = new_direction.astype(int)
48 | #
49 | # 3. use the new directions for each parcel to determine the new ind for
50 | # each parcel
51 | new_inds = water_tools._calculate_new_inds(
52 | current_inds,
53 | new_direction,
54 | delta.ravel_walk_flat)
55 | new_inds0 = np.copy(new_inds)
56 |
57 | # choose N indices randomly to jump
58 | new_inds[jidx] = delta.free_surf_walk_inds[jidx, pidx-2]
59 |
60 | # copy inputs and then run the function to get new outputs
61 | new_inds, looped = water_tools._check_for_loops(
62 | delta.free_surf_walk_inds[:, :pidx-1], new_inds, pidx + 1, delta.L0,
63 | delta.CTR, delta.stage - delta.H_SL)
64 |
65 |
66 | # make the figure
67 | fig, ax = plt.subplots(1, 2, figsize=(10, 4))
68 |
69 | delta.show_attribute('eta', ax=ax[0], grid=False, cmap='cividis')
70 | delta.show_attribute('eta', ax=ax[1], grid=False, cmap='cividis')
71 |
72 |
73 | def _fill_out_an_axis(_ax, _sc=1):
74 | for j in range(len(jidx)):
75 | walk = delta.free_surf_walk_inds[jidx[j], :]
76 | walk = walk[:pidx-2]
77 | yend, xend = pyDeltaRCM.shared_tools.custom_unravel(
78 | walk[-1], _shp)
79 | ynew, xnew = pyDeltaRCM.shared_tools.custom_unravel(
80 | new_inds[jidx[j]], _shp)
81 | pyDeltaRCM.debug_tools.plot_line(
82 | walk, shape=_shp, color=cm(j),
83 | multiline=True, nozeros=True, lw=1.5*_sc, ax=_ax)
84 | _ax.plot(xend, yend,
85 | marker='o', ms=3*_sc, color=cm(j))
86 | _ax.plot(xnew, ynew,
87 | marker='o', ms=3*_sc, color=cm(j))
88 |
89 | # return the last set
90 | return yend, xend, ynew, xnew
91 |
92 |
93 | # fill out both axes with the same info
94 | _fill_out_an_axis(_ax=ax[0])
95 | yend, xend, ynew, xnew = _fill_out_an_axis(_ax=ax[1], _sc=2)
96 |
97 | # sub region of the original image
98 | _f = int(delta.W / delta.L) # ensure x-y scale same
99 | _s = 10
100 | x1, x2, y1, y2 = xend-(_s*_f), xnew+(_s*_f), yend-(_s), ynew+(_s)
101 | ax[1].set_xlim(x1, x2)
102 | ax[1].set_ylim(y2, y1)
103 | ax[1].set_xticks([])
104 | ax[1].set_yticks([])
105 |
106 | _r = Rectangle((x1, y2), _s*_f*2, -_s*2, ec='k', fc='none')
107 | ax[0].add_patch(_r)
108 |
109 | plt.show()
110 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/_smooth_free_surface.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib.pyplot as plt
4 | import matplotlib
5 |
6 | import pyDeltaRCM
7 |
8 | # filter out the warning raised about no netcdf being found
9 | warnings.filterwarnings("ignore", category=UserWarning)
10 |
11 |
12 | n = 10
13 | cm = matplotlib.colormaps['tab10']
14 |
15 |
16 | # init delta model
17 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
18 | delta = pyDeltaRCM.DeltaModel(
19 | out_dir=output_dir,
20 | resume_checkpoint='../../_resources/checkpoint')
21 |
22 |
23 | _shp = delta.eta.shape
24 |
25 |
26 | # manually call only the necessary paths
27 | delta.init_water_iteration()
28 | delta.run_water_iteration()
29 |
30 | # lines cobbled together from compute_free_surface and finalize_free_surface
31 | delta.sfc_visit, delta.sfc_sum = pyDeltaRCM.water_tools._accumulate_free_surface_walks(
32 | delta.free_surf_walk_inds, delta.free_surf_flag, delta.cell_type,
33 | delta.uw, delta.ux, delta.uy, delta.depth,
34 | delta._dx, delta._u0, delta.h0, delta._H_SL, delta._S0)
35 | Hnew = delta.eta + delta.depth
36 | Hnew[delta.sfc_visit > 0] = (delta.sfc_sum[delta.sfc_visit > 0] /
37 | delta.sfc_visit[delta.sfc_visit > 0])
38 | Hnew[Hnew < delta._H_SL] = delta._H_SL
39 | Hnew[Hnew < delta.eta] = delta.eta[Hnew < delta.eta]
40 |
41 | # now run the smoothing function to get grids
42 | Hsmth = pyDeltaRCM.water_tools._smooth_free_surface(
43 | Hnew, delta.cell_type, delta._Nsmooth, delta._Csmooth)
44 |
45 | # set up axis
46 | fig, ax = plt.subplots(1, 3, sharex=True, sharey=True, figsize=(12, 4))
47 |
48 | # fill in axis0
49 | pyDeltaRCM.debug_tools.plot_domain(
50 | Hnew, ax=ax[0], grid=False, cmap='viridis')
51 | ax[0].set_title('stage before smoothing')
52 |
53 | # fill in axis1
54 | pyDeltaRCM.debug_tools.plot_domain(
55 | Hsmth, ax=ax[1], grid=False, cmap='viridis')
56 | ax[1].set_title('stage after smoothing')
57 |
58 |
59 | # fill in axis2
60 | _diff = Hsmth - Hnew
61 | pyDeltaRCM.debug_tools.plot_domain(
62 | _diff, ax=ax[2], grid=False, cmap='RdBu',
63 | vmin=-0.1, vmax=0.1)
64 | ax[2].set_title('difference (after - before)')
65 |
66 |
67 | plt.tight_layout()
68 | plt.show()
69 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/compute_free_surface_inputs.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 |
6 | import pyDeltaRCM
7 |
8 |
9 | # filter out the warning raised about no netcdf being found
10 | warnings.filterwarnings("ignore", category=UserWarning)
11 |
12 |
13 | n = 1
14 | cm = matplotlib.colormaps['tab10']
15 |
16 |
17 | # init delta model
18 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
19 | delta = pyDeltaRCM.DeltaModel(
20 | out_dir=output_dir,
21 | resume_checkpoint='../../_resources/checkpoint')
22 | _shp = delta.eta.shape
23 |
24 |
25 | delta.init_water_iteration()
26 | delta.run_water_iteration()
27 |
28 |
29 | fig, ax = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(9, 3))
30 |
31 | # fill in axis
32 | pyDeltaRCM.debug_tools.plot_domain(
33 | delta.eta, ax=ax[0], grid=False, cmap='cividis',
34 | label='bed elevation (m)')
35 | pyDeltaRCM.debug_tools.plot_domain(
36 | delta.eta, ax=ax[1], grid=False, cmap='cividis',
37 | label='bed elevation (m)')
38 | delta.show_line(delta.free_surf_walk_inds[::10, :].T, 'k-',
39 | ax=ax[1], alpha=0.1,
40 | multiline=True, nozeros=True)
41 |
42 | fig.show()
43 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/compute_free_surface_outputs.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | import pyDeltaRCM
8 |
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 1
15 | cm = matplotlib.colormaps['tab10']
16 |
17 |
18 | # init delta model
19 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
20 | delta = pyDeltaRCM.DeltaModel(
21 | out_dir=output_dir,
22 | resume_checkpoint='../../_resources/checkpoint')
23 | _shp = delta.eta.shape
24 |
25 |
26 | delta.init_water_iteration()
27 | delta.run_water_iteration()
28 | delta.compute_free_surface()
29 |
30 |
31 | # pidx = 60
32 |
33 | # sfc_visit, sfc_sum = pyDeltaRCM.water_tools._accumulate_free_surface_walks(
34 | # delta.free_surf_walk_inds, delta.free_surf_flag, delta.cell_type,
35 | # delta.uw, delta.ux, delta.uy, delta.depth,
36 | # delta._dx, delta._u0, delta.h0, delta._H_SL, delta._S0)
37 |
38 |
39 | Hnew = np.full_like(delta.sfc_visit, np.nan)
40 | Hnew[delta.sfc_visit > 0] = (delta.sfc_sum[delta.sfc_visit > 0] /
41 | delta.sfc_visit[delta.sfc_visit > 0])
42 |
43 |
44 | # stage_new = delta.eta + delta.depth
45 | # stage_new[delta.sfc_visit > 0] = (delta.sfc_sum[delta.sfc_visit > 0] /
46 | # delta.sfc_visit[delta.sfc_visit > 0])
47 |
48 |
49 | fig, ax = plt.subplots(2, 2, sharex=True, sharey=True, figsize=(9, 4))
50 |
51 | pyDeltaRCM.debug_tools.plot_domain(
52 | delta.sfc_visit, ax=ax[0, 0], grid=False, cmap='Greys',
53 | label='sfc_visit (-)')
54 | pyDeltaRCM.debug_tools.plot_domain(
55 | delta.sfc_sum, ax=ax[0, 1], grid=False, cmap='Blues',
56 | label='sfc_sum (m)')
57 |
58 | pyDeltaRCM.debug_tools.plot_domain(
59 | Hnew, ax=ax[1, 0], grid=False,
60 | label='computed Hnew (m)')
61 | pyDeltaRCM.debug_tools.plot_domain(
62 | delta.Hnew, ax=ax[1, 1], grid=False,
63 | label='stage (m)')
64 |
65 | fig.show()
66 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/flooding_correction.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import numpy as np
4 | import matplotlib.pyplot as plt
5 | import matplotlib
6 |
7 | import pyDeltaRCM
8 |
9 | # filter out the warning raised about no netcdf being found
10 | warnings.filterwarnings("ignore", category=UserWarning)
11 |
12 |
13 | n = 10
14 | cm = matplotlib.colormaps['tab10']
15 |
16 |
17 | # init delta model
18 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
19 | delta = pyDeltaRCM.DeltaModel(
20 | out_dir=output_dir,
21 | resume_checkpoint='../../_resources/checkpoint')
22 |
23 |
24 | _shp = delta.eta.shape
25 |
26 |
27 | # manually call only the necessary paths
28 | delta.init_water_iteration()
29 | delta.run_water_iteration()
30 |
31 | # lines cobbled together from compute_free_surface and finalize_free_surface
32 | delta.sfc_visit, delta.sfc_sum = pyDeltaRCM.water_tools._accumulate_free_surface_walks(
33 | delta.free_surf_walk_inds, delta.free_surf_flag, delta.cell_type,
34 | delta.uw, delta.ux, delta.uy, delta.depth,
35 | delta._dx, delta._u0, delta.h0, delta._H_SL, delta._S0)
36 | Hnew = delta.eta + delta.depth
37 | Hnew[delta.sfc_visit > 0] = (delta.sfc_sum[delta.sfc_visit > 0] /
38 | delta.sfc_visit[delta.sfc_visit > 0])
39 | Hnew[Hnew < delta._H_SL] = delta._H_SL
40 | Hnew[Hnew < delta.eta] = delta.eta[Hnew < delta.eta]
41 |
42 | # now run the smoothing function to get grids
43 | Hsmth = pyDeltaRCM.water_tools._smooth_free_surface(
44 | Hnew, delta.cell_type, delta._Nsmooth, delta._Csmooth)
45 |
46 | delta.stage = (((1 - delta._omega_sfc) * delta.stage) +
47 | (delta._omega_sfc * Hsmth))
48 |
49 | before_flood = np.copy(delta.stage)
50 | delta.flooding_correction()
51 | after_flood = np.copy(delta.stage)
52 |
53 | # set up axis
54 | fig, ax = plt.subplots(1, 3, sharex=True, sharey=True, figsize=(12, 4))
55 |
56 | # fill in axis0
57 | pyDeltaRCM.debug_tools.plot_domain(
58 | before_flood, ax=ax[0], grid=False, cmap='viridis')
59 | ax[0].set_title('stage before flooding correction')
60 |
61 | # fill in axis1
62 | pyDeltaRCM.debug_tools.plot_domain(
63 | after_flood, ax=ax[1], grid=False, cmap='viridis')
64 | ax[1].set_title('stage after flooding correction')
65 |
66 |
67 | # fill in axis2
68 | _diff = after_flood - before_flood
69 | pyDeltaRCM.debug_tools.plot_domain(
70 | _diff, ax=ax[2], grid=False, cmap='RdBu',
71 | vmin=-0.1, vmax=0.1)
72 | ax[2].set_title('difference (after - before)')
73 |
74 |
75 | plt.tight_layout()
76 | plt.show()
77 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/run_water_iteration.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | import pyDeltaRCM
8 |
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 10
15 | cm = matplotlib.colormaps['tab10']
16 |
17 |
18 | # init delta model
19 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
20 | delta = pyDeltaRCM.DeltaModel(
21 | out_dir=output_dir)
22 |
23 | delta_later = pyDeltaRCM.DeltaModel(
24 | out_dir=output_dir,
25 | resume_checkpoint='../../_resources/checkpoint')
26 |
27 |
28 | _shp = delta_later.eta.shape
29 |
30 |
31 | # manually call only the necessary paths
32 | delta.init_water_iteration()
33 | delta.run_water_iteration()
34 |
35 | delta_later.init_water_iteration()
36 | delta_later.run_water_iteration()
37 |
38 |
39 | # define a function to fill in the walks of given idx
40 | def _plot_idxs_walks_to_step(delta_inds, _step, _idxs, _ax) -> None:
41 | for i in range(len(_idxs)):
42 | iidx = _idxs[i]
43 | walk = delta_inds[iidx, :]
44 | walk = walk[:_step]
45 | pyDeltaRCM.debug_tools.plot_line(
46 | walk, shape=_shp, color=cm(i),
47 | nozeros=True)
48 | yend, xend = pyDeltaRCM.shared_tools.custom_unravel(
49 | walk[-1], _shp)
50 | _ax.plot(xend, yend,
51 | marker='o', ms=3, color=cm(i))
52 |
53 |
54 | # declare the idxs to use:
55 | idxs = np.random.randint(low=0, high=delta._Np_water, size=n)
56 | ps = [5, 25, 75]
57 |
58 | # set up axis
59 | fig, ax = plt.subplots(2, 3, sharex=True, sharey=True, figsize=(12, 4))
60 | vmin, vmax = delta.eta.min(), delta.eta.max()
61 |
62 | # fill in axis0
63 | pyDeltaRCM.debug_tools.plot_domain(
64 | delta.eta, ax=ax[0, 0], grid=False, cmap='cividis')
65 | _plot_idxs_walks_to_step(
66 | delta.free_surf_walk_inds, _step=ps[0], _idxs=idxs, _ax=ax[0, 0])
67 | ax[0, 0].set_title('after {} steps'.format(ps[0]))
68 | pyDeltaRCM.debug_tools.plot_domain(
69 | delta_later.eta, ax=ax[1, 0], grid=False, vmin=vmin, vmax=vmax, cmap='cividis')
70 | _plot_idxs_walks_to_step(
71 | delta_later.free_surf_walk_inds, _step=ps[0], _idxs=idxs, _ax=ax[1, 0])
72 | # ax[1, 0].set_title('after {} steps'.format(ps[0]))
73 |
74 |
75 | # fill in axis1
76 | pyDeltaRCM.debug_tools.plot_domain(
77 | delta.eta, ax=ax[0, 1], grid=False, cmap='cividis')
78 | _plot_idxs_walks_to_step(
79 | delta.free_surf_walk_inds, _step=ps[1], _idxs=idxs, _ax=ax[0, 1])
80 | ax[0, 1].set_title('after {} steps'.format(ps[1]))
81 | pyDeltaRCM.debug_tools.plot_domain(
82 | delta_later.eta, ax=ax[1, 1], grid=False, vmin=vmin, vmax=vmax, cmap='cividis')
83 | _plot_idxs_walks_to_step(
84 | delta_later.free_surf_walk_inds, _step=ps[1], _idxs=idxs, _ax=ax[1, 1])
85 | # ax[1, 1].set_title('after {} steps'.format(ps[1]))
86 |
87 |
88 | # fill in axis2
89 | pyDeltaRCM.debug_tools.plot_domain(
90 | delta.eta, ax=ax[0, 2], grid=False, cmap='cividis')
91 | _plot_idxs_walks_to_step(
92 | delta.free_surf_walk_inds, _step=ps[2], _idxs=idxs, _ax=ax[0, 2])
93 | ax[0, 2].set_title('after {} steps'.format(ps[2]))
94 | pyDeltaRCM.debug_tools.plot_domain(
95 | delta_later.eta, ax=ax[1, 2], grid=False, vmin=vmin, vmax=vmax, cmap='cividis')
96 | _plot_idxs_walks_to_step(
97 | delta_later.free_surf_walk_inds, _step=ps[2], _idxs=idxs, _ax=ax[1, 2])
98 | # ax[1, 3].set_title('after {} steps'.format(ps[3]))
99 |
100 |
101 | plt.tight_layout()
102 | plt.show()
103 |
--------------------------------------------------------------------------------
/docs/source/pyplots/water_tools/water_weights_examples.py:
--------------------------------------------------------------------------------
1 | import warnings
2 |
3 | import matplotlib
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | import pyDeltaRCM
8 |
9 |
10 | # filter out the warning raised about no netcdf being found
11 | warnings.filterwarnings("ignore", category=UserWarning)
12 |
13 |
14 | n = 10
15 | cm = matplotlib.colormaps['tab10']
16 |
17 | # init delta model
18 | with pyDeltaRCM.shared_tools._docs_temp_directory() as output_dir:
19 | delta = pyDeltaRCM.DeltaModel(
20 | out_dir=output_dir,
21 | resume_checkpoint='../../_resources/checkpoint')
22 |
23 | _shp = delta.eta.shape
24 |
25 |
26 | # manually call only the necessary paths
27 | delta.init_water_iteration()
28 | delta.run_water_iteration()
29 |
30 |
31 | NPLOT = 5
32 | hdr: int = NPLOT // 2
33 |
34 | # fig, ax = plt.subplots()
35 | fig = plt.figure(figsize=(6, 9))
36 | gs = fig.add_gridspec(
37 | nrows=NPLOT+hdr, ncols=5,
38 | left=0.05, right=0.95, top=0.95, bottom=0.05,
39 | wspace=0.01, hspace=0.2)
40 |
41 | hdr_ax = fig.add_subplot(gs[:hdr, :])
42 | pyDeltaRCM.debug_tools.plot_domain(
43 | delta.eta, ax=hdr_ax, grid=False, cmap='cividis', vmin=-3, vmax=0.5)
44 | hdr_ax.set_xticks([])
45 | hdr_ax.set_yticks([])
46 | hdr_ax.set_xlim(0, delta.W // 2)
47 | hdr_ax.set_ylim(delta.L // 2, 0)
48 |
49 |
50 | def plot_pxpy_weights(pxpy, i):
51 |
52 | px, py = pxpy
53 |
54 | hdr_ax.text(py, px, str(i-hdr),
55 | fontsize=9, color='white',
56 | ha='center', va='center')
57 |
58 | __ax_list = []
59 |
60 | def _make_single_axis(i, j, values, **kwargs):
61 | __ax = fig.add_subplot(gs[i, j])
62 | __ax.set_xticks([])
63 | __ax.set_yticks([])
64 | __ax.imshow(values, **kwargs)
65 | for _i in range(3):
66 | for _j in range(3):
67 | __ax.text(
68 | _j, _i, str(np.round(values[_i, _j], 2)),
69 | ha='center', va='center', fontsize=8)
70 | return __ax
71 |
72 | # grab the data from the fields and put it into axis
73 | _eta_data = delta.eta[px-1:px+2, py-1:py+2]
74 | _eta_ax = _make_single_axis(
75 | i, 0, _eta_data, cmap='cividis', vmin=-3, vmax=0.5)
76 | __ax_list.append(_eta_ax)
77 |
78 | _dpth_data = delta.depth[px-1:px+2, py-1:py+2]
79 | _dpth_ax = _make_single_axis(
80 | i, 1, _dpth_data, cmap='Blues', vmin=0, vmax=5)
81 | __ax_list.append(_dpth_ax)
82 |
83 | _stge_data = delta.stage[px-1:px+2, py-1:py+2]
84 | _stge_ax = _make_single_axis(
85 | i, 2, _stge_data, cmap='viridis', vmin=0, vmax=5)
86 | __ax_list.append(_stge_ax)
87 |
88 | _vel_data = delta.uw[px-1:px+2, py-1:py+2]
89 | _vel_ax = _make_single_axis(
90 | i, 3, _vel_data, cmap='plasma', vmin=0, vmax=1.5)
91 | __ax_list.append(_vel_ax)
92 |
93 | _wght_data = delta.water_weights[px, py, :].reshape((3, 3))
94 | _wght_ax = _make_single_axis(
95 | i, 4, _wght_data, cmap='YlGn', vmin=0, vmax=1)
96 | __ax_list.append(_wght_ax)
97 |
98 | return __ax_list
99 |
100 |
101 | # define the example location set
102 | _ex_set = [(10, 94), (20, 78), (38, 72), (22, 87), (47, 43)]
103 |
104 |
105 | # plot the points
106 | ax0 = plot_pxpy_weights(_ex_set[0], hdr+0)
107 | ax1 = plot_pxpy_weights(_ex_set[1], hdr+1)
108 | ax2 = plot_pxpy_weights(_ex_set[2], hdr+2)
109 | ax3 = plot_pxpy_weights(_ex_set[3], hdr+3)
110 | ax4 = plot_pxpy_weights(_ex_set[4], hdr+4)
111 |
112 | # labels
113 | for a, axx in enumerate([ax0, ax1, ax2, ax3, ax4]):
114 | axx[0].set_ylabel(str(a), rotation=0, labelpad=10,
115 | ha='center', va='center')
116 |
117 | albls = ['bed elevation\n(eta)', 'depth',
118 | 'stage', 'velocity\n(uw)', 'water weights']
119 | for a, (axx, albl) in enumerate(zip(ax4, albls)):
120 | axx.set_xlabel(albl)
121 |
122 | # show
123 | plt.show()
124 |
--------------------------------------------------------------------------------
/docs/source/reference/debug_tools/index.rst:
--------------------------------------------------------------------------------
1 | .. api.debug_tools:
2 |
3 | ***********
4 | debug_tools
5 | ***********
6 |
7 | .. currentmodule:: pyDeltaRCM.debug_tools
8 |
9 | The debugging tools are defined in ``pyDeltaRCM.debug_tools``.
10 |
11 | .. todo::
12 |
13 | Add paragraph description of the module. What stages are defined here generally?
14 |
15 |
16 | Public API methods attached to model
17 | ------------------------------------
18 |
19 | The following methods are defined in the ``debug_tools`` class, of the ``pyDeltaRCM.debug_tools`` module.
20 | They are then attached as methods of the `DeltaModel` and can be called at any time during run.
21 |
22 | .. autosummary::
23 |
24 | debug_tools
25 |
26 | .. autoclass:: debug_tools
27 |
28 |
29 | Public plotting methods
30 | -----------------------
31 |
32 | The functions defined below are (generally) the actual workers that handle the plotting for the methods defined above and attached to model.
33 | We expose these functions here because they are be useful in the documentation, where they are used extensively.
34 |
35 | .. autofunction:: plot_domain
36 | .. autofunction:: plot_ind
37 | .. autofunction:: plot_line
38 |
--------------------------------------------------------------------------------
/docs/source/reference/hook_tools/index.rst:
--------------------------------------------------------------------------------
1 | *********************************
2 | hook_tools
3 | *********************************
4 |
5 | .. currentmodule:: pyDeltaRCM.hook_tools
6 |
7 | .. todo::
8 |
9 | Add paragraph description of the module. What stages are defined here generally? Link to relevant documentation about hooks in user guide and model list.
10 |
11 |
12 | Public API methods attached to model
13 | ------------------------------------
14 |
15 | The following methods are defined in the ``hook_tools`` class, of the ``pyDeltaRCM.hook_tools`` module.
16 |
17 | .. autosummary::
18 |
19 | hook_tools
20 |
21 | .. autoclass:: hook_tools
22 |
--------------------------------------------------------------------------------
/docs/source/reference/index.rst:
--------------------------------------------------------------------------------
1 | .. api:
2 |
3 | =============
4 | API reference
5 | =============
6 |
7 | The :obj:`DeltaModel` class, defined in `pyDeltaRCM.model`, is the main class of pyDeltaRCM, which provides the object that is manipulated to evolve the numerical delta model.
8 | This class uses "mix-in" classes, which are defined in separate files (Python `modules`), that break out logically based on the various stages of model use, and components of the model iteration sequence.
9 | Most model functionality is organized into the various mix-in classes, that are then inherited by the `DeltaModel`.
10 | Additionally, several routines of the model are organized into module-level functions, which are "jitted" via the `numba `_ code optimizer library for Python.
11 |
12 | This index lists the `pyDeltaRCM` organization, hopefully providing enough information to begin to determine where various components of the model are implemented.
13 | The index includes model classes, methods, and attributes, as well as additionally utility classes and functions.
14 |
15 | .. toctree::
16 | :maxdepth: 2
17 |
18 | model/index
19 | preprocessor/index
20 | iteration_tools/index
21 | init_tools/index
22 | water_tools/index
23 | sed_tools/index
24 | shared_tools/index
25 | hook_tools/index
26 | debug_tools/index
27 |
28 |
29 | References
30 | ----------
31 |
32 | * :ref:`modindex`
33 | * :ref:`search`
34 |
35 |
36 | Search the Index
37 | ==================
38 |
39 | * :ref:`genindex`
40 |
--------------------------------------------------------------------------------
/docs/source/reference/init_tools/index.rst:
--------------------------------------------------------------------------------
1 | .. api.init_tools:
2 |
3 | **********
4 | init_tools
5 | **********
6 |
7 | .. currentmodule:: pyDeltaRCM.init_tools
8 |
9 |
10 | The model initialization is managed by :obj:`~pyDeltaRCM.model.DeltaModel.__init__`, but the actual initialization is mostly handled by routines in `init_tools`.
11 | The major steps of initialization are:
12 |
13 | .. autosummary::
14 |
15 | init_tools.import_files
16 | init_tools.init_logger
17 | init_tools.process_input_to_model
18 | init_tools.determine_random_seed
19 | init_tools.create_other_variables
20 | init_tools.create_domain
21 | init_tools.init_sediment_routers
22 | init_tools.init_subsidence
23 |
24 | and then depending on the checkpointing configuration, the following methods may be called:
25 |
26 | .. autosummary::
27 |
28 | init_tools.load_checkpoint
29 | init_tools.init_output_file
30 | pyDeltaRCM.iteration_tools.iteration_tools.output_data
31 | pyDeltaRCM.iteration_tools.iteration_tools.output_checkpoint
32 | pyDeltaRCM.iteration_tools.iteration_tools.log_model_time
33 |
34 |
35 | Public API methods attached to model
36 | ------------------------------------
37 |
38 | The following methods are defined in the ``init_tools`` class, of the ``pyDeltaRCM.init_tools`` module.
39 |
40 | .. currentmodule:: pyDeltaRCM.init_tools
41 |
42 | .. autosummary::
43 |
44 | init_tools
45 |
46 | .. autoclass:: init_tools
47 |
--------------------------------------------------------------------------------
/docs/source/reference/iteration_tools/index.rst:
--------------------------------------------------------------------------------
1 | .. api.iteration_tools:
2 |
3 | ***************
4 | iteration_tools
5 | ***************
6 |
7 | .. currentmodule:: pyDeltaRCM.iteration_tools
8 |
9 | .. todo::
10 |
11 | Add paragraph description of the module. What stages are defined here generally? Make a table with the main ones like in water tools?
12 |
13 |
14 | Public API methods attached to model
15 | ------------------------------------
16 |
17 | The following methods are defined in the ``iteration_tools`` class, of the ``pyDeltaRCM.iteration_tools`` module.
18 |
19 | .. autosummary::
20 |
21 | iteration_tools
22 |
23 | .. autoclass:: iteration_tools
24 |
--------------------------------------------------------------------------------
/docs/source/reference/model/index.rst:
--------------------------------------------------------------------------------
1 | .. api.model:
2 |
3 | *****
4 | model
5 | *****
6 |
7 | This is the main model code.
8 |
9 | This class is defined in ``pyDeltaRCM.model``.
10 |
11 |
12 | The DeltaModel class and all attributes and methods
13 | ---------------------------------------------------
14 |
15 | .. currentmodule:: pyDeltaRCM.model
16 |
17 | .. autosummary::
18 | :toctree: ../../_autosummary
19 |
20 | ~DeltaModel
21 |
22 |
23 |
24 |
25 | Model configuration reference
26 | -----------------------------
27 |
28 | .. toctree::
29 | :maxdepth: 1
30 |
31 | yaml_defaults
32 | model_hooks
33 |
--------------------------------------------------------------------------------
/docs/source/reference/model/model_hooks.rst:
--------------------------------------------------------------------------------
1 | Available Model Hooks
2 | =====================
3 |
4 | .. important::
5 |
6 | Have a suggestion for another `hook` in the DeltaModel? Get in touch via
7 | the GitHub issue tracker!
8 |
9 |
10 | Method hooks
11 | ------------
12 |
13 | As described extensively in the :ref:`User Guide on how to customize the model
14 | `, hooks are methods in the model sequence that do
15 | nothing by default, but can be augmented to provide arbitrary desired
16 | behavior in the model. Hooks have been integrated throughout the model
17 | initialization and update sequences, to allow the users to achieve complex
18 | behavior at various stages of the model sequence.
19 |
20 | A complete list of hooks in the model follows:
21 |
22 | .. currentmodule:: pyDeltaRCM.hook_tools
23 |
24 | .. csv-table:: Available model method hooks
25 | :header: "Initializing", "Updating"
26 | :widths: 40, 40
27 |
28 | :obj:`~hook_tools.hook_import_files`, :obj:`~hook_tools.hook_solve_water_and_sediment_timestep`
29 | :obj:`~hook_tools.hook_process_input_to_model`, :obj:`~hook_tools.hook_apply_subsidence`
30 | :obj:`~hook_tools.hook_create_other_variables`, :obj:`~hook_tools.hook_finalize_timestep`
31 | :obj:`~hook_tools.hook_create_domain`, :obj:`~hook_tools.hook_route_water`
32 | :obj:`~hook_tools.hook_load_checkpoint`, :obj:`~hook_tools.hook_init_water_iteration`
33 | :obj:`~hook_tools.hook_init_output_file`, :obj:`~hook_tools.hook_run_water_iteration`
34 | , :obj:`~hook_tools.hook_compute_free_surface`
35 | , :obj:`~hook_tools.hook_finalize_water_iteration`
36 | , :obj:`~hook_tools.hook_route_sediment`
37 | , :obj:`~hook_tools.hook_route_all_sand_parcels`
38 | , :obj:`~hook_tools.hook_topo_diffusion`
39 | , :obj:`~hook_tools.hook_route_all_mud_parcels`
40 | , :obj:`~hook_tools.hook_compute_sand_frac`
41 | , :obj:`~hook_tools.hook_after_route_water`
42 | , :obj:`~hook_tools.hook_after_route_sediment`
43 | , :obj:`~hook_tools.hook_output_data`
44 | , :obj:`~hook_tools.hook_output_checkpoint`
45 |
46 |
47 | Array hooks
48 | -----------
49 |
50 | The `DeltaModel` also incorporates a few arrays that enable a similar effect
51 | to method hooks. These arrays are initialized with all ``1`` or all ``0``
52 | values by default (depending on the scenario), and provide a convenient
53 | location to augment the model with varied behavior.
54 |
55 | A complete list of behavior-modifying arrays in the model follows:
56 |
57 | .. csv-table:: Available model array hooks
58 | :header: "Array name", "function", "default value"
59 | :widths: 20, 50, 10
60 |
61 | `mod_water_weight`, modifies the neighbor-weighting of water parcels during routing according to ``(depth * mod_water_weight)**theta_water``, 1
62 | `mod_sed_weight`, modifies the neighbor-weighting of the sediment parcel routing according to ``(depth * mod_sed_weight)**theta_sed``, 1
63 | `mod_erosion`, linearly modifies the "erodibility" of cells according to ``mod_erosion * Vp_sed * (U_loc**beta - U_ero**beta) / U_ero**beta``, 1
64 |
65 |
--------------------------------------------------------------------------------
/docs/source/reference/model/yaml_defaults.rst:
--------------------------------------------------------------------------------
1 | Default Model Variable Values
2 | =============================
3 |
4 | .. hint::
5 |
6 | A complete list of the meaning of each YAML parameter can be found at
7 | :doc:`../../info/yamlparameters`.
8 |
9 |
10 | Default model parameter values are defined as:
11 |
12 | .. literalinclude:: ../../../../pyDeltaRCM/default.yml
13 | :language: yaml
14 | :linenos:
15 |
--------------------------------------------------------------------------------
/docs/source/reference/preprocessor/index.rst:
--------------------------------------------------------------------------------
1 | .. api.preprocessor:
2 |
3 | *********************************
4 | Preprocessor
5 | *********************************
6 |
7 | .. currentmodule:: pyDeltaRCM.preprocessor
8 |
9 | The high-level API is principally defined in ``pyDeltaRCM.preprocessor``.
10 |
11 | .. todo::
12 |
13 | add paragraph description of the module. What can we do with this? Why does it exist? Link to the relevant documentation in the user guide and examples.
14 |
15 |
16 | Preprocessor classes and API
17 | ----------------------------
18 |
19 | The following classes are defined in the ``pyDeltaRCM.preprocessor`` module and enable the high-level model API to work at both the command line and as a Python object.
20 |
21 | .. autosummary::
22 | :toctree: ../../_autosummary
23 |
24 | PreprocessorCLI
25 | :members:
26 | :inherited-members:
27 |
28 | Preprocessor
29 | :members:
30 | :inherited-members:
31 |
32 | BasePreprocessor
33 |
34 | Preprocessor function and utilities
35 | -----------------------------------
36 |
37 | .. todo:: add description, what are these?
38 |
39 | .. autofunction:: preprocessor_wrapper
40 | .. autofunction:: scale_relative_sea_level_rise_rate
41 | .. autofunction:: _write_yaml_config_to_file
42 |
--------------------------------------------------------------------------------
/docs/source/reference/sed_tools/index.rst:
--------------------------------------------------------------------------------
1 | .. api.sed_tools:
2 |
3 | *********************************
4 | sed_tools
5 | *********************************
6 |
7 | .. currentmodule:: pyDeltaRCM.sed_tools
8 |
9 | .. todo:: add paragraph description of the module
10 |
11 |
12 | The tools are defined in ``pyDeltaRCM.sed_tools``.
13 |
14 |
15 | Public API methods attached to model
16 | ------------------------------------
17 |
18 | The following methods are defined in the ``sed_tools`` class, of the ``pyDeltaRCM.sed_tools`` module.
19 |
20 | .. autosummary::
21 |
22 | sed_tools
23 |
24 | .. autoclass:: sed_tools
25 |
26 |
27 | Router classes
28 | --------------
29 |
30 | The following classes are defined in the ``pyDeltaRCM.sed_tools`` module. These sediment routing classes are jitted for speed.
31 |
32 | .. autosummary::
33 | :toctree: ../../_autosummary
34 |
35 | SandRouter
36 | :members:
37 | :inherited-members:
38 | :private-members:
39 |
40 | MudRouter
41 | :members:
42 | :inherited-members:
43 | :private-members:
44 |
45 | BaseRouter
46 | :members:
47 | :inherited-members:
48 | :private-members:
49 |
50 | sed_tools helper functions
51 | ----------------------------
52 |
53 | Additionally, the sediment parcel step-weighting function is defined at the module level in ``pyDeltaRCM.sed_tools``.
54 |
55 | .. autofunction:: _get_weight_at_cell_sediment
56 |
--------------------------------------------------------------------------------
/docs/source/reference/shared_tools/index.rst:
--------------------------------------------------------------------------------
1 | .. api.shared_tools:
2 |
3 | *********************************
4 | shared_tools
5 | *********************************
6 |
7 | .. currentmodule:: pyDeltaRCM.shared_tools
8 |
9 |
10 | .. todo:: add paragraph description of the module
11 |
12 |
13 | The tools are defined in ``pyDeltaRCM.shared_tools``.
14 |
15 |
16 | Shared functions
17 | ----------------
18 |
19 | This module defines several functions that are used throughout the model, and so are organized here for convenience.
20 |
21 | .. autofunction:: get_random_uniform
22 | .. autofunction:: get_inlet_weights
23 | .. autofunction:: get_start_indices
24 | .. autofunction:: get_steps
25 | .. autofunction:: random_pick
26 | .. autofunction:: custom_unravel
27 | .. autofunction:: custom_ravel
28 | .. autofunction:: custom_pad
29 | .. autofunction:: get_weight_sfc_int
30 | .. autofunction:: custom_yaml_loader
31 |
32 |
33 | Time scaling functions
34 | ----------------------
35 |
36 | Scaling of real-world time and model time is an important topic covered in detail in :doc:`/info/modeltime`.
37 | Several functions are defined here which can help with scaling between model and real-world time.
38 |
39 | .. autofunction:: scale_model_time
40 | .. autofunction:: _scale_factor
41 |
42 |
43 | Utilities
44 | ---------
45 |
46 | Additionally, functions defined in ``pyDeltaRCM.shared_tools`` manage the random state of the model, and help with documentation and version management.
47 |
48 | .. autofunction:: set_random_seed
49 | .. autofunction:: get_random_state
50 | .. autofunction:: set_random_state
51 | .. autofunction:: _docs_temp_directory
52 | .. autofunction:: _get_version
53 |
--------------------------------------------------------------------------------
/docs/source/reference/water_tools/index.rst:
--------------------------------------------------------------------------------
1 | .. api.water_tools:
2 |
3 | *********************************
4 | water_tools
5 | *********************************
6 |
7 | .. currentmodule:: pyDeltaRCM.water_tools
8 |
9 |
10 | The :obj:`~pyDeltaRCM.water_tools.water_tools.route_water` routine manages the water routing.
11 | During :obj:`~pyDeltaRCM.water_tools.water_tools.route_water`, water iteration is repeated a total of :obj:`~pyDeltaRCM.model.DeltaModel.itermax` times.
12 | During each of these iterations of the water routing, the following methods are called *in order*:
13 |
14 | .. autosummary::
15 |
16 | water_tools.init_water_iteration
17 | water_tools.run_water_iteration
18 | water_tools.compute_free_surface
19 | water_tools.finalize_water_iteration
20 |
21 |
22 | Public API methods attached to model
23 | ------------------------------------
24 |
25 | The following methods are defined in the ``water_tools`` class, of the ``pyDeltaRCM.water_tools`` module.
26 |
27 | .. autosummary::
28 |
29 | water_tools
30 |
31 | .. autoclass:: water_tools
32 |
33 |
34 | water_tools helper functions
35 | ----------------------------
36 |
37 | The following routines are jitted for speed.
38 | They generally take a large number of arrays and constants and return a new array(s) to continue with the model progression within the methods defined above.
39 |
40 | .. autofunction:: _get_weight_at_cell_water
41 | .. autofunction:: _choose_next_directions
42 | .. autofunction:: _calculate_new_inds
43 | .. autofunction:: _check_for_loops
44 | .. autofunction:: _update_dirQfield
45 | .. autofunction:: _update_absQfield
46 | .. autofunction:: _accumulate_free_surface_walks
47 | .. autofunction:: _smooth_free_surface
48 |
--------------------------------------------------------------------------------
/pyDeltaRCM/__init__.py:
--------------------------------------------------------------------------------
1 | from .model import DeltaModel
2 | from .preprocessor import Preprocessor
3 | from .shared_tools import _get_version
4 |
5 | __all__ = ['DeltaModel', 'Preprocessor']
6 | __version__: str = _get_version()
7 |
--------------------------------------------------------------------------------
/pyDeltaRCM/__main__.py:
--------------------------------------------------------------------------------
1 | from . import preprocessor
2 |
3 | if __name__ == '__main__':
4 | preprocessor.preprocessor_wrapper()
5 |
--------------------------------------------------------------------------------
/pyDeltaRCM/_version.py:
--------------------------------------------------------------------------------
1 | def __version__() -> str:
2 | """
3 | Private version declaration, gets assigned to pyDeltaRCM.__version__
4 | during import
5 | """
6 | return "2.1.6"
7 |
--------------------------------------------------------------------------------
/pyDeltaRCM/default.yml:
--------------------------------------------------------------------------------
1 | out_dir:
2 | type: 'str'
3 | default: 'deltaRCM_Output'
4 | verbose:
5 | type: 'int'
6 | default: 0
7 | seed:
8 | type: ['int', 'None']
9 | default: null
10 | Length:
11 | type: ['float', 'int']
12 | default: 5000.
13 | Width:
14 | type: ['float', 'int']
15 | default: 10000.
16 | dx:
17 | type: ['float', 'int']
18 | default: 50.
19 | L0_meters:
20 | type: ['float', 'int']
21 | default: 150.0
22 | S0:
23 | type: ['float', 'int']
24 | default: 0.00015
25 | itermax:
26 | type: 'int'
27 | default: 3
28 | Np_water:
29 | type: 'int'
30 | default: 2000
31 | u0:
32 | type: ['float', 'int']
33 | default: 1.0
34 | N0_meters:
35 | type: ['float', 'int']
36 | default: 250.0
37 | h0:
38 | type: ['float', 'int']
39 | default: 5.0
40 | hb:
41 | type: ['float', 'int', 'None']
42 | default: null
43 | H_SL:
44 | type: ['float', 'int']
45 | default: 0.0
46 | SLR:
47 | type: ['float', 'int']
48 | default: 0.0
49 | Np_sed:
50 | type: 'int'
51 | default: 2000
52 | f_bedload:
53 | type: ['float', 'int']
54 | default: 0.5
55 | active_layer_thickness:
56 | type: ['float', 'int', 'None']
57 | default: null
58 | C0_percent:
59 | type: ['float', 'int']
60 | default: 0.1
61 | Csmooth:
62 | type: ['float', 'int']
63 | default: 0.9
64 | toggle_subsidence:
65 | type: 'bool'
66 | default: False
67 | subsidence_rate:
68 | type: ['float', 'int']
69 | default: 2e-9
70 | start_subsidence:
71 | type: ['float', 'int']
72 | default: 216000
73 | save_eta_figs:
74 | type: 'bool'
75 | default: False
76 | save_stage_figs:
77 | type: 'bool'
78 | default: False
79 | save_depth_figs:
80 | type: 'bool'
81 | default: False
82 | save_discharge_figs:
83 | type: 'bool'
84 | default: False
85 | save_velocity_figs:
86 | type: 'bool'
87 | default: False
88 | save_sedflux_figs:
89 | type: 'bool'
90 | default: False
91 | save_sandfrac_figs:
92 | type: 'bool'
93 | default: False
94 | save_figs_sequential:
95 | type: 'bool'
96 | default: True
97 | save_metadata:
98 | type: 'bool'
99 | default: False
100 | save_eta_grids:
101 | type: 'bool'
102 | default: False
103 | save_stage_grids:
104 | type: 'bool'
105 | default: False
106 | save_depth_grids:
107 | type: 'bool'
108 | default: False
109 | save_discharge_grids:
110 | type: 'bool'
111 | default: False
112 | save_velocity_grids:
113 | type: 'bool'
114 | default: False
115 | save_sedflux_grids:
116 | type: 'bool'
117 | default: False
118 | save_sandfrac_grids:
119 | type: 'bool'
120 | default: False
121 | save_discharge_components:
122 | type: 'bool'
123 | default: False
124 | save_velocity_components:
125 | type: 'bool'
126 | default: False
127 | save_dt:
128 | type: 'int'
129 | default: 86400
130 | checkpoint_dt:
131 | type: ['int', 'None']
132 | default: null
133 | save_checkpoint:
134 | type: 'bool'
135 | default: False
136 | resume_checkpoint:
137 | type: ['bool', 'str']
138 | default: False
139 | omega_sfc:
140 | type: ['float', 'int']
141 | default: 0.1
142 | omega_flow:
143 | type: ['float', 'int']
144 | default: 0.9
145 | Nsmooth:
146 | type: 'int'
147 | default: 10
148 | theta_water:
149 | type: ['float', 'int']
150 | default: 1.0
151 | coeff_theta_sand:
152 | type: ['float', 'int']
153 | default: 2.0
154 | coeff_theta_mud:
155 | type: ['float', 'int']
156 | default: 1.0
157 | beta:
158 | type: 'int'
159 | default: 3
160 | sed_lag:
161 | type: ['float', 'int']
162 | default: 1.0
163 | coeff_U_dep_mud:
164 | type: ['float', 'int']
165 | default: 0.3
166 | coeff_U_ero_mud:
167 | type: ['float', 'int']
168 | default: 1.5
169 | coeff_U_ero_sand:
170 | type: ['float', 'int']
171 | default: 1.05
172 | alpha:
173 | type: ['float', 'int']
174 | default: 0.1
175 | stepmax:
176 | type: ['float', 'int', 'None']
177 | default: null
178 | sand_frac_bc:
179 | type: ['float', 'int']
180 | default: 0
181 | clobber_netcdf:
182 | type: 'bool'
183 | default: False
184 | legacy_netcdf:
185 | type: 'bool'
186 | default: False
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "pyDeltaRCM"
3 | requires-python = ">=3.11"
4 | description = "Python version of original Matlab DeltaRCM."
5 | keywords = []
6 | authors = [
7 | { name = "Andrew Moodie", email = "amoodie@tamu.edu" },
8 | ]
9 | maintainers = [
10 | { name = "Andrew Moodie", email = "amoodie@tamu.edu" },
11 | ]
12 | classifiers = [
13 | "Intended Audience :: Science/Research",
14 | "License :: OSI Approved :: MIT License",
15 | "Operating System :: OS Independent",
16 | "Programming Language :: Python :: 3 :: Only",
17 | "Programming Language :: Python :: 3.11",
18 | "Programming Language :: Python :: 3.12",
19 | "Programming Language :: Python :: 3.13",
20 | "Topic :: Scientific/Engineering :: Hydrology",
21 | "Topic :: Scientific/Engineering :: Physics",
22 | ]
23 | dependencies = [
24 | "importlib-resources; python_version < '3.12'",
25 | "matplotlib",
26 | "scipy",
27 | "netCDF4",
28 | "pyyaml",
29 | "numba",
30 | "numpy"
31 | ]
32 | dynamic = [
33 | "version",
34 | "readme",
35 | ]
36 |
37 | [project.license]
38 | text = "MIT"
39 |
40 | [project.urls]
41 | documentation = "https://deltarcm.org/pyDeltaRCM"
42 | homepage = "https://deltarcm.org/pyDeltaRCM"
43 | repository = "https://github.com/DeltaRCM/pyDeltaRCM"
44 |
45 | [project.optional-dependencies]
46 | docs = [
47 | "sphinx",
48 | ]
49 | testing = [
50 | "coveralls",
51 | "pytest",
52 | "pytest-cov",
53 | "pytest-mpl"
54 | ]
55 |
56 | [build-system]
57 | requires = [
58 | "setuptools >=61",
59 | ]
60 | build-backend = "setuptools.build_meta"
61 |
62 | [tool.setuptools]
63 | include-package-data = true
64 |
65 | [tool.setuptools.dynamic.readme]
66 | file = "README.rst"
67 | content-type = "text/x-rst"
68 |
69 | [tool.setuptools.dynamic.version]
70 | attr = "pyDeltaRCM._version.__version__"
71 |
72 | [tool.setuptools.packages.find]
73 | where = [
74 | ".",
75 | ]
76 | include = [
77 | "pyDeltaRCM*",
78 | ]
79 |
80 | [project.scripts]
81 | pyDeltaRCM = "pyDeltaRCM.preprocessor:preprocessor_wrapper"
82 |
83 | [tool.coverage.run]
84 | relative_files = true
85 |
86 | [tool.pytest.ini_options]
87 | minversion = "6.0"
88 | testpaths = [
89 | "tests",
90 | ]
91 | norecursedirs = [
92 | ".*",
93 | "*.egg*",
94 | "build",
95 | "dist",
96 | ]
97 | addopts = [
98 | "--ignore=setup.py",
99 | "--tb=native",
100 | "--durations=16",
101 | "--strict-markers",
102 | "--doctest-modules",
103 | "-vvv",
104 | ]
105 | doctest_optionflags = [
106 | "NORMALIZE_WHITESPACE",
107 | "IGNORE_EXCEPTION_DETAIL",
108 | "ELLIPSIS",
109 | ]
--------------------------------------------------------------------------------
/requirements-docs.txt:
--------------------------------------------------------------------------------
1 | sphinx
2 |
--------------------------------------------------------------------------------
/requirements-test.txt:
--------------------------------------------------------------------------------
1 | pytest
2 | pytest-mpl
3 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | matplotlib>=3.6.1
2 | scipy>=1.5
3 | netCDF4
4 | pyyaml>=5.1
5 | numba
6 | numpy
7 |
--------------------------------------------------------------------------------
/strat_preprocess.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import scipy as sp
3 | from PIL import Image, ImageDraw
4 | import netCDF4
5 |
6 | vertical_spacing = 0.05 # in meters
7 | max_depth_of_section = 5 # meters
8 |
9 | fp = 'deltaRCM_Output/pyDeltaRCM_output.nc'
10 | nc = netCDF4.Dataset(fp)
11 |
12 | strata_sf = nc.variables['strata_sand_frac'][:]
13 | strata_depth = nc.variables['strata_depth'][:]
14 |
15 |
16 | # shortcuts for array sizes
17 | dz, dx, dy = strata_depth.shape
18 | nx, ny, nz = dx, dy, int(5/vertical_spacing)
19 |
20 | # preserves only the oldest surface when cross-cutting
21 | strata = np.zeros_like(strata_depth)
22 | strata[-1,:,:] = strata_depth[-1,:,:]
23 |
24 | for i in range(1,dz):
25 | strata[-i-1,:,:] = np.minimum(strata_depth[-i-1,:,:], strata[-i,:,:])
26 |
27 |
28 | # combines depths and sand fractions into stratigraphy
29 | stratigraphy = np.zeros((nz, nx, ny))
30 |
31 | for j in range(dx):
32 |
33 | mask = np.ones((nz,ny)) * -1
34 |
35 | for i in np.arange(dz-1,-1,-1):
36 |
37 | seds = strata[i,j,:] + max_depth_of_section
38 |
39 | sf = strata_sf[i,j,:]
40 | sf[sf<0] = 0
41 |
42 | poly = list(zip(np.arange(ny), seds / vertical_spacing)) + list(zip(np.arange(ny)*2, np.arange(ny)*0))
43 |
44 | img = Image.new("L", [ny, nz], 0)
45 | ImageDraw.Draw(img).polygon(poly, outline=1, fill=1)
46 | img = np.flipud(img).astype(float)
47 |
48 | img *= sf
49 | mask[img > 0] = img[img > 0]
50 |
51 | stratigraphy[:,j,:] = mask
52 |
53 | print('Saving stratigraphy...')
54 | np.save('deltaRCM_Output/stratigraphy.npy', stratigraphy)
55 | print('Done')
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/__init__.py
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_list_index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_list_index.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_list_mix_tuple_index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_list_mix_tuple_index.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_list_tuple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_list_tuple.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_args.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_args.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_kwargs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_kwargs.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_multiple_index_calls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_multiple_index_calls.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_no_grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_no_grid.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_single_index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_single_index.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_cell_type_single_tuple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_cell_type_single_tuple.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_velocity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_velocity.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_domain_withlabel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_domain_withlabel.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_iwalk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_iwalk.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_plot_multiple_subplots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_plot_multiple_subplots.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_show_line_pts_Nx2_array.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_show_line_pts_Nx2_array.png
--------------------------------------------------------------------------------
/tests/imgs_baseline/test_show_line_set_points.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/imgs_baseline/test_show_line_set_points.png
--------------------------------------------------------------------------------
/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeltaRCM/pyDeltaRCM/cfc01e47542bffc98e394fe1ca07d7f41f8588c7/tests/integration/__init__.py
--------------------------------------------------------------------------------
/tests/test_sed_tools.py:
--------------------------------------------------------------------------------
1 | # unit tests for sed_tools.py
2 |
3 | import numpy as np
4 | from pathlib import Path
5 |
6 | import pytest
7 | import unittest.mock as mock
8 |
9 | from pyDeltaRCM.model import DeltaModel
10 | from . import utilities
11 |
12 |
13 | class TestSedimentRoute:
14 |
15 | def test_route_sediment(self, tmp_path: Path) -> None:
16 | # create a delta with default settings
17 | p = utilities.yaml_from_dict(tmp_path, 'input.yaml')
18 | _delta = DeltaModel(input_file=p)
19 |
20 | # mock top-level methods
21 | _delta.log_info = mock.MagicMock()
22 | _delta.init_sediment_iteration = mock.MagicMock()
23 | _delta.route_all_sand_parcels = mock.MagicMock()
24 | _delta.topo_diffusion = mock.MagicMock()
25 | _delta.route_all_mud_parcels = mock.MagicMock()
26 |
27 | # run the method
28 | _delta.route_sediment()
29 |
30 | # methods called
31 | assert (_delta.log_info.call_count == 4)
32 | assert (_delta.init_sediment_iteration.called is True)
33 | assert (_delta.route_all_sand_parcels.called is True)
34 | assert (_delta.topo_diffusion.called is True)
35 | assert (_delta.route_all_mud_parcels.called is True)
36 |
37 | def test_sed_route_deprecated(self, tmp_path: Path) -> None:
38 | # create a delta with default settings
39 | p = utilities.yaml_from_dict(tmp_path, 'input.yaml')
40 | _delta = DeltaModel(input_file=p)
41 |
42 | # mock top-level methods
43 | _delta.logger = mock.MagicMock()
44 | _delta.route_sediment = mock.MagicMock()
45 |
46 | # check warning raised
47 | with pytest.warns(UserWarning):
48 | _delta.sed_route()
49 |
50 | # and logged
51 | assert (_delta.logger.warning.called is True)
52 |
53 |
54 | class TestInitSedimentIteration:
55 |
56 | def test_fields_cleared(self, tmp_path: Path) -> None:
57 | # create a delta with default settings
58 | p = utilities.yaml_from_dict(tmp_path, 'input.yaml')
59 | _delta = DeltaModel(input_file=p)
60 |
61 | # alter field for initial values going into function
62 | _delta.qs += np.random.uniform(0, 1, size=_delta.eta.shape)
63 | _delta.Vp_dep_sand += np.random.uniform(0, 1, size=_delta.eta.shape)
64 | _delta.Vp_dep_mud += np.random.uniform(0, 1, size=_delta.eta.shape)
65 |
66 | assert not np.all(_delta.qs == 0) # field has info
67 |
68 | # call the method
69 | _delta.init_sediment_iteration()
70 |
71 | # assertions
72 | assert np.all(_delta.pad_depth[1:-1, 1:-1] == _delta.depth)
73 | assert np.all(_delta.qs == 0) # field is cleared
74 | assert np.all(_delta.Vp_dep_sand == 0)
75 | assert np.all(_delta.Vp_dep_mud == 0)
76 |
77 |
78 | class TestRouteAllSandParcels:
79 |
80 | def test_route_sand_parcels(self, tmp_path: Path) -> None:
81 | # create a delta with default settings
82 | p = utilities.yaml_from_dict(tmp_path, 'input.yaml',
83 | {'Np_sed': 1000,
84 | 'f_bedload': 0.6})
85 | _delta = DeltaModel(input_file=p)
86 |
87 | # mock top-level methods / objects
88 | _delta.log_info = mock.MagicMock()
89 | _delta._sr = mock.MagicMock()
90 |
91 | # mock the shared tools start indices
92 | def _patched_starts(inlet, inlet_weights, num_starts):
93 | return np.random.randint(0, 5, size=(num_starts,))
94 |
95 | patcher = mock.patch(
96 | 'pyDeltaRCM.shared_tools.get_start_indices',
97 | new=_patched_starts)
98 | patcher.start()
99 |
100 | # run the method
101 | _delta.route_all_sand_parcels()
102 |
103 | # methods called
104 | assert (_delta._sr.run.call_count == 1)
105 | assert (_delta.log_info.call_count == 3)
106 |
107 | # stop the patch
108 | patcher.stop()
109 |
110 |
111 | class TestRouteAllMudParcels:
112 |
113 | def test_route_mud_parcels(self, tmp_path: Path) -> None:
114 | # create a delta with default settings
115 | p = utilities.yaml_from_dict(tmp_path, 'input.yaml',
116 | {'Np_sed': 1000,
117 | 'f_bedload': 0.6})
118 | _delta = DeltaModel(input_file=p)
119 |
120 | # mock top-level methods / objects
121 | _delta.log_info = mock.MagicMock()
122 | _delta._mr = mock.MagicMock()
123 |
124 | # mock the shared tools start indices
125 | def _patched_starts(inlet, inlet_weights, num_starts):
126 | return np.random.randint(0, 5, size=(num_starts,))
127 |
128 | patcher = mock.patch(
129 | 'pyDeltaRCM.shared_tools.get_start_indices',
130 | new=_patched_starts)
131 | patcher.start()
132 |
133 | # run the method
134 | _delta.route_all_mud_parcels()
135 |
136 | # methods called
137 | assert (_delta._mr.run.call_count == 1)
138 | assert (_delta.log_info.call_count == 3)
139 |
140 | # stop the patch
141 | patcher.stop()
142 |
--------------------------------------------------------------------------------
/tests/utilities.py:
--------------------------------------------------------------------------------
1 | import glob
2 | import io
3 | import os
4 | from pathlib import Path
5 | from typing import Any, Dict, List, Optional, Tuple, Union
6 |
7 | import numpy as np
8 |
9 | import pytest
10 | from pyDeltaRCM.model import DeltaModel
11 | from pyDeltaRCM import shared_tools
12 |
13 | # utilities for file writing
14 |
15 |
16 | def create_temporary_file(tmp_path: Path, file_name: str) -> Tuple[Path, io.TextIOWrapper]:
17 | d = tmp_path / 'configs'
18 | d.mkdir(parents=True, exist_ok=True)
19 | p = d / file_name
20 | f = open(p, "w")
21 | return p, f
22 |
23 |
24 | def write_parameter_to_file(f: io.TextIOWrapper, varname: str, varvalue: Any) -> None:
25 | f.write(varname + ': ' + str(varvalue) + '\n')
26 |
27 |
28 | def write_matrix_to_file(f: io.TextIOWrapper, keys: List[str], lists) -> None:
29 | # assert len(keys) == len(lists)
30 | f.write('matrix' + ': ' + '\n')
31 | for i in range(len(keys)):
32 | f.write(' ' + keys[i] + ': ' + '\n')
33 | for j in range(len(lists[i])):
34 | f.write(' ' + '- ' + str(lists[i][j]) + '\n')
35 |
36 |
37 | def write_set_to_file(f: io.TextIOWrapper, set_list: List[Dict[str, Union[int, float]]]) -> None:
38 | f.write('set' + ': ' + '\n')
39 | for i, _set in enumerate(set_list):
40 | f.write(' - {')
41 | for j, (k, v) in enumerate(_set.items()):
42 | f.write(k + ': ' + str(v) + ', ')
43 | f.write('}' + '\n')
44 |
45 |
46 | def yaml_from_dict(tmp_path: Path, file_name: str, _dict: Optional[Dict[str, Any]]=None) -> Path:
47 | p, f = create_temporary_file(tmp_path, file_name)
48 | if (_dict is None):
49 | _dict = {'out_dir': tmp_path / 'out_dir'}
50 | elif ('out_dir' not in _dict.keys()):
51 | _dict['out_dir'] = tmp_path / 'out_dir'
52 |
53 | for k in _dict.keys():
54 | write_parameter_to_file(f, k, _dict[k])
55 | f.close()
56 | return p
57 |
58 |
59 | @pytest.fixture(scope='function')
60 | def test_DeltaModel(tmp_path: Path) -> DeltaModel:
61 | file_name = 'user_parameters.yaml'
62 | p, f = create_temporary_file(tmp_path, file_name)
63 | write_parameter_to_file(f, 'out_dir', tmp_path / 'out_dir')
64 | write_parameter_to_file(f, 'Length', 10.0)
65 | write_parameter_to_file(f, 'Width', 10.0)
66 | write_parameter_to_file(f, 'seed', 0)
67 | write_parameter_to_file(f, 'dx', 1.0)
68 | write_parameter_to_file(f, 'L0_meters', 1.0)
69 | write_parameter_to_file(f, 'S0', 0.0002)
70 | write_parameter_to_file(f, 'itermax', 1)
71 | write_parameter_to_file(f, 'Np_water', 10)
72 | write_parameter_to_file(f, 'u0', 1.0)
73 | write_parameter_to_file(f, 'N0_meters', 2.0)
74 | write_parameter_to_file(f, 'h0', 1.0)
75 | write_parameter_to_file(f, 'H_SL', 0.0)
76 | write_parameter_to_file(f, 'SLR', 0.001)
77 | write_parameter_to_file(f, 'Np_sed', 10)
78 | write_parameter_to_file(f, 'f_bedload', 0.5)
79 | write_parameter_to_file(f, 'C0_percent', 0.1)
80 | write_parameter_to_file(f, 'toggle_subsidence', False)
81 | write_parameter_to_file(f, 'subsidence_rate', 0.0)
82 | write_parameter_to_file(f, 'start_subsidence', 50.)
83 | write_parameter_to_file(f, 'save_eta_figs', False)
84 | write_parameter_to_file(f, 'save_stage_figs', False)
85 | write_parameter_to_file(f, 'save_depth_figs', False)
86 | write_parameter_to_file(f, 'save_discharge_figs', False)
87 | write_parameter_to_file(f, 'save_velocity_figs', False)
88 | write_parameter_to_file(f, 'save_eta_grids', False)
89 | write_parameter_to_file(f, 'save_stage_grids', False)
90 | write_parameter_to_file(f, 'save_depth_grids', False)
91 | write_parameter_to_file(f, 'save_discharge_grids', False)
92 | write_parameter_to_file(f, 'save_velocity_grids', False)
93 | write_parameter_to_file(f, 'save_dt', 500)
94 | f.close()
95 | _delta = DeltaModel(input_file=p)
96 | return _delta
97 |
98 |
99 | class FastIteratingDeltaModel:
100 | """A Fast iterating DeltaModel
101 |
102 | This class is useful in patching the DeltaModel for timing tests. The
103 | patched DeltaModel uses the random number generation internally, so it
104 | will verify functionality in any checkpointing scenarios, and overwriting
105 | only the `solve_water_and_sediment_timestep` method removes most of the jitting compilation
106 | time and much of the actual computation time.
107 | """
108 |
109 | def solve_water_and_sediment_timestep(self) -> None:
110 | """PATCH"""
111 |
112 | def _get_random_field(shp: Tuple[int, ...]) -> np.ndarray:
113 | """Get a field or randoms using the shared function.
114 |
115 | It is critical to use the `shared_tools.get_random_uniform` for
116 | reproducibility.
117 | """
118 | field = np.zeros(shp, dtype=np.float32)
119 | for i in range(shp[0]):
120 | for j in range(shp[1]):
121 | field[i, j] = shared_tools.get_random_uniform(1)
122 | return field
123 |
124 | shp = self.eta.shape
125 | self.eta += _get_random_field(shp)
126 | self.uw += _get_random_field(shp)
127 | self.ux += _get_random_field(shp)
128 | self.uy += _get_random_field(shp)
129 | self.depth += _get_random_field(shp)
130 | self.stage += _get_random_field(shp)
131 |
132 |
133 | def read_endtime_from_log(log_folder) -> float:
134 | _logs = glob.glob(os.path.join(log_folder, '*.log'))
135 | assert len(_logs) == 1 # log file exists
136 | with open(_logs[0], 'r') as _logfile:
137 | _lines = _logfile.readlines()
138 | _t = 0
139 | for i, _line in enumerate(_lines):
140 | if 'Time: ' in _line:
141 | _t = _line.split(' ')[6]
142 | _t = _t.strip(' ;')
143 | return float(_t)
144 |
--------------------------------------------------------------------------------