Skip to content

Add minor reservoirs to hydrology - #143

Open
Katie Blackford (KatieBlackford) wants to merge 50 commits into
MetOffice:mainfrom
KatieBlackford:vn8.2_minor_reservoirs
Open

Katie Blackford (KatieBlackford) wants to merge 50 commits into
MetOffice:mainfrom
KatieBlackford:vn8.2_minor_reservoirs

Conversation

@KatieBlackford

@KatieBlackford Katie Blackford (KatieBlackford) commented Aug 21, 2026 •

Copy link
Copy Markdown

PR Summary

The code allows for minor reservoirs, these are defined as small water bodies that are not on the main river stem but collect and retain local runoff which is then available for water abstractions.

Closes #32

Sci/Tech Reviewer: Sonja (@sfolwell)
Code Reviewer: James Bruten (@james-bruten-mo)

linked MetOffice/um#121
linked MetOffice/lfric_apps#859

Code Quality Checklist

(Some checks are automatically carried out via the CI pipeline)

  • I have performed a self-review of my own code
  • My code follows the project's style guidelines
  • Comments have been included that aid understanding and enhance the readability of the code
  • My changes generate no new warnings
  • If editing rose-meta/jules-shared then have you supplied a linked UM and LFRic Apps PR?

Testing

  • I have tested this change locally, using the JULES rose-stem suite
  • If shared files have been modified, I have run the UM and LFRic Apps rose stem suites
  • If any tests fail (rose-stem or CI) the reason is understood and acceptable (eg. kgo changes)
  • I have added tests to cover new functionality as appropriate (eg. system tests, unit tests, etc.)

trac.log

Test Suite Results - jules - vn8.2_minor_reservoirs_test/run2

Suite Information

Item Value
Suite Name vn8.2_minor_reservoirs_test/run2
Suite User katbla6
Workflow Start 2026-10-27T16:19:14
Groups Run all
Dependency Reference Main Like
jules KatieBlackford/jules@vn8.2_minor_reservoirs_test False
SimSys_Scripts MetOffice/SimSys_Scripts@2026.07.1 True

Task Information

✅ succeeded tasks - 213

Security Considerations

  • I have reviewed my changes for potential security issues
  • Sensitive data is properly handled (if applicable)
  • Authentication and authorisation are properly implemented (if applicable)

Performance Impact

  • Performance of the code has been considered and, if applicable, suitable performance measurements have been conducted

AI Assistance and Attribution

  • Some of the content of this change has been produced with the assistance of Generative AI tool name (e.g., Met Office Github Copilot Enterprise, Github Copilot Personal, ChatGPT GPT-4, etc) and I have followed the Simulation Systems AI policy (including attribution labels)

Documentation

  • Where appropriate I have updated documentation related to this change and confirmed that it builds correctly

Approvals

Please request all relevant approvals. See the CodeOwners.txt file for section owners.

Technical

  • JULES Code Owner
  • OpenMP
  • River Routing
  • Rose Stem
  • Rose Metadata
  • Upgrade Macros

Scientific

  • Surface
  • Hydrology
  • Vegetation
  • Veg3 RED Demography
  • Biogeochemistry
  • Biogenic fluxes
  • Fire
  • Lakes
  • Evaluation
  • Imogen

Sci/Tech Review

  • I understand this area of code and the changes being added
  • The proposed changes correspond to the pull request description
  • Documentation is sufficient (do documentation papers need updating)
  • Sufficient testing has been completed

Please alert the code reviewer via a tag when you have approved the SR

Code Review

  • All dependencies have been resolved
  • Related Issues have been properly linked and addressed
  • CLA compliance has been confirmed
  • Code quality standards have been met
  • Tests are adequate and have passed
  • Documentation is complete and accurate
  • Security considerations have been addressed
  • Performance impact is acceptable

Phil Harris (ppharris) and others added 25 commits March 2, 2026 16:44
Co-authored-by: James Bruten <109733895+james-bruten-mo@users.noreply.github.com>
…de to rivers code) as a variable on "global" land points rather than scattering and then regathering.
return_flow_sw now called return_flow_river for clarity.
Updates from config-dump and metadata-check.
…ble, 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).
@github-actions github-actions Bot added the cla-signed The CLA has been signed as part of this PR - added by GA label Aug 21, 2026
@doucla Douglas Clark (doucla) added this to the Autumn 2026 milestone Aug 21, 2026
@doucla Douglas Clark (doucla) added the Linked UM This PR is linked to a MetOffice/um PR label Aug 21, 2026
@maggiehendry

Copy link
Copy Markdown
Collaborator

Katie Blackford (@KatieBlackford), Douglas Clark (@doucla) I was just wondering if you'd seen what I'd noted in relation to LFRic apps? If you need me to run the lfric_coupled_developer testing let me know.

