diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7ecd4727..9006962d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -12,3 +12,4 @@ | DanCopsey | Dan Copsey | Met Office | 2026-08-24 | | Pierre-siddall | Pierre Siddall | Met Office | 2026-08-26 | | mo-arthurargles | Arthur Argles | Met Office | 2026-09-04 | +| HEBaron | Helen Baron | UKCEH | 2026-08-26 | diff --git a/doc/source/namelists/ancillaries.nml.rst b/doc/source/namelists/ancillaries.nml.rst index e03d06b7..9aaeb223 100644 --- a/doc/source/namelists/ancillaries.nml.rst +++ b/doc/source/namelists/ancillaries.nml.rst @@ -1093,7 +1093,7 @@ This namelist specifies the options available for initialising irrigated fractio .. nml:namelist:: JULES_RIVERS_PROPS -This namelist specifies how spatially varying river routing properties (including overbank inundation and minor reservoirs) should be set. +This namelist specifies how spatially varying river routing properties (including overbank inundation, reservoirs and minor reservoirs) should be set. .. note:: ``read_from_dump`` is not currently implemented for this namelist, meaning that river ancillary variables cannot be read from a dump file. Initial values of river prognostic variables can however be read from a dump file (see :nml:lst:`JULES_INITIAL`). @@ -1467,16 +1467,6 @@ The following table summarises river routing properties required to run RFM or T | | This is only used if :nml:mem:`JULES_OVERBANK::overbank_model` = 3. | | | | +----------------------------+-----------------------------------------------------------------------------------------------------------+ -| ``minor_res_capacity_grid``| Storage capacity of minor reservoirs (kg). | -| | | -| | This is only used if :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | -| | | -+----------------------------+-----------------------------------------------------------------------------------------------------------+ -| ``minor_res_frac_grid`` | Catchment area of minor reservoirs as fraction of area of gridbox. | -| | | -| | This is only used if :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | -| | | -+----------------------------+-----------------------------------------------------------------------------------------------------------+ | ``rivers_outflow_number`` | Number assigned to each river mouth and inland basin on the Rivers grid, to identify the river which | | | discharges into it. | | | | @@ -1497,6 +1487,56 @@ The following table summarises river routing properties required to run RFM or T | | climatology, rather than the dump. If Rivers storage is requested from an ancillary then | | | ``rivers_sto_rp`` should not be requested via :nml:lst:`JULES_INITIAL`. | +----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``minor_res_capacity_grid``| Storage capacity of minor reservoirs (kg). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``minor_res_frac_grid`` | Catchment area of minor reservoirs as fraction of area of gridbox. | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_capacity_grid`` | Storage capacity of reservoirs (kg). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_catch_grid`` | Catchment area of reservoirs (m\ :sup:`2`). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_year_grid`` | Initialisation year of reservoirs. | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_critical_grid`` | Critical storage of reservoirs (kg). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_flood_grid`` | Flood storage of reservoirs (kg). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_emergency_grid`` | Emergency storage of reservoirs (kg). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_normal_release_grid``| Normal release rate of reservoirs (kg s\ :sup:`-1`). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ +| ``res_flood_release_grid`` | Flood release rate of reservoirs (kg s\ :sup:`-1`). | +| | | +| | This is only used if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | +| | | ++----------------------------+-----------------------------------------------------------------------------------------------------------+ Example of how to set up the river grid diff --git a/doc/source/namelists/initial_conditions.nml.rst b/doc/source/namelists/initial_conditions.nml.rst index 0a88ac26..cb60e606 100644 --- a/doc/source/namelists/initial_conditions.nml.rst +++ b/doc/source/namelists/initial_conditions.nml.rst @@ -430,6 +430,11 @@ The required variables for a particular configuration, along with their 'type' a +----------------------------------+-----------------------------------------------------------------------------------------+---------+ | ``inland_outflow_rp`` | Inland basin flow on river routing points (kg m\ :sup:`-2` s\ :sup:`-1`). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ +| Required if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE and | +| :nml:mem:`JULES_INITIAL::dump_file` = TRUE | ++----------------------------------+-----------------------------------------------------------------------------------------+---------+ +| ``res_storage`` | Water stored in reservoirs, on river routing points (kg). | none | ++----------------------------------+-----------------------------------------------------------------------------------------+---------+ | Required if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE and | | :nml:mem:`JULES_INITIAL::dump_file` = TRUE | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ @@ -440,7 +445,6 @@ The required variables for a particular configuration, along with their 'type' a | ``t_growth_gb`` | Running mean air temperature (K). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ - .. warning:: if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::i_river_vn` = '2' and :nml:mem:`JULES_INITIAL::dump_file` = FALSE, ``rfm_surfstore_rp``, ``rfm_substore_rp``, ``rfm_flowin_rp`` and ``rfm_bflowin`` are initialised to zero. @@ -449,6 +453,10 @@ The required variables for a particular configuration, along with their 'type' a if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::i_river_vn` = '1,3' and :nml:mem:`JULES_INITIAL::dump_file` = FALSE, ``rivers_sto_rp`` is initialised to zero **unless** it is initialised from an ancillary via :nml:lst:`JULES_RIVERS_PROPS`. +.. warning:: + if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE and :nml:mem:`JULES_INITIAL::dump_file` = FALSE, + ``res_storage`` is initialised to zero. + .. warning:: if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE and :nml:mem:`JULES_INITIAL::dump_file` = FALSE, ``minor_res_storage`` is initialised to zero. diff --git a/doc/source/namelists/jules_rivers.nml.rst b/doc/source/namelists/jules_rivers.nml.rst index 19ecfb31..2f7e7403 100644 --- a/doc/source/namelists/jules_rivers.nml.rst +++ b/doc/source/namelists/jules_rivers.nml.rst @@ -44,6 +44,18 @@ River routing introduces two more grids to a JULES run: the river routing input ``3`` Use a standalone JULES implementation of the TRIP model (see Oki et al. 1999). +.. nml:member:: l_reservoirs + + :type: logical + :default: F + + Switch for enabling routing through reservoirs. Only used if :nml:mem:`JULES_RIVERS::l_rivers` is TRUE. + + TRUE + River flow is routed through reservoirs. + + FALSE + No reservoirs are modelled. .. nml:member:: l_minor_reservoirs @@ -58,7 +70,6 @@ River routing introduces two more grids to a JULES run: the river routing input FALSE No minor reservoirs are modelled. - .. nml:member:: l_riv_overbank :type: logical diff --git a/doc/source/output-variables.rst b/doc/source/output-variables.rst index 4dd6c6cc..8c4a3aff 100644 --- a/doc/source/output-variables.rst +++ b/doc/source/output-variables.rst @@ -490,6 +490,42 @@ Rivers | ``frac_fplain_rp`` | Overbank inundation area as a fraction of river routing gridcell area. | np_rivers | | | Only available if :nml:mem:`JULES_RIVERS::l_riv_overbank` = TRUE. | | +-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_capacity`` | Storage capacity of reservoirs (kg). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_catch`` | Catchment area of reservoirs (m\ :sup:`2`). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_year`` | Initialisation year of reservoirs. | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_critical`` | Critical storage of reservoirs (kg). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_flood`` | Flood storage of reservoirs (kg). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_emergency`` | Emergency storage of reservoirs (kg). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_normal_release`` | Normal release rate of reservoirs (kg s\ :sup:`-1`). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_flood_release`` | Flood release rate of reservoirs (kg s\ :sup:`-1`). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``res_storage`` | Water stored in reservoirs (kg). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ | Output regridded to the JULES model grid | +-------------------------------+-----------------------------------------------------------------------------------------------+------------+ | ``rflow`` | Gridbox river flow rate (kg m\ :sup:`-2` s\ :sup:`-1`). | | @@ -1396,6 +1432,9 @@ These variables are only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_r | ``gw_nr_abstracted`` | Water abstracted from non-renewable groundwater sources (kg s\ :sup:`-1`). | | | | Only available if a suitable groundwater model is used. | | +---------------------------+--------------------------------------------------------------------------------+------------+ +| ``res_abstracted`` | Water abstracted from reservoirs (kg s\ :sup:`-1`). | | +| | Only available if :nml:mem:`JULES_RIVERS::l_reservoirs` = TRUE. | | ++---------------------------+--------------------------------------------------------------------------------+------------+ | ``minor_res_abstracted`` | Water abstracted from minor reservoirs (kg s\ :sup:`-1`). | | | | Only available if :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | | +---------------------------+--------------------------------------------------------------------------------+------------+ diff --git a/etc/fcm-make/make-river.cfg b/etc/fcm-make/make-river.cfg index d7ee7f3e..52a750bc 100644 --- a/etc/fcm-make/make-river.cfg +++ b/etc/fcm-make/make-river.cfg @@ -60,6 +60,7 @@ extract.path-incl[river] = $extract_path_incl \ src/control/shared/p_s_parms.F90 \ src/control/shared/prognostics.F90 \ src/control/shared/surf_couple_rivers_mod.F90 \ + src/control/shared/time_info_mod.F90 \ src/control/shared/water_resources_vars_mod.F90 \ src/control/shared/jules_water_tracers_mod.F90 \ src/control/standalone/next_time_mod.F90 \ diff --git a/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf index 043d2552..87c1b429 100644 --- a/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf @@ -27,6 +27,7 @@ trigger=namelist:jules_deposition=l_deposition_from_ukca: 1; =namelist:jules_radiation=l_cosz: 0; =namelist:jules_radiation=l_dolr_land_black: 1; =namelist:jules_radiation=l_sea_alb_var_chl: 1; + =namelist:jules_rivers=l_reservoirs: 0; =namelist:jules_rivers=l_minor_reservoirs: 0; =namelist:jules_rivers=l_riv_overbank: 0; =namelist:jules_rivers=trip_globe_shape: 1; diff --git a/rose-meta/jules-shared/jules-rivers/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-rivers/HEAD/rose-meta.conf index 47831d9c..a8432d9c 100644 --- a/rose-meta/jules-shared/jules-rivers/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-rivers/HEAD/rose-meta.conf @@ -70,6 +70,14 @@ value-titles=RFM,TRIP values=2,3 widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget +[namelist:jules_rivers=l_reservoirs] +compulsory=true +description=Switch to activate reservoirs +fail-if=this == '.true.' and namelist:jules_model_environment=l_jules_parent != 0; # only available in standalone mode +sort-key=a8 +type=logical +url=https://metoffice.github.io/jules/latest/namelists/jules_rivers.nml.html#JULES_RIVERS::l_reservoirs + [namelist:jules_rivers=l_minor_reservoirs] compulsory=true description=Switch to activate minor reservoirs @@ -93,7 +101,8 @@ description=Enable river routing sort-key=a trigger=namelist:jules_rivers=i_river_vn: .true.; = namelist:jules_rivers=nstep_rivers: .true.; - = namelist:jules_rivers=l_minor_reservoirs: .true.; + = namelist:jules_rivers=l_reservoirs: .true.; + = namelist:jules_rivers=l_minor_reservoirs: .true.; = namelist:jules_rivers=l_riv_overbank: .true.; = namelist:jules_overbank: .true.; = namelist:jules_rivers_props: .true.; diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index 49df21e8..98a8b7e0 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -2148,13 +2148,13 @@ sort-key=06 url=https://metoffice.github.io/jules/latest/namelists/initial_conditions.nml.html#JULES_INITIAL::var values='canht','canopy','cropcanht','cropdvi','cropharvc','croplai', ='cropreservec','croprootc','cs','frac','frac_agr_prev','frac_past_prev', - ='frac_biocrop_prev','gs','lai','minor_res_storage','n_inorg','nsnow','ns','rfm_bflowin_rp', - ='rfm_flowin_rp','rfm_substore_rp','rfm_surfstore_rp','rgrain','rgrainl', - ='rho_snow','rivers_sto_rp','rivers_outflow_rp','snow_depth','snow_ds', - ='snow_grnd','snow_ice','snow_liq','snow_tile','sthu_irr','sthuf', - ='sthzw','t_growth_gb','t_soil','tsnow','tstar_tile','tsoil_deep', - ='wood_prod_fast','wood_prod_med','wood_prod_slow','years_since_harvest', - ='zw','inland_outflow_rp' + ='frac_biocrop_prev','gs','lai','minor_res_storage','n_inorg','nsnow','ns', + ='res_storage','rfm_bflowin_rp','rfm_flowin_rp','rfm_substore_rp','rfm_surfstore_rp', + ='rgrain','rgrainl','rho_snow','rivers_sto_rp','rivers_outflow_rp', + ='snow_depth','snow_ds','snow_grnd','snow_ice','snow_liq','snow_tile', + ='sthu_irr','sthuf','sthzw','t_growth_gb','t_soil','tsnow','tstar_tile', + ='tsoil_deep','wood_prod_fast','wood_prod_med','wood_prod_slow', + ='years_since_harvest','zw','inland_outflow_rp' [namelist:jules_initial=var_name] compulsory=true diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 0bb9609e..a82e36ab 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -214,3 +214,18 @@ def upgrade(self,config, meta_config=None): # Add settings self.add_setting(config, ["namelist:jules_rivers", "l_minor_reservoirs"], ".false.") return config, self.reports + + +class vn82_t148(MacroUpgrade): + + """Upgrade macro from JULES by Helen Baron""" + + BEFORE_TAG = "vn8.2_t32" + AFTER_TAG = "vn8.2_t148" + + def upgrade(self, config, meta_config=None): + """Upgrade a JULES runtime app configuration.""" + + # Add settings + self.add_setting(config, ["namelist:jules_rivers", "l_reservoirs"], ".false.") + return config, self.reports diff --git a/src/control/rivers-standalone/rivers_control_mod.F90 b/src/control/rivers-standalone/rivers_control_mod.F90 index 6ce9cc04..39fe10bc 100644 --- a/src/control/rivers-standalone/rivers_control_mod.F90 +++ b/src/control/rivers-standalone/rivers_control_mod.F90 @@ -121,10 +121,12 @@ SUBROUTINE rivers_control ( & flowin(row_length, rows), & bflowin(row_length, rows), & twatstor(river_row_length, river_rows), & - abstracted_minor_res_global(land_pts), & + net_abstracted_river_global(land_pts), & + ! Net abstraction from rivers (kg m-2) + abstracted_res_global(land_pts), & + ! Water abstracted from reservoirs (kg). + abstracted_minor_res_global(land_pts) ! Water abstracted from minor reservoirs (kg). - net_abstracted_river_global(land_pts) - ! Net abstraction from rivers (kg m-2) REAL(KIND=real_jlslsm) :: & !Passed between river routing and UM diagnostics_riv only @@ -140,6 +142,7 @@ SUBROUTINE rivers_control ( & !End of header ! Abstractions of water are zero in rivers-only configuration. +abstracted_res_global(:) = 0.0 abstracted_minor_res_global(:) = 0.0 net_abstracted_river_global(:) = 0.0 @@ -149,7 +152,8 @@ SUBROUTINE rivers_control ( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - abstracted_minor_res_global, net_abstracted_river_global, & + abstracted_res_global, abstracted_minor_res_global, & + net_abstracted_river_global, & fluxes%sub_surf_roff_gb, fluxes%surf_roff_gb, & wtrac_jls%sub_surf_roff_gb, wtrac_jls%surf_roff_gb, & !INTEGER, INTENT(INOUT) diff --git a/src/control/shared/jules_rivers_mod.F90 b/src/control/shared/jules_rivers_mod.F90 index be56343d..4fe61549 100644 --- a/src/control/shared/jules_rivers_mod.F90 +++ b/src/control/shared/jules_rivers_mod.F90 @@ -146,9 +146,13 @@ MODULE jules_rivers_mod ! - OASIS send field contains 'inland_outflow' ! - The diagnostic 'inland_outflow_rp' has been requested ! - UM-TRIP when l_inland = T - ,l_init_storage = .FALSE. + ,l_init_storage = .FALSE. & ! Set to true if an initial river storage ancillary file is ! used + ,l_reservoirs = .FALSE. + ! Switch for reservoirs. + ! .TRUE. = consider major reservoirs + ! .FALSE. = do not consider reservoirs INTEGER :: & nstep_rivers = imdi & @@ -242,7 +246,7 @@ MODULE jules_rivers_mod ! Single namelist definition for UM and standalone !------------------------------------------------------------------------------ NAMELIST /jules_rivers/ & - l_rivers, l_minor_reservoirs, l_riv_overbank, & + l_rivers, l_reservoirs, l_minor_reservoirs, l_riv_overbank, & l_adapt_timestep, l_sea_level, & l_vary_sea_level, i_river_vn, nstep_rivers, & trip_globe_shape, & @@ -413,6 +417,27 @@ MODULE jules_rivers_mod river_manning_grid(:,:) ! Manning roughness coefficient for river channel (1). +!------------------------------------------------------------------------------ +! Ancillary arrays for reservoirs, defined on 2D rivers grid. +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), ALLOCATABLE :: & + res_capacity_grid(:,:), & + ! Storage capacity of reservoirs (kg). + res_catch_grid(:,:), & + ! Catchment area of reservoirs (m2). + res_year_grid(:,:), & + ! Initialisation year of reservoirs. + res_critical_grid(:,:), & + ! Critical storage of reservoir (kg). + res_flood_grid(:,:), & + ! Flood storage of reservoir (kg). + res_emergency_grid(:,:), & + ! Emergency storage of reservoir (kg). + res_normal_release_grid(:,:), & + ! Normal release rate of reservoir (kg s-1). + res_flood_release_grid(:,:) + ! Flood release rate of reservoir (kg s-1). + !------------------------------------------------------------------------------ ! Ancillary arrays for minor reservoirs, defined on 2D rivers grid. !------------------------------------------------------------------------------ @@ -634,6 +659,40 @@ MODULE jules_rivers_mod ! River outflow into the ocean (kg s-1) REAL(KIND=real_jlslsm), ALLOCATABLE :: inland_outflow_rp(:) ! Inland basin flow into soil moisture (kg m-2 s-1) + + !---------------------------------------------------------------------------- + ! Reservoir ancillary variables, defined on river points. + !---------------------------------------------------------------------------- + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_capacity(:) + ! Storage capacity of reservoirs (kg). + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_catch(:) + ! Catchment area of reservoirs (m). + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_year(:) + ! Initialisation year of reservoirs. + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_critical(:) + ! Critical storage of reservoir (kg). + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_flood(:) + ! Flood storage of reservoir (kg). + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_emergency(:) + ! Emergency storage of reservoir (kg). + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_normal_release(:) + ! Normal release rate of reservoir (kg s-1). + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_flood_release(:) + ! Flood release rate of reservoir (kg s-1). + + !---------------------------------------------------------------------------- + ! Reservoir prognostic variables, defined on river points. + !---------------------------------------------------------------------------- + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_storage(:) + ! Water stored in reservoirs (kg). + REAL(KIND=real_jlslsm), ALLOCATABLE :: res_cap_current(:) + ! Capacity of currently active reservoirs (kg). + + ! Variables for coupling with water resources. + !---------------------------------------------------------------------------- + REAL, ALLOCATABLE :: tot_abstracted_res_global(:) + ! Water abstracted from reservoirs over river + ! timestep, on global land points (kg). END TYPE rivers_data_type TYPE :: rivers_type @@ -707,6 +766,17 @@ MODULE jules_rivers_mod REAL(KIND=real_jlslsm), POINTER :: rivers_boxareas_rp(:) REAL(KIND=real_jlslsm), POINTER :: rivers_outflow_rp(:) REAL(KIND=real_jlslsm), POINTER :: inland_outflow_rp(:) + REAL(KIND=real_jlslsm), POINTER :: res_capacity(:) + REAL(KIND=real_jlslsm), POINTER :: res_catch(:) + REAL(KIND=real_jlslsm), POINTER :: res_storage(:) + REAL(KIND=real_jlslsm), POINTER :: res_cap_current(:) + REAL(KIND=real_jlslsm), POINTER :: res_year(:) + REAL(KIND=real_jlslsm), POINTER :: res_critical(:) + REAL(KIND=real_jlslsm), POINTER :: res_flood(:) + REAL(KIND=real_jlslsm), POINTER :: res_emergency(:) + REAL(KIND=real_jlslsm), POINTER :: res_normal_release(:) + REAL(KIND=real_jlslsm), POINTER :: res_flood_release(:) + REAL(KIND=real_jlslsm), POINTER :: tot_abstracted_res_global(:) END TYPE rivers_type CONTAINS @@ -1217,6 +1287,7 @@ SUBROUTINE print_nlist_jules_rivers() WRITE(lineBuffer,*)' l_rivers = ',l_rivers CALL jules_print('jules_rivers',lineBuffer) +WRITE(lineBuffer,*)' l_reservoirs = ',l_reservoirs WRITE(lineBuffer,*)' l_minor_reservoirs = ',l_minor_reservoirs CALL jules_print('jules_rivers',lineBuffer) WRITE(lineBuffer,*)' l_riv_overbank = ',l_riv_overbank @@ -1382,6 +1453,7 @@ SUBROUTINE read_nml_jules_rivers(unit_in) REAL(KIND=real_jlslsm) :: rivers_speed REAL(KIND=real_jlslsm) :: runoff_factor LOGICAL :: l_adapt_timestep + LOGICAL :: l_reservoirs LOGICAL :: l_minor_reservoirs LOGICAL :: l_riv_overbank LOGICAL :: l_rivers @@ -1421,6 +1493,7 @@ SUBROUTINE read_nml_jules_rivers(unit_in) my_nml % rivers_speed = rivers_speed my_nml % runoff_factor = runoff_factor my_nml % l_adapt_timestep = l_adapt_timestep + my_nml % l_reservoirs = l_reservoirs my_nml % l_minor_reservoirs = l_minor_reservoirs my_nml % l_riv_overbank = l_riv_overbank my_nml % l_rivers = l_rivers @@ -1449,6 +1522,7 @@ SUBROUTINE read_nml_jules_rivers(unit_in) rivers_speed = my_nml % rivers_speed runoff_factor = my_nml % runoff_factor l_adapt_timestep = my_nml % l_adapt_timestep + l_reservoirs = my_nml % l_reservoirs l_minor_reservoirs = my_nml % l_minor_reservoirs l_riv_overbank = my_nml % l_riv_overbank l_rivers = my_nml % l_rivers diff --git a/src/control/shared/jules_water_resources_mod.F90 b/src/control/shared/jules_water_resources_mod.F90 index 9379a1bd..c0c60a0e 100644 --- a/src/control/shared/jules_water_resources_mod.F90 +++ b/src/control/shared/jules_water_resources_mod.F90 @@ -202,6 +202,8 @@ MODULE jules_water_resources_mod ! Index of livestock use in multi-use arrays. use_transfers = 0, & ! Index of transfers in multi-use arrays. + sw_res_source = 0, & + ! Index of reservoirs in surface water source arrays. water_res_count = 0 ! Counter of timesteps done in current water resource timestep. @@ -566,7 +568,7 @@ SUBROUTINE set_jules_water_resources( l_top ) !------------------------------------------------------------------------------ ! This dependency on jules_rivers_mod is not ideal. -USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_rivers +USE jules_rivers_mod, ONLY: l_reservoirs, l_minor_reservoirs, l_rivers IMPLICIT NONE @@ -637,6 +639,10 @@ SUBROUTINE set_jules_water_resources( l_top ) n_sw_source = n_sw_source + 1 sw_river_source = n_sw_source END IF + IF ( l_reservoirs ) THEN + n_sw_source = n_sw_source + 1 + sw_res_source = n_sw_source + END IF IF ( l_minor_reservoirs ) THEN n_sw_source = n_sw_source + 1 sw_minor_res_source = n_sw_source diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index 9ad1eca5..9e19b9c7 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -860,7 +860,7 @@ SUBROUTINE surf_couple_extra( & flandg, crop_vars%frac_irr_soilt, ainfo%frac_soilt, & ainfo%frac_surft, grid_area_ij, & forcing%ls_rain_ij, forcing%ls_snow_ij, forcing%lw_down_ij, & - rivers%minor_res_storage, & + rivers%res_storage, rivers%minor_res_storage, & rivers%rfm_surfstore_rp, rivers%rivers_sto_rp, & psparms%smvccl_soilt, & psparms%smvcst_soilt, psparms%smvcwt_soilt, psparms%sthf_soilt, & @@ -875,9 +875,11 @@ SUBROUTINE surf_couple_extra( & sthzw_soilt, fluxes%sub_surf_roff_gb, crop_vars%tl_1_day_av_gb, & crop_vars%tl_1_day_av_use_gb, & water_resources%priority_order, & + water_resources%abstracted_res_global, & water_resources%abstracted_minor_res_global, & water_resources%net_abstracted_river_global, & water_resources%gw_abstracted, crop_vars%irrig_water_gb, & + water_resources%abstracted_res, & water_resources%abstracted_minor_res, & water_resources%abstracted_river, water_resources%conveyance_loss, & water_resources%demand_unmet, water_resources%gw_avail, & @@ -891,6 +893,7 @@ SUBROUTINE surf_couple_extra( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) + water_resources%abstracted_res_global, & water_resources%abstracted_minor_res_global, & water_resources%net_abstracted_river_global, & fluxes%sub_surf_roff_gb, fluxes%surf_roff_gb, & @@ -1432,4 +1435,4 @@ SUBROUTINE surf_couple_extra( & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN END SUBROUTINE surf_couple_extra -END MODULE surf_couple_extra_mod +END MODULE surf_couple_extra_mod \ No newline at end of file diff --git a/src/control/shared/surf_couple_rivers_mod.F90 b/src/control/shared/surf_couple_rivers_mod.F90 index 9e5f3229..819a1937 100644 --- a/src/control/shared/surf_couple_rivers_mod.F90 +++ b/src/control/shared/surf_couple_rivers_mod.F90 @@ -18,12 +18,14 @@ SUBROUTINE surf_couple_rivers( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - abstracted_minor_res_global, net_abstracted_river_global, & + abstracted_res_global, abstracted_minor_res_global, & + net_abstracted_river_global, & sub_surf_roff, surf_roff, sub_surf_roff_wtrac, surf_roff_wtrac, & !INTEGER, INTENT(INOUT) a_steps_since_riv, & !REAL, INTENT (INOUT) - tot_surf_runoff_gb, tot_sub_runoff_gb, acc_lake_evap_gb, & + tot_surf_runoff_gb, tot_sub_runoff_gb, & + acc_lake_evap_gb, & tot_surf_runoff_gb_wtrac, tot_sub_runoff_gb_wtrac, & acc_lake_evap_gb_wtrac, & !REAL, INTENT (OUT) @@ -56,12 +58,14 @@ SUBROUTINE surf_couple_rivers( & USE jules_rivers_mod, ONLY: i_river_vn, nstep_rivers, & rivers_camaflood, rivers_rfm, & rivers_trip, rivers_call, np_rivers, & - rivers_type, l_minor_reservoirs, & + rivers_type, l_reservoirs, & + l_minor_reservoirs, & l_riv_overbank, & l_vary_sea_level, & ! UM only l_inland_outflow, rivers_um_trip, & - rivers_first + rivers_first, & + l_reservoirs USE jules_model_environment_mod, ONLY: l_oasis_rivers USE timestep_mod, ONLY: timestep @@ -148,6 +152,8 @@ SUBROUTINE surf_couple_rivers( & a_steps_since_riv REAL(KIND=real_jlslsm), INTENT(IN) :: & + abstracted_res_global(global_land_pts), & + ! Water abstracted from reservoirs (kg). abstracted_minor_res_global(global_land_pts), & ! Water abstracted from minor reservoirs (kg). net_abstracted_river_global(global_land_pts), & @@ -240,6 +246,9 @@ SUBROUTINE surf_couple_rivers( & REAL(KIND=real_jlslsm), ALLOCATABLE :: global_rrun(:) REAL(KIND=real_jlslsm), ALLOCATABLE :: global_rflow(:) REAL(KIND=real_jlslsm), ALLOCATABLE :: global_sea_level(:) +REAL(KIND=real_jlslsm), ALLOCATABLE :: abstracted_res_rp(:) + ! Water abstracted from reservoirs over river timestep, on river points + ! (kg). REAL(KIND=real_jlslsm), ALLOCATABLE :: abstracted_minor_res_rp(:) ! Water abstracted from minor reservoirs over river timestep, on river points ! (kg). @@ -367,6 +376,11 @@ SUBROUTINE surf_couple_rivers( & rivers%tot_net_abstracted_river_global(:) = 0.0 END IF + ! Initialise the accumulated abstraction from reservoirs. + IF ( l_water_resources .AND. l_reservoirs ) THEN + rivers%tot_abstracted_res_global(:) = 0.0 + END IF + ! Initialise the accumulated abstraction from minor reservoirs. IF ( l_water_resources .AND. l_minor_reservoirs ) THEN rivers%tot_abstracted_minor_res_global(:) = 0.0 @@ -420,6 +434,12 @@ SUBROUTINE surf_couple_rivers( & rivers%tot_net_abstracted_river_global ) END IF + ! Accumulate abstraction from reservoirs. + IF ( l_water_resources .AND. l_reservoirs ) THEN + CALL accumulate_abstraction( global_land_pts, abstracted_res_global, & + rivers%tot_abstracted_res_global ) + END IF + ! Accumulate abstraction from minor reservoirs. IF ( l_water_resources .AND. l_minor_reservoirs ) THEN CALL accumulate_abstraction( global_land_pts, & @@ -584,6 +604,17 @@ SUBROUTINE surf_couple_rivers( & ALLOCATE(net_abstracted_river_rp(tmp_river_size), STAT = ERROR) error_sum = error_sum + ERROR + ! Allocate global abstraction from reservoirs. + IF ( .NOT. l_oasis_rivers .AND. l_reservoirs & + .AND. is_master_task() ) THEN + tmp_river_size = np_rivers + ELSE + ! Allocate at minimum size. + tmp_river_size = 1 + END IF + ALLOCATE(abstracted_res_rp(tmp_river_size), STAT = ERROR) + error_sum = error_sum + ERROR + ! Allocate abstraction from minor reservoirs. IF ( .NOT. l_oasis_rivers .AND. l_minor_reservoirs & .AND. is_master_task() ) THEN @@ -600,6 +631,10 @@ SUBROUTINE surf_couple_rivers( & CALL ereport( RoutineName, errorstatus, & "Error allocating river coupling variables." ) ELSE + ! Initialise abstraction from reservoirs to zero - this value is + ! passed to subroutine rivers_route_rp and used if l_reservoirs=T but + ! l_water_resources=F. + abstracted_res_rp(:) = 0.0 ! Initialise abstraction from minor reservoirs to zero - this value is ! passed to subroutine rivers_route_rp and used if l_minor_reservoirs=T ! but l_water_resources=F. @@ -633,8 +668,9 @@ SUBROUTINE surf_couple_rivers( & ! No regridding is required between the land and river grids as this ! is done by the OASIS coupler. Only the science routine needs calling. - CALL rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & - net_abstracted_river_rp, rivers ) + CALL rivers_route_rp( sw_river_source, abstracted_res_rp, & + abstracted_minor_res_rp, net_abstracted_river_rp,& + rivers ) ELSE @@ -680,6 +716,16 @@ SUBROUTINE surf_couple_rivers( & net_abstracted_river_rp ) END IF + ! Regrid abstraction from reservoirs. + IF ( l_reservoirs .AND. l_water_resources ) THEN + CALL landpts_to_rivpts( global_land_pts, np_rivers, & + rivers%map_river_to_land_points, & + rivers%global_land_index, & + rivers%rivers_index_rp, & + rivers%tot_abstracted_res_global, & + abstracted_res_rp ) + END IF + ! Regrid abstraction from minor reservoirs. IF ( l_minor_reservoirs .AND. l_water_resources ) THEN CALL landpts_to_rivpts( global_land_pts, np_rivers, & @@ -691,8 +737,9 @@ SUBROUTINE surf_couple_rivers( & END IF ! Call the routing science routine. - CALL rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & - net_abstracted_river_rp, rivers ) + CALL rivers_route_rp( sw_river_source, abstracted_res_rp, & + abstracted_minor_res_rp, net_abstracted_river_rp,& + rivers ) ! Regrid selected outputs from rivers to land grid. CALL rivpts_to_landpts( global_land_pts, np_rivers, & @@ -759,6 +806,7 @@ SUBROUTINE surf_couple_rivers( & #endif ! Deallocate local variables (in reverse order to allocation). + DEALLOCATE(abstracted_res_rp) DEALLOCATE(abstracted_minor_res_rp) DEALLOCATE(net_abstracted_river_rp) DEALLOCATE(global_sea_level) diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 29eaa916..684d4ec8 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -70,6 +70,8 @@ MODULE water_resources_control_mod ! This does not include "non-renewable" groundwater. gw_nr_abstracted_global(:), & ! Water abstracted from non-renewable groundwater (kg). + res_storage_global(:), & + ! Water stored in reservoirs, on land points (kg). minor_res_storage_global(:), & ! Water stored in minor reservoirs, on land points (kg). return_flow_gw_global(:), & @@ -110,7 +112,7 @@ SUBROUTINE water_resources_control( global_land_pts, & flandg, frac_irr_soilt, frac_soilt, & frac_surft, grid_area_ij, & ls_rain_ij, ls_snow_ij, lw_down, minor_res_storage, & - rfm_surfstore_rp, rivers_sto_rp, smvccl_soilt, & + res_storage, rfm_surfstore_rp, rivers_sto_rp, smvccl_soilt, & smvcst_soilt, smvcwt_soilt, sthf_soilt, & sw_surft, tl_1_ij, tstar_surft, & icntmax_gb, plant_n_gb, demand_accum, & @@ -119,11 +121,12 @@ SUBROUTINE water_resources_control( global_land_pts, & sthu_irr_soilt, sthu_soilt, & sthzw_soilt, sub_surf_roff, tl_1_day_av_gb, & tl_1_day_av_use_gb, & - priority_order, abstracted_minor_res_global, & - net_abstracted_river_global, gw_abstracted, irrig_water_gb, & - abstracted_minor_res, abstracted_river, conveyance_loss, & - demand_unmet, gw_avail_start, gw_nr_abstracted, sw_abstracted, & - sw_avail_total, water_removed ) + priority_order, abstracted_res_global, & + abstracted_minor_res_global, net_abstracted_river_global, & + gw_abstracted, irrig_water_gb, abstracted_minor_res, & + abstracted_res, abstracted_river, & + conveyance_loss, demand_unmet, gw_avail_start, gw_nr_abstracted, & + sw_abstracted, sw_avail_total, water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -148,7 +151,7 @@ SUBROUTINE water_resources_control( global_land_pts, & USE jules_irrig_mod, ONLY: irr_crop_doell, irr_crop -USE jules_rivers_mod, ONLY: l_minor_reservoirs, np_rivers +USE jules_rivers_mod, ONLY: l_reservoirs, l_minor_reservoirs, np_rivers USE jules_soil_mod, ONLY: sm_levels @@ -156,8 +159,8 @@ SUBROUTINE water_resources_control( global_land_pts, & USE jules_water_resources_mod, ONLY: & l_have_groundwater, l_have_surface_water, l_water_irrigation, & - nstep_water_res, n_sw_source, nwater_use, sw_minor_res_source, & - sw_river_source, use_irrigation, water_res_count + nstep_water_res, n_sw_source, nwater_use, sw_res_source, & + sw_minor_res_source, sw_river_source, use_irrigation, water_res_count USE parallel_mod, ONLY: is_master_task @@ -225,6 +228,8 @@ SUBROUTINE water_resources_control( global_land_pts, & ! Large-scale snowfall rate (kg m-2 s-1). lw_down(row_length,rows), & ! Surface downward longwave radiation (W m-2). + res_storage(np_rivers), & + ! Water stored in reservoirs (kg). minor_res_storage(np_rivers), & ! Water stored in minor reservoirs (kg). rfm_surfstore_rp(np_rivers), & @@ -289,14 +294,14 @@ SUBROUTINE water_resources_control( global_land_pts, & tl_1_day_av_use_gb(land_pts,ndpy,nyav) ! Daily average air temperature (K). -!------------------------------------------------------------------------------ -! Array arguments with INTENT(OUT) -!------------------------------------------------------------------------------ ! Coupling variables and diagnostics. REAL(KIND=real_jlslsm), INTENT(OUT) :: & !---------------------------------------------------------------------------- ! Coupling variables !---------------------------------------------------------------------------- + abstracted_res_global(global_land_pts), & + ! Water abstracted from reservoirs, on global land points (kg). + ! This is used to couple to reservoirs. abstracted_minor_res_global(global_land_pts), & ! Water abstracted from minor reservoirs, on global land points (kg). ! This is used to couple to minor reservoirs. @@ -315,6 +320,8 @@ SUBROUTINE water_resources_control( global_land_pts, & ! Water added to soil via irrigation (kg m-2 s-1). This is for coupling ! to a soil model - though that is currently done internally to the water ! resources code. + abstracted_res(land_pts), & + ! Water abstracted from reservoirs (kg). Diagnostic only. abstracted_minor_res(land_pts), & ! Water abstracted from minor reservoirs (kg). Diagnostic only. abstracted_river(land_pts), & @@ -378,11 +385,6 @@ SUBROUTINE water_resources_control( global_land_pts, & supply_irrig(land_pts) ! Water supplied for irrigation (kg). -! Dr Hook variables -INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 -INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 -REAL(KIND=jprb) :: zhook_handle - !------------------------------------------------------------------------------ !end of header IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) @@ -412,6 +414,9 @@ SUBROUTINE water_resources_control( global_land_pts, & ! These "global" arrays are only allocated at full size on the master task ! (see water_resources_alloc), so they must only be accessed there. IF ( is_master_task() ) THEN + IF ( l_reservoirs ) THEN + abstracted_res_global(:) = 0.0 + END IF IF ( l_minor_reservoirs ) THEN abstracted_minor_res_global(:) = 0.0 END IF @@ -428,6 +433,9 @@ SUBROUTINE water_resources_control( global_land_pts, & demand_unmet(:,:) = 0.0 water_removed(:) = 0.0 ! Initialise diagnostics. +IF ( l_reservoirs ) THEN + abstracted_res(:) = 0.0 +END IF IF ( l_minor_reservoirs ) THEN abstracted_minor_res(:) = 0.0 END IF @@ -521,12 +529,13 @@ SUBROUTINE water_resources_control( global_land_pts, & ! Global arrays should have been allocated before this routine is called. !------------------------------------------------------------------------ CALL regrid_to_land( global_land_index, map_river_to_land_points, & - rivers_index_rp, minor_res_storage, & - rfm_surfstore_rp, rivers_sto_rp, & + rivers_index_rp, res_storage, minor_res_storage, & + rfm_surfstore_rp, rivers_sto_rp, res_storage_global,& minor_res_storage_global, river_storage_global ) ! Calculate water available for abstraction. - CALL calc_avail_surface_water( minor_res_storage_global, & + CALL calc_avail_surface_water( res_storage_global, & + minor_res_storage_global, & river_storage_global, & sw_avail_global ) @@ -546,6 +555,12 @@ SUBROUTINE water_resources_control( global_land_pts, & conveyance_loss_global, return_flow_gw_global, & return_flow_river_global, supply_irrig_global ) + ! If reservoirs are modelled, save abstraction in a new variable. + IF ( sw_res_source > 0 ) THEN + abstracted_res_global(:) & + = sw_abstracted_global(:,sw_res_source) + END IF + ! If minor reservoirs are modelled, save abstraction in a new variable. IF ( sw_minor_res_source > 0 ) THEN abstracted_minor_res_global(:) & @@ -579,10 +594,11 @@ SUBROUTINE water_resources_control( global_land_pts, & ! There are no prognostic variables to be scattered. !---------------------------------------------------------------------------- CALL scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & - abstracted_minor_res, abstracted_river, & - gw_nr_abstracted, return_flow_gw, & - return_flow_river, sfc_water_frac, supply_irrig, & - sw_abstracted, sw_avail_total, water_removed ) + abstracted_res, abstracted_minor_res, & + abstracted_river, gw_nr_abstracted, & + return_flow_gw, return_flow_river, sfc_water_frac,& + supply_irrig, sw_abstracted, sw_avail_total, & + water_removed ) !---------------------------------------------------------------------------- ! Deallocate global arrays. @@ -667,11 +683,6 @@ SUBROUTINE initialise_water_resources( priority_order ) i ! Loop counter. -! Dr Hook variables -INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 -INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 -REAL(KIND=jprb) :: zhook_handle - !------------------------------------------------------------------------------ !end of header IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) @@ -762,11 +773,6 @@ SUBROUTINE accumulate_demand( demand_rate_domestic, & !------------------------------------------------------------------------------ CHARACTER(LEN=*), PARAMETER :: RoutineName = 'ACCUMULATE_DEMAND' -! Dr Hook variables -INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 -INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 -REAL(KIND=jprb) :: zhook_handle - !------------------------------------------------------------------------------ !end of header IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) @@ -837,11 +843,6 @@ SUBROUTINE add_conveyance_loss( conv_loss_frac, demand_accum ) INTEGER :: i ! Loop counter. -! Dr Hook variables -INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 -INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 -REAL(KIND=jprb) :: zhook_handle - !------------------------------------------------------------------------------ !end of header IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) @@ -875,7 +876,7 @@ SUBROUTINE allocate_global_water( l_allocate ) USE ereport_mod, ONLY: ereport -USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_rivers +USE jules_rivers_mod, ONLY: l_reservoirs, l_minor_reservoirs, l_rivers USE jules_water_resources_mod, ONLY: l_have_groundwater, l_have_surface_water, & l_prioritise, l_water_irrigation, n_sw_source, nwater_use @@ -915,12 +916,13 @@ SUBROUTINE allocate_global_water( l_allocate ) ! Size for irrigation arrays. land_size_gw, & ! Size for groundwater arrays. + land_size_res, & + ! Size for reservoir arrays. land_size_minor_res, & ! Size for minor reservoir arrays. land_size_rivers, & ! Size for river arrays. land_size_sw - ! Size for surface water arrays. ! Dr Hook variables INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 @@ -955,6 +957,11 @@ SUBROUTINE allocate_global_water( l_allocate ) ELSE land_size_rivers = 1 END IF + IF ( l_reservoirs ) THEN + land_size_res = global_land_pts + ELSE + land_size_res = 1 + END IF IF ( l_minor_reservoirs ) THEN land_size_minor_res = global_land_pts ELSE @@ -970,6 +977,7 @@ SUBROUTINE allocate_global_water( l_allocate ) land_size = 1 land_size_irrig = 1 land_size_gw = 1 + land_size_res = 1 land_size_minor_res = 1 land_size_rivers = 1 land_size_sw = 1 @@ -990,6 +998,8 @@ SUBROUTINE allocate_global_water( l_allocate ) error_sum = error_sum + ERROR ALLOCATE(gw_nr_abstracted_global(land_size_gw), STAT = ERROR) error_sum = error_sum + ERROR + ALLOCATE(res_storage_global(land_size_res), STAT = ERROR) + error_sum = error_sum + ERROR ALLOCATE(minor_res_storage_global(land_size_minor_res), STAT = ERROR) error_sum = error_sum + ERROR @@ -1037,6 +1047,7 @@ SUBROUTINE allocate_global_water( l_allocate ) gw_abstracted_global(:) = 0.0 gw_avail_global(:) = 0.0 gw_nr_abstracted_global(:) = 0.0 + res_storage_global(:) = 0.0 minor_res_storage_global(:) = 0.0 priority_order_global(:,:) = 0 return_flow_gw_global(:) = 0.0 @@ -1074,6 +1085,9 @@ SUBROUTINE allocate_global_water( l_allocate ) DEALLOCATE(return_flow_river_global) END IF IF ( ALLOCATED(priority_order_global) ) DEALLOCATE(priority_order_global) + IF ( ALLOCATED(res_storage_global) ) THEN + DEALLOCATE(res_storage_global) + END IF IF ( ALLOCATED(minor_res_storage_global) ) THEN DEALLOCATE(minor_res_storage_global) END IF @@ -1189,7 +1203,8 @@ END SUBROUTINE gather_global_water !############################################################################## SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & - abstracted_minor_res, abstracted_river, & + abstracted_res, abstracted_minor_res, & + abstracted_river, & gw_nr_abstracted, return_flow_gw, & return_flow_river, sfc_water_frac, & supply_irrig, sw_abstracted, sw_avail_total, & @@ -1202,12 +1217,12 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & USE ancil_info, ONLY: land_pts ! for the current task -USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_rivers +USE jules_rivers_mod, ONLY: l_reservoirs, l_minor_reservoirs, l_rivers USE jules_water_resources_mod, ONLY: l_have_groundwater, l_have_surface_water, & l_water_irrigation, n_sw_source, nwater_use, & - partition_calc_from_stores, partition_method, sw_minor_res_source, & - sw_river_source + partition_calc_from_stores, partition_method, sw_res_source, & + sw_minor_res_source, sw_river_source USE model_grid_mod, ONLY: global_land_pts @@ -1227,6 +1242,8 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & ! Water abstracted from renewable groundwater (kg). gw_nr_abstracted(land_pts), & ! Water abstracted from non-renewable groundwater (kg). + abstracted_res(land_pts), & + ! Water abstracted from reservoirs (kg). abstracted_minor_res(land_pts), & ! Water abstracted from minor reservoirs (kg). abstracted_river(land_pts), & @@ -1303,6 +1320,11 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & END DO CALL scatter_land_field( sw_avail_total_start_global, sw_avail_total ) + IF ( l_reservoirs ) THEN + CALL scatter_land_field( sw_abstracted_global(:,sw_res_source), & + abstracted_res ) + END IF + ! Save diagnostic of abstraction from minor reservoirs. IF ( l_minor_reservoirs ) THEN CALL scatter_land_field( sw_abstracted_global(:,sw_minor_res_source), & @@ -1330,9 +1352,10 @@ END SUBROUTINE scatter_global_water !############################################################################## SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & - rivers_index_rp, minor_res_storage, & - rfm_surfstore_rp, rivers_sto_rp, & - minor_res_storage_global, river_storage_global ) + rivers_index_rp, res_storage, & + minor_res_storage, rfm_surfstore_rp, rivers_sto_rp, & + res_storage_global, minor_res_storage_global, & + river_storage_global ) !------------------------------------------------------------------------------ ! Description: @@ -1341,8 +1364,8 @@ SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & USE ereport_mod, ONLY: ereport -USE jules_rivers_mod, ONLY: i_river_vn, l_minor_reservoirs, l_rivers, & - np_rivers, rivers_rfm, rivers_trip +USE jules_rivers_mod, ONLY: i_river_vn, l_reservoirs, l_minor_reservoirs, & + l_rivers, np_rivers, rivers_rfm, rivers_trip USE model_grid_mod, ONLY: global_land_pts @@ -1365,6 +1388,8 @@ SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & ! Index of points where routing is calculated. REAL(KIND=real_jlslsm), INTENT(IN) :: & + res_storage(np_rivers), & + ! Water stored in reservoirs (kg). minor_res_storage(np_rivers), & ! Water stored in minor reservoirs (kg). rfm_surfstore_rp(np_rivers), & @@ -1376,6 +1401,8 @@ SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & ! Array arguments with INTENT(OUT). !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm), INTENT(OUT) :: & + res_storage_global(global_land_pts), & + ! Water stored in reservoirs, on land points (kg). minor_res_storage_global(global_land_pts), & ! Water stored in minor reservoirs, on land points (kg). river_storage_global(global_land_pts) @@ -1440,6 +1467,18 @@ SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & END IF ! l_rivers +!------------------------------------------------------------------------------ +! Get reservoir storage onto land points. +!------------------------------------------------------------------------------ +IF ( l_reservoirs ) THEN + ! Initialise. + res_storage_global(:) = 0.0 + CALL rivpts_to_landpts( global_land_pts, np_rivers, & + map_river_to_land_points, global_land_index, & + rivers_index_rp, res_storage, & + res_storage_global ) +END IF + !------------------------------------------------------------------------------ ! Get minor reservoir storage onto land points. !------------------------------------------------------------------------------ diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index edea4e52..eb546761 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -74,6 +74,8 @@ MODULE water_resources_vars_mod !-------------------------------------------------------------------------- ! Fluxes for coupling. !-------------------------------------------------------------------------- + abstracted_res_global(:), & + ! Water abstracted from reservoirs, on global land points (kg). abstracted_minor_res_global(:), & ! Water abstracted from minor reservoirs, on global land points (kg). net_abstracted_river_global(:), & @@ -107,6 +109,8 @@ MODULE water_resources_vars_mod !-------------------------------------------------------------------------- ! Diagnostics. !-------------------------------------------------------------------------- + abstracted_res(:), & + ! Water abstracted from reservoirs (kg). abstracted_minor_res(:), & ! Water abstracted from minor reservoirs (kg). abstracted_river(:), & @@ -130,6 +134,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: demand_rate_industry(:) REAL(KIND=real_jlslsm), POINTER :: demand_rate_livestock(:) REAL(KIND=real_jlslsm), POINTER :: demand_rate_transfers(:) + REAL(KIND=real_jlslsm), POINTER :: abstracted_res_global(:) REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res_global(:) REAL(KIND=real_jlslsm), POINTER :: net_abstracted_river_global(:) REAL(KIND=real_jlslsm), POINTER :: demand_accum(:,:) @@ -139,6 +144,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: gw_nr_abstracted(:) REAL(KIND=real_jlslsm), POINTER :: sw_abstracted(:,:) REAL(KIND=real_jlslsm), POINTER :: sw_avail_total(:) + REAL(KIND=real_jlslsm), POINTER :: abstracted_res(:) REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res(:) REAL(KIND=real_jlslsm), POINTER :: abstracted_river(:) REAL(KIND=real_jlslsm), POINTER :: conveyance_loss(:) @@ -156,10 +162,10 @@ MODULE water_resources_vars_mod SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & nwater_use, sw_river_source, l_have_groundwater, & - l_have_surface_water, l_is_master_task, l_minor_reservoirs, & - l_water_domestic, l_water_industry, l_water_irrigation, & - l_water_livestock, l_water_resources, l_water_transfers, & - water_resources_data ) + l_have_surface_water, l_is_master_task, l_reservoirs, & + l_minor_reservoirs, l_water_domestic, l_water_industry, & + l_water_irrigation, l_water_livestock, l_water_resources, & + l_water_transfers, water_resources_data ) !No USE statements other than Dr Hook USE parkind1, ONLY: jprb, jpim @@ -190,6 +196,8 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & ! Flag indicating if we have surface water represented (e.g. rivers). l_is_master_task, & ! Flag indicating if this call is from the master task. + l_reservoirs, & + ! Switch for reservoirs. l_minor_reservoirs, & ! Switch for minor_reservoirs. l_water_domestic, & @@ -214,9 +222,10 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & ! Local variables !------------------------------------------------------------------------------ INTEGER :: & - global_land_pts_minor_res, global_land_pts_rivers, land_pts_dim, & - land_pts_gw, land_pts_minor_res, land_pts_sw, land_pts_rivers, & - n_sw_source_dim, nwater_use_dim + global_land_pts_res, global_land_pts_minor_res, global_land_pts_rivers, & + land_pts_dim, land_pts_gw, land_pts_res, land_pts_minor_res, land_pts_sw, & + land_pts_rivers, n_sw_source_dim, nwater_use_dim + ! Sizes used when allocating arrays. INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 @@ -236,13 +245,15 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & !------------------------------------------------------------------------------ ! Set default sizes that are used if water resources (or a particular part of ! the parameterisation) are not selected. +global_land_pts_res = 1 global_land_pts_minor_res = 1 global_land_pts_rivers = 1 +land_pts_res = 1 +land_pts_minor_res = 1 land_pts_dim = 1 land_pts_gw = 1 land_pts_rivers = 1 land_pts_sw = 1 -land_pts_minor_res = 1 n_sw_source_dim = 1 nwater_use_dim = 1 IF ( l_water_resources ) THEN @@ -262,6 +273,13 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & global_land_pts_rivers = global_land_pts END IF END IF + IF ( l_reservoirs ) THEN + land_pts_res = land_pts + ! The "global" variable only needs to be full size on master task. + IF ( l_is_master_task ) THEN + global_land_pts_res = global_land_pts + END IF + END IF IF ( l_minor_reservoirs ) THEN land_pts_minor_res = land_pts ! The "global" variable only needs to be full size on master task. @@ -313,6 +331,14 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & ALLOCATE( water_resources_data%demand_rate_transfers(1) ) END IF +!------------------------------------------------------------------------------ +! Coupling to reservoirs. +! Only allocated at full size if reservoirs are modelled. +! Allocated space for all (global) land points because both the water resource +! and river codes operate globally. +!------------------------------------------------------------------------------ +ALLOCATE( water_resources_data & + %abstracted_res_global(global_land_pts_res) ) !------------------------------------------------------------------------------ ! Coupling to minor reservoirs. ! Only allocated at full size if minor reservoirs are modelled. @@ -344,6 +370,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & ALLOCATE( water_resources_data%sw_abstracted(land_pts_sw,n_sw_source_dim) ) ALLOCATE( water_resources_data%sw_avail_total(land_pts_sw) ) ! Diagnostics. +ALLOCATE( water_resources_data%abstracted_res(land_pts_res) ) ALLOCATE( water_resources_data%abstracted_minor_res(land_pts_minor_res) ) ALLOCATE( water_resources_data%abstracted_river(land_pts_rivers) ) ALLOCATE( water_resources_data%conveyance_loss(land_pts_dim) ) @@ -359,6 +386,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & water_resources_data%demand_rate_industry(:) = 0.0 water_resources_data%demand_rate_livestock(:) = 0.0 water_resources_data%demand_rate_transfers(:) = 0.0 +water_resources_data%abstracted_res_global(:) = 0.0 water_resources_data%abstracted_minor_res_global(:) = 0.0 water_resources_data%net_abstracted_river_global(:) = 0.0 water_resources_data%demand_accum(:,:) = 0.0 @@ -368,6 +396,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & water_resources_data%gw_nr_abstracted(:) = 0.0 water_resources_data%sw_abstracted(:,:) = 0.0 water_resources_data%sw_avail_total(:) = 0.0 +water_resources_data%abstracted_res(:) = 0.0 water_resources_data%abstracted_minor_res(:) = 0.0 water_resources_data%abstracted_river(:) = 0.0 water_resources_data%conveyance_loss(:) = 0.0 @@ -411,6 +440,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) DEALLOCATE( water_resources_data%water_removed ) DEALLOCATE( water_resources_data%conveyance_loss ) DEALLOCATE( water_resources_data%abstracted_river ) +DEALLOCATE( water_resources_data%abstracted_res ) DEALLOCATE( water_resources_data%abstracted_minor_res ) DEALLOCATE( water_resources_data%sw_avail_total ) DEALLOCATE( water_resources_data%sw_abstracted ) @@ -420,6 +450,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) DEALLOCATE( water_resources_data%gw_abstracted ) DEALLOCATE( water_resources_data%demand_accum ) DEALLOCATE( water_resources_data%net_abstracted_river_global ) +DEALLOCATE( water_resources_data%abstracted_res_global ) DEALLOCATE( water_resources_data%abstracted_minor_res_global ) DEALLOCATE( water_resources_data%demand_rate_transfers ) DEALLOCATE( water_resources_data%demand_rate_livestock ) @@ -484,6 +515,8 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) => water_resources_data%demand_rate_livestock water_resources%demand_rate_transfers & => water_resources_data%demand_rate_transfers +water_resources%abstracted_res_global & + => water_resources_data%abstracted_res_global water_resources%abstracted_minor_res_global & => water_resources_data%abstracted_minor_res_global water_resources%net_abstracted_river_global & @@ -495,6 +528,7 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) water_resources%gw_nr_abstracted => water_resources_data%gw_nr_abstracted water_resources%sw_abstracted => water_resources_data%sw_abstracted water_resources%sw_avail_total => water_resources_data%sw_avail_total +water_resources%abstracted_res => water_resources_data%abstracted_res water_resources%abstracted_minor_res & => water_resources_data%abstracted_minor_res water_resources%abstracted_river => water_resources_data%abstracted_river @@ -539,6 +573,7 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%demand_rate_industry ) NULLIFY( water_resources%demand_rate_livestock ) NULLIFY( water_resources%demand_rate_transfers ) +NULLIFY( water_resources%abstracted_res_global ) NULLIFY( water_resources%abstracted_minor_res_global ) NULLIFY( water_resources%net_abstracted_river_global ) NULLIFY( water_resources%demand_accum ) @@ -548,6 +583,7 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%gw_nr_abstracted ) NULLIFY( water_resources%sw_abstracted ) NULLIFY( water_resources%sw_avail_total ) +NULLIFY( water_resources%abstracted_res ) NULLIFY( water_resources%abstracted_minor_res ) NULLIFY( water_resources%abstracted_river ) NULLIFY( water_resources%conveyance_loss ) diff --git a/src/control/um/check_unavailable_options_mod.F90 b/src/control/um/check_unavailable_options_mod.F90 index 8118dcf7..5f078bff 100644 --- a/src/control/um/check_unavailable_options_mod.F90 +++ b/src/control/um/check_unavailable_options_mod.F90 @@ -23,7 +23,7 @@ SUBROUTINE check_unavailable_options() USE jules_irrig_mod, ONLY: l_irrig_limit USE jules_urban_mod, ONLY: l_urban_empirical USE jules_rivers_mod, ONLY: l_riv_overbank, l_rivers, i_river_vn, & - rivers_um_trip, rivers_rfm, l_minor_reservoirs + rivers_um_trip, rivers_rfm, l_reservoirs, l_minor_reservoirs USE jules_soil_biogeochem_mod, ONLY: l_ch4_microbe, l_label_frac_cs USE jules_soil_mod, ONLY: l_tile_soil, l_bedrock USE jules_surface_types_mod, ONLY: ncpft @@ -190,6 +190,14 @@ SUBROUTINE check_unavailable_options() CALL jules_print(RoutineName, jules_message, level = PrNorm) END IF +IF ( l_reservoirs ) THEN + error_sum = error_sum + 1 + WRITE(jules_message,'(I0,A,L1)') error_sum, & + ": Reservoirs are only available to standalone. " // & + "l_reservoirs = ", l_reservoirs + CALL jules_print(RoutineName, jules_message, level = PrNorm) +END IF + IF ( l_minor_reservoirs ) THEN error_sum = error_sum + 1 WRITE(jules_message,'(I0,A,L1)') error_sum, & diff --git a/src/initialisation/shared/allocate_jules_arrays.F90 b/src/initialisation/shared/allocate_jules_arrays.F90 index f9ec0f7a..f7b7a1bd 100644 --- a/src/initialisation/shared/allocate_jules_arrays.F90 +++ b/src/initialisation/shared/allocate_jules_arrays.F90 @@ -31,8 +31,8 @@ SUBROUTINE allocate_jules_arrays(crop_vars_data,psparms_data,top_pdm_data, & lake_data, & forcing_data, & rivers_data, & - !veg3_parm_(data), & - !veg3_field_(data), & + !veg3_parm_(data), & + !veg3_field_(data), & chemvars_data, water_resources_data, & wtrac_jls_data & ) @@ -56,6 +56,7 @@ SUBROUTINE allocate_jules_arrays(crop_vars_data,psparms_data,top_pdm_data, & n_sw_source, nwater_use, sw_river_source USE jules_deposition_mod, ONLY: l_deposition, ndry_dep_species USE jules_water_tracers_mod, ONLY: l_wtrac_jls +USE jules_rivers_mod, ONLY: l_reservoirs !Variables- dimensions USE jules_surface_types_mod, ONLY: ncpft,nnpft @@ -305,7 +306,7 @@ SUBROUTINE allocate_jules_arrays(crop_vars_data,psparms_data,top_pdm_data, & CALL water_resources_alloc( global_land_pts, land_pts, n_sw_source, & nwater_use, sw_river_source, l_have_groundwater, & l_have_surface_water, is_master_task(), & - l_minor_reservoirs, & + l_reservoirs, l_minor_reservoirs, & l_water_domestic, l_water_industry, & l_water_irrigation, & l_water_livestock, l_water_resources, & diff --git a/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 b/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 index a8ff5e89..73625118 100644 --- a/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 +++ b/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 @@ -1039,9 +1039,12 @@ SUBROUTINE remap_ancil( nx_rivers, ny_rivers, rivers_dx, & USE jules_rivers_mod, ONLY: & channel_depth_grid, channel_width_grid, mean_sea_level_grid, & - minor_res_capacity_grid, minor_res_frac_grid, river_distance_grid, & - river_elevation_grid, river_elevation_grid, river_length_grid, & - river_manning_grid, river_nextx_grid, river_nexty_grid, rivers_type + minor_res_capacity_grid, minor_res_frac_grid, & + river_distance_grid, river_elevation_grid, river_length_grid, & + river_manning_grid, river_nextx_grid, river_nexty_grid, & + res_capacity_grid, res_catch_grid, res_year_grid, & + res_critical_grid, res_flood_grid, res_emergency_grid, & + res_normal_release_grid, res_flood_release_grid, rivers_type USE overbank_inundation_mod, ONLY: & hypsometric_quantiles_grid, logn_mean, logn_stdev, nquantile_hypso @@ -1217,6 +1220,41 @@ SUBROUTINE remap_ancil( nx_rivers, ny_rivers, rivers_dx, & ! Extract the first column from the 2D field. rivers%rivers_ygrid(:) = tmp_2d_coord(1,:) + !---------------------------------------------------------------------------- + ! Cases for reservoir variables. + !---------------------------------------------------------------------------- +CASE ( 'res_capacity_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_capacity_grid ) + +CASE ( 'res_catch_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_catch_grid ) + +CASE ( 'res_year_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_year_grid ) + +CASE ( 'res_critical_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_critical_grid ) + +CASE ( 'res_flood_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_flood_grid ) + +CASE ( 'res_emergency_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_emergency_grid ) + +CASE ( 'res_normal_release_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_normal_release_grid ) + +CASE ( 'res_flood_release_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, res_flood_release_grid ) + CASE DEFAULT CALL log_fatal( RoutineName, & "Do not recognise var: " // TRIM(var) ) @@ -1271,7 +1309,7 @@ SUBROUTINE remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, & !------------------------------------------------------------------------------ LOGICAL, OPTIONAL, INTENT(IN) :: & is_x_index_arg - ! Flag indicating if the field is an index of x location on grid.& + ! Flag indicating if the field is an index of x location on grid. & !------------------------------------------------------------------------------ ! Local scalar variables. @@ -2244,7 +2282,10 @@ SUBROUTINE set_river_point_values( rivers_x1_input, & rivers_camaflood, river_distance_grid, & rivers_dx, rivers_dy, river_elevation_grid, river_length_grid, & river_manning_grid, rivers_rfm, rivers_trip, rivers_x1, l_outflow_per_river, & - l_init_storage, & + l_init_storage, l_reservoirs, & + res_capacity_grid, res_catch_grid, res_year_grid, & + res_critical_grid, res_flood_grid, res_emergency_grid, & + res_normal_release_grid, res_flood_release_grid, & ! types rivers_type @@ -2485,6 +2526,24 @@ SUBROUTINE set_river_point_values( rivers_x1_input, & END IF ! l_riv_overbank + !------------------------------------------------------------------------ + ! Set reservoir ancillary variables, if required. + !------------------------------------------------------------------------ + IF ( l_reservoirs ) THEN + + rivers%res_capacity(ip) = res_capacity_grid(irx,iry) + rivers%res_catch(ip) = res_catch_grid(irx,iry) + rivers%res_year(ip) = res_year_grid(irx,iry) + rivers%res_critical(ip) = res_critical_grid(irx,iry) + rivers%res_flood(ip) = res_flood_grid(irx,iry) + rivers%res_emergency(ip) = res_emergency_grid(irx,iry) + rivers%res_normal_release(ip) = & + res_normal_release_grid(irx,iry) + rivers%res_flood_release(ip) = & + res_flood_release_grid(irx,iry) + + END IF ! l_reservoirs + !------------------------------------------------------------------------ ! Set minor reservoir ancillary variables, if required. !------------------------------------------------------------------------ diff --git a/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 index 821a8793..19563fc4 100644 --- a/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 @@ -51,6 +51,7 @@ SUBROUTINE init_rivers_props(rivers, rivers_data) rivers_camaflood, rivers_rfm, & rivers_trip, y1_land_grid, l_riv_overbank, l_outflow_per_river, & l_init_storage, & + l_reservoirs, & ! types rivers_type, rivers_data_type @@ -321,6 +322,28 @@ SUBROUTINE init_rivers_props(rivers, rivers_data) required_vars(nvars_required) = 'rivers_outflow_number' END IF + !---------------------------------------------------------------------------- + ! Add variables for reservoirs. + !---------------------------------------------------------------------------- + IF ( l_reservoirs ) THEN + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_capacity_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_catch_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_year_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_critical_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_flood_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_emergency_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_normal_release_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'res_flood_release_grid' + END IF + nvars_optional = nvars_optional + 1 optional_vars(nvars_optional) = 'rivers_outflow_number' diff --git a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 index 3593a783..a93f6fb0 100644 --- a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 @@ -35,7 +35,7 @@ MODULE jules_rivers_props_mod !----------------------------------------------------------------------------- ! Scalars in namelist. -INTEGER, PARAMETER :: nvars_max = 9 +INTEGER, PARAMETER :: nvars_max = 17 ! The maximum possible number of ancillary variables that are read in. INTEGER :: nvars @@ -69,7 +69,7 @@ MODULE jules_rivers_props_mod l_ignore_ancil_rivers_check = .FALSE. ! Switch to check river routing & river number ancillary for compatibility. ! The current Rose stem test ancils are not compatible as the land sea - ! mask is different. Setting this to true maintains bit comparability & + ! mask is different. Setting this to true maintains bit comparability & ! protects the calculation of the coupling field needed for the LFRic ! coupled miniapp. @@ -166,8 +166,8 @@ SUBROUTINE check_jules_rivers_props() USE jules_rivers_mod, ONLY: nx_rivers_in=>nx_rivers, ny_rivers_in=>ny_rivers, & i_river_vn, land_dx, land_dy, l_init_storage, & - l_minor_reservoirs, l_riv_overbank, & - nx_land_grid, ny_land_grid, & + l_minor_reservoirs, l_reservoirs, & + l_riv_overbank, nx_land_grid, ny_land_grid, & x1_land_grid, y1_land_grid, rivers_length, & l_outflow_per_river, rivers_camaflood, & rivers_regrid, rivers_rfm @@ -191,7 +191,7 @@ SUBROUTINE check_jules_rivers_props() INTEGER :: i ! Loop counter INTEGER, PARAMETER :: & - nvar_values = 11 ! Number of recognised identifiers + nvar_values = 19 ! Number of recognised identifiers CHARACTER(LEN=identifier_len) :: & var_values(nvar_values) ! Names of recognised identifiers @@ -216,6 +216,14 @@ SUBROUTINE check_jules_rivers_props() 'rivers_storage ', & 'logn_mean ', & 'logn_stdev ', & + 'res_capacity_grid ', & + 'res_catch_grid ', & + 'res_year_grid ', & + 'res_critical_grid ', & + 'res_flood_grid ', & + 'res_emergency_grid ', & + 'res_normal_release_grid', & + 'res_flood_release_grid ', & 'minor_res_capacity_grid', & 'minor_res_frac_grid '] @@ -399,7 +407,12 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & river_length_grid, river_manning_grid, & river_nextx_grid, river_nexty_grid, rivers_rfm, & rivers_trip, rivers_data_type, rivers_type, & - l_outflow_per_river, l_init_storage + l_outflow_per_river, l_init_storage, & + l_reservoirs, res_capacity_grid, res_catch_grid, & + res_year_grid, res_critical_grid, & + res_flood_grid, res_emergency_grid, & + res_normal_release_grid, & + res_flood_release_grid IMPLICIT NONE @@ -564,6 +577,29 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & ALLOCATE( rivers_data%rivers_storage(nx_size,ny_size), STAT = ERROR ) error_sum = error_sum + ERROR +! Reservoir 2D ancillary variables. +IF ( l_reservoirs ) THEN + nx_size = nx_rivers + ny_size = ny_rivers +ELSE + nx_size = 1 + ny_size = 1 +END IF +ALLOCATE( res_capacity_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( res_catch_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( res_year_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( res_critical_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( res_flood_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( res_emergency_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( res_normal_release_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( res_flood_release_grid(nx_size,ny_size), STAT = ERROR ) ! Minor reservoir 2D ancillary variables. IF ( l_minor_reservoirs ) THEN nx_size = nx_rivers @@ -603,7 +639,15 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & rivers_data%rivers_seq(:,:) = rmdi rivers_data%rivers_outflow_number(:,:) = rmdi rivers_data%rivers_storage(:,:) = rmdi -rivers_data%land_fraction_2d(:,:) = rmdi +rivers_data%land_fraction_2d(:,:) = rmdi +res_capacity_grid(:,:) = rmdi +res_catch_grid(:,:) = rmdi +res_year_grid(:,:) = rmdi +res_critical_grid(:,:) = rmdi +res_flood_grid(:,:) = rmdi +res_emergency_grid(:,:) = rmdi +res_normal_release_grid(:,:) = rmdi +res_flood_release_grid(:,:) = rmdi minor_res_capacity_grid(:,:) = rmdi minor_res_frac_grid(:,:) = rmdi @@ -641,10 +685,10 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) USE jules_model_environment_mod, ONLY: l_oasis_rivers -USE jules_rivers_mod, ONLY: i_river_vn, l_minor_reservoirs, l_sea_level, & - l_vary_sea_level, rivers_camaflood, & - rivers_data_type, rivers_rfm, & - rivers_trip, rivers_type, l_outflow_per_river +USE jules_rivers_mod, ONLY: i_river_vn, l_sea_level, l_vary_sea_level, & + rivers_camaflood, rivers_data_type, rivers_rfm, & + rivers_trip, rivers_type, l_outflow_per_river, & + l_reservoirs, l_minor_reservoirs USE jules_water_resources_mod, ONLY: l_water_resources @@ -911,6 +955,45 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) ALLOCATE(rivers_data%rivers_outflow_number_rp(np_rivers_tmp), STAT = ERROR) error_sum = error_sum + ERROR +!------------------------------------------------------------------------------ +! Allocate reservoir variables. +!------------------------------------------------------------------------------ +IF ( l_reservoirs .AND. is_master_task() ) THEN + ! Full size. + np_rivers_tmp = np_rivers + np_global_land_tmp = global_land_pts +ELSE + ! Minimum size. + np_rivers_tmp = 1 + np_global_land_tmp = 1 +END IF +! Reservoir ancillaries. +ALLOCATE( rivers_data%res_capacity(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_catch(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_year(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_critical(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_flood(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_emergency(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_normal_release(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_flood_release(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +! Reservoir prognostics. +ALLOCATE( rivers_data%res_storage(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%res_cap_current(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +! Reservoir coupling to rivers. +ALLOCATE( rivers_data%tot_abstracted_res_global(np_global_land_tmp), & + STAT = ERROR ) +error_sum = error_sum + ERROR + !------------------------------------------------------------------------------ ! Allocate minor reservoir variables. !------------------------------------------------------------------------------ @@ -1029,13 +1112,28 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers_data%sub_surf_roff_rp(:) = 0.0 rivers_data%surf_roff_rp(:) = 0.0 +! Initialise reservoir variables. Storage (the state variable) should be +! initialised to zero until better initialisation is possible. +rivers_data%res_capacity(:) = rmdi +rivers_data%res_catch(:) = rmdi +rivers_data%res_year(:) = rmdi +rivers_data%res_critical(:) = rmdi +rivers_data%res_flood(:) = rmdi +rivers_data%res_emergency(:) = rmdi +rivers_data%res_normal_release(:)= rmdi +rivers_data%res_flood_release(:) = rmdi +rivers_data%res_storage(:) = 0.0 +rivers_data%res_cap_current(:) = 0.0 + ! Initialise minor reservoir variables. Storage (the state variable) should be ! initialised to zero until better initialisation is possible. rivers_data%minor_res_capacity(:) = rmdi rivers_data%minor_res_frac(:) = rmdi rivers_data%minor_res_storage(:) = 0.0 + ! Initialise further variables to couple to water resources. +rivers_data%tot_abstracted_res_global(:) = rmdi rivers_data%tot_abstracted_minor_res_global(:) = rmdi rivers_data%tot_net_abstracted_river_global(:) = rmdi @@ -1107,6 +1205,21 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers%sub_surf_roff_rp => rivers_data%sub_surf_roff_rp rivers%surf_roff_rp => rivers_data%surf_roff_rp + +! Reservoir variables. +rivers%res_capacity => rivers_data%res_capacity +rivers%res_catch => rivers_data%res_catch +rivers%res_year => rivers_data%res_year +rivers%res_critical => rivers_data%res_critical +rivers%res_flood => rivers_data%res_flood +rivers%res_emergency => rivers_data%res_emergency +rivers%res_normal_release => rivers_data%res_normal_release +rivers%res_flood_release => rivers_data%res_flood_release +rivers%res_storage => rivers_data%res_storage +rivers%res_cap_current => rivers_data%res_cap_current +rivers%tot_abstracted_res_global & + => rivers_data%tot_abstracted_res_global + ! Minor reservoir variables. rivers%minor_res_capacity => rivers_data%minor_res_capacity rivers%minor_res_frac => rivers_data%minor_res_frac @@ -1133,7 +1246,11 @@ SUBROUTINE deallocate_river_props( ) USE jules_rivers_mod, ONLY: & channel_depth_grid, channel_width_grid, minor_res_capacity_grid, & minor_res_frac_grid, river_distance_grid, river_elevation_grid, & - river_length_grid, river_manning_grid, river_nextx_grid, river_nexty_grid + river_length_grid, river_manning_grid, river_nextx_grid, river_nexty_grid, & + res_capacity_grid, res_catch_grid, res_year_grid, & + res_critical_grid, res_flood_grid, res_emergency_grid, & + res_normal_release_grid, res_flood_release_grid + IMPLICIT NONE @@ -1194,6 +1311,32 @@ SUBROUTINE deallocate_river_props( ) DEALLOCATE( river_manning_grid ) END IF +! Reservoir variables. +IF ( ALLOCATED( res_capacity_grid ) ) THEN + DEALLOCATE( res_capacity_grid ) +END IF +IF ( ALLOCATED( res_catch_grid ) ) THEN + DEALLOCATE( res_catch_grid ) +END IF +IF ( ALLOCATED( res_year_grid ) ) THEN + DEALLOCATE( res_year_grid ) +END IF +IF ( ALLOCATED( res_critical_grid ) ) THEN + DEALLOCATE( res_critical_grid ) +END IF +IF ( ALLOCATED( res_flood_grid ) ) THEN + DEALLOCATE( res_flood_grid ) +END IF +IF ( ALLOCATED( res_emergency_grid ) ) THEN + DEALLOCATE( res_emergency_grid ) +END IF +IF ( ALLOCATED( res_normal_release_grid ) ) THEN + DEALLOCATE( res_normal_release_grid ) +END IF +IF ( ALLOCATED( res_flood_release_grid ) ) THEN + DEALLOCATE( res_flood_release_grid ) +END IF + ! Minor reservoir variables. IF ( ALLOCATED( minor_res_capacity_grid ) ) THEN DEALLOCATE( minor_res_capacity_grid ) @@ -1209,4 +1352,4 @@ END SUBROUTINE deallocate_river_props !############################################################################## END MODULE jules_rivers_props_mod -#endif +#endif \ No newline at end of file diff --git a/src/initialisation/standalone/init_output_mod.F90 b/src/initialisation/standalone/init_output_mod.F90 index fa280e1d..acab5ba5 100644 --- a/src/initialisation/standalone/init_output_mod.F90 +++ b/src/initialisation/standalone/init_output_mod.F90 @@ -349,7 +349,7 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_outflow_per_river, l_rivers, & l_riv_overbank, i_river_vn, rivers_camaflood, rivers_rfm, rivers_trip, & - l_inland_outflow + l_inland_outflow, l_reservoirs USE jules_deposition_mod, ONLY: l_deposition, l_deposition_flux @@ -694,6 +694,10 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & CASE ( 'area', 'channel_depth_grid', 'channel_width_grid', & 'direction', 'hypso_quantiles_grid', 'latitude_2d', 'logn_mean', & 'logn_stdev', 'longitude_2d', 'mean_sea_level_grid', & + 'res_capacity_grid', 'res_catch_grid', & + 'res_year_grid', 'res_critical_grid', & + 'res_flood_grid', 'res_emergency_grid', & + 'res_normal_release_grid', 'res_flood_release_grid', & 'minor_res_capacity_grid', 'minor_res_frac_grid', & 'river_distance_grid', 'river_elevation_grid', 'river_length_grid', & 'river_manning_grid', 'river_nextx_grid', 'river_nexty_grid', & @@ -823,6 +827,14 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & END SELECT END IF + IF ( .NOT. l_water_resources .OR. .NOT. l_reservoirs ) THEN + SELECT CASE ( var(j) ) + CASE ( 'res_abstracted' ) + remove_var = .TRUE. + message = 'Water resources + reservoirs not used.' + END SELECT + END IF + IF ( .NOT. l_water_resources .OR. .NOT. l_minor_reservoirs ) THEN SELECT CASE ( var(j) ) CASE ( 'minor_res_abstracted' ) @@ -840,6 +852,19 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & END SELECT END IF + !---------------------------------------------------------------------------- + ! Variables that are only allowed with reservoirs. + !---------------------------------------------------------------------------- + IF ( .NOT. l_reservoirs ) THEN + SELECT CASE ( var(j) ) + CASE ( 'res_capacity', 'res_catch', 'res_storage', 'res_year', & + 'res_critical', 'res_flood', 'res_emergency', & + 'res_normal_release', 'res_flood_release' ) + remove_var = .TRUE. + message = 'Reservoirs not used.' + END SELECT + END IF ! l_reservoirs + !--------------------------------------------------------------------------- ! Variables that are only allowed with atmospheric deposition !--------------------------------------------------------------------------- diff --git a/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 b/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 index 80c35e44..8f713006 100644 --- a/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 +++ b/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 @@ -993,9 +993,14 @@ FUNCTION get_default_ic_values(total_snow) RESULT(defaults_dict) CASE ( 'lake_h_ice_gb' ) CALL dict_set(defaults_dict, 'lake_h_ice_gb' , lake_H_ice_0) + !Reservoirs + CASE ( 'res_storage' ) + CALL dict_set(defaults_dict, 'res_storage', 0.0) + !Minor reservoirs CASE ( 'minor_res_storage' ) CALL dict_set(defaults_dict, 'minor_res_storage', 0.0) + !Snow variables ! CASE ( 'rho_snow' ) ! CASE ( 'snow_depth' ) diff --git a/src/io/dump/get_dim_info_mod.F90 b/src/io/dump/get_dim_info_mod.F90 index e7aa1243..9db65e2f 100644 --- a/src/io/dump/get_dim_info_mod.F90 +++ b/src/io/dump/get_dim_info_mod.F90 @@ -565,8 +565,7 @@ SUBROUTINE get_dim_info_rivers( l_reading, identifier, ndims, dim_sizes, & 'rivers_outflow_rp', 'outflow_per_river', 'inland_outflow_rp', & 'flood_flow', 'flood_flow_prev', 'flood_storage', 'flood_storage_prev', & 'river_channel_flow', 'river_channel_storage', 'river_depth_prev', & - 'river_flow_prev', 'minor_res_storage' & - ) + 'river_flow_prev','res_storage', 'minor_res_storage') ndims = 1 dim_names(1) = p_rivers_dim_name dim_sizes(1) = np_rivers diff --git a/src/io/dump/read_dump_mod.F90 b/src/io/dump/read_dump_mod.F90 index b97b500b..f72b10cb 100644 --- a/src/io/dump/read_dump_mod.F90 +++ b/src/io/dump/read_dump_mod.F90 @@ -988,7 +988,8 @@ SUBROUTINE read_dump(file_name, identifiers) 'rfm_bflowin_rp', 'rfm_flowin_rp', & 'rfm_substore_rp', 'rfm_surfstore_rp', 'river_channel_storage', & 'river_channel_flow', 'river_depth_prev', 'river_flow_prev', & - 'rivers_outflow_rp', 'rivers_sto_rp', 'inland_outflow_rp' ) + 'rivers_outflow_rp', 'rivers_sto_rp', 'inland_outflow_rp', & + 'res_storage' ) ! nothing to do !------------------------------------------------------------------------- diff --git a/src/io/dump/read_dump_var_rivers_mod.F90 b/src/io/dump/read_dump_var_rivers_mod.F90 index f8b0f66f..aab01498 100644 --- a/src/io/dump/read_dump_var_rivers_mod.F90 +++ b/src/io/dump/read_dump_var_rivers_mod.F90 @@ -103,6 +103,9 @@ SUBROUTINE read_dump_var_rivers( identifier, FILE, var_id ) CASE ( 'inland_outflow_rp' ) CALL file_read_var(FILE, var_id, rivers%inland_outflow_rp) +CASE ( 'res_storage' ) + CALL file_read_var(FILE, var_id, rivers%res_storage) + CASE DEFAULT CALL log_fatal( RoutineName, & "Unexpected variable in dump - " // TRIM(identifier) ) diff --git a/src/io/dump/required_vars_for_rivers_mod.F90 b/src/io/dump/required_vars_for_rivers_mod.F90 index 01ff4e5b..a2ecbd40 100644 --- a/src/io/dump/required_vars_for_rivers_mod.F90 +++ b/src/io/dump/required_vars_for_rivers_mod.F90 @@ -17,7 +17,7 @@ SUBROUTINE required_vars_for_rivers( nvars, identifiers, & USE jules_rivers_mod, ONLY: l_outflow_per_river, i_river_vn, rivers_camaflood, & rivers_rfm, rivers_trip, l_init_storage, & - l_inland_outflow, l_minor_reservoirs + l_inland_outflow, l_reservoirs, l_minor_reservoirs USE logging_mod, ONLY: log_warn @@ -139,6 +139,15 @@ SUBROUTINE required_vars_for_rivers( nvars, identifiers, & END SELECT +IF ( l_reservoirs ) THEN + IF ( read_or_write_dump_local ) THEN + CALL add_to_list( 'res_storage', nvars, identifiers ) + ELSE + CALL log_warn( RoutineName, & + "Storage in reservoirs will be initialised to zero.") + END IF +END IF + IF ( l_minor_reservoirs ) THEN IF ( read_or_write_dump_local ) THEN CALL add_to_list( 'minor_res_storage', nvars, identifiers ) diff --git a/src/io/dump/write_dump_mod.F90 b/src/io/dump/write_dump_mod.F90 index cd5a19b8..d9c3649a 100644 --- a/src/io/dump/write_dump_mod.F90 +++ b/src/io/dump/write_dump_mod.F90 @@ -676,6 +676,7 @@ SUBROUTINE write_dump() 'seed_rain', 'ch4_ppbv' ) ! Nothing to do + CASE ( 'minor_res_storage', 'rivers_lat_rp', 'rivers_lon_rp', & 'rivers_sto_rp', 'rivers_x_coord_rp', 'rivers_y_coord_rp', & 'rfm_surfstore_rp', 'rfm_substore_rp', & @@ -683,7 +684,7 @@ SUBROUTINE write_dump() 'inland_outflow_rp', & 'flood_flow', 'flood_flow_prev', 'flood_storage', & 'flood_storage_prev', 'river_channel_flow', 'river_channel_storage', & - 'river_depth_prev', 'river_flow_prev' ) + 'river_depth_prev', 'river_flow_prev', 'res_storage' ) ! Rivers are run on a single task, hence nothing to do here. !------------------------------------------------------------------------- diff --git a/src/io/dump/write_dump_var_rivers_mod.F90 b/src/io/dump/write_dump_var_rivers_mod.F90 index 5e1eb987..a2eb6654 100644 --- a/src/io/dump/write_dump_var_rivers_mod.F90 +++ b/src/io/dump/write_dump_var_rivers_mod.F90 @@ -116,6 +116,9 @@ SUBROUTINE write_dump_var_rivers( identifier, FILE, var_id ) CASE ( 'inland_outflow_rp' ) CALL file_write_var(FILE, var_id, rivers%inland_outflow_rp) +CASE ( 'res_storage' ) + CALL file_write_var(FILE, var_id, rivers%res_storage) + CASE DEFAULT CALL log_fatal( RoutineName, & "Unrecognised variable for dump - " // TRIM(identifier) ) diff --git a/src/io/model_interface/extract_var.inc b/src/io/model_interface/extract_var.inc index 1b71d626..d8957573 100644 --- a/src/io/model_interface/extract_var.inc +++ b/src/io/model_interface/extract_var.inc @@ -2730,6 +2730,33 @@ CASE ( 'frac_fplain_lp' ) cube_land = cube_from_array(frac_fplain_lp) cube = map_from_land(cube_land) +CASE ( 'res_capacity' ) + cube = cube_from_array(rivers%res_capacity) + +CASE ( 'res_catch' ) + cube = cube_from_array(rivers%res_catch) + +CASE ( 'res_year' ) + cube = cube_from_array(rivers%res_year) + +CASE ( 'res_critical' ) + cube = cube_from_array(rivers%res_critical) + +CASE ( 'res_flood' ) + cube = cube_from_array(rivers%res_flood) + +CASE ( 'res_emergency' ) + cube = cube_from_array(rivers%res_emergency) + +CASE ( 'res_normal_release' ) + cube = cube_from_array(rivers%res_normal_release) + +CASE ( 'res_flood_release' ) + cube = cube_from_array(rivers%res_flood_release) + +CASE ( 'res_storage' ) + cube = cube_from_array(rivers%res_storage) + CASE ( 'minor_res_capacity' ) cube = cube_from_array(rivers%minor_res_capacity) @@ -3434,6 +3461,11 @@ CASE ( 'gw_nr_abstracted' ) cube_land = cube_from_array( water_resources%gw_nr_abstracted / timestep ) cube = map_from_land(cube_land) +CASE ( 'res_abstracted' ) + ! Convert kg to kg s-1. + cube_land = cube_from_array( water_resources%abstracted_res / timestep ) + cube = map_from_land(cube_land) + CASE ( 'minor_res_abstracted' ) ! Convert kg to kg s-1. cube_land = cube_from_array( water_resources%abstracted_minor_res / timestep ) diff --git a/src/io/model_interface/model_interface_mod.F90 b/src/io/model_interface/model_interface_mod.F90 index fcad6126..a2f49a43 100644 --- a/src/io/model_interface/model_interface_mod.F90 +++ b/src/io/model_interface/model_interface_mod.F90 @@ -176,7 +176,8 @@ MODULE model_interface_mod ! Array holding the metadata for all model variables that we can use for input ! or output. The CABLE land surface model adds 10 prognostics for tiled ! soil/snow prognostics. -INTEGER, PARAMETER :: n_vars = 731 + +INTEGER, PARAMETER :: n_vars = 749 TYPE(var_metadata) :: metadata(n_vars) ! Include the metadata DATA statement diff --git a/src/io/model_interface/populate_var.inc b/src/io/model_interface/populate_var.inc index e02a46ae..ee970a3f 100644 --- a/src/io/model_interface/populate_var.inc +++ b/src/io/model_interface/populate_var.inc @@ -35,7 +35,10 @@ USE jules_rivers_mod, ONLY: & channel_depth_grid, channel_width_grid, mean_sea_level_grid, & minor_res_capacity_grid, minor_res_frac_grid, river_distance_grid, & river_elevation_grid, river_length_grid, river_manning_grid, & - river_nextx_grid, river_nexty_grid + river_nextx_grid, river_nexty_grid, & + res_capacity_grid, res_catch_grid, res_year_grid, & + res_critical_grid, res_flood_grid, res_emergency_grid, & + res_normal_release_grid, res_flood_release_grid USE jules_soil_mod, ONLY: & sm_levels, l_tile_soil, l_broadcast_ancils @@ -2496,6 +2499,14 @@ CASE ( 'sea_level_lp' ) rivers%sea_level_lp(:) = const_val END IF +CASE ( 'res_storage' ) + IF ( PRESENT(cube) ) THEN + cube_land = cube_create([ SIZE(cube%values) ]) + CALL cube_get_data(cube_land, rivers%res_storage) + ELSE + rivers%res_storage(:) = const_val + END IF + !----------------------------------------------------------------------------- ! Overbank inundation variables !----------------------------------------------------------------------------- @@ -2521,6 +2532,62 @@ CASE ( 'logn_stdev' ) logn_stdev(:,:) = const_val END IF +CASE ( 'res_capacity_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_capacity_grid) + ELSE + res_capacity_grid(:,:) = const_val + END IF + +CASE ( 'res_catch_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_catch_grid) + ELSE + res_catch_grid(:,:) = const_val + END IF + +CASE ( 'res_year_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_year_grid) + ELSE + res_year_grid(:,:) = const_val + END IF + +CASE ( 'res_critical_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_critical_grid) + ELSE + res_critical_grid(:,:) = const_val + END IF + +CASE ( 'res_flood_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_flood_grid) + ELSE + res_flood_grid(:,:) = const_val + END IF + +CASE ( 'res_emergency_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_emergency_grid) + ELSE + res_emergency_grid(:,:) = const_val + END IF + +CASE ( 'res_normal_release_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_normal_release_grid) + ELSE + res_normal_release_grid(:,:) = const_val + END IF + +CASE ( 'res_flood_release_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, res_flood_release_grid) + ELSE + res_flood_release_grid(:,:) = const_val + END IF + CASE ( 'minor_res_capacity_grid' ) IF ( PRESENT(cube) ) THEN CALL cube_get_data(cube, minor_res_capacity_grid) diff --git a/src/io/model_interface/variable_metadata.inc b/src/io/model_interface/variable_metadata.inc index 86fd193f..90acdc78 100644 --- a/src/io/model_interface/variable_metadata.inc +++ b/src/io/model_interface/variable_metadata.inc @@ -9469,4 +9469,230 @@ DATA metadata(731) / var_metadata( & ! Units "kg s-1" & ) / +!----------------------------------------------------------------------------- +! Metadata for res_capacity_grid +!----------------------------------------------------------------------------- +DATA metadata(732) / var_metadata( & +! String identifier + 'res_capacity_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_catch_grid +!----------------------------------------------------------------------------- +DATA metadata(733) / var_metadata( & +! String identifier + 'res_catch_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_year_grid +!----------------------------------------------------------------------------- +DATA metadata(734) / var_metadata( & +! String identifier + 'res_year_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_critical_grid +!----------------------------------------------------------------------------- +DATA metadata(735) / var_metadata( & +! String identifier + 'res_critical_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_flood_grid +!----------------------------------------------------------------------------- +DATA metadata(736) / var_metadata( & +! String identifier + 'res_flood_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_emergency_grid +!----------------------------------------------------------------------------- +DATA metadata(737) / var_metadata( & +! String identifier + 'res_emergency_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_normal_release_grid +!----------------------------------------------------------------------------- +DATA metadata(738) / var_metadata( & +! String identifier + 'res_normal_release_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_flood_release_grid +!----------------------------------------------------------------------------- +DATA metadata(739) / var_metadata( & +! String identifier + 'res_flood_release_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_capacity +!----------------------------------------------------------------------------- +DATA metadata(740) / var_metadata( & +! String identifier + 'res_capacity', & +! Variable type + var_type_rp, & +! Long name + "Storage capacity of reservoirs", & +! Units + "kg" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_catch +!----------------------------------------------------------------------------- +DATA metadata(741) / var_metadata( & +! String identifier + 'res_catch', & +! Variable type + var_type_rp, & +! Long name + "Catchment area of reservoirs", & +! Units + "m2" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_year +!----------------------------------------------------------------------------- +DATA metadata(742) / var_metadata( & +! String identifier + 'res_year', & +! Variable type + var_type_rp, & +! Long name + "Initialisation year of reservoirs", & +! Units + "1" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_critical +!----------------------------------------------------------------------------- +DATA metadata(743) / var_metadata( & +! String identifier + 'res_critical', & +! Variable type + var_type_rp, & +! Long name + "Critical storage of reservoirs", & +! Units + "kg" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_flood +!----------------------------------------------------------------------------- +DATA metadata(744) / var_metadata( & +! String identifier + 'res_flood', & +! Variable type + var_type_rp, & +! Long name + "Flood storage of reservoirs", & +! Units + "kg" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_emergency +!----------------------------------------------------------------------------- +DATA metadata(745) / var_metadata( & +! String identifier + 'res_emergency', & +! Variable type + var_type_rp, & +! Long name + "Emergency storage of reservoirs", & +! Units + "kg" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_normal_release +!----------------------------------------------------------------------------- +DATA metadata(746) / var_metadata( & +! String identifier + 'res_normal_release', & +! Variable type + var_type_rp, & +! Long name + "Normal release rate of reservoirs", & +! Units + "kg s-1" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_flood_release +!----------------------------------------------------------------------------- +DATA metadata(747) / var_metadata( & +! String identifier + 'res_flood_release', & +! Variable type + var_type_rp, & +! Long name + "Flood release rate of reservoirs", & +! Units + "kg s-1" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_storage +!----------------------------------------------------------------------------- +DATA metadata(748) / var_metadata( & +! String identifier + 'res_storage', & +! Variable type + var_type_rp, & +! Long name + "Water stored in reservoirs", & +! Units + "kg" & + ) / +!----------------------------------------------------------------------------- +! Metadata for res_abstracted +!----------------------------------------------------------------------------- +DATA metadata(749) / var_metadata( & +! String identifier + 'res_abstracted', & +! Variable type + var_type_surface, & +! Long name + "Water abstracted from reservoirs", & +! Units + "kg s-1" & + ) / #endif diff --git a/src/science/river_routing/rivers_route_mod.F90 b/src/science/river_routing/rivers_route_mod.F90 index 6121b2b0..aa30b946 100644 --- a/src/science/river_routing/rivers_route_mod.F90 +++ b/src/science/river_routing/rivers_route_mod.F90 @@ -28,8 +28,9 @@ MODULE rivers_route_mod !############################################################################## -SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & - net_abstracted_river_rp, rivers ) +SUBROUTINE rivers_route_rp( sw_river_source, abstracted_res_rp, & + abstracted_minor_res_rp, net_abstracted_river_rp, & + rivers ) !------------------------------------------------------------------------------ ! @@ -43,7 +44,7 @@ SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & USE jules_rivers_mod, ONLY: & ! imported scalars with intent(in) - i_river_vn, l_minor_reservoirs, np_rivers, nstep_rivers, & + i_river_vn, l_reservoirs, l_minor_reservoirs, np_rivers, nstep_rivers, & rivers_camaflood, rivers_rfm, rivers_trip, rivers_type USE rivers_route_camaflood_mod, ONLY: & @@ -65,6 +66,8 @@ SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & jules_message, & jules_print +USE time_info_mod, ONLY: current_model_time + IMPLICIT NONE !------------------------------------------------------------------------------ @@ -76,6 +79,9 @@ SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & ! abstraction. REAL(KIND=real_jlslsm), INTENT(IN) :: & + abstracted_res_rp(:), & + ! Water abstracted from reservoirs over river timestep, on river + ! points (kg). abstracted_minor_res_rp(:), & ! Water abstracted from minor reservoirs over river timestep, on river ! points (kg). @@ -90,7 +96,11 @@ SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & !------------------------------------------------------------------------------ ! Local scalar variables !------------------------------------------------------------------------------ -INTEGER :: ip ! loop counter +INTEGER :: ip ! loop counter + +INTEGER :: year ! current model year +INTEGER, SAVE :: year_change = -1 +! year of last reservoir capacity update !------------------------------------------------------------------------------ ! Local array variables @@ -120,6 +130,19 @@ SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & rivers%rrun_rp(ip) = rivers%rrun_surf_rp(ip) + rivers%rrun_sub_surf_rp(ip) END DO +!------------------------------------------------------------------------------ +! Update reservoir capacities at the start and on each year change. +!------------------------------------------------------------------------------ +IF ( l_reservoirs ) THEN + CALL current_model_time(year=year) + IF ( year /= year_change ) THEN + CALL update_reservoirs( rivers%res_capacity, & + rivers%res_year, & + rivers%res_cap_current ) + year_change = year + END IF +END IF + !------------------------------------------------------------------------------ ! Call the routing science routine. !------------------------------------------------------------------------------ @@ -138,6 +161,7 @@ SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & CALL rivers_route_rfm( sw_river_source, net_abstracted_river_rp, & rivers%rrun_surf_rp, rivers%rrun_sub_surf_rp, & rivers%rflow_rp, baseflow, & + abstracted_res_rp, & ! imported river arrays rivers) CASE ( rivers_trip ) @@ -145,9 +169,18 @@ SUBROUTINE rivers_route_rp( sw_river_source, abstracted_minor_res_rp, & rivers%rrun_surf_rp, rivers%rrun_sub_surf_rp, & rivers%rflow_rp, baseflow, rivers%rivers_outflow_rp, & rivers%rivers_next_rp, rivers%rivers_seq_rp, & - rivers%rivers_sto_rp,rivers%rivers_boxareas_rp, & + rivers%rivers_sto_rp, rivers%rivers_boxareas_rp, & rivers%rivers_lat_rp, rivers%rivers_lon_rp, & - rivers%inland_outflow_rp, rivers%land_fraction_rp ) + rivers%inland_outflow_rp, rivers%land_fraction_rp, & + abstracted_res_rp, & + rivers%res_cap_current, & + rivers%res_catch, & + rivers%res_critical, rivers%res_flood, & + rivers%res_emergency, & + rivers%res_normal_release, & + rivers%res_flood_release, & + rivers%res_storage ) + CASE DEFAULT WRITE(jules_message,*) 'ERROR: rivers_drive: ' // & 'do not recognise i_river_vn=', i_river_vn @@ -363,4 +396,51 @@ END SUBROUTINE adjust_routestore !############################################################################## +SUBROUTINE update_reservoirs( res_capacity, res_year, & + res_cap_current ) + +USE jules_rivers_mod, ONLY: & +! imported scalars + np_rivers + +USE time_info_mod, ONLY: current_model_time + +IMPLICIT NONE + +!------------------------------------------------------------------------------ +! Array arguments with intent(in). +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN) :: & + res_capacity(np_rivers), & + ! Capacity of reservoirs (kg). + res_year(np_rivers) + ! Build year of reservoirs. + +!------------------------------------------------------------------------------ +! Array arguments with intent(inout). +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & + res_cap_current(np_rivers) + ! Capacity of currently active reservoirs (kg). + +!------------------------------------------------------------------------------ +! Local scalar variables. +!------------------------------------------------------------------------------ +INTEGER :: i ! Loop counter. +INTEGER :: year ! Current model year. + +!end of header +!------------------------------------------------------------------------------ +CALL current_model_time(year) + +DO i = 1, np_rivers + IF ( res_year(i) <= year ) THEN + res_cap_current(i) = res_capacity(i) + END IF +END DO + +END SUBROUTINE update_reservoirs + +!############################################################################## + END MODULE rivers_route_mod diff --git a/src/science/river_routing/rivers_route_rfm_mod.F90 b/src/science/river_routing/rivers_route_rfm_mod.F90 index d38b7c68..9e910407 100644 --- a/src/science/river_routing/rivers_route_rfm_mod.F90 +++ b/src/science/river_routing/rivers_route_rfm_mod.F90 @@ -66,13 +66,13 @@ MODULE rivers_route_rfm_mod SUBROUTINE rivers_route_rfm( sw_river_source, net_abstracted_river_rp, & sfc_runoff, sub_sfc_runoff, outflow, baseflow, & - rivers ) + abstracted_res_rp, rivers ) USE jules_rivers_mod, ONLY: & ! imported scalars nstep_rivers, np_rivers, river_mouth & ,rivers_first, rivers_length, runoff_factor, cland, criver, cbland & - ,cbriver, retl, retr, rfm_land, rfm_river, rfm_sea, & + ,cbriver, retl, retr, rfm_land, rfm_river, rfm_sea, l_reservoirs, & ! imported type rivers_type @@ -86,6 +86,10 @@ SUBROUTINE rivers_route_rfm( sw_river_source, net_abstracted_river_rp, & !----------------------------------------------------------------------------- +USE route_reservoirs_mod, ONLY: & +! imported procedures + route_reservoirs + USE um_types, ONLY: real_jlslsm IMPLICIT NONE @@ -104,7 +108,10 @@ SUBROUTINE rivers_route_rfm( sw_river_source, net_abstracted_river_rp, & ! average rate of surface runoff since last rivers call (kg m-2 s-1) REAL(KIND=real_jlslsm), INTENT(IN) :: sub_sfc_runoff(np_rivers) ! average rate of sub-surface runoff since last call (kg m-2 s-1) +REAL(KIND=real_jlslsm), INTENT(IN) :: abstracted_res_rp(:) + ! Water abstracted from reservoirs over river timestep (kg). +! Array arguments with intent(out) REAL(KIND=real_jlslsm), INTENT(OUT) :: outflow(np_rivers) ! rate of channel surface flow leaving gridbox (kg m-2 s-1) REAL(KIND=real_jlslsm), INTENT(OUT) :: baseflow(np_rivers) @@ -130,8 +137,10 @@ SUBROUTINE rivers_route_rfm( sw_river_source, net_abstracted_river_rp, & ! initial river flow [m3/s] ,dt & ! river routing model timestep (s) - ,dx + ,dx & ! distance between midpoints of neighbouring cells (m) + ,reservoir_flow + ! flow in and out of reservoir (kg s-1) REAL(KIND=real_jlslsm) :: & substore_n(np_rivers) & @@ -246,6 +255,25 @@ SUBROUTINE rivers_route_rfm( sw_river_source, net_abstracted_river_rp, & rn = rivers%rivers_next_rp(ip) landtype = rivers%rfm_land_rp(ip) + !------------------------------------------------------------------------------- + ! If reservoirs are considered and capacity > 0, route through reservoirs. + !------------------------------------------------------------------------------- + IF (l_reservoirs) THEN + IF (rivers%res_cap_current(ip) > 0.0) THEN + reservoir_flow = rivers%rfm_flowin_rp(ip) * 1000.0 / dt + CALL route_reservoirs(dt, abstracted_res_rp(ip), & + rivers%res_cap_current(ip), & + rivers%res_catch(ip), & + rivers%res_critical(ip), & + rivers%res_flood(ip), & + rivers%res_emergency(ip), & + rivers%res_normal_release(ip), & + rivers%res_flood_release(ip), & + rivers%res_storage(ip), reservoir_flow) + rivers%rfm_flowin_rp(ip) = reservoir_flow * dt / 1000.0 + END IF + END IF + IF (landtype == rfm_land) THEN !Gridcell is land ! land surface (Lewis et al. 2018:eqnB4) diff --git a/src/science/river_routing/rivers_route_trip_mod.F90 b/src/science/river_routing/rivers_route_trip_mod.F90 index 3aeeebd9..10c5e2ba 100644 --- a/src/science/river_routing/rivers_route_trip_mod.F90 +++ b/src/science/river_routing/rivers_route_trip_mod.F90 @@ -43,15 +43,18 @@ MODULE rivers_route_trip_mod SUBROUTINE rivers_route_trip( sw_river_source, net_abstracted_river_rp, & sfc_runoff, sub_sfc_runoff, outflow, baseflow, & rivers_outflow_rp, rivers_next_rp, & - rivers_seq_rp, rivers_sto_rp , & - rivers_boxareas_rp, & - rivers_lat_rp, rivers_lon_rp, & - inland_outflow_rp, land_fraction_rp ) + rivers_seq_rp, rivers_sto_rp, & + rivers_boxareas_rp, rivers_lat_rp, rivers_lon_rp,& + inland_outflow_rp, land_fraction_rp, & + abstracted_res_rp,res_cap_current, res_catch, & + res_critical, res_flood,res_emergency, & + res_normal_release, res_flood_release, & + res_storage ) USE jules_rivers_mod, ONLY: & ! imported scalars with intent(in) np_rivers,nstep_rivers,nseqmax,river_mouth,rivers_meander,rivers_speed, & - inland_drainage, l_inland_outflow + inland_drainage, l_inland_outflow, l_reservoirs USE rivers_utils, ONLY: & ! imported procedures @@ -62,12 +65,15 @@ SUBROUTINE rivers_route_trip( sw_river_source, net_abstracted_river_rp, & USE missing_data_mod, ONLY: imdi +USE route_reservoirs_mod, ONLY: & +! imported procedures + route_reservoirs + USE um_types, ONLY: real_jlslsm IMPLICIT NONE !----------------------------------------------------------------------------- - INTEGER, INTENT(IN) :: & sw_river_source ! A value > 0 indicates that rivers are used as a source of water for @@ -107,6 +113,28 @@ SUBROUTINE rivers_route_trip( sw_river_source, net_abstracted_river_rp, & ! Water storage (kg). REAL, INTENT(IN) :: land_fraction_rp(:) +REAL(KIND=real_jlslsm), INTENT(IN) :: & + abstracted_res_rp(np_rivers), & + ! Water abstracted from reservoirs over river timestep (kg). + res_cap_current(np_rivers), & + ! Storage capacity of reservoirs (kg). + res_catch(np_rivers), & + ! Upstream catchment area of reservoirs (m2). + res_critical(np_rivers), & + ! Critical storage threshold of reservoirs (kg). + res_flood(np_rivers), & + ! Flood storage threshold of reservoirs (kg). + res_emergency(np_rivers), & + ! Emergency storage threshold of reservoirs (kg). + res_normal_release(np_rivers), & + ! Normal release rate from reservoirs (kg s-1). + res_flood_release(np_rivers) + ! Flood release rate from reservoirs (kg s-1). + +REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & + res_storage(np_rivers) + ! Water stored in reservoirs (kg). + INTEGER :: & ! local scalars (work/loop counters) ip, iseq & @@ -205,6 +233,23 @@ SUBROUTINE rivers_route_trip( sw_river_source, net_abstracted_river_rp, & ! Get index (location in rivers vector) of the point to consider. IF ( rivers_seq_rp(ip) == iseq ) THEN + !------------------------------------------------------------------------------- + ! If reservoirs are considered and capacity > 0, route through them. + !------------------------------------------------------------------------------- + IF (l_reservoirs) THEN + IF (res_cap_current(ip) > 0.0) THEN + CALL route_reservoirs(dt, abstracted_res_rp(ip), & + res_cap_current(ip), & + res_catch(ip), & + res_critical(ip), & + res_flood(ip), & + res_emergency(ip), & + res_normal_release(ip), & + res_flood_release(ip), & + res_storage(ip), inflow(ip)) + END IF + END IF + !----------------------------------------------------------------------- ! Calculate the coefficient "c" of the model. ! c=u/(d*r), where u is effective flow speed, @@ -230,6 +275,8 @@ SUBROUTINE rivers_route_trip( sw_river_source, net_abstracted_river_rp, & !----------------------------------------------------------------------- outflow(ip) = inflow(ip) + (store_old - rivers_sto_rp(ip)) / dt + + !----------------------------------------------------------------------- ! Add outflow to inflow of next downstream point. !----------------------------------------------------------------------- diff --git a/src/science/river_routing/route_reservoirs_mod.F90 b/src/science/river_routing/route_reservoirs_mod.F90 new file mode 100644 index 00000000..4eaba18c --- /dev/null +++ b/src/science/river_routing/route_reservoirs_mod.F90 @@ -0,0 +1,142 @@ +!******************************COPYRIGHT************************************** +! (c) UK Centre for Ecology & Hydrology. +! All rights reserved. +! +! This routine has been licensed to the other JULES partners for use and +! distribution under the JULES collaboration agreement, subject to the terms +! and conditions set out therein. +! +! [Met Office Ref SC0237] +!******************************COPYRIGHT************************************** + +MODULE route_reservoirs_mod + +USE um_types, ONLY: real_jlslsm + +IMPLICIT NONE + +PRIVATE ! Private scope by default +PUBLIC route_reservoirs + +CONTAINS + +!############################################################################## + +SUBROUTINE route_reservoirs( dt, abstracted_res_rp, & + res_cap_current, & + res_catch, & + res_critical, res_flood, & + res_emergency, & + res_normal_release, & + res_flood_release, & + res_storage, reservoir_flow ) + +! Route runoff through reservoirs. + +USE jules_rivers_mod, ONLY: dt_rivers, nstep_rivers + +USE timestep_mod, ONLY: timestep + +IMPLICIT NONE +!------------------------------------------------------------------------------ +! Scalar arguments with INTENT(IN) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN) :: & + dt, & + ! Timestep of routing model (s) + abstracted_res_rp, & + ! Water abstracted from reservoirs (kg). + res_cap_current, & + ! Storage capacity of reservoirs (kg). + res_catch, & + ! Upstream catchment area of reservoirs (m2). + res_critical, & + ! Critical storage threshold of reservoirs (kg). + res_flood, & + ! Flood storage threshold of reservoirs (kg). + res_emergency, & + ! Emergency storage threshold of reservoirs (kg). + res_normal_release, & + ! Normal release rate from reservoirs (kg s-1). + res_flood_release + ! Flood release rate from reservoirs (kg s-1). + +!------------------------------------------------------------------------------ +! Scalar arguments with INTENT(IN OUT) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & + res_storage, & + ! Water stored in reservoirs (kg). + reservoir_flow + ! Flow in and out of reservoir (kg s-1) + +!------------------------------------------------------------------------------ +! Local scalar variables +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm) :: & + k + ! Release coefficient. + +!end of header +!------------------------------------------------------------------------------ + +! Update reservoir storage with inflow and abstractions +res_storage = res_storage + reservoir_flow * dt & + - abstracted_res_rp + +k = MAX( 0.0, 1.0 - (res_cap_current - res_storage) / 1000.0 & + / ( res_catch * 0.2 ) ) + +! Calculate reservoir release based on storage and inflow + +! Release calculation if inflow is not extremely high +IF (reservoir_flow < res_flood_release) THEN + + ! Calculate outflow depending on storage level + IF (res_storage <= res_critical) THEN + reservoir_flow = res_normal_release * & + res_storage / res_flood + ELSE IF (res_storage <= res_emergency) THEN + reservoir_flow = res_normal_release / 2.0 + & + ( (res_storage - res_critical) / & + (res_emergency - res_critical) ) ** 2.0 * & + ( res_flood_release - res_normal_release ) + ELSE + reservoir_flow = res_flood_release + END IF + + ! Release calculation if inflow is extremely high +ELSE + + ! Calculate outflow depending on storage level + IF (res_storage <= res_critical) THEN + reservoir_flow = res_normal_release * & + res_storage / res_flood + ELSE IF (res_storage <= res_flood) THEN + reservoir_flow = res_normal_release / 2.0 + & + (res_storage - res_critical) / & + (res_flood - res_critical) * & + ( res_flood_release - res_normal_release ) + ELSE IF (res_storage <= res_emergency) THEN + reservoir_flow = res_flood_release + k * & + (res_storage - res_flood) / & + (res_emergency - res_flood) * & + ( reservoir_flow - res_flood_release ) + ELSE + reservoir_flow = reservoir_flow + END IF + +END IF + +! Ensure that release never exceeds storage +reservoir_flow = MIN( reservoir_flow, res_storage/dt ) + +! Update reservoir storage with release +res_storage = res_storage - reservoir_flow * dt + +RETURN +END SUBROUTINE route_reservoirs + +!############################################################################## + +END MODULE route_reservoirs_mod diff --git a/src/science/water_resources/calc_avail_water_mod.F90 b/src/science/water_resources/calc_avail_water_mod.F90 index fba8cedc..3becdfd5 100644 --- a/src/science/water_resources/calc_avail_water_mod.F90 +++ b/src/science/water_resources/calc_avail_water_mod.F90 @@ -162,7 +162,8 @@ END SUBROUTINE calc_avail_groundwater !############################################################################## !############################################################################## -SUBROUTINE calc_avail_surface_water( minor_res_storage_global, & +SUBROUTINE calc_avail_surface_water( res_storage_global, & + minor_res_storage_global, & river_storage_global, & sw_avail_global ) @@ -174,10 +175,10 @@ SUBROUTINE calc_avail_surface_water( minor_res_storage_global, & USE model_grid_mod, ONLY: global_land_pts -USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_rivers +USE jules_rivers_mod, ONLY: l_reservoirs, l_minor_reservoirs, l_rivers USE jules_water_resources_mod, ONLY: n_sw_source, sw_minor_res_source, & - sw_river_source + sw_res_source, sw_river_source IMPLICIT NONE @@ -185,6 +186,8 @@ SUBROUTINE calc_avail_surface_water( minor_res_storage_global, & ! Array arguments with INTENT(IN). !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm), INTENT(IN) :: & + res_storage_global(global_land_pts), & + ! Water stored in reservoirs, on land points (kg). minor_res_storage_global(global_land_pts), & ! Water stored in minor reservoirs, on land points (kg). river_storage_global(global_land_pts) @@ -221,6 +224,11 @@ SUBROUTINE calc_avail_surface_water( minor_res_storage_global, & ! Include water available from rivers. sw_avail_global(:,sw_river_source) = river_storage_global(:) + IF ( l_reservoirs ) THEN + ! Include water stored in reservoirs. + sw_avail_global(:,sw_res_source) = res_storage_global(:) + END IF + IF ( l_minor_reservoirs ) THEN ! Include water stored in minor reservoirs. sw_avail_global(:,sw_minor_res_source) = minor_res_storage_global(:)