Skip to content

Diagnostics required by lfric2um for PS49 - #658

Open
iboutle wants to merge 21 commits into
MetOffice:mainfrom
iboutle:new_diags
Open

Diagnostics required by lfric2um for PS49#658
iboutle wants to merge 21 commits into
MetOffice:mainfrom
iboutle:new_diags

Conversation

@iboutle

@iboutle iboutle commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

PR Summary

Sci/Tech Reviewer: Martin Best (@mo-martinbest)
Code Reviewer: Matthew Hambley (@MatthewHambley)

This change add the following diagnostics that have been requested by lfric2um for driving the UKV & Mogreps-UK at PS49, and other downstream uses from PS49 itself:

UM stashcode LFRic diagnostic
26 surface__z0m_sea
32 seaice__ice_mean_thickness
49 seaice__ice_mean_temperature
507 surface__sea_temperature
508 surface__sea_ice_surface_temperature
242 snow__snow_under_canopy
380 snow__n_snow_layers
279 soil__soil_sat_frac
281 soil__wetness_under_soil
3-228 surface__sea_mean_heat_flux
3-232 surface__sea_mean_moisture_flux
3-235 seaice__ssi_mean_topmelt_heat_flux
3-343 surface__ssi_mean_heat_flux
3-542 surface__land_mean_heat_flux
3-543 surface__land_mean_latent_heat
3-544 surface__ssi_mean_latent_heat

We have also fixed the calucation of stash 31 / surface__sea_ice_fraction and 505 / surface__land_fraction to be correct for coupled models with 5 sea-ice categories (previously these were only correct for a single sea-ice category)

ecb42cc has been tagged as tag3.1_new_diags for use at vn3.1

Some example output of the new diagnostics to prove they work:
Screenshot from 2026-07-23 16-37-24
Screenshot from 2026-07-23 16-36-36
Screenshot from 2026-07-23 16-36-14
Screenshot from 2026-07-23 16-35-42
Screenshot from 2026-08-12 09-34-21
Screenshot from 2026-08-11 09-52-04Screenshot from 2026-08-11 09-51-28
Screenshot from 2026-08-11 15-42-58Screenshot from 2026-08-11 15-13-53
Screenshot from 2026-08-11 15-41-29Screenshot from 2026-08-11 15-41-04
Screenshot from 2026-08-11 15-40-07Screenshot from 2026-08-11 15-39-32

Code Quality Checklist

  • 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
  • All automated checks in the CI pipeline have completed successfully

Testing

  • I have tested this change locally, using the LFRic Apps rose-stem suite
  • If any tests fail (rose-stem or CI) the reason is understood and acceptable (e.g. kgo changes)
  • I have added tests to cover new functionality as appropriate (e.g. system tests, unit tests, etc.)
  • Any new tests have been assigned an appropriate amount of compute resource and have been allocated to an appropriate testing group (i.e. the developer tests are for jobs which use a small amount of compute resource and complete in a matter of minutes)

trac.log

Test Suite Results - lfric_apps - new_diags/run3

Suite Information

Item Value
Suite Name new_diags/run3
Suite User ian.boutle
Workflow Start 2026-08-11T12:49:48
Groups Run developer', 'lfric_atm_nwp_gal9_oper-C224_MG_ex1a_cce_production-32bit
Dependency Reference Main Like
casim MetOffice/casim@2026.07.1 True
jules MetOffice/jules@2026.07.1 True
lfric_apps iboutle/lfric_apps@new_diags False
lfric_core MetOffice/lfric_core@2026.07.1 True
moci MetOffice/moci@2026.07.1 True
SimSys_Scripts MetOffice/SimSys_Scripts@2026.07.1 True
socrates MetOffice/socrates@2026.07.1 True
socrates-spectral MetOffice/socrates-spectral@2026.07.1 True
ukca MetOffice/ukca@2026.07.1 True

Task Information

✅ succeeded tasks - 1213

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

PSyclone Approval

  • If you have edited any PSyclone-related code (e.g. PSyKAl-lite, Kernel interface, optimisation scripts, LFRic data structure code) then please contact the TCD Team

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

@iboutle iboutle self-assigned this Jul 23, 2026
@iboutle iboutle added this to the Autumn 2026 milestone Jul 23, 2026
@github-actions github-actions Bot added the cla-modified The CLA has been modified as part of this PR - added by GA label Jul 23, 2026
@iboutle
iboutle marked this pull request as ready for review July 24, 2026 14:17
@iboutle

iboutle commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Just going to grab this back as a few more have cropped up that make sense to add here

