HydPy 6.2.dev1__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hydpy/__init__.py +275 -0
- hydpy/aliases.py +2554 -0
- hydpy/auxs/__init__.py +0 -0
- hydpy/auxs/anntools.py +1305 -0
- hydpy/auxs/armatools.py +883 -0
- hydpy/auxs/calibtools.py +3337 -0
- hydpy/auxs/interptools.py +1094 -0
- hydpy/auxs/iuhtools.py +543 -0
- hydpy/auxs/networktools.py +597 -0
- hydpy/auxs/ppolytools.py +809 -0
- hydpy/auxs/quadtools.py +61 -0
- hydpy/auxs/roottools.py +228 -0
- hydpy/auxs/smoothtools.py +273 -0
- hydpy/auxs/statstools.py +2125 -0
- hydpy/auxs/validtools.py +81 -0
- hydpy/conf/HydPyConfigBase.xsd +68637 -0
- hydpy/conf/HydPyConfigBase.xsdt +358 -0
- hydpy/conf/HydPyConfigMultipleRuns.xsd +25 -0
- hydpy/conf/HydPyConfigSingleRun.xsd +24 -0
- hydpy/conf/__init__.py +0 -0
- hydpy/conf/a_coefficients_explicit_lobatto_sequence.npy +0 -0
- hydpy/conf/support_points_for_smoothpar_logistic2.npy +0 -0
- hydpy/config.py +42 -0
- hydpy/core/__init__.py +0 -0
- hydpy/core/aliastools.py +214 -0
- hydpy/core/autodoctools.py +1947 -0
- hydpy/core/auxfiletools.py +1169 -0
- hydpy/core/devicetools.py +3810 -0
- hydpy/core/exceptiontools.py +269 -0
- hydpy/core/filetools.py +1985 -0
- hydpy/core/hydpytools.py +3089 -0
- hydpy/core/importtools.py +1398 -0
- hydpy/core/indextools.py +345 -0
- hydpy/core/itemtools.py +1849 -0
- hydpy/core/masktools.py +460 -0
- hydpy/core/modeltools.py +4868 -0
- hydpy/core/netcdftools.py +2683 -0
- hydpy/core/objecttools.py +2023 -0
- hydpy/core/optiontools.py +1045 -0
- hydpy/core/parametertools.py +4674 -0
- hydpy/core/printtools.py +222 -0
- hydpy/core/propertytools.py +643 -0
- hydpy/core/pubtools.py +254 -0
- hydpy/core/selectiontools.py +1571 -0
- hydpy/core/sequencetools.py +4476 -0
- hydpy/core/seriestools.py +339 -0
- hydpy/core/testtools.py +2483 -0
- hydpy/core/timetools.py +3567 -0
- hydpy/core/typingtools.py +333 -0
- hydpy/core/variabletools.py +2615 -0
- hydpy/cythons/__init__.py +24 -0
- hydpy/cythons/annutils.pxd +33 -0
- hydpy/cythons/annutils.pyi +25 -0
- hydpy/cythons/annutils.pyx +120 -0
- hydpy/cythons/autogen/__init__.py +0 -0
- hydpy/cythons/autogen/annutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/annutils.pxd +42 -0
- hydpy/cythons/autogen/annutils.pyx +129 -0
- hydpy/cythons/autogen/c_arma.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_arma.pxd +179 -0
- hydpy/cythons/autogen/c_arma.pyx +356 -0
- hydpy/cythons/autogen/c_arma_rimorido.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_arma_rimorido.pxd +179 -0
- hydpy/cythons/autogen/c_arma_rimorido.pyx +356 -0
- hydpy/cythons/autogen/c_conv.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv.pxd +198 -0
- hydpy/cythons/autogen/c_conv.pyx +491 -0
- hydpy/cythons/autogen/c_conv_idw.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_idw.pxd +124 -0
- hydpy/cythons/autogen/c_conv_idw.pyx +264 -0
- hydpy/cythons/autogen/c_conv_idw_ed.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_idw_ed.pxd +197 -0
- hydpy/cythons/autogen/c_conv_idw_ed.pyx +481 -0
- hydpy/cythons/autogen/c_conv_nn.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_nn.pxd +120 -0
- hydpy/cythons/autogen/c_conv_nn.pyx +224 -0
- hydpy/cythons/autogen/c_dam.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam.pxd +805 -0
- hydpy/cythons/autogen/c_dam.pyx +1477 -0
- hydpy/cythons/autogen/c_dam_llake.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_llake.pxd +364 -0
- hydpy/cythons/autogen/c_dam_llake.pyx +705 -0
- hydpy/cythons/autogen/c_dam_lreservoir.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_lreservoir.pxd +365 -0
- hydpy/cythons/autogen/c_dam_lreservoir.pyx +708 -0
- hydpy/cythons/autogen/c_dam_lretention.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_lretention.pxd +340 -0
- hydpy/cythons/autogen/c_dam_lretention.pyx +625 -0
- hydpy/cythons/autogen/c_dam_pump.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_pump.pxd +402 -0
- hydpy/cythons/autogen/c_dam_pump.pyx +724 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.pxd +452 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.pyx +829 -0
- hydpy/cythons/autogen/c_dam_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_sluice.pxd +404 -0
- hydpy/cythons/autogen/c_dam_sluice.pyx +726 -0
- hydpy/cythons/autogen/c_dam_v001.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v001.pxd +452 -0
- hydpy/cythons/autogen/c_dam_v001.pyx +816 -0
- hydpy/cythons/autogen/c_dam_v002.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v002.pxd +394 -0
- hydpy/cythons/autogen/c_dam_v002.pyx +703 -0
- hydpy/cythons/autogen/c_dam_v003.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v003.pxd +417 -0
- hydpy/cythons/autogen/c_dam_v003.pyx +744 -0
- hydpy/cythons/autogen/c_dam_v004.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v004.pxd +486 -0
- hydpy/cythons/autogen/c_dam_v004.pyx +891 -0
- hydpy/cythons/autogen/c_dam_v005.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v005.pxd +524 -0
- hydpy/cythons/autogen/c_dam_v005.pyx +928 -0
- hydpy/cythons/autogen/c_dummy.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy.pxd +151 -0
- hydpy/cythons/autogen/c_dummy.pyx +263 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_node2node.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_node2node.pxd +89 -0
- hydpy/cythons/autogen/c_dummy_node2node.pyx +148 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_snowcover.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowcover.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowcover.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_soilwater.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_soilwater.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_soilwater.pyx +104 -0
- hydpy/cythons/autogen/c_evap.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap.pxd +1029 -0
- hydpy/cythons/autogen/c_evap.pyx +2601 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.pxd +227 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.pyx +584 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.pxd +193 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.pyx +478 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.pxd +681 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.pyx +1642 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.pxd +532 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.pyx +1296 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.pxd +179 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.pyx +328 -0
- hydpy/cythons/autogen/c_evap_pet_m.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_m.pxd +124 -0
- hydpy/cythons/autogen/c_evap_pet_m.pyx +214 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.pxd +126 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.pyx +214 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.pxd +305 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.pyx +624 -0
- hydpy/cythons/autogen/c_evap_ret_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_io.pxd +112 -0
- hydpy/cythons/autogen/c_evap_ret_io.pyx +176 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.pxd +139 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.pyx +273 -0
- hydpy/cythons/autogen/c_exch.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch.pxd +230 -0
- hydpy/cythons/autogen/c_exch.pyx +462 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.pxd +134 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.pyx +255 -0
- hydpy/cythons/autogen/c_exch_waterlevel.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_waterlevel.pxd +54 -0
- hydpy/cythons/autogen/c_exch_waterlevel.pyx +78 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.pxd +156 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.pyx +282 -0
- hydpy/cythons/autogen/c_ga.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga.pxd +353 -0
- hydpy/cythons/autogen/c_ga.pyx +1204 -0
- hydpy/cythons/autogen/c_ga_garto.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga_garto.pxd +330 -0
- hydpy/cythons/autogen/c_ga_garto.pyx +1105 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.pxd +236 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.pyx +944 -0
- hydpy/cythons/autogen/c_gland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland.pxd +437 -0
- hydpy/cythons/autogen/c_gland.pyx +726 -0
- hydpy/cythons/autogen/c_gland_gr4.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr4.pxd +382 -0
- hydpy/cythons/autogen/c_gland_gr4.pyx +605 -0
- hydpy/cythons/autogen/c_gland_gr5.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr5.pxd +368 -0
- hydpy/cythons/autogen/c_gland_gr5.pyx +568 -0
- hydpy/cythons/autogen/c_gland_gr6.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr6.pxd +420 -0
- hydpy/cythons/autogen/c_gland_gr6.pyx +673 -0
- hydpy/cythons/autogen/c_hland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland.pxd +855 -0
- hydpy/cythons/autogen/c_hland.pyx +2486 -0
- hydpy/cythons/autogen/c_hland_96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96.pxd +631 -0
- hydpy/cythons/autogen/c_hland_96.pyx +1724 -0
- hydpy/cythons/autogen/c_hland_96c.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96c.pxd +621 -0
- hydpy/cythons/autogen/c_hland_96c.pyx +1822 -0
- hydpy/cythons/autogen/c_hland_96p.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96p.pxd +683 -0
- hydpy/cythons/autogen/c_hland_96p.pyx +1911 -0
- hydpy/cythons/autogen/c_kinw.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw.pxd +509 -0
- hydpy/cythons/autogen/c_kinw.pyx +965 -0
- hydpy/cythons/autogen/c_kinw_williams.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw_williams.pxd +409 -0
- hydpy/cythons/autogen/c_kinw_williams.pyx +763 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.pxd +220 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.pyx +440 -0
- hydpy/cythons/autogen/c_lland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland.pxd +1386 -0
- hydpy/cythons/autogen/c_lland.pyx +3679 -0
- hydpy/cythons/autogen/c_lland_dd.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_dd.pxd +679 -0
- hydpy/cythons/autogen/c_lland_dd.pyx +1719 -0
- hydpy/cythons/autogen/c_lland_knauf.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_knauf.pxd +1096 -0
- hydpy/cythons/autogen/c_lland_knauf.pyx +2784 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.pxd +1369 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.pyx +3625 -0
- hydpy/cythons/autogen/c_meteo.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo.pxd +469 -0
- hydpy/cythons/autogen/c_meteo.pyx +879 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.pxd +75 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.pyx +107 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.pxd +209 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.pyx +339 -0
- hydpy/cythons/autogen/c_meteo_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_io.pxd +63 -0
- hydpy/cythons/autogen/c_meteo_glob_io.pyx +91 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.pxd +289 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.pyx +527 -0
- hydpy/cythons/autogen/c_meteo_precip_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_precip_io.pxd +112 -0
- hydpy/cythons/autogen/c_meteo_precip_io.pyx +176 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pxd +87 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pyx +123 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.pxd +209 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.pyx +343 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.pxd +286 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.pyx +519 -0
- hydpy/cythons/autogen/c_meteo_temp_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_temp_io.pxd +112 -0
- hydpy/cythons/autogen/c_meteo_temp_io.pyx +176 -0
- hydpy/cythons/autogen/c_musk.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk.pxd +282 -0
- hydpy/cythons/autogen/c_musk.pyx +605 -0
- hydpy/cythons/autogen/c_musk_classic.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk_classic.pxd +138 -0
- hydpy/cythons/autogen/c_musk_classic.pyx +226 -0
- hydpy/cythons/autogen/c_musk_mct.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk_mct.pxd +282 -0
- hydpy/cythons/autogen/c_musk_mct.pyx +609 -0
- hydpy/cythons/autogen/c_rconc.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc.pxd +119 -0
- hydpy/cythons/autogen/c_rconc.pyx +174 -0
- hydpy/cythons/autogen/c_rconc_nash.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc_nash.pxd +111 -0
- hydpy/cythons/autogen/c_rconc_nash.pyx +185 -0
- hydpy/cythons/autogen/c_rconc_uh.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc_uh.pxd +92 -0
- hydpy/cythons/autogen/c_rconc_uh.pyx +125 -0
- hydpy/cythons/autogen/c_sw1d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d.pxd +511 -0
- hydpy/cythons/autogen/c_sw1d.pyx +1263 -0
- hydpy/cythons/autogen/c_sw1d_channel.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_channel.pxd +119 -0
- hydpy/cythons/autogen/c_sw1d_channel.pyx +300 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.pxd +240 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.pyx +476 -0
- hydpy/cythons/autogen/c_sw1d_lias.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_lias.pxd +320 -0
- hydpy/cythons/autogen/c_sw1d_lias.pyx +619 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.pxd +325 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.pyx +644 -0
- hydpy/cythons/autogen/c_sw1d_network.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_network.pxd +90 -0
- hydpy/cythons/autogen/c_sw1d_network.pyx +246 -0
- hydpy/cythons/autogen/c_sw1d_pump.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_pump.pxd +256 -0
- hydpy/cythons/autogen/c_sw1d_pump.pyx +502 -0
- hydpy/cythons/autogen/c_sw1d_q_in.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_q_in.pxd +224 -0
- hydpy/cythons/autogen/c_sw1d_q_in.pyx +383 -0
- hydpy/cythons/autogen/c_sw1d_q_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_q_out.pxd +224 -0
- hydpy/cythons/autogen/c_sw1d_q_out.pyx +383 -0
- hydpy/cythons/autogen/c_sw1d_storage.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_storage.pxd +193 -0
- hydpy/cythons/autogen/c_sw1d_storage.pyx +349 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.pxd +212 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.pyx +404 -0
- hydpy/cythons/autogen/c_test.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test.pxd +175 -0
- hydpy/cythons/autogen/c_test.pyx +348 -0
- hydpy/cythons/autogen/c_test_discontinous.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_discontinous.pxd +146 -0
- hydpy/cythons/autogen/c_test_discontinous.pyx +256 -0
- hydpy/cythons/autogen/c_test_stiff0d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_stiff0d.pxd +146 -0
- hydpy/cythons/autogen/c_test_stiff0d.pyx +250 -0
- hydpy/cythons/autogen/c_test_stiff1d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_stiff1d.pxd +145 -0
- hydpy/cythons/autogen/c_test_stiff1d.pyx +294 -0
- hydpy/cythons/autogen/c_whmod.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod.pxd +482 -0
- hydpy/cythons/autogen/c_whmod.pyx +1156 -0
- hydpy/cythons/autogen/c_whmod_rural.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod_rural.pxd +411 -0
- hydpy/cythons/autogen/c_whmod_rural.pyx +982 -0
- hydpy/cythons/autogen/c_whmod_urban.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod_urban.pxd +482 -0
- hydpy/cythons/autogen/c_whmod_urban.pyx +1155 -0
- hydpy/cythons/autogen/c_wland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland.pxd +842 -0
- hydpy/cythons/autogen/c_wland.pyx +1890 -0
- hydpy/cythons/autogen/c_wland_gd.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland_gd.pxd +829 -0
- hydpy/cythons/autogen/c_wland_gd.pyx +1847 -0
- hydpy/cythons/autogen/c_wland_wag.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland_wag.pxd +810 -0
- hydpy/cythons/autogen/c_wland_wag.pyx +1780 -0
- hydpy/cythons/autogen/c_wq.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq.pxd +275 -0
- hydpy/cythons/autogen/c_wq.pyx +652 -0
- hydpy/cythons/autogen/c_wq_trapeze.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_trapeze.pxd +170 -0
- hydpy/cythons/autogen/c_wq_trapeze.pyx +400 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.pxd +243 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.pyx +578 -0
- hydpy/cythons/autogen/c_wq_walrus.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_walrus.pxd +61 -0
- hydpy/cythons/autogen/c_wq_walrus.pyx +82 -0
- hydpy/cythons/autogen/configutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/configutils.pxd +17 -0
- hydpy/cythons/autogen/configutils.pyx +119 -0
- hydpy/cythons/autogen/interfaceutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/interfaceutils.pxd +31 -0
- hydpy/cythons/autogen/interfaceutils.pyx +82 -0
- hydpy/cythons/autogen/interputils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/interputils.pxd +42 -0
- hydpy/cythons/autogen/interputils.pyx +118 -0
- hydpy/cythons/autogen/masterinterface.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/masterinterface.pxd +153 -0
- hydpy/cythons/autogen/masterinterface.pyx +222 -0
- hydpy/cythons/autogen/pointerutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/pointerutils.pxd +31 -0
- hydpy/cythons/autogen/pointerutils.pyx +650 -0
- hydpy/cythons/autogen/ppolyutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/ppolyutils.pxd +35 -0
- hydpy/cythons/autogen/ppolyutils.pyx +59 -0
- hydpy/cythons/autogen/quadutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/quadutils.pxd +26 -0
- hydpy/cythons/autogen/quadutils.pyx +973 -0
- hydpy/cythons/autogen/rootutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/rootutils.pxd +28 -0
- hydpy/cythons/autogen/rootutils.pyx +109 -0
- hydpy/cythons/autogen/sequenceutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/sequenceutils.pxd +45 -0
- hydpy/cythons/autogen/sequenceutils.pyx +101 -0
- hydpy/cythons/autogen/smoothutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/smoothutils.pxd +29 -0
- hydpy/cythons/autogen/smoothutils.pyx +833 -0
- hydpy/cythons/configutils.pxd +8 -0
- hydpy/cythons/configutils.pyi +5 -0
- hydpy/cythons/configutils.pyx +110 -0
- hydpy/cythons/interfaceutils.pxd +22 -0
- hydpy/cythons/interfaceutils.pyi +15 -0
- hydpy/cythons/interfaceutils.pyx +73 -0
- hydpy/cythons/interputils.pxd +33 -0
- hydpy/cythons/interputils.pyi +32 -0
- hydpy/cythons/interputils.pyx +109 -0
- hydpy/cythons/modelutils.py +2990 -0
- hydpy/cythons/pointerutils.pxd +22 -0
- hydpy/cythons/pointerutils.pyi +89 -0
- hydpy/cythons/pointerutils.pyx +641 -0
- hydpy/cythons/ppolyutils.pxd +26 -0
- hydpy/cythons/ppolyutils.pyi +21 -0
- hydpy/cythons/ppolyutils.pyx +50 -0
- hydpy/cythons/quadutils.pxd +17 -0
- hydpy/cythons/quadutils.pyi +13 -0
- hydpy/cythons/quadutils.pyx +964 -0
- hydpy/cythons/rootutils.pxd +19 -0
- hydpy/cythons/rootutils.pyi +21 -0
- hydpy/cythons/rootutils.pyx +100 -0
- hydpy/cythons/sequenceutils.pxd +36 -0
- hydpy/cythons/sequenceutils.pyi +7 -0
- hydpy/cythons/sequenceutils.pyx +92 -0
- hydpy/cythons/smoothutils.pxd +20 -0
- hydpy/cythons/smoothutils.pyi +15 -0
- hydpy/cythons/smoothutils.pyx +824 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_dill_assl.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_kalk.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_leun.py +14 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_marb.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_dill_assl_lahn_leun.py +5 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_leun_lahn_kalk.py +5 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_marb_lahn_leun.py +5 -0
- hydpy/data/HydPy-H-Lahn/control/default/land.py +9 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_dill_assl.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_kalk.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_leun.py +56 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_marb.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_dill_assl_lahn_leun.py +7 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_leun_lahn_kalk.py +7 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_marb_lahn_leun.py +7 -0
- hydpy/data/HydPy-H-Lahn/multiple_runs.xml +309 -0
- hydpy/data/HydPy-H-Lahn/multiple_runs_alpha.xml +71 -0
- hydpy/data/HydPy-H-Lahn/network/default/headwaters.py +11 -0
- hydpy/data/HydPy-H-Lahn/network/default/nonheadwaters.py +11 -0
- hydpy/data/HydPy-H-Lahn/network/default/streams.py +8 -0
- hydpy/data/HydPy-H-Lahn/series/default/dill_assl_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalairtemperature.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalevapotranspiration.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_p.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_t.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_kalk_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_leun_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_marb_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/obs_q.nc +0 -0
- hydpy/data/HydPy-H-Lahn/single_run.xml +152 -0
- hydpy/data/HydPy-H-Lahn/single_run.xmlt +143 -0
- hydpy/data/__init__.py +17 -0
- hydpy/docs/__init__.py +0 -0
- hydpy/docs/autofigs/__init__.py +0 -0
- hydpy/docs/bib/__init__.py +0 -0
- hydpy/docs/bib/refs.bib +566 -0
- hydpy/docs/combine_docversions.py +133 -0
- hydpy/docs/draw_model_sketches.py +1301 -0
- hydpy/docs/enable_autodoc.py +7 -0
- hydpy/docs/figs/HydPy-G-GR4.png +0 -0
- hydpy/docs/figs/HydPy-G-GR5.png +0 -0
- hydpy/docs/figs/HydPy-G-GR6.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96-COSERO.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96-PREVAH.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96.png +0 -0
- hydpy/docs/figs/HydPy-H-Lahn.png +0 -0
- hydpy/docs/figs/HydPy-KinW-Williams.png +0 -0
- hydpy/docs/figs/HydPy-L-DD.png +0 -0
- hydpy/docs/figs/HydPy-W-Wag.png +0 -0
- hydpy/docs/figs/HydPy_Logo.png +0 -0
- hydpy/docs/figs/HydPy_Logo_Text.png +0 -0
- hydpy/docs/figs/IDLE-editor.png +0 -0
- hydpy/docs/figs/IDLE-shell.png +0 -0
- hydpy/docs/figs/LAWA_river-basin-bumbers.png +0 -0
- hydpy/docs/figs/__init__.py +0 -0
- hydpy/docs/html_/__init__.py +0 -0
- hydpy/docs/polish_html.py +57 -0
- hydpy/docs/prepare.py +224 -0
- hydpy/docs/publish_docs.py +53 -0
- hydpy/docs/rst/HydPy-ARMA.rst +27 -0
- hydpy/docs/rst/HydPy-Conv.rst +22 -0
- hydpy/docs/rst/HydPy-Dam.rst +79 -0
- hydpy/docs/rst/HydPy-Dummy.rst +21 -0
- hydpy/docs/rst/HydPy-Evap.rst +26 -0
- hydpy/docs/rst/HydPy-Exch.rst +36 -0
- hydpy/docs/rst/HydPy-G.rst +40 -0
- hydpy/docs/rst/HydPy-GA.rst +34 -0
- hydpy/docs/rst/HydPy-H.rst +24 -0
- hydpy/docs/rst/HydPy-KinW.rst +32 -0
- hydpy/docs/rst/HydPy-L.rst +42 -0
- hydpy/docs/rst/HydPy-Meteo.rst +28 -0
- hydpy/docs/rst/HydPy-Musk.rst +21 -0
- hydpy/docs/rst/HydPy-Rconc.rst +17 -0
- hydpy/docs/rst/HydPy-SW1D.rst +49 -0
- hydpy/docs/rst/HydPy-Test.rst +19 -0
- hydpy/docs/rst/HydPy-W.rst +20 -0
- hydpy/docs/rst/HydPy-WHMod.rst +19 -0
- hydpy/docs/rst/HydPy-WQ.rst +20 -0
- hydpy/docs/rst/__init__.py +0 -0
- hydpy/docs/rst/additional_repositories.rst +40 -0
- hydpy/docs/rst/auxiliaries.rst +31 -0
- hydpy/docs/rst/continuous_integration.rst +75 -0
- hydpy/docs/rst/core.rst +75 -0
- hydpy/docs/rst/cythons.rst +47 -0
- hydpy/docs/rst/definitions.rst +506 -0
- hydpy/docs/rst/developer_guide.rst +54 -0
- hydpy/docs/rst/example_projects.rst +40 -0
- hydpy/docs/rst/execution.rst +22 -0
- hydpy/docs/rst/framework_tools.rst +56 -0
- hydpy/docs/rst/how_to_read_the_reference_manual.rst +156 -0
- hydpy/docs/rst/hydpydependencies.rst +55 -0
- hydpy/docs/rst/index.rst +125 -0
- hydpy/docs/rst/installation.rst +155 -0
- hydpy/docs/rst/model_families.rst +79 -0
- hydpy/docs/rst/model_overview.rst +291 -0
- hydpy/docs/rst/modelimports.rst +10 -0
- hydpy/docs/rst/options.rst +119 -0
- hydpy/docs/rst/programming_style.rst +572 -0
- hydpy/docs/rst/project_structure.rst +520 -0
- hydpy/docs/rst/quickstart.rst +304 -0
- hydpy/docs/rst/reference_manual.rst +29 -0
- hydpy/docs/rst/required_tools.rst +50 -0
- hydpy/docs/rst/simulation.rst +514 -0
- hydpy/docs/rst/submodel_interfaces.rst +32 -0
- hydpy/docs/rst/tests_and_documentation.rst +85 -0
- hydpy/docs/rst/user_guide.rst +38 -0
- hydpy/docs/rst/version_control.rst +116 -0
- hydpy/docs/rst/zbibliography.rst +8 -0
- hydpy/docs/sphinx/__init__.py +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/frameset.html +11 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/rstsource.html +15 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/versionchanges.html +33 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/defindex.html +35 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/domainindex.html +56 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex-single.html +63 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex-split.html +41 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex.html +76 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/globaltoc.html +11 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/layout.html +221 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/localtoc.html +15 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/opensearch.xml +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/page.html +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/relations.html +23 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/search.html +65 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/searchbox.html +21 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/searchfield.html +23 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/sourcelink.html +18 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/basic.css_t +925 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/doctools.js +156 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/documentation_options.js_t +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/file.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/language_data.js_t +26 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/minus.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/plus.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/searchtools.js +574 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/sphinx_highlight.js +154 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/theme.conf +16 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/layout.html +23 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/static/classic.css_t +358 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/static/sidebar.js_t +72 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/theme.conf +32 -0
- hydpy/docs/sphinx/conf.py +398 -0
- hydpy/docs/sphinx/defaultlinks_extension.py +36 -0
- hydpy/docs/sphinx/integrationtest_extension.py +104 -0
- hydpy/docs/sphinx/projectstructure_extension.py +58 -0
- hydpy/docs/sphinx/submodelgraph_extension.py +53 -0
- hydpy/exe/__init__.py +0 -0
- hydpy/exe/commandtools.py +651 -0
- hydpy/exe/hyd.py +277 -0
- hydpy/exe/modelimports.py +41 -0
- hydpy/exe/replacetools.py +216 -0
- hydpy/exe/servertools.py +2348 -0
- hydpy/exe/xmltools.py +3280 -0
- hydpy/interfaces/__init__.py +0 -0
- hydpy/interfaces/aetinterfaces.py +94 -0
- hydpy/interfaces/dischargeinterfaces.py +45 -0
- hydpy/interfaces/petinterfaces.py +117 -0
- hydpy/interfaces/precipinterfaces.py +42 -0
- hydpy/interfaces/radiationinterfaces.py +79 -0
- hydpy/interfaces/rconcinterfaces.py +30 -0
- hydpy/interfaces/routinginterfaces.py +324 -0
- hydpy/interfaces/soilinterfaces.py +96 -0
- hydpy/interfaces/stateinterfaces.py +98 -0
- hydpy/interfaces/tempinterfaces.py +46 -0
- hydpy/models/__init__.py +0 -0
- hydpy/models/arma/__init__.py +14 -0
- hydpy/models/arma/arma_control.py +383 -0
- hydpy/models/arma/arma_derived.py +204 -0
- hydpy/models/arma/arma_fluxes.py +41 -0
- hydpy/models/arma/arma_inlets.py +11 -0
- hydpy/models/arma/arma_logs.py +19 -0
- hydpy/models/arma/arma_model.py +461 -0
- hydpy/models/arma/arma_outlets.py +11 -0
- hydpy/models/arma_rimorido.py +381 -0
- hydpy/models/conv/__init__.py +12 -0
- hydpy/models/conv/conv_control.py +303 -0
- hydpy/models/conv/conv_derived.py +271 -0
- hydpy/models/conv/conv_fluxes.py +54 -0
- hydpy/models/conv/conv_inlets.py +11 -0
- hydpy/models/conv/conv_model.py +687 -0
- hydpy/models/conv/conv_outlets.py +11 -0
- hydpy/models/conv_idw.py +120 -0
- hydpy/models/conv_idw_ed.py +184 -0
- hydpy/models/conv_nn.py +112 -0
- hydpy/models/dam/__init__.py +16 -0
- hydpy/models/dam/dam_aides.py +17 -0
- hydpy/models/dam/dam_control.py +346 -0
- hydpy/models/dam/dam_derived.py +559 -0
- hydpy/models/dam/dam_factors.py +46 -0
- hydpy/models/dam/dam_fluxes.py +179 -0
- hydpy/models/dam/dam_inlets.py +29 -0
- hydpy/models/dam/dam_logs.py +52 -0
- hydpy/models/dam/dam_model.py +5011 -0
- hydpy/models/dam/dam_outlets.py +23 -0
- hydpy/models/dam/dam_receivers.py +41 -0
- hydpy/models/dam/dam_senders.py +23 -0
- hydpy/models/dam/dam_solver.py +75 -0
- hydpy/models/dam/dam_states.py +11 -0
- hydpy/models/dam_llake.py +499 -0
- hydpy/models/dam_lreservoir.py +548 -0
- hydpy/models/dam_lretention.py +343 -0
- hydpy/models/dam_pump.py +278 -0
- hydpy/models/dam_pump_sluice.py +339 -0
- hydpy/models/dam_sluice.py +319 -0
- hydpy/models/dam_v001.py +1127 -0
- hydpy/models/dam_v002.py +381 -0
- hydpy/models/dam_v003.py +422 -0
- hydpy/models/dam_v004.py +665 -0
- hydpy/models/dam_v005.py +479 -0
- hydpy/models/dummy/__init__.py +15 -0
- hydpy/models/dummy/dummy_control.py +22 -0
- hydpy/models/dummy/dummy_fluxes.py +11 -0
- hydpy/models/dummy/dummy_inlets.py +11 -0
- hydpy/models/dummy/dummy_inputs.py +41 -0
- hydpy/models/dummy/dummy_model.py +196 -0
- hydpy/models/dummy/dummy_outlets.py +11 -0
- hydpy/models/dummy_interceptedwater.py +85 -0
- hydpy/models/dummy_node2node.py +83 -0
- hydpy/models/dummy_snowalbedo.py +84 -0
- hydpy/models/dummy_snowcover.py +84 -0
- hydpy/models/dummy_snowycanopy.py +86 -0
- hydpy/models/dummy_soilwater.py +85 -0
- hydpy/models/evap/__init__.py +13 -0
- hydpy/models/evap/evap_control.py +354 -0
- hydpy/models/evap/evap_derived.py +236 -0
- hydpy/models/evap/evap_factors.py +188 -0
- hydpy/models/evap/evap_fixed.py +68 -0
- hydpy/models/evap/evap_fluxes.py +150 -0
- hydpy/models/evap/evap_inputs.py +54 -0
- hydpy/models/evap/evap_logs.py +91 -0
- hydpy/models/evap/evap_masks.py +48 -0
- hydpy/models/evap/evap_model.py +9170 -0
- hydpy/models/evap/evap_parameters.py +149 -0
- hydpy/models/evap/evap_sequences.py +32 -0
- hydpy/models/evap/evap_states.py +18 -0
- hydpy/models/evap_aet_hbv96.py +372 -0
- hydpy/models/evap_aet_minhas.py +331 -0
- hydpy/models/evap_aet_morsim.py +627 -0
- hydpy/models/evap_pet_ambav1.py +483 -0
- hydpy/models/evap_pet_hbv96.py +147 -0
- hydpy/models/evap_pet_m.py +94 -0
- hydpy/models/evap_pet_mlc.py +107 -0
- hydpy/models/evap_ret_fao56.py +265 -0
- hydpy/models/evap_ret_io.py +74 -0
- hydpy/models/evap_ret_tw2002.py +165 -0
- hydpy/models/exch/__init__.py +14 -0
- hydpy/models/exch/exch_control.py +262 -0
- hydpy/models/exch/exch_derived.py +36 -0
- hydpy/models/exch/exch_factors.py +26 -0
- hydpy/models/exch/exch_fluxes.py +48 -0
- hydpy/models/exch/exch_inlets.py +11 -0
- hydpy/models/exch/exch_logs.py +12 -0
- hydpy/models/exch/exch_model.py +451 -0
- hydpy/models/exch/exch_outlets.py +17 -0
- hydpy/models/exch/exch_receivers.py +17 -0
- hydpy/models/exch_branch_hbv96.py +186 -0
- hydpy/models/exch_waterlevel.py +73 -0
- hydpy/models/exch_weir_hbv96.py +609 -0
- hydpy/models/ga/__init__.py +14 -0
- hydpy/models/ga/ga_aides.py +17 -0
- hydpy/models/ga/ga_control.py +208 -0
- hydpy/models/ga/ga_derived.py +77 -0
- hydpy/models/ga/ga_fluxes.py +83 -0
- hydpy/models/ga/ga_inputs.py +26 -0
- hydpy/models/ga/ga_logs.py +17 -0
- hydpy/models/ga/ga_model.py +2952 -0
- hydpy/models/ga/ga_states.py +87 -0
- hydpy/models/ga_garto.py +1001 -0
- hydpy/models/ga_garto_submodel1.py +79 -0
- hydpy/models/gland/__init__.py +14 -0
- hydpy/models/gland/gland_control.py +90 -0
- hydpy/models/gland/gland_derived.py +113 -0
- hydpy/models/gland/gland_fluxes.py +137 -0
- hydpy/models/gland/gland_inputs.py +12 -0
- hydpy/models/gland/gland_model.py +1439 -0
- hydpy/models/gland/gland_outlets.py +11 -0
- hydpy/models/gland/gland_states.py +90 -0
- hydpy/models/gland_gr4.py +501 -0
- hydpy/models/gland_gr5.py +463 -0
- hydpy/models/gland_gr6.py +487 -0
- hydpy/models/hland/__init__.py +20 -0
- hydpy/models/hland/hland_aides.py +19 -0
- hydpy/models/hland/hland_constants.py +37 -0
- hydpy/models/hland/hland_control.py +1530 -0
- hydpy/models/hland/hland_derived.py +683 -0
- hydpy/models/hland/hland_factors.py +57 -0
- hydpy/models/hland/hland_fixed.py +42 -0
- hydpy/models/hland/hland_fluxes.py +279 -0
- hydpy/models/hland/hland_inputs.py +19 -0
- hydpy/models/hland/hland_masks.py +107 -0
- hydpy/models/hland/hland_model.py +4664 -0
- hydpy/models/hland/hland_outlets.py +11 -0
- hydpy/models/hland/hland_parameters.py +227 -0
- hydpy/models/hland/hland_sequences.py +382 -0
- hydpy/models/hland/hland_states.py +236 -0
- hydpy/models/hland_96.py +1812 -0
- hydpy/models/hland_96c.py +1196 -0
- hydpy/models/hland_96p.py +1204 -0
- hydpy/models/kinw/__init__.py +18 -0
- hydpy/models/kinw/kinw_aides.py +306 -0
- hydpy/models/kinw/kinw_control.py +270 -0
- hydpy/models/kinw/kinw_derived.py +197 -0
- hydpy/models/kinw/kinw_fixed.py +33 -0
- hydpy/models/kinw/kinw_fluxes.py +37 -0
- hydpy/models/kinw/kinw_inlets.py +11 -0
- hydpy/models/kinw/kinw_model.py +3026 -0
- hydpy/models/kinw/kinw_outlets.py +11 -0
- hydpy/models/kinw/kinw_solver.py +45 -0
- hydpy/models/kinw/kinw_states.py +17 -0
- hydpy/models/kinw_williams.py +1299 -0
- hydpy/models/kinw_williams_ext.py +768 -0
- hydpy/models/lland/__init__.py +42 -0
- hydpy/models/lland/lland_aides.py +38 -0
- hydpy/models/lland/lland_constants.py +88 -0
- hydpy/models/lland/lland_control.py +1329 -0
- hydpy/models/lland/lland_derived.py +380 -0
- hydpy/models/lland/lland_factors.py +18 -0
- hydpy/models/lland/lland_fixed.py +128 -0
- hydpy/models/lland/lland_fluxes.py +626 -0
- hydpy/models/lland/lland_inlets.py +12 -0
- hydpy/models/lland/lland_inputs.py +33 -0
- hydpy/models/lland/lland_logs.py +17 -0
- hydpy/models/lland/lland_masks.py +212 -0
- hydpy/models/lland/lland_model.py +7690 -0
- hydpy/models/lland/lland_outlets.py +12 -0
- hydpy/models/lland/lland_parameters.py +195 -0
- hydpy/models/lland/lland_sequences.py +67 -0
- hydpy/models/lland/lland_states.py +280 -0
- hydpy/models/lland_dd.py +2270 -0
- hydpy/models/lland_knauf.py +2156 -0
- hydpy/models/lland_knauf_ic.py +1920 -0
- hydpy/models/meteo/__init__.py +12 -0
- hydpy/models/meteo/meteo_control.py +154 -0
- hydpy/models/meteo/meteo_derived.py +159 -0
- hydpy/models/meteo/meteo_factors.py +88 -0
- hydpy/models/meteo/meteo_fixed.py +19 -0
- hydpy/models/meteo/meteo_fluxes.py +46 -0
- hydpy/models/meteo/meteo_inputs.py +47 -0
- hydpy/models/meteo/meteo_logs.py +30 -0
- hydpy/models/meteo/meteo_model.py +2904 -0
- hydpy/models/meteo/meteo_parameters.py +14 -0
- hydpy/models/meteo/meteo_sequences.py +22 -0
- hydpy/models/meteo_clear_glob_io.py +77 -0
- hydpy/models/meteo_glob_fao56.py +217 -0
- hydpy/models/meteo_glob_io.py +68 -0
- hydpy/models/meteo_glob_morsim.py +444 -0
- hydpy/models/meteo_precip_io.py +76 -0
- hydpy/models/meteo_psun_sun_glob_io.py +83 -0
- hydpy/models/meteo_sun_fao56.py +188 -0
- hydpy/models/meteo_sun_morsim.py +466 -0
- hydpy/models/meteo_temp_io.py +76 -0
- hydpy/models/musk/__init__.py +15 -0
- hydpy/models/musk/musk_control.py +328 -0
- hydpy/models/musk/musk_derived.py +32 -0
- hydpy/models/musk/musk_factors.py +53 -0
- hydpy/models/musk/musk_fluxes.py +24 -0
- hydpy/models/musk/musk_inlets.py +11 -0
- hydpy/models/musk/musk_masks.py +15 -0
- hydpy/models/musk/musk_model.py +838 -0
- hydpy/models/musk/musk_outlets.py +11 -0
- hydpy/models/musk/musk_sequences.py +88 -0
- hydpy/models/musk/musk_solver.py +68 -0
- hydpy/models/musk/musk_states.py +64 -0
- hydpy/models/musk_classic.py +228 -0
- hydpy/models/musk_mct.py +1247 -0
- hydpy/models/rconc/__init__.py +12 -0
- hydpy/models/rconc/rconc_control.py +473 -0
- hydpy/models/rconc/rconc_derived.py +76 -0
- hydpy/models/rconc/rconc_fluxes.py +19 -0
- hydpy/models/rconc/rconc_logs.py +74 -0
- hydpy/models/rconc/rconc_model.py +260 -0
- hydpy/models/rconc/rconc_states.py +11 -0
- hydpy/models/rconc_nash.py +48 -0
- hydpy/models/rconc_uh.py +53 -0
- hydpy/models/sw1d/__init__.py +17 -0
- hydpy/models/sw1d/sw1d_control.py +356 -0
- hydpy/models/sw1d/sw1d_derived.py +85 -0
- hydpy/models/sw1d/sw1d_factors.py +78 -0
- hydpy/models/sw1d/sw1d_fixed.py +12 -0
- hydpy/models/sw1d/sw1d_fluxes.py +55 -0
- hydpy/models/sw1d/sw1d_inlets.py +17 -0
- hydpy/models/sw1d/sw1d_model.py +3385 -0
- hydpy/models/sw1d/sw1d_outlets.py +11 -0
- hydpy/models/sw1d/sw1d_receivers.py +11 -0
- hydpy/models/sw1d/sw1d_senders.py +11 -0
- hydpy/models/sw1d/sw1d_states.py +23 -0
- hydpy/models/sw1d_channel.py +2051 -0
- hydpy/models/sw1d_gate_out.py +599 -0
- hydpy/models/sw1d_lias.py +105 -0
- hydpy/models/sw1d_lias_sluice.py +531 -0
- hydpy/models/sw1d_network.py +1219 -0
- hydpy/models/sw1d_pump.py +448 -0
- hydpy/models/sw1d_q_in.py +79 -0
- hydpy/models/sw1d_q_out.py +81 -0
- hydpy/models/sw1d_storage.py +78 -0
- hydpy/models/sw1d_weir_out.py +75 -0
- hydpy/models/test/__init__.py +14 -0
- hydpy/models/test/test_control.py +28 -0
- hydpy/models/test/test_fluxes.py +17 -0
- hydpy/models/test/test_model.py +201 -0
- hydpy/models/test/test_solver.py +48 -0
- hydpy/models/test/test_states.py +17 -0
- hydpy/models/test_discontinous.py +46 -0
- hydpy/models/test_stiff0d.py +47 -0
- hydpy/models/test_stiff1d.py +42 -0
- hydpy/models/whmod/__init__.py +21 -0
- hydpy/models/whmod/whmod_constants.py +77 -0
- hydpy/models/whmod/whmod_control.py +333 -0
- hydpy/models/whmod/whmod_derived.py +210 -0
- hydpy/models/whmod/whmod_factors.py +9 -0
- hydpy/models/whmod/whmod_fluxes.py +105 -0
- hydpy/models/whmod/whmod_inputs.py +15 -0
- hydpy/models/whmod/whmod_masks.py +178 -0
- hydpy/models/whmod/whmod_model.py +2091 -0
- hydpy/models/whmod/whmod_parameters.py +155 -0
- hydpy/models/whmod/whmod_sequences.py +193 -0
- hydpy/models/whmod/whmod_states.py +73 -0
- hydpy/models/whmod_rural.py +794 -0
- hydpy/models/whmod_urban.py +1011 -0
- hydpy/models/wland/__init__.py +43 -0
- hydpy/models/wland/wland_aides.py +55 -0
- hydpy/models/wland/wland_constants.py +103 -0
- hydpy/models/wland/wland_control.py +508 -0
- hydpy/models/wland/wland_derived.py +330 -0
- hydpy/models/wland/wland_factors.py +11 -0
- hydpy/models/wland/wland_fixed.py +12 -0
- hydpy/models/wland/wland_fluxes.py +166 -0
- hydpy/models/wland/wland_inputs.py +33 -0
- hydpy/models/wland/wland_masks.py +54 -0
- hydpy/models/wland/wland_model.py +3755 -0
- hydpy/models/wland/wland_outlets.py +11 -0
- hydpy/models/wland/wland_parameters.py +214 -0
- hydpy/models/wland/wland_sequences.py +108 -0
- hydpy/models/wland/wland_solver.py +45 -0
- hydpy/models/wland/wland_states.py +56 -0
- hydpy/models/wland_gd.py +888 -0
- hydpy/models/wland_wag.py +1244 -0
- hydpy/models/wq/__init__.py +14 -0
- hydpy/models/wq/wq_control.py +117 -0
- hydpy/models/wq/wq_derived.py +182 -0
- hydpy/models/wq/wq_factors.py +79 -0
- hydpy/models/wq/wq_fluxes.py +17 -0
- hydpy/models/wq/wq_model.py +1889 -0
- hydpy/models/wq_trapeze.py +168 -0
- hydpy/models/wq_trapeze_strickler.py +101 -0
- hydpy/models/wq_walrus.py +57 -0
- hydpy/py.typed +0 -0
- hydpy/tests/.coveragerc +22 -0
- hydpy/tests/__init__.py +0 -0
- hydpy/tests/check_consistency.py +32 -0
- hydpy/tests/hydpydoctestcustomize.pth +1 -0
- hydpy/tests/hydpydoctestcustomize.py +15 -0
- hydpy/tests/iotesting/__init__.py +0 -0
- hydpy/tests/run_doctests.py +233 -0
- hydpy-6.2.dev1.data/scripts/hyd.py +277 -0
- hydpy-6.2.dev1.dist-info/LICENSE +165 -0
- hydpy-6.2.dev1.dist-info/METADATA +163 -0
- hydpy-6.2.dev1.dist-info/RECORD +890 -0
- hydpy-6.2.dev1.dist-info/WHEEL +5 -0
- hydpy-6.2.dev1.dist-info/licenses_hydpy_installer.txt +42 -0
- hydpy-6.2.dev1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2952 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. _`issue 89`: https://github.com/hydpy-dev/hydpy/issues/89
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# imports...
|
|
6
|
+
# ...from site-packages
|
|
7
|
+
import numpy
|
|
8
|
+
|
|
9
|
+
# ...from HydPy
|
|
10
|
+
from hydpy.core import importtools
|
|
11
|
+
from hydpy.core import modeltools
|
|
12
|
+
from hydpy.core.typingtools import *
|
|
13
|
+
from hydpy.cythons import modelutils
|
|
14
|
+
from hydpy.interfaces import soilinterfaces
|
|
15
|
+
|
|
16
|
+
# ...from hland
|
|
17
|
+
from hydpy.models.ga import ga_control
|
|
18
|
+
from hydpy.models.ga import ga_derived
|
|
19
|
+
from hydpy.models.ga import ga_inputs
|
|
20
|
+
from hydpy.models.ga import ga_fluxes
|
|
21
|
+
from hydpy.models.ga import ga_states
|
|
22
|
+
from hydpy.models.ga import ga_logs
|
|
23
|
+
from hydpy.models.ga import ga_aides
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Calc_SurfaceWaterSupply_V1(modeltools.Method):
|
|
27
|
+
r"""Take rainfall as the possible supply for infiltration through the soil's
|
|
28
|
+
surface.
|
|
29
|
+
|
|
30
|
+
Basic equation:
|
|
31
|
+
:math:`SurfaceWaterSupply = Rainfall`
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
|
|
35
|
+
>>> from hydpy.models.ga import *
|
|
36
|
+
>>> parameterstep()
|
|
37
|
+
>>> nmbsoils(2)
|
|
38
|
+
>>> inputs.rainfall = 2.0
|
|
39
|
+
>>> model.calc_surfacewatersupply_v1()
|
|
40
|
+
>>> fluxes.surfacewatersupply
|
|
41
|
+
surfacewatersupply(2.0, 2.0)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
45
|
+
REQUIREDSEQUENCES = (ga_inputs.Rainfall,)
|
|
46
|
+
RESULTSEQUENCES = (ga_fluxes.SurfaceWaterSupply,)
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def __call__(model: modeltools.Model) -> None:
|
|
50
|
+
con = model.parameters.control.fastaccess
|
|
51
|
+
inp = model.sequences.inputs.fastaccess
|
|
52
|
+
flu = model.sequences.fluxes.fastaccess
|
|
53
|
+
|
|
54
|
+
for s in range(con.nmbsoils):
|
|
55
|
+
flu.surfacewatersupply[s] = inp.rainfall
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Calc_SoilWaterSupply_V1(modeltools.Method):
|
|
59
|
+
r"""Take capillary rise as the possible supply for water additions through the
|
|
60
|
+
soil's bottom.
|
|
61
|
+
|
|
62
|
+
Basic equation:
|
|
63
|
+
:math:`SoilWaterSupply = CapillaryRise`
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
|
|
67
|
+
>>> from hydpy.models.ga import *
|
|
68
|
+
>>> parameterstep()
|
|
69
|
+
>>> nmbsoils(2)
|
|
70
|
+
>>> inputs.capillaryrise = 2.0
|
|
71
|
+
>>> model.calc_soilwatersupply_v1()
|
|
72
|
+
>>> fluxes.soilwatersupply
|
|
73
|
+
soilwatersupply(2.0, 2.0)
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
77
|
+
REQUIREDSEQUENCES = (ga_inputs.CapillaryRise,)
|
|
78
|
+
RESULTSEQUENCES = (ga_fluxes.SoilWaterSupply,)
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def __call__(model: modeltools.Model) -> None:
|
|
82
|
+
con = model.parameters.control.fastaccess
|
|
83
|
+
inp = model.sequences.inputs.fastaccess
|
|
84
|
+
flu = model.sequences.fluxes.fastaccess
|
|
85
|
+
|
|
86
|
+
for s in range(con.nmbsoils):
|
|
87
|
+
flu.soilwatersupply[s] = inp.capillaryrise
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Calc_Demand_V1(modeltools.Method):
|
|
91
|
+
r"""Take evaporation as the demand for extracting water from the soil's surface and
|
|
92
|
+
body.
|
|
93
|
+
|
|
94
|
+
Basic equation:
|
|
95
|
+
:math:`Demand = Evaporation`
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
|
|
99
|
+
>>> from hydpy.models.ga import *
|
|
100
|
+
>>> parameterstep()
|
|
101
|
+
>>> nmbsoils(2)
|
|
102
|
+
>>> inputs.evaporation = 2.0
|
|
103
|
+
>>> model.calc_demand_v1()
|
|
104
|
+
>>> fluxes.demand
|
|
105
|
+
demand(2.0, 2.0)
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
109
|
+
REQUIREDSEQUENCES = (ga_inputs.Evaporation,)
|
|
110
|
+
RESULTSEQUENCES = (ga_fluxes.Demand,)
|
|
111
|
+
|
|
112
|
+
@staticmethod
|
|
113
|
+
def __call__(model: modeltools.Model) -> None:
|
|
114
|
+
con = model.parameters.control.fastaccess
|
|
115
|
+
inp = model.sequences.inputs.fastaccess
|
|
116
|
+
flu = model.sequences.fluxes.fastaccess
|
|
117
|
+
|
|
118
|
+
for s in range(con.nmbsoils):
|
|
119
|
+
flu.demand[s] = inp.evaporation
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class Return_RelativeMoisture_V1(modeltools.Method):
|
|
123
|
+
r"""Calculate and return the relative soil water content for the given bin-soil
|
|
124
|
+
combination.
|
|
125
|
+
|
|
126
|
+
Basic equation (:cite:t:`ref-Lai2015`, equation 11):
|
|
127
|
+
:math:`RelativeMoisture =
|
|
128
|
+
\frac{FrontMoisture - ResidualMoisture}{SaturationMoisture - ResidualMoisture}`
|
|
129
|
+
|
|
130
|
+
Method |Return_RelativeMoisture_V1| prevents returning values smaller than zero or
|
|
131
|
+
larger than one that might arise due to violations of the residualor saturation
|
|
132
|
+
water content.
|
|
133
|
+
|
|
134
|
+
Examples:
|
|
135
|
+
|
|
136
|
+
>>> from hydpy.models.ga import *
|
|
137
|
+
>>> simulationstep("1h")
|
|
138
|
+
>>> parameterstep("1h")
|
|
139
|
+
>>> nmbsoils(2)
|
|
140
|
+
>>> nmbbins(5)
|
|
141
|
+
>>> residualmoisture(0.1, 0.2)
|
|
142
|
+
>>> saturationmoisture(0.5, 0.8)
|
|
143
|
+
>>> states.moisture = [[0.0, 0.0],
|
|
144
|
+
... [0.1, 0.2],
|
|
145
|
+
... [0.3, 0.65],
|
|
146
|
+
... [0.5, 0.8],
|
|
147
|
+
... [1.0, 1.0]]
|
|
148
|
+
>>> from hydpy import round_
|
|
149
|
+
>>> for soil in range(2):
|
|
150
|
+
... for bin_ in range(5):
|
|
151
|
+
... print(f"soil: {soil}, bin: {bin_} -> relativemoisture ", end="")
|
|
152
|
+
... round_(model.return_relativemoisture_v1(bin_, soil))
|
|
153
|
+
soil: 0, bin: 0 -> relativemoisture 0.0
|
|
154
|
+
soil: 0, bin: 1 -> relativemoisture 0.0
|
|
155
|
+
soil: 0, bin: 2 -> relativemoisture 0.5
|
|
156
|
+
soil: 0, bin: 3 -> relativemoisture 1.0
|
|
157
|
+
soil: 0, bin: 4 -> relativemoisture 1.0
|
|
158
|
+
soil: 1, bin: 0 -> relativemoisture 0.0
|
|
159
|
+
soil: 1, bin: 1 -> relativemoisture 0.0
|
|
160
|
+
soil: 1, bin: 2 -> relativemoisture 0.75
|
|
161
|
+
soil: 1, bin: 3 -> relativemoisture 1.0
|
|
162
|
+
soil: 1, bin: 4 -> relativemoisture 1.0
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
CONTROLPARAMETERS = (ga_control.ResidualMoisture, ga_control.SaturationMoisture)
|
|
166
|
+
REQUIREDSEQUENCES = (ga_states.Moisture,)
|
|
167
|
+
|
|
168
|
+
@staticmethod
|
|
169
|
+
def __call__(model: modeltools.Model, b: int, s: int) -> float:
|
|
170
|
+
con = model.parameters.control.fastaccess
|
|
171
|
+
sta = model.sequences.states.fastaccess
|
|
172
|
+
|
|
173
|
+
moisture: float = min(sta.moisture[b, s], con.saturationmoisture[s])
|
|
174
|
+
moisture = max(moisture, con.residualmoisture[s])
|
|
175
|
+
return (moisture - con.residualmoisture[s]) / (
|
|
176
|
+
con.saturationmoisture[s] - con.residualmoisture[s]
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class Return_Conductivity_V1(modeltools.Method):
|
|
181
|
+
r"""Based on the Brooks-Corey soil moisture characteristic model
|
|
182
|
+
:cite:p:`ref-Brooks1966`, calculate and return the conductivity for the given
|
|
183
|
+
bin-soil combination.
|
|
184
|
+
|
|
185
|
+
Basic equation (:cite:t:`ref-Lai2015`, equation 11):
|
|
186
|
+
:math:`Conductivity = SaturatedConductivity \cdot
|
|
187
|
+
RelativeMoisture^{3 + 2 / PoreSizeDistribution}`
|
|
188
|
+
|
|
189
|
+
Examples:
|
|
190
|
+
|
|
191
|
+
>>> from hydpy.models.ga import *
|
|
192
|
+
>>> simulationstep("1h")
|
|
193
|
+
>>> parameterstep("1h")
|
|
194
|
+
>>> nmbsoils(2)
|
|
195
|
+
>>> nmbbins(3)
|
|
196
|
+
>>> residualmoisture(0.1, 0.2)
|
|
197
|
+
>>> saturationmoisture(0.5, 0.8)
|
|
198
|
+
>>> poresizedistribution(0.3, 0.4)
|
|
199
|
+
>>> saturatedconductivity(10.0, 20.0)
|
|
200
|
+
>>> states.moisture = [[0.1, 0.0],
|
|
201
|
+
... [0.3, 0.5],
|
|
202
|
+
... [0.5, 1.0]]
|
|
203
|
+
>>> from hydpy import round_
|
|
204
|
+
>>> for soil in range(2):
|
|
205
|
+
... for bin_ in range(3):
|
|
206
|
+
... print(f"soil: {soil}, bin: {bin_} -> conductivity ", end="")
|
|
207
|
+
... round_(model.return_conductivity_v1(bin_, soil))
|
|
208
|
+
soil: 0, bin: 0 -> conductivity 0.0
|
|
209
|
+
soil: 0, bin: 1 -> conductivity 0.012304
|
|
210
|
+
soil: 0, bin: 2 -> conductivity 10.0
|
|
211
|
+
soil: 1, bin: 0 -> conductivity 0.0
|
|
212
|
+
soil: 1, bin: 1 -> conductivity 0.078125
|
|
213
|
+
soil: 1, bin: 2 -> conductivity 20.0
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
SUBMETHODS = (Return_RelativeMoisture_V1,)
|
|
217
|
+
CONTROLPARAMETERS = (
|
|
218
|
+
ga_control.ResidualMoisture,
|
|
219
|
+
ga_control.SaturationMoisture,
|
|
220
|
+
ga_control.SaturatedConductivity,
|
|
221
|
+
ga_control.PoreSizeDistribution,
|
|
222
|
+
)
|
|
223
|
+
REQUIREDSEQUENCES = (ga_states.Moisture,)
|
|
224
|
+
|
|
225
|
+
@staticmethod
|
|
226
|
+
def __call__(model: modeltools.Model, b: int, s: int) -> float:
|
|
227
|
+
con = model.parameters.control.fastaccess
|
|
228
|
+
|
|
229
|
+
return con.saturatedconductivity[s] * (
|
|
230
|
+
model.return_relativemoisture_v1(b, s)
|
|
231
|
+
** (3.0 + 2.0 / con.poresizedistribution[s])
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class Return_CapillaryDrive_V1(modeltools.Method):
|
|
236
|
+
r"""Based on the Brooks-Corey soil moisture characteristic model
|
|
237
|
+
:cite:p:`ref-Brooks1966`, calculate and return the capillary drive between the
|
|
238
|
+
water contents of the given bins for the defined soil.
|
|
239
|
+
|
|
240
|
+
Basic equation (:cite:t:`ref-Lai2015`, equation 11):
|
|
241
|
+
:math:`CapillaryDrive_{bin1,bin2} =
|
|
242
|
+
\frac{AirEntryPotential}{3 \cdot PoreSizeDistribution + 1} \cdot
|
|
243
|
+
\begin{cases}
|
|
244
|
+
RelativeMoisture_{bin2}^{3 + 1 / PoreSizeDistribution} -
|
|
245
|
+
RelativeMoisture_{bin1}^{3 + 1 / PoreSizeDistribution}
|
|
246
|
+
&|\ Moisture_{bin2} < SaturationMoisture
|
|
247
|
+
\\
|
|
248
|
+
3 \cdot PoreSizeDistribution + 2 -
|
|
249
|
+
RelativeMoisture_{bin1}^{3 + 1 / PoreSizeDistribution}
|
|
250
|
+
&|\ Moisture_{bin2} = SaturationMoisture
|
|
251
|
+
\end{cases}`
|
|
252
|
+
|
|
253
|
+
Examples:
|
|
254
|
+
|
|
255
|
+
>>> from hydpy.models.ga import *
|
|
256
|
+
>>> simulationstep("1h")
|
|
257
|
+
>>> parameterstep("1h")
|
|
258
|
+
>>> nmbsoils(2)
|
|
259
|
+
>>> nmbbins(3)
|
|
260
|
+
>>> residualmoisture(0.1, 0.2)
|
|
261
|
+
>>> saturationmoisture(0.5, 0.8)
|
|
262
|
+
>>> airentrypotential(0.1, 0.2)
|
|
263
|
+
>>> poresizedistribution(0.3, 0.4)
|
|
264
|
+
>>> saturatedconductivity(10.0, 20.0)
|
|
265
|
+
>>> states.moisture = [[0.1, 0.0],
|
|
266
|
+
... [0.3, 0.5],
|
|
267
|
+
... [0.5, 1.0]]
|
|
268
|
+
>>> from hydpy import round_
|
|
269
|
+
>>> for soil in range(2):
|
|
270
|
+
... for bin_ in range(2):
|
|
271
|
+
... print(f"soil: {soil}, bin: {bin_} -> capillarydrive ", end="")
|
|
272
|
+
... round_(model.return_capillarydrive_v1(bin_, bin_ + 1, soil))
|
|
273
|
+
soil: 0, bin: 0 -> capillarydrive 0.000653
|
|
274
|
+
soil: 0, bin: 1 -> capillarydrive 0.151979
|
|
275
|
+
soil: 1, bin: 0 -> capillarydrive 0.002009
|
|
276
|
+
soil: 1, bin: 1 -> capillarydrive 0.2889
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
SUBMETHODS = (Return_RelativeMoisture_V1,)
|
|
280
|
+
CONTROLPARAMETERS = (
|
|
281
|
+
ga_control.ResidualMoisture,
|
|
282
|
+
ga_control.SaturationMoisture,
|
|
283
|
+
ga_control.AirEntryPotential,
|
|
284
|
+
ga_control.PoreSizeDistribution,
|
|
285
|
+
)
|
|
286
|
+
REQUIREDSEQUENCES = (ga_states.Moisture,)
|
|
287
|
+
|
|
288
|
+
@staticmethod
|
|
289
|
+
def __call__(model: modeltools.Model, b1: int, b2: int, s: int) -> float:
|
|
290
|
+
con = model.parameters.control.fastaccess
|
|
291
|
+
sta = model.sequences.states.fastaccess
|
|
292
|
+
|
|
293
|
+
exp: float = 1.0 / con.poresizedistribution[s] + 3.0
|
|
294
|
+
if sta.moisture[b2, s] < con.saturationmoisture[s]:
|
|
295
|
+
subtrahend: float = model.return_relativemoisture_v1(b2, s) ** exp
|
|
296
|
+
else:
|
|
297
|
+
subtrahend = 3.0 * con.poresizedistribution[s] + 2.0
|
|
298
|
+
return (
|
|
299
|
+
con.airentrypotential[s]
|
|
300
|
+
* (subtrahend - model.return_relativemoisture_v1(b1, s) ** exp)
|
|
301
|
+
/ (3.0 * con.poresizedistribution[s] + 1.0)
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class Percolate_FilledBin_V1(modeltools.Method):
|
|
306
|
+
r"""Calculate the percolation of water through the filled first bin due to
|
|
307
|
+
gravitational forcing.
|
|
308
|
+
|
|
309
|
+
Basic equation:
|
|
310
|
+
:math:`Percolation = DT \cdot Conductivity`
|
|
311
|
+
|
|
312
|
+
Example:
|
|
313
|
+
|
|
314
|
+
For simplicity, we make each soil compartment's first (and only) bin saturated
|
|
315
|
+
so that actual conductivity equals saturated conductivity:
|
|
316
|
+
|
|
317
|
+
>>> from hydpy.models.ga import *
|
|
318
|
+
>>> simulationstep("1h")
|
|
319
|
+
>>> parameterstep("1h")
|
|
320
|
+
>>> nmbsoils(3)
|
|
321
|
+
>>> nmbbins(2)
|
|
322
|
+
>>> dt(0.5)
|
|
323
|
+
>>> soildepth(100.0, 200.0, 300.0)
|
|
324
|
+
>>> residualmoisture(0.1)
|
|
325
|
+
>>> saturationmoisture(0.5)
|
|
326
|
+
>>> poresizedistribution(0.3)
|
|
327
|
+
>>> saturatedconductivity(6.0, 8.0, 10.0)
|
|
328
|
+
>>> states.moisture = 0.5
|
|
329
|
+
>>> aides.actualsurfacewater = 2.0, 4.0, 6.0
|
|
330
|
+
>>> fluxes.percolation = 1.0
|
|
331
|
+
>>> for soil in range(3):
|
|
332
|
+
... model.percolate_filledbin_v1(soil)
|
|
333
|
+
>>> aides.actualsurfacewater
|
|
334
|
+
actualsurfacewater(0.0, 0.0, 1.0)
|
|
335
|
+
>>> fluxes.percolation
|
|
336
|
+
percolation(3.0, 5.0, 6.0)
|
|
337
|
+
|
|
338
|
+
By the way, |Percolate_FilledBin_V1| sets the first bin's front depth to the
|
|
339
|
+
respective soil compartment's depth:
|
|
340
|
+
|
|
341
|
+
>>> states.frontdepth
|
|
342
|
+
frontdepth([[100.0, 200.0, 300.0],
|
|
343
|
+
[nan, nan, nan]])
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
SUBMETHODS = (Return_RelativeMoisture_V1, Return_Conductivity_V1)
|
|
347
|
+
CONTROLPARAMETERS = (
|
|
348
|
+
ga_control.DT,
|
|
349
|
+
ga_control.SoilDepth,
|
|
350
|
+
ga_control.ResidualMoisture,
|
|
351
|
+
ga_control.SaturationMoisture,
|
|
352
|
+
ga_control.SaturatedConductivity,
|
|
353
|
+
ga_control.PoreSizeDistribution,
|
|
354
|
+
)
|
|
355
|
+
REQUIREDSEQUENCES = (ga_states.Moisture,)
|
|
356
|
+
UPDATEDSEQUENCES = (
|
|
357
|
+
ga_states.FrontDepth,
|
|
358
|
+
ga_aides.ActualSurfaceWater,
|
|
359
|
+
ga_fluxes.Percolation,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
@staticmethod
|
|
363
|
+
def __call__(model: modeltools.Model, s: int) -> None:
|
|
364
|
+
con = model.parameters.control.fastaccess
|
|
365
|
+
flu = model.sequences.fluxes.fastaccess
|
|
366
|
+
sta = model.sequences.states.fastaccess
|
|
367
|
+
aid = model.sequences.aides.fastaccess
|
|
368
|
+
|
|
369
|
+
sta.frontdepth[0, s] = con.soildepth[s]
|
|
370
|
+
potinfiltration: float = con.dt * model.return_conductivity_v1(0, s)
|
|
371
|
+
if potinfiltration < aid.actualsurfacewater[s]:
|
|
372
|
+
aid.actualsurfacewater[s] -= potinfiltration
|
|
373
|
+
flu.percolation[s] += potinfiltration
|
|
374
|
+
else:
|
|
375
|
+
flu.percolation[s] += aid.actualsurfacewater[s]
|
|
376
|
+
aid.actualsurfacewater[s] = 0.0
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
class Return_DryDepth_V1(modeltools.Method):
|
|
380
|
+
r"""Calculate and return the "dry depth".
|
|
381
|
+
|
|
382
|
+
Basic equations (:cite:t:`ref-Lai2015`, equation 7, modified, see `issue 89`_):
|
|
383
|
+
:math:`
|
|
384
|
+
\frac{\tau + \sqrt{\tau^2 + 4 \cdot \tau \cdot EffectiveCapillarySuction}}{2}`
|
|
385
|
+
|
|
386
|
+
:math:`
|
|
387
|
+
\tau = DT \cdot \frac{SaturatedConductivity}{SaturationMoisture - FrontMoisture}`
|
|
388
|
+
|
|
389
|
+
Example:
|
|
390
|
+
|
|
391
|
+
>>> from hydpy.models.ga import *
|
|
392
|
+
>>> simulationstep("1h")
|
|
393
|
+
>>> parameterstep("1h")
|
|
394
|
+
>>> nmbsoils(3)
|
|
395
|
+
>>> nmbbins(2)
|
|
396
|
+
>>> dt(0.5)
|
|
397
|
+
>>> residualmoisture(0.1, 0.2, 0.2)
|
|
398
|
+
>>> saturationmoisture(0.5, 0.8, 0.8)
|
|
399
|
+
>>> poresizedistribution(0.3, 0.4, 0.4)
|
|
400
|
+
>>> saturatedconductivity(10.0, 20.0, 20.0)
|
|
401
|
+
>>> airentrypotential(0.1, 0.2, 0.2)
|
|
402
|
+
>>> derived.effectivecapillarysuction.update()
|
|
403
|
+
>>> states.moisture = [[0.3, 0.5, 0.8], [nan, nan, nan]]
|
|
404
|
+
>>> from hydpy import round_
|
|
405
|
+
>>> for soil in range(3):
|
|
406
|
+
... round_(model.return_drydepth_v1(soil))
|
|
407
|
+
25.151711
|
|
408
|
+
33.621747
|
|
409
|
+
inf
|
|
410
|
+
"""
|
|
411
|
+
|
|
412
|
+
CONTROLPARAMETERS = (
|
|
413
|
+
ga_control.DT,
|
|
414
|
+
ga_control.SaturationMoisture,
|
|
415
|
+
ga_control.SaturatedConductivity,
|
|
416
|
+
)
|
|
417
|
+
DERIVEDPARAMETERS = (ga_derived.EffectiveCapillarySuction,)
|
|
418
|
+
REQUIREDSEQUENCES = (ga_states.Moisture,)
|
|
419
|
+
|
|
420
|
+
@staticmethod
|
|
421
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
422
|
+
con = model.parameters.control.fastaccess
|
|
423
|
+
der = model.parameters.derived.fastaccess
|
|
424
|
+
sta = model.sequences.states.fastaccess
|
|
425
|
+
|
|
426
|
+
if sta.moisture[0, s] < con.saturationmoisture[s]:
|
|
427
|
+
tau: float = (
|
|
428
|
+
con.dt
|
|
429
|
+
* con.saturatedconductivity[s]
|
|
430
|
+
/ (con.saturationmoisture[s] - sta.moisture[0, s])
|
|
431
|
+
)
|
|
432
|
+
return 0.5 * (
|
|
433
|
+
tau + (tau**2 + 4.0 * tau * der.effectivecapillarysuction[s]) ** 0.5
|
|
434
|
+
)
|
|
435
|
+
return modelutils.inf
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
class Return_LastActiveBin_V1(modeltools.Method):
|
|
439
|
+
r"""Find the index of the last active bin (that either contains a wetting front or
|
|
440
|
+
uniform moisture over the complete soil depth).
|
|
441
|
+
|
|
442
|
+
Example:
|
|
443
|
+
|
|
444
|
+
>>> from hydpy.models.ga import *
|
|
445
|
+
>>> simulationstep("1h")
|
|
446
|
+
>>> parameterstep("1h")
|
|
447
|
+
>>> nmbsoils(3)
|
|
448
|
+
>>> nmbbins(3)
|
|
449
|
+
>>> states.moisture = [[0.1, 0.1, 0.1],
|
|
450
|
+
... [0.1, 0.5, 0.5],
|
|
451
|
+
... [0.1, 1.0, 0.1]]
|
|
452
|
+
>>> for soil in range(3):
|
|
453
|
+
... print(f"soil: {soil} -> bin: {model.return_lastactivebin_v1(soil)}")
|
|
454
|
+
soil: 0 -> bin: 0
|
|
455
|
+
soil: 1 -> bin: 2
|
|
456
|
+
soil: 2 -> bin: 1
|
|
457
|
+
"""
|
|
458
|
+
|
|
459
|
+
CONTROLPARAMETERS = (ga_control.NmbBins,)
|
|
460
|
+
REQUIREDSEQUENCES = (ga_states.Moisture,)
|
|
461
|
+
|
|
462
|
+
@staticmethod
|
|
463
|
+
def __call__(model: modeltools.Model, s: int) -> int:
|
|
464
|
+
con = model.parameters.control.fastaccess
|
|
465
|
+
sta = model.sequences.states.fastaccess
|
|
466
|
+
|
|
467
|
+
for b in range(con.nmbbins - 1, 0, -1):
|
|
468
|
+
if sta.moisture[b, s] > sta.moisture[0, s]:
|
|
469
|
+
return b
|
|
470
|
+
return 0
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
class Active_Bin_V1(modeltools.Method):
|
|
474
|
+
r"""Activate a bin to the right of the bin with the given index.
|
|
475
|
+
|
|
476
|
+
We need to activate another bin if the current last bin's moisture decreases and
|
|
477
|
+
rainfall intensity exceeds saturated conductivity.
|
|
478
|
+
|
|
479
|
+
Basic equations (related to :cite:t:`ref-Lai2015`):
|
|
480
|
+
:math:`MoistureChange_{bin+1} =
|
|
481
|
+
\frac{ActualSurfaceWater - DT \cdot 2 \cdot Conductivity_{bin}}{DryDepth}`
|
|
482
|
+
|
|
483
|
+
:math:`Moisture_{bin+1} = Moisture_{bin} + MoistureChange_{bin+1}`
|
|
484
|
+
|
|
485
|
+
:math:`Infiltration_{bin+1} = DT \cdot SaturatedConductivity \cdot
|
|
486
|
+
\left( \frac{EffectiveCapillarySuction}{DryDepth} + 1 \right)`
|
|
487
|
+
|
|
488
|
+
:math:`FrontDepth_{bin+1} = \frac{Infiltration_{bin+1}}{MoistureChange_{bin+1}}`
|
|
489
|
+
|
|
490
|
+
The calculation of infiltration and the new front depth follows equation 4 of
|
|
491
|
+
:cite:t:`ref-Lai2015`, except for using :math:`Moisture_{bin}` instead of
|
|
492
|
+
:math:`ResidualMoisture` and :math:`Moisture_{bin+1}` instead of
|
|
493
|
+
:math:`SaturationMoisture`. Regarding the moisture change, :cite:t:`ref-Lai2015`
|
|
494
|
+
does not seem to mention the given basic equation explicitly.
|
|
495
|
+
|
|
496
|
+
Examples:
|
|
497
|
+
|
|
498
|
+
Method |Active_Bin_V1| is a little complicated, so we perform multiple test
|
|
499
|
+
calculations considering different special cases. We use the following setting
|
|
500
|
+
for all these test calculations.
|
|
501
|
+
|
|
502
|
+
>>> from hydpy.models.ga_garto import *
|
|
503
|
+
>>> simulationstep("1h")
|
|
504
|
+
>>> parameterstep("1h")
|
|
505
|
+
>>> nmbsoils(1)
|
|
506
|
+
>>> nmbbins(3)
|
|
507
|
+
>>> dt(0.25)
|
|
508
|
+
>>> sealed(False)
|
|
509
|
+
>>> soilarea(1.0)
|
|
510
|
+
>>> soildepth(1000.0)
|
|
511
|
+
>>> residualmoisture(0.1)
|
|
512
|
+
>>> saturationmoisture(0.5)
|
|
513
|
+
>>> airentrypotential(0.1)
|
|
514
|
+
>>> poresizedistribution(0.3)
|
|
515
|
+
>>> saturatedconductivity(10.0)
|
|
516
|
+
>>> derived.soilareafraction.update()
|
|
517
|
+
>>> derived.effectivecapillarysuction.update()
|
|
518
|
+
|
|
519
|
+
We define a test function that applies |Active_Bin_V1| for a definable initial
|
|
520
|
+
surface water depth. The function checks that the water volume remains
|
|
521
|
+
unchanged, prints the moisture change, the resulting moisture state, and the
|
|
522
|
+
depth of the new active front (as calculated by |Active_Bin_V1|), and
|
|
523
|
+
additionally prints the related infiltration (which |Active_Bin_V1| does not
|
|
524
|
+
calculate on its own):
|
|
525
|
+
|
|
526
|
+
>>> from hydpy.core.objecttools import repr_, repr_values
|
|
527
|
+
>>> def check(actualsurfacewater):
|
|
528
|
+
... states.moisture = [[0.1], [0.3], [0.1]]
|
|
529
|
+
... states.frontdepth = [[1000.0], [500.0], [0.0]]
|
|
530
|
+
... logs.moisturechange = [[nan], [-inf], [nan]]
|
|
531
|
+
... aides.actualsurfacewater = actualsurfacewater
|
|
532
|
+
... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
533
|
+
... model.active_bin_v1(1, 0)
|
|
534
|
+
... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
535
|
+
... assert old_volume == new_volume
|
|
536
|
+
... infiltration = actualsurfacewater - aides.actualsurfacewater[0]
|
|
537
|
+
... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}")
|
|
538
|
+
... print(f"moisture: {repr_values(states.moisture[:, 0])}")
|
|
539
|
+
... print(f"infiltration: {repr_(infiltration)}")
|
|
540
|
+
... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
|
|
541
|
+
|
|
542
|
+
The first example deals with a moderate rainfall intensity (a relatively small
|
|
543
|
+
surface water depth), where everything works as described by the basic
|
|
544
|
+
equations defined above:
|
|
545
|
+
|
|
546
|
+
>>> check(actualsurfacewater=1.0)
|
|
547
|
+
moisturechange: nan, -inf, 0.155311
|
|
548
|
+
moisture: 0.1, 0.3, 0.455311
|
|
549
|
+
infiltration: 1.0
|
|
550
|
+
frontdepth: 1000.0, 500.0, 6.438686
|
|
551
|
+
|
|
552
|
+
For high rainfall intensities, the calculated moisture change could result in
|
|
553
|
+
the actual moisture exceeding the saturation moisture. In such cases,
|
|
554
|
+
|Active_Bin_V1| corrects the moisture but leaves the moisture change as is:
|
|
555
|
+
|
|
556
|
+
ToDo: clip the moisture change?
|
|
557
|
+
|
|
558
|
+
>>> check(actualsurfacewater=5.0)
|
|
559
|
+
moisturechange: nan, -inf, 0.780401
|
|
560
|
+
moisture: 0.1, 0.3, 0.5
|
|
561
|
+
infiltration: 2.55963
|
|
562
|
+
frontdepth: 1000.0, 500.0, 12.798152
|
|
563
|
+
|
|
564
|
+
A particularity of method |Active_Bin_V1| is to set the moisture change to its
|
|
565
|
+
highest possible value if the original moisture change (following the basic
|
|
566
|
+
equation) is negative. Such situations can arise when the pre-existing active
|
|
567
|
+
fronts have already infiltrated a significant amount of the rainfall available
|
|
568
|
+
for the given numerical timestep:
|
|
569
|
+
|
|
570
|
+
ToDo: set the moisture change to zero?
|
|
571
|
+
|
|
572
|
+
>>> check(actualsurfacewater=0.001)
|
|
573
|
+
moisturechange: nan, -inf, 0.2
|
|
574
|
+
moisture: 0.1, 0.3, 0.5
|
|
575
|
+
infiltration: 0.001
|
|
576
|
+
frontdepth: 1000.0, 500.0, 0.005
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
Even for zero remaining surface water, |Active_Bin_V1| activates a bin and sets
|
|
580
|
+
its moisture value to the saturation value (without calculating any
|
|
581
|
+
infiltration):
|
|
582
|
+
|
|
583
|
+
>>> check(actualsurfacewater=0.0)
|
|
584
|
+
moisturechange: nan, -inf, 0.2
|
|
585
|
+
moisture: 0.1, 0.3, 0.5
|
|
586
|
+
infiltration: 0.0
|
|
587
|
+
frontdepth: 1000.0, 500.0, 0.0
|
|
588
|
+
|
|
589
|
+
A very special case is when the initially calculated moisture change (following
|
|
590
|
+
the basic equation) is zero. Only then, |Active_Bin_V1| refrains from
|
|
591
|
+
activating another bin:
|
|
592
|
+
|
|
593
|
+
|Active_Bin_V1| checks if the initially calculated moisture change (following
|
|
594
|
+
the basic equation) is zero. Only then does it refrain from activating another
|
|
595
|
+
bin:
|
|
596
|
+
|
|
597
|
+
>>> actualsurfacewater=control.dt * 2.0 * model.return_conductivity_v1(1, 0)
|
|
598
|
+
>>> check(actualsurfacewater=actualsurfacewater)
|
|
599
|
+
moisturechange: nan, -inf, 0.0
|
|
600
|
+
moisture: 0.1, 0.3, 0.1
|
|
601
|
+
infiltration: 0.0
|
|
602
|
+
frontdepth: 1000.0, 500.0, 0.0
|
|
603
|
+
|
|
604
|
+
The following two examples illustrate highly deviating ways of front activation
|
|
605
|
+
around the "zero moisture change" case (the second example also shows that
|
|
606
|
+
infiltration becomes restricted when the front depth would otherwise overshoot
|
|
607
|
+
the soil depth):
|
|
608
|
+
|
|
609
|
+
>>> check(actualsurfacewater=actualsurfacewater-1e-5)
|
|
610
|
+
moisturechange: nan, -inf, 0.2
|
|
611
|
+
moisture: 0.1, 0.3, 0.5
|
|
612
|
+
infiltration: 0.006142
|
|
613
|
+
frontdepth: 1000.0, 500.0, 0.03071
|
|
614
|
+
|
|
615
|
+
>>> check(actualsurfacewater=actualsurfacewater+1e-5)
|
|
616
|
+
moisturechange: nan, -inf, 0.000002
|
|
617
|
+
moisture: 0.1, 0.3, 0.300002
|
|
618
|
+
infiltration: 0.001563
|
|
619
|
+
frontdepth: 1000.0, 500.0, 1000.0
|
|
620
|
+
"""
|
|
621
|
+
|
|
622
|
+
CONTROLPARAMETERS = (
|
|
623
|
+
ga_control.DT,
|
|
624
|
+
ga_control.SoilDepth,
|
|
625
|
+
ga_control.SaturationMoisture,
|
|
626
|
+
ga_control.SaturatedConductivity,
|
|
627
|
+
)
|
|
628
|
+
DERIVEDPARAMETERS = (ga_derived.EffectiveCapillarySuction,)
|
|
629
|
+
UPDATEDSEQUENCES = (
|
|
630
|
+
ga_states.Moisture,
|
|
631
|
+
ga_states.FrontDepth,
|
|
632
|
+
ga_logs.MoistureChange,
|
|
633
|
+
ga_aides.ActualSurfaceWater,
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
@staticmethod
|
|
637
|
+
def __call__(model: modeltools.Model, b: int, s: int) -> None:
|
|
638
|
+
con = model.parameters.control.fastaccess
|
|
639
|
+
der = model.parameters.derived.fastaccess
|
|
640
|
+
sta = model.sequences.states.fastaccess
|
|
641
|
+
log = model.sequences.logs.fastaccess
|
|
642
|
+
aid = model.sequences.aides.fastaccess
|
|
643
|
+
|
|
644
|
+
drydepth: float = model.return_drydepth_v1(s)
|
|
645
|
+
conductivity: float = model.return_conductivity_v1(b, s)
|
|
646
|
+
log.moisturechange[b + 1, s] = (
|
|
647
|
+
aid.actualsurfacewater[s] - con.dt * 2.0 * conductivity
|
|
648
|
+
) / drydepth
|
|
649
|
+
if log.moisturechange[b + 1, s] < 0.0:
|
|
650
|
+
log.moisturechange[b + 1, s] = (
|
|
651
|
+
con.saturationmoisture[s] - sta.moisture[b, s]
|
|
652
|
+
)
|
|
653
|
+
if log.moisturechange[b + 1, s] > 0.0:
|
|
654
|
+
sta.moisture[b + 1, s] = min(
|
|
655
|
+
sta.moisture[b, s] + log.moisturechange[b + 1, s],
|
|
656
|
+
con.saturationmoisture[s],
|
|
657
|
+
)
|
|
658
|
+
deltamoisture: float = sta.moisture[b + 1, s] - sta.moisture[b, s]
|
|
659
|
+
potinfiltration: float = min(
|
|
660
|
+
con.dt
|
|
661
|
+
* con.saturatedconductivity[s]
|
|
662
|
+
* (der.effectivecapillarysuction[s] / drydepth + 1.0),
|
|
663
|
+
con.soildepth[s] * deltamoisture,
|
|
664
|
+
)
|
|
665
|
+
if aid.actualsurfacewater[s] > potinfiltration:
|
|
666
|
+
sta.frontdepth[b + 1, s] = potinfiltration / deltamoisture
|
|
667
|
+
aid.actualsurfacewater[s] -= potinfiltration
|
|
668
|
+
else:
|
|
669
|
+
sta.frontdepth[b + 1, s] = aid.actualsurfacewater[s] / deltamoisture
|
|
670
|
+
aid.actualsurfacewater[s] = 0.0
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
class Shift_Front_V1(modeltools.Method):
|
|
674
|
+
r"""Increase the selected bin's wetting front depth without modifying its relative
|
|
675
|
+
moisture following a variation of the Talbot-Ogden equation
|
|
676
|
+
:cite:p:`ref-Talbot2008`.
|
|
677
|
+
|
|
678
|
+
Method |Shift_Front_V1| applies for active wetting front bins that are not the last
|
|
679
|
+
active bin or that are saturated (|Moisture| equals |SaturationMoisture|). The
|
|
680
|
+
latter holds only for periods with rainfall intensity exceeding saturated
|
|
681
|
+
conductivity.
|
|
682
|
+
|
|
683
|
+
Basic equation (:cite:t:`ref-Lai2015`, equation 8, modified):
|
|
684
|
+
:math:`FrontDepth_{bin, new} = FrontDepth_{bin, old} + DT \cdot
|
|
685
|
+
\frac{Conductivity_{bin-1} - Conductivity_{bin}}
|
|
686
|
+
{Moisture_{bin} - Moisture_{bin-1}} \cdot \left(1 +
|
|
687
|
+
\frac{CapillaryDrive_{0, LastActiveBin} + InitialSurfaceWater}{FrontDepth_{bin}}
|
|
688
|
+
\right)`
|
|
689
|
+
|
|
690
|
+
Note the used equation deviates from equation 8 of :cite:t:`ref-Lai2015` in adding
|
|
691
|
+
the initial surface water depth to the effective capillary drive, which increases
|
|
692
|
+
infiltration. Using |InitialSurfaceWater| instead of |ActualSurfaceWater| assures
|
|
693
|
+
the bin processing order does not affect the individual infiltration rates.
|
|
694
|
+
|
|
695
|
+
Examples:
|
|
696
|
+
|
|
697
|
+
For comparison, we perform the following examples similar to those of method
|
|
698
|
+
|Active_Bin_V1|. The general setting is identical, except that we initialise
|
|
699
|
+
one more bin:
|
|
700
|
+
|
|
701
|
+
>>> from hydpy.models.ga_garto import *
|
|
702
|
+
>>> simulationstep("1h")
|
|
703
|
+
>>> parameterstep("1h")
|
|
704
|
+
>>> nmbsoils(1)
|
|
705
|
+
>>> nmbbins(4)
|
|
706
|
+
>>> dt(0.25)
|
|
707
|
+
>>> sealed(False)
|
|
708
|
+
>>> soilarea(1.0)
|
|
709
|
+
>>> soildepth(1000.0)
|
|
710
|
+
>>> residualmoisture(0.1)
|
|
711
|
+
>>> saturationmoisture(0.5)
|
|
712
|
+
>>> airentrypotential(0.1)
|
|
713
|
+
>>> poresizedistribution(0.3)
|
|
714
|
+
>>> saturatedconductivity(10.0)
|
|
715
|
+
>>> derived.soilareafraction.update()
|
|
716
|
+
>>> derived.effectivecapillarysuction.update()
|
|
717
|
+
|
|
718
|
+
The test function also behaves similarly but allows for more modifications
|
|
719
|
+
of the initial states, supports selecting the considered bin, and applies
|
|
720
|
+
|Shift_Front_V1| instead of |Active_Bin_V1|:
|
|
721
|
+
|
|
722
|
+
>>> from hydpy.core.objecttools import repr_, repr_values
|
|
723
|
+
>>> def check(
|
|
724
|
+
... bin_, initialsurfacewater, actualsurfacewater, frontdepth, moisture
|
|
725
|
+
... ):
|
|
726
|
+
... states.moisture = [[m] for m in moisture]
|
|
727
|
+
... states.frontdepth = [[fd] for fd in frontdepth]
|
|
728
|
+
... logs.moisturechange = nan
|
|
729
|
+
... aides.initialsurfacewater = initialsurfacewater
|
|
730
|
+
... aides.actualsurfacewater = actualsurfacewater
|
|
731
|
+
... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
732
|
+
... model.shift_front_v1(bin_, 0)
|
|
733
|
+
... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
734
|
+
... assert old_volume == new_volume
|
|
735
|
+
... infiltration = actualsurfacewater - aides.actualsurfacewater[0]
|
|
736
|
+
... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}")
|
|
737
|
+
... print(f"moisture: {repr_values(states.moisture[:, 0])}")
|
|
738
|
+
... print(f"infiltration: {repr_(infiltration)}")
|
|
739
|
+
... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
|
|
740
|
+
|
|
741
|
+
|Shift_Front_V1| is to be applied on non-last active wetting front bins and the
|
|
742
|
+
last bin if it is saturated. We start with demonstrating its functionality for
|
|
743
|
+
the latter case.
|
|
744
|
+
|
|
745
|
+
The first example is standard so far that the given basic equation applies
|
|
746
|
+
without additional restrictions and initial and actual surface water depths are
|
|
747
|
+
identical. 2.75 mm of the available surface water infiltrate and shift the
|
|
748
|
+
wetting front by about 13.75 mm:
|
|
749
|
+
|
|
750
|
+
>>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=10.0,
|
|
751
|
+
... frontdepth=[1000.0, 500.0, 100.0, 0.0],
|
|
752
|
+
... moisture=[0.1, 0.3, 0.5, 0.1])
|
|
753
|
+
moisturechange: nan, nan, nan, nan
|
|
754
|
+
moisture: 0.1, 0.3, 0.5, 0.1
|
|
755
|
+
infiltration: 2.750428
|
|
756
|
+
frontdepth: 1000.0, 500.0, 113.752138, 0.0
|
|
757
|
+
|
|
758
|
+
Next, we decrease the amount of available surface water to 1 mm but let the
|
|
759
|
+
initial surface water depth at 10 mm. Thus, the potential infiltration stays
|
|
760
|
+
as is, but the actual infiltration reduces to 1 mm (and the front shift to
|
|
761
|
+
5 mm):
|
|
762
|
+
|
|
763
|
+
>>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=1.0,
|
|
764
|
+
... frontdepth=[1000.0, 500.0, 100.0, 0.0],
|
|
765
|
+
... moisture=[0.1, 0.3, 0.5, 0.1])
|
|
766
|
+
moisturechange: nan, nan, nan, nan
|
|
767
|
+
moisture: 0.1, 0.3, 0.5, 0.1
|
|
768
|
+
infiltration: 1.0
|
|
769
|
+
frontdepth: 1000.0, 500.0, 105.0, 0.0
|
|
770
|
+
|
|
771
|
+
For small or zero initial front depths, |Shift_Front_V1| uses the method
|
|
772
|
+
|Return_DryDepth_V1| to advance the front instead of the basic equation:
|
|
773
|
+
|
|
774
|
+
>>> from hydpy import round_
|
|
775
|
+
>>> round_(model.return_drydepth_v1(0))
|
|
776
|
+
6.399076
|
|
777
|
+
>>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=10.0,
|
|
778
|
+
... frontdepth=[1000.0, 500.0, 0.0, 0.0],
|
|
779
|
+
... moisture=[0.1, 0.3, 0.5, 0.1])
|
|
780
|
+
moisturechange: nan, nan, nan, nan
|
|
781
|
+
moisture: 0.1, 0.3, 0.5, 0.1
|
|
782
|
+
infiltration: 1.279815
|
|
783
|
+
frontdepth: 1000.0, 500.0, 6.399076, 0.0
|
|
784
|
+
|
|
785
|
+
|Shift_Front_V1| prevents a wetting front from overshooting the soil depth but
|
|
786
|
+
not the depth of other fronts:
|
|
787
|
+
|
|
788
|
+
>>> check(bin_=2, initialsurfacewater=10.0, actualsurfacewater=10.0,
|
|
789
|
+
... frontdepth=[1000.0, 999.0, 998.0, 0.0],
|
|
790
|
+
... moisture=[0.1, 0.3, 0.5, 0.1])
|
|
791
|
+
moisturechange: nan, nan, nan, nan
|
|
792
|
+
moisture: 0.1, 0.3, 0.5, 0.1
|
|
793
|
+
infiltration: 0.4
|
|
794
|
+
frontdepth: 1000.0, 999.0, 1000.0, 0.0
|
|
795
|
+
|
|
796
|
+
In principle, |Shift_Front_V1| works for the active, non-last bins as described
|
|
797
|
+
above:
|
|
798
|
+
|
|
799
|
+
>>> check(bin_=1, initialsurfacewater=10.0, actualsurfacewater=1.0,
|
|
800
|
+
... frontdepth=[1000.0, 300.0, 200.0, 100.0],
|
|
801
|
+
... moisture=[0.2, 0.3, 0.4, 0.5])
|
|
802
|
+
moisturechange: nan, nan, nan, nan
|
|
803
|
+
moisture: 0.2, 0.3, 0.4, 0.5
|
|
804
|
+
infiltration: 0.003176
|
|
805
|
+
frontdepth: 1000.0, 300.031762, 200.0, 100.0
|
|
806
|
+
|
|
807
|
+
However, for these bins, it also applies to rain-free periods. Then, its front
|
|
808
|
+
shifts as usual while keeping its relative moisture. As the considered bin
|
|
809
|
+
cannot (completely) take the corrensponding absolute moisture decrease from the
|
|
810
|
+
surface, it takes water from the last active bin instead, decreasing its depth
|
|
811
|
+
but not its relative moisture:
|
|
812
|
+
|
|
813
|
+
>>> check(bin_=1, initialsurfacewater=0.0, actualsurfacewater=0.0,
|
|
814
|
+
... frontdepth=[1000.0, 300.0, 200.0, 100.0],
|
|
815
|
+
... moisture=[0.2, 0.3, 0.4, 0.5])
|
|
816
|
+
moisturechange: nan, nan, nan, nan
|
|
817
|
+
moisture: 0.2, 0.3, 0.4, 0.5
|
|
818
|
+
infiltration: 0.0
|
|
819
|
+
frontdepth: 1000.0, 300.030738, 200.0, 99.969262
|
|
820
|
+
|
|
821
|
+
If the last active bin does not contain enough water, the second-last bin must
|
|
822
|
+
help out:
|
|
823
|
+
|
|
824
|
+
>>> check(bin_=1, initialsurfacewater=0.0, actualsurfacewater=0.0,
|
|
825
|
+
... frontdepth=[1000.0, 300.0, 200.0, 0.01],
|
|
826
|
+
... moisture=[0.2, 0.3, 0.4, 0.5])
|
|
827
|
+
moisturechange: nan, nan, nan, 0.0
|
|
828
|
+
moisture: 0.2, 0.3, 0.4, 0.2
|
|
829
|
+
infiltration: 0.0
|
|
830
|
+
frontdepth: 1000.0, 300.030738, 199.979262, 0.0
|
|
831
|
+
|
|
832
|
+
If all bins that possess higher relative moisture than the considered bin do
|
|
833
|
+
not contain enough water, the shift of the wetting front becomes restricted:
|
|
834
|
+
|
|
835
|
+
>>> check(bin_=1, initialsurfacewater=0.0, actualsurfacewater=0.0,
|
|
836
|
+
... frontdepth=[1000.0, 300.0, 0.02, 0.01],
|
|
837
|
+
... moisture=[0.2, 0.3, 0.4, 0.5])
|
|
838
|
+
moisturechange: nan, nan, 0.0, 0.0
|
|
839
|
+
moisture: 0.2, 0.3, 0.2, 0.2
|
|
840
|
+
infiltration: 0.0
|
|
841
|
+
frontdepth: 1000.0, 300.03, 0.0, 0.0
|
|
842
|
+
|
|
843
|
+
All examples above show that |Shift_Front_V1| never modifies |MoistureChange|,
|
|
844
|
+
except when deactivating a bin. Then, it sets the moisture change to zero.
|
|
845
|
+
"""
|
|
846
|
+
|
|
847
|
+
SUBMETHODS = (
|
|
848
|
+
Return_RelativeMoisture_V1,
|
|
849
|
+
Return_LastActiveBin_V1,
|
|
850
|
+
Return_DryDepth_V1,
|
|
851
|
+
Return_Conductivity_V1,
|
|
852
|
+
Return_CapillaryDrive_V1,
|
|
853
|
+
)
|
|
854
|
+
CONTROLPARAMETERS = (
|
|
855
|
+
ga_control.DT,
|
|
856
|
+
ga_control.NmbBins,
|
|
857
|
+
ga_control.SoilDepth,
|
|
858
|
+
ga_control.ResidualMoisture,
|
|
859
|
+
ga_control.SaturationMoisture,
|
|
860
|
+
ga_control.SaturatedConductivity,
|
|
861
|
+
ga_control.AirEntryPotential,
|
|
862
|
+
ga_control.PoreSizeDistribution,
|
|
863
|
+
)
|
|
864
|
+
DERIVEDPARAMETERS = (ga_derived.EffectiveCapillarySuction,)
|
|
865
|
+
REQUIREDSEQUENCES = (ga_aides.InitialSurfaceWater,)
|
|
866
|
+
UPDATEDSEQUENCES = (
|
|
867
|
+
ga_states.Moisture,
|
|
868
|
+
ga_states.FrontDepth,
|
|
869
|
+
ga_logs.MoistureChange,
|
|
870
|
+
ga_aides.ActualSurfaceWater,
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
@staticmethod
|
|
874
|
+
def __call__(model: modeltools.Model, b: int, s: int) -> None:
|
|
875
|
+
con = model.parameters.control.fastaccess
|
|
876
|
+
sta = model.sequences.states.fastaccess
|
|
877
|
+
aid = model.sequences.aides.fastaccess
|
|
878
|
+
log = model.sequences.logs.fastaccess
|
|
879
|
+
|
|
880
|
+
b_last = model.return_lastactivebin_v1(s)
|
|
881
|
+
drydepth: float = model.return_drydepth_v1(s)
|
|
882
|
+
if sta.frontdepth[b, s] < drydepth:
|
|
883
|
+
frontshift: float = drydepth
|
|
884
|
+
else:
|
|
885
|
+
cond1: float = model.return_conductivity_v1(b - 1, s)
|
|
886
|
+
cond2: float = model.return_conductivity_v1(b, s)
|
|
887
|
+
drive: float = model.return_capillarydrive_v1(0, b_last, s)
|
|
888
|
+
frontshift = (
|
|
889
|
+
con.dt * (cond2 - cond1) / (sta.moisture[b, s] - sta.moisture[b - 1, s])
|
|
890
|
+
) * (1.0 + (drive + aid.initialsurfacewater[s]) / sta.frontdepth[b, s])
|
|
891
|
+
frontshift = min(frontshift, con.soildepth[s] - sta.frontdepth[b, s])
|
|
892
|
+
|
|
893
|
+
deltamoisture_b: float = sta.moisture[b, s] - sta.moisture[b - 1, s]
|
|
894
|
+
required: float = frontshift * deltamoisture_b
|
|
895
|
+
if required < aid.actualsurfacewater[s]:
|
|
896
|
+
sta.frontdepth[b, s] += frontshift
|
|
897
|
+
aid.actualsurfacewater[s] -= required
|
|
898
|
+
else:
|
|
899
|
+
required -= aid.actualsurfacewater[s]
|
|
900
|
+
sta.frontdepth[b, s] += aid.actualsurfacewater[s] / deltamoisture_b
|
|
901
|
+
aid.actualsurfacewater[s] = 0.0
|
|
902
|
+
for b_last in range(b_last, b, -1):
|
|
903
|
+
deltamoisture_bb: float = (
|
|
904
|
+
sta.moisture[b_last, s] - sta.moisture[b_last - 1, s]
|
|
905
|
+
)
|
|
906
|
+
available: float = deltamoisture_bb * sta.frontdepth[b_last, s]
|
|
907
|
+
if available < required:
|
|
908
|
+
required -= available
|
|
909
|
+
sta.frontdepth[b, s] += available / deltamoisture_b
|
|
910
|
+
sta.frontdepth[b_last, s] = 0.0
|
|
911
|
+
sta.moisture[b_last, s] = sta.moisture[0, s]
|
|
912
|
+
log.moisturechange[b_last, s] = 0.0
|
|
913
|
+
else:
|
|
914
|
+
sta.frontdepth[b_last, s] -= required / deltamoisture_bb
|
|
915
|
+
sta.frontdepth[b, s] += required / deltamoisture_b
|
|
916
|
+
break
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
class Redistribute_Front_V1(modeltools.Method):
|
|
920
|
+
r"""Modify the selected bin's wetting front depth and relative moisture content
|
|
921
|
+
based on a Green & Ampt redistribution equation.
|
|
922
|
+
|
|
923
|
+
|Redistribute_Front_V1| applies for the last active wetting front bin when rainfall
|
|
924
|
+
intensity does not exceed saturated conductivity.
|
|
925
|
+
|
|
926
|
+
Basic equations (:cite:t:`ref-Lai2015`, equation 6)
|
|
927
|
+
:math:`p = \cases{1.7 &| ActualSurfaceWater = 0 \\ 1.0 &| ActualSurfaceWater > 0}`
|
|
928
|
+
|
|
929
|
+
:math:`MoistureChange_{bin} = \frac{1}{FrontDepth_{bin}} \cdot
|
|
930
|
+
\left( ActualSurfaceWater - DT \cdot \left( Conductivity_{bin} -
|
|
931
|
+
\frac{p \cdot SaturatedConductivity \cdot CapillaryDrive_{bin-1,bin}}
|
|
932
|
+
{FrontDepth_{bin}} \right) \right)`
|
|
933
|
+
|
|
934
|
+
:math:`Moisture_{bin,old} = Moisture_{bin,new} + MoistureChange_{bin}`
|
|
935
|
+
|
|
936
|
+
:math:`Infiltration_{bin} = DT \cdot SaturatedConductivity \cdot
|
|
937
|
+
\left( 1 + \frac{EffectiveCapillarySuction}{FrontDepth_{bin}} \right)`
|
|
938
|
+
|
|
939
|
+
:math:`FrontDepth_{bin,new} = \frac{Infiltration_{bin} +
|
|
940
|
+
FrontDepth_{bin,old} \cdot (Moisture_{bin,old} - Moisture_{bin-1})}
|
|
941
|
+
{Moisture_{bin,new} - Moisture_{bin-1}}`
|
|
942
|
+
|
|
943
|
+
:cite:t:`ref-Lai2015` define only the calculation of the moisture change
|
|
944
|
+
explicitly. The infiltration calculation and the corresponding shift of the
|
|
945
|
+
wetting front depth rest on the GARTO source code provided by the authors. One
|
|
946
|
+
might have expected to use :math:`Conductivity_{bin}` and
|
|
947
|
+
:math:`CapillaryDrive_{bin-1,bin}` instead of :math:`SaturatedConductivity` and
|
|
948
|
+
:math:`EffectiveCapillarySuction`. There is a remark of the authors (possibly
|
|
949
|
+
concerning the :math:`CapillaryDrive_{bin-1,bin}` vs
|
|
950
|
+
:math:`EffectiveCapillarySuction` issue only) that oscillations in infiltration
|
|
951
|
+
rates might show up otherwise. Maybe we can discuss this with the authors or
|
|
952
|
+
investigate ourselves in more detail later.
|
|
953
|
+
|
|
954
|
+
If the bin's initial front depth is zero, the basic equations for calculating
|
|
955
|
+
moisture change and infiltration become obsolete. |Redistribute_Front_V1| then
|
|
956
|
+
proceeds as follows:
|
|
957
|
+
|
|
958
|
+
:math:`MoistureChange_{bin} =
|
|
959
|
+
(ActualSurfaceWater - DT \cdot Conductivity_{bin-1}) / DryDepth`
|
|
960
|
+
|
|
961
|
+
:math:`Infiltration_{bin} = DT \cdot SaturatedConductivity \cdot
|
|
962
|
+
\left( 1 + \frac{EffectiveCapillarySuction}{DryDepth} \right)`
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
Examples:
|
|
966
|
+
|
|
967
|
+
For comparison, we perform the following examples similar to those of method
|
|
968
|
+
|Shift_Front_V1|. The general setting is identical:
|
|
969
|
+
|
|
970
|
+
>>> from hydpy.models.ga_garto import *
|
|
971
|
+
>>> simulationstep("1h")
|
|
972
|
+
>>> parameterstep("1h")
|
|
973
|
+
>>> nmbsoils(1)
|
|
974
|
+
>>> nmbbins(4)
|
|
975
|
+
>>> dt(0.25)
|
|
976
|
+
>>> sealed(False)
|
|
977
|
+
>>> soilarea(1.0)
|
|
978
|
+
>>> soildepth(1000.0)
|
|
979
|
+
>>> residualmoisture(0.1)
|
|
980
|
+
>>> saturationmoisture(0.5)
|
|
981
|
+
>>> airentrypotential(0.1)
|
|
982
|
+
>>> poresizedistribution(0.3)
|
|
983
|
+
>>> saturatedconductivity(10.0)
|
|
984
|
+
>>> derived.soilareafraction.update()
|
|
985
|
+
>>> derived.effectivecapillarysuction.update()
|
|
986
|
+
|
|
987
|
+
The test function behaves similarly. However it neglects the initial surface
|
|
988
|
+
water depth, which is not a relevant input to |Redistribute_Front_V1|, and
|
|
989
|
+
considers percolation, which |Redistribute_Front_V1| might update when
|
|
990
|
+
deactivating surface wetting fronts:
|
|
991
|
+
|
|
992
|
+
>>> from hydpy.core.objecttools import repr_, repr_values
|
|
993
|
+
>>> def check(bin_, actualsurfacewater, frontdepth, moisture):
|
|
994
|
+
... states.moisture = [[m] for m in moisture]
|
|
995
|
+
... states.frontdepth = [[fd] for fd in frontdepth]
|
|
996
|
+
... logs.moisturechange = nan
|
|
997
|
+
... aides.actualsurfacewater = actualsurfacewater
|
|
998
|
+
... fluxes.percolation[0] = 0.0
|
|
999
|
+
... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
1000
|
+
... model.redistribute_front_v1(bin_, 0)
|
|
1001
|
+
... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
1002
|
+
... assert old_volume == new_volume + fluxes.percolation[0]
|
|
1003
|
+
... infiltration = actualsurfacewater - aides.actualsurfacewater[0]
|
|
1004
|
+
... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}")
|
|
1005
|
+
... print(f"moisture: {repr_values(states.moisture[:, 0])}")
|
|
1006
|
+
... print(f"infiltration: {repr_(infiltration)}")
|
|
1007
|
+
... print(f"percolation: {repr_(fluxes.percolation[0])}")
|
|
1008
|
+
... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
|
|
1009
|
+
|
|
1010
|
+
In the first example, the given basic equations apply without modifications.
|
|
1011
|
+
Due to missing surface water, relative moisture decreases. Consequently, the
|
|
1012
|
+
front's depth increases to keep the bin's total water volume:
|
|
1013
|
+
|
|
1014
|
+
>>> check(bin_=2, actualsurfacewater=0.0,
|
|
1015
|
+
... frontdepth=[1000.0, 500.0, 100.0, 0.0],
|
|
1016
|
+
... moisture=[0.1, 0.3, 0.4, 0.1])
|
|
1017
|
+
moisturechange: nan, nan, -0.001553, nan
|
|
1018
|
+
moisture: 0.1, 0.3, 0.398447, 0.1
|
|
1019
|
+
infiltration: 0.0
|
|
1020
|
+
percolation: 0.0
|
|
1021
|
+
frontdepth: 1000.0, 500.0, 101.57736, 0.0
|
|
1022
|
+
|
|
1023
|
+
With enough available surface water, the bin's relative soil moisture
|
|
1024
|
+
increases. In the following example, this moisture increase outweighs the
|
|
1025
|
+
actual infiltration. So the front depth must must decrease to keep the
|
|
1026
|
+
absolute water volume.
|
|
1027
|
+
|
|
1028
|
+
>>> check(bin_=2, actualsurfacewater=5.0,
|
|
1029
|
+
... frontdepth=[1000.0, 500.0, 100.0, 0.0],
|
|
1030
|
+
... moisture=[0.1, 0.3, 0.4, 0.1])
|
|
1031
|
+
moisturechange: nan, nan, 0.048449, nan
|
|
1032
|
+
moisture: 0.1, 0.3, 0.448449, 0.1
|
|
1033
|
+
infiltration: 2.503816
|
|
1034
|
+
percolation: 0.0
|
|
1035
|
+
frontdepth: 1000.0, 500.0, 84.229985, 0.0
|
|
1036
|
+
|
|
1037
|
+
For zero initial front depth, |Redistribute_Front_V1| prefers the alternative
|
|
1038
|
+
equations for calculating moisture change and infiltration defined above:
|
|
1039
|
+
|
|
1040
|
+
>>> check(bin_=2, actualsurfacewater=0.5,
|
|
1041
|
+
... frontdepth=[1000.0, 500.0, 0.0, 0.0],
|
|
1042
|
+
... moisture=[0.1, 0.3, 0.4, 0.1])
|
|
1043
|
+
moisturechange: nan, nan, 0.077656, nan
|
|
1044
|
+
moisture: 0.1, 0.3, 0.477656, 0.1
|
|
1045
|
+
infiltration: 0.5
|
|
1046
|
+
percolation: 0.0
|
|
1047
|
+
frontdepth: 1000.0, 500.0, 2.814434, 0.0
|
|
1048
|
+
|
|
1049
|
+
|Redistribute_Front_V1| ensures the updated moisture content does not exceed
|
|
1050
|
+
the saturation content, even if the calculated moisture change suggests so:
|
|
1051
|
+
|
|
1052
|
+
ToDo: clip moisture change?
|
|
1053
|
+
|
|
1054
|
+
>>> check(bin_=2, actualsurfacewater=20.0,
|
|
1055
|
+
... frontdepth=[1000.0, 500.0, 100.0, 0.0],
|
|
1056
|
+
... moisture=[0.1, 0.3, 0.4, 0.1])
|
|
1057
|
+
moisturechange: nan, nan, 0.198449, nan
|
|
1058
|
+
moisture: 0.1, 0.3, 0.5, 0.1
|
|
1059
|
+
infiltration: 2.503816
|
|
1060
|
+
percolation: 0.0
|
|
1061
|
+
frontdepth: 1000.0, 500.0, 62.519079, 0.0
|
|
1062
|
+
|
|
1063
|
+
A moisture decrease that would result in falling below the moisture value of
|
|
1064
|
+
the left neighbour bin causes the deactivation of the affected bin. If the
|
|
1065
|
+
left neighbour contains an active wetting front, |Redistribute_Front_V1| adds
|
|
1066
|
+
the remaining soil water and infiltration to this bin by increasing its front
|
|
1067
|
+
depth:
|
|
1068
|
+
|
|
1069
|
+
ToDo: What if the front depth of the left neigbour bin exceeds soil depth
|
|
1070
|
+
afterwards?
|
|
1071
|
+
|
|
1072
|
+
>>> check(bin_=2, actualsurfacewater=0.001,
|
|
1073
|
+
... frontdepth=[1000.0, 500.0, 100.0, 0.0],
|
|
1074
|
+
... moisture=[0.1, 0.3, 0.30001, 0.1])
|
|
1075
|
+
moisturechange: nan, nan, 0.0, nan
|
|
1076
|
+
moisture: 0.1, 0.3, 0.1, 0.1
|
|
1077
|
+
infiltration: 0.001
|
|
1078
|
+
percolation: 0.0
|
|
1079
|
+
frontdepth: 1000.0, 500.01, 0.0, 0.0
|
|
1080
|
+
|
|
1081
|
+
If the left neighbour is the first, completely "filled" bin, the remaining soil
|
|
1082
|
+
water and infiltration increase its moisture content:
|
|
1083
|
+
|
|
1084
|
+
>>> soildepth(500.0)
|
|
1085
|
+
>>> check(bin_=1, actualsurfacewater=0.001,
|
|
1086
|
+
... frontdepth=[500.0, 100.0, 0.0, 0.0],
|
|
1087
|
+
... moisture=[0.3, 0.30001, 0.1, 0.1])
|
|
1088
|
+
moisturechange: nan, 0.0, nan, nan
|
|
1089
|
+
moisture: 0.300004, 0.300004, 0.300004, 0.300004
|
|
1090
|
+
infiltration: 0.001
|
|
1091
|
+
percolation: 0.0
|
|
1092
|
+
frontdepth: 500.0, 0.0, 0.0, 0.0
|
|
1093
|
+
|
|
1094
|
+
ToDo: In the original GARTO code, the remaining soil water and infiltration
|
|
1095
|
+
become percolation. However, when evaporation interferes with the
|
|
1096
|
+
original equations, this simplification can result in percolation rates
|
|
1097
|
+
larger than saturated conductivity. We observed this in the
|
|
1098
|
+
:ref:`ga_garto_24h_1000mm_evap_continuous` example, where percolation was
|
|
1099
|
+
20 mm/h (the rainfall rate) in the 21st hour despite a saturated
|
|
1100
|
+
conductivity of 13.2 mm/h. For our assumption, the percolation rate is
|
|
1101
|
+
12.8 mm/h. Nevertheless, we should keep this deviation from the original
|
|
1102
|
+
implementation in mind for a while; in case it brings unexpected side
|
|
1103
|
+
effects in future applications.
|
|
1104
|
+
"""
|
|
1105
|
+
|
|
1106
|
+
SUBMETHODS = (
|
|
1107
|
+
Return_RelativeMoisture_V1,
|
|
1108
|
+
Return_DryDepth_V1,
|
|
1109
|
+
Return_Conductivity_V1,
|
|
1110
|
+
Return_CapillaryDrive_V1,
|
|
1111
|
+
)
|
|
1112
|
+
CONTROLPARAMETERS = (
|
|
1113
|
+
ga_control.NmbBins,
|
|
1114
|
+
ga_control.DT,
|
|
1115
|
+
ga_control.SoilDepth,
|
|
1116
|
+
ga_control.ResidualMoisture,
|
|
1117
|
+
ga_control.SaturationMoisture,
|
|
1118
|
+
ga_control.SaturatedConductivity,
|
|
1119
|
+
ga_control.AirEntryPotential,
|
|
1120
|
+
ga_control.PoreSizeDistribution,
|
|
1121
|
+
)
|
|
1122
|
+
DERIVEDPARAMETERS = (ga_derived.EffectiveCapillarySuction,)
|
|
1123
|
+
UPDATEDSEQUENCES = (
|
|
1124
|
+
ga_states.Moisture,
|
|
1125
|
+
ga_states.FrontDepth,
|
|
1126
|
+
ga_logs.MoistureChange,
|
|
1127
|
+
ga_aides.ActualSurfaceWater,
|
|
1128
|
+
)
|
|
1129
|
+
|
|
1130
|
+
@staticmethod
|
|
1131
|
+
def __call__(model: modeltools.Model, b: int, s: int) -> None:
|
|
1132
|
+
con = model.parameters.control.fastaccess
|
|
1133
|
+
der = model.parameters.derived.fastaccess
|
|
1134
|
+
sta = model.sequences.states.fastaccess
|
|
1135
|
+
aid = model.sequences.aides.fastaccess
|
|
1136
|
+
log = model.sequences.logs.fastaccess
|
|
1137
|
+
|
|
1138
|
+
if sta.frontdepth[b, s] > 0.0:
|
|
1139
|
+
conductivity: float = model.return_conductivity_v1(b, s)
|
|
1140
|
+
capillarydrive: float = model.return_capillarydrive_v1(b - 1, b, s)
|
|
1141
|
+
factor: float = 1.0 if aid.actualsurfacewater[s] > 0.0 else 1.7
|
|
1142
|
+
log.moisturechange[b, s] = (con.dt / sta.frontdepth[b, s]) * (
|
|
1143
|
+
max(aid.actualsurfacewater[s], 0.0) / con.dt
|
|
1144
|
+
- conductivity
|
|
1145
|
+
- (factor * con.saturatedconductivity[s] * capillarydrive)
|
|
1146
|
+
/ sta.frontdepth[b, s]
|
|
1147
|
+
)
|
|
1148
|
+
potinfiltration: float = (
|
|
1149
|
+
con.dt
|
|
1150
|
+
* con.saturatedconductivity[s]
|
|
1151
|
+
* (1.0 + der.effectivecapillarysuction[s] / sta.frontdepth[b, s])
|
|
1152
|
+
)
|
|
1153
|
+
else:
|
|
1154
|
+
drydepth: float = model.return_drydepth_v1(s)
|
|
1155
|
+
conductivity = model.return_conductivity_v1(b - 1, s)
|
|
1156
|
+
log.moisturechange[b, s] = (
|
|
1157
|
+
aid.actualsurfacewater[s] - con.dt * conductivity
|
|
1158
|
+
) / drydepth
|
|
1159
|
+
potinfiltration = (
|
|
1160
|
+
con.dt
|
|
1161
|
+
* con.saturatedconductivity[s]
|
|
1162
|
+
* (1.0 + der.effectivecapillarysuction[s] / drydepth)
|
|
1163
|
+
)
|
|
1164
|
+
|
|
1165
|
+
initialcontent: float = sta.frontdepth[b, s] * (
|
|
1166
|
+
sta.moisture[b, s] - sta.moisture[b - 1, s]
|
|
1167
|
+
)
|
|
1168
|
+
|
|
1169
|
+
sta.moisture[b, s] += log.moisturechange[b, s]
|
|
1170
|
+
sta.moisture[b, s] = min(sta.moisture[b, s], con.saturationmoisture[s])
|
|
1171
|
+
sta.moisture[b, s] = max(sta.moisture[b, s], sta.moisture[b - 1, s])
|
|
1172
|
+
|
|
1173
|
+
if aid.actualsurfacewater[s] > potinfiltration:
|
|
1174
|
+
volume: float = potinfiltration + initialcontent
|
|
1175
|
+
aid.actualsurfacewater[s] -= potinfiltration
|
|
1176
|
+
else:
|
|
1177
|
+
volume = aid.actualsurfacewater[s] + initialcontent
|
|
1178
|
+
aid.actualsurfacewater[s] = 0.0
|
|
1179
|
+
|
|
1180
|
+
if sta.moisture[b, s] > sta.moisture[b - 1, s]:
|
|
1181
|
+
sta.frontdepth[b, s] = volume / (
|
|
1182
|
+
sta.moisture[b, s] - sta.moisture[b - 1, s]
|
|
1183
|
+
)
|
|
1184
|
+
else:
|
|
1185
|
+
if b > 1:
|
|
1186
|
+
sta.frontdepth[b - 1, s] += volume / (
|
|
1187
|
+
sta.moisture[b - 1, s] - sta.moisture[b - 2, s]
|
|
1188
|
+
)
|
|
1189
|
+
sta.moisture[b, s] = sta.moisture[0, s]
|
|
1190
|
+
elif b == 1:
|
|
1191
|
+
sta.moisture[0, s] += volume / con.soildepth[s]
|
|
1192
|
+
for bb in range(1, con.nmbbins):
|
|
1193
|
+
sta.moisture[bb, s] = sta.moisture[0, s]
|
|
1194
|
+
sta.frontdepth[b, s] = 0.0
|
|
1195
|
+
log.moisturechange[b, s] = 0.0
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
class Infiltrate_WettingFrontBins_V1(modeltools.Method):
|
|
1199
|
+
r"""Process infiltration into the wetting front bins.
|
|
1200
|
+
|
|
1201
|
+
|Infiltrate_WettingFrontBins_V1| does not perform any calculations itself but
|
|
1202
|
+
selects the proper submethods to do so. It either does nothing (if the filled bin
|
|
1203
|
+
is saturated) or calls |Redistribute_Front_V1|, |Shift_Front_V1|, or
|
|
1204
|
+
|Active_Bin_V1| (primarily depending on the initial surface water depth and the
|
|
1205
|
+
current moisture contents).
|
|
1206
|
+
|
|
1207
|
+
|Infiltrate_WettingFrontBins_V1| is specifically designed for |ga_garto|.
|
|
1208
|
+
|
|
1209
|
+
Examples:
|
|
1210
|
+
|
|
1211
|
+
Instead of triggering actual calculations, we try to show how
|
|
1212
|
+
|Infiltrate_WettingFrontBins_V1| selects the mentioned methods based on mocking
|
|
1213
|
+
them. Therefore, we must import the model in pure Python mode:
|
|
1214
|
+
|
|
1215
|
+
>>> from hydpy.core.importtools import reverse_model_wildcard_import
|
|
1216
|
+
>>> reverse_model_wildcard_import()
|
|
1217
|
+
>>> from hydpy import pub, print_vector
|
|
1218
|
+
>>> with pub.options.usecython(False):
|
|
1219
|
+
... from hydpy.models.ga import *
|
|
1220
|
+
... simulationstep("1h")
|
|
1221
|
+
... parameterstep("1h")
|
|
1222
|
+
|
|
1223
|
+
We define only those parameters required for selecting the proper methods:
|
|
1224
|
+
|
|
1225
|
+
>>> nmbsoils(1)
|
|
1226
|
+
>>> nmbbins(5)
|
|
1227
|
+
>>> dt(0.25)
|
|
1228
|
+
>>> saturationmoisture(0.6)
|
|
1229
|
+
>>> saturatedconductivity(10.0)
|
|
1230
|
+
|
|
1231
|
+
The following test function prepares the initial surface water depth, the
|
|
1232
|
+
(current) relative moisture, and the (previous) moisture change. Afterwards,
|
|
1233
|
+
it replaces the mentioned methods with mocks, invokes
|
|
1234
|
+
|Infiltrate_WettingFrontBins_V1|, and prints the passed arguments of all mock
|
|
1235
|
+
calls:
|
|
1236
|
+
|
|
1237
|
+
>>> from unittest.mock import patch
|
|
1238
|
+
>>> def check(initialsurfacewater, moisture, moisturechange):
|
|
1239
|
+
... states.moisture = [[m] for m in moisture]
|
|
1240
|
+
... logs.moisturechange = [[mc] for mc in moisturechange]
|
|
1241
|
+
... aides.initialsurfacewater = initialsurfacewater
|
|
1242
|
+
... with patch.object(
|
|
1243
|
+
... model, "redistribute_front_v1"
|
|
1244
|
+
... ) as redistribute_front_v1, patch.object(
|
|
1245
|
+
... model, "shift_front_v1"
|
|
1246
|
+
... ) as shift_front_v1, patch.object(
|
|
1247
|
+
... model, "active_bin_v1"
|
|
1248
|
+
... ) as active_bin_v1:
|
|
1249
|
+
... model.infiltrate_wettingfrontbins_v1(0)
|
|
1250
|
+
... for mock in (shift_front_v1, redistribute_front_v1, active_bin_v1):
|
|
1251
|
+
... if mock.called:
|
|
1252
|
+
... print(mock._extract_mock_name(), end=": ")
|
|
1253
|
+
... print_vector([str(call)[4:] for call in mock.mock_calls])
|
|
1254
|
+
|
|
1255
|
+
If the first (filled) bin is saturated, |Infiltrate_WettingFrontBins_V1| does
|
|
1256
|
+
nothing:
|
|
1257
|
+
|
|
1258
|
+
>>> check(initialsurfacewater=20.0,
|
|
1259
|
+
... moisture=[0.6, 0.6, 0.6, 0.6, 0.6],
|
|
1260
|
+
... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0])
|
|
1261
|
+
|
|
1262
|
+
If a wetting front bin is saturated, |Infiltrate_WettingFrontBins_V1| calls
|
|
1263
|
+
either |Shift_Front_V1| or |Redistribute_Front_V1|, depending on whether
|
|
1264
|
+
the surface water depth (rainfall intensity) exceeds saturated conductivity or
|
|
1265
|
+
not:
|
|
1266
|
+
|
|
1267
|
+
>>> check(initialsurfacewater=20.0,
|
|
1268
|
+
... moisture=[0.1, 0.6, 0.6, 0.6, 0.6],
|
|
1269
|
+
... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0])
|
|
1270
|
+
shift_front_v1: (1, 0)
|
|
1271
|
+
|
|
1272
|
+
>>> check(initialsurfacewater=2.0,
|
|
1273
|
+
... moisture=[0.1, 0.6, 0.6, 0.6, 0.6],
|
|
1274
|
+
... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0])
|
|
1275
|
+
redistribute_front_v1: (1, 0)
|
|
1276
|
+
|
|
1277
|
+
If all bins are active, |Infiltrate_WettingFrontBins_V1| calls |Shift_Front_V1|
|
|
1278
|
+
for all bins except for the last one, for which it calls
|
|
1279
|
+
|Redistribute_Front_V1|:
|
|
1280
|
+
|
|
1281
|
+
>>> check(initialsurfacewater=2.0,
|
|
1282
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.5],
|
|
1283
|
+
... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0])
|
|
1284
|
+
shift_front_v1: (1, 0), (2, 0), (3, 0)
|
|
1285
|
+
redistribute_front_v1: (4, 0)
|
|
1286
|
+
|
|
1287
|
+
If there is at least one inactivated bin and the last active bin is not
|
|
1288
|
+
saturated, |Infiltrate_WettingFrontBins_V1| either calls |Active_Bin_V1| to
|
|
1289
|
+
activate a new bin right to it or calls |Redistribute_Front_V1|, depending on
|
|
1290
|
+
whether rainfall intensity exceeds saturated conductivity and the active bin's
|
|
1291
|
+
relative moisture decreased previously or not:
|
|
1292
|
+
|
|
1293
|
+
>>> check(initialsurfacewater=20.0,
|
|
1294
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.1],
|
|
1295
|
+
... moisturechange=[0.0, 0.0, 0.0, -1.0, 0.0])
|
|
1296
|
+
shift_front_v1: (1, 0), (2, 0)
|
|
1297
|
+
active_bin_v1: (3, 0)
|
|
1298
|
+
|
|
1299
|
+
>>> check(initialsurfacewater=2.0,
|
|
1300
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.1],
|
|
1301
|
+
... moisturechange=[0.0, 0.0, 0.0, -1.0, 0.0])
|
|
1302
|
+
shift_front_v1: (1, 0), (2, 0)
|
|
1303
|
+
redistribute_front_v1: (3, 0)
|
|
1304
|
+
|
|
1305
|
+
>>> check(initialsurfacewater=20.0,
|
|
1306
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.1],
|
|
1307
|
+
... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0])
|
|
1308
|
+
shift_front_v1: (1, 0), (2, 0)
|
|
1309
|
+
redistribute_front_v1: (3, 0)
|
|
1310
|
+
|
|
1311
|
+
>>> check(initialsurfacewater=2.0,
|
|
1312
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.1],
|
|
1313
|
+
... moisturechange=[0.0, 0.0, 0.0, 0.0, 0.0])
|
|
1314
|
+
shift_front_v1: (1, 0), (2, 0)
|
|
1315
|
+
redistribute_front_v1: (3, 0)
|
|
1316
|
+
|
|
1317
|
+
>>> reverse_model_wildcard_import()
|
|
1318
|
+
"""
|
|
1319
|
+
|
|
1320
|
+
SUBMETHODS = (
|
|
1321
|
+
Return_RelativeMoisture_V1,
|
|
1322
|
+
Return_DryDepth_V1,
|
|
1323
|
+
Return_Conductivity_V1,
|
|
1324
|
+
Return_CapillaryDrive_V1,
|
|
1325
|
+
Active_Bin_V1,
|
|
1326
|
+
Shift_Front_V1,
|
|
1327
|
+
Redistribute_Front_V1,
|
|
1328
|
+
)
|
|
1329
|
+
CONTROLPARAMETERS = (
|
|
1330
|
+
ga_control.NmbBins,
|
|
1331
|
+
ga_control.DT,
|
|
1332
|
+
ga_control.SoilDepth,
|
|
1333
|
+
ga_control.ResidualMoisture,
|
|
1334
|
+
ga_control.SaturationMoisture,
|
|
1335
|
+
ga_control.SaturatedConductivity,
|
|
1336
|
+
ga_control.AirEntryPotential,
|
|
1337
|
+
ga_control.PoreSizeDistribution,
|
|
1338
|
+
)
|
|
1339
|
+
DERIVEDPARAMETERS = (ga_derived.EffectiveCapillarySuction,)
|
|
1340
|
+
REQUIREDSEQUENCES = (ga_aides.InitialSurfaceWater,)
|
|
1341
|
+
UPDATEDSEQUENCES = (
|
|
1342
|
+
ga_states.Moisture,
|
|
1343
|
+
ga_states.FrontDepth,
|
|
1344
|
+
ga_logs.MoistureChange,
|
|
1345
|
+
ga_aides.ActualSurfaceWater,
|
|
1346
|
+
)
|
|
1347
|
+
|
|
1348
|
+
@staticmethod
|
|
1349
|
+
def __call__(model: modeltools.Model, s: int) -> None:
|
|
1350
|
+
con = model.parameters.control.fastaccess
|
|
1351
|
+
sta = model.sequences.states.fastaccess
|
|
1352
|
+
log = model.sequences.logs.fastaccess
|
|
1353
|
+
aid = model.sequences.aides.fastaccess
|
|
1354
|
+
for b in range(1, con.nmbbins):
|
|
1355
|
+
if sta.moisture[0, s] >= con.saturationmoisture[s]:
|
|
1356
|
+
break
|
|
1357
|
+
if sta.moisture[b, s] >= con.saturationmoisture[s]:
|
|
1358
|
+
if aid.initialsurfacewater[s] < con.dt * con.saturatedconductivity[s]:
|
|
1359
|
+
model.redistribute_front_v1(b, s)
|
|
1360
|
+
else:
|
|
1361
|
+
model.shift_front_v1(b, s)
|
|
1362
|
+
break
|
|
1363
|
+
if b == con.nmbbins - 1:
|
|
1364
|
+
model.redistribute_front_v1(b, s)
|
|
1365
|
+
break
|
|
1366
|
+
if sta.moisture[0, s] < sta.moisture[b, s] < sta.moisture[b + 1, s]:
|
|
1367
|
+
log.moisturechange[b, s] = 0.0
|
|
1368
|
+
model.shift_front_v1(b, s)
|
|
1369
|
+
elif (
|
|
1370
|
+
(aid.initialsurfacewater[s] > con.dt * con.saturatedconductivity[s])
|
|
1371
|
+
and (log.moisturechange[b, s] < 0.0)
|
|
1372
|
+
and (sta.moisture[b, s] > sta.moisture[0, s])
|
|
1373
|
+
):
|
|
1374
|
+
model.active_bin_v1(b, s)
|
|
1375
|
+
break
|
|
1376
|
+
else:
|
|
1377
|
+
model.redistribute_front_v1(b, s)
|
|
1378
|
+
break
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
class Merge_FrontDepthOvershootings_V1(modeltools.Method):
|
|
1382
|
+
r"""Merge those neighbour bins where the wetting front's depth of the right
|
|
1383
|
+
neighbour exceeds the wetting front's depth of the left neighbour.
|
|
1384
|
+
|
|
1385
|
+
Examples:
|
|
1386
|
+
|
|
1387
|
+
For comparison, we perform the following examples similar to those of method
|
|
1388
|
+
|Active_Bin_V1|. However, in contrast to |Active_Bin_V1|,
|
|
1389
|
+
|Merge_FrontDepthOvershootings_V1| only needs to know the number of available
|
|
1390
|
+
bins and their current states only, making the general set-up much shorter:
|
|
1391
|
+
|
|
1392
|
+
>>> from hydpy.models.ga_garto import *
|
|
1393
|
+
>>> parameterstep()
|
|
1394
|
+
>>> nmbsoils(1)
|
|
1395
|
+
>>> nmbbins(5)
|
|
1396
|
+
>>> sealed(False)
|
|
1397
|
+
>>> soilarea(1.0)
|
|
1398
|
+
>>> soildepth(1000.0)
|
|
1399
|
+
>>> derived.soilareafraction.update()
|
|
1400
|
+
|
|
1401
|
+
Instead of accepting different values for the actual surface water depth, the
|
|
1402
|
+
test function here allows defining the respective front's depth, moisture and
|
|
1403
|
+
moisture change:
|
|
1404
|
+
|
|
1405
|
+
>>> from hydpy.core.objecttools import repr_, repr_values
|
|
1406
|
+
>>> def check(frontdepth, moisture, moisturechange):
|
|
1407
|
+
... states.frontdepth = [[fd] for fd in frontdepth]
|
|
1408
|
+
... states.moisture = [[m] for m in moisture]
|
|
1409
|
+
... logs.moisturechange = [[mc] for mc in moisturechange]
|
|
1410
|
+
... old_volume = round(model.watercontent, 12)
|
|
1411
|
+
... model.merge_frontdepthovershootings_v1(0)
|
|
1412
|
+
... new_volume = round(model.watercontent, 12)
|
|
1413
|
+
... assert old_volume == new_volume
|
|
1414
|
+
... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
|
|
1415
|
+
... print(f"moisture: {repr_values(states.moisture[:, 0])}")
|
|
1416
|
+
... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}")
|
|
1417
|
+
|
|
1418
|
+
Nothing happens as long as all bins have smaller front depths than their left
|
|
1419
|
+
neighbours. Note that |Merge_FrontDepthOvershootings_V1| also becomes active
|
|
1420
|
+
only if relative moisture increases from left to right. Hence, in the
|
|
1421
|
+
following example, there is no merging of the two inactive bins, which (as
|
|
1422
|
+
usual) both have zero front depths:
|
|
1423
|
+
|
|
1424
|
+
>>> check(frontdepth=[1000.0, 500.0, 100.0, 0.0, 0.0],
|
|
1425
|
+
... moisture=[0.1, 0.3, 0.5, 0.1, 0.1],
|
|
1426
|
+
... moisturechange=[0.2, 0.4, 0.6, 0.0, 0.0])
|
|
1427
|
+
frontdepth: 1000.0, 500.0, 100.0, 0.0, 0.0
|
|
1428
|
+
moisture: 0.1, 0.3, 0.5, 0.1, 0.1
|
|
1429
|
+
moisturechange: 0.2, 0.4, 0.6, 0.0, 0.0
|
|
1430
|
+
|
|
1431
|
+
For equal depths, |Merge_FrontDepthOvershootings_V1| deactivates the left
|
|
1432
|
+
neighbour bin and sets the moisture change of the left neighbour to zero:
|
|
1433
|
+
|
|
1434
|
+
>>> check(frontdepth=[1000.0, 500.0, 500.0, 0.0, 0.0],
|
|
1435
|
+
... moisture=[0.1, 0.3, 0.5, 0.1, 0.1],
|
|
1436
|
+
... moisturechange=[0.2, 0.4, 0.6, 0.0, 0.0])
|
|
1437
|
+
frontdepth: 1000.0, 500.0, 0.0, 0.0, 0.0
|
|
1438
|
+
moisture: 0.1, 0.5, 0.1, 0.1, 0.1
|
|
1439
|
+
moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
|
|
1440
|
+
|
|
1441
|
+
In case of an overshooting, |Merge_FrontDepthOvershootings_V1| must add the
|
|
1442
|
+
(additional) water content of the (deactivated) right neighbour to the
|
|
1443
|
+
(preserved) left neighbour:
|
|
1444
|
+
|
|
1445
|
+
>>> check(frontdepth=[1000.0, 500.0, 600.0, 0.0, 0.0],
|
|
1446
|
+
... moisture=[0.1, 0.3, 0.5, 0.1, 0.1],
|
|
1447
|
+
... moisturechange=[0.2, 0.4, 0.6, 0.0, 0.0])
|
|
1448
|
+
frontdepth: 1000.0, 550.0, 0.0, 0.0, 0.0
|
|
1449
|
+
moisture: 0.1, 0.5, 0.1, 0.1, 0.1
|
|
1450
|
+
moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
|
|
1451
|
+
|
|
1452
|
+
All right neighbours of a deactivated bin move (at least) one place to the
|
|
1453
|
+
left:
|
|
1454
|
+
|
|
1455
|
+
>>> check(frontdepth=[1000.0, 500.0, 600.0, 400.0, 0.0],
|
|
1456
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.1],
|
|
1457
|
+
... moisturechange=[0.2, 0.4, 0.6, 0.8, 0.0])
|
|
1458
|
+
frontdepth: 1000.0, 550.0, 400.0, 0.0, 0.0
|
|
1459
|
+
moisture: 0.1, 0.3, 0.4, 0.1, 0.1
|
|
1460
|
+
moisturechange: 0.2, 0.0, 0.8, 0.0, 0.0
|
|
1461
|
+
|
|
1462
|
+
If the last bin is active, it gets properly deactivated:
|
|
1463
|
+
|
|
1464
|
+
>>> check(frontdepth=[1000.0, 500.0, 600.0, 400.0, 300.0],
|
|
1465
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.5],
|
|
1466
|
+
... moisturechange=[0.2, 0.4, 0.6, 0.8, 1.0])
|
|
1467
|
+
frontdepth: 1000.0, 550.0, 400.0, 300.0, 0.0
|
|
1468
|
+
moisture: 0.1, 0.3, 0.4, 0.5, 0.1
|
|
1469
|
+
moisturechange: 0.2, 0.0, 0.8, 1.0, 0.0
|
|
1470
|
+
|
|
1471
|
+
The two last examples demonstrate that the underlying algorithm works stably in
|
|
1472
|
+
case multiple mergings are necessary:
|
|
1473
|
+
|
|
1474
|
+
>>> check(frontdepth=[1000.0, 500.0, 600.0, 700.0, 0.0],
|
|
1475
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.1],
|
|
1476
|
+
... moisturechange=[0.2, 0.4, 0.6, 0.8, 0.0])
|
|
1477
|
+
frontdepth: 1000.0, 600.0, 0.0, 0.0, 0.0
|
|
1478
|
+
moisture: 0.1, 0.4, 0.1, 0.1, 0.1
|
|
1479
|
+
moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
|
|
1480
|
+
|
|
1481
|
+
>>> check(frontdepth=[1000.0, 500.0, 600.0, 400.0, 500.0],
|
|
1482
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.5],
|
|
1483
|
+
... moisturechange=[0.2, 0.4, 0.6, 0.8, 1.0])
|
|
1484
|
+
frontdepth: 1000.0, 550.0, 450.0, 0.0, 0.0
|
|
1485
|
+
moisture: 0.1, 0.3, 0.5, 0.1, 0.1
|
|
1486
|
+
moisturechange: 0.2, 0.0, 0.0, 0.0, 0.0
|
|
1487
|
+
"""
|
|
1488
|
+
|
|
1489
|
+
CONTROLPARAMETERS = (ga_control.NmbBins,)
|
|
1490
|
+
UPDATEDSEQUENCES = (
|
|
1491
|
+
ga_states.Moisture,
|
|
1492
|
+
ga_states.FrontDepth,
|
|
1493
|
+
ga_logs.MoistureChange,
|
|
1494
|
+
)
|
|
1495
|
+
|
|
1496
|
+
@staticmethod
|
|
1497
|
+
def __call__(model: modeltools.Model, s: int) -> None:
|
|
1498
|
+
con = model.parameters.control.fastaccess
|
|
1499
|
+
sta = model.sequences.states.fastaccess
|
|
1500
|
+
log = model.sequences.logs.fastaccess
|
|
1501
|
+
b = con.nmbbins - 1
|
|
1502
|
+
while b > 1:
|
|
1503
|
+
if (sta.frontdepth[b, s] >= sta.frontdepth[b - 1, s]) and (
|
|
1504
|
+
sta.moisture[b, s] > sta.moisture[b - 1, s]
|
|
1505
|
+
):
|
|
1506
|
+
content_thisbin: float = sta.frontdepth[b, s] * (
|
|
1507
|
+
sta.moisture[b, s] - sta.moisture[b - 1, s]
|
|
1508
|
+
)
|
|
1509
|
+
content_lastbin: float = sta.frontdepth[b - 1, s] * (
|
|
1510
|
+
sta.moisture[b - 1, s] - sta.moisture[b - 2, s]
|
|
1511
|
+
)
|
|
1512
|
+
sta.frontdepth[b - 1, s] = (content_thisbin + content_lastbin) / (
|
|
1513
|
+
sta.moisture[b, s] - sta.moisture[b - 2, s]
|
|
1514
|
+
)
|
|
1515
|
+
sta.moisture[b - 1, s] = sta.moisture[b, s]
|
|
1516
|
+
sta.frontdepth[b, s] = 0.0
|
|
1517
|
+
sta.moisture[b, s] = sta.moisture[0, s]
|
|
1518
|
+
log.moisturechange[b - 1, s] = 0.0
|
|
1519
|
+
log.moisturechange[b, s] = 0.0
|
|
1520
|
+
for bb in range(b + 1, con.nmbbins):
|
|
1521
|
+
if sta.moisture[bb, s] > sta.moisture[0, s]:
|
|
1522
|
+
sta.moisture[bb - 1, s] = sta.moisture[bb, s]
|
|
1523
|
+
sta.moisture[bb, s] = sta.moisture[0, s]
|
|
1524
|
+
sta.frontdepth[bb - 1, s] = sta.frontdepth[bb, s]
|
|
1525
|
+
sta.frontdepth[bb, s] = 0.0
|
|
1526
|
+
log.moisturechange[bb - 1, s] = log.moisturechange[bb, s]
|
|
1527
|
+
log.moisturechange[bb, s] = 0.0
|
|
1528
|
+
b += 1
|
|
1529
|
+
b -= 1
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
class Merge_SoilDepthOvershootings_V1(modeltools.Method):
|
|
1533
|
+
r"""Merge bins with wetting front depth larger than soil depth with their
|
|
1534
|
+
left neighbour bins and add their water excess to percolation.
|
|
1535
|
+
|
|
1536
|
+
|Merge_SoilDepthOvershootings_V1| assumes proper sorting of wetting front depths
|
|
1537
|
+
(decreasing from left to right), as ensured by |Merge_FrontDepthOvershootings_V1|.
|
|
1538
|
+
|
|
1539
|
+
Examples:
|
|
1540
|
+
|
|
1541
|
+
For comparison, we perform the following examples similar to those of the
|
|
1542
|
+
related method |Merge_FrontDepthOvershootings_V1|. The general setting is
|
|
1543
|
+
identical:
|
|
1544
|
+
|
|
1545
|
+
>>> from hydpy.models.ga_garto import *
|
|
1546
|
+
>>> parameterstep()
|
|
1547
|
+
>>> nmbsoils(1)
|
|
1548
|
+
>>> nmbbins(5)
|
|
1549
|
+
>>> sealed(False)
|
|
1550
|
+
>>> soilarea(1.0)
|
|
1551
|
+
>>> soildepth(1000.0)
|
|
1552
|
+
>>> derived.soilareafraction.update()
|
|
1553
|
+
|
|
1554
|
+
The test function is similar but must also consider percolation:
|
|
1555
|
+
|
|
1556
|
+
>>> from hydpy.core.objecttools import repr_, repr_values
|
|
1557
|
+
>>> def check(frontdepth, moisture, moisturechange):
|
|
1558
|
+
... states.frontdepth = [[fd] for fd in frontdepth]
|
|
1559
|
+
... states.moisture = [[m] for m in moisture]
|
|
1560
|
+
... logs.moisturechange = [[mc] for mc in moisturechange]
|
|
1561
|
+
... fluxes.percolation = 0.0
|
|
1562
|
+
... old_volume = round(model.watercontent, 12)
|
|
1563
|
+
... model.merge_soildepthovershootings_v1(0)
|
|
1564
|
+
... new_volume = round(model.watercontent + fluxes.percolation[0], 12)
|
|
1565
|
+
... assert old_volume == new_volume
|
|
1566
|
+
... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
|
|
1567
|
+
... print(f"moisture: {repr_values(states.moisture[:, 0])}")
|
|
1568
|
+
... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}")
|
|
1569
|
+
... print(f"percolation: {repr_(fluxes.percolation[0])}")
|
|
1570
|
+
|
|
1571
|
+
Nothing happens as long as all bins have smaller front depths than their left
|
|
1572
|
+
neighbours. Note that |Merge_SoilDepthOvershootings_V1| also becomes active
|
|
1573
|
+
only if relative moisture increases from left to right. Hence, in the
|
|
1574
|
+
following example, there is no merging of the two inactive bins, which (as
|
|
1575
|
+
usual) both have zero front depths:
|
|
1576
|
+
|
|
1577
|
+
>>> check(frontdepth=[1000.0, 900.0, 800.0, 0.0, 0.0],
|
|
1578
|
+
... moisture=[0.1, 0.2, 0.3, 0.1, 0.1],
|
|
1579
|
+
... moisturechange=[0.0, 1.0, 2.0, 0.0, 0.0])
|
|
1580
|
+
frontdepth: 1000.0, 900.0, 800.0, 0.0, 0.0
|
|
1581
|
+
moisture: 0.1, 0.2, 0.3, 0.1, 0.1
|
|
1582
|
+
moisturechange: 0.0, 1.0, 2.0, 0.0, 0.0
|
|
1583
|
+
percolation: 0.0
|
|
1584
|
+
|
|
1585
|
+
If a single front's depth reaches the soil bottom exactly,
|
|
1586
|
+
|Merge_SoilDepthOvershootings_V1| deactivates the affected bin and takes its
|
|
1587
|
+
relative moisture value as the new initial moisture:
|
|
1588
|
+
|
|
1589
|
+
>>> check(frontdepth=[1000.0, 1000.0, 0.0, 0.0, 0.0],
|
|
1590
|
+
... moisture=[0.1, 0.2, 0.1, 0.1, 0.1],
|
|
1591
|
+
... moisturechange=[0.0, 1.0, 0.0, 0.0, 0.0])
|
|
1592
|
+
frontdepth: 1000.0, 0.0, 0.0, 0.0, 0.0
|
|
1593
|
+
moisture: 0.2, 0.2, 0.2, 0.2, 0.2
|
|
1594
|
+
moisturechange: 0.0, 0.0, 0.0, 0.0, 0.0
|
|
1595
|
+
percolation: 0.0
|
|
1596
|
+
|
|
1597
|
+
Parts of the front lying below the soil's bottom become percolation:
|
|
1598
|
+
|
|
1599
|
+
>>> check(frontdepth=[1000.0, 1100.0, 0.0, 0.0, 0.0],
|
|
1600
|
+
... moisture=[0.1, 0.2, 0.1, 0.1, 0.1],
|
|
1601
|
+
... moisturechange=[0.0, 1.0, 0.0, 0.0, 0.0])
|
|
1602
|
+
frontdepth: 1000.0, 0.0, 0.0, 0.0, 0.0
|
|
1603
|
+
moisture: 0.2, 0.2, 0.2, 0.2, 0.2
|
|
1604
|
+
moisturechange: 0.0, 0.0, 0.0, 0.0, 0.0
|
|
1605
|
+
percolation: 10.0
|
|
1606
|
+
|
|
1607
|
+
All remaining active wetting front bins move (at least) one place to the left:
|
|
1608
|
+
|
|
1609
|
+
>>> check(frontdepth=[1000.0, 1100.0, 800.0, 700.0, 600.0],
|
|
1610
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.5],
|
|
1611
|
+
... moisturechange=[0.0, 1.0, 2.0, 3.0, 4.0])
|
|
1612
|
+
frontdepth: 1000.0, 800.0, 700.0, 600.0, 0.0
|
|
1613
|
+
moisture: 0.2, 0.3, 0.4, 0.5, 0.2
|
|
1614
|
+
moisturechange: 0.0, 2.0, 3.0, 4.0, 0.0
|
|
1615
|
+
percolation: 10.0
|
|
1616
|
+
|
|
1617
|
+
The two last examples demonstrate that the underlying algorithm works stably in
|
|
1618
|
+
case multiple mergings are necessary:
|
|
1619
|
+
|
|
1620
|
+
>>> check(frontdepth=[1000.0, 1200.0, 1100.0, 700.0, 0.0],
|
|
1621
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.1],
|
|
1622
|
+
... moisturechange=[0.0, 1.0, 2.0, 3.0, 0.0])
|
|
1623
|
+
frontdepth: 1000.0, 700.0, 0.0, 0.0, 0.0
|
|
1624
|
+
moisture: 0.3, 0.4, 0.3, 0.3, 0.3
|
|
1625
|
+
moisturechange: 0.0, 3.0, 0.0, 0.0, 0.0
|
|
1626
|
+
percolation: 30.0
|
|
1627
|
+
|
|
1628
|
+
>>> check(frontdepth=[1000.0, 1200.0, 1200.0, 1100.0, 1100.0],
|
|
1629
|
+
... moisture=[0.1, 0.2, 0.3, 0.4, 0.5],
|
|
1630
|
+
... moisturechange=[0.0, 1.0, 2.0, 3.0, 4.0])
|
|
1631
|
+
frontdepth: 1000.0, 0.0, 0.0, 0.0, 0.0
|
|
1632
|
+
moisture: 0.5, 0.5, 0.5, 0.5, 0.5
|
|
1633
|
+
moisturechange: 0.0, 0.0, 0.0, 0.0, 0.0
|
|
1634
|
+
percolation: 60.0
|
|
1635
|
+
"""
|
|
1636
|
+
|
|
1637
|
+
CONTROLPARAMETERS = (ga_control.NmbBins, ga_control.SoilDepth)
|
|
1638
|
+
UPDATEDSEQUENCES = (
|
|
1639
|
+
ga_states.FrontDepth,
|
|
1640
|
+
ga_states.Moisture,
|
|
1641
|
+
ga_logs.MoistureChange,
|
|
1642
|
+
ga_fluxes.Percolation,
|
|
1643
|
+
)
|
|
1644
|
+
|
|
1645
|
+
@staticmethod
|
|
1646
|
+
def __call__(model: modeltools.Model, s: int) -> None:
|
|
1647
|
+
con = model.parameters.control.fastaccess
|
|
1648
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1649
|
+
sta = model.sequences.states.fastaccess
|
|
1650
|
+
log = model.sequences.logs.fastaccess
|
|
1651
|
+
|
|
1652
|
+
while (sta.frontdepth[1, s] >= con.soildepth[s]) and (
|
|
1653
|
+
sta.moisture[1, s] > sta.moisture[0, s]
|
|
1654
|
+
):
|
|
1655
|
+
flu.percolation[s] += (sta.frontdepth[1, s] - con.soildepth[s]) * (
|
|
1656
|
+
sta.moisture[1, s] - sta.moisture[0, s]
|
|
1657
|
+
)
|
|
1658
|
+
sta.frontdepth[1, s] = 0.0
|
|
1659
|
+
log.moisturechange[1, s] = 0.0
|
|
1660
|
+
sta.moisture[0, s] = sta.moisture[1, s]
|
|
1661
|
+
for b in range(2, con.nmbbins):
|
|
1662
|
+
if sta.moisture[b, s] > sta.moisture[0, s]:
|
|
1663
|
+
sta.frontdepth[b - 1, s] = sta.frontdepth[b, s]
|
|
1664
|
+
log.moisturechange[b - 1, s] = log.moisturechange[b, s]
|
|
1665
|
+
sta.moisture[b - 1, s] = sta.moisture[b, s]
|
|
1666
|
+
sta.frontdepth[b, s] = 0.0
|
|
1667
|
+
log.moisturechange[b, s] = 0.0
|
|
1668
|
+
sta.moisture[b, s] = sta.moisture[0, s]
|
|
1669
|
+
|
|
1670
|
+
|
|
1671
|
+
class Water_AllBins_V1(modeltools.Method):
|
|
1672
|
+
r"""Water the soil's body by (potentially) adding water to all active bins.
|
|
1673
|
+
|
|
1674
|
+
The soil water addition calculated by |Water_AllBins_V1| equals the defined soil
|
|
1675
|
+
water supply, except adding the complete supply would exceed the saturation water
|
|
1676
|
+
content.
|
|
1677
|
+
|
|
1678
|
+
Note that the caller needs to pass the supply as a method parameter, which allows
|
|
1679
|
+
him to decide whether to add everything in one simulation step or multiple
|
|
1680
|
+
numerical substeps.
|
|
1681
|
+
|
|
1682
|
+
Examples:
|
|
1683
|
+
|
|
1684
|
+
We prepare a single shallow soil compartment divided into four bins:
|
|
1685
|
+
|
|
1686
|
+
>>> from hydpy.models.ga_garto import *
|
|
1687
|
+
>>> simulationstep("1d")
|
|
1688
|
+
>>> parameterstep("1d")
|
|
1689
|
+
>>> nmbsoils(1)
|
|
1690
|
+
>>> nmbbins(4)
|
|
1691
|
+
>>> dt(0.5)
|
|
1692
|
+
>>> sealed(False)
|
|
1693
|
+
>>> soilarea(1.0)
|
|
1694
|
+
>>> soildepth(100.0)
|
|
1695
|
+
>>> saturationmoisture(0.5)
|
|
1696
|
+
>>> derived.soilareafraction.update()
|
|
1697
|
+
|
|
1698
|
+
The following test function works similar to the one defined for demonstrating
|
|
1699
|
+
|Active_Bin_V1| but considers the soil water addition instead of infiltration:
|
|
1700
|
+
|
|
1701
|
+
>>> from hydpy.core.objecttools import repr_, repr_values
|
|
1702
|
+
>>> def check(soilwatersupply, moisture, frontdepth):
|
|
1703
|
+
... fluxes.soilwatersupply[0] = soilwatersupply
|
|
1704
|
+
... states.moisture = [[m] for m in moisture]
|
|
1705
|
+
... states.frontdepth = [[fd] for fd in frontdepth]
|
|
1706
|
+
... logs.moisturechange = [[1.0], [2.0], [3.0], [4.0]]
|
|
1707
|
+
... fluxes.soilwateraddition[0] = 0.0
|
|
1708
|
+
... old_volume = round(model.watercontent, 12)
|
|
1709
|
+
... model.water_allbins_v1(0, soilwatersupply)
|
|
1710
|
+
... new_volume = round(model.watercontent, 12)
|
|
1711
|
+
... assert old_volume + fluxes.soilwateraddition[0] == new_volume
|
|
1712
|
+
... print(f"soilwatersupply: {repr_(fluxes.soilwatersupply[0])}")
|
|
1713
|
+
... print(f"moisture: {repr_values(states.moisture[:, 0])}")
|
|
1714
|
+
... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
|
|
1715
|
+
... print(f"moisturechange: {repr_values(logs.moisturechange[:, 0])}")
|
|
1716
|
+
... print(f"soilwateraddition: {repr_(fluxes.soilwateraddition[0])}")
|
|
1717
|
+
|
|
1718
|
+
For zero soil water supply, |Water_AllBins_V1| does nothing:
|
|
1719
|
+
|
|
1720
|
+
>>> check(soilwatersupply=0.0,
|
|
1721
|
+
... moisture=[0.1, 0.3, 0.1, 0.1],
|
|
1722
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0])
|
|
1723
|
+
soilwatersupply: 0.0
|
|
1724
|
+
moisture: 0.1, 0.3, 0.1, 0.1
|
|
1725
|
+
frontdepth: 100.0, 50.0, 0.0, 0.0
|
|
1726
|
+
moisturechange: 1.0, 2.0, 3.0, 4.0
|
|
1727
|
+
soilwateraddition: 0.0
|
|
1728
|
+
|
|
1729
|
+
|Water_AllBins_V1| tries to add the supply to the dryest bin by increasing its
|
|
1730
|
+
relative moisture content:
|
|
1731
|
+
|
|
1732
|
+
>>> check(soilwatersupply=5.0,
|
|
1733
|
+
... moisture=[0.1, 0.3, 0.1, 0.1],
|
|
1734
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0])
|
|
1735
|
+
soilwatersupply: 5.0
|
|
1736
|
+
moisture: 0.2, 0.3, 0.2, 0.2
|
|
1737
|
+
frontdepth: 100.0, 50.0, 0.0, 0.0
|
|
1738
|
+
moisturechange: 0.0, 2.0, 3.0, 4.0
|
|
1739
|
+
soilwateraddition: 5.0
|
|
1740
|
+
|
|
1741
|
+
If a bin is not the last active bin, its highest possible moisture content is
|
|
1742
|
+
restricted by the relative moisture value of its right neighbour bin. If two
|
|
1743
|
+
bins get the same moisture, one of them becomes obsolete, so we can remove it
|
|
1744
|
+
and shift all its right neighbours one place to the left:
|
|
1745
|
+
|
|
1746
|
+
>>> check(soilwatersupply=10.0,
|
|
1747
|
+
... moisture=[0.1, 0.3, 0.1, 0.1],
|
|
1748
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0])
|
|
1749
|
+
soilwatersupply: 10.0
|
|
1750
|
+
moisture: 0.3, 0.3, 0.3, 0.3
|
|
1751
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
1752
|
+
moisturechange: 0.0, 3.0, 4.0, 0.0
|
|
1753
|
+
soilwateraddition: 10.0
|
|
1754
|
+
|
|
1755
|
+
If the first bin cannot take enough water, |Water_AllBins_V1| updates the front
|
|
1756
|
+
depth and increases the water content of the second bin:
|
|
1757
|
+
|
|
1758
|
+
>>> check(soilwatersupply=20.0,
|
|
1759
|
+
... moisture=[0.1, 0.3, 0.1, 0.1],
|
|
1760
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0])
|
|
1761
|
+
soilwatersupply: 20.0
|
|
1762
|
+
moisture: 0.4, 0.4, 0.4, 0.4
|
|
1763
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
1764
|
+
moisturechange: 0.0, 3.0, 4.0, 0.0
|
|
1765
|
+
soilwateraddition: 20.0
|
|
1766
|
+
|
|
1767
|
+
However, no bin can possess relative moisture higher than indicated by
|
|
1768
|
+
saturation moisture:
|
|
1769
|
+
|
|
1770
|
+
>>> check(soilwatersupply=40.0,
|
|
1771
|
+
... moisture=[0.1, 0.3, 0.1, 0.1],
|
|
1772
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0])
|
|
1773
|
+
soilwatersupply: 40.0
|
|
1774
|
+
moisture: 0.5, 0.5, 0.5, 0.5
|
|
1775
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
1776
|
+
moisturechange: 0.0, 3.0, 4.0, 0.0
|
|
1777
|
+
soilwateraddition: 30.0
|
|
1778
|
+
|
|
1779
|
+
|Water_AllBins_V1| deactivates multiple bins when necessary:
|
|
1780
|
+
|
|
1781
|
+
>>> check(soilwatersupply=40.0,
|
|
1782
|
+
... moisture=[0.1, 0.3, 0.5, 0.1],
|
|
1783
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0])
|
|
1784
|
+
soilwatersupply: 40.0
|
|
1785
|
+
moisture: 0.5, 0.5, 0.5, 0.5
|
|
1786
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
1787
|
+
moisturechange: 0.0, 4.0, 0.0, 0.0
|
|
1788
|
+
soilwateraddition: 30.0
|
|
1789
|
+
|
|
1790
|
+
>>> check(soilwatersupply=10.0,
|
|
1791
|
+
... moisture=[0.1, 0.2, 0.3, 0.4],
|
|
1792
|
+
... frontdepth=[100.0, 75.0, 50.0, 25.0])
|
|
1793
|
+
soilwatersupply: 10.0
|
|
1794
|
+
moisture: 0.333333, 0.4, 0.333333, 0.333333
|
|
1795
|
+
frontdepth: 100.0, 25.0, 0.0, 0.0
|
|
1796
|
+
moisturechange: 0.0, 4.0, 0.0, 0.0
|
|
1797
|
+
soilwateraddition: 10.0
|
|
1798
|
+
|
|
1799
|
+
>>> check(soilwatersupply=30.0,
|
|
1800
|
+
... moisture=[0.1, 0.2, 0.3, 0.4],
|
|
1801
|
+
... frontdepth=[100.0, 75.0, 50.0, 25.0])
|
|
1802
|
+
soilwatersupply: 30.0
|
|
1803
|
+
moisture: 0.5, 0.5, 0.5, 0.5
|
|
1804
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
1805
|
+
moisturechange: 0.0, 0.0, 0.0, 0.0
|
|
1806
|
+
soilwateraddition: 25.0
|
|
1807
|
+
|
|
1808
|
+
The last two examples demonstrate, similar to the first example, that
|
|
1809
|
+
|Water_AllBins_V1| adjusts the relative moisture value of all non-active bins
|
|
1810
|
+
after increasing the moisture of the first bin:
|
|
1811
|
+
|
|
1812
|
+
>>> check(soilwatersupply=10.0,
|
|
1813
|
+
... moisture=[0.1, 0.1, 0.1, 0.1],
|
|
1814
|
+
... frontdepth=[100.0, 0.0, 0.0, 0.0])
|
|
1815
|
+
soilwatersupply: 10.0
|
|
1816
|
+
moisture: 0.2, 0.2, 0.2, 0.2
|
|
1817
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
1818
|
+
moisturechange: 0.0, 2.0, 3.0, 4.0
|
|
1819
|
+
soilwateraddition: 10.0
|
|
1820
|
+
|
|
1821
|
+
>>> check(soilwatersupply=50.0,
|
|
1822
|
+
... moisture=[0.1, 0.1, 0.1, 0.1],
|
|
1823
|
+
... frontdepth=[100.0, 0.0, 0.0, 0.0])
|
|
1824
|
+
soilwatersupply: 50.0
|
|
1825
|
+
moisture: 0.5, 0.5, 0.5, 0.5
|
|
1826
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
1827
|
+
moisturechange: 0.0, 2.0, 3.0, 4.0
|
|
1828
|
+
soilwateraddition: 40.0
|
|
1829
|
+
"""
|
|
1830
|
+
|
|
1831
|
+
CONTROLPARAMETERS = (
|
|
1832
|
+
ga_control.NmbBins,
|
|
1833
|
+
ga_control.SoilDepth,
|
|
1834
|
+
ga_control.SaturationMoisture,
|
|
1835
|
+
)
|
|
1836
|
+
UPDATEDSEQUENCES = (
|
|
1837
|
+
ga_states.Moisture,
|
|
1838
|
+
ga_states.FrontDepth,
|
|
1839
|
+
ga_logs.MoistureChange,
|
|
1840
|
+
ga_fluxes.SoilWaterAddition,
|
|
1841
|
+
)
|
|
1842
|
+
|
|
1843
|
+
@staticmethod
|
|
1844
|
+
def __call__(model: modeltools.Model, s: int, supply: float) -> None:
|
|
1845
|
+
con = model.parameters.control.fastaccess
|
|
1846
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1847
|
+
sta = model.sequences.states.fastaccess
|
|
1848
|
+
log = model.sequences.logs.fastaccess
|
|
1849
|
+
|
|
1850
|
+
if supply <= 0.0:
|
|
1851
|
+
return
|
|
1852
|
+
|
|
1853
|
+
rest: float = supply
|
|
1854
|
+
bl = model.return_lastactivebin_v1(s)
|
|
1855
|
+
for b in range(bl):
|
|
1856
|
+
freedepth: float = con.soildepth[s] - sta.frontdepth[b + 1, s]
|
|
1857
|
+
freecontent: float = freedepth * (
|
|
1858
|
+
sta.moisture[b + 1, s] - sta.moisture[b, s]
|
|
1859
|
+
)
|
|
1860
|
+
if rest <= freecontent:
|
|
1861
|
+
flu.soilwateraddition[s] += supply
|
|
1862
|
+
sta.moisture[b, s] += rest / freedepth
|
|
1863
|
+
rest = 0.0
|
|
1864
|
+
initmoisture: float = sta.moisture[b, s]
|
|
1865
|
+
break
|
|
1866
|
+
rest -= freecontent
|
|
1867
|
+
sta.frontdepth[b + 1, s] = con.soildepth[s]
|
|
1868
|
+
initmoisture = sta.moisture[b + 1, s]
|
|
1869
|
+
|
|
1870
|
+
if rest > 0.0:
|
|
1871
|
+
freecontent = con.soildepth[s] * (
|
|
1872
|
+
con.saturationmoisture[s] - sta.moisture[bl, s]
|
|
1873
|
+
)
|
|
1874
|
+
if rest <= freecontent:
|
|
1875
|
+
flu.soilwateraddition[s] += supply
|
|
1876
|
+
sta.moisture[bl, s] += rest / con.soildepth[s]
|
|
1877
|
+
else:
|
|
1878
|
+
rest -= freecontent
|
|
1879
|
+
flu.soilwateraddition[s] += supply - rest
|
|
1880
|
+
sta.moisture[bl, s] = con.saturationmoisture[s]
|
|
1881
|
+
initmoisture = sta.moisture[bl, s]
|
|
1882
|
+
|
|
1883
|
+
for b in range(con.nmbbins):
|
|
1884
|
+
if sta.moisture[b, s] <= initmoisture:
|
|
1885
|
+
sta.moisture[b, s] = initmoisture
|
|
1886
|
+
|
|
1887
|
+
for b in range(bl):
|
|
1888
|
+
while (sta.moisture[b, s] == sta.moisture[b + 1, s]) and (
|
|
1889
|
+
sta.frontdepth[b + 1, s] > 0.0
|
|
1890
|
+
):
|
|
1891
|
+
sta.frontdepth[b + 1] = sta.frontdepth[b]
|
|
1892
|
+
for bb in range(b, con.nmbbins - 1):
|
|
1893
|
+
sta.moisture[bb, s] = sta.moisture[bb + 1, s]
|
|
1894
|
+
sta.frontdepth[bb, s] = sta.frontdepth[bb + 1, s]
|
|
1895
|
+
log.moisturechange[bb, s] = log.moisturechange[bb + 1, s]
|
|
1896
|
+
sta.moisture[con.nmbbins - 1, s] = sta.moisture[0, s]
|
|
1897
|
+
sta.frontdepth[con.nmbbins - 1, s] = 0.0
|
|
1898
|
+
log.moisturechange[con.nmbbins - 1, s] = 0.0
|
|
1899
|
+
log.moisturechange[0, s] = 0.0
|
|
1900
|
+
|
|
1901
|
+
return
|
|
1902
|
+
|
|
1903
|
+
|
|
1904
|
+
class Withdraw_AllBins_V1(modeltools.Method):
|
|
1905
|
+
r"""Take withdrawal from the available surface water and (potentially) from all
|
|
1906
|
+
active bins.
|
|
1907
|
+
|
|
1908
|
+
The withdrawal calculated by |Withdraw_AllBins_V1| equals the defined demand,
|
|
1909
|
+
except no water exceeding the residual moisture is left. Hence, for example,
|
|
1910
|
+
actual evaporation is more suitable for specifying the demand than potential
|
|
1911
|
+
evaporation.
|
|
1912
|
+
|
|
1913
|
+
Note that the caller needs to pass the demand as a method parameter, which allows
|
|
1914
|
+
him to decide whether to subtract everything in one simulation step or multiple
|
|
1915
|
+
numerical substeps.
|
|
1916
|
+
|
|
1917
|
+
Examples:
|
|
1918
|
+
|
|
1919
|
+
We prepare a single shallow soil compartment divided into four bins:
|
|
1920
|
+
|
|
1921
|
+
>>> from hydpy.models.ga_garto import *
|
|
1922
|
+
>>> simulationstep("1d")
|
|
1923
|
+
>>> parameterstep("1d")
|
|
1924
|
+
>>> nmbsoils(1)
|
|
1925
|
+
>>> nmbbins(4)
|
|
1926
|
+
>>> dt(0.5)
|
|
1927
|
+
>>> sealed(False)
|
|
1928
|
+
>>> soilarea(1.0)
|
|
1929
|
+
>>> soildepth(100.0)
|
|
1930
|
+
>>> residualmoisture(0.1)
|
|
1931
|
+
>>> derived.soilareafraction.update()
|
|
1932
|
+
|
|
1933
|
+
The following test function works similar to the one defined for demonstrating
|
|
1934
|
+
|Active_Bin_V1| but considers the withdrawal instead of infiltration:
|
|
1935
|
+
|
|
1936
|
+
>>> from hydpy.core.objecttools import repr_, repr_values
|
|
1937
|
+
>>> def check(demand, actualsurfacewater, frontdepth, moisture):
|
|
1938
|
+
... states.moisture = [[m] for m in moisture]
|
|
1939
|
+
... states.frontdepth = [[fd] for fd in frontdepth]
|
|
1940
|
+
... logs.moisturechange = nan
|
|
1941
|
+
... aides.actualsurfacewater = actualsurfacewater
|
|
1942
|
+
... fluxes.withdrawal[0] = 0.0
|
|
1943
|
+
... old_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
1944
|
+
... model.withdraw_allbins_v1(0, control.dt * demand)
|
|
1945
|
+
... new_volume = round(model.watercontent + aides.actualsurfacewater[0], 12)
|
|
1946
|
+
... assert old_volume == new_volume + fluxes.withdrawal[0]
|
|
1947
|
+
... print(f"withdrawal: {repr_(fluxes.withdrawal[0])}")
|
|
1948
|
+
... print(f"actualsurfacewater: {repr_(aides.actualsurfacewater[0])}")
|
|
1949
|
+
... print(f"moisture: {repr_values(states.moisture[:, 0])}")
|
|
1950
|
+
... print(f"frontdepth: {repr_values(states.frontdepth[:, 0])}")
|
|
1951
|
+
|
|
1952
|
+
For zero demand, |Withdraw_AllBins_V1| does nothing:
|
|
1953
|
+
|
|
1954
|
+
>>> check(demand=0.0, actualsurfacewater=20.0,
|
|
1955
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0],
|
|
1956
|
+
... moisture=[0.1, 0.3, 0.1, 0.1])
|
|
1957
|
+
withdrawal: 0.0
|
|
1958
|
+
actualsurfacewater: 20.0
|
|
1959
|
+
moisture: 0.1, 0.3, 0.1, 0.1
|
|
1960
|
+
frontdepth: 100.0, 50.0, 0.0, 0.0
|
|
1961
|
+
|
|
1962
|
+
If possible, |Withdraw_AllBins_V1| withdraws only surface water:
|
|
1963
|
+
|
|
1964
|
+
>>> check(demand=10.0, actualsurfacewater=20.0,
|
|
1965
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0],
|
|
1966
|
+
... moisture=[0.1, 0.3, 0.1, 0.1])
|
|
1967
|
+
withdrawal: 5.0
|
|
1968
|
+
actualsurfacewater: 15.0
|
|
1969
|
+
moisture: 0.1, 0.3, 0.1, 0.1
|
|
1970
|
+
frontdepth: 100.0, 50.0, 0.0, 0.0
|
|
1971
|
+
|
|
1972
|
+
If no surface water is available, |Withdraw_AllBins_V1| tries to take all
|
|
1973
|
+
withdrawal from the wettest bin by reducing its relative moisture content:
|
|
1974
|
+
|
|
1975
|
+
>>> check(demand=10.0, actualsurfacewater=0.0,
|
|
1976
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0],
|
|
1977
|
+
... moisture=[0.1, 0.3, 0.1, 0.1])
|
|
1978
|
+
withdrawal: 5.0
|
|
1979
|
+
actualsurfacewater: 0.0
|
|
1980
|
+
moisture: 0.1, 0.2, 0.1, 0.1
|
|
1981
|
+
frontdepth: 100.0, 50.0, 0.0, 0.0
|
|
1982
|
+
|
|
1983
|
+
The following example shows that |Withdraw_AllBins_V1| still prefers surface
|
|
1984
|
+
water over soil water if the demand exceeds the available surface water:
|
|
1985
|
+
|
|
1986
|
+
>>> check(demand=10.0, actualsurfacewater=2.5,
|
|
1987
|
+
... frontdepth=[100.0, 50.0, 0.0, 0.0],
|
|
1988
|
+
... moisture=[0.1, 0.3, 0.1, 0.1])
|
|
1989
|
+
withdrawal: 5.0
|
|
1990
|
+
actualsurfacewater: 0.0
|
|
1991
|
+
moisture: 0.1, 0.25, 0.1, 0.1
|
|
1992
|
+
frontdepth: 100.0, 50.0, 0.0, 0.0
|
|
1993
|
+
|
|
1994
|
+
If the wettest bin does not contain enough water, |Withdraw_AllBins_V1|
|
|
1995
|
+
proceeds from right to left in taking the remaining demand:
|
|
1996
|
+
|
|
1997
|
+
>>> check(demand=10.0, actualsurfacewater=0.0,
|
|
1998
|
+
... frontdepth=[100.0, 75.0, 50.0, 25.0],
|
|
1999
|
+
... moisture=[0.1, 0.2, 0.3, 0.4])
|
|
2000
|
+
withdrawal: 5.0
|
|
2001
|
+
actualsurfacewater: 0.0
|
|
2002
|
+
moisture: 0.1, 0.2, 0.25, 0.1
|
|
2003
|
+
frontdepth: 100.0, 75.0, 50.0, 0.0
|
|
2004
|
+
|
|
2005
|
+
However, |Withdraw_AllBins_V1| never takes more water than indicated by soil's
|
|
2006
|
+
residual moisture:
|
|
2007
|
+
|
|
2008
|
+
>>> check(demand=40.0, actualsurfacewater=0.0,
|
|
2009
|
+
... frontdepth=[100.0, 75.0, 50.0, 25.0],
|
|
2010
|
+
... moisture=[0.1, 0.2, 0.3, 0.4])
|
|
2011
|
+
withdrawal: 15.0
|
|
2012
|
+
actualsurfacewater: 0.0
|
|
2013
|
+
moisture: 0.1, 0.1, 0.1, 0.1
|
|
2014
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
2015
|
+
|
|
2016
|
+
The last two examples show that |Withdraw_AllBins_V1| can also take water from
|
|
2017
|
+
the filled bin (if it is not already dry, as in the previous example):
|
|
2018
|
+
|
|
2019
|
+
>>> check(demand=10.0, actualsurfacewater=0.0,
|
|
2020
|
+
... frontdepth=[100.0, 0.0, 0.0, 0.0],
|
|
2021
|
+
... moisture=[0.2, 0.2, 0.2, 0.2])
|
|
2022
|
+
withdrawal: 5.0
|
|
2023
|
+
actualsurfacewater: 0.0
|
|
2024
|
+
moisture: 0.15, 0.2, 0.2, 0.2
|
|
2025
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
2026
|
+
|
|
2027
|
+
>>> check(demand=40.0, actualsurfacewater=0.0,
|
|
2028
|
+
... frontdepth=[100.0, 0.0, 0.0, 0.0],
|
|
2029
|
+
... moisture=[0.2, 0.2, 0.2, 0.2])
|
|
2030
|
+
withdrawal: 10.0
|
|
2031
|
+
actualsurfacewater: 0.0
|
|
2032
|
+
moisture: 0.1, 0.2, 0.2, 0.2
|
|
2033
|
+
frontdepth: 100.0, 0.0, 0.0, 0.0
|
|
2034
|
+
|
|
2035
|
+
As the last examples show, |Withdraw_AllBins_V1| does not update the other
|
|
2036
|
+
bins' moisture after removing water from the filled bin, which is surprising
|
|
2037
|
+
but agrees with the author's GARTO source code and gave better results for
|
|
2038
|
+
shallow soils in some comparisons.
|
|
2039
|
+
"""
|
|
2040
|
+
|
|
2041
|
+
CONTROLPARAMETERS = (
|
|
2042
|
+
ga_control.NmbBins,
|
|
2043
|
+
ga_control.SoilDepth,
|
|
2044
|
+
ga_control.ResidualMoisture,
|
|
2045
|
+
)
|
|
2046
|
+
UPDATEDSEQUENCES = (
|
|
2047
|
+
ga_states.Moisture,
|
|
2048
|
+
ga_states.FrontDepth,
|
|
2049
|
+
ga_aides.ActualSurfaceWater,
|
|
2050
|
+
ga_fluxes.Withdrawal,
|
|
2051
|
+
)
|
|
2052
|
+
|
|
2053
|
+
@staticmethod
|
|
2054
|
+
def __call__(model: modeltools.Model, s: int, demand: float) -> None:
|
|
2055
|
+
con = model.parameters.control.fastaccess
|
|
2056
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2057
|
+
sta = model.sequences.states.fastaccess
|
|
2058
|
+
aid = model.sequences.aides.fastaccess
|
|
2059
|
+
|
|
2060
|
+
if demand <= 0.0:
|
|
2061
|
+
return
|
|
2062
|
+
|
|
2063
|
+
if demand < aid.actualsurfacewater[s]:
|
|
2064
|
+
aid.actualsurfacewater[s] -= demand
|
|
2065
|
+
flu.withdrawal[s] += demand
|
|
2066
|
+
return
|
|
2067
|
+
demand -= aid.actualsurfacewater[s]
|
|
2068
|
+
flu.withdrawal[s] += aid.actualsurfacewater[s]
|
|
2069
|
+
aid.actualsurfacewater[s] = 0.0
|
|
2070
|
+
|
|
2071
|
+
for b in range(con.nmbbins - 1, 0, -1):
|
|
2072
|
+
if sta.moisture[b, s] > sta.moisture[0, s]:
|
|
2073
|
+
available: float = sta.frontdepth[b, s] * (
|
|
2074
|
+
sta.moisture[b, s] - sta.moisture[b - 1, s]
|
|
2075
|
+
)
|
|
2076
|
+
if demand <= available:
|
|
2077
|
+
sta.moisture[b, s] -= demand / sta.frontdepth[b, s]
|
|
2078
|
+
flu.withdrawal[s] += demand
|
|
2079
|
+
return
|
|
2080
|
+
flu.withdrawal[s] += available
|
|
2081
|
+
demand -= available
|
|
2082
|
+
sta.moisture[b, s] = sta.moisture[0, s]
|
|
2083
|
+
sta.frontdepth[b, s] = 0.0
|
|
2084
|
+
|
|
2085
|
+
if sta.moisture[0, s] <= con.residualmoisture[s]:
|
|
2086
|
+
return
|
|
2087
|
+
|
|
2088
|
+
available = con.soildepth[s] * (sta.moisture[0, s] - con.residualmoisture[s])
|
|
2089
|
+
if demand <= available:
|
|
2090
|
+
sta.moisture[0, s] -= demand / con.soildepth[s]
|
|
2091
|
+
flu.withdrawal[s] += demand
|
|
2092
|
+
else:
|
|
2093
|
+
flu.withdrawal[s] += available
|
|
2094
|
+
sta.moisture[0, s] = con.residualmoisture[s]
|
|
2095
|
+
return
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
class Perform_GARTO_V1(modeltools.Method):
|
|
2099
|
+
r"""Perform the GARTO algorithm for the numerical substeps and aggregate their
|
|
2100
|
+
results.
|
|
2101
|
+
|
|
2102
|
+
Method |Perform_GARTO_V1| executes its submethods |Percolate_FilledBin_V1|,
|
|
2103
|
+
|Infiltrate_WettingFrontBins_V1|, |Merge_FrontDepthOvershootings_V1|,
|
|
2104
|
+
|Merge_SoilDepthOvershootings_V1|, |Water_AllBins_V1|, and |Withdraw_AllBins_V1| in
|
|
2105
|
+
the order of mentioning on all non-sealed soil compartments. Additionally, it
|
|
2106
|
+
converts surface water that cannot infiltrate (or evaporate) during a numerical
|
|
2107
|
+
substep immediately to surface runoff (no ponding). So, it provides all core
|
|
2108
|
+
functionalities of application model |ga_garto|, and the explanations and test
|
|
2109
|
+
results for |ga_garto| essentially apply to |Perform_GARTO_V1|, too.
|
|
2110
|
+
"""
|
|
2111
|
+
|
|
2112
|
+
SUBMETHODS = (
|
|
2113
|
+
Return_LastActiveBin_V1,
|
|
2114
|
+
Return_Conductivity_V1,
|
|
2115
|
+
Return_DryDepth_V1,
|
|
2116
|
+
Return_CapillaryDrive_V1,
|
|
2117
|
+
Percolate_FilledBin_V1,
|
|
2118
|
+
Infiltrate_WettingFrontBins_V1,
|
|
2119
|
+
Merge_FrontDepthOvershootings_V1,
|
|
2120
|
+
Merge_SoilDepthOvershootings_V1,
|
|
2121
|
+
Water_AllBins_V1,
|
|
2122
|
+
Withdraw_AllBins_V1,
|
|
2123
|
+
)
|
|
2124
|
+
CONTROLPARAMETERS = (
|
|
2125
|
+
ga_control.NmbSoils,
|
|
2126
|
+
ga_control.NmbBins,
|
|
2127
|
+
ga_control.DT,
|
|
2128
|
+
ga_control.SoilDepth,
|
|
2129
|
+
ga_control.Sealed,
|
|
2130
|
+
ga_control.ResidualMoisture,
|
|
2131
|
+
ga_control.SaturationMoisture,
|
|
2132
|
+
ga_control.SaturatedConductivity,
|
|
2133
|
+
ga_control.AirEntryPotential,
|
|
2134
|
+
ga_control.PoreSizeDistribution,
|
|
2135
|
+
)
|
|
2136
|
+
DERIVEDPARAMETERS = (ga_derived.NmbSubsteps, ga_derived.EffectiveCapillarySuction)
|
|
2137
|
+
REQUIREDSEQUENCES = (
|
|
2138
|
+
ga_fluxes.SurfaceWaterSupply,
|
|
2139
|
+
ga_fluxes.SoilWaterSupply,
|
|
2140
|
+
ga_fluxes.Demand,
|
|
2141
|
+
)
|
|
2142
|
+
UPDATEDSEQUENCES = (
|
|
2143
|
+
ga_aides.InitialSurfaceWater,
|
|
2144
|
+
ga_aides.ActualSurfaceWater,
|
|
2145
|
+
ga_states.Moisture,
|
|
2146
|
+
ga_states.FrontDepth,
|
|
2147
|
+
ga_logs.MoistureChange,
|
|
2148
|
+
)
|
|
2149
|
+
RESULTSEQUENCES = (
|
|
2150
|
+
ga_fluxes.Infiltration,
|
|
2151
|
+
ga_fluxes.Percolation,
|
|
2152
|
+
ga_fluxes.SoilWaterAddition,
|
|
2153
|
+
ga_fluxes.Withdrawal,
|
|
2154
|
+
ga_fluxes.SurfaceRunoff,
|
|
2155
|
+
)
|
|
2156
|
+
|
|
2157
|
+
@staticmethod
|
|
2158
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2159
|
+
con = model.parameters.control.fastaccess
|
|
2160
|
+
der = model.parameters.derived.fastaccess
|
|
2161
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2162
|
+
aid = model.sequences.aides.fastaccess
|
|
2163
|
+
for s in range(con.nmbsoils):
|
|
2164
|
+
flu.percolation[s] = 0.0
|
|
2165
|
+
flu.infiltration[s] = 0.0
|
|
2166
|
+
flu.soilwateraddition[s] = 0.0
|
|
2167
|
+
if con.sealed[s]:
|
|
2168
|
+
if flu.demand[s] < flu.surfacewatersupply[s]:
|
|
2169
|
+
flu.withdrawal[s] = flu.demand[s]
|
|
2170
|
+
flu.surfacerunoff[s] = flu.surfacewatersupply[s] - flu.demand[s]
|
|
2171
|
+
else:
|
|
2172
|
+
flu.withdrawal[s] = flu.surfacewatersupply[s]
|
|
2173
|
+
flu.surfacerunoff[s] = 0.0
|
|
2174
|
+
else:
|
|
2175
|
+
aid.initialsurfacewater[s] = con.dt * flu.surfacewatersupply[s]
|
|
2176
|
+
flu.withdrawal[s] = 0.0
|
|
2177
|
+
flu.surfacerunoff[s] = 0.0
|
|
2178
|
+
for _ in range(der.nmbsubsteps):
|
|
2179
|
+
aid.actualsurfacewater[s] = aid.initialsurfacewater[s]
|
|
2180
|
+
model.percolate_filledbin_v1(s)
|
|
2181
|
+
model.infiltrate_wettingfrontbins_v1(s)
|
|
2182
|
+
flu.infiltration[s] += (
|
|
2183
|
+
aid.initialsurfacewater[s] - aid.actualsurfacewater[s]
|
|
2184
|
+
)
|
|
2185
|
+
model.merge_frontdepthovershootings_v1(s)
|
|
2186
|
+
model.merge_soildepthovershootings_v1(s)
|
|
2187
|
+
model.water_allbins_v1(s, con.dt * flu.soilwatersupply[s])
|
|
2188
|
+
model.withdraw_allbins_v1(s, con.dt * flu.demand[s])
|
|
2189
|
+
flu.surfacerunoff[s] += aid.actualsurfacewater[s]
|
|
2190
|
+
|
|
2191
|
+
|
|
2192
|
+
class Calc_TotalInfiltration_V1(modeltools.Method):
|
|
2193
|
+
r"""Calculate the average infiltration from all soil compartments.
|
|
2194
|
+
|
|
2195
|
+
Basic equation:
|
|
2196
|
+
:math:`TotalInfiltration =
|
|
2197
|
+
\sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot Infiltration_i`
|
|
2198
|
+
|
|
2199
|
+
Example:
|
|
2200
|
+
|
|
2201
|
+
>>> from hydpy.models.ga import *
|
|
2202
|
+
>>> parameterstep()
|
|
2203
|
+
>>> nmbsoils(2)
|
|
2204
|
+
>>> derived.soilareafraction(0.8, 0.2)
|
|
2205
|
+
>>> fluxes.infiltration = 1.0, 2.0
|
|
2206
|
+
>>> model.calc_totalinfiltration_v1()
|
|
2207
|
+
>>> fluxes.totalinfiltration
|
|
2208
|
+
totalinfiltration(1.2)
|
|
2209
|
+
"""
|
|
2210
|
+
|
|
2211
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
2212
|
+
DERIVEDPARAMETERS = (ga_derived.SoilAreaFraction,)
|
|
2213
|
+
REQUIREDSEQUENCES = (ga_fluxes.Infiltration,)
|
|
2214
|
+
RESULTSEQUENCES = (ga_fluxes.TotalInfiltration,)
|
|
2215
|
+
|
|
2216
|
+
@staticmethod
|
|
2217
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2218
|
+
con = model.parameters.control.fastaccess
|
|
2219
|
+
der = model.parameters.derived.fastaccess
|
|
2220
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2221
|
+
|
|
2222
|
+
flu.totalinfiltration = 0.0
|
|
2223
|
+
for s in range(con.nmbsoils):
|
|
2224
|
+
flu.totalinfiltration += der.soilareafraction[s] * flu.infiltration[s]
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
class Calc_TotalPercolation_V1(modeltools.Method):
|
|
2228
|
+
r"""Calculate the average percolation from all soil compartments.
|
|
2229
|
+
|
|
2230
|
+
Basic equation:
|
|
2231
|
+
:math:`TotalPercolation =
|
|
2232
|
+
\sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot Percolation_i`
|
|
2233
|
+
|
|
2234
|
+
Example:
|
|
2235
|
+
|
|
2236
|
+
>>> from hydpy.models.ga import *
|
|
2237
|
+
>>> parameterstep()
|
|
2238
|
+
>>> nmbsoils(2)
|
|
2239
|
+
>>> derived.soilareafraction(0.8, 0.2)
|
|
2240
|
+
>>> fluxes.percolation = 1.0, 2.0
|
|
2241
|
+
>>> model.calc_totalpercolation_v1()
|
|
2242
|
+
>>> fluxes.totalpercolation
|
|
2243
|
+
totalpercolation(1.2)
|
|
2244
|
+
"""
|
|
2245
|
+
|
|
2246
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
2247
|
+
DERIVEDPARAMETERS = (ga_derived.SoilAreaFraction,)
|
|
2248
|
+
REQUIREDSEQUENCES = (ga_fluxes.Percolation,)
|
|
2249
|
+
RESULTSEQUENCES = (ga_fluxes.TotalPercolation,)
|
|
2250
|
+
|
|
2251
|
+
@staticmethod
|
|
2252
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2253
|
+
con = model.parameters.control.fastaccess
|
|
2254
|
+
der = model.parameters.derived.fastaccess
|
|
2255
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2256
|
+
|
|
2257
|
+
flu.totalpercolation = 0.0
|
|
2258
|
+
for s in range(con.nmbsoils):
|
|
2259
|
+
flu.totalpercolation += der.soilareafraction[s] * flu.percolation[s]
|
|
2260
|
+
|
|
2261
|
+
|
|
2262
|
+
class Calc_TotalSoilWaterAddition_V1(modeltools.Method):
|
|
2263
|
+
r"""Calculate the average soil water addition to all soil compartments.
|
|
2264
|
+
|
|
2265
|
+
Basic equation:
|
|
2266
|
+
:math:`TotalSoilWaterAddition =
|
|
2267
|
+
\sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot SoilWaterAddition_i`
|
|
2268
|
+
|
|
2269
|
+
Example:
|
|
2270
|
+
|
|
2271
|
+
>>> from hydpy.models.ga import *
|
|
2272
|
+
>>> parameterstep()
|
|
2273
|
+
>>> nmbsoils(2)
|
|
2274
|
+
>>> derived.soilareafraction(0.8, 0.2)
|
|
2275
|
+
>>> fluxes.soilwateraddition = 1.0, 2.0
|
|
2276
|
+
>>> model.calc_totalsoilwateraddition_v1()
|
|
2277
|
+
>>> fluxes.totalsoilwateraddition
|
|
2278
|
+
totalsoilwateraddition(1.2)
|
|
2279
|
+
"""
|
|
2280
|
+
|
|
2281
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
2282
|
+
DERIVEDPARAMETERS = (ga_derived.SoilAreaFraction,)
|
|
2283
|
+
REQUIREDSEQUENCES = (ga_fluxes.SoilWaterAddition,)
|
|
2284
|
+
RESULTSEQUENCES = (ga_fluxes.TotalSoilWaterAddition,)
|
|
2285
|
+
|
|
2286
|
+
@staticmethod
|
|
2287
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2288
|
+
con = model.parameters.control.fastaccess
|
|
2289
|
+
der = model.parameters.derived.fastaccess
|
|
2290
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2291
|
+
|
|
2292
|
+
flu.totalsoilwateraddition = 0.0
|
|
2293
|
+
for s in range(con.nmbsoils):
|
|
2294
|
+
flu.totalsoilwateraddition += (
|
|
2295
|
+
der.soilareafraction[s] * flu.soilwateraddition[s]
|
|
2296
|
+
)
|
|
2297
|
+
|
|
2298
|
+
|
|
2299
|
+
class Calc_TotalWithdrawal_V1(modeltools.Method):
|
|
2300
|
+
r"""Calculate the average withdrawal from all soil compartments.
|
|
2301
|
+
|
|
2302
|
+
Basic equation:
|
|
2303
|
+
:math:`TotalWithdrawal =
|
|
2304
|
+
\sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot Withdrawal_i`
|
|
2305
|
+
|
|
2306
|
+
Example:
|
|
2307
|
+
|
|
2308
|
+
>>> from hydpy.models.ga import *
|
|
2309
|
+
>>> parameterstep()
|
|
2310
|
+
>>> nmbsoils(2)
|
|
2311
|
+
>>> derived.soilareafraction(0.8, 0.2)
|
|
2312
|
+
>>> fluxes.withdrawal = 1.0, 2.0
|
|
2313
|
+
>>> model.calc_totalwithdrawal_v1()
|
|
2314
|
+
>>> fluxes.totalwithdrawal
|
|
2315
|
+
totalwithdrawal(1.2)
|
|
2316
|
+
"""
|
|
2317
|
+
|
|
2318
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
2319
|
+
DERIVEDPARAMETERS = (ga_derived.SoilAreaFraction,)
|
|
2320
|
+
REQUIREDSEQUENCES = (ga_fluxes.Withdrawal,)
|
|
2321
|
+
RESULTSEQUENCES = (ga_fluxes.TotalWithdrawal,)
|
|
2322
|
+
|
|
2323
|
+
@staticmethod
|
|
2324
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2325
|
+
con = model.parameters.control.fastaccess
|
|
2326
|
+
der = model.parameters.derived.fastaccess
|
|
2327
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2328
|
+
|
|
2329
|
+
flu.totalwithdrawal = 0.0
|
|
2330
|
+
for s in range(con.nmbsoils):
|
|
2331
|
+
flu.totalwithdrawal += der.soilareafraction[s] * flu.withdrawal[s]
|
|
2332
|
+
|
|
2333
|
+
|
|
2334
|
+
class Calc_TotalSurfaceRunoff_V1(modeltools.Method):
|
|
2335
|
+
r"""Calculate the average surface runoff from all soil compartments.
|
|
2336
|
+
|
|
2337
|
+
Basic equation:
|
|
2338
|
+
:math:`TotalSurfaceRunoff =
|
|
2339
|
+
\sum_{i=1}^{NmbSoils} SoilAreaFraction_i \cdot SurfaceRunoff_i`
|
|
2340
|
+
|
|
2341
|
+
Example:
|
|
2342
|
+
|
|
2343
|
+
>>> from hydpy.models.ga import *
|
|
2344
|
+
>>> parameterstep()
|
|
2345
|
+
>>> nmbsoils(2)
|
|
2346
|
+
>>> derived.soilareafraction(0.8, 0.2)
|
|
2347
|
+
>>> fluxes.surfacerunoff = 1.0, 2.0
|
|
2348
|
+
>>> model.calc_totalsurfacerunoff_v1()
|
|
2349
|
+
>>> fluxes.totalsurfacerunoff
|
|
2350
|
+
totalsurfacerunoff(1.2)
|
|
2351
|
+
"""
|
|
2352
|
+
|
|
2353
|
+
CONTROLPARAMETERS = (ga_control.NmbSoils,)
|
|
2354
|
+
DERIVEDPARAMETERS = (ga_derived.SoilAreaFraction,)
|
|
2355
|
+
REQUIREDSEQUENCES = (ga_fluxes.SurfaceRunoff,)
|
|
2356
|
+
RESULTSEQUENCES = (ga_fluxes.TotalSurfaceRunoff,)
|
|
2357
|
+
|
|
2358
|
+
@staticmethod
|
|
2359
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2360
|
+
con = model.parameters.control.fastaccess
|
|
2361
|
+
der = model.parameters.derived.fastaccess
|
|
2362
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2363
|
+
|
|
2364
|
+
flu.totalsurfacerunoff = 0.0
|
|
2365
|
+
for s in range(con.nmbsoils):
|
|
2366
|
+
flu.totalsurfacerunoff += der.soilareafraction[s] * flu.surfacerunoff[s]
|
|
2367
|
+
|
|
2368
|
+
|
|
2369
|
+
class Set_InitialSurfaceWater_V1(modeltools.Method):
|
|
2370
|
+
"""Set the given initial surface water depth for the selected soil compartment.
|
|
2371
|
+
|
|
2372
|
+
Example:
|
|
2373
|
+
|
|
2374
|
+
Note that |Set_InitialSurfaceWater_V1| multiplies the given value with |DT| to
|
|
2375
|
+
adjust it to the numerical substep width:
|
|
2376
|
+
|
|
2377
|
+
>>> from hydpy.models.ga import *
|
|
2378
|
+
>>> parameterstep()
|
|
2379
|
+
>>> nmbsoils(2)
|
|
2380
|
+
>>> dt.value = 0.5
|
|
2381
|
+
>>> model.set_initialsurfacewater_v1(0, 2.0)
|
|
2382
|
+
>>> model.set_initialsurfacewater_v1(1, 4.0)
|
|
2383
|
+
>>> aides.initialsurfacewater
|
|
2384
|
+
initialsurfacewater(1.0, 2.0)
|
|
2385
|
+
"""
|
|
2386
|
+
|
|
2387
|
+
CONTROLPARAMETERS = (ga_control.DT,)
|
|
2388
|
+
RESULTSEQUENCES = (ga_aides.InitialSurfaceWater,)
|
|
2389
|
+
|
|
2390
|
+
@staticmethod
|
|
2391
|
+
def __call__(model: modeltools.Model, s: int, v: float) -> None:
|
|
2392
|
+
con = model.parameters.control.fastaccess
|
|
2393
|
+
aid = model.sequences.aides.fastaccess
|
|
2394
|
+
|
|
2395
|
+
aid.initialsurfacewater[s] = con.dt * v
|
|
2396
|
+
|
|
2397
|
+
|
|
2398
|
+
class Set_ActualSurfaceWater_V1(modeltools.Method):
|
|
2399
|
+
"""Set the given actual surface water depth for the selected soil compartment.
|
|
2400
|
+
|
|
2401
|
+
Example:
|
|
2402
|
+
|
|
2403
|
+
Note that |Set_ActualSurfaceWater_V1| multiplies the given value with |DT| to
|
|
2404
|
+
adjust it to the numerical substep width:
|
|
2405
|
+
|
|
2406
|
+
>>> from hydpy.models.ga import *
|
|
2407
|
+
>>> parameterstep()
|
|
2408
|
+
>>> nmbsoils(2)
|
|
2409
|
+
>>> dt.value = 0.5
|
|
2410
|
+
>>> model.set_actualsurfacewater_v1(0, 2.0)
|
|
2411
|
+
>>> model.set_actualsurfacewater_v1(1, 4.0)
|
|
2412
|
+
>>> aides.actualsurfacewater
|
|
2413
|
+
actualsurfacewater(1.0, 2.0)
|
|
2414
|
+
"""
|
|
2415
|
+
|
|
2416
|
+
CONTROLPARAMETERS = (ga_control.DT,)
|
|
2417
|
+
RESULTSEQUENCES = (ga_aides.ActualSurfaceWater,)
|
|
2418
|
+
|
|
2419
|
+
@staticmethod
|
|
2420
|
+
def __call__(model: modeltools.Model, s: int, v: float) -> None:
|
|
2421
|
+
con = model.parameters.control.fastaccess
|
|
2422
|
+
aid = model.sequences.aides.fastaccess
|
|
2423
|
+
|
|
2424
|
+
aid.actualsurfacewater[s] = con.dt * v
|
|
2425
|
+
|
|
2426
|
+
|
|
2427
|
+
class Set_SoilWaterSupply_V1(modeltools.Method):
|
|
2428
|
+
"""Set the (potential) water supply to the soil's body.
|
|
2429
|
+
|
|
2430
|
+
Example:
|
|
2431
|
+
|
|
2432
|
+
>>> from hydpy.models.ga import *
|
|
2433
|
+
>>> parameterstep()
|
|
2434
|
+
>>> nmbsoils(2)
|
|
2435
|
+
>>> model.set_soilwatersupply_v1(0, 2.0)
|
|
2436
|
+
>>> model.set_soilwatersupply_v1(1, 4.0)
|
|
2437
|
+
>>> fluxes.soilwatersupply
|
|
2438
|
+
soilwatersupply(2.0, 4.0)
|
|
2439
|
+
"""
|
|
2440
|
+
|
|
2441
|
+
RESULTSEQUENCES = (ga_fluxes.SoilWaterSupply,)
|
|
2442
|
+
|
|
2443
|
+
@staticmethod
|
|
2444
|
+
def __call__(model: modeltools.Model, s: int, v: float) -> None:
|
|
2445
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2446
|
+
|
|
2447
|
+
flu.soilwatersupply[s] = v
|
|
2448
|
+
|
|
2449
|
+
|
|
2450
|
+
class Set_SoilWaterDemand_V1(modeltools.Method):
|
|
2451
|
+
"""Set the (potential) water withdrawal from the soil's surface and body.
|
|
2452
|
+
|
|
2453
|
+
Example:
|
|
2454
|
+
|
|
2455
|
+
>>> from hydpy.models.ga import *
|
|
2456
|
+
>>> parameterstep()
|
|
2457
|
+
>>> nmbsoils(2)
|
|
2458
|
+
>>> model.set_soilwaterdemand_v1(0, 2.0)
|
|
2459
|
+
>>> model.set_soilwaterdemand_v1(1, 4.0)
|
|
2460
|
+
>>> fluxes.demand
|
|
2461
|
+
demand(2.0, 4.0)
|
|
2462
|
+
"""
|
|
2463
|
+
|
|
2464
|
+
RESULTSEQUENCES = (ga_fluxes.Demand,)
|
|
2465
|
+
|
|
2466
|
+
@staticmethod
|
|
2467
|
+
def __call__(model: modeltools.Model, s: int, v: float) -> None:
|
|
2468
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2469
|
+
|
|
2470
|
+
flu.demand[s] = v
|
|
2471
|
+
|
|
2472
|
+
|
|
2473
|
+
class Execute_Infiltration_V1(modeltools.Method):
|
|
2474
|
+
"""Calculate infiltration (and percolation).
|
|
2475
|
+
|
|
2476
|
+
The interface method |Execute_Infiltration_V1| subsequently executes the GARTO
|
|
2477
|
+
methods |Percolate_FilledBin_V1|, |Infiltrate_WettingFrontBins_V1|,
|
|
2478
|
+
|Merge_FrontDepthOvershootings_V1|, and |Merge_SoilDepthOvershootings_V1| for all
|
|
2479
|
+
numerical substeps.
|
|
2480
|
+
"""
|
|
2481
|
+
|
|
2482
|
+
SUBMETHODS = (
|
|
2483
|
+
Return_LastActiveBin_V1,
|
|
2484
|
+
Return_Conductivity_V1,
|
|
2485
|
+
Return_DryDepth_V1,
|
|
2486
|
+
Return_CapillaryDrive_V1,
|
|
2487
|
+
Percolate_FilledBin_V1,
|
|
2488
|
+
Infiltrate_WettingFrontBins_V1,
|
|
2489
|
+
Merge_FrontDepthOvershootings_V1,
|
|
2490
|
+
Merge_SoilDepthOvershootings_V1,
|
|
2491
|
+
)
|
|
2492
|
+
CONTROLPARAMETERS = (
|
|
2493
|
+
ga_control.NmbBins,
|
|
2494
|
+
ga_control.DT,
|
|
2495
|
+
ga_control.SoilDepth,
|
|
2496
|
+
ga_control.ResidualMoisture,
|
|
2497
|
+
ga_control.SaturationMoisture,
|
|
2498
|
+
ga_control.SaturatedConductivity,
|
|
2499
|
+
ga_control.AirEntryPotential,
|
|
2500
|
+
ga_control.PoreSizeDistribution,
|
|
2501
|
+
)
|
|
2502
|
+
DERIVEDPARAMETERS = (ga_derived.NmbSubsteps, ga_derived.EffectiveCapillarySuction)
|
|
2503
|
+
REQUIREDSEQUENCES = (ga_aides.InitialSurfaceWater,)
|
|
2504
|
+
UPDATEDSEQUENCES = (
|
|
2505
|
+
ga_aides.ActualSurfaceWater,
|
|
2506
|
+
ga_states.Moisture,
|
|
2507
|
+
ga_states.FrontDepth,
|
|
2508
|
+
ga_logs.MoistureChange,
|
|
2509
|
+
)
|
|
2510
|
+
RESULTSEQUENCES = (
|
|
2511
|
+
ga_fluxes.Infiltration,
|
|
2512
|
+
ga_fluxes.Percolation,
|
|
2513
|
+
ga_fluxes.SurfaceRunoff,
|
|
2514
|
+
)
|
|
2515
|
+
|
|
2516
|
+
@staticmethod
|
|
2517
|
+
def __call__(model: modeltools.Model, s: int) -> None:
|
|
2518
|
+
der = model.parameters.derived.fastaccess
|
|
2519
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2520
|
+
aid = model.sequences.aides.fastaccess
|
|
2521
|
+
|
|
2522
|
+
initialactualsurfacewater: float = aid.actualsurfacewater[s]
|
|
2523
|
+
flu.infiltration[s] = 0.0
|
|
2524
|
+
flu.percolation[s] = 0.0
|
|
2525
|
+
flu.surfacerunoff[s] = 0.0
|
|
2526
|
+
for _ in range(der.nmbsubsteps):
|
|
2527
|
+
aid.actualsurfacewater[s] = initialactualsurfacewater
|
|
2528
|
+
model.percolate_filledbin_v1(s)
|
|
2529
|
+
model.infiltrate_wettingfrontbins_v1(s)
|
|
2530
|
+
flu.infiltration[s] += initialactualsurfacewater - aid.actualsurfacewater[s]
|
|
2531
|
+
model.merge_frontdepthovershootings_v1(s)
|
|
2532
|
+
model.merge_soildepthovershootings_v1(s)
|
|
2533
|
+
flu.surfacerunoff[s] += aid.actualsurfacewater[s]
|
|
2534
|
+
aid.actualsurfacewater[s] = 0.0
|
|
2535
|
+
|
|
2536
|
+
|
|
2537
|
+
class Add_SoilWater_V1(modeltools.Method):
|
|
2538
|
+
"""Add the (direct) soil water supply to the soil's body.
|
|
2539
|
+
|
|
2540
|
+
The interface method |Add_SoilWater_V1| only calls |Withdraw_AllBins_V1|.
|
|
2541
|
+
"""
|
|
2542
|
+
|
|
2543
|
+
SUBMETHODS = (Water_AllBins_V1,)
|
|
2544
|
+
CONTROLPARAMETERS = (
|
|
2545
|
+
ga_control.NmbBins,
|
|
2546
|
+
ga_control.SoilDepth,
|
|
2547
|
+
ga_control.SaturationMoisture,
|
|
2548
|
+
)
|
|
2549
|
+
REQUIREDSEQUENCES = (ga_fluxes.SoilWaterSupply,)
|
|
2550
|
+
UPDATEDSEQUENCES = (
|
|
2551
|
+
ga_states.FrontDepth,
|
|
2552
|
+
ga_states.Moisture,
|
|
2553
|
+
ga_logs.MoistureChange,
|
|
2554
|
+
)
|
|
2555
|
+
RESULTSEQUENCES = (ga_fluxes.SoilWaterAddition,)
|
|
2556
|
+
|
|
2557
|
+
@staticmethod
|
|
2558
|
+
def __call__(model: modeltools.Model, s: int) -> None:
|
|
2559
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2560
|
+
|
|
2561
|
+
flu.soilwateraddition[s] = 0.0
|
|
2562
|
+
model.water_allbins_v1(s, flu.soilwatersupply[s])
|
|
2563
|
+
|
|
2564
|
+
|
|
2565
|
+
class Remove_SoilWater_V1(modeltools.Method):
|
|
2566
|
+
"""Remove the water demand from the soil's body and eventually from the soil's
|
|
2567
|
+
surface.
|
|
2568
|
+
|
|
2569
|
+
The interface method |Remove_SoilWater_V1| only calls |Withdraw_AllBins_V1|.
|
|
2570
|
+
Hence, whether |Remove_SoilWater_V1| can remove surface water depends on the order
|
|
2571
|
+
the different interface methods are applied and is thus a decision of the calling
|
|
2572
|
+
model.
|
|
2573
|
+
"""
|
|
2574
|
+
|
|
2575
|
+
SUBMETHODS = (Withdraw_AllBins_V1,)
|
|
2576
|
+
CONTROLPARAMETERS = (
|
|
2577
|
+
ga_control.NmbBins,
|
|
2578
|
+
ga_control.SoilDepth,
|
|
2579
|
+
ga_control.ResidualMoisture,
|
|
2580
|
+
)
|
|
2581
|
+
REQUIREDSEQUENCES = (ga_fluxes.Demand,)
|
|
2582
|
+
UPDATEDSEQUENCES = (
|
|
2583
|
+
ga_aides.ActualSurfaceWater,
|
|
2584
|
+
ga_states.FrontDepth,
|
|
2585
|
+
ga_states.Moisture,
|
|
2586
|
+
)
|
|
2587
|
+
RESULTSEQUENCES = (ga_fluxes.Withdrawal,)
|
|
2588
|
+
|
|
2589
|
+
@staticmethod
|
|
2590
|
+
def __call__(model: modeltools.Model, s: int) -> None:
|
|
2591
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2592
|
+
aid = model.sequences.aides.fastaccess
|
|
2593
|
+
|
|
2594
|
+
aid.actualsurfacewater[s] = 0.0
|
|
2595
|
+
flu.withdrawal[s] = 0.0
|
|
2596
|
+
model.withdraw_allbins_v1(s, flu.demand[s])
|
|
2597
|
+
|
|
2598
|
+
|
|
2599
|
+
class Get_Infiltration_V1(modeltools.Method):
|
|
2600
|
+
"""Get the current infiltration to the selected soil compartment.
|
|
2601
|
+
|
|
2602
|
+
Example:
|
|
2603
|
+
|
|
2604
|
+
>>> from hydpy.models.ga import *
|
|
2605
|
+
>>> parameterstep()
|
|
2606
|
+
>>> nmbsoils(2)
|
|
2607
|
+
>>> fluxes.infiltration = 2.0, 4.0
|
|
2608
|
+
>>> from hydpy import round_
|
|
2609
|
+
>>> round_(model.get_infiltration_v1(0))
|
|
2610
|
+
2.0
|
|
2611
|
+
>>> round_(model.get_infiltration_v1(1))
|
|
2612
|
+
4.0
|
|
2613
|
+
"""
|
|
2614
|
+
|
|
2615
|
+
RESULTSEQUENCES = (ga_fluxes.Infiltration,)
|
|
2616
|
+
|
|
2617
|
+
@staticmethod
|
|
2618
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
2619
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2620
|
+
|
|
2621
|
+
return flu.infiltration[s]
|
|
2622
|
+
|
|
2623
|
+
|
|
2624
|
+
class Get_Percolation_V1(modeltools.Method):
|
|
2625
|
+
"""Get the current percolation from the selected soil compartment.
|
|
2626
|
+
|
|
2627
|
+
Example:
|
|
2628
|
+
|
|
2629
|
+
>>> from hydpy.models.ga import *
|
|
2630
|
+
>>> parameterstep()
|
|
2631
|
+
>>> nmbsoils(2)
|
|
2632
|
+
>>> fluxes.percolation = 2.0, 4.0
|
|
2633
|
+
>>> from hydpy import round_
|
|
2634
|
+
>>> round_(model.get_percolation_v1(0))
|
|
2635
|
+
2.0
|
|
2636
|
+
>>> round_(model.get_percolation_v1(1))
|
|
2637
|
+
4.0
|
|
2638
|
+
"""
|
|
2639
|
+
|
|
2640
|
+
RESULTSEQUENCES = (ga_fluxes.Percolation,)
|
|
2641
|
+
|
|
2642
|
+
@staticmethod
|
|
2643
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
2644
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2645
|
+
|
|
2646
|
+
return flu.percolation[s]
|
|
2647
|
+
|
|
2648
|
+
|
|
2649
|
+
class Get_SoilWaterAddition_V1(modeltools.Method):
|
|
2650
|
+
"""Get the current soil water addition to the selected soil compartment.
|
|
2651
|
+
|
|
2652
|
+
Example:
|
|
2653
|
+
|
|
2654
|
+
>>> from hydpy.models.ga import *
|
|
2655
|
+
>>> parameterstep()
|
|
2656
|
+
>>> nmbsoils(2)
|
|
2657
|
+
>>> fluxes.soilwateraddition = 2.0, 4.0
|
|
2658
|
+
>>> from hydpy import round_
|
|
2659
|
+
>>> round_(model.get_soilwateraddition_v1(0))
|
|
2660
|
+
2.0
|
|
2661
|
+
>>> round_(model.get_soilwateraddition_v1(1))
|
|
2662
|
+
4.0
|
|
2663
|
+
"""
|
|
2664
|
+
|
|
2665
|
+
RESULTSEQUENCES = (ga_fluxes.SoilWaterAddition,)
|
|
2666
|
+
|
|
2667
|
+
@staticmethod
|
|
2668
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
2669
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2670
|
+
|
|
2671
|
+
return flu.soilwateraddition[s]
|
|
2672
|
+
|
|
2673
|
+
|
|
2674
|
+
class Get_SoilWaterRemoval_V1(modeltools.Method):
|
|
2675
|
+
"""Get the current soil (and surface water) withdrawal from the selected soil
|
|
2676
|
+
compartment.
|
|
2677
|
+
|
|
2678
|
+
Example:
|
|
2679
|
+
|
|
2680
|
+
>>> from hydpy.models.ga import *
|
|
2681
|
+
>>> parameterstep()
|
|
2682
|
+
>>> nmbsoils(2)
|
|
2683
|
+
>>> fluxes.withdrawal = 2.0, 4.0
|
|
2684
|
+
>>> from hydpy import round_
|
|
2685
|
+
>>> round_(model.get_soilwaterremoval_v1(0))
|
|
2686
|
+
2.0
|
|
2687
|
+
>>> round_(model.get_soilwaterremoval_v1(1))
|
|
2688
|
+
4.0
|
|
2689
|
+
"""
|
|
2690
|
+
|
|
2691
|
+
RESULTSEQUENCES = (ga_fluxes.Withdrawal,)
|
|
2692
|
+
|
|
2693
|
+
@staticmethod
|
|
2694
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
2695
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2696
|
+
|
|
2697
|
+
return flu.withdrawal[s]
|
|
2698
|
+
|
|
2699
|
+
|
|
2700
|
+
class Get_SoilWaterContent_V1(modeltools.Method):
|
|
2701
|
+
r"""Get the current soil water content of the selected soil compartment.
|
|
2702
|
+
|
|
2703
|
+
Basic equation:
|
|
2704
|
+
:math:`SoilWaterContent = Moisture_1 \cdot SoilDepth +
|
|
2705
|
+
\sum_{i=2}^{NmbBins} (Moisture_i - Moisture_{i-1}) \cdot FrontDepth_i`
|
|
2706
|
+
|
|
2707
|
+
Example:
|
|
2708
|
+
|
|
2709
|
+
>>> from hydpy.models.ga import *
|
|
2710
|
+
>>> parameterstep()
|
|
2711
|
+
>>> nmbsoils(3)
|
|
2712
|
+
>>> nmbbins(4)
|
|
2713
|
+
>>> sealed(False, False, True)
|
|
2714
|
+
>>> soilarea(1.0, 2.0, 3.0)
|
|
2715
|
+
>>> soildepth(100.0, 200, nan)
|
|
2716
|
+
>>> residualmoisture(0.1, 0.2, nan)
|
|
2717
|
+
>>> saturationmoisture(0.5, 0.8, nan)
|
|
2718
|
+
>>> states.moisture = [[0.3, 0.2, nan],
|
|
2719
|
+
... [0.3, 0.3, nan],
|
|
2720
|
+
... [0.3, 0.5, nan],
|
|
2721
|
+
... [0.3, 0.8, nan]]
|
|
2722
|
+
>>> states.frontdepth = [[100.0, 200.0, nan],
|
|
2723
|
+
... [0.0, 150.0, nan],
|
|
2724
|
+
... [0.0, 100.0, nan],
|
|
2725
|
+
... [0.0, 50.0, nan]]
|
|
2726
|
+
>>> from hydpy import round_
|
|
2727
|
+
>>> round_(model.get_soilwatercontent_v1(0))
|
|
2728
|
+
30.0
|
|
2729
|
+
>>> round_(model.get_soilwatercontent_v1(1))
|
|
2730
|
+
90.0
|
|
2731
|
+
>>> round_(model.get_soilwatercontent_v1(2))
|
|
2732
|
+
0.0
|
|
2733
|
+
"""
|
|
2734
|
+
|
|
2735
|
+
CONTROLPARAMETERS = (ga_control.NmbBins, ga_control.Sealed, ga_control.SoilDepth)
|
|
2736
|
+
REQUIREDSEQUENCES = (ga_states.Moisture, ga_states.FrontDepth)
|
|
2737
|
+
|
|
2738
|
+
@staticmethod
|
|
2739
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
2740
|
+
con = model.parameters.control.fastaccess
|
|
2741
|
+
sta = model.sequences.states.fastaccess
|
|
2742
|
+
|
|
2743
|
+
if con.sealed[s]:
|
|
2744
|
+
return 0.0
|
|
2745
|
+
wc: float = con.soildepth[s] * sta.moisture[0, s]
|
|
2746
|
+
for b in range(1, con.nmbbins):
|
|
2747
|
+
if sta.moisture[b, s] == sta.moisture[0, s]:
|
|
2748
|
+
break
|
|
2749
|
+
wc += sta.frontdepth[b, s] * (sta.moisture[b, s] - sta.moisture[b - 1, s])
|
|
2750
|
+
return wc
|
|
2751
|
+
|
|
2752
|
+
|
|
2753
|
+
class Model(modeltools.AdHocModel):
|
|
2754
|
+
"""|ga.DOCNAME.complete|."""
|
|
2755
|
+
|
|
2756
|
+
DOCNAME = modeltools.DocName(short="GA")
|
|
2757
|
+
__HYDPY_ROOTMODEL__ = None
|
|
2758
|
+
|
|
2759
|
+
INLET_METHODS = ()
|
|
2760
|
+
RECEIVER_METHODS = ()
|
|
2761
|
+
RUN_METHODS = (
|
|
2762
|
+
Calc_SurfaceWaterSupply_V1,
|
|
2763
|
+
Calc_SoilWaterSupply_V1,
|
|
2764
|
+
Calc_Demand_V1,
|
|
2765
|
+
Perform_GARTO_V1,
|
|
2766
|
+
Calc_TotalInfiltration_V1,
|
|
2767
|
+
Calc_TotalPercolation_V1,
|
|
2768
|
+
Calc_TotalSoilWaterAddition_V1,
|
|
2769
|
+
Calc_TotalWithdrawal_V1,
|
|
2770
|
+
Calc_TotalSurfaceRunoff_V1,
|
|
2771
|
+
)
|
|
2772
|
+
INTERFACE_METHODS = (
|
|
2773
|
+
Set_InitialSurfaceWater_V1,
|
|
2774
|
+
Set_ActualSurfaceWater_V1,
|
|
2775
|
+
Set_SoilWaterSupply_V1,
|
|
2776
|
+
Set_SoilWaterDemand_V1,
|
|
2777
|
+
Execute_Infiltration_V1,
|
|
2778
|
+
Add_SoilWater_V1,
|
|
2779
|
+
Remove_SoilWater_V1,
|
|
2780
|
+
Get_Infiltration_V1,
|
|
2781
|
+
Get_Percolation_V1,
|
|
2782
|
+
Get_SoilWaterAddition_V1,
|
|
2783
|
+
Get_SoilWaterRemoval_V1,
|
|
2784
|
+
Get_SoilWaterContent_V1,
|
|
2785
|
+
)
|
|
2786
|
+
ADD_METHODS = (
|
|
2787
|
+
Return_RelativeMoisture_V1,
|
|
2788
|
+
Return_Conductivity_V1,
|
|
2789
|
+
Return_CapillaryDrive_V1,
|
|
2790
|
+
Return_DryDepth_V1,
|
|
2791
|
+
Return_LastActiveBin_V1,
|
|
2792
|
+
Active_Bin_V1,
|
|
2793
|
+
Percolate_FilledBin_V1,
|
|
2794
|
+
Shift_Front_V1,
|
|
2795
|
+
Redistribute_Front_V1,
|
|
2796
|
+
Infiltrate_WettingFrontBins_V1,
|
|
2797
|
+
Merge_FrontDepthOvershootings_V1,
|
|
2798
|
+
Merge_SoilDepthOvershootings_V1,
|
|
2799
|
+
Water_AllBins_V1,
|
|
2800
|
+
Withdraw_AllBins_V1,
|
|
2801
|
+
)
|
|
2802
|
+
OUTLET_METHODS = ()
|
|
2803
|
+
SENDER_METHODS = ()
|
|
2804
|
+
SUBMODELINTERFACES = ()
|
|
2805
|
+
SUBMODELS = ()
|
|
2806
|
+
|
|
2807
|
+
|
|
2808
|
+
class BaseModel(modeltools.AdHocModel):
|
|
2809
|
+
"""General base class for GARTO-like Green-Ampt models."""
|
|
2810
|
+
|
|
2811
|
+
def check_waterbalance(self, initial_conditions: ConditionsModel) -> float:
|
|
2812
|
+
r"""Determine the water balance error of the previous simulation run in mm.
|
|
2813
|
+
|
|
2814
|
+
Method |ga_model.BaseModel.check_waterbalance| calculates the balance error as
|
|
2815
|
+
follows:
|
|
2816
|
+
|
|
2817
|
+
:math:`\sum_{t=t0}^{t1} \big(
|
|
2818
|
+
Rainfall_t - TotalPercolation_t + TotalSoilWaterAddition_t - TotalWithdrawal_t
|
|
2819
|
+
- Percolation_t \big) +b\big( WaterVolume_{t0} - WaterVolume_{t1} \big)`
|
|
2820
|
+
|
|
2821
|
+
The returned error should always be in scale with numerical precision so that
|
|
2822
|
+
it does not affect the simulation results in any relevant manner.
|
|
2823
|
+
|
|
2824
|
+
Pick the required initial conditions before starting the simulation via
|
|
2825
|
+
property |Sequences.conditions|. See the integration tests of the application
|
|
2826
|
+
model |ga_garto| for some examples.
|
|
2827
|
+
"""
|
|
2828
|
+
inputs = self.sequences.inputs
|
|
2829
|
+
fluxes = self.sequences.fluxes
|
|
2830
|
+
first = initial_conditions["model"]["states"]
|
|
2831
|
+
old_watercontent = self._calc_watercontent(
|
|
2832
|
+
frontdepth=first["frontdepth"], # type: ignore[arg-type]
|
|
2833
|
+
moisture=first["moisture"], # type: ignore[arg-type]
|
|
2834
|
+
)
|
|
2835
|
+
return float(
|
|
2836
|
+
numpy.sum(inputs.rainfall.evalseries)
|
|
2837
|
+
+ numpy.sum(fluxes.totalsoilwateraddition.evalseries)
|
|
2838
|
+
- numpy.sum(fluxes.totalpercolation.evalseries)
|
|
2839
|
+
- numpy.sum(fluxes.totalwithdrawal.evalseries)
|
|
2840
|
+
- numpy.sum(fluxes.totalsurfacerunoff.evalseries)
|
|
2841
|
+
+ (old_watercontent - self.watercontent)
|
|
2842
|
+
)
|
|
2843
|
+
|
|
2844
|
+
@property
|
|
2845
|
+
def watercontents(self) -> NDArrayFloat:
|
|
2846
|
+
"""The unique water content of each soil compartment in mm.
|
|
2847
|
+
|
|
2848
|
+
Property |ga_model.BaseModel.watercontents| generally returns zero values for
|
|
2849
|
+
sealed soil compartments:
|
|
2850
|
+
|
|
2851
|
+
>>> from hydpy.models.ga_garto import *
|
|
2852
|
+
>>> parameterstep()
|
|
2853
|
+
>>> nmbsoils(3)
|
|
2854
|
+
>>> nmbbins(4)
|
|
2855
|
+
>>> sealed(False, False, True)
|
|
2856
|
+
>>> soilarea(1.0, 2.0, 3.0)
|
|
2857
|
+
>>> soildepth(100.0, 200, nan)
|
|
2858
|
+
>>> residualmoisture(0.1, 0.2, nan)
|
|
2859
|
+
>>> saturationmoisture(0.5, 0.8, nan)
|
|
2860
|
+
>>> derived.soilareafraction.update()
|
|
2861
|
+
>>> states.moisture = [[0.3, 0.2, nan],
|
|
2862
|
+
... [0.3, 0.3, nan],
|
|
2863
|
+
... [0.3, 0.5, nan],
|
|
2864
|
+
... [0.3, 0.8, nan]]
|
|
2865
|
+
>>> states.frontdepth = [[100.0, 200.0, nan],
|
|
2866
|
+
... [0.0, 150.0, nan],
|
|
2867
|
+
... [0.0, 100.0, nan],
|
|
2868
|
+
... [0.0, 50.0, nan]]
|
|
2869
|
+
>>> from hydpy import print_vector
|
|
2870
|
+
>>> print_vector(model.watercontents)
|
|
2871
|
+
30.0, 90.0, 0.0
|
|
2872
|
+
"""
|
|
2873
|
+
states = self.sequences.states
|
|
2874
|
+
return self._calc_watercontents(
|
|
2875
|
+
frontdepth=states.frontdepth.values, moisture=states.moisture.values
|
|
2876
|
+
)
|
|
2877
|
+
|
|
2878
|
+
@property
|
|
2879
|
+
def watercontent(self) -> float:
|
|
2880
|
+
"""The average water content of all soil compartments in mm.
|
|
2881
|
+
|
|
2882
|
+
Property |ga_model.BaseModel.watercontent| includes sealed soil compartments in
|
|
2883
|
+
the average, which is why the presence of sealing reduces the returned value:
|
|
2884
|
+
|
|
2885
|
+
>>> from hydpy.models.ga_garto import *
|
|
2886
|
+
>>> parameterstep()
|
|
2887
|
+
>>> nmbsoils(3)
|
|
2888
|
+
>>> nmbbins(4)
|
|
2889
|
+
>>> sealed(False, False, True)
|
|
2890
|
+
>>> soilarea(1.0, 2.0, 3.0)
|
|
2891
|
+
>>> soildepth(100.0, 200, nan)
|
|
2892
|
+
>>> residualmoisture(0.1, 0.2, nan)
|
|
2893
|
+
>>> saturationmoisture(0.5, 0.8, nan)
|
|
2894
|
+
>>> derived.soilareafraction.update()
|
|
2895
|
+
>>> states.moisture = [[0.3, 0.2, nan],
|
|
2896
|
+
... [0.3, 0.3, nan],
|
|
2897
|
+
... [0.3, 0.5, nan],
|
|
2898
|
+
... [0.3, 0.8, nan]]
|
|
2899
|
+
>>> states.frontdepth = [[100.0, 200.0, nan],
|
|
2900
|
+
... [0.0, 150.0, nan],
|
|
2901
|
+
... [0.0, 100.0, nan],
|
|
2902
|
+
... [0.0, 50.0, nan]]
|
|
2903
|
+
>>> from hydpy import round_
|
|
2904
|
+
>>> round_(model.watercontent)
|
|
2905
|
+
35.0
|
|
2906
|
+
|
|
2907
|
+
>>> soilarea(1.0, 2.0, 0.0)
|
|
2908
|
+
>>> derived.soilareafraction.update()
|
|
2909
|
+
>>> round_(model.watercontent)
|
|
2910
|
+
70.0
|
|
2911
|
+
"""
|
|
2912
|
+
states = self.sequences.states
|
|
2913
|
+
return self._calc_watercontent(
|
|
2914
|
+
frontdepth=states.frontdepth.values, moisture=states.moisture.values
|
|
2915
|
+
)
|
|
2916
|
+
|
|
2917
|
+
def _calc_watercontents(
|
|
2918
|
+
self, frontdepth: NDArrayFloat, moisture: NDArrayFloat
|
|
2919
|
+
) -> NDArrayFloat:
|
|
2920
|
+
frontdepth = frontdepth.copy()
|
|
2921
|
+
frontdepth[0, :] = self.parameters.control.soildepth.values
|
|
2922
|
+
deltamoisture = numpy.diff(moisture, axis=0, prepend=0.0)
|
|
2923
|
+
deltamoisture = numpy.clip(deltamoisture, 0.0, numpy.inf)
|
|
2924
|
+
watercontents = numpy.sum(frontdepth * deltamoisture, axis=0)
|
|
2925
|
+
watercontents[self.parameters.control.sealed.values] = 0.0
|
|
2926
|
+
return watercontents
|
|
2927
|
+
|
|
2928
|
+
def _calc_watercontent(
|
|
2929
|
+
self, frontdepth: NDArrayFloat, moisture: NDArrayFloat
|
|
2930
|
+
) -> float:
|
|
2931
|
+
weights = self.parameters.derived.soilareafraction.values
|
|
2932
|
+
watercontents = self._calc_watercontents(
|
|
2933
|
+
frontdepth=frontdepth, moisture=moisture
|
|
2934
|
+
)
|
|
2935
|
+
return numpy.nansum(weights * watercontents)
|
|
2936
|
+
|
|
2937
|
+
|
|
2938
|
+
class Base_SoilModel_V1(BaseModel, soilinterfaces.SoilModel_V1):
|
|
2939
|
+
"""Base class for |ga.DOCNAME.long| models that comply with the |SoilModel_V1|
|
|
2940
|
+
submodel interface."""
|
|
2941
|
+
|
|
2942
|
+
@importtools.define_targetparameter(ga_control.NmbSoils)
|
|
2943
|
+
def prepare_nmbzones(self, nmbzones: int) -> None:
|
|
2944
|
+
"""Set the number of soil compartments.
|
|
2945
|
+
|
|
2946
|
+
>>> from hydpy.models.ga_garto_submodel1 import *
|
|
2947
|
+
>>> parameterstep()
|
|
2948
|
+
>>> model.prepare_nmbzones(2)
|
|
2949
|
+
>>> nmbsoils
|
|
2950
|
+
nmbsoils(2)
|
|
2951
|
+
"""
|
|
2952
|
+
self.parameters.control.nmbsoils(nmbzones)
|