Skip to content

Commit 0c32e61

Browse files
committed
s20 diag thickness
1 parent 0b1651e commit 0c32e61

8 files changed

Lines changed: 358 additions & 9 deletions

File tree

CONTRIBUTORS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributors
2-
| GitHub user | Real Name | Affiliation | Date |
3-
| ------------------- | ------------------ | -------------------------------- | ---------- |
2+
| GitHub user | Real Name | Affiliation | Date |
3+
|---------------------|---------------------| -------------------------------- |------------|
44
| james-bruten-mo | James Bruten | Met Office | 2025-12-09 |
55
| jedbakerMO | Jed Baker | Met Office | 2025-12-29 |
66
| jennyhickson | Jenny Hickson | Met Office | 2025-12-10 |
@@ -9,6 +9,7 @@
99
| mo-rickywong | Ricky Wong | Met Office | 2026-24-02 |
1010
| yaswant | Yaswant Pradhan | Met Office | 2025-12-16 |
1111
| oakleybrunt | Oakley Brunt | Met Office | 2025-12-19 |
12+
| bblay-mo | Byron Blay | Met Office | 2026-01-07 |
1213
| harry-shepherd | Harry Shepherd | Met Office | 2026-01-08 |
1314
| DrTVockerodtMO | Terence Vockerodt | Met Office | 2026-01-08 |
1415
| ricky-lv426 | Ricky Olivier | University of Exeter | 2026-01-12 |

applications/lfric_atm/example/iodef.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@
9494
<field field_ref="forcing__dt_force" />
9595
</file>
9696

97+
<file id="lf_diag_aviation" name="lf_diag_aviation" output_freq="6h" convention="UGRID" enabled=".TRUE.">
98+
<field field_ref="aviation__geopot_thickness_850"/>
99+
<field field_ref="aviation__geopot_thickness_500"/>
100+
</file>
101+
97102
<file id="lfric_averages" name="lfric_averages" output_freq="12h" convention="UGRID" enabled=".TRUE.">
98103
<field field_ref="theta" operation="average" />
99104
<field field_ref="exner" operation="average" />

applications/lfric_atm/metadata/field_def_diags.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,11 @@
991991
<!-- Vertical integrals -->
992992
<field id="processed__sw_aer_optical_depth_rts" field_ref="radiation__sw_aer_optical_depth_rts" grid_ref="vert_sum_face_grid"/>
993993
<field id="processed__lw_aer_optical_depth_rts" field_ref="radiation__lw_aer_optical_depth_rts" grid_ref="vert_sum_face_grid"/>
994+
995+
<!-- Aviation diagnostics -->
996+
<field id="aviation__geopot_thickness_850" name="aviation_geopot_thickness_850" standard_name="atmosphere_layer_thickness_expressed_as_geopotential_height_difference" long_name="geopotential_height_thickness_between_1000hPa_and_850hPa" unit="m" domain_ref="face"/>
997+
<field id="aviation__geopot_thickness_500" name="aviation_geopot_thickness_500" standard_name="atmosphere_layer_thickness_expressed_as_geopotential_height_difference" long_name="geopotential_height_thickness_between_1000hPa_and_500hPa" unit="m" domain_ref="face"/>
998+
994999
</field_group>
9951000

