From 8f86b82979554f70df57c3a482f924f161d69c47 Mon Sep 17 00:00:00 2001 From: Phil Harris Date: Mon, 26 Jan 2026 08:41:40 +0000 Subject: [PATCH 01/24] Rose stem fixes for cehwl site (#35) Co-authored-by: James Bruten <109733895+james-bruten-mo@users.noreply.github.com> --- CONTRIBUTORS.md | 1 + etc/fcm-make/make-river.cfg | 8 +++++--- etc/fcm-make/make.cfg | 3 +++ etc/fcm-make/mpi/nompi.cfg | 4 ++++ etc/fcm-make/platform/ceh-rocky9.cfg | 23 +++++++++++++++++++++++ rose-stem/include/cehwl1/runtime.cylc | 15 ++++++++------- 6 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 etc/fcm-make/platform/ceh-rocky9.cfg diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c34eb45d..0d331a8a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -3,3 +3,4 @@ | GitHub user | Real Name | Affiliation | Date | | ----------- | --------- | ----------- | ---- | | james-bruten-mo | James Bruten | Met Office | 2025-12-09 | +| ppharris | Phil Harris | UKCEH | 2025-12-18 | diff --git a/etc/fcm-make/make-river.cfg b/etc/fcm-make/make-river.cfg index d4ae66ba..96438df1 100644 --- a/etc/fcm-make/make-river.cfg +++ b/etc/fcm-make/make-river.cfg @@ -10,6 +10,7 @@ # Use environment variables to control the configuration via include files ################################################################################ # Variables defined initially so we can append to them later: +$extract_path_incl = bin utils/drhook_dummy $fpp_defs{?} = RIVERS_ONLY $fflags = $ldflags = @@ -18,6 +19,9 @@ $external_libs = $inc_paths = $lib_paths = +# File that FCM should use to check MPI dependencies under JULES_MPI=nompi. +$nompi_trigger_file = river/src/control/rivers-standalone/river.F90 + # Select a platform config; provided by the user. $JULES_PLATFORM{?} = custom @@ -40,8 +44,7 @@ extract.location[river] = $HERE/../.. # be rewritten to allow more of JULES to be excluded. extract.path-excl[river] = / # everything -extract.path-incl[river] = bin \ - utils/drhook_dummy \ +extract.path-incl[river] = $extract_path_incl \ src/control/rivers-standalone \ src/initialisation/rivers-standalone \ src/io/rivers-standalone \ @@ -226,7 +229,6 @@ preprocess.target{category} = src preprocess.target{task} = install process preprocess.prop{file-ext.h} = .inc - ################################################################################ # Configure the build step ################################################################################ diff --git a/etc/fcm-make/make.cfg b/etc/fcm-make/make.cfg index 0995d875..cf27c477 100644 --- a/etc/fcm-make/make.cfg +++ b/etc/fcm-make/make.cfg @@ -18,6 +18,9 @@ $external_libs = $inc_paths = $lib_paths = +# File that FCM should use to check MPI dependencies under JULES_MPI=nompi. +$nompi_trigger_file = jules/src/control/standalone/jules.F90 + # Select a platform config; provided by the user. $JULES_PLATFORM{?} = custom diff --git a/etc/fcm-make/mpi/nompi.cfg b/etc/fcm-make/mpi/nompi.cfg index 7fabf5dc..8320de9b 100644 --- a/etc/fcm-make/mpi/nompi.cfg +++ b/etc/fcm-make/mpi/nompi.cfg @@ -12,3 +12,7 @@ $external_libs = $external_libs $oasis_libs $ncdf_libs_dynamic # Add additional flags for dynamic linking for NetCDF $ldflags = $ldflags $ncdf_ldflags_dynamic + +# Explicit dependencies to ensure that FCM compiles/links code that doesn't have +# an explicit interface. +build.prop{dep.o}[$nompi_trigger_file] = mpi_init.o diff --git a/etc/fcm-make/platform/ceh-rocky9.cfg b/etc/fcm-make/platform/ceh-rocky9.cfg new file mode 100644 index 00000000..b9f1896a --- /dev/null +++ b/etc/fcm-make/platform/ceh-rocky9.cfg @@ -0,0 +1,23 @@ +################################################################################ +# This platform file should be used when building on the JULES CEH Linux +# CEHwl1 +# +# It makes sure that the compiler is gfortran, that MPI is off (since the +# default NetCDF installation does not support MPI), and that the NetCDF paths +# are correctly set up should the user switch NetCDF on +################################################################################ + +# Load environment variable pre-settings +include = $HERE/envars.cfg + +# Override any of the input variables that we need to for the CEH Linux +# CEHwl1 +$JULES_REMOTE = local +$JULES_COMPILER = gfortran_10_plus +$JULES_NETCDF = netcdf +$JULES_MPI = nompi +$JULES_NETCDF_INC_PATH = /usr/lib64/gfortran/modules +$JULES_NETCDF_LIB_PATH = /usr/lib64 + +# Now load the the build config settings based on the supplied environment variables. +include = $HERE/load_settings.cfg diff --git a/rose-stem/include/cehwl1/runtime.cylc b/rose-stem/include/cehwl1/runtime.cylc index b3920f50..ff80691c 100644 --- a/rose-stem/include/cehwl1/runtime.cylc +++ b/rose-stem/include/cehwl1/runtime.cylc @@ -6,7 +6,7 @@ inherit = None, EXTRACT_AND_BUILD, LINUX [[[environment]]] ROSE_TASK_N_JOBS = 2 - JULES_PLATFORM = ceh + JULES_PLATFORM = ceh-rocky9 [[fcm_make_debug]] inherit = CEH_BUILD @@ -24,9 +24,10 @@ inherit = None, EXTRACT_AND_BUILD_RIVER, LINUX [[[environment]]] ROSE_TASK_N_JOBS = 2 - JULES_PLATFORM = ceh + JULES_PLATFORM = ceh-rocky9 JULES_BUILD = normal JULES_OMP = omp + SOURCE_PATH_PREFIX = river ############################################################################### ## Compute jobs @@ -35,10 +36,10 @@ inherit = None, LINUX, COMPUTE platform = localhost [[[environment]]] - LOOBOS_INSTALL_DIR = /data/rosestem/loobos/ - GSWP2_INSTALL_DIR = /data/rosestem/gswp2 - ERAINT_INSTALL_DIR = /data/rosestem/eraint/ - IMOGEN_INSTALL_DIR = /data/rosestem/imogen/ + LOOBOS_INSTALL_DIR = /mnt/rosestem/loobos/ + GSWP2_INSTALL_DIR = /mnt/rosestem/gswp2 + ERAINT_INSTALL_DIR = /mnt/rosestem/eraint/ + IMOGEN_INSTALL_DIR = /mnt/rosestem/imogen/ [[remote_init_ceh]] inherit = CEH_COMPUTE @@ -406,7 +407,7 @@ [[CEH_NETCDF_COMPARISON]] inherit = None, LINUX, NETCDF_COMPARISON [[[environment]]] - KGO_DIR = /data/rosestem/rose-stem-kgo/{{ KGO_VERSION }} + KGO_DIR = /mnt/rosestem/rose-stem-kgo/{{ KGO_VERSION }} [[nccmp_loobos_gl4]] inherit = KGO_CHECK, CEH_NETCDF_COMPARISON From f75c761d4a6bb085d4d70d952efc6dfc373640dd Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Mon, 2 Mar 2026 17:00:02 +0000 Subject: [PATCH 02/24] rsync-ed with code from my now deleted fork (which was also for branch vn8.0_minor_reservoirs). --- .../route_minor_reservoirs_mod.F90 | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/science/river_routing/route_minor_reservoirs_mod.F90 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..09b8c637 --- /dev/null +++ b/src/science/river_routing/route_minor_reservoirs_mod.F90 @@ -0,0 +1,93 @@ +!cxyz add header + +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 + + ! 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 DO + +!print*,'bottom RES_ROUTE range storage=',minval(minor_res_storage),maxval(minor_res_storage) + +RETURN +END SUBROUTINE route_minor_reservoirs + +!############################################################################## + +END MODULE route_minor_reservoirs_mod From effec7bcdc5bffdd9078e4f8a99596faed87cede Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Mon, 2 Mar 2026 17:28:49 +0000 Subject: [PATCH 03/24] Now including modified files that I forgot to "add" last time round! --- .../jules-standalone/HEAD/rose-meta.conf | 14 +- rose-meta/jules-standalone/versions.py | 12 +- rose-stem/include/cehwl1/graph.cylc | 4 +- src/control/rivers-standalone/control_mod.F90 | 23 +- src/control/shared/jules_rivers_mod.F90 | 79 ++++- .../shared/jules_water_resources_mod.F90 | 40 ++- src/control/shared/surf_couple_extra_mod.F90 | 17 +- src/control/shared/surf_couple_rivers_mod.F90 | 319 ++++++++++++++---- .../shared/water_resources_control_mod.F90 | 272 +++++++++++++-- .../shared/water_resources_vars_mod.F90 | 68 ++-- src/control/standalone/control.F90 | 4 +- .../allocate_river_arrays_mod.F90 | 10 +- .../shared/allocate_jules_arrays.F90 | 11 +- .../init_rivers_process_data_mod.F90 | 49 ++- .../ancillaries/init_rivers_props_mod.F90 | 16 +- .../init_water_resources_props_mod.F90 | 2 +- .../ancillaries/jules_rivers_props_mod.F90 | 121 +++++-- .../standalone/init_output_mod.F90 | 60 +++- .../standalone/init_water_resources_mod.F90 | 9 +- src/io/dump/get_dim_info_mod.F90 | 8 +- src/io/dump/read_dump_var_rivers_mod.F90 | 3 + src/io/dump/required_vars_for_rivers_mod.F90 | 12 +- src/io/dump/write_dump_mod.F90 | 4 +- src/io/dump/write_dump_var_rivers_mod.F90 | 3 + src/io/model_interface/extract_var.inc | 16 +- .../model_interface/model_interface_mod.F90 | 2 +- src/io/model_interface/populate_var.inc | 19 +- src/io/model_interface/variable_metadata.inc | 78 ++++- .../river_routing/rivers_route_mod.F90 | 58 +++- .../water_resources/calc_avail_water_mod.F90 | 47 ++- .../water_resources/water_resources_drive.F90 | 64 ++-- 31 files changed, 1147 insertions(+), 297 deletions(-) diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index bc7aea34..f8f76586 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -2418,12 +2418,13 @@ fail-if=len(this) != namelist:jules_initial=nvars; = namelist:jules_rivers=l_rivers == '.true.' and namelist:jules_rivers=i_river_vn == "2" and not any(this == "'rfm_substore_rp'"); # rfm_substore_rp must be initialised if rivers is switched on and i_river_vn='2' : rfm = namelist:jules_rivers=l_rivers == '.true.' and namelist:jules_rivers=i_river_vn == "2" and not any(this == "'rfm_flowin_rp'"); # rfm_flowin_rp must be initialised if rivers is switched on and i_river_vn='2' : rfm = namelist:jules_rivers=l_rivers == '.true.' and namelist:jules_rivers=i_river_vn == "2" and not any(this == "'rfm_bflowin_rp'"); # rfm_bflowin_rp must be initialised if rivers is switched on and i_river_vn='2' : rfm + = namelist:jules_rivers=l_rivers == '.true.' and namelist:jules_rivers=l_minor_reservoirs == ".true." and not any(this == "'minor_res_storage'"); # minor_res_storage must be initialised if rivers is switched on and l_minor_reservoirs='.true' length=: sort-key=06 url=http://jules-lsm.github.io/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', @@ -2835,7 +2836,7 @@ url=http://jules-lsm.github.io/latest/namelists/model_environment.nml.html#namel [namelist:jules_model_environment=l_jules_parent] compulsory=true -description=Switch to identify the environment in which JULES is being run. +description=Switch to identify the e 0 ) THEN + ALLOCATE(rivers_data%tot_net_abstracted_river(land_pts)) +ELSE + ALLOCATE(rivers_data%tot_net_abstracted_river(1)) +END IF ALLOCATE(rivers_data%acc_lake_evap_gb(t_i_length,t_j_length)) ALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts(land_pts)) ALLOCATE(rivers_data%rivers_adj_on_landpts(land_pts)) @@ -731,6 +789,8 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, rivers_data) #else ALLOCATE(rivers_data%tot_surf_runoff_gb(1)) ALLOCATE(rivers_data%tot_sub_runoff_gb(1)) +ALLOCATE(rivers_data%tot_abstracted_minor_res(1)) +ALLOCATE(rivers_data%tot_net_abstracted_river(1)) ALLOCATE(rivers_data%acc_lake_evap_gb(1,1)) ALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts(1)) ALLOCATE(rivers_data%rivers_adj_on_landpts(1)) @@ -761,6 +821,8 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, rivers_data) rivers_data%tot_surf_runoff_gb(:) = 0.0 rivers_data%tot_sub_runoff_gb(:) = 0.0 +rivers_data%tot_abstracted_minor_res(:) = 0.0 +rivers_data%tot_net_abstracted_river(:) = 0.0 rivers_data%acc_lake_evap_gb(:,:) = 0.0 rivers_data%rivers_sto_per_m2_on_landpts(:) = 0.0 rivers_data%rivers_adj_on_landpts(:) = 0.0 @@ -1163,6 +1225,8 @@ SUBROUTINE print_nlist_jules_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 @@ -1304,7 +1368,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 = 6 +INTEGER, PARAMETER :: n_log = 7 TYPE :: my_namelist SEQUENCE @@ -1327,6 +1391,7 @@ SUBROUTINE read_nml_jules_rivers(unit_in) 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 @@ -1366,6 +1431,7 @@ SUBROUTINE read_nml_jules_rivers(unit_in) 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 @@ -1394,6 +1460,7 @@ SUBROUTINE read_nml_jules_rivers(unit_in) 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 @@ -1433,6 +1500,8 @@ SUBROUTINE rivers_dealloc(rivers_data) DEALLOCATE(rivers_data%tot_surf_runoff_gb) DEALLOCATE(rivers_data%tot_sub_runoff_gb) +DEALLOCATE(rivers_data%tot_abstracted_minor_res) +DEALLOCATE(rivers_data%tot_net_abstracted_river) DEALLOCATE(rivers_data%acc_lake_evap_gb) DEALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts) DEALLOCATE(rivers_data%rivers_adj_on_landpts) @@ -1506,6 +1575,8 @@ SUBROUTINE rivers_assoc(rivers, rivers_data) rivers%tot_surf_runoff_gb => rivers_data%tot_surf_runoff_gb rivers%tot_sub_runoff_gb => rivers_data%tot_sub_runoff_gb +rivers%tot_abstracted_minor_res => rivers_data%tot_abstracted_minor_res +rivers%tot_net_abstracted_river => rivers_data%tot_net_abstracted_river rivers%acc_lake_evap_gb => rivers_data%acc_lake_evap_gb rivers%rivers_sto_per_m2_on_landpts => rivers_data%rivers_sto_per_m2_on_landpts rivers%rivers_adj_on_landpts => rivers_data%rivers_adj_on_landpts @@ -1577,6 +1648,8 @@ SUBROUTINE rivers_nullify(rivers) NULLIFY(rivers%tot_surf_runoff_gb) NULLIFY(rivers%tot_sub_runoff_gb) +NULLIFY(rivers%tot_abstracted_minor_res) +NULLIFY(rivers%tot_net_abstracted_river) NULLIFY(rivers%acc_lake_evap_gb) NULLIFY(rivers%rivers_sto_per_m2_on_landpts) NULLIFY(rivers%rivers_adj_on_landpts) diff --git a/src/control/shared/jules_water_resources_mod.F90 b/src/control/shared/jules_water_resources_mod.F90 index 2b44c3bb..cea06d57 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, & @@ -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,14 +551,24 @@ 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." ) + ! If any water use would potentially include return flow to rivers (as coded + ! in SUBROUTINE calc_return_flow), check that rivers are modelled. + ! The domestic and industrial uses return water to rivers in preference to + ! groundwater, while the livestock use returns water to groundwater in + ! preference to rivers; in all cases we need either rivers or groundwater. + ! Note that by testing on l_rivers rather than l_have_surface_water we cater + ! for a potential future extension in which we might have rivers (l_rivers=T) + ! that are not used as a water source (likely as part of a counter-factual + ! experiment). + IF ( .NOT. l_have_groundwater .AND. .NOT. l_rivers ) THEN + ! We have neither groundwater nor rivers. + ! Check if a return flow would potentially go to rivers. + IF ( use_domestic > 0 .OR. use_industry > 0 .OR. use_livestock > 0 ) THEN + ! This would potentially return to rivers. + error_status = 101 ! a fatal error + CALL ereport ( RoutineName, error_status, & + "Rivers must be included to allow return flow." ) + END IF END IF END IF ! l_water_resources @@ -572,7 +585,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 @@ -636,15 +650,17 @@ 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. !---------------------------------------------------------------------------- ! 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 +873,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 ca35dc00..513361b1 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, tot_abstracted_minor_res, & + tot_net_abstracted_river, acc_lake_evap_gb, twatstor, & asteps_since_triffid, & inlandout_atm_gb, & !OUT @@ -387,6 +388,10 @@ SUBROUTINE surf_couple_extra( & acc_lake_evap_gb(row_length,rows), & tot_surf_runoff_gb(land_pts), & tot_sub_runoff_gb(land_pts), & + tot_abstracted_minor_res(land_pts), & + ! Water abstracted from minor reservoirs over river timestep (kg). + tot_net_abstracted_river(land_pts), & + ! Water abstracted from rivers over river timestep (kg m-2). twatstor(river_row_length, river_rows), & inlandout_atm_gb(land_pts) @@ -852,13 +857,14 @@ 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, & @@ -867,7 +873,8 @@ SUBROUTINE surf_couple_extra( & 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, & + crop_vars%irrig_water_gb, water_resources%abstracted_minor_res, & + water_resources%net_abstracted_river, & water_resources%sw_abstracted, water_resources%sw_avail_total, & water_resources%water_removed ) END IF @@ -878,13 +885,15 @@ SUBROUTINE surf_couple_extra( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) + water_resources%abstracted_minor_res, & water_resources%net_abstracted_river, & 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, tot_abstracted_minor_res, & + tot_net_abstracted_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/surf_couple_rivers_mod.F90 b/src/control/shared/surf_couple_rivers_mod.F90 index ba24b206..381fcd16 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, net_abstracted_river, & 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, & + tot_net_abstracted_river, 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, rivers_um_trip, rivers_first @@ -79,6 +81,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 @@ -144,6 +148,8 @@ SUBROUTINE surf_couple_rivers( & a_steps_since_riv REAL(KIND=real_jlslsm), INTENT(IN) :: & + abstracted_minor_res(land_pts), & + ! Water abstracted from minor reservoirs (kg). net_abstracted_river(land_pts), & ! Net abstraction from rivers (kg m-2). surf_roff(land_pts), & @@ -184,6 +190,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(land_pts), & + ! Water abstracted from minor reservoirs over river timestep (kg). + tot_net_abstracted_river(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), & @@ -231,9 +241,18 @@ SUBROUTINE surf_couple_rivers( & ! Average rate of subsurface runoff over river timestep (kg m-2 s-1). REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_surf_runoff(:) ! Average rate of surface runoff over river timestep (kg m-2 s-1). +REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_abstracted_minor_res(:) + ! Water abstracted from minor reservoirs over river timestep (kg). +REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_net_abstracted_river(:) + ! Water abstracted from rivers over river timestep (kg). 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) :: & @@ -243,17 +262,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) :: & @@ -282,10 +301,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) @@ -322,9 +339,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 @@ -347,7 +366,18 @@ SUBROUTINE surf_couple_rivers( & rivers%rrun_sub_surf_rp(:) = 0.0 rivers%rrun_surf_rp(:) = 0.0 END IF -END IF + + ! Initialise the accumulated abstraction from rivers. + IF ( sw_river_source > 0 ) THEN + tot_net_abstracted_river(:) = 0.0 + END IF + + ! Initialise the accumulated abstraction from minor reservoirs. + IF ( l_water_resources .AND. l_minor_reservoirs ) THEN + tot_abstracted_minor_res(:) = 0.0 + END IF + +END IF ! a_steps_since_riv == 0 ! Increment counters. a_steps_since_riv = a_steps_since_riv + 1 @@ -358,33 +388,45 @@ 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 + ! Accumulate abstraction from rivers. + IF ( sw_river_source > 0 ) THEN + CALL accumulate_abstraction( land_pts, net_abstracted_river, & + tot_net_abstracted_river ) + END IF + + ! Accumulate abstraction from minor reservoirs. + IF ( l_water_resources .AND. l_minor_reservoirs ) THEN + CALL accumulate_abstraction( land_pts, abstracted_minor_res, & + tot_abstracted_minor_res ) + END IF + + END IF ! l_oasis_rivers) ! Could this UM ifdef be replaced with the i_rivers_vn switch? @@ -500,54 +542,106 @@ 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 - ALLOCATE(global_sea_level(1), STAT = ERROR) - error_sum = error_sum + ERROR + 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 + tmp_land_size = global_land_pts + tmp_river_size = np_rivers + ELSE + ! Allocate at minimum size. + tmp_land_size = 1 + tmp_river_size = 1 + END IF + ALLOCATE(global_tot_net_abstracted_river(tmp_land_size), STAT = ERROR) + error_sum = error_sum + ERROR + ALLOCATE(net_abstracted_river_rp(tmp_river_size), STAT = ERROR) + error_sum = error_sum + ERROR + + ! Allocate global abstraction from minor reservoirs. + IF ( .NOT. l_oasis_rivers .AND. l_minor_reservoirs & + .AND. is_master_task() ) THEN + ! Note that global_tot_abstracted_minor_res is required at full size only + ! if l_water_resources=T, but for simplicity we only test on + ! l_minor_reservoirs here. + tmp_land_size = global_land_pts + tmp_river_size = np_rivers + ELSE + ! Allocate at minimum size. + tmp_land_size = 1 + tmp_river_size = 1 + END IF + ALLOCATE(global_tot_abstracted_minor_res(tmp_land_size), STAT = ERROR) + error_sum = error_sum + ERROR + 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 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 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 + ! Gather abstraction from river. + IF ( sw_river_source > 0 ) THEN + CALL gather_land_field( tot_net_abstracted_river, & + global_tot_net_abstracted_river, & + rivers%global_land_index ) + END IF + ! Gather abstraction from minor reservoirs. + IF ( l_minor_reservoirs .AND. l_water_resources ) THEN + CALL gather_land_field( tot_abstracted_minor_res, & + global_tot_abstracted_minor_res, & + rivers%global_land_index ) + END IF + END IF ! .NOT. l_oasis_rivers ) THEN !------------------------------------------------------------------------- ! Call routing driver on single processor @@ -555,18 +649,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, & @@ -580,8 +680,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, & @@ -589,10 +689,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, & + global_tot_net_abstracted_river, & + 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, & + global_tot_abstracted_minor_res, & + 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, & @@ -604,7 +725,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 @@ -612,6 +734,7 @@ SUBROUTINE surf_couple_rivers( & IF ( l_riv_overbank ) THEN CALL overbank_update(rivers%rfm_rivflow_rp) END IF + END IF ! end is_master !------------------------------------------------------------------------- @@ -654,6 +777,11 @@ 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(global_tot_abstracted_minor_res) + DEALLOCATE(net_abstracted_river_rp) + DEALLOCATE(global_tot_net_abstracted_river) DEALLOCATE(global_sea_level) DEALLOCATE(global_rflow) DEALLOCATE(global_rrun) @@ -705,7 +833,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) @@ -714,15 +841,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 @@ -732,8 +857,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) @@ -773,19 +896,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..72be47aa 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -70,10 +70,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(:), & ! 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(:), & @@ -100,19 +104,19 @@ SUBROUTINE water_resources_control( & 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, & - sw_avail_total, water_removed ) + irrig_water_gb, abstracted_minor_res, net_abstracted_river, & + sw_abstracted, sw_avail_total, water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -137,7 +141,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, l_rivers, np_rivers USE jules_soil_mod, ONLY: sm_levels @@ -212,6 +216,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 +256,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), & @@ -294,6 +300,10 @@ SUBROUTINE water_resources_control( & ! Water abstracted from non-renewable groundwater (kg). irrig_water_gb(land_pts), & ! Water added to soil via irrigation (kg m-2 s-1). + abstracted_minor_res(land_pts), & + ! Water abstracted from minor reservoirs (kg). + ! Note that this has reduced size if it is not required. + !cxyz Perhaps don't specify size? net_abstracted_river(land_pts), & ! Net abstraction from river (kg m-2). sw_abstracted(land_pts,n_sw_source), & @@ -348,8 +358,6 @@ SUBROUTINE water_resources_control( & ! Water that is returned to renewable groundwater after use (kg). return_flow_sw(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). @@ -387,11 +395,17 @@ 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. +! rather than as rates (e.g. kg s-1) they need to be zero on these +! intermediate timesteps. !------------------------------------------------------------------------------ -! Initialise coupling flux. -net_abstracted_river(:) = 0.0 -! Initialise abstractions. +! Initialise coupling fluxes. +IF ( l_minor_reservoirs ) THEN + abstracted_minor_res(:) = 0.0 +END IF +IF ( sw_river_source > 0 ) THEN + net_abstracted_river(:) = 0.0 +END IF +! Initialise abstractions. cxyz Always allocated at full size? gw_abstracted(:) = 0.0 gw_nr_abstracted(:) = 0.0 sw_abstracted(:,:) = 0.0 @@ -473,24 +487,35 @@ SUBROUTINE water_resources_control( & CALL gather_global_water( priority_order, conv_loss_frac, demand_accum, & 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 ) + + 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, & @@ -498,6 +523,7 @@ SUBROUTINE water_resources_control( & sw_abstracted_global, sw_avail_global, water_removed_global, & conveyance_loss_global, return_flow_gw_global, & return_flow_sw_global, supply_irrig_global ) + END IF ! is_master_task !---------------------------------------------------------------------------- @@ -506,6 +532,7 @@ SUBROUTINE water_resources_control( & ! There are no prognostic variables to be scattered. !---------------------------------------------------------------------------- CALL scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & + abstracted_minor_res, & gw_nr_abstracted, return_flow_gw, return_flow_sw, & sfc_water_frac, supply_irrig, sw_abstracted, & sw_avail_total, water_removed ) @@ -811,6 +838,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,9 +875,13 @@ 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. @@ -860,7 +893,7 @@ SUBROUTINE allocate_global_water( l_allocate ) !---------------------------------------------------------------------------- ! 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 +907,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 +927,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 +947,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,6 +957,9 @@ SUBROUTINE allocate_global_water( l_allocate ) END IF error_sum = error_sum + ERROR + ALLOCATE(river_storage_global(land_size_rivers), STAT = ERROR) + error_sum = error_sum + ERROR + ! Both SW and GW return flows are needed at full size, even if either ! source is not active. ALLOCATE(return_flow_gw_global(land_size), STAT = ERROR) @@ -944,9 +994,11 @@ 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 + river_storage_global(:) = 0.0 sfc_water_frac_global(:) = 0.0 supply_irrig_global(:) = 0.0 sw_abstracted_global(:,:) = 0.0 @@ -973,9 +1025,13 @@ 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(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) @@ -1075,6 +1131,7 @@ END SUBROUTINE gather_global_water !############################################################################## SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & + abstracted_minor_res, & gw_nr_abstracted, return_flow_gw, & return_flow_sw, sfc_water_frac, supply_irrig, & sw_abstracted, sw_avail_total, water_removed ) @@ -1086,9 +1143,11 @@ 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 + 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 USE model_grid_mod, ONLY: global_land_pts @@ -1108,6 +1167,8 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & ! Water abstracted from renewable groundwater (kg). gw_nr_abstracted(land_pts), & ! Water abstracted from non-renewable groundwater (kg). + abstracted_minor_res(land_pts), & + ! Water abstracted from minor reservoirs (kg). return_flow_gw(land_pts), & ! Water that is returned to renewable groundwater after use (kg). return_flow_sw(land_pts), & @@ -1157,11 +1218,20 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & CALL scatter_land_field( sfc_water_frac_global, sfc_water_frac ) END IF ! Surface water always includes rivers, so we always calculate return flow. + !cxyz No longer true. 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 ) + ! Abstraction from minor reservoirs. + !cxyz Note that it is slightly daft that we are scattering here only to later + ! regather in rivers code (as for net abs from river?) - but this does + ! allows this to better follow existing code. + IF ( l_minor_reservoirs ) THEN + CALL scatter_land_field( sw_abstracted_global(:,sw_minor_res_source), & + abstracted_minor_res ) + END IF END IF ! Fields for irrigation. @@ -1175,6 +1245,136 @@ END SUBROUTINE scatter_global_water !############################################################################## !############################################################################## +SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & + rivers_index_rp, minor_res_storage, & + rfm_surfstore_rp, rivers_sto_rp, & + minor_res_storage_global, river_storage_global ) + +!------------------------------------------------------------------------------ +! 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. + +! 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_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 calc_river_flux( land_pts, grid_area_lp, return_flow_sw, & sw_abstracted_river, net_abstracted_river ) diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index f6b9b8d5..8ff91556 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -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. !-------------------------------------------------------------------------- + abstracted_minor_res(:), & + ! Water abstracted from minor reservoirs (kg). net_abstracted_river(:), & - ! Net abstraction from river (kg). + ! Net abstraction from river (kg m-2). !-------------------------------------------------------------------------- ! Diagnostics (also used internally). - ! All abstractions are gross (not net of returns) fluxes unless stated + ! All abstractions are gross fluxes (not net of returns) unless stated ! otherwise. !-------------------------------------------------------------------------- demand_accum(:,:), & @@ -117,6 +119,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: demand_rate_industry(:) REAL(KIND=real_jlslsm), POINTER :: demand_rate_livestock(:) REAL(KIND=real_jlslsm), POINTER :: demand_rate_transfers(:) + REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res(:) REAL(KIND=real_jlslsm), POINTER :: net_abstracted_river(:) REAL(KIND=real_jlslsm), POINTER :: demand_accum(:,:) REAL(KIND=real_jlslsm), POINTER :: demand_unmet(:,:) @@ -138,10 +141,10 @@ MODULE water_resources_vars_mod !############################################################################## SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & - l_have_groundwater, l_have_surface_water, & - l_water_domestic, l_water_industry, l_water_irrigation, & - l_water_livestock, l_water_resources, l_water_transfers, & - water_resources_data ) + sw_river_source, l_have_groundwater, l_have_surface_water, & + l_minor_reservoirs, l_water_domestic, l_water_industry, & + l_water_irrigation, l_water_livestock, l_water_resources, & + l_water_transfers, water_resources_data ) !No USE statements other than Dr Hook USE parkind1, ONLY: jprb, jpim @@ -157,8 +160,10 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ! 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 +171,8 @@ 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_minor_reservoirs, & + ! Switch for minor_reservoirs. l_water_domestic, & ! Switch to consider demand for water for domestic use. l_water_industry, & @@ -189,7 +195,8 @@ 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 + land_pts_dim, land_pts_gw, land_pts_minor_res, land_pts_sw, & + land_pts_sw_rivers, n_sw_source_dim, nwater_use_dim ! Sizes used when allocating arrays. INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 @@ -209,11 +216,13 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & !----------------------------------------------------------------------------- ! 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 +land_pts_dim = 1 +land_pts_gw = 1 +land_pts_minor_res = 1 +land_pts_sw = 1 +land_pts_sw_rivers = 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 @@ -224,6 +233,12 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & IF ( l_have_surface_water ) THEN land_pts_sw = land_pts END IF + IF ( sw_river_source > 0 ) THEN + land_pts_sw_rivers = land_pts + END IF + IF ( l_minor_reservoirs ) THEN + land_pts_minor_res = land_pts + END IF END IF !----------------------------------------------------------------------------- @@ -232,7 +247,7 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ALLOCATE( water_resources_data%priority_order(land_pts_dim,nwater_use_dim) ) !----------------------------------------------------------------------------- -! Ancillary fields. +! Ancillary fields on land points. ! Although these are not required for every configuration, they are commonly ! required and hence for convenience we always allocate them. !----------------------------------------------------------------------------- @@ -268,9 +283,18 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & END IF !----------------------------------------------------------------------------- -! Coupling to rivers - which are always modelled if l_have_surface_water=T. +! Coupling to minor reservoirs. +! Only allocated at full size if minor reservoirs are modelled. +!----------------------------------------------------------------------------- +print*,'alloc l_minor_reservoirs=',l_minor_reservoirs +ALLOCATE( water_resources_data%abstracted_minor_res(land_pts_minor_res) ) +print*,'Alloc size=',size( water_resources_data%abstracted_minor_res ) + +!----------------------------------------------------------------------------- +! Coupling to rivers. +! Only allocated at full size if rivers are modelled. !----------------------------------------------------------------------------- -ALLOCATE( water_resources_data%net_abstracted_river(land_pts_sw) ) +ALLOCATE( water_resources_data%net_abstracted_river(land_pts_sw_rivers) ) !----------------------------------------------------------------------------- ! Other variables. @@ -296,6 +320,7 @@ 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%abstracted_minor_res(:) = 0.0 water_resources_data%net_abstracted_river(:) = 0.0 water_resources_data%demand_accum(:,:) = 0.0 water_resources_data%demand_unmet(:,:) = 0.0 @@ -340,6 +365,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) +!cxy Should deallocate in reverse order. DEALLOCATE( water_resources_data%priority_order ) DEALLOCATE( water_resources_data%conv_loss_frac ) DEALLOCATE( water_resources_data%sfc_water_frac ) @@ -347,6 +373,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) 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%abstracted_minor_res ) DEALLOCATE( water_resources_data%net_abstracted_river ) DEALLOCATE( water_resources_data%demand_accum ) DEALLOCATE( water_resources_data%demand_unmet ) @@ -412,6 +439,8 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) => water_resources_data%demand_rate_livestock water_resources%demand_rate_transfers & => water_resources_data%demand_rate_transfers +water_resources%abstracted_minor_res & + => water_resources_data%abstracted_minor_res water_resources%net_abstracted_river & => water_resources_data%net_abstracted_river water_resources%demand_accum => water_resources_data%demand_accum @@ -461,6 +490,7 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%demand_rate_industry ) NULLIFY( water_resources%demand_rate_livestock ) NULLIFY( water_resources%demand_rate_transfers ) +NULLIFY( water_resources%abstracted_minor_res ) NULLIFY( water_resources%net_abstracted_river ) NULLIFY( water_resources%demand_accum ) NULLIFY( water_resources%demand_unmet ) diff --git a/src/control/standalone/control.F90 b/src/control/standalone/control.F90 index 0542a79b..60544f0a 100644 --- a/src/control/standalone/control.F90 +++ b/src/control/standalone/control.F90 @@ -892,7 +892,9 @@ SUBROUTINE control ( & toppdm%fwetl_soilt, toppdm%zw_soilt, toppdm%sthzw_soilt, & ls_rainfrac_land, & substore, surfstore, flowin, bflowin, & - rivers%tot_surf_runoff_gb, rivers%tot_sub_runoff_gb,rivers%acc_lake_evap_gb, & + rivers%tot_surf_runoff_gb, rivers%tot_sub_runoff_gb, & + rivers%tot_abstracted_minor_res, rivers%tot_net_abstracted_river, & + rivers%acc_lake_evap_gb, & twatstor, asteps_since_triffid, & inlandout_atm_gb, & !OUT diff --git a/src/initialisation/rivers-standalone/allocate_river_arrays_mod.F90 b/src/initialisation/rivers-standalone/allocate_river_arrays_mod.F90 index 8c9bdf65..f97cc833 100644 --- a/src/initialisation/rivers-standalone/allocate_river_arrays_mod.F90 +++ b/src/initialisation/rivers-standalone/allocate_river_arrays_mod.F90 @@ -95,6 +95,12 @@ SUBROUTINE allocate_river_arrays(psparms_data,ainfo_data, progs_data, & INTEGER, PARAMETER :: river_row_length_dum = 1 INTEGER, PARAMETER :: river_rows_dum = 1 +! Water resources is not available with rivers-standalone. Set values so that +! water resource variables are not allocated. +INTEGER, PARAMETER :: tmp_sw_river_source = 0 +LOGICAL, PARAMETER :: tmp_l_minor_reservoirs = .FALSE. +LOGICAL, PARAMETER :: tmp_l_water_resources = .FALSE. + INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 REAL(KIND=jprb) :: zhook_handle @@ -152,7 +158,9 @@ SUBROUTINE allocate_river_arrays(psparms_data,ainfo_data, progs_data, & nice, nsoilt, ntype, & ainfo_data) -CALL jules_rivers_alloc(temp_size, t_i_length, t_j_length, rivers_data) +CALL jules_rivers_alloc(temp_size, t_i_length, t_j_length, & + tmp_sw_river_source, tmp_l_water_resources, & + rivers_data) CALL coastal_alloc(temp_size, t_i_length, t_j_length, & u_i_length, u_j_length, & diff --git a/src/initialisation/shared/allocate_jules_arrays.F90 b/src/initialisation/shared/allocate_jules_arrays.F90 index 2712494b..b501c4db 100644 --- a/src/initialisation/shared/allocate_jules_arrays.F90 +++ b/src/initialisation/shared/allocate_jules_arrays.F90 @@ -46,13 +46,14 @@ SUBROUTINE allocate_jules_arrays(crop_vars_data,psparms_data,top_pdm_data, & USE jules_surface_mod, ONLY: l_flake_model USE jules_soil_mod, ONLY: l_bedrock, ns_deep USE jules_radiation_mod, ONLY: l_albedo_obs +USE jules_rivers_mod, ONLY: l_minor_reservoirs USE jules_soil_biogeochem_mod,ONLY: soil_model_ecosse, soil_bgc_model, & l_label_frac_cs, l_layeredc, dim_ch4layer USE jules_water_resources_mod,ONLY: l_have_groundwater, l_have_surface_water, & l_water_domestic, l_water_industry, & l_water_irrigation,l_water_livestock, & l_water_resources, l_water_transfers, & - n_sw_source, nwater_use + n_sw_source, nwater_use, sw_river_source USE jules_deposition_mod, ONLY: l_deposition, ndry_dep_species USE jules_water_tracers_mod, ONLY: l_wtrac_jls @@ -265,7 +266,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,9 +292,10 @@ 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, & +CALL water_resources_alloc( land_pts, n_sw_source, nwater_use, sw_river_source,& l_have_groundwater, l_have_surface_water, & - l_water_domestic, l_water_industry, & + l_minor_reservoirs, l_water_domestic, & + l_water_industry, & l_water_irrigation, l_water_livestock, & l_water_resources, l_water_transfers, & water_resources_data ) 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 3f637d79..5983a611 100644 --- a/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 +++ b/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 @@ -1018,9 +1018,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 @@ -1074,7 +1074,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, & @@ -1160,6 +1160,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 @@ -2201,9 +2212,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, & @@ -2373,8 +2386,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 @@ -2434,11 +2447,29 @@ 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) + IF ( rivers%minor_res_capacity(ip) /= rivers%minor_res_capacity(ip).OR.& + rivers%minor_res_frac(ip) /= rivers%minor_res_frac(ip) ) THEN + print*,'ISSUE ',ip,rivers%minor_res_capacity(ip),rivers%minor_res_frac(ip) + END IF + + END IF ! l_minor_reservoirs + END IF ! point_mask END DO ! iy END DO ! ix +print*,'SET range minor_res_capacity=',MINVAL(rivers%minor_res_capacity(:)), & + MAXVAL(rivers%minor_res_capacity(:)) +print*,'SET range minor_res_frac=',MINVAL(rivers%minor_res_frac(:)), & + MAXVAL(rivers%minor_res_frac(:)) END SUBROUTINE set_river_point_values diff --git a/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/init_rivers_props_mod.F90 index 85d8774e..c16ca2c9 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 model_grid_mod, ONLY: global_land_pts, l_coord_latlon @@ -295,6 +299,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 a48715f2..58a9dc71 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 !------------------------------------------------------------------------------ @@ -546,7 +551,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 @@ -557,6 +562,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 @@ -583,6 +601,8 @@ SUBROUTINE allocate_river_vars_grid( global_land_pts, nx_rivers, ny_rivers, & rivers_data%rivers_seq(:,:) = rmdi rivers_data%rivers_outflow_number(:,:) = rmdi rivers_data%rivers_storage(:,:) = rmdi +minor_res_capacity_grid(:,:) = rmdi +minor_res_frac_grid(:,:) = rmdi ! Associate pointers rivers%rivers_dir => rivers_data%rivers_dir @@ -611,8 +631,9 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) USE jules_model_environment_mod, ONLY: l_oasis_rivers -USE jules_rivers_mod, ONLY: i_river_vn, l_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 missing_data_mod, ONLY: imdi, rmdi @@ -872,6 +893,26 @@ 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 +ELSE + ! Minimum size. + np_rivers_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 + IF ( error_sum /= 0 ) THEN CALL log_fatal( RoutineName, "Error allocating for routing point arrays." ) END IF @@ -900,6 +941,7 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) ! Initialise CaMa-Flood array values ! CaMa-Flood ancillary variables. +!cxyz Note not zero despite message in required_vars_for_rivers (out of scope!). rivers_data%channel_depth(:) = rmdi rivers_data%channel_width(:) = rmdi rivers_data%river_distance(:) = rmdi @@ -946,6 +988,12 @@ 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 + !------------------------------------------------------------------------------ ! Associate pointers !------------------------------------------------------------------------------ @@ -1012,6 +1060,11 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers%sub_surf_roff_rp => rivers_data%sub_surf_roff_rp rivers%surf_roff_rp => rivers_data%surf_roff_rp +! Associate pointers for 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 + RETURN END SUBROUTINE allocate_rivers_vars_rp @@ -1022,18 +1075,19 @@ SUBROUTINE deallocate_river_props( ) !------------------------------------------------------------------------------ ! Description: ! Deallocate river variables that are not needed any further. +!cxyz Ideally in reverse order... !------------------------------------------------------------------------------ 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 ) @@ -1063,7 +1117,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 @@ -1088,6 +1142,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 a69129c6..07a5ebc1 100644 --- a/src/initialisation/standalone/init_output_mod.F90 +++ b/src/initialisation/standalone/init_output_mod.F90 @@ -346,8 +346,8 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & l_water_industry, l_water_irrigation, l_water_livestock, & l_water_resources, l_water_transfers, no_model, nr_gwater_model -USE jules_rivers_mod, ONLY: l_rivers, l_riv_overbank, l_outflow_per_river, & - i_river_vn, rivers_camaflood, rivers_rfm, rivers_trip +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 USE jules_deposition_mod, ONLY: l_deposition, l_deposition_flux @@ -645,10 +645,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. @@ -663,15 +664,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' ) @@ -680,6 +682,34 @@ 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_abstracted', 'minor_res_capacity', 'minor_res_frac', & + 'minor_res_storage' ) + remove_var = .TRUE. + message = 'Minor reservoirs not used.' + END SELECT + + ELSE + + ! l_minor_reservoirs = T + !-------------------------------------------------------------------------- + ! Variables that are only allowed with minor reservoirs in combination + ! with water resources. + !-------------------------------------------------------------------------- + IF ( .NOT. l_water_resources ) THEN + SELECT CASE ( var(j) ) + CASE ( 'minor_res_abstracted' ) + remove_var = .TRUE. + message = 'Minor reservoirs + water resources not used.' + END SELECT + END IF + + END IF ! l_minor_reservoirs + !--------------------------------------------------------------------------- ! Thermal acclimation variables. !--------------------------------------------------------------------------- @@ -697,7 +727,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', 'water_demand', 'water_demand_unmet', & + 'water_removed' ) remove_var = .TRUE. message = 'Water resources (l_water_resources) not selected.' END SELECT @@ -709,7 +740,7 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & ! 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 @@ -717,7 +748,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 @@ -725,7 +756,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 @@ -733,7 +764,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 @@ -741,7 +772,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 @@ -749,7 +780,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 @@ -763,7 +794,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. 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/io/dump/get_dim_info_mod.F90 b/src/io/dump/get_dim_info_mod.F90 index a23e7b27..e3c28bd5 100644 --- a/src/io/dump/get_dim_info_mod.F90 +++ b/src/io/dump/get_dim_info_mod.F90 @@ -558,10 +558,10 @@ 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', & +CASE ( 'minor_res_storage', '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', & 'flood_flow', 'flood_flow_prev', 'flood_storage', 'flood_storage_prev', & 'river_channel_flow', 'river_channel_storage', 'river_depth_prev', & 'river_flow_prev' & diff --git a/src/io/dump/read_dump_var_rivers_mod.F90 b/src/io/dump/read_dump_var_rivers_mod.F90 index aa53f957..3e5da0d9 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 47771afe..f6705ce1 100644 --- a/src/io/dump/required_vars_for_rivers_mod.F90 +++ b/src/io/dump/required_vars_for_rivers_mod.F90 @@ -15,7 +15,8 @@ SUBROUTINE required_vars_for_rivers( nvars, identifiers, & nvars_from_ancil, vars_from_ancil, & read_or_write_dump ) -USE jules_rivers_mod, ONLY: l_outflow_per_river, i_river_vn, rivers_camaflood, & +USE jules_rivers_mod, ONLY: i_river_vn, l_minor_reservoirs, & + l_outflow_per_river, rivers_camaflood, & rivers_rfm, rivers_trip, l_init_storage USE logging_mod, ONLY: log_warn @@ -129,6 +130,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 2c5e6b40..21ad140a 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', & 'flood_flow', 'flood_flow_prev', 'flood_storage', & diff --git a/src/io/dump/write_dump_var_rivers_mod.F90 b/src/io/dump/write_dump_var_rivers_mod.F90 index cf86b15e..cf938f49 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 49d27599..52ff8505 100644 --- a/src/io/model_interface/extract_var.inc +++ b/src/io/model_interface/extract_var.inc @@ -2665,7 +2665,7 @@ CASE ( 'rivers_sto_rp' ) cube = cube_from_array(rivers%rivers_sto_rp) CASE ( 'rfm_bflowin_rp' ) - ! Internal units are m3/timestep, convert to m3/s + ! Internal units are m<3/timestep, convert to m3/s workspace_rivers = rivers%rfm_bflowin_rp * nstep_rivers * timestep cube = cube_from_array(workspace_rivers) @@ -2727,6 +2727,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) @@ -3417,6 +3426,11 @@ 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 ( '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 b3c63407..b4e25f45 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 = 722 +INTEGER, PARAMETER :: n_vars = 728 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 4dc4976c..9385517e 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 @@ -2504,6 +2505,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 0efd8ac3..55f6c463 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 @@ -9354,4 +9354,80 @@ DATA metadata(722) / var_metadata( & ! Units "kg s-1" & ) / +!----------------------------------------------------------------------------- +! Metadata for minor_res_capacity_grid +!----------------------------------------------------------------------------- +DATA metadata(723) / 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(724) / 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(725) / 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(726) / 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(727) / 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(728) / var_metadata( & +! String identifier + 'minor_res_abstracted', & +! Variable type + var_type_surface, & +! Long name + "Water abstracted from minor_reservoirs", & +! Units + "kg s-1" & + ) / #endif diff --git a/src/science/river_routing/rivers_route_mod.F90 b/src/science/river_routing/rivers_route_mod.F90 index a7dc380d..6d2b4ed3 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,34 @@ 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. +!------------------------------------------------------------------------------ +!cxyz Do we need to test both? That IS clearer. +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/water_resources/calc_avail_water_mod.F90 b/src/science/water_resources/calc_avail_water_mod.F90 index 1c96bede..6914a6fa 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,19 +212,20 @@ 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) ) + + ! Include water available from rivers. + sw_avail_global(:,sw_river_source) = river_storage_global(:) + + IF ( l_minor_reservoirs ) THEN + ! Include water stored in minor reservoirs. + sw_avail_global(:,sw_minor_res_source) = minor_res_storage_global(:) + END IF + END IF IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) diff --git a/src/science/water_resources/water_resources_drive.F90 b/src/science/water_resources/water_resources_drive.F90 index af7f0465..c2c68e01 100644 --- a/src/science/water_resources/water_resources_drive.F90 +++ b/src/science/water_resources/water_resources_drive.F90 @@ -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_sw, & + 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 @@ -474,11 +475,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 +506,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. @@ -568,7 +570,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,11 +580,12 @@ 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_sw, water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -593,7 +596,7 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_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, & + l_have_groundwater, nwater_use, rf_domestic, & rf_livestock, rf_industry, use_environment, use_domestic, use_industry, & use_irrigation, use_livestock, use_transfers @@ -610,7 +613,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). @@ -671,14 +674,15 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_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). + ! water to either renewable groundwater or river water; if the preferred sink + ! is not modelled the other is used. We know that at least one of l_rivers + ! and l_have_groundwater is TRUE when water resources are modelled. If the + ! only groundwater is "non-renewable", any groundwater return is instead + ! later added to runoff (not groundwater). !--------------------------------------------------------------------------- IF ( i == use_domestic ) THEN - ! Domestic water is returned to rivers, if those are modelled. + ! Domestic water is returned to rivers, if those are modelled, otherwise to + ! groundwater. IF ( l_rivers ) THEN return_flow_frac_gw = 0.0 return_flow_frac_sw = rf_domestic @@ -688,7 +692,8 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & END IF removed_frac = 1.0 - rf_domestic ELSE IF ( i == use_industry ) THEN - ! Industrial water is returned to rivers, if those are modelled. + ! Industrial water is returned to rivers, if those are modelled, otherwise + ! to groundwater. IF ( l_rivers ) THEN return_flow_frac_gw = 0.0 return_flow_frac_sw = rf_industry @@ -698,7 +703,8 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted, conveyance_loss_use, & END IF removed_frac = 1.0 - rf_industry ELSE IF ( i == use_livestock ) THEN - ! Livestock water is returned to groundwater, if that is modelled. + ! Livestock water is returned to groundwater, if that is modelled, + ! otherwise to rivers. IF ( l_have_groundwater ) THEN return_flow_frac_gw = rf_livestock return_flow_frac_sw = 0.0 @@ -721,7 +727,7 @@ 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. From 24290920213540cfbe8cdf23c201f068bff8953d Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Fri, 29 May 2026 16:37:59 +0100 Subject: [PATCH 04/24] Now passing abstraction from minor reservoirs (from water resource code to rivers code) as a variable on "global" land points rather than scattering and then regathering. --- src/control/rivers-standalone/control_mod.F90 | 17 +++-- src/control/shared/jules_rivers_mod.F90 | 20 +---- src/control/shared/surf_couple_extra_mod.F90 | 24 +++--- src/control/shared/surf_couple_rivers_mod.F90 | 37 +++------- .../shared/water_resources_control_mod.F90 | 48 ++++++++---- .../shared/water_resources_vars_mod.F90 | 73 ++++++++++++------- src/control/standalone/control.F90 | 4 +- .../shared/allocate_jules_arrays.F90 | 8 +- .../ancillaries/jules_rivers_props_mod.F90 | 24 +++++- 9 files changed, 150 insertions(+), 105 deletions(-) diff --git a/src/control/rivers-standalone/control_mod.F90 b/src/control/rivers-standalone/control_mod.F90 index 907ebfd7..9d71f854 100644 --- a/src/control/rivers-standalone/control_mod.F90 +++ b/src/control/rivers-standalone/control_mod.F90 @@ -121,11 +121,12 @@ SUBROUTINE control ( & flowin(row_length, rows), & bflowin(row_length, rows), & twatstor(river_row_length, river_rows), & - abstracted_minor_res(land_pts), & +!cxyz Size not done yet. + abstracted_minor_res_global(land_pts), & ! Water abstracted from minor reservoirs (kg). net_abstracted_river(land_pts), & ! Net abstraction from rivers (kg m-2) - tot_abstracted_minor_res(land_pts), & + tot_abstracted_minor_res_global(land_pts), & ! Water abstracted from minor reservoirs over river timestep (kg). tot_net_abstracted_river(land_pts) ! Water abstracted from rivers over river timestep (kg m-2). @@ -144,10 +145,10 @@ SUBROUTINE control ( & !End of header ! Abstractions of water are zero in rivers-only configuration. -abstracted_minor_res(:) = 0.0 -net_abstracted_river(:) = 0.0 -tot_abstracted_minor_res(:) = 0.0 -tot_net_abstracted_river(:) = 0.0 +abstracted_minor_res_global(:) = 0.0 +net_abstracted_river(:) = 0.0 +tot_abstracted_minor_res_global(:) = 0.0 +tot_net_abstracted_river(:) = 0.0 SELECT CASE ( lsm_id ) CASE ( rivers ) @@ -155,14 +156,14 @@ SUBROUTINE control ( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - abstracted_minor_res, net_abstracted_river, & + abstracted_minor_res_global, net_abstracted_river, & 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, & - tot_abstracted_minor_res, & + tot_abstracted_minor_res_global, & tot_net_abstracted_river, river%acc_lake_evap_gb, & wtrac_jls%tot_surf_runoff_gb, wtrac_jls%tot_sub_runoff_gb, & wtrac_jls%acc_lake_evap_gb, & diff --git a/src/control/shared/jules_rivers_mod.F90 b/src/control/shared/jules_rivers_mod.F90 index c1fb722d..82237315 100644 --- a/src/control/shared/jules_rivers_mod.F90 +++ b/src/control/shared/jules_rivers_mod.F90 @@ -429,9 +429,9 @@ MODULE jules_rivers_mod REAL, ALLOCATABLE :: tot_sub_runoff_gb(:) ! accumulated sub-surface runoff (production) ! rate between calls to rivers (kg m-2 s-1) - REAL, ALLOCATABLE :: tot_abstracted_minor_res(:) + REAL, ALLOCATABLE :: tot_abstracted_minor_res_global(:) ! Water abstracted from minor reservoirs over river - ! timestep (kg). + ! timestep, on global land points (kg). REAL, ALLOCATABLE :: tot_net_abstracted_river(:) ! Water abstracted from rivers over river timestep ! (kg m-2). @@ -498,10 +498,6 @@ MODULE jules_rivers_mod REAL(KIND=real_jlslsm), ALLOCATABLE :: rrun_sub_surf_rp(:) ! Sub-surface runoff after river routing on river ! vector (kg/m2/s) -! REAL(KIND=real_jlslsm), ALLOCATABLE :: minor_res_abstracted_rp(:) - ! Water abstracted from minor reservoirs, on river - ! points (kg). - ! cxyz only needs to be here for diagnostic, otherwise could be local to routing. REAL(KIND=real_jlslsm), ALLOCATABLE :: sub_surf_roff_rp(:) ! OASIS-Rivers: Sub-surface runoff on river vector (kg m-2 s-1) REAL(KIND=real_jlslsm), ALLOCATABLE :: surf_roff_rp(:) @@ -629,7 +625,7 @@ MODULE jules_rivers_mod TYPE :: rivers_type REAL, POINTER :: tot_surf_runoff_gb(:) REAL, POINTER :: tot_sub_runoff_gb(:) - REAL, POINTER :: tot_abstracted_minor_res(:) + REAL, POINTER :: tot_abstracted_minor_res_global(:) REAL, POINTER :: tot_net_abstracted_river(:) REAL, POINTER :: acc_lake_evap_gb(:,:) REAL, POINTER :: rivers_sto_per_m2_on_landpts(:) @@ -733,11 +729,6 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & #if !defined(LFRIC) ALLOCATE(rivers_data%tot_surf_runoff_gb(land_pts)) ALLOCATE(rivers_data%tot_sub_runoff_gb(land_pts)) -IF ( l_water_resources .AND. l_minor_reservoirs ) THEN - ALLOCATE(rivers_data%tot_abstracted_minor_res(land_pts)) -ELSE - ALLOCATE(rivers_data%tot_abstracted_minor_res(1)) -END IF IF ( l_water_resources .AND. sw_river_source > 0 ) THEN ALLOCATE(rivers_data%tot_net_abstracted_river(land_pts)) ELSE @@ -789,7 +780,6 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & #else ALLOCATE(rivers_data%tot_surf_runoff_gb(1)) ALLOCATE(rivers_data%tot_sub_runoff_gb(1)) -ALLOCATE(rivers_data%tot_abstracted_minor_res(1)) ALLOCATE(rivers_data%tot_net_abstracted_river(1)) ALLOCATE(rivers_data%acc_lake_evap_gb(1,1)) ALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts(1)) @@ -821,7 +811,6 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & rivers_data%tot_surf_runoff_gb(:) = 0.0 rivers_data%tot_sub_runoff_gb(:) = 0.0 -rivers_data%tot_abstracted_minor_res(:) = 0.0 rivers_data%tot_net_abstracted_river(:) = 0.0 rivers_data%acc_lake_evap_gb(:,:) = 0.0 rivers_data%rivers_sto_per_m2_on_landpts(:) = 0.0 @@ -1500,7 +1489,6 @@ SUBROUTINE rivers_dealloc(rivers_data) DEALLOCATE(rivers_data%tot_surf_runoff_gb) DEALLOCATE(rivers_data%tot_sub_runoff_gb) -DEALLOCATE(rivers_data%tot_abstracted_minor_res) DEALLOCATE(rivers_data%tot_net_abstracted_river) DEALLOCATE(rivers_data%acc_lake_evap_gb) DEALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts) @@ -1575,7 +1563,6 @@ SUBROUTINE rivers_assoc(rivers, rivers_data) rivers%tot_surf_runoff_gb => rivers_data%tot_surf_runoff_gb rivers%tot_sub_runoff_gb => rivers_data%tot_sub_runoff_gb -rivers%tot_abstracted_minor_res => rivers_data%tot_abstracted_minor_res rivers%tot_net_abstracted_river => rivers_data%tot_net_abstracted_river rivers%acc_lake_evap_gb => rivers_data%acc_lake_evap_gb rivers%rivers_sto_per_m2_on_landpts => rivers_data%rivers_sto_per_m2_on_landpts @@ -1648,7 +1635,6 @@ SUBROUTINE rivers_nullify(rivers) NULLIFY(rivers%tot_surf_runoff_gb) NULLIFY(rivers%tot_sub_runoff_gb) -NULLIFY(rivers%tot_abstracted_minor_res) NULLIFY(rivers%tot_net_abstracted_river) NULLIFY(rivers%acc_lake_evap_gb) NULLIFY(rivers%rivers_sto_per_m2_on_landpts) diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index 513361b1..500dce86 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -79,7 +79,7 @@ SUBROUTINE surf_couple_extra( & zw_soilt, sthzw_soilt, & ls_rainfrac_gb, & substore, surfstore, flowin, bflowin, & - tot_surf_runoff_gb, tot_sub_runoff_gb, tot_abstracted_minor_res, & + tot_surf_runoff_gb, tot_sub_runoff_gb, & tot_net_abstracted_river, acc_lake_evap_gb, twatstor, & asteps_since_triffid, & inlandout_atm_gb, & @@ -123,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 +248,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 +265,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,7 +390,6 @@ SUBROUTINE surf_couple_extra( & acc_lake_evap_gb(row_length,rows), & tot_surf_runoff_gb(land_pts), & tot_sub_runoff_gb(land_pts), & - tot_abstracted_minor_res(land_pts), & ! Water abstracted from minor reservoirs over river timestep (kg). tot_net_abstracted_river(land_pts), & ! Water abstracted from rivers over river timestep (kg m-2). @@ -845,7 +846,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, & @@ -873,7 +874,9 @@ SUBROUTINE surf_couple_extra( & 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%abstracted_minor_res, & + crop_vars%irrig_water_gb, & + water_resources%abstracted_minor_res, & + water_resources%abstracted_minor_res_global, & water_resources%net_abstracted_river, & water_resources%sw_abstracted, water_resources%sw_avail_total, & water_resources%water_removed ) @@ -885,14 +888,15 @@ SUBROUTINE surf_couple_extra( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - water_resources%abstracted_minor_res, & + water_resources%abstracted_minor_res_global, & water_resources%net_abstracted_river, & 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, tot_abstracted_minor_res, & + !REAL, INTENT (INOUT)< + tot_surf_runoff_gb, tot_sub_runoff_gb, & + rivers%tot_abstracted_minor_res_global, & tot_net_abstracted_river, acc_lake_evap_gb, & wtrac_jls%tot_surf_runoff_gb, wtrac_jls%tot_sub_runoff_gb, & wtrac_jls%acc_lake_evap_gb, & diff --git a/src/control/shared/surf_couple_rivers_mod.F90 b/src/control/shared/surf_couple_rivers_mod.F90 index 381fcd16..e61aa2cb 100644 --- a/src/control/shared/surf_couple_rivers_mod.F90 +++ b/src/control/shared/surf_couple_rivers_mod.F90 @@ -18,12 +18,12 @@ SUBROUTINE surf_couple_rivers( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - abstracted_minor_res, net_abstracted_river, & + abstracted_minor_res_global, net_abstracted_river, & 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, tot_abstracted_minor_res, & + tot_surf_runoff_gb, tot_sub_runoff_gb, tot_abstracted_minor_res_global, & tot_net_abstracted_river, acc_lake_evap_gb, & tot_surf_runoff_gb_wtrac, tot_sub_runoff_gb_wtrac, & acc_lake_evap_gb_wtrac, & @@ -148,7 +148,7 @@ SUBROUTINE surf_couple_rivers( & a_steps_since_riv REAL(KIND=real_jlslsm), INTENT(IN) :: & - abstracted_minor_res(land_pts), & + abstracted_minor_res_global(global_land_pts), & ! Water abstracted from minor reservoirs (kg). net_abstracted_river(land_pts), & ! Net abstraction from rivers (kg m-2). @@ -190,7 +190,7 @@ 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(land_pts), & + tot_abstracted_minor_res_global(global_land_pts), & ! Water abstracted from minor reservoirs over river timestep (kg). tot_net_abstracted_river(land_pts), & ! Water abstracted from rivers over river timestep (kg m-2). @@ -241,8 +241,6 @@ SUBROUTINE surf_couple_rivers( & ! Average rate of subsurface runoff over river timestep (kg m-2 s-1). REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_surf_runoff(:) ! Average rate of surface runoff over river timestep (kg m-2 s-1). -REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_abstracted_minor_res(:) - ! Water abstracted from minor reservoirs over river timestep (kg). REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_net_abstracted_river(:) ! Water abstracted from rivers over river timestep (kg). REAL(KIND=real_jlslsm), ALLOCATABLE :: global_rrun(:) @@ -374,7 +372,7 @@ SUBROUTINE surf_couple_rivers( & ! Initialise the accumulated abstraction from minor reservoirs. IF ( l_water_resources .AND. l_minor_reservoirs ) THEN - tot_abstracted_minor_res(:) = 0.0 + tot_abstracted_minor_res_global(:) = 0.0 END IF END IF ! a_steps_since_riv == 0 @@ -422,8 +420,8 @@ SUBROUTINE surf_couple_rivers( & ! Accumulate abstraction from minor reservoirs. IF ( l_water_resources .AND. l_minor_reservoirs ) THEN - CALL accumulate_abstraction( land_pts, abstracted_minor_res, & - tot_abstracted_minor_res ) + CALL accumulate_abstraction( global_land_pts, abstracted_minor_res_global, & + tot_abstracted_minor_res_global ) END IF @@ -571,6 +569,7 @@ SUBROUTINE surf_couple_rivers( & ALLOCATE(global_sea_level(tmp_land_size), STAT = ERROR) error_sum = error_sum + ERROR +!cxyz ! Allocate abstraction from rivers. IF ( .NOT. l_oasis_rivers .AND. sw_river_source > 0 & .AND. is_master_task() ) THEN @@ -586,21 +585,16 @@ SUBROUTINE surf_couple_rivers( & ALLOCATE(net_abstracted_river_rp(tmp_river_size), STAT = ERROR) error_sum = error_sum + ERROR - ! Allocate global abstraction from minor reservoirs. + ! Allocate abstraction from minor reservoirs. IF ( .NOT. l_oasis_rivers .AND. l_minor_reservoirs & .AND. is_master_task() ) THEN - ! Note that global_tot_abstracted_minor_res is required at full size only - ! if l_water_resources=T, but for simplicity we only test on - ! l_minor_reservoirs here. - tmp_land_size = global_land_pts tmp_river_size = np_rivers ELSE ! Allocate at minimum size. - tmp_land_size = 1 tmp_river_size = 1 END IF - ALLOCATE(global_tot_abstracted_minor_res(tmp_land_size), STAT = ERROR) - error_sum = error_sum + ERROR + !!ALLOCATE(global_tot_abstracted_minor_res(tmp_land_size), STAT = ERROR) + !!error_sum = error_sum + ERROR ALLOCATE(abstracted_minor_res_rp(tmp_river_size), STAT = ERROR) error_sum = error_sum + ERROR @@ -635,12 +629,6 @@ SUBROUTINE surf_couple_rivers( & global_tot_net_abstracted_river, & rivers%global_land_index ) END IF - ! Gather abstraction from minor reservoirs. - IF ( l_minor_reservoirs .AND. l_water_resources ) THEN - CALL gather_land_field( tot_abstracted_minor_res, & - global_tot_abstracted_minor_res, & - rivers%global_land_index ) - END IF END IF ! .NOT. l_oasis_rivers ) THEN !------------------------------------------------------------------------- @@ -705,7 +693,7 @@ SUBROUTINE surf_couple_rivers( & rivers%map_river_to_land_points, & rivers%global_land_index, & rivers%rivers_index_rp, & - global_tot_abstracted_minor_res, & + tot_abstracted_minor_res_global, & abstracted_minor_res_rp ) END IF @@ -779,7 +767,6 @@ SUBROUTINE surf_couple_rivers( & ! Deallocate local variables (in reverse order to allocation). DEALLOCATE(abstracted_minor_res_rp) - DEALLOCATE(global_tot_abstracted_minor_res) DEALLOCATE(net_abstracted_river_rp) DEALLOCATE(global_tot_net_abstracted_river) DEALLOCATE(global_sea_level) diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 72be47aa..8eb5a4b8 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -97,7 +97,7 @@ MODULE water_resources_control_mod !############################################################################## -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, & @@ -115,8 +115,8 @@ SUBROUTINE water_resources_control( & 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, abstracted_minor_res, net_abstracted_river, & - sw_abstracted, sw_avail_total, water_removed ) + irrig_water_gb, abstracted_minor_res, abstracted_minor_res_global,& + net_abstracted_river, sw_abstracted, sw_avail_total, water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -149,10 +149,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 @@ -170,6 +168,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) !------------------------------------------------------------------------------ @@ -301,7 +306,11 @@ SUBROUTINE water_resources_control( & irrig_water_gb(land_pts), & ! Water added to soil via irrigation (kg m-2 s-1). abstracted_minor_res(land_pts), & - ! Water abstracted from minor reservoirs (kg). + ! Water abstracted from minor reservoirs (kg). Diagnostic only. + !cxyz Perhaps don't specify size? + 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. !cxyz Perhaps don't specify size? net_abstracted_river(land_pts), & @@ -400,7 +409,7 @@ SUBROUTINE water_resources_control( & !------------------------------------------------------------------------------ ! Initialise coupling fluxes. IF ( l_minor_reservoirs ) THEN - abstracted_minor_res(:) = 0.0 + abstracted_minor_res_global(:) = 0.0 END IF IF ( sw_river_source > 0 ) THEN net_abstracted_river(:) = 0.0 @@ -412,6 +421,10 @@ SUBROUTINE water_resources_control( & ! Initialise other fluxes. demand_unmet(:,:) = 0.0 water_removed(:) = 0.0 +! Initialise diagnostics. +IF ( l_minor_reservoirs ) THEN + abstracted_minor_res(:) = 0.0 +END IF !------------------------------------------------------------------------------ ! Add to the accumulated demands (only for prescribed demands). @@ -524,6 +537,12 @@ SUBROUTINE water_resources_control( & conveyance_loss_global, return_flow_gw_global, & return_flow_sw_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 + END IF ! is_master_task !---------------------------------------------------------------------------- @@ -1212,11 +1231,13 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & ! 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. !cxyz No longer true. CALL scatter_land_field( return_flow_sw_global, return_flow_sw ) @@ -1224,15 +1245,14 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & 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 ) - ! Abstraction from minor reservoirs. - !cxyz Note that it is slightly daft that we are scattering here only to later - ! regather in rivers code (as for net abs from river?) - but this does - ! allows this to better follow existing code. + + ! 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 -END IF + +END IF ! l_have_surface_water ! Fields for irrigation. IF ( l_water_irrigation ) THEN diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index 8ff91556..904d52bc 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -9,6 +9,7 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +!cxyz Note annoying variations of line length for "-----". !----------------------------------------------------------------------------- ! Description: ! Contains variables and field types for water resource modelling. @@ -74,12 +75,12 @@ MODULE water_resources_vars_mod !-------------------------------------------------------------------------- ! Fluxes for coupling. !-------------------------------------------------------------------------- - abstracted_minor_res(:), & - ! Water abstracted from minor reservoirs (kg). + abstracted_minor_res_global(:), & + ! Water abstracted from minor reservoirs, on global land points (kg). net_abstracted_river(:), & ! Net abstraction from river (kg m-2). !-------------------------------------------------------------------------- - ! Diagnostics (also used internally). + ! Diagnostics (also used internally). !cxyz rephrase to emphaise internal ! All abstractions are gross fluxes (not net of returns) unless stated ! otherwise. !-------------------------------------------------------------------------- @@ -102,9 +103,14 @@ MODULE water_resources_vars_mod sw_avail_total(:), & ! Surface water that is available for abstraction at start of timestep, ! summed over sources (kg). - water_removed(:) + water_removed(:), & ! Water that is removed from the system during use, e.g. incorporated - ! into manufactured goods (kg). + ! into manufactured goods (kg). !cxyz diag? + !-------------------------------------------------------------------------- + ! Diagnosstics (not also used internally). + !-------------------------------------------------------------------------- + abstracted_minor_res(:) + ! Water abstracted from minor reservoirs (kg). END TYPE @@ -119,7 +125,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: demand_rate_industry(:) REAL(KIND=real_jlslsm), POINTER :: demand_rate_livestock(:) REAL(KIND=real_jlslsm), POINTER :: demand_rate_transfers(:) - REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res(:) + REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res_global(:) REAL(KIND=real_jlslsm), POINTER :: net_abstracted_river(:) REAL(KIND=real_jlslsm), POINTER :: demand_accum(:,:) REAL(KIND=real_jlslsm), POINTER :: demand_unmet(:,:) @@ -129,6 +135,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: sw_abstracted(:,:) REAL(KIND=real_jlslsm), POINTER :: sw_avail_total(:) REAL(KIND=real_jlslsm), POINTER :: water_removed(:) + REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res(:) END TYPE @@ -140,7 +147,8 @@ MODULE water_resources_vars_mod !############################################################################## -SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & +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_minor_reservoirs, l_water_domestic, l_water_industry, & l_water_irrigation, l_water_livestock, l_water_resources, & @@ -156,6 +164,8 @@ 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, & @@ -195,8 +205,8 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & ! Local variables !------------------------------------------------------------------------------ INTEGER :: & - land_pts_dim, land_pts_gw, land_pts_minor_res, land_pts_sw, & - land_pts_sw_rivers, n_sw_source_dim, nwater_use_dim + global_land_pts_minor_res, land_pts_dim, land_pts_gw, land_pts_minor_res, & + land_pts_sw, land_pts_sw_rivers, n_sw_source_dim, nwater_use_dim ! Sizes used when allocating arrays. INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 @@ -216,9 +226,9 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & !----------------------------------------------------------------------------- ! Set default sizes that are used if water resources (or a particular part of ! the parameterisation) are not selected. +global_land_pts_minor_res = 1 land_pts_dim = 1 land_pts_gw = 1 -land_pts_minor_res = 1 land_pts_sw = 1 land_pts_sw_rivers = 1 n_sw_source_dim = 1 @@ -228,18 +238,20 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & 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 IF ( sw_river_source > 0 ) THEN - land_pts_sw_rivers = land_pts + land_pts_sw_rivers = land_pts END IF IF ( l_minor_reservoirs ) THEN land_pts_minor_res = land_pts +!cxyz Only full size on master. + global_land_pts_minor_res = global_land_pts END IF -END IF +END IF ! l_water_resources !----------------------------------------------------------------------------- ! Priority order. @@ -248,8 +260,9 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & !----------------------------------------------------------------------------- ! Ancillary fields on land points. -! Although these are not required for every configuration, they are commonly -! required and hence for convenience we always allocate them. +! 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) ) @@ -285,10 +298,13 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & !----------------------------------------------------------------------------- ! 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. +!------------------------------------------------------------------------------ print*,'alloc l_minor_reservoirs=',l_minor_reservoirs -ALLOCATE( water_resources_data%abstracted_minor_res(land_pts_minor_res) ) -print*,'Alloc size=',size( water_resources_data%abstracted_minor_res ) +ALLOCATE( water_resources_data & + %abstracted_minor_res_global(global_land_pts_minor_res) ) +print*,'Alloc size=',size( water_resources_data%abstracted_minor_res_global ) !----------------------------------------------------------------------------- ! Coupling to rivers. @@ -309,6 +325,8 @@ 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) ) +! Diagnstics. +ALLOCATE( water_resources_data%abstracted_minor_res(land_pts_minor_res) ) !----------------------------------------------------------------------------- ! Initialise arrays. @@ -320,7 +338,7 @@ 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%abstracted_minor_res(:) = 0.0 +water_resources_data%abstracted_minor_res_global(:) = 0.0 water_resources_data%net_abstracted_river(:) = 0.0 water_resources_data%demand_accum(:,:) = 0.0 water_resources_data%demand_unmet(:,:) = 0.0 @@ -330,6 +348,7 @@ SUBROUTINE water_resources_alloc( land_pts, n_sw_source, nwater_use, & 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 IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -365,7 +384,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) -!cxy Should deallocate in reverse order. +!cxyz Should deallocate in reverse order. DEALLOCATE( water_resources_data%priority_order ) DEALLOCATE( water_resources_data%conv_loss_frac ) DEALLOCATE( water_resources_data%sfc_water_frac ) @@ -373,7 +392,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) 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%abstracted_minor_res ) +DEALLOCATE( water_resources_data%abstracted_minor_res_global ) DEALLOCATE( water_resources_data%net_abstracted_river ) DEALLOCATE( water_resources_data%demand_accum ) DEALLOCATE( water_resources_data%demand_unmet ) @@ -383,6 +402,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) DEALLOCATE( water_resources_data%gw_nr_abstracted ) DEALLOCATE( water_resources_data%sw_abstracted ) DEALLOCATE( water_resources_data%sw_avail_total ) +DEALLOCATE( water_resources_data%abstracted_minor_res ) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -439,8 +459,8 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) => water_resources_data%demand_rate_livestock water_resources%demand_rate_transfers & => water_resources_data%demand_rate_transfers -water_resources%abstracted_minor_res & - => water_resources_data%abstracted_minor_res +water_resources%abstracted_minor_res_global & + => water_resources_data%abstracted_minor_res_global water_resources%net_abstracted_river & => water_resources_data%net_abstracted_river water_resources%demand_accum => water_resources_data%demand_accum @@ -451,6 +471,8 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) water_resources%gw_nr_abstracted => water_resources_data%gw_nr_abstracted water_resources%sw_abstracted => water_resources_data%sw_abstracted water_resources%sw_avail_total => water_resources_data%sw_avail_total +water_resources%abstracted_minor_res & + => water_resources_data%abstracted_minor_res IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -490,7 +512,7 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%demand_rate_industry ) NULLIFY( water_resources%demand_rate_livestock ) NULLIFY( water_resources%demand_rate_transfers ) -NULLIFY( water_resources%abstracted_minor_res ) +NULLIFY( water_resources%abstracted_minor_res_global ) NULLIFY( water_resources%net_abstracted_river ) NULLIFY( water_resources%demand_accum ) NULLIFY( water_resources%demand_unmet ) @@ -500,6 +522,7 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%gw_nr_abstracted ) NULLIFY( water_resources%sw_abstracted ) NULLIFY( water_resources%sw_avail_total ) +NULLIFY( water_resources%abstracted_minor_res ) 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 60544f0a..03a8ed43 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 @@ -292,7 +297,8 @@ 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, sw_river_source,& +CALL water_resources_alloc( global_land_pts, & + land_pts, n_sw_source, nwater_use, sw_river_source,& l_have_groundwater, l_have_surface_water, & l_minor_reservoirs, l_water_domestic, & l_water_industry, & diff --git a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 index 58a9dc71..b9f8b8c9 100644 --- a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 @@ -629,6 +629,12 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) 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_minor_reservoirs, l_sea_level, & @@ -663,6 +669,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 @@ -898,10 +906,12 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) !------------------------------------------------------------------------------ IF ( l_minor_reservoirs .AND. is_master_task() ) THEN ! Full size. - np_rivers_tmp = np_rivers + np_rivers_tmp = np_rivers + np_global_land_tmp = global_land_pts ELSE ! Minimum size. - np_rivers_tmp = 1 + np_rivers_tmp = 1 + np_global_land_tmp = 1 END IF ! Minor reservoir ancillaries. @@ -912,6 +922,10 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) ! Minor reservoir prognostics. ALLOCATE( rivers_data%minor_res_storage(np_rivers_tmp), STAT = ERROR ) error_sum = error_sum + ERROR +! Minor reservoir coupling. +ALLOCATE( rivers_data%tot_abstracted_minor_res_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." ) @@ -993,6 +1007,8 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers_data%minor_res_capacity(:) = rmdi rivers_data%minor_res_frac(:) = rmdi rivers_data%minor_res_storage(:) = 0.0 +!cxyz initialise coupling to zero or handled elsewhere? +rivers_data%tot_abstracted_minor_res_global(:) = 0.0 !------------------------------------------------------------------------------ ! Associate pointers @@ -1060,10 +1076,12 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers%sub_surf_roff_rp => rivers_data%sub_surf_roff_rp rivers%surf_roff_rp => rivers_data%surf_roff_rp -! Associate pointers for reservoir variables. +! Associate pointers for 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 RETURN END SUBROUTINE allocate_rivers_vars_rp From c1921fecbf777ea07bde7cba9a66fe6bbadeeb2d Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Mon, 8 Jun 2026 15:52:07 +0100 Subject: [PATCH 05/24] Net abstraction from rivers is now also passed to rivers as a global (not local) land point variable. --- src/control/rivers-standalone/control_mod.F90 | 14 ++-- src/control/shared/jules_rivers_mod.F90 | 32 ++++---- src/control/shared/surf_couple_extra_mod.F90 | 12 ++- src/control/shared/surf_couple_rivers_mod.F90 | 34 +++------ .../shared/water_resources_control_mod.F90 | 74 ++++++++++++------- .../shared/water_resources_vars_mod.F90 | 34 +++++---- src/control/standalone/control.F90 | 1 - .../ancillaries/jules_rivers_props_mod.F90 | 41 ++++++++-- 8 files changed, 136 insertions(+), 106 deletions(-) diff --git a/src/control/rivers-standalone/control_mod.F90 b/src/control/rivers-standalone/control_mod.F90 index 9d71f854..790e9071 100644 --- a/src/control/rivers-standalone/control_mod.F90 +++ b/src/control/rivers-standalone/control_mod.F90 @@ -121,14 +121,14 @@ SUBROUTINE control ( & flowin(row_length, rows), & bflowin(row_length, rows), & twatstor(river_row_length, river_rows), & -!cxyz Size not done yet. +!cxyz Sizes not done yet. abstracted_minor_res_global(land_pts), & ! Water abstracted from minor reservoirs (kg). - net_abstracted_river(land_pts), & + 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(land_pts) + tot_net_abstracted_river_global(land_pts) ! Water abstracted from rivers over river timestep (kg m-2). REAL(KIND=real_jlslsm) :: & @@ -146,9 +146,9 @@ SUBROUTINE control ( & ! Abstractions of water are zero in rivers-only configuration. abstracted_minor_res_global(:) = 0.0 -net_abstracted_river(:) = 0.0 +net_abstracted_river_global(:) = 0.0 tot_abstracted_minor_res_global(:) = 0.0 -tot_net_abstracted_river(:) = 0.0 +tot_net_abstracted_river_global(:) = 0.0 SELECT CASE ( lsm_id ) CASE ( rivers ) @@ -156,7 +156,7 @@ SUBROUTINE control ( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - abstracted_minor_res_global, net_abstracted_river, & + 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) @@ -164,7 +164,7 @@ SUBROUTINE control ( & !REAL, INTENT (INOUT) river%tot_surf_runoff_gb, river%tot_sub_runoff_gb, & tot_abstracted_minor_res_global, & - tot_net_abstracted_river, river%acc_lake_evap_gb, & + 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 82237315..32b4dd7e 100644 --- a/src/control/shared/jules_rivers_mod.F90 +++ b/src/control/shared/jules_rivers_mod.F90 @@ -429,12 +429,6 @@ MODULE jules_rivers_mod REAL, ALLOCATABLE :: tot_sub_runoff_gb(:) ! accumulated sub-surface runoff (production) ! rate between calls to rivers (kg m-2 s-1) - 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(:) - ! Water abstracted from rivers over river timestep - ! (kg m-2). REAL, ALLOCATABLE :: acc_lake_evap_gb(:,:) ! accumulated lake evap over river routing ! timestep (Kg/m2) - on 2D full global field @@ -574,6 +568,16 @@ MODULE jules_rivers_mod 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 @@ -625,8 +629,6 @@ MODULE jules_rivers_mod TYPE :: rivers_type REAL, POINTER :: tot_surf_runoff_gb(:) REAL, POINTER :: tot_sub_runoff_gb(:) - REAL, POINTER :: tot_abstracted_minor_res_global(:) - REAL, POINTER :: tot_net_abstracted_river(:) REAL, POINTER :: acc_lake_evap_gb(:,:) REAL, POINTER :: rivers_sto_per_m2_on_landpts(:) REAL, POINTER :: rivers_adj_on_landpts(:) @@ -672,6 +674,8 @@ MODULE jules_rivers_mod 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(:,:) @@ -729,11 +733,6 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & #if !defined(LFRIC) ALLOCATE(rivers_data%tot_surf_runoff_gb(land_pts)) ALLOCATE(rivers_data%tot_sub_runoff_gb(land_pts)) -IF ( l_water_resources .AND. sw_river_source > 0 ) THEN - ALLOCATE(rivers_data%tot_net_abstracted_river(land_pts)) -ELSE - ALLOCATE(rivers_data%tot_net_abstracted_river(1)) -END IF ALLOCATE(rivers_data%acc_lake_evap_gb(t_i_length,t_j_length)) ALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts(land_pts)) ALLOCATE(rivers_data%rivers_adj_on_landpts(land_pts)) @@ -780,7 +779,6 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & #else ALLOCATE(rivers_data%tot_surf_runoff_gb(1)) ALLOCATE(rivers_data%tot_sub_runoff_gb(1)) -ALLOCATE(rivers_data%tot_net_abstracted_river(1)) ALLOCATE(rivers_data%acc_lake_evap_gb(1,1)) ALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts(1)) ALLOCATE(rivers_data%rivers_adj_on_landpts(1)) @@ -811,7 +809,6 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & rivers_data%tot_surf_runoff_gb(:) = 0.0 rivers_data%tot_sub_runoff_gb(:) = 0.0 -rivers_data%tot_net_abstracted_river(:) = 0.0 rivers_data%acc_lake_evap_gb(:,:) = 0.0 rivers_data%rivers_sto_per_m2_on_landpts(:) = 0.0 rivers_data%rivers_adj_on_landpts(:) = 0.0 @@ -1489,7 +1486,6 @@ SUBROUTINE rivers_dealloc(rivers_data) DEALLOCATE(rivers_data%tot_surf_runoff_gb) DEALLOCATE(rivers_data%tot_sub_runoff_gb) -DEALLOCATE(rivers_data%tot_net_abstracted_river) DEALLOCATE(rivers_data%acc_lake_evap_gb) DEALLOCATE(rivers_data%rivers_sto_per_m2_on_landpts) DEALLOCATE(rivers_data%rivers_adj_on_landpts) @@ -1563,7 +1559,6 @@ SUBROUTINE rivers_assoc(rivers, rivers_data) rivers%tot_surf_runoff_gb => rivers_data%tot_surf_runoff_gb rivers%tot_sub_runoff_gb => rivers_data%tot_sub_runoff_gb -rivers%tot_net_abstracted_river => rivers_data%tot_net_abstracted_river rivers%acc_lake_evap_gb => rivers_data%acc_lake_evap_gb rivers%rivers_sto_per_m2_on_landpts => rivers_data%rivers_sto_per_m2_on_landpts rivers%rivers_adj_on_landpts => rivers_data%rivers_adj_on_landpts @@ -1635,12 +1630,11 @@ SUBROUTINE rivers_nullify(rivers) NULLIFY(rivers%tot_surf_runoff_gb) NULLIFY(rivers%tot_sub_runoff_gb) -NULLIFY(rivers%tot_net_abstracted_river) NULLIFY(rivers%acc_lake_evap_gb) 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/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index 500dce86..a20c8c66 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -80,7 +80,7 @@ SUBROUTINE surf_couple_extra( & ls_rainfrac_gb, & substore, surfstore, flowin, bflowin, & tot_surf_runoff_gb, tot_sub_runoff_gb, & - tot_net_abstracted_river, acc_lake_evap_gb, twatstor, & + acc_lake_evap_gb, twatstor, & asteps_since_triffid, & inlandout_atm_gb, & !OUT @@ -391,8 +391,6 @@ SUBROUTINE surf_couple_extra( & tot_surf_runoff_gb(land_pts), & tot_sub_runoff_gb(land_pts), & ! Water abstracted from minor reservoirs over river timestep (kg). - tot_net_abstracted_river(land_pts), & - ! Water abstracted from rivers over river timestep (kg m-2). twatstor(river_row_length, river_rows), & inlandout_atm_gb(land_pts) @@ -877,7 +875,7 @@ SUBROUTINE surf_couple_extra( & crop_vars%irrig_water_gb, & water_resources%abstracted_minor_res, & water_resources%abstracted_minor_res_global, & - water_resources%net_abstracted_river, & + water_resources%net_abstracted_river_global, & water_resources%sw_abstracted, water_resources%sw_avail_total, & water_resources%water_removed ) END IF @@ -889,15 +887,15 @@ SUBROUTINE surf_couple_extra( & land_pts, n_wtrac_jls, & !REAL, INTENT(IN) water_resources%abstracted_minor_res_global, & - water_resources%net_abstracted_river, & + 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)< + !REAL, INTENT (INOUT) tot_surf_runoff_gb, tot_sub_runoff_gb, & rivers%tot_abstracted_minor_res_global, & - tot_net_abstracted_river, acc_lake_evap_gb, & + 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 e61aa2cb..e58b19b1 100644 --- a/src/control/shared/surf_couple_rivers_mod.F90 +++ b/src/control/shared/surf_couple_rivers_mod.F90 @@ -18,13 +18,13 @@ SUBROUTINE surf_couple_rivers( & !INTEGER, INTENT(IN) land_pts, n_wtrac_jls, & !REAL, INTENT(IN) - abstracted_minor_res_global, 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, tot_abstracted_minor_res_global, & - tot_net_abstracted_river, acc_lake_evap_gb, & + 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) @@ -150,7 +150,7 @@ SUBROUTINE surf_couple_rivers( & REAL(KIND=real_jlslsm), INTENT(IN) :: & abstracted_minor_res_global(global_land_pts), & ! Water abstracted from minor reservoirs (kg). - net_abstracted_river(land_pts), & + 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) @@ -192,7 +192,7 @@ SUBROUTINE surf_couple_rivers( & ! 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(land_pts), & + 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), & @@ -241,8 +241,6 @@ SUBROUTINE surf_couple_rivers( & ! Average rate of subsurface runoff over river timestep (kg m-2 s-1). REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_surf_runoff(:) ! Average rate of surface runoff over river timestep (kg m-2 s-1). -REAL(KIND=real_jlslsm), ALLOCATABLE :: global_tot_net_abstracted_river(:) - ! Water abstracted from rivers over river timestep (kg). REAL(KIND=real_jlslsm), ALLOCATABLE :: global_rrun(:) REAL(KIND=real_jlslsm), ALLOCATABLE :: global_rflow(:) REAL(KIND=real_jlslsm), ALLOCATABLE :: global_sea_level(:) @@ -367,7 +365,7 @@ SUBROUTINE surf_couple_rivers( & ! Initialise the accumulated abstraction from rivers. IF ( sw_river_source > 0 ) THEN - tot_net_abstracted_river(:) = 0.0 + tot_net_abstracted_river_global(:) = 0.0 END IF ! Initialise the accumulated abstraction from minor reservoirs. @@ -412,10 +410,10 @@ SUBROUTINE surf_couple_rivers( & END DO END IF ! l_wtrac_jls - ! Accumulate abstraction from rivers. + ! Accumulate net abstraction from rivers. IF ( sw_river_source > 0 ) THEN - CALL accumulate_abstraction( land_pts, net_abstracted_river, & - tot_net_abstracted_river ) + CALL accumulate_abstraction( global_land_pts, net_abstracted_river_global, & + tot_net_abstracted_river_global ) END IF ! Accumulate abstraction from minor reservoirs. @@ -573,17 +571,14 @@ SUBROUTINE surf_couple_rivers( & ! Allocate abstraction from rivers. IF ( .NOT. l_oasis_rivers .AND. sw_river_source > 0 & .AND. is_master_task() ) THEN - tmp_land_size = global_land_pts tmp_river_size = np_rivers ELSE ! Allocate at minimum size. - tmp_land_size = 1 tmp_river_size = 1 END IF - ALLOCATE(global_tot_net_abstracted_river(tmp_land_size), STAT = ERROR) - error_sum = error_sum + ERROR ALLOCATE(net_abstracted_river_rp(tmp_river_size), STAT = ERROR) error_sum = error_sum + ERROR + !cxyz do we need to initalise as below for minor res? ! Allocate abstraction from minor reservoirs. IF ( .NOT. l_oasis_rivers .AND. l_minor_reservoirs & @@ -593,8 +588,6 @@ SUBROUTINE surf_couple_rivers( & ! Allocate at minimum size. tmp_river_size = 1 END IF - !!ALLOCATE(global_tot_abstracted_minor_res(tmp_land_size), STAT = ERROR) - !!error_sum = error_sum + ERROR ALLOCATE(abstracted_minor_res_rp(tmp_river_size), STAT = ERROR) error_sum = error_sum + ERROR @@ -623,12 +616,6 @@ SUBROUTINE surf_couple_rivers( & CALL gather_land_field(rivers%sea_level_lp, global_sea_level, & rivers%global_land_index ) END IF - ! Gather abstraction from river. - IF ( sw_river_source > 0 ) THEN - CALL gather_land_field( tot_net_abstracted_river, & - global_tot_net_abstracted_river, & - rivers%global_land_index ) - END IF END IF ! .NOT. l_oasis_rivers ) THEN !------------------------------------------------------------------------- @@ -683,7 +670,7 @@ SUBROUTINE surf_couple_rivers( & rivers%map_river_to_land_points, & rivers%global_land_index, & rivers%rivers_index_rp, & - global_tot_net_abstracted_river, & + tot_net_abstracted_river_global, & net_abstracted_river_rp ) END IF @@ -768,7 +755,6 @@ SUBROUTINE surf_couple_rivers( & ! Deallocate local variables (in reverse order to allocation). DEALLOCATE(abstracted_minor_res_rp) DEALLOCATE(net_abstracted_river_rp) - DEALLOCATE(global_tot_net_abstracted_river) DEALLOCATE(global_sea_level) DEALLOCATE(global_rflow) DEALLOCATE(global_rrun) diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 8eb5a4b8..0dced7e0 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(:), & @@ -116,7 +118,8 @@ SUBROUTINE water_resources_control( global_land_pts, & tl_1_day_av_use_gb, priority_order, demand_unmet, gw_abstracted, & gw_avail_start, gw_nr_abstracted, & irrig_water_gb, abstracted_minor_res, abstracted_minor_res_global,& - net_abstracted_river, sw_abstracted, sw_avail_total, water_removed ) + net_abstracted_river_global, sw_abstracted, sw_avail_total, & + water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -313,8 +316,9 @@ SUBROUTINE water_resources_control( global_land_pts, & ! This is used to couple to minor reservoirs. ! Note that this has reduced size if it is not required. !cxyz Perhaps don't specify size? - net_abstracted_river(land_pts), & - ! Net abstraction from river (kg m-2). + net_abstracted_river_global(global_land_pts), & + ! Net abstraction from river, on global land points (kg m-2). + !cxy size OK, as above? sw_abstracted(land_pts,n_sw_source), & ! Water that is abstracted from surface waters (kg). sw_avail_total(land_pts), & @@ -412,7 +416,7 @@ SUBROUTINE water_resources_control( global_land_pts, & abstracted_minor_res_global(:) = 0.0 END IF IF ( sw_river_source > 0 ) THEN - net_abstracted_river(:) = 0.0 + net_abstracted_river_global(:) = 0.0 END IF ! Initialise abstractions. cxyz Always allocated at full size? gw_abstracted(:) = 0.0 @@ -498,7 +502,7 @@ SUBROUTINE water_resources_control( global_land_pts, & ! 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 ) IF ( is_master_task() ) THEN @@ -517,6 +521,7 @@ SUBROUTINE water_resources_control( global_land_pts, & 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 ) @@ -543,6 +548,16 @@ SUBROUTINE water_resources_control( global_land_pts, & = sw_abstracted_global(:,sw_minor_res_source) END IF + !-------------------------------------------------------------------------- + ! Calculate the net abstraction from rivers. + !-------------------------------------------------------------------------- + IF ( sw_river_source > 0 ) THEN + CALL calc_river_flux( global_land_pts, grid_area_global, & + return_flow_sw_global, & + sw_abstracted_global(:,sw_river_source), & + net_abstracted_river_global ) + END IF + END IF ! is_master_task !---------------------------------------------------------------------------- @@ -562,15 +577,6 @@ SUBROUTINE water_resources_control( global_land_pts, & 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. !---------------------------------------------------------------------------- @@ -1004,6 +1010,10 @@ SUBROUTINE allocate_global_water( l_allocate ) ALLOCATE(water_removed_global(land_size), STAT = ERROR) error_sum = error_sum + ERROR + !cxyz Using river size - which I think is OK. + 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 @@ -1024,6 +1034,7 @@ SUBROUTINE allocate_global_water( l_allocate ) 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, & @@ -1036,6 +1047,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) @@ -1068,7 +1080,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: @@ -1078,7 +1090,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 @@ -1099,6 +1111,8 @@ 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) @@ -1143,6 +1157,11 @@ 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 + RETURN END SUBROUTINE gather_global_water @@ -1395,8 +1414,10 @@ END SUBROUTINE regrid_to_land !############################################################################## !############################################################################## -SUBROUTINE calc_river_flux( land_pts, grid_area_lp, return_flow_sw, & - sw_abstracted_river, net_abstracted_river ) +SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & + return_flow_sw_global, & + sw_abstracted_river_global, & + net_abstracted_river_global ) !------------------------------------------------------------------------------ ! Description: @@ -1409,25 +1430,25 @@ 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), & + return_flow_sw_global(global_land_pts), & ! Water that is returned to surface waters after use (kg). - sw_abstracted_river(land_pts) + 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). !------------------------------------------------------------------------------ @@ -1440,9 +1461,10 @@ SUBROUTINE calc_river_flux( land_pts, grid_area_lp, return_flow_sw, & !end of header ! 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_sw_global(l) ) & + / grid_area_global(l) END DO RETURN diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index 904d52bc..e34cb0aa 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -77,8 +77,8 @@ MODULE water_resources_vars_mod !-------------------------------------------------------------------------- abstracted_minor_res_global(:), & ! Water abstracted from minor reservoirs, on global land points (kg). - net_abstracted_river(:), & - ! Net abstraction from river (kg m-2). + net_abstracted_river_global(:), & + ! Net abstraction from river, on global land points (kg m-2). !-------------------------------------------------------------------------- ! Diagnostics (also used internally). !cxyz rephrase to emphaise internal ! All abstractions are gross fluxes (not net of returns) unless stated @@ -126,7 +126,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: demand_rate_livestock(:) REAL(KIND=real_jlslsm), POINTER :: demand_rate_transfers(:) REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res_global(:) - REAL(KIND=real_jlslsm), POINTER :: net_abstracted_river(:) + 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(:) @@ -205,8 +205,9 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! Local variables !------------------------------------------------------------------------------ INTEGER :: & - global_land_pts_minor_res, land_pts_dim, land_pts_gw, land_pts_minor_res, & - land_pts_sw, land_pts_sw_rivers, n_sw_source_dim, nwater_use_dim + global_land_pts_minor_res, global_land_pts_sw_rivers, land_pts_dim, & + land_pts_gw, land_pts_minor_res, land_pts_sw, land_pts_sw_rivers, & + n_sw_source_dim, nwater_use_dim ! Sizes used when allocating arrays. INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 @@ -227,10 +228,10 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! Set default sizes that are used if water resources (or a particular part of ! the parameterisation) are not selected. global_land_pts_minor_res = 1 +global_land_pts_sw_rivers = 1 land_pts_dim = 1 land_pts_gw = 1 land_pts_sw = 1 -land_pts_sw_rivers = 1 n_sw_source_dim = 1 nwater_use_dim = 1 IF ( l_water_resources ) THEN @@ -244,7 +245,9 @@ SUBROUTINE water_resources_alloc( global_land_pts, & land_pts_sw = land_pts END IF IF ( sw_river_source > 0 ) THEN - land_pts_sw_rivers = land_pts + !XXland_pts_sw_rivers = land_pts !cxyz do we want a diagnostic? +!cxyz Only full size on master. + global_land_pts_sw_rivers = global_land_pts END IF IF ( l_minor_reservoirs ) THEN land_pts_minor_res = land_pts @@ -303,14 +306,17 @@ SUBROUTINE water_resources_alloc( global_land_pts, & !------------------------------------------------------------------------------ print*,'alloc l_minor_reservoirs=',l_minor_reservoirs ALLOCATE( water_resources_data & - %abstracted_minor_res_global(global_land_pts_minor_res) ) + %abstracted_minor_res_global(global_land_pts_minor_res) ) print*,'Alloc size=',size( water_resources_data%abstracted_minor_res_global ) !----------------------------------------------------------------------------- ! 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(land_pts_sw_rivers) ) +ALLOCATE( water_resources_data & + %net_abstracted_river_global(global_land_pts_sw_rivers) ) !----------------------------------------------------------------------------- ! Other variables. @@ -339,7 +345,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, & water_resources_data%demand_rate_livestock(:) = 0.0 water_resources_data%demand_rate_transfers(:) = 0.0 water_resources_data%abstracted_minor_res_global(:) = 0.0 -water_resources_data%net_abstracted_river(:) = 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 @@ -393,7 +399,7 @@ SUBROUTINE water_resources_dealloc(water_resources_data) DEALLOCATE( water_resources_data%demand_rate_livestock ) DEALLOCATE( water_resources_data%demand_rate_transfers ) DEALLOCATE( water_resources_data%abstracted_minor_res_global ) -DEALLOCATE( water_resources_data%net_abstracted_river ) +DEALLOCATE( water_resources_data%net_abstracted_river_global ) DEALLOCATE( water_resources_data%demand_accum ) DEALLOCATE( water_resources_data%demand_unmet ) DEALLOCATE( water_resources_data%water_removed ) @@ -461,8 +467,8 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) => water_resources_data%demand_rate_transfers water_resources%abstracted_minor_res_global & => water_resources_data%abstracted_minor_res_global -water_resources%net_abstracted_river & - => water_resources_data%net_abstracted_river +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 @@ -513,7 +519,7 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%demand_rate_livestock ) NULLIFY( water_resources%demand_rate_transfers ) NULLIFY( water_resources%abstracted_minor_res_global ) -NULLIFY( water_resources%net_abstracted_river ) +NULLIFY( water_resources%net_abstracted_river_global ) NULLIFY( water_resources%demand_accum ) NULLIFY( water_resources%demand_unmet ) NULLIFY( water_resources%water_removed ) diff --git a/src/control/standalone/control.F90 b/src/control/standalone/control.F90 index 03a8ed43..f9bfa6eb 100644 --- a/src/control/standalone/control.F90 +++ b/src/control/standalone/control.F90 @@ -893,7 +893,6 @@ SUBROUTINE control ( & ls_rainfrac_land, & substore, surfstore, flowin, bflowin, & rivers%tot_surf_runoff_gb, rivers%tot_sub_runoff_gb, & - rivers%tot_net_abstracted_river, & rivers%acc_lake_evap_gb, & twatstor, asteps_since_triffid, & inlandout_atm_gb, & diff --git a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 index b9f8b8c9..535b2cce 100644 --- a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 @@ -624,7 +624,7 @@ 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 @@ -642,6 +642,8 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) 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 @@ -922,11 +924,27 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) ! Minor reservoir prognostics. ALLOCATE( rivers_data%minor_res_storage(np_rivers_tmp), STAT = ERROR ) error_sum = error_sum + ERROR -! Minor reservoir coupling. +! 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 @@ -1010,6 +1028,9 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) !cxyz initialise coupling to zero or handled elsewhere? rivers_data%tot_abstracted_minor_res_global(:) = 0.0 +! Initialise further variables to couple to water resources. +rivers_data%tot_net_abstracted_river_global(:) = 0.0 + !------------------------------------------------------------------------------ ! Associate pointers !------------------------------------------------------------------------------ @@ -1030,10 +1051,10 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers%rrun_sub_surf_rp => rivers_data%rrun_sub_surf_rp rivers%rrun_surf_rp => rivers_data%rrun_surf_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 @@ -1056,7 +1077,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 @@ -1067,22 +1088,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 -! Associate pointers for minor reservoir variables. +! 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 From 63bf14bd25fba8b4820913d0231646e2baba16f8 Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Fri, 12 Jun 2026 11:50:56 +0100 Subject: [PATCH 06/24] Added diagnostics conveyance_loss and river_abstracted. --- src/control/shared/surf_couple_extra_mod.F90 | 7 ++- .../shared/water_resources_control_mod.F90 | 42 +++++++++---- .../shared/water_resources_vars_mod.F90 | 60 ++++++++++++------- .../standalone/init_output_mod.F90 | 41 +++++++------ src/io/model_interface/extract_var.inc | 10 ++++ .../model_interface/model_interface_mod.F90 | 2 +- src/io/model_interface/variable_metadata.inc | 38 ++++++++++-- 7 files changed, 135 insertions(+), 65 deletions(-) diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index a20c8c66..ab104372 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -869,12 +869,13 @@ SUBROUTINE surf_couple_extra( & 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, & + crop_vars%tl_1_day_av_use_gb, & + water_resources%priority_order, water_resources%conveyance_loss, & water_resources%demand_unmet, water_resources%gw_abstracted, & water_resources%gw_avail, water_resources%gw_nr_abstracted, & - crop_vars%irrig_water_gb, & - water_resources%abstracted_minor_res, & + crop_vars%irrig_water_gb, water_resources%abstracted_minor_res, & water_resources%abstracted_minor_res_global, & + water_resources%abstracted_river, & water_resources%net_abstracted_river_global, & water_resources%sw_abstracted, water_resources%sw_avail_total, & water_resources%water_removed ) diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 0dced7e0..24d030cd 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -115,11 +115,12 @@ SUBROUTINE water_resources_control( global_land_pts, & 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, & + tl_1_day_av_use_gb, & + priority_order, conveyance_loss, demand_unmet, gw_abstracted, & gw_avail_start, gw_nr_abstracted, & irrig_water_gb, abstracted_minor_res, abstracted_minor_res_global,& - net_abstracted_river_global, sw_abstracted, sw_avail_total, & - water_removed ) + abstracted_river, net_abstracted_river_global, sw_abstracted, & + sw_avail_total, water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -298,6 +299,8 @@ SUBROUTINE water_resources_control( global_land_pts, & ! Diagnostics and coupling variables. REAL(KIND=real_jlslsm), INTENT(OUT) :: & + 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), & @@ -316,9 +319,11 @@ SUBROUTINE water_resources_control( global_land_pts, & ! This is used to couple to minor reservoirs. ! Note that this has reduced size if it is not required. !cxyz Perhaps don't specify size? + abstracted_river(land_pts), & + ! Water abstracted from rivers (kg). Diagnostic only. net_abstracted_river_global(global_land_pts), & ! Net abstraction from river, on global land points (kg m-2). - !cxy size OK, as above? + !cxyz size OK, as above? sw_abstracted(land_pts,n_sw_source), & ! Water that is abstracted from surface waters (kg). sw_avail_total(land_pts), & @@ -351,8 +356,6 @@ SUBROUTINE water_resources_control( global_land_pts, & ! 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 @@ -423,12 +426,16 @@ SUBROUTINE water_resources_control( global_land_pts, & 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). @@ -550,7 +557,7 @@ SUBROUTINE water_resources_control( global_land_pts, & !-------------------------------------------------------------------------- ! Calculate the net abstraction from rivers. - !-------------------------------------------------------------------------- + !------------<-------------------------------------------------------------- IF ( sw_river_source > 0 ) THEN CALL calc_river_flux( global_land_pts, grid_area_global, & return_flow_sw_global, & @@ -566,10 +573,10 @@ SUBROUTINE water_resources_control( global_land_pts, & ! There are no prognostic variables to be scattered. !---------------------------------------------------------------------------- CALL scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & - abstracted_minor_res, & - 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_sw, sfc_water_frac, supply_irrig, & + sw_abstracted, sw_avail_total, water_removed ) !---------------------------------------------------------------------------- ! Deallocate global arrays. @@ -1169,7 +1176,7 @@ END SUBROUTINE gather_global_water !############################################################################## SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & - abstracted_minor_res, & + 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 ) @@ -1185,7 +1192,8 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & USE jules_water_resources_mod, ONLY: l_have_groundwater, l_have_surface_water, & l_water_irrigation, n_sw_source, nwater_use, & - partition_calc_from_stores, partition_method, sw_minor_res_source + partition_calc_from_stores, partition_method, sw_minor_res_source, & + sw_river_source USE model_grid_mod, ONLY: global_land_pts @@ -1207,6 +1215,8 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & ! 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), & @@ -1271,6 +1281,12 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & abstracted_minor_res ) END IF + ! Save diagnostic of abstraction from rivers. + IF ( l_minor_reservoirs ) THEN + CALL scatter_land_field( sw_abstracted_global(:,sw_river_source), & + abstracted_river ) + END IF + END IF ! l_have_surface_water ! Fields for irrigation. diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index e34cb0aa..d1ce3aa8 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -80,10 +80,13 @@ MODULE water_resources_vars_mod net_abstracted_river_global(:), & ! Net abstraction from river, on global land points (kg m-2). !-------------------------------------------------------------------------- - ! Diagnostics (also used internally). !cxyz rephrase to emphaise internal + ! Internal/work variables (some of which are also used as diagnostics). ! All abstractions are gross fluxes (not net of returns) unless stated ! otherwise. + ! cxyz check if any just diagnostic !-------------------------------------------------------------------------- + conveyance_loss(:), & + ! Water that is lost during conveyance (kg). demand_accum(:,:), & ! Demands for water accumulated over the water resource timestep (kg). ! These include allowance for any conveyance loss. @@ -103,14 +106,16 @@ MODULE water_resources_vars_mod sw_avail_total(:), & ! Surface water that is available for abstraction at start of timestep, ! summed over sources (kg). - water_removed(:), & - ! Water that is removed from the system during use, e.g. incorporated - ! into manufactured goods (kg). !cxyz diag? !-------------------------------------------------------------------------- - ! Diagnosstics (not also used internally). + ! Diagnostics (not also used internally). !-------------------------------------------------------------------------- - abstracted_minor_res(:) - ! Water abstracted from minor reservoirs (kg). + abstracted_minor_res(:), & + ! Water abstracted from minor reservoirs (kg). + abstracted_river(:), & + ! Water abstracted from rivers (kg). + water_removed(:) + ! Water that is removed from the system during use, e.g. incorporated + ! into manufactured goods (kg). END TYPE @@ -127,6 +132,7 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: demand_rate_transfers(:) REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res_global(:) REAL(KIND=real_jlslsm), POINTER :: net_abstracted_river_global(:) + REAL(KIND=real_jlslsm), POINTER :: conveyance_loss(:) REAL(KIND=real_jlslsm), POINTER :: demand_accum(:,:) REAL(KIND=real_jlslsm), POINTER :: demand_unmet(:,:) REAL(KIND=real_jlslsm), POINTER :: gw_abstracted(:) @@ -134,8 +140,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 :: water_removed(:) REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res(:) + REAL(KIND=real_jlslsm), POINTER :: abstracted_river(:) + REAL(KIND=real_jlslsm), POINTER :: water_removed(:) END TYPE @@ -205,8 +212,8 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! Local variables !------------------------------------------------------------------------------ INTEGER :: & - global_land_pts_minor_res, global_land_pts_sw_rivers, land_pts_dim, & - land_pts_gw, land_pts_minor_res, land_pts_sw, land_pts_sw_rivers, & + 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. @@ -228,9 +235,10 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! Set default sizes that are used if water resources (or a particular part of ! the parameterisation) are not selected. global_land_pts_minor_res = 1 -global_land_pts_sw_rivers = 1 +global_land_pts_rivers = 1 land_pts_dim = 1 land_pts_gw = 1 +land_pts_rivers = 1 land_pts_sw = 1 n_sw_source_dim = 1 nwater_use_dim = 1 @@ -245,9 +253,9 @@ SUBROUTINE water_resources_alloc( global_land_pts, & land_pts_sw = land_pts END IF IF ( sw_river_source > 0 ) THEN - !XXland_pts_sw_rivers = land_pts !cxyz do we want a diagnostic? + land_pts_rivers = land_pts !cxyz Only full size on master. - global_land_pts_sw_rivers = global_land_pts + global_land_pts_rivers = global_land_pts END IF IF ( l_minor_reservoirs ) THEN land_pts_minor_res = land_pts @@ -316,14 +324,14 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! and river codes operate globally. !----------------------------------------------------------------------------- ALLOCATE( water_resources_data & - %net_abstracted_river_global(global_land_pts_sw_rivers) ) + %net_abstracted_river_global(global_land_pts_rivers) ) !----------------------------------------------------------------------------- ! Other variables. !----------------------------------------------------------------------------- +ALLOCATE( water_resources_data%conveyance_loss(land_pts_dim) ) 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) ) @@ -331,8 +339,10 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! 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) ) -! Diagnstics. +! 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%water_removed(land_pts_dim) ) !----------------------------------------------------------------------------- ! Initialise arrays. @@ -346,15 +356,17 @@ SUBROUTINE water_resources_alloc( global_land_pts, & water_resources_data%demand_rate_transfers(:) = 0.0 water_resources_data%abstracted_minor_res_global(:) = 0.0 water_resources_data%net_abstracted_river_global(:) = 0.0 +water_resources_data%conveyance_loss(:) = 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%water_removed(:) = 0.0 IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -400,15 +412,17 @@ SUBROUTINE water_resources_dealloc(water_resources_data) DEALLOCATE( water_resources_data%demand_rate_transfers ) DEALLOCATE( water_resources_data%abstracted_minor_res_global ) DEALLOCATE( water_resources_data%net_abstracted_river_global ) +DEALLOCATE( water_resources_data%conveyance_loss ) DEALLOCATE( water_resources_data%demand_accum ) DEALLOCATE( water_resources_data%demand_unmet ) -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%sw_avail_total ) DEALLOCATE( water_resources_data%abstracted_minor_res ) +DEALLOCATE( water_resources_data%abstracted_river ) +DEALLOCATE( water_resources_data%water_removed ) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -470,15 +484,17 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) water_resources%net_abstracted_river_global & => water_resources_data%net_abstracted_river_global water_resources%demand_accum => water_resources_data%demand_accum +water_resources%conveyance_loss => water_resources_data%conveyance_loss 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_data%abstracted_minor_res +water_resources%abstracted_river => water_resources_data%abstracted_river +water_resources%water_removed => water_resources_data%water_removed IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -520,15 +536,17 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%demand_rate_transfers ) NULLIFY( water_resources%abstracted_minor_res_global ) NULLIFY( water_resources%net_abstracted_river_global ) +NULLIFY( water_resources%conveyance_loss ) 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%water_removed ) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN diff --git a/src/initialisation/standalone/init_output_mod.F90 b/src/initialisation/standalone/init_output_mod.F90 index 07a5ebc1..915609f9 100644 --- a/src/initialisation/standalone/init_output_mod.F90 +++ b/src/initialisation/standalone/init_output_mod.F90 @@ -687,28 +687,11 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & !---------------------------------------------------------------------------- IF ( .NOT. l_minor_reservoirs ) THEN SELECT CASE ( var(j) ) - CASE ( 'minor_res_abstracted', 'minor_res_capacity', 'minor_res_frac', & - 'minor_res_storage' ) + CASE ( 'minor_res_capacity', 'minor_res_frac', 'minor_res_storage' ) remove_var = .TRUE. message = 'Minor reservoirs not used.' END SELECT - - ELSE - - ! l_minor_reservoirs = T - !-------------------------------------------------------------------------- - ! Variables that are only allowed with minor reservoirs in combination - ! with water resources. - !-------------------------------------------------------------------------- - IF ( .NOT. l_water_resources ) THEN - SELECT CASE ( var(j) ) - CASE ( 'minor_res_abstracted' ) - remove_var = .TRUE. - message = 'Minor reservoirs + water resources not used.' - END SELECT - END IF - - END IF ! l_minor_reservoirs + END IF !--------------------------------------------------------------------------- ! Thermal acclimation variables. @@ -727,8 +710,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', & - 'water_removed' ) + 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 @@ -819,6 +802,22 @@ 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. .NOT. l_rivers ) THEN + SELECT CASE ( var(j) ) + CASE ( 'river_abstracted' ) + remove_var = .TRUE. + message = 'Water resources + rivers not used.' + END SELECT + END IF + !--------------------------------------------------------------------------- ! Variables that are only allowed with atmospheric deposition !--------------------------------------------------------------------------- diff --git a/src/io/model_interface/extract_var.inc b/src/io/model_interface/extract_var.inc index 52ff8505..a08e85b6 100644 --- a/src/io/model_interface/extract_var.inc +++ b/src/io/model_interface/extract_var.inc @@ -3324,6 +3324,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) @@ -3431,6 +3436,11 @@ CASE ( 'minor_res_abstracted' ) 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 b4e25f45..c60dca20 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 = 728 +INTEGER, PARAMETER :: n_vars = 730 TYPE(var_metadata) :: metadata(n_vars) ! Include the metadata DATA statement diff --git a/src/io/model_interface/variable_metadata.inc b/src/io/model_interface/variable_metadata.inc index 55f6c463..1bb1ef31 100644 --- a/src/io/model_interface/variable_metadata.inc +++ b/src/io/model_interface/variable_metadata.inc @@ -9355,9 +9355,22 @@ DATA metadata(722) / var_metadata( & "kg s-1" & ) / !----------------------------------------------------------------------------- -! Metadata for minor_res_capacity_grid +! Metadata for conveyance_loss !----------------------------------------------------------------------------- DATA metadata(723) / 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(724) / var_metadata( & ! String identifier 'minor_res_capacity_grid', & ! Variable type @@ -9369,7 +9382,7 @@ DATA metadata(723) / var_metadata( & !----------------------------------------------------------------------------- ! Metadata for minor_res_frac_grid !----------------------------------------------------------------------------- -DATA metadata(724) / var_metadata( & +DATA metadata(725) / var_metadata( & ! String identifier 'minor_res_frac_grid', & ! Variable type @@ -9381,7 +9394,7 @@ DATA metadata(724) / var_metadata( & !----------------------------------------------------------------------------- ! Metadata for minor_res_capacity !----------------------------------------------------------------------------- -DATA metadata(725) / var_metadata( & +DATA metadata(726) / var_metadata( & ! String identifier 'minor_res_capacity', & ! Variable type @@ -9394,7 +9407,7 @@ DATA metadata(725) / var_metadata( & !----------------------------------------------------------------------------- ! Metadata for minor_res_frac !----------------------------------------------------------------------------- -DATA metadata(726) / var_metadata( & +DATA metadata(727) / var_metadata( & ! String identifier 'minor_res_frac', & ! Variable type @@ -9407,7 +9420,7 @@ DATA metadata(726) / var_metadata( & !----------------------------------------------------------------------------- ! Metadata for minor_res_storage !----------------------------------------------------------------------------- -DATA metadata(727) / var_metadata( & +DATA metadata(728) / var_metadata( & ! String identifier 'minor_res_storage', & ! Variable type @@ -9420,7 +9433,7 @@ DATA metadata(727) / var_metadata( & !----------------------------------------------------------------------------- ! Metadata for minor_res_abstracted !----------------------------------------------------------------------------- -DATA metadata(728) / var_metadata( & +DATA metadata(729) / var_metadata( & ! String identifier 'minor_res_abstracted', & ! Variable type @@ -9430,4 +9443,17 @@ DATA metadata(728) / var_metadata( & ! Units "kg s-1" & ) / +!----------------------------------------------------------------------------- +! Metadata for river_abstracted +!----------------------------------------------------------------------------- +DATA metadata(730) / var_metadata( & +! String identifier + 'river_abstracted', & +! Variable type + var_type_surface, & +! Long name + "Water abstracted from rivers", & +! Units + "kg s-1" & + ) / #endif From dddcc0bca45ed5c9f5d781b130e7d50772624341 Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Fri, 12 Jun 2026 16:23:18 +0100 Subject: [PATCH 07/24] Tidying and clarifying. --- src/control/rivers-standalone/control_mod.F90 | 2 +- src/control/shared/surf_couple_extra_mod.F90 | 14 +-- src/control/shared/surf_couple_rivers_mod.F90 | 11 +-- .../shared/water_resources_control_mod.F90 | 55 +++++++----- .../shared/water_resources_vars_mod.F90 | 85 ++++++++++--------- .../shared/allocate_jules_arrays.F90 | 18 ++-- .../ancillaries/jules_rivers_props_mod.F90 | 7 +- .../standalone/init_output_mod.F90 | 4 +- .../river_routing/rivers_route_mod.F90 | 1 - .../route_minor_reservoirs_mod.F90 | 11 ++- 10 files changed, 116 insertions(+), 92 deletions(-) diff --git a/src/control/rivers-standalone/control_mod.F90 b/src/control/rivers-standalone/control_mod.F90 index 790e9071..10e9a056 100644 --- a/src/control/rivers-standalone/control_mod.F90 +++ b/src/control/rivers-standalone/control_mod.F90 @@ -121,7 +121,7 @@ SUBROUTINE control ( & flowin(row_length, rows), & bflowin(row_length, rows), & twatstor(river_row_length, river_rows), & -!cxyz Sizes not done yet. +!cxyz Do we need global_landpts here? abstracted_minor_res_global(land_pts), & ! Water abstracted from minor reservoirs (kg). net_abstracted_river_global(land_pts), & diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index ab104372..5d6c7c3b 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -870,15 +870,15 @@ SUBROUTINE surf_couple_extra( & 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%conveyance_loss, & - water_resources%demand_unmet, water_resources%gw_abstracted, & - water_resources%gw_avail, water_resources%gw_nr_abstracted, & - crop_vars%irrig_water_gb, water_resources%abstracted_minor_res, & + water_resources%priority_order, & water_resources%abstracted_minor_res_global, & - water_resources%abstracted_river, & water_resources%net_abstracted_river_global, & - water_resources%sw_abstracted, water_resources%sw_avail_total, & - water_resources%water_removed ) + 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 diff --git a/src/control/shared/surf_couple_rivers_mod.F90 b/src/control/shared/surf_couple_rivers_mod.F90 index e58b19b1..2955c930 100644 --- a/src/control/shared/surf_couple_rivers_mod.F90 +++ b/src/control/shared/surf_couple_rivers_mod.F90 @@ -567,10 +567,10 @@ SUBROUTINE surf_couple_rivers( & ALLOCATE(global_sea_level(tmp_land_size), STAT = ERROR) error_sum = error_sum + ERROR -!cxyz ! 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. @@ -578,7 +578,6 @@ SUBROUTINE surf_couple_rivers( & END IF ALLOCATE(net_abstracted_river_rp(tmp_river_size), STAT = ERROR) error_sum = error_sum + ERROR - !cxyz do we need to initalise as below for minor res? ! Allocate abstraction from minor reservoirs. IF ( .NOT. l_oasis_rivers .AND. l_minor_reservoirs & @@ -596,10 +595,12 @@ SUBROUTINE surf_couple_rivers( & CALL ereport( RoutineName, errorstatus, & "Error related to allocation of abstraction variables." ) ELSE - ! Initialise abstraction to zero - this value is passed to - ! subroutine rivers_route_rp and used if l_minor_reservoirs=T but - ! l_water_resources=F. + ! 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 !-------------------------------------------------------------------------- diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 24d030cd..b3a2434e 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -116,10 +116,10 @@ SUBROUTINE water_resources_control( global_land_pts, & sthu_irr_soilt, sthu_soilt, & sthzw_soilt, sub_surf_roff, tl_1_day_av_gb, & tl_1_day_av_use_gb, & - priority_order, conveyance_loss, demand_unmet, gw_abstracted, & - gw_avail_start, gw_nr_abstracted, & - irrig_water_gb, abstracted_minor_res, abstracted_minor_res_global,& - abstracted_river, net_abstracted_river_global, sw_abstracted, & + 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 ) !------------------------------------------------------------------------------ @@ -297,33 +297,42 @@ SUBROUTINE water_resources_control( global_land_pts, & ! 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. + !cxyz Perhaps don't specify size? + 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). - abstracted_minor_res(land_pts), & - ! Water abstracted from minor reservoirs (kg). Diagnostic only. - !cxyz Perhaps don't specify size? - 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. - !cxyz Perhaps don't specify size? - abstracted_river(land_pts), & - ! Water abstracted from rivers (kg). Diagnostic only. - net_abstracted_river_global(global_land_pts), & - ! Net abstraction from river, on global land points (kg m-2). - !cxyz size OK, as above? sw_abstracted(land_pts,n_sw_source), & ! Water that is abstracted from surface waters (kg). sw_avail_total(land_pts), & @@ -421,7 +430,7 @@ SUBROUTINE water_resources_control( global_land_pts, & IF ( sw_river_source > 0 ) THEN net_abstracted_river_global(:) = 0.0 END IF -! Initialise abstractions. cxyz Always allocated at full size? +! Initialise abstractions. gw_abstracted(:) = 0.0 gw_nr_abstracted(:) = 0.0 sw_abstracted(:,:) = 0.0 diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index d1ce3aa8..149c6684 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -76,17 +76,14 @@ MODULE water_resources_vars_mod ! Fluxes for coupling. !-------------------------------------------------------------------------- abstracted_minor_res_global(:), & - ! Water abstracted from minor reservoirs, on global land points (kg). + ! 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). !-------------------------------------------------------------------------- ! Internal/work variables (some of which are also used as diagnostics). ! All abstractions are gross fluxes (not net of returns) unless stated ! otherwise. - ! cxyz check if any just diagnostic !-------------------------------------------------------------------------- - conveyance_loss(:), & - ! Water that is lost during conveyance (kg). demand_accum(:,:), & ! Demands for water accumulated over the water resource timestep (kg). ! These include allowance for any conveyance loss. @@ -95,7 +92,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. @@ -107,12 +106,14 @@ MODULE water_resources_vars_mod ! Surface water that is available for abstraction at start of timestep, ! summed over sources (kg). !-------------------------------------------------------------------------- - ! Diagnostics (not also used internally). + ! 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). @@ -132,7 +133,6 @@ MODULE water_resources_vars_mod REAL(KIND=real_jlslsm), POINTER :: demand_rate_transfers(:) REAL(KIND=real_jlslsm), POINTER :: abstracted_minor_res_global(:) REAL(KIND=real_jlslsm), POINTER :: net_abstracted_river_global(:) - REAL(KIND=real_jlslsm), POINTER :: conveyance_loss(:) REAL(KIND=real_jlslsm), POINTER :: demand_accum(:,:) REAL(KIND=real_jlslsm), POINTER :: demand_unmet(:,:) REAL(KIND=real_jlslsm), POINTER :: gw_abstracted(:) @@ -142,6 +142,7 @@ MODULE water_resources_vars_mod 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 @@ -154,12 +155,12 @@ MODULE water_resources_vars_mod !############################################################################## -SUBROUTINE water_resources_alloc( global_land_pts, & - land_pts, n_sw_source, nwater_use, & - sw_river_source, l_have_groundwater, l_have_surface_water, & - l_minor_reservoirs, l_water_domestic, l_water_industry, & - l_water_irrigation, l_water_livestock, l_water_resources, & - l_water_transfers, water_resources_data ) +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 ) !No USE statements other than Dr Hook USE parkind1, ONLY: jprb, jpim @@ -188,6 +189,8 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! non-renewable). l_have_surface_water, & ! Flag indicating if we have surface water represented (e.g. rivers). + l_is_master_task, & + ! Flag indicating if this call is from the master task. l_minor_reservoirs, & ! Switch for minor_reservoirs. l_water_domestic, & @@ -254,13 +257,17 @@ SUBROUTINE water_resources_alloc( global_land_pts, & END IF IF ( sw_river_source > 0 ) THEN land_pts_rivers = land_pts -!cxyz Only full size on master. - global_land_pts_rivers = global_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 -!cxyz Only full size on master. - global_land_pts_minor_res = global_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 @@ -329,7 +336,6 @@ SUBROUTINE water_resources_alloc( global_land_pts, & !----------------------------------------------------------------------------- ! Other variables. !----------------------------------------------------------------------------- -ALLOCATE( water_resources_data%conveyance_loss(land_pts_dim) ) ALLOCATE( water_resources_data%demand_accum(land_pts_dim,nwater_use_dim) ) ALLOCATE( water_resources_data%demand_unmet(land_pts_dim,nwater_use_dim) ) ! Groundwater variables. @@ -342,6 +348,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, & ! 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) ) !----------------------------------------------------------------------------- @@ -356,7 +363,6 @@ SUBROUTINE water_resources_alloc( global_land_pts, & water_resources_data%demand_rate_transfers(:) = 0.0 water_resources_data%abstracted_minor_res_global(:) = 0.0 water_resources_data%net_abstracted_river_global(:) = 0.0 -water_resources_data%conveyance_loss(:) = 0.0 water_resources_data%demand_accum(:,:) = 0.0 water_resources_data%demand_unmet(:,:) = 0.0 water_resources_data%gw_abstracted(:) = 0.0 @@ -366,6 +372,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, & 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) @@ -402,27 +409,27 @@ SUBROUTINE water_resources_dealloc(water_resources_data) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) -!cxyz Should deallocate in reverse order. -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%abstracted_minor_res_global ) -DEALLOCATE( water_resources_data%net_abstracted_river_global ) +! Deallocate in reverse order to allocation. +DEALLOCATE( water_resources_data%water_removed ) DEALLOCATE( water_resources_data%conveyance_loss ) -DEALLOCATE( water_resources_data%demand_accum ) +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%gw_avail ) -DEALLOCATE( water_resources_data%gw_nr_abstracted ) -DEALLOCATE( water_resources_data%sw_abstracted ) -DEALLOCATE( water_resources_data%sw_avail_total ) -DEALLOCATE( water_resources_data%abstracted_minor_res ) -DEALLOCATE( water_resources_data%abstracted_river ) -DEALLOCATE( water_resources_data%water_removed ) +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 @@ -484,7 +491,6 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) water_resources%net_abstracted_river_global & => water_resources_data%net_abstracted_river_global water_resources%demand_accum => water_resources_data%demand_accum -water_resources%conveyance_loss => water_resources_data%conveyance_loss water_resources%demand_unmet => water_resources_data%demand_unmet water_resources%gw_abstracted => water_resources_data%gw_abstracted water_resources%gw_avail => water_resources_data%gw_avail @@ -494,6 +500,7 @@ SUBROUTINE water_resources_assoc(water_resources,water_resources_data) 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) @@ -536,7 +543,6 @@ SUBROUTINE water_resources_nullify(water_resources) NULLIFY( water_resources%demand_rate_transfers ) NULLIFY( water_resources%abstracted_minor_res_global ) NULLIFY( water_resources%net_abstracted_river_global ) -NULLIFY( water_resources%conveyance_loss ) NULLIFY( water_resources%demand_accum ) NULLIFY( water_resources%demand_unmet ) NULLIFY( water_resources%gw_abstracted ) @@ -546,6 +552,7 @@ SUBROUTINE water_resources_nullify(water_resources) 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) diff --git a/src/initialisation/shared/allocate_jules_arrays.F90 b/src/initialisation/shared/allocate_jules_arrays.F90 index f27a5043..32e5e4ea 100644 --- a/src/initialisation/shared/allocate_jules_arrays.F90 +++ b/src/initialisation/shared/allocate_jules_arrays.F90 @@ -148,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 @@ -297,14 +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( global_land_pts, & - land_pts, n_sw_source, nwater_use, sw_river_source,& - l_have_groundwater, l_have_surface_water, & - l_minor_reservoirs, l_water_domestic, & - l_water_industry, & - l_water_irrigation, l_water_livestock, & - l_water_resources, l_water_transfers, & - water_resources_data ) +CALL water_resources_alloc( global_land_pts, land_pts, n_sw_source, & + nwater_use, sw_river_source, l_have_groundwater, & + l_have_surface_water, is_master_task(), & + l_minor_reservoirs, & + l_water_domestic, l_water_industry, & + 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/jules_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 index 535b2cce..ebb8d009 100644 --- a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 @@ -973,7 +973,6 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) ! Initialise CaMa-Flood array values ! CaMa-Flood ancillary variables. -!cxyz Note not zero despite message in required_vars_for_rivers (out of scope!). rivers_data%channel_depth(:) = rmdi rivers_data%channel_width(:) = rmdi rivers_data%river_distance(:) = rmdi @@ -1025,11 +1024,10 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) rivers_data%minor_res_capacity(:) = rmdi rivers_data%minor_res_frac(:) = rmdi rivers_data%minor_res_storage(:) = 0.0 -!cxyz initialise coupling to zero or handled elsewhere? -rivers_data%tot_abstracted_minor_res_global(:) = 0.0 ! Initialise further variables to couple to water resources. -rivers_data%tot_net_abstracted_river_global(:) = 0.0 +rivers_data%tot_abstracted_minor_res_global(:) = rmdi +rivers_data%tot_net_abstracted_river_global(:) = rmdi !------------------------------------------------------------------------------ ! Associate pointers @@ -1118,7 +1116,6 @@ SUBROUTINE deallocate_river_props( ) !------------------------------------------------------------------------------ ! Description: ! Deallocate river variables that are not needed any further. -!cxyz Ideally in reverse order... !------------------------------------------------------------------------------ USE jules_rivers_mod, ONLY: & diff --git a/src/initialisation/standalone/init_output_mod.F90 b/src/initialisation/standalone/init_output_mod.F90 index 915609f9..0691d4d0 100644 --- a/src/initialisation/standalone/init_output_mod.F90 +++ b/src/initialisation/standalone/init_output_mod.F90 @@ -719,8 +719,8 @@ 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', 'unmet_domestic' ) diff --git a/src/science/river_routing/rivers_route_mod.F90 b/src/science/river_routing/rivers_route_mod.F90 index 6d2b4ed3..bdb0aebe 100644 --- a/src/science/river_routing/rivers_route_mod.F90 +++ b/src/science/river_routing/rivers_route_mod.F90 @@ -123,7 +123,6 @@ SUBROUTINE rivers_route_rp( abstracted_minor_res_rp, net_abstracted_river_rp, & ! surface runoff variable becomes a more generic source/sink term for rivers. ! The resulting term can be negative. !------------------------------------------------------------------------------ -!cxyz Do we need to test both? That IS clearer. IF ( l_water_resources .AND. sw_river_source > 0 ) THEN ! Calculate reciprocal of timestep length. recip_timestep = 1.0 / ( REAL(nstep_rivers) * timestep ) diff --git a/src/science/river_routing/route_minor_reservoirs_mod.F90 b/src/science/river_routing/route_minor_reservoirs_mod.F90 index 09b8c637..8d8a0312 100644 --- a/src/science/river_routing/route_minor_reservoirs_mod.F90 +++ b/src/science/river_routing/route_minor_reservoirs_mod.F90 @@ -1,4 +1,13 @@ -!cxyz add header +!******************************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 From 6acd700bd88f4a180d11135c085773e01e23a9ce Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Fri, 19 Jun 2026 16:32:08 +0100 Subject: [PATCH 08/24] Corrected checks around requirements for return flows. return_flow_sw now called return_flow_river for clarity. --- src/control/rivers-standalone/control_mod.F90 | 1 - .../shared/jules_water_resources_mod.F90 | 28 +------ .../shared/water_resources_control_mod.F90 | 54 +++++++------- .../shared/water_resources_vars_mod.F90 | 31 ++++---- .../standalone/init_output_mod.F90 | 8 +- .../water_resources/update_soil_water_mod.F90 | 2 +- .../water_resources/water_resources_drive.F90 | 73 ++++++++++--------- 7 files changed, 93 insertions(+), 104 deletions(-) diff --git a/src/control/rivers-standalone/control_mod.F90 b/src/control/rivers-standalone/control_mod.F90 index 10e9a056..15807d30 100644 --- a/src/control/rivers-standalone/control_mod.F90 +++ b/src/control/rivers-standalone/control_mod.F90 @@ -121,7 +121,6 @@ SUBROUTINE control ( & flowin(row_length, rows), & bflowin(row_length, rows), & twatstor(river_row_length, river_rows), & -!cxyz Do we need global_landpts here? abstracted_minor_res_global(land_pts), & ! Water abstracted from minor reservoirs (kg). net_abstracted_river_global(land_pts), & diff --git a/src/control/shared/jules_water_resources_mod.F90 b/src/control/shared/jules_water_resources_mod.F90 index cea06d57..9379a1bd 100644 --- a/src/control/shared/jules_water_resources_mod.F90 +++ b/src/control/shared/jules_water_resources_mod.F90 @@ -207,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 @@ -551,26 +551,6 @@ SUBROUTINE check_jules_water_resources( l_top ) END IF ! l_have_surface_water .AND. l_have_groundwater - ! If any water use would potentially include return flow to rivers (as coded - ! in SUBROUTINE calc_return_flow), check that rivers are modelled. - ! The domestic and industrial uses return water to rivers in preference to - ! groundwater, while the livestock use returns water to groundwater in - ! preference to rivers; in all cases we need either rivers or groundwater. - ! Note that by testing on l_rivers rather than l_have_surface_water we cater - ! for a potential future extension in which we might have rivers (l_rivers=T) - ! that are not used as a water source (likely as part of a counter-factual - ! experiment). - IF ( .NOT. l_have_groundwater .AND. .NOT. l_rivers ) THEN - ! We have neither groundwater nor rivers. - ! Check if a return flow would potentially go to rivers. - IF ( use_domestic > 0 .OR. use_industry > 0 .OR. use_livestock > 0 ) THEN - ! This would potentially return to rivers. - error_status = 101 ! a fatal error - CALL ereport ( RoutineName, error_status, & - "Rivers must be included to allow return flow." ) - END IF - END IF - END IF ! l_water_resources END SUBROUTINE check_jules_water_resources @@ -649,7 +629,7 @@ SUBROUTINE set_jules_water_resources( l_top ) !---------------------------------------------------------------------------- ! Set index for each available surface water source to show position in - ! surface water arrays. + ! surface water arrays. If a source exists, it is used. !---------------------------------------------------------------------------- ! Initialise as no surface water sources. n_sw_source = 0 diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index b3a2434e..b595590a 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -76,7 +76,7 @@ MODULE water_resources_control_mod ! 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). @@ -145,7 +145,7 @@ SUBROUTINE water_resources_control( global_land_pts, & USE jules_irrig_mod, ONLY: irr_crop_doell, irr_crop -USE jules_rivers_mod, ONLY: l_minor_reservoirs, l_rivers, np_rivers +USE jules_rivers_mod, ONLY: l_minor_reservoirs, np_rivers USE jules_soil_mod, ONLY: sm_levels @@ -322,7 +322,6 @@ SUBROUTINE water_resources_control( global_land_pts, & ! resources code. abstracted_minor_res(land_pts), & ! Water abstracted from minor reservoirs (kg). Diagnostic only. - !cxyz Perhaps don't specify size? abstracted_river(land_pts), & ! Water abstracted from rivers (kg). Diagnostic only. conveyance_loss(land_pts), & @@ -381,7 +380,7 @@ SUBROUTINE water_resources_control( global_land_pts, & ! 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). supply_irrig(land_pts) ! Water supplied for irrigation (kg). @@ -556,7 +555,7 @@ SUBROUTINE water_resources_control( global_land_pts, & 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 @@ -569,7 +568,7 @@ SUBROUTINE water_resources_control( global_land_pts, & !------------<-------------------------------------------------------------- IF ( sw_river_source > 0 ) THEN CALL calc_river_flux( global_land_pts, grid_area_global, & - return_flow_sw_global, & + return_flow_river_global, & sw_abstracted_global(:,sw_river_source), & net_abstracted_river_global ) END IF @@ -584,7 +583,7 @@ SUBROUTINE water_resources_control( global_land_pts, & CALL 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, & + return_flow_river, sfc_water_frac, supply_irrig, & sw_abstracted, sw_avail_total, water_removed ) !---------------------------------------------------------------------------- @@ -1001,11 +1000,11 @@ SUBROUTINE allocate_global_water( l_allocate ) ALLOCATE(river_storage_global(land_size_rivers), STAT = ERROR) error_sum = error_sum + ERROR - ! Both SW and GW return flows are needed at full size, even if either - ! source is not active. + ! 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 @@ -1026,7 +1025,6 @@ SUBROUTINE allocate_global_water( l_allocate ) ALLOCATE(water_removed_global(land_size), STAT = ERROR) error_sum = error_sum + ERROR - !cxyz Using river size - which I think is OK. ALLOCATE(grid_area_global(land_size_rivers), STAT = ERROR) error_sum = error_sum + ERROR @@ -1042,7 +1040,7 @@ SUBROUTINE allocate_global_water( l_allocate ) 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 @@ -1074,7 +1072,9 @@ SUBROUTINE allocate_global_water( l_allocate ) 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) @@ -1187,8 +1187,9 @@ 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: @@ -1197,7 +1198,7 @@ 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 +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, & @@ -1228,7 +1229,7 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & ! 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. @@ -1264,9 +1265,15 @@ 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 @@ -1276,9 +1283,6 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & CALL scatter_land_field( sfc_water_frac_global, sfc_water_frac ) END IF - ! Surface water always includes rivers, so we always calculate return flow. - !cxyz No longer true. - 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 @@ -1291,7 +1295,7 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & END IF ! Save diagnostic of abstraction from rivers. - IF ( l_minor_reservoirs ) THEN + IF ( sw_river_source > 0 ) THEN CALL scatter_land_field( sw_abstracted_global(:,sw_river_source), & abstracted_river ) END IF @@ -1440,7 +1444,7 @@ END SUBROUTINE regrid_to_land !############################################################################## SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & - return_flow_sw_global, & + return_flow_river_global, & sw_abstracted_river_global, & net_abstracted_river_global ) @@ -1464,7 +1468,7 @@ SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & REAL(KIND=real_jlslsm), INTENT(IN) :: & grid_area_global(global_land_pts), & ! Area of gridbox (m2). - return_flow_sw_global(global_land_pts), & + return_flow_river_global(global_land_pts), & ! Water that is returned to surface waters after use (kg). sw_abstracted_river_global(global_land_pts) ! Water abstracted from river (kg). @@ -1488,7 +1492,7 @@ SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & ! Calculate net abstraction and change units from kg to kg m-2. DO l=1,global_land_pts net_abstracted_river_global(l) = ( sw_abstracted_river_global(l) & - - return_flow_sw_global(l) ) & + - return_flow_river_global(l) ) & / grid_area_global(l) END DO diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index 149c6684..7add2ff2 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -9,8 +9,7 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** -!cxyz Note annoying variations of line length for "-----". -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! Description: ! Contains variables and field types for water resource modelling. ! @@ -19,7 +18,7 @@ ! ! Code Description: ! Language: Fortran 90. -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ MODULE water_resources_vars_mod @@ -231,10 +230,10 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & 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. global_land_pts_minor_res = 1 @@ -276,19 +275,19 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & !----------------------------------------------------------------------------- ALLOCATE( water_resources_data%priority_order(land_pts_dim,nwater_use_dim) ) -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! 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 @@ -313,7 +312,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & ALLOCATE( water_resources_data%demand_rate_transfers(1) ) END IF -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! 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 @@ -324,18 +323,18 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & %abstracted_minor_res_global(global_land_pts_minor_res) ) print*,'Alloc size=',size( water_resources_data%abstracted_minor_res_global ) -!----------------------------------------------------------------------------- +!------------------------------------------------------------------------------ ! 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) ) ! Groundwater variables. @@ -351,9 +350,9 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & 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 diff --git a/src/initialisation/standalone/init_output_mod.F90 b/src/initialisation/standalone/init_output_mod.F90 index 0691d4d0..8a07265f 100644 --- a/src/initialisation/standalone/init_output_mod.F90 +++ b/src/initialisation/standalone/init_output_mod.F90 @@ -344,7 +344,8 @@ 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_minor_reservoirs, l_outflow_per_river, l_rivers, & l_riv_overbank, i_river_vn, rivers_camaflood, rivers_rfm, rivers_trip @@ -810,11 +811,12 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & END SELECT END IF - IF ( .NOT. l_water_resources .OR. .NOT. l_rivers ) THEN + 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 = 'Water resources + rivers not used.' + message = 'Rivers not used for abstractions.' END SELECT END IF 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 c2c68e01..6f05d773 100644 --- a/src/science/water_resources/water_resources_drive.F90 +++ b/src/science/water_resources/water_resources_drive.F90 @@ -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). @@ -232,7 +232,7 @@ SUBROUTINE water_resources_drive( global_land_pts, priority_order, & ! Calculate return flows. !------------------------------------------------------------------------------ CALL calc_return_flow( global_land_pts, abstracted_per_use, & - conveyance_loss_use, return_flow_gw, return_flow_sw, & + conveyance_loss_use, return_flow_gw, return_flow_river, & water_removed ) !------------------------------------------------------------------------------ @@ -585,7 +585,7 @@ END SUBROUTINE calc_conveyance_loss SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & conveyance_loss_use, return_flow_gw, & - return_flow_sw, water_removed ) + return_flow_river, water_removed ) !------------------------------------------------------------------------------ ! Description: @@ -626,7 +626,7 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & ! 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 @@ -648,7 +648,7 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_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. !------------------------------------------------------------------------------ @@ -666,53 +666,57 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_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; if the preferred sink - ! is not modelled the other is used. We know that at least one of l_rivers - ! and l_have_groundwater is TRUE when water resources are modelled. If the - ! only groundwater is "non-renewable", any groundwater return is instead - ! later added to runoff (not groundwater). + ! water to either groundwater or river water; if the preferred sink + ! is not modelled the other is used if available. If neither is available + ! the default is to add to the groundwater variable because later code will + ! divert that return flow to runoff. !--------------------------------------------------------------------------- IF ( i == use_domestic ) THEN ! Domestic water is returned to rivers, if those are modelled, otherwise to - ! groundwater. + ! groundwater (in which case there is no need to check whether groundwater + ! is included because the return flow will be added to runoff in that + ! configuration). IF ( l_rivers ) THEN - return_flow_frac_gw = 0.0 - return_flow_frac_sw = rf_domestic + return_flow_frac_gw = 0.0 + return_flow_frac_river = rf_domestic ELSE - return_flow_frac_gw = rf_domestic - return_flow_frac_sw = 0.0 + return_flow_frac_gw = rf_domestic + return_flow_frac_river = 0.0 END IF - removed_frac = 1.0 - rf_domestic + removed_frac = 1.0 - rf_domestic ELSE IF ( i == use_industry ) THEN ! Industrial water is returned to rivers, if those are modelled, otherwise ! to groundwater. IF ( l_rivers ) THEN - return_flow_frac_gw = 0.0 - return_flow_frac_sw = rf_industry + return_flow_frac_gw = 0.0 + return_flow_frac_river = rf_industry ELSE - return_flow_frac_gw = rf_industry - return_flow_frac_sw = 0.0 + return_flow_frac_gw = rf_industry + return_flow_frac_river = 0.0 END IF - removed_frac = 1.0 - rf_industry + removed_frac = 1.0 - rf_industry ELSE IF ( i == use_livestock ) THEN - ! Livestock water is returned to groundwater, if that is modelled, - ! otherwise to rivers. - IF ( l_have_groundwater ) THEN - return_flow_frac_gw = rf_livestock - return_flow_frac_sw = 0.0 + ! Livestock water is returned to groundwater, otherwise to + ! rivers. If neither is available we add to the groundwater return flow + ! which is later added to runoff. + IF ( l_have_groundwater & + .OR. ( .NOT. l_have_groundwater .AND. .NOT. l_rivers ) ) THEN + return_flow_frac_gw = rf_livestock + return_flow_frac_river = 0.0 ELSE - return_flow_frac_gw = 0.0 - return_flow_frac_sw = rf_livestock + ! No groundwater but rivers. + return_flow_frac_gw = 0.0 + return_flow_frac_river = rf_livestock END IF - removed_frac = 1.0 - rf_livestock + 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 @@ -732,7 +736,8 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & ! Add to totals. Both GW and SW return flows are always calculated, though ! either can be zero if those sources are not represented. 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 From 4fb2bd61bff6bbe867139fc8cd645c3e22c31ec2 Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Fri, 19 Jun 2026 17:06:13 +0100 Subject: [PATCH 09/24] Fix - minor_res_storage can now be read from a dump. --- src/io/dump/read_dump_mod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/io/dump/read_dump_mod.F90 b/src/io/dump/read_dump_mod.F90 index fa78cbb2..1f1eea38 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' ) From 68db6847806900b7c974d759cfb9b07d746bd391 Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Fri, 19 Jun 2026 17:34:26 +0100 Subject: [PATCH 10/24] Tidying. --- src/control/shared/jules_rivers_mod.F90 | 8 ++++---- src/control/shared/surf_couple_rivers_mod.F90 | 2 +- src/control/shared/water_resources_control_mod.F90 | 8 ++++---- src/control/shared/water_resources_vars_mod.F90 | 2 -- .../ancillaries/init_rivers_process_data_mod.F90 | 9 --------- .../standalone/ancillaries/jules_rivers_props_mod.F90 | 2 +- src/science/river_routing/route_minor_reservoirs_mod.F90 | 2 -- 7 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/control/shared/jules_rivers_mod.F90 b/src/control/shared/jules_rivers_mod.F90 index 32b4dd7e..bc04119e 100644 --- a/src/control/shared/jules_rivers_mod.F90 +++ b/src/control/shared/jules_rivers_mod.F90 @@ -126,8 +126,8 @@ MODULE jules_rivers_mod ! Control rerouting of inland basin water ,l_minor_reservoirs = .FALSE. & ! Switch for minor_reservoirs. - ! .TRUE. = consider minor reservoirs - ! .FALSE. = do not consider 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. & @@ -711,9 +711,9 @@ SUBROUTINE jules_rivers_alloc(land_pts, t_i_length, t_j_length, & !Arguments INTEGER, INTENT(IN) :: land_pts, t_i_length, t_j_length -INTEGER, INTENT(in) :: sw_river_source +INTEGER, INTENT(IN) :: sw_river_source ! Index of river water in surface water source arrays. -LOGICAL, INTENT(in) :: l_water_resources +LOGICAL, INTENT(IN) :: l_water_resources ! Switch to select water resource management modelling. TYPE(rivers_data_type), INTENT(IN OUT) :: rivers_data diff --git a/src/control/shared/surf_couple_rivers_mod.F90 b/src/control/shared/surf_couple_rivers_mod.F90 index 2955c930..793218a8 100644 --- a/src/control/shared/surf_couple_rivers_mod.F90 +++ b/src/control/shared/surf_couple_rivers_mod.F90 @@ -421,7 +421,7 @@ SUBROUTINE surf_couple_rivers( & CALL accumulate_abstraction( global_land_pts, abstracted_minor_res_global, & tot_abstracted_minor_res_global ) END IF - + END IF ! l_oasis_rivers) diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index b595590a..cfe9ac44 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -1073,7 +1073,7 @@ SUBROUTINE allocate_global_water( l_allocate ) IF ( ALLOCATED(river_storage_global) ) DEALLOCATE(river_storage_global) IF ( ALLOCATED(return_flow_gw_global) ) DEALLOCATE(return_flow_gw_global) IF ( ALLOCATED(return_flow_river_global) ) THEN - DEALLOCATE(return_flow_river_global) + DEALLOCATE(return_flow_river_global) END IF IF ( ALLOCATED(priority_order_global) ) DEALLOCATE(priority_order_global) IF ( ALLOCATED(minor_res_storage_global) ) THEN @@ -1290,13 +1290,13 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & ! Save diagnostic of abstraction from minor reservoirs. IF ( l_minor_reservoirs ) THEN - CALL scatter_land_field( sw_abstracted_global(:,sw_minor_res_source), & + 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), & + CALL scatter_land_field( sw_abstracted_global(:,sw_river_source), & abstracted_river ) END IF @@ -1325,7 +1325,7 @@ SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & USE ereport_mod, ONLY: ereport -USE jules_rivers_mod, ONLY: i_river_vn, l_minor_reservoirs, l_rivers, & +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 diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index 7add2ff2..ea1052af 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -318,10 +318,8 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & ! Allocated space for all (global) land points because both the water resource ! and river codes operate globally. !------------------------------------------------------------------------------ -print*,'alloc l_minor_reservoirs=',l_minor_reservoirs ALLOCATE( water_resources_data & %abstracted_minor_res_global(global_land_pts_minor_res) ) -print*,'Alloc size=',size( water_resources_data%abstracted_minor_res_global ) !------------------------------------------------------------------------------ ! Coupling to rivers. 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 5983a611..2b639801 100644 --- a/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 +++ b/src/initialisation/standalone/ancillaries/init_rivers_process_data_mod.F90 @@ -2454,10 +2454,6 @@ SUBROUTINE set_river_point_values( rivers_x1_input, & rivers%minor_res_capacity(ip) = minor_res_capacity_grid(irx,iry) rivers%minor_res_frac(ip) = minor_res_frac_grid(irx,iry) - IF ( rivers%minor_res_capacity(ip) /= rivers%minor_res_capacity(ip).OR.& - rivers%minor_res_frac(ip) /= rivers%minor_res_frac(ip) ) THEN - print*,'ISSUE ',ip,rivers%minor_res_capacity(ip),rivers%minor_res_frac(ip) - END IF END IF ! l_minor_reservoirs @@ -2466,11 +2462,6 @@ SUBROUTINE set_river_point_values( rivers_x1_input, & END DO ! iy END DO ! ix -print*,'SET range minor_res_capacity=',MINVAL(rivers%minor_res_capacity(:)), & - MAXVAL(rivers%minor_res_capacity(:)) -print*,'SET range minor_res_frac=',MINVAL(rivers%minor_res_frac(:)), & - MAXVAL(rivers%minor_res_frac(:)) - END SUBROUTINE set_river_point_values !############################################################################## diff --git a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 index ebb8d009..eac3fdfe 100644 --- a/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 +++ b/src/initialisation/standalone/ancillaries/jules_rivers_props_mod.F90 @@ -1103,7 +1103,7 @@ SUBROUTINE allocate_rivers_vars_rp( np_rivers, rivers, rivers_data ) => rivers_data%tot_abstracted_minor_res_global ! Further variables to couple to water resources. -rivers%tot_net_abstracted_river_global & +rivers%tot_net_abstracted_river_global & => rivers_data%tot_net_abstracted_river_global RETURN diff --git a/src/science/river_routing/route_minor_reservoirs_mod.F90 b/src/science/river_routing/route_minor_reservoirs_mod.F90 index 8d8a0312..7023d439 100644 --- a/src/science/river_routing/route_minor_reservoirs_mod.F90 +++ b/src/science/river_routing/route_minor_reservoirs_mod.F90 @@ -92,8 +92,6 @@ SUBROUTINE route_minor_reservoirs( abstracted_minor_res_rp, minor_res_capacity,& END DO -!print*,'bottom RES_ROUTE range storage=',minval(minor_res_storage),maxval(minor_res_storage) - RETURN END SUBROUTINE route_minor_reservoirs From 97407c173a7e68336f2eaba8db7d020eb18fcaae Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Mon, 22 Jun 2026 11:18:56 +0100 Subject: [PATCH 11/24] Removed git text from metadata, updated macro. Updates from config-dump and metadata-check. --- rose-meta/jules-fcm-make/HEAD/rose-meta.conf | 12 ++++++------ rose-meta/jules-standalone/HEAD/rose-meta.conf | 4 ---- rose-meta/jules-standalone/versions.py | 6 +++--- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/rose-meta/jules-fcm-make/HEAD/rose-meta.conf b/rose-meta/jules-fcm-make/HEAD/rose-meta.conf index 5cb48f7e..0ee390ed 100644 --- a/rose-meta/jules-fcm-make/HEAD/rose-meta.conf +++ b/rose-meta/jules-fcm-make/HEAD/rose-meta.conf @@ -93,12 +93,12 @@ trigger=env=JULES_REMOTE: custom; = env=JULES_NETCDF_INC_PATH: custom; = env=JULES_NETCDF_LIB_PATH: custom; url=https://metoffice.github.io/jules/latest/building-and-running/fcm.html#environment-variables-used-when-building-jules-using-fcm-make -values=bom-dr, bom-xc40-intel, ceh, - =ceh-rocky9, custom, jasmin-gcc-nompi, - =jasmin-intel-nompi, jasmin-lotus-intel, meto-azspice-gnu-mpi, - =meto-azspice-gnu-nompi, meto-ex1a-cce, meto-ex1a-gfortran, - =nci-gfortran, nci-intel, niwa-cs500-gfortran, - =niwa-cs500-intel, niwa-xc50-cce, niwa-xc50-gfortran, +values=bom-dr, bom-xc40-intel, ceh, + =ceh-rocky9, custom, jasmin-gcc-nompi, + =jasmin-intel-nompi, jasmin-lotus-intel, meto-azspice-gnu-mpi, + =meto-azspice-gnu-nompi, meto-ex1a-cce, meto-ex1a-gfortran, + =nci-gfortran, nci-intel, niwa-cs500-gfortran, + =niwa-cs500-intel, niwa-xc50-cce, niwa-xc50-gfortran, =niwa-xc50-intel, uoe-linux-gfortran, vm, =$JULES_PLATFORM widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index ab6bd822..2c688225 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -2823,10 +2823,7 @@ fail-if=len(this) != namelist:jules_latlon=nvars length=: sort-key=6 type=character -<<<<<<< HEAD url=https://metoffice.github.io/jules/latest/namelists/ancillaries.nml.html#JULES_LATLON::var_name -======= -url=http://jules-lsm.github.io/latest/namelists/ancillaries.nml.html#JULES_LATLON::var_name [namelist:jules_model_environment] compulsory=true @@ -3110,7 +3107,6 @@ trigger=namelist:jules_pftparm: 1; url=http://jules-lsm.github.io/latest/namelists/model_environment.nml.html#JULES_MODEL_ENVIRONMENT::lsm_id value-titles='jules','cable','rivers-only' values=1,2,3 ->>>>>>> doucla/vn8.0_minor_reservoirs [namelist:jules_model_grid] compulsory=true diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 5dac45aa..c3d7b7e6 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -43,12 +43,12 @@ from .version79_80 import * from .version80_81 import * -class vn80_t32(MacroUpgrade): +class vn81_t32(MacroUpgrade): """Upgrade macro from JULES by Douglas Clark""" - BEFORE_TAG = "vn8.0" - AFTER_TAG = "vn8.0_t32" + BEFORE_TAG = "vn8.1" + AFTER_TAG = "vn8.1_t32" def upgrade(self,config, meta_config=None): """Upgrade a JULES runtime app configuration.""" From 98b4634dd73e4a5ed1d20be69b9a81a305475a91 Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Mon, 22 Jun 2026 11:22:55 +0100 Subject: [PATCH 12/24] Corrected and added to CONTRIBUTORS.md. --- CONTRIBUTORS.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b103cbcb..3e5bb751 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,6 +1,5 @@ # Contributors -<<<<<<< HEAD | GitHub user | Real Name | Affiliation | Date | | --------------- | ---------------- | ----------- | ---------- | | james-bruten-mo | James Bruten | Met Office | 2025-12-09 | @@ -10,9 +9,4 @@ | 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 | -======= -| GitHub user | Real Name | Affiliation | Date | -| ----------- | --------- | ----------- | ---- | -| james-bruten-mo | James Bruten | Met Office | 2025-12-09 | -| ppharris | Phil Harris | UKCEH | 2025-12-18 | ->>>>>>> doucla/vn8.0_minor_reservoirs +| doucla | Douglas Clark | UKCEH | 2026-06-22 | From 50bbfee47b134b867660ff933ce3e29389ab9e97 Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Mon, 22 Jun 2026 11:33:02 +0100 Subject: [PATCH 13/24] Correcting another mistake in previous merge. --- .../jules-standalone/HEAD/rose-meta.conf | 283 ------------------ 1 file changed, 283 deletions(-) diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index 2c688225..ac79c058 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -2825,289 +2825,6 @@ sort-key=6 type=character url=https://metoffice.github.io/jules/latest/namelists/ancillaries.nml.html#JULES_LATLON::var_name -[namelist:jules_model_environment] -compulsory=true -description=Not all JULES options are available in all environments in which JULES is run e.g. standalone, - =UM, (LIS, MONC, CABLE). The model environment is specified here so that options that are - =unavailable can be made inaccessible via the meta data and thus will not appear in the gui. -ns=namelist/JULES Science Settings/jules_model_environment -sort-key=01 -title=Model environment interface -url=http://jules-lsm.github.io/latest/namelists/model_environment.nml.html#namelist-JULES_MODEL_ENVIRONMENT - -[namelist:jules_model_environment=l_jules_parent] -compulsory=true -description=Switch to identify the e Date: Mon, 22 Jun 2026 14:34:46 +0100 Subject: [PATCH 14/24] Updated user doc to reflect minor reservoirs. --- doc/source/namelists/ancillaries.nml.rst | 18 ++++-- .../namelists/initial_conditions.nml.rst | 23 +++++--- doc/source/namelists/jules_rivers.nml.rst | 23 ++++++-- doc/source/output-variables.rst | 55 +++++++++++++++---- 4 files changed, 93 insertions(+), 26 deletions(-) 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 3d70b899..dcc20fdb 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,11 +423,16 @@ 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_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 | +----------------------------------+-----------------------------------------------------------------------------------------+---------+ @@ -439,6 +444,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 4349855d..81ba18a2 100644 --- a/doc/source/output-variables.rst +++ b/doc/source/output-variables.rst @@ -462,10 +462,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. | | +-------------------------------+-----------------------------------------------------------------------------------------------+------------+ @@ -1292,10 +1304,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. | | @@ -1309,9 +1318,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. | | @@ -1336,7 +1342,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`). | | @@ -1362,18 +1371,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`). | | +---------------------------+--------------------------------------------------------------------------------+------------+ From 26e08005f72db45f34740085f22bfc73f59e1b2f Mon Sep 17 00:00:00 2001 From: Douglas Clark Date: Fri, 26 Jun 2026 13:59:07 +0100 Subject: [PATCH 15/24] Return flows are now calculated initially assuming the sink is available, before a later decision based on configuration. Makes coupling slightly more clear/clean. Also tidying and adding DrHook (right now I'm bemused as to how some bits were compilable previously). --- .../shared/water_resources_control_mod.F90 | 149 ++++++++++++++---- .../water_resources/water_resources_drive.F90 | 123 ++++++--------- 2 files changed, 166 insertions(+), 106 deletions(-) diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index cfe9ac44..37f1a433 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -95,6 +95,11 @@ 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 !############################################################################## @@ -385,11 +390,6 @@ SUBROUTINE water_resources_control( global_land_pts, & supply_irrig(land_pts) ! Water supplied for irrigation (kg). -! Dr Hook variables -INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 -INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 -REAL(KIND=jprb) :: zhook_handle - !------------------------------------------------------------------------------ !end of header IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) @@ -563,9 +563,18 @@ SUBROUTINE water_resources_control( global_land_pts, & = 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, & @@ -669,16 +678,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 @@ -765,11 +768,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) @@ -840,11 +838,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) @@ -927,6 +920,7 @@ SUBROUTINE allocate_global_water( l_allocate ) !------------------------------------------------------------------------------ !end of header +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) IF ( l_allocate ) THEN @@ -1089,6 +1083,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 @@ -1134,6 +1129,11 @@ SUBROUTINE gather_global_water( priority_order, conv_loss_frac, demand_accum, & 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. !------------------------------------------------------------------------------ @@ -1148,6 +1148,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 ) @@ -1178,6 +1179,7 @@ SUBROUTINE gather_global_water( priority_order, conv_loss_frac, demand_accum, & 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 @@ -1244,6 +1246,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 !------------------------------------------------------------------------------ @@ -1251,6 +1258,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 ) @@ -1307,6 +1315,7 @@ SUBROUTINE scatter_global_water( conveyance_loss, demand_unmet, gw_abstracted, & 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 @@ -1377,11 +1386,6 @@ SUBROUTINE regrid_to_land( global_land_index, map_river_to_land_points, & 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) @@ -1443,6 +1447,88 @@ 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, & @@ -1469,7 +1555,7 @@ SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & grid_area_global(global_land_pts), & ! Area of gridbox (m2). return_flow_river_global(global_land_pts), & - ! Water that is returned to surface waters after use (kg). + ! Water that is returned to rivers after use (kg). sw_abstracted_river_global(global_land_pts) ! Water abstracted from river (kg). @@ -1480,6 +1566,11 @@ SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & 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. !------------------------------------------------------------------------------ @@ -1488,6 +1579,7 @@ SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & !------------------------------------------------------------------------------ !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,global_land_pts @@ -1496,6 +1588,7 @@ SUBROUTINE calc_river_flux( global_land_pts, grid_area_global, & / 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/science/water_resources/water_resources_drive.F90 b/src/science/water_resources/water_resources_drive.F90 index 6f05d773..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 @@ -292,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. !------------------------------------------------------------------------------ @@ -299,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 @@ -387,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. !------------------------------------------------------------------------------ @@ -401,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 @@ -520,6 +517,11 @@ SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted_per_use, & 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. !------------------------------------------------------------------------------ @@ -534,11 +536,6 @@ SUBROUTINE calc_conveyance_loss( global_land_pts, abstracted_per_use, & 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 @@ -589,14 +586,12 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & !------------------------------------------------------------------------------ ! 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, nwater_use, rf_domestic, & + nwater_use, rf_domestic, & rf_livestock, rf_industry, use_environment, use_domestic, use_industry, & use_irrigation, use_livestock, use_transfers @@ -624,14 +619,17 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_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_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. !------------------------------------------------------------------------------ @@ -651,11 +649,6 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & 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 @@ -673,50 +666,25 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & DO i = 1, nwater_use !--------------------------------------------------------------------------- - ! Set fraction of flow that is returned for this water use. Each use returns - ! water to either groundwater or river water; if the preferred sink - ! is not modelled the other is used if available. If neither is available - ! the default is to add to the groundwater variable because later code will - ! divert that return flow to runoff. + ! 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, otherwise to - ! groundwater (in which case there is no need to check whether groundwater - ! is included because the return flow will be added to runoff in that - ! configuration). - IF ( l_rivers ) THEN - return_flow_frac_gw = 0.0 - return_flow_frac_river = rf_domestic - ELSE - return_flow_frac_gw = rf_domestic - return_flow_frac_river = 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, otherwise - ! to groundwater. - IF ( l_rivers ) THEN - return_flow_frac_gw = 0.0 - return_flow_frac_river = rf_industry - ELSE - return_flow_frac_gw = rf_industry - return_flow_frac_river = 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, otherwise to - ! rivers. If neither is available we add to the groundwater return flow - ! which is later added to runoff. - IF ( l_have_groundwater & - .OR. ( .NOT. l_have_groundwater .AND. .NOT. l_rivers ) ) THEN - return_flow_frac_gw = rf_livestock - return_flow_frac_river = 0.0 - ELSE - ! No groundwater but rivers. - return_flow_frac_gw = 0.0 - return_flow_frac_river = 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 @@ -733,8 +701,7 @@ SUBROUTINE calc_return_flow( global_land_pts, abstracted_per_use, & ! This is the water abstracted, minus conveyance loss. 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_river(l) = return_flow_river(l) & + return_flow_frac_river * delivered From 403ac460dd792c33213da9d91d9f7bba9f81adcf Mon Sep 17 00:00:00 2001 From: KatieBlackford <61746372+KatieBlackford@users.noreply.github.com> Date: Wed, 15 Jul 2026 16:35:53 +0100 Subject: [PATCH 16/24] Fixed error in previous merge --- src/io/model_interface/variable_metadata.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/io/model_interface/variable_metadata.inc b/src/io/model_interface/variable_metadata.inc index 3a61ca2a..c33dd863 100644 --- a/src/io/model_interface/variable_metadata.inc +++ b/src/io/model_interface/variable_metadata.inc @@ -9366,6 +9366,7 @@ DATA metadata(723) / var_metadata( & "Inland basin flow on river routing grid", & ! Units "kg m-2 s-1" & + ) / !----------------------------------------------------------------------------- ! Metadata for conveyance_loss !----------------------------------------------------------------------------- From 77d11a36cc707c2b504e1bc90cda6ec32cd965e1 Mon Sep 17 00:00:00 2001 From: KatieBlackford <61746372+KatieBlackford@users.noreply.github.com> Date: Wed, 15 Jul 2026 16:51:26 +0100 Subject: [PATCH 17/24] Fixed another merge error --- src/initialisation/standalone/init_output_mod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/initialisation/standalone/init_output_mod.F90 b/src/initialisation/standalone/init_output_mod.F90 index 27f679d6..fa280e1d 100644 --- a/src/initialisation/standalone/init_output_mod.F90 +++ b/src/initialisation/standalone/init_output_mod.F90 @@ -348,7 +348,8 @@ SUBROUTINE check_output_vars( nvars, var, var_name, output_type, & sw_river_source 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_riv_overbank, i_river_vn, rivers_camaflood, rivers_rfm, rivers_trip, & + l_inland_outflow USE jules_deposition_mod, ONLY: l_deposition, l_deposition_flux From d5ab1d6c39da68717c1a671b3088f47715d84bb4 Mon Sep 17 00:00:00 2001 From: KatieBlackford <61746372+KatieBlackford@users.noreply.github.com> Date: Thu, 30 Jul 2026 12:30:14 +0100 Subject: [PATCH 18/24] Fixes to run parallel --- src/control/shared/surf_couple_rivers_mod.F90 | 41 +++++++++++-------- .../shared/water_resources_control_mod.F90 | 14 ++++--- .../shared/water_resources_vars_mod.F90 | 1 + 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/control/shared/surf_couple_rivers_mod.F90 b/src/control/shared/surf_couple_rivers_mod.F90 index 4dd0c861..0b7a2738 100644 --- a/src/control/shared/surf_couple_rivers_mod.F90 +++ b/src/control/shared/surf_couple_rivers_mod.F90 @@ -364,14 +364,18 @@ SUBROUTINE surf_couple_rivers( & rivers%rrun_surf_rp(:) = 0.0 END IF - ! Initialise the accumulated abstraction from rivers. - IF ( sw_river_source > 0 ) THEN - tot_net_abstracted_river_global(:) = 0.0 - 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 + ! 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 @@ -411,19 +415,22 @@ SUBROUTINE surf_couple_rivers( & END DO END IF ! l_wtrac_jls - ! 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 + ! 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 ) + ! 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? diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 37f1a433..09076dd3 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -423,11 +423,15 @@ SUBROUTINE water_resources_control( global_land_pts, & ! intermediate timesteps. !------------------------------------------------------------------------------ ! Initialise coupling fluxes. -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 +! 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 diff --git a/src/control/shared/water_resources_vars_mod.F90 b/src/control/shared/water_resources_vars_mod.F90 index ea1052af..bbc7c0f9 100644 --- a/src/control/shared/water_resources_vars_mod.F90 +++ b/src/control/shared/water_resources_vars_mod.F90 @@ -242,6 +242,7 @@ SUBROUTINE water_resources_alloc( global_land_pts, land_pts, n_sw_source, & 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 From 99029d8cb8de01360e2564e31c309d8dc427614f Mon Sep 17 00:00:00 2001 From: Helen Baron Date: Wed, 5 Aug 2026 15:16:10 +0100 Subject: [PATCH 19/24] fix to ensure minor reservoirs work when dump file called in JULES_initial --- .../standalone/initial_conditions/init_ic_mod.F90 | 3 +++ src/io/model_interface/populate_var.inc | 8 ++++++++ 2 files changed, 11 insertions(+) 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/model_interface/populate_var.inc b/src/io/model_interface/populate_var.inc index 8876fe5c..cc05833d 100644 --- a/src/io/model_interface/populate_var.inc +++ b/src/io/model_interface/populate_var.inc @@ -2432,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) ]) From 4a30af7aa1fd9be99516a4d450648fd495b0c656 Mon Sep 17 00:00:00 2001 From: KatieBlackford <61746372+KatieBlackford@users.noreply.github.com> Date: Mon, 17 Aug 2026 09:11:49 +0100 Subject: [PATCH 20/24] Bug fix for valid ancil data --- .../route_minor_reservoirs_mod.F90 | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/science/river_routing/route_minor_reservoirs_mod.F90 b/src/science/river_routing/route_minor_reservoirs_mod.F90 index 7023d439..13e0fd8c 100644 --- a/src/science/river_routing/route_minor_reservoirs_mod.F90 +++ b/src/science/river_routing/route_minor_reservoirs_mod.F90 @@ -72,22 +72,28 @@ SUBROUTINE route_minor_reservoirs( abstracted_minor_res_rp, minor_res_capacity,& DO i = 1, np_rivers - ! 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) + ! Only route through a minor reservoir where the ancillary data are + ! physically valid. + 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 From 9c68cc1ab6a9b47dcb14c4029383596179e65a6b Mon Sep 17 00:00:00 2001 From: KatieBlackford <61746372+KatieBlackford@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:34:55 +0100 Subject: [PATCH 21/24] Fixed metadata error and signed CLA --- CONTRIBUTORS.md | 1 + rose-meta/jules-standalone/HEAD/rose-meta.conf | 2 +- src/science/river_routing/route_minor_reservoirs_mod.F90 | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 3e5bb751..d2b7fb23 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -10,3 +10,4 @@ | 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/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index bd4376b6..05f31be2 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -4092,7 +4092,7 @@ compulsory=true description=Switch to activate minor reservoirs sort-key=a8 type=logical -url=http://jules-lsm.github.io/latest/namelists/jules_rivers.nml.html#JULES_RIVERS_RESOURCES::l_minor_reservoirs +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 diff --git a/src/science/river_routing/route_minor_reservoirs_mod.F90 b/src/science/river_routing/route_minor_reservoirs_mod.F90 index 13e0fd8c..399df072 100644 --- a/src/science/river_routing/route_minor_reservoirs_mod.F90 +++ b/src/science/river_routing/route_minor_reservoirs_mod.F90 @@ -72,8 +72,7 @@ SUBROUTINE route_minor_reservoirs( abstracted_minor_res_rp, minor_res_capacity,& DO i = 1, np_rivers - ! Only route through a minor reservoir where the ancillary data are - ! physically valid. + ! 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 From e2e83e2352423a50f062a25f762bf979c4654134 Mon Sep 17 00:00:00 2001 From: KatieBlackford <61746372+KatieBlackford@users.noreply.github.com> Date: Fri, 21 Aug 2026 14:53:22 +0100 Subject: [PATCH 22/24] Removed unused calc_avail_river_water subroutine --- .../water_resources/calc_avail_water_mod.F90 | 105 ------------------ 1 file changed, 105 deletions(-) diff --git a/src/science/water_resources/calc_avail_water_mod.F90 b/src/science/water_resources/calc_avail_water_mod.F90 index 6914a6fa..fba8cedc 100644 --- a/src/science/water_resources/calc_avail_water_mod.F90 +++ b/src/science/water_resources/calc_avail_water_mod.F90 @@ -232,111 +232,6 @@ SUBROUTINE calc_avail_surface_water( minor_res_storage_global, & 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 - -USE jules_rivers_mod, ONLY: i_river_vn, 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) :: & - 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 - -IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) -RETURN -END SUBROUTINE calc_avail_river_water - !############################################################################## END MODULE calc_avail_water_mod From 0997888bdcb5c888390621dfbdde922c6517727d Mon Sep 17 00:00:00 2001 From: KatieBlackford <61746372+KatieBlackford@users.noreply.github.com> Date: Fri, 21 Aug 2026 16:01:41 +0100 Subject: [PATCH 23/24] Cutting down overly long lines --- src/control/shared/water_resources_control_mod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/control/shared/water_resources_control_mod.F90 b/src/control/shared/water_resources_control_mod.F90 index 09076dd3..5aed4e9b 100644 --- a/src/control/shared/water_resources_control_mod.F90 +++ b/src/control/shared/water_resources_control_mod.F90 @@ -525,10 +525,10 @@ SUBROUTINE water_resources_control( global_land_pts, & 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 !------------------------------------------------------------------------ From 3d0a2b6d8d0c7dd149fdcb2de76cebf703893093 Mon Sep 17 00:00:00 2001 From: Katie Blackford <61746372+KatieBlackford@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:16:40 +0100 Subject: [PATCH 24/24] Apply suggestions from code review Co-authored-by: Douglas Clark --- rose-meta/jules-standalone/versions.py | 6 +++--- src/io/model_interface/extract_var.inc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index ff9aab7d..c7f423d0 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -45,12 +45,12 @@ from .version81_82 import * -class vn81_t32(MacroUpgrade): +class vn82_t32(MacroUpgrade): """Upgrade macro from JULES by Douglas Clark""" - BEFORE_TAG = "vn8.1" - AFTER_TAG = "vn8.1_t32" + BEFORE_TAG = "vn8.2" + AFTER_TAG = "vn8.2_t32" def upgrade(self,config, meta_config=None): """Upgrade a JULES runtime app configuration.""" diff --git a/src/io/model_interface/extract_var.inc b/src/io/model_interface/extract_var.inc index b0788e6a..1b71d626 100644 --- a/src/io/model_interface/extract_var.inc +++ b/src/io/model_interface/extract_var.inc @@ -2665,7 +2665,7 @@ CASE ( 'rivers_sto_rp' ) cube = cube_from_array(rivers%rivers_sto_rp) CASE ( 'rfm_bflowin_rp' ) - ! Internal units are m<3/timestep, convert to m3/s + ! Internal units are m3/timestep, convert to m3/s workspace_rivers = rivers%rfm_bflowin_rp * nstep_rivers * timestep cube = cube_from_array(workspace_rivers)