@doucla

Copy link
Copy Markdown
Contributor

o

Maggie - yes, thanks, we saw your comments relating to LFRic apps. We have made various tweaks recently but are also investigating some unexpected (bad!) behaviour that we found in more recent tests - we're trying to understand what's going on before hopefully completing this work/PR.

…is done by no longer cominging the abstraction with the surface runoff field, but instead keeping abstractions separate.

net_abstracted_river_rp is now passed into SUBROUTINE rivers_route_rp (now with units of kg rather than kg m-2).
Note that the treatment of negative runoff in RFM has now reverted to how it looked at approx vn7.9, BEFORE we started to incorporate abstractions.
@doucla

Copy link
Copy Markdown
Contributor

Sonja (@sfolwell) - we have had to make a few late changes on this branch since your review, primarily to stop the occurrence of negative river stores. I think the changes Oct 12-14 are most relevant here. Broadly, although the abstraction from rivers was calculated to avoid taking more water than is available (at the start of the timestep), if we look at the TRIP code (rivers_route_trip_mod.F90) the store was also being reduced by the outflow over the timestep - and the sum of those (abstraction and outflow) could result in store < 0. (Remember that the abstraction term was being combined with the surface runoff, for "convenience" [so we thought].)

The solution has been to keep the abstraction separate from surface runoff, and to remove the abstraction as a separate action before any other river flow calculations are done. This has removed the problem of negative stores, without affecting the positive results seen in all other aspects of our testing.

I'm not suggesting that you need to redo your review! But perhaps you could take a look and indicate your continued approval via a comment. Thanks!

@doucla Douglas Clark (doucla) added the Linked Apps This PR is linked to a MetOffice/lfric_apps PR label Oct 15, 2026

@maggiehendry Maggie (maggiehendry) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a possible issue with memory corruption when l_oasis_rivers. I tried to test this with the LFRic apps branch, but they are at incompatible revisions. To be compatible this branch needs to be upgraded to at least 332ca85. Please see MetOffice/lfric_apps#859 (comment). This branch also needs to be tested with the JULES group in the UM Rose stem tests. The UM branch is also not at a compatible revision (see https://github.com/MetOffice/um/pull/121#issuecomment-6273619299).

I haven't finished reviewing this as I haven't had a chance yet to look at the ancillaries, dump & model interface changes. I am most likely out of the office until Thursday so I thought I'd submit this now and start a new review on Thursday.

Comment thread doc/source/namelists/ancillaries.nml.rst
Comment thread doc/source/namelists/initial_conditions.nml.rst Outdated
Comment on lines +452 to +454
.. 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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to check that this is actually the case. It might be missing data.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor_res_storage is initialised to zero (see jules_rivers_props_mod).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialising to zero in this way follows the general pattern that is used for river-related variables (which in general do not have the full flexibility that land-point variables have in terms of ways they can be initialised; from memory the only options are to read from a dump file or be set to zero).

Comment thread doc/source/output-variables.rst Outdated
Comment thread doc/source/output-variables.rst
Comment thread src/control/shared/surf_couple_rivers_mod.F90 Outdated
Comment thread src/control/shared/surf_couple_rivers_mod.F90 Outdated
Comment on lines +78 to +83
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).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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).
REAL(KIND=real_jlslsm), INTENT(IN) :: &
abstracted_minor_res_rp(:), &
! Water abstracted from minor reservoirs over river timestep, on river
! points (kg).
net_abstracted_river_rp(:)
! Water abstracted from rivers over river timestep, on river points (kg).

When l_oasis_rivers these are allocated with a size of 1, not np_rivers. Passing an explicit shape array of the wrong size will end up in the memory being corrupted so just pass as assumed shape.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested changes have been applied in latest commit (97312c9)

! Array arguments with INTENT(IN)
!------------------------------------------------------------------------------
REAL(KIND=real_jlslsm), INTENT(IN) :: &
abstracted_minor_res_rp(np_rivers), &

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also is size 1 when l_oasis_rivers. Probably safer to pass all as assumed size. I can't test this as this branch is three revisions behind the associated LFRic apps branch. This branch will need updating to at least 332ca85 in order to test with the LFRic apps branch.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to abstracted_minor_res_rp(:) in latest commit (97312c9) and branch has also bee updated to 332ca85 in commit 1e14805.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

James Bruten (@james-bruten-mo). This isn't called unless l_minor_reservoirs = T and currently the metadata makes l_minor_reservoirs unavailable when the parent model is the OASIS coupler when l_oasis_rivers = T. The code when l_oasis_rivers, abstracted_minor_res_rp is allocated with size 1, but the loop is i = 1, np_rivers with abstracted_minor_res_rp(i) which will currently go out of bounds if it ever does get called in the future. What is best to do here? I'm questioning the assumed vs explicit shape here as it'll be out-of-bounds regardless. If it isn't called does it matter if abstracted_minor_res_rp has a different size to what is allocated? An parallel ereport should be added to src/control/standalone/check_unavailable_options_mod.F90 for the l_oasis_rivers and l_minor_reservoirs combinations, which I'll request.