Ubuntu and others added 11 commits August 10, 2026 14:45
Adds surface__sea_heat_flux and surface__sea_moisture_flux, equivalent
to UM STASH 3-228 SFC SH FLX FROM OPEN SEA:SEA MN and 3-232 EVAP FROM
OPEN SEA: SEA MEAN.

This is an XML-only change. The open-sea tile is extracted from the
existing surface__tile_heat_flux and surface__tile_moisture_flux fields
using the surface_tiles_sea_zoom axis, then the pseudo-level coordinate
is dropped, following the pattern already used for surface__sea_tile and
surface__sea_temperature.

A third field is then needed for each because the UM diagnostics are sea
means. JULES applies h_sea = (1 - ice_fract) * h_sea and the equivalent
for e_sea in the "Calculate sea mean diagnostics" block of
jules_ssi_sf_implicit, so the flux is averaged over the whole sea
portion of the grid-box with the sea-ice part contributing zero. The
LFRic tiled fluxes are per unit open water, being formed as a residual
divided by the open-sea tile fraction, so they are multiplied by
(1 - surface__sea_ice_fraction) to match. The rescaling cannot be
combined with the earlier steps as it needs both operands on the same
grid.

Some of the content of this change has been produced with the assistance
of Anthropic Claude Opus 5 (Claude Code).
Adds seaice__sea_mean_topmelt_heat_flux, equivalent to UM STASH 3-235
SEAICE TOP MELT LH FLX:SEA MEAN.

Unlike the open sea flux diagnostics this cannot be done in XML alone.
The UM sums sf_diag%sice_mlt_htf over the sea-ice categories, but LFRic
never sets sf_diag%simlt so that array is never filled. The underlying
melt rate is available though, as fluxes%sice_melt is copied onto the
sea-ice tiles of snowice_melt in jules_imp_kernel_mod, so the diagnostic
is reconstructed from there. Averaging over the tiles has to be done in
the code rather than in XIOS, following the precedent set for
surface__sea_ice_tile.

The tile order is land, sea, sea-ice, so averaging the tiled melt rate
over the sea and sea-ice tiles, weighted by their fractions, divides by
the marine fraction of the grid-box. This gives the ice_fract_ncat
weighting the UM applies in jules_ssi_sf_implicit directly, with no
rescaling needed in XML, because jules_imp_kernel_mod sets the melt rate
on the sea tile to zero and so only the sea-ice contributes to the sum.
The latent heat of fusion then converts the melt rate to an energy flux.

Note this covers only the surface melt contribution. The second term the
UM accumulates in sice_htf, where the ice surface temperature overshoots
the melting point, has no LFRic equivalent as sice_htf is never called.

Some of the content of this change has been produced with the assistance
of Anthropic Claude Opus 5 (Claude Code).
Adds surface__land_mean_heat_flux and surface__land_mean_latent_heat,
the surface sensible and latent heat fluxes averaged over the land
portion of the grid-box, matching the UM's land-mean surface flux
diagnostics.

Both are computed with weighted_ave_kernel_type over the land tiles,
weighted by the grid-box tile fractions.  Because the land tile
fractions sum to the land fraction, that average divides by the land
fraction and so reproduces the UM sum over land tiles of the tiled flux
weighted by the land-relative tile fraction: LFRic's tile_fraction is a
grid-box fraction, and the JULES interface divides it by the land
fraction when it fills frac_surft.  The tiled fields used are the same
ones the UM sums, ftl_surft and le_surft.

The latent heat flux is only accumulated when it has been requested, so
the new diagnostic is added to the existing test that activates it, and
both diagnostics are output on the second loop only, alongside the
other tile-averaged diagnostics.

The two fields are added to the lfric_atm field definitions and to the
hourly instantaneous group of the operational global output stream,
alongside the other grid-mean surface fluxes there.

Some of the content of this change has been produced with the
assistance of Anthropic Claude Opus 5 (Claude Code).
Adds surface__ssi_mean_heat_flux and surface__ssi_mean_latent_heat, the
surface sensible and latent heat fluxes averaged over the sea and
sea-ice portion of the grid-box, matching the UM's mean sea surface
sensible heat flux and its open sea and sea-ice latent heat flux.

Both are computed with weighted_ave_kernel_type over the sea and
sea-ice tiles, weighted by the grid-box tile fractions.  The tile order
is land, sea, sea-ice, so those tiles are contiguous, and because their
fractions sum to the marine fraction the average divides by it and so
gives a mean over the marine portion of the grid-box.

For the sensible heat flux this reproduces the UM residual, the
grid-box mean flux less the land contribution divided by the marine
fraction, because the interface fills the sea tile with exactly the
residual needed to make the tile fractions and tiled fluxes recover the
grid-box mean.  For the latent heat flux it reproduces the UM sum of
the sea-mean evaporation and sea-ice sublimation terms, since JULES
rescales those by fractions of the sea whereas the tile fractions here
are fractions of the grid-box.