9961001
<!-- Integer diagnostic group -->
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
!-----------------------------------------------------------------------------
2+
! (C) Crown copyright 2025 Met Office. All rights reserved.
3+
! The file LICENCE, distributed with this code, contains details of the terms
4+
! under which the code may be used.
5+
!-----------------------------------------------------------------------------
6+
!
7+
! The main entry point for calculating section 20 aviation diagnostics.
8+
!
9+
! Code Owner: Please refer to the UM file CodeOwners.txt
10+
! This file currently belongs in section: physics_schemes_interface
11+
! whilst discussions are ongoing about its final location.
12+
!
13+
MODULE aviation_diags_alg_mod
14+
15+
USE constants_mod, ONLY: r_def, i_def, l_def, str_long
16+
USE field_mod, ONLY: field_type
17+
USE io_config_mod, ONLY: USE_xios_io
18+
USE initialise_diagnostics_mod, ONLY: init_diag => init_diagnostic_field
19+
20+
USE lfric_xios_diag_mod, ONLY: get_axis_dimension, get_axis_values
21+
USE log_mod, ONLY: log_event, log_scratch_space, &
22+
LOG_LEVEL_ALWAYS, LOG_LEVEL_ERROR, &
23+
LOG_LEVEL_INFO, LOG_LEVEL_DEBUG
24+
25+
USE aviation_diags_kernel_mod, ONLY: aviation_diags_kernel_type
26+
27+
IMPLICIT NONE
28+
29+
PRIVATE
30+
PUBLIC :: aviation_diags_alg
31+
32+
CONTAINS
33+
34+
! Algorithm to calculate the section 20 aviation diagnostics.
35+
SUBROUTINE aviation_diags_alg(plev_geopot)
36+
37+
IMPLICIT NONE
38+
39+
! Arguments
40+
41+
! We calculate the result from this input field.
42+
TYPE(field_type), INTENT(IN) :: plev_geopot
43+
44+
45+
! Local variables
46+
47+
! These flags tell us which results are requested at this time step.
48+
LOGICAL(l_def) :: aviation_thick_850_flag, aviation_thick_500_flag
49+
50+
! The array of pressure levels.
51+
INTEGER(I_DEF) :: nplev
52+
REAL(R_DEF), ALLOCATABLE :: plevs(:)
53+
INTEGER(I_DEF) :: plevs_alloc_stat
54+
55+
! Level indices for the three pressure levels we want to read.
56+
INTEGER(I_DEF) :: i1000, i850, i500
57+
58+
! Approximate equality tolerance - is there a common variable somewhere?
59+
REAL(R_DEF), PARAMETER :: plev_tol = 0.1_r_def
60+
61+
! The two output fields we produce.
62+
TYPE( field_type ) :: aviation_thick_850, aviation_thick_500
63+
64+
INTEGER(I_DEF) :: i
65+
66+
character(len=str_long) :: message
67+
68+
69+
! Check the request flags.
70+
aviation_thick_850_flag = &
71+
init_diag(aviation_thick_850, 'aviation__geopot_thickness_850')
72+
aviation_thick_500_flag = &
73+
init_diag(aviation_thick_500, 'aviation__geopot_thickness_500')
74+
75+
! Anything to do?
76+
IF ( .NOT. (aviation_thick_850_flag .OR. aviation_thick_500_flag) ) THEN
77+
! Nothing requested at this time step.
78+
RETURN
79+
END IF
80+
81+
IF ( .NOT. use_xios_io ) THEN
82+
RETURN
83+
ENDIF
84+
85+
! Initialise required fields to 1. Todo: Why 1 and not 0?
86+
IF ( aviation_thick_850_flag ) THEN
87+
message = 'Section 20: geopot thick 850 requested'
88+
CALL log_event( message, LOG_LEVEL_DEBUG )
89+
CALL invoke( setval_c(aviation_thick_850, 1.0_r_def))
90+
END IF
91+
92+
IF ( aviation_thick_500_flag ) THEN
93+
message = 'Section 20: geopot thick 500 requested'
94+
CALL log_event( message, LOG_LEVEL_DEBUG )
95+
CALL invoke( setval_c(aviation_thick_500, 1.0_r_def))
96+
END IF
97+
98+
99+
! Get the array of pressure levels.
100+
nplev = get_axis_dimension('pressure_levels')
101+
IF (nplev <= 0) THEN
102+
message = 'Section 20: No pressure levels'
103+
CALL log_event( message, LOG_LEVEL_DEBUG )
104+
RETURN
105+
END IF
106+
107+
ALLOCATE(plevs(nplev), stat=plevs_alloc_stat)
108+
IF (plevs_alloc_stat /= 0) THEN
109+
message = 'Section 20: allocate(plevs) failed'
110+
CALL log_event( message, LOG_LEVEL_DEBUG )
111+
112+
RETURN
113+
END IF
114+
plevs = get_axis_values('pressure_levels',nplev)
115+
116+
! Find the level indices for our three pressures of interest.
117+
! Assumes hPa.
118+
i1000 = -1
119+
i850 = -1
120+
i500 = -1
121+
DO i = 1, nplev
122+
123+
! 1000?
124+
IF ( abs(plevs(i) - 100000.0_r_def) < plev_tol ) THEN
125+
i1000 = i
126+
127+
! 850?
128+
ELSE IF ( abs(plevs(i) - 85000.0_r_def) < plev_tol ) THEN
129+
i850 = i
130+
131+
! 500?
132+
ELSE IF ( abs(plevs(i) - 50000.0_r_def) < plev_tol ) THEN
133+
i500 = i
134+
135+
END IF
136+
END DO
137+
138+
! Check we found the required levels.
139+
IF (i1000 == -1) THEN
140+
message = 'Section 20: could not find 1000hPa'
141+
CALL log_event( message, LOG_LEVEL_INFO )
142+
RETURN
143+
END IF
144+
145+
IF (aviation_thick_850_flag .AND. i850 == -1) THEN
146+
message = 'Section 20: could not find 850hPa'
147+
CALL log_event( message, LOG_LEVEL_INFO )
148+
RETURN
149+
END IF
150+
151+
IF (aviation_thick_500_flag .AND. i500 == -1) THEN
152+
message = 'Section 20: could not find 500hPa'
153+
CALL log_event( message, LOG_LEVEL_INFO )
154+
RETURN
155+
END IF
156+
157+
! Call the kernel to subtract the levels.
158+
! Todo: Comment why we initialise to 1.0 and not 0.0. I can't remember.
159+
CALL invoke( aviation_diags_kernel_type( &
160+
aviation_thick_850, aviation_thick_500, &
161+
plev_geopot, &
162+
aviation_thick_850_flag, aviation_thick_500_flag, &
163+
i1000, i850, i500))
164+
165+
! Write the fields
166+
IF (aviation_thick_850_flag) CALL aviation_thick_850%write_field()
167+
IF (aviation_thick_500_flag) CALL aviation_thick_500%write_field()
168+
169+
! Clean up.
170+
IF (allocated(plevs)) THEN
171+
DEALLOCATE(plevs)
172+
END IF
173+
174+
END SUBROUTINE aviation_diags_alg
175+
176+
END MODULE aviation_diags_alg_mod

