diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5f7f9a905..60e64e4c5 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -46,6 +46,7 @@ | theabro | Nathan Luke Abraham | NCAS & University of Cambridge | 2026-04-15 | | ss421 | Steven Sandbach | Met Office | 2026-04-20 | | MichaelWhitall | Michael Whitall | Met Office | 2026-04-22 | +| DanCopsey | Dan Copsey | Met Office | 2026-05-14 | | marcstring | Marc Stringer | NCAS, Reading University | 2026-05-06 | | cameronbateman-mo | Cameron Bateman | Met Office | 2026-05-28 | | davelee2804 | David Lee | Bureau of Meteorology, Australia | 2026-06-02 | diff --git a/applications/lfric_atm/example/configuration.nml b/applications/lfric_atm/example/configuration.nml index 7f330ba60..8033061cc 100644 --- a/applications/lfric_atm/example/configuration.nml +++ b/applications/lfric_atm/example/configuration.nml @@ -336,6 +336,7 @@ write_minmax_tseries=.false., / &jules_hydrology l_hydrology=.true., +l_inland=.false., l_var_rainfrac=.true., / &jules_model_environment_lfric diff --git a/applications/lfric_atm/metadata/field_def_diags.xml b/applications/lfric_atm/metadata/field_def_diags.xml index 36f092c6d..cbe51e1b1 100644 --- a/applications/lfric_atm/metadata/field_def_diags.xml +++ b/applications/lfric_atm/metadata/field_def_diags.xml @@ -638,6 +638,7 @@ + diff --git a/applications/lfric_atm/metadata/lfric_dictionary.xml b/applications/lfric_atm/metadata/lfric_dictionary.xml index 3ab44ca0b..739df77f9 100644 --- a/applications/lfric_atm/metadata/lfric_dictionary.xml +++ b/applications/lfric_atm/metadata/lfric_dictionary.xml @@ -399,5 +399,6 @@ + diff --git a/applications/lfric_coupled/example/configuration.nml b/applications/lfric_coupled/example/configuration.nml index 0648d72ae..616aa93b3 100644 --- a/applications/lfric_coupled/example/configuration.nml +++ b/applications/lfric_coupled/example/configuration.nml @@ -168,6 +168,7 @@ write_minmax_tseries=.false., / &jules_hydrology l_hydrology=.true., +l_inland=.false., l_var_rainfrac=.false. / &jules_model_environment_lfric diff --git a/dependencies.yaml b/dependencies.yaml index 6e03afa85..51cb4bda9 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -22,8 +22,8 @@ casim: ref: 2026.03.2 jules: - source: git@github.com:MetOffice/jules.git - ref: 3647a42962613d1f50d02d7660c86dece056f87c + source: git@github.com:DanCopsey/jules.git + ref: inland_flow lfric_apps: source: diff --git a/interfaces/coupled_interface/source/algorithm/coupler_update_prognostics_mod.X90 b/interfaces/coupled_interface/source/algorithm/coupler_update_prognostics_mod.X90 index 6149953e4..92036846a 100644 --- a/interfaces/coupled_interface/source/algorithm/coupler_update_prognostics_mod.X90 +++ b/interfaces/coupled_interface/source/algorithm/coupler_update_prognostics_mod.X90 @@ -159,6 +159,13 @@ module coupler_update_prognostics_mod 'Ocean surface v from coupler', fld ) call depository%get_field('sea_v_current', fld_ptr1) call invoke(setval_x(fld_ptr1, fld)) + case ("lf_inland_flow") + call log_field_minmax( LOG_LEVEL_DEBUG, & + 'Inland basin flow from coupler', fld) + call depository%get_field('inland_basin_flow', fld_ptr1) + call invoke(setval_X( fld_ptr1, fld )) + fld_ptr1 => null() + case default write(log_scratch_space, '(3A)' ) & "PROBLEM coupler_update_prognostics variable ", & diff --git a/interfaces/coupled_interface/source/coupler_mod.F90 b/interfaces/coupled_interface/source/coupler_mod.F90 index 6791d3a78..b75cdc651 100644 --- a/interfaces/coupled_interface/source/coupler_mod.F90 +++ b/interfaces/coupled_interface/source/coupler_mod.F90 @@ -296,6 +296,10 @@ subroutine create_coupling_fields( mesh, & call add_cpl_field(depository, prognostic_fields, & 'lf_svnocean', vector_space, checkpoint_restart_flag) + ! From TRIP river model + call add_cpl_field(depository, prognostic_fields, & + 'lf_inland_flow', vector_space, checkpoint_restart_flag) + end subroutine create_coupling_fields diff --git a/interfaces/jules_interface/build/extract.yaml b/interfaces/jules_interface/build/extract.yaml index b57f5c3ff..75f0f1ef5 100644 --- a/interfaces/jules_interface/build/extract.yaml +++ b/interfaces/jules_interface/build/extract.yaml @@ -67,6 +67,7 @@ jules: - src/control/shared/wtrac_extra_mod.F90 - src/initialisation/shared/calc_urban_aero_fields_mod.F90 - src/initialisation/shared/check_compatible_options_mod.F90 + - src/initialisation/shared/check_compatible_options_rivers_mod.F90 - src/initialisation/shared/freeze_soil.F90 - src/initialisation/shared/wtrac_check_options_mod.F90 - src/science/deposition/deposition_check_species_mod.F90 diff --git a/interfaces/jules_interface/rose-meta/jules-lsm/versions.py b/interfaces/jules_interface/rose-meta/jules-lsm/versions.py index 00aaf3d3e..7d7d2592f 100644 --- a/interfaces/jules_interface/rose-meta/jules-lsm/versions.py +++ b/interfaces/jules_interface/rose-meta/jules-lsm/versions.py @@ -18,7 +18,6 @@ def __repr__(self): __str__ = __repr__ - """ Copy this template and complete to add your macro class vnXX_txxx(MacroUpgrade): @@ -391,3 +390,14 @@ def upgrade(self, config, meta_config=None): ) return config, self.reports + +class vn31_t401(MacroUpgrade): + """Upgrade macro for ticket #401 by Dan Copsey.""" + + BEFORE_TAG = "vn3.1_t205" + AFTER_TAG = "vn3.1_t401" + + def upgrade(self, config, meta_config=None): + # Add settings + self.add_setting(config, ["namelist:jules_hydrology", "l_inland"], ".false.") + return config, self.reports diff --git a/interfaces/jules_interface/source/algorithm/init_soil_fields_alg_mod.x90 b/interfaces/jules_interface/source/algorithm/init_soil_fields_alg_mod.x90 index c370e62b0..71bcb9201 100644 --- a/interfaces/jules_interface/source/algorithm/init_soil_fields_alg_mod.x90 +++ b/interfaces/jules_interface/source/algorithm/init_soil_fields_alg_mod.x90 @@ -69,6 +69,7 @@ contains type( field_type ), pointer :: wetness_under_soil => null() type( field_type ), pointer :: surface_runoff => null() type( field_type ), pointer :: sub_surface_runoff => null() + type( field_type ), pointer :: inland_basin_flow => null() call soil_fields%get_field('soil_albedo', soil_albedo) call soil_fields%get_field('soil_moist_wilt', soil_moist_wilt) @@ -95,6 +96,7 @@ contains call soil_fields%get_field('wetness_under_soil', wetness_under_soil) call soil_fields%get_field('surface_runoff', surface_runoff) call soil_fields%get_field('sub_surface_runoff', sub_surface_runoff) + call soil_fields%get_field('inland_basin_flow',inland_basin_flow) ! Set soil ancillaries to fixed values for if no ancil is read call invoke( setval_c(soil_albedo, 0.11_r_def), & @@ -114,6 +116,7 @@ contains setval_c(c_wet_frac, 1.0_r_def), & setval_c(surface_runoff, 0.0_r_def), & setval_c(sub_surface_runoff, 0.0_r_def), & + setval_c(inland_basin_flow, 0.0_r_def ), & ! Set soil prognostics when no values are provided by um2lfric setval_c(soil_sat_frac, 1.0_r_def), & setval_c(water_table, 1.0_r_def), & diff --git a/interfaces/jules_interface/source/algorithm/jules_extra_alg_mod.x90 b/interfaces/jules_interface/source/algorithm/jules_extra_alg_mod.x90 index 68241339a..c85bf2d92 100644 --- a/interfaces/jules_interface/source/algorithm/jules_extra_alg_mod.x90 +++ b/interfaces/jules_interface/source/algorithm/jules_extra_alg_mod.x90 @@ -91,6 +91,7 @@ contains type( field_type ), pointer :: snowice_melt => null() type( field_type ), pointer :: snowice_sublimation => null() type( field_type ), pointer :: urbztm => null() + type( field_type ), pointer :: inland_basin_flow => null() ! Sea ice fields type( field_type ), pointer :: sea_ice_thickness => null() @@ -205,6 +206,7 @@ contains call soil_fields%get_field('wetness_under_soil', wetness_under_soil) call soil_fields%get_field('surface_runoff', surface_runoff) call soil_fields%get_field('sub_surface_runoff', sub_surface_runoff) + call soil_fields%get_field('inland_basin_flow', inland_basin_flow) ! Snow fields call snow_fields%get_field('tile_snow_mass', tile_snow_mass) @@ -247,6 +249,7 @@ contains mean_topog_index, a_sat_frac, c_sat_frac, & a_wet_frac, c_wet_frac, tile_temperature, & net_prim_prod, snowice_sublimation, surf_heat_flux, & + inland_basin_flow, & canopy_evap, water_extraction, & thermal_cond_wet_soil, urbztm, & soil_temperature, soil_moisture, & @@ -298,6 +301,9 @@ contains sea_ice_pensolar, melt_pond_fraction, & melt_pond_depth) + ! Output extra coupling diagnostics + call inland_basin_flow%write_field('soil__inland_basin_flow') + end if end subroutine jules_extra_alg diff --git a/interfaces/jules_interface/source/kernel/jules_extra_kernel_mod.F90 b/interfaces/jules_interface/source/kernel/jules_extra_kernel_mod.F90 index 14885cc8b..171092e90 100644 --- a/interfaces/jules_interface/source/kernel/jules_extra_kernel_mod.F90 +++ b/interfaces/jules_interface/source/kernel/jules_extra_kernel_mod.F90 @@ -32,7 +32,7 @@ module jules_extra_kernel_mod !> type, public, extends(kernel_type) :: jules_extra_kernel_type private - type(arg_type) :: meta_args(58) = (/ & + type(arg_type) :: meta_args(59) = (/ & arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_1), & ! ls_rain arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_1), & ! conv_rain arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_1), & ! ls_snow @@ -62,6 +62,7 @@ module jules_extra_kernel_mod arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_1), & ! net_prim_prod arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_2), & ! snowice_sublimation arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_2), & ! surf_heat_flux + arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_1), & ! inland_basin_flow arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_2), & ! canopy_evap arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_4), & ! water_extraction arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_DISCONTINUOUS_SPACE_1), & ! thermal_cond_wet_soil @@ -137,6 +138,7 @@ module jules_extra_kernel_mod !> @param[in] net_prim_prod Net Primary Productivity (kg m-2 s-1) !> @param[in] snowice_sublimation Sublimation of snow and ice (kg m-2 s-1) !> @param[in] surf_heat_flux Surface heat flux (W m-2) + !> @param[in] inland_basin_flow Inland flow of water from rivers to soil (kg m-2 s-1) !> @param[in] canopy_evap Canopy evaporation from land tiles (kg m-2 s-1) !> @param[in] water_extraction Extraction of water from each soil layer (kg m-2 s-1) !> @param[in] thermal_cond_wet_soil Thermal conductivity of soil (W m-1 K-1) @@ -212,6 +214,7 @@ subroutine jules_extra_code( & net_prim_prod, & snowice_sublimation, & surf_heat_flux, & + inland_basin_flow, & canopy_evap, & water_extraction, & thermal_cond_wet_soil, & @@ -421,6 +424,7 @@ subroutine jules_extra_code( & real(kind=r_def), intent(in) :: net_prim_prod(undf_2d) real(kind=r_def), intent(in) :: thermal_cond_wet_soil(undf_2d) real(kind=r_def), intent(in) :: urbztm(undf_2d) + real(kind=r_def), intent(in) :: inland_basin_flow(undf_2d) real(kind=r_def), intent(inout) :: canopy_water(undf_tile) real(kind=r_def), intent(inout) :: tile_snow_mass(undf_tile) @@ -902,6 +906,7 @@ subroutine jules_extra_code( & allocate(fsat_soilt(land_pts, nsoilt)) allocate(zw_soilt(land_pts, nsoilt)) allocate(sthzw_soilt(land_pts, nsoilt)) + allocate(inlandout_atm_gb(land_pts)) do l = 1, land_pts ! Soil saturated fraction fsat_soilt(l,1) = real(soil_sat_frac(map_2d(1,ainfo%land_index(l))), r_um) @@ -909,6 +914,8 @@ subroutine jules_extra_code( & zw_soilt(l,1) = real(water_table(map_2d(1,ainfo%land_index(l))), r_um) ! Soil wetness below soil column sthzw_soilt(l,1) = real(wetness_under_soil(map_2d(1,ainfo%land_index(l))), r_um) + ! Inland basin flow + inlandout_atm_gb(l) = real(inland_basin_flow(map_2d(1,ainfo%land_index(l))), r_um) end do !---------------------------------------------------------------------------- @@ -929,7 +936,6 @@ subroutine jules_extra_code( & allocate(dhf_surf_minus_soil(land_pts)) allocate(tot_surf_runoff(land_pts)) allocate(tot_sub_runoff(land_pts)) - allocate(inlandout_atm_gb(land_pts)) call surf_couple_extra( & !Driving data and associated INTENT(IN) @@ -1049,8 +1055,10 @@ subroutine jules_extra_code( & ! Wetness below soil column wetness_under_soil(map_2d(1,ainfo%land_index(l))) = real(sthzw_soilt(l,1), r_def) ! River runoffs - surface_runoff(map_2d(1,ainfo%land_index(l))) = real(fluxes%surf_roff_gb(l), r_def) - sub_surface_runoff(map_2d(1,ainfo%land_index(l))) = real(fluxes%sub_surf_roff_gb(l), r_def) + surface_runoff(map_2d(1,ainfo%land_index(l))) = real(fluxes%surf_roff_gb(l), r_def) * & + flandg(ainfo%land_index(l), 1) + sub_surface_runoff(map_2d(1,ainfo%land_index(l))) = real(fluxes%sub_surf_roff_gb(l), r_def) * & + flandg(ainfo%land_index(l), 1) end do if (.not. associated(soil_moisture_content, empty_real_data) ) then diff --git a/interfaces/jules_interface/source/support/jules_physics_init_mod.f90 b/interfaces/jules_interface/source/support/jules_physics_init_mod.f90 index 9736bfddd..fbb90ca54 100644 --- a/interfaces/jules_interface/source/support/jules_physics_init_mod.f90 +++ b/interfaces/jules_interface/source/support/jules_physics_init_mod.f90 @@ -108,7 +108,7 @@ subroutine jules_physics_init(config) use c_z0h_z0m, only: c_z0h_z0m_print, c_z0h_z0m_check, z0h_z0m use jules_hydrology_mod, only: check_jules_hydrology, & print_nlist_jules_hydrology, l_hydrology, l_top, l_var_rainfrac, & - nfita, ti_max, ti_wetl, zw_max + nfita, ti_max, ti_wetl, zw_max, l_inland use jules_irrig_mod, only: l_irrig_dmd use jules_radiation_mod, only: i_sea_alb_method, & l_embedded_snow, l_mask_snow_orog, & @@ -197,6 +197,7 @@ subroutine jules_physics_init(config) ! JULES hydrology settings - contained in module jules_hydrology ! ---------------------------------------------------------------- l_hydrology = config%jules_hydrology%l_hydrology() + l_inland = config%jules_hydrology%l_inland() l_top = .true. l_var_rainfrac = config%jules_hydrology%l_var_rainfrac() nfita = 30 diff --git a/rose-stem/app/lfric_coupled_rivers/rose-app.conf b/rose-stem/app/lfric_coupled_rivers/rose-app.conf index 35e9afab0..1f49936e0 100644 --- a/rose-stem/app/lfric_coupled_rivers/rose-app.conf +++ b/rose-stem/app/lfric_coupled_rivers/rose-app.conf @@ -1,4 +1,4 @@ -meta=jules-standalone/vn7.9_t1392 +meta=jules-standalone/vn8.1_t34 [command] default=rose-run jules.exe @@ -67,6 +67,7 @@ y_dim_name='latitude' [namelist:jules_land_frac] file='$RIV_NUMBER_ANCILLARY/river_mask_fracarea_ancil.nc' +l_use_land_fraction=.false. land_frac_name='lsmask' [namelist:jules_latlon] @@ -128,7 +129,6 @@ prnt_writers=1 !!cland=0.2 !!criver=0.62 i_river_vn=3 -!!l_inland=.false. !!l_riv_overbank=.false. l_rivers=.true. !!lake_water_conserve_method=1 diff --git a/rose-stem/site/meto/kgos/lfric_coupled/ex1a/checksum_lfric_coupled_nwp_gal9-C48_ex1a_cce_fast-debug-64bit.txt b/rose-stem/site/meto/kgos/lfric_coupled/ex1a/checksum_lfric_coupled_nwp_gal9-C48_ex1a_cce_fast-debug-64bit.txt index 879448cab..fd63bdf5f 100644 --- a/rose-stem/site/meto/kgos/lfric_coupled/ex1a/checksum_lfric_coupled_nwp_gal9-C48_ex1a_cce_fast-debug-64bit.txt +++ b/rose-stem/site/meto/kgos/lfric_coupled/ex1a/checksum_lfric_coupled_nwp_gal9-C48_ex1a_cce_fast-debug-64bit.txt @@ -1,9 +1,9 @@ -Inner product checksum rho = 411B5409D804A878 -Inner product checksum theta = 42735B1D0D01AE5C -Inner product checksum u = 456F4385CD1ACE02 -Inner product checksum mr1 = 4036846D52D0A856 -Inner product checksum mr2 = 3F3FA19DE10519BC -Inner product checksum mr3 = 3F00ED1994A93DC6 -Inner product checksum mr4 = 3F36893E43F07BCC +Inner product checksum rho = 411B540A96B37E4F +Inner product checksum theta = 42735B1DC4620029 +Inner product checksum u = 456F4479A8EB9CF2 +Inner product checksum mr1 = 4036851FACCD4D6A +Inner product checksum mr2 = 3F3FA5B17FDDA974 +Inner product checksum mr3 = 3F00D65E266F8C62 +Inner product checksum mr4 = 3F368FE5FDCA5515 Inner product checksum mr5 = 0 Inner product checksum mr6 = 0 diff --git a/science/gungho/source/driver/create_physics_prognostics_mod.F90 b/science/gungho/source/driver/create_physics_prognostics_mod.F90 index 6e6545f72..e53228520 100644 --- a/science/gungho/source/driver/create_physics_prognostics_mod.F90 +++ b/science/gungho/source/driver/create_physics_prognostics_mod.F90 @@ -941,6 +941,7 @@ subroutine process_physics_prognostics(processor) empty = (.not. l_urban2t) )) call processor%apply(make_spec('urbemisc', main%surface, W3, twod=.true., & empty = (.not. l_urban2t))) + ! 2D fields, need checkpointing for urban-2-tile schemes call processor%apply(make_spec('urbwrr', main%surface, twod=.true., & ckp=l_urban2t, empty = (.not. l_urban2t) )) @@ -1039,6 +1040,8 @@ subroutine process_physics_prognostics(processor) call processor%apply(make_spec('soil_moist_avail', main%soil, W3, twod=.true.)) call processor%apply(make_spec('thermal_cond_wet_soil', main%soil, W3, & twod=.true.)) + call processor%apply(make_spec('inland_basin_flow', main%soil, W3, & + twod=.true.)) !======================================================================== ! Fields owned by the snow scheme diff --git a/science/gungho/source/driver/gungho_model_mod.F90 b/science/gungho/source/driver/gungho_model_mod.F90 index b2a7c7a15..d8b152969 100644 --- a/science/gungho/source/driver/gungho_model_mod.F90 +++ b/science/gungho/source/driver/gungho_model_mod.F90 @@ -794,9 +794,9 @@ subroutine initialise_infrastructure( io_context_name, modeldb ) ! Set up collections to hold 2d coupling fields call modeldb%fields%add_empty_field_collection("cpl_snd_2d" , & - table_len = 30) + table_len = 1) call modeldb%fields%add_empty_field_collection("cpl_rcv_2d" , & - table_len = 30) + table_len = 1) cpl_snd_2d => modeldb%fields%get_field_collection("cpl_snd_2d") cpl_rcv_2d => modeldb%fields%get_field_collection("cpl_rcv_2d")