diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index db1cc110..d2b7fb23 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -2,6 +2,12 @@ | GitHub user | Real Name | Affiliation | Date | | --------------- | ---------------- | ----------- | ---------- | -| yaswant | Yaswant Pradhan | Met Office | 2026-06-30 | -| doucla | Douglas Clark | UKCEH | 2026-07-03 | -| james-bruten-mo | James Bruten | Met Office | 2026-07-09 | +| james-bruten-mo | James Bruten | Met Office | 2025-12-09 | +| ppharris | Phil Harris | UKCEH | 2025-12-18 | +| maggiehendry | Maggie Hendry | Met Office | 2026-01-26 | +| andrewcoughtrie | Andrew Coughtrie | Met Office | 2026-02-10 | +| yaswant | Yaswant Pradhan | Met Office | 2026-02-11 | +| ScottWales | Scott Wales | Bureau of Meteorology | 2026-02-16 | +| t00sa | Sam Clarke-Green | Met Office | 2026-02-27 | +| doucla | Douglas Clark | UKCEH | 2026-06-22 | +| KatieBlackford | Katie Blackford | UKCEH | 2026-08-21 | diff --git a/doc/source/namelists/ancillaries.nml.rst b/doc/source/namelists/ancillaries.nml.rst index 2b9bd9b2..6a3ce697 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 should be set. +This namelist specifies how spatially varying river routing properties (including overbank inundation and minor reservirs) 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`). @@ -1455,18 +1455,28 @@ The following table summarises river routing properties required to run RFM or T | ``longitude_2d`` | The longitude of each river grid point must be specified. This field is required only if the model | | | coordinates are latitude and longitude, i.e. if :nml:mem:`JULES_LATLON::l_coord_latlon` = FALSE. | +----------------------------+-----------------------------------------------------------------------------------------------------------+ -| ``logn_mean`` | Mean of ln(elevation-elev_min) for each grid cell (in units ln(m)) | +| ``logn_mean`` | Mean of ln(elevation-elev_min) for each grid cell (in units ln(m)). | | | | | | This is only used if :nml:mem:`JULES_OVERBANK::overbank_model` = 3. | | | | | | Note that elev_min is DEM minimum, not river/lake bed level (therefore large values close to water | | | bodies can occur in floodplain gridcells). | +----------------------------+-----------------------------------------------------------------------------------------------------------+ -| ``logn_stdev`` | Standard deviation of ln(elevation-elev_min) for each grid cell (in units ln(m)) | +| ``logn_stdev`` | Standard deviation of ln(elevation-elev_min) for each grid cell (in units ln(m)). | | | | | | 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. | | | | @@ -1479,7 +1489,7 @@ The following table summarises river routing properties required to run RFM or T | | via OASIS the river outflow is distributed over the corresponding river outflow points on the ocean grid. | | | This is to ensure that water is conserved and rivers discharge into the correct ocean grid points. | +----------------------------+-----------------------------------------------------------------------------------------------------------+ -| ``rivers_storage`` | Water storage (kg) on the Rivers grid. | +| ``rivers_storage`` | Water storage (kg) on the rivers grid. | | | | | | This is only used if :nml:mem:`JULES_RIVERS::i_river_vn` = 3. | | | | diff --git a/doc/source/namelists/initial_conditions.nml.rst b/doc/source/namelists/initial_conditions.nml.rst index 1fdffedb..ac129648 100644 --- a/doc/source/namelists/initial_conditions.nml.rst +++ b/doc/source/namelists/initial_conditions.nml.rst @@ -402,18 +402,18 @@ The required variables for a particular configuration, along with their 'type' a | Required if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::i_river_vn` = '2' and | | :nml:mem:`JULES_INITIAL::dump_file` = TRUE | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ -| ``rfm_surfstore_rp`` | Surface water storage on river routing points (m3) | none | +| ``rfm_surfstore_rp`` | Surface water storage on river routing points (m3). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ -| ``rfm_substore_rp`` | Sub-surface water storage on river routing points (m3) | none | +| ``rfm_substore_rp`` | Sub-surface water storage on river routing points (m3). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ -| ``rfm_flowin_rp`` | Surface flow into a grid box on river routing points (m3) | none | +| ``rfm_flowin_rp`` | Surface flow into a grid box on river routing points (m3). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ -| ``rfm_bflowin_rp`` | Sub-surface flow into a grid box on river routing points (m3) | none | +| ``rfm_bflowin_rp`` | Sub-surface flow into a grid box on river routing points (m3). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ | Required if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::i_river_vn` = '1,3' and | | :nml:mem:`JULES_INITIAL::dump_file` = TRUE | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ -| ``rivers_sto_rp`` | Water storage (kg) | none | +| ``rivers_sto_rp`` | Water storage (kg). | none | | | | | | | **Alternatively**, can be initialised from an ancillary file via | | | | :nml:lst:`JULES_RIVERS_PROPS`. It cannot be requested via :nml:lst:`JULES_INITIAL` | | @@ -423,7 +423,12 @@ The required variables for a particular configuration, along with their 'type' a | :nml:mem:`JULES_INITIAL::dump_file` = TRUE and :nml:mem:`OASIS_RIVERS::send_fields` or | | :nml:mem:`JULES_OUTPUT_PROFILE::var` contains ``outflow_per_river``. | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ -| ``rivers_outflow_rp`` | River outflow on river routing points (kg s\ :sup:`-1`) | none | +| ``rivers_outflow_rp`` | River outflow on river routing points (kg s\ :sup:`-1`). | 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 | ++----------------------------------+-----------------------------------------------------------------------------------------+---------+ +| ``minor_res_storage`` | Water stored in minor reservoirs, on river routing points (kg). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ | Required if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE, :nml:mem:`JULES_RIVERS::i_river_vn` = '3', | | :nml:mem:`JULES_INITIAL::dump_file` = TRUE and :nml:mem:`OASIS_RIVERS::send_fields` contains ``inland_outflow``. | @@ -432,7 +437,7 @@ The required variables for a particular configuration, along with their 'type' a +----------------------------------+-----------------------------------------------------------------------------------------+---------+ | Required if :nml:mem:`JULES_VEGETATION::photo_acclim_model` = 2 or 3 | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ -| ``t_growth_gb`` | Running mean air temperature (K) | none | +| ``t_growth_gb`` | Running mean air temperature (K). | none | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ @@ -444,6 +449,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_minor_reservoirs` = TRUE and :nml:mem:`JULES_INITIAL::dump_file` = FALSE, + ``minor_res_storage`` is initialised to zero. + .. |mu| unicode:: μ .. u diff --git a/doc/source/namelists/jules_rivers.nml.rst b/doc/source/namelists/jules_rivers.nml.rst index f5c5cc0f..19ecfb31 100644 --- a/doc/source/namelists/jules_rivers.nml.rst +++ b/doc/source/namelists/jules_rivers.nml.rst @@ -44,6 +44,21 @@ 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_minor_reservoirs + + :type: logical + :default: F + + Switch for enabling routing through minor reservoirs. Only used if :nml:mem:`JULES_RIVERS::l_rivers` is TRUE. + + TRUE + Surface runoff is routed through minor reservoirs before reaching the river network. + + FALSE + No minor reservoirs are modelled. + + .. nml:member:: l_riv_overbank :type: logical @@ -96,7 +111,7 @@ River routing introduces two more grids to a JULES run: the river routing input :type: real :permitted: > 0 :default: None - :suggested: 0.20 m/s (global), 0.40 m/s (1 km resolution, Bell et al. 2007) + :suggested: 0.20 m s\ :sup:`-1` (global), 0.40 m s\ :sup:`-1` (1 km resolution, Bell et al. 2007) The land wave speed (kinematic wave speed for surface flow in a land grid box on the river routing grid, m s\ :sup:`-1`). This is the speed at which water moves through surface soil in a non-river grid cell (even without major rivers, there are always minor water courses so these cells do still contribute flow to neighbouring cells). @@ -106,7 +121,7 @@ River routing introduces two more grids to a JULES run: the river routing input :type: real :permitted: > 0 :default: None - :suggested: 0.62 m/s (global), 0.50 m/s (1 km resolution, Bell et al. 2007) + :suggested: 0.62 m s\ :sup:`-1` (global), 0.50 m s\ :sup:`-1` (1 km resolution, Bell et al. 2007) The river wave speed (kinematic wave speed for surface flow in a river grid box on the river routing grid, m s\ :sup:`-1`). This value should be close to the :nml:mem:`rivers_speed` used by TRIP, but not identical because RFM makes different assumptions about e.g. meandering. @@ -116,7 +131,7 @@ River routing introduces two more grids to a JULES run: the river routing input :type: real :permitted: > 0 :default: None - :suggested: <= :nml:mem:`cland`. 0.10 m/s (global), 0.05 m/s (1 km resolution, Bell et al. 2007) + :suggested: <= :nml:mem:`cland`. 0.10 m s\ :sup:`-1` (global), 0.05 m s\ :sup:`-1` (1 km resolution, Bell et al. 2007) The subsurface land wave speed (kinematic wave speed for subsurface flow in a land grid box on the river routing grid, m s\ :sup:`-1`). @@ -126,7 +141,7 @@ River routing introduces two more grids to a JULES run: the river routing input :type: real :permitted: > 0 :default: None - :suggested: <= :nml:mem:`criver`. 0.15 m/s (global), 0.05 m/s (1 km resolution, Bell et al. 2007) + :suggested: <= :nml:mem:`criver`. 0.15 m s\ :sup:`-1` (global), 0.05 m s\ :sup:`-1` (1 km resolution, Bell et al. 2007) The subsurface river wave speed (kinematic wave speed for subsurface flow in a river grid box on the river routing grid, m s\ :sup:`-1`). diff --git a/doc/source/output-variables.rst b/doc/source/output-variables.rst index 1e337f3c..9d628759 100644 --- a/doc/source/output-variables.rst +++ b/doc/source/output-variables.rst @@ -471,10 +471,22 @@ Rivers | | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | | | :nml:mem:`JULES_RIVERS::i_river_vn` = 2. | | +-------------------------------+-----------------------------------------------------------------------------------------------+------------+ -| ``rivers_sto_rp`` | River routing gridbox river storage (kg) | np_rivers | +| ``rivers_sto_rp`` | River routing gridbox river storage (kg). | np_rivers | | | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | | | :nml:mem:`JULES_RIVERS::i_river_vn` = 3. | | +-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``minor_res_capacity`` | Storage capacity of minor reservoirs (kg). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``minor_res_frac`` | Catchment area of minor reservoirs as fraction of area of gridbox | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ +| ``minor_res_storage`` | Water stored in minor reservoirs (kg). | np_rivers | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE and | | +| | :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | | ++-------------------------------+-----------------------------------------------------------------------------------------------+------------+ | ``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. | | +-------------------------------+-----------------------------------------------------------------------------------------------+------------+ @@ -1301,10 +1313,7 @@ These variables are only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_r +---------------------------+--------------------------------------------------------------------------------+------------+ | Name | Description | Dimensions | +===========================+================================================================================+============+ -| ``conv_loss_frac`` | Fraction of abstracted water that is lost during conveyance from source to | | -| | user. | | -+---------------------------+--------------------------------------------------------------------------------+------------+ -| ``sfc_water_frac`` | Target for the fraction of demand to be met from surface water. | | +| Variables that quantify the demand for water: | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``demand_rate_domestic`` | Demand rate for water for domestic use (kg s\ :sup:`-1`). | | | | Only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_domestic` = TRUE. | | @@ -1318,9 +1327,6 @@ These variables are only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_r | ``demand_rate_transfers`` | Demand rate for water for transfers (kg s\ :sup:`-1`). | | | | Only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_transfers` = TRUE. | | +---------------------------+--------------------------------------------------------------------------------+------------+ -| ``water_demand`` | Demand for water across all water resource sectors (kg s\ :sup:`-1`), including| | -| | any allowance for conveyance loss. | | -+---------------------------+--------------------------------------------------------------------------------+------------+ | ``demand_domestic`` | Demand for water for domestic use (kg s\ :sup:`-1`), including any allowance | | | | for conveyance loss. | | | | Only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_domestic` = TRUE. | | @@ -1345,7 +1351,10 @@ These variables are only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_r | | conveyance loss. | | | | Only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_transfers` = TRUE. | | +---------------------------+--------------------------------------------------------------------------------+------------+ -| ``water_demand_unmet`` | The part of the total demand for water that is not satisfied (kg s\ :sup:`-1`).| | +| ``water_demand`` | Demand for water across all water resource sectors (kg s\ :sup:`-1`), including| | +| | any allowance for conveyance loss. | | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| Variables that quantify how much of the demand for water cannot be met: | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``unmet_domestic`` | The part of the demand for water for domestic use that is not satisfied | | | | (kg s\ :sup:`-1`). | | @@ -1371,18 +1380,42 @@ These variables are only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_r | | (kg s\ :sup:`-1`). | | | | Only available if :nml:mem:`JULES_WATER_RESOURCES::l_water_transfers` = TRUE. | | +---------------------------+--------------------------------------------------------------------------------+------------+ -| ``irrig_water`` | Water applied as irrigation (kg m\ :sup:`-2` s\ :sup:`-1`). | | -| | Only available if :nml:mem:`JULES_IRRIG::l_irrig_dmd` = TRUE. | | +| ``water_demand_unmet`` | The part of the total demand for water that is not satisfied (kg s\ :sup:`-1`).| | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| Variables that quantify how much water is available and abstracted: | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``gw_avail`` | Groundwater that is available for abstraction at start of timestep (kg) . | | +| | Only available if groundwater sources are modelled. | | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``sw_avail`` | Surface water that is available for abstraction at start of timestep (kg). | | +| | Only available if surface water sources are modelled. | | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``gw_abstracted`` | Water abstracted from renewable groundwater sources (kg s\ :sup:`-1`). | | +| | Only available if a suitable groundwater model is used. | | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``gw_nr_abstracted`` | Water abstracted from non-renewable groundwater sources (kg s\ :sup:`-1`). | | +| | Only available if a suitable groundwater model is used. | | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| ``minor_res_abstracted`` | Water abstracted from minor reservoirs (kg s\ :sup:`-1`). | | +| | Only available if :nml:mem:`JULES_RIVERS::l_minor_reservoirs` = TRUE. | | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| ``river_abstracted`` | Water abstracted from rivers (kg s\ :sup:`-1`). | | +| | Only available if :nml:mem:`JULES_RIVERS::l_rivers` = TRUE. | | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``sw_abstracted`` | Water abstracted from surface water sources (kg s\ :sup:`-1`). | | +| | Only available if surface water sources are modelled. | | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| ``irrig_water`` | Water applied as irrigation (kg m\ :sup:`-2` s\ :sup:`-1`). | | +| | Only available if :nml:mem:`JULES_IRRIG::l_irrig_dmd` = TRUE. | | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| Miscellaneous water resource variables: | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| ``conv_loss_frac`` | Fraction of abstracted water that is lost during conveyance from source to | | +| | user (an input to the model). | | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| ``conveyance_loss`` | Water that is lost during conveyance (kg s\ :sup:`-1`). | | ++---------------------------+--------------------------------------------------------------------------------+------------+ +| ``sfc_water_frac`` | Target for the fraction of demand to be met from surface water. | | +---------------------------+--------------------------------------------------------------------------------+------------+ | ``water_removed`` | Water that is removed from the system during use (kg s\ :sup:`-1`). | | +---------------------------+--------------------------------------------------------------------------------+------------+ diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index e30a27c5..05f31be2 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -2425,7 +2425,7 @@ 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','n_inorg','nsnow','ns','rfm_bflowin_rp', + ='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', @@ -4076,6 +4076,24 @@ value-titles=RFM,TRIP values=2,3 widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget +[namelist:jules_rivers=l_inland] +compulsory=true +description=Re-routing inland basin water back to soil moisture +help=Selecting 'Re-routing inland basin water back to soil moisture' is only + =applicable to the global river routing scheme 1A and fixes a bug where + =water from inland outflow points was previously 'lost' to the system on + =regridding. The re-routed water is held over until the next timestep + =and added to the change in top-level soil moisture. +sort-key=aa2 +type=logical + +[namelist:jules_rivers=l_minor_reservoirs] +compulsory=true +description=Switch to activate minor reservoirs +sort-key=a8 +type=logical +url=https://metoffice.github.io/jules/latest/namelists/jules_rivers.nml.html#JULES_RIVERS::l_minor_reservoirs + [namelist:jules_rivers=l_riv_overbank] compulsory=true description=Enable overbank inundation @@ -4091,6 +4109,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_inland: .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/versions.py b/rose-meta/jules-standalone/versions.py index 1d4c41a9..c7f423d0 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -45,15 +45,17 @@ from .version81_82 import * -class vnYY_txxxx(MacroUpgrade): +class vn82_t32(MacroUpgrade): - """Upgrade macro from JULES by Author""" + """Upgrade macro from JULES by Douglas Clark""" - BEFORE_TAG = "vnY.Y" - AFTER_TAG = "vnY.Y_txxxx" + BEFORE_TAG = "vn8.2" + AFTER_TAG = "vn8.2_t32" - def upgrade(self, config, meta_config=None): + def upgrade(self,config, meta_config=None): """Upgrade a JULES runtime app configuration.""" # Add settings + self.add_setting(config, ["namelist:jules_rivers", "l_minor_reservoirs"], ".false.") return config, self.reports + diff --git a/rose-stem/include/cehwl1/graph.cylc b/rose-stem/include/cehwl1/graph.cylc index d35e8781..62bbdbd8 100644 --- a/rose-stem/include/cehwl1/graph.cylc +++ b/rose-stem/include/cehwl1/graph.cylc @@ -235,13 +235,13 @@ "eraint" : ["eraint_rfm_2ddata", "eraint_trip_2ddata", "scripts"], - "gswp2_es" : ["gswp2_es_1p1", "gswp2_es_curr", "gswp2_es_beta", "scripts"], + "gswp2_es" : ["gswp2_es_1p1", "gswp2_es_curr", "gswp2_es_beta", "scripts"], "imogen" : ["imogen_layeredc","imogen_layeredc_co2conc", "imogen_layeredc_dtempg","imogen_layeredc_ch4", "scripts"], "tutorial" : ["loobos_crops"], - "scripts" : ["umdp3_check", "metadata_check", "site_validator"], + "scripts" : ["umdp3_check", "metadata_check", "site_validator"], } %} diff --git a/src/control/rivers-standalone/control_mod.F90 b/src/control/rivers-standalone/control_mod.F90 index 14d32fa3..15807d30 100644 --- a/src/control/rivers-standalone/control_mod.F90 +++ b/src/control/rivers-standalone/control_mod.F90 @@ -121,8 +121,14 @@ SUBROUTINE control ( & flowin(row_length, rows), & bflowin(row_length, rows), & twatstor(river_row_length, river_rows), & - net_abstracted_river(land_pts) - ! Net abstraction from rivers (kg m-2). + 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) + tot_abstracted_minor_res_global(land_pts), & + ! Water abstracted from minor reservoirs over river timestep (kg). + tot_net_abstracted_river_global(land_pts) + ! Water abstracted from rivers over river timestep (kg m-2). REAL(KIND=real_jlslsm) :: & !Passed between river routing and UM diagnostics_riv only @@ -137,8 +143,11 @@ SUBROUTINE control ( & !------------------------------------------------------------------------------ !End of header -! Abstraction of water is zero in rivers-only configuration. -net_abstracted_river(:) = 0.0 +! Abstractions of water are zero in rivers-only configuration. +abstracted_minor_res_global(:) = 0.0 +net_abstracted_river_global(:) = 0.0 +tot_abstracted_minor_res_global(:) = 0.0 +tot_net_abstracted_river_global(:) = 0.0 SELECT CASE ( lsm_id ) CASE ( rivers ) @@ -146,13 +155,15 @@ SUBROUTINE control ( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - net_abstracted_river, fluxes%sub_surf_roff_gb, fluxes%surf_roff_gb, & + 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) a_steps_since_riv, & !REAL, INTENT (INOUT) river%tot_surf_runoff_gb, river%tot_sub_runoff_gb, & - river%acc_lake_evap_gb, & + tot_abstracted_minor_res_global, & + tot_net_abstracted_river_global, river%acc_lake_evap_gb, & wtrac_jls%tot_surf_runoff_gb, wtrac_jls%tot_sub_runoff_gb, & wtrac_jls%acc_lake_evap_gb, & !REAL, INTENT (OUT) diff --git a/src/control/shared/jules_rivers_mod.F90 b/src/control/shared/jules_rivers_mod.F90 index 38b019f9..db0b8958 100644 --- a/src/control/shared/jules_rivers_mod.F90 +++ b/src/control/shared/jules_rivers_mod.F90 @@ -122,6 +122,12 @@ MODULE jules_rivers_mod LOGICAL :: & l_rivers = .FALSE. & ! Switch for runoff routing + ,l_inland = .FALSE. & + ! Control rerouting of inland basin water + ,l_minor_reservoirs = .FALSE. & + ! Switch for minor_reservoirs. + ! .TRUE. = consider minor reservoirs + ! .FALSE. = do not consider minor reservoirs ,l_riv_overbank = .FALSE. & ! Logical to control overbank inundation ,l_outflow_per_river = .FALSE. & @@ -238,7 +244,8 @@ MODULE jules_rivers_mod ! Single namelist definition for UM and standalone !------------------------------------------------------------------------------ NAMELIST /jules_rivers/ & - l_rivers, l_riv_overbank, l_adapt_timestep, l_sea_level, & + l_rivers, l_inland, l_minor_reservoirs, l_riv_overbank, & + l_adapt_timestep, l_sea_level, & l_vary_sea_level, i_river_vn, nstep_rivers, & trip_globe_shape, & cland, criver, cbland, cbriver, runoff_factor, retl, retr, & @@ -408,6 +415,15 @@ MODULE jules_rivers_mod river_manning_grid(:,:) ! Manning roughness coefficient for river channel (1). +!------------------------------------------------------------------------------ +! Ancillary arrays for minor reservoirs, defined on 2D rivers grid. +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), ALLOCATABLE :: & + minor_res_capacity_grid(:,:), & + ! Storage capacity of minor reservoirs (kg). + minor_res_frac_grid(:,:) + ! Catchment area of minor reservoirs as fraction of area. + CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='JULES_RIVERS_MOD' !------------------------------------------------------------------------------ @@ -545,6 +561,30 @@ MODULE jules_rivers_mod REAL(KIND=real_jlslsm), ALLOCATABLE :: river_depth(:) ! Depth of water in river channel (m). + !---------------------------------------------------------------------------- + ! Minor reservoir ancillary variables, defined on river points. + !---------------------------------------------------------------------------- + REAL(KIND=real_jlslsm), ALLOCATABLE :: minor_res_capacity(:) + ! Storage capacity of minor reservoirs (kg). + REAL(KIND=real_jlslsm), ALLOCATABLE :: minor_res_frac(:) + ! Catchment area of minor reservoirs as fraction of area. + + !---------------------------------------------------------------------------- + ! Minor reservoir prognostic variables, defined on river points. + !---------------------------------------------------------------------------- + REAL(KIND=real_jlslsm), ALLOCATABLE :: minor_res_storage(:) + ! Water stored in minor reservoirs (kg). + + !---------------------------------------------------------------------------- + ! Variables for coupling with water resources. + !---------------------------------------------------------------------------- + REAL, ALLOCATABLE :: tot_abstracted_minor_res_global(:) + ! Water abstracted from minor reservoirs over river + ! timestep, on global land points (kg). + REAL, ALLOCATABLE :: tot_net_abstracted_river_global(:) + ! Water abstracted from rivers over river timestep, + ! on global land points(kg m-2). + ! Ancillary arrays defined on full 2D rivers grid. REAL(KIND=real_jlslsm), ALLOCATABLE :: rivers_seq(:,:) ! River routing pathway sequence @@ -645,6 +685,11 @@ MODULE jules_rivers_mod REAL(KIND=real_jlslsm), POINTER :: river_channel_storage(:) REAL(KIND=real_jlslsm), POINTER :: river_flow_prev(:) REAL(KIND=real_jlslsm), POINTER :: river_depth(:) + REAL(KIND=real_jlslsm), POINTER :: minor_res_capacity(:) + REAL(KIND=real_jlslsm), POINTER :: minor_res_frac(:) + REAL(KIND=real_jlslsm), POINTER :: minor_res_storage(:) + REAL(KIND=real_jlslsm), POINTER :: tot_abstracted_minor_res_global(:) + REAL(KIND=real_jlslsm), POINTER :: tot_net_abstracted_river_global(:) REAL(KIND=real_jlslsm), POINTER :: rivers_seq(:,:) REAL(KIND=real_jlslsm), POINTER :: rivers_dir(:,:) REAL(KIND=real_jlslsm), POINTER :: rivers_dra(:,:) @@ -670,7 +715,8 @@ MODULE jules_rivers_mod !############################################################################## -SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, rivers_data) +SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & + sw_river_source, l_water_resources, rivers_data) !No USE statements other than Dr Hook USE parkind1, ONLY: jprb, jpim @@ -680,6 +726,10 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, rivers_data) !Arguments INTEGER, INTENT(IN) :: land_pts, t_i_length, t_j_length +INTEGER, INTENT(IN) :: sw_river_source + ! Index of river water in surface water source arrays. +LOGICAL, INTENT(IN) :: l_water_resources + ! Switch to select water resource management modelling. TYPE(rivers_data_type), INTENT(IN OUT) :: rivers_data !Local variables @@ -1174,6 +1224,10 @@ SUBROUTINE print_nlist_jules_rivers() WRITE(lineBuffer,*)' l_rivers = ',l_rivers CALL jules_print('jules_rivers',lineBuffer) +WRITE(lineBuffer,*)' l_inland = ',l_inland +CALL jules_print('jules_rivers',lineBuffer) +WRITE(lineBuffer,*)' l_minor_reservoirs = ',l_minor_reservoirs +CALL jules_print('jules_rivers',lineBuffer) WRITE(lineBuffer,*)' l_riv_overbank = ',l_riv_overbank CALL jules_print('jules_rivers',lineBuffer) WRITE(lineBuffer,*)' i_river_vn = ',i_river_vn @@ -1315,7 +1369,7 @@ SUBROUTINE read_nml_jules_rivers(unit_in) INTEGER, PARAMETER :: no_of_types = 3 INTEGER, PARAMETER :: n_int = 5 INTEGER, PARAMETER :: n_real = 12 -INTEGER, PARAMETER :: n_log = 5 +INTEGER, PARAMETER :: n_log = 7 TYPE :: my_namelist SEQUENCE @@ -1337,6 +1391,8 @@ 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_inland + LOGICAL :: l_minor_reservoirs LOGICAL :: l_riv_overbank LOGICAL :: l_rivers LOGICAL :: l_sea_level @@ -1375,6 +1431,8 @@ 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_inland = l_inland + my_nml % l_minor_reservoirs = l_minor_reservoirs my_nml % l_riv_overbank = l_riv_overbank my_nml % l_rivers = l_rivers my_nml % l_sea_level = l_sea_level @@ -1402,6 +1460,8 @@ 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_inland = my_nml % l_inland + l_minor_reservoirs = my_nml % l_minor_reservoirs l_riv_overbank = my_nml % l_riv_overbank l_rivers = my_nml % l_rivers l_sea_level = my_nml % l_sea_level @@ -1589,7 +1649,7 @@ SUBROUTINE rivers_nullify(rivers) NULLIFY(rivers%rivers_sto_per_m2_on_landpts) NULLIFY(rivers%rivers_adj_on_landpts) #if defined(UM_JULES) -NULLIFY(rivers%map_river_to_land_points) +NULLIFY(rivers%map_river<_to_land_points) NULLIFY(rivers%global_land_index) NULLIFY(rivers%rfm_iarea_rp) NULLIFY(rivers%rfm_land_rp) diff --git a/src/control/shared/jules_water_resources_mod.F90 b/src/control/shared/jules_water_resources_mod.F90 index 2b44c3bb..9379a1bd 100644 --- a/src/control/shared/jules_water_resources_mod.F90 +++ b/src/control/shared/jules_water_resources_mod.F90 @@ -188,6 +188,8 @@ MODULE jules_water_resources_mod !---------------------------------------------------------------------------- sw_river_source = 0, & ! Index of river water in surface water source arrays. + sw_minor_res_source = 0, & + ! Index of minor reservoirs in surface water source arrays. use_domestic = 0, & ! Index of domestic use in multi-use arrays. use_environment = 0, & @@ -205,12 +207,12 @@ MODULE jules_water_resources_mod LOGICAL :: & l_have_groundwater = .FALSE., & - ! Flag indicating if we have a model of groundwater (renewable or - ! non-renewable). + ! Flag indicating if groundwater sources (renewable or non-renewable) are + ! represented. l_have_renew_gwater = .FALSE., & ! Flag indicating if we have a model of renewable groundwater. l_have_surface_water = .FALSE. - ! Flag indicating if we have surface water represented (e.g. rivers). + ! Flag indicating if surface water sources (e.g. rivers) are represented. ! TRUE means n_sw_source > 0. CONTAINS @@ -224,6 +226,7 @@ SUBROUTINE check_jules_water_resources( l_top ) USE jules_print_mgr, ONLY: jules_message +! This dependency on jules_rivers_mod is not ideal. USE jules_rivers_mod, ONLY: l_rivers !------------------------------------------------------------------------------ @@ -548,16 +551,6 @@ SUBROUTINE check_jules_water_resources( l_top ) END IF ! l_have_surface_water .AND. l_have_groundwater - ! Check that any surface water sources include rivers - so that we know we - ! can add return flow to rivers. At present this is guaranteed because rivers - ! are the only possible surface water source that has been coded. - ! The dependency on jules_rivers_mod here is not ideal. - IF ( l_have_surface_water .AND. .NOT. l_rivers ) THEN - error_status = 101 ! a fatal error - CALL ereport ( RoutineName, error_status, & - "Rivers must be included in any surface water sources." ) - END IF - END IF ! l_water_resources END SUBROUTINE check_jules_water_resources @@ -572,7 +565,8 @@ SUBROUTINE set_jules_water_resources( l_top ) ! Sets values related to water resource code. !------------------------------------------------------------------------------ -USE jules_rivers_mod, ONLY: l_rivers +! This dependency on jules_rivers_mod is not ideal. +USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_rivers IMPLICIT NONE @@ -635,16 +629,18 @@ SUBROUTINE set_jules_water_resources( l_top ) !---------------------------------------------------------------------------- ! Set index for each available surface water source to show position in - ! surface water arrays. - ! At present there is only one possible source, but others will follow. + ! surface water arrays. If a source exists, it is used. !---------------------------------------------------------------------------- ! Initialise as no surface water sources. n_sw_source = 0 IF ( l_rivers ) THEN - ! If rivers are modelled, they are always included as a source of water. n_sw_source = n_sw_source + 1 sw_river_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 + END IF ! Set surface water flag if we have any surface water sources. IF ( n_sw_source > 0 ) THEN @@ -857,8 +853,8 @@ SUBROUTINE read_nml_jules_water_resources (unitnumber) nr_gwater_model = my_nml % nr_gwater_model nstep_water_res = my_nml % nstep_water_res partition_method = my_nml % partition_method - l_water_domestic = my_nml % l_water_domestic l_prioritise = my_nml % l_prioritise + l_water_domestic = my_nml % l_water_domestic l_water_environment = my_nml % l_water_environment l_water_industry = my_nml % l_water_industry l_water_irrigation = my_nml % l_water_irrigation diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index 4b52d3c1..eb4148fd 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -79,7 +79,8 @@ SUBROUTINE surf_couple_extra( & zw_soilt, sthzw_soilt, & ls_rainfrac_gb, & substore, surfstore, flowin, bflowin, & - tot_surf_runoff_gb, tot_sub_runoff_gb, acc_lake_evap_gb, twatstor, & + tot_surf_runoff_gb, tot_sub_runoff_gb, & + acc_lake_evap_gb, twatstor, & asteps_since_triffid, & inlandout_atm_gb, & !OUT @@ -122,7 +123,7 @@ SUBROUTINE surf_couple_extra( & USE water_resources_vars_mod, ONLY: water_resources_type USE jules_wtrac_type_mod, ONLY: jls_wtrac_type -! In general CABLE utilizes a required subset of tbe JULES types, however; +! In general CABLE utilizes a required subset of the JULES types, however; USE work_vars_mod_cbl, ONLY: work_vars_type ! and some kept thru timestep !Import interfaces to subroutines called @@ -248,7 +249,9 @@ SUBROUTINE surf_couple_extra( & #if defined(UM_JULES) && !defined(LFRIC) USE atm_fields_mod, ONLY: disturb_veg_prev -USE atm_step_local, ONLY: STASHwork19, STASHwork8, STASHwork26 +USE atm_land_sea_mask, ONLY: global_land_pts => atmos_number_of_landpts + +USE atm_step_local, ONLY: STASHwork19, STASHwork8, STASHwork26 USE model_domain_mod, ONLY: model_type, mt_single_column @@ -263,7 +266,7 @@ SUBROUTINE surf_couple_extra( & USE metstats_mod, ONLY: metstats_prog, l_metstats -USE model_grid_mod, ONLY: grid_area_ij +USE model_grid_mod, ONLY: global_land_pts, grid_area_ij USE model_time_mod, ONLY: current_time #endif @@ -388,6 +391,7 @@ SUBROUTINE surf_couple_extra( & acc_lake_evap_gb(row_length,rows), & tot_surf_runoff_gb(land_pts), & tot_sub_runoff_gb(land_pts), & + ! Water abstracted from minor reservoirs over river timestep (kg). twatstor(river_row_length, river_rows), & inlandout_atm_gb(land_pts) @@ -841,7 +845,7 @@ SUBROUTINE surf_couple_extra( & #if !defined(UM_JULES) ! Water resources (standalone; not yet allowed in UM). IF ( l_water_resources ) THEN - CALL water_resources_control( & + CALL water_resources_control( global_land_pts, & rivers%global_land_index, ainfo%land_index, & rivers%map_river_to_land_points, rivers%rivers_index_rp, & forcing%con_rain_ij, forcing%con_snow_ij, & @@ -853,24 +857,29 @@ 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%rfm_surfstore_rp, rivers%rivers_sto_rp, & psparms%smvccl_soilt, & psparms%smvcst_soilt, psparms%smvcwt_soilt, psparms%sthf_soilt, & fluxes%sw_surft, forcing%tl_1_ij, progs%tstar_surft, & crop_vars%icntmax_gb, crop_vars%plant_n_gb, & water_resources%demand_accum, & crop_vars%prec_1_day_av_gb, crop_vars%prec_1_day_av_use_gb, & - rivers%rfm_surfstore_rp, rivers%rivers_sto_rp, & crop_vars%rn_1_day_av_gb, & crop_vars%rn_1_day_av_use_gb, water_resources%sfc_water_frac, & progs%smcl_soilt, & crop_vars%sthu_irr_soilt, psparms%sthu_soilt, & 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%demand_unmet, water_resources%gw_abstracted, & - water_resources%gw_avail, water_resources%gw_nr_abstracted, & - crop_vars%irrig_water_gb, water_resources%net_abstracted_river, & - water_resources%sw_abstracted, water_resources%sw_avail_total, & - water_resources%water_removed ) + crop_vars%tl_1_day_av_use_gb, & + water_resources%priority_order, & + water_resources%abstracted_minor_res_global, & + water_resources%net_abstracted_river_global, & + water_resources%gw_abstracted, crop_vars%irrig_water_gb, & + water_resources%abstracted_minor_res, & + water_resources%abstracted_river, water_resources%conveyance_loss, & + water_resources%demand_unmet, water_resources%gw_avail, & + water_resources%gw_nr_abstracted, water_resources%sw_abstracted, & + water_resources%sw_avail_total, water_resources%water_removed ) END IF #endif @@ -879,13 +888,16 @@ SUBROUTINE surf_couple_extra( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - water_resources%net_abstracted_river, & + water_resources%abstracted_minor_res_global, & + water_resources%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) 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, & + rivers%tot_abstracted_minor_res_global, & + rivers%tot_net_abstracted_river_global, acc_lake_evap_gb, & wtrac_jls%tot_surf_runoff_gb, wtrac_jls%tot_sub_runoff_gb, & wtrac_jls%acc_lake_evap_gb, & !REAL, INTENT (OUT) diff --git a/src/control/shared/surf_couple_rivers_mod.F90 b/src/control/shared/surf_couple_rivers_mod.F90 index 56f5740b..0b7a2738 100644 --- a/src/control/shared/surf_couple_rivers_mod.F90 +++ b/src/control/shared/surf_couple_rivers_mod.F90 @@ -18,12 +18,13 @@ SUBROUTINE surf_couple_rivers( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - net_abstracted_river, & + 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, tot_abstracted_minor_res_global, & + tot_net_abstracted_river_global, acc_lake_evap_gb, & tot_surf_runoff_gb_wtrac, tot_sub_runoff_gb_wtrac, & acc_lake_evap_gb_wtrac, & !REAL, INTENT (OUT) @@ -56,7 +57,8 @@ 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_riv_overbank, & + rivers_type, l_minor_reservoirs, & + l_riv_overbank, & l_vary_sea_level, & ! UM only l_inland_outflow, rivers_um_trip, & @@ -80,6 +82,8 @@ SUBROUTINE surf_couple_rivers( & USE rivers_regrid_mod, ONLY: landpts_to_rivpts, rivpts_to_landpts +USE jules_water_resources_mod, ONLY: l_water_resources, sw_river_source + USE jules_water_tracers_mod, ONLY: l_wtrac_jls !Module imports - Variables required only in UM-mode @@ -145,7 +149,9 @@ SUBROUTINE surf_couple_rivers( & a_steps_since_riv REAL(KIND=real_jlslsm), INTENT(IN) :: & - net_abstracted_river(land_pts), & + abstracted_minor_res_global(global_land_pts), & + ! Water abstracted from minor reservoirs (kg). + net_abstracted_river_global(global_land_pts), & ! Net abstraction from rivers (kg m-2). surf_roff(land_pts), & ! Surface runoff (kg m-2 s-1) @@ -185,6 +191,10 @@ SUBROUTINE surf_couple_rivers( & ! Average rate of surface runoff over river timestep (kg m-2 s-1). tot_sub_runoff_gb(land_pts), & ! Average rate of subsurface runoff over river timestep (kg m-2 s-1). + tot_abstracted_minor_res_global(global_land_pts), & + ! Water abstracted from minor reservoirs over river timestep (kg). + tot_net_abstracted_river_global(global_land_pts), & + ! Water abstracted from rivers over river timestep (kg m-2). acc_lake_evap_gb(row_length,rows), & tot_surf_runoff_gb_wtrac(land_pts,n_wtrac_jls), & tot_sub_runoff_gb_wtrac(land_pts,n_wtrac_jls), & @@ -235,6 +245,11 @@ 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_minor_res_rp(:) + ! Water abstracted from minor reservoirs over river timestep, on river points + ! (kg). +REAL(KIND=real_jlslsm), ALLOCATABLE :: net_abstracted_river_rp(:) + ! Water abstracted from rivers over river timestep, on river points (kg m-2). #if defined(UM_JULES) REAL(KIND=real_jlslsm) :: & @@ -244,17 +259,17 @@ SUBROUTINE surf_couple_rivers( & REAL(KIND=real_jlslsm), ALLOCATABLE :: inlandout_atmos_wtrac(:,:,:) ! inlandout_atmos_gb_wtrac on (i,j) grid -REAL(KIND=real_jlslsm), ALLOCATABLE :: net_abstracted_river_wtrac(:,:) - ! Net abstraction of water tracers from rivers - ! (kg m-2). !Local variables INTEGER :: & ERROR, & - ! Error status from each call to ALLOCATE. + ! Error status from each call to ALLOCATE. error_sum, & - ! Accumulated error status. - l,i,j,ip,i_wt + ! Accumulated error status. + l,i,j,ip,i_wt, & + ! Counters + tmp_land_size, tmp_river_size + ! Sizes used in allocation. #if defined(UM_JULES) REAL(KIND=real_jlslsm) :: & @@ -283,10 +298,8 @@ SUBROUTINE surf_couple_rivers( & ! Allocate water tracer fields IF (l_wtrac_jls) THEN ALLOCATE(inlandout_atmos_wtrac(row_length,rows,n_wtrac_jls)) - ALLOCATE(net_abstracted_river_wtrac(land_pts,n_wtrac_jls)) ELSE ALLOCATE(inlandout_atmos_wtrac(1,1,1)) - ALLOCATE(net_abstracted_river_wtrac(1,1)) END IF #if defined(UM_JULES) @@ -323,9 +336,11 @@ SUBROUTINE surf_couple_rivers( & #endif -!Initialise the accumulated surface and subsurface runoff to zero -!at the beginning of river routing timestep +! Initialise accumulated fluxes to zero at the beginning of river routing +! timestep. IF ( a_steps_since_riv == 0 ) THEN + + ! Initialise the accumulated surface and subsurface runoff. tot_surf_runoff_gb(:) = 0.0 tot_sub_runoff_gb(:) = 0.0 acc_lake_evap_gb(:,:) = 0.0 @@ -348,7 +363,22 @@ SUBROUTINE surf_couple_rivers( & rivers%rrun_sub_surf_rp(:) = 0.0 rivers%rrun_surf_rp(:) = 0.0 END IF -END IF + + ! These "global" arrays are only allocated at full size on the master task, + ! so they must only be accessed there. + IF ( is_master_task() ) THEN + ! Initialise the accumulated abstraction from rivers. + IF ( sw_river_source > 0 ) THEN + tot_net_abstracted_river_global(:) = 0.0 + END IF + + ! Initialise the accumulated abstraction from minor reservoirs. + IF ( l_water_resources .AND. l_minor_reservoirs ) THEN + tot_abstracted_minor_res_global(:) = 0.0 + END IF + END IF + +END IF ! a_steps_since_riv == 0 ! Increment counters. a_steps_since_riv = a_steps_since_riv + 1 @@ -359,33 +389,48 @@ SUBROUTINE surf_couple_rivers( & rivers_call = .FALSE. END IF -!Accumulate the runoff as Kg/m2/s over the River Routing period (that is, -! between calls to river routing). +! Accumulate input fluxes over the river routing period (that is, between calls +! to river routing). IF (l_oasis_rivers) THEN - CALL accumulate_runoff(np_rivers, net_abstracted_river, & + ! Accumulate runoff (on river points). + CALL accumulate_runoff(np_rivers, & rivers%surf_roff_rp, rivers%sub_surf_roff_rp, & rivers%rrun_surf_rp, rivers%rrun_sub_surf_rp) ELSE - CALL accumulate_runoff(land_pts, net_abstracted_river, & + ! Accumulate runoff (on land points). + CALL accumulate_runoff(land_pts, & surf_roff, sub_surf_roff, & tot_surf_runoff_gb, tot_sub_runoff_gb) ! Repeat for water tracers IF (l_wtrac_jls) THEN - ! Water tracers are not yet represented in the water resources code, hence - ! set net abstraction of tracers to zero. - net_abstracted_river_wtrac(:,:) = 0.0 DO i_wt = 1, n_wtrac_jls - CALL accumulate_runoff(land_pts, net_abstracted_river_wtrac(:,i_wt), & + CALL accumulate_runoff(land_pts, & surf_roff_wtrac(:,i_wt), sub_surf_roff_wtrac(:,i_wt), & tot_surf_runoff_gb_wtrac(:,i_wt), & tot_sub_runoff_gb_wtrac(:,i_wt)) END DO END IF ! l_wtrac_jls + ! These "global" arrays are only allocated at full size on the master task, + ! so they must only be accessed there. + IF ( is_master_task() ) THEN + ! Accumulate net abstraction from rivers. + IF ( sw_river_source > 0 ) THEN + CALL accumulate_abstraction( global_land_pts, net_abstracted_river_global, & + tot_net_abstracted_river_global ) + END IF + + ! Accumulate abstraction from minor reservoirs. + IF ( l_water_resources .AND. l_minor_reservoirs ) THEN + CALL accumulate_abstraction( global_land_pts, abstracted_minor_res_global, & + tot_abstracted_minor_res_global ) + END IF + END IF + END IF ! l_oasis_rivers) ! Could this UM ifdef be replaced with the i_rivers_vn switch? @@ -501,54 +546,86 @@ SUBROUTINE surf_couple_rivers( & END IF #endif !-------------------------------------------------------------------------- - ! Gather runoff information from all processors + ! Allocate coupling arrays. + ! These are global land point arrays or river point arrays. !-------------------------------------------------------------------------- - + ! Allocate runoff arrays. IF (.NOT. l_oasis_rivers .AND. is_master_task()) THEN - ALLOCATE(global_tot_sub_runoff(global_land_pts), STAT = ERROR) - error_sum = ERROR - ALLOCATE(global_tot_surf_runoff(global_land_pts), STAT = ERROR) - error_sum = error_sum + ERROR - ALLOCATE(global_rrun(global_land_pts), STAT = ERROR) - error_sum = error_sum + ERROR - ALLOCATE(global_rflow(global_land_pts), STAT = ERROR) - error_sum = error_sum + ERROR + tmp_land_size = global_land_pts ELSE - ALLOCATE(global_tot_sub_runoff(1), STAT = ERROR) - error_sum = ERROR - ALLOCATE(global_tot_surf_runoff(1), STAT = ERROR) - error_sum = error_sum + ERROR - ALLOCATE(global_rrun(1), STAT = ERROR) - error_sum = error_sum + ERROR - ALLOCATE(global_rflow(1), STAT = ERROR) - error_sum = error_sum + ERROR + ! Allocate at minimum size. + tmp_land_size = 1 END IF - + ALLOCATE(global_tot_sub_runoff(tmp_land_size), STAT = ERROR) + error_sum = ERROR + ALLOCATE(global_tot_surf_runoff(tmp_land_size), STAT = ERROR) + error_sum = error_sum + ERROR + ALLOCATE(global_rrun(tmp_land_size), STAT = ERROR) + error_sum = error_sum + ERROR + ALLOCATE(global_rflow(tmp_land_size), STAT = ERROR) + error_sum = error_sum + ERROR + + ! Allocate sea level array. IF ( .NOT. l_oasis_rivers .AND. l_vary_sea_level .AND. is_master_task() ) & THEN - ALLOCATE(global_sea_level(global_land_pts), STAT = ERROR) - error_sum = error_sum + ERROR + tmp_land_size = global_land_pts + ELSE + tmp_land_size = 1 + END IF + ALLOCATE(global_sea_level(tmp_land_size), STAT = ERROR) + error_sum = error_sum + ERROR + + ! Allocate abstraction from rivers. + IF ( .NOT. l_oasis_rivers .AND. sw_river_source > 0 & + .AND. is_master_task() ) THEN + ! Water resource code will calclate abstraction. + tmp_river_size = np_rivers + ELSE + ! Allocate at minimum size. + tmp_river_size = 1 + END IF + ALLOCATE(net_abstracted_river_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 + tmp_river_size = np_rivers ELSE - ALLOCATE(global_sea_level(1), STAT = ERROR) - error_sum = error_sum + ERROR + ! Allocate at minimum size. + tmp_river_size = 1 END IF + ALLOCATE(abstracted_minor_res_rp(tmp_river_size), STAT = ERROR) + error_sum = error_sum + ERROR IF ( error_sum /= 0 ) THEN errorstatus = 10 CALL ereport( RoutineName, errorstatus, & - "Error related to allocation of runoff variables." ) + "Error related to allocation of abstraction variables." ) + ELSE + ! 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. + abstracted_minor_res_rp(:) = 0.0 + ! Initialise abstraction from rivers. + net_abstracted_river_rp(:) = 0.0 END IF - IF (.NOT. l_oasis_rivers) THEN + !-------------------------------------------------------------------------- + ! Gather fluxes from all processors + !-------------------------------------------------------------------------- + IF ( .NOT. l_oasis_rivers ) THEN + ! Gather runoff. CALL gather_land_field(tot_sub_runoff_gb, global_tot_sub_runoff, & rivers%global_land_index) CALL gather_land_field(tot_surf_runoff_gb, global_tot_surf_runoff, & rivers%global_land_index) + ! Gather sea level. IF ( l_vary_sea_level ) THEN CALL gather_land_field(rivers%sea_level_lp, global_sea_level, & rivers%global_land_index ) END IF - END IF + END IF ! .NOT. l_oasis_rivers ) THEN !------------------------------------------------------------------------- ! Call routing driver on single processor @@ -556,18 +633,24 @@ SUBROUTINE surf_couple_rivers( & IF ( is_master_task() ) THEN IF (l_oasis_rivers) THEN + ! 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( rivers ) + CALL rivers_route_rp( abstracted_minor_res_rp, net_abstracted_river_rp,& + rivers ) + ELSE + ! Initialisation DO l = 1, global_land_pts global_rflow(l)= 0.0 global_rrun(l) = 0.0 END DO - ! Regrid surface and subsurface runoff from land points to rivers - ! points. + !---------------------------------------------------------------------- + ! Regrid coupling fields from land points to rivers. + !---------------------------------------------------------------------- + ! Regrid runoff. CALL landpts_to_rivpts( global_land_pts, np_rivers, & rivers%map_river_to_land_points, & rivers%global_land_index, & @@ -581,8 +664,8 @@ SUBROUTINE surf_couple_rivers( & rivers%rivers_index_rp, & global_tot_surf_runoff, rivers%rrun_surf_rp ) + ! Regrid sea level. IF ( l_vary_sea_level ) THEN - ! Regrid sea level from land points to river points. CALL landpts_to_rivpts( global_land_pts, np_rivers, & rivers%map_river_to_land_points, & rivers%global_land_index, & @@ -590,10 +673,31 @@ SUBROUTINE surf_couple_rivers( & global_sea_level, rivers%sea_level ) END IF + ! Regrid abstraction from rivers. + IF ( sw_river_source > 0 ) THEN + CALL landpts_to_rivpts( global_land_pts, np_rivers, & + rivers%map_river_to_land_points, & + rivers%global_land_index, & + rivers%rivers_index_rp, & + tot_net_abstracted_river_global, & + net_abstracted_river_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, & + rivers%map_river_to_land_points, & + rivers%global_land_index, & + rivers%rivers_index_rp, & + tot_abstracted_minor_res_global, & + abstracted_minor_res_rp ) + END IF + ! Call the routing science routine. - CALL rivers_route_rp( rivers ) + CALL rivers_route_rp( abstracted_minor_res_rp, net_abstracted_river_rp,& + rivers ) - ! Regrid outputs from rivers to land grid + ! Regrid selected outputs from rivers to land grid. CALL rivpts_to_landpts( global_land_pts, np_rivers, & rivers%map_river_to_land_points, & rivers%global_land_index, & @@ -605,7 +709,8 @@ SUBROUTINE surf_couple_rivers( & rivers%global_land_index, & rivers%rivers_index_rp, & rivers%rrun_rp, global_rrun ) - END IF + + END IF ! l_oasis_rivers !----------------------------------------------------------------------- ! Compute overbank inundation @@ -613,6 +718,7 @@ SUBROUTINE surf_couple_rivers( & IF ( l_riv_overbank ) THEN CALL overbank_update(rivers%rfm_rivflow_rp) END IF + END IF ! end is_master !------------------------------------------------------------------------- @@ -655,6 +761,9 @@ SUBROUTINE surf_couple_rivers( & END IF ! .NOT. l_oasis_rivers #endif + ! Deallocate local variables (in reverse order to allocation). + DEALLOCATE(abstracted_minor_res_rp) + DEALLOCATE(net_abstracted_river_rp) DEALLOCATE(global_sea_level) DEALLOCATE(global_rflow) DEALLOCATE(global_rrun) @@ -706,7 +815,6 @@ SUBROUTINE surf_couple_rivers( & END IF ! rivers_call ! Deallocate water tracer fields -DEALLOCATE(net_abstracted_river_wtrac) DEALLOCATE(inlandout_atmos_wtrac) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) @@ -715,15 +823,13 @@ END SUBROUTINE surf_couple_rivers !--------------------------------------------------------------------------- -SUBROUTINE accumulate_runoff(npoints, net_abstracted_river, surf_runoff, & - sub_runoff, surf_runoff_accum, sub_runoff_accum) +SUBROUTINE accumulate_runoff(npoints, surf_runoff, sub_runoff, & + surf_runoff_accum, sub_runoff_accum) ! Accumulate the surface and subsurface runoff over the river routing period. -! This is a generic routine used for normal water and water tracers +! This is a generic routine used for normal water and water tracers. -USE jules_rivers_mod, ONLY: nstep_rivers -USE jules_water_resources_mod, ONLY: sw_river_source -USE timestep_mod, ONLY: timestep +USE jules_rivers_mod, ONLY: nstep_rivers USE parkind1, ONLY: jprb, jpim USE yomhook, ONLY: lhook, dr_hook @@ -733,8 +839,6 @@ SUBROUTINE accumulate_runoff(npoints, net_abstracted_river, surf_runoff, & INTEGER, INTENT(IN) :: npoints ! No. of points REAL(KIND=real_jlslsm), INTENT(IN) :: & - net_abstracted_river(npoints), & - ! Net abstraction from rivers (kg m-2). surf_runoff(npoints), & ! Surface runoff (kg m-2 s-1) sub_runoff(npoints) @@ -774,19 +878,69 @@ SUBROUTINE accumulate_runoff(npoints, net_abstracted_river, surf_runoff, & (sub_runoff(ip) / REAL(nstep_rivers)) END IF - ! Consider abstraction of river water by water resources. - IF ( sw_river_source > 0 ) THEN - ! Remove net abstraction from the accumulated surface runoff. - ! Convert units of abstraction from kg m-2 to kg m-2 s-1. - surf_runoff_accum(ip) = surf_runoff_accum(ip) - & - ( net_abstracted_river(ip) / & - (REAL(nstep_rivers) * timestep) ) - END IF - END DO IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN END SUBROUTINE accumulate_runoff +!############################################################################## + +SUBROUTINE accumulate_abstraction( npoints, abstracted, tot_abstracted ) + +! Accumulate an abstraction - essentially just adding to a sum. + +USE parkind1, ONLY: jprb, jpim +USE yomhook, ONLY: lhook, dr_hook + +IMPLICIT NONE + +!------------------------------------------------------------------------------ +! Scalar arguments with INTENT(IN) +!------------------------------------------------------------------------------ +INTEGER, INTENT(IN) :: npoints ! No. of points + +!------------------------------------------------------------------------------ +! Array arguments with INTENT(IN) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN) :: & + abstracted(npoints) + ! Water abstracted (various units). + +!------------------------------------------------------------------------------ +! Array arguments with INTENT(IN OUT) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & + tot_abstracted(npoints) + ! Accumulated water abstracted (various units). + +!------------------------------------------------------------------------------ +! Local scalar variables +!------------------------------------------------------------------------------ +INTEGER :: ip ! Loop counter + +!------------------------------------------------------------------------------ +! Local scalar parameters +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'ACCUMULATE_ABSTRACTION' + +!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) + +DO ip = 1, npoints + + tot_abstracted(ip) = tot_abstracted(ip) + abstracted(ip) + +END DO + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) +RETURN +END SUBROUTINE accumulate_abstraction + END MODULE surf_couple_rivers_mod diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 335194d8..5aed4e9b 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -63,6 +63,8 @@ MODULE water_resources_control_mod ! Demands for water accumulated over the water resource timestep (kg). demand_unmet_global(:,:), & ! The part of the demand for water that is not satisfied (kg). + grid_area_global(:), & + ! Gridbox area (m2). gw_abstracted_global(:), & ! Water abstracted from renewable groundwater (kg). gw_avail_global(:), & @@ -70,10 +72,14 @@ MODULE water_resources_control_mod ! This does not include "non-renewable" groundwater. gw_nr_abstracted_global(:), & ! Water abstracted from non-renewable groundwater (kg). + minor_res_storage_global(:), & + ! Water stored in minor reservoirs, on land points (kg). return_flow_gw_global(:), & ! Water that is returned to renewable groundwater after use (kg). - return_flow_sw_global(:), & + return_flow_river_global(:), & ! Water that is returned to rivers after use (kg). + river_storage_global(:), & + ! Water in rivers, on land points (kg). sfc_water_frac_global(:), & ! Fraction of demand to be met from surface water. supply_irrig_global(:), & @@ -89,29 +95,36 @@ MODULE water_resources_control_mod ! Water that is removed from the system during use, e.g. incorporated into ! manufactured goods (kg). +! Dr Hook variables +INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 +INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 +REAL(KIND=jprb) :: zhook_handle + CONTAINS !############################################################################## -SUBROUTINE water_resources_control( & +SUBROUTINE water_resources_control( global_land_pts, & global_land_index, land_index, map_river_to_land_points, & rivers_index_rp, con_rain_ij, con_snow_ij, & conv_loss_frac, demand_rate_domestic, demand_rate_industry, & demand_rate_livestock, demand_rate_transfers, dvi_cpft, & flandg, frac_irr_soilt, frac_soilt, & frac_surft, grid_area_ij, & - ls_rain_ij, ls_snow_ij, lw_down, smvccl_soilt, & + ls_rain_ij, ls_snow_ij, lw_down, minor_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, & prec_1_day_av_gb, prec_1_day_av_use_gb, & - rfm_surfstore_rp, rivers_sto_rp, rn_1_day_av_gb, & - rn_1_day_av_use_gb, sfc_water_frac, smcl_soilt, & + rn_1_day_av_gb,rn_1_day_av_use_gb, sfc_water_frac, smcl_soilt, & sthu_irr_soilt, sthu_soilt, & sthzw_soilt, sub_surf_roff, tl_1_day_av_gb, & - tl_1_day_av_use_gb, priority_order, demand_unmet, gw_abstracted, & - gw_avail_start, gw_nr_abstracted, & - irrig_water_gb, net_abstracted_river, sw_abstracted, & + 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 ) !------------------------------------------------------------------------------ @@ -137,7 +150,7 @@ SUBROUTINE water_resources_control( & USE jules_irrig_mod, ONLY: irr_crop_doell, irr_crop -USE jules_rivers_mod, ONLY: l_rivers, np_rivers +USE jules_rivers_mod, ONLY: l_minor_reservoirs, np_rivers USE jules_soil_mod, ONLY: sm_levels @@ -145,10 +158,8 @@ SUBROUTINE water_resources_control( & 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_river_source, use_irrigation, & - water_res_count - -USE model_grid_mod, ONLY: global_land_pts + nstep_water_res, n_sw_source, nwater_use, sw_minor_res_source, & + sw_river_source, use_irrigation, water_res_count USE parallel_mod, ONLY: is_master_task @@ -166,6 +177,13 @@ SUBROUTINE water_resources_control( & IMPLICIT NONE +!------------------------------------------------------------------------------ +! Scalar arguments with INTENT(IN) +!------------------------------------------------------------------------------ +INTEGER, INTENT(IN) :: & + global_land_pts + ! Number of land points (summed over all tasks). + !------------------------------------------------------------------------------ ! Array arguments with INTENT(IN) !------------------------------------------------------------------------------ @@ -212,6 +230,12 @@ SUBROUTINE water_resources_control( & ! Large-scale snowfall rate (kg m-2 s-1). lw_down(row_length,rows), & ! Surface downward longwave radiation (W m-2). + minor_res_storage(np_rivers), & + ! Water stored in minor reservoirs (kg). + rfm_surfstore_rp(np_rivers), & + ! River surface storage (m3). + rivers_sto_rp(np_rivers), & + ! River water storage (kg). smvccl_soilt(land_pts,nsoilt,sm_levels), & ! Critical volumetric SMC (cubic m per cubic m of soil). smvcst_soilt(land_pts,nsoilt,sm_levels), & @@ -246,10 +270,6 @@ SUBROUTINE water_resources_control( & ! Average precipitation rate for the current day (kg m-2 s-1). prec_1_day_av_use_gb(land_pts,ndpy,nyav), & ! Daily average precipitation rate (kg m-2 s-1). - rfm_surfstore_rp(np_rivers), & - ! River surface storage (m3). - rivers_sto_rp(np_rivers), & - ! River water storage (kg). rn_1_day_av_gb(land_pts), & ! Average net radiation for the current day (W m-2). rn_1_day_av_use_gb(land_pts,ndpy,nyav), & @@ -282,20 +302,41 @@ SUBROUTINE water_resources_control( & ! Priorities of water demands at each gridpoint, in order of decreasing ! priority. Values are the index in multi-sector arrays. -! Diagnostics and coupling variables. +! Coupling variables and diagnostics. REAL(KIND=real_jlslsm), INTENT(OUT) :: & + !---------------------------------------------------------------------------- + ! Coupling variables + !---------------------------------------------------------------------------- + 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. + ! Note that this has reduced size if it is not required. + net_abstracted_river_global(global_land_pts), & + ! Net abstraction from river, on global land points (kg m-2). + ! Note that this has reduced size if it is not required. + !---------------------------------------------------------------------------- + ! Variables that are passed out for diagnostic purposes. + !---------------------------------------------------------------------------- + gw_abstracted(land_pts), & + ! Water abstracted from renewable groundwater (kg). This is for coupling + ! to a groundwater model - though that is currently done internally to + ! the water resources code. + irrig_water_gb(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_minor_res(land_pts), & + ! Water abstracted from minor reservoirs (kg). Diagnostic only. + abstracted_river(land_pts), & + ! Water abstracted from rivers (kg). Diagnostic only. + conveyance_loss(land_pts), & + ! Water that is lost during conveyance (kg). demand_unmet(land_pts,nwater_use), & ! The part of the demand for water that is not satisfied (kg). - gw_abstracted(land_pts), & - ! Water abstracted from renewable groundwater (kg). gw_avail_start(land_pts), & ! Groundwater that is available for abstraction at start of timestep (kg). gw_nr_abstracted(land_pts), & ! Water abstracted from non-renewable groundwater (kg). - irrig_water_gb(land_pts), & - ! Water added to soil via irrigation (kg m-2 s-1). - net_abstracted_river(land_pts), & - ! Net abstraction from river (kg m-2). sw_abstracted(land_pts,n_sw_source), & ! Water that is abstracted from surface waters (kg). sw_avail_total(land_pts), & @@ -328,8 +369,6 @@ SUBROUTINE water_resources_control( & ! Local array variables !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm) :: & - conveyance_loss(land_pts), & - ! Water that is lost during conveyance (kg). demand_irrig_layer(land_pts,nsoilt,sm_levels), & ! Demand for irrigation water for each soil layer (kg m-2). ! This has sm_levels layers (though we only need nlayer_irrig) for ease of @@ -346,18 +385,11 @@ SUBROUTINE water_resources_control( & ! Area of land in gridbox (m2). return_flow_gw(land_pts), & ! Water that is returned to renewable groundwater after use (kg). - return_flow_sw(land_pts), & + return_flow_river(land_pts), & ! Water that is returned to rivers after use (kg). - river_abstracted(np_rivers), & - ! Water abstracted from river store (kg). 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) @@ -387,17 +419,35 @@ SUBROUTINE water_resources_control( & ! here because on timesteps on which the water resource model is not called ! they are potentially still used for coupling to other components and/or as ! diagnostics. As these fluxes are currently passed as increments (e.g. kg) -! rather than as rates (e.g. kg s-1) they need to be zero on these timesteps. -!------------------------------------------------------------------------------ -! Initialise coupling flux. -net_abstracted_river(:) = 0.0 +! rather than as rates (e.g. kg s-1) they need to be zero on these +! intermediate timesteps. +!------------------------------------------------------------------------------ +! Initialise coupling fluxes. +! 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_minor_reservoirs ) THEN + abstracted_minor_res_global(:) = 0.0 + END IF + IF ( sw_river_source > 0 ) THEN + net_abstracted_river_global(:) = 0.0 + END IF +END IF ! Initialise abstractions. gw_abstracted(:) = 0.0 gw_nr_abstracted(:) = 0.0 sw_abstracted(:,:) = 0.0 ! Initialise other fluxes. +conveyance_loss(:) = 0.0 demand_unmet(:,:) = 0.0 water_removed(:) = 0.0 +! Initialise diagnostics. +IF ( l_minor_reservoirs ) THEN + abstracted_minor_res(:) = 0.0 +END IF +IF ( sw_river_source > 0 ) THEN + abstracted_river(:) = 0.0 +END IF !------------------------------------------------------------------------------ ! Add to the accumulated demands (only for prescribed demands). @@ -471,33 +521,71 @@ SUBROUTINE water_resources_control( & ! Fields on land_pts need to be gathered into global equivalents. !---------------------------------------------------------------------------- CALL gather_global_water( priority_order, conv_loss_frac, demand_accum, & - gw_avail_start, sfc_water_frac ) + grid_area_lp, gw_avail_start, sfc_water_frac ) - !---------------------------------------------------------------------------- - ! Calculate the surface water available for abstraction. - ! As this can involve the river grid, we only do this on the master task. - ! Global arrays should have been allocated before this routine is called. - !---------------------------------------------------------------------------- - IF ( l_have_surface_water .AND. is_master_task() ) THEN - CALL calc_avail_surface_water( global_land_index, map_river_to_land_points,& - rivers_index_rp, rfm_surfstore_rp, & - rivers_sto_rp, sw_avail_global ) - ! Save the start of timestep total for diagnostic purposes. - sw_avail_total_start_global(:) = SUM(sw_avail_global,2) - END IF - - !---------------------------------------------------------------------------- - ! Call the top-level routine for the chosen model, on a single processor. - ! Initially only one model is available. - !---------------------------------------------------------------------------- IF ( is_master_task() ) THEN + + !-------------------------------------------------------------------------- + ! Calculate the surface water available for abstraction. + ! As this can involve the river grid, we only do this on the master task. + !-------------------------------------------------------------------------- + IF ( l_have_surface_water ) THEN + + !------------------------------------------------------------------------ + ! Regrid river variables onto land points. + ! 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, & + minor_res_storage_global, river_storage_global ) + + ! Calculate water available for abstraction. + CALL calc_avail_surface_water( minor_res_storage_global, & + river_storage_global, & + sw_avail_global ) + + ! Save the total at start of timestep for diagnostic purposes. + sw_avail_total_start_global(:) = SUM(sw_avail_global,2) + END IF + + !-------------------------------------------------------------------------- + ! Call the top-level routine for the chosen model. + ! Initially only one model is available. + !-------------------------------------------------------------------------- CALL water_resources_drive( global_land_pts, priority_order_global, & conv_loss_frac_global, demand_accum_global, & demand_unmet_global, gw_abstracted_global, gw_avail_global, & gw_nr_abstracted_global, sfc_water_frac_global, & sw_abstracted_global, sw_avail_global, water_removed_global, & conveyance_loss_global, return_flow_gw_global, & - return_flow_sw_global, supply_irrig_global ) + return_flow_river_global, supply_irrig_global ) + + ! If minor reservoirs are modelled, save abstraction in a new variable. + IF ( sw_minor_res_source > 0 ) THEN + abstracted_minor_res_global(:) & + = sw_abstracted_global(:,sw_minor_res_source) + END IF + + !-------------------------------------------------------------------------- + ! Decide where return flows should go. + ! This is essentially part of coupling to other parts of the model but the + ! current code structure requires this bit to be done now (before net + ! abstraction from rivers is calculated). + !-------------------------------------------------------------------------- + CALL redirect_return_flows( global_land_pts, return_flow_gw_global, & + return_flow_river_global ) + + !-------------------------------------------------------------------------- + ! Calculate the net abstraction from rivers. + !-------------------------------------------------------------------------- + IF ( sw_river_source > 0 ) THEN + CALL calc_river_flux( global_land_pts, grid_area_global, & + return_flow_river_global, & + sw_abstracted_global(:,sw_river_source), & + net_abstracted_river_global ) + END IF + END IF ! is_master_task !---------------------------------------------------------------------------- @@ -506,9 +594,10 @@ SUBROUTINE water_resources_control( & ! There are no prognostic variables to be scattered. !---------------------------------------------------------------------------- CALL scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & - gw_nr_abstracted, return_flow_gw, return_flow_sw, & - sfc_water_frac, supply_irrig, sw_abstracted, & - sw_avail_total, water_removed ) + 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. @@ -516,15 +605,6 @@ SUBROUTINE water_resources_control( & l_allocate = .FALSE. CALL allocate_global_water( l_allocate ) - !---------------------------------------------------------------------------- - ! Calculate the net abstraction from rivers. - !---------------------------------------------------------------------------- - IF ( sw_river_source > 0 ) THEN - CALL calc_river_flux( land_pts, grid_area_lp, return_flow_sw, & - sw_abstracted(:,sw_river_source), & - net_abstracted_river ) - END IF - !---------------------------------------------------------------------------- ! Update soil and groundwater stores. !---------------------------------------------------------------------------- @@ -602,16 +682,10 @@ 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) - IF ( l_prioritise ) THEN ! Set sector priorities at each location. ! At present these are the same at all locations and it is simply a case @@ -698,11 +772,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) @@ -773,11 +842,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) @@ -811,6 +875,8 @@ SUBROUTINE allocate_global_water( l_allocate ) USE ereport_mod, ONLY: ereport +USE jules_rivers_mod, ONLY: 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 @@ -846,21 +912,26 @@ SUBROUTINE allocate_global_water( l_allocate ) land_size, & ! Size for arrays. land_size_irrig, & - ! Size for arrays for irrigation variables. + ! Size for irrigation arrays. land_size_gw, & ! Size for groundwater 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. !------------------------------------------------------------------------------ !end of header +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) IF ( l_allocate ) THEN !---------------------------------------------------------------------------- ! Allocate arrays. ! These are allocated at full size only on the master task, and only if a - ! parameterisation is selected - otherwise alocate minimum size. + ! parameterisation is selected - otherwise allocate minimum size. !---------------------------------------------------------------------------- IF ( is_master_task() ) THEN land_size = global_land_pts @@ -874,6 +945,16 @@ SUBROUTINE allocate_global_water( l_allocate ) ELSE land_size_sw = 1 END IF + IF ( l_rivers ) THEN + land_size_rivers = global_land_pts + ELSE + land_size_rivers = 1 + END IF + IF ( l_minor_reservoirs ) THEN + land_size_minor_res = global_land_pts + ELSE + land_size_minor_res = 1 + END IF IF ( l_water_irrigation ) THEN land_size_irrig = global_land_pts ELSE @@ -884,6 +965,8 @@ SUBROUTINE allocate_global_water( l_allocate ) land_size = 1 land_size_irrig = 1 land_size_gw = 1 + land_size_minor_res = 1 + land_size_rivers = 1 land_size_sw = 1 END IF @@ -902,6 +985,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(minor_res_storage_global(land_size_minor_res), STAT = ERROR) + error_sum = error_sum + ERROR IF ( l_prioritise ) THEN ALLOCATE(priority_order_global(land_size,nwater_use), STAT = ERROR) @@ -910,11 +995,14 @@ SUBROUTINE allocate_global_water( l_allocate ) END IF error_sum = error_sum + ERROR - ! Both SW and GW return flows are needed at full size, even if either - ! source is not active. + ALLOCATE(river_storage_global(land_size_rivers), STAT = ERROR) + error_sum = error_sum + ERROR + + ! Return flows to groundater and rivers are both needed at full size, even + ! if either source is not active. ALLOCATE(return_flow_gw_global(land_size), STAT = ERROR) error_sum = error_sum + ERROR - ALLOCATE(return_flow_sw_global(land_size), STAT = ERROR) + ALLOCATE(return_flow_river_global(land_size), STAT = ERROR) error_sum = error_sum + ERROR IF ( l_have_groundwater .AND. l_have_surface_water ) THEN @@ -935,6 +1023,9 @@ SUBROUTINE allocate_global_water( l_allocate ) ALLOCATE(water_removed_global(land_size), STAT = ERROR) error_sum = error_sum + ERROR + ALLOCATE(grid_area_global(land_size_rivers), STAT = ERROR) + error_sum = error_sum + ERROR + IF ( error_sum == 0 ) THEN ! Initialise arrays. conveyance_loss_global(:) = 0.0 @@ -944,15 +1035,18 @@ SUBROUTINE allocate_global_water( l_allocate ) gw_abstracted_global(:) = 0.0 gw_avail_global(:) = 0.0 gw_nr_abstracted_global(:) = 0.0 + minor_res_storage_global(:) = 0.0 priority_order_global(:,:) = 0 return_flow_gw_global(:) = 0.0 - return_flow_sw_global(:) = 0.0 + return_flow_river_global(:) = 0.0 + river_storage_global(:) = 0.0 sfc_water_frac_global(:) = 0.0 supply_irrig_global(:) = 0.0 sw_abstracted_global(:,:) = 0.0 sw_avail_global(:,:) = 0.0 sw_avail_total_start_global(:) = 0.0 water_removed_global(:) = 0.0 + grid_area_global(:) = 0.0 ELSE errorstatus = 10 CALL ereport( RoutineName, errorstatus, & @@ -965,6 +1059,7 @@ SUBROUTINE allocate_global_water( l_allocate ) ! l_allocate = .FALSE. ! Deallocate arrays, in opposite order to the allocation. !---------------------------------------------------------------------------- + IF ( ALLOCATED(grid_area_global) ) DEALLOCATE(grid_area_global) IF ( ALLOCATED(water_removed_global) ) DEALLOCATE(water_removed_global) IF ( ALLOCATED(sw_avail_total_start_global) ) THEN DEALLOCATE(sw_avail_total_start_global) @@ -973,9 +1068,15 @@ SUBROUTINE allocate_global_water( l_allocate ) IF ( ALLOCATED(sw_abstracted_global) ) DEALLOCATE(sw_abstracted_global) IF ( ALLOCATED(supply_irrig_global) ) DEALLOCATE(supply_irrig_global) IF ( ALLOCATED(sfc_water_frac_global) ) DEALLOCATE(sfc_water_frac_global) + IF ( ALLOCATED(river_storage_global) ) DEALLOCATE(river_storage_global) IF ( ALLOCATED(return_flow_gw_global) ) DEALLOCATE(return_flow_gw_global) - IF ( ALLOCATED(return_flow_sw_global) ) DEALLOCATE(return_flow_sw_global) + IF ( ALLOCATED(return_flow_river_global) ) THEN + DEALLOCATE(return_flow_river_global) + END IF IF ( ALLOCATED(priority_order_global) ) DEALLOCATE(priority_order_global) + IF ( ALLOCATED(minor_res_storage_global) ) THEN + DEALLOCATE(minor_res_storage_global) + END IF IF ( ALLOCATED(gw_nr_abstracted_global)) DEALLOCATE(gw_nr_abstracted_global) IF ( ALLOCATED(gw_avail_global) ) DEALLOCATE(gw_avail_global) IF ( ALLOCATED(gw_abstracted_global) ) DEALLOCATE(gw_abstracted_global) @@ -986,6 +1087,7 @@ SUBROUTINE allocate_global_water( l_allocate ) END IF ! l_allocate +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN END SUBROUTINE allocate_global_water @@ -993,7 +1095,7 @@ END SUBROUTINE allocate_global_water !############################################################################## SUBROUTINE gather_global_water( priority_order, conv_loss_frac, demand_accum, & - gw_avail_start, sfc_water_frac ) + grid_area_lp, gw_avail_start, sfc_water_frac ) !------------------------------------------------------------------------------ ! Description: @@ -1003,7 +1105,7 @@ SUBROUTINE gather_global_water( priority_order, conv_loss_frac, demand_accum, & USE ancil_info, ONLY: land_pts ! for the current task USE jules_water_resources_mod, ONLY: l_have_groundwater, l_prioritise, & - nwater_use, partition_ancil, partition_method + nwater_use, partition_ancil, partition_method, sw_river_source USE model_grid_mod, ONLY: global_land_pts @@ -1024,11 +1126,18 @@ SUBROUTINE gather_global_water( priority_order, conv_loss_frac, demand_accum, & ! Fraction of water that is lost during conveyance from source to user. demand_accum(land_pts,nwater_use), & ! Demands for water accumulated over the water resource timestep (kg). + grid_area_lp(land_pts), & + ! Area of gridbox (m2). gw_avail_start(land_pts), & ! Groundwater that is available for abstraction at start of timestep (kg). sfc_water_frac(land_pts) ! Fraction of demand to be met from surface water. +!------------------------------------------------------------------------------ +! Local parameters +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'GATHER_GLOBAL_WATER' + !------------------------------------------------------------------------------ ! Local variables. !------------------------------------------------------------------------------ @@ -1043,6 +1152,7 @@ SUBROUTINE gather_global_water( priority_order, conv_loss_frac, demand_accum, & !------------------------------------------------------------------------------ !end of header +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) CALL gather_land_field( conv_loss_frac, conv_loss_frac_global ) @@ -1068,6 +1178,12 @@ SUBROUTINE gather_global_water( priority_order, conv_loss_frac, demand_accum, & CALL gather_land_field( sfc_water_frac, sfc_water_frac_global ) END IF +! We only need to gather grid_area_lp if there is abstraction from rivers. +IF ( sw_river_source > 0 ) THEN + CALL gather_land_field( grid_area_lp, grid_area_global ) +END IF + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN END SUBROUTINE gather_global_water @@ -1075,9 +1191,11 @@ END SUBROUTINE gather_global_water !############################################################################## SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & + abstracted_minor_res, abstracted_river, & gw_nr_abstracted, return_flow_gw, & - return_flow_sw, sfc_water_frac, supply_irrig, & - sw_abstracted, sw_avail_total, water_removed ) + return_flow_river, sfc_water_frac, & + supply_irrig, sw_abstracted, sw_avail_total, & + water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -1086,9 +1204,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_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 + partition_calc_from_stores, partition_method, sw_minor_res_source, & + sw_river_source USE model_grid_mod, ONLY: global_land_pts @@ -1108,9 +1229,13 @@ 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_minor_res(land_pts), & + ! Water abstracted from minor reservoirs (kg). + abstracted_river(land_pts), & + ! Water abstracted from rivers (kg). return_flow_gw(land_pts), & ! Water that is returned to renewable groundwater after use (kg). - return_flow_sw(land_pts), & + return_flow_river(land_pts), & ! Water that is returned to rivers after use (kg). sfc_water_frac(land_pts), & ! Target fraction of demand to be met by surface water. @@ -1125,6 +1250,11 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & ! Water that is removed from the system during use, e.g. incorporated into ! manufactured goods (kg). +!------------------------------------------------------------------------------ +! Local parameters +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'SCATTER_GLOBAL_WATER' + !------------------------------------------------------------------------------ ! Local scalar variables !------------------------------------------------------------------------------ @@ -1132,6 +1262,7 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & !------------------------------------------------------------------------------ !end of header +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) ! Fields that are always required. CALL scatter_land_field( conveyance_loss_global, conveyance_loss ) @@ -1146,37 +1277,266 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & CALL scatter_land_field( gw_nr_abstracted_global, gw_nr_abstracted ) END IF ! Note that return_flow_gw is always used, even if groundwater is not -! modelled. +! modelled (in that case it is added to runoff). CALL scatter_land_field( return_flow_gw_global, return_flow_gw ) +! Return flow to rivers is always calculated (but can be zero). However +! it is only required further if we have rivers. +IF ( l_rivers ) THEN + CALL scatter_land_field( return_flow_river_global, return_flow_river ) +END IF + ! Fields that are only required if we are modelling surface water sources. IF ( l_have_surface_water ) THEN + ! Surface water fraction only needs to be scattered if it was calculated by ! the master task. If it was read as an ancillary field, nothing to do here. IF ( partition_method == partition_calc_from_stores ) THEN CALL scatter_land_field( sfc_water_frac_global, sfc_water_frac ) END IF - ! Surface water always includes rivers, so we always calculate return flow. - CALL scatter_land_field( return_flow_sw_global, return_flow_sw ) + DO i = 1, n_sw_source CALL scatter_land_field( sw_abstracted_global(:,i), sw_abstracted(:,i) ) END DO CALL scatter_land_field( sw_avail_total_start_global, sw_avail_total ) -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), & + abstracted_minor_res ) + END IF + + ! Save diagnostic of abstraction from rivers. + IF ( sw_river_source > 0 ) THEN + CALL scatter_land_field( sw_abstracted_global(:,sw_river_source), & + abstracted_river ) + END IF + +END IF ! l_have_surface_water ! Fields for irrigation. IF ( l_water_irrigation ) THEN CALL scatter_land_field( supply_irrig_global, supply_irrig ) END IF +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN END SUBROUTINE scatter_global_water !############################################################################## !############################################################################## -SUBROUTINE calc_river_flux( land_pts, grid_area_lp, return_flow_sw, & - sw_abstracted_river, net_abstracted_river ) +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 ) + +!------------------------------------------------------------------------------ +! Description: +! Regrid water resource-related variables from river grid to land grid. +!------------------------------------------------------------------------------ + +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 model_grid_mod, ONLY: global_land_pts + +USE rivers_regrid_mod, ONLY: rivpts_to_landpts + +USE water_constants_mod, ONLY: rho_water + + +IMPLICIT NONE + +!------------------------------------------------------------------------------ +! Array arguments with INTENT(IN). +!------------------------------------------------------------------------------ +INTEGER, INTENT(IN) :: & + global_land_index(global_land_pts), & + ! List of indices for the land model grid. + map_river_to_land_points(np_rivers), & + ! List of coincident land point numbers, on river points. + rivers_index_rp(np_rivers) + ! Index of points where routing is calculated. + +REAL(KIND=real_jlslsm), INTENT(IN) :: & + minor_res_storage(np_rivers), & + ! Water stored in minor reservoirs (kg). + rfm_surfstore_rp(np_rivers), & + ! River surface storage (m3). + rivers_sto_rp(np_rivers) + ! River water storage (kg). + +!------------------------------------------------------------------------------ +! Array arguments with INTENT(OUT). +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(OUT) :: & + minor_res_storage_global(global_land_pts), & + ! Water stored in minor reservoirs, on land points (kg). + river_storage_global(global_land_pts) + ! Water in rivers, on land points (kg). + +!------------------------------------------------------------------------------ +! Local parameters. +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'REGRID_TO_LAND' + +!------------------------------------------------------------------------------ +! Local scalar variables. +!------------------------------------------------------------------------------ +INTEGER :: & + errorstatus + ! Error value. + +!------------------------------------------------------------------------------ +!end of header +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) + +IF ( l_rivers ) THEN + + !---------------------------------------------------------------------------- + ! Convert river storage to a variable on land points. + ! Select code for the current river model as variables differ between models. + ! This is later used to define the river water available for abstraction, + ! which informs the approach taken below for rivers_rfm. + !---------------------------------------------------------------------------- + + ! Initialise. + river_storage_global(:) = 0.0 + + SELECT CASE ( i_river_vn ) + + CASE ( rivers_rfm ) + ! We will only include the surface store in the available water. + CALL rivpts_to_landpts( global_land_pts, np_rivers, & + map_river_to_land_points,global_land_index, & + rivers_index_rp, rfm_surfstore_rp, & + river_storage_global ) + ! Convert units from m3 to kg. + river_storage_global(:) = river_storage_global(:) * rho_water + + CASE ( rivers_trip ) + CALL rivpts_to_landpts( global_land_pts, np_rivers, & + map_river_to_land_points, global_land_index, & + rivers_index_rp, rivers_sto_rp, & + river_storage_global ) + + CASE DEFAULT + + errorstatus = 101 ! a fatal error + CALL ereport(RoutineName, errorstatus, 'Unknown value of i_river_vn.') + + END SELECT ! i_river_vn + +END IF ! l_rivers + +!------------------------------------------------------------------------------ +! Get minor reservoir storage onto land points. +!------------------------------------------------------------------------------ +IF ( l_minor_reservoirs ) THEN + ! Initialise. + minor_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, minor_res_storage, & + minor_res_storage_global ) +END IF + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) +RETURN +END SUBROUTINE regrid_to_land + +!############################################################################## +!############################################################################## + +SUBROUTINE redirect_return_flows( global_land_pts, & + return_flow_gw_global, & + return_flow_river_global ) + +!------------------------------------------------------------------------------ +! Description: +! Change the destination of return flows depending on what sinks are +! available. +!------------------------------------------------------------------------------ + +USE jules_rivers_mod, ONLY: l_rivers +USE jules_water_resources_mod, ONLY: l_have_renew_gwater + +IMPLICIT NONE + +!------------------------------------------------------------------------------ +! Scalar arguments with INTENT(IN) +!------------------------------------------------------------------------------ +INTEGER, INTENT(IN) :: & + global_land_pts + ! The number of land points. + +!------------------------------------------------------------------------------ +! Array arguments with INTENT(IN OUT) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & + return_flow_gw_global(global_land_pts), & + ! Water that is returned to renewable groundwater after use (kg). + return_flow_river_global(global_land_pts) + ! Water that is returned to rivers after use (kg). + +!------------------------------------------------------------------------------ +! Local parameters +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'REDIRECT_RETURN_FLOWS' + +!------------------------------------------------------------------------------ +! Local variables. +!------------------------------------------------------------------------------ +INTEGER :: & + l ! Loop counter. + +!------------------------------------------------------------------------------ +!end of header +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) + +!------------------------------------------------------------------------------ +! Return flows to groundwater and rivers have been calculated assuming those +! sinks are available. If the preferred sink is not modelled the other is used +! (if available). If neither is available we add to the groundwater return flow +! because later code will divert that to runoff. +! Note that if both rivers and renewable groundwater are modelled nothing is +! changed in this subroutine. +!------------------------------------------------------------------------------ +IF ( l_rivers .AND. .NOT. l_have_renew_gwater ) THEN + + ! River are modelled but renewable groundwater is not. + ! Direct all return flows to rivers. + DO l=1,global_land_pts + return_flow_river_global(l) = return_flow_river_global(l) & + + return_flow_gw_global(l) + return_flow_gw_global(l) = 0.0 + END DO + +ELSE IF ( .NOT. l_rivers ) THEN + + ! Rivers are not modelled. Groundwater might or might not be modelled. + ! Direct all return flows to groundwater (for now). + DO l=1,global_land_pts + return_flow_gw_global(l) = return_flow_gw_global(l) & + + return_flow_river_global(l) + return_flow_river_global(l) = 0.0 + END DO + +END IF + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) +RETURN +END SUBROUTINE redirect_return_flows + +!############################################################################## +!############################################################################## +SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & + return_flow_river_global, & + sw_abstracted_river_global, & + net_abstracted_river_global ) !------------------------------------------------------------------------------ ! Description: @@ -1189,27 +1549,32 @@ SUBROUTINE calc_river_flux( land_pts, grid_area_lp, return_flow_sw, & ! Scalar arguments with INTENT(IN) !------------------------------------------------------------------------------ INTEGER, INTENT(IN) :: & - land_pts + global_land_pts ! The number of land points. !------------------------------------------------------------------------------ ! Array arguments with INTENT(IN) !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm), INTENT(IN) :: & - grid_area_lp(land_pts), & + grid_area_global(global_land_pts), & ! Area of gridbox (m2). - return_flow_sw(land_pts), & - ! Water that is returned to surface waters after use (kg). - sw_abstracted_river(land_pts) + return_flow_river_global(global_land_pts), & + ! Water that is returned to rivers after use (kg). + sw_abstracted_river_global(global_land_pts) ! Water abstracted from river (kg). !------------------------------------------------------------------------------ ! Array arguments with INTENT(OUT) !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm), INTENT(OUT) :: & - net_abstracted_river(land_pts) + net_abstracted_river_global(global_land_pts) ! Net abstraction from river (kg m-2). +!------------------------------------------------------------------------------ +! Local parameters +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_RIVER_FLUX' + !------------------------------------------------------------------------------ ! Local variables. !------------------------------------------------------------------------------ @@ -1218,13 +1583,16 @@ SUBROUTINE calc_river_flux( land_pts, grid_area_lp, return_flow_sw, & !------------------------------------------------------------------------------ !end of header +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) ! Calculate net abstraction and change units from kg to kg m-2. -DO l=1,land_pts - net_abstracted_river(l) = ( sw_abstracted_river(l) - return_flow_sw(l) ) & - / grid_area_lp(l) +DO l=1,global_land_pts + net_abstracted_river_global(l) = ( sw_abstracted_river_global(l) & + - return_flow_river_global(l) ) & + / grid_area_global(l) END DO +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN END SUBROUTINE calc_river_flux diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index f6b9b8d5..bbc7c0f9 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -9,7 +9,7 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! Description: ! Contains variables and field types for water resource modelling. ! @@ -18,7 +18,7 @@ ! ! Code Description: ! Language: Fortran 90. -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ MODULE water_resources_vars_mod @@ -52,7 +52,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), ALLOCATABLE :: & !-------------------------------------------------------------------------- - ! Ancillary fields. + ! Ancillary fields on land points. !-------------------------------------------------------------------------- conv_loss_frac(:), & ! Fraction of water that is lost during conveyance from source to user. @@ -72,13 +72,15 @@ MODULE water_resources_vars_mod demand_rate_transfers(:), & ! Demand for water for (explicit) transfers (kg s-1). !-------------------------------------------------------------------------- - ! Flux for coupling to rivers. + ! Fluxes for coupling. !-------------------------------------------------------------------------- - net_abstracted_river(:), & - ! Net abstraction from river (kg). + abstracted_minor_res_global(:), & + ! Water abstracted from minor reservoirs, on global land points (kg). + net_abstracted_river_global(:), & + ! Net abstraction from river, on global land points (kg m-2). !-------------------------------------------------------------------------- - ! Diagnostics (also used internally). - ! All abstractions are gross (not net of returns) fluxes unless stated + ! Internal/work variables (some of which are also used as diagnostics). + ! All abstractions are gross fluxes (not net of returns) unless stated ! otherwise. !-------------------------------------------------------------------------- demand_accum(:,:), & @@ -89,7 +91,9 @@ MODULE water_resources_vars_mod demand_unmet(:,:), & ! The part of the demand for water that is not satisfied (kg). gw_abstracted(:), & - ! Water abstracted from renewable groundwater (kg). + ! Water abstracted from renewable groundwater (kg). This is for coupling + ! to a groundwater model - though that is currently done internally to + ! the water resources code. gw_avail(:), & ! Groundwater that is available for abstraction at the start of the ! timestep (kg). This does not include "non-renewable" groundwater. @@ -100,6 +104,15 @@ MODULE water_resources_vars_mod sw_avail_total(:), & ! Surface water that is available for abstraction at start of timestep, ! summed over sources (kg). + !-------------------------------------------------------------------------- + ! Diagnostics. + !-------------------------------------------------------------------------- + abstracted_minor_res(:), & + ! Water abstracted from minor reservoirs (kg). + abstracted_river(:), & + ! Water abstracted from rivers (kg). + conveyance_loss(:), & + ! Water that is lost during conveyance (kg). water_removed(:) ! Water that is removed from the system during use, e.g. incorporated ! into manufactured goods (kg). @@ -117,7 +130,8 @@ 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 :: net_abstracted_river(:) + 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(:,:) REAL(KIND=real_jlslsm), POINTER :: demand_unmet(:,:) REAL(KIND=real_jlslsm), POINTER :: gw_abstracted(:) @@ -125,6 +139,9 @@ 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_minor_res(:) + REAL(KIND=real_jlslsm), POINTER :: abstracted_river(:) + REAL(KIND=real_jlslsm), POINTER :: conveyance_loss(:) REAL(KIND=real_jlslsm), POINTER :: water_removed(:) END TYPE @@ -137,8 +154,9 @@ MODULE water_resources_vars_mod !############################################################################## -SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & - l_have_groundwater, l_have_surface_water, & +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 ) @@ -153,12 +171,16 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ! Scalar arguments with INTENT(IN) !------------------------------------------------------------------------------ INTEGER, INTENT(IN) :: & + global_land_pts, & + ! Number of land points (total over all tasks). land_pts, & ! Number of land points (current task). n_sw_source, & ! Number of surface water sources. - nwater_use + nwater_use, & ! Number of water resource sectors that are considered. + sw_river_source + ! Indicates if rivers are modelled. LOGICAL, INTENT(IN) :: & l_have_groundwater, & @@ -166,7 +188,10 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ! non-renewable). l_have_surface_water, & ! Flag indicating if we have surface water represented (e.g. rivers). - ! TRUE means n_sw_source > 0. + l_is_master_task, & + ! Flag indicating if this call is from the master task. + l_minor_reservoirs, & + ! Switch for minor_reservoirs. l_water_domestic, & ! Switch to consider demand for water for domestic use. l_water_industry, & @@ -189,7 +214,9 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ! Local variables !------------------------------------------------------------------------------ INTEGER :: & - land_pts_dim, land_pts_gw, land_pts_sw, n_sw_source_dim, nwater_use_dim + 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 ! Sizes used when allocating arrays. INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 @@ -203,46 +230,65 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! Arrays are always allocated, but with minimal size if the science is not ! selected. Decide on sizes. -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! Set default sizes that are used if water resources (or a particular part of ! the parameterisation) are not selected. -land_pts_dim = 1 -land_pts_gw = 1 -land_pts_sw = 1 -n_sw_source_dim = 1 -nwater_use_dim = 1 +global_land_pts_minor_res = 1 +global_land_pts_rivers = 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 land_pts_dim = land_pts n_sw_source_dim = n_sw_source nwater_use_dim = nwater_use IF ( l_have_groundwater ) THEN - land_pts_gw = land_pts + land_pts_gw = land_pts END IF IF ( l_have_surface_water ) THEN - land_pts_sw = land_pts + land_pts_sw = land_pts END IF -END IF + IF ( sw_river_source > 0 ) THEN + land_pts_rivers = land_pts + ! The "global" variable only needs to be full size on master task. + IF ( l_is_master_task ) THEN + global_land_pts_rivers = 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. + IF ( l_is_master_task ) THEN + global_land_pts_minor_res = global_land_pts + END IF + END IF +END IF ! l_water_resources !----------------------------------------------------------------------------- ! Priority order. !----------------------------------------------------------------------------- ALLOCATE( water_resources_data%priority_order(land_pts_dim,nwater_use_dim) ) -!----------------------------------------------------------------------------- -! Ancillary fields. -! Although these are not required for every configuration, they are commonly -! required and hence for convenience we always allocate them. -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ +! Ancillary fields on land points. +! Although these are not required for every configuration that includes water +! resources they are commonly required and hence for convenience we always +! allocate them. +!------------------------------------------------------------------------------ ALLOCATE( water_resources_data%conv_loss_frac(land_pts_dim) ) ALLOCATE( water_resources_data%sfc_water_frac(land_pts_dim) ) -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! Individual demands (which can be prescibed). ! We allocate a minimum size if a sector is not being used. -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ IF ( l_water_domestic ) THEN ALLOCATE( water_resources_data%demand_rate_domestic(land_pts_dim) ) ELSE @@ -267,17 +313,29 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ALLOCATE( water_resources_data%demand_rate_transfers(1) ) END IF -!----------------------------------------------------------------------------- -! Coupling to rivers - which are always modelled if l_have_surface_water=T. -!----------------------------------------------------------------------------- -ALLOCATE( water_resources_data%net_abstracted_river(land_pts_sw) ) +!------------------------------------------------------------------------------ +! Coupling to minor reservoirs. +! Only allocated at full size if minor 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_minor_res_global(global_land_pts_minor_res) ) -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ +! Coupling to rivers. +! Only allocated at full size if rivers are modelled. +! Allocated space for all (global) land points because both the water resource +! and river codes operate globally. +!------------------------------------------------------------------------------ +ALLOCATE( water_resources_data & + %net_abstracted_river_global(global_land_pts_rivers) ) + +!------------------------------------------------------------------------------ ! Other variables. -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ALLOCATE( water_resources_data%demand_accum(land_pts_dim,nwater_use_dim) ) ALLOCATE( water_resources_data%demand_unmet(land_pts_dim,nwater_use_dim) ) -ALLOCATE( water_resources_data%water_removed(land_pts_dim) ) ! Groundwater variables. ALLOCATE( water_resources_data%gw_abstracted(land_pts_gw) ) ALLOCATE( water_resources_data%gw_avail(land_pts_gw) ) @@ -285,10 +343,15 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ! Surface water variables. 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_minor_res(land_pts_minor_res) ) +ALLOCATE( water_resources_data%abstracted_river(land_pts_rivers) ) +ALLOCATE( water_resources_data%conveyance_loss(land_pts_dim) ) +ALLOCATE( water_resources_data%water_removed(land_pts_dim) ) -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! Initialise arrays. -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ water_resources_data%priority_order(:,:) = 0 water_resources_data%conv_loss_frac(:) = 0.0 water_resources_data%sfc_water_frac(:) = 0.0 @@ -296,15 +359,19 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & 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%net_abstracted_river(:) = 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 water_resources_data%demand_unmet(:,:) = 0.0 -water_resources_data%water_removed(:) = 0.0 water_resources_data%gw_abstracted(:) = 0.0 water_resources_data%gw_avail(:) = 0.0 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_minor_res(:) = 0.0 +water_resources_data%abstracted_river(:) = 0.0 +water_resources_data%conveyance_loss(:) = 0.0 +water_resources_data%water_removed(:) = 0.0 IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -340,22 +407,27 @@ SUBROUTINE water_resources_dealloc(water_resources_data) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) -DEALLOCATE( water_resources_data%priority_order ) -DEALLOCATE( water_resources_data%conv_loss_frac ) -DEALLOCATE( water_resources_data%sfc_water_frac ) -DEALLOCATE( water_resources_data%demand_rate_domestic ) -DEALLOCATE( water_resources_data%demand_rate_industry ) -DEALLOCATE( water_resources_data%demand_rate_livestock ) -DEALLOCATE( water_resources_data%demand_rate_transfers ) -DEALLOCATE( water_resources_data%net_abstracted_river ) -DEALLOCATE( water_resources_data%demand_accum ) -DEALLOCATE( water_resources_data%demand_unmet ) +! Deallocate in reverse order to allocation. DEALLOCATE( water_resources_data%water_removed ) -DEALLOCATE( water_resources_data%gw_abstracted ) -DEALLOCATE( water_resources_data%gw_avail ) -DEALLOCATE( water_resources_data%gw_nr_abstracted ) -DEALLOCATE( water_resources_data%sw_abstracted ) +DEALLOCATE( water_resources_data%conveyance_loss ) +DEALLOCATE( water_resources_data%abstracted_river ) +DEALLOCATE( water_resources_data%abstracted_minor_res ) DEALLOCATE( water_resources_data%sw_avail_total ) +DEALLOCATE( water_resources_data%sw_abstracted ) +DEALLOCATE( water_resources_data%gw_nr_abstracted ) +DEALLOCATE( water_resources_data%gw_avail ) +DEALLOCATE( water_resources_data%demand_unmet ) +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_minor_res_global ) +DEALLOCATE( water_resources_data%demand_rate_transfers ) +DEALLOCATE( water_resources_data%demand_rate_livestock ) +DEALLOCATE( water_resources_data%demand_rate_industry ) +DEALLOCATE( water_resources_data%demand_rate_domestic ) +DEALLOCATE( water_resources_data%sfc_water_frac ) +DEALLOCATE( water_resources_data%conv_loss_frac ) +DEALLOCATE( water_resources_data%priority_order ) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -412,16 +484,22 @@ 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%net_abstracted_river & - => water_resources_data%net_abstracted_river +water_resources%abstracted_minor_res_global & + => water_resources_data%abstracted_minor_res_global +water_resources%net_abstracted_river_global & + => water_resources_data%net_abstracted_river_global water_resources%demand_accum => water_resources_data%demand_accum water_resources%demand_unmet => water_resources_data%demand_unmet -water_resources%water_removed => water_resources_data%water_removed water_resources%gw_abstracted => water_resources_data%gw_abstracted water_resources%gw_avail => water_resources_data%gw_avail 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_minor_res & + => water_resources_data%abstracted_minor_res +water_resources%abstracted_river => water_resources_data%abstracted_river +water_resources%conveyance_loss => water_resources_data%conveyance_loss +water_resources%water_removed => water_resources_data%water_removed IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -461,15 +539,19 @@ 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%net_abstracted_river ) +NULLIFY( water_resources%abstracted_minor_res_global ) +NULLIFY( water_resources%net_abstracted_river_global ) NULLIFY( water_resources%demand_accum ) NULLIFY( water_resources%demand_unmet ) -NULLIFY( water_resources%water_removed ) NULLIFY( water_resources%gw_abstracted ) NULLIFY( water_resources%gw_avail ) NULLIFY( water_resources%gw_nr_abstracted ) NULLIFY( water_resources%sw_abstracted ) NULLIFY( water_resources%sw_avail_total ) +NULLIFY( water_resources%abstracted_minor_res ) +NULLIFY( water_resources%abstracted_river ) +NULLIFY( water_resources%conveyance_loss ) +NULLIFY( water_resources%water_removed ) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN diff --git a/src/control/standalone/control.F90 b/src/control/standalone/control.F90 index 0542a79b..f9bfa6eb 100644 --- a/src/control/standalone/control.F90 +++ b/src/control/standalone/control.F90 @@ -271,7 +271,7 @@ SUBROUTINE control ( & !Total resistance factor, fracaero_t+(1-fracaero_t)*RESFS for snow-free !land, 1 for snow. rhokh(tdims%i_start:tdims%i_end,tdims%j_start:tdims%j_end), & - ! Grid-box surface exchange coefficients + ! Grid-box surfac atmos_number_of_landpts +#else +USE model_grid_mod, ONLY: global_land_pts +#endif USE theta_field_sizes, ONLY: t_i_length, t_j_length, & u_i_length,u_j_length, & v_i_length,v_j_length @@ -142,6 +148,8 @@ SUBROUTINE allocate_jules_arrays(crop_vars_data,psparms_data,top_pdm_data, & USE Field_Types, ONLY: fld_type_r #endif +USE parallel_mod, ONLY: is_master_task + USE parkind1, ONLY: jprb, jpim USE yomhook, ONLY: lhook, dr_hook @@ -265,7 +273,8 @@ SUBROUTINE allocate_jules_arrays(crop_vars_data,psparms_data,top_pdm_data, & nice,nsoilt,ntype, & ainfo_data) -CALL jules_rivers_alloc(land_pts, t_i_length, t_j_length, rivers_data) +CALL jules_rivers_alloc(land_pts, t_i_length, t_j_length, & + sw_river_source, l_water_resources, rivers_data) CALL forcing_alloc(t_i_length,t_j_length, u_i_length, u_j_length, & v_i_length, v_j_length, forcing_data) @@ -290,12 +299,14 @@ SUBROUTINE allocate_jules_arrays(crop_vars_data,psparms_data,top_pdm_data, & CALL deposition_species_alloc(ntype, ndry_dep_species, l_deposition) -CALL water_resources_alloc( land_pts, n_sw_source, nwater_use, & - l_have_groundwater, l_have_surface_water, & +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_water_domestic, l_water_industry, & - l_water_irrigation, l_water_livestock, & - l_water_resources, l_water_transfers, & - water_resources_data ) + l_water_irrigation, & + l_water_livestock, l_water_resources, & + l_water_transfers, water_resources_data ) ! Set up local river grid sizes (Note, water tracers only work in UM_JULES) #if defined(UM_JULES) 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 d2b50cfe..6a5dc22d 100644 --- a/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 +++ b/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 @@ -1029,9 +1029,9 @@ SUBROUTINE remap_ancil( nx_rivers, ny_rivers, rivers_dx, & USE jules_rivers_mod, ONLY: & channel_depth_grid, channel_width_grid, mean_sea_level_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_elevation_grid, river_length_grid, & + river_manning_grid, river_nextx_grid, river_nexty_grid, rivers_type USE overbank_inundation_mod, ONLY: & hypsometric_quantiles_grid, logn_mean, logn_stdev, nquantile_hypso @@ -1085,7 +1085,7 @@ SUBROUTINE remap_ancil( nx_rivers, ny_rivers, rivers_dx, & SELECT CASE ( var ) !---------------------------------------------------------------------------- - ! Cases for river (not overbank) variables. + ! Cases for river variables. !---------------------------------------------------------------------------- CASE ( 'area' ) CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & @@ -1175,6 +1175,17 @@ SUBROUTINE remap_ancil( nx_rivers, ny_rivers, rivers_dx, & CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & rivers%rivers_xgrid, logn_stdev ) + !---------------------------------------------------------------------------- + ! Cases for minor reservoir variables. + !---------------------------------------------------------------------------- +CASE ( 'minor_res_capacity_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, minor_res_capacity_grid ) + +CASE ( 'minor_res_frac_grid' ) + CALL remap_field( nx_rivers, ny_rivers, rivers_dx, l_shift_x, l_reverse_y, & + rivers%rivers_xgrid, minor_res_frac_grid ) + !---------------------------------------------------------------------------- ! Cases for the 1-D coordinate variables. ! Rather than requiring separate 1-D remapping routines, we instead create @@ -2216,9 +2227,11 @@ SUBROUTINE set_river_point_values( rivers_x1_input, & USE jules_model_environment_mod, ONLY: l_oasis_rivers USE jules_rivers_mod, ONLY: & - a_thresh, channel_depth_grid, channel_width_grid, i_river_vn, l_sea_level, & - l_riv_overbank, mean_sea_level_grid, np_rivers, nseqmax, nx_rivers, & - ny_rivers, rfm_land, rfm_river, rivers_camaflood, river_distance_grid, & + a_thresh, channel_depth_grid, channel_width_grid, i_river_vn, & + l_minor_reservoirs, l_sea_level, l_riv_overbank, & + mean_sea_level_grid, minor_res_capacity_grid, minor_res_frac_grid, & + np_rivers, nseqmax, nx_rivers, ny_rivers, rfm_land, rfm_river, & + 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, & @@ -2393,8 +2406,8 @@ SUBROUTINE set_river_point_values( rivers_x1_input, & rivers%channel_width(ip) = channel_width_grid(irx,iry) rivers%river_distance(ip) = river_distance_grid(irx,iry) rivers%river_elevation(ip) = river_elevation_grid(irx,iry) - rivers% river_length(ip) = river_length_grid(irx,iry) - rivers% river_manning(ip) = river_manning_grid(irx,iry) + rivers%river_length(ip) = river_length_grid(irx,iry) + rivers%river_manning(ip) = river_manning_grid(irx,iry) IF ( l_sea_level ) THEN rivers%mean_sea_level(ip) = mean_sea_level_grid(irx,iry) END IF @@ -2462,6 +2475,16 @@ SUBROUTINE set_river_point_values( rivers_x1_input, & END IF ! l_riv_overbank + !------------------------------------------------------------------------ + ! Set minor reservoir ancillary variables, if required. + !------------------------------------------------------------------------ + IF ( l_minor_reservoirs ) THEN + + rivers%minor_res_capacity(ip) = minor_res_capacity_grid(irx,iry) + rivers%minor_res_frac(ip) = minor_res_frac_grid(irx,iry) + + END IF ! l_minor_reservoirs + END IF ! point_mask END DO ! iy diff --git a/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 index 541870ba..821a8793 100644 --- a/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 @@ -47,7 +47,8 @@ SUBROUTINE init_rivers_props(rivers, rivers_data) USE io_constants, ONLY: max_file_name_len, namelist_unit USE jules_rivers_mod, ONLY: & - i_river_vn, l_rivers, l_sea_level, rivers_camaflood, rivers_rfm, & + i_river_vn, l_rivers, l_minor_reservoirs, l_sea_level, & + rivers_camaflood, rivers_rfm, & rivers_trip, y1_land_grid, l_riv_overbank, l_outflow_per_river, & l_init_storage, & ! types @@ -60,6 +61,9 @@ SUBROUTINE init_rivers_props(rivers, rivers_data) var_name, l_use_area, nx_rivers, ny_rivers, file_name_coords, & x_dim_name, y_dim_name, is_climatology +USE jules_water_resources_mod, ONLY: & + l_water_resources + USE logging_mod, ONLY: log_fatal, log_info USE jules_print_mgr, ONLY: jules_message @@ -298,6 +302,16 @@ SUBROUTINE init_rivers_props(rivers, rivers_data) required_vars(nvars_required) = 'area' END IF + !---------------------------------------------------------------------------- + ! Add variables for minor reservoirs. + !---------------------------------------------------------------------------- + IF ( l_minor_reservoirs ) THEN + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'minor_res_capacity_grid' + nvars_required = nvars_required + 1 + required_vars(nvars_required) = 'minor_res_frac_grid' + END IF + ! OASIS-Rivers: ! l_outflow_per_river is set before now by check_oasis_rivers and is ! true when outflow_per_river is present in send_fields; requires the diff --git a/src/initialisation/standalone/ancillaries/init_water_resources_props_mod.F90 b/src/initialisation/standalone/ancillaries/init_water_resources_props_mod.F90 index 69afb014..4de9c071 100644 --- a/src/initialisation/standalone/ancillaries/init_water_resources_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/init_water_resources_props_mod.F90 @@ -38,7 +38,7 @@ SUBROUTINE init_water_resources_props !------------------------------------------------------------------------------ ! Description: -! Reads ancillary fields related to water resource modelling. +! Reads ancillary fields related to water resource modelling. ! ! Code Owner: Please refer to ModuleLeaders.txt ! This file belongs in TECHNICAL diff --git a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 index d847d1a0..3593a783 100644 --- a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 @@ -165,11 +165,12 @@ MODULE jules_rivers_props_mod 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_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, & - l_init_storage + i_river_vn, land_dx, land_dy, l_init_storage, & + l_minor_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 USE model_grid_mod, ONLY: l_coord_latlon @@ -190,7 +191,7 @@ SUBROUTINE check_jules_rivers_props() INTEGER :: i ! Loop counter INTEGER, PARAMETER :: & - nvar_values = 9 ! Number of recognised identifiers + nvar_values = 11 ! Number of recognised identifiers CHARACTER(LEN=identifier_len) :: & var_values(nvar_values) ! Names of recognised identifiers @@ -206,15 +207,17 @@ SUBROUTINE check_jules_rivers_props() ny_rivers_in = ny_rivers ! Check that the requested identifiers are recognised. -var_values(:) = ['area ', & - 'direction ', & - 'sequence ', & - 'latitude_2d ', & - 'longitude_2d ', & - 'rivers_outflow_number', & - 'rivers_storage ', & - 'logn_mean ', & - 'logn_stdev '] +var_values(:) = ['area ', & + 'direction ', & + 'sequence ', & + 'latitude_2d ', & + 'longitude_2d ', & + 'rivers_outflow_number ', & + 'rivers_storage ', & + 'logn_mean ', & + 'logn_stdev ', & + 'minor_res_capacity_grid', & + 'minor_res_frac_grid '] DO i = 1, nvars IF ( .NOT. ANY( var_values(:) == var(i) ) ) THEN @@ -389,7 +392,9 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & !------------------------------------------------------------------------------ USE jules_rivers_mod, ONLY: channel_depth_grid, channel_width_grid, i_river_vn,& - l_sea_level, mean_sea_level_grid, rivers_camaflood,& + l_minor_reservoirs, l_sea_level, & + mean_sea_level_grid, minor_res_capacity_grid, & + minor_res_frac_grid, rivers_camaflood, & river_distance_grid, river_elevation_grid, & river_length_grid, river_manning_grid, & river_nextx_grid, river_nexty_grid, rivers_rfm, & @@ -423,10 +428,10 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & CHARACTER(LEN=*), PARAMETER :: RoutineName = 'ALLOCATE_RIVER_VARS_GRID' INTEGER :: & - ERROR, error_sum, & - ! Error values. - nx_size, ny_size - ! Sizes used for allocations. + ERROR, error_sum, & + ! Error values. + nx_size, ny_size + ! Sizes used for allocations. !end of header !------------------------------------------------------------------------------ @@ -548,7 +553,7 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & ALLOCATE( rivers_data%rivers_outflow_number(nx_size,ny_size), STAT = ERROR ) error_sum = error_sum + ERROR - +! River storage. IF ( l_init_storage ) THEN nx_size = nx_rivers ny_size = ny_rivers @@ -559,6 +564,19 @@ 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 +! Minor reservoir 2D ancillary variables. +IF ( l_minor_reservoirs ) THEN + nx_size = nx_rivers + ny_size = ny_rivers +ELSE + nx_size = 1 + ny_size = 1 +END IF +ALLOCATE( minor_res_capacity_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( minor_res_frac_grid(nx_size,ny_size), STAT = ERROR ) +error_sum = error_sum + ERROR + IF ( error_sum /= 0 ) THEN CALL log_fatal( RoutineName, "Error allocating for rivers arrays." ) END IF @@ -586,6 +604,8 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & rivers_data%rivers_outflow_number(:,:) = rmdi rivers_data%rivers_storage(:,:) = rmdi rivers_data%land_fraction_2d(:,:) = rmdi +minor_res_capacity_grid(:,:) = rmdi +minor_res_frac_grid(:,:) = rmdi ! Associate pointers rivers%rivers_dir => rivers_data%rivers_dir @@ -608,17 +628,26 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) !------------------------------------------------------------------------------ ! Description: ! Allocate river point variables, initialise, and associate pointers. -! Also allocates at least one variable on land points. +! Also allocates related variables on land points. !------------------------------------------------------------------------------ USE ancil_info, ONLY: land_pts +#if defined(UM_JULES) +USE atm_land_sea_mask, ONLY: global_land_pts => atmos_number_of_landpts +#else +USE model_grid_mod, ONLY: global_land_pts +#endif + USE jules_model_environment_mod, ONLY: l_oasis_rivers -USE jules_rivers_mod, ONLY: i_river_vn, l_sea_level, l_vary_sea_level, & - rivers_camaflood, rivers_data_type, rivers_rfm, & +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_water_resources_mod, ONLY: l_water_resources + USE missing_data_mod, ONLY: imdi, rmdi USE parallel_mod, ONLY: is_master_task @@ -646,6 +675,8 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) INTEGER :: & ERROR, error_sum, & ! Error flags. + np_global_land_tmp, & + ! Number of global land points (across all tasks) to allocate for. np_land_tmp, & ! Number of land points to allocate for. np_rivers_tmp @@ -880,6 +911,48 @@ 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 minor reservoir variables. +!------------------------------------------------------------------------------ +IF ( l_minor_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 + +! Minor reservoir ancillaries. +ALLOCATE( rivers_data%minor_res_capacity(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +ALLOCATE( rivers_data%minor_res_frac(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +! Minor reservoir prognostics. +ALLOCATE( rivers_data%minor_res_storage(np_rivers_tmp), STAT = ERROR ) +error_sum = error_sum + ERROR +! Minor reservoir coupling to rivers. +ALLOCATE( rivers_data%tot_abstracted_minor_res_global(np_global_land_tmp), & + STAT = ERROR ) +error_sum = error_sum + ERROR + +!------------------------------------------------------------------------------ +! Allocate further variables for coupling to water resources. +!------------------------------------------------------------------------------ +IF ( l_water_resources .AND. is_master_task() ) THEN + ! Full size. + np_global_land_tmp = global_land_pts +ELSE + ! Minimum size. + np_global_land_tmp = 1 +END IF + +! Coupling abstractions from rivers. +ALLOCATE( rivers_data%tot_net_abstracted_river_global(np_global_land_tmp), & + STAT = ERROR ) +error_sum = error_sum + ERROR + IF ( error_sum /= 0 ) THEN CALL log_fatal( RoutineName, "Error allocating for routing point arrays." ) END IF @@ -956,6 +1029,16 @@ 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 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_minor_res_global(:) = rmdi +rivers_data%tot_net_abstracted_river_global(:) = rmdi + !------------------------------------------------------------------------------ ! Associate pointers !------------------------------------------------------------------------------ @@ -978,10 +1061,10 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers%rrun_surf_rp => rivers_data%rrun_surf_rp rivers%inland_outflow_rp => rivers_data%inland_outflow_rp -! Associate pointers for regridding variable. +! Regridding variable. rivers%map_river_to_land_points => rivers_data%map_river_to_land_points -! Associate pointers for CaMa-Flood variables. +! CaMa-Flood variables. ! CaMa-Flood ancillary variables. rivers%channel_depth => rivers_data%channel_depth rivers%channel_width => rivers_data%channel_width @@ -1004,7 +1087,7 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) ! CaMa-Flood diagnostic variables. rivers%river_depth => rivers_data%river_depth -! Associate pointers for RFM variables. +! RFM variables. rivers%rfm_flowobs1_rp => rivers_data%rfm_flowobs1_rp rivers%rfm_iarea_rp => rivers_data%rfm_iarea_rp rivers%rfm_land_rp => rivers_data%rfm_land_rp @@ -1015,15 +1098,26 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers%rfm_substore_rp => rivers_data%rfm_substore_rp rivers%rfm_surfstore_rp => rivers_data%rfm_surfstore_rp -! Associate pointers for TRIP variables. +! TRIP variables. rivers%rivers_seq_rp => rivers_data%rivers_seq_rp rivers%rivers_sto_rp => rivers_data%rivers_sto_rp -! Associate pointers for coupling variables. +! Coupling variables. rivers%rivers_outflow_number_rp => rivers_data%rivers_outflow_number_rp rivers%sub_surf_roff_rp => rivers_data%sub_surf_roff_rp rivers%surf_roff_rp => rivers_data%surf_roff_rp +! Minor reservoir variables. +rivers%minor_res_capacity => rivers_data%minor_res_capacity +rivers%minor_res_frac => rivers_data%minor_res_frac +rivers%minor_res_storage => rivers_data%minor_res_storage +rivers%tot_abstracted_minor_res_global & + => rivers_data%tot_abstracted_minor_res_global + +! Further variables to couple to water resources. +rivers%tot_net_abstracted_river_global & + => rivers_data%tot_net_abstracted_river_global + RETURN END SUBROUTINE allocate_rivers_vars_rp @@ -1037,15 +1131,15 @@ SUBROUTINE deallocate_river_props( ) !------------------------------------------------------------------------------ USE jules_rivers_mod, ONLY: & - channel_depth_grid, channel_width_grid, river_distance_grid, & - river_elevation_grid, river_length_grid, river_manning_grid, & - river_nextx_grid, river_nexty_grid + 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 IMPLICIT NONE !------------------------------------------------------------------------------ -! Variables that are only allocated on master task and in some configurations -! - hence first check if allocated. +! Variables that are only allocated in some configurations and/or on master +! task - hence first check if allocated. !------------------------------------------------------------------------------ IF ( ALLOCATED(direction_grid) ) THEN DEALLOCATE( direction_grid ) @@ -1075,7 +1169,7 @@ SUBROUTINE deallocate_river_props( ) DEALLOCATE( river_nexty_grid ) END IF -! CaMa-Flood variables that are only allocated on master task. +! CaMa-Flood variables. IF ( ALLOCATED( channel_depth_grid ) ) THEN DEALLOCATE( channel_depth_grid ) END IF @@ -1100,6 +1194,15 @@ SUBROUTINE deallocate_river_props( ) DEALLOCATE( river_manning_grid ) END IF +! Minor reservoir variables. +IF ( ALLOCATED( minor_res_capacity_grid ) ) THEN + DEALLOCATE( minor_res_capacity_grid ) +END IF + +IF ( ALLOCATED( minor_res_frac_grid ) ) THEN + DEALLOCATE( minor_res_frac_grid ) +END IF + RETURN END SUBROUTINE deallocate_river_props diff --git a/src/initialisation/standalone/init_output_mod.F90 b/src/initialisation/standalone/init_output_mod.F90 index f35234c0..fa280e1d 100644 --- a/src/initialisation/standalone/init_output_mod.F90 +++ b/src/initialisation/standalone/init_output_mod.F90 @@ -344,10 +344,12 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & USE jules_water_resources_mod, ONLY: l_have_groundwater, l_have_renew_gwater, & l_have_surface_water, l_water_domestic, l_water_environment, & l_water_industry, l_water_irrigation, l_water_livestock, & - l_water_resources, l_water_transfers, no_model, nr_gwater_model + l_water_resources, l_water_transfers, no_model, nr_gwater_model, & + sw_river_source -USE jules_rivers_mod, ONLY: l_rivers, l_riv_overbank, l_outflow_per_river, & - i_river_vn, rivers_camaflood, rivers_rfm, rivers_trip, l_inland_outflow +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 USE jules_deposition_mod, ONLY: l_deposition, l_deposition_flux @@ -664,10 +666,11 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & ELSE !------------------------------------------------------------------------- - ! Variables that are only allowed with river routing. + ! Rivers are not selected. + ! Check for variables that are only allowed with river routing. ! First we check for variables on the river output grid (which allow us to ! shortern the list by omitting those), then by name for any other river - ! variable.< + ! variable. !------------------------------------------------------------------------- IF ( is_river_var(var(j)) ) THEN remove_var = .TRUE. @@ -682,15 +685,16 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & END IF ! l_rivers - !--------------------------------------------------------------------------- + !---------------------------------------------------------------------------- ! River 2D ancillary variables (including for overbank inundation) - these ! can be read in but not output (because code for 2D river grid outputs does ! not exist). - !--------------------------------------------------------------------------- + !---------------------------------------------------------------------------- SELECT CASE ( var(j) ) CASE ( 'area', 'channel_depth_grid', 'channel_width_grid', & 'direction', 'hypso_quantiles_grid', 'latitude_2d', 'logn_mean', & 'logn_stdev', 'longitude_2d', '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', & 'rivers_xgrid', 'rivers_ygrid', 'sequence' ) @@ -699,6 +703,17 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & 'for output.' END SELECT + !---------------------------------------------------------------------------- + ! Variables that are only allowed with minor reservoirs. + !---------------------------------------------------------------------------- + IF ( .NOT. l_minor_reservoirs ) THEN + SELECT CASE ( var(j) ) + CASE ( 'minor_res_capacity', 'minor_res_frac', 'minor_res_storage' ) + remove_var = .TRUE. + message = 'Minor reservoirs not used.' + END SELECT + END IF + !--------------------------------------------------------------------------- ! Thermal acclimation variables. !--------------------------------------------------------------------------- @@ -716,7 +731,8 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & ! Water resource variables that only require l_water_resources=T. IF ( .NOT. l_water_resources ) THEN SELECT CASE ( var(j) ) - CASE ( 'conv_loss_frac', 'water_demand', 'water_demand_unmet' ) + CASE ( 'conv_loss_frac', 'conveyance_loss', 'water_demand', & + 'water_demand_unmet', 'water_removed' ) remove_var = .TRUE. message = 'Water resources (l_water_resources) not selected.' END SELECT @@ -724,11 +740,11 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & ! Water resource variables that also require another switch. - ! These sector-specific switches are set to F if l_water_resources=F, - ! so we don't need to test l_water_resources here. + ! Sector-specific switches (such as l_water_domestic) are FALSE if + ! l_water_resources=F, so we don't need to test l_water_resources here. IF ( .NOT. l_water_domestic ) THEN SELECT CASE ( var(j) ) - CASE ( 'demand_domestic', 'demand_rate_domestic', 'domestic_unmet' ) + CASE ( 'demand_domestic', 'demand_rate_domestic', 'unmet_domestic' ) remove_var = .TRUE. message = 'l_water_domestic not selected.' END SELECT @@ -736,7 +752,7 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & IF ( .NOT. l_water_environment ) THEN SELECT CASE ( var(j) ) - CASE ( 'demand_environment', 'environment_unmet' ) + CASE ( 'demand_environment', 'unmet_environment' ) remove_var = .TRUE. message = 'l_water_environment not selected.' END SELECT @@ -744,7 +760,7 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & IF ( .NOT. l_water_industry ) THEN SELECT CASE ( var(j) ) - CASE ( 'demand_industry', 'demand_rate_industry', 'industry_unmet' ) + CASE ( 'demand_industry', 'demand_rate_industry', 'unmet_industry' ) remove_var = .TRUE. message = 'l_water_industry not selected.' END SELECT @@ -752,7 +768,7 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & IF ( .NOT. l_water_irrigation ) THEN SELECT CASE ( var(j) ) - CASE ( 'demand_irrigation', 'grid_area', 'irrigation_unmet' ) + CASE ( 'demand_irrigation', 'grid_area', 'unmet_irrigation' ) remove_var = .TRUE. message = 'l_water_irrigation not selected.' END SELECT @@ -760,7 +776,7 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & IF ( .NOT. l_water_livestock ) THEN SELECT CASE ( var(j) ) - CASE ( 'demand_livestock', 'demand_rate_livestock','livestock_unmet' ) + CASE ( 'demand_livestock', 'demand_rate_livestock','unmet_livestock' ) remove_var = .TRUE. message = 'l_water_livestock not selected.' END SELECT @@ -768,7 +784,7 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & IF ( .NOT. l_water_transfers ) THEN SELECT CASE ( var(j) ) - CASE ( 'demand_transfers', 'transfers_unmet' ) + CASE ( 'demand_transfers', 'unmet_transfers' ) remove_var = .TRUE. message = 'l_water_transfers not selected.' END SELECT @@ -782,7 +798,8 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & END SELECT END IF - IF ( nr_gwater_model == no_model ) THEN + IF ( .NOT. l_water_resources .OR. & + ( l_water_resources .AND. nr_gwater_model == no_model ) ) THEN SELECT CASE ( var(j) ) CASE ( 'gw_nr_abstracted' ) remove_var = .TRUE. @@ -806,6 +823,23 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & END SELECT END IF + IF ( .NOT. l_water_resources .OR. .NOT. l_minor_reservoirs ) THEN + SELECT CASE ( var(j) ) + CASE ( 'minor_res_abstracted' ) + remove_var = .TRUE. + message = 'Water resources + minor reservoirs not used.' + END SELECT + END IF + + IF ( .NOT. l_water_resources .OR. sw_river_source == 0 ) THEN + ! Rivers aren't being used as a source of water for abstraction. + SELECT CASE ( var(j) ) + CASE ( 'river_abstracted' ) + remove_var = .TRUE. + message = 'Rivers not used for abstractions.' + END SELECT + END IF + !--------------------------------------------------------------------------- ! Variables that are only allowed with atmospheric deposition !--------------------------------------------------------------------------- diff --git a/src/initialisation/standalone/init_water_resources_mod.F90 b/src/initialisation/standalone/init_water_resources_mod.F90 index 1dfd5ae3..00734311 100644 --- a/src/initialisation/standalone/init_water_resources_mod.F90 +++ b/src/initialisation/standalone/init_water_resources_mod.F90 @@ -39,10 +39,11 @@ SUBROUTINE init_water_resources(nml_dir) ! imported procedures check_jules_water_resources, & ! imported variables - l_prioritise, l_water_domestic, l_water_environment, l_water_industry, & - l_water_irrigation, l_water_livestock, l_water_resources, l_water_transfers, & - no_model, nr_gwater_last, nr_gwater_model, nr_gwater_use, nwater_use, & - priority, partition_ancil, partition_calc_from_stores, partition_method, & + l_prioritise, l_water_domestic, l_water_environment, & + l_water_industry, l_water_irrigation, l_water_livestock, l_water_resources, & + l_water_transfers, no_model, nr_gwater_last, nr_gwater_model, nr_gwater_use, & + nwater_use, priority, partition_ancil, partition_calc_from_stores, & + partition_method, & ! imported namelist jules_water_resources diff --git a/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 b/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 index 15fc5381..80c35e44 100644 --- a/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 +++ b/src/initialisation/standalone/initial_conditions/init_ic_mod.F90 @@ -993,6 +993,9 @@ 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) + !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 be189123..e7aa1243 100644 --- a/src/io/dump/get_dim_info_mod.F90 +++ b/src/io/dump/get_dim_info_mod.F90 @@ -558,13 +558,14 @@ SUBROUTINE get_dim_info_rivers( l_reading, identifier, ndims, dim_sizes, & SELECT CASE ( identifier ) ! River routing variables. + CASE ( 'rivers_lat_rp', 'rivers_lon_rp', 'rivers_x_coord_rp', & 'rivers_y_coord_rp', 'rivers_sto_rp', 'rfm_surfstore_rp', & 'rfm_substore_rp', 'rfm_flowin_rp', 'rfm_bflowin_rp', & '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' & + 'river_flow_prev', 'minor_res_storage' & ) ndims = 1 dim_names(1) = p_rivers_dim_name diff --git a/src/io/dump/read_dump_mod.F90 b/src/io/dump/read_dump_mod.F90 index fcfd4493..b97b500b 100644 --- a/src/io/dump/read_dump_mod.F90 +++ b/src/io/dump/read_dump_mod.F90 @@ -984,7 +984,8 @@ SUBROUTINE read_dump(file_name, identifiers) ! River routing variables CASE ( 'flood_flow', 'flood_flow_prev', 'flood_storage', & - 'flood_storage_prev', 'rfm_bflowin_rp', 'rfm_flowin_rp', & + 'flood_storage_prev', 'minor_res_storage', & + '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' ) diff --git a/src/io/dump/read_dump_var_rivers_mod.F90 b/src/io/dump/read_dump_var_rivers_mod.F90 index 2045b2b8..f8b0f66f 100644 --- a/src/io/dump/read_dump_var_rivers_mod.F90 +++ b/src/io/dump/read_dump_var_rivers_mod.F90 @@ -67,6 +67,9 @@ SUBROUTINE read_dump_var_rivers( identifier, FILE, var_id ) CASE ( 'flood_storage_prev' ) CALL file_read_var(FILE, var_id, rivers%flood_storage_prev) +CASE ( 'minor_res_storage' ) + CALL file_read_var(FILE, var_id, rivers%minor_res_storage) + CASE ( 'rfm_bflowin_rp' ) CALL file_read_var(FILE, var_id, rivers%rfm_bflowin_rp) diff --git a/src/io/dump/required_vars_for_rivers_mod.F90 b/src/io/dump/required_vars_for_rivers_mod.F90 index 8bbbe4a4..01ff4e5b 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_inland_outflow, l_minor_reservoirs USE logging_mod, ONLY: log_warn @@ -139,6 +139,15 @@ SUBROUTINE required_vars_for_rivers( nvars, identifiers, & END SELECT +IF ( l_minor_reservoirs ) THEN + IF ( read_or_write_dump_local ) THEN + CALL add_to_list( 'minor_res_storage', nvars, identifiers ) + ELSE + CALL log_warn( RoutineName, & + "Storage in minor reservoirs will be initialised to zero.") + END IF +END IF + RETURN END SUBROUTINE required_vars_for_rivers diff --git a/src/io/dump/write_dump_mod.F90 b/src/io/dump/write_dump_mod.F90 index 55a56520..cd5a19b8 100644 --- a/src/io/dump/write_dump_mod.F90 +++ b/src/io/dump/write_dump_mod.F90 @@ -676,8 +676,8 @@ SUBROUTINE write_dump() 'seed_rain', 'ch4_ppbv' ) ! Nothing to do - CASE ( 'rivers_lat_rp', 'rivers_lon_rp', 'rivers_sto_rp', & - 'rivers_x_coord_rp', 'rivers_y_coord_rp', & + 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', & 'rfm_flowin_rp', 'rfm_bflowin_rp', 'rivers_outflow_rp', & 'inland_outflow_rp', & diff --git a/src/io/dump/write_dump_var_rivers_mod.F90 b/src/io/dump/write_dump_var_rivers_mod.F90 index 20475240..5e1eb987 100644 --- a/src/io/dump/write_dump_var_rivers_mod.F90 +++ b/src/io/dump/write_dump_var_rivers_mod.F90 @@ -68,6 +68,9 @@ SUBROUTINE write_dump_var_rivers( identifier, FILE, var_id ) CASE ( 'flood_storage_prev' ) CALL file_write_var(FILE, var_id, rivers%flood_storage_prev) +CASE ( 'minor_res_storage' ) + CALL file_write_var(FILE, var_id, rivers%minor_res_storage) + CASE ( 'rfm_bflowin_rp' ) CALL file_write_var(FILE, var_id, rivers%rfm_bflowin_rp) diff --git a/src/io/model_interface/extract_var.inc b/src/io/model_interface/extract_var.inc index 83077bc9..1b71d626 100644 --- a/src/io/model_interface/extract_var.inc +++ b/src/io/model_interface/extract_var.inc @@ -2730,6 +2730,15 @@ CASE ( 'frac_fplain_lp' ) cube_land = cube_from_array(frac_fplain_lp) cube = map_from_land(cube_land) +CASE ( 'minor_res_capacity' ) + cube = cube_from_array(rivers%minor_res_capacity) + +CASE ( 'minor_res_frac' ) + cube = cube_from_array(rivers%minor_res_frac) + +CASE ( 'minor_res_storage' ) + cube = cube_from_array(rivers%minor_res_storage) + CASE ( 'lake_depth' ) cube_land = cube_from_array(lake_vars%lake_depth_gb) cube = map_from_land(cube_land) @@ -3318,6 +3327,11 @@ CASE ( 'conv_loss_frac' ) cube_land = cube_from_array( water_resources%conv_loss_frac ) cube = map_from_land(cube_land) +CASE ( 'conveyance_loss' ) + ! Convert kg to kg s-1. + cube_land = cube_from_array(water_resources%conveyance_loss / timestep) + cube = map_from_land(cube_land) + CASE ( 'demand_rate_domestic' ) cube_land = cube_from_array(water_resources%demand_rate_domestic) cube = map_from_land(cube_land) @@ -3420,6 +3434,16 @@ CASE ( 'gw_nr_abstracted' ) cube_land = cube_from_array( water_resources%gw_nr_abstracted / 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 ) + cube = map_from_land(cube_land) + +CASE ( 'river_abstracted' ) + ! Convert kg to kg s-1. + cube_land = cube_from_array( water_resources%abstracted_river / timestep ) + cube = map_from_land(cube_land) + CASE ( 'sfc_water_frac' ) cube_land = cube_from_array( water_resources%sfc_water_frac ) cube = map_from_land(cube_land) diff --git a/src/io/model_interface/model_interface_mod.F90 b/src/io/model_interface/model_interface_mod.F90 index b06b80a8..fcad6126 100644 --- a/src/io/model_interface/model_interface_mod.F90 +++ b/src/io/model_interface/model_interface_mod.F90 @@ -176,7 +176,7 @@ 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 = 723 +INTEGER, PARAMETER :: n_vars = 731 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 5b1ca8af..cc05833d 100644 --- a/src/io/model_interface/populate_var.inc +++ b/src/io/model_interface/populate_var.inc @@ -33,8 +33,9 @@ USE prognostics, ONLY: & USE jules_rivers_mod, ONLY: & ! 2D ancillary fields used during initialisation. channel_depth_grid, channel_width_grid, mean_sea_level_grid, & - river_distance_grid, river_elevation_grid, river_length_grid, & - river_manning_grid, river_nextx_grid, river_nexty_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 USE jules_soil_mod, ONLY: & sm_levels, l_tile_soil, l_broadcast_ancils @@ -2431,6 +2432,14 @@ CASE ( 'rivers_sto_rp' ) rivers%rivers_sto_rp(:) = const_val END IF +CASE ( 'minor_res_storage' ) + IF ( PRESENT(cube) ) THEN + cube_land = cube_create([ SIZE(cube%values) ]) + CALL cube_get_data(cube_land, rivers%minor_res_storage) + ELSE + rivers%minor_res_storage(:) = const_val + END IF + CASE ( 'rivers_outflow_rp' ) IF ( PRESENT(cube) ) THEN cube_land = cube_create([ SIZE(cube%values) ]) @@ -2512,6 +2521,20 @@ CASE ( 'logn_stdev' ) logn_stdev(:,:) = const_val END IF +CASE ( 'minor_res_capacity_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, minor_res_capacity_grid) + ELSE + minor_res_capacity_grid(:,:) = const_val + END IF + +CASE ( 'minor_res_frac_grid' ) + IF ( PRESENT(cube) ) THEN + CALL cube_get_data(cube, minor_res_frac_grid) + ELSE + minor_res_frac_grid(:,:) = const_val + END IF + !----------------------------------------------------------------------------- ! Fire and metstats variables- land points only !----------------------------------------------------------------------------- diff --git a/src/io/model_interface/variable_metadata.inc b/src/io/model_interface/variable_metadata.inc index 8b7fa44c..c33dd863 100644 --- a/src/io/model_interface/variable_metadata.inc +++ b/src/io/model_interface/variable_metadata.inc @@ -7951,7 +7951,7 @@ DATA metadata(614) / var_metadata( & "kg m-2 s-1" & ) / !----------------------------------------------------------------------------- -! Metadata for grid_area +! Metadata for grid_area_rp !----------------------------------------------------------------------------- DATA metadata(615) / var_metadata( & ! String identifier @@ -9367,4 +9367,106 @@ DATA metadata(723) / var_metadata( & ! Units "kg m-2 s-1" & ) / +!----------------------------------------------------------------------------- +! Metadata for conveyance_loss +!----------------------------------------------------------------------------- +DATA metadata(724) / var_metadata( & +! String identifier + 'conveyance_loss', & +! Variable type + var_type_surface, & +! Long name + "Water that is lost during conveyance", & +! Units + "kg s-1" & + ) / +!----------------------------------------------------------------------------- +! Metadata for minor_res_capacity_grid +!----------------------------------------------------------------------------- +DATA metadata(725) / var_metadata( & +! String identifier + 'minor_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 minor_res_frac_grid +!----------------------------------------------------------------------------- +DATA metadata(726) / var_metadata( & +! String identifier + 'minor_res_frac_grid', & +! Variable type + var_type_surface, & +! Variable is not available for output, so give dummy values for long name and +! units + "", "" & + ) / +!----------------------------------------------------------------------------- +! Metadata for minor_res_capacity +!----------------------------------------------------------------------------- +DATA metadata(727) / var_metadata( & +! String identifier + 'minor_res_capacity', & +! Variable type + var_type_rp, & +! Long name + "Storage capacity of minor reservoirs", & +! Units + "kg" & + ) / +!----------------------------------------------------------------------------- +! Metadata for minor_res_frac +!----------------------------------------------------------------------------- +DATA metadata(728) / var_metadata( & +! String identifier + 'minor_res_frac', & +! Variable type + var_type_rp, & +! Long name + "Catchment area of minor reservoirs as fraction of area", & +! Units + "1" & + ) / +!----------------------------------------------------------------------------- +! Metadata for minor_res_storage +!----------------------------------------------------------------------------- +DATA metadata(729) / var_metadata( & +! String identifier + 'minor_res_storage', & +! Variable type + var_type_rp, & +! Long name + "Water stored in minor reservoirs", & +! Units + "kg" & + ) / +!----------------------------------------------------------------------------- +! Metadata for minor_res_abstracted +!----------------------------------------------------------------------------- +DATA metadata(730) / var_metadata( & +! String identifier + 'minor_res_abstracted', & +! Variable type + var_type_surface, & +! Long name + "Water abstracted from minor_reservoirs", & +! Units + "kg s-1" & + ) / +!----------------------------------------------------------------------------- +! Metadata for river_abstracted +!----------------------------------------------------------------------------- +DATA metadata(731) / var_metadata( & +! String identifier + 'river_abstracted', & +! Variable type + var_type_surface, & +! Long name + "Water abstracted from rivers", & +! 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 9f94355b..ba2c65ff 100644 --- a/src/science/river_routing/rivers_route_mod.F90 +++ b/src/science/river_routing/rivers_route_mod.F90 @@ -28,7 +28,8 @@ MODULE rivers_route_mod !############################################################################## -SUBROUTINE rivers_route_rp(rivers) +SUBROUTINE rivers_route_rp( abstracted_minor_res_rp, net_abstracted_river_rp, & + rivers ) !------------------------------------------------------------------------------ ! @@ -42,8 +43,11 @@ SUBROUTINE rivers_route_rp(rivers) USE jules_rivers_mod, ONLY: & ! imported scalars with intent(in) - i_river_vn, rivers_camaflood, rivers_rfm, rivers_trip, np_rivers, & - rivers_type + i_river_vn, l_minor_reservoirs, np_rivers, nstep_rivers, & + rivers_camaflood, rivers_rfm, rivers_trip, rivers_type + +USE jules_water_resources_mod, ONLY: & + l_water_resources, sw_river_source USE rivers_route_camaflood_mod, ONLY: & ! imported procedures @@ -57,12 +61,29 @@ SUBROUTINE rivers_route_rp(rivers) ! imported procedures rivers_route_trip +USE route_minor_reservoirs_mod, ONLY: & + route_minor_reservoirs + +USE timestep_mod, ONLY: & + timestep + USE jules_print_mgr, ONLY: & jules_message, & jules_print IMPLICIT NONE +!------------------------------------------------------------------------------ +! Arguments with INTENT(IN) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN) :: & + abstracted_minor_res_rp(np_rivers), & + ! Water abstracted from minor reservoirs over river timestep, on river + ! points (kg). + net_abstracted_river_rp(np_rivers) + ! Water abstracted from rivers over river timestep, on river points + ! (kg m-2). + !------------------------------------------------------------------------------ ! Arguments with INTENT(IN OUT) !------------------------------------------------------------------------------ @@ -73,6 +94,9 @@ SUBROUTINE rivers_route_rp(rivers) !------------------------------------------------------------------------------ INTEGER :: ip ! loop counter +REAL(KIND=real_jlslsm) :: recip_timestep + ! Reciprocal of river timestep length (s-1). + !------------------------------------------------------------------------------ ! Local array variables !------------------------------------------------------------------------------ @@ -82,6 +106,33 @@ SUBROUTINE rivers_route_rp(rivers) !end of header +!------------------------------------------------------------------------------ +! Route surface runoff through minor reservoirs. +!------------------------------------------------------------------------------ +IF ( l_minor_reservoirs ) THEN + CALL route_minor_reservoirs( abstracted_minor_res_rp, & + rivers%minor_res_capacity, & + rivers%minor_res_frac, & + rivers%rivers_boxareas_rp, & + rivers%minor_res_storage, & + rivers%rrun_surf_rp ) +END IF + +!------------------------------------------------------------------------------ +! Remove net abstraction from rivers from surface runoff - in effect the +! surface runoff variable becomes a more generic source/sink term for rivers. +! The resulting term can be negative. +!------------------------------------------------------------------------------ +IF ( l_water_resources .AND. sw_river_source > 0 ) THEN + ! Calculate reciprocal of timestep length. + recip_timestep = 1.0 / ( REAL(nstep_rivers) * timestep ) + DO ip = 1, np_rivers + rivers%rrun_surf_rp(ip) = rivers%rrun_surf_rp(ip) & + ! Convert abstraction from kg m-2 to kg m-2 s-1. + - net_abstracted_river_rp(ip) * recip_timestep + END DO +END IF + !------------------------------------------------------------------------------ ! Calculate total runoff diagnostic. !------------------------------------------------------------------------------ diff --git a/src/science/river_routing/route_minor_reservoirs_mod.F90 b/src/science/river_routing/route_minor_reservoirs_mod.F90 new file mode 100644 index 00000000..399df072 --- /dev/null +++ b/src/science/river_routing/route_minor_reservoirs_mod.F90 @@ -0,0 +1,105 @@ +!******************************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_minor_reservoirs_mod + +USE um_types, ONLY: real_jlslsm + +IMPLICIT NONE + +PRIVATE ! Private scope by default +PUBLIC route_minor_reservoirs + +CONTAINS + +!############################################################################## + +SUBROUTINE route_minor_reservoirs( abstracted_minor_res_rp, minor_res_capacity,& + minor_res_frac, rivers_boxareas_rp, & + minor_res_storage, surf_runoff ) + +! Route runoff through minor reservoirs. + +USE jules_rivers_mod, ONLY: dt_rivers, np_rivers, nstep_rivers + +USE timestep_mod, ONLY: timestep + +IMPLICIT NONE +!------------------------------------------------------------------------------ +! Array arguments with INTENT(IN) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN) :: & + abstracted_minor_res_rp(np_rivers), & + ! Water abstracted from minor reservoirs (kg). + minor_res_capacity(np_rivers), & + ! Storage capacity of minor reservoirs (kg). + minor_res_frac(np_rivers), & + ! Catchment area of minor reservoirs as fraction of grid box. + rivers_boxareas_rp(np_rivers) + ! Area of each river grid pixel (m2). + +!------------------------------------------------------------------------------ +! Array arguments with INTENT(IN OUT) +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & + minor_res_storage(np_rivers), & + ! Water stored in minor reservoirs (kg). + surf_runoff(np_rivers) + ! Average rate of surface runoff since last call (kg m-2 s-1) + +!------------------------------------------------------------------------------ +! Local scalar variables +!------------------------------------------------------------------------------ +INTEGER :: & + i ! Loop counter. + +REAL(KIND=real_jlslsm) :: & + dt ! Routing timestep length (s). + +!end of header +!------------------------------------------------------------------------------ + +! Calculate timestep length. +dt = REAL(nstep_rivers) * timestep + +DO i = 1, np_rivers + + ! Only route through a minor reservoir where such a reservoir exists + IF ( minor_res_frac(i) > 0.0 .AND. minor_res_capacity(i) > 0.0 ) THEN + + ! Add a fraction of surface runoff to storage in minor reservoirs and + ! reduce the amount of runoff entering rivers by the same amount. + minor_res_storage(i) = minor_res_storage(i) & + + surf_runoff(i) & + * minor_res_frac(i) * rivers_boxareas_rp(i) * dt + surf_runoff(i) = surf_runoff(i) * ( 1.0 - minor_res_frac(i) ) + ! Remove water abstracted. + minor_res_storage(i) = minor_res_storage(i) - abstracted_minor_res_rp(i) + + ! If reservoir overflows, reduce storage to capacity and add the + ! overflow to runoff entering rivers. + IF ( minor_res_storage(i) > minor_res_capacity(i) ) THEN + surf_runoff(i) = surf_runoff(i) & + + ( minor_res_storage(i) - minor_res_capacity(i) ) & + / ( rivers_boxareas_rp(i) * dt ) + minor_res_storage(i) = minor_res_capacity(i) + END IF + + END IF + +END DO + +RETURN +END SUBROUTINE route_minor_reservoirs + +!############################################################################## + +END MODULE route_minor_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 1c96bede..fba8cedc 100644 --- a/src/science/water_resources/calc_avail_water_mod.F90 +++ b/src/science/water_resources/calc_avail_water_mod.F90 @@ -162,10 +162,9 @@ END SUBROUTINE calc_avail_groundwater !############################################################################## !############################################################################## -SUBROUTINE calc_avail_surface_water( global_land_index, & - map_river_to_land_points, & - rivers_index_rp, rfm_surfstore_rp, & - rivers_sto_rp, sw_avail_global ) +SUBROUTINE calc_avail_surface_water( minor_res_storage_global, & + river_storage_global, & + sw_avail_global ) !------------------------------------------------------------------------------ ! Description: @@ -175,28 +174,21 @@ SUBROUTINE calc_avail_surface_water( global_land_index, & USE model_grid_mod, ONLY: global_land_pts -USE jules_rivers_mod, ONLY: l_rivers, np_rivers +USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_rivers -USE jules_water_resources_mod, ONLY: n_sw_source, sw_river_source +USE jules_water_resources_mod, ONLY: n_sw_source, sw_minor_res_source, & + sw_river_source IMPLICIT NONE !------------------------------------------------------------------------------ ! Array arguments with INTENT(IN). !------------------------------------------------------------------------------ -INTEGER, INTENT(IN) :: & - global_land_index(global_land_pts), & - ! List of indices for the land model grid. - map_river_to_land_points(np_rivers), & - ! List of coincident land point numbers, on river points. - rivers_index_rp(np_rivers) - ! Index of points where routing is calculated. - REAL(KIND=real_jlslsm), INTENT(IN) :: & - rfm_surfstore_rp(np_rivers), & - ! River surface storage (m3). - rivers_sto_rp(np_rivers) - ! River water storage (kg). + minor_res_storage_global(global_land_pts), & + ! Water stored in minor reservoirs, on land points (kg). + river_storage_global(global_land_pts) + ! Water in rivers, on land points (kg). !------------------------------------------------------------------------------ ! Array arguments with INTENT(OUT). @@ -220,129 +212,25 @@ SUBROUTINE calc_avail_surface_water( global_land_index, & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) !------------------------------------------------------------------------------ -! Initialise values. +! Initialise output values. !------------------------------------------------------------------------------ sw_avail_global(:,:) = 0.0 -!------------------------------------------------------------------------------ -! Calculate the available water in rivers. -! At present this is the only possible source of surface water. -!------------------------------------------------------------------------------ IF ( l_rivers ) THEN - CALL calc_avail_river_water( global_land_index, map_river_to_land_points, & - rivers_index_rp, rfm_surfstore_rp, & - rivers_sto_rp, & - sw_avail_global(:,sw_river_source) ) -END IF - -IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) -RETURN -END SUBROUTINE calc_avail_surface_water - -!############################################################################## -!############################################################################## - -SUBROUTINE calc_avail_river_water( global_land_index, map_river_to_land_points,& - rivers_index_rp, rfm_surfstore_rp, & - rivers_sto_rp, river_avail_global ) - -!------------------------------------------------------------------------------ -! Description: -! Calculate water available from river storage, on the land grid. -!------------------------------------------------------------------------------ -USE ereport_mod, ONLY: ereport + ! Include water available from rivers. + sw_avail_global(:,sw_river_source) = river_storage_global(:) -USE jules_rivers_mod, ONLY: i_river_vn, np_rivers, rivers_rfm, rivers_trip + IF ( l_minor_reservoirs ) THEN + ! Include water stored in minor reservoirs. + sw_avail_global(:,sw_minor_res_source) = minor_res_storage_global(:) + END IF -USE model_grid_mod, ONLY: global_land_pts - -USE rivers_regrid_mod, ONLY: rivpts_to_landpts - -USE water_constants_mod, ONLY: rho_water - - -IMPLICIT NONE - -!------------------------------------------------------------------------------ -! Array arguments with INTENT(IN). -!------------------------------------------------------------------------------ -INTEGER, INTENT(IN) :: & - global_land_index(global_land_pts), & - ! List of indices for the land model grid. - map_river_to_land_points(np_rivers), & - ! List of coincident land point numbers, on river points. - rivers_index_rp(np_rivers) - ! Index of points where routing is calculated. - -REAL(KIND=real_jlslsm), INTENT(IN) :: & - rfm_surfstore_rp(np_rivers), & - ! River surface storage (m3). - rivers_sto_rp(np_rivers) - ! River water storage (kg). - -!------------------------------------------------------------------------------ -! Array arguments with INTENT(OUT). -!------------------------------------------------------------------------------ -REAL(KIND=real_jlslsm), INTENT(OUT) :: & - river_avail_global(global_land_pts) - ! Available river water, on land points (kg). - -!------------------------------------------------------------------------------ -! Local parameters. -!------------------------------------------------------------------------------ -CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_AVAIL_RIVER_WATER' - -!------------------------------------------------------------------------------ -! Local scalar variables. -!------------------------------------------------------------------------------ -INTEGER :: & - errorstatus - ! Error value. - -! 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) - -!------------------------------------------------------------------------------ -! Initialise values. -!------------------------------------------------------------------------------ -river_avail_global(:) = 0.0 - -!------------------------------------------------------------------------------ -! Select code for the current river model: variables differ between models. -! Convert a variable on river points to one on land points. -!------------------------------------------------------------------------------ -SELECT CASE ( i_river_vn ) - -CASE ( rivers_rfm ) - ! We will only include the surface store in the available water. - CALL rivpts_to_landpts( global_land_pts, np_rivers, map_river_to_land_points,& - global_land_index, rivers_index_rp, & - rfm_surfstore_rp, river_avail_global ) - ! Convert units from m3 to kg. - river_avail_global(:) = river_avail_global(:) * rho_water - -CASE ( rivers_trip ) - CALL rivpts_to_landpts( global_land_pts, np_rivers, map_river_to_land_points,& - global_land_index, rivers_index_rp, & - rivers_sto_rp, river_avail_global ) - -CASE DEFAULT - - errorstatus = 101 ! a fatal error - CALL ereport(RoutineName, errorstatus, 'Unknown value of i_river_vn.') - -END SELECT ! i_river_vn +END IF IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN -END SUBROUTINE calc_avail_river_water +END SUBROUTINE calc_avail_surface_water !############################################################################## diff --git a/src/science/water_resources/update_soil_water_mod.F90 b/src/science/water_resources/update_soil_water_mod.F90 index 42fc388a..686d6e25 100644 --- a/src/science/water_resources/update_soil_water_mod.F90 +++ b/src/science/water_resources/update_soil_water_mod.F90 @@ -175,7 +175,7 @@ SUBROUTINE update_soil_water( conveyance_loss, demand_irrig, & ELSE ! Without renewable groundwater, the water added is added to sub-surface ! runoff. It might be better to add to soil moisture, but that has not been - ! coded. + ! coded. Here we convert units from kg to kg m-2 s-1. DO l = 1, land_pts sub_surf_roff(l) = sub_surf_roff(l) + water_added(l) & / ( land_area(l) * timestep_len ) diff --git a/src/science/water_resources/water_resources_drive.F90 b/src/science/water_resources/water_resources_drive.F90 index af7f0465..af6df544 100644 --- a/src/science/water_resources/water_resources_drive.F90 +++ b/src/science/water_resources/water_resources_drive.F90 @@ -34,7 +34,7 @@ MODULE water_resources_drive_mod PUBLIC water_resources_drive ! Module parameters. -CHARACTER(LEN=*), PARAMETER, PRIVATE :: & +CHARACTER(LEN=*), PARAMETER :: & ModuleName = 'WATER_RESOURCES_DRIVE_MOD' CONTAINS @@ -47,7 +47,7 @@ SUBROUTINE water_resources_drive( global_land_pts, priority_order, & gw_nr_abstracted, sfc_water_frac, & sw_abstracted, sw_avail, water_removed, & conveyance_loss, return_flow_gw, & - return_flow_sw, supply_irrig ) + return_flow_river, supply_irrig ) !------------------------------------------------------------------------------ ! Description: @@ -118,7 +118,7 @@ SUBROUTINE water_resources_drive( global_land_pts, priority_order, & ! Water that is lost during conveyance (kg). return_flow_gw(global_land_pts), & ! Water that is returned to renewable groundwater after use (kg). - return_flow_sw(global_land_pts), & + return_flow_river(global_land_pts), & ! Water that is returned to rivers after use (kg). supply_irrig(global_land_pts) ! Water supplied for irrigation (kg). @@ -139,7 +139,7 @@ SUBROUTINE water_resources_drive( global_land_pts, priority_order, & ! Local array variables !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm) :: & - abstracted(global_land_pts,nwater_use), & + abstracted_per_use(global_land_pts,nwater_use), & ! Water abstracted for each use (kg). conveyance_loss_use(global_land_pts,nwater_use), & ! Water that is lost during conveyance, for each water use (kg). @@ -216,23 +216,24 @@ SUBROUTINE water_resources_drive( global_land_pts, priority_order, & !------------------------------------------------------------------------------ DO i = 1, nwater_use IF ( i == use_environment ) THEN - abstracted(:,i) = 0.0 + abstracted_per_use(:,i) = 0.0 ELSE - abstracted(:,i) = demand_accum(:,i) - demand_unmet(:,i) + abstracted_per_use(:,i) = demand_accum(:,i) - demand_unmet(:,i) END IF END DO !------------------------------------------------------------------------------ ! Calculate conveyance loss. !------------------------------------------------------------------------------ -CALL calc_conveyance_loss( global_land_pts, abstracted, conv_loss_frac, & +CALL calc_conveyance_loss( global_land_pts, abstracted_per_use, conv_loss_frac,& conveyance_loss, conveyance_loss_use ) -!--------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! Calculate return flows. !------------------------------------------------------------------------------ -CALL calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & - return_flow_gw, return_flow_sw, water_removed ) +CALL calc_return_flow( global_land_pts, abstracted_per_use, & + conveyance_loss_use, return_flow_gw, return_flow_river, & + water_removed ) !------------------------------------------------------------------------------ ! Calculate the water supplied for irrigation. @@ -240,7 +241,7 @@ SUBROUTINE water_resources_drive( global_land_pts, priority_order, & IF ( l_water_irrigation ) THEN DO l = 1, global_land_pts ! Water supplied is the water abstracted, minus conveyance loss. - supply_irrig(l) = abstracted(l,use_irrigation) & + supply_irrig(l) = abstracted_per_use(l,use_irrigation) & - conveyance_loss_use(l,use_irrigation) END DO END IF @@ -291,6 +292,16 @@ SUBROUTINE calc_target_split( global_land_pts, gw_avail, sw_avail, & sfc_water_frac(global_land_pts) ! Fraction of demand to be met from surface water. +!------------------------------------------------------------------------------ +! Local parameters. +!------------------------------------------------------------------------------ +REAL(KIND=real_jlslsm), PARAMETER :: & + water_min = 1.0e-10 + ! A minimum amount of water below which calculations are not performed + ! (kg). + +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_TARGET_SPLIT' + !------------------------------------------------------------------------------ ! Local scalar variables. !------------------------------------------------------------------------------ @@ -298,25 +309,12 @@ SUBROUTINE calc_target_split( global_land_pts, gw_avail, sw_avail, & l ! Loop counter. -!------------------------------------------------------------------------------ -! Local scalar variables. -!------------------------------------------------------------------------------ REAL(KIND=real_jlslsm) :: & denom, & ! Denominator (kg). surface_water ! Available surface water, multiplied by weighting factor (kg). -!------------------------------------------------------------------------------ -! Local parameters. -!------------------------------------------------------------------------------ -REAL(KIND=real_jlslsm), PARAMETER :: & - water_min = 1.0e-10 - ! A minimum amount of water below which calculations are not performed - ! (kg). - -CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_TARGET_SPLIT' - ! Dr Hook variables INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 @@ -386,6 +384,11 @@ SUBROUTINE split_demands( global_land_pts, demand_accum, sfc_water_frac, & demand_gw(global_land_pts,nwater_use) ! Demand for water from groundwater, for each water use (kg). +!------------------------------------------------------------------------------ +! Local parameters. +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'SPLIT_DEMANDS' + !------------------------------------------------------------------------------ ! Local scalar variables. !------------------------------------------------------------------------------ @@ -400,11 +403,6 @@ SUBROUTINE split_demands( global_land_pts, demand_accum, sfc_water_frac, & sw_frac(global_land_pts,nwater_use) ! Surface water fraction for each water use. -!------------------------------------------------------------------------------ -! Local parameters. -!------------------------------------------------------------------------------ -CHARACTER(LEN=*), PARAMETER :: RoutineName = 'SPLIT_DEMANDS' - ! Dr Hook variables INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 @@ -474,11 +472,12 @@ SUBROUTINE split_demands( global_land_pts, demand_accum, sfc_water_frac, & RETURN END SUBROUTINE split_demands -!############################################################################# -!############################################################################# +!############################################################################## +!############################################################################## -SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted, conv_loss_frac, & - conveyance_loss, conveyance_loss_use ) +SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted_per_use, & + conv_loss_frac, conveyance_loss, & + conveyance_loss_use ) !------------------------------------------------------------------------------ ! Description: @@ -504,7 +503,7 @@ SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted, conv_loss_frac, & ! Array arguments with INTENT(IN) !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm), INTENT(IN) :: & - abstracted(global_land_pts,nwater_use), & + abstracted_per_use(global_land_pts,nwater_use), & ! Water abstracted to meet each use (kg). conv_loss_frac(global_land_pts) ! Fraction of water that is lost during conveyance from source to user. @@ -518,6 +517,11 @@ SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted, conv_loss_frac, & conveyance_loss_use(global_land_pts,nwater_use) ! Water that is lost during conveyance, for each water use (kg). +!------------------------------------------------------------------------------ +! Local parameters. +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_CONVEYANCE_LOSS' + !------------------------------------------------------------------------------ ! Local scalar variables. !------------------------------------------------------------------------------ @@ -532,11 +536,6 @@ SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted, conv_loss_frac, & loss_frac(global_land_pts) ! Fraction of water that is lost during conveyance. -!------------------------------------------------------------------------------ -! Local parameters. -!------------------------------------------------------------------------------ -CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_CONVEYANCE_LOSS' - ! Dr Hook variables INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 @@ -568,7 +567,7 @@ SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted, conv_loss_frac, & ! Calculate conveyance loss for this use and add to total. !--------------------------------------------------------------------------- DO l = 1, global_land_pts - conveyance_loss_use(l,i) = loss_frac(l) * abstracted(l,i) + conveyance_loss_use(l,i) = loss_frac(l) * abstracted_per_use(l,i) conveyance_loss(l) = conveyance_loss(l) + conveyance_loss_use(l,i) END DO @@ -578,22 +577,21 @@ SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted, conv_loss_frac, & RETURN END SUBROUTINE calc_conveyance_loss -!############################################################################# -!############################################################################# +!############################################################################## +!############################################################################## -SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & - return_flow_gw, return_flow_sw, water_removed ) +SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & + conveyance_loss_use, return_flow_gw, & + return_flow_river, water_removed ) !------------------------------------------------------------------------------ ! Description: -! Calculate return flows (i.e. water that is returned after use) and water -! that is removed from the system during use. +! Partition the water delivered for each use into a return flow and water +! removed through that use. !------------------------------------------------------------------------------ -USE jules_rivers_mod, ONLY: l_rivers - USE jules_water_resources_mod, ONLY: & - l_have_groundwater, l_have_surface_water, nwater_use, rf_domestic, & + nwater_use, rf_domestic, & rf_livestock, rf_industry, use_environment, use_domestic, use_industry, & use_irrigation, use_livestock, use_transfers @@ -610,7 +608,7 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & ! Array arguments with INTENT(IN) !------------------------------------------------------------------------------ REAL(KIND=real_jlslsm), INTENT(IN) :: & - abstracted(global_land_pts,nwater_use), & + abstracted_per_use(global_land_pts,nwater_use), & ! Water abstracted to meet each use (kg). conveyance_loss_use(global_land_pts,nwater_use) ! Water that is lost during conveyance, for each water use (kg). @@ -621,14 +619,17 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & REAL(KIND=real_jlslsm), INTENT(OUT) :: & return_flow_gw(global_land_pts), & ! Water that is returned to renewable groundwater after use (kg). - ! If there is no renewable groundwater, this water is later added to - ! the runoff flux. - return_flow_sw(global_land_pts), & + return_flow_river(global_land_pts), & ! Water that is returned to rivers after use (kg). water_removed(global_land_pts) ! Water that is removed from the system during use, e.g. incorporated into ! manufactured goods (kg). +!------------------------------------------------------------------------------ +! Local parameters. +!------------------------------------------------------------------------------ +CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_RETURN_FLOW' + !------------------------------------------------------------------------------ ! Local scalar variables. !------------------------------------------------------------------------------ @@ -645,14 +646,9 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & return_flow_frac_gw, & ! Fraction of the water delivered that is then returned to renewable ! groundwater. - return_flow_frac_sw + return_flow_frac_river ! Fraction of the water delivered that is then returned to rivers. -!------------------------------------------------------------------------------ -! Local parameters. -!------------------------------------------------------------------------------ -CHARACTER(LEN=*), PARAMETER :: RoutineName = 'CALC_RETURN_FLOW' - ! Dr Hook variables INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 @@ -663,50 +659,32 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) ! Initialise return flows and water removed. -return_flow_gw(:) = 0.0 -return_flow_sw(:) = 0.0 -water_removed(:) = 0.0 +return_flow_gw(:) = 0.0 +return_flow_river(:) = 0.0 +water_removed(:) = 0.0 DO i = 1, nwater_use !--------------------------------------------------------------------------- - ! Set fraction of flow that is returned for this water use. Each use returns - ! water to either renewable groundwater or river water, but if that sink is - ! not modelled the other is used. We know that at least one of l_rivers and - ! l_have_groundwater is always TRUE when water resources are modelled. If - ! the only groundwater is "non-renewable", any groundwater return is instead - ! later added to runoff (not groundwater). + ! Set the fraction of flow that is returned for this water use. Each use + ! returns water to either groundwater or rivers. The complementary fraction + ! is removed from the system (e.g. by being incorporated into a product). !--------------------------------------------------------------------------- IF ( i == use_domestic ) THEN - ! Domestic water is returned to rivers, if those are modelled. - IF ( l_rivers ) THEN - return_flow_frac_gw = 0.0 - return_flow_frac_sw = rf_domestic - ELSE - return_flow_frac_gw = rf_domestic - return_flow_frac_sw = 0.0 - END IF - removed_frac = 1.0 - rf_domestic + ! Domestic water is returned to rivers. + return_flow_frac_gw = 0.0 + return_flow_frac_river = rf_domestic + removed_frac = 1.0 - rf_domestic ELSE IF ( i == use_industry ) THEN - ! Industrial water is returned to rivers, if those are modelled. - IF ( l_rivers ) THEN - return_flow_frac_gw = 0.0 - return_flow_frac_sw = rf_industry - ELSE - return_flow_frac_gw = rf_industry - return_flow_frac_sw = 0.0 - END IF - removed_frac = 1.0 - rf_industry + ! Industrial water is returned to rivers. + return_flow_frac_gw = 0.0 + return_flow_frac_river = rf_industry + removed_frac = 1.0 - rf_industry ELSE IF ( i == use_livestock ) THEN - ! Livestock water is returned to groundwater, if that is modelled. - IF ( l_have_groundwater ) THEN - return_flow_frac_gw = rf_livestock - return_flow_frac_sw = 0.0 - ELSE - return_flow_frac_gw = 0.0 - return_flow_frac_sw = rf_livestock - END IF - removed_frac = 1.0 - rf_livestock + ! Livestock water is returned to renewable groundwater. + return_flow_frac_gw = rf_livestock + return_flow_frac_river = 0.0 + removed_frac = 1.0 - rf_livestock ELSE ! For all other uses no water is returned and none is removed (in that the ! water remains in the system and is accounted for). There is nothing more @@ -721,12 +699,12 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & ! Calculate the water delivered to meet this demand in this gridbox. ! This is the water abstracted, minus conveyance loss. - delivered = abstracted(l,i) - conveyance_loss_use(l,i) + delivered = abstracted_per_use(l,i) - conveyance_loss_use(l,i) - ! Add to totals. Both GW and SW return flows are always calculated, though - ! either can be zero if those sources are not represented. + ! Add to totals return_flow_gw(l) = return_flow_gw(l) + return_flow_frac_gw * delivered - return_flow_sw(l) = return_flow_sw(l) + return_flow_frac_sw * delivered + return_flow_river(l) = return_flow_river(l) & + + return_flow_frac_river * delivered water_removed(l) = water_removed(l) + removed_frac * delivered END DO