interfaces/physics_schemes_interface/source/algorithm/pres_lev_diags_alg_mod.x90

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ contains
4343
!> @param[in] exner_w3 Exner pressure
4444
!> @param[in] mr Mixing ratio bundle
4545
!> @param[in] moist_dyn Moist_dynamics factors (for 1+sum(m_x))
46+
!> @param[out] plev_geopot Geopotential height on pressure levels
4647
subroutine pres_lev_diags_alg(derived_fields, theta_wth, exner_w3, &
47-
mr, moist_dyn)
48+
mr, moist_dyn, plev_geopot)
4849

4950
use psykal_lite_phys_mod, only: invoke_pres_interp_kernel_type, &
5051
invoke_heaviside_kernel_type, &
@@ -59,6 +60,7 @@ contains
5960
type( field_type ), intent(in) :: theta_wth, exner_w3
6061
type( field_type ), intent(in) :: mr(nummr)
6162
type( field_type ), intent(in) :: moist_dyn(num_moist_factors)
63+
type( field_type ), intent(out) :: plev_geopot
6264
! Internal variables
6365
type( field_type ), pointer :: exner_wth
6466
type( field_type ), pointer :: u_in_w3
@@ -70,7 +72,7 @@ contains
7072

7173
! Define fields
7274
type( field_type ) :: plev_heaviside, plev_temp, plev_u, plev_v, &
73-
plev_w, plev_geopot, temp, omega, plev_omega, plev_mv, plev_qv, qv, &
75+
plev_w, temp, omega, plev_omega, plev_mv, plev_qv, qv, &
7476
plev_thetaw, plev_temp_save
7577
integer(i_def) :: nplev
7678
real(r_def) :: minus_g
@@ -81,9 +83,13 @@ contains
8183
plev_u_flag, plev_u_clim_flag, plev_v_flag, plev_v_clim_flag, &
8284
plev_w_flag, plev_w_clim_flag, plev_omega_clim_flag, &
8385
plev_mv_clim_flag, plev_qv_clim_flag, &
84-
plev_geopot_flag, plev_geopot_clim_flag, plev_thetaw_flag
86+
plev_geopot_flag, plev_geopot_clim_flag, plev_thetaw_flag, &
87+
aviation_thickness_flag
8588
integer(tik) :: id
8689

90+
! For code tidiness, combines all flags requiring plev_geopot.
91+
logical(l_def) :: plev_gepot_required
92+
8793
if ( LPROF ) call start_timing( id, 'diags.pressure_lev' )
8894

8995
nplev = get_axis_dimension('pressure_levels')
@@ -257,9 +263,16 @@ contains
257263
end if
258264

259265
! Geopotential height on pressure levels
266+
aviation_thickness_flag = diag_samp('aviation__geopot_thickness_850') .or. &
267+
diag_samp('aviation__geopot_thickness_500')
260268
plev_geopot_clim_flag = diag_samp('plev__geopot_clim')
261-
plev_geopot_flag = init_diag(plev_geopot, 'plev__geopot', activate=plev_geopot_clim_flag)
262-
if ((plev_geopot_flag .or. plev_geopot_clim_flag) .and. use_xios_io) then
269+
plev_geopot_flag = init_diag(plev_geopot, 'plev__geopot', &
270+
activate=plev_geopot_clim_flag .or. aviation_thickness_flag)
271+
272+
plev_gepot_required = plev_geopot_flag .or. &
273+
plev_geopot_clim_flag .or. &
274+
aviation_thickness_flag
275+
if (plev_gepot_required .and. use_xios_io) then
263276

264277
height_w3 => get_height_fv(W3, exner_w3%get_mesh_id())
265278
call invoke_geo_on_pres_kernel_type(height_w3, exner_w3, theta_wth, &

0 commit comments

Comments
 (0)