├── doc
├── requirements.txt
├── pics
│ ├── logo.PNG
│ ├── logo_2.PNG
│ ├── demo
│ │ ├── Network.png
│ │ ├── SingleNode.png
│ │ ├── SingleUnit.png
│ │ ├── Network_scheme.png
│ │ ├── SingleReservoir.png
│ │ ├── SingleNode_scheme.png
│ │ ├── SingleUnit_scheme.png
│ │ └── SingleReservoir_scheme.png
│ ├── components
│ │ ├── node.png
│ │ ├── unit.png
│ │ ├── linker.png
│ │ ├── junction.png
│ │ ├── network.png
│ │ ├── splitter.png
│ │ ├── transparent.png
│ │ └── node_routing.png
│ ├── logo_inverted_2.PNG
│ ├── reference
│ │ ├── uml.png
│ │ └── class_uml.png
│ ├── build_element
│ │ ├── lag.png
│ │ └── reservoir.png
│ ├── elements_list
│ │ └── lag.png
│ ├── logo_transparent.PNG
│ ├── popular_models
│ │ ├── M4.png
│ │ ├── gr4j.png
│ │ └── hymod.png
│ ├── contribute
│ │ ├── schematic.png
│ │ ├── schematic_2.png
│ │ └── schematic_with_logo.png
│ ├── logo_inverted_colors.PNG
│ ├── logo_transparent_2.png
│ ├── case_studies
│ │ ├── ThurHESS2020.png
│ │ ├── ThurSchemeNodes.png
│ │ └── model_structure_thur.png
│ └── numerical_solver
│ │ └── bench_all.png
├── license.rst
├── components_code.py
├── share_models_code.py
├── numerical_solver_code.py
├── installation.rst
├── sfpy_in_literature.rst
├── testing.rst
├── customize_components_code.py
├── conf.py
├── interfaces_code.py
├── examples.rst
├── customize_components.rst
├── share_models.rst
├── reference.rst
├── changelog.rst
├── index.rst
├── contribute.rst
├── interfaces.rst
├── model_thur_hess2020.py
└── case_studies.rst
├── requirements_dev.txt
├── requirements.txt
├── pyproject.toml
├── .gitignore
├── test
├── unittest
│ ├── test_all.sh
│ ├── test_requirements.txt
│ ├── 01_FR.py
│ └── 07_FR_2dt.py
└── reference_results
│ ├── 01_FR
│ ├── flexConfig_ML01.dat
│ ├── flexConfig_Areas.dat
│ ├── Results.csv
│ ├── SuperflexRes.dat
│ ├── test.py
│ ├── modelInfo.dat
│ ├── test.INF_DAT
│ ├── input.dat
│ └── M01_main.dat
│ ├── 02_UR
│ ├── flexConfig_ML01.dat
│ ├── flexConfig_Areas.dat
│ ├── test.py
│ ├── Results.csv
│ ├── SuperflexRes.dat
│ ├── modelInfo.dat
│ ├── test.INF_DAT
│ ├── input.dat
│ └── M01_main.dat
│ ├── 03_UR_FR
│ ├── flexConfig_ML01.dat
│ ├── flexConfig_Areas.dat
│ ├── test.py
│ ├── Results.csv
│ ├── modelInfo.dat
│ ├── SuperflexRes.dat
│ ├── test.INF_DAT
│ ├── input.dat
│ └── M01_main.dat
│ ├── 05_2HRUs
│ ├── flexConfig_HRU1.dat
│ ├── flexConfig_HRU2.dat
│ ├── flexConfig_Areas.dat
│ ├── test.py
│ ├── modelInfo.dat
│ ├── test.INF_DAT
│ ├── input.dat
│ ├── Results.csv
│ ├── SuperflexRes.dat
│ └── M01_main.dat
│ ├── 07_FR_2dt
│ ├── flexConfig_ML01.dat
│ ├── flexConfig_Areas.dat
│ ├── Results.csv
│ ├── SuperflexRes.dat
│ ├── test.py
│ ├── modelInfo.dat
│ ├── test.INF_DAT
│ ├── input.dat
│ └── M01_main.dat
│ ├── 08_UR_2dt
│ ├── flexConfig_ML01.dat
│ ├── flexConfig_Areas.dat
│ ├── test.py
│ ├── Results.csv
│ ├── SuperflexRes.dat
│ ├── modelInfo.dat
│ ├── test.INF_DAT
│ ├── input.dat
│ └── M01_main.dat
│ ├── 04_UR_FR_SR
│ ├── flexConfig_ML01.dat
│ ├── flexConfig_Areas.dat
│ ├── test.py
│ ├── modelInfo.dat
│ ├── test.INF_DAT
│ ├── Results.csv
│ ├── SuperflexRes.dat
│ ├── input.dat
│ └── M01_main.dat
│ ├── 06_3Cats_2HRUs
│ ├── flexConfig_HRU1.dat
│ ├── flexConfig_HRU2.dat
│ ├── flexConfig_Areas.dat
│ ├── test.py
│ ├── modelInfo.dat
│ ├── test.INF_DAT
│ └── input.dat
│ └── README.md
├── .flake8
├── AUTHORS
├── .github
└── workflows
│ ├── pre-commit.yaml
│ ├── automatic_test.yml
│ └── publish_to_pypi.yml
├── readthedocs.yml
├── .pre-commit-config.yaml
├── setup.py
├── README.md
├── superflexpy
├── __init__.py
├── framework
│ └── __init__.py
├── implementation
│ ├── root_finders
│ │ ├── __init__.py
│ │ └── explicit.py
│ ├── models
│ │ ├── __init__.py
│ │ ├── m4_sf_2011.py
│ │ ├── hymod.py
│ │ └── gr4j.py
│ ├── __init__.py
│ ├── numerical_approximators
│ │ └── __init__.py
│ └── elements
│ │ └── __init__.py
└── utils
│ ├── __init__.py
│ └── root_finder.py
└── examples
└── README.md
/doc/requirements.txt:
--------------------------------------------------------------------------------
1 | superflexpy
2 |
--------------------------------------------------------------------------------
/requirements_dev.txt:
--------------------------------------------------------------------------------
1 | pre-commit==3.5.0
2 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | matplotlib==3.8.2
2 | numba==0.57.1
3 | numpy==1.24.3
4 |
--------------------------------------------------------------------------------
/doc/pics/logo.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/logo.PNG
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.isort]
2 | profile = "black"
3 | [tool.black]
4 | line-length = 120
5 |
--------------------------------------------------------------------------------
/doc/pics/logo_2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/logo_2.PNG
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/__pycache__
2 | build/
3 | dist/
4 | superflexpy.egg-info/
5 | **/.ipynb_checkpoints
6 |
--------------------------------------------------------------------------------
/doc/pics/demo/Network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/Network.png
--------------------------------------------------------------------------------
/test/unittest/test_all.sh:
--------------------------------------------------------------------------------
1 | cd test/unittest/
2 | for f in *.py; do echo Running "$f"; python "$f"; done
3 |
--------------------------------------------------------------------------------
/doc/pics/components/node.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/node.png
--------------------------------------------------------------------------------
/doc/pics/components/unit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/unit.png
--------------------------------------------------------------------------------
/doc/pics/demo/SingleNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/SingleNode.png
--------------------------------------------------------------------------------
/doc/pics/demo/SingleUnit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/SingleUnit.png
--------------------------------------------------------------------------------
/doc/pics/logo_inverted_2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/logo_inverted_2.PNG
--------------------------------------------------------------------------------
/doc/pics/reference/uml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/reference/uml.png
--------------------------------------------------------------------------------
/test/unittest/test_requirements.txt:
--------------------------------------------------------------------------------
1 | pandas==2.1.3
2 | matplotlib==3.8.2
3 | numba==0.57.1
4 | numpy==1.24.3
5 |
--------------------------------------------------------------------------------
/doc/pics/build_element/lag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/build_element/lag.png
--------------------------------------------------------------------------------
/doc/pics/components/linker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/linker.png
--------------------------------------------------------------------------------
/doc/pics/elements_list/lag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/elements_list/lag.png
--------------------------------------------------------------------------------
/doc/pics/logo_transparent.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/logo_transparent.PNG
--------------------------------------------------------------------------------
/doc/pics/popular_models/M4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/popular_models/M4.png
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | extend-ignore = E203
3 | max-line-length = 120
4 | exclude = doc,test,.git,.venv,__pycache__,venv
5 |
--------------------------------------------------------------------------------
/doc/pics/components/junction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/junction.png
--------------------------------------------------------------------------------
/doc/pics/components/network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/network.png
--------------------------------------------------------------------------------
/doc/pics/components/splitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/splitter.png
--------------------------------------------------------------------------------
/doc/pics/contribute/schematic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/contribute/schematic.png
--------------------------------------------------------------------------------
/doc/pics/demo/Network_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/Network_scheme.png
--------------------------------------------------------------------------------
/doc/pics/demo/SingleReservoir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/SingleReservoir.png
--------------------------------------------------------------------------------
/doc/pics/logo_inverted_colors.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/logo_inverted_colors.PNG
--------------------------------------------------------------------------------
/doc/pics/logo_transparent_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/logo_transparent_2.png
--------------------------------------------------------------------------------
/doc/pics/popular_models/gr4j.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/popular_models/gr4j.png
--------------------------------------------------------------------------------
/doc/pics/popular_models/hymod.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/popular_models/hymod.png
--------------------------------------------------------------------------------
/doc/pics/reference/class_uml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/reference/class_uml.png
--------------------------------------------------------------------------------
/doc/pics/components/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/transparent.png
--------------------------------------------------------------------------------
/doc/pics/contribute/schematic_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/contribute/schematic_2.png
--------------------------------------------------------------------------------
/doc/pics/demo/SingleNode_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/SingleNode_scheme.png
--------------------------------------------------------------------------------
/doc/pics/demo/SingleUnit_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/SingleUnit_scheme.png
--------------------------------------------------------------------------------
/doc/pics/build_element/reservoir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/build_element/reservoir.png
--------------------------------------------------------------------------------
/doc/pics/case_studies/ThurHESS2020.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/case_studies/ThurHESS2020.png
--------------------------------------------------------------------------------
/doc/pics/components/node_routing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/components/node_routing.png
--------------------------------------------------------------------------------
/doc/pics/demo/SingleReservoir_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/demo/SingleReservoir_scheme.png
--------------------------------------------------------------------------------
/doc/pics/numerical_solver/bench_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/numerical_solver/bench_all.png
--------------------------------------------------------------------------------
/doc/pics/case_studies/ThurSchemeNodes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/case_studies/ThurSchemeNodes.png
--------------------------------------------------------------------------------
/doc/pics/contribute/schematic_with_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/contribute/schematic_with_logo.png
--------------------------------------------------------------------------------
/doc/pics/case_studies/model_structure_thur.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/doc/pics/case_studies/model_structure_thur.png
--------------------------------------------------------------------------------
/test/reference_results/01_FR/flexConfig_ML01.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/01_FR/flexConfig_ML01.dat
--------------------------------------------------------------------------------
/test/reference_results/02_UR/flexConfig_ML01.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/02_UR/flexConfig_ML01.dat
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/flexConfig_ML01.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/03_UR_FR/flexConfig_ML01.dat
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/flexConfig_HRU1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/05_2HRUs/flexConfig_HRU1.dat
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/flexConfig_HRU2.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/05_2HRUs/flexConfig_HRU2.dat
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/flexConfig_ML01.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/07_FR_2dt/flexConfig_ML01.dat
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/flexConfig_ML01.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/08_UR_2dt/flexConfig_ML01.dat
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/flexConfig_ML01.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/04_UR_FR_SR/flexConfig_ML01.dat
--------------------------------------------------------------------------------
/test/reference_results/06_3Cats_2HRUs/flexConfig_HRU1.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/06_3Cats_2HRUs/flexConfig_HRU1.dat
--------------------------------------------------------------------------------
/test/reference_results/06_3Cats_2HRUs/flexConfig_HRU2.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dalmo1991/superflexPy/HEAD/test/reference_results/06_3Cats_2HRUs/flexConfig_HRU2.dat
--------------------------------------------------------------------------------
/doc/license.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 16/10/2020
2 |
3 | .. _license:
4 |
5 | License
6 | =======
7 |
8 | .. highlight:: none
9 | .. literalinclude:: LICENSE
10 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 1.0
6 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 1.0
6 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 1.0
6 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 1.0
6 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 1.0
6 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 1.0
6 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 40.0 60.0
6 |
--------------------------------------------------------------------------------
/doc/components_code.py:
--------------------------------------------------------------------------------
1 | e1 = Element(parameters={"p1": 0.1}, states={"S": 10.0})
2 |
3 | u1 = Unit([e1])
4 | u2 = Unit([e1])
5 |
6 | e1.set_parameters({"e1_p1": 0.2})
7 | u1.set_parameters({"u1_e1_p1": 0.3})
8 | u2.set_parameters({"u2_e1_p1": 0.4})
9 |
--------------------------------------------------------------------------------
/test/reference_results/06_3Cats_2HRUs/flexConfig_Areas.dat:
--------------------------------------------------------------------------------
1 | FLEX_HRU_CHARACTERISTICS_FILE_V1.1
2 | ! Description: HRUs characterisics (-1=NA, depending on mask Unit Presence Matrix)
3 | !========
4 | AREAS (km2)
5 | 2.5 7.5
6 | 8.0 12.0
7 | 24.0 6.0
8 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | List of contributors (alphabetical order)
2 |
3 | Format: Name Surname, Affiliation, e-mail
4 |
5 | Marco Dal Molin, EAWAG, marco.dalmolin.1991@gmail.com
6 | Fabrizio Fenicia, EAWAG, fabrizio.fenicia@eawag.ch
7 | Dmitri Kavetski, University of Adelaide, dmitri.kavetski@adelaide.edu.au
8 |
--------------------------------------------------------------------------------
/.github/workflows/pre-commit.yaml:
--------------------------------------------------------------------------------
1 | name: pre-commit
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches: [master]
7 |
8 | jobs:
9 | pre-commit:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 | - uses: actions/setup-python@v3
14 | - uses: pre-commit/action@v3.0.0
15 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/Results.csv:
--------------------------------------------------------------------------------
1 | # Q_FR, S_FR
2 | 3.159780226522707953e-05,9.996840219773421576e-02
3 | 3.166701113934160539e-01,3.983298290804318409e+00
4 | 2.663570722380119715e-01,3.716941218566306659e+00
5 | 4.951976392398618643e+00,1.196496482616768731e+01
6 | 3.707744781785232480e+00,1.065722004438245385e+01
7 | 9.457787016280562398e+00,1.549943302810189394e+01
8 | 6.532500080672547504e+00,1.336693294742934945e+01
9 | 4.038812792135322738e+00,1.102812015529402778e+01
10 | 2.270004410544121498e+00,8.758115744749906284e+00
11 | 5.176552544186736071e+01,3.059259030288254877e+01
12 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/Results.csv:
--------------------------------------------------------------------------------
1 | # Q_FR, S_FR
2 | 1.780900587186331975e-04,1.996438198825627452e-01
3 | 1.064800016990280485e+00,6.470043785902002575e+00
4 | 6.234754642204936026e-01,5.223092857461010929e+00
5 | 8.415470448389710256e+00,1.479215196068158455e+01
6 | 4.196754269805919257e+00,1.119864342106974497e+01
7 | 1.151488566525114265e+01,1.676887209056745220e+01
8 | 6.227557886749018223e+00,1.311375631706941824e+01
9 | 3.220350228412992344e+00,1.007305586024343214e+01
10 | 1.413431427615711833e+00,7.246193005012008470e+00
11 | 6.089951208253958015e+01,3.264716883993278884e+01
12 |
--------------------------------------------------------------------------------
/test/reference_results/README.md:
--------------------------------------------------------------------------------
1 | # Note
2 |
3 | This folder contains reference results for testing SuperflexPy.
4 |
5 | Only the files `Results.csv` and `input.dat` are relevant for testing. All the
6 | others are here only for reproducibility purposes, storing information on the
7 | configuration of Superflex (Fenicia et al., 2011).
8 |
9 | ### Bibliography
10 |
11 | Fenicia, F., D. Kavetski, and H. H. G. Savenije (2011), Elements of a flexible approach for conceptual hydrological modeling: 1. Motivation and theoretical development, Water Resources Research, 47(11), W11510, 10.1029/2010wr010174.
12 |
--------------------------------------------------------------------------------
/.github/workflows/automatic_test.yml:
--------------------------------------------------------------------------------
1 | name: unittest on push
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches:
7 | - master
8 | - release
9 |
10 | jobs:
11 | test:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Prepare the repo
15 | uses: actions/checkout@master
16 | - name: Set up Python 3.11
17 | uses: actions/setup-python@v1
18 | with:
19 | python-version: 3.11
20 | - name: Install packages
21 | run: pip install -r test/unittest/test_requirements.txt
22 | - name: Test
23 | run: bash test/unittest/test_all.sh
24 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/SuperflexRes.dat:
--------------------------------------------------------------------------------
1 | Data modelled by SF_ISO
2 | C1Wv%Qstream U1F1Wv%Sf[1]
3 | 3.15978022652271E-05 9.99684021977342E-02
4 | 3.16670111393416E-01 3.98329829080432E+00
5 | 2.66357072238012E-01 3.71694121856631E+00
6 | 4.95197639239862E+00 1.19649648261677E+01
7 | 3.70774478178523E+00 1.06572200443825E+01
8 | 9.45778701628056E+00 1.54994330281019E+01
9 | 6.53250008067255E+00 1.33669329474293E+01
10 | 4.03881279213532E+00 1.10281201552940E+01
11 | 2.27000441054412E+00 8.75811574474991E+00
12 | 5.17655254418674E+01 3.05925903028825E+01
13 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/SuperflexRes.dat:
--------------------------------------------------------------------------------
1 | Data modelled by SF_ISO
2 | C1Wv%Qstream U1F1Wv%Sf[1]
3 | 1.78090058718633E-04 1.99643819882563E-01
4 | 1.06480001699028E+00 6.47004378590200E+00
5 | 6.23475464220494E-01 5.22309285746101E+00
6 | 8.41547044838971E+00 1.47921519606816E+01
7 | 4.19675426980592E+00 1.11986434210697E+01
8 | 1.15148856652511E+01 1.67688720905675E+01
9 | 6.22755788674902E+00 1.31137563170694E+01
10 | 3.22035022841299E+00 1.00730558602434E+01
11 | 1.41343142761571E+00 7.24619300501201E+00
12 | 6.08995120825396E+01 3.26471688399328E+01
13 |
--------------------------------------------------------------------------------
/readthedocs.yml:
--------------------------------------------------------------------------------
1 | # .readthedocs.yml
2 | # Read the Docs configuration file
3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4 |
5 | # Required
6 | version: 2
7 |
8 | build:
9 | os: ubuntu-22.04
10 | tools:
11 | python: "3.11"
12 |
13 | # Build documentation in the docs/ directory with Sphinx
14 | sphinx:
15 | configuration: doc/conf.py
16 |
17 | # Optionally build your docs in additional formats such as PDF and ePub
18 | formats: all
19 |
20 | # Optionally set the version of Python and requirements required to build your docs
21 | python:
22 | install:
23 | - requirements: doc/requirements.txt
24 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.5.0
4 | hooks:
5 | - id: trailing-whitespace
6 | - id: end-of-file-fixer
7 | - id: check-yaml
8 | - id: check-added-large-files
9 | - repo: https://github.com/PyCQA/flake8
10 | rev: 6.1.0
11 | hooks:
12 | - id: flake8
13 | exclude: ^(doc/|^test/)
14 | - repo: https://github.com/pycqa/isort
15 | rev: 5.12.0
16 | hooks:
17 | - id: isort
18 | args: ["--profile", "black", "--filter-files"]
19 | - repo: https://github.com/psf/black
20 | rev: 23.11.0
21 | hooks:
22 | - id: black
23 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir, path
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir(path.abspath(path.dirname(__file__)))
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt("Results.csv", X=output, delimiter=",", header="Q_FR, S_FR")
29 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir, path
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir(path.abspath(path.dirname(__file__)))
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt("Results.csv", X=output, delimiter=",", header="Q_UR, E_UR, S_UR")
29 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir("/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/01_FR/")
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt("Results.csv", X=output, delimiter=",", header="Q_FR, S_FR")
29 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir("/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/02_UR/")
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt("Results.csv", X=output, delimiter=",", header="Q_UR, E_UR, S_UR")
29 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir("/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/03_UR_FR/")
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt("Results.csv", X=output, delimiter=",", header="Q_out, E_UR, S_UR, S_FR")
29 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir("/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/04_UR_FR_SR/")
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt("Results.csv", X=output, delimiter=",", header="Q_out, E_UR, S_UR, S_FR, S_SR")
29 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/Results.csv:
--------------------------------------------------------------------------------
1 | # Q_UR, E_UR, S_UR
2 | 3.009856864469894096e-03,5.258974893186536548e+00,4.838015249948993457e+00
3 | 8.864692811194890831e-02,5.130691213399449779e+00,3.818677108437596335e+00
4 | 0.000000000000000000e+00,3.202714842730908007e+00,6.159622657066883278e-01
5 | 7.808764814858565328e-01,5.443911796302973727e+00,7.591173987917855470e+00
6 | 6.872763881524802942e-02,5.242400307174300167e+00,4.680046041928307865e+00
7 | 1.635054241653562945e+00,5.566199717157565452e+00,1.177879208311717996e+01
8 | 4.077257815005328467e-01,5.532314801708615448e+00,1.023875149990803024e+01
9 | 7.918930542498503478e-02,5.386421012745326919e+00,6.473141181737718242e+00
10 | 0.000000000000000000e+00,4.586741093407180614e+00,1.886400088330537628e+00
11 | 3.774060787574933329e+01,5.713300529257533178e+00,3.203249168332367702e+01
12 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/Results.csv:
--------------------------------------------------------------------------------
1 | # Q_UR, E_UR, S_UR
2 | 5.186073603391754125e-04,4.350451541277550405e+00,1.498059702724222175e+00
3 | 1.895615082737465290e-02,4.247304505087319271e+00,1.365538390894836418e+00
4 | 0.000000000000000000e+00,6.511671950550351751e-01,6.320400078476612338e-02
5 | 1.581811726237999594e+00,5.573191220252586398e+00,1.215319810780359155e+01
6 | 1.006375051760131228e-01,5.358518452123193221e+00,6.034886193205179161e+00
7 | 2.949405595047687623e+00,5.640889987188658417e+00,1.745429502873248850e+01
8 | 6.367529840457144541e-01,5.599342162879759499e+00,1.378210473488154264e+01
9 | 7.569693251013522028e-02,5.374656926342401775e+00,6.281397017176455044e+00
10 | 0.000000000000000000e+00,2.892244096750379967e+00,4.969088236756952215e-01
11 | 4.904745394822768390e+01,5.727410394778824632e+00,3.814718013766267291e+01
12 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import setuptools
4 |
5 | setuptools.setup(
6 | name="superflexpy",
7 | version="1.3.2",
8 | author="Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski",
9 | author_email="marco.dalmolin.1991@gmail.com",
10 | description="Framework for building hydrological models",
11 | long_description=open(os.path.join(os.path.dirname(__file__), "README.md")).read(),
12 | long_description_content_type="text/markdown",
13 | url="https://superflexpy.readthedocs.io/en/latest/",
14 | license="LGPL",
15 | packages=setuptools.find_packages(),
16 | classifiers=[
17 | "Development Status :: 5 - Production/Stable", # https://martin-thoma.com/software-development-stages/
18 | "Topic :: Scientific/Engineering :: Hydrology",
19 | ],
20 | install_requires=["numba==0.57.1", "numpy==1.24.3"],
21 | )
22 |
--------------------------------------------------------------------------------
/.github/workflows/publish_to_pypi.yml:
--------------------------------------------------------------------------------
1 | name: publish releases automatically on PyPI
2 |
3 | # Trigger on push on release branch
4 | on:
5 | push:
6 | branches:
7 | - release
8 |
9 | jobs:
10 | create_and_publish:
11 | name: publish releases automatically on PyPI
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Select branch
15 | uses: actions/checkout@master
16 | with:
17 | ref: 'release' # The default behavior is that it checkouts to the trigger so we don't need this
18 | - name: Set up Python 3.11
19 | uses: actions/setup-python@v1
20 | with:
21 | python-version: 3.11
22 | - name: Build the package
23 | run: python setup.py sdist
24 | - name: Publish on PyPI
25 | uses: pypa/gh-action-pypi-publish@master
26 | with:
27 | password: ${{ secrets.PYPI_ACCESS_TOKEN }}
28 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir("/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/05_2HRUs/")
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt(
29 | "Results.csv",
30 | X=output,
31 | delimiter=",",
32 | header="Q_tot, Q_H1, E_FR_H1, S_FR_H1, Q_H2, E_UR_H2, S_UR_H2, S_FR_H2, S_SR_H2",
33 | )
34 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/SuperflexRes.dat:
--------------------------------------------------------------------------------
1 | Data modelled by SF_ISO
2 | C1Wv%Qstream U1F1Wv%Eact U1F1Wv%Su[1]
3 | 3.00985686446989E-03 5.25897489318654E+00 4.83801524994899E+00
4 | 8.86469281119489E-02 5.13069121339945E+00 3.81867710843760E+00
5 | 0.00000000000000E+00 3.20271484273091E+00 6.15962265706688E-01
6 | 7.80876481485857E-01 5.44391179630297E+00 7.59117398791786E+00
7 | 6.87276388152480E-02 5.24240030717430E+00 4.68004604192831E+00
8 | 1.63505424165356E+00 5.56619971715757E+00 1.17787920831172E+01
9 | 4.07725781500533E-01 5.53231480170862E+00 1.02387514999080E+01
10 | 7.91893054249850E-02 5.38642101274533E+00 6.47314118173772E+00
11 | 0.00000000000000E+00 4.58674109340718E+00 1.88640008833054E+00
12 | 3.77406078757493E+01 5.71330052925753E+00 3.20324916833237E+01
13 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/SuperflexRes.dat:
--------------------------------------------------------------------------------
1 | Data modelled by SF_ISO
2 | C1Wv%Qstream U1F1Wv%Eact U1F1Wv%Su[1]
3 | 5.18607360339175E-04 4.35045154127755E+00 1.49805970272422E+00
4 | 1.89561508273747E-02 4.24730450508732E+00 1.36553839089484E+00
5 | 0.00000000000000E+00 6.51167195055035E-01 6.32040007847661E-02
6 | 1.58181172623800E+00 5.57319122025259E+00 1.21531981078036E+01
7 | 1.00637505176013E-01 5.35851845212319E+00 6.03488619320518E+00
8 | 2.94940559504769E+00 5.64088998718866E+00 1.74542950287325E+01
9 | 6.36752984045714E-01 5.59934216287976E+00 1.37821047348815E+01
10 | 7.56969325101352E-02 5.37465692634240E+00 6.28139701717646E+00
11 | 0.00000000000000E+00 2.89224409675038E+00 4.96908823675695E-01
12 | 4.90474539482277E+01 5.72741039477882E+00 3.81471801376627E+01
13 |
--------------------------------------------------------------------------------
/test/reference_results/06_3Cats_2HRUs/test.py:
--------------------------------------------------------------------------------
1 | """
2 | File to create the results with Superflex
3 | """
4 |
5 | import sys
6 |
7 | # Add the path where the Superflex module is
8 | sys.path.append("/home/dalmo/Documents/BitBucket/superflexPython/C_so/")
9 | from os import chdir
10 |
11 | import numpy as np
12 | from superflex import Superflex_C
13 |
14 | chdir("/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/06_3Cats_2HRUs/")
15 |
16 | # Initialize the class
17 | sup = Superflex_C()
18 |
19 | # Load the model
20 | dims = sup.load_model()
21 |
22 | # Initialize the parameters
23 | parameters = np.array([[]])
24 |
25 | # Get the output
26 | output = sup.run_model(parameters)
27 |
28 | np.savetxt(
29 | "Results.csv",
30 | X=output,
31 | delimiter=",",
32 | header="Q_c1, Q_c2, Q_c3, Q_c1_h1, S_c1_h1_FR, Q_c2_h1, S_c2_h1_FR, Q_c3_h1, S_c3_h1_FR, Q_c1_h2, E_c1_h2_UR, S_c1_h2_UR, S_c1_h2_FR, S_c1_h2_SR, Q_c2_h2, E_c2_h2_UR, S_c2_h2_UR, S_c2_h2_FR, S_c2_h2_SR, Q_c3_h2, E_c3_h2_UR, S_c3_h2_UR, S_c3_h2_FR, S_c3_h2_SR",
33 | )
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/dalmo1991/superflexPy/actions)
2 | [](https://zenodo.org/badge/latestdoi/208847505)
3 |
4 | # SuperflexPy: The flexible language of hydrological modelling
5 |
6 | 
7 |
8 | SuperflexPy is an open-source framework written in Python for constructing
9 | flexible, conceptual, distributed hydrological models.
10 |
11 | Refer to the [documentation](https://superflexpy.readthedocs.io/) to learn to
12 | use the SuperflexPy, [install](https://pypi.org/project/superflexpy/) the
13 | package from here. [Examples](examples/) showing the basic usage of SuperflexPy
14 | are available.
15 |
16 | ## Development
17 |
18 | Please install all packages listed in the [requirements_dev.txt](requirements_dev.txt) file,
19 | the run `pre-commit install` to install the git hooks. This will enable code formatting and linting on every git commit.
20 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/Results.csv:
--------------------------------------------------------------------------------
1 | # Q_out, E_UR, S_UR, S_FR
2 | 4.970073536521080624e-09,5.258974893186536548e+00,4.838015249948993457e+00,3.009851894396357776e-03
3 | 2.541618578426108855e-05,5.130691213399449779e+00,3.818677108437596335e+00,9.163136382056072393e-02
4 | 2.539857716377526181e-05,3.202714842730908007e+00,6.159622657066883278e-01,9.160596524339441327e-02
5 | 6.969221550195355691e-03,5.443911796302973727e+00,7.591173987917855470e+00,8.655132251790572662e-01
6 | 8.251167171282486681e-03,5.242400307174300167e+00,4.680046041928307865e+00,9.259896968230227898e-01
7 | 9.545560128715058212e-02,5.566199717157565452e+00,1.177879208311717996e+01,2.465588337189435375e+00
8 | 1.251954915358534648e-01,5.532314801708615448e+00,1.023875149990803024e+01,2.748118627154114701e+00
9 | 1.205390933205765930e-01,5.386421012745326919e+00,6.473141181737718242e+00,2.706768839258514081e+00
10 | 1.087900105934205414e-01,4.586741093407180614e+00,1.886400088330537628e+00,2.597978828665093332e+00
11 | 1.959586382954269723e+01,5.713300529257533178e+00,3.203249168332367702e+01,2.074272287487173472e+01
12 |
--------------------------------------------------------------------------------
/doc/share_models_code.py:
--------------------------------------------------------------------------------
1 | from superflexpy.framework.unit import Unit
2 | from superflexpy.implementation.elements.hbv import PowerReservoir, UnsaturatedReservoir
3 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
4 | ImplicitEulerPython,
5 | )
6 | from superflexpy.implementation.root_finders.pegasus import PegasusPython
7 |
8 | root_finder = PegasusPython()
9 | numeric_approximator = ImplicitEulerPython(root_finder=root_finder)
10 |
11 | ur = UnsaturatedReservoir(
12 | parameters={"Smax": 50.0, "Ce": 1.0, "m": 0.01, "beta": 2.0},
13 | states={"S0": 25.0},
14 | approximation=numeric_approximator,
15 | id="UR",
16 | )
17 |
18 | fr = PowerReservoir(
19 | parameters={"k": 0.1, "alpha": 1.0}, states={"S0": 10.0}, approximation=numeric_approximator, id="FR"
20 | )
21 |
22 | model = Unit(layers=[[ur], [fr]], id="M4")
23 |
24 | from superflexpy.implementation.models.m4_sf_2011 import model
25 |
26 | model.set_input([P, E])
27 | model.set_timestep(1.0)
28 | model.reset_states()
29 |
30 | output = model.get_output()
31 |
32 | from .my_new_model import model
33 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$03_UR_FR/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$03_UR_FR/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$03_UR_FR/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 4 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,4,5,6 output S
12 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$04_UR_FR_SR/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$04_UR_FR_SR/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$04_UR_FR_SR/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 5 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,4,5,6,7 output S
12 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$05_2HRUs/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$05_2HRUs/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$05_2HRUs/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 9 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,2,4,5,6,8,9,10,11 output S
12 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/SuperflexRes.dat:
--------------------------------------------------------------------------------
1 | Data modelled by SF_ISO
2 | C1Wv%Qstream U1F1Wv%Eact U1F1Wv%Su[1] U1F1Wv%Sf[1]
3 | 4.97007353652108E-09 5.25897489318654E+00 4.83801524994899E+00 3.00985189439636E-03
4 | 2.54161857842611E-05 5.13069121339945E+00 3.81867710843760E+00 9.16313638205607E-02
5 | 2.53985771637753E-05 3.20271484273091E+00 6.15962265706688E-01 9.16059652433944E-02
6 | 6.96922155019536E-03 5.44391179630297E+00 7.59117398791786E+00 8.65513225179057E-01
7 | 8.25116717128249E-03 5.24240030717430E+00 4.68004604192831E+00 9.25989696823023E-01
8 | 9.54556012871506E-02 5.56619971715757E+00 1.17787920831172E+01 2.46558833718944E+00
9 | 1.25195491535853E-01 5.53231480170862E+00 1.02387514999080E+01 2.74811862715411E+00
10 | 1.20539093320577E-01 5.38642101274533E+00 6.47314118173772E+00 2.70676883925851E+00
11 | 1.08790010593421E-01 4.58674109340718E+00 1.88640008833054E+00 2.59797882866509E+00
12 | 1.95958638295427E+01 5.71330052925753E+00 3.20324916833237E+01 2.07427228748717E+01
13 |
--------------------------------------------------------------------------------
/superflexpy/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import framework, implementation, utils
27 |
28 | __all__ = ["framework", "implementation", "utils"]
29 |
--------------------------------------------------------------------------------
/superflexpy/framework/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import element, network, node, unit
27 |
28 | __all__ = ["element", "network", "node", "unit"]
29 |
--------------------------------------------------------------------------------
/superflexpy/implementation/root_finders/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import explicit, newton, pegasus
27 |
28 | __all__ = ["explicit", "newton", "pegasus"]
29 |
--------------------------------------------------------------------------------
/superflexpy/implementation/models/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import gr4j, hymod, m4_sf_2011, thur_M2
27 |
28 | __all__ = ["gr4j", "hymod", "m4_sf_2011", "thur_M2"]
29 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$01_FR/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$01_FR/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$01_FR/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 2 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,5 output S
12 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$02_UR/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$02_UR/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$02_UR/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 3 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,4,5 output S
12 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples of the usage of SuperflexPy
2 |
3 | This folder contains Jupyter notebooks with example models constructed using
4 | SuperflexPy. The examples can be visualized using GitHub or executed in a
5 | sandbox environment using [](https://mybinder.org/v2/gh/dalmo1991/superflexPy/master?filepath=examples)
6 |
7 | The examples are the following:
8 |
9 | - [Run a simple model](./01_run_simple_model.ipynb)
10 | - [Calibrate a model](./02_calibrate_a_model.ipynb)
11 | - [Initialize a single element model](./03_init_single_element_model.ipynb)
12 | - [Initialize a single unit model](./04_init_single_unit_model.ipynb)
13 | - [Initialize a simple node model](./05_init_single_node_model.ipynb)
14 | - [Initialize a complete (network) model](./06_init_complete_model.ipynb)
15 | - [Create a new reservoir](./07_create_reservoir.ipynb)
16 | - [Replicate GR4J](./08_GR4J.ipynb)
17 | - [Replicate Hymod](./09_Hymod.ipynb)
18 | - [Replicate M02 in Dal Molin et al., HESS, 2020](./10_Thur_M2.ipynb)
19 | - [Replicate M4 in Kavetski and Fenicia, WRR, 2011](./11_M4_sfPaper.ipynb)
20 | - [Modify M4 in Kavetski and Fenicia, WRR, 2011](./12_M4_sfPaper_changed.ipynb)
21 |
--------------------------------------------------------------------------------
/superflexpy/utils/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import generic_component, numerical_approximator, root_finder
27 |
28 | __all__ = ["generic_component", "numerical_approximator", "root_finder"]
29 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$07_FR_2dt/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$07_FR_2dt/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$07_FR_2dt/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 2 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,5 output S
12 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$08_UR_2dt/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$08_UR_2dt/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$08_UR_2dt/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 3 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,4,5 output S
12 |
--------------------------------------------------------------------------------
/test/reference_results/06_3Cats_2HRUs/modelInfo.dat:
--------------------------------------------------------------------------------
1 | FLEX_MODEL_INFO_FILE_V1.00
2 | "$(CASE_STUDIES)$" "/home/dalmo/Documents/BitBucket/superflexpy_aug2019/test/reference_results/" relative path
3 | "$(CASE_STUDIES)$06_3Cats_2HRUs/test.INF_DAT" inf_dat file (rel to case study path)
4 | "$(CASE_STUDIES)$06_3Cats_2HRUs/M01_main.dat" flexConfig file
5 | "" fileNamePar (if blank uses parameters from flexConfig file)
6 | "$(CASE_STUDIES)$06_3Cats_2HRUs/SuperflexRes.dat" fileNameOut (if blank if blank it no file is written)
7 | 2 parameter format (1:all, 2:fitted, 3:fitted matrix)
8 | 0, 0, 24 nX, nY, nS (0 if no output)
9 | 0 output X
10 | 0 output Y
11 | 1,2,3,4,7,8,11,12,15,16,18,19,20,21,22,24,25,26,27,28,30,31,32,33 output S
12 |
--------------------------------------------------------------------------------
/superflexpy/implementation/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import elements, models, numerical_approximators, root_finders
27 |
28 | __all__ = ["elements", "models", "numerical_approximators", "root_finders"]
29 |
--------------------------------------------------------------------------------
/superflexpy/implementation/numerical_approximators/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import explicit_euler, implicit_euler, runge_kutta_4
27 |
28 | __all__ = ["explicit_euler", "implicit_euler", "runge_kutta_4"]
29 |
--------------------------------------------------------------------------------
/superflexpy/implementation/elements/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | from . import gr4j, hbv, hymod, structure_elements, thur_model_hess
27 |
28 | __all__ = ["gr4j", "hbv", "hymod", "structure_elements", "thur_model_hess"]
29 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$01_FR/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 9 ! number of data columns in observation data file
10 |
11 | 2,1 ! number of columns for inputs (X) and others (Y)
12 | 7,8 ! column indices of observed input data
13 | 9 ! column indices of observed other data
14 |
15 | 1.e0,1.e0 ! conversion factors for input data
16 | 1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$02_UR/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 9 ! number of data columns in observation data file
10 |
11 | 2,1 ! number of columns for inputs (X) and others (Y)
12 | 7,8 ! column indices of observed input data
13 | 9 ! column indices of observed other data
14 |
15 | 1.e0,1.e0 ! conversion factors for input data
16 | 1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$03_UR_FR/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 9 ! number of data columns in observation data file
10 |
11 | 2,1 ! number of columns for inputs (X) and others (Y)
12 | 7,8 ! column indices of observed input data
13 | 9 ! column indices of observed other data
14 |
15 | 1.e0,1.e0 ! conversion factors for input data
16 | 1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$05_2HRUs/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 9 ! number of data columns in observation data file
10 |
11 | 2,1 ! number of columns for inputs (X) and others (Y)
12 | 7,8 ! column indices of observed input data
13 | 9 ! column indices of observed other data
14 |
15 | 1.e0,1.e0 ! conversion factors for input data
16 | 1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$07_FR_2dt/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 9 ! number of data columns in observation data file
10 |
11 | 2,1 ! number of columns for inputs (X) and others (Y)
12 | 7,8 ! column indices of observed input data
13 | 9 ! column indices of observed other data
14 |
15 | 1.e0,1.e0 ! conversion factors for input data
16 | 1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$08_UR_2dt/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 9 ! number of data columns in observation data file
10 |
11 | 2,1 ! number of columns for inputs (X) and others (Y)
12 | 7,8 ! column indices of observed input data
13 | 9 ! column indices of observed other data
14 |
15 | 1.e0,1.e0 ! conversion factors for input data
16 | 1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$04_UR_FR_SR/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 9 ! number of data columns in observation data file
10 |
11 | 2,1 ! number of columns for inputs (X) and others (Y)
12 | 7,8 ! column indices of observed input data
13 | 9 ! column indices of observed other data
14 |
15 | 1.e0,1.e0 ! conversion factors for input data
16 | 1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/doc/numerical_solver_code.py:
--------------------------------------------------------------------------------
1 | """
2 | This code contains a quick example to implement the nomerical approximator
3 | and the root finder. The only purpose of this code is being put in the
4 | documentation.
5 | """
6 |
7 | from ...superflexpy.utils.numerical_approximator import NumericalApproximator
8 | from ...superflexpy.utils.root_finder import RootFinder
9 |
10 |
11 | class CustomRootFinder(RootFinder):
12 | def solve(self, diff_eq_fun, fluxes_fun, S0, dt, ind, args):
13 | # Some code here
14 |
15 | return root
16 |
17 |
18 | class CustomNumericalApproximator(NumericalApproximator):
19 | @staticmethod
20 | def _get_fluxes(fluxes_fun, S, S0, args, dt):
21 | # Some code here
22 |
23 | return fluxes
24 |
25 | @staticmethod
26 | def _differential_equation(fluxes_fun, S, S0, dt, args, ind):
27 | # Some code here
28 |
29 | return [diff_eq, min_val, max_val, d_diff_eq]
30 |
31 |
32 | class CustomODESolver:
33 | # The class may implement other methods
34 |
35 | def solve(self, fluxes_fun, S0, dt, args):
36 | # Some code here
37 |
38 | return states
39 |
40 | def get_fluxes(self, fluxes_fun, S, S0, dt, args):
41 | # Some code here
42 |
43 | return fluxes
44 |
--------------------------------------------------------------------------------
/test/reference_results/06_3Cats_2HRUs/test.INF_DAT:
--------------------------------------------------------------------------------
1 | DATA_SPEX_FILE_V1.3
2 | "Lacmalac data" ! file comment (not used)
3 | "$(CASE_STUDIES)$06_3Cats_2HRUs/input.dat" ! observation file
4 |
5 | 0 ! file format (unsupported), 0=standard
6 | 5 ! number of header lines to skip to format specification
7 | 7 ! number of header lines to the data cols
8 |
9 | 17 ! number of data columns in observation data file
10 |
11 | 6,3 ! number of columns for inputs (X) and others (Y)
12 | 6,7,8,9,10,11 ! column indices of observed input data
13 | 12,14,16 ! column indices of observed other data
14 |
15 | 1.e0,1.e0,1.e0,1.e0,1.e0,1.e0 ! conversion factors for input data
16 | 1.e0,1.e0,1.e0 ! conversion factors for other data
17 |
18 | 0 ! number of quality code columns (ie, number of distinct values on the next line)
19 | 0 ! indxQC: quality code columns for all data
20 | 0,0 ! quality code columns for observed input data (relative to indxQC)
21 | 0 ! quality code columns for observed other data (relative to indxQC)
22 |
23 | 1, 1, 10 ! iStartWarmInfern, iStartInfern, iEndInfern 1, 27, 679 / 1, 680, 1331 / 1, 27, 353 / 1, 27, 1331 / 1, 27, 6549
24 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/Results.csv:
--------------------------------------------------------------------------------
1 | # Q_out, E_UR, S_UR, S_FR, S_SR
2 | 2.109139143916991476e-07,5.258974893186536548e+00,4.838015249948993457e+00,9.029568143400985066e-04,2.106689136215304358e-03
3 | 7.668930222361160562e-06,5.130691213399449779e+00,3.818677108437596335e+00,2.749578163005263545e-02,6.415312350222930615e-02
4 | 7.668145885635599773e-06,3.202714842730908007e+00,6.159622657066883278e-01,2.749452815505013317e-02,6.414670883134616919e-02
5 | 4.104495408040214244e-04,5.443911796302973727e+00,7.591173987917855470e+00,2.614080929775984830e-01,6.106991759538503706e-01
6 | 4.867007414670093310e-04,5.242400307174300167e+00,4.680046041928307865e+00,2.816055581455917389e-01,6.587426488596379581e-01
7 | 5.331958260418389467e-03,5.566199717157565452e+00,1.177879208311717996e+01,7.669701824120410683e-01,1.803100307986333251e+00
8 | 7.514327856159554175e-03,5.532314801708615448e+00,1.023875149990803024e+01,8.819824189585497853e-01,2.088299525084197583e+00
9 | 7.858097956005493170e-03,5.386421012745326919e+00,6.473141181737718242e+00,8.980954643987495434e-01,2.143517687112975523e+00
10 | 7.699797584115572295e-03,4.586741093407180614e+00,1.886400088330537628e+00,8.906099971503117496e-01,2.143303356777297886e+00
11 | 2.755480883685404336e+00,5.713300529257533178e+00,3.203249168332367702e+01,9.460167363487958170e+00,2.855887298250357631e+01
12 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/SuperflexRes.dat:
--------------------------------------------------------------------------------
1 | Data modelled by SF_ISO
2 | C1Wv%Qstream U1F1Wv%Eact U1F1Wv%Su[1] U1F1Wv%Sf[1] U1F1Wv%Ss[1]
3 | 2.10913914391699E-07 5.25897489318654E+00 4.83801524994899E+00 9.02956814340099E-04 2.10668913621530E-03
4 | 7.66893022236116E-06 5.13069121339945E+00 3.81867710843760E+00 2.74957816300526E-02 6.41531235022293E-02
5 | 7.66814588563560E-06 3.20271484273091E+00 6.15962265706688E-01 2.74945281550501E-02 6.41467088313462E-02
6 | 4.10449540804021E-04 5.44391179630297E+00 7.59117398791786E+00 2.61408092977598E-01 6.10699175953850E-01
7 | 4.86700741467009E-04 5.24240030717430E+00 4.68004604192831E+00 2.81605558145592E-01 6.58742648859638E-01
8 | 5.33195826041839E-03 5.56619971715757E+00 1.17787920831172E+01 7.66970182412041E-01 1.80310030798633E+00
9 | 7.51432785615955E-03 5.53231480170862E+00 1.02387514999080E+01 8.81982418958550E-01 2.08829952508420E+00
10 | 7.85809795600549E-03 5.38642101274533E+00 6.47314118173772E+00 8.98095464398750E-01 2.14351768711298E+00
11 | 7.69979758411557E-03 4.58674109340718E+00 1.88640008833054E+00 8.90609997150312E-01 2.14330335677730E+00
12 | 2.75548088368540E+00 5.71330052925753E+00 3.20324916833237E+01 9.46016736348796E+00 2.85588729825036E+01
13 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 1.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | year, month, day, hour, min, QC, P (mm/d), E (mm/d), Q_obs (mm/d)
8 | 1985 1 2 0 0 0 1.000000e-001 0.000000e+000 2.646000e-001
9 | 1985 1 3 0 0 0 4.200000e+000 0.000000e+000 4.426105e-001
10 | 1985 1 4 0 0 0 0.000000e+000 0.000000e+000 3.278842e-001
11 | 1985 1 5 0 0 0 1.320000e+001 0.000000e+000 5.415158e-001
12 | 1985 1 6 0 0 0 2.400000e+000 0.000000e+000 6.209053e-001
13 | 1985 1 7 0 0 0 1.430000e+001 0.000000e+000 1.255737e+000
14 | 1985 1 8 0 0 0 4.400000e+000 0.000000e+000 7.436842e-001
15 | 1985 1 9 0 0 0 1.700000e+000 0.000000e+000 4.998316e-001
16 | 1985 1 10 0 0 0 0.000000e+000 0.000000e+000 2.404421e-001
17 | 1985 1 11 0 0 0 7.360000e+001 0.000000e+000 2.727445e+001
18 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 1.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | year, month, day, hour, min, QC, P (mm/d), E (mm/d), Q_obs (mm/d)
8 | 1985 1 2 0 0 0 1.000000e-001 3.830020e+000 2.646000e-001
9 | 1985 1 3 0 0 0 4.200000e+000 3.830020e+000 4.426105e-001
10 | 1985 1 4 0 0 0 0.000000e+000 3.830020e+000 3.278842e-001
11 | 1985 1 5 0 0 0 1.320000e+001 3.830020e+000 5.415158e-001
12 | 1985 1 6 0 0 0 2.400000e+000 3.830020e+000 6.209053e-001
13 | 1985 1 7 0 0 0 1.430000e+001 3.830020e+000 1.255737e+000
14 | 1985 1 8 0 0 0 4.400000e+000 3.830020e+000 7.436842e-001
15 | 1985 1 9 0 0 0 1.700000e+000 3.830020e+000 4.998316e-001
16 | 1985 1 10 0 0 0 0.000000e+000 3.830020e+000 2.404421e-001
17 | 1985 1 11 0 0 0 7.360000e+001 3.830020e+000 2.727445e+001
18 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 1.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | year, month, day, hour, min, QC, P (mm/d), E (mm/d), Q_obs (mm/d)
8 | 1985 1 2 0 0 0 1.000000e-001 3.830020e+000 2.646000e-001
9 | 1985 1 3 0 0 0 4.200000e+000 3.830020e+000 4.426105e-001
10 | 1985 1 4 0 0 0 0.000000e+000 3.830020e+000 3.278842e-001
11 | 1985 1 5 0 0 0 1.320000e+001 3.830020e+000 5.415158e-001
12 | 1985 1 6 0 0 0 2.400000e+000 3.830020e+000 6.209053e-001
13 | 1985 1 7 0 0 0 1.430000e+001 3.830020e+000 1.255737e+000
14 | 1985 1 8 0 0 0 4.400000e+000 3.830020e+000 7.436842e-001
15 | 1985 1 9 0 0 0 1.700000e+000 3.830020e+000 4.998316e-001
16 | 1985 1 10 0 0 0 0.000000e+000 3.830020e+000 2.404421e-001
17 | 1985 1 11 0 0 0 7.360000e+001 3.830020e+000 2.727445e+001
18 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 1.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | year, month, day, hour, min, QC, P (mm/d), E (mm/d), Q_obs (mm/d)
8 | 1985 1 2 0 0 0 1.000000e-001 3.830020e+000 2.646000e-001
9 | 1985 1 3 0 0 0 4.200000e+000 3.830020e+000 4.426105e-001
10 | 1985 1 4 0 0 0 0.000000e+000 3.830020e+000 3.278842e-001
11 | 1985 1 5 0 0 0 1.320000e+001 3.830020e+000 5.415158e-001
12 | 1985 1 6 0 0 0 2.400000e+000 3.830020e+000 6.209053e-001
13 | 1985 1 7 0 0 0 1.430000e+001 3.830020e+000 1.255737e+000
14 | 1985 1 8 0 0 0 4.400000e+000 3.830020e+000 7.436842e-001
15 | 1985 1 9 0 0 0 1.700000e+000 3.830020e+000 4.998316e-001
16 | 1985 1 10 0 0 0 0.000000e+000 3.830020e+000 2.404421e-001
17 | 1985 1 11 0 0 0 7.360000e+001 3.830020e+000 2.727445e+001
18 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 2.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | year, month, day, hour, min, QC, P (mm/d), E (mm/d), Q_obs (mm/d)
8 | 1985 1 2 0 0 0 1.000000e-001 0.000000e+000 2.646000e-001
9 | 1985 1 3 0 0 0 4.200000e+000 0.000000e+000 4.426105e-001
10 | 1985 1 4 0 0 0 0.000000e+000 0.000000e+000 3.278842e-001
11 | 1985 1 5 0 0 0 1.320000e+001 0.000000e+000 5.415158e-001
12 | 1985 1 6 0 0 0 2.400000e+000 0.000000e+000 6.209053e-001
13 | 1985 1 7 0 0 0 1.430000e+001 0.000000e+000 1.255737e+000
14 | 1985 1 8 0 0 0 4.400000e+000 0.000000e+000 7.436842e-001
15 | 1985 1 9 0 0 0 1.700000e+000 0.000000e+000 4.998316e-001
16 | 1985 1 10 0 0 0 0.000000e+000 0.000000e+000 2.404421e-001
17 | 1985 1 11 0 0 0 7.360000e+001 0.000000e+000 2.727445e+001
18 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 2.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | year, month, day, hour, min, QC, P (mm/d), E (mm/d), Q_obs (mm/d)
8 | 1985 1 2 0 0 0 1.000000e-001 3.830020e+000 2.646000e-001
9 | 1985 1 3 0 0 0 4.200000e+000 3.830020e+000 4.426105e-001
10 | 1985 1 4 0 0 0 0.000000e+000 3.830020e+000 3.278842e-001
11 | 1985 1 5 0 0 0 1.320000e+001 3.830020e+000 5.415158e-001
12 | 1985 1 6 0 0 0 2.400000e+000 3.830020e+000 6.209053e-001
13 | 1985 1 7 0 0 0 1.430000e+001 3.830020e+000 1.255737e+000
14 | 1985 1 8 0 0 0 4.400000e+000 3.830020e+000 7.436842e-001
15 | 1985 1 9 0 0 0 1.700000e+000 3.830020e+000 4.998316e-001
16 | 1985 1 10 0 0 0 0.000000e+000 3.830020e+000 2.404421e-001
17 | 1985 1 11 0 0 0 7.360000e+001 3.830020e+000 2.727445e+001
18 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 1.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | year, month, day, hour, min, QC, P (mm/d), E (mm/d), Q_obs (mm/d)
8 | 1985 1 2 0 0 0 1.000000e-001 3.830020e+000 2.646000e-001
9 | 1985 1 3 0 0 0 4.200000e+000 3.830020e+000 4.426105e-001
10 | 1985 1 4 0 0 0 0.000000e+000 3.830020e+000 3.278842e-001
11 | 1985 1 5 0 0 0 1.320000e+001 3.830020e+000 5.415158e-001
12 | 1985 1 6 0 0 0 2.400000e+000 3.830020e+000 6.209053e-001
13 | 1985 1 7 0 0 0 1.430000e+001 3.830020e+000 1.255737e+000
14 | 1985 1 8 0 0 0 4.400000e+000 3.830020e+000 7.436842e-001
15 | 1985 1 9 0 0 0 1.700000e+000 3.830020e+000 4.998316e-001
16 | 1985 1 10 0 0 0 0.000000e+000 3.830020e+000 2.404421e-001
17 | 1985 1 11 0 0 0 7.360000e+001 3.830020e+000 2.727445e+001
18 |
--------------------------------------------------------------------------------
/doc/installation.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 03/05/2021
2 |
3 | .. .. warning:: This guide is still work in progress. New pages are being written
4 | .. and existing ones modified. Once the guide will reach its final
5 | .. version, this box will disappear.
6 |
7 | .. _installation_label:
8 |
9 | Installation
10 | ============
11 |
12 | SuperflexPy is implemented using Python 3 (version 3.7.3). It is not compatible
13 | with Python 2.
14 |
15 | SuperflexPy is available as a Python package at
16 | `PyPI repository `_
17 |
18 | The simplest way to install SuperflexPy is to use the package installer for
19 | Python (pip). Open the operating system command prompt and run the command
20 |
21 | .. code-block:: bash
22 |
23 | pip install superflexpy
24 |
25 | To upgrade to a newer SuperflexPy version (when available), run the following command
26 |
27 | .. code-block:: bash
28 |
29 | pip install --upgrade superflexpy
30 |
31 | Dependencies
32 | ------------
33 |
34 | SuperflexPy requires the following Python packages
35 |
36 | - `Numpy `_
37 | - `Numba `_
38 |
39 | All dependencies are available through pip and will be installed automatically
40 | when installing SuperflexPy.
41 |
42 | Note that Numba is required only if the modeler wishes to use the Numba
43 | optimized implementation of the numerical solvers. GPU acceleration (CUDA) is
44 | currently not supported but will be explored in future versions.
45 |
--------------------------------------------------------------------------------
/doc/sfpy_in_literature.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 09/08/2022
2 |
3 | .. _sfpy_lit:
4 |
5 | SuperflexPy in the scientific literature
6 | ========================================
7 |
8 | This page lists the scientific publications presenting SuperflexPy or using it
9 | in specific applications.
10 |
11 | .. tip::
12 | If you use SuperflexPy for your publication, please `open an issue `_ in the GitHub
13 | repository so we will add it to this page.
14 |
15 | Previous publications on FLEX and Superflex
16 | -------------------------------------------
17 |
18 | - Fenicia, F., Savenije, H. H. G.,Matgen, P., and Pfister, L.: **Understanding catchment behavior through stepwise model concept improvement**, Water Resources Research, 44, W01402, https://doi.org/10.1029/2006WR005563, 2008.
19 | - Fenicia, F., Kavetski D., and Savenije H. H. G.: **Elements of a flexible approach for conceptual hydrological modeling: 1. Motivation and theoretical development**, Water Resources Research, 47(11), W11510, https://doi.org/10.1029/2010wr010174, 2011
20 | - Kavetski, D., and Fenicia F.: **Elements of a flexible approach for conceptual hydrological modeling: 2. Application and experimental insights**, Water Resources Research, 47(11), W11511, https://doi.org/10.1029/2011wr010748, 2011
21 |
22 | Publications on SuperflexPy
23 | ---------------------------
24 |
25 | - Dal Molin, M., Kavetski, D., and Fenicia, F.: **SuperflexPy 1.3.0: an open**
26 | **source framework for building, testing and improving conceptual**
27 | **hydrological models**, Geosci. Model Dev., https://doi.org/10.5194/gmd-14-7047-2021, 2021.
28 |
29 | Publications using SuperflexPy
30 | ------------------------------
31 |
32 | - Jansen, K. F., Teuling, A.J., Craig, J. R., Dal Molin, M., Knoben, W. J. M.,
33 | Parajka, J., Vis, M., and Melsen, L. A.: **Mimicry of a conceptual**
34 | **hydrological model (HBV): what's in a name?**, Water Resources Research, 57,
35 | e2020WR029143. https://doi.org/10.1029/2020WR029143, 2020.
36 |
--------------------------------------------------------------------------------
/doc/testing.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 04/05/2021
2 |
3 | .. _tests:
4 |
5 | Automated testing
6 | =================
7 |
8 | Current testing of SuperflexPy consists of validating its numerical results
9 | against the original implementation of
10 | `Superflex `_. This testing is done for
11 | selected model configurations and selected sets of parameters and inputs.
12 |
13 | This testing strategy implicitly checks auxiliary methods, including setting
14 | parameters and states, retrieving the internal fluxes of the model, setting
15 | inputs and getting outputs, etc..
16 |
17 | The testing code is contained in folder :code:`test` and uses the Python module
18 | :code:`unittest`. The folder contains :code:`reference_results`
19 | and :code:`unittest` containing the scripts that run the tests.
20 |
21 | Current testing covers:
22 |
23 | - Specific elements (reservoirs and lag functions) that
24 | are implemented in Superflex (e.g. :code:`01_FR.py`, :code:`02_UR.py`);
25 | - Multiple elements in a unit (e.g.
26 | :code:`03_UR_FR.py`, :code:`04_UR_FR_SR.py`);
27 | - Multiple units in a node (e.g. :code:`05_2HRUs.py`);
28 | - Multiple nodes inside a network (e.g.
29 | :code:`06_3Cats_2HRUs.py`);
30 | - Auxiliary methods, which are tested implicitly, i.e. assuming that
31 | errors in the auxiliary methods propagate to the results.
32 |
33 | Current testing does not cover:
34 |
35 | - Elements for which numerical results are not available (e.g. some components
36 | of GR4J);
37 | - Usage of the Explicit Euler solver;
38 | - Edge cases (e.g. extreme values of parameters and states)
39 |
40 | Users contributing SuperflexPy extensions should provide reference
41 | results and the code that tests them (including input data and model parameter
42 | values).
43 |
44 | As the SuperflexPy framework continues to develop, additional facilities for
45 | unit-testing and integrated-testing will be employed.
46 |
47 | Automation
48 | ----------
49 |
50 | Any push of new code to any branch on the github repository will trigger
51 | automatic testing based on the scripts contained in the folder
52 | :code:`test/unittest`.
53 |
--------------------------------------------------------------------------------
/doc/customize_components_code.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from superflexpy.framework.node import Node
4 |
5 |
6 | class RoutedNone(Node):
7 | """
8 | Node class with parameters 't_internal' and 't_external' that implements
9 | internal and external routing using a triangular lag (symmentric) with
10 | base t_internal and t_external respectively. Settng the value lower to 1
11 | means no lag.
12 | """
13 |
14 | def _internal_routing(self, flux):
15 | t_internal = self.get_parameters(names=[self._prefix_local_parameters + "t_internal"])
16 | flux_out = []
17 |
18 | for f in flux:
19 | flux_out.append(self._route(f, t_internal))
20 |
21 | return flux_out
22 |
23 | def external_routing(self, flux):
24 | t_external = self.get_parameters(names=[self._prefix_local_parameters + "t_external"])
25 | flux_out = []
26 |
27 | for f in flux:
28 | flux_out.append(self._route(f, t_external))
29 |
30 | return flux_out
31 |
32 | def _route(self, flux, time):
33 | state = np.zeros(int(np.ceil(time)))
34 | weight = self._calculate_weight(time)
35 |
36 | out = []
37 | for value in flux:
38 | state = state + weight * value
39 | out.append(state[0])
40 | state[0] = 0
41 | state = np.roll(state, shift=-1)
42 |
43 | return np.array(out)
44 |
45 | def _calculate_weight(self, time):
46 | weight = []
47 |
48 | array_length = np.ceil(time)
49 |
50 | for i in range(int(array_length)):
51 | weight.append(self._calculate_lag_area(i + 1, time) - self._calculate_lag_area(i, time))
52 |
53 | return weight
54 |
55 | @staticmethod
56 | def _calculate_lag_area(portion, time):
57 | half_time = time / 2
58 |
59 | if portion <= 0:
60 | value = 0
61 | elif portion < half_time:
62 | value = 2 * (portion / time) ** 2
63 | elif portion < time:
64 | value = 1 - 2 * ((time - portion) / time) ** 2
65 | else:
66 | value = 1
67 |
68 | return value
69 |
--------------------------------------------------------------------------------
/superflexpy/implementation/models/m4_sf_2011.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 |
25 | This file implements the model M4 presented in Kavetsi and Fenicia, 2011.
26 |
27 | Reference
28 | ---------
29 |
30 | Kavetski, D., and F. Fenicia (2011), Elements of a flexible approach
31 | for conceptual hydrological modeling: 2. Application and experimental insights,
32 | Water Resour. Res., 47, W11511, doi:10.1029/2011WR010748
33 | """
34 |
35 | from superflexpy.framework.unit import Unit
36 | from superflexpy.implementation.elements.hbv import PowerReservoir, UnsaturatedReservoir
37 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
38 | ImplicitEulerPython,
39 | )
40 | from superflexpy.implementation.root_finders.pegasus import PegasusPython
41 |
42 | root_finder = PegasusPython()
43 | numeric_approximator = ImplicitEulerPython(root_finder=root_finder)
44 |
45 | ur = UnsaturatedReservoir(
46 | parameters={"Smax": 50.0, "Ce": 1.0, "m": 0.01, "beta": 2.0},
47 | states={"S0": 25.0},
48 | approximation=numeric_approximator,
49 | id="UR",
50 | )
51 |
52 | fr = PowerReservoir(
53 | parameters={"k": 0.1, "alpha": 1.0}, states={"S0": 10.0}, approximation=numeric_approximator, id="FR"
54 | )
55 |
56 | model = Unit(layers=[[ur], [fr]], id="M4")
57 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/Results.csv:
--------------------------------------------------------------------------------
1 | # Q_tot, Q_H1, E_FR_H1, S_FR_H1, Q_H2, E_UR_H2, S_UR_H2, S_FR_H2, S_SR_H2
2 | 1.276566925472585057e-05,3.159780226522707953e-05,0.000000000000000000e+00,9.996840219773421576e-02,2.109139143916991476e-07,5.258974893186536548e+00,4.838015249948993457e+00,9.029568143400985066e-04,2.106689136215304358e-03
3 | 1.266726459154998430e-01,3.166701113934160539e-01,0.000000000000000000e+00,3.983298290804318409e+00,7.668930222361160562e-06,5.130691213399449779e+00,3.818677108437596335e+00,2.749578163005263545e-02,6.415312350222930615e-02
4 | 1.065474297827361805e-01,2.663570722380119715e-01,0.000000000000000000e+00,3.716941218566306659e+00,7.668145885635599773e-06,3.202714842730908007e+00,6.159622657066883278e-01,2.749452815505013317e-02,6.414670883134616919e-02
5 | 1.981036826683929997e+00,4.951976392398618643e+00,0.000000000000000000e+00,1.196496482616768731e+01,4.104495408040214244e-04,5.443911796302973727e+00,7.591173987917855470e+00,2.614080929775984830e-01,6.106991759538503706e-01
6 | 1.483389933158973051e+00,3.707744781785232480e+00,0.000000000000000000e+00,1.065722004438245385e+01,4.867007414670093310e-04,5.242400307174300167e+00,4.680046041928307865e+00,2.816055581455917389e-01,6.587426488596379581e-01
7 | 3.786313981468475642e+00,9.457787016280562398e+00,0.000000000000000000e+00,1.549943302810189394e+01,5.331958260418389467e-03,5.566199717157565452e+00,1.177879208311717996e+01,7.669701824120410683e-01,1.803100307986333251e+00
8 | 2.617508628982714747e+00,6.532500080672547504e+00,0.000000000000000000e+00,1.336693294742934945e+01,7.514327856159554175e-03,5.532314801708615448e+00,1.023875149990803024e+01,8.819824189585497853e-01,2.088299525084197583e+00
9 | 1.620239975627732365e+00,4.038812792135322738e+00,0.000000000000000000e+00,1.102812015529402778e+01,7.858097956005493170e-03,5.386421012745326919e+00,6.473141181737718242e+00,8.980954643987495434e-01,2.143517687112975523e+00
10 | 9.126216427681178578e-01,2.270004410544121498e+00,0.000000000000000000e+00,8.758115744749906284e+00,7.699797584115572295e-03,4.586741093407180614e+00,1.886400088330537628e+00,8.906099971503117496e-01,2.143303356777297886e+00
11 | 2.235949870695818831e+01,5.176552544186736071e+01,0.000000000000000000e+00,3.059259030288254877e+01,2.755480883685404336e+00,5.713300529257533178e+00,3.203249168332367702e+01,9.460167363487958170e+00,2.855887298250357631e+01
12 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/SuperflexRes.dat:
--------------------------------------------------------------------------------
1 | Data modelled by SF_ISO
2 | C1Wv%Qstream U1F1Wv%Qstrm U1F1Wv%Eact U1F1Wv%Sf[1] U2F1Wv%Qstrm U2F1Wv%Eact U2F1Wv%Su[1] U2F1Wv%Sf[1] U2F1Wv%Ss[1]
3 | 1.27656692547259E-05 3.15978022652271E-05 0.00000000000000E+00 9.99684021977342E-02 2.10913914391699E-07 5.25897489318654E+00 4.83801524994899E+00 9.02956814340099E-04 2.10668913621530E-03
4 | 1.26672645915500E-01 3.16670111393416E-01 0.00000000000000E+00 3.98329829080432E+00 7.66893022236116E-06 5.13069121339945E+00 3.81867710843760E+00 2.74957816300526E-02 6.41531235022293E-02
5 | 1.06547429782736E-01 2.66357072238012E-01 0.00000000000000E+00 3.71694121856631E+00 7.66814588563560E-06 3.20271484273091E+00 6.15962265706688E-01 2.74945281550501E-02 6.41467088313462E-02
6 | 1.98103682668393E+00 4.95197639239862E+00 0.00000000000000E+00 1.19649648261677E+01 4.10449540804021E-04 5.44391179630297E+00 7.59117398791786E+00 2.61408092977598E-01 6.10699175953850E-01
7 | 1.48338993315897E+00 3.70774478178523E+00 0.00000000000000E+00 1.06572200443825E+01 4.86700741467009E-04 5.24240030717430E+00 4.68004604192831E+00 2.81605558145592E-01 6.58742648859638E-01
8 | 3.78631398146848E+00 9.45778701628056E+00 0.00000000000000E+00 1.54994330281019E+01 5.33195826041839E-03 5.56619971715757E+00 1.17787920831172E+01 7.66970182412041E-01 1.80310030798633E+00
9 | 2.61750862898271E+00 6.53250008067255E+00 0.00000000000000E+00 1.33669329474293E+01 7.51432785615955E-03 5.53231480170862E+00 1.02387514999080E+01 8.81982418958550E-01 2.08829952508420E+00
10 | 1.62023997562773E+00 4.03881279213532E+00 0.00000000000000E+00 1.10281201552940E+01 7.85809795600549E-03 5.38642101274533E+00 6.47314118173772E+00 8.98095464398750E-01 2.14351768711298E+00
11 | 9.12621642768118E-01 2.27000441054412E+00 0.00000000000000E+00 8.75811574474991E+00 7.69979758411557E-03 4.58674109340718E+00 1.88640008833054E+00 8.90609997150312E-01 2.14330335677730E+00
12 | 2.23594987069582E+01 5.17655254418674E+01 0.00000000000000E+00 3.05925903028825E+01 2.75548088368540E+00 5.71330052925753E+00 3.20324916833237E+01 9.46016736348796E+00 2.85588729825036E+01
13 |
--------------------------------------------------------------------------------
/doc/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 | # http://www.sphinx-doc.org/en/master/config
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 | sys.path.insert(0, os.path.abspath("../"))
17 |
18 |
19 | # -- Project information -----------------------------------------------------
20 |
21 | project = "SuperflexPy"
22 | copyright = "2021, Marco Dal Molin, Dmitri Kavetski, Fabrizio Fenicia"
23 | author = "Marco Dal Molin, Dmitri Kavetski, Fabrizio Fenicia"
24 |
25 | # The full version, including alpha/beta/rc tags
26 | release = "1.3.0"
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 = [
35 | "sphinx.ext.autodoc",
36 | "sphinx.ext.napoleon",
37 | "sphinx.ext.viewcode",
38 | ]
39 |
40 | napoleon_numpy_docstring = True
41 | autodoc_member_order = "bysource"
42 |
43 | # Add any paths that contain templates here, relative to this directory.
44 | templates_path = ["_templates"]
45 |
46 | # List of patterns, relative to source directory, that match files and
47 | # directories to ignore when looking for source files.
48 | # This pattern also affects html_static_path and html_extra_path.
49 | exclude_patterns = []
50 | master_doc = "index"
51 |
52 | # -- Options for HTML output -------------------------------------------------
53 |
54 | # The theme to use for HTML and HTML Help pages. See the documentation for
55 | # a list of builtin themes.
56 | #
57 | html_theme = "sphinx_rtd_theme"
58 | html_theme_options = {"logo_only": True}
59 | html_logo = os.path.join(os.path.abspath(os.path.dirname(__file__)), "pics", "logo_inverted_2.PNG")
60 |
61 | # Add any paths that contain custom static files (such as style sheets) here,
62 | # relative to this directory. They are copied after the builtin static files,
63 | # so a file named "default.css" will overwrite the builtin "default.css".
64 | html_static_path = ["_static"]
65 |
--------------------------------------------------------------------------------
/doc/interfaces_code.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import spotpy
3 |
4 | from superflexpy.framework.unit import Unit
5 | from superflexpy.implementation.elements.hbv import PowerReservoir
6 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
7 | ImplicitEulerPython,
8 | )
9 | from superflexpy.implementation.root_finders.pegasus import PegasusPython
10 |
11 | root_finder = PegasusPython()
12 | num_app = ImplicitEulerPython(root_finder=root_finder)
13 |
14 | reservoir_1 = PowerReservoir(parameters={"k": 0.1, "alpha": 2.0}, states={"S0": 10.0}, approximation=num_app, id="FR1")
15 | reservoir_2 = PowerReservoir(parameters={"k": 0.5, "alpha": 1.0}, states={"S0": 10.0}, approximation=num_app, id="FR2")
16 |
17 | hyd_mod = Unit(layers=[[reservoir_1], [reservoir_2]], id="model")
18 |
19 |
20 | class spotpy_model(object):
21 | def __init__(self, model, inputs, dt, observations, parameters, parameter_names, output_index):
22 | self._model = model
23 | self._model.set_input(inputs)
24 | self._model.set_timestep(dt)
25 |
26 | self._parameters = parameters
27 | self._parameter_names = parameter_names
28 | self._observarions = observations
29 | self._output_index = output_index
30 |
31 | def parameters(self):
32 | return spotpy.parameter.generate(self._parameters)
33 |
34 | def simulation(self, parameters):
35 | named_parameters = {}
36 | for p_name, p in zip(self._parameter_names, parameters):
37 | named_parameters[p_name] = p
38 |
39 | self._model.set_parameters(named_parameters)
40 | self._model.reset_states()
41 | output = self._model.get_output()
42 |
43 | return output[self._output_index]
44 |
45 | def evaluation(self):
46 | return self._observarions
47 |
48 | def objectivefunction(self, simulation, evaluation):
49 | obj_fun = spotpy.objectivefunctions.nashsutcliffe(evaluation=evaluation, simulation=simulation)
50 |
51 | return obj_fun
52 |
53 |
54 | P = np.array([0.1, 0.0, 1.5])
55 | Q_obs = np.array([5.0, 3.2, 4.5])
56 |
57 |
58 | spotpy_hyd_mod = spotpy_model(
59 | model=hyd_mod,
60 | inputs=[P],
61 | dt=1.0,
62 | observations=Q_obs,
63 | parameters=[
64 | spotpy.parameter.Uniform("model_FR1_k", 1e-4, 1e-1),
65 | spotpy.parameter.Uniform("model_FR2_k", 1e-3, 1.0),
66 | ],
67 | parameter_names=["model_FR1_k", "model_FR2_k"],
68 | output_index=0,
69 | )
70 |
71 |
72 | sampler = spotpy.algorithms.sceua(spotpy_hyd_mod, dbname="calibration", dbformat="csv")
73 | sampler.sample(repetitions=5000)
74 |
--------------------------------------------------------------------------------
/superflexpy/implementation/models/hymod.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 |
25 | This file implements a version of the model Hymod
26 | """
27 |
28 | from superflexpy.framework.unit import Unit
29 | from superflexpy.implementation.elements.hymod import LinearReservoir, UpperZone
30 | from superflexpy.implementation.elements.structure_elements import (
31 | Junction,
32 | Splitter,
33 | Transparent,
34 | )
35 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
36 | ImplicitEulerPython,
37 | )
38 | from superflexpy.implementation.root_finders.pegasus import PegasusPython
39 |
40 | root_finder = PegasusPython() # Use the default parameters
41 | numerical_approximation = ImplicitEulerPython(root_finder)
42 |
43 | upper_zone = UpperZone(
44 | parameters={"Smax": 50.0, "m": 0.01, "beta": 2.0},
45 | states={"S0": 10.0},
46 | approximation=numerical_approximation,
47 | id="uz",
48 | )
49 |
50 | splitter = Splitter(weight=[[0.6], [0.4]], direction=[[0], [0]], id="spl")
51 |
52 | channel_routing_1 = LinearReservoir(
53 | parameters={"k": 0.1}, states={"S0": 10.0}, approximation=numerical_approximation, id="cr1"
54 | )
55 |
56 | channel_routing_2 = LinearReservoir(
57 | parameters={"k": 0.1}, states={"S0": 10.0}, approximation=numerical_approximation, id="cr2"
58 | )
59 |
60 | channel_routing_3 = LinearReservoir(
61 | parameters={"k": 0.1}, states={"S0": 10.0}, approximation=numerical_approximation, id="cr3"
62 | )
63 |
64 | lower_zone = LinearReservoir(parameters={"k": 0.1}, states={"S0": 10.0}, approximation=numerical_approximation, id="lz")
65 |
66 | transparent_1 = Transparent(id="tr1")
67 |
68 | transparent_2 = Transparent(id="tr2")
69 |
70 | junction = Junction(direction=[[0, 0]], id="jun") # First output
71 |
72 | model = Unit(
73 | layers=[
74 | [upper_zone],
75 | [splitter],
76 | [channel_routing_1, lower_zone],
77 | [channel_routing_2, transparent_1],
78 | [channel_routing_3, transparent_2],
79 | [junction],
80 | ],
81 | id="model",
82 | )
83 |
--------------------------------------------------------------------------------
/test/reference_results/06_3Cats_2HRUs/input.dat:
--------------------------------------------------------------------------------
1 | Maimai data courtesy Jeff McDonnell
2 | 1.0 ! stepsize (d)
3 | ST1: All data in mm/d
4 | ST2
5 | ST3
6 | * ! list directed format ok here
7 | Year, Month, Day, Hour, Min, P_C1, P_C2, P_C3, E_C1, E_C2, E_C3, Q_C1, QC_Q_C1, Q_C2, QC_Q_C2, Q_C3, QC_Q_C3,
8 | 1981 1 1 0 0 2.50000 2.56000 3.81000 0.59700 0.65600 0.64500 1.38891 0 1.44086 0 1.43339 0
9 | 1981 1 2 0 0 8.02000 4.86000 5.39000 0.35900 0.12500 0.08000 1.44721 0 1.34096 0 1.11329 0
10 | 1981 1 3 0 0 10.48000 8.37000 9.43000 0.66200 0.80700 0.60900 3.71258 0 5.50120 0 1.96873 0
11 | 1981 1 4 0 0 19.42000 24.47000 27.28000 0.24200 0.21200 0.13600 7.55982 0 11.28273 0 11.68680 0
12 | 1981 1 5 0 0 1.49000 4.36000 6.31000 0.26400 0.13200 0.13900 4.24939 0 4.11050 0 4.44464 0
13 | 1981 1 6 0 0 6.53000 7.75000 11.03000 0.00000 0.00000 0.00700 3.18157 0 2.83220 0 2.64144 0
14 | 1981 1 7 0 0 1.63000 5.23000 7.14000 0.00000 0.00000 0.25200 2.59718 0 2.24096 0 2.06458 0
15 | 1981 1 8 0 0 0.31000 0.79000 1.08000 0.00000 0.00000 0.00000 2.15247 0 1.87579 0 1.70221 0
16 | 1981 1 9 0 0 0.26000 0.75000 0.69000 0.00000 0.07400 0.22900 1.98105 0 1.86998 0 1.44663 0
17 | 1981 1 10 0 0 1.95000 1.37000 1.15000 0.00000 0.00000 0.18100 1.92873 0 1.67512 0 1.67596 0
18 |
--------------------------------------------------------------------------------
/doc/examples.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 04/05/2021
2 |
3 | .. _examples:
4 |
5 | Examples
6 | ========
7 |
8 | The following examples are available as Jupyter notebooks. All examples can be either
9 | visualized on GitHub or run in a sandbox environment.
10 |
11 | - Run a simple model `visualize `_ - `run `_
12 | - Calibrate a model `visualize `_ - `run `_
13 | - Initialize a single element model `visualize `_ - `run `_
14 | - Initialize a single unit model: `visualize `_ - `run `_
15 | - Initialize a simple node model: `visualize `_ - `run `_
16 | - Initialize a complete (network) model: `visualize `_ - `run `_
17 | - Create a new reservoir: `visualize `_ - `run `_
18 | - Replicate GR4J: `visualize `_ - `run `_
19 | - Replicate Hymod: `visualize `_ - `run `_
20 | - Replicate M02 in Dal Molin et al., HESS, 2020: `visualize `_ - `run `_
21 | - Replicate M4 in Kavetski and Fenicia, WRR, 2011: `visualize `_ - `run `_
22 | - Modify M4 in Kavetski and Fenicia, WRR, 2011: `visualize `_ - `run `_
23 |
--------------------------------------------------------------------------------
/superflexpy/implementation/models/gr4j.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 |
25 | This file implements a version of the model GR4J
26 | """
27 |
28 | from superflexpy.framework.unit import Unit
29 | from superflexpy.implementation.elements.gr4j import (
30 | FluxAggregator,
31 | InterceptionFilter,
32 | ProductionStore,
33 | RoutingStore,
34 | UnitHydrograph1,
35 | UnitHydrograph2,
36 | )
37 | from superflexpy.implementation.elements.structure_elements import (
38 | Junction,
39 | Splitter,
40 | Transparent,
41 | )
42 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
43 | ImplicitEulerPython,
44 | )
45 | from superflexpy.implementation.root_finders.pegasus import PegasusPython
46 |
47 | x1, x2, x3, x4 = (50.0, 0.1, 20.0, 3.5)
48 |
49 | root_finder = PegasusPython() # Use the default parameters
50 | numerical_approximation = ImplicitEulerPython(root_finder)
51 |
52 | interception_filter = InterceptionFilter(id="ir")
53 |
54 | production_store = ProductionStore(
55 | parameters={"x1": x1, "alpha": 2.0, "beta": 5.0, "ni": 4 / 9},
56 | states={"S0": 10.0},
57 | approximation=numerical_approximation,
58 | id="ps",
59 | )
60 |
61 | splitter = Splitter(weight=[[0.9], [0.1]], direction=[[0], [0]], id="spl")
62 |
63 | unit_hydrograph_1 = UnitHydrograph1(parameters={"lag-time": x4}, states={"lag": None}, id="uh1")
64 |
65 | unit_hydrograph_2 = UnitHydrograph2(parameters={"lag-time": 2 * x4}, states={"lag": None}, id="uh2")
66 |
67 | routing_store = RoutingStore(
68 | parameters={"x2": x2, "x3": x3, "gamma": 5.0, "omega": 3.5},
69 | states={"S0": 10.0},
70 | approximation=numerical_approximation,
71 | id="rs",
72 | )
73 |
74 | transparent = Transparent(id="tr")
75 |
76 | junction = Junction(
77 | direction=[[0, None], [1, None], [None, 0]], id="jun" # First output # Second output # Third output
78 | )
79 |
80 | flux_aggregator = FluxAggregator(id="fa")
81 |
82 | model = Unit(
83 | layers=[
84 | [interception_filter],
85 | [production_store],
86 | [splitter],
87 | [unit_hydrograph_1, unit_hydrograph_2],
88 | [routing_store, transparent],
89 | [junction],
90 | [flux_aggregator],
91 | ],
92 | id="model",
93 | )
94 |
--------------------------------------------------------------------------------
/doc/customize_components.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 04/05/2021
2 |
3 | .. .. warning:: This guide is still work in progress. New pages are being written
4 | .. and existing ones modified. Once the guide will reach its final
5 | .. version, this box will disappear.
6 |
7 | .. _customize_components:
8 |
9 | Expand SuperflexPy: Build customized components
10 | ===============================================
11 |
12 | .. _routing_node:
13 |
14 | Adding routing to a node
15 | ------------------------
16 |
17 | Nodes in SuperflexPy have the capability to apply a lag to the fluxes simulated
18 | by the units. Such lags can represent routing delays in the fluxes as they
19 | propagate through the catchment ("internal" routing), or routing delays associated with the river
20 | network ("external" routing). Both types of routing can be implemented within
21 | a SuperflexPy node.
22 |
23 | The default implementation of the node (:code:`Node` class in
24 | :code:`superflexpy.framework.node`) does not provide the routing functionality.
25 | The methods :code:`_internal_routing` and :code:`external_routing` exist but are
26 | set to simply return the incoming fluxes without any transformation.
27 |
28 | To support routing within a node, we need to create a customized node that implements
29 | the methods :code:`_internal_routing` and :code:`external_routing`
30 | for given lag functions. The object-oriented design of
31 | SuperflexPy simplifies this operation, because the new node class inherits all
32 | the methods from the original class, and has to overwrite only the two methods
33 | that are responsible for the routing.
34 |
35 | In this example, we illustrate an implementation of routing with a lag function
36 | in the shape of an isosceles triangle with base :code:`t_internal` and
37 | :code:`t_external`, for internal and external routing respectively. This new
38 | implementation is similar to the implementation of the :ref:`build_lag`.
39 |
40 | The first step is to import the :code:`Node` component from SuperflexPy and
41 | define the class :code:`RoutedNode`
42 |
43 | .. literalinclude:: customize_components_code.py
44 | :language: python
45 | :lines: 1, 4, 5
46 | :linenos:
47 |
48 | We then need to implement the methods :code:`_internal_routing` and
49 | :code:`external_routing`. Both methods receive as input a list of fluxes,
50 | and return as output the fluxes (in the same order of the inputs) with the
51 | delay applied.
52 |
53 | .. literalinclude:: customize_components_code.py
54 | :language: python
55 | :lines: 13-31
56 | :linenos:
57 |
58 | In this simple example, the two routing mechanisms are handled using the same
59 | lag functional form. Hence, the methods :code:`_internal_routing` and :code:`external_routing`
60 | take advantage of the method :code:`_route`
61 | (line 7 and 17).
62 |
63 | The method :code:`_route` is implemented as follows
64 |
65 | .. literalinclude:: customize_components_code.py
66 | :language: python
67 | :lines: 33-73
68 | :linenos:
69 |
70 | Note that the code in this block is similar to the code implemented in
71 | :ref:`build_lag`. The methods in this last code block are "support" methods that
72 | make the code more organized and easier to maintain. The same numerical results
73 | can be obtained by moving the functionality of these methods directly into
74 | :code:`_internal_routing` and :code:`external_routing`, though the resulting code would be less modular.
75 |
--------------------------------------------------------------------------------
/superflexpy/utils/root_finder.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 |
25 | This file contains the implementation of the base class for the root finder in
26 | case of elements governed by ODEs
27 | """
28 |
29 |
30 | class RootFinder:
31 | """
32 | This is the abstract class for the creation of a RootFinder. It defines how
33 | the solver of the differential equation must be implemented.
34 | """
35 |
36 | architecture = None
37 | """
38 | Implementation required to increase the performance (e.g. numba)
39 | """
40 |
41 | def __init__(self, tol_F=1e-8, tol_x=1e-8, iter_max=10):
42 | """
43 | The constructor of the subclass must accept the parameters of the
44 | solver.
45 |
46 | Parameters
47 | ----------
48 | tol_F : float
49 | Tolerance on the y axis (distance from 0) that stops the solver
50 | tol_x : float
51 | Tolerance on the x axis (distance between two roots) that stops
52 | the solver
53 | iter_max : int
54 | Maximum number of iteration of the solver. After this value it
55 | raises a runtime error
56 | """
57 |
58 | self._tol_F = tol_F
59 | self._tol_x = tol_x
60 | self._iter_max = iter_max
61 | self._name = "Solver"
62 |
63 | def get_settings(self):
64 | """
65 | This method returns the settings of the root finder.
66 |
67 | Returns
68 | -------
69 | float
70 | Function tollerance (tol_F)
71 | float
72 | X tollerance (tol_x)
73 | int
74 | Maximum number of iterations (iter_max)
75 | """
76 |
77 | return (
78 | self._tol_F,
79 | self._tol_x,
80 | self._iter_max,
81 | )
82 |
83 | def __repr__(self):
84 | str = "Module: superflexPy\nClass: {}\n".format(self._name)
85 | str += "Parameters:\n"
86 | str += "\ttol_F = {}\n".format(self._tol_F)
87 | str += "\ttol_x = {}\n".format(self._tol_x)
88 | str += "\titer_max = {}".format(self._iter_max)
89 |
90 | return str
91 |
92 | def solve(self, *args, **kwargs):
93 | """
94 | To be implemented by any child class. This method finds the root of the
95 | numerical approximation of the differential equation. It can operate
96 | over the whole time series.
97 | """
98 |
99 | raise NotImplementedError("The method solve must be implemented")
100 |
--------------------------------------------------------------------------------
/doc/share_models.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 04/05/2021
2 |
3 | Sharing model configurations
4 | ============================
5 |
6 | A key goal of SuperflexPy is to facilitate collaboration between research
7 | groups, and to help compare and improve modelling solutions. To this end, users
8 | can share model configurations that can be imported and run by other users. Note
9 | that models built with SuperflexPy are Python objects that, once initialized,
10 | can be imported into other scripts.
11 |
12 | A user who wishes to share their model configuration with the community can
13 | create a Python script (with a descriptive name) that initializes the model
14 | (without running it) and "upload" it to the GitHub repository in the folder
15 | :code:`superflexpy/implementation/models/`. This "upload" requires the following steps: (1)
16 | fork the `SuperflexPy `_
17 | repository, (2) add the script to the local fork of the repository, and (3)
18 | make a pull request to the original repository (see :ref:`contribute` for
19 | further details). The contributed code will be checked by the repository maintainers. Assuming all checks
20 | are passed the newly incorporated code will be incorporated in the following release of SuperflexPy
21 | and thus made available to other SuperflexPy users.
22 |
23 | The user will maintain authorship on the contributed code, which will be
24 | released with the same :ref:`license` as SuperflexPy. It is good practice to
25 | include unit tests to enable users to ensure the new code is operating as expected (see :ref:`tests`).
26 |
27 | Practical example with M4
28 | -------------------------
29 |
30 | We illustrate of how to distribute SuperflexPy models to colleagues using as an
31 | example the model :ref:`M4_example`.
32 |
33 | First, we create the file :code:`m4_sf_2011.py` that contains the code to
34 | initialize the model
35 |
36 | .. literalinclude:: share_models_code.py
37 | :language: python
38 | :lines: 1-29
39 | :linenos:
40 |
41 | Then we incorporate the file :code:`m4_sf_2011.py` into the SuperflexPy repository in the folder
42 | :code:`superflexpy/implementation/models/` following the steps illustrated
43 | in the previous section (fork, change, and pull request).
44 |
45 | Once the next release of SuperflexPy is available, the M4 model implementation
46 | will be available in the updated installed package.
47 | General users can then use this new model in their own application, by importing it as shown below.
48 |
49 | .. literalinclude:: share_models_code.py
50 | :language: python
51 | :lines: 31-37
52 | :linenos:
53 |
54 | Sharing models "privately" with other users
55 | -------------------------------------------
56 |
57 | Model configurations can be shared "privately" between research groups without
58 | waiting for a new release of the framework.
59 |
60 | This can be done by creating a :code:`my_new_model.py` file that initializes the
61 | model and then sharing the file "privately" with other users.
62 |
63 | The recipients of the new file can then save it on their machines and use
64 | local importing. Assuming that the script that the recipients use to run the
65 | model is in the same folder as the file initializing the model, the new model can be used as follows
66 |
67 | .. literalinclude:: share_models_code.py
68 | :language: python
69 | :lines: 39, 32, 32-37
70 | :linenos:
71 |
72 | Note the local import in line 1.
73 |
74 | As we believe in the `F.A.I.R. `_
75 | principles, we encourage modelers to share their models with the whole
76 | community, using the procedure detailed earlier.
77 |
78 | Dumping objects with Pickle
79 | ---------------------------
80 |
81 | Python offers the module
82 | `Pickle `_ to serialize objects
83 | to binary files. This approach enables the distribution of binary files, but
84 | has the disadvantage of lacking transparency in the model structure.
85 |
--------------------------------------------------------------------------------
/doc/reference.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 20/07/2021
2 |
3 | .. .. warning:: This guide is still work in progress. New pages are being written
4 | .. and existing ones modified. Once the guide will reach its final
5 | .. version, this box will disappear.
6 |
7 | Reference
8 | =========
9 |
10 | This reference provides details of the classes within SuperflexPy. This page is
11 | limited to the core framework (i.e. content of :code:`superflexpy/framework/`
12 | and :code:`superflexpy/utils/`), in order to provide a clear reference for the
13 | classes that should be customized to extend SuperflexPy. Particular
14 | implementations of components (i.e. the content of
15 | :code:`superflexpy/implementation/`) are not included.
16 |
17 | The following diagram follows the standards of
18 | `UML `_ and shows the organization
19 | of the classes composing the framework. All the classes in the diagram can be
20 | extended through inheritance to create customized components.
21 |
22 | .. image:: pics/reference/class_uml.png
23 | :align: center
24 |
25 | superflexpy.framework.element
26 | -----------------------------
27 |
28 | .. autoclass:: superflexpy.framework.element.BaseElement
29 | :members:
30 | :undoc-members:
31 | :private-members:
32 | :show-inheritance:
33 | :special-members: __init__
34 |
35 | .. autoclass:: superflexpy.framework.element.ParameterizedElement
36 | :members:
37 | :undoc-members:
38 | :private-members:
39 | :special-members: __init__
40 | :show-inheritance:
41 |
42 | .. autoclass:: superflexpy.framework.element.StateElement
43 | :members:
44 | :undoc-members:
45 | :private-members:
46 | :special-members: __init__
47 | :show-inheritance:
48 |
49 | .. autoclass:: superflexpy.framework.element.StateParameterizedElement
50 | :members:
51 | :undoc-members:
52 | :private-members:
53 | :special-members: __init__
54 | :show-inheritance:
55 |
56 | .. autoclass:: superflexpy.framework.element.ODEsElement
57 | :members:
58 | :undoc-members:
59 | :private-members:
60 | :special-members: __init__
61 | :show-inheritance:
62 |
63 | .. autoclass:: superflexpy.framework.element.LagElement
64 | :members:
65 | :undoc-members:
66 | :private-members:
67 | :special-members: __init__
68 | :show-inheritance:
69 |
70 | superflexpy.utils.generic_component
71 | -----------------------------------
72 |
73 | .. autoclass:: superflexpy.utils.generic_component.GenericComponent
74 | :members:
75 | :undoc-members:
76 | :private-members:
77 | :special-members: __init__
78 | :show-inheritance:
79 |
80 | superflexpy.framework.unit
81 | --------------------------
82 |
83 | .. autoclass:: superflexpy.framework.unit.Unit
84 | :members:
85 | :undoc-members:
86 | :private-members:
87 | :special-members: __init__
88 | :show-inheritance:
89 |
90 | superflexpy.framework.node
91 | --------------------------
92 |
93 | .. autoclass:: superflexpy.framework.node.Node
94 | :members:
95 | :undoc-members:
96 | :private-members:
97 | :special-members: __init__
98 | :show-inheritance:
99 |
100 | superflexpy.framework.network
101 | -----------------------------
102 |
103 | .. autoclass:: superflexpy.framework.network.Network
104 | :members:
105 | :undoc-members:
106 | :private-members:
107 | :special-members: __init__
108 | :show-inheritance:
109 |
110 | superflexpy.utils.root_finder
111 | -----------------------------
112 |
113 | .. autoclass:: superflexpy.utils.root_finder.RootFinder
114 | :members:
115 | :undoc-members:
116 | :private-members:
117 | :special-members: __init__
118 | :show-inheritance:
119 |
120 | superflexpy.utils.numerical_approximator
121 | ----------------------------------------
122 |
123 | .. autoclass:: superflexpy.utils.numerical_approximator.NumericalApproximator
124 | :members:
125 | :special-members: __init__
126 | :show-inheritance:
127 |
--------------------------------------------------------------------------------
/doc/changelog.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 29/11/2021
2 |
3 | Change log
4 | ==========
5 |
6 | Version 1.3.1
7 | -------------
8 |
9 | Minor changes
10 | .............
11 |
12 | - Added the classifier :code:`Topic :: Scientific/Engineering :: Hydrology`
13 |
14 | Version 1.3.0
15 | -------------
16 |
17 | Major changes to existing components
18 | ....................................
19 |
20 | - :code:`ODEsElements` can now return the derivative of the fluxes together with
21 | the fluxes. This enables the usage of numerical solvers that use the
22 | derivatives (e.g., Newton methods).
23 | - Folder structure improved. The numerical approximators and the root finders
24 | have been moved from the folder :code:`implementation/computation` to
25 | :code:`implementation/numerical_approximators` and
26 | :code:`implementation/root_finders`, respectively. Names of the files have
27 | been slightly modified to be coherent with this new folder organization.
28 |
29 | New code
30 | ........
31 |
32 | - Implemented a new numerical approximator implementing Runge Kutta 4
33 | - Implemented a new root finder implementing a Newton-bisection method
34 | - Implemented a new root finder implementing a trivial algorithm to solve
35 | explicit algebraic equations.
36 |
37 | Version 1.2.1
38 | -------------
39 |
40 | Minor changes
41 | .............
42 |
43 | - The network attribute :code:`topography` has been changed to :code:`topology`.
44 |
45 | Version 1.2.0
46 | -------------
47 |
48 | Major changes to existing components
49 | ....................................
50 |
51 | - The abbreviation of "differential equation" changes, in the code, from
52 | :code:`dif_eq` to :code:`diff_eq`. This change regards variables names, both
53 | in the methods arguments and implementation.
54 |
55 | - The class :code:`FastReservoir` has been changed to :code:`PowerReservoir`. No
56 | changes in the functionality of the class.
57 |
58 | Minor changes
59 | .............
60 |
61 | - Testing improved.
62 |
63 | Version 1.1.0
64 | -------------
65 |
66 | Major changes to existing components
67 | ....................................
68 |
69 | - Form this version, SuperflexPy is released under license LGPL. For details,
70 | read :ref:`license`
71 |
72 | Minor changes to existing components
73 | ....................................
74 |
75 | - Bug fix on the solution of the differential equations of the reservoirs. The
76 | calculation of the maximum storage was not correct.
77 |
78 | Version 1.0.0
79 | -------------
80 |
81 | Version 1.0.0 represents the first mature release of SuperflexPy. Many aspects
82 | have changed since earlier 0.x releases both in terms of code organization
83 | and conceptualization of the framework. **Models built with versions 0.x are**
84 | **not compatible with this version and with the following releases**.
85 |
86 | Major changes to existing components
87 | ....................................
88 |
89 | - New numerical solver structure for elements controlled by ordinary
90 | differential equations (ODEs). A new component, the
91 | :code:`NumericaApproximator` is introduced; its task it to get the fluxes from
92 | the elements and construct an approximation of the ODEs. In the previous
93 | release of the framework the approximation was hard coded in the element
94 | implementation.
95 |
96 | - :code:`ODEsElement` have now to implement the methods :code:`_fluxes` and
97 | :code:`_fluxes_python` instead of :code:`_differential_equation`
98 |
99 | - Added the possibility for nodes and units to have local states and parameters.
100 | To this end, some internal functionalities for finding the element given the
101 | :code:`id` have been changed to account for the presence of states and
102 | parameters at a level higher then the elements.
103 |
104 | Minor changes to existing components
105 | ....................................
106 |
107 | - Added implicit or explicit check at initialization of units, nodes, and
108 | network that the components that they contain are of the right type (e.g. a
109 | node must contain units)
110 |
111 | - Minor changes to :code:`RootFinder` to accommodate the new numerical
112 | implementation.
113 |
114 | - Added Numba implementation of GR4J elements
115 |
116 | New code
117 | ........
118 |
119 | - Added :code:`hymod` elements
120 |
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | .. .. warning:: This guide is still work in progress. New pages are being written
2 | .. and existing ones modified. Once the guide will reach its final
3 | .. version, this box will disappear.
4 |
5 | .. image:: pics/logo_transparent_2.png
6 | :align: center
7 |
8 | ===========
9 | SuperflexPy
10 | ===========
11 |
12 | SuperflexPy is an open-source Python framework for constructing conceptual
13 | hydrological models for lumped and semi-distributed applications.
14 |
15 | SuperflexPy builds on our 10 year experience with the development and
16 | application of `Superflex `_, including
17 | collaborations with colleagues at the Eawag (Switzerland), TU-Delft
18 | (Netherlands), LIST (Luxembourg), University of Adelaide (Australia), and
19 | others. The SuperflexPy framework offers a brand new implementation of
20 | Superflex, allowing the modeler to build fully customized, spatially-distributed
21 | hydrological models.
22 |
23 | Thanks to its object-oriented architecture, SuperflexPy can be easily
24 | extended to meet your modelling requirements, including the creation of new
25 | components with customized internal structure, in just a few lines of Python
26 | code.
27 |
28 | Constructing a hydrological model is straightforward with SuperflexPy:
29 |
30 | - inputs and outputs are handled directly by the modeler using common Python
31 | libraries (e.g. Numpy or Pandas). The modeller can use hence data files of
32 | their own design, without the need to pre- and/or post- process
33 | data into text formats prescribed by the framework itself;
34 |
35 | - the framework components are declared and initialized through a Python script;
36 |
37 | - the framework components are implemented as classes with built-in functionalities for
38 | handling parameters and states, routing fluxes, and solving the model
39 | equations (e.g. describing reservoirs, lag functions, etc.);
40 |
41 | - the numerical implementation is separated from the conceptual model, allowing
42 | the use of different numerical methods for solving the model equations;
43 |
44 | - the framework can be run at multiple levels of complexity, from a
45 | single-bucket model to a model that represents an entire river network;
46 |
47 | - the framework is available as an open source Python package from
48 | `Github `_;
49 |
50 | - the framework can be easily interfaced with other Python modules for
51 | calibration and uncertainty analysis.
52 |
53 | Team
54 | ----
55 |
56 | SuperflexPy is developed and maintained by researchers in the
57 | `Hydrological Modelling Group
58 | `_
59 | at `Eawag `_, with the support of external collaborators.
60 |
61 | The core team consists of:
62 |
63 | - `Dr. Marco Dal Molin `_ (implementation and design)
64 |
65 | - `Dr. Fabrizio Fenicia `_
66 | (design and supervision)
67 |
68 | - `Prof. Dmitri Kavetski `_
69 | (design and supervision)
70 |
71 | Stay in touch
72 | -------------
73 |
74 | If you wish to receive emails about ongoing SuperflexPy developments\,
75 | please `subscribe `_ to our mailing list.
76 |
77 | .. note:: Using SuperflexPy requires a general knowledge of Python and Numpy.
78 | Other Python libraries may be needed for pre- and post- processing of
79 | the data.
80 |
81 | In line with the Python terminology, we will use the word **define**
82 | when referring to the definition of a class, and **initialize** when
83 | referring to the creation of an instance of a class, i.e. an object.
84 |
85 | .. toctree::
86 | :maxdepth: 1
87 | :hidden:
88 |
89 | installation
90 | contribute
91 | introduction
92 | components
93 | numerical_solver
94 | demo
95 | elements_list
96 | build_element
97 | customize_components
98 | popular_models
99 | case_studies
100 | sfpy_in_literature
101 | share_models
102 | interfaces
103 | examples
104 | testing
105 | license
106 | reference
107 | changelog
108 |
--------------------------------------------------------------------------------
/superflexpy/implementation/root_finders/explicit.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 |
25 | This file contains the implementation of a trivial solver to use when the
26 | algebraic equation to solve is explicit and, therefore does not require
27 | iteration (e.g., with Explicit Euler or Runge Kutta).
28 | """
29 |
30 |
31 | import numba as nb
32 |
33 | from ...utils.root_finder import RootFinder
34 |
35 |
36 | class ExplicitPython(RootFinder):
37 | """
38 | This class defined a root finder to be used when the algebraic equation is
39 | explicit.
40 | """
41 |
42 | def __init__(self):
43 | """
44 | This is the initializer of the ExplicitRootFinderPython class. As the
45 | root finder it not iterative, no parameters defining the convergence are
46 | needed.
47 | """
48 |
49 | super().__init__(tol_F=None, tol_x=None, iter_max=None)
50 |
51 | self._name = "ExplicitRootFinderPython"
52 | self.architecture = "python"
53 | self._error_message = "module : superflexPy, solver : {},".format(self._name)
54 | self._error_message += " Error message : "
55 |
56 | def solve(self, diff_eq, fluxes, S0, dt, ind, args):
57 | """
58 | This method calculated the root of the input function.
59 |
60 | Parameters
61 | ----------
62 | diff_eq : function
63 | Function be solved. The function must accept the following inputs:
64 | - fluxes : function used to calculate the fluxes given parameters
65 | and state
66 | - S : proposed root. If None, the function must initialize the root
67 | - S0 : state at the beginning of the time step
68 | - dt : time step
69 | - kwargs : other parameters needed by diff_eq
70 | It must return three float values:
71 | - Value of the function given the root and the kwargs
72 | - Lower x boundary for the search
73 | - Upper x boundary for the search
74 | fluxes : function
75 | Function to be passed to diff_eq. See specificatio in
76 | superflexpy.utils.numerical_approximator
77 | S0 : float
78 | state at the beginning of the time step
79 | dt : float
80 | time step
81 | kwargs : dict(str: float)
82 | parameters needed by diff_eq
83 |
84 | Returns
85 | -------
86 | float
87 | Root of the function
88 | """
89 |
90 | return -diff_eq(fluxes=fluxes, S=0, S0=S0, dt=dt, args=args, ind=ind)[0]
91 |
92 |
93 | class ExplicitNumba(RootFinder):
94 | """
95 | This class defined a root finder to be used when the algebraic equation is
96 | explicit.
97 | """
98 |
99 | def __init__(self):
100 | """
101 | This is the initializer of the ExplicitRootFinderNumba class. As the
102 | root finder it not iterative, no parameters defining the convergence are
103 | needed.
104 | """
105 |
106 | super().__init__(tol_F=None, tol_x=None, iter_max=None)
107 |
108 | self._name = "ExplicitRootFinderPython"
109 | self.architecture = "python"
110 | self._error_message = "module : superflexPy, solver : {},".format(self._name)
111 | self._error_message += " Error message : "
112 |
113 | @staticmethod
114 | @nb.jit(nopython=True)
115 | def solve(diff_eq, fluxes, S0, dt, ind, args, tol_F, tol_x, iter_max):
116 | return -diff_eq(fluxes=fluxes, S=0, S0=S0, dt=dt, args=args, ind=ind)[0]
117 |
--------------------------------------------------------------------------------
/doc/contribute.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 22/07/2021
2 |
3 | .. .. warning:: This guide is still work in progress. New pages are being written
4 | .. and existing ones modified. Once the guide will reach its final
5 | .. version, this box will disappear.
6 |
7 | .. _contribute:
8 |
9 | Software organization and contribution
10 | ======================================
11 |
12 | .. image:: pics/contribute/schematic_with_logo.png
13 | :align: center
14 |
15 | The SuperflexPy framework comprises the following components:
16 |
17 | - **Source code**: Latest version of all the code necessary to use the
18 | framework. The source code would normally be accessed only by advanced
19 | users, e.g. to understand the internal organization of the framework, to install
20 | manually the latest version, to extend the framework with new
21 | functionality, etc.
22 | - **Packaged release**: Latest stable version of the framework available for
23 | users.
24 | - **Documentation**: Detailed explanation of the framework.
25 | - **Examples**: Introduction to SuperflexPy for a new user, providing working
26 | models and demonstrating potential applications.
27 | - **Scientific references**: Publications that present and/or use
28 | the framework in scientific contexts.
29 |
30 | The source code, documentation, and examples are part of the official repository
31 | of SuperflexPy hosted on `GitHub `_.
32 | A user who wishes to read the source code and/or modify any aspect of
33 | SuperflexPy (source code, documentation, and examples) can do it using GitHub.
34 |
35 | New releases of the software are available from the official Python Package
36 | Index (PyPI), where SuperflexPy has a
37 | `dedicated page `_.
38 |
39 | The documentation builds automatically from the
40 | `source folder `_ on
41 | GitHub and is published online in
42 | `Read the Docs `_.
43 |
44 | Examples are available on GitHub as Jupyter notebooks. These examples can be
45 | visualized statically or run in a sandbox environment (Binder). Refer to :ref:`examples` for
46 | a list of the available examples.
47 |
48 | The scientific publication introducing SuperflexPy has been published in
49 | *Geoscientific Model Development* (`link `_).
50 |
51 | Contributions
52 | -------------
53 |
54 | Contributions to the framework can be made in the following ways:
55 |
56 | - Submit issues on bugs, desired features, etc;
57 | - Solve open issues;
58 | - Extend the documentation with new demos and examples;
59 | - Extend and/or modify the framework;
60 | - Use and cite the framework in your publications.
61 |
62 | Code contribution by external users will be mainly additive (i.e., adding new
63 | components, as illustrated in :ref:`build_element` and :ref:`customize_components`)
64 | and should include also appropriate testing (:ref:`tests`).
65 |
66 | Contributors will maintain authorship of the contributed code and are invited
67 | to include, in all files, their contact information to facilitate future
68 | collaboration. The authors and maintainers of SuperflexPy will undertake a basic
69 | inspection of the contributed code to identify any quality issues.
70 |
71 | The typical workflow that should be followed when contributing to a GitHub
72 | project is described
73 | `here `_.
74 |
75 | In summary,
76 | the following steps should be followed:
77 |
78 | 1. Fork the SuperflexPy repository to the user GitHub account;
79 | 2. Clone the fork on the user computer;
80 | 3. Modify the code, commit the changes, and push them to the GitHub fork of
81 | SuperflexPy;
82 | 4. Make a pull request on GitHub to the SuperflexPy repository.
83 |
84 | Branching scheme of the GitHub repository
85 | .........................................
86 |
87 | Updates to SuperflexPy are made directly in the branch :code:`master`, which
88 | is the most up-to-date branch. The branch :code:`release` is used only
89 | for the staging of new software releases and, therefore, code should not be
90 | pushed directly to it.
91 |
92 | When a code update is merged from :code:`master` to :code:`release`, a
93 | new version of the package is automatically released on PyPI. Remember to update
94 | the version number in the :code:`setup.py` file to avoid conflicts.
95 |
96 | Developers are free to create new branches, but pull requests must be directed to
97 | :code:`master` and not to :code:`release`.
98 |
99 | Documentation and examples are generated from the :code:`master`
100 | branch.
101 |
--------------------------------------------------------------------------------
/doc/interfaces.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 04/05/2021
2 |
3 | Interfacing SuperflexPy with other frameworks
4 | =============================================
5 |
6 | SuperflexPy does not integrate tools for calibration or uncertainty analysis. In
7 | this page we show an example on how a model built using SuperflexPy can be
8 | interfaced with other tools to perform this task.
9 |
10 | SuperflexPy + SPOTPY
11 | --------------------
12 |
13 | .. note:: This example is for illustration purposes only, and as such does not
14 | represent a specific recommendation of SPOTPY or of any specific
15 | calibration algorithm.
16 |
17 | `SPOTPY `_ is a Python framework for
18 | calibration, uncertainty, and sensitivity analysis.
19 |
20 | A model can be interfaced with SPOTPY by defining a class that wraps the model
21 | and implements the following methods:
22 |
23 | - :code:`__init__`: initializes the class, defining some attributes;
24 | - :code:`parameters`: returns the parameters considered in the analysis (note
25 | that they may not be all the parameters used by the SuperflexPy model but
26 | only the ones that we want to vary in the analysis);
27 | - :code:`simulation`: returns the output of the simulation;
28 | - :code:`evaluation`: returns the observed output;
29 | - :code:`objectivefunction`: defines the objective function to use to evaluate
30 | the simulation results.
31 |
32 | Method :code:`__init__`
33 | .......................
34 |
35 | .. literalinclude:: interfaces_code.py
36 | :language: python
37 | :lines: 5, 7, 29-40
38 | :linenos:
39 |
40 | The class :code:`spotpy_model` is initialized defining the SuperflexPy :code:`model` that is used.
41 | The :code:`model`, which can be any SuperflexPy component (from element to
42 | network), must be defined before; the :code:`spotpy_model` class sets only the :code:`inputs`
43 | and the :code:`dt`.
44 |
45 | Other variables necessary to initialize the class :code:`spotpy_model` are:
46 |
47 | - :code:`parameters` and :code:`parameters_names`, which define the parameters
48 | considered in the calibration. The first variable is a list of :code:`spotpy.parameter`
49 | objects, the second variable is a list of the names of the SuperflexPy parameters;
50 | - :code:`observations`, which is an array of observed output values;
51 | - :code:`output_index`, which is the index of the output flux to be considered
52 | when evaluating the SuperflexPy simulation. This specification is necessary in
53 | the case of multiple output fluxes.
54 |
55 | Method :code:`parameters`
56 | .........................
57 |
58 | .. literalinclude:: interfaces_code.py
59 | :language: python
60 | :lines: 44-45
61 | :linenos:
62 |
63 | The method :code:`parameters` generates a new parameter set using the SPOTPY functionalities.
64 |
65 | Method :code:`simulation`
66 | .........................
67 |
68 | .. literalinclude:: interfaces_code.py
69 | :language: python
70 | :lines: 49-59
71 | :linenos:
72 |
73 | The method :code:`simulation` sets the parameters (lines 3-7), resets the states to their initial
74 | value (line 8), runs the SuperflexPy model (line 9), and returns the output
75 | flux for the evaluation of the objective function (line 11).
76 |
77 | Method :code:`evaluation`
78 | .........................
79 |
80 | .. literalinclude:: interfaces_code.py
81 | :language: python
82 | :lines: 63-64
83 | :linenos:
84 |
85 | The method :code:`evaluation` returns the observed flux, used for the evaluation of the objective function.
86 |
87 | Method :code:`objectivefunction`
88 | ................................
89 |
90 | .. literalinclude:: interfaces_code.py
91 | :language: python
92 | :lines: 68-73
93 | :linenos:
94 |
95 | The method :code:`objectivefunction` defines the objective function used to measure the model fit to the observed data. In this
96 | case, the Nash-Sutcliffe efficiency is used.
97 |
98 | Example of use
99 | ..............
100 |
101 | We now show how to employ the implementation above to calibrate a lumped model
102 | composed of 2 reservoirs.
103 |
104 | First, we initialize the SuperflexPy model, as follows
105 | (see :ref:`demo` for more details on how to set-up a model).
106 |
107 | .. literalinclude:: interfaces_code.py
108 | :language: python
109 | :lines: 1-4, 9-24
110 | :linenos:
111 |
112 | Then, we initialize an instance of the :code:`spotpy_model` class
113 |
114 | .. literalinclude:: interfaces_code.py
115 | :language: python
116 | :lines: 81-92
117 | :linenos:
118 |
119 | The arrays :code:`P` and :code:`Q_obs` in lines 3 and 5 contain time series of precipitation (input)
120 | and observed streamflow (output). In this example, lines 6-10 indicate the two parameters that we calibrate
121 | (:code:`model_FR1_k` and :code:`model_FR2_k`) together with their range of
122 | variability.
123 |
124 | We can now call the SPOTPY method to calibrate the model. Here, the SCE algorithm option is used.
125 |
126 | .. literalinclude:: interfaces_code.py
127 | :language: python
128 | :lines: 96-97
129 | :linenos:
130 |
--------------------------------------------------------------------------------
/test/unittest/01_FR.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | import sys
27 | import unittest
28 | from os.path import abspath, dirname, join
29 |
30 | import numpy as np
31 | import pandas as pd
32 |
33 | # Package path is 2 levels above this file
34 | package_path = join(abspath(dirname(__file__)), "..", "..")
35 | sys.path.insert(0, package_path)
36 |
37 | from superflexpy.implementation.elements.hbv import PowerReservoir
38 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
39 | ImplicitEulerNumba,
40 | ImplicitEulerPython,
41 | )
42 | from superflexpy.implementation.root_finders.pegasus import PegasusNumba, PegasusPython
43 |
44 |
45 | class TestFR(unittest.TestCase):
46 | """
47 | This class tests the functionality of the reservoir FR alone.
48 | We compare the results with superflex in two scenarios:
49 | - start and stop to check that it saves the intermediate states
50 | - 2 rounds to check that it re-sets the states to the initial value
51 | """
52 |
53 | def _init_model(self, solver):
54 | if solver == "numba":
55 | solver = PegasusNumba()
56 | num_app = ImplicitEulerNumba(root_finder=solver)
57 | elif solver == "python":
58 | solver = PegasusPython()
59 | num_app = ImplicitEulerPython(root_finder=solver)
60 |
61 | fr = PowerReservoir(parameters={"k": 0.01, "alpha": 2.5}, states={"S0": 0.0}, approximation=num_app, id="FR")
62 |
63 | fr.set_timestep(1.0)
64 | self._model = fr
65 |
66 | def _read_inputs(self):
67 | data = pd.read_csv(
68 | "{}/test/reference_results/01_FR/input.dat".format(package_path),
69 | header=6,
70 | sep="\s+|,\s+|,",
71 | engine="python",
72 | )
73 | self._precipitation = data.iloc[:, 6].values
74 | self._pet = data.iloc[:, 7].values
75 |
76 | def _read_outputs(self):
77 | self._superflex_output = pd.read_csv("{}/test/reference_results/01_FR/Results.csv".format(package_path))
78 |
79 | def _test_fr_start_stop(self, solver):
80 | self._init_model(solver=solver)
81 | self._read_outputs()
82 | self._read_inputs()
83 |
84 | # First half of time series
85 | self._model.set_input([self._precipitation[:5]])
86 | out = self._model.get_output()
87 |
88 | msg = "Fail in the first half"
89 |
90 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[:5, 0]), msg=msg)
91 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[:5, 1]), msg=msg)
92 |
93 | # Second half of time series
94 | self._model.set_input([self._precipitation[5:]])
95 | out = self._model.get_output()
96 |
97 | msg = "Fail in the second half"
98 |
99 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[5:, 0]), msg=msg)
100 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[5:, 1]), msg=msg)
101 |
102 | def test_fr_start_stop_python(self):
103 | self._test_fr_start_stop(solver="python")
104 |
105 | def test_fr_start_stop_numba(self):
106 | self._test_fr_start_stop(solver="numba")
107 |
108 | def _test_2_rounds(self, solver):
109 | self._init_model(solver=solver)
110 | self._read_outputs()
111 | self._read_inputs()
112 |
113 | # First half of time series
114 | self._model.set_input([self._precipitation])
115 | out = self._model.get_output()
116 |
117 | msg = "Fail in the first round"
118 |
119 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[:, 0]), msg=msg)
120 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[:, 1]), msg=msg)
121 |
122 | # Second half of time series
123 | self._model.reset_states()
124 | out = self._model.get_output()
125 |
126 | msg = "Fail in the second round"
127 |
128 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[:, 0]), msg=msg)
129 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[:, 1]), msg=msg)
130 |
131 | def test_2_rounds_python(self):
132 | self._test_2_rounds(solver="python")
133 |
134 | def test_2_rounds_numba(self):
135 | self._test_2_rounds(solver="numba")
136 |
137 |
138 | # if __name__ == "__main__":
139 | unittest.main()
140 | # test = TestFR()
141 | # test.test_2_rounds_python()
142 |
--------------------------------------------------------------------------------
/test/unittest/07_FR_2dt.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright 2020 Marco Dal Molin et al.
3 |
4 | This file is part of SuperflexPy.
5 |
6 | SuperflexPy is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | SuperflexPy is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Lesser General Public License for more details.
15 |
16 | You should have received a copy of the GNU Lesser General Public License
17 | along with SuperflexPy. If not, see .
18 |
19 | This file is part of the SuperflexPy modelling framework. For details about it,
20 | visit the page https://superflexpy.readthedocs.io
21 |
22 | CODED BY: Marco Dal Molin
23 | DESIGNED BY: Marco Dal Molin, Fabrizio Fenicia, Dmitri Kavetski
24 | """
25 |
26 | import sys
27 | import unittest
28 | from os.path import abspath, dirname, join
29 |
30 | import numpy as np
31 | import pandas as pd
32 |
33 | # Package path is 2 levels above this file
34 | package_path = join(abspath(dirname(__file__)), "..", "..")
35 | sys.path.insert(0, package_path)
36 |
37 | from superflexpy.implementation.elements.hbv import PowerReservoir
38 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
39 | ImplicitEulerNumba,
40 | ImplicitEulerPython,
41 | )
42 | from superflexpy.implementation.root_finders.pegasus import PegasusNumba, PegasusPython
43 |
44 |
45 | class TestFR(unittest.TestCase):
46 | """
47 | This class tests the functionality of the reservoir FR alone.
48 | We compare the results with superflex in two scenarios:
49 | - start and stop to check that it saves the intermediate states
50 | - 2 rounds to check that it re-sets the states to the initial value
51 | """
52 |
53 | def _init_model(self, solver):
54 | if solver == "numba":
55 | solver = PegasusNumba()
56 | num_app = ImplicitEulerNumba(root_finder=solver)
57 | elif solver == "python":
58 | solver = PegasusPython()
59 | num_app = ImplicitEulerPython(root_finder=solver)
60 |
61 | fr = PowerReservoir(parameters={"k": 0.01, "alpha": 2.5}, states={"S0": 0.0}, approximation=num_app, id="FR")
62 |
63 | fr.set_timestep(2.0)
64 | self._model = fr
65 |
66 | def _read_inputs(self):
67 | data = pd.read_csv(
68 | "{}/test/reference_results/07_FR_2dt/input.dat".format(package_path),
69 | header=6,
70 | sep="\s+|,\s+|,",
71 | engine="python",
72 | )
73 | self._precipitation = data.iloc[:, 6].values
74 | self._pet = data.iloc[:, 7].values
75 |
76 | def _read_outputs(self):
77 | self._superflex_output = pd.read_csv("{}/test/reference_results/07_FR_2dt/Results.csv".format(package_path))
78 |
79 | def _test_fr_start_stop(self, solver):
80 | self._init_model(solver=solver)
81 | self._read_outputs()
82 | self._read_inputs()
83 |
84 | # First half of time series
85 | self._model.set_input([self._precipitation[:5]])
86 | out = self._model.get_output()
87 |
88 | msg = "Fail in the first half"
89 |
90 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[:5, 0]), msg=msg)
91 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[:5, 1]), msg=msg)
92 |
93 | # Second half of time series
94 | self._model.set_input([self._precipitation[5:]])
95 | out = self._model.get_output()
96 |
97 | msg = "Fail in the second half"
98 |
99 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[5:, 0]), msg=msg)
100 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[5:, 1]), msg=msg)
101 |
102 | def test_fr_start_stop_python(self):
103 | self._test_fr_start_stop(solver="python")
104 |
105 | def test_fr_start_stop_numba(self):
106 | self._test_fr_start_stop(solver="numba")
107 |
108 | def _test_2_rounds(self, solver):
109 | self._init_model(solver=solver)
110 | self._read_outputs()
111 | self._read_inputs()
112 |
113 | # First half of time series
114 | self._model.set_input([self._precipitation])
115 | out = self._model.get_output()
116 |
117 | msg = "Fail in the first round"
118 |
119 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[:, 0]), msg=msg)
120 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[:, 1]), msg=msg)
121 |
122 | # Second half of time series
123 | self._model.reset_states()
124 | out = self._model.get_output()
125 |
126 | msg = "Fail in the second round"
127 |
128 | self.assertTrue(np.allclose(out, self._superflex_output.iloc[:, 0]), msg=msg)
129 | self.assertTrue(np.allclose(self._model.state_array[:, 0], self._superflex_output.iloc[:, 1]), msg=msg)
130 |
131 | def test_2_rounds_python(self):
132 | self._test_2_rounds(solver="python")
133 |
134 | def test_2_rounds_numba(self):
135 | self._test_2_rounds(solver="numba")
136 |
137 |
138 | # if __name__ == "__main__":
139 | unittest.main()
140 | # test = TestFR()
141 | # test.test_2_rounds_python()
142 |
--------------------------------------------------------------------------------
/test/reference_results/01_FR/M01_main.dat:
--------------------------------------------------------------------------------
1 | FLEX_MAIN_CONFIGURATION_FILE_V1.05
2 | ! Description: FLEX-SPAM model configuration file
3 | !========
4 | 01 ! index describing model configuration (for ease of reference/documentation)
5 | "M01" ! nametag describing model configuration (eg, "stdFLEX/powerAS", etc)
6 | !========
7 | FLEX NUMERICS
8 | 1 ! numerical solver for interception reservoir (0=odeint, 1=fixed-spm-implicit, 2=bounded EE, -1=simple-threshold, -2=algebraic-statique)
9 | 3 ! numerical solver for simple reservoirs (0=odeint, 3=fixed-liebre-implicit, 2=bounded EE)
10 | 1 ! numerical solver for UR zone (0=odeint, 1=fixed-spm-implicit, 2=bounded EE)
11 | !========
12 | FLEX DISTRIBUTION
13 | 1 ! number of HRUs
14 | 1 ! number of catchments
15 | 0 ! number of tracers
16 | 1 ! number of layers (dead storages)
17 | !========
18 | HRU CHARACTERISTICS FILE NAME
19 | "*/flexConfig_Areas.dat"
20 | !========
21 | UNITS FILE NAME
22 | "*/flexConfig_ML01.dat"
23 | !========
24 | UNITS PRESENCE MATRIX
25 | FC_01(Lumped) ! ID
26 | .true. !
27 | !========
28 | INPUTS DESCRIPTION
29 | 2 ! precipitation input (1=lumped,2=perSubcatchment(ID),3=perFied)
30 | 0 ! tracer input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
31 | 2 ! etp input (1=lumped,2=perSubcatchment(ID),3=perFied)
32 | 0 ! temperature input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
33 | !========
34 | DRAINAGE DISTANCES
35 | riverScaleInc riverScaleOut riverSlopeInc riverSlopeOut
36 | 1.0 1.0 1.0 1.0
37 | !========
38 | DEPENDENCIES
39 | DrainsInto
40 | 0
41 | !========
42 | RIVER ROUTING CONVOLUTION INFORMATION
43 | "none",.false.,-1,1 ! convolution function "symTri","genTri","kiedKeid","none", for symTri only tS and tR are needed; couple scales (if true relative scaleInc and scaleOut is preserved) smoothing options; maximum number of convolution states
44 | !========
45 | ACTIVE_PARAMETER_INFO ! (parameters visible to BATEA)
46 | parName parDef parLo parHi parScal parSD parTran parFit linkTo Comment
47 | "Cmlt_P, - " 1.0 0.9 1.1 10.0 -9999.9 0 F 0 (cannot be dead) Rainfall multiplication factor
48 | "Cmlt_E, - " 1.0 0.2 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor for evaporation
49 | "CmltSmax_IR, - " 1.0 1.e-1 3.0 10.0 -9999.9 1 F 0 (cannot be dead) Intercaption multiplication factor
50 | "CmltSmax_UR, - " 1.0 1.e-1 500.0 10.0 -9999.9 1 F 0 (cannot be dead) SuMax multiplication factor
51 | "CmltBetaQq_UR, -" 1.0 1.e-2 10.0 10.0 -9999.9 1 F 0 (cannot be dead) BetaQq multiplication factor
52 | "Cmlt_P_WR, - " 1.0 1.e-1 3.0 10.0 -9999.9 0 F 0 (cannot be dead) Multiplication factor to wCorr in snow reservoir
53 | "CmltK_Qm_WR, - " 1.0 1.e-1 10.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qm in snow reservoir
54 | "CmltK_Qq_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qq in slow reservoir
55 | "CmltK_Qb_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qb in slow reservoir
56 | !========
57 | MORTO_PARAMETER_INFO ! (parameters that dont exist for this configuration)
58 | "tFall_IL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
59 | "K_IL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
60 | "tFall_OL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
61 | "K_OL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
62 | "tStart_IL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
63 | "tRise_IL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
64 | "betaM_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
65 | "betaS_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
66 | "tStart_OL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
67 | "tRise_OL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
68 | "betaM_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
69 | "betaS_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
70 | !========
71 |
--------------------------------------------------------------------------------
/test/reference_results/02_UR/M01_main.dat:
--------------------------------------------------------------------------------
1 | FLEX_MAIN_CONFIGURATION_FILE_V1.05
2 | ! Description: FLEX-SPAM model configuration file
3 | !========
4 | 01 ! index describing model configuration (for ease of reference/documentation)
5 | "M01" ! nametag describing model configuration (eg, "stdFLEX/powerAS", etc)
6 | !========
7 | FLEX NUMERICS
8 | 1 ! numerical solver for interception reservoir (0=odeint, 1=fixed-spm-implicit, 2=bounded EE, -1=simple-threshold, -2=algebraic-statique)
9 | 3 ! numerical solver for simple reservoirs (0=odeint, 3=fixed-liebre-implicit, 2=bounded EE)
10 | 1 ! numerical solver for UR zone (0=odeint, 1=fixed-spm-implicit, 2=bounded EE)
11 | !========
12 | FLEX DISTRIBUTION
13 | 1 ! number of HRUs
14 | 1 ! number of catchments
15 | 0 ! number of tracers
16 | 1 ! number of layers (dead storages)
17 | !========
18 | HRU CHARACTERISTICS FILE NAME
19 | "*/flexConfig_Areas.dat"
20 | !========
21 | UNITS FILE NAME
22 | "*/flexConfig_ML01.dat"
23 | !========
24 | UNITS PRESENCE MATRIX
25 | FC_01(Lumped) ! ID
26 | .true. !
27 | !========
28 | INPUTS DESCRIPTION
29 | 2 ! precipitation input (1=lumped,2=perSubcatchment(ID),3=perFied)
30 | 0 ! tracer input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
31 | 2 ! etp input (1=lumped,2=perSubcatchment(ID),3=perFied)
32 | 0 ! temperature input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
33 | !========
34 | DRAINAGE DISTANCES
35 | riverScaleInc riverScaleOut riverSlopeInc riverSlopeOut
36 | 1.0 1.0 1.0 1.0
37 | !========
38 | DEPENDENCIES
39 | DrainsInto
40 | 0
41 | !========
42 | RIVER ROUTING CONVOLUTION INFORMATION
43 | "none",.false.,-1,1 ! convolution function "symTri","genTri","kiedKeid","none", for symTri only tS and tR are needed; couple scales (if true relative scaleInc and scaleOut is preserved) smoothing options; maximum number of convolution states
44 | !========
45 | ACTIVE_PARAMETER_INFO ! (parameters visible to BATEA)
46 | parName parDef parLo parHi parScal parSD parTran parFit linkTo Comment
47 | "Cmlt_P, - " 1.0 0.9 1.1 10.0 -9999.9 0 F 0 (cannot be dead) Rainfall multiplication factor
48 | "Cmlt_E, - " 1.0 0.2 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor for evaporation
49 | "CmltSmax_IR, - " 1.0 1.e-1 3.0 10.0 -9999.9 1 F 0 (cannot be dead) Intercaption multiplication factor
50 | "CmltSmax_UR, - " 1.0 1.e-1 500.0 10.0 -9999.9 1 F 0 (cannot be dead) SuMax multiplication factor
51 | "CmltBetaQq_UR, -" 1.0 1.e-2 10.0 10.0 -9999.9 1 F 0 (cannot be dead) BetaQq multiplication factor
52 | "Cmlt_P_WR, - " 1.0 1.e-1 3.0 10.0 -9999.9 0 F 0 (cannot be dead) Multiplication factor to wCorr in snow reservoir
53 | "CmltK_Qm_WR, - " 1.0 1.e-1 10.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qm in snow reservoir
54 | "CmltK_Qq_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qq in slow reservoir
55 | "CmltK_Qb_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qb in slow reservoir
56 | !========
57 | MORTO_PARAMETER_INFO ! (parameters that dont exist for this configuration)
58 | "tFall_IL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
59 | "K_IL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
60 | "tFall_OL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
61 | "K_OL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
62 | "tStart_IL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
63 | "tRise_IL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
64 | "betaM_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
65 | "betaS_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
66 | "tStart_OL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
67 | "tRise_OL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
68 | "betaM_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
69 | "betaS_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
70 | !========
71 |
--------------------------------------------------------------------------------
/test/reference_results/03_UR_FR/M01_main.dat:
--------------------------------------------------------------------------------
1 | FLEX_MAIN_CONFIGURATION_FILE_V1.05
2 | ! Description: FLEX-SPAM model configuration file
3 | !========
4 | 01 ! index describing model configuration (for ease of reference/documentation)
5 | "M01" ! nametag describing model configuration (eg, "stdFLEX/powerAS", etc)
6 | !========
7 | FLEX NUMERICS
8 | 1 ! numerical solver for interception reservoir (0=odeint, 1=fixed-spm-implicit, 2=bounded EE, -1=simple-threshold, -2=algebraic-statique)
9 | 3 ! numerical solver for simple reservoirs (0=odeint, 3=fixed-liebre-implicit, 2=bounded EE)
10 | 1 ! numerical solver for UR zone (0=odeint, 1=fixed-spm-implicit, 2=bounded EE)
11 | !========
12 | FLEX DISTRIBUTION
13 | 1 ! number of HRUs
14 | 1 ! number of catchments
15 | 0 ! number of tracers
16 | 1 ! number of layers (dead storages)
17 | !========
18 | HRU CHARACTERISTICS FILE NAME
19 | "*/flexConfig_Areas.dat"
20 | !========
21 | UNITS FILE NAME
22 | "*/flexConfig_ML01.dat"
23 | !========
24 | UNITS PRESENCE MATRIX
25 | FC_01(Lumped) ! ID
26 | .true. !
27 | !========
28 | INPUTS DESCRIPTION
29 | 2 ! precipitation input (1=lumped,2=perSubcatchment(ID),3=perFied)
30 | 0 ! tracer input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
31 | 2 ! etp input (1=lumped,2=perSubcatchment(ID),3=perFied)
32 | 0 ! temperature input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
33 | !========
34 | DRAINAGE DISTANCES
35 | riverScaleInc riverScaleOut riverSlopeInc riverSlopeOut
36 | 1.0 1.0 1.0 1.0
37 | !========
38 | DEPENDENCIES
39 | DrainsInto
40 | 0
41 | !========
42 | RIVER ROUTING CONVOLUTION INFORMATION
43 | "none",.false.,-1,1 ! convolution function "symTri","genTri","kiedKeid","none", for symTri only tS and tR are needed; couple scales (if true relative scaleInc and scaleOut is preserved) smoothing options; maximum number of convolution states
44 | !========
45 | ACTIVE_PARAMETER_INFO ! (parameters visible to BATEA)
46 | parName parDef parLo parHi parScal parSD parTran parFit linkTo Comment
47 | "Cmlt_P, - " 1.0 0.9 1.1 10.0 -9999.9 0 F 0 (cannot be dead) Rainfall multiplication factor
48 | "Cmlt_E, - " 1.0 0.2 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor for evaporation
49 | "CmltSmax_IR, - " 1.0 1.e-1 3.0 10.0 -9999.9 1 F 0 (cannot be dead) Intercaption multiplication factor
50 | "CmltSmax_UR, - " 1.0 1.e-1 500.0 10.0 -9999.9 1 F 0 (cannot be dead) SuMax multiplication factor
51 | "CmltBetaQq_UR, -" 1.0 1.e-2 10.0 10.0 -9999.9 1 F 0 (cannot be dead) BetaQq multiplication factor
52 | "Cmlt_P_WR, - " 1.0 1.e-1 3.0 10.0 -9999.9 0 F 0 (cannot be dead) Multiplication factor to wCorr in snow reservoir
53 | "CmltK_Qm_WR, - " 1.0 1.e-1 10.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qm in snow reservoir
54 | "CmltK_Qq_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qq in slow reservoir
55 | "CmltK_Qb_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qb in slow reservoir
56 | !========
57 | MORTO_PARAMETER_INFO ! (parameters that dont exist for this configuration)
58 | "tFall_IL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
59 | "K_IL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
60 | "tFall_OL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
61 | "K_OL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
62 | "tStart_IL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
63 | "tRise_IL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
64 | "betaM_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
65 | "betaS_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
66 | "tStart_OL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
67 | "tRise_OL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
68 | "betaM_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
69 | "betaS_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
70 | !========
71 |
--------------------------------------------------------------------------------
/test/reference_results/07_FR_2dt/M01_main.dat:
--------------------------------------------------------------------------------
1 | FLEX_MAIN_CONFIGURATION_FILE_V1.05
2 | ! Description: FLEX-SPAM model configuration file
3 | !========
4 | 01 ! index describing model configuration (for ease of reference/documentation)
5 | "M01" ! nametag describing model configuration (eg, "stdFLEX/powerAS", etc)
6 | !========
7 | FLEX NUMERICS
8 | 1 ! numerical solver for interception reservoir (0=odeint, 1=fixed-spm-implicit, 2=bounded EE, -1=simple-threshold, -2=algebraic-statique)
9 | 3 ! numerical solver for simple reservoirs (0=odeint, 3=fixed-liebre-implicit, 2=bounded EE)
10 | 1 ! numerical solver for UR zone (0=odeint, 1=fixed-spm-implicit, 2=bounded EE)
11 | !========
12 | FLEX DISTRIBUTION
13 | 1 ! number of HRUs
14 | 1 ! number of catchments
15 | 0 ! number of tracers
16 | 1 ! number of layers (dead storages)
17 | !========
18 | HRU CHARACTERISTICS FILE NAME
19 | "*/flexConfig_Areas.dat"
20 | !========
21 | UNITS FILE NAME
22 | "*/flexConfig_ML01.dat"
23 | !========
24 | UNITS PRESENCE MATRIX
25 | FC_01(Lumped) ! ID
26 | .true. !
27 | !========
28 | INPUTS DESCRIPTION
29 | 2 ! precipitation input (1=lumped,2=perSubcatchment(ID),3=perFied)
30 | 0 ! tracer input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
31 | 2 ! etp input (1=lumped,2=perSubcatchment(ID),3=perFied)
32 | 0 ! temperature input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
33 | !========
34 | DRAINAGE DISTANCES
35 | riverScaleInc riverScaleOut riverSlopeInc riverSlopeOut
36 | 1.0 1.0 1.0 1.0
37 | !========
38 | DEPENDENCIES
39 | DrainsInto
40 | 0
41 | !========
42 | RIVER ROUTING CONVOLUTION INFORMATION
43 | "none",.false.,-1,1 ! convolution function "symTri","genTri","kiedKeid","none", for symTri only tS and tR are needed; couple scales (if true relative scaleInc and scaleOut is preserved) smoothing options; maximum number of convolution states
44 | !========
45 | ACTIVE_PARAMETER_INFO ! (parameters visible to BATEA)
46 | parName parDef parLo parHi parScal parSD parTran parFit linkTo Comment
47 | "Cmlt_P, - " 1.0 0.9 1.1 10.0 -9999.9 0 F 0 (cannot be dead) Rainfall multiplication factor
48 | "Cmlt_E, - " 1.0 0.2 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor for evaporation
49 | "CmltSmax_IR, - " 1.0 1.e-1 3.0 10.0 -9999.9 1 F 0 (cannot be dead) Intercaption multiplication factor
50 | "CmltSmax_UR, - " 1.0 1.e-1 500.0 10.0 -9999.9 1 F 0 (cannot be dead) SuMax multiplication factor
51 | "CmltBetaQq_UR, -" 1.0 1.e-2 10.0 10.0 -9999.9 1 F 0 (cannot be dead) BetaQq multiplication factor
52 | "Cmlt_P_WR, - " 1.0 1.e-1 3.0 10.0 -9999.9 0 F 0 (cannot be dead) Multiplication factor to wCorr in snow reservoir
53 | "CmltK_Qm_WR, - " 1.0 1.e-1 10.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qm in snow reservoir
54 | "CmltK_Qq_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qq in slow reservoir
55 | "CmltK_Qb_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qb in slow reservoir
56 | !========
57 | MORTO_PARAMETER_INFO ! (parameters that dont exist for this configuration)
58 | "tFall_IL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
59 | "K_IL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
60 | "tFall_OL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
61 | "K_OL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
62 | "tStart_IL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
63 | "tRise_IL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
64 | "betaM_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
65 | "betaS_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
66 | "tStart_OL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
67 | "tRise_OL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
68 | "betaM_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
69 | "betaS_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
70 | !========
71 |
--------------------------------------------------------------------------------
/test/reference_results/08_UR_2dt/M01_main.dat:
--------------------------------------------------------------------------------
1 | FLEX_MAIN_CONFIGURATION_FILE_V1.05
2 | ! Description: FLEX-SPAM model configuration file
3 | !========
4 | 01 ! index describing model configuration (for ease of reference/documentation)
5 | "M01" ! nametag describing model configuration (eg, "stdFLEX/powerAS", etc)
6 | !========
7 | FLEX NUMERICS
8 | 1 ! numerical solver for interception reservoir (0=odeint, 1=fixed-spm-implicit, 2=bounded EE, -1=simple-threshold, -2=algebraic-statique)
9 | 3 ! numerical solver for simple reservoirs (0=odeint, 3=fixed-liebre-implicit, 2=bounded EE)
10 | 1 ! numerical solver for UR zone (0=odeint, 1=fixed-spm-implicit, 2=bounded EE)
11 | !========
12 | FLEX DISTRIBUTION
13 | 1 ! number of HRUs
14 | 1 ! number of catchments
15 | 0 ! number of tracers
16 | 1 ! number of layers (dead storages)
17 | !========
18 | HRU CHARACTERISTICS FILE NAME
19 | "*/flexConfig_Areas.dat"
20 | !========
21 | UNITS FILE NAME
22 | "*/flexConfig_ML01.dat"
23 | !========
24 | UNITS PRESENCE MATRIX
25 | FC_01(Lumped) ! ID
26 | .true. !
27 | !========
28 | INPUTS DESCRIPTION
29 | 2 ! precipitation input (1=lumped,2=perSubcatchment(ID),3=perFied)
30 | 0 ! tracer input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
31 | 2 ! etp input (1=lumped,2=perSubcatchment(ID),3=perFied)
32 | 0 ! temperature input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
33 | !========
34 | DRAINAGE DISTANCES
35 | riverScaleInc riverScaleOut riverSlopeInc riverSlopeOut
36 | 1.0 1.0 1.0 1.0
37 | !========
38 | DEPENDENCIES
39 | DrainsInto
40 | 0
41 | !========
42 | RIVER ROUTING CONVOLUTION INFORMATION
43 | "none",.false.,-1,1 ! convolution function "symTri","genTri","kiedKeid","none", for symTri only tS and tR are needed; couple scales (if true relative scaleInc and scaleOut is preserved) smoothing options; maximum number of convolution states
44 | !========
45 | ACTIVE_PARAMETER_INFO ! (parameters visible to BATEA)
46 | parName parDef parLo parHi parScal parSD parTran parFit linkTo Comment
47 | "Cmlt_P, - " 1.0 0.9 1.1 10.0 -9999.9 0 F 0 (cannot be dead) Rainfall multiplication factor
48 | "Cmlt_E, - " 1.0 0.2 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor for evaporation
49 | "CmltSmax_IR, - " 1.0 1.e-1 3.0 10.0 -9999.9 1 F 0 (cannot be dead) Intercaption multiplication factor
50 | "CmltSmax_UR, - " 1.0 1.e-1 500.0 10.0 -9999.9 1 F 0 (cannot be dead) SuMax multiplication factor
51 | "CmltBetaQq_UR, -" 1.0 1.e-2 10.0 10.0 -9999.9 1 F 0 (cannot be dead) BetaQq multiplication factor
52 | "Cmlt_P_WR, - " 1.0 1.e-1 3.0 10.0 -9999.9 0 F 0 (cannot be dead) Multiplication factor to wCorr in snow reservoir
53 | "CmltK_Qm_WR, - " 1.0 1.e-1 10.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qm in snow reservoir
54 | "CmltK_Qq_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qq in slow reservoir
55 | "CmltK_Qb_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qb in slow reservoir
56 | !========
57 | MORTO_PARAMETER_INFO ! (parameters that dont exist for this configuration)
58 | "tFall_IL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
59 | "K_IL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
60 | "tFall_OL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
61 | "K_OL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
62 | "tStart_IL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
63 | "tRise_IL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
64 | "betaM_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
65 | "betaS_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
66 | "tStart_OL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
67 | "tRise_OL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
68 | "betaM_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
69 | "betaS_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
70 | !========
71 |
--------------------------------------------------------------------------------
/test/reference_results/04_UR_FR_SR/M01_main.dat:
--------------------------------------------------------------------------------
1 | FLEX_MAIN_CONFIGURATION_FILE_V1.05
2 | ! Description: FLEX-SPAM model configuration file
3 | !========
4 | 01 ! index describing model configuration (for ease of reference/documentation)
5 | "M01" ! nametag describing model configuration (eg, "stdFLEX/powerAS", etc)
6 | !========
7 | FLEX NUMERICS
8 | 1 ! numerical solver for interception reservoir (0=odeint, 1=fixed-spm-implicit, 2=bounded EE, -1=simple-threshold, -2=algebraic-statique)
9 | 3 ! numerical solver for simple reservoirs (0=odeint, 3=fixed-liebre-implicit, 2=bounded EE)
10 | 1 ! numerical solver for UR zone (0=odeint, 1=fixed-spm-implicit, 2=bounded EE)
11 | !========
12 | FLEX DISTRIBUTION
13 | 1 ! number of HRUs
14 | 1 ! number of catchments
15 | 0 ! number of tracers
16 | 1 ! number of layers (dead storages)
17 | !========
18 | HRU CHARACTERISTICS FILE NAME
19 | "*/flexConfig_Areas.dat"
20 | !========
21 | UNITS FILE NAME
22 | "*/flexConfig_ML01.dat"
23 | !========
24 | UNITS PRESENCE MATRIX
25 | FC_01(Lumped) ! ID
26 | .true. !
27 | !========
28 | INPUTS DESCRIPTION
29 | 2 ! precipitation input (1=lumped,2=perSubcatchment(ID),3=perFied)
30 | 0 ! tracer input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
31 | 2 ! etp input (1=lumped,2=perSubcatchment(ID),3=perFied)
32 | 0 ! temperature input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
33 | !========
34 | DRAINAGE DISTANCES
35 | riverScaleInc riverScaleOut riverSlopeInc riverSlopeOut
36 | 1.0 1.0 1.0 1.0
37 | !========
38 | DEPENDENCIES
39 | DrainsInto
40 | 0
41 | !========
42 | RIVER ROUTING CONVOLUTION INFORMATION
43 | "none",.false.,-1,1 ! convolution function "symTri","genTri","kiedKeid","none", for symTri only tS and tR are needed; couple scales (if true relative scaleInc and scaleOut is preserved) smoothing options; maximum number of convolution states
44 | !========
45 | ACTIVE_PARAMETER_INFO ! (parameters visible to BATEA)
46 | parName parDef parLo parHi parScal parSD parTran parFit linkTo Comment
47 | "Cmlt_P, - " 1.0 0.9 1.1 10.0 -9999.9 0 F 0 (cannot be dead) Rainfall multiplication factor
48 | "Cmlt_E, - " 1.0 0.2 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor for evaporation
49 | "CmltSmax_IR, - " 1.0 1.e-1 3.0 10.0 -9999.9 1 F 0 (cannot be dead) Intercaption multiplication factor
50 | "CmltSmax_UR, - " 1.0 1.e-1 500.0 10.0 -9999.9 1 F 0 (cannot be dead) SuMax multiplication factor
51 | "CmltBetaQq_UR, -" 1.0 1.e-2 10.0 10.0 -9999.9 1 F 0 (cannot be dead) BetaQq multiplication factor
52 | "Cmlt_P_WR, - " 1.0 1.e-1 3.0 10.0 -9999.9 0 F 0 (cannot be dead) Multiplication factor to wCorr in snow reservoir
53 | "CmltK_Qm_WR, - " 1.0 1.e-1 10.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qm in snow reservoir
54 | "CmltK_Qq_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qq in slow reservoir
55 | "CmltK_Qb_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qb in slow reservoir
56 | !========
57 | MORTO_PARAMETER_INFO ! (parameters that dont exist for this configuration)
58 | "tFall_IL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
59 | "K_IL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
60 | "tFall_OL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
61 | "K_OL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
62 | "tStart_IL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
63 | "tRise_IL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
64 | "betaM_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
65 | "betaS_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
66 | "tStart_OL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
67 | "tRise_OL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
68 | "betaM_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
69 | "betaS_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
70 | !========
71 |
--------------------------------------------------------------------------------
/test/reference_results/05_2HRUs/M01_main.dat:
--------------------------------------------------------------------------------
1 | FLEX_MAIN_CONFIGURATION_FILE_V1.05
2 | ! Description: FLEX-SPAM model configuration file
3 | !========
4 | 01 ! index describing model configuration (for ease of reference/documentation)
5 | "M01" ! nametag describing model configuration (eg, "stdFLEX/powerAS", etc)
6 | !========
7 | FLEX NUMERICS
8 | 1 ! numerical solver for interception reservoir (0=odeint, 1=fixed-spm-implicit, 2=bounded EE, -1=simple-threshold, -2=algebraic-statique)
9 | 3 ! numerical solver for simple reservoirs (0=odeint, 3=fixed-liebre-implicit, 2=bounded EE)
10 | 1 ! numerical solver for UR zone (0=odeint, 1=fixed-spm-implicit, 2=bounded EE)
11 | !========
12 | FLEX DISTRIBUTION
13 | 2 ! number of HRUs
14 | 1 ! number of catchments
15 | 0 ! number of tracers
16 | 1 ! number of layers (dead storages)
17 | !========
18 | HRU CHARACTERISTICS FILE NAME
19 | "*/flexConfig_Areas.dat"
20 | !========
21 | UNITS FILE NAME
22 | "*/flexConfig_HRU1.dat"
23 | "*/flexConfig_HRU2.dat"
24 | !========
25 | UNITS PRESENCE MATRIX
26 | FC_01(Cons) FC_01(NotCons) ! ID
27 | .true. .true. !
28 | !========
29 | INPUTS DESCRIPTION
30 | 2 ! precipitation input (1=lumped,2=perSubcatchment(ID),3=perFied)
31 | 0 ! tracer input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
32 | 2 ! etp input (1=lumped,2=perSubcatchment(ID),3=perFied)
33 | 0 ! temperature input (0=absent,1=lumped,2=perSubcatchment(ID),3=perFied)
34 | !========
35 | DRAINAGE DISTANCES
36 | riverScaleInc riverScaleOut riverSlopeInc riverSlopeOut
37 | 1.0 1.0 1.0 1.0
38 | !========
39 | DEPENDENCIES
40 | DrainsInto
41 | 0
42 | !========
43 | RIVER ROUTING CONVOLUTION INFORMATION
44 | "none",.false.,-1,1 ! convolution function "symTri","genTri","kiedKeid","none", for symTri only tS and tR are needed; couple scales (if true relative scaleInc and scaleOut is preserved) smoothing options; maximum number of convolution states
45 | !========
46 | ACTIVE_PARAMETER_INFO ! (parameters visible to BATEA)
47 | parName parDef parLo parHi parScal parSD parTran parFit linkTo Comment
48 | "Cmlt_P, - " 1.0 0.9 1.1 10.0 -9999.9 0 F 0 (cannot be dead) Rainfall multiplication factor
49 | "Cmlt_E, - " 1.0 0.2 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor for evaporation
50 | "CmltSmax_IR, - " 1.0 1.e-1 3.0 10.0 -9999.9 1 F 0 (cannot be dead) Intercaption multiplication factor
51 | "CmltSmax_UR, - " 1.0 1.e-1 500.0 10.0 -9999.9 1 F 0 (cannot be dead) SuMax multiplication factor
52 | "CmltBetaQq_UR, -" 1.0 1.e-2 10.0 10.0 -9999.9 1 F 0 (cannot be dead) BetaQq multiplication factor
53 | "Cmlt_P_WR, - " 1.0 1.e-1 3.0 10.0 -9999.9 0 F 0 (cannot be dead) Multiplication factor to wCorr in snow reservoir
54 | "CmltK_Qm_WR, - " 1.0 1.e-1 10.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qm in snow reservoir
55 | "CmltK_Qq_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qq in slow reservoir
56 | "CmltK_Qb_SR, - " 1.0 1.e-1 5.0 10.0 -9999.9 1 F 0 (cannot be dead) Multiplication factor to K_Qb in slow reservoir
57 | !========
58 | MORTO_PARAMETER_INFO ! (parameters that dont exist for this configuration)
59 | "tFall_IL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
60 | "K_IL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
61 | "tFall_OL, t " 0.5 0.5 20.0 10.0 -9999.9 0 T 0 Time base for river routing - TFall
62 | "K_OL, 1/t " 0.0 1.e-2 4.0 10.0 -9999.9 0 F 0 k for linear nash cascade ("kiedKeid") (uses TRise as nRes)
63 | "tStart_IL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
64 | "tRise_IL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
65 | "betaM_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
66 | "betaS_IL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
67 | "tStart_OL, t " 0.0 0.0 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TStart
68 | "tRise_OL, t " 1.0 0.5 10.0 10.0 -9999.9 0 F 0 Time base for river routing - TRise
69 | "betaM_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power slope
70 | "betaS_OL, - " 1.0 0.1 1.0 10.0 -9999.9 0 F 0 Power storage (kiedKeid) or length/slope (convolution)
71 | !========
72 |
--------------------------------------------------------------------------------
/doc/model_thur_hess2020.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 | import sys
3 |
4 | REPO_FOLDER = pathlib.Path(__file__).absolute().parents[2]
5 | sys.path.insert(0, str(REPO_FOLDER))
6 | from superflexpy.framework.network import Network
7 | from superflexpy.framework.node import Node
8 | from superflexpy.framework.unit import Unit
9 | from superflexpy.implementation.elements.structure_elements import (
10 | Junction,
11 | Splitter,
12 | Transparent,
13 | )
14 | from superflexpy.implementation.elements.thur_model_hess import (
15 | HalfTriangularLag,
16 | PowerReservoir,
17 | SnowReservoir,
18 | UnsaturatedReservoir,
19 | )
20 | from superflexpy.implementation.numerical_approximators.implicit_euler import (
21 | ImplicitEulerPython,
22 | )
23 | from superflexpy.implementation.root_finders.pegasus import PegasusPython
24 |
25 | solver = PegasusPython()
26 | approximator = ImplicitEulerPython(root_finder=solver)
27 |
28 | # Fluxes in the order P, T, PET
29 | upper_splitter = Splitter(
30 | direction=[
31 | [0, 1, None], # P and T go to the snow reservoir
32 | [2, None, None], # PET goes to the transparent element
33 | ],
34 | weight=[[1.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
35 | id="upper-splitter",
36 | )
37 |
38 | snow = SnowReservoir(
39 | parameters={"t0": 0.0, "k": 0.01, "m": 2.0}, states={"S0": 0.0}, approximation=approximator, id="snow"
40 | )
41 |
42 | upper_transparent = Transparent(id="upper-transparent")
43 |
44 | upper_junction = Junction(direction=[[0, None], [None, 0]], id="upper-junction")
45 |
46 | unsaturated = UnsaturatedReservoir(
47 | parameters={"Smax": 50.0, "Ce": 1.0, "m": 0.01, "beta": 2.0},
48 | states={"S0": 10.0},
49 | approximation=approximator,
50 | id="unsaturated",
51 | )
52 |
53 | lower_splitter = Splitter(
54 | direction=[[0], [0]],
55 | weight=[[0.3], [0.7]], # Portion to slow reservoir # Portion to fast reservoir
56 | id="lower-splitter",
57 | )
58 |
59 | lag_fun = HalfTriangularLag(parameters={"lag-time": 2.0}, states={"lag": None}, id="lag-fun")
60 |
61 | fast = PowerReservoir(parameters={"k": 0.01, "alpha": 3.0}, states={"S0": 0.0}, approximation=approximator, id="fast")
62 |
63 | slow = PowerReservoir(parameters={"k": 1e-4, "alpha": 1.0}, states={"S0": 0.0}, approximation=approximator, id="slow")
64 |
65 | lower_transparent = Transparent(id="lower-transparent")
66 |
67 | lower_junction = Junction(direction=[[0, 0]], id="lower-junction")
68 |
69 | consolidated = Unit(
70 | layers=[
71 | [upper_splitter],
72 | [snow, upper_transparent],
73 | [upper_junction],
74 | [unsaturated],
75 | [lower_splitter],
76 | [slow, lag_fun],
77 | [lower_transparent, fast],
78 | [lower_junction],
79 | ],
80 | id="consolidated",
81 | )
82 |
83 | unconsolidated = Unit(
84 | layers=[
85 | [upper_splitter],
86 | [snow, upper_transparent],
87 | [upper_junction],
88 | [unsaturated],
89 | [lower_splitter],
90 | [slow, lag_fun],
91 | [lower_transparent, fast],
92 | [lower_junction],
93 | ],
94 | id="unconsolidated",
95 | )
96 |
97 | andelfingen = Node(units=[consolidated, unconsolidated], weights=[0.24, 0.76], area=403.3, id="andelfingen")
98 |
99 | appenzell = Node(units=[consolidated, unconsolidated], weights=[0.92, 0.08], area=74.4, id="appenzell")
100 |
101 | frauenfeld = Node(units=[consolidated, unconsolidated], weights=[0.49, 0.51], area=134.4, id="frauenfeld")
102 |
103 | halden = Node(units=[consolidated, unconsolidated], weights=[0.34, 0.66], area=314.3, id="halden")
104 |
105 | herisau = Node(units=[consolidated, unconsolidated], weights=[0.88, 0.12], area=16.7, id="herisau")
106 |
107 | jonschwil = Node(units=[consolidated, unconsolidated], weights=[0.9, 0.1], area=401.6, id="jonschwil")
108 |
109 | mogelsberg = Node(units=[consolidated, unconsolidated], weights=[0.92, 0.08], area=88.1, id="mogelsberg")
110 |
111 | mosnang = Node(units=[consolidated], weights=[1.0], area=3.1, id="mosnang")
112 |
113 | stgallen = Node(units=[consolidated, unconsolidated], weights=[0.87, 0.13], area=186.6, id="stgallen")
114 |
115 | waengi = Node(units=[consolidated, unconsolidated], weights=[0.63, 0.37], area=78.9, id="waengi")
116 |
117 | thur_catchment = Network(
118 | nodes=[
119 | andelfingen,
120 | appenzell,
121 | frauenfeld,
122 | halden,
123 | herisau,
124 | jonschwil,
125 | mogelsberg,
126 | mosnang,
127 | stgallen,
128 | waengi,
129 | ],
130 | topology={
131 | "andelfingen": None,
132 | "appenzell": "stgallen",
133 | "frauenfeld": "andelfingen",
134 | "halden": "andelfingen",
135 | "herisau": "halden",
136 | "jonschwil": "halden",
137 | "mogelsberg": "jonschwil",
138 | "mosnang": "jonschwil",
139 | "stgallen": "halden",
140 | "waengi": "frauenfeld",
141 | },
142 | )
143 |
144 | thur_catchment.set_timestep(1.0)
145 |
146 | catchments = [
147 | andelfingen,
148 | appenzell,
149 | frauenfeld,
150 | halden,
151 | herisau,
152 | jonschwil,
153 | mogelsberg,
154 | mosnang,
155 | stgallen,
156 | waengi,
157 | ]
158 |
159 | catchments_names = [
160 | "andelfingen",
161 | "appenzell",
162 | "frauenfeld",
163 | "halden",
164 | "herisau",
165 | "jonschwil",
166 | "mogelsberg",
167 | "mosnang",
168 | "stgallen",
169 | "waengi",
170 | ]
171 |
172 | df = {}
173 |
174 | for cat, cat_name in zip(catchments, catchments_names):
175 | cat.set_input(
176 | [
177 | df["P_{}".format(cat_name)].values,
178 | df["T_{}".format(cat_name)].values,
179 | df["PET_{}".format(cat_name)].values,
180 | ]
181 | )
182 |
183 | thur_catchment.set_timestep(1.0)
184 |
185 | output = thur_catchment.get_output()
186 |
--------------------------------------------------------------------------------
/doc/case_studies.rst:
--------------------------------------------------------------------------------
1 | .. note:: Last update 04/05/2021
2 |
3 | .. .. warning:: This guide is still work in progress. New pages are being written
4 | .. and existing ones modified. Once the guide will reach its final
5 | .. version, this box will disappear.
6 |
7 | .. _case_studies:
8 |
9 | Case studies
10 | ============
11 |
12 | This page describes the model configurations used in research publications based
13 | on Superflex and SuperflexPy.
14 |
15 | .. _thur_case_study:
16 |
17 | Dal Molin et al., 2020, HESS
18 | ----------------------------
19 |
20 | This section describes the implementation of the semi-distributed hydrological
21 | model M02 presented in the article:
22 |
23 | Dal Molin, M., Schirmer, M., Zappa, M., and Fenicia, F.: **Understanding**
24 | **dominant controls on streamflow spatial variability to set up a**
25 | **semi-distributed hydrological model: the case study of the Thur**
26 | **catchment**, Hydrol. Earth Syst. Sci., 24, 1319–1345,
27 | https://doi.org/10.5194/hess-24-1319-2020, 2020.
28 |
29 | In this application, the Thur catchment is discretized into 10 subcatchments and 2
30 | hydrological response units (HRUs). Please refer to the article for the details;
31 | here we only show the SuperflexPy code needed to reproduce the model from the
32 | publication.
33 |
34 | Model structure
35 | ...............
36 |
37 | The two HRUs are represented using the same model structure, shown in the
38 | figure below.
39 |
40 | .. image:: pics/case_studies/model_structure_thur.png
41 | :align: center
42 |
43 | This model structure is similar to :ref:`hymod`; its implementation using
44 | SuperflexPy is presented next.
45 |
46 | .. image:: pics/case_studies/ThurHESS2020.png
47 | :align: center
48 |
49 | This model structure includes a snow model, and hence requires time series of
50 | temperature as an input in addition to precipitation and PET.
51 | Inputs are assigned to the element in the first layer of the unit and the
52 | model structure then propagates these inputs through all the elements until they
53 | reach the element (snow reservoir) where they are actually needed. Consequently, all the elements
54 | upstream of the snow reservoir have to be able to handle (i.e. to input and output) that input.
55 |
56 | In this model, the choice of temperature as input is convenient because
57 | temperature is required by the element appearing first in the model structure.
58 |
59 | In other cases, an alternative solution would have been to design the snow
60 | reservoir such that the temperature is one of its state variables. This solution
61 | would be preferable if the snow reservoir is not the first element of the
62 | structure, given that temperature is not an input commonly used by other
63 | elements.
64 |
65 | The discretization of the Thur catchment into units (HRUs) and nodes
66 | (subcatchments) is represented in the figure below.
67 |
68 | .. image:: pics/case_studies/ThurSchemeNodes.png
69 | :align: center
70 |
71 | Initializing the elements
72 | .........................
73 |
74 | All elements required for this model structure are already available in
75 | SuperflexPy. Therefore they just need to be imported.
76 |
77 | .. literalinclude:: model_thur_hess2020.py
78 | :language: python
79 | :lines: 5-6, 10, 11
80 | :linenos:
81 |
82 | Elements are then initialized, defining the initial state and parameter values.
83 |
84 | .. literalinclude:: model_thur_hess2020.py
85 | :language: python
86 | :lines: 13-15, 17-96
87 | :linenos:
88 |
89 | Initializing the HRUs structure
90 | ...............................
91 |
92 | We now define the two units that represent the HRUs.
93 |
94 | .. literalinclude:: model_thur_hess2020.py
95 | :language: python
96 | :lines: 98-124
97 | :linenos:
98 |
99 | Initializing the catchments
100 | ...........................
101 |
102 | We now assign the units (HRUs) to the nodes (catchments).
103 |
104 | .. literalinclude:: model_thur_hess2020.py
105 | :language: python
106 | :lines: 126-194
107 | :linenos:
108 |
109 | Note that all nodes incorporate the information about their :code:`area`, which
110 | is used by the network to calculate their contribution to the total outflow.
111 |
112 | There is no requirement for a node to contain all units. For example, the unit
113 | :code:`unconsolidated` is not present in the Mosnang subcatchment. Hence, as
114 | shown in line 50, the node :code:`mosnang` is defined to contain only the unit
115 | :code:`consolidated`.
116 |
117 | Initializing the network
118 | ........................
119 |
120 | The last step consists in creating the network that connects all the nodes
121 | previously initialized.
122 |
123 | .. literalinclude:: model_thur_hess2020.py
124 | :language: python
125 | :lines: 196-221
126 | :linenos:
127 |
128 | Running the model
129 | .................
130 |
131 | Before the model can be run, we need to set the input fluxes and the time step size.
132 |
133 | The input fluxes are assigned to the individual nodes (catchments).
134 | Here, the data is available as a Pandas DataFrame, with columns names :code:`P_name_of_the_catchment`,
135 | :code:`T_name_of_the_catchment`, and :code:`PET_name_of_the_catchment`.
136 |
137 | The inputs can be set using a :code:`for` loop
138 |
139 | .. literalinclude:: model_thur_hess2020.py
140 | :language: python
141 | :lines: 253-258
142 | :linenos:
143 |
144 | The model time step size is set next. This can be done directly at the
145 | network level, which automatically sets the time step size to all lower-level
146 | model components.
147 |
148 | .. literalinclude:: model_thur_hess2020.py
149 | :language: python
150 | :lines: 260
151 | :linenos:
152 |
153 | We can now run the model and access its output (see :ref:`demo_network` for details).
154 |
155 | .. literalinclude:: model_thur_hess2020.py
156 | :language: python
157 | :lines: 262
158 | :linenos:
159 |
--------------------------------------------------------------------------------