REAL(KIND=real_jlslsm), INTENT(IN) :: &
! arrays with intent(in)
net_abstracted_river_rp(np_rivers), &

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comments regarding allocated size.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to net_abstracted_river_rp(:) in latest commit (97312c9)

Co-authored-by: Maggie <145924708+maggiehendry@users.noreply.github.com>
@yaswant
Yaswant Pradhan (yaswant) removed the request for review from a team October 22, 2026 12:25
@maggiehendry

Copy link
Copy Markdown
Collaborator

Apologies. I haven't looked through your review changes yet. I have managed to do the UM & LFRic apps testing which didn't highlight any memory issues. However, there are a few bugs which I've fixed in a bob in order to run the UM & LFRic apps testing (see d874fb6). These will need adding to your branch. Please see the dr hook issues described in https://github.com/MetOffice/um/pull/121#pullrequestreview-5625351448 which will also need fixing.

@KatieBlackford

Copy link
Copy Markdown
Author

Apologies. I haven't looked through your review changes yet. I have managed to do the UM & LFRic apps testing which didn't highlight any memory issues. However, there are a few bugs which I've fixed in a bob in order to run the UM & LFRic apps testing (see d874fb6). These will need adding to your branch. Please see the dr hook issues described in MetOffice/um#121 (review) which will also need fixing.

These problems should now have been addressed in the latest 2 commits.

@maggiehendry Maggie (maggiehendry) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor items plus questions for James Bruten (@james-bruten-mo) (CR). Still to review the I/O (dump, initial conditions etc.) and will start another review for this for expediency.

Comment thread doc/source/output-variables.rst Outdated
| | 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 |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| ``minor_res_frac`` | Catchment area of minor reservoirs as fraction of area of gridbox. | np_rivers |
| ``minor_res_frac`` | Catchment area of minor reservoirs as fraction of area of gridbox. | np_rivers |

Sorry, there's too many spaces now. Doc doesn't build with:

doc/source/output-variables.rst:420: ERROR: Malformed table.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit af24399.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit af24399.

! Array arguments with INTENT(IN)
!------------------------------------------------------------------------------
REAL(KIND=real_jlslsm), INTENT(IN) :: &
abstracted_minor_res_rp(np_rivers), &

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

James Bruten (@james-bruten-mo). This isn't called unless l_minor_reservoirs = T and currently the metadata makes l_minor_reservoirs unavailable when the parent model is the OASIS coupler when l_oasis_rivers = T. The code when l_oasis_rivers, abstracted_minor_res_rp is allocated with size 1, but the loop is i = 1, np_rivers with abstracted_minor_res_rp(i) which will currently go out of bounds if it ever does get called in the future. What is best to do here? I'm questioning the assumed vs explicit shape here as it'll be out-of-bounds regardless. If it isn't called does it matter if abstracted_minor_res_rp has a different size to what is allocated? An parallel ereport should be added to src/control/standalone/check_unavailable_options_mod.F90 for the l_oasis_rivers and l_minor_reservoirs combinations, which I'll request.

* 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)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an ereport to src/control/standalone/check_unavailable_options_mod.F90 for l_oasis_rivers and l_minor_reservoirs (and similarly for l_water_resources) as I don't think there's anything in the code that'll prevent this scenario (jules_water_resources currently isn't read by Rivers-standalone, but for completeness please add so it's obvious they can't be used together). Perhaps mention in the message that relevant arrays would need allocating at full size. The metadata already makes this combination unavailable.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added two new ereport to src/control/standalone/check_unavailable_options_mod.F90 in commit af24399.

REAL(KIND=real_jlslsm), INTENT(IN) :: &
! arrays with intent(in)
net_abstracted_river_rp(np_rivers), &
net_abstracted_river_rp(:), &

@maggiehendry Maggie (maggiehendry) Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

James Bruten (@james-bruten-mo) can we have your expert advice on this please. When this routine is called when l_oasis_rivers=T (Rivers-standalone coupled via OASIS) net_abstracted_river_rp has size 1, otherwise it has size np_rivers. There's a loop i = 1, np_rivers with net_abstracted_river_rp(i) but the loop is only entered when sw_river_source > 0, which will only be the case if l_water_resources=T. This currently cannot happen as l_water_resources=F for Rivers-standalone as init_jules_water_resources is currently not called so jules_water_resources isn't read. Does it matter what size of array is passed? I had originally suggested it would be better passing as assumed size as a result of the mismatch in size. I'm now wondering. Similarly for RFM routine. Also see comment regarding src/science/river_routing/route_minor_reservoirs_mod.F90.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to say that it would be great to have some sort of standard advice (documented) as to how to proceed with this kind of issue (e.g. we have had previous email discussions - which I can't currently find - around what to do with assumed-size arrays and the likes). But that (wider) advice can wait for now!