The two fields are added to the lfric_atm field definitions and to the
hourly instantaneous group of the operational global output stream,
alongside the land means.

Some of the content of this change has been produced with the
assistance of Anthropic Claude Opus 5 (Claude Code).
The diagnostics that average over the marine portion of the grid-box
each worked out the number of sea plus sea-ice tiles for themselves.
Derive it once as n_ssi_tile in jules_control_init, alongside the other
tile counts and indices, and use it from jules_imp_diags and
jules_seaice_diags.

n_surf_tile is now expressed in terms of it as well, so the two counts
cannot drift apart.

Some of the content of this change has been produced with the
assistance of Anthropic Claude Opus 5 (Claude Code).
The sea tile of z0m_tile is filled from the JULES prognostic z0msea in
jules_exp_kernel_mod, so extracting it needs no new code: a zoom onto
the sea tile in the XML gives the open sea roughness length directly.

Some of the content of this change has been produced with the assistance
of Anthropic Claude Opus 5 (Claude Code).
@iboutle

iboutle commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Martin Best (@mo-martinbest) this is good to go again now - just added a couple more diagnostics in the same vein as the rest (sea-mean and land-mean fluxes)

Adds seaice__ice_mean_thickness and seaice__ice_mean_temperature, the
sea-ice thickness and bulk temperature aggregated from the categories
onto a single level, matching the UM's sea-ice depth and sea-ice
temperature after timestep.  Those two UM fields are the non-category
twins of the by-category thickness and top layer temperature, and are
what the UM uses when only one category is active.

Both are formed with weighted_ave_kernel_type over the sea-ice
categories, weighted by the category fractions, so the kernel divides
by the total ice fraction and returns a mean over the ice.  For the
temperature this is exactly the bulk temperature that sice_htf forms
internally, which is otherwise held only in the JULES prognostic
structure and so cannot be output.  For the thickness the same average
is correct because the category thicknesses are physical depths, as
their use in the conduction term of sice_htf shows, rather than
fraction weighted quantities.

The weights are the sea-ice tile fractions already extracted from the
tile fractions for seaice__sea_ice_fraction.  These are fractions of
the grid-box whereas JULES works in fractions of the marine portion,
but the normalisation cancels in the ratio so the result is unchanged.
Where there is no ice the total weight is zero, the kernel leaves the
output at zero, and both fields should be masked on the ice fraction
before use.

Some of the content of this change has been produced with the
assistance of Anthropic Claude Opus 5 (Claude Code).
@github-actions

Copy link
Copy Markdown

⚠️ Hello iboutle!

Your CLA signature was found on the base branch, but you appear to have modified the CONTRIBUTORS.md file in this PR.

Please do not edit the CONTRIBUTORS.md file. If you have already signed the CLA, revert changes to the file and your signature will be picked up.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This all looks fine to me in with regards tot he Sci review.
Matthew Hambley (@MatthewHambley) passing to you for code review.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm afraid this change does not comply with the LLM policy Not only has an invalid LLM potentially been used but each commit which includes LLM generated code needs to acknowledge that, which I don't see.

This is likely to be time consuming. Files modified by invalid models need to be redeveloped and the branch will need to be restructured with correct attribution in commit messages. This latter point may break the pull request, requiring this one to be closed and a fresh one to be opened.

Comment thread interfaces/jules_interface/source/algorithm/jules_extra_alg_mod.x90
@iboutle

iboutle commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

I'm afraid this change does not comply with the LLM policy Not only has an invalid LLM potentially been used but each commit which includes LLM generated code needs to acknowledge that, which I don't see.

This is likely to be time consuming. Files modified by invalid models need to be redeveloped and the branch will need to be restructured with correct attribution in commit messages. This latter point may break the pull request, requiring this one to be closed and a fresh one to be opened.

Hi Matthew Hambley (@MatthewHambley) - Yaswant Pradhan (@yaswant) was consulted in advance of starting this work, as we're making use of Claude to accelerate work on a large backlog of diagnostics needed for PS49. The wording in the file headers is what we agreed upon, and the LLM policy is in need of an update to show that this is an acceptable usage. Additionally, each commit by Claude is clearly identifiable as a different author to myself.

@iboutle

iboutle commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Matthew Hambley (@MatthewHambley) just noticed #679 - this PR does comply with everything in the modified template (but we've no need to wait for #679 before progressing this). Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-modified The CLA has been modified as part of this PR - added by GA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants