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,4664 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. _`issue 68`: https://github.com/hydpy-dev/hydpy/issues/68
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# imports...
|
|
6
|
+
# ...from site-packages
|
|
7
|
+
import numpy
|
|
8
|
+
|
|
9
|
+
# ...from HydPy
|
|
10
|
+
from hydpy import config
|
|
11
|
+
from hydpy.core import importtools
|
|
12
|
+
from hydpy.core import modeltools
|
|
13
|
+
from hydpy.cythons import modelutils
|
|
14
|
+
from hydpy.core.typingtools import *
|
|
15
|
+
from hydpy.interfaces import aetinterfaces
|
|
16
|
+
from hydpy.interfaces import precipinterfaces
|
|
17
|
+
from hydpy.interfaces import rconcinterfaces
|
|
18
|
+
from hydpy.interfaces import tempinterfaces
|
|
19
|
+
from hydpy.interfaces import stateinterfaces
|
|
20
|
+
|
|
21
|
+
# ...from hland
|
|
22
|
+
from hydpy.models.hland import hland_constants
|
|
23
|
+
from hydpy.models.hland.hland_constants import FIELD, FOREST, GLACIER, ILAKE, SEALED
|
|
24
|
+
from hydpy.models.hland import hland_control
|
|
25
|
+
from hydpy.models.hland import hland_derived
|
|
26
|
+
from hydpy.models.hland import hland_fixed
|
|
27
|
+
from hydpy.models.hland import hland_inputs
|
|
28
|
+
from hydpy.models.hland import hland_factors
|
|
29
|
+
from hydpy.models.hland import hland_fluxes
|
|
30
|
+
from hydpy.models.hland import hland_states
|
|
31
|
+
from hydpy.models.hland import hland_aides
|
|
32
|
+
from hydpy.models.hland import hland_outlets
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Calc_TC_V1(modeltools.Method):
|
|
36
|
+
r"""Adjust the measured air temperature to the altitude of the individual zones.
|
|
37
|
+
|
|
38
|
+
Basic equation:
|
|
39
|
+
:math:`TC = T + TCorr - TCAlt \cdot (ZoneZ - Z)`
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
|
|
43
|
+
Prepare two zones, the first lying at the reference height and the second 200
|
|
44
|
+
meters above:
|
|
45
|
+
|
|
46
|
+
>>> from hydpy.models.hland import *
|
|
47
|
+
>>> simulationstep("12h")
|
|
48
|
+
>>> parameterstep("1d")
|
|
49
|
+
>>> nmbzones(2)
|
|
50
|
+
>>> zonez(2.0, 4.0)
|
|
51
|
+
>>> derived.z(2.0)
|
|
52
|
+
|
|
53
|
+
Applying the usual temperature lapse rate of 0.6°C/100m does not affect the
|
|
54
|
+
first zone but reduces the temperature of the second zone by 1.2°C:
|
|
55
|
+
|
|
56
|
+
>>> tcorr(1.0)
|
|
57
|
+
>>> tcalt(0.6)
|
|
58
|
+
>>> inputs.t = 5.0
|
|
59
|
+
>>> model.calc_tc_v1()
|
|
60
|
+
>>> factors.tc
|
|
61
|
+
tc(6.0, 4.8)
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
CONTROLPARAMETERS = (
|
|
65
|
+
hland_control.NmbZones,
|
|
66
|
+
hland_control.TCorr,
|
|
67
|
+
hland_control.TCAlt,
|
|
68
|
+
hland_control.ZoneZ,
|
|
69
|
+
)
|
|
70
|
+
DERIVEDPARAMETERS = (hland_derived.Z,)
|
|
71
|
+
REQUIREDSEQUENCES = (hland_inputs.T,)
|
|
72
|
+
RESULTSEQUENCES = (hland_factors.TC,)
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def __call__(model: modeltools.Model) -> None:
|
|
76
|
+
con = model.parameters.control.fastaccess
|
|
77
|
+
der = model.parameters.derived.fastaccess
|
|
78
|
+
inp = model.sequences.inputs.fastaccess
|
|
79
|
+
fac = model.sequences.factors.fastaccess
|
|
80
|
+
for k in range(con.nmbzones):
|
|
81
|
+
fac.tc[k] = inp.t + con.tcorr[k] - con.tcalt[k] * (con.zonez[k] - der.z)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class Calc_FracRain_V1(modeltools.Method):
|
|
85
|
+
r"""Determine the temperature-dependent fraction of (liquid) rainfall
|
|
86
|
+
and (total) precipitation.
|
|
87
|
+
|
|
88
|
+
Basic equation:
|
|
89
|
+
:math:`FracRain = \frac{TC-(TT-\frac{TTInt}{2})}{TTInt}`
|
|
90
|
+
|
|
91
|
+
Restriction:
|
|
92
|
+
:math:`0 \leq FracRain \leq 1`
|
|
93
|
+
|
|
94
|
+
Examples:
|
|
95
|
+
|
|
96
|
+
The threshold temperature of seven zones is 0°C, and the corresponding
|
|
97
|
+
temperature interval of mixed precipitation 2°C:
|
|
98
|
+
|
|
99
|
+
>>> from hydpy.models.hland import *
|
|
100
|
+
>>> simulationstep("12h")
|
|
101
|
+
>>> parameterstep("1d")
|
|
102
|
+
>>> nmbzones(7)
|
|
103
|
+
>>> tt(0.0)
|
|
104
|
+
>>> ttint(2.0)
|
|
105
|
+
|
|
106
|
+
The fraction of rainfall is zero below -1°C, is one above 1°C, and increases
|
|
107
|
+
linearly in between:
|
|
108
|
+
|
|
109
|
+
>>> factors.tc = -10.0, -1.0, -0.5, 0.0, 0.5, 1.0, 10.0
|
|
110
|
+
>>> model.calc_fracrain_v1()
|
|
111
|
+
>>> factors.fracrain
|
|
112
|
+
fracrain(0.0, 0.0, 0.25, 0.5, 0.75, 1.0, 1.0)
|
|
113
|
+
|
|
114
|
+
Note the particular case of a zero temperature interval. With an actual
|
|
115
|
+
temperature being equal to the threshold temperature, the rainfall fraction
|
|
116
|
+
is one:
|
|
117
|
+
|
|
118
|
+
>>> ttint(0.0)
|
|
119
|
+
>>> model.calc_fracrain_v1()
|
|
120
|
+
>>> factors.fracrain
|
|
121
|
+
fracrain(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0)
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.TT, hland_control.TTInt)
|
|
125
|
+
REQUIREDSEQUENCES = (hland_factors.TC,)
|
|
126
|
+
RESULTSEQUENCES = (hland_factors.FracRain,)
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def __call__(model: modeltools.Model) -> None:
|
|
130
|
+
con = model.parameters.control.fastaccess
|
|
131
|
+
fac = model.sequences.factors.fastaccess
|
|
132
|
+
for k in range(con.nmbzones):
|
|
133
|
+
d_dt = con.ttint[k] / 2.0
|
|
134
|
+
if fac.tc[k] >= (con.tt[k] + d_dt):
|
|
135
|
+
fac.fracrain[k] = 1.0
|
|
136
|
+
elif fac.tc[k] <= (con.tt[k] - d_dt):
|
|
137
|
+
fac.fracrain[k] = 0.0
|
|
138
|
+
else:
|
|
139
|
+
fac.fracrain[k] = (fac.tc[k] - (con.tt[k] - d_dt)) / con.ttint[k]
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class Calc_RFC_SFC_V1(modeltools.Method):
|
|
143
|
+
r"""Calculate the corrected fractions of rainfall/snowfall and total precipitation.
|
|
144
|
+
|
|
145
|
+
Basic equations:
|
|
146
|
+
:math:`RfC = RfCF \cdot FracRain`
|
|
147
|
+
|
|
148
|
+
:math:`SfC = SfCF \cdot (1 - FracRain)`
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
|
|
152
|
+
Assume five zones with different temperatures and hence different fractions of
|
|
153
|
+
rainfall and total precipitation:
|
|
154
|
+
|
|
155
|
+
>>> from hydpy.models.hland import *
|
|
156
|
+
>>> simulationstep("12h")
|
|
157
|
+
>>> parameterstep("1d")
|
|
158
|
+
>>> nmbzones(5)
|
|
159
|
+
>>> factors.fracrain = 0.0, 0.25, 0.5, 0.75, 1.0
|
|
160
|
+
|
|
161
|
+
With no rainfall and no snowfall correction (due to the respective factors
|
|
162
|
+
being one), the corrected fraction related to rain is identical to the original
|
|
163
|
+
fraction, while the corrected fraction related to snow behaves the opposite:
|
|
164
|
+
|
|
165
|
+
>>> rfcf(1.0)
|
|
166
|
+
>>> sfcf(1.0)
|
|
167
|
+
>>> model.calc_rfc_sfc_v1()
|
|
168
|
+
>>> factors.rfc
|
|
169
|
+
rfc(0.0, 0.25, 0.5, 0.75, 1.0)
|
|
170
|
+
>>> factors.sfc
|
|
171
|
+
sfc(1.0, 0.75, 0.5, 0.25, 0.0)
|
|
172
|
+
|
|
173
|
+
With a rainfall reduction of 20% and a snowfall increase of 20 %, the corrected
|
|
174
|
+
fractions are as follows:
|
|
175
|
+
|
|
176
|
+
>>> rfcf(0.8)
|
|
177
|
+
>>> sfcf(1.2)
|
|
178
|
+
>>> model.calc_rfc_sfc_v1()
|
|
179
|
+
>>> factors.rfc
|
|
180
|
+
rfc(0.0, 0.2, 0.4, 0.6, 0.8)
|
|
181
|
+
>>> factors.sfc
|
|
182
|
+
sfc(1.2, 0.9, 0.6, 0.3, 0.0)
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.RfCF, hland_control.SfCF)
|
|
186
|
+
REQUIREDSEQUENCES = (hland_factors.FracRain,)
|
|
187
|
+
RESULTSEQUENCES = (hland_factors.RfC, hland_factors.SfC)
|
|
188
|
+
|
|
189
|
+
@staticmethod
|
|
190
|
+
def __call__(model: modeltools.Model) -> None:
|
|
191
|
+
con = model.parameters.control.fastaccess
|
|
192
|
+
fac = model.sequences.factors.fastaccess
|
|
193
|
+
for k in range(con.nmbzones):
|
|
194
|
+
fac.rfc[k] = fac.fracrain[k] * con.rfcf[k]
|
|
195
|
+
fac.sfc[k] = (1.0 - fac.fracrain[k]) * con.sfcf[k]
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class Calc_PC_V1(modeltools.Method):
|
|
199
|
+
r"""Apply the precipitation correction factors and adjust precipitation to the
|
|
200
|
+
altitude of the individual zones.
|
|
201
|
+
|
|
202
|
+
Basic equation:
|
|
203
|
+
:math:`PC = P \cdot PCorr \cdot (1 + PCAlt \cdot (ZoneZ - Z)) \cdot (RfC + SfC)`
|
|
204
|
+
|
|
205
|
+
Examples:
|
|
206
|
+
|
|
207
|
+
Five zones are at an elevation of 200 m. A precipitation value of 5 mm has
|
|
208
|
+
been measured at a gauge at an elevation of 300 m:
|
|
209
|
+
|
|
210
|
+
>>> from hydpy.models.hland import *
|
|
211
|
+
>>> simulationstep("12h")
|
|
212
|
+
>>> parameterstep("1d")
|
|
213
|
+
>>> nmbzones(5)
|
|
214
|
+
>>> zonez(3.0)
|
|
215
|
+
>>> inputs.p = 5.0
|
|
216
|
+
>>> derived.z(2.0)
|
|
217
|
+
|
|
218
|
+
The first four zones illustrate the individual precipitation corrections due to
|
|
219
|
+
the general (|PCorr|, first zone), the altitude (|PCAlt|, second zone), the
|
|
220
|
+
rainfall (|RfC|, third zone), and the snowfall adjustment (|SfC|, fourth zone).
|
|
221
|
+
The fifth zone illustrates the interaction between all corrections:
|
|
222
|
+
|
|
223
|
+
>>> pcorr(1.3, 1.0, 1.0, 1.0, 1.3)
|
|
224
|
+
>>> pcalt(0.0, 0.1, 0.0, 0.0, 0.1)
|
|
225
|
+
>>> factors.rfc = 0.5, 0.5, 0.4, 0.5, 0.4
|
|
226
|
+
>>> factors.sfc = 0.5, 0.5, 0.5, 0.7, 0.7
|
|
227
|
+
>>> model.calc_pc_v1()
|
|
228
|
+
>>> fluxes.pc
|
|
229
|
+
pc(6.5, 5.5, 4.5, 6.0, 7.865)
|
|
230
|
+
|
|
231
|
+
Usually, one would set zero or positive values for parameter |PCAlt|. But it
|
|
232
|
+
is also allowed to assign negative values to reflect possible negative
|
|
233
|
+
relationships between precipitation and altitude. Method |Calc_PC_V1| performs
|
|
234
|
+
the required truncations to prevent negative precipitation values:
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
>>> pcalt(-1.0)
|
|
238
|
+
>>> model.calc_pc_v1()
|
|
239
|
+
>>> fluxes.pc
|
|
240
|
+
pc(0.0, 0.0, 0.0, 0.0, 0.0)
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
CONTROLPARAMETERS = (
|
|
244
|
+
hland_control.NmbZones,
|
|
245
|
+
hland_control.PCAlt,
|
|
246
|
+
hland_control.ZoneZ,
|
|
247
|
+
hland_control.PCorr,
|
|
248
|
+
)
|
|
249
|
+
DERIVEDPARAMETERS = (hland_derived.Z,)
|
|
250
|
+
REQUIREDSEQUENCES = (hland_inputs.P, hland_factors.RfC, hland_factors.SfC)
|
|
251
|
+
RESULTSEQUENCES = (hland_fluxes.PC,)
|
|
252
|
+
|
|
253
|
+
@staticmethod
|
|
254
|
+
def __call__(model: modeltools.Model) -> None:
|
|
255
|
+
con = model.parameters.control.fastaccess
|
|
256
|
+
der = model.parameters.derived.fastaccess
|
|
257
|
+
inp = model.sequences.inputs.fastaccess
|
|
258
|
+
fac = model.sequences.factors.fastaccess
|
|
259
|
+
flu = model.sequences.fluxes.fastaccess
|
|
260
|
+
for k in range(con.nmbzones):
|
|
261
|
+
flu.pc[k] = inp.p * (1.0 + con.pcalt[k] * (con.zonez[k] - der.z))
|
|
262
|
+
if flu.pc[k] <= 0.0:
|
|
263
|
+
flu.pc[k] = 0.0
|
|
264
|
+
else:
|
|
265
|
+
flu.pc[k] *= con.pcorr[k] * (fac.rfc[k] + fac.sfc[k])
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class Calc_TF_Ic_V1(modeltools.Method):
|
|
269
|
+
r"""Calculate throughfall and update the interception storage accordingly.
|
|
270
|
+
|
|
271
|
+
Basic equation:
|
|
272
|
+
.. math::
|
|
273
|
+
TF =
|
|
274
|
+
\begin{cases}
|
|
275
|
+
PC &|\ Ic = IcMax
|
|
276
|
+
\\
|
|
277
|
+
0 &|\ Ic < IcMax
|
|
278
|
+
\end{cases}
|
|
279
|
+
|
|
280
|
+
Examples:
|
|
281
|
+
|
|
282
|
+
Initialise seven zones of different types. Assume a general interception
|
|
283
|
+
capacity of 2 mm. All zones receive a precipitation input of 0.5 mm:
|
|
284
|
+
|
|
285
|
+
>>> from hydpy.models.hland import *
|
|
286
|
+
>>> simulationstep("12h")
|
|
287
|
+
>>> parameterstep("1d")
|
|
288
|
+
>>> nmbzones(7)
|
|
289
|
+
>>> zonetype(GLACIER, ILAKE, FIELD, FOREST, SEALED, SEALED, SEALED)
|
|
290
|
+
>>> icmax(2.0)
|
|
291
|
+
>>> fluxes.pc = 0.5
|
|
292
|
+
>>> states.ic = 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0
|
|
293
|
+
>>> model.calc_tf_ic_v1()
|
|
294
|
+
|
|
295
|
+
The interception routine does not apply to glaciers (first zone) and internal
|
|
296
|
+
lakes (second zone). Hence, all precipitation becomes throughfall. For fields,
|
|
297
|
+
forests, and sealed areas, the interception routine works identical, so the
|
|
298
|
+
results of zone three to five are equal. The last three zones demonstrate that
|
|
299
|
+
all precipitation is stored until the intercepted water reaches the available
|
|
300
|
+
capacity; afterwards, all precipitation becomes throughfall. Initial storage
|
|
301
|
+
reduces the effective capacity of the respective simulation step:
|
|
302
|
+
|
|
303
|
+
>>> states.ic
|
|
304
|
+
ic(0.0, 0.0, 0.5, 0.5, 0.5, 1.5, 2.0)
|
|
305
|
+
>>> fluxes.tf
|
|
306
|
+
tf(0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5)
|
|
307
|
+
|
|
308
|
+
A zero precipitation example:
|
|
309
|
+
|
|
310
|
+
>>> fluxes.pc = 0.0
|
|
311
|
+
>>> states.ic = 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0
|
|
312
|
+
>>> model.calc_tf_ic_v1()
|
|
313
|
+
>>> states.ic
|
|
314
|
+
ic(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0)
|
|
315
|
+
>>> fluxes.tf
|
|
316
|
+
tf(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
317
|
+
|
|
318
|
+
A high precipitation example:
|
|
319
|
+
|
|
320
|
+
>>> fluxes.pc = 5.0
|
|
321
|
+
>>> states.ic = 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0
|
|
322
|
+
>>> model.calc_tf_ic_v1()
|
|
323
|
+
>>> states.ic
|
|
324
|
+
ic(0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 2.0)
|
|
325
|
+
>>> fluxes.tf
|
|
326
|
+
tf(5.0, 5.0, 3.0, 3.0, 3.0, 4.0, 5.0)
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
CONTROLPARAMETERS = (
|
|
330
|
+
hland_control.NmbZones,
|
|
331
|
+
hland_control.ZoneType,
|
|
332
|
+
hland_control.IcMax,
|
|
333
|
+
)
|
|
334
|
+
REQUIREDSEQUENCES = (hland_fluxes.PC,)
|
|
335
|
+
UPDATEDSEQUENCES = (hland_states.Ic,)
|
|
336
|
+
RESULTSEQUENCES = (hland_fluxes.TF,)
|
|
337
|
+
|
|
338
|
+
@staticmethod
|
|
339
|
+
def __call__(model: modeltools.Model) -> None:
|
|
340
|
+
con = model.parameters.control.fastaccess
|
|
341
|
+
flu = model.sequences.fluxes.fastaccess
|
|
342
|
+
sta = model.sequences.states.fastaccess
|
|
343
|
+
for k in range(con.nmbzones):
|
|
344
|
+
if con.zonetype[k] in (FIELD, FOREST, SEALED):
|
|
345
|
+
flu.tf[k] = max(flu.pc[k] - (con.icmax[k] - sta.ic[k]), 0.0)
|
|
346
|
+
sta.ic[k] += flu.pc[k] - flu.tf[k]
|
|
347
|
+
else:
|
|
348
|
+
flu.tf[k] = flu.pc[k]
|
|
349
|
+
sta.ic[k] = 0.0
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class Calc_EI_Ic_AETModel_V1(modeltools.Method):
|
|
353
|
+
r"""Let a submodel that follows the |AETModel_V1| submodel interface calculate
|
|
354
|
+
interception evaporation and adjust the amount of intercepted water.
|
|
355
|
+
|
|
356
|
+
Basic equation:
|
|
357
|
+
:math:`\frac{dIc_i}{dt} = -EI_i`
|
|
358
|
+
|
|
359
|
+
Examples:
|
|
360
|
+
|
|
361
|
+
We build an example based on |evap_aet_hbv96| for calculating interception
|
|
362
|
+
evaporation, which uses |evap_ret_io| for querying potential
|
|
363
|
+
evapotranspiration:
|
|
364
|
+
|
|
365
|
+
>>> from hydpy.models.hland_96 import *
|
|
366
|
+
>>> parameterstep("1h")
|
|
367
|
+
>>> nmbzones(5)
|
|
368
|
+
>>> zonetype(GLACIER, SEALED, FIELD, FOREST, ILAKE)
|
|
369
|
+
>>> area(1.0)
|
|
370
|
+
>>> zonearea(0.05, 0.1, 0.2, 0.3, 0.35)
|
|
371
|
+
>>> zonez(5.0)
|
|
372
|
+
>>> icmax(3.0)
|
|
373
|
+
>>> fc(50.0)
|
|
374
|
+
>>> fluxes.tf = 0.5
|
|
375
|
+
>>> with model.add_aetmodel_v1("evap_aet_hbv96"):
|
|
376
|
+
... with model.add_petmodel_v1("evap_ret_io"):
|
|
377
|
+
... evapotranspirationfactor(0.6, 0.8, 1.0, 1.2, 1.4)
|
|
378
|
+
... inputs.referenceevapotranspiration = 1.0
|
|
379
|
+
|
|
380
|
+
|Calc_EI_Ic_AETModel_V1| uses the flux returned by the submodel to adjust |Ic|:
|
|
381
|
+
|
|
382
|
+
>>> states.ic = 2.0
|
|
383
|
+
>>> model.calc_ei_ic_v1()
|
|
384
|
+
>>> fluxes.ei
|
|
385
|
+
ei(0.0, 0.8, 1.0, 1.2, 0.0)
|
|
386
|
+
>>> states.ic
|
|
387
|
+
ic(0.0, 1.2, 1.0, 0.8, 0.0)
|
|
388
|
+
>>> fluxes.tf
|
|
389
|
+
tf(0.5, 0.5, 0.5, 0.5, 0.5)
|
|
390
|
+
|
|
391
|
+
|Calc_EI_Ic_AETModel_V1| eventually reduces |EI| so that |Ic| does not become
|
|
392
|
+
negative:
|
|
393
|
+
|
|
394
|
+
>>> model.aetmodel.petmodel.sequences.inputs.referenceevapotranspiration = 5.0
|
|
395
|
+
>>> states.ic = 2.0
|
|
396
|
+
>>> model.calc_ei_ic_v1()
|
|
397
|
+
>>> fluxes.ei
|
|
398
|
+
ei(0.0, 2.0, 2.0, 2.0, 0.0)
|
|
399
|
+
>>> states.ic
|
|
400
|
+
ic(0.0, 0.0, 0.0, 0.0, 0.0)
|
|
401
|
+
>>> fluxes.tf
|
|
402
|
+
tf(0.5, 0.5, 0.5, 0.5, 0.5)
|
|
403
|
+
|
|
404
|
+
In contrast, |Calc_EI_Ic_AETModel_V1| does not reduce negative |EI| values
|
|
405
|
+
(condensation) that cause an overshoot of the interception storage capacity:
|
|
406
|
+
|
|
407
|
+
>>> model.aetmodel.petmodel.sequences.inputs.referenceevapotranspiration = -3.0
|
|
408
|
+
>>> states.ic = 2.0
|
|
409
|
+
>>> model.calc_ei_ic_v1()
|
|
410
|
+
>>> fluxes.ei
|
|
411
|
+
ei(0.0, -2.4, -3.0, -3.6, 0.0)
|
|
412
|
+
>>> states.ic
|
|
413
|
+
ic(0.0, 4.4, 5.0, 5.6, 0.0)
|
|
414
|
+
>>> fluxes.tf
|
|
415
|
+
tf(0.5, 0.5, 0.5, 0.5, 0.5)
|
|
416
|
+
"""
|
|
417
|
+
|
|
418
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
419
|
+
UPDATEDSEQUENCES = (hland_states.Ic,)
|
|
420
|
+
RESULTSEQUENCES = (hland_fluxes.EI,)
|
|
421
|
+
|
|
422
|
+
@staticmethod
|
|
423
|
+
def __call__(model: modeltools.Model, submodel: aetinterfaces.AETModel_V1) -> None:
|
|
424
|
+
con = model.parameters.control.fastaccess
|
|
425
|
+
flu = model.sequences.fluxes.fastaccess
|
|
426
|
+
sta = model.sequences.states.fastaccess
|
|
427
|
+
submodel.determine_interceptionevaporation()
|
|
428
|
+
for k in range(con.nmbzones):
|
|
429
|
+
if con.zonetype[k] in (FIELD, FOREST, SEALED):
|
|
430
|
+
flu.ei[k] = min(submodel.get_interceptionevaporation(k), sta.ic[k])
|
|
431
|
+
sta.ic[k] -= flu.ei[k]
|
|
432
|
+
else:
|
|
433
|
+
flu.ei[k] = 0.0
|
|
434
|
+
sta.ic[k] = 0.0
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class Calc_EI_Ic_V1(modeltools.Method):
|
|
438
|
+
"""Let a submodel that follows the |AETModel_V1| submodel interface calculate
|
|
439
|
+
interception evaporation and adjust the amount of intercepted water."""
|
|
440
|
+
|
|
441
|
+
SUBMODELINTERFACES = (aetinterfaces.AETModel_V1,)
|
|
442
|
+
SUBMETHODS = (Calc_EI_Ic_AETModel_V1,)
|
|
443
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
444
|
+
UPDATEDSEQUENCES = (hland_states.Ic,)
|
|
445
|
+
RESULTSEQUENCES = (hland_fluxes.EI,)
|
|
446
|
+
|
|
447
|
+
@staticmethod
|
|
448
|
+
def __call__(model: modeltools.Model) -> None:
|
|
449
|
+
if model.aetmodel_typeid == 1:
|
|
450
|
+
model.calc_ei_ic_aetmodel_v1(
|
|
451
|
+
cast(aetinterfaces.AETModel_V1, model.aetmodel)
|
|
452
|
+
)
|
|
453
|
+
# ToDo:
|
|
454
|
+
# else:
|
|
455
|
+
# assert_never(model.petmodel)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
class Calc_SP_WC_V1(modeltools.Method):
|
|
459
|
+
r"""Add throughfall to the snow layer.
|
|
460
|
+
|
|
461
|
+
Basic equations:
|
|
462
|
+
:math:`\frac{dSP}{dt} = SFDist \cdot TF \cdot \frac{SfC}{SfC + RfC}`
|
|
463
|
+
|
|
464
|
+
:math:`\frac{dWC}{dt} = SFDist \cdot TF \cdot \frac{RfC}{SfC + RfC}`
|
|
465
|
+
|
|
466
|
+
Examples:
|
|
467
|
+
|
|
468
|
+
Consider the following setting, in which nine zones of different types receive
|
|
469
|
+
a throughfall of 10 mm:
|
|
470
|
+
|
|
471
|
+
>>> from hydpy.models.hland import *
|
|
472
|
+
>>> simulationstep("12h")
|
|
473
|
+
>>> parameterstep("1d")
|
|
474
|
+
>>> nmbzones(9)
|
|
475
|
+
>>> sclass(1)
|
|
476
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED, FIELD, FIELD, FIELD, FIELD)
|
|
477
|
+
>>> sfdist(0.2)
|
|
478
|
+
>>> fluxes.tf = 10.0
|
|
479
|
+
>>> factors.sfc = 0.5, 0.5, 0.5, 0.5, 0.5, 0.2, 0.8, 1.0, 4.0
|
|
480
|
+
>>> factors.rfc = 0.5, 0.5, 0.5, 0.5, 0.5, 0.8, 0.2, 4.0, 1.0
|
|
481
|
+
>>> states.sp = 2.0
|
|
482
|
+
>>> states.wc = 1.0
|
|
483
|
+
>>> model.calc_sp_wc_v1()
|
|
484
|
+
>>> states.sp
|
|
485
|
+
sp(0.0, 7.0, 7.0, 7.0, 7.0, 4.0, 10.0, 4.0, 10.0)
|
|
486
|
+
>>> states.wc
|
|
487
|
+
wc(0.0, 6.0, 6.0, 6.0, 6.0, 9.0, 3.0, 9.0, 3.0)
|
|
488
|
+
|
|
489
|
+
The snow routine does not apply to internal lakes, which is why both the ice
|
|
490
|
+
storage and the water storage of the first zone remain unchanged. The snow
|
|
491
|
+
routine is identical for fields, forests, sealed areas, and glaciers (besides
|
|
492
|
+
the additional glacier melt), which is why the results zone three to five are
|
|
493
|
+
equal. The last four zones illustrate that method |Calc_SP_WC_V1| applies the
|
|
494
|
+
corrected snowfall and rainfall fractions "relatively", considering that the
|
|
495
|
+
throughfall is already corrected.
|
|
496
|
+
|
|
497
|
+
When both factors are zero, neither the water nor the ice content of the snow
|
|
498
|
+
layer changes:
|
|
499
|
+
|
|
500
|
+
>>> factors.sfc = 0.0
|
|
501
|
+
>>> factors.rfc = 0.0
|
|
502
|
+
>>> states.sp = 2.0
|
|
503
|
+
>>> states.wc = 1.0
|
|
504
|
+
>>> model.calc_sp_wc_v1()
|
|
505
|
+
>>> states.sp
|
|
506
|
+
sp(0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0)
|
|
507
|
+
>>> states.wc
|
|
508
|
+
wc(0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
|
|
509
|
+
|
|
510
|
+
In the above examples, we did not divide the zones into snow classes. If we do
|
|
511
|
+
so, method |Calc_SP_WC_V1| adds different amounts of snow and rainfall to the
|
|
512
|
+
individual snow classes based on the current values of parameter |SFDist|:
|
|
513
|
+
|
|
514
|
+
>>> sclass(2)
|
|
515
|
+
>>> sfdist(0.0, 2.0)
|
|
516
|
+
>>> factors.sfc = 0.5, 0.5, 0.5, 0.5, 0.5, 0.2, 0.8, 1.0, 4.0
|
|
517
|
+
>>> factors.rfc = 0.5, 0.5, 0.5, 0.5, 0.5, 0.8, 0.2, 4.0, 1.0
|
|
518
|
+
>>> states.sp = 2.0
|
|
519
|
+
>>> states.wc = 1.0
|
|
520
|
+
>>> model.calc_sp_wc_v1()
|
|
521
|
+
>>> states.sp
|
|
522
|
+
sp([[0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0],
|
|
523
|
+
[0.0, 12.0, 12.0, 12.0, 12.0, 6.0, 18.0, 6.0, 18.0]])
|
|
524
|
+
>>> states.wc
|
|
525
|
+
wc([[0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
|
|
526
|
+
[0.0, 11.0, 11.0, 11.0, 11.0, 17.0, 5.0, 17.0, 5.0]])
|
|
527
|
+
"""
|
|
528
|
+
|
|
529
|
+
CONTROLPARAMETERS = (
|
|
530
|
+
hland_control.NmbZones,
|
|
531
|
+
hland_control.SClass,
|
|
532
|
+
hland_control.ZoneType,
|
|
533
|
+
hland_control.SFDist,
|
|
534
|
+
)
|
|
535
|
+
REQUIREDSEQUENCES = (hland_fluxes.TF, hland_factors.RfC, hland_factors.SfC)
|
|
536
|
+
UPDATEDSEQUENCES = (hland_states.WC, hland_states.SP)
|
|
537
|
+
|
|
538
|
+
@staticmethod
|
|
539
|
+
def __call__(model: modeltools.Model) -> None:
|
|
540
|
+
con = model.parameters.control.fastaccess
|
|
541
|
+
fac = model.sequences.factors.fastaccess
|
|
542
|
+
flu = model.sequences.fluxes.fastaccess
|
|
543
|
+
sta = model.sequences.states.fastaccess
|
|
544
|
+
for k in range(con.nmbzones):
|
|
545
|
+
if con.zonetype[k] != ILAKE:
|
|
546
|
+
d_denom = fac.rfc[k] + fac.sfc[k]
|
|
547
|
+
if d_denom > 0.0:
|
|
548
|
+
d_rain = flu.tf[k] * fac.rfc[k] / d_denom
|
|
549
|
+
d_snow = flu.tf[k] * fac.sfc[k] / d_denom
|
|
550
|
+
for c in range(con.sclass):
|
|
551
|
+
sta.wc[c, k] += con.sfdist[c] * d_rain
|
|
552
|
+
sta.sp[c, k] += con.sfdist[c] * d_snow
|
|
553
|
+
else:
|
|
554
|
+
for c in range(con.sclass):
|
|
555
|
+
sta.wc[c, k] = 0.0
|
|
556
|
+
sta.sp[c, k] = 0.0
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
class Calc_SPL_WCL_SP_WC_V1(modeltools.Method):
|
|
560
|
+
r"""Calculate the subbasin-internal redistribution losses of the snow layer.
|
|
561
|
+
|
|
562
|
+
Basic equations:
|
|
563
|
+
:math:`\frac{dSP}{dt} = -SPL`
|
|
564
|
+
|
|
565
|
+
:math:`\frac{dWC}{dt} = -WCL`
|
|
566
|
+
|
|
567
|
+
:math:`SPL = SP \cdot RelExcess`
|
|
568
|
+
|
|
569
|
+
:math:`WCL = WC \cdot RelExcess`
|
|
570
|
+
|
|
571
|
+
:math:`RelExcess = \frac{max(SP + WC - SMax, 0)}{SP + WC}`
|
|
572
|
+
|
|
573
|
+
Examples:
|
|
574
|
+
|
|
575
|
+
We prepare eight zones. We use the first five to show the identical behaviour
|
|
576
|
+
of the land-use types |GLACIER|, |FIELD|, |FOREST|, and |SEALED| and the unique
|
|
577
|
+
behaviour of type |ILAKE|. Zones six to eight serve to demonstrate the effects
|
|
578
|
+
of different initial states:
|
|
579
|
+
|
|
580
|
+
>>> from hydpy.models.hland import *
|
|
581
|
+
>>> simulationstep("12h")
|
|
582
|
+
>>> parameterstep("1d")
|
|
583
|
+
>>> nmbzones(8)
|
|
584
|
+
>>> sclass(1)
|
|
585
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED, FIELD, FIELD, FIELD)
|
|
586
|
+
>>> smax(500.0)
|
|
587
|
+
|
|
588
|
+
Internal lakes do not possess a snow module and cannot redistribute any snow.
|
|
589
|
+
Hence, |Calc_SPL_WCL_SP_WC_V1| sets the loss (|SPL| and |WCL|) and state (|SP|
|
|
590
|
+
and |WC|) sequences to zero. For all other zones, the total amount of snow
|
|
591
|
+
redistribution depends on how much the total water equivalent exceeds the
|
|
592
|
+
threshold parameter |SMax| (consistently set to 500 m). The fraction between
|
|
593
|
+
the liquid (|WCL|) and frozen (|SPL|) loss depends on the fraction between
|
|
594
|
+
the actual storage of liquid (|WC|) and frozen (|SP|) water in the snow layer:
|
|
595
|
+
|
|
596
|
+
>>> states.sp = 600.0, 600.0, 600.0, 600.0, 600.0, 60.0, 800.0, 0.0
|
|
597
|
+
>>> states.wc = 200.0, 200.0, 200.0, 200.0, 200.0, 20.0, 0.0, 800.0
|
|
598
|
+
>>> model.calc_spl_wcl_sp_wc_v1()
|
|
599
|
+
>>> fluxes.spl
|
|
600
|
+
spl(0.0, 225.0, 225.0, 225.0, 225.0, 0.0, 300.0, 0.0)
|
|
601
|
+
>>> fluxes.wcl
|
|
602
|
+
wcl(0.0, 75.0, 75.0, 75.0, 75.0, 0.0, 0.0, 300.0)
|
|
603
|
+
>>> states.sp
|
|
604
|
+
sp(0.0, 375.0, 375.0, 375.0, 375.0, 60.0, 500.0, 0.0)
|
|
605
|
+
>>> states.wc
|
|
606
|
+
wc(0.0, 125.0, 125.0, 125.0, 125.0, 20.0, 0.0, 500.0)
|
|
607
|
+
|
|
608
|
+
The above example deals with a single snow class. Here, we add a second snow
|
|
609
|
+
class to illustrate that the total snow loss of each zone does not depend on
|
|
610
|
+
its average snow storage but the degree of exceedance of |SMax| within its
|
|
611
|
+
individual snow classes:
|
|
612
|
+
|
|
613
|
+
>>> sclass(2)
|
|
614
|
+
>>> states.sp = [[600.0, 600.0, 600.0, 600.0, 600.0, 60.0, 800.0, 0.0],
|
|
615
|
+
... [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
|
|
616
|
+
>>> states.wc = [[200.0, 200.0, 200.0, 200.0, 200.0, 20.0, 0.0, 800.0],
|
|
617
|
+
... [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
|
|
618
|
+
>>> model.calc_spl_wcl_sp_wc_v1()
|
|
619
|
+
>>> fluxes.spl
|
|
620
|
+
spl(0.0, 112.5, 112.5, 112.5, 112.5, 0.0, 150.0, 0.0)
|
|
621
|
+
>>> fluxes.wcl
|
|
622
|
+
wcl(0.0, 37.5, 37.5, 37.5, 37.5, 0.0, 0.0, 150.0)
|
|
623
|
+
>>> states.sp
|
|
624
|
+
sp([[0.0, 375.0, 375.0, 375.0, 375.0, 60.0, 500.0, 0.0],
|
|
625
|
+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
|
|
626
|
+
>>> states.wc
|
|
627
|
+
wc([[0.0, 125.0, 125.0, 125.0, 125.0, 20.0, 0.0, 500.0],
|
|
628
|
+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
|
|
629
|
+
"""
|
|
630
|
+
|
|
631
|
+
CONTROLPARAMETERS = (
|
|
632
|
+
hland_control.NmbZones,
|
|
633
|
+
hland_control.SClass,
|
|
634
|
+
hland_control.ZoneType,
|
|
635
|
+
hland_control.SMax,
|
|
636
|
+
)
|
|
637
|
+
UPDATEDSEQUENCES = (hland_states.WC, hland_states.SP)
|
|
638
|
+
RESULTSEQUENCES = (hland_fluxes.SPL, hland_fluxes.WCL)
|
|
639
|
+
|
|
640
|
+
@staticmethod
|
|
641
|
+
def __call__(model: modeltools.Model) -> None:
|
|
642
|
+
con = model.parameters.control.fastaccess
|
|
643
|
+
flu = model.sequences.fluxes.fastaccess
|
|
644
|
+
sta = model.sequences.states.fastaccess
|
|
645
|
+
for k in range(con.nmbzones):
|
|
646
|
+
flu.spl[k] = 0.0
|
|
647
|
+
flu.wcl[k] = 0.0
|
|
648
|
+
if con.zonetype[k] == ILAKE:
|
|
649
|
+
for c in range(con.sclass):
|
|
650
|
+
sta.sp[c, k] = 0.0
|
|
651
|
+
sta.wc[c, k] = 0.0
|
|
652
|
+
elif not modelutils.isinf(con.smax[k]):
|
|
653
|
+
for c in range(con.sclass):
|
|
654
|
+
d_snow = sta.sp[c, k] + sta.wc[c, k]
|
|
655
|
+
d_excess = d_snow - con.smax[k]
|
|
656
|
+
if d_excess > 0.0:
|
|
657
|
+
d_excess_sp = d_excess * sta.sp[c, k] / d_snow
|
|
658
|
+
d_excess_wc = d_excess * sta.wc[c, k] / d_snow
|
|
659
|
+
flu.spl[k] += d_excess_sp / con.sclass
|
|
660
|
+
flu.wcl[k] += d_excess_wc / con.sclass
|
|
661
|
+
sta.sp[c, k] -= d_excess_sp
|
|
662
|
+
sta.wc[c, k] -= d_excess_wc
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
class Calc_SPG_WCG_SP_WC_V1(modeltools.Method):
|
|
666
|
+
r"""Calculate the subbasin-internal redistribution gains of the snow layer.
|
|
667
|
+
|
|
668
|
+
Basic equations:
|
|
669
|
+
:math:`\frac{dSP}{dt} = -SPG`
|
|
670
|
+
|
|
671
|
+
:math:`\frac{dWC}{dt} = -WCG`
|
|
672
|
+
|
|
673
|
+
Examples:
|
|
674
|
+
|
|
675
|
+
We prepare an example consisting of seven zones, sorted by (non-strictly)
|
|
676
|
+
descending elevation. For now, there is a single snow class per zone, and the
|
|
677
|
+
zones' areas are identical (1.0 km²). The last zone is of type |ILAKE| and
|
|
678
|
+
does not participate in snow redistribution. We use the same configuration for
|
|
679
|
+
|SMax| (the maximum snow storage) and |SRed| (defining the redistribution
|
|
680
|
+
paths) throughout all examples:
|
|
681
|
+
|
|
682
|
+
>>> from hydpy.models.hland import *
|
|
683
|
+
>>> simulationstep("12h")
|
|
684
|
+
>>> parameterstep("1d")
|
|
685
|
+
>>> area(7.0)
|
|
686
|
+
>>> nmbzones(7)
|
|
687
|
+
>>> sclass(1)
|
|
688
|
+
>>> zonetype(GLACIER, FIELD, FOREST, SEALED, FOREST, FIELD, ILAKE)
|
|
689
|
+
>>> zonez(30.0, 25.0, 20.0, 15.0, 10.0, 10.0, 5.0)
|
|
690
|
+
>>> zonearea(1.0)
|
|
691
|
+
>>> psi(1.0)
|
|
692
|
+
>>> sfdist(1.0)
|
|
693
|
+
>>> smax(500.0)
|
|
694
|
+
>>> sred([[0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0],
|
|
695
|
+
... [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
|
|
696
|
+
... [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
|
|
697
|
+
... [0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0],
|
|
698
|
+
... [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
699
|
+
... [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
700
|
+
... [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
|
|
701
|
+
|
|
702
|
+
For convenience, we prepare a function that updates all relevant derived
|
|
703
|
+
parameters:
|
|
704
|
+
|
|
705
|
+
>>> def update():
|
|
706
|
+
... derived.rellandarea.update()
|
|
707
|
+
... derived.relzoneareas.update()
|
|
708
|
+
... derived.rellowerzonearea.update()
|
|
709
|
+
... derived.zonearearatios.update()
|
|
710
|
+
... derived.indiceszonez.update()
|
|
711
|
+
... derived.sredorder.update()
|
|
712
|
+
... derived.srednumber.update()
|
|
713
|
+
... derived.sredend.update()
|
|
714
|
+
>>> update()
|
|
715
|
+
|
|
716
|
+
In the first example, the total snow water equivalent (300 mm) is way below
|
|
717
|
+
|SRed| (500 mm). Hence, all frozen (|SPL|) and liquid (|WCL|) water released
|
|
718
|
+
deposits completely in the target zones:
|
|
719
|
+
|
|
720
|
+
>>> states.sp = 200.0
|
|
721
|
+
>>> states.wc = 100.0
|
|
722
|
+
>>> fluxes.spl = 20.0, 20.0, 20.0, 20.0, 0.0, 0.0, 0.0
|
|
723
|
+
>>> fluxes.wcl = 10.0, 10.0, 10.0, 10.0, 0.0, 0.0, 0.0
|
|
724
|
+
>>> model.calc_spg_wcg_sp_wc_v1()
|
|
725
|
+
>>> fluxes.spg
|
|
726
|
+
spg(0.0, 4.0, 24.0, 24.0, 14.0, 14.0, 0.0)
|
|
727
|
+
>>> fluxes.wcg
|
|
728
|
+
wcg(0.0, 2.0, 12.0, 12.0, 7.0, 7.0, 0.0)
|
|
729
|
+
>>> states.sp
|
|
730
|
+
sp(200.0, 204.0, 224.0, 224.0, 214.0, 214.0, 0.0)
|
|
731
|
+
>>> states.wc
|
|
732
|
+
wc(100.0, 102.0, 112.0, 112.0, 107.0, 107.0, 0.0)
|
|
733
|
+
|
|
734
|
+
The following test function checks that method |Calc_SPG_WCG_SP_WC_V1| does not
|
|
735
|
+
introduce any water balance errors:
|
|
736
|
+
|
|
737
|
+
>>> from hydpy import repr_
|
|
738
|
+
>>> def check(sp_old, wc_old):
|
|
739
|
+
... def check_vector(deltas):
|
|
740
|
+
... return numpy.max(numpy.abs(numpy.sum(deltas, axis=0)))
|
|
741
|
+
... sp_new = states.sp.average_values()
|
|
742
|
+
... sp_delta_l = fluxes.spl.average_values()
|
|
743
|
+
... sp_delta_g = fluxes.spg.average_values()
|
|
744
|
+
... sp_old_array = numpy.array(6 * [sp_old] + [0.0])
|
|
745
|
+
... wc_new = states.wc.average_values()
|
|
746
|
+
... wc_delta_l = fluxes.wcl.average_values()
|
|
747
|
+
... wc_delta_g = fluxes.wcg.average_values()
|
|
748
|
+
... wc_old_array = numpy.array(6 * [wc_old] + [0.0])
|
|
749
|
+
... errors = [sp_old + sp_delta_l - sp_new,
|
|
750
|
+
... sp_delta_l - sp_delta_g,
|
|
751
|
+
... check_vector(sp_old_array + fluxes.spg - states.sp),
|
|
752
|
+
... wc_old + wc_delta_l - wc_new,
|
|
753
|
+
... wc_delta_l - wc_delta_g,
|
|
754
|
+
... check_vector(wc_old_array + fluxes.wcg - states.wc)]
|
|
755
|
+
... print(*(repr_(error) for error in errors), sep=", ")
|
|
756
|
+
|
|
757
|
+
The possible errors related to different aspects of the frozen and the liquid
|
|
758
|
+
water content of the snow layer are all within the range of the given numerical
|
|
759
|
+
precision:
|
|
760
|
+
|
|
761
|
+
>>> check(sp_old=200.0, wc_old=100.0)
|
|
762
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0
|
|
763
|
+
|
|
764
|
+
Next, we increase the size of the first area and decrease the size of the
|
|
765
|
+
second area by the same amount. The different results for |SPG| and |WCG|
|
|
766
|
+
reflect that the loss terms (|SPL| and |WCL|) relate to the sizes of the
|
|
767
|
+
supplying zones while the gain terms (|SPG| and |WCG|) relate to the sizes of
|
|
768
|
+
the receiving zones:
|
|
769
|
+
|
|
770
|
+
>>> zonearea(1.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0)
|
|
771
|
+
>>> update()
|
|
772
|
+
>>> states.sp = 200.0
|
|
773
|
+
>>> states.wc = 100.0
|
|
774
|
+
>>> model.calc_spg_wcg_sp_wc_v1()
|
|
775
|
+
>>> fluxes.spg
|
|
776
|
+
spg(0.0, 12.0, 16.0, 26.0, 16.0, 16.0, 0.0)
|
|
777
|
+
>>> fluxes.wcg
|
|
778
|
+
wcg(0.0, 6.0, 8.0, 13.0, 8.0, 8.0, 0.0)
|
|
779
|
+
>>> states.sp
|
|
780
|
+
sp(200.0, 212.0, 216.0, 226.0, 216.0, 216.0, 0.0)
|
|
781
|
+
>>> states.wc
|
|
782
|
+
wc(100.0, 106.0, 108.0, 113.0, 108.0, 108.0, 0.0)
|
|
783
|
+
>>> check(sp_old=200.0, wc_old=100.0)
|
|
784
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0
|
|
785
|
+
|
|
786
|
+
When modelling high mountain areas, even the lowest zones (the so-called
|
|
787
|
+
"dead-ends") can receive substantial amounts of redistributed snow. Therefore,
|
|
788
|
+
the simple "from top to bottom" approach described so far can result in
|
|
789
|
+
unrealistic snow towers for these dead-ends, especially if their size is small
|
|
790
|
+
compared to the size of the snow-delivering area. To prevent such artefacts,
|
|
791
|
+
method |Calc_SPG_WCG_SP_WC_V1| takes the total snow amount of all dead-ends
|
|
792
|
+
exceeding the |Smax| threshold and distributes it gradually to the other zones,
|
|
793
|
+
starting from the lowest in the order defined by parameter |IndicesZoneZ|:
|
|
794
|
+
|
|
795
|
+
>>> zonearea(1.0)
|
|
796
|
+
>>> update()
|
|
797
|
+
>>> states.sp = 400.0
|
|
798
|
+
>>> states.wc = 75.0
|
|
799
|
+
>>> model.calc_spg_wcg_sp_wc_v1()
|
|
800
|
+
>>> fluxes.spg
|
|
801
|
+
spg(0.0, 13.333333, 16.666667, 16.666667, 16.666667, 16.666667, 0.0)
|
|
802
|
+
>>> fluxes.wcg
|
|
803
|
+
wcg(0.0, 6.666667, 8.333333, 8.333333, 8.333333, 8.333333, 0.0)
|
|
804
|
+
>>> states.sp
|
|
805
|
+
sp(400.0, 413.333333, 416.666667, 416.666667, 416.666667, 416.666667,
|
|
806
|
+
0.0)
|
|
807
|
+
>>> states.wc
|
|
808
|
+
wc(75.0, 81.666667, 83.333333, 83.333333, 83.333333, 83.333333, 0.0)
|
|
809
|
+
>>> check(sp_old=400.0, wc_old=75.0)
|
|
810
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0
|
|
811
|
+
|
|
812
|
+
If the total snow amount of all zone reaches |SMax|, |Calc_SPG_WCG_SP_WC_V1|
|
|
813
|
+
distributes all remaining excess evenly to all non-lake zones:
|
|
814
|
+
|
|
815
|
+
>>> states.sp = 400.0
|
|
816
|
+
>>> states.wc = 90.0
|
|
817
|
+
>>> model.calc_spg_wcg_sp_wc_v1()
|
|
818
|
+
>>> fluxes.spg
|
|
819
|
+
spg(13.333333, 13.333333, 13.333333, 13.333333, 13.333333, 13.333333,
|
|
820
|
+
0.0)
|
|
821
|
+
>>> fluxes.wcg
|
|
822
|
+
wcg(6.666667, 6.666667, 6.666667, 6.666667, 6.666667, 6.666667, 0.0)
|
|
823
|
+
>>> states.sp
|
|
824
|
+
sp(413.333333, 413.333333, 413.333333, 413.333333, 413.333333,
|
|
825
|
+
413.333333, 0.0)
|
|
826
|
+
>>> states.wc
|
|
827
|
+
wc(96.666667, 96.666667, 96.666667, 96.666667, 96.666667, 96.666667, 0.0)
|
|
828
|
+
>>> check(sp_old=400.0, wc_old=90.0)
|
|
829
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0
|
|
830
|
+
|
|
831
|
+
Introducing multiple snow classes within each zone complicates things. We
|
|
832
|
+
repeat some of the above examples with an increased number of snow classes:
|
|
833
|
+
|
|
834
|
+
>>> sclass(2)
|
|
835
|
+
>>> update()
|
|
836
|
+
|
|
837
|
+
The "normal" snow redistribution relies similarly on parameter |SFDist| as the
|
|
838
|
+
snowfall accumulation does. We show this by repeating the first example with
|
|
839
|
+
the most extreme configuration of |SFDist|, where the second snow class
|
|
840
|
+
receives the entire amount of incoming snow:
|
|
841
|
+
|
|
842
|
+
>>> sfdist(0.0, 2.0)
|
|
843
|
+
>>> states.sp = 200.0
|
|
844
|
+
>>> states.wc = 100.0
|
|
845
|
+
>>> fluxes.spl = 20.0, 20.0, 20.0, 20.0, 0.0, 0.0, 0.0
|
|
846
|
+
>>> fluxes.wcl = 10.0, 10.0, 10.0, 10.0, 0.0, 0.0, 0.0
|
|
847
|
+
>>> model.calc_spg_wcg_sp_wc_v1()
|
|
848
|
+
>>> fluxes.spg
|
|
849
|
+
spg(0.0, 4.0, 24.0, 24.0, 14.0, 14.0, 0.0)
|
|
850
|
+
>>> fluxes.wcg
|
|
851
|
+
wcg(0.0, 2.0, 12.0, 12.0, 7.0, 7.0, 0.0)
|
|
852
|
+
>>> states.sp
|
|
853
|
+
sp([[200.0, 200.0, 200.0, 200.0, 200.0, 200.0, 0.0],
|
|
854
|
+
[200.0, 208.0, 248.0, 248.0, 228.0, 228.0, 0.0]])
|
|
855
|
+
>>> states.wc
|
|
856
|
+
wc([[100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 0.0],
|
|
857
|
+
[100.0, 104.0, 124.0, 124.0, 114.0, 114.0, 0.0]])
|
|
858
|
+
|
|
859
|
+
During the eventual "bottom to top" re-redistribution, on the other hand,
|
|
860
|
+
the fractions between the gains of individual snow classes do not depend on
|
|
861
|
+
|SFDist| but their remaining capacities:
|
|
862
|
+
|
|
863
|
+
>>> states.sp = 400.0
|
|
864
|
+
>>> states.wc = 75.0
|
|
865
|
+
>>> model.calc_spg_wcg_sp_wc_v1()
|
|
866
|
+
>>> fluxes.spg
|
|
867
|
+
spg(0.0, 13.333333, 16.666667, 16.666667, 16.666667, 16.666667, 0.0)
|
|
868
|
+
>>> fluxes.wcg
|
|
869
|
+
wcg(0.0, 6.666667, 8.333333, 8.333333, 8.333333, 8.333333, 0.0)
|
|
870
|
+
>>> states.sp
|
|
871
|
+
sp([[400.0, 412.280702, 416.666667, 416.666667, 416.666667, 416.666667,
|
|
872
|
+
0.0],
|
|
873
|
+
[400.0, 414.385965, 416.666667, 416.666667, 416.666667, 416.666667,
|
|
874
|
+
0.0]])
|
|
875
|
+
>>> states.wc
|
|
876
|
+
wc([[75.0, 81.140351, 83.333333, 83.333333, 83.333333, 83.333333, 0.0],
|
|
877
|
+
[75.0, 82.192982, 83.333333, 83.333333, 83.333333, 83.333333, 0.0]])
|
|
878
|
+
>>> check(sp_old=400.0, wc_old=75.0)
|
|
879
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0
|
|
880
|
+
|
|
881
|
+
During a subbasin-wide excess of |SMax|, all snow classes of a specific zone
|
|
882
|
+
handle the same total snow water equivalent:
|
|
883
|
+
|
|
884
|
+
>>> states.sp = 400.0
|
|
885
|
+
>>> states.wc = 90.0
|
|
886
|
+
>>> model.calc_spg_wcg_sp_wc_v1()
|
|
887
|
+
>>> fluxes.spg
|
|
888
|
+
spg(13.333333, 13.333333, 13.333333, 13.333333, 13.333333, 13.333333,
|
|
889
|
+
0.0)
|
|
890
|
+
>>> fluxes.wcg
|
|
891
|
+
wcg(6.666667, 6.666667, 6.666667, 6.666667, 6.666667, 6.666667, 0.0)
|
|
892
|
+
>>> states.sp
|
|
893
|
+
sp([[413.333333, 413.333333, 413.333333, 413.333333, 413.333333,
|
|
894
|
+
413.333333, 0.0],
|
|
895
|
+
[413.333333, 413.333333, 413.333333, 413.333333, 413.333333,
|
|
896
|
+
413.333333, 0.0]])
|
|
897
|
+
>>> states.wc
|
|
898
|
+
wc([[96.666667, 96.666667, 96.666667, 96.666667, 96.666667, 96.666667,
|
|
899
|
+
0.0],
|
|
900
|
+
[96.666667, 96.666667, 96.666667, 96.666667, 96.666667, 96.666667,
|
|
901
|
+
0.0]])
|
|
902
|
+
>>> check(sp_old=400.0, wc_old=90.0)
|
|
903
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0
|
|
904
|
+
"""
|
|
905
|
+
|
|
906
|
+
CONTROLPARAMETERS = (
|
|
907
|
+
hland_control.NmbZones,
|
|
908
|
+
hland_control.SClass,
|
|
909
|
+
hland_control.ZoneType,
|
|
910
|
+
hland_control.SFDist,
|
|
911
|
+
hland_control.SMax,
|
|
912
|
+
hland_control.SRed,
|
|
913
|
+
)
|
|
914
|
+
DERIVEDPARAMETERS = (
|
|
915
|
+
hland_derived.RelLandArea,
|
|
916
|
+
hland_derived.RelZoneAreas,
|
|
917
|
+
hland_derived.ZoneAreaRatios,
|
|
918
|
+
hland_derived.IndicesZoneZ,
|
|
919
|
+
hland_derived.SRedNumber,
|
|
920
|
+
hland_derived.SRedOrder,
|
|
921
|
+
hland_derived.SRedEnd,
|
|
922
|
+
)
|
|
923
|
+
REQUIREDSEQUENCES = (hland_fluxes.SPL, hland_fluxes.WCL)
|
|
924
|
+
UPDATEDSEQUENCES = (hland_states.WC, hland_states.SP)
|
|
925
|
+
RESULTSEQUENCES = (
|
|
926
|
+
hland_aides.SPE,
|
|
927
|
+
hland_aides.WCE,
|
|
928
|
+
hland_fluxes.SPG,
|
|
929
|
+
hland_fluxes.WCG,
|
|
930
|
+
)
|
|
931
|
+
|
|
932
|
+
@staticmethod
|
|
933
|
+
def __call__(model: modeltools.Model) -> None:
|
|
934
|
+
con = model.parameters.control.fastaccess
|
|
935
|
+
der = model.parameters.derived.fastaccess
|
|
936
|
+
flu = model.sequences.fluxes.fastaccess
|
|
937
|
+
sta = model.sequences.states.fastaccess
|
|
938
|
+
aid = model.sequences.aides.fastaccess
|
|
939
|
+
|
|
940
|
+
# initialise gain and excess:
|
|
941
|
+
for i in range(con.nmbzones):
|
|
942
|
+
flu.spg[i] = 0.0
|
|
943
|
+
flu.wcg[i] = 0.0
|
|
944
|
+
aid.spe[i] = 0.0
|
|
945
|
+
aid.wce[i] = 0.0
|
|
946
|
+
if con.zonetype[i] == ILAKE:
|
|
947
|
+
for c in range(con.sclass):
|
|
948
|
+
sta.sp[c, i] = 0.0
|
|
949
|
+
sta.wc[c, i] = 0.0
|
|
950
|
+
|
|
951
|
+
# redistribute losses from top to bottom:
|
|
952
|
+
for i in range(der.srednumber):
|
|
953
|
+
# f: from, t: to
|
|
954
|
+
f, t = der.sredorder[i, 0], der.sredorder[i, 1]
|
|
955
|
+
d_f = der.zonearearatios[f, t] * con.sred[f, t]
|
|
956
|
+
d_gain_frozen = d_f * (flu.spl[f] + aid.spe[f])
|
|
957
|
+
d_gain_liquid = d_f * (flu.wcl[f] + aid.wce[f])
|
|
958
|
+
d_gain_total = d_gain_frozen + d_gain_liquid
|
|
959
|
+
for c in range(con.sclass):
|
|
960
|
+
d_gain_pot = con.sfdist[c] * d_gain_total
|
|
961
|
+
if d_gain_pot > 0.0:
|
|
962
|
+
d_gain_max = con.smax[t] - sta.sp[c, t] - sta.wc[c, t]
|
|
963
|
+
d_fraction_gain = min(d_gain_max / d_gain_pot, 1.0)
|
|
964
|
+
d_factor_gain = d_fraction_gain * con.sfdist[c]
|
|
965
|
+
flu.spg[t] += d_factor_gain * d_gain_frozen / con.sclass
|
|
966
|
+
flu.wcg[t] += d_factor_gain * d_gain_liquid / con.sclass
|
|
967
|
+
sta.sp[c, t] += d_factor_gain * d_gain_frozen
|
|
968
|
+
sta.wc[c, t] += d_factor_gain * d_gain_liquid
|
|
969
|
+
d_factor_excess = (1.0 - d_fraction_gain) * con.sfdist[c]
|
|
970
|
+
aid.spe[t] += d_factor_excess * d_gain_frozen / con.sclass
|
|
971
|
+
aid.wce[t] += d_factor_excess * d_gain_liquid / con.sclass
|
|
972
|
+
|
|
973
|
+
# check for remaining excess at the dead ends:
|
|
974
|
+
d_excess_frozen_basin, d_excess_liquid_basin = 0.0, 0.0
|
|
975
|
+
for i in range(con.nmbzones):
|
|
976
|
+
if der.sredend[i]:
|
|
977
|
+
d_excess_frozen_basin += der.relzoneareas[i] * (aid.spe[i] + flu.spl[i])
|
|
978
|
+
d_excess_liquid_basin += der.relzoneareas[i] * (aid.wce[i] + flu.wcl[i])
|
|
979
|
+
if (d_excess_frozen_basin + d_excess_liquid_basin) <= 0.0:
|
|
980
|
+
return
|
|
981
|
+
|
|
982
|
+
# redistribute the remaining excess from bottom to top:
|
|
983
|
+
for i in range(con.nmbzones):
|
|
984
|
+
t = der.indiceszonez[i]
|
|
985
|
+
if con.zonetype[t] == ILAKE:
|
|
986
|
+
continue
|
|
987
|
+
d_excess_frozen_zone = d_excess_frozen_basin / der.relzoneareas[t]
|
|
988
|
+
d_excess_liquid_zone = d_excess_liquid_basin / der.relzoneareas[t]
|
|
989
|
+
d_excess_total_zone = d_excess_frozen_zone + d_excess_liquid_zone
|
|
990
|
+
d_gain_max_cum = 0.0
|
|
991
|
+
for c in range(con.sclass):
|
|
992
|
+
d_gain_max_cum += con.smax[t] - sta.sp[c, t] - sta.wc[c, t]
|
|
993
|
+
if d_gain_max_cum <= 0.0:
|
|
994
|
+
continue
|
|
995
|
+
d_fraction_gain_zone = min(
|
|
996
|
+
d_gain_max_cum / con.sclass / d_excess_total_zone, 1.0
|
|
997
|
+
)
|
|
998
|
+
d_excess_frozen_zone_actual = d_fraction_gain_zone * d_excess_frozen_zone
|
|
999
|
+
d_excess_liquid_zone_actual = d_fraction_gain_zone * d_excess_liquid_zone
|
|
1000
|
+
for c in range(con.sclass):
|
|
1001
|
+
d_fraction_gain_class = (
|
|
1002
|
+
con.smax[t] - sta.sp[c, t] - sta.wc[c, t]
|
|
1003
|
+
) / d_gain_max_cum
|
|
1004
|
+
d_delta_sp_zone = d_fraction_gain_class * d_excess_frozen_zone_actual
|
|
1005
|
+
d_delta_wc_zone = d_fraction_gain_class * d_excess_liquid_zone_actual
|
|
1006
|
+
flu.spg[t] += d_delta_sp_zone
|
|
1007
|
+
flu.wcg[t] += d_delta_wc_zone
|
|
1008
|
+
sta.sp[c, t] += d_delta_sp_zone * con.sclass
|
|
1009
|
+
sta.wc[c, t] += d_delta_wc_zone * con.sclass
|
|
1010
|
+
d_excess_frozen_basin -= d_excess_frozen_zone_actual * der.relzoneareas[t]
|
|
1011
|
+
d_excess_liquid_basin -= d_excess_liquid_zone_actual * der.relzoneareas[t]
|
|
1012
|
+
if (d_excess_frozen_basin + d_excess_liquid_basin) <= 0.0:
|
|
1013
|
+
return
|
|
1014
|
+
|
|
1015
|
+
# redistribute the still remaining excess evenly:
|
|
1016
|
+
d_excess_frozen_land = d_excess_frozen_basin / der.rellandarea
|
|
1017
|
+
d_excess_liquid_land = d_excess_liquid_basin / der.rellandarea
|
|
1018
|
+
for t in range(con.nmbzones):
|
|
1019
|
+
if con.zonetype[t] != ILAKE:
|
|
1020
|
+
flu.spg[t] += d_excess_frozen_land
|
|
1021
|
+
flu.wcg[t] += d_excess_liquid_land
|
|
1022
|
+
for c in range(con.sclass):
|
|
1023
|
+
sta.sp[c, t] += d_excess_frozen_land
|
|
1024
|
+
sta.wc[c, t] += d_excess_liquid_land
|
|
1025
|
+
return
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
class Calc_CFAct_V1(modeltools.Method):
|
|
1029
|
+
r"""Adjust the day degree factor for snow to the current day of the year.
|
|
1030
|
+
|
|
1031
|
+
Basic equations:
|
|
1032
|
+
:math:`CFAct = max( CFMax + f \cdot CFVar, 0 )`
|
|
1033
|
+
|
|
1034
|
+
:math:`f = sin(2 \cdot Pi \cdot (DOY + 1) / 366) / 2`
|
|
1035
|
+
|
|
1036
|
+
Examples:
|
|
1037
|
+
|
|
1038
|
+
We initialise five zones of different types but the same values for |CFMax| and
|
|
1039
|
+
|CFVar|. For internal lakes, |CFAct| is always zero. In all other cases,
|
|
1040
|
+
results are identical and follow a sinusoid curve throughout the year (of which
|
|
1041
|
+
we show only selected points as the maximum around June 20 and the minimum
|
|
1042
|
+
around December 20):
|
|
1043
|
+
|
|
1044
|
+
>>> from hydpy.models.hland import *
|
|
1045
|
+
>>> simulationstep("12h")
|
|
1046
|
+
>>> parameterstep("1d")
|
|
1047
|
+
>>> nmbzones(5)
|
|
1048
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED)
|
|
1049
|
+
>>> cfmax(4.0)
|
|
1050
|
+
>>> cfvar(3.0)
|
|
1051
|
+
>>> from hydpy import UnitTest
|
|
1052
|
+
>>> test = UnitTest(model=model,
|
|
1053
|
+
... method=model.calc_cfact_v1,
|
|
1054
|
+
... last_example=10,
|
|
1055
|
+
... parseqs=(derived.doy, factors.cfact))
|
|
1056
|
+
>>> test.nexts.doy = 0, 1, 170, 171, 172, 353, 354, 355, 364, 365
|
|
1057
|
+
>>> test()
|
|
1058
|
+
| ex. | doy | cfact |
|
|
1059
|
+
-------------------------------------------------------------------------------
|
|
1060
|
+
| 1 | 0 0 0 0 0 | 0.0 1.264648 1.264648 1.264648 1.264648 |
|
|
1061
|
+
| 2 | 1 1 1 1 1 | 0.0 1.267289 1.267289 1.267289 1.267289 |
|
|
1062
|
+
| 3 | 170 170 170 170 170 | 0.0 2.749762 2.749762 2.749762 2.749762 |
|
|
1063
|
+
| 4 | 171 171 171 171 171 | 0.0 2.749976 2.749976 2.749976 2.749976 |
|
|
1064
|
+
| 5 | 172 172 172 172 172 | 0.0 2.749969 2.749969 2.749969 2.749969 |
|
|
1065
|
+
| 6 | 353 353 353 353 353 | 0.0 1.250238 1.250238 1.250238 1.250238 |
|
|
1066
|
+
| 7 | 354 354 354 354 354 | 0.0 1.250024 1.250024 1.250024 1.250024 |
|
|
1067
|
+
| 8 | 355 355 355 355 355 | 0.0 1.250031 1.250031 1.250031 1.250031 |
|
|
1068
|
+
| 9 | 364 364 364 364 364 | 0.0 1.260018 1.260018 1.260018 1.260018 |
|
|
1069
|
+
| 10 | 365 365 365 365 365 | 0.0 1.262224 1.262224 1.262224 1.262224 |
|
|
1070
|
+
|
|
1071
|
+
Now, we convert all zones to type |FIELD| and vary |CFVar|. If we set |CFVar|
|
|
1072
|
+
to zero, |CFAct| always equals |CFMax| (see zone one). If we change the sign
|
|
1073
|
+
of |CFVar|, the sinusoid curve shifts a half year to reflect the southern
|
|
1074
|
+
hemisphere's annual cycle of radiation (compare zone two and three). Finally,
|
|
1075
|
+
|Calc_CFAct_V1| prevents negative values of |CFAct| by setting them to zero
|
|
1076
|
+
(see zone four and five):
|
|
1077
|
+
|
|
1078
|
+
>>> zonetype(FIELD)
|
|
1079
|
+
>>> cfvar(0.0, 3.0, -3.0, 10.0, -10.0)
|
|
1080
|
+
>>> test()
|
|
1081
|
+
| ex. | doy | cfact |
|
|
1082
|
+
-------------------------------------------------------------------------------
|
|
1083
|
+
| 1 | 0 0 0 0 0 | 2.0 1.264648 2.735352 0.0 4.451173 |
|
|
1084
|
+
| 2 | 1 1 1 1 1 | 2.0 1.267289 2.732711 0.0 4.442371 |
|
|
1085
|
+
| 3 | 170 170 170 170 170 | 2.0 2.749762 1.250238 4.499206 0.0 |
|
|
1086
|
+
| 4 | 171 171 171 171 171 | 2.0 2.749976 1.250024 4.499919 0.0 |
|
|
1087
|
+
| 5 | 172 172 172 172 172 | 2.0 2.749969 1.250031 4.499896 0.0 |
|
|
1088
|
+
| 6 | 353 353 353 353 353 | 2.0 1.250238 2.749762 0.0 4.499206 |
|
|
1089
|
+
| 7 | 354 354 354 354 354 | 2.0 1.250024 2.749976 0.0 4.499919 |
|
|
1090
|
+
| 8 | 355 355 355 355 355 | 2.0 1.250031 2.749969 0.0 4.499896 |
|
|
1091
|
+
| 9 | 364 364 364 364 364 | 2.0 1.260018 2.739982 0.0 4.466606 |
|
|
1092
|
+
| 10 | 365 365 365 365 365 | 2.0 1.262224 2.737776 0.0 4.459252 |
|
|
1093
|
+
"""
|
|
1094
|
+
|
|
1095
|
+
CONTROLPARAMETERS = (
|
|
1096
|
+
hland_control.NmbZones,
|
|
1097
|
+
hland_control.ZoneType,
|
|
1098
|
+
hland_control.CFMax,
|
|
1099
|
+
hland_control.CFVar,
|
|
1100
|
+
)
|
|
1101
|
+
FIXEDPARAMETERS = (hland_fixed.Pi,)
|
|
1102
|
+
DERIVEDPARAMETERS = (hland_derived.DOY,)
|
|
1103
|
+
RESULTSEQUENCES = (hland_factors.CFAct,)
|
|
1104
|
+
|
|
1105
|
+
@staticmethod
|
|
1106
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1107
|
+
con = model.parameters.control.fastaccess
|
|
1108
|
+
der = model.parameters.derived.fastaccess
|
|
1109
|
+
fix = model.parameters.fixed.fastaccess
|
|
1110
|
+
fac = model.sequences.factors.fastaccess
|
|
1111
|
+
d_factor = 0.5 * modelutils.sin(
|
|
1112
|
+
2 * fix.pi * (der.doy[model.idx_sim] + 1) / 366 - 1.39
|
|
1113
|
+
)
|
|
1114
|
+
for k in range(con.nmbzones):
|
|
1115
|
+
if con.zonetype[k] != ILAKE:
|
|
1116
|
+
fac.cfact[k] = max(con.cfmax[k] + d_factor * con.cfvar[k], 0.0)
|
|
1117
|
+
else:
|
|
1118
|
+
fac.cfact[k] = 0.0
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
class Calc_Melt_SP_WC_V1(modeltools.Method):
|
|
1122
|
+
r"""Calculate the melting of the ice content within the snow layer and update both
|
|
1123
|
+
the snow layers' ice and the water content.
|
|
1124
|
+
|
|
1125
|
+
Basic equations:
|
|
1126
|
+
:math:`\frac{dSP}{dt} = - Melt`
|
|
1127
|
+
|
|
1128
|
+
:math:`\frac{dWC}{dt} = + Melt`
|
|
1129
|
+
|
|
1130
|
+
:math:`Melt = min(CFAct \cdot (TC - TTM), SP)`
|
|
1131
|
+
|
|
1132
|
+
Examples:
|
|
1133
|
+
|
|
1134
|
+
We initialise seven zones with the same threshold temperature and degree-day
|
|
1135
|
+
factor but different zone types and initial ice contents:
|
|
1136
|
+
|
|
1137
|
+
>>> from hydpy.models.hland import *
|
|
1138
|
+
>>> simulationstep("12h")
|
|
1139
|
+
>>> parameterstep("1d")
|
|
1140
|
+
>>> nmbzones(7)
|
|
1141
|
+
>>> sclass(1)
|
|
1142
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED, SEALED, SEALED)
|
|
1143
|
+
>>> derived.ttm = 2.0
|
|
1144
|
+
>>> factors.cfact(2.0)
|
|
1145
|
+
>>> states.sp = 0.0, 10.0, 10.0, 10.0, 10.0, 5.0, 0.0
|
|
1146
|
+
>>> states.wc = 2.0
|
|
1147
|
+
|
|
1148
|
+
When the actual temperature equals the threshold temperature for melting and
|
|
1149
|
+
refreezing, no melting occurs, and the states remain unchanged:
|
|
1150
|
+
|
|
1151
|
+
>>> factors.tc = 2.0
|
|
1152
|
+
>>> model.calc_melt_sp_wc_v1()
|
|
1153
|
+
>>> fluxes.melt
|
|
1154
|
+
melt(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1155
|
+
>>> states.sp
|
|
1156
|
+
sp(0.0, 10.0, 10.0, 10.0, 10.0, 5.0, 0.0)
|
|
1157
|
+
>>> states.wc
|
|
1158
|
+
wc(0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0)
|
|
1159
|
+
|
|
1160
|
+
The same holds for an actual temperature lower than the threshold temperature:
|
|
1161
|
+
|
|
1162
|
+
>>> states.sp = 0.0, 10.0, 10.0, 10.0, 10.0, 5.0, 0.0
|
|
1163
|
+
>>> states.wc = 2.0
|
|
1164
|
+
>>> factors.tc = -1.0
|
|
1165
|
+
>>> model.calc_melt_sp_wc_v1()
|
|
1166
|
+
>>> fluxes.melt
|
|
1167
|
+
melt(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1168
|
+
>>> states.sp
|
|
1169
|
+
sp(0.0, 10.0, 10.0, 10.0, 10.0, 5.0, 0.0)
|
|
1170
|
+
>>> states.wc
|
|
1171
|
+
wc(0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0)
|
|
1172
|
+
|
|
1173
|
+
With an actual temperature of 3°C above the threshold temperature, melting can
|
|
1174
|
+
occur. The actual melting is consistent with potential melting, except for the
|
|
1175
|
+
first zone, an internal lake, and the last two zones, for which potential
|
|
1176
|
+
melting exceeds the available frozen water content of the snow layer:
|
|
1177
|
+
|
|
1178
|
+
>>> states.sp = 0.0, 10.0, 10.0, 10.0, 10.0, 5.0, 0.0
|
|
1179
|
+
>>> states.wc = 2.0
|
|
1180
|
+
>>> factors.tc = 5.0
|
|
1181
|
+
>>> model.calc_melt_sp_wc_v1()
|
|
1182
|
+
>>> fluxes.melt
|
|
1183
|
+
melt(0.0, 6.0, 6.0, 6.0, 6.0, 5.0, 0.0)
|
|
1184
|
+
>>> states.sp
|
|
1185
|
+
sp(0.0, 4.0, 4.0, 4.0, 4.0, 0.0, 0.0)
|
|
1186
|
+
>>> states.wc
|
|
1187
|
+
wc(0.0, 8.0, 8.0, 8.0, 8.0, 7.0, 2.0)
|
|
1188
|
+
|
|
1189
|
+
In the above examples, we did not divide the zones into snow classes. If we do
|
|
1190
|
+
so, method |Calc_Melt_SP_WC_V1| assumes a uniform distribution of the
|
|
1191
|
+
potential melting among the individual classes. This assumption implies that
|
|
1192
|
+
if a single snow class does not provide enough frozen water, the actual melting
|
|
1193
|
+
of the total zone must be smaller than its potential melt rate:
|
|
1194
|
+
|
|
1195
|
+
>>> sclass(2)
|
|
1196
|
+
>>> states.sp = [[0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 0.0],
|
|
1197
|
+
... [0.0, 10.0, 10.0, 10.0, 10.0, 10.0, 0.0]]
|
|
1198
|
+
>>> states.wc = [[0.0], [2.0]]
|
|
1199
|
+
>>> model.calc_melt_sp_wc_v1()
|
|
1200
|
+
>>> fluxes.melt
|
|
1201
|
+
melt([[0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 0.0],
|
|
1202
|
+
[0.0, 6.0, 6.0, 6.0, 6.0, 6.0, 0.0]])
|
|
1203
|
+
>>> states.sp
|
|
1204
|
+
sp([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
1205
|
+
[0.0, 4.0, 4.0, 4.0, 4.0, 4.0, 0.0]])
|
|
1206
|
+
>>> states.wc
|
|
1207
|
+
wc([[0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 0.0],
|
|
1208
|
+
[0.0, 8.0, 8.0, 8.0, 8.0, 8.0, 2.0]])
|
|
1209
|
+
"""
|
|
1210
|
+
|
|
1211
|
+
CONTROLPARAMETERS = (
|
|
1212
|
+
hland_control.NmbZones,
|
|
1213
|
+
hland_control.SClass,
|
|
1214
|
+
hland_control.ZoneType,
|
|
1215
|
+
)
|
|
1216
|
+
DERIVEDPARAMETERS = (hland_derived.TTM,)
|
|
1217
|
+
REQUIREDSEQUENCES = (hland_factors.TC, hland_factors.CFAct)
|
|
1218
|
+
UPDATEDSEQUENCES = (hland_states.WC, hland_states.SP)
|
|
1219
|
+
RESULTSEQUENCES = (hland_fluxes.Melt,)
|
|
1220
|
+
|
|
1221
|
+
@staticmethod
|
|
1222
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1223
|
+
con = model.parameters.control.fastaccess
|
|
1224
|
+
der = model.parameters.derived.fastaccess
|
|
1225
|
+
fac = model.sequences.factors.fastaccess
|
|
1226
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1227
|
+
sta = model.sequences.states.fastaccess
|
|
1228
|
+
for k in range(con.nmbzones):
|
|
1229
|
+
if con.zonetype[k] != ILAKE:
|
|
1230
|
+
if fac.tc[k] > der.ttm[k]:
|
|
1231
|
+
d_potmelt = fac.cfact[k] * (fac.tc[k] - der.ttm[k])
|
|
1232
|
+
for c in range(con.sclass):
|
|
1233
|
+
flu.melt[c, k] = min(d_potmelt, sta.sp[c, k])
|
|
1234
|
+
sta.sp[c, k] -= flu.melt[c, k]
|
|
1235
|
+
sta.wc[c, k] += flu.melt[c, k]
|
|
1236
|
+
else:
|
|
1237
|
+
for c in range(con.sclass):
|
|
1238
|
+
flu.melt[c, k] = 0.0
|
|
1239
|
+
else:
|
|
1240
|
+
for c in range(con.sclass):
|
|
1241
|
+
flu.melt[c, k] = 0.0
|
|
1242
|
+
sta.wc[c, k] = 0.0
|
|
1243
|
+
sta.sp[c, k] = 0.0
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
class Calc_Refr_SP_WC_V1(modeltools.Method):
|
|
1247
|
+
r"""Calculate refreezing of the water content within the snow layer and
|
|
1248
|
+
update both the snow layers' ice and the water content.
|
|
1249
|
+
|
|
1250
|
+
Basic equations:
|
|
1251
|
+
:math:`\frac{dSP}{dt} = + Refr`
|
|
1252
|
+
|
|
1253
|
+
:math:`\frac{dWC}{dt} = - Refr`
|
|
1254
|
+
|
|
1255
|
+
:math:`Refr = min(cfr \cdot cfmax \cdot (TTM - TC), WC)`
|
|
1256
|
+
|
|
1257
|
+
Examples:
|
|
1258
|
+
|
|
1259
|
+
We initialise seven zones with the same threshold temperature, degree-day factor
|
|
1260
|
+
and refreezing coefficient but different zone types and initial states:
|
|
1261
|
+
|
|
1262
|
+
>>> from hydpy.models.hland import *
|
|
1263
|
+
>>> simulationstep("12h")
|
|
1264
|
+
>>> parameterstep("1d")
|
|
1265
|
+
>>> nmbzones(7)
|
|
1266
|
+
>>> sclass(1)
|
|
1267
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED, SEALED, SEALED)
|
|
1268
|
+
>>> cfmax(4.0)
|
|
1269
|
+
>>> cfr(0.1)
|
|
1270
|
+
>>> derived.ttm = 2.0
|
|
1271
|
+
>>> states.sp = 2.0
|
|
1272
|
+
>>> states.wc = 0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0
|
|
1273
|
+
|
|
1274
|
+
Note that the assumed length of the simulation step is half a day. Hence the
|
|
1275
|
+
effective value of the degree-day factor is not 4 but 2:
|
|
1276
|
+
|
|
1277
|
+
>>> cfmax
|
|
1278
|
+
cfmax(4.0)
|
|
1279
|
+
>>> from hydpy import round_
|
|
1280
|
+
>>> round_(cfmax.values[0])
|
|
1281
|
+
2.0
|
|
1282
|
+
|
|
1283
|
+
When the actual temperature equals the threshold temperature for melting and
|
|
1284
|
+
refreezing, no refreezing occurs, and the states remain unchanged:
|
|
1285
|
+
|
|
1286
|
+
>>> factors.tc = 2.0
|
|
1287
|
+
>>> model.calc_refr_sp_wc_v1()
|
|
1288
|
+
>>> fluxes.refr
|
|
1289
|
+
refr(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1290
|
+
>>> states.sp
|
|
1291
|
+
sp(0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0)
|
|
1292
|
+
>>> states.wc
|
|
1293
|
+
wc(0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0)
|
|
1294
|
+
|
|
1295
|
+
The same holds for an actual temperature higher than the threshold temperature:
|
|
1296
|
+
|
|
1297
|
+
>>> states.sp = 2.0
|
|
1298
|
+
>>> states.wc = 0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0
|
|
1299
|
+
>>> factors.tc = 2.0
|
|
1300
|
+
>>> model.calc_refr_sp_wc_v1()
|
|
1301
|
+
>>> fluxes.refr
|
|
1302
|
+
refr(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1303
|
+
>>> states.sp
|
|
1304
|
+
sp(0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0)
|
|
1305
|
+
>>> states.wc
|
|
1306
|
+
wc(0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0)
|
|
1307
|
+
|
|
1308
|
+
With an actual temperature of 3°C above the threshold temperature, there is no
|
|
1309
|
+
refreezing:
|
|
1310
|
+
|
|
1311
|
+
>>> states.sp = 2.0
|
|
1312
|
+
>>> states.wc = 0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0
|
|
1313
|
+
>>> factors.tc = 5.0
|
|
1314
|
+
>>> model.calc_refr_sp_wc_v1()
|
|
1315
|
+
>>> fluxes.refr
|
|
1316
|
+
refr(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1317
|
+
>>> states.sp
|
|
1318
|
+
sp(0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0)
|
|
1319
|
+
>>> states.wc
|
|
1320
|
+
wc(0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0)
|
|
1321
|
+
|
|
1322
|
+
With an actual temperature of 3°C below the threshold temperature, refreezing
|
|
1323
|
+
can occur. Actual refreezing is consistent with potential refreezing, except
|
|
1324
|
+
for the first zone, an internal lake, and the last two zones, for which
|
|
1325
|
+
potential refreezing exceeds the available liquid water content of the snow
|
|
1326
|
+
layer:
|
|
1327
|
+
|
|
1328
|
+
>>> states.sp = 2.0
|
|
1329
|
+
>>> states.wc = 0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0
|
|
1330
|
+
>>> factors.tc = -1.0
|
|
1331
|
+
>>> model.calc_refr_sp_wc_v1()
|
|
1332
|
+
>>> fluxes.refr
|
|
1333
|
+
refr(0.0, 0.6, 0.6, 0.6, 0.6, 0.5, 0.0)
|
|
1334
|
+
>>> states.sp
|
|
1335
|
+
sp(0.0, 2.6, 2.6, 2.6, 2.6, 2.5, 2.0)
|
|
1336
|
+
>>> states.wc
|
|
1337
|
+
wc(0.0, 0.4, 0.4, 0.4, 0.4, 0.0, 0.0)
|
|
1338
|
+
|
|
1339
|
+
In the above examples, we did not divide the zones into snow classes. If we do
|
|
1340
|
+
so, method |Calc_Refr_SP_WC_V1| assumes a uniform distribution of the potential
|
|
1341
|
+
refreezing among the individual classes. This assumption implies that if a
|
|
1342
|
+
single snow class does not provide enough liquid water, the actual refreezing
|
|
1343
|
+
of the total zone must be smaller than its potential refreezing rate:
|
|
1344
|
+
|
|
1345
|
+
>>> sclass(2)
|
|
1346
|
+
>>> states.sp = [[0.0], [2.0]]
|
|
1347
|
+
>>> states.wc = [[0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.0],
|
|
1348
|
+
... [0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0]]
|
|
1349
|
+
>>> model.calc_refr_sp_wc_v1()
|
|
1350
|
+
>>> fluxes.refr
|
|
1351
|
+
refr([[0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.0],
|
|
1352
|
+
[0.0, 0.6, 0.6, 0.6, 0.6, 0.6, 0.0]])
|
|
1353
|
+
>>> states.sp
|
|
1354
|
+
sp([[0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.0],
|
|
1355
|
+
[0.0, 2.6, 2.6, 2.6, 2.6, 2.6, 2.0]])
|
|
1356
|
+
>>> states.wc
|
|
1357
|
+
wc([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
1358
|
+
[0.0, 0.4, 0.4, 0.4, 0.4, 0.4, 0.0]])
|
|
1359
|
+
"""
|
|
1360
|
+
|
|
1361
|
+
CONTROLPARAMETERS = (
|
|
1362
|
+
hland_control.NmbZones,
|
|
1363
|
+
hland_control.SClass,
|
|
1364
|
+
hland_control.ZoneType,
|
|
1365
|
+
hland_control.CFR,
|
|
1366
|
+
hland_control.CFMax,
|
|
1367
|
+
)
|
|
1368
|
+
DERIVEDPARAMETERS = (hland_derived.TTM,)
|
|
1369
|
+
REQUIREDSEQUENCES = (hland_factors.TC,)
|
|
1370
|
+
UPDATEDSEQUENCES = (hland_states.WC, hland_states.SP)
|
|
1371
|
+
RESULTSEQUENCES = (hland_fluxes.Refr,)
|
|
1372
|
+
|
|
1373
|
+
@staticmethod
|
|
1374
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1375
|
+
con = model.parameters.control.fastaccess
|
|
1376
|
+
der = model.parameters.derived.fastaccess
|
|
1377
|
+
fac = model.sequences.factors.fastaccess
|
|
1378
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1379
|
+
sta = model.sequences.states.fastaccess
|
|
1380
|
+
for k in range(con.nmbzones):
|
|
1381
|
+
if con.zonetype[k] != ILAKE:
|
|
1382
|
+
if fac.tc[k] < der.ttm[k]:
|
|
1383
|
+
d_potrefr = con.cfr[k] * con.cfmax[k] * (der.ttm[k] - fac.tc[k])
|
|
1384
|
+
for c in range(con.sclass):
|
|
1385
|
+
flu.refr[c, k] = min(d_potrefr, sta.wc[c, k])
|
|
1386
|
+
sta.sp[c, k] += flu.refr[c, k]
|
|
1387
|
+
sta.wc[c, k] -= flu.refr[c, k]
|
|
1388
|
+
else:
|
|
1389
|
+
for c in range(con.sclass):
|
|
1390
|
+
flu.refr[c, k] = 0.0
|
|
1391
|
+
else:
|
|
1392
|
+
for c in range(con.sclass):
|
|
1393
|
+
flu.refr[c, k] = 0.0
|
|
1394
|
+
sta.wc[c, k] = 0.0
|
|
1395
|
+
sta.sp[c, k] = 0.0
|
|
1396
|
+
|
|
1397
|
+
|
|
1398
|
+
class Calc_In_WC_V1(modeltools.Method):
|
|
1399
|
+
r"""Calculate the actual water release from the snow layer due to the exceedance of
|
|
1400
|
+
the snow layers' capacity for (liquid) water.
|
|
1401
|
+
|
|
1402
|
+
Basic equations:
|
|
1403
|
+
:math:`\frac{dWC}{dt} = -In`
|
|
1404
|
+
|
|
1405
|
+
:math:`-In = max(WC - WHC \cdot SP, 0)`
|
|
1406
|
+
|
|
1407
|
+
Examples:
|
|
1408
|
+
|
|
1409
|
+
We initialise seven zones of different types with different frozen water
|
|
1410
|
+
contents of the snow layer and set the relative water holding capacity to 20 %:
|
|
1411
|
+
|
|
1412
|
+
>>> from hydpy.models.hland import *
|
|
1413
|
+
>>> simulationstep("12h")
|
|
1414
|
+
>>> parameterstep("1d")
|
|
1415
|
+
>>> nmbzones(7)
|
|
1416
|
+
>>> sclass(1)
|
|
1417
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED, SEALED, SEALED)
|
|
1418
|
+
>>> whc(0.2)
|
|
1419
|
+
>>> states.sp = 0.0, 10.0, 10.0, 10.0, 10.0, 5.0, 0.0
|
|
1420
|
+
|
|
1421
|
+
Also, we set the actual value of stand precipitation to 5 mm/d:
|
|
1422
|
+
|
|
1423
|
+
>>> fluxes.tf = 5.0
|
|
1424
|
+
|
|
1425
|
+
When there is no (liquid) water content in the snow layer, no water can be
|
|
1426
|
+
released:
|
|
1427
|
+
|
|
1428
|
+
>>> states.wc = 0.0
|
|
1429
|
+
>>> model.calc_in_wc_v1()
|
|
1430
|
+
>>> fluxes.in_
|
|
1431
|
+
in_(5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1432
|
+
>>> states.wc
|
|
1433
|
+
wc(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1434
|
+
|
|
1435
|
+
When there is a (liquid) water content in the snow layer, the water release
|
|
1436
|
+
depends on the frozen water content. Note the special cases of the first zone
|
|
1437
|
+
being an internal lake, for which the snow routine does not apply, and of the
|
|
1438
|
+
last zone, which has no ice content and thus effectively is not a snow layer:
|
|
1439
|
+
|
|
1440
|
+
>>> states.wc = 5.0
|
|
1441
|
+
>>> model.calc_in_wc_v1()
|
|
1442
|
+
>>> fluxes.in_
|
|
1443
|
+
in_(5.0, 3.0, 3.0, 3.0, 3.0, 4.0, 5.0)
|
|
1444
|
+
>>> states.wc
|
|
1445
|
+
wc(0.0, 2.0, 2.0, 2.0, 2.0, 1.0, 0.0)
|
|
1446
|
+
|
|
1447
|
+
For a relative water holding capacity of zero, the snow layer releases all
|
|
1448
|
+
liquid water immediately:
|
|
1449
|
+
|
|
1450
|
+
>>> whc(0.0)
|
|
1451
|
+
>>> states.wc = 5.0
|
|
1452
|
+
>>> model.calc_in_wc_v1()
|
|
1453
|
+
>>> fluxes.in_
|
|
1454
|
+
in_(5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0)
|
|
1455
|
+
>>> states.wc
|
|
1456
|
+
wc(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1457
|
+
|
|
1458
|
+
In the above examples, we did not divide the zones into snow classes. If we do
|
|
1459
|
+
so, method |Calc_In_WC_V1| averages the water release of all snow classes of
|
|
1460
|
+
each zone:
|
|
1461
|
+
|
|
1462
|
+
>>> sclass(2)
|
|
1463
|
+
>>> whc(0.0)
|
|
1464
|
+
>>> states.sp = 0.0, 10.0, 10.0, 10.0, 10.0, 5.0, 0.0
|
|
1465
|
+
>>> states.wc = [[2.0], [3.0]]
|
|
1466
|
+
>>> model.calc_in_wc_v1()
|
|
1467
|
+
>>> fluxes.in_
|
|
1468
|
+
in_(5.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5)
|
|
1469
|
+
>>> states.wc
|
|
1470
|
+
wc([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
1471
|
+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
|
|
1472
|
+
|
|
1473
|
+
For the single lake zone, method |Calc_In_WC_V1| passed the stand precipitation
|
|
1474
|
+
directly to |In_| in all examples.
|
|
1475
|
+
"""
|
|
1476
|
+
|
|
1477
|
+
CONTROLPARAMETERS = (
|
|
1478
|
+
hland_control.NmbZones,
|
|
1479
|
+
hland_control.SClass,
|
|
1480
|
+
hland_control.ZoneType,
|
|
1481
|
+
hland_control.WHC,
|
|
1482
|
+
)
|
|
1483
|
+
REQUIREDSEQUENCES = (hland_fluxes.TF, hland_states.SP)
|
|
1484
|
+
UPDATEDSEQUENCES = (hland_states.WC,)
|
|
1485
|
+
RESULTSEQUENCES = (hland_fluxes.In_,)
|
|
1486
|
+
|
|
1487
|
+
@staticmethod
|
|
1488
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1489
|
+
con = model.parameters.control.fastaccess
|
|
1490
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1491
|
+
sta = model.sequences.states.fastaccess
|
|
1492
|
+
for k in range(con.nmbzones):
|
|
1493
|
+
flu.in_[k] = 0.0
|
|
1494
|
+
if con.zonetype[k] != ILAKE:
|
|
1495
|
+
for c in range(con.sclass):
|
|
1496
|
+
d_wc_old = sta.wc[c, k]
|
|
1497
|
+
sta.wc[c, k] = min(d_wc_old, con.whc[k] * sta.sp[c, k])
|
|
1498
|
+
flu.in_[k] += (d_wc_old - sta.wc[c, k]) / con.sclass
|
|
1499
|
+
else:
|
|
1500
|
+
flu.in_[k] = flu.tf[k]
|
|
1501
|
+
for c in range(con.sclass):
|
|
1502
|
+
sta.wc[c, k] = 0.0
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
class Calc_SWE_V1(modeltools.Method):
|
|
1506
|
+
r"""Calculate the total snow water equivalent.
|
|
1507
|
+
|
|
1508
|
+
Basic equation:
|
|
1509
|
+
:math:`SWE = SP + WC`
|
|
1510
|
+
|
|
1511
|
+
Example:
|
|
1512
|
+
|
|
1513
|
+
We initialise five zones of different types, each one with two snow classes.
|
|
1514
|
+
For internal lakes, |Calc_SWE_V1| generally sets the snow water equivalent to
|
|
1515
|
+
zero. For all others, the given basic equation applies:
|
|
1516
|
+
|
|
1517
|
+
>>> from hydpy.models.hland import *
|
|
1518
|
+
>>> parameterstep()
|
|
1519
|
+
>>> nmbzones(5)
|
|
1520
|
+
>>> sclass(2)
|
|
1521
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED)
|
|
1522
|
+
>>> states.wc = [[0.1, 0.2, 0.3, 0.4, 0.5], [0.6, 0.7, 0.8, 0.9, 1.0]]
|
|
1523
|
+
>>> states.sp = [[1.0, 2.0, 3.0, 4.0, 5.0], [6.0, 7.0, 8.0, 9.0, 10.0]]
|
|
1524
|
+
>>> model.calc_swe_v1()
|
|
1525
|
+
>>> factors.swe
|
|
1526
|
+
swe([[0.0, 2.2, 3.3, 4.4, 5.5],
|
|
1527
|
+
[0.0, 7.7, 8.8, 9.9, 11.0]])
|
|
1528
|
+
"""
|
|
1529
|
+
|
|
1530
|
+
CONTROLPARAMETERS = (
|
|
1531
|
+
hland_control.NmbZones,
|
|
1532
|
+
hland_control.SClass,
|
|
1533
|
+
hland_control.ZoneType,
|
|
1534
|
+
)
|
|
1535
|
+
REQUIREDSEQUENCES = (hland_states.SP, hland_states.WC)
|
|
1536
|
+
RESULTSEQUENCES = (hland_factors.SWE,)
|
|
1537
|
+
|
|
1538
|
+
@staticmethod
|
|
1539
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1540
|
+
con = model.parameters.control.fastaccess
|
|
1541
|
+
fac = model.sequences.factors.fastaccess
|
|
1542
|
+
sta = model.sequences.states.fastaccess
|
|
1543
|
+
for k in range(con.nmbzones):
|
|
1544
|
+
if con.zonetype[k] != ILAKE:
|
|
1545
|
+
for c in range(con.sclass):
|
|
1546
|
+
fac.swe[c, k] = sta.sp[c, k] + sta.wc[c, k]
|
|
1547
|
+
else:
|
|
1548
|
+
for c in range(con.sclass):
|
|
1549
|
+
fac.swe[c, k] = 0.0
|
|
1550
|
+
|
|
1551
|
+
|
|
1552
|
+
class Calc_SR_V1(modeltools.Method):
|
|
1553
|
+
r"""Calculate the sealed surface runoff.
|
|
1554
|
+
|
|
1555
|
+
Basic equations:
|
|
1556
|
+
.. math::
|
|
1557
|
+
SR =
|
|
1558
|
+
\begin{cases}
|
|
1559
|
+
In &|\ ZoneType_k = SEALED
|
|
1560
|
+
\\
|
|
1561
|
+
0 &|\ ZoneType_k \neq SEALED
|
|
1562
|
+
\end{cases}
|
|
1563
|
+
|
|
1564
|
+
Example:
|
|
1565
|
+
|
|
1566
|
+
>>> from hydpy.models.hland import *
|
|
1567
|
+
>>> parameterstep()
|
|
1568
|
+
>>> nmbzones(5)
|
|
1569
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED)
|
|
1570
|
+
>>> fluxes.in_ = 1.0
|
|
1571
|
+
>>> fluxes.sr = 2.0
|
|
1572
|
+
>>> model.calc_sr_v1()
|
|
1573
|
+
>>> fluxes.sr
|
|
1574
|
+
sr(0.0, 0.0, 0.0, 0.0, 1.0)
|
|
1575
|
+
"""
|
|
1576
|
+
|
|
1577
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
1578
|
+
REQUIREDSEQUENCES = (hland_fluxes.In_,)
|
|
1579
|
+
RESULTSEQUENCES = (hland_fluxes.SR,)
|
|
1580
|
+
|
|
1581
|
+
@staticmethod
|
|
1582
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1583
|
+
con = model.parameters.control.fastaccess
|
|
1584
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1585
|
+
for k in range(con.nmbzones):
|
|
1586
|
+
if con.zonetype[k] == SEALED:
|
|
1587
|
+
flu.sr[k] = flu.in_[k]
|
|
1588
|
+
else:
|
|
1589
|
+
flu.sr[k] = 0.0
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
class Calc_GAct_V1(modeltools.Method):
|
|
1593
|
+
r"""Adjust the day degree factor for glacier ice to the current day of the year.
|
|
1594
|
+
|
|
1595
|
+
Basic equations:
|
|
1596
|
+
:math:`GAct = max( GMelt + f \cdot GVar, 0 )`
|
|
1597
|
+
|
|
1598
|
+
:math:`f = sin(2 \cdot Pi \cdot (DOY + 1) / 366) / 2`
|
|
1599
|
+
|
|
1600
|
+
Examples:
|
|
1601
|
+
|
|
1602
|
+
The following examples agree with the ones |Calc_CFAct_V1|, except that method
|
|
1603
|
+
|Calc_GAct_V1| applies the given basic equations only for zones of types
|
|
1604
|
+
|GLACIER| and sets |GAct| to zero for all other zone types:
|
|
1605
|
+
|
|
1606
|
+
>>> from hydpy.models.hland import *
|
|
1607
|
+
>>> simulationstep("12h")
|
|
1608
|
+
>>> parameterstep("1d")
|
|
1609
|
+
>>> nmbzones(5)
|
|
1610
|
+
>>> zonetype(ILAKE, GLACIER, FIELD, FOREST, SEALED)
|
|
1611
|
+
>>> gmelt(4.0)
|
|
1612
|
+
>>> gvar(3.0)
|
|
1613
|
+
>>> from hydpy import UnitTest
|
|
1614
|
+
>>> test = UnitTest(model=model,
|
|
1615
|
+
... method=model.calc_gact_v1,
|
|
1616
|
+
... last_example=10,
|
|
1617
|
+
... parseqs=(derived.doy, factors.gact))
|
|
1618
|
+
>>> test.nexts.doy = 0, 1, 170, 171, 172, 353, 354, 355, 364, 365
|
|
1619
|
+
>>> test()
|
|
1620
|
+
| ex. | doy | gact |
|
|
1621
|
+
-----------------------------------------------------------------
|
|
1622
|
+
| 1 | 0 0 0 0 0 | 0.0 1.264648 0.0 0.0 0.0 |
|
|
1623
|
+
| 2 | 1 1 1 1 1 | 0.0 1.267289 0.0 0.0 0.0 |
|
|
1624
|
+
| 3 | 170 170 170 170 170 | 0.0 2.749762 0.0 0.0 0.0 |
|
|
1625
|
+
| 4 | 171 171 171 171 171 | 0.0 2.749976 0.0 0.0 0.0 |
|
|
1626
|
+
| 5 | 172 172 172 172 172 | 0.0 2.749969 0.0 0.0 0.0 |
|
|
1627
|
+
| 6 | 353 353 353 353 353 | 0.0 1.250238 0.0 0.0 0.0 |
|
|
1628
|
+
| 7 | 354 354 354 354 354 | 0.0 1.250024 0.0 0.0 0.0 |
|
|
1629
|
+
| 8 | 355 355 355 355 355 | 0.0 1.250031 0.0 0.0 0.0 |
|
|
1630
|
+
| 9 | 364 364 364 364 364 | 0.0 1.260018 0.0 0.0 0.0 |
|
|
1631
|
+
| 10 | 365 365 365 365 365 | 0.0 1.262224 0.0 0.0 0.0 |
|
|
1632
|
+
|
|
1633
|
+
>>> zonetype(GLACIER)
|
|
1634
|
+
>>> gvar(0.0, 3.0, -3.0, 10.0, -10.0)
|
|
1635
|
+
>>> test()
|
|
1636
|
+
| ex. | doy | gact |
|
|
1637
|
+
-------------------------------------------------------------------------------
|
|
1638
|
+
| 1 | 0 0 0 0 0 | 2.0 1.264648 2.735352 0.0 4.451173 |
|
|
1639
|
+
| 2 | 1 1 1 1 1 | 2.0 1.267289 2.732711 0.0 4.442371 |
|
|
1640
|
+
| 3 | 170 170 170 170 170 | 2.0 2.749762 1.250238 4.499206 0.0 |
|
|
1641
|
+
| 4 | 171 171 171 171 171 | 2.0 2.749976 1.250024 4.499919 0.0 |
|
|
1642
|
+
| 5 | 172 172 172 172 172 | 2.0 2.749969 1.250031 4.499896 0.0 |
|
|
1643
|
+
| 6 | 353 353 353 353 353 | 2.0 1.250238 2.749762 0.0 4.499206 |
|
|
1644
|
+
| 7 | 354 354 354 354 354 | 2.0 1.250024 2.749976 0.0 4.499919 |
|
|
1645
|
+
| 8 | 355 355 355 355 355 | 2.0 1.250031 2.749969 0.0 4.499896 |
|
|
1646
|
+
| 9 | 364 364 364 364 364 | 2.0 1.260018 2.739982 0.0 4.466606 |
|
|
1647
|
+
| 10 | 365 365 365 365 365 | 2.0 1.262224 2.737776 0.0 4.459252 |
|
|
1648
|
+
"""
|
|
1649
|
+
|
|
1650
|
+
CONTROLPARAMETERS = (
|
|
1651
|
+
hland_control.NmbZones,
|
|
1652
|
+
hland_control.ZoneType,
|
|
1653
|
+
hland_control.GMelt,
|
|
1654
|
+
hland_control.GVar,
|
|
1655
|
+
)
|
|
1656
|
+
FIXEDPARAMETERS = (hland_fixed.Pi,)
|
|
1657
|
+
DERIVEDPARAMETERS = (hland_derived.DOY,)
|
|
1658
|
+
RESULTSEQUENCES = (hland_factors.GAct,)
|
|
1659
|
+
|
|
1660
|
+
@staticmethod
|
|
1661
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1662
|
+
con = model.parameters.control.fastaccess
|
|
1663
|
+
der = model.parameters.derived.fastaccess
|
|
1664
|
+
fix = model.parameters.fixed.fastaccess
|
|
1665
|
+
fac = model.sequences.factors.fastaccess
|
|
1666
|
+
d_factor = 0.5 * modelutils.sin(
|
|
1667
|
+
2 * fix.pi * (der.doy[model.idx_sim] + 1) / 366 - 1.39
|
|
1668
|
+
)
|
|
1669
|
+
for k in range(con.nmbzones):
|
|
1670
|
+
if con.zonetype[k] == GLACIER:
|
|
1671
|
+
fac.gact[k] = max(con.gmelt[k] + d_factor * con.gvar[k], 0.0)
|
|
1672
|
+
else:
|
|
1673
|
+
fac.gact[k] = 0.0
|
|
1674
|
+
|
|
1675
|
+
|
|
1676
|
+
class Calc_GlMelt_In_V1(modeltools.Method):
|
|
1677
|
+
r"""Calculate the melting of non-snow-covered glaciers and add it to the water
|
|
1678
|
+
release of the snow module.
|
|
1679
|
+
|
|
1680
|
+
Basic equation:
|
|
1681
|
+
.. math::
|
|
1682
|
+
GlMelt =
|
|
1683
|
+
\begin{cases}
|
|
1684
|
+
max(GMelt \cdot (TC - TTM), 0) &|\ SP = 0
|
|
1685
|
+
\\
|
|
1686
|
+
0 &|\ SP > 0
|
|
1687
|
+
\end{cases}
|
|
1688
|
+
|
|
1689
|
+
Examples:
|
|
1690
|
+
|
|
1691
|
+
We prepare eight zones. The first four zones are no glaciers, a snow layer
|
|
1692
|
+
covers the sixth zone, and the last two zones actual temperature is not above
|
|
1693
|
+
the threshold temperature. Hence, glacier melting occurs only in the fifth
|
|
1694
|
+
zone:
|
|
1695
|
+
|
|
1696
|
+
>>> from hydpy.models.hland import *
|
|
1697
|
+
>>> simulationstep("12h")
|
|
1698
|
+
>>> parameterstep("1d")
|
|
1699
|
+
>>> nmbzones(8)
|
|
1700
|
+
>>> sclass(1)
|
|
1701
|
+
>>> zonetype(FIELD, FOREST, ILAKE, SEALED, GLACIER, GLACIER, GLACIER, GLACIER)
|
|
1702
|
+
>>> derived.ttm(2.0)
|
|
1703
|
+
>>> factors.tc = 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 2.0, 1.0
|
|
1704
|
+
>>> factors.gact = 2.0
|
|
1705
|
+
>>> states.sp = 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0
|
|
1706
|
+
>>> fluxes.in_ = 3.0
|
|
1707
|
+
>>> model.calc_glmelt_in_v1()
|
|
1708
|
+
>>> fluxes.glmelt
|
|
1709
|
+
glmelt(0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0)
|
|
1710
|
+
>>> fluxes.in_
|
|
1711
|
+
in_(3.0, 3.0, 3.0, 3.0, 5.0, 3.0, 3.0, 3.0)
|
|
1712
|
+
|
|
1713
|
+
In the above examples, we did not divide the zones into snow classes. If we do
|
|
1714
|
+
so, method |Calc_GlMelt_In_V1| sums the glacier melt of all non-snow-covered
|
|
1715
|
+
snow classes of each glacier zone. This assumption implies that if there is a
|
|
1716
|
+
single snow-covered snow class, the actual glacier melting of the total zone
|
|
1717
|
+
must be smaller than its potential melt rate:
|
|
1718
|
+
|
|
1719
|
+
>>> sclass(2)
|
|
1720
|
+
>>> factors.tc = 3.0
|
|
1721
|
+
>>> fluxes.in_ = 3.0
|
|
1722
|
+
>>> states.sp = [[0.0, 0.0, 0.1, 0.1, 0.0, 0.0, 0.1, 0.1],
|
|
1723
|
+
... [0.0, 0.1, 0.0, 0.1, 0.0, 0.1, 0.0, 0.1]]
|
|
1724
|
+
>>> model.calc_glmelt_in_v1()
|
|
1725
|
+
>>> fluxes.glmelt
|
|
1726
|
+
glmelt(0.0, 0.0, 0.0, 0.0, 2.0, 1.0, 1.0, 0.0)
|
|
1727
|
+
>>> fluxes.in_
|
|
1728
|
+
in_(3.0, 3.0, 3.0, 3.0, 5.0, 4.0, 4.0, 3.0)
|
|
1729
|
+
"""
|
|
1730
|
+
|
|
1731
|
+
CONTROLPARAMETERS = (
|
|
1732
|
+
hland_control.NmbZones,
|
|
1733
|
+
hland_control.SClass,
|
|
1734
|
+
hland_control.ZoneType,
|
|
1735
|
+
)
|
|
1736
|
+
DERIVEDPARAMETERS = (hland_derived.TTM,)
|
|
1737
|
+
REQUIREDSEQUENCES = (hland_states.SP, hland_factors.TC, hland_factors.GAct)
|
|
1738
|
+
UPDATEDSEQUENCES = (hland_fluxes.In_,)
|
|
1739
|
+
RESULTSEQUENCES = (hland_fluxes.GlMelt,)
|
|
1740
|
+
|
|
1741
|
+
@staticmethod
|
|
1742
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1743
|
+
con = model.parameters.control.fastaccess
|
|
1744
|
+
der = model.parameters.derived.fastaccess
|
|
1745
|
+
fac = model.sequences.factors.fastaccess
|
|
1746
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1747
|
+
sta = model.sequences.states.fastaccess
|
|
1748
|
+
for k in range(con.nmbzones):
|
|
1749
|
+
flu.glmelt[k] = 0.0
|
|
1750
|
+
if (con.zonetype[k] == GLACIER) and (fac.tc[k] > der.ttm[k]):
|
|
1751
|
+
d_glmeltpot = fac.gact[k] / con.sclass * (fac.tc[k] - der.ttm[k])
|
|
1752
|
+
for c in range(con.sclass):
|
|
1753
|
+
if sta.sp[c, k] <= 0.0:
|
|
1754
|
+
flu.glmelt[k] += d_glmeltpot
|
|
1755
|
+
flu.in_[k] += d_glmeltpot
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
class Calc_R_SM_V1(modeltools.Method):
|
|
1759
|
+
r"""Calculate effective precipitation and update the soil moisture.
|
|
1760
|
+
|
|
1761
|
+
Basic equations:
|
|
1762
|
+
:math:`\frac{dSM}{dt} = IN - R`
|
|
1763
|
+
|
|
1764
|
+
:math:`R = IN \cdot \left( \frac{SM}{FC} \right)^{Beta}`
|
|
1765
|
+
|
|
1766
|
+
|
|
1767
|
+
Examples:
|
|
1768
|
+
|
|
1769
|
+
We initialise seven zones of different types. The field capacity of all fields
|
|
1770
|
+
and forests is 200 mm, the input of each zone is 10 mm:
|
|
1771
|
+
|
|
1772
|
+
>>> from hydpy.models.hland import *
|
|
1773
|
+
>>> simulationstep("12h")
|
|
1774
|
+
>>> parameterstep("1d")
|
|
1775
|
+
>>> nmbzones(7)
|
|
1776
|
+
>>> zonetype(ILAKE, GLACIER, SEALED, FIELD, FIELD, FOREST, FOREST)
|
|
1777
|
+
>>> fc(200.0)
|
|
1778
|
+
>>> fluxes.in_ = 10.0
|
|
1779
|
+
|
|
1780
|
+
With the typical nonlinearity parameter value of 2, relative soil moisture of
|
|
1781
|
+
50 % (zones five and six) results in a discharge coefficient of 25 %. For
|
|
1782
|
+
a completely dried (zone four) or saturated soil (zone seven), the discharge
|
|
1783
|
+
coefficient is generally 0 % and 100 %, respectively. Glaciers, internal lakes
|
|
1784
|
+
and sealed areas always route 100% of their input as effective precipitation:
|
|
1785
|
+
|
|
1786
|
+
>>> beta(2.0)
|
|
1787
|
+
>>> states.sm = 0.0, 0.0, 0.0, 0.0, 100.0, 100.0, 200.0
|
|
1788
|
+
>>> model.calc_r_sm_v1()
|
|
1789
|
+
>>> fluxes.r
|
|
1790
|
+
r(10.0, 10.0, 10.0, 0.0, 2.5, 2.5, 10.0)
|
|
1791
|
+
>>> states.sm
|
|
1792
|
+
sm(0.0, 0.0, 0.0, 10.0, 107.5, 107.5, 200.0)
|
|
1793
|
+
|
|
1794
|
+
By decreasing the nonlinearity parameter, the discharge coefficient increases.
|
|
1795
|
+
A parameter value of zero leads to a discharge coefficient of 100 % for any
|
|
1796
|
+
soil moisture:
|
|
1797
|
+
|
|
1798
|
+
>>> beta(0.0)
|
|
1799
|
+
>>> states.sm = 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0
|
|
1800
|
+
>>> model.calc_r_sm_v1()
|
|
1801
|
+
>>> fluxes.r
|
|
1802
|
+
r(10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0)
|
|
1803
|
+
>>> states.sm
|
|
1804
|
+
sm(0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0)
|
|
1805
|
+
|
|
1806
|
+
Also, with a field capacity of zero, the discharge coefficient always equates
|
|
1807
|
+
to 100 %:
|
|
1808
|
+
|
|
1809
|
+
>>> fc(0.0)
|
|
1810
|
+
>>> beta(2.0)
|
|
1811
|
+
>>> states.sm = 0.0
|
|
1812
|
+
>>> model.calc_r_sm_v1()
|
|
1813
|
+
>>> fluxes.r
|
|
1814
|
+
r(10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0)
|
|
1815
|
+
>>> states.sm
|
|
1816
|
+
sm(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1817
|
+
"""
|
|
1818
|
+
|
|
1819
|
+
CONTROLPARAMETERS = (
|
|
1820
|
+
hland_control.NmbZones,
|
|
1821
|
+
hland_control.ZoneType,
|
|
1822
|
+
hland_control.FC,
|
|
1823
|
+
hland_control.Beta,
|
|
1824
|
+
)
|
|
1825
|
+
REQUIREDSEQUENCES = (hland_fluxes.In_,)
|
|
1826
|
+
UPDATEDSEQUENCES = (hland_states.SM,)
|
|
1827
|
+
RESULTSEQUENCES = (hland_fluxes.R,)
|
|
1828
|
+
|
|
1829
|
+
@staticmethod
|
|
1830
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1831
|
+
con = model.parameters.control.fastaccess
|
|
1832
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1833
|
+
sta = model.sequences.states.fastaccess
|
|
1834
|
+
for k in range(con.nmbzones):
|
|
1835
|
+
if con.zonetype[k] in (FIELD, FOREST):
|
|
1836
|
+
if con.fc[k] > 0.0:
|
|
1837
|
+
flu.r[k] = flu.in_[k] * (sta.sm[k] / con.fc[k]) ** con.beta[k]
|
|
1838
|
+
flu.r[k] = max(flu.r[k], sta.sm[k] + flu.in_[k] - con.fc[k])
|
|
1839
|
+
else:
|
|
1840
|
+
flu.r[k] = flu.in_[k]
|
|
1841
|
+
sta.sm[k] += flu.in_[k] - flu.r[k]
|
|
1842
|
+
else:
|
|
1843
|
+
flu.r[k] = flu.in_[k]
|
|
1844
|
+
sta.sm[k] = 0.0
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
class Calc_CF_SM_V1(modeltools.Method):
|
|
1848
|
+
r"""Calculate capillary flow and update the soil moisture.
|
|
1849
|
+
|
|
1850
|
+
Basic equations:
|
|
1851
|
+
:math:`\frac{dSM}{dt} = CF`
|
|
1852
|
+
|
|
1853
|
+
:math:`CF = CFLUX \cdot (1 - \frac{SM}{FC})`
|
|
1854
|
+
|
|
1855
|
+
Examples:
|
|
1856
|
+
|
|
1857
|
+
We initialise seven zones of different types. For all fields and forests, the
|
|
1858
|
+
field capacity is 200 mm and the maximum capillary flow rate is 4 mm/d:
|
|
1859
|
+
|
|
1860
|
+
>>> from hydpy.models.hland import *
|
|
1861
|
+
>>> simulationstep("12h")
|
|
1862
|
+
>>> parameterstep("1d")
|
|
1863
|
+
>>> nmbzones(7)
|
|
1864
|
+
>>> zonetype(ILAKE, GLACIER, SEALED, FIELD, FOREST, FOREST, FOREST)
|
|
1865
|
+
>>> fc(200.0)
|
|
1866
|
+
>>> cflux(4.0)
|
|
1867
|
+
|
|
1868
|
+
Note that the assumed length of the simulation step is only half a day. Hence
|
|
1869
|
+
the maximum capillary flow per simulation step is 2 instead of 4:
|
|
1870
|
+
|
|
1871
|
+
>>> cflux
|
|
1872
|
+
cflux(4.0)
|
|
1873
|
+
>>> from hydpy import round_
|
|
1874
|
+
>>> round_(cflux.values[0])
|
|
1875
|
+
2.0
|
|
1876
|
+
|
|
1877
|
+
For fields and forests, the actual capillary return flow depends only on the
|
|
1878
|
+
relative soil moisture deficit, provided that the upper zone layer stores
|
|
1879
|
+
enough water or that enough "routable" effective precipitation is available:
|
|
1880
|
+
|
|
1881
|
+
>>> fluxes.r = 0.0
|
|
1882
|
+
>>> states.sm = 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0
|
|
1883
|
+
>>> states.uz = 20.0
|
|
1884
|
+
>>> model.calc_cf_sm_v1()
|
|
1885
|
+
>>> fluxes.cf
|
|
1886
|
+
cf(0.0, 0.0, 0.0, 1.0, 1.0, 2.0, 0.0)
|
|
1887
|
+
>>> states.sm
|
|
1888
|
+
sm(0.0, 0.0, 0.0, 101.0, 101.0, 2.0, 200.0)
|
|
1889
|
+
|
|
1890
|
+
>>> states.sm = 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0
|
|
1891
|
+
>>> states.uz = 0.0
|
|
1892
|
+
>>> model.calc_cf_sm_v1()
|
|
1893
|
+
>>> fluxes.cf
|
|
1894
|
+
cf(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1895
|
+
>>> states.sm
|
|
1896
|
+
sm(0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0)
|
|
1897
|
+
|
|
1898
|
+
If the upper zone layer is empty and no effective precipitation is available,
|
|
1899
|
+
capillary flow is zero:
|
|
1900
|
+
|
|
1901
|
+
>>> fluxes.r = 0.0
|
|
1902
|
+
>>> states.sm = 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0
|
|
1903
|
+
>>> states.uz = 0.0
|
|
1904
|
+
>>> model.calc_cf_sm_v1()
|
|
1905
|
+
>>> fluxes.cf
|
|
1906
|
+
cf(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1907
|
+
>>> states.sm
|
|
1908
|
+
sm(0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0)
|
|
1909
|
+
|
|
1910
|
+
In the following example, both the upper zone layer and effective precipitation
|
|
1911
|
+
provide water for the capillary flow but less than the maximum flow rate times
|
|
1912
|
+
the relative soil moisture:
|
|
1913
|
+
|
|
1914
|
+
>>> fluxes.r = 0.1
|
|
1915
|
+
>>> states.sm = 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0
|
|
1916
|
+
>>> states.uz = 0.2
|
|
1917
|
+
>>> model.calc_cf_sm_v1()
|
|
1918
|
+
>>> fluxes.cf
|
|
1919
|
+
cf(0.0, 0.0, 0.0, 0.3, 0.3, 0.3, 0.0)
|
|
1920
|
+
>>> states.sm
|
|
1921
|
+
sm(0.0, 0.0, 0.0, 100.3, 100.3, 0.3, 200.0)
|
|
1922
|
+
|
|
1923
|
+
Even unrealistic high maximum capillary flow rates do not result in overfilled
|
|
1924
|
+
soils:
|
|
1925
|
+
|
|
1926
|
+
>>> cflux(1000.0)
|
|
1927
|
+
>>> fluxes.r = 200.0
|
|
1928
|
+
>>> states.sm = 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 200.0
|
|
1929
|
+
>>> states.uz = 200.0
|
|
1930
|
+
>>> model.calc_cf_sm_v1()
|
|
1931
|
+
>>> fluxes.cf
|
|
1932
|
+
cf(0.0, 0.0, 0.0, 100.0, 100.0, 200.0, 0.0)
|
|
1933
|
+
>>> states.sm
|
|
1934
|
+
sm(0.0, 0.0, 0.0, 200.0, 200.0, 200.0, 200.0)
|
|
1935
|
+
|
|
1936
|
+
For soils with zero field capacity, capillary flow is always zero:
|
|
1937
|
+
|
|
1938
|
+
>>> fc(0.0)
|
|
1939
|
+
>>> states.sm = 0.0
|
|
1940
|
+
>>> model.calc_cf_sm_v1()
|
|
1941
|
+
>>> fluxes.cf
|
|
1942
|
+
cf(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1943
|
+
>>> states.sm
|
|
1944
|
+
sm(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
1945
|
+
"""
|
|
1946
|
+
|
|
1947
|
+
CONTROLPARAMETERS = (
|
|
1948
|
+
hland_control.NmbZones,
|
|
1949
|
+
hland_control.ZoneType,
|
|
1950
|
+
hland_control.FC,
|
|
1951
|
+
hland_control.CFlux,
|
|
1952
|
+
)
|
|
1953
|
+
REQUIREDSEQUENCES = (hland_fluxes.R, hland_states.UZ)
|
|
1954
|
+
UPDATEDSEQUENCES = (hland_states.SM,)
|
|
1955
|
+
RESULTSEQUENCES = (hland_fluxes.CF,)
|
|
1956
|
+
|
|
1957
|
+
@staticmethod
|
|
1958
|
+
def __call__(model: modeltools.Model) -> None:
|
|
1959
|
+
con = model.parameters.control.fastaccess
|
|
1960
|
+
flu = model.sequences.fluxes.fastaccess
|
|
1961
|
+
sta = model.sequences.states.fastaccess
|
|
1962
|
+
for k in range(con.nmbzones):
|
|
1963
|
+
if con.zonetype[k] in (FIELD, FOREST):
|
|
1964
|
+
if con.fc[k] > 0.0:
|
|
1965
|
+
flu.cf[k] = con.cflux[k] * (1.0 - sta.sm[k] / con.fc[k])
|
|
1966
|
+
flu.cf[k] = min(flu.cf[k], sta.uz + flu.r[k])
|
|
1967
|
+
flu.cf[k] = min(flu.cf[k], con.fc[k] - sta.sm[k])
|
|
1968
|
+
else:
|
|
1969
|
+
flu.cf[k] = 0.0
|
|
1970
|
+
sta.sm[k] += flu.cf[k]
|
|
1971
|
+
else:
|
|
1972
|
+
flu.cf[k] = 0.0
|
|
1973
|
+
sta.sm[k] = 0.0
|
|
1974
|
+
|
|
1975
|
+
|
|
1976
|
+
class Calc_EA_SM_AETModel_V1(modeltools.Method):
|
|
1977
|
+
r"""Let a submodel that follows the |AETModel_V1| submodel interface calculate
|
|
1978
|
+
soil evapotranspiration and adjust the soil water content.
|
|
1979
|
+
|
|
1980
|
+
Basic equation:
|
|
1981
|
+
:math:`\frac{dSM_i}{dt} = -EA_i`
|
|
1982
|
+
|
|
1983
|
+
Examples:
|
|
1984
|
+
|
|
1985
|
+
We build an example based on |evap_aet_hbv96| for calculating soil
|
|
1986
|
+
evapotranspiration:
|
|
1987
|
+
|
|
1988
|
+
>>> from hydpy.models.hland_96 import *
|
|
1989
|
+
>>> parameterstep("1h")
|
|
1990
|
+
>>> nmbzones(5)
|
|
1991
|
+
>>> zonetype(GLACIER, SEALED, FIELD, FOREST, ILAKE)
|
|
1992
|
+
>>> area(1.0)
|
|
1993
|
+
>>> zonearea(0.05, 0.1, 0.2, 0.3, 0.35)
|
|
1994
|
+
>>> zonez(5.0)
|
|
1995
|
+
>>> fc(50.0)
|
|
1996
|
+
>>> fluxes.r = 0.5
|
|
1997
|
+
>>> with model.add_aetmodel_v1("evap_aet_hbv96"):
|
|
1998
|
+
... soilmoisturelimit(0.0)
|
|
1999
|
+
... excessreduction(field=0.5, forest=0.0)
|
|
2000
|
+
|
|
2001
|
+
|Calc_EA_SM_AETModel_V1| uses the flux returned by the submodel to adjust |SM|:
|
|
2002
|
+
|
|
2003
|
+
>>> model.aetmodel.sequences.fluxes.potentialinterceptionevaporation = 1.0
|
|
2004
|
+
>>> model.aetmodel.sequences.fluxes.potentialsoilevapotranspiration = 1.0
|
|
2005
|
+
>>> model.aetmodel.sequences.fluxes.interceptionevaporation = 1.0
|
|
2006
|
+
>>> states.sm = 3.0
|
|
2007
|
+
>>> model.calc_ea_sm_v1()
|
|
2008
|
+
>>> fluxes.ea
|
|
2009
|
+
ea(0.0, 0.0, 0.5, 1.0, 0.0)
|
|
2010
|
+
>>> states.sm
|
|
2011
|
+
sm(0.0, 0.0, 2.5, 2.0, 0.0)
|
|
2012
|
+
>>> fluxes.r
|
|
2013
|
+
r(0.5, 0.5, 0.5, 0.5, 0.5)
|
|
2014
|
+
|
|
2015
|
+
|Calc_EA_SM_AETModel_V1| eventually reduces |EA| so that |SM| does not become
|
|
2016
|
+
negative:
|
|
2017
|
+
|
|
2018
|
+
>>> model.aetmodel.sequences.fluxes.potentialinterceptionevaporation = 5.0
|
|
2019
|
+
>>> model.aetmodel.sequences.fluxes.potentialsoilevapotranspiration = 5.0
|
|
2020
|
+
>>> model.aetmodel.sequences.fluxes.interceptionevaporation = 5.0
|
|
2021
|
+
>>> states.sm = 3.0
|
|
2022
|
+
>>> model.calc_ea_sm_v1()
|
|
2023
|
+
>>> fluxes.ea
|
|
2024
|
+
ea(0.0, 0.0, 2.5, 3.0, 0.0)
|
|
2025
|
+
>>> states.sm
|
|
2026
|
+
sm(0.0, 0.0, 0.5, 0.0, 0.0)
|
|
2027
|
+
>>> fluxes.r
|
|
2028
|
+
r(0.5, 0.5, 0.5, 0.5, 0.5)
|
|
2029
|
+
|
|
2030
|
+
|Calc_EA_SM_AETModel_V1| converts any amounts of condensation (negative |EA|)
|
|
2031
|
+
that would cause soil water to exceed field capacity to the effective soil
|
|
2032
|
+
response (|R|):
|
|
2033
|
+
|
|
2034
|
+
>>> model.aetmodel.sequences.fluxes.potentialinterceptionevaporation = -5.0
|
|
2035
|
+
>>> model.aetmodel.sequences.fluxes.potentialsoilevapotranspiration = -5.0
|
|
2036
|
+
>>> model.aetmodel.sequences.fluxes.interceptionevaporation = -5.0
|
|
2037
|
+
>>> states.sm = 47.0
|
|
2038
|
+
>>> model.calc_ea_sm_v1()
|
|
2039
|
+
>>> fluxes.ea
|
|
2040
|
+
ea(0.0, 0.0, -2.5, -5.0, 0.0)
|
|
2041
|
+
>>> states.sm
|
|
2042
|
+
sm(0.0, 0.0, 49.5, 50.0, 0.0)
|
|
2043
|
+
>>> fluxes.r
|
|
2044
|
+
r(0.5, 0.5, 0.5, 2.5, 0.5)
|
|
2045
|
+
"""
|
|
2046
|
+
|
|
2047
|
+
CONTROLPARAMETERS = (
|
|
2048
|
+
hland_control.NmbZones,
|
|
2049
|
+
hland_control.ZoneType,
|
|
2050
|
+
hland_control.FC,
|
|
2051
|
+
)
|
|
2052
|
+
UPDATEDSEQUENCES = (hland_states.SM, hland_fluxes.R)
|
|
2053
|
+
RESULTSEQUENCES = (hland_fluxes.EA,)
|
|
2054
|
+
|
|
2055
|
+
@staticmethod
|
|
2056
|
+
def __call__(model: modeltools.Model, submodel: aetinterfaces.AETModel_V1) -> None:
|
|
2057
|
+
con = model.parameters.control.fastaccess
|
|
2058
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2059
|
+
sta = model.sequences.states.fastaccess
|
|
2060
|
+
submodel.determine_soilevapotranspiration()
|
|
2061
|
+
for k in range(con.nmbzones):
|
|
2062
|
+
if con.zonetype[k] in (FIELD, FOREST):
|
|
2063
|
+
flu.ea[k] = min(submodel.get_soilevapotranspiration(k), sta.sm[k])
|
|
2064
|
+
sta.sm[k] -= flu.ea[k]
|
|
2065
|
+
if sta.sm[k] > con.fc[k]:
|
|
2066
|
+
flu.r[k] += sta.sm[k] - con.fc[k]
|
|
2067
|
+
sta.sm[k] = con.fc[k]
|
|
2068
|
+
else:
|
|
2069
|
+
flu.ea[k] = 0.0
|
|
2070
|
+
sta.sm[k] = 0.0
|
|
2071
|
+
|
|
2072
|
+
|
|
2073
|
+
class Calc_EA_SM_V1(modeltools.Method):
|
|
2074
|
+
"""Let a submodel that follows the |AETModel_V1| submodel interface calculate soil
|
|
2075
|
+
evapotranspiration and adjust the soil water content."""
|
|
2076
|
+
|
|
2077
|
+
SUBMODELINTERFACES = (aetinterfaces.AETModel_V1,)
|
|
2078
|
+
SUBMETHODS = (Calc_EA_SM_AETModel_V1,)
|
|
2079
|
+
CONTROLPARAMETERS = (
|
|
2080
|
+
hland_control.NmbZones,
|
|
2081
|
+
hland_control.ZoneType,
|
|
2082
|
+
hland_control.FC,
|
|
2083
|
+
)
|
|
2084
|
+
UPDATEDSEQUENCES = (hland_states.SM, hland_fluxes.R)
|
|
2085
|
+
RESULTSEQUENCES = (hland_fluxes.EA,)
|
|
2086
|
+
|
|
2087
|
+
@staticmethod
|
|
2088
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2089
|
+
if model.aetmodel_typeid == 1:
|
|
2090
|
+
model.calc_ea_sm_aetmodel_v1(
|
|
2091
|
+
cast(aetinterfaces.AETModel_V1, model.aetmodel)
|
|
2092
|
+
)
|
|
2093
|
+
# ToDo:
|
|
2094
|
+
# else:
|
|
2095
|
+
# assert_never(model.petmodel)
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
class Calc_InUZ_V1(modeltools.Method):
|
|
2099
|
+
r"""Accumulate the total inflow into the upper zone layer.
|
|
2100
|
+
|
|
2101
|
+
Basic equation:
|
|
2102
|
+
.. math::
|
|
2103
|
+
InUZ = \sum_{k=1}^{NmbZones} \frac{RelZoneAreas_k}{RelUpperZoneArea} \cdot
|
|
2104
|
+
\begin{cases}
|
|
2105
|
+
R-CF &|\ ZoneType_k \in \{FIELD, FOREST, GLACIER \}
|
|
2106
|
+
\\
|
|
2107
|
+
0 &|\ ZoneType_k \notin \{FIELD, FOREST, GLACIER \}
|
|
2108
|
+
\end{cases}
|
|
2109
|
+
|
|
2110
|
+
Examples:
|
|
2111
|
+
|
|
2112
|
+
We initialise five zones of different land-use types and sizes. Method
|
|
2113
|
+
|Calc_InUZ_V1| takes only those of type |FIELD|, |FOREST|, and |GLACIER| into
|
|
2114
|
+
account:
|
|
2115
|
+
|
|
2116
|
+
>>> from hydpy.models.hland import *
|
|
2117
|
+
>>> simulationstep("12h")
|
|
2118
|
+
>>> parameterstep("1d")
|
|
2119
|
+
>>> nmbzones(5)
|
|
2120
|
+
>>> zonetype(FIELD, FOREST, ILAKE, GLACIER, SEALED)
|
|
2121
|
+
>>> derived.relzoneareas = 0.25, 0.2, 0.4, 0.05, 0.1
|
|
2122
|
+
>>> derived.relupperzonearea = 0.5
|
|
2123
|
+
>>> fluxes.r = 2.0, 4.0, 1.0, 6.0, 1.0
|
|
2124
|
+
>>> fluxes.cf = 1.0, 2.0, 0.5, 3.0, 0.5
|
|
2125
|
+
>>> model.calc_inuz_v1()
|
|
2126
|
+
>>> fluxes.inuz
|
|
2127
|
+
inuz(1.6)
|
|
2128
|
+
|
|
2129
|
+
Internal lakes and sealed areas do not contribute to the upper zone layer.
|
|
2130
|
+
Hence, for a subbasin consisting only of such zones, |InUZ| is zero:
|
|
2131
|
+
|
|
2132
|
+
>>> zonetype(ILAKE, ILAKE, ILAKE, SEALED, SEALED)
|
|
2133
|
+
>>> model.calc_inuz_v1()
|
|
2134
|
+
>>> fluxes.inuz
|
|
2135
|
+
inuz(0.0)
|
|
2136
|
+
"""
|
|
2137
|
+
|
|
2138
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
2139
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelUpperZoneArea)
|
|
2140
|
+
REQUIREDSEQUENCES = (hland_fluxes.R, hland_fluxes.CF)
|
|
2141
|
+
RESULTSEQUENCES = (hland_fluxes.InUZ,)
|
|
2142
|
+
|
|
2143
|
+
@staticmethod
|
|
2144
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2145
|
+
con = model.parameters.control.fastaccess
|
|
2146
|
+
der = model.parameters.derived.fastaccess
|
|
2147
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2148
|
+
flu.inuz = 0.0
|
|
2149
|
+
for k in range(con.nmbzones):
|
|
2150
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
2151
|
+
flu.inuz += (
|
|
2152
|
+
der.relzoneareas[k] / der.relupperzonearea * (flu.r[k] - flu.cf[k])
|
|
2153
|
+
)
|
|
2154
|
+
|
|
2155
|
+
|
|
2156
|
+
class Calc_SUZ_V1(modeltools.Method):
|
|
2157
|
+
r"""Add the effective precipitation to the upper storage reservoir.
|
|
2158
|
+
|
|
2159
|
+
Basic equation:
|
|
2160
|
+
:math:`\frac{SUZ}{dt} = R`
|
|
2161
|
+
|
|
2162
|
+
Example:
|
|
2163
|
+
|
|
2164
|
+
For internal lakes and sealed areas, method |Calc_SUZ_V1| always sets |SUZ| to
|
|
2165
|
+
zero:
|
|
2166
|
+
|
|
2167
|
+
>>> from hydpy.models.hland import *
|
|
2168
|
+
>>> simulationstep("12h")
|
|
2169
|
+
>>> parameterstep()
|
|
2170
|
+
>>> nmbzones(4)
|
|
2171
|
+
>>> zonetype(FIELD, ILAKE, GLACIER, SEALED)
|
|
2172
|
+
>>> states.suz = 1.0, 0.0, 2.0, 0.0
|
|
2173
|
+
>>> fluxes.r = 2.0
|
|
2174
|
+
>>> model.calc_suz_v1()
|
|
2175
|
+
>>> states.suz
|
|
2176
|
+
suz(3.0, 0.0, 4.0, 0.0)
|
|
2177
|
+
"""
|
|
2178
|
+
|
|
2179
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
2180
|
+
REQUIREDSEQUENCES = (hland_fluxes.R,)
|
|
2181
|
+
UPDATEDSEQUENCES = (hland_states.SUZ,)
|
|
2182
|
+
|
|
2183
|
+
@staticmethod
|
|
2184
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2185
|
+
con = model.parameters.control.fastaccess
|
|
2186
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2187
|
+
sta = model.sequences.states.fastaccess
|
|
2188
|
+
for k in range(con.nmbzones):
|
|
2189
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
2190
|
+
sta.suz[k] += flu.r[k]
|
|
2191
|
+
else:
|
|
2192
|
+
sta.suz[k] = 0.0
|
|
2193
|
+
|
|
2194
|
+
|
|
2195
|
+
class Calc_ContriArea_V1(modeltools.Method):
|
|
2196
|
+
r"""Determine the relative size of the contributing area of the whole subbasin.
|
|
2197
|
+
|
|
2198
|
+
Basic equation:
|
|
2199
|
+
:math:`ContriArea = \left( \frac{SM}{FC} \right)^{Beta}`
|
|
2200
|
+
|
|
2201
|
+
Examples:
|
|
2202
|
+
|
|
2203
|
+
We initialise five zones. Method |Calc_ContriArea_V1| takes only the first two
|
|
2204
|
+
zones of type field and forest into account (even though glaciers also
|
|
2205
|
+
contribute to the inflow of the upper zone layer):
|
|
2206
|
+
|
|
2207
|
+
>>> from hydpy.models.hland import *
|
|
2208
|
+
>>> simulationstep("12h")
|
|
2209
|
+
>>> parameterstep("1d")
|
|
2210
|
+
>>> nmbzones(5)
|
|
2211
|
+
>>> zonetype(FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
2212
|
+
>>> beta(2.0)
|
|
2213
|
+
>>> fc(200.0)
|
|
2214
|
+
>>> resparea(True)
|
|
2215
|
+
>>> derived.relzoneareas(1.0/6.0, 2.0/6.0, 1.0/6.0, 1.0/6.0, 1.0/6.0)
|
|
2216
|
+
>>> derived.relsoilarea(0.5)
|
|
2217
|
+
|
|
2218
|
+
With relative soil moisture of 100 % in the whole subbasin, the contributing
|
|
2219
|
+
area is also 100 %:
|
|
2220
|
+
|
|
2221
|
+
>>> states.sm = 200.0
|
|
2222
|
+
>>> model.calc_contriarea_v1()
|
|
2223
|
+
>>> factors.contriarea
|
|
2224
|
+
contriarea(1.0)
|
|
2225
|
+
|
|
2226
|
+
Relative soil moistures of 0 % result in a contributing area of 0 %:
|
|
2227
|
+
|
|
2228
|
+
>>> states.sm = 0.0
|
|
2229
|
+
>>> model.calc_contriarea_v1()
|
|
2230
|
+
>>> factors.contriarea
|
|
2231
|
+
contriarea(0.0)
|
|
2232
|
+
|
|
2233
|
+
For the given value 2 of the nonlinearity parameter |Beta|, soil moisture of
|
|
2234
|
+
50 % corresponds to contributing area of 25 %:
|
|
2235
|
+
|
|
2236
|
+
>>> states.sm = 100.0
|
|
2237
|
+
>>> model.calc_contriarea_v1()
|
|
2238
|
+
>>> factors.contriarea
|
|
2239
|
+
contriarea(0.25)
|
|
2240
|
+
|
|
2241
|
+
Setting the |RespArea| option to |False|, the soil area (total area of all
|
|
2242
|
+
field and forest zones in the subbasin) to zero, or all field capacities to
|
|
2243
|
+
zero, results in contributing area values of 100 %:
|
|
2244
|
+
|
|
2245
|
+
>>> resparea(False)
|
|
2246
|
+
>>> model.calc_contriarea_v1()
|
|
2247
|
+
>>> factors.contriarea
|
|
2248
|
+
contriarea(1.0)
|
|
2249
|
+
|
|
2250
|
+
>>> resparea(True)
|
|
2251
|
+
>>> derived.relsoilarea(0.0)
|
|
2252
|
+
>>> model.calc_contriarea_v1()
|
|
2253
|
+
>>> factors.contriarea
|
|
2254
|
+
contriarea(1.0)
|
|
2255
|
+
|
|
2256
|
+
>>> derived.relsoilarea(0.5)
|
|
2257
|
+
>>> fc(0.0)
|
|
2258
|
+
>>> states.sm = 0.0
|
|
2259
|
+
>>> model.calc_contriarea_v1()
|
|
2260
|
+
>>> factors.contriarea
|
|
2261
|
+
contriarea(1.0)
|
|
2262
|
+
"""
|
|
2263
|
+
|
|
2264
|
+
CONTROLPARAMETERS = (
|
|
2265
|
+
hland_control.RespArea,
|
|
2266
|
+
hland_control.NmbZones,
|
|
2267
|
+
hland_control.ZoneType,
|
|
2268
|
+
hland_control.FC,
|
|
2269
|
+
hland_control.Beta,
|
|
2270
|
+
)
|
|
2271
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelSoilArea)
|
|
2272
|
+
REQUIREDSEQUENCES = (hland_states.SM,)
|
|
2273
|
+
RESULTSEQUENCES = (hland_factors.ContriArea,)
|
|
2274
|
+
|
|
2275
|
+
@staticmethod
|
|
2276
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2277
|
+
con = model.parameters.control.fastaccess
|
|
2278
|
+
der = model.parameters.derived.fastaccess
|
|
2279
|
+
fac = model.sequences.factors.fastaccess
|
|
2280
|
+
sta = model.sequences.states.fastaccess
|
|
2281
|
+
fac.contriarea = 1.0
|
|
2282
|
+
if con.resparea and (der.relsoilarea > 0.0):
|
|
2283
|
+
for k in range(con.nmbzones):
|
|
2284
|
+
if con.zonetype[k] in (FIELD, FOREST):
|
|
2285
|
+
if con.fc[k] > 0.0:
|
|
2286
|
+
d_weight = der.relzoneareas[k] / der.relsoilarea
|
|
2287
|
+
fac.contriarea *= (sta.sm[k] / con.fc[k]) ** d_weight
|
|
2288
|
+
fac.contriarea **= con.beta[k]
|
|
2289
|
+
|
|
2290
|
+
|
|
2291
|
+
class Calc_Q0_Perc_UZ_V1(modeltools.Method):
|
|
2292
|
+
r"""Calculate the percolation and direct runoff leaving the upper zone storage
|
|
2293
|
+
and update it accordingly.
|
|
2294
|
+
|
|
2295
|
+
Basic equations:
|
|
2296
|
+
:math:`\frac{dUZ}{dt} = InUZ - Perc - Q0`
|
|
2297
|
+
|
|
2298
|
+
:math:`Perc = PercMax \cdot ContriArea`
|
|
2299
|
+
|
|
2300
|
+
:math:`Q0 = K \cdot \left( \frac{UZ}{ContriArea} \right)^{1+Alpha}`
|
|
2301
|
+
|
|
2302
|
+
Note that the system behaviour of this method depends strongly on the
|
|
2303
|
+
specifications of the options |RespArea| and |RecStep|.
|
|
2304
|
+
|
|
2305
|
+
Examples:
|
|
2306
|
+
|
|
2307
|
+
First, we prepare a small helper function for checking if method
|
|
2308
|
+
|Calc_Q0_Perc_UZ_V1| always complies with the water balance equation, assuming
|
|
2309
|
+
an initial content of the upper zone storage of 1 mm:
|
|
2310
|
+
|
|
2311
|
+
>>> from hydpy import round_
|
|
2312
|
+
>>> def check():
|
|
2313
|
+
... error = 1.0 + fluxes.inuz - fluxes.perc - fluxes.q0 - states.uz
|
|
2314
|
+
... assert round(error, 12) == 0
|
|
2315
|
+
|
|
2316
|
+
The upper zone layer routine is an exception compared to the other subroutines
|
|
2317
|
+
of |hland| regarding numerical accuracy. Method |Calc_Q0_Perc_UZ_V1| divides
|
|
2318
|
+
each simulation step into substeps and solves each substep with the explicit
|
|
2319
|
+
Euler method. The more substeps involved, the more precise the numerical
|
|
2320
|
+
integration of the underlying ordinary differential equations. In the first
|
|
2321
|
+
example, we omit this option by setting the |RecStep| parameter, which defines
|
|
2322
|
+
the number of substeps, to one:
|
|
2323
|
+
|
|
2324
|
+
>>> from hydpy.models.hland import *
|
|
2325
|
+
>>> simulationstep("12h")
|
|
2326
|
+
>>> parameterstep("1d")
|
|
2327
|
+
>>> recstep(2)
|
|
2328
|
+
>>> derived.dt = 1/recstep
|
|
2329
|
+
>>> percmax(2.0)
|
|
2330
|
+
>>> alpha(1.0)
|
|
2331
|
+
>>> k(2.0)
|
|
2332
|
+
>>> factors.contriarea = 1.0
|
|
2333
|
+
>>> fluxes.inuz = 0.0
|
|
2334
|
+
>>> states.uz = 1.0
|
|
2335
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2336
|
+
>>> fluxes.perc
|
|
2337
|
+
perc(1.0)
|
|
2338
|
+
>>> fluxes.q0
|
|
2339
|
+
q0(0.0)
|
|
2340
|
+
>>> states.uz
|
|
2341
|
+
uz(0.0)
|
|
2342
|
+
>>> check()
|
|
2343
|
+
|
|
2344
|
+
Due to the sequential calculation of the upper zone routine, the upper zone
|
|
2345
|
+
storage drains completely through percolation, and no water remains for fast
|
|
2346
|
+
discharge response. By dividing the simulation step into 100 substeps, method
|
|
2347
|
+
|Calc_Q0_Perc_UZ_V1| also calculates a considerable amount of direct runoff:
|
|
2348
|
+
|
|
2349
|
+
>>> recstep(200)
|
|
2350
|
+
>>> derived.dt = 1.0/recstep
|
|
2351
|
+
>>> states.uz = 1.0
|
|
2352
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2353
|
+
>>> fluxes.perc
|
|
2354
|
+
perc(0.786934)
|
|
2355
|
+
>>> fluxes.q0
|
|
2356
|
+
q0(0.213066)
|
|
2357
|
+
>>> states.uz
|
|
2358
|
+
uz(0.0)
|
|
2359
|
+
>>> check()
|
|
2360
|
+
|
|
2361
|
+
Note that the assumed length of the simulation step is half a day. Hence the
|
|
2362
|
+
effective values of the maximum percolation rate and the storage coefficient
|
|
2363
|
+
are not 2 but 1:
|
|
2364
|
+
|
|
2365
|
+
>>> percmax
|
|
2366
|
+
percmax(2.0)
|
|
2367
|
+
>>> k
|
|
2368
|
+
k(2.0)
|
|
2369
|
+
>>> percmax.value
|
|
2370
|
+
1.0
|
|
2371
|
+
>>> k.value
|
|
2372
|
+
1.0
|
|
2373
|
+
|
|
2374
|
+
By decreasing the contributing area, one reduces percolation but increases the
|
|
2375
|
+
fast discharge response:
|
|
2376
|
+
|
|
2377
|
+
>>> factors.contriarea = 0.5
|
|
2378
|
+
>>> states.uz = 1.0
|
|
2379
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2380
|
+
>>> fluxes.perc
|
|
2381
|
+
perc(0.434108)
|
|
2382
|
+
>>> fluxes.q0
|
|
2383
|
+
q0(0.565892)
|
|
2384
|
+
>>> states.uz
|
|
2385
|
+
uz(0.0)
|
|
2386
|
+
>>> check()
|
|
2387
|
+
|
|
2388
|
+
Without any contributing area, the complete amount of water stored in the upper
|
|
2389
|
+
zone layer is released as direct discharge immediately:
|
|
2390
|
+
|
|
2391
|
+
>>> factors.contriarea = 0.0
|
|
2392
|
+
>>> states.uz = 1.0
|
|
2393
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2394
|
+
>>> fluxes.perc
|
|
2395
|
+
perc(0.0)
|
|
2396
|
+
>>> fluxes.q0
|
|
2397
|
+
q0(1.0)
|
|
2398
|
+
>>> states.uz
|
|
2399
|
+
uz(0.0)
|
|
2400
|
+
>>> check()
|
|
2401
|
+
|
|
2402
|
+
Resetting |RecStep| leads to more transparent results. Note that direct
|
|
2403
|
+
discharge drains the rest of the upper zone storage due to the storage
|
|
2404
|
+
coefficient's large value and the numerical approximation's low accuracy:
|
|
2405
|
+
|
|
2406
|
+
>>> recstep(2)
|
|
2407
|
+
>>> factors.contriarea = 0.5
|
|
2408
|
+
>>> derived.dt = 1.0/recstep
|
|
2409
|
+
>>> states.uz = 1.0
|
|
2410
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2411
|
+
>>> fluxes.perc
|
|
2412
|
+
perc(0.5)
|
|
2413
|
+
>>> fluxes.q0
|
|
2414
|
+
q0(0.5)
|
|
2415
|
+
>>> states.uz
|
|
2416
|
+
uz(0.0)
|
|
2417
|
+
>>> check()
|
|
2418
|
+
|
|
2419
|
+
Applying a more reasonable storage coefficient leads to the following results:
|
|
2420
|
+
|
|
2421
|
+
>>> k(0.5)
|
|
2422
|
+
>>> states.uz = 1.0
|
|
2423
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2424
|
+
>>> fluxes.perc
|
|
2425
|
+
perc(0.5)
|
|
2426
|
+
>>> fluxes.q0
|
|
2427
|
+
q0(0.25)
|
|
2428
|
+
>>> states.uz
|
|
2429
|
+
uz(0.25)
|
|
2430
|
+
>>> check()
|
|
2431
|
+
|
|
2432
|
+
Adding an input of 0.3 mm results in the same percolation value (which here is
|
|
2433
|
+
determined by the maximum percolation rate only) but increases the direct
|
|
2434
|
+
response (which always depends on the actual upper zone storage):
|
|
2435
|
+
|
|
2436
|
+
>>> fluxes.inuz = 0.3
|
|
2437
|
+
>>> states.uz = 1.0
|
|
2438
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2439
|
+
>>> fluxes.perc
|
|
2440
|
+
perc(0.5)
|
|
2441
|
+
>>> fluxes.q0
|
|
2442
|
+
q0(0.64)
|
|
2443
|
+
>>> states.uz
|
|
2444
|
+
uz(0.16)
|
|
2445
|
+
>>> check()
|
|
2446
|
+
|
|
2447
|
+
Due to the same reasons, another increase in numerical accuracy has no impact
|
|
2448
|
+
on percolation but decreases the direct response:
|
|
2449
|
+
|
|
2450
|
+
>>> recstep(200)
|
|
2451
|
+
>>> derived.dt = 1.0/recstep
|
|
2452
|
+
>>> states.uz = 1.0
|
|
2453
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2454
|
+
>>> fluxes.perc
|
|
2455
|
+
perc(0.5)
|
|
2456
|
+
>>> fluxes.q0
|
|
2457
|
+
q0(0.421708)
|
|
2458
|
+
>>> states.uz
|
|
2459
|
+
uz(0.378292)
|
|
2460
|
+
>>> check()
|
|
2461
|
+
|
|
2462
|
+
If phases of capillary rise, |InUZ| is negative and constant throughout the
|
|
2463
|
+
complete simulation interval. However, if |UZ| runs dry during the simulation
|
|
2464
|
+
interval, it can no contribute to the capillary rise. To always comply with
|
|
2465
|
+
the water balance equation, method |Calc_Q0_Perc_UZ_V1| reduces both |Perc|
|
|
2466
|
+
and |Q0| by the same factor in such situations. Reducing |InUZ| would be more
|
|
2467
|
+
reasonable but would also require modifying |CF| and |SM| (and others?), which
|
|
2468
|
+
is way too much effort given the minor impact of this manipulation on the
|
|
2469
|
+
general simulation results. The following two examples show how the
|
|
2470
|
+
manipulation works if the capillary rise requires all (first example) or half
|
|
2471
|
+
(second example) of the available water.
|
|
2472
|
+
|
|
2473
|
+
>>> fluxes.inuz = -1.0
|
|
2474
|
+
>>> states.uz = 1.0
|
|
2475
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2476
|
+
>>> fluxes.perc
|
|
2477
|
+
perc(0.0)
|
|
2478
|
+
>>> fluxes.q0
|
|
2479
|
+
q0(0.0)
|
|
2480
|
+
>>> states.uz
|
|
2481
|
+
uz(0.0)
|
|
2482
|
+
>>> check()
|
|
2483
|
+
|
|
2484
|
+
>>> fluxes.inuz = -0.5
|
|
2485
|
+
>>> states.uz = 1.0
|
|
2486
|
+
>>> model.calc_q0_perc_uz_v1()
|
|
2487
|
+
>>> fluxes.perc
|
|
2488
|
+
perc(0.323912)
|
|
2489
|
+
>>> fluxes.q0
|
|
2490
|
+
q0(0.176088)
|
|
2491
|
+
>>> states.uz
|
|
2492
|
+
uz(0.0)
|
|
2493
|
+
>>> check()
|
|
2494
|
+
"""
|
|
2495
|
+
|
|
2496
|
+
CONTROLPARAMETERS = (
|
|
2497
|
+
hland_control.RecStep,
|
|
2498
|
+
hland_control.PercMax,
|
|
2499
|
+
hland_control.K,
|
|
2500
|
+
hland_control.Alpha,
|
|
2501
|
+
)
|
|
2502
|
+
DERIVEDPARAMETERS = (hland_derived.DT,)
|
|
2503
|
+
REQUIREDSEQUENCES = (hland_factors.ContriArea, hland_fluxes.InUZ)
|
|
2504
|
+
UPDATEDSEQUENCES = (hland_states.UZ,)
|
|
2505
|
+
RESULTSEQUENCES = (hland_fluxes.Perc, hland_fluxes.Q0)
|
|
2506
|
+
|
|
2507
|
+
@staticmethod
|
|
2508
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2509
|
+
con = model.parameters.control.fastaccess
|
|
2510
|
+
der = model.parameters.derived.fastaccess
|
|
2511
|
+
fac = model.sequences.factors.fastaccess
|
|
2512
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2513
|
+
sta = model.sequences.states.fastaccess
|
|
2514
|
+
uz_old: float = sta.uz
|
|
2515
|
+
flu.perc = 0.0
|
|
2516
|
+
flu.q0 = 0.0
|
|
2517
|
+
for _ in range(con.recstep):
|
|
2518
|
+
sta.uz = max(sta.uz + der.dt * flu.inuz, 0.0)
|
|
2519
|
+
perc: float = min(der.dt * con.percmax * fac.contriarea, sta.uz)
|
|
2520
|
+
sta.uz -= perc
|
|
2521
|
+
flu.perc += perc
|
|
2522
|
+
if sta.uz > 0.0:
|
|
2523
|
+
if fac.contriarea > 0.0:
|
|
2524
|
+
q0: float = min(
|
|
2525
|
+
der.dt * con.k * (sta.uz / fac.contriarea) ** (1.0 + con.alpha),
|
|
2526
|
+
sta.uz,
|
|
2527
|
+
)
|
|
2528
|
+
else:
|
|
2529
|
+
q0 = sta.uz
|
|
2530
|
+
sta.uz -= q0
|
|
2531
|
+
flu.q0 += q0
|
|
2532
|
+
error: float = sta.uz - (uz_old + flu.inuz - flu.perc - flu.q0)
|
|
2533
|
+
if error > 0.0:
|
|
2534
|
+
factor: float = 1.0 - error / (flu.perc + flu.q0)
|
|
2535
|
+
flu.perc *= factor
|
|
2536
|
+
flu.q0 *= factor
|
|
2537
|
+
|
|
2538
|
+
|
|
2539
|
+
class Calc_DP_SUZ_V1(modeltools.Method):
|
|
2540
|
+
r"""Calculate the deep percolation and remove it from the upper storage reservoir.
|
|
2541
|
+
|
|
2542
|
+
Basic equation:
|
|
2543
|
+
:math:`DP = min(PERCMax, SUZ)`
|
|
2544
|
+
|
|
2545
|
+
:math:`\frac{SUZ}{dt} = -DP`
|
|
2546
|
+
|
|
2547
|
+
:math:`\frac{SUZ}{dt} = -RS -RI`
|
|
2548
|
+
|
|
2549
|
+
Example:
|
|
2550
|
+
|
|
2551
|
+
For internal lakes and sealed areas, method |Calc_DP_SUZ_V1| always sets the
|
|
2552
|
+
values of |DP| and |SUZ| to zero:
|
|
2553
|
+
|
|
2554
|
+
>>> from hydpy.models.hland import *
|
|
2555
|
+
>>> simulationstep("1h")
|
|
2556
|
+
>>> parameterstep("1d")
|
|
2557
|
+
>>> nmbzones(9)
|
|
2558
|
+
>>> zonetype(FIELD, FIELD, FIELD, FIELD, FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
2559
|
+
>>> percmax(4.8)
|
|
2560
|
+
>>> states.suz = 0.0, 0.1, 0.2, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4
|
|
2561
|
+
>>> model.calc_dp_suz_v1()
|
|
2562
|
+
>>> fluxes.dp
|
|
2563
|
+
dp(0.0, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0, 0.0)
|
|
2564
|
+
>>> states.suz
|
|
2565
|
+
suz(0.0, 0.0, 0.0, 0.1, 0.2, 0.2, 0.2, 0.0, 0.0)
|
|
2566
|
+
"""
|
|
2567
|
+
|
|
2568
|
+
CONTROLPARAMETERS = (
|
|
2569
|
+
hland_control.NmbZones,
|
|
2570
|
+
hland_control.ZoneType,
|
|
2571
|
+
hland_control.PercMax,
|
|
2572
|
+
)
|
|
2573
|
+
UPDATEDSEQUENCES = (hland_states.SUZ,)
|
|
2574
|
+
RESULTSEQUENCES = (hland_fluxes.DP,)
|
|
2575
|
+
|
|
2576
|
+
@staticmethod
|
|
2577
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2578
|
+
con = model.parameters.control.fastaccess
|
|
2579
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2580
|
+
sta = model.sequences.states.fastaccess
|
|
2581
|
+
for k in range(con.nmbzones):
|
|
2582
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
2583
|
+
flu.dp[k] = min(sta.suz[k], con.percmax)
|
|
2584
|
+
sta.suz[k] -= flu.dp[k]
|
|
2585
|
+
else:
|
|
2586
|
+
flu.dp[k] = 0.0
|
|
2587
|
+
sta.suz[k] = 0.0
|
|
2588
|
+
|
|
2589
|
+
|
|
2590
|
+
class Calc_QAb_QVs_BW_V1(modeltools.Method):
|
|
2591
|
+
"""Calculate the flow and the percolation from a two-outlet reservoir and update it.
|
|
2592
|
+
|
|
2593
|
+
Method |Calc_QAb_QVs_BW_V1| is an "additional method" used by the "run methods"
|
|
2594
|
+
|Calc_QAb1_QVs1_BW1_V1| and |Calc_QAb2_QVs2_BW2_V1| for calculating the flow and
|
|
2595
|
+
the percolation from the surface water reservoir and the interflow reservoir,
|
|
2596
|
+
respectively. See the documentation on method |Calc_QAb1_QVs1_BW1_V1| for further
|
|
2597
|
+
information.
|
|
2598
|
+
"""
|
|
2599
|
+
|
|
2600
|
+
# positional arguments required for consistency with the cythonized extension class:
|
|
2601
|
+
@staticmethod
|
|
2602
|
+
def __call__( # pylint: disable=too-many-positional-arguments
|
|
2603
|
+
model: modeltools.Model,
|
|
2604
|
+
k: int,
|
|
2605
|
+
h: VectorFloat,
|
|
2606
|
+
k1: VectorFloat,
|
|
2607
|
+
k2: VectorFloat,
|
|
2608
|
+
s0: VectorFloat,
|
|
2609
|
+
qz: VectorFloat,
|
|
2610
|
+
qa1: VectorFloat,
|
|
2611
|
+
qa2: VectorFloat,
|
|
2612
|
+
t0: float,
|
|
2613
|
+
/,
|
|
2614
|
+
) -> None:
|
|
2615
|
+
d_h = h[k]
|
|
2616
|
+
d_k1 = k1[k]
|
|
2617
|
+
d_k2 = k2[k]
|
|
2618
|
+
d_qz = qz[k]
|
|
2619
|
+
d_s0 = s0[k]
|
|
2620
|
+
if (d_k1 == 0.0) and (d_s0 > d_h):
|
|
2621
|
+
qa1[k] += d_s0 - d_h
|
|
2622
|
+
s0[k] = d_s0 = d_h
|
|
2623
|
+
if (d_k1 == 0.0) and (d_s0 == d_h) and (d_qz > d_h / d_k2):
|
|
2624
|
+
d_qa2 = d_h / d_k2
|
|
2625
|
+
d_dt = 1.0 - t0
|
|
2626
|
+
qa2[k] += d_dt * d_qa2
|
|
2627
|
+
qa1[k] += d_dt * (d_qz - d_qa2)
|
|
2628
|
+
elif d_k2 == 0.0:
|
|
2629
|
+
qa2[k] += d_s0 + d_qz
|
|
2630
|
+
s0[k] = 0.0
|
|
2631
|
+
elif (d_s0 < d_h) or (d_s0 == d_h and d_qz <= d_h / d_k2):
|
|
2632
|
+
if (d_s0 == d_h) or (d_qz <= d_h / d_k2):
|
|
2633
|
+
d_t1 = 1.0
|
|
2634
|
+
elif modelutils.isinf(d_k2):
|
|
2635
|
+
d_t1 = (d_h - d_s0) / d_qz
|
|
2636
|
+
else:
|
|
2637
|
+
d_t1 = t0 + d_k2 * modelutils.log(
|
|
2638
|
+
(d_qz - d_s0 / d_k2) / (d_qz - d_h / d_k2)
|
|
2639
|
+
)
|
|
2640
|
+
if 0.0 < d_t1 < 1.0:
|
|
2641
|
+
qa2[k] += (d_t1 - t0) * d_qz - (d_h - d_s0)
|
|
2642
|
+
s0[k] = d_h
|
|
2643
|
+
model.calc_qab_qvs_bw_v1(k, h, k1, k2, s0, qz, qa1, qa2, d_t1)
|
|
2644
|
+
elif modelutils.isinf(d_k2):
|
|
2645
|
+
s0[k] += (1.0 - t0) * d_qz
|
|
2646
|
+
else:
|
|
2647
|
+
d_dt = 1.0 - t0
|
|
2648
|
+
d_k2qz = d_k2 * d_qz
|
|
2649
|
+
s0[k] = d_k2qz - (d_k2qz - d_s0) * modelutils.exp(-d_dt / d_k2)
|
|
2650
|
+
qa2[k] += d_s0 - s0[k] + d_dt * d_qz
|
|
2651
|
+
else:
|
|
2652
|
+
d_v1 = 1.0 / d_k1 + 1.0 / d_k2
|
|
2653
|
+
d_v2 = d_qz + d_h / d_k1
|
|
2654
|
+
d_nom = d_v2 - d_h * d_v1
|
|
2655
|
+
d_denom = d_v2 - d_s0 * d_v1
|
|
2656
|
+
if (d_s0 == d_h) or (d_denom == 0.0) or (not 0 < d_nom / d_denom <= 1):
|
|
2657
|
+
d_t1 = 1.0
|
|
2658
|
+
else:
|
|
2659
|
+
d_t1 = t0 - 1.0 / d_v1 * modelutils.log(d_nom / d_denom)
|
|
2660
|
+
d_t1 = min(d_t1, 1.0)
|
|
2661
|
+
d_dt = d_t1 - t0
|
|
2662
|
+
d_v3 = (d_v2 * d_dt) / d_v1
|
|
2663
|
+
d_v4 = d_denom / d_v1**2 * (1.0 - modelutils.exp(-d_dt * d_v1))
|
|
2664
|
+
d_qa1 = (d_v3 - d_v4 - d_h * d_dt) / d_k1
|
|
2665
|
+
d_qa2 = (d_v3 - d_v4) / d_k2
|
|
2666
|
+
qa1[k] += d_qa1
|
|
2667
|
+
qa2[k] += d_qa2
|
|
2668
|
+
if d_t1 == 1.0:
|
|
2669
|
+
s0[k] += d_dt * d_qz - d_qa1 - d_qa2
|
|
2670
|
+
else:
|
|
2671
|
+
s0[k] = d_h
|
|
2672
|
+
if d_t1 < 1.0:
|
|
2673
|
+
model.calc_qab_qvs_bw_v1(k, h, k1, k2, s0, qz, qa1, qa2, d_t1)
|
|
2674
|
+
|
|
2675
|
+
|
|
2676
|
+
class Calc_QAb1_QVs1_BW1_V1(modeltools.Method):
|
|
2677
|
+
r"""Calculate the flow and the percolation from the surface flow reservoir and
|
|
2678
|
+
update it.
|
|
2679
|
+
|
|
2680
|
+
Basic equations:
|
|
2681
|
+
:math:`\frac{dBW1}{dt} = R - QAb1 - QVs1`
|
|
2682
|
+
|
|
2683
|
+
:math:`QAb1 = \frac{max(BW1 - H1, 0)}{TAb1}`
|
|
2684
|
+
|
|
2685
|
+
:math:`QVs1 = \frac{BW1}{TVs1}`
|
|
2686
|
+
|
|
2687
|
+
We follow the new COSERO implementation described in :cite:t:`ref-Kling2005` and
|
|
2688
|
+
:cite:t:`ref-Kling2006` and solve the given ordinary differential equation under the
|
|
2689
|
+
assumption of constant inflow (|R|). Despite the simple appearance of the short
|
|
2690
|
+
equation, its solution is quite complicated due to the threshold |H1| used
|
|
2691
|
+
(:cite:t:`ref-Kling2005` and :cite:t:`ref-Kling2006` explain the math in some
|
|
2692
|
+
detail).
|
|
2693
|
+
Additionally, we allow setting either |TAb1| or |TVs1| to |numpy.inf| or zero,
|
|
2694
|
+
allowing for disabling certain surface flow reservoir functionalities.
|
|
2695
|
+
Consequently, our source code includes many branches, and extensive testing is
|
|
2696
|
+
required to get some confidence in its robustness. We verified each of the
|
|
2697
|
+
following tests with numerical integration results. You can find this independent
|
|
2698
|
+
test code in `issue 68`_. Please tell us if you encounter a plausible combination
|
|
2699
|
+
of parameter values not adequately covered by our tests or source code.
|
|
2700
|
+
|
|
2701
|
+
Examples:
|
|
2702
|
+
|
|
2703
|
+
We prepare eight zones with identical values for the control parameters |H1|,
|
|
2704
|
+
|TAb1|, and |TVs1|. We only vary the inflow (|R|) and the initial state
|
|
2705
|
+
(|BW1|). For the first and the second zone, |BW1| changes but remains
|
|
2706
|
+
permanently below |H1|. Hence, all water leaving the storage leaves via
|
|
2707
|
+
percolation. For the third and the fourth zone, |BW1| also changes but is
|
|
2708
|
+
permanently above |H1|. Hence, there is a continuous generation of percolation
|
|
2709
|
+
and surface runoff. For the fifth and sixth zone, |BW1| starts below and ends
|
|
2710
|
+
above |H1| and the other way round. For the seventh and the eighth zone,
|
|
2711
|
+
inflow and outflow are balanced:
|
|
2712
|
+
|
|
2713
|
+
>>> from hydpy.models.hland import *
|
|
2714
|
+
>>> simulationstep("12h")
|
|
2715
|
+
>>> parameterstep("1d")
|
|
2716
|
+
>>> nmbzones(8)
|
|
2717
|
+
>>> zonetype(FIELD)
|
|
2718
|
+
>>> h1(4.0)
|
|
2719
|
+
>>> tab1(1.0)
|
|
2720
|
+
>>> tvs1(2.0)
|
|
2721
|
+
>>> fluxes.r = 0.0, 2.0, 0.0, 2.0, 5.0, 0.1, 0.5, 2.5
|
|
2722
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2723
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2724
|
+
>>> fluxes.qab1
|
|
2725
|
+
qab1(0.0, 0.0, 1.561119, 1.956437, 0.246114, 0.181758, 0.0, 1.0)
|
|
2726
|
+
>>> fluxes.qvs1
|
|
2727
|
+
qvs1(0.442398, 0.672805, 1.780559, 1.978219, 1.007586, 1.086805, 0.5,
|
|
2728
|
+
1.5)
|
|
2729
|
+
>>> states.bw1
|
|
2730
|
+
bw1(1.557602, 3.327195, 5.658322, 7.065344, 5.7463, 3.831437, 2.0, 6.0)
|
|
2731
|
+
|
|
2732
|
+
In the following examples, we keep the general configuration but set either
|
|
2733
|
+
|TAb1| or |TVs1| to |numpy.inf| or zero (you can replace |numpy.inf| with a
|
|
2734
|
+
high value and zero with a low value to confirm the correct "direction" of our
|
|
2735
|
+
handling of these special cases):
|
|
2736
|
+
|
|
2737
|
+
>>> infinity = inf
|
|
2738
|
+
>>> zero = 0.0
|
|
2739
|
+
|
|
2740
|
+
Setting |TAb1| to |numpy.inf| disables the surface runoff:
|
|
2741
|
+
|
|
2742
|
+
>>> tab1(infinity)
|
|
2743
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2744
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2745
|
+
>>> fluxes.qab1
|
|
2746
|
+
qab1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2747
|
+
>>> fluxes.qvs1
|
|
2748
|
+
qvs1(0.442398, 0.672805, 1.990793, 2.221199, 1.018414, 1.117516, 0.5,
|
|
2749
|
+
1.615203)
|
|
2750
|
+
>>> states.bw1
|
|
2751
|
+
bw1(1.557602, 3.327195, 7.009207, 8.778801, 5.981586, 3.982484, 2.0,
|
|
2752
|
+
6.884797)
|
|
2753
|
+
|
|
2754
|
+
Setting |TAb1| to zero enforces that all water exceeding |H1| becomes surface
|
|
2755
|
+
runoff immediately:
|
|
2756
|
+
|
|
2757
|
+
>>> tab1(zero)
|
|
2758
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2759
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2760
|
+
>>> fluxes.qab1
|
|
2761
|
+
qab1(0.0, 0.0, 5.0, 6.0, 2.115471, 1.0, 0.0, 3.5)
|
|
2762
|
+
>>> fluxes.qvs1
|
|
2763
|
+
qvs1(0.442398, 0.672805, 0.884797, 1.0, 0.884529, 0.896317, 0.5, 1.0)
|
|
2764
|
+
>>> states.bw1
|
|
2765
|
+
bw1(1.557602, 3.327195, 3.115203, 4.0, 4.0, 3.203683, 2.0, 4.0)
|
|
2766
|
+
|
|
2767
|
+
Setting |TVs1| to |numpy.inf| disables the percolation:
|
|
2768
|
+
|
|
2769
|
+
>>> tab1(1.0)
|
|
2770
|
+
>>> tvs1(infinity)
|
|
2771
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2772
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2773
|
+
>>> fluxes.qab1
|
|
2774
|
+
qab1(0.0, 0.0, 1.967347, 2.393469, 0.408182, 0.414775, 0.0, 1.319592)
|
|
2775
|
+
>>> fluxes.qvs1
|
|
2776
|
+
qvs1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2777
|
+
>>> states.bw1
|
|
2778
|
+
bw1(2.0, 4.0, 7.032653, 8.606531, 6.591818, 4.685225, 2.5, 7.180408)
|
|
2779
|
+
|
|
2780
|
+
Setting |TAb1| to zero ensures that all availalbe water becomes percolation
|
|
2781
|
+
immediately:
|
|
2782
|
+
|
|
2783
|
+
>>> tvs1(zero)
|
|
2784
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2785
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2786
|
+
>>> fluxes.qab1
|
|
2787
|
+
qab1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2788
|
+
>>> fluxes.qvs1
|
|
2789
|
+
qvs1(2.0, 4.0, 9.0, 11.0, 7.0, 5.1, 2.5, 8.5)
|
|
2790
|
+
>>> states.bw1
|
|
2791
|
+
bw1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2792
|
+
|
|
2793
|
+
The following examples repeat the ones above for the edge case where the
|
|
2794
|
+
threshold value |H1| is zero:
|
|
2795
|
+
|
|
2796
|
+
>>> h1(0.0)
|
|
2797
|
+
>>> tvs1(2.0)
|
|
2798
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2799
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2800
|
+
>>> fluxes.qab1
|
|
2801
|
+
qab1(0.703511, 1.09883, 3.165801, 3.561119, 1.691807, 1.778544,
|
|
2802
|
+
0.802341, 2.604682)
|
|
2803
|
+
>>> fluxes.qvs1
|
|
2804
|
+
qvs1(0.351756, 0.549415, 1.5829, 1.780559, 0.845904, 0.889272, 0.40117,
|
|
2805
|
+
1.302341)
|
|
2806
|
+
>>> states.bw1
|
|
2807
|
+
bw1(0.944733, 2.351756, 4.251299, 5.658322, 4.462289, 2.432184,
|
|
2808
|
+
1.296489, 4.592977)
|
|
2809
|
+
|
|
2810
|
+
>>> tab1(infinity)
|
|
2811
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2812
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2813
|
+
>>> fluxes.qab1
|
|
2814
|
+
qab1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2815
|
+
>>> fluxes.qvs1
|
|
2816
|
+
qvs1(0.442398, 0.672805, 1.990793, 2.221199, 1.018414, 1.117516, 0.5,
|
|
2817
|
+
1.615203)
|
|
2818
|
+
>>> states.bw1
|
|
2819
|
+
bw1(1.557602, 3.327195, 7.009207, 8.778801, 5.981586, 3.982484, 2.0,
|
|
2820
|
+
6.884797)
|
|
2821
|
+
|
|
2822
|
+
>>> tab1(zero)
|
|
2823
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2824
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2825
|
+
>>> fluxes.qab1
|
|
2826
|
+
qab1(2.0, 4.0, 9.0, 11.0, 7.0, 5.1, 2.5, 8.5)
|
|
2827
|
+
>>> fluxes.qvs1
|
|
2828
|
+
qvs1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2829
|
+
>>> states.bw1
|
|
2830
|
+
bw1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2831
|
+
|
|
2832
|
+
>>> tab1(1.0)
|
|
2833
|
+
>>> tvs1(infinity)
|
|
2834
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2835
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2836
|
+
>>> fluxes.qab1
|
|
2837
|
+
qab1(0.786939, 1.213061, 3.541224, 3.967347, 1.852245, 1.988653,
|
|
2838
|
+
0.893469, 2.893469)
|
|
2839
|
+
>>> fluxes.qvs1
|
|
2840
|
+
qvs1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2841
|
+
>>> states.bw1
|
|
2842
|
+
bw1(1.213061, 2.786939, 5.458776, 7.032653, 5.147755, 3.111347,
|
|
2843
|
+
1.606531, 5.606531)
|
|
2844
|
+
|
|
2845
|
+
>>> tvs1(zero)
|
|
2846
|
+
>>> states.bw1 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2847
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2848
|
+
>>> fluxes.qab1
|
|
2849
|
+
qab1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2850
|
+
>>> fluxes.qvs1
|
|
2851
|
+
qvs1(2.0, 4.0, 9.0, 11.0, 7.0, 5.1, 2.5, 8.5)
|
|
2852
|
+
>>> states.bw1
|
|
2853
|
+
bw1(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
2854
|
+
|
|
2855
|
+
|Calc_QAb1_QVs1_BW1_V1| processes forest and glacier zones like field zones but
|
|
2856
|
+
sets the values of |QAb1|, |QVs1|, and |BW1| to zero for internal lakes and
|
|
2857
|
+
sealed areas:
|
|
2858
|
+
|
|
2859
|
+
>>> zonetype(FOREST, GLACIER, ILAKE, SEALED, FOREST, GLACIER, ILAKE, SEALED)
|
|
2860
|
+
>>> h1(4.0)
|
|
2861
|
+
>>> tab1(1.0)
|
|
2862
|
+
>>> tvs1(2.0)
|
|
2863
|
+
>>> fluxes.r = 2.0, 2.0, 2.0, 2.0, 2.5, 2.5, 2.5, 2.5
|
|
2864
|
+
>>> states.bw1 = 2.0, 2.0, 2.0, 2.0, 6.0, 6.0, 6.0, 6.0
|
|
2865
|
+
>>> model.calc_qab1_qvs1_bw1_v1()
|
|
2866
|
+
>>> fluxes.qab1
|
|
2867
|
+
qab1(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0)
|
|
2868
|
+
>>> fluxes.qvs1
|
|
2869
|
+
qvs1(0.672805, 0.672805, 0.0, 0.0, 1.5, 1.5, 0.0, 0.0)
|
|
2870
|
+
>>> states.bw1
|
|
2871
|
+
bw1(3.327195, 3.327195, 0.0, 0.0, 6.0, 6.0, 0.0, 0.0)
|
|
2872
|
+
"""
|
|
2873
|
+
|
|
2874
|
+
CONTROLPARAMETERS = (
|
|
2875
|
+
hland_control.NmbZones,
|
|
2876
|
+
hland_control.ZoneType,
|
|
2877
|
+
hland_control.H1,
|
|
2878
|
+
hland_control.TAb1,
|
|
2879
|
+
hland_control.TVs1,
|
|
2880
|
+
)
|
|
2881
|
+
REQUIREDSEQUENCES = (hland_fluxes.R,)
|
|
2882
|
+
UPDATEDSEQUENCES = (hland_states.BW1,)
|
|
2883
|
+
RESULTSEQUENCES = (hland_fluxes.QAb1, hland_fluxes.QVs1)
|
|
2884
|
+
SUBMETHODS = (Calc_QAb_QVs_BW_V1,)
|
|
2885
|
+
|
|
2886
|
+
@staticmethod
|
|
2887
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2888
|
+
con = model.parameters.control.fastaccess
|
|
2889
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2890
|
+
sta = model.sequences.states.fastaccess
|
|
2891
|
+
for k in range(con.nmbzones):
|
|
2892
|
+
flu.qab1[k] = 0.0
|
|
2893
|
+
flu.qvs1[k] = 0.0
|
|
2894
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
2895
|
+
model.calc_qab_qvs_bw_v1(
|
|
2896
|
+
k,
|
|
2897
|
+
con.h1,
|
|
2898
|
+
con.tab1,
|
|
2899
|
+
con.tvs1,
|
|
2900
|
+
sta.bw1,
|
|
2901
|
+
flu.r,
|
|
2902
|
+
flu.qab1,
|
|
2903
|
+
flu.qvs1,
|
|
2904
|
+
0.0,
|
|
2905
|
+
)
|
|
2906
|
+
else:
|
|
2907
|
+
sta.bw1[k] = 0.0
|
|
2908
|
+
|
|
2909
|
+
|
|
2910
|
+
class Calc_QAb2_QVs2_BW2_V1(modeltools.Method):
|
|
2911
|
+
r"""Calculate the flow and the percolation from the interflow reservoir and update
|
|
2912
|
+
it.
|
|
2913
|
+
|
|
2914
|
+
Basic equations:
|
|
2915
|
+
:math:`\frac{dBW2}{dt} = QVs1 - QAb2 - QVs2`
|
|
2916
|
+
|
|
2917
|
+
:math:`QAb2 = \frac{max(BW2 - H2, 0)}{TAb2}`
|
|
2918
|
+
|
|
2919
|
+
:math:`QVs2 = \frac{BW2}{TVs2}`
|
|
2920
|
+
|
|
2921
|
+
Method |Calc_QAb2_QVs2_BW2_V1| is functionally identical with method
|
|
2922
|
+
|Calc_QAb1_QVs1_BW1_V1| and also relies on the "additional method"
|
|
2923
|
+
|Calc_QAb_QVs_BW_V1|. Please see the documentation on method
|
|
2924
|
+
|Calc_QAb1_QVs1_BW1_V1|, which provides more information and exhaustive example
|
|
2925
|
+
calculations.
|
|
2926
|
+
|
|
2927
|
+
Example:
|
|
2928
|
+
|
|
2929
|
+
We only repeat the first and the last example of the documentation on method
|
|
2930
|
+
|Calc_QAb1_QVs1_BW1_V1| to verify that method |Calc_QAb2_QVs2_BW2_V1| calls
|
|
2931
|
+
method |Calc_QAb_QVs_BW_V1| correctly:
|
|
2932
|
+
|
|
2933
|
+
>>> from hydpy.models.hland import *
|
|
2934
|
+
>>> simulationstep("12h")
|
|
2935
|
+
>>> parameterstep("1d")
|
|
2936
|
+
>>> nmbzones(8)
|
|
2937
|
+
>>> zonetype(FIELD)
|
|
2938
|
+
>>> h2(4.0)
|
|
2939
|
+
>>> tab2(1.0)
|
|
2940
|
+
>>> tvs2(2.0)
|
|
2941
|
+
>>> fluxes.qvs1 = 0.0, 2.0, 0.0, 2.0, 5.0, 0.1, 0.5, 2.5
|
|
2942
|
+
>>> states.bw2 = 2.0, 2.0, 9.0, 9.0, 2.0, 5.0, 2.0, 6.0
|
|
2943
|
+
>>> model.calc_qab2_qvs2_bw2_v1()
|
|
2944
|
+
>>> fluxes.qab2
|
|
2945
|
+
qab2(0.0, 0.0, 1.561119, 1.956437, 0.246114, 0.181758, 0.0, 1.0)
|
|
2946
|
+
>>> fluxes.qvs2
|
|
2947
|
+
qvs2(0.442398, 0.672805, 1.780559, 1.978219, 1.007586, 1.086805, 0.5,
|
|
2948
|
+
1.5)
|
|
2949
|
+
>>> states.bw2
|
|
2950
|
+
bw2(1.557602, 3.327195, 5.658322, 7.065344, 5.7463, 3.831437, 2.0, 6.0)
|
|
2951
|
+
|
|
2952
|
+
|Calc_QAb2_QVs2_BW2_V1| processes forest and glacier zones like field zones but
|
|
2953
|
+
sets the values of |QAb2|, |QVs2|, and |BW2| to zero for internal lakes and
|
|
2954
|
+
sealed areas:
|
|
2955
|
+
|
|
2956
|
+
>>> zonetype(FOREST, GLACIER, ILAKE, SEALED, FOREST, GLACIER, ILAKE, SEALED)
|
|
2957
|
+
>>> fluxes.qvs1 = 2.0, 2.0, 2.0, 2.0, 2.5, 2.5, 2.5, 2.5
|
|
2958
|
+
>>> states.bw2 = 2.0, 2.0, 2.0, 2.0, 6.0, 6.0, 6.0, 6.0
|
|
2959
|
+
>>> model.calc_qab2_qvs2_bw2_v1()
|
|
2960
|
+
>>> fluxes.qab2
|
|
2961
|
+
qab2(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0)
|
|
2962
|
+
>>> fluxes.qvs2
|
|
2963
|
+
qvs2(0.672805, 0.672805, 0.0, 0.0, 1.5, 1.5, 0.0, 0.0)
|
|
2964
|
+
>>> states.bw2
|
|
2965
|
+
bw2(3.327195, 3.327195, 0.0, 0.0, 6.0, 6.0, 0.0, 0.0)
|
|
2966
|
+
"""
|
|
2967
|
+
|
|
2968
|
+
CONTROLPARAMETERS = (
|
|
2969
|
+
hland_control.NmbZones,
|
|
2970
|
+
hland_control.ZoneType,
|
|
2971
|
+
hland_control.H2,
|
|
2972
|
+
hland_control.TAb2,
|
|
2973
|
+
hland_control.TVs2,
|
|
2974
|
+
)
|
|
2975
|
+
REQUIREDSEQUENCES = (hland_fluxes.QVs1,)
|
|
2976
|
+
UPDATEDSEQUENCES = (hland_states.BW2,)
|
|
2977
|
+
RESULTSEQUENCES = (hland_fluxes.QAb2, hland_fluxes.QVs2)
|
|
2978
|
+
SUBMETHODS = (Calc_QAb_QVs_BW_V1,)
|
|
2979
|
+
|
|
2980
|
+
@staticmethod
|
|
2981
|
+
def __call__(model: modeltools.Model) -> None:
|
|
2982
|
+
con = model.parameters.control.fastaccess
|
|
2983
|
+
flu = model.sequences.fluxes.fastaccess
|
|
2984
|
+
sta = model.sequences.states.fastaccess
|
|
2985
|
+
for k in range(con.nmbzones):
|
|
2986
|
+
flu.qab2[k] = 0.0
|
|
2987
|
+
flu.qvs2[k] = 0.0
|
|
2988
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
2989
|
+
model.calc_qab_qvs_bw_v1(
|
|
2990
|
+
k,
|
|
2991
|
+
con.h2,
|
|
2992
|
+
con.tab2,
|
|
2993
|
+
con.tvs2,
|
|
2994
|
+
sta.bw2,
|
|
2995
|
+
flu.qvs1,
|
|
2996
|
+
flu.qab2,
|
|
2997
|
+
flu.qvs2,
|
|
2998
|
+
0.0,
|
|
2999
|
+
)
|
|
3000
|
+
else:
|
|
3001
|
+
sta.bw2[k] = 0.0
|
|
3002
|
+
|
|
3003
|
+
|
|
3004
|
+
class Calc_RS_RI_SUZ_V1(modeltools.Method):
|
|
3005
|
+
r"""Calculate the surface runoff and the interflow and remove them from the upper
|
|
3006
|
+
storage reservoir.
|
|
3007
|
+
|
|
3008
|
+
Basic equation:
|
|
3009
|
+
:math:`RS = (SUZ - SGR) \cdot (1 - W0)`
|
|
3010
|
+
|
|
3011
|
+
:math:`RI = SUZ \cdot (1 - W1)`
|
|
3012
|
+
|
|
3013
|
+
:math:`\frac{SUZ}{dt} = -(RS + RI)`
|
|
3014
|
+
|
|
3015
|
+
Examples:
|
|
3016
|
+
|
|
3017
|
+
For internal lakes and sealed areas, method |Calc_RS_RI_SUZ_V1| always sets the
|
|
3018
|
+
values of |RS|, |RI|, and |SUZ| to zero:
|
|
3019
|
+
|
|
3020
|
+
>>> from hydpy.models.hland import *
|
|
3021
|
+
>>> simulationstep("12h")
|
|
3022
|
+
>>> parameterstep()
|
|
3023
|
+
>>> nmbzones(9)
|
|
3024
|
+
>>> zonetype(FIELD, FIELD, FIELD, FIELD, FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3025
|
+
>>> sgr(10.0)
|
|
3026
|
+
>>> derived.w0 = 0.4
|
|
3027
|
+
>>> derived.w1 = 0.8
|
|
3028
|
+
>>> states.suz = 0.0, 5.0, 10.0, 15.0, 20.0, 20.0, 20.0, 20.0, 20.0
|
|
3029
|
+
>>> model.calc_rs_ri_suz_v1()
|
|
3030
|
+
>>> fluxes.rs
|
|
3031
|
+
rs(0.0, 0.0, 0.0, 3.0, 6.0, 6.0, 6.0, 0.0, 0.0)
|
|
3032
|
+
>>> fluxes.ri
|
|
3033
|
+
ri(0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 4.0, 0.0, 0.0)
|
|
3034
|
+
>>> states.suz
|
|
3035
|
+
suz(0.0, 4.0, 8.0, 9.0, 10.0, 10.0, 10.0, 0.0, 0.0)
|
|
3036
|
+
|
|
3037
|
+
Theoretically, the parallel calculation of |RS| and |RI| can result in negative
|
|
3038
|
+
values of |SUZ|. The checks implemented for the parameter classes |K0| and
|
|
3039
|
+
|K1| should prevent this problem. However, to be definitely on the safe side,
|
|
3040
|
+
method |Calc_RS_RI_SUZ_V1| also checks if the final state of |SUZ| is negative
|
|
3041
|
+
and, when necessary, resets it to zero and reduces |RS| and |RI| accordingly
|
|
3042
|
+
(with the same fraction):
|
|
3043
|
+
|
|
3044
|
+
>>> derived.w0 = 0.1
|
|
3045
|
+
>>> derived.w1 = 0.2
|
|
3046
|
+
>>> states.suz = 0.0, 5.0, 10.0, 15.0, 20.0, 20.0, 20.0, 20.0, 20.0
|
|
3047
|
+
>>> model.calc_rs_ri_suz_v1()
|
|
3048
|
+
>>> fluxes.rs
|
|
3049
|
+
rs(0.0, 0.0, 0.0, 4.909091, 10.8, 10.8, 10.8, 0.0, 0.0)
|
|
3050
|
+
>>> fluxes.ri
|
|
3051
|
+
ri(0.0, 4.0, 8.0, 13.090909, 19.2, 19.2, 19.2, 0.0, 0.0)
|
|
3052
|
+
>>> states.suz
|
|
3053
|
+
suz(0.0, 1.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
|
3054
|
+
"""
|
|
3055
|
+
|
|
3056
|
+
CONTROLPARAMETERS = (
|
|
3057
|
+
hland_control.NmbZones,
|
|
3058
|
+
hland_control.ZoneType,
|
|
3059
|
+
hland_control.SGR,
|
|
3060
|
+
)
|
|
3061
|
+
DERIVEDPARAMETERS = (hland_derived.W0, hland_derived.W1)
|
|
3062
|
+
UPDATEDSEQUENCES = (hland_states.SUZ,)
|
|
3063
|
+
RESULTSEQUENCES = (hland_fluxes.RS, hland_fluxes.RI)
|
|
3064
|
+
|
|
3065
|
+
@staticmethod
|
|
3066
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3067
|
+
con = model.parameters.control.fastaccess
|
|
3068
|
+
der = model.parameters.derived.fastaccess
|
|
3069
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3070
|
+
sta = model.sequences.states.fastaccess
|
|
3071
|
+
for k in range(con.nmbzones):
|
|
3072
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
3073
|
+
if sta.suz[k] > con.sgr[k]:
|
|
3074
|
+
flu.rs[k] = (sta.suz[k] - con.sgr[k]) * (1.0 - der.w0[k])
|
|
3075
|
+
else:
|
|
3076
|
+
flu.rs[k] = 0.0
|
|
3077
|
+
flu.ri[k] = sta.suz[k] * (1.0 - der.w1[k])
|
|
3078
|
+
sta.suz[k] -= flu.rs[k] + flu.ri[k]
|
|
3079
|
+
if sta.suz[k] < 0.0:
|
|
3080
|
+
d_f = 1.0 - sta.suz[k] / (flu.rs[k] + flu.ri[k])
|
|
3081
|
+
flu.rs[k] *= d_f
|
|
3082
|
+
flu.ri[k] *= d_f
|
|
3083
|
+
sta.suz[k] = 0.0
|
|
3084
|
+
else:
|
|
3085
|
+
sta.suz[k] = 0.0
|
|
3086
|
+
flu.rs[k] = 0.0
|
|
3087
|
+
flu.ri[k] = 0.0
|
|
3088
|
+
|
|
3089
|
+
|
|
3090
|
+
class Calc_LZ_V1(modeltools.Method):
|
|
3091
|
+
r"""Add percolation from the upper zone layera and lake precipitation to the lower
|
|
3092
|
+
zone storage.
|
|
3093
|
+
|
|
3094
|
+
Basic equation:
|
|
3095
|
+
.. math::
|
|
3096
|
+
\frac{dLZ}{dt} = \frac{RelUpperZoneArea}{RelLowerZoneArea} \cdot Perc +
|
|
3097
|
+
\sum_{k=1}^{NmbZones} \frac{RelZoneAreas_k}{RelLowerZoneArea} \cdot
|
|
3098
|
+
\begin{cases}
|
|
3099
|
+
Pc_k &|\ ZoneType_k = ILAKE
|
|
3100
|
+
\\
|
|
3101
|
+
0 &|\ ZoneType_k \neq ILAKE
|
|
3102
|
+
\end{cases}
|
|
3103
|
+
|
|
3104
|
+
Examples:
|
|
3105
|
+
|
|
3106
|
+
We define a subbasin with five zones of different land-use types and sizes:
|
|
3107
|
+
|
|
3108
|
+
>>> from hydpy.models.hland import *
|
|
3109
|
+
>>> simulationstep("12h")
|
|
3110
|
+
>>> parameterstep("1d")
|
|
3111
|
+
>>> nmbzones(5)
|
|
3112
|
+
>>> zonetype(FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3113
|
+
>>> area(100.0)
|
|
3114
|
+
>>> zonearea(10.0, 20.0, 30.0, 15.0, 25.0)
|
|
3115
|
+
>>> psi(1.0)
|
|
3116
|
+
|
|
3117
|
+
To ensure the consistency of the values of the relevant derived parameters, we
|
|
3118
|
+
apply their |Parameter.update| methods:
|
|
3119
|
+
|
|
3120
|
+
>>> derived.relzoneareas.update()
|
|
3121
|
+
>>> derived.relupperzonearea.update()
|
|
3122
|
+
>>> derived.rellowerzonearea.update()
|
|
3123
|
+
|
|
3124
|
+
First, we set the precipitation intensity (|PC|) to 30 mm and the percolation
|
|
3125
|
+
intensity (|PERC|) to zero. Only the internal lake zone passes its value for
|
|
3126
|
+
|PC| directly to the lower zone layer. The fraction between its size (15 km²)
|
|
3127
|
+
and the extent of the lower zone layer (75 km²) is 1/5. Hence, the single
|
|
3128
|
+
zone's input of 30 mm increases the lower zone layer's water content by 6 mm:
|
|
3129
|
+
|
|
3130
|
+
>>> fluxes.pc = 30.0
|
|
3131
|
+
>>> fluxes.perc = 0.0
|
|
3132
|
+
>>> states.lz = 10.0
|
|
3133
|
+
>>> model.calc_lz_v1()
|
|
3134
|
+
>>> states.lz
|
|
3135
|
+
lz(16.0)
|
|
3136
|
+
|
|
3137
|
+
Second, we set |PC| to zero and the percolation intensity to 5 mm. The
|
|
3138
|
+
fraction between the extents of the upper zone layer (60 km²) and the lower
|
|
3139
|
+
zone layer (75 km³) is 4/5. Hence, percolation released by the upper zone layer
|
|
3140
|
+
increases the content of the lower zone layer by 4 mm:
|
|
3141
|
+
|
|
3142
|
+
>>> fluxes.pc = 0.0
|
|
3143
|
+
>>> fluxes.perc = 5.0
|
|
3144
|
+
>>> model.calc_lz_v1()
|
|
3145
|
+
>>> states.lz
|
|
3146
|
+
lz(20.0)
|
|
3147
|
+
|
|
3148
|
+
In case the extent of the lower zone area is zero (which is possible for
|
|
3149
|
+
completely sealed subbasins only) method |Calc_LZ_V1| sets |LZ| to zero:
|
|
3150
|
+
|
|
3151
|
+
>>> derived.rellowerzonearea(0.0)
|
|
3152
|
+
>>> model.calc_lz_v1()
|
|
3153
|
+
>>> states.lz
|
|
3154
|
+
lz(0.0)
|
|
3155
|
+
"""
|
|
3156
|
+
|
|
3157
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3158
|
+
DERIVEDPARAMETERS = (
|
|
3159
|
+
hland_derived.RelUpperZoneArea,
|
|
3160
|
+
hland_derived.RelLowerZoneArea,
|
|
3161
|
+
hland_derived.RelZoneAreas,
|
|
3162
|
+
)
|
|
3163
|
+
REQUIREDSEQUENCES = (hland_fluxes.Perc, hland_fluxes.PC)
|
|
3164
|
+
UPDATEDSEQUENCES = (hland_states.LZ,)
|
|
3165
|
+
|
|
3166
|
+
@staticmethod
|
|
3167
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3168
|
+
con = model.parameters.control.fastaccess
|
|
3169
|
+
der = model.parameters.derived.fastaccess
|
|
3170
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3171
|
+
sta = model.sequences.states.fastaccess
|
|
3172
|
+
if der.rellowerzonearea > 0.0:
|
|
3173
|
+
sta.lz += der.relupperzonearea / der.rellowerzonearea * flu.perc
|
|
3174
|
+
for k in range(con.nmbzones):
|
|
3175
|
+
if con.zonetype[k] == ILAKE:
|
|
3176
|
+
sta.lz += der.relzoneareas[k] / der.rellowerzonearea * flu.pc[k]
|
|
3177
|
+
else:
|
|
3178
|
+
sta.lz = 0.0
|
|
3179
|
+
|
|
3180
|
+
|
|
3181
|
+
class Calc_LZ_V2(modeltools.Method):
|
|
3182
|
+
r"""Add percolation from the interflow reservoir and lake precipitation to the
|
|
3183
|
+
lower zone storage.
|
|
3184
|
+
|
|
3185
|
+
Basic equation:
|
|
3186
|
+
.. math::
|
|
3187
|
+
\frac{dLZ}{dt} =
|
|
3188
|
+
\sum_{k=1}^{NmbZones} \frac{RelZoneAreas_k}{RelLowerZoneArea} \cdot
|
|
3189
|
+
\begin{cases}
|
|
3190
|
+
QVs2_k &|\ ZoneType_k \in \{ FIELD, FOREST, GLACIER \}
|
|
3191
|
+
\\
|
|
3192
|
+
Pc_k &|\ ZoneType_k = ILAKE
|
|
3193
|
+
\\
|
|
3194
|
+
0 &|\ ZoneType_k = SEALED
|
|
3195
|
+
\end{cases}
|
|
3196
|
+
|
|
3197
|
+
Example:
|
|
3198
|
+
|
|
3199
|
+
The first three zones of type |FIELD|, |FOREST|, and |GLACIER| contribute via
|
|
3200
|
+
deep percolation to the lower zone reservoir. For the fourth zone of type
|
|
3201
|
+
|ILAKE|, precipitation contributes directly to the lower zone storage. The
|
|
3202
|
+
fifth zone of type |SEALED| does not contribute to the lower zone storage at
|
|
3203
|
+
all:
|
|
3204
|
+
|
|
3205
|
+
>>> from hydpy.models.hland import *
|
|
3206
|
+
>>> simulationstep("12h")
|
|
3207
|
+
>>> parameterstep("1d")
|
|
3208
|
+
>>> nmbzones(5)
|
|
3209
|
+
>>> zonetype(FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3210
|
+
>>> derived.relzoneareas = 0.24, 0.18, 0.12, 0.06, 0.4
|
|
3211
|
+
>>> derived.rellowerzonearea = 0.6
|
|
3212
|
+
>>> fluxes.qvs2 = 1.0, 2.0, 3.0, nan, nan
|
|
3213
|
+
>>> fluxes.pc = nan, nan, nan, 14.0, nan
|
|
3214
|
+
>>> states.lz = 5.0
|
|
3215
|
+
>>> model.calc_lz_v2()
|
|
3216
|
+
>>> states.lz
|
|
3217
|
+
lz(8.0)
|
|
3218
|
+
"""
|
|
3219
|
+
|
|
3220
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3221
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLowerZoneArea)
|
|
3222
|
+
REQUIREDSEQUENCES = (hland_fluxes.QVs2, hland_fluxes.PC)
|
|
3223
|
+
UPDATEDSEQUENCES = (hland_states.LZ,)
|
|
3224
|
+
|
|
3225
|
+
@staticmethod
|
|
3226
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3227
|
+
con = model.parameters.control.fastaccess
|
|
3228
|
+
der = model.parameters.derived.fastaccess
|
|
3229
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3230
|
+
sta = model.sequences.states.fastaccess
|
|
3231
|
+
for k in range(con.nmbzones):
|
|
3232
|
+
if con.zonetype[k] == ILAKE:
|
|
3233
|
+
sta.lz += der.relzoneareas[k] / der.rellowerzonearea * flu.pc[k]
|
|
3234
|
+
elif con.zonetype[k] != SEALED:
|
|
3235
|
+
sta.lz += der.relzoneareas[k] / der.rellowerzonearea * flu.qvs2[k]
|
|
3236
|
+
|
|
3237
|
+
|
|
3238
|
+
class Calc_GR1_V1(modeltools.Method):
|
|
3239
|
+
r"""Calculate the recharge to the fast response groundwater reservoir.
|
|
3240
|
+
|
|
3241
|
+
Basic equation:
|
|
3242
|
+
:math:`GR1 = min \left(DP, \frac{SG1Max - SG1}{K2} \right)`
|
|
3243
|
+
|
|
3244
|
+
Examples:
|
|
3245
|
+
|
|
3246
|
+
For internal lakes and sealed areas, method |Calc_GR1_V1| always sets the values
|
|
3247
|
+
of |GR1| and |SG1| to zero:
|
|
3248
|
+
|
|
3249
|
+
>>> from hydpy.models.hland import *
|
|
3250
|
+
>>> simulationstep("1h")
|
|
3251
|
+
>>> parameterstep("1d")
|
|
3252
|
+
>>> nmbzones(9)
|
|
3253
|
+
>>> zonetype(FIELD, FIELD, FIELD, FIELD, FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3254
|
+
>>> sg1max(10.0)
|
|
3255
|
+
>>> k2(10.0/24.0)
|
|
3256
|
+
>>> from hydpy import round_
|
|
3257
|
+
>>> round_(k2.values[0])
|
|
3258
|
+
10.0
|
|
3259
|
+
>>> fluxes.dp = 0.5
|
|
3260
|
+
>>> states.sg1 = 0.0, 5.0, 9.0, 9.9, 10.0, 5.0, 5.0, 5.0, 5.0
|
|
3261
|
+
>>> model.calc_gr1_v1()
|
|
3262
|
+
>>> fluxes.gr1
|
|
3263
|
+
gr1(0.5, 0.5, 0.1, 0.01, 0.0, 0.5, 0.5, 0.0, 0.0)
|
|
3264
|
+
|
|
3265
|
+
For unreasonably low values of parameter |K2|, the sum of |SG1| and |GR1| could
|
|
3266
|
+
theoretically become larger than |SG1Max|. We let method |Calc_GR1_V1| reduce
|
|
3267
|
+
|GR1| when necessary to ensure this does not happen:
|
|
3268
|
+
|
|
3269
|
+
>>> k2.values = 0.5
|
|
3270
|
+
>>> states.sg1 = 0.0, 5.0, 9.0, 9.9, 10.0, 5.0, 5.0, 5.0, 5.0
|
|
3271
|
+
>>> model.calc_gr1_v1()
|
|
3272
|
+
>>> fluxes.gr1
|
|
3273
|
+
gr1(0.5, 0.5, 0.5, 0.1, 0.0, 0.5, 0.5, 0.0, 0.0)
|
|
3274
|
+
"""
|
|
3275
|
+
|
|
3276
|
+
CONTROLPARAMETERS = (
|
|
3277
|
+
hland_control.NmbZones,
|
|
3278
|
+
hland_control.ZoneType,
|
|
3279
|
+
hland_control.SG1Max,
|
|
3280
|
+
hland_control.K2,
|
|
3281
|
+
)
|
|
3282
|
+
REQUIREDSEQUENCES = (hland_fluxes.DP,)
|
|
3283
|
+
UPDATEDSEQUENCES = (hland_states.SG1,)
|
|
3284
|
+
RESULTSEQUENCES = (hland_fluxes.GR1,)
|
|
3285
|
+
|
|
3286
|
+
@staticmethod
|
|
3287
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3288
|
+
con = model.parameters.control.fastaccess
|
|
3289
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3290
|
+
sta = model.sequences.states.fastaccess
|
|
3291
|
+
for k in range(con.nmbzones):
|
|
3292
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
3293
|
+
flu.gr1[k] = min(flu.dp[k], (con.sg1max[k] - sta.sg1[k]) / con.k2[k])
|
|
3294
|
+
flu.gr1[k] -= max(sta.sg1[k] + flu.gr1[k] - con.sg1max[k], 0.0)
|
|
3295
|
+
else:
|
|
3296
|
+
sta.sg1[k] = 0.0
|
|
3297
|
+
flu.gr1[k] = 0.0
|
|
3298
|
+
|
|
3299
|
+
|
|
3300
|
+
class Calc_RG1_SG1_V1(modeltools.Method):
|
|
3301
|
+
r"""Calculate the discharge from the fast response groundwater reservoir and
|
|
3302
|
+
subtract it.
|
|
3303
|
+
|
|
3304
|
+
Basic equation:
|
|
3305
|
+
:math:`SG1_{new} = W2 \cdot SG1_{old} + (1 - W2) \cdot K2 \cdot GR1`
|
|
3306
|
+
|
|
3307
|
+
:math:`RG1 = SG1_{old} + GR1 - SG1_{new}`
|
|
3308
|
+
|
|
3309
|
+
Example:
|
|
3310
|
+
|
|
3311
|
+
For internal lakes and sealed areas, method |Calc_RG1_SG1_V1| always sets the
|
|
3312
|
+
values of |GR1| and |SG1| to zero:
|
|
3313
|
+
|
|
3314
|
+
>>> from hydpy.models.hland import *
|
|
3315
|
+
>>> simulationstep("1h")
|
|
3316
|
+
>>> parameterstep("1d")
|
|
3317
|
+
>>> nmbzones(7)
|
|
3318
|
+
>>> zonetype(FIELD, FIELD, FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3319
|
+
>>> k2(1.0/24, 10.0/24, 100.0/24, 100.0/24, 100.0/24, 100.0/24, 100.0/24)
|
|
3320
|
+
>>> from hydpy import round_
|
|
3321
|
+
>>> round_(k2.values)
|
|
3322
|
+
1.442695, 10.0, 100.0, 100.0, 100.0, 100.0, 100.0
|
|
3323
|
+
>>> derived.w2.update()
|
|
3324
|
+
>>> fluxes.gr1 = 2.0
|
|
3325
|
+
>>> states.sg1 = 5.0
|
|
3326
|
+
>>> model.calc_rg1_sg1_v1()
|
|
3327
|
+
>>> fluxes.rg1
|
|
3328
|
+
rg1(3.057305, 0.572561, 0.059718, 0.059718, 0.059718, 0.0, 0.0)
|
|
3329
|
+
>>> states.sg1
|
|
3330
|
+
sg1(3.942695, 6.427439, 6.940282, 6.940282, 6.940282, 0.0, 0.0)
|
|
3331
|
+
"""
|
|
3332
|
+
|
|
3333
|
+
CONTROLPARAMETERS = (
|
|
3334
|
+
hland_control.NmbZones,
|
|
3335
|
+
hland_control.ZoneType,
|
|
3336
|
+
hland_control.K2,
|
|
3337
|
+
)
|
|
3338
|
+
DERIVEDPARAMETERS = (hland_derived.W2,)
|
|
3339
|
+
REQUIREDSEQUENCES = (hland_fluxes.GR1,)
|
|
3340
|
+
UPDATEDSEQUENCES = (hland_states.SG1,)
|
|
3341
|
+
RESULTSEQUENCES = (hland_fluxes.RG1,)
|
|
3342
|
+
|
|
3343
|
+
@staticmethod
|
|
3344
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3345
|
+
con = model.parameters.control.fastaccess
|
|
3346
|
+
der = model.parameters.derived.fastaccess
|
|
3347
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3348
|
+
sta = model.sequences.states.fastaccess
|
|
3349
|
+
for k in range(con.nmbzones):
|
|
3350
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
3351
|
+
d_sg1 = sta.sg1[k]
|
|
3352
|
+
sta.sg1[k] = (
|
|
3353
|
+
der.w2[k] * d_sg1 + (1.0 - der.w2[k]) * con.k2[k] * flu.gr1[k]
|
|
3354
|
+
)
|
|
3355
|
+
flu.rg1[k] = d_sg1 + flu.gr1[k] - sta.sg1[k]
|
|
3356
|
+
else:
|
|
3357
|
+
sta.sg1[k] = 0.0
|
|
3358
|
+
flu.rg1[k] = 0.0
|
|
3359
|
+
|
|
3360
|
+
|
|
3361
|
+
class Calc_GR2_GR3_V1(modeltools.Method):
|
|
3362
|
+
r"""Calculate the recharge of the first-order and the second-order slow response
|
|
3363
|
+
groundwater reservoir.
|
|
3364
|
+
|
|
3365
|
+
Basic equations:
|
|
3366
|
+
.. math::
|
|
3367
|
+
GRT =
|
|
3368
|
+
\sum_{k=1}^{NmbZones} \frac{RelZoneAreas_k}{RelLowerZoneArea} \cdot
|
|
3369
|
+
\begin{cases}
|
|
3370
|
+
DP_k - GR1_k &|\ ZoneType_k \in \{ FIELD, FOREST, GLACIER \}
|
|
3371
|
+
\\
|
|
3372
|
+
Pc_k &|\ ZoneType_k = ILAKE
|
|
3373
|
+
\\
|
|
3374
|
+
0 &|\ ZoneType_k = SEALED
|
|
3375
|
+
\end{cases}
|
|
3376
|
+
|
|
3377
|
+
:math:`GR2 = FSG \cdot GRT`
|
|
3378
|
+
|
|
3379
|
+
:math:`GR3 = (1 - FSG) \cdot GRT`
|
|
3380
|
+
|
|
3381
|
+
Example:
|
|
3382
|
+
|
|
3383
|
+
Method |Calc_GR2_GR3_V1| aggregates the given input (term "GRT" in the given
|
|
3384
|
+
basic equations) divides it between |GR2| and |GR3|:
|
|
3385
|
+
|
|
3386
|
+
>>> from hydpy.models.hland import *
|
|
3387
|
+
>>> simulationstep("12h")
|
|
3388
|
+
>>> parameterstep("1d")
|
|
3389
|
+
>>> nmbzones(5)
|
|
3390
|
+
>>> zonetype(FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3391
|
+
>>> derived.relzoneareas(0.24, 0.18, 0.12, 0.06, 0.4)
|
|
3392
|
+
>>> derived.rellowerzonearea(0.6)
|
|
3393
|
+
>>> fluxes.gr1 = 1.0, 2.0, 3.0, nan, nan
|
|
3394
|
+
>>> fluxes.dp = 4.0, 6.0, 8.0, nan, nan
|
|
3395
|
+
>>> fluxes.pc = nan, nan, nan, 11.0, nan
|
|
3396
|
+
>>> model.calc_gr2_gr3_v1()
|
|
3397
|
+
>>> fluxes.gr2
|
|
3398
|
+
gr2(4.0)
|
|
3399
|
+
>>> fluxes.gr3
|
|
3400
|
+
gr3(0.5)
|
|
3401
|
+
"""
|
|
3402
|
+
|
|
3403
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3404
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLowerZoneArea)
|
|
3405
|
+
FIXEDPARAMETERS = (hland_fixed.FSG,)
|
|
3406
|
+
REQUIREDSEQUENCES = (hland_fluxes.PC, hland_fluxes.DP, hland_fluxes.GR1)
|
|
3407
|
+
RESULTSEQUENCES = (hland_fluxes.GR2, hland_fluxes.GR3)
|
|
3408
|
+
|
|
3409
|
+
@staticmethod
|
|
3410
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3411
|
+
con = model.parameters.control.fastaccess
|
|
3412
|
+
der = model.parameters.derived.fastaccess
|
|
3413
|
+
fix = model.parameters.fixed.fastaccess
|
|
3414
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3415
|
+
flu.gr2 = 0.0
|
|
3416
|
+
flu.gr3 = 0.0
|
|
3417
|
+
for k in range(con.nmbzones):
|
|
3418
|
+
if con.zonetype[k] == SEALED:
|
|
3419
|
+
continue
|
|
3420
|
+
d_weight = der.relzoneareas[k] / der.rellowerzonearea
|
|
3421
|
+
if con.zonetype[k] == ILAKE:
|
|
3422
|
+
d_total = d_weight * flu.pc[k]
|
|
3423
|
+
else:
|
|
3424
|
+
d_total = d_weight * (flu.dp[k] - flu.gr1[k])
|
|
3425
|
+
flu.gr2 += fix.fsg * d_total
|
|
3426
|
+
flu.gr3 += (1.0 - fix.fsg) * d_total
|
|
3427
|
+
|
|
3428
|
+
|
|
3429
|
+
class Calc_EL_SG2_SG3_AETModel_V1(modeltools.Method):
|
|
3430
|
+
r"""Let a submodel that follows the |AETModel_V1| submodel interface calculate
|
|
3431
|
+
lake evaporation and adjust the slow response groundwater reservoirs.
|
|
3432
|
+
|
|
3433
|
+
Basic equations:
|
|
3434
|
+
:math:`\frac{dSG2_i}{dt} =
|
|
3435
|
+
-FSG \cdot \frac{RelZoneAreas_i}{RelLowerZoneArea} \cdot EL_i`
|
|
3436
|
+
|
|
3437
|
+
:math:`\frac{dSG3_i}{dt} =
|
|
3438
|
+
-(1 - FSG) \cdot \frac{RelZoneAreas_i}{RelLowerZoneArea} \cdot EL_i`
|
|
3439
|
+
|
|
3440
|
+
Examples:
|
|
3441
|
+
|
|
3442
|
+
We build an example based on |evap_aet_hbv96| for calculating lake evaporation:
|
|
3443
|
+
|
|
3444
|
+
>>> from hydpy.models.hland_96p import *
|
|
3445
|
+
>>> parameterstep("1h")
|
|
3446
|
+
>>> nmbzones(5)
|
|
3447
|
+
>>> zonetype(GLACIER, SEALED, FIELD, FOREST, ILAKE)
|
|
3448
|
+
>>> area(0.9)
|
|
3449
|
+
>>> zonearea(0.2, 0.1, 0.1, 0.1, 0.4)
|
|
3450
|
+
>>> psi(1.0)
|
|
3451
|
+
>>> zonez(5.0)
|
|
3452
|
+
>>> fc(50.0)
|
|
3453
|
+
>>> derived.relzoneareas.update()
|
|
3454
|
+
>>> derived.rellowerzonearea.update()
|
|
3455
|
+
>>> factors.tc = 10.0
|
|
3456
|
+
>>> with model.add_aetmodel_v1("evap_aet_hbv96"):
|
|
3457
|
+
... temperaturethresholdice(0.0)
|
|
3458
|
+
|
|
3459
|
+
|Calc_EL_SG2_SG3_AETModel_V1| uses the flux returned by the submodel to adjust
|
|
3460
|
+
|SG2| and |SG3|, considering the total extent of the groundwater-affected
|
|
3461
|
+
subarea and the fraction between the spatial extents of the first-order and the
|
|
3462
|
+
second-order slow response groundwater reservoir:
|
|
3463
|
+
|
|
3464
|
+
>>> model.aetmodel.sequences.fluxes.potentialwaterevaporation = 2.25
|
|
3465
|
+
>>> states.sg2 = 3.0
|
|
3466
|
+
>>> states.sg3 = 0.3
|
|
3467
|
+
>>> model.calc_el_sg2_sg3_v1()
|
|
3468
|
+
>>> fluxes.el
|
|
3469
|
+
el(0.0, 0.0, 0.0, 0.0, 2.25)
|
|
3470
|
+
>>> states.sg2
|
|
3471
|
+
sg2(2.0)
|
|
3472
|
+
>>> states.sg3
|
|
3473
|
+
sg3(0.175)
|
|
3474
|
+
|
|
3475
|
+
Zones of type |ILAKE| are assumed to have an open water surface, so evaporation
|
|
3476
|
+
is always possible. Therefore, applying |Calc_EL_SG2_SG3_AETModel_V1| can
|
|
3477
|
+
result in negative |SG2| and |SG3| values:
|
|
3478
|
+
|
|
3479
|
+
>>> model.aetmodel.sequences.fluxes.potentialwaterevaporation = 4.5
|
|
3480
|
+
>>> states.sg2 = 1.0
|
|
3481
|
+
>>> states.sg3 = 0.1
|
|
3482
|
+
>>> model.calc_el_sg2_sg3_v1()
|
|
3483
|
+
>>> fluxes.el
|
|
3484
|
+
el(0.0, 0.0, 0.0, 0.0, 4.5)
|
|
3485
|
+
>>> states.sg2
|
|
3486
|
+
sg2(-1.0)
|
|
3487
|
+
>>> states.sg3
|
|
3488
|
+
sg3(-0.15)
|
|
3489
|
+
"""
|
|
3490
|
+
|
|
3491
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3492
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLowerZoneArea)
|
|
3493
|
+
FIXEDPARAMETERS = (hland_fixed.FSG,)
|
|
3494
|
+
UPDATEDSEQUENCES = (hland_states.SG2, hland_states.SG3)
|
|
3495
|
+
RESULTSEQUENCES = (hland_fluxes.EL,)
|
|
3496
|
+
|
|
3497
|
+
@staticmethod
|
|
3498
|
+
def __call__(model: modeltools.Model, submodel: aetinterfaces.AETModel_V1) -> None:
|
|
3499
|
+
con = model.parameters.control.fastaccess
|
|
3500
|
+
der = model.parameters.derived.fastaccess
|
|
3501
|
+
fix = model.parameters.fixed.fastaccess
|
|
3502
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3503
|
+
sta = model.sequences.states.fastaccess
|
|
3504
|
+
submodel.determine_waterevaporation()
|
|
3505
|
+
for k in range(con.nmbzones):
|
|
3506
|
+
if con.zonetype[k] == ILAKE:
|
|
3507
|
+
flu.el[k] = submodel.get_waterevaporation(k)
|
|
3508
|
+
weight: float = der.relzoneareas[k] / der.rellowerzonearea
|
|
3509
|
+
sta.sg2 -= fix.fsg * weight * flu.el[k]
|
|
3510
|
+
sta.sg3 -= (1.0 - fix.fsg) * weight * flu.el[k]
|
|
3511
|
+
else:
|
|
3512
|
+
flu.el[k] = 0.0
|
|
3513
|
+
|
|
3514
|
+
|
|
3515
|
+
class Calc_EL_SG2_SG3_V1(modeltools.Method):
|
|
3516
|
+
"""Let a submodel that follows the |AETModel_V1| submodel interface calculate
|
|
3517
|
+
interception evaporation, soil evapotranspiration, and open water evaporation, and
|
|
3518
|
+
adjust the related interception, soil water, and slow response groundwater storages
|
|
3519
|
+
accordingly."""
|
|
3520
|
+
|
|
3521
|
+
SUBMODELINTERFACES = (aetinterfaces.AETModel_V1,)
|
|
3522
|
+
SUBMETHODS = (Calc_EL_SG2_SG3_AETModel_V1,)
|
|
3523
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3524
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLowerZoneArea)
|
|
3525
|
+
FIXEDPARAMETERS = (hland_fixed.FSG,)
|
|
3526
|
+
UPDATEDSEQUENCES = (hland_states.SG2, hland_states.SG3)
|
|
3527
|
+
RESULTSEQUENCES = (hland_fluxes.EL,)
|
|
3528
|
+
|
|
3529
|
+
@staticmethod
|
|
3530
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3531
|
+
if model.aetmodel_typeid == 1:
|
|
3532
|
+
model.calc_el_sg2_sg3_aetmodel_v1(
|
|
3533
|
+
cast(aetinterfaces.AETModel_V1, model.aetmodel)
|
|
3534
|
+
)
|
|
3535
|
+
# ToDo:
|
|
3536
|
+
# else:
|
|
3537
|
+
# assert_never(model.petmodel)
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
class Calc_RG2_SG2_V1(modeltools.Method):
|
|
3541
|
+
r"""Calculate the discharge from the first-order slow response groundwater
|
|
3542
|
+
reservoir and subtract it.
|
|
3543
|
+
|
|
3544
|
+
Basic equation:
|
|
3545
|
+
:math:`SG2_{new} = W3 \cdot SG2_{old} + (1 - W3) \cdot K3 \cdot GR2`
|
|
3546
|
+
|
|
3547
|
+
:math:`RG2 = SG2_{old} + GR2 - SG2_{new}`
|
|
3548
|
+
|
|
3549
|
+
Examples:
|
|
3550
|
+
|
|
3551
|
+
>>> from hydpy.models.hland import *
|
|
3552
|
+
>>> simulationstep("1h")
|
|
3553
|
+
>>> parameterstep("1d")
|
|
3554
|
+
>>> k3(2.0/24)
|
|
3555
|
+
>>> from hydpy import round_
|
|
3556
|
+
>>> round_(k3.values)
|
|
3557
|
+
2.0
|
|
3558
|
+
>>> derived.w3.update()
|
|
3559
|
+
>>> fluxes.gr2 = 2.0
|
|
3560
|
+
|
|
3561
|
+
For non-negative |SG2| values, method |Calc_RG2_SG2_V1| strictly follows the
|
|
3562
|
+
given base equation:
|
|
3563
|
+
|
|
3564
|
+
>>> states.sg2 = 5.0
|
|
3565
|
+
>>> model.calc_rg2_sg2_v1()
|
|
3566
|
+
>>> fluxes.rg2
|
|
3567
|
+
rg2(2.393469)
|
|
3568
|
+
>>> states.sg2
|
|
3569
|
+
sg2(4.606531)
|
|
3570
|
+
|
|
3571
|
+
For negative |SG2| values, it uses |RG2| to fill the groundwater storage
|
|
3572
|
+
so that no discharge occurs:
|
|
3573
|
+
|
|
3574
|
+
>>> states.sg2 = -3.0
|
|
3575
|
+
>>> model.calc_rg2_sg2_v1()
|
|
3576
|
+
>>> fluxes.rg2
|
|
3577
|
+
rg2(0.0)
|
|
3578
|
+
>>> states.sg2
|
|
3579
|
+
sg2(-1.0)
|
|
3580
|
+
|
|
3581
|
+
>>> states.sg2 = -2.0
|
|
3582
|
+
>>> model.calc_rg2_sg2_v1()
|
|
3583
|
+
>>> fluxes.rg2
|
|
3584
|
+
rg2(0.0)
|
|
3585
|
+
>>> states.sg2
|
|
3586
|
+
sg2(0.0)
|
|
3587
|
+
|
|
3588
|
+
If the sum of |SG2| and |RG2| is positive, recharge first fills the deficit.
|
|
3589
|
+
In the remaining time, |Calc_RG2_SG2_V1| handles the remaining recharge as
|
|
3590
|
+
implied by the basic equations (with parameters |K3| and |W3| adapted to the
|
|
3591
|
+
remaining time interval):
|
|
3592
|
+
|
|
3593
|
+
>>> states.sg2 = -1.0
|
|
3594
|
+
>>> model.calc_rg2_sg2_v1()
|
|
3595
|
+
>>> fluxes.rg2
|
|
3596
|
+
rg2(0.115203)
|
|
3597
|
+
>>> states.sg2
|
|
3598
|
+
sg2(0.884797)
|
|
3599
|
+
"""
|
|
3600
|
+
|
|
3601
|
+
CONTROLPARAMETERS = (hland_control.K3,)
|
|
3602
|
+
DERIVEDPARAMETERS = (hland_derived.W3,)
|
|
3603
|
+
REQUIREDSEQUENCES = (hland_fluxes.GR2,)
|
|
3604
|
+
UPDATEDSEQUENCES = (hland_states.SG2,)
|
|
3605
|
+
RESULTSEQUENCES = (hland_fluxes.RG2,)
|
|
3606
|
+
|
|
3607
|
+
@staticmethod
|
|
3608
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3609
|
+
con = model.parameters.control.fastaccess
|
|
3610
|
+
der = model.parameters.derived.fastaccess
|
|
3611
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3612
|
+
sta = model.sequences.states.fastaccess
|
|
3613
|
+
d_sg2 = sta.sg2
|
|
3614
|
+
d_gr2 = flu.gr2
|
|
3615
|
+
d_k3 = con.k3
|
|
3616
|
+
d_w3 = der.w3
|
|
3617
|
+
if d_sg2 < 0.0 < d_gr2:
|
|
3618
|
+
d_add = min(-sta.sg2, d_gr2)
|
|
3619
|
+
d_k3 *= d_gr2 / d_add
|
|
3620
|
+
d_w3 = modelutils.exp(-1.0 / d_k3)
|
|
3621
|
+
d_sg2 += d_add
|
|
3622
|
+
d_gr2 -= d_add
|
|
3623
|
+
if d_sg2 >= 0.0:
|
|
3624
|
+
sta.sg2 = d_w3 * d_sg2 + (1.0 - d_w3) * d_k3 * d_gr2
|
|
3625
|
+
flu.rg2 = d_sg2 + d_gr2 - sta.sg2
|
|
3626
|
+
else:
|
|
3627
|
+
sta.sg2 = d_sg2
|
|
3628
|
+
flu.rg2 = 0.0
|
|
3629
|
+
|
|
3630
|
+
|
|
3631
|
+
class Calc_RG3_SG3_V1(modeltools.Method):
|
|
3632
|
+
r"""Calculate the discharge from the second-order slow response groundwater
|
|
3633
|
+
reservoir and subtract it.
|
|
3634
|
+
|
|
3635
|
+
Basic equation:
|
|
3636
|
+
:math:`SG3_{new} = W4 \cdot SG3_{old} + (1 - W4) \cdot K4 \cdot GR3`
|
|
3637
|
+
|
|
3638
|
+
:math:`RG3 = SG3_{old} + GR3 - SG3_{new}`
|
|
3639
|
+
|
|
3640
|
+
Examples:
|
|
3641
|
+
|
|
3642
|
+
>>> from hydpy.models.hland import *
|
|
3643
|
+
>>> simulationstep("1h")
|
|
3644
|
+
>>> parameterstep("1d")
|
|
3645
|
+
>>> derived.k4(1.0/24)
|
|
3646
|
+
>>> from hydpy import round_
|
|
3647
|
+
>>> round_(derived.k4.values)
|
|
3648
|
+
1.0
|
|
3649
|
+
>>> derived.w4.update()
|
|
3650
|
+
>>> fluxes.gr3 = 2.0
|
|
3651
|
+
|
|
3652
|
+
For non-negative |SG3| values, method |Calc_RG3_SG3_V1| strictly follows the
|
|
3653
|
+
given base equation:
|
|
3654
|
+
|
|
3655
|
+
>>> states.sg3 = 5.0
|
|
3656
|
+
>>> model.calc_rg3_sg3_v1()
|
|
3657
|
+
>>> fluxes.rg3
|
|
3658
|
+
rg3(3.896362)
|
|
3659
|
+
>>> states.sg3
|
|
3660
|
+
sg3(3.103638)
|
|
3661
|
+
|
|
3662
|
+
For negative |SG3| values, it uses |RG3| to fill the groundwater storage
|
|
3663
|
+
so that no discharge occurs:
|
|
3664
|
+
|
|
3665
|
+
>>> states.sg3 = -3.0
|
|
3666
|
+
>>> model.calc_rg3_sg3_v1()
|
|
3667
|
+
>>> fluxes.rg3
|
|
3668
|
+
rg3(0.0)
|
|
3669
|
+
>>> states.sg3
|
|
3670
|
+
sg3(-1.0)
|
|
3671
|
+
|
|
3672
|
+
>>> states.sg3 = -2.0
|
|
3673
|
+
>>> model.calc_rg3_sg3_v1()
|
|
3674
|
+
>>> fluxes.rg3
|
|
3675
|
+
rg3(0.0)
|
|
3676
|
+
>>> states.sg3
|
|
3677
|
+
sg3(0.0)
|
|
3678
|
+
|
|
3679
|
+
If the sum of |SG3| and |RG3| is positive, recharge first fills the deficit.
|
|
3680
|
+
In the remaining time, |Calc_RG3_SG3_V1| handles the remaining recharge as
|
|
3681
|
+
implied by the basic equations (with parameters |hland_derived.K4| and |W4|
|
|
3682
|
+
adapted to the remaining time interval):
|
|
3683
|
+
|
|
3684
|
+
>>> states.sg3 = -1.0
|
|
3685
|
+
>>> model.calc_rg3_sg3_v1()
|
|
3686
|
+
>>> fluxes.rg3
|
|
3687
|
+
rg3(0.213061)
|
|
3688
|
+
>>> states.sg3
|
|
3689
|
+
sg3(0.786939)
|
|
3690
|
+
"""
|
|
3691
|
+
|
|
3692
|
+
DERIVEDPARAMETERS = (hland_derived.K4, hland_derived.W4)
|
|
3693
|
+
REQUIREDSEQUENCES = (hland_fluxes.GR3,)
|
|
3694
|
+
UPDATEDSEQUENCES = (hland_states.SG3,)
|
|
3695
|
+
RESULTSEQUENCES = (hland_fluxes.RG3,)
|
|
3696
|
+
|
|
3697
|
+
@staticmethod
|
|
3698
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3699
|
+
der = model.parameters.derived.fastaccess
|
|
3700
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3701
|
+
sta = model.sequences.states.fastaccess
|
|
3702
|
+
d_sg3 = sta.sg3
|
|
3703
|
+
d_gr3 = flu.gr3
|
|
3704
|
+
d_k4 = der.k4
|
|
3705
|
+
d_w4 = der.w4
|
|
3706
|
+
if d_sg3 < 0.0 < d_gr3:
|
|
3707
|
+
d_add = min(-sta.sg3, d_gr3)
|
|
3708
|
+
d_k4 *= d_gr3 / d_add
|
|
3709
|
+
d_w4 = modelutils.exp(-1.0 / d_k4)
|
|
3710
|
+
d_sg3 += d_add
|
|
3711
|
+
d_gr3 -= d_add
|
|
3712
|
+
if d_sg3 >= 0.0:
|
|
3713
|
+
sta.sg3 = d_w4 * d_sg3 + (1.0 - d_w4) * d_k4 * d_gr3
|
|
3714
|
+
flu.rg3 = d_sg3 + d_gr3 - sta.sg3
|
|
3715
|
+
else:
|
|
3716
|
+
sta.sg3 = d_sg3
|
|
3717
|
+
flu.rg3 = 0.0
|
|
3718
|
+
|
|
3719
|
+
|
|
3720
|
+
class Calc_EL_LZ_AETModel_V1(modeltools.Method):
|
|
3721
|
+
r"""Let a submodel that follows the |AETModel_V1| submodel interface calculate
|
|
3722
|
+
lake evaporation and adjust the lower zone's water content.
|
|
3723
|
+
|
|
3724
|
+
Basic equation:
|
|
3725
|
+
:math:`\frac{dLZ_i}{dt} = -\frac{RelZoneAreas_i}{RelLowerZoneArea} \cdot EL_i`
|
|
3726
|
+
|
|
3727
|
+
Examples:
|
|
3728
|
+
|
|
3729
|
+
We build an example based on |evap_aet_hbv96| for calculating lake evaporation:
|
|
3730
|
+
|
|
3731
|
+
>>> from hydpy.models.hland_96 import *
|
|
3732
|
+
>>> parameterstep("1h")
|
|
3733
|
+
>>> nmbzones(5)
|
|
3734
|
+
>>> zonetype(GLACIER, SEALED, FIELD, FOREST, ILAKE)
|
|
3735
|
+
>>> area(0.9)
|
|
3736
|
+
>>> zonearea(0.2, 0.1, 0.1, 0.1, 0.4)
|
|
3737
|
+
>>> psi(1.0)
|
|
3738
|
+
>>> zonez(5.0)
|
|
3739
|
+
>>> fc(50.0)
|
|
3740
|
+
>>> derived.relzoneareas.update()
|
|
3741
|
+
>>> derived.rellowerzonearea.update()
|
|
3742
|
+
>>> factors.tc = 10.0
|
|
3743
|
+
>>> with model.add_aetmodel_v1("evap_aet_hbv96"):
|
|
3744
|
+
... temperaturethresholdice(0.0)
|
|
3745
|
+
|
|
3746
|
+
|Calc_EL_LZ_AETModel_V1| uses the flux returned by the submodel to adjust |LZ|,
|
|
3747
|
+
considering the extent of the groundwater-affected subarea:
|
|
3748
|
+
|
|
3749
|
+
>>> model.aetmodel.sequences.fluxes.potentialwaterevaporation = 2.0
|
|
3750
|
+
>>> states.lz = 3.0
|
|
3751
|
+
>>> model.calc_el_lz_v1()
|
|
3752
|
+
>>> fluxes.el
|
|
3753
|
+
el(0.0, 0.0, 0.0, 0.0, 2.0)
|
|
3754
|
+
>>> states.lz
|
|
3755
|
+
lz(2.0)
|
|
3756
|
+
|
|
3757
|
+
Zones of type |ILAKE| are assumed to have an open water surface, so evaporation
|
|
3758
|
+
is always possible. Therefore, applying |Calc_EL_LZ_AETModel_V1| can result in
|
|
3759
|
+
negative |LZ| values:
|
|
3760
|
+
|
|
3761
|
+
>>> model.aetmodel.sequences.fluxes.potentialwaterevaporation = 6.0
|
|
3762
|
+
>>> states.lz = 1.0
|
|
3763
|
+
>>> model.calc_el_lz_v1()
|
|
3764
|
+
>>> fluxes.el
|
|
3765
|
+
el(0.0, 0.0, 0.0, 0.0, 6.0)
|
|
3766
|
+
>>> states.lz
|
|
3767
|
+
lz(-2.0)
|
|
3768
|
+
"""
|
|
3769
|
+
|
|
3770
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3771
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLowerZoneArea)
|
|
3772
|
+
UPDATEDSEQUENCES = (hland_states.LZ,)
|
|
3773
|
+
RESULTSEQUENCES = (hland_fluxes.EL,)
|
|
3774
|
+
|
|
3775
|
+
@staticmethod
|
|
3776
|
+
def __call__(model: modeltools.Model, submodel: aetinterfaces.AETModel_V1) -> None:
|
|
3777
|
+
con = model.parameters.control.fastaccess
|
|
3778
|
+
der = model.parameters.derived.fastaccess
|
|
3779
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3780
|
+
sta = model.sequences.states.fastaccess
|
|
3781
|
+
submodel.determine_waterevaporation()
|
|
3782
|
+
for k in range(con.nmbzones):
|
|
3783
|
+
if con.zonetype[k] == ILAKE:
|
|
3784
|
+
flu.el[k] = submodel.get_waterevaporation(k)
|
|
3785
|
+
sta.lz -= der.relzoneareas[k] / der.rellowerzonearea * flu.el[k]
|
|
3786
|
+
else:
|
|
3787
|
+
flu.el[k] = 0.0
|
|
3788
|
+
|
|
3789
|
+
|
|
3790
|
+
class Calc_EL_LZ_V1(modeltools.Method):
|
|
3791
|
+
"""Let a submodel that follows the |AETModel_V1| submodel interface calculate lake
|
|
3792
|
+
evaporation and adjust the lower zone's water content."""
|
|
3793
|
+
|
|
3794
|
+
SUBMODELINTERFACES = (aetinterfaces.AETModel_V1,)
|
|
3795
|
+
SUBMETHODS = (Calc_EL_LZ_AETModel_V1,)
|
|
3796
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3797
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLowerZoneArea)
|
|
3798
|
+
UPDATEDSEQUENCES = (hland_states.LZ,)
|
|
3799
|
+
RESULTSEQUENCES = (hland_fluxes.EL,)
|
|
3800
|
+
|
|
3801
|
+
@staticmethod
|
|
3802
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3803
|
+
if model.aetmodel_typeid == 1:
|
|
3804
|
+
model.calc_el_lz_aetmodel_v1(
|
|
3805
|
+
cast(aetinterfaces.AETModel_V1, model.aetmodel)
|
|
3806
|
+
)
|
|
3807
|
+
# ToDo:
|
|
3808
|
+
# else:
|
|
3809
|
+
# assert_never(model.petmodel)
|
|
3810
|
+
|
|
3811
|
+
|
|
3812
|
+
class Calc_Q1_LZ_V1(modeltools.Method):
|
|
3813
|
+
r"""Calculate the slow response of the lower zone layer.
|
|
3814
|
+
|
|
3815
|
+
Basic equations:
|
|
3816
|
+
.. math::
|
|
3817
|
+
Q1 =
|
|
3818
|
+
\begin{cases}
|
|
3819
|
+
K4 \cdot LZ^{1 + Gamma} &|\ LZ > 0
|
|
3820
|
+
\\
|
|
3821
|
+
0 &|\ LZ \leq 0
|
|
3822
|
+
\end{cases}
|
|
3823
|
+
|
|
3824
|
+
:math:`\frac{dLZ}{dt} = -Q1`
|
|
3825
|
+
|
|
3826
|
+
Examples:
|
|
3827
|
+
|
|
3828
|
+
As long as the lower zone storage is negative or zero, there is no slow
|
|
3829
|
+
discharge response:
|
|
3830
|
+
|
|
3831
|
+
>>> from hydpy.models.hland import *
|
|
3832
|
+
>>> simulationstep("12h")
|
|
3833
|
+
>>> parameterstep("1d")
|
|
3834
|
+
>>> k4(0.2)
|
|
3835
|
+
>>> gamma(0.0)
|
|
3836
|
+
>>> states.lz = -2.0
|
|
3837
|
+
>>> model.calc_q1_lz_v1()
|
|
3838
|
+
>>> fluxes.q1
|
|
3839
|
+
q1(0.0)
|
|
3840
|
+
>>> states.lz
|
|
3841
|
+
lz(-2.0)
|
|
3842
|
+
|
|
3843
|
+
>>> states.lz = 0.0
|
|
3844
|
+
>>> model.calc_q1_lz_v1()
|
|
3845
|
+
>>> fluxes.q1
|
|
3846
|
+
q1(0.0)
|
|
3847
|
+
>>> states.lz
|
|
3848
|
+
lz(0.0)
|
|
3849
|
+
|
|
3850
|
+
For storage values above zero the linear or nonlinear storage routing equation
|
|
3851
|
+
applies:
|
|
3852
|
+
|
|
3853
|
+
>>> states.lz = 2.0
|
|
3854
|
+
>>> model.calc_q1_lz_v1()
|
|
3855
|
+
>>> fluxes.q1
|
|
3856
|
+
q1(0.2)
|
|
3857
|
+
>>> states.lz
|
|
3858
|
+
lz(1.8)
|
|
3859
|
+
|
|
3860
|
+
>>> gamma(1.0)
|
|
3861
|
+
>>> states.lz = 2.0
|
|
3862
|
+
>>> model.calc_q1_lz_v1()
|
|
3863
|
+
>>> fluxes.q1
|
|
3864
|
+
q1(0.4)
|
|
3865
|
+
>>> states.lz
|
|
3866
|
+
lz(1.6)
|
|
3867
|
+
|
|
3868
|
+
Note that the assumed length of the simulation step is half a day. Hence the
|
|
3869
|
+
effective value of the storage coefficient is not 0.2 but 0.1:
|
|
3870
|
+
|
|
3871
|
+
>>> k4
|
|
3872
|
+
k4(0.2)
|
|
3873
|
+
>>> k4.value
|
|
3874
|
+
0.1
|
|
3875
|
+
"""
|
|
3876
|
+
|
|
3877
|
+
CONTROLPARAMETERS = (hland_control.K4, hland_control.Gamma)
|
|
3878
|
+
UPDATEDSEQUENCES = (hland_states.LZ,)
|
|
3879
|
+
RESULTSEQUENCES = (hland_fluxes.Q1,)
|
|
3880
|
+
|
|
3881
|
+
@staticmethod
|
|
3882
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3883
|
+
con = model.parameters.control.fastaccess
|
|
3884
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3885
|
+
sta = model.sequences.states.fastaccess
|
|
3886
|
+
if sta.lz > 0.0:
|
|
3887
|
+
flu.q1 = con.k4 * sta.lz ** (1.0 + con.gamma)
|
|
3888
|
+
else:
|
|
3889
|
+
flu.q1 = 0.0
|
|
3890
|
+
sta.lz -= flu.q1
|
|
3891
|
+
|
|
3892
|
+
|
|
3893
|
+
class Calc_InRC_V1(modeltools.Method):
|
|
3894
|
+
r"""Calculate the input of the runoff concentration submodel.
|
|
3895
|
+
|
|
3896
|
+
Basic equation:
|
|
3897
|
+
.. math::
|
|
3898
|
+
InRC = A_U \cdot Q0 + A_L \cdot Q1 +
|
|
3899
|
+
\sum_{k=1}^{N} A_Z^k \cdot \begin{cases}
|
|
3900
|
+
R &|\ T_Z^k = S
|
|
3901
|
+
\\
|
|
3902
|
+
0 &|\ T_Z^k \neq S
|
|
3903
|
+
\end{cases}
|
|
3904
|
+
\\ \\
|
|
3905
|
+
N = NmbZones \\
|
|
3906
|
+
A_U = RelUpperZoneArea \\
|
|
3907
|
+
A_L = RelLowerZoneArea \\
|
|
3908
|
+
A_Z = RelZoneAreas \\
|
|
3909
|
+
T_Z = ZoneType \\
|
|
3910
|
+
S = SEALED
|
|
3911
|
+
|
|
3912
|
+
Example:
|
|
3913
|
+
|
|
3914
|
+
We define a subbasin with five zones of different land-use types and sizes:
|
|
3915
|
+
|
|
3916
|
+
>>> from hydpy.models.hland import *
|
|
3917
|
+
>>> simulationstep("12h")
|
|
3918
|
+
>>> parameterstep("1d")
|
|
3919
|
+
>>> nmbzones(5)
|
|
3920
|
+
>>> zonetype(FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3921
|
+
>>> area(100.0)
|
|
3922
|
+
>>> zonearea(10.0, 20.0, 30.0, 15.0, 25.0)
|
|
3923
|
+
>>> psi(1.0)
|
|
3924
|
+
|
|
3925
|
+
To ensure the consistency of the values of the relevant derived parameters, we
|
|
3926
|
+
apply their |Parameter.update| methods:
|
|
3927
|
+
|
|
3928
|
+
>>> derived.relzoneareas.update()
|
|
3929
|
+
>>> derived.relupperzonearea.update()
|
|
3930
|
+
>>> derived.rellowerzonearea.update()
|
|
3931
|
+
|
|
3932
|
+
The runoff concentration submodel receives freshly generated runoff (|R|)
|
|
3933
|
+
directly from the sealed zone (0.5 mm), direct runoff (|Q0|) indirectly from
|
|
3934
|
+
the field, forest, and glacier zones (0.6 mm) and base flow (|Q1|) indirectly
|
|
3935
|
+
from the field, forest, glacier and internal lake zones (3.0 mm):
|
|
3936
|
+
|
|
3937
|
+
>>> fluxes.r = 2.0
|
|
3938
|
+
>>> fluxes.q0 = 1.0
|
|
3939
|
+
>>> fluxes.q1 = 4.0
|
|
3940
|
+
>>> model.calc_inrc_v1()
|
|
3941
|
+
>>> fluxes.inrc
|
|
3942
|
+
inrc(4.1)
|
|
3943
|
+
"""
|
|
3944
|
+
|
|
3945
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
3946
|
+
DERIVEDPARAMETERS = (
|
|
3947
|
+
hland_derived.RelZoneAreas,
|
|
3948
|
+
hland_derived.RelUpperZoneArea,
|
|
3949
|
+
hland_derived.RelLowerZoneArea,
|
|
3950
|
+
)
|
|
3951
|
+
REQUIREDSEQUENCES = (hland_fluxes.R, hland_fluxes.Q0, hland_fluxes.Q1)
|
|
3952
|
+
RESULTSEQUENCES = (hland_fluxes.InRC,)
|
|
3953
|
+
|
|
3954
|
+
@staticmethod
|
|
3955
|
+
def __call__(model: modeltools.Model) -> None:
|
|
3956
|
+
con = model.parameters.control.fastaccess
|
|
3957
|
+
der = model.parameters.derived.fastaccess
|
|
3958
|
+
flu = model.sequences.fluxes.fastaccess
|
|
3959
|
+
flu.inrc = der.relupperzonearea * flu.q0 + der.rellowerzonearea * flu.q1
|
|
3960
|
+
for k in range(con.nmbzones):
|
|
3961
|
+
if con.zonetype[k] == SEALED:
|
|
3962
|
+
flu.inrc += der.relzoneareas[k] * flu.r[k]
|
|
3963
|
+
|
|
3964
|
+
|
|
3965
|
+
class Calc_InRC_V2(modeltools.Method):
|
|
3966
|
+
r"""Calculate the input of the runoff concentration submodel.
|
|
3967
|
+
|
|
3968
|
+
Basic equation:
|
|
3969
|
+
.. math::
|
|
3970
|
+
InRC = A_L \cdot (RG2 + RG3) +
|
|
3971
|
+
\sum_{k=1}^{N}
|
|
3972
|
+
\begin{cases}
|
|
3973
|
+
RS + RI + RG1 &|\ T_Z^k \in \{FI, FO, G \}
|
|
3974
|
+
\\
|
|
3975
|
+
R &|\ T_Z^k = S
|
|
3976
|
+
\\
|
|
3977
|
+
0 &|\ T_Z^k = L
|
|
3978
|
+
\end{cases}
|
|
3979
|
+
\\ \\
|
|
3980
|
+
N = NmbZones \\
|
|
3981
|
+
A_L = RelLowerZoneArea \\
|
|
3982
|
+
Z_T = ZoneType \\
|
|
3983
|
+
FI = FIELD \\
|
|
3984
|
+
FO = FOREST \\
|
|
3985
|
+
G = GLACIER \\
|
|
3986
|
+
S = SEALED \\
|
|
3987
|
+
L = ILAKE
|
|
3988
|
+
|
|
3989
|
+
Example:
|
|
3990
|
+
|
|
3991
|
+
Besides adding all components, method |Calc_InRC_V2| needs to aggregate the HRU
|
|
3992
|
+
level values of |RS|, |RI|, |RG1|, and |R| to the subbasin level:
|
|
3993
|
+
|
|
3994
|
+
>>> from hydpy.models.hland import *
|
|
3995
|
+
>>> simulationstep("12h")
|
|
3996
|
+
>>> parameterstep("1d")
|
|
3997
|
+
>>> nmbzones(5)
|
|
3998
|
+
>>> zonetype(FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
3999
|
+
>>> derived.relzoneareas(0.35, 0.25, 0.15, 0.05, 0.2)
|
|
4000
|
+
>>> derived.rellowerzonearea(0.8)
|
|
4001
|
+
>>> fluxes.rs = 0.1, 0.2, 0.3, nan, nan
|
|
4002
|
+
>>> fluxes.ri = 0.4, 0.6, 0.8, nan, nan
|
|
4003
|
+
>>> fluxes.rg1 = 1.1, 1.4, 1.7, nan, nan
|
|
4004
|
+
>>> fluxes.r = nan, nan, nan, nan, 2.0
|
|
4005
|
+
>>> fluxes.rg2 = 3.0
|
|
4006
|
+
>>> fluxes.rg3 = 4.0
|
|
4007
|
+
>>> model.calc_inrc_v2()
|
|
4008
|
+
>>> fluxes.inrc
|
|
4009
|
+
inrc(7.53)
|
|
4010
|
+
"""
|
|
4011
|
+
|
|
4012
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
4013
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLowerZoneArea)
|
|
4014
|
+
REQUIREDSEQUENCES = (
|
|
4015
|
+
hland_fluxes.R,
|
|
4016
|
+
hland_fluxes.RS,
|
|
4017
|
+
hland_fluxes.RI,
|
|
4018
|
+
hland_fluxes.RG1,
|
|
4019
|
+
hland_fluxes.RG2,
|
|
4020
|
+
hland_fluxes.RG3,
|
|
4021
|
+
)
|
|
4022
|
+
RESULTSEQUENCES = (hland_fluxes.InRC,)
|
|
4023
|
+
|
|
4024
|
+
@staticmethod
|
|
4025
|
+
def __call__(model: modeltools.Model) -> None:
|
|
4026
|
+
con = model.parameters.control.fastaccess
|
|
4027
|
+
der = model.parameters.derived.fastaccess
|
|
4028
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4029
|
+
flu.inrc = der.rellowerzonearea * (flu.rg2 + flu.rg3)
|
|
4030
|
+
for k in range(con.nmbzones):
|
|
4031
|
+
if con.zonetype[k] in (FIELD, FOREST, GLACIER):
|
|
4032
|
+
flu.inrc += der.relzoneareas[k] * (flu.rs[k] + flu.ri[k] + flu.rg1[k])
|
|
4033
|
+
elif con.zonetype[k] == SEALED:
|
|
4034
|
+
flu.inrc += der.relzoneareas[k] * flu.r[k]
|
|
4035
|
+
|
|
4036
|
+
|
|
4037
|
+
class Calc_InRC_V3(modeltools.Method):
|
|
4038
|
+
r"""Calculate the input of the runoff concentration submodel.
|
|
4039
|
+
|
|
4040
|
+
Basic equation:
|
|
4041
|
+
.. math::
|
|
4042
|
+
InRC = \sum_{k=1}^{N} \frac{A_Z^k}{A_L} \cdot
|
|
4043
|
+
\begin{cases}
|
|
4044
|
+
QAb1 + QAb2 &|\ T_Z^k \in \{FI, FO, G \}
|
|
4045
|
+
\\
|
|
4046
|
+
R &|\ T_Z^k = S
|
|
4047
|
+
\\
|
|
4048
|
+
0 &|\ T_Z^k = L
|
|
4049
|
+
\end{cases}
|
|
4050
|
+
\\ \\
|
|
4051
|
+
N = NmbZones \\
|
|
4052
|
+
A_Z = RelZoneAreas \\
|
|
4053
|
+
A_L = RelLandArea \\
|
|
4054
|
+
T_Z = ZoneType \\
|
|
4055
|
+
FI = FIELD \\
|
|
4056
|
+
FO = FOREST \\
|
|
4057
|
+
G = GLACIER \\
|
|
4058
|
+
S = SEALED \\
|
|
4059
|
+
L = ILAKE
|
|
4060
|
+
|
|
4061
|
+
Example:
|
|
4062
|
+
|
|
4063
|
+
The runoff concentration submodel receives surface flow (|QAb1| and |QAb2|)
|
|
4064
|
+
from the first three zones of type |FIELD|, |FOREST|, and |GLACIER|, receives
|
|
4065
|
+
directly generated runoff from the fifth zone of type |SEALED|, and receives
|
|
4066
|
+
nothing from the fourth zone of type |ILAKE|:
|
|
4067
|
+
|
|
4068
|
+
>>> from hydpy.models.hland import *
|
|
4069
|
+
>>> simulationstep("12h")
|
|
4070
|
+
>>> parameterstep("1d")
|
|
4071
|
+
>>> nmbzones(5)
|
|
4072
|
+
>>> zonetype(FIELD, FOREST, GLACIER, ILAKE, SEALED)
|
|
4073
|
+
>>> derived.relzoneareas = 0.35, 0.25, 0.15, 0.2, 0.05
|
|
4074
|
+
>>> derived.rellandarea(0.8)
|
|
4075
|
+
>>> fluxes.qab1 = 1.0, 2.0, 3.0, nan, nan
|
|
4076
|
+
>>> fluxes.qab2 = 3.0, 6.0, 9.0, nan, nan
|
|
4077
|
+
>>> fluxes.r = nan, nan, nan, nan, 8.0
|
|
4078
|
+
>>> model.calc_inrc_v3()
|
|
4079
|
+
>>> fluxes.inrc
|
|
4080
|
+
inrc(7.0)
|
|
4081
|
+
"""
|
|
4082
|
+
|
|
4083
|
+
CONTROLPARAMETERS = (hland_control.NmbZones, hland_control.ZoneType)
|
|
4084
|
+
DERIVEDPARAMETERS = (hland_derived.RelZoneAreas, hland_derived.RelLandArea)
|
|
4085
|
+
REQUIREDSEQUENCES = (hland_fluxes.R, hland_fluxes.QAb1, hland_fluxes.QAb2)
|
|
4086
|
+
RESULTSEQUENCES = (hland_fluxes.InRC,)
|
|
4087
|
+
|
|
4088
|
+
@staticmethod
|
|
4089
|
+
def __call__(model: modeltools.Model) -> None:
|
|
4090
|
+
con = model.parameters.control.fastaccess
|
|
4091
|
+
der = model.parameters.derived.fastaccess
|
|
4092
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4093
|
+
flu.inrc = 0.0
|
|
4094
|
+
for k in range(con.nmbzones):
|
|
4095
|
+
if con.zonetype[k] == ILAKE:
|
|
4096
|
+
continue
|
|
4097
|
+
d_weight = der.relzoneareas[k] / der.rellandarea
|
|
4098
|
+
if con.zonetype[k] == SEALED:
|
|
4099
|
+
flu.inrc += d_weight * flu.r[k]
|
|
4100
|
+
else:
|
|
4101
|
+
flu.inrc += d_weight * (flu.qab1[k] + flu.qab2[k])
|
|
4102
|
+
|
|
4103
|
+
|
|
4104
|
+
class Calc_OutRC_RConcModel_V1(modeltools.Method):
|
|
4105
|
+
"""Let a submodel that follows the |RConcModel_V1| submodel interface calculate
|
|
4106
|
+
runoff concentration."""
|
|
4107
|
+
|
|
4108
|
+
REQUIREDSEQUENCES = (hland_fluxes.InRC,)
|
|
4109
|
+
RESULTSEQUENCES = (hland_fluxes.OutRC,)
|
|
4110
|
+
|
|
4111
|
+
@staticmethod
|
|
4112
|
+
def __call__(
|
|
4113
|
+
model: modeltools.Model, submodel: rconcinterfaces.RConcModel_V1
|
|
4114
|
+
) -> None:
|
|
4115
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4116
|
+
submodel.set_inflow(flu.inrc)
|
|
4117
|
+
submodel.determine_outflow()
|
|
4118
|
+
flu.outrc = submodel.get_outflow()
|
|
4119
|
+
|
|
4120
|
+
|
|
4121
|
+
class Calc_OutRC_V1(modeltools.Method):
|
|
4122
|
+
"""If the model has a submodel that follows the |RConcModel_V1| submodel interface,
|
|
4123
|
+
calculate runoff concentration. If not, set the output equal to the input.
|
|
4124
|
+
|
|
4125
|
+
Examples:
|
|
4126
|
+
|
|
4127
|
+
A model without a submodel for runoff concentration directs the input directly
|
|
4128
|
+
to the output:
|
|
4129
|
+
|
|
4130
|
+
>>> from hydpy.models.hland_96 import *
|
|
4131
|
+
>>> simulationstep("1h")
|
|
4132
|
+
>>> parameterstep("1d")
|
|
4133
|
+
>>> fluxes.inrc = 1.0
|
|
4134
|
+
>>> model.calc_outrc_v1()
|
|
4135
|
+
>>> fluxes.outrc
|
|
4136
|
+
outrc(1.0)
|
|
4137
|
+
|
|
4138
|
+
If a submodel for runoff concentration is added (in this case, a unit
|
|
4139
|
+
hydrograph with three ordinates), the output for the first time step
|
|
4140
|
+
corresponds to the portion of the input specified by the first ordinate (since
|
|
4141
|
+
the initial conditions of the logging sequence |rconc_logs.QUH| were set to
|
|
4142
|
+
zero, and thus no additional runoff portions from previous time steps are
|
|
4143
|
+
included):
|
|
4144
|
+
|
|
4145
|
+
>>> with model.add_rconcmodel_v1("rconc_uh"):
|
|
4146
|
+
... uh([0.3,0.4,0.3])
|
|
4147
|
+
... logs.quh = 0.0, 0.0, 0.0
|
|
4148
|
+
>>> model.calc_outrc_v1()
|
|
4149
|
+
>>> fluxes.outrc
|
|
4150
|
+
outrc(0.3)
|
|
4151
|
+
"""
|
|
4152
|
+
|
|
4153
|
+
SUBMODELINTERFACES = (rconcinterfaces.RConcModel_V1,)
|
|
4154
|
+
SUBMETHODS = (Calc_OutRC_RConcModel_V1,)
|
|
4155
|
+
REQUIREDSEQUENCES = (hland_fluxes.InRC,)
|
|
4156
|
+
RESULTSEQUENCES = (hland_fluxes.OutRC,)
|
|
4157
|
+
|
|
4158
|
+
@staticmethod
|
|
4159
|
+
def __call__(model: modeltools.Model) -> None:
|
|
4160
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4161
|
+
if model.rconcmodel is None:
|
|
4162
|
+
flu.outrc = flu.inrc
|
|
4163
|
+
elif model.rconcmodel_typeid == 1:
|
|
4164
|
+
model.calc_outrc_rconcmodel_v1(
|
|
4165
|
+
cast(rconcinterfaces.RConcModel_V1, model.rconcmodel)
|
|
4166
|
+
)
|
|
4167
|
+
|
|
4168
|
+
|
|
4169
|
+
class Calc_RT_V1(modeltools.Method):
|
|
4170
|
+
r"""Calculate the total discharge in mm.
|
|
4171
|
+
|
|
4172
|
+
Basic equation:
|
|
4173
|
+
:math:`RT = OutRC`
|
|
4174
|
+
|
|
4175
|
+
Examples:
|
|
4176
|
+
|
|
4177
|
+
>>> from hydpy.models.hland import *
|
|
4178
|
+
>>> parameterstep()
|
|
4179
|
+
>>> fluxes.outrc = 3.0
|
|
4180
|
+
>>> model.calc_rt_v1()
|
|
4181
|
+
>>> fluxes.rt
|
|
4182
|
+
rt(3.0)
|
|
4183
|
+
"""
|
|
4184
|
+
|
|
4185
|
+
REQUIREDSEQUENCES = (hland_fluxes.OutRC,)
|
|
4186
|
+
RESULTSEQUENCES = (hland_fluxes.RT,)
|
|
4187
|
+
|
|
4188
|
+
@staticmethod
|
|
4189
|
+
def __call__(model: modeltools.Model) -> None:
|
|
4190
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4191
|
+
flu.rt = flu.outrc
|
|
4192
|
+
|
|
4193
|
+
|
|
4194
|
+
class Calc_RT_V2(modeltools.Method):
|
|
4195
|
+
r"""Calculate the total discharge in mm.
|
|
4196
|
+
|
|
4197
|
+
Basic equation:
|
|
4198
|
+
:math:`RT = RelUpperZoneArea \cdot OutRC + RelLowerZoneArea \cdot Q1`
|
|
4199
|
+
|
|
4200
|
+
Example:
|
|
4201
|
+
|
|
4202
|
+
>>> from hydpy.models.hland import *
|
|
4203
|
+
>>> parameterstep()
|
|
4204
|
+
>>> derived.rellandarea(0.8)
|
|
4205
|
+
>>> derived.rellowerzonearea(0.6)
|
|
4206
|
+
>>> fluxes.outrc = 2.5
|
|
4207
|
+
>>> fluxes.q1 = 1.0
|
|
4208
|
+
>>> model.calc_rt_v2()
|
|
4209
|
+
>>> fluxes.rt
|
|
4210
|
+
rt(2.6)
|
|
4211
|
+
"""
|
|
4212
|
+
|
|
4213
|
+
DERIVEDPARAMETERS = (hland_derived.RelLandArea, hland_derived.RelLowerZoneArea)
|
|
4214
|
+
REQUIREDSEQUENCES = (hland_fluxes.OutRC, hland_fluxes.Q1)
|
|
4215
|
+
RESULTSEQUENCES = (hland_fluxes.RT,)
|
|
4216
|
+
|
|
4217
|
+
@staticmethod
|
|
4218
|
+
def __call__(model: modeltools.Model) -> None:
|
|
4219
|
+
der = model.parameters.derived.fastaccess
|
|
4220
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4221
|
+
flu.rt = der.rellandarea * flu.outrc + der.rellowerzonearea * flu.q1
|
|
4222
|
+
|
|
4223
|
+
|
|
4224
|
+
class Calc_QT_V1(modeltools.Method):
|
|
4225
|
+
r"""Calculate the total discharge in m³/s.
|
|
4226
|
+
|
|
4227
|
+
Basic equation:
|
|
4228
|
+
:math:`QT = QFactor \cdot RT`
|
|
4229
|
+
|
|
4230
|
+
Example:
|
|
4231
|
+
|
|
4232
|
+
>>> from hydpy.models.hland import *
|
|
4233
|
+
>>> simulationstep("12h")
|
|
4234
|
+
>>> parameterstep("1d")
|
|
4235
|
+
>>> derived.qfactor(0.5)
|
|
4236
|
+
>>> fluxes.rt = 2.0
|
|
4237
|
+
>>> model.calc_qt_v1()
|
|
4238
|
+
>>> fluxes.qt
|
|
4239
|
+
qt(1.0)
|
|
4240
|
+
"""
|
|
4241
|
+
|
|
4242
|
+
DERIVEDPARAMETERS = (hland_derived.QFactor,)
|
|
4243
|
+
REQUIREDSEQUENCES = (hland_fluxes.RT,)
|
|
4244
|
+
RESULTSEQUENCES = (hland_fluxes.QT,)
|
|
4245
|
+
|
|
4246
|
+
@staticmethod
|
|
4247
|
+
def __call__(model: modeltools.Model) -> None:
|
|
4248
|
+
der = model.parameters.derived.fastaccess
|
|
4249
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4250
|
+
flu.qt = der.qfactor * flu.rt
|
|
4251
|
+
|
|
4252
|
+
|
|
4253
|
+
class Pass_Q_V1(modeltools.Method):
|
|
4254
|
+
r"""Update the outlet link sequence."""
|
|
4255
|
+
|
|
4256
|
+
REQUIREDSEQUENCES = (hland_fluxes.QT,)
|
|
4257
|
+
RESULTSEQUENCES = (hland_outlets.Q,)
|
|
4258
|
+
|
|
4259
|
+
@staticmethod
|
|
4260
|
+
def __call__(model: modeltools.Model) -> None:
|
|
4261
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4262
|
+
out = model.sequences.outlets.fastaccess
|
|
4263
|
+
out.q[0] += flu.qt
|
|
4264
|
+
|
|
4265
|
+
|
|
4266
|
+
class Get_Temperature_V1(modeltools.Method):
|
|
4267
|
+
"""Get the selected zone's current temperature.
|
|
4268
|
+
|
|
4269
|
+
Example:
|
|
4270
|
+
|
|
4271
|
+
>>> from hydpy.models.hland import *
|
|
4272
|
+
>>> parameterstep()
|
|
4273
|
+
>>> nmbzones(2)
|
|
4274
|
+
>>> factors.tc = 2.0, 4.0
|
|
4275
|
+
>>> from hydpy import round_
|
|
4276
|
+
>>> round_(model.get_temperature_v1(0))
|
|
4277
|
+
2.0
|
|
4278
|
+
>>> round_(model.get_temperature_v1(1))
|
|
4279
|
+
4.0
|
|
4280
|
+
"""
|
|
4281
|
+
|
|
4282
|
+
REQUIREDSEQUENCES = (hland_factors.TC,)
|
|
4283
|
+
|
|
4284
|
+
@staticmethod
|
|
4285
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
4286
|
+
fac = model.sequences.factors.fastaccess
|
|
4287
|
+
|
|
4288
|
+
return fac.tc[s]
|
|
4289
|
+
|
|
4290
|
+
|
|
4291
|
+
class Get_MeanTemperature_V1(modeltools.Method):
|
|
4292
|
+
"""Get the basin's current mean temperature.
|
|
4293
|
+
|
|
4294
|
+
Example:
|
|
4295
|
+
|
|
4296
|
+
>>> from hydpy.models.hland import *
|
|
4297
|
+
>>> parameterstep()
|
|
4298
|
+
>>> inputs.t = 2.0
|
|
4299
|
+
>>> from hydpy import round_
|
|
4300
|
+
>>> round_(model.get_meantemperature_v1())
|
|
4301
|
+
2.0
|
|
4302
|
+
"""
|
|
4303
|
+
|
|
4304
|
+
REQUIREDSEQUENCES = (hland_inputs.T,)
|
|
4305
|
+
|
|
4306
|
+
@staticmethod
|
|
4307
|
+
def __call__(model: modeltools.Model) -> float:
|
|
4308
|
+
inp = model.sequences.inputs.fastaccess
|
|
4309
|
+
|
|
4310
|
+
return inp.t
|
|
4311
|
+
|
|
4312
|
+
|
|
4313
|
+
class Get_Precipitation_V1(modeltools.Method):
|
|
4314
|
+
"""Get the current precipitation from the selected zone.
|
|
4315
|
+
|
|
4316
|
+
Example:
|
|
4317
|
+
|
|
4318
|
+
>>> from hydpy.models.hland import *
|
|
4319
|
+
>>> parameterstep()
|
|
4320
|
+
>>> nmbzones(2)
|
|
4321
|
+
>>> fluxes.pc = 2.0, 4.0
|
|
4322
|
+
>>> from hydpy import round_
|
|
4323
|
+
>>> round_(model.get_precipitation_v1(0))
|
|
4324
|
+
2.0
|
|
4325
|
+
>>> round_(model.get_precipitation_v1(1))
|
|
4326
|
+
4.0
|
|
4327
|
+
"""
|
|
4328
|
+
|
|
4329
|
+
REQUIREDSEQUENCES = (hland_fluxes.PC,)
|
|
4330
|
+
|
|
4331
|
+
@staticmethod
|
|
4332
|
+
def __call__(model: modeltools.Model, s: int) -> float:
|
|
4333
|
+
flu = model.sequences.fluxes.fastaccess
|
|
4334
|
+
|
|
4335
|
+
return flu.pc[s]
|
|
4336
|
+
|
|
4337
|
+
|
|
4338
|
+
class Get_InterceptedWater_V1(modeltools.Method):
|
|
4339
|
+
"""Get the selected zone's current amount of intercepted water.
|
|
4340
|
+
|
|
4341
|
+
Example:
|
|
4342
|
+
|
|
4343
|
+
>>> from hydpy.models.hland import *
|
|
4344
|
+
>>> parameterstep()
|
|
4345
|
+
>>> nmbzones(2)
|
|
4346
|
+
>>> states.ic = 2.0, 4.0
|
|
4347
|
+
>>> from hydpy import round_
|
|
4348
|
+
>>> round_(model.get_interceptedwater_v1(0))
|
|
4349
|
+
2.0
|
|
4350
|
+
>>> round_(model.get_interceptedwater_v1(1))
|
|
4351
|
+
4.0
|
|
4352
|
+
"""
|
|
4353
|
+
|
|
4354
|
+
REQUIREDSEQUENCES = (hland_states.Ic,)
|
|
4355
|
+
|
|
4356
|
+
@staticmethod
|
|
4357
|
+
def __call__(model: modeltools.Model, k: int) -> float:
|
|
4358
|
+
sta = model.sequences.states.fastaccess
|
|
4359
|
+
|
|
4360
|
+
return sta.ic[k]
|
|
4361
|
+
|
|
4362
|
+
|
|
4363
|
+
class Get_SoilWater_V1(modeltools.Method):
|
|
4364
|
+
"""Get the selected zone's current soil water content.
|
|
4365
|
+
|
|
4366
|
+
Example:
|
|
4367
|
+
|
|
4368
|
+
>>> from hydpy.models.hland import *
|
|
4369
|
+
>>> parameterstep()
|
|
4370
|
+
>>> nmbzones(2)
|
|
4371
|
+
>>> states.sm = 2.0, 4.0
|
|
4372
|
+
>>> from hydpy import round_
|
|
4373
|
+
>>> round_(model.get_soilwater_v1(0))
|
|
4374
|
+
2.0
|
|
4375
|
+
>>> round_(model.get_soilwater_v1(1))
|
|
4376
|
+
4.0
|
|
4377
|
+
"""
|
|
4378
|
+
|
|
4379
|
+
REQUIREDSEQUENCES = (hland_states.SM,)
|
|
4380
|
+
|
|
4381
|
+
@staticmethod
|
|
4382
|
+
def __call__(model: modeltools.Model, k: int) -> float:
|
|
4383
|
+
sta = model.sequences.states.fastaccess
|
|
4384
|
+
|
|
4385
|
+
return sta.sm[k]
|
|
4386
|
+
|
|
4387
|
+
|
|
4388
|
+
class Get_SnowCover_V1(modeltools.Method):
|
|
4389
|
+
"""Get the selected zone's current snow cover degree.
|
|
4390
|
+
|
|
4391
|
+
Example:
|
|
4392
|
+
|
|
4393
|
+
Each snow class with a non-zero amount of snow counts as completely covered:
|
|
4394
|
+
|
|
4395
|
+
>>> from hydpy.models.hland import *
|
|
4396
|
+
>>> parameterstep()
|
|
4397
|
+
>>> nmbzones(3)
|
|
4398
|
+
>>> sclass(2)
|
|
4399
|
+
>>> states.sp = [[0.0, 0.0, 1.0], [0.0, 1.0, 1.0]]
|
|
4400
|
+
>>> from hydpy import round_
|
|
4401
|
+
>>> round_(model.get_snowcover_v1(0))
|
|
4402
|
+
0.0
|
|
4403
|
+
>>> round_(model.get_snowcover_v1(1))
|
|
4404
|
+
0.5
|
|
4405
|
+
>>> round_(model.get_snowcover_v1(2))
|
|
4406
|
+
1.0
|
|
4407
|
+
"""
|
|
4408
|
+
|
|
4409
|
+
CONTROLPARAMETERS = (hland_control.SClass,)
|
|
4410
|
+
REQUIREDSEQUENCES = (hland_states.SP,)
|
|
4411
|
+
|
|
4412
|
+
@staticmethod
|
|
4413
|
+
def __call__(model: modeltools.Model, k: int) -> float:
|
|
4414
|
+
con = model.parameters.control.fastaccess
|
|
4415
|
+
sta = model.sequences.states.fastaccess
|
|
4416
|
+
|
|
4417
|
+
snowcovered: float = 0.0
|
|
4418
|
+
for c in range(con.sclass):
|
|
4419
|
+
snowcovered += sta.sp[c, k] > 0.0
|
|
4420
|
+
return snowcovered / con.sclass
|
|
4421
|
+
|
|
4422
|
+
|
|
4423
|
+
class Model(modeltools.AdHocModel):
|
|
4424
|
+
"""|hland.DOCNAME.complete|."""
|
|
4425
|
+
|
|
4426
|
+
DOCNAME = modeltools.DocName(short="H")
|
|
4427
|
+
__HYDPY_ROOTMODEL__ = None
|
|
4428
|
+
|
|
4429
|
+
INLET_METHODS = ()
|
|
4430
|
+
RECEIVER_METHODS = ()
|
|
4431
|
+
RUN_METHODS = (
|
|
4432
|
+
Calc_TC_V1,
|
|
4433
|
+
Calc_FracRain_V1,
|
|
4434
|
+
Calc_RFC_SFC_V1,
|
|
4435
|
+
Calc_PC_V1,
|
|
4436
|
+
Calc_TF_Ic_V1,
|
|
4437
|
+
Calc_EI_Ic_V1,
|
|
4438
|
+
Calc_SP_WC_V1,
|
|
4439
|
+
Calc_SPL_WCL_SP_WC_V1,
|
|
4440
|
+
Calc_SPG_WCG_SP_WC_V1,
|
|
4441
|
+
Calc_CFAct_V1,
|
|
4442
|
+
Calc_Melt_SP_WC_V1,
|
|
4443
|
+
Calc_Refr_SP_WC_V1,
|
|
4444
|
+
Calc_In_WC_V1,
|
|
4445
|
+
Calc_SWE_V1,
|
|
4446
|
+
Calc_SR_V1,
|
|
4447
|
+
Calc_GAct_V1,
|
|
4448
|
+
Calc_GlMelt_In_V1,
|
|
4449
|
+
Calc_R_SM_V1,
|
|
4450
|
+
Calc_CF_SM_V1,
|
|
4451
|
+
Calc_EA_SM_V1,
|
|
4452
|
+
Calc_InUZ_V1,
|
|
4453
|
+
Calc_SUZ_V1,
|
|
4454
|
+
Calc_ContriArea_V1,
|
|
4455
|
+
Calc_Q0_Perc_UZ_V1,
|
|
4456
|
+
Calc_DP_SUZ_V1,
|
|
4457
|
+
Calc_QAb1_QVs1_BW1_V1,
|
|
4458
|
+
Calc_QAb2_QVs2_BW2_V1,
|
|
4459
|
+
Calc_RS_RI_SUZ_V1,
|
|
4460
|
+
Calc_LZ_V1,
|
|
4461
|
+
Calc_LZ_V2,
|
|
4462
|
+
Calc_GR1_V1,
|
|
4463
|
+
Calc_RG1_SG1_V1,
|
|
4464
|
+
Calc_GR2_GR3_V1,
|
|
4465
|
+
Calc_RG2_SG2_V1,
|
|
4466
|
+
Calc_RG3_SG3_V1,
|
|
4467
|
+
Calc_EL_SG2_SG3_V1,
|
|
4468
|
+
Calc_EL_LZ_V1,
|
|
4469
|
+
Calc_Q1_LZ_V1,
|
|
4470
|
+
Calc_InRC_V1,
|
|
4471
|
+
Calc_InRC_V3,
|
|
4472
|
+
Calc_OutRC_V1,
|
|
4473
|
+
Calc_InRC_V2,
|
|
4474
|
+
Calc_RT_V1,
|
|
4475
|
+
Calc_RT_V2,
|
|
4476
|
+
Calc_QT_V1,
|
|
4477
|
+
)
|
|
4478
|
+
INTERFACE_METHODS = (
|
|
4479
|
+
Get_Temperature_V1,
|
|
4480
|
+
Get_MeanTemperature_V1,
|
|
4481
|
+
Get_Precipitation_V1,
|
|
4482
|
+
Get_InterceptedWater_V1,
|
|
4483
|
+
Get_SoilWater_V1,
|
|
4484
|
+
Get_SnowCover_V1,
|
|
4485
|
+
)
|
|
4486
|
+
ADD_METHODS = (
|
|
4487
|
+
Calc_EI_Ic_AETModel_V1,
|
|
4488
|
+
Calc_EA_SM_AETModel_V1,
|
|
4489
|
+
Calc_EL_LZ_AETModel_V1,
|
|
4490
|
+
Calc_EL_SG2_SG3_AETModel_V1,
|
|
4491
|
+
Calc_QAb_QVs_BW_V1,
|
|
4492
|
+
Calc_OutRC_RConcModel_V1,
|
|
4493
|
+
)
|
|
4494
|
+
OUTLET_METHODS = (Pass_Q_V1,)
|
|
4495
|
+
SENDER_METHODS = ()
|
|
4496
|
+
SUBMODELINTERFACES = (aetinterfaces.AETModel_V1, rconcinterfaces.RConcModel_V1)
|
|
4497
|
+
SUBMODELS = ()
|
|
4498
|
+
|
|
4499
|
+
aetmodel = modeltools.SubmodelProperty(aetinterfaces.AETModel_V1)
|
|
4500
|
+
aetmodel_is_mainmodel = modeltools.SubmodelIsMainmodelProperty()
|
|
4501
|
+
aetmodel_typeid = modeltools.SubmodelTypeIDProperty()
|
|
4502
|
+
|
|
4503
|
+
rconcmodel = modeltools.SubmodelProperty(rconcinterfaces.RConcModel_V1)
|
|
4504
|
+
rconcmodel_is_mainmodel = modeltools.SubmodelIsMainmodelProperty()
|
|
4505
|
+
rconcmodel_typeid = modeltools.SubmodelTypeIDProperty()
|
|
4506
|
+
|
|
4507
|
+
|
|
4508
|
+
class Main_AETModel_V1(modeltools.AdHocModel):
|
|
4509
|
+
"""Base class for |hland.DOCNAME.long| models that use submodels that comply with
|
|
4510
|
+
the |AETModel_V1| interface."""
|
|
4511
|
+
|
|
4512
|
+
aetmodel: modeltools.SubmodelProperty
|
|
4513
|
+
aetmodel_is_mainmodel = modeltools.SubmodelIsMainmodelProperty()
|
|
4514
|
+
aetmodel_typeid = modeltools.SubmodelTypeIDProperty()
|
|
4515
|
+
|
|
4516
|
+
@importtools.prepare_submodel(
|
|
4517
|
+
"aetmodel",
|
|
4518
|
+
aetinterfaces.AETModel_V1,
|
|
4519
|
+
aetinterfaces.AETModel_V1.prepare_nmbzones,
|
|
4520
|
+
aetinterfaces.AETModel_V1.prepare_subareas,
|
|
4521
|
+
aetinterfaces.AETModel_V1.prepare_elevations,
|
|
4522
|
+
aetinterfaces.AETModel_V1.prepare_maxsoilwater,
|
|
4523
|
+
aetinterfaces.AETModel_V1.prepare_water,
|
|
4524
|
+
aetinterfaces.AETModel_V1.prepare_interception,
|
|
4525
|
+
aetinterfaces.AETModel_V1.prepare_soil,
|
|
4526
|
+
aetinterfaces.AETModel_V1.prepare_plant,
|
|
4527
|
+
landtype_constants=hland_constants.CONSTANTS,
|
|
4528
|
+
landtype_refindices=hland_control.ZoneType,
|
|
4529
|
+
refweights=hland_control.ZoneArea,
|
|
4530
|
+
)
|
|
4531
|
+
def add_aetmodel_v1(
|
|
4532
|
+
self,
|
|
4533
|
+
aetmodel: aetinterfaces.AETModel_V1,
|
|
4534
|
+
/,
|
|
4535
|
+
*,
|
|
4536
|
+
refresh: bool, # pylint: disable=unused-argument
|
|
4537
|
+
) -> None:
|
|
4538
|
+
"""Initialise the given submodel that follows the |AETModel_V1| interface and
|
|
4539
|
+
is responsible for calculating the different kinds of actual
|
|
4540
|
+
evapotranspiration.
|
|
4541
|
+
|
|
4542
|
+
>>> from hydpy.models.hland_96 import *
|
|
4543
|
+
>>> parameterstep()
|
|
4544
|
+
>>> nmbzones(5)
|
|
4545
|
+
>>> area(10.0)
|
|
4546
|
+
>>> zonetype(FIELD, FOREST, ILAKE, GLACIER, SEALED)
|
|
4547
|
+
>>> zonearea(2.0)
|
|
4548
|
+
>>> zonez(3.0)
|
|
4549
|
+
>>> fc(200.0)
|
|
4550
|
+
>>> with model.add_aetmodel_v1("evap_aet_hbv96"):
|
|
4551
|
+
... nmbhru
|
|
4552
|
+
... water
|
|
4553
|
+
... interception
|
|
4554
|
+
... soil
|
|
4555
|
+
... excessreduction(field=1.0, forest=0.5, default=nan)
|
|
4556
|
+
... for method, arguments in model.preparemethod2arguments.items():
|
|
4557
|
+
... print(method, arguments[0][0], sep=": ")
|
|
4558
|
+
nmbhru(5)
|
|
4559
|
+
water(field=False, forest=False, glacier=False, ilake=True,
|
|
4560
|
+
sealed=False)
|
|
4561
|
+
interception(field=True, forest=True, glacier=False, ilake=False,
|
|
4562
|
+
sealed=True)
|
|
4563
|
+
soil(field=True, forest=True, glacier=False, ilake=False, sealed=False)
|
|
4564
|
+
prepare_nmbzones: 5
|
|
4565
|
+
prepare_zonetypes: [1 2 4 3 5]
|
|
4566
|
+
prepare_subareas: [2. 2. 2. 2. 2.]
|
|
4567
|
+
prepare_elevations: [300. 300. 300. 300. 300.]
|
|
4568
|
+
prepare_maxsoilwater: [200. 200. 200. 200. 200.]
|
|
4569
|
+
prepare_water: [False False True False False]
|
|
4570
|
+
prepare_interception: [ True True False False True]
|
|
4571
|
+
prepare_plant: [ True True False False False]
|
|
4572
|
+
prepare_soil: [ True True False False False]
|
|
4573
|
+
|
|
4574
|
+
>>> ered = model.aetmodel.parameters.control.excessreduction
|
|
4575
|
+
>>> ered
|
|
4576
|
+
excessreduction(field=1.0, forest=0.5)
|
|
4577
|
+
>>> zonetype(FOREST, FIELD, ILAKE, GLACIER, SEALED)
|
|
4578
|
+
>>> ered
|
|
4579
|
+
excessreduction(field=0.5, forest=1.0)
|
|
4580
|
+
>>> from hydpy import round_
|
|
4581
|
+
>>> round_(ered.average_values())
|
|
4582
|
+
0.75
|
|
4583
|
+
"""
|
|
4584
|
+
control = self.parameters.control
|
|
4585
|
+
nmbzones = control.nmbzones.value
|
|
4586
|
+
zonetype = control.zonetype.values
|
|
4587
|
+
|
|
4588
|
+
aetmodel.prepare_nmbzones(nmbzones)
|
|
4589
|
+
aetmodel.prepare_zonetypes(zonetype)
|
|
4590
|
+
aetmodel.prepare_subareas(control.zonearea.value)
|
|
4591
|
+
aetmodel.prepare_elevations(100.0 * control.zonez.values)
|
|
4592
|
+
aetmodel.prepare_maxsoilwater(control.fc.values)
|
|
4593
|
+
sel = numpy.full(nmbzones, False, dtype=config.NP_BOOL)
|
|
4594
|
+
sel[zonetype == ILAKE] = True
|
|
4595
|
+
aetmodel.prepare_water(sel)
|
|
4596
|
+
sel = ~sel
|
|
4597
|
+
sel[zonetype == GLACIER] = False
|
|
4598
|
+
aetmodel.prepare_interception(sel)
|
|
4599
|
+
sel[zonetype == SEALED] = False
|
|
4600
|
+
aetmodel.prepare_plant(sel)
|
|
4601
|
+
aetmodel.prepare_soil(sel)
|
|
4602
|
+
|
|
4603
|
+
|
|
4604
|
+
class Main_RConcModel_V1(modeltools.AdHocModel):
|
|
4605
|
+
"""Base class for |hland.DOCNAME.long| models that use submodels that comply with
|
|
4606
|
+
the |RConcModel_V1| interface."""
|
|
4607
|
+
|
|
4608
|
+
rconcmodel: modeltools.SubmodelProperty
|
|
4609
|
+
rconcmodel_is_mainmodel = modeltools.SubmodelIsMainmodelProperty()
|
|
4610
|
+
rconcmodel_typeid = modeltools.SubmodelTypeIDProperty()
|
|
4611
|
+
|
|
4612
|
+
@importtools.prepare_submodel("rconcmodel", rconcinterfaces.RConcModel_V1)
|
|
4613
|
+
def add_rconcmodel_v1(
|
|
4614
|
+
self, rconcmodel: rconcinterfaces.RConcModel_V1, /, *, refresh: bool
|
|
4615
|
+
) -> None:
|
|
4616
|
+
"""Initialise the given submodel that follows the |RConcModel_V1| interface and
|
|
4617
|
+
is responsible for calculating the runoff concentration.
|
|
4618
|
+
|
|
4619
|
+
>>> from hydpy.models.hland_96 import *
|
|
4620
|
+
>>> simulationstep("12h")
|
|
4621
|
+
>>> parameterstep("1d")
|
|
4622
|
+
>>> with model.add_rconcmodel_v1("rconc_uh"):
|
|
4623
|
+
... uh([0.3, 0.5, 0.2])
|
|
4624
|
+
... logs.quh.shape = 3
|
|
4625
|
+
... logs.quh = 1.0, 3.0, 0.0
|
|
4626
|
+
>>> model.sequences.fluxes.inrc = 0.0
|
|
4627
|
+
>>> model.calc_outrc_v1()
|
|
4628
|
+
>>> fluxes.outrc
|
|
4629
|
+
outrc(1.0)
|
|
4630
|
+
"""
|
|
4631
|
+
|
|
4632
|
+
def _get_rconcmodel_waterbalance(
|
|
4633
|
+
self, initial_conditions: ConditionsModel
|
|
4634
|
+
) -> float:
|
|
4635
|
+
r"""Get the water balance of the rconc submodel if used."""
|
|
4636
|
+
if self.rconcmodel:
|
|
4637
|
+
rconcmodel_conditions = initial_conditions["model.rconcmodel"]
|
|
4638
|
+
return self.rconcmodel.get_waterbalance(rconcmodel_conditions)
|
|
4639
|
+
return 0.0
|
|
4640
|
+
|
|
4641
|
+
|
|
4642
|
+
class Sub_TempModel_V1(modeltools.AdHocModel, tempinterfaces.TempModel_V1):
|
|
4643
|
+
"""Base class for |hland.DOCNAME.long| models that comply with the |TempModel_V1|
|
|
4644
|
+
submodel interface."""
|
|
4645
|
+
|
|
4646
|
+
|
|
4647
|
+
class Sub_PrecipModel_V1(modeltools.AdHocModel, precipinterfaces.PrecipModel_V1):
|
|
4648
|
+
"""Base class for |hland.DOCNAME.long| models that comply with the |PrecipModel_V1|
|
|
4649
|
+
submodel interface."""
|
|
4650
|
+
|
|
4651
|
+
|
|
4652
|
+
class Sub_IntercModel_V1(modeltools.AdHocModel, stateinterfaces.IntercModel_V1):
|
|
4653
|
+
"""Base class for |hland.DOCNAME.long| models that comply with the |IntercModel_V1|
|
|
4654
|
+
submodel interface."""
|
|
4655
|
+
|
|
4656
|
+
|
|
4657
|
+
class Sub_SoilWaterModel_V1(modeltools.AdHocModel, stateinterfaces.SoilWaterModel_V1):
|
|
4658
|
+
"""Base class for |hland.DOCNAME.long| models that comply with the
|
|
4659
|
+
|SoilWaterModel_V1| submodel interface."""
|
|
4660
|
+
|
|
4661
|
+
|
|
4662
|
+
class Sub_SnowCoverModel_V1(modeltools.AdHocModel, stateinterfaces.SnowCoverModel_V1):
|
|
4663
|
+
"""Base class for |hland.DOCNAME.long| models that comply with the
|
|
4664
|
+
|SnowCoverModel_V1| submodel interface."""
|