Is there any danger if we declare as assumed size here? (I prefer to avoid assumed size where possible, but where the size depends on the configuration as here they seem like the possible answer.) As Maggie says, the IF clauses should protect it from ever being run, and I (possibly naively) feel that assumed size would avoid any memory access issues when it is size=1.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really sure. I imagine it doesn't make much difference either way given the if statements. I think I'd edge towards assumed size here, given its configuration dependent.

@maggiehendry Maggie (maggiehendry) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now had a look at the dump IO and all looks fine 😄. Just comments, no action required.

  • I'd strongly encourage you to add a Rose stem test otherwise your work may be broken by someone else.
  • To make you aware, I will be having a look at the design of the initialisation of the Rivers required vars soon as LFRic coupled requires some additional functionality.
  • In general, need to consider whether the water resources code should be made available to Rivers-standalone. Obviously not one for now but something to consider. I've mentioned this PR to Dan Copsey (@DanCopsey) in an email.

! 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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced that this is the best place to allocate land point arrays, but as I need to sort out all the array allocation anyway I'm not going to think overly about it now.

@maggiehendry

Copy link
Copy Markdown
Collaborator

Apologies. I haven't looked through your review changes yet. I have managed to do the UM & LFRic apps testing which didn't highlight any memory issues. However, there are a few bugs which I've fixed in a bob in order to run the UM & LFRic apps testing (see d874fb6). These will need adding to your branch. Please see the dr hook issues described in MetOffice/um#121 (review) which will also need fixing.

These problems should now have been addressed in the latest 2 commits.

drhook_check now passes in UM Rose stem 😃

@doucla

Copy link
Copy Markdown
Contributor

I've now had a look at the dump IO and all looks fine 😄. Just comments, no action required.

  • I'd strongly encourage you to add a Rose stem test otherwise your work may be broken by someone else.
  • To make you aware, I will be having a look at the design of the initialisation of the Rivers required vars soon as LFRic coupled requires some additional functionality.
  • In general, need to consider whether the water resources code should be made available to Rivers-standalone. Obviously not one for now but something to consider. I've mentioned this PR to Dan Copsey (Dan Copsey (@DanCopsey)) in an email.

Agreed re rose stem - this is already on my "tracker" issue #183 .

Re rivers-standalone - just to note that in "true standalone mode" (i.e. just a river model, not coupled to anything) there probably is no (or very limited) use for the water resource (WR) code as most bits require some sort of input from the land code (e.g. to calculate abstractions from reservoirs). In coupled mode (e.g. in LFRic) the WR functionality is potentially useful - though whether it has to be contemplated any time soon is another question. (Not sure that helps you at all here, but I just thought I would attempt to clarify!)

@DanCopsey

Copy link
Copy Markdown
Contributor

I've now had a look at the dump IO and all looks fine 😄. Just comments, no action required.

  • I'd strongly encourage you to add a Rose stem test otherwise your work may be broken by someone else.
  • To make you aware, I will be having a look at the design of the initialisation of the Rivers required vars soon as LFRic coupled requires some additional functionality.
  • In general, need to consider whether the water resources code should be made available to Rivers-standalone. Obviously not one for now but something to consider. I've mentioned this PR to Dan Copsey (Dan Copsey (Dan Copsey (@DanCopsey))) in an email.

Agreed re rose stem - this is already on my "tracker" issue #183 .

Re rivers-standalone - just to note that in "true standalone mode" (i.e. just a river model, not coupled to anything) there probably is no (or very limited) use for the water resource (WR) code as most bits require some sort of input from the land code (e.g. to calculate abstractions from reservoirs). In coupled mode (e.g. in LFRic) the WR functionality is potentially useful - though whether it has to be contemplated any time soon is another question. (Not sure that helps you at all here, but I just thought I would attempt to clarify!)

Thanks for the heads up about the minor reservoirs and water resources code. I think our plan for the LFRic coupled climate model is to eventually move to using Camaflood so we may have no need for this but it looks good though.

…asis_rivers and l_minor_reservoirs / l_water_resources to check_unavailable_options_mod.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The CLA has been signed as part of this PR - added by GA Linked Apps This PR is linked to a MetOffice/lfric_apps PR Linked UM This PR is linked to a MetOffice/um PR macro This PR contains a metadata upgrade macro

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add minor reservoirs to hydrology (old ticket #1123)

9 participants