diff --git a/applications/lfric_atm/metadata/field_def_diags.xml b/applications/lfric_atm/metadata/field_def_diags.xml index 5a6a6a360..36f092c6d 100644 --- a/applications/lfric_atm/metadata/field_def_diags.xml +++ b/applications/lfric_atm/metadata/field_def_diags.xml @@ -331,6 +331,7 @@ + diff --git a/interfaces/physics_schemes_interface/source/diagnostics/cld_diags_mod.x90 b/interfaces/physics_schemes_interface/source/diagnostics/cld_diags_mod.x90 index 6b6eb9a40..08e956dd6 100644 --- a/interfaces/physics_schemes_interface/source/diagnostics/cld_diags_mod.x90 +++ b/interfaces/physics_schemes_interface/source/diagnostics/cld_diags_mod.x90 @@ -39,6 +39,7 @@ module cld_diags_mod cld_amount_maxrnd_flag, & ceil_cld_amount_maxrnd_flag, & cld_base_altitude_flag, & + cld_top_altitude_flag, & low_cld_base_altitude_flag, & very_low_cld_amount_flag, & low_cld_amount_flag, & @@ -124,6 +125,7 @@ contains type( field_type ) :: cld_amount_maxrnd type( field_type ) :: ceil_cld_amount_maxrnd type( field_type ) :: cld_base_altitude + type( field_type ) :: cld_top_altitude type( field_type ) :: low_cld_base_altitude type( field_type ) :: very_low_cld_amount type( field_type ) :: low_cld_amount @@ -156,6 +158,7 @@ contains cld_amount_maxrnd_flag = init_diag(cld_amount_maxrnd, 'cloud__cloud_amount_maxrnd') ceil_cld_amount_maxrnd_flag = init_diag(ceil_cld_amount_maxrnd, 'cloud__ceilometer_cloud_amount_maxrnd') cld_base_altitude_flag = init_diag(cld_base_altitude, 'cloud__cloud_base_altitude') + cld_top_altitude_flag = init_diag(cld_top_altitude, 'cloud__cloud_top_altitude') low_cld_base_altitude_flag = init_diag(low_cld_base_altitude, 'cloud__low_cloud_base_altitude') very_low_cld_amount_flag = init_diag(very_low_cld_amount, 'cloud__very_low_type_cloud_amount') low_cld_amount_flag = init_diag(low_cld_amount, 'cloud__low_type_cloud_amount') @@ -176,6 +179,7 @@ contains cld_amount_maxrnd_flag .or. & ceil_cld_amount_maxrnd_flag .or. & cld_base_altitude_flag .or. & + cld_top_altitude_flag .or. & low_cld_base_altitude_flag .or. & very_low_cld_amount_flag .or. & low_cld_amount_flag .or. & @@ -196,6 +200,7 @@ contains cld_amount_maxrnd_flag .or. & ceil_cld_amount_maxrnd_flag .or. & cld_base_altitude_flag .or. & + cld_top_altitude_flag .or. & low_cld_base_altitude_flag .or. & very_low_cld_amount_flag .or. & low_cld_amount_flag .or. & @@ -235,6 +240,7 @@ contains cld_amount_maxrnd_flag .or. & ceil_cld_amount_maxrnd_flag .or. & cld_base_altitude_flag .or. & + cld_top_altitude_flag .or. & low_cld_base_altitude_flag .or. & very_low_cld_amount_flag .or. & low_cld_amount_flag .or. & @@ -256,6 +262,7 @@ contains cld_amount_maxrnd, & ceil_cld_amount_maxrnd, & cld_base_altitude, & + cld_top_altitude, & low_cld_base_altitude, & very_low_cld_amount, & low_cld_amount, & @@ -355,6 +362,7 @@ contains if (cld_amount_maxrnd_flag) call cld_amount_maxrnd%write_field() if (ceil_cld_amount_maxrnd_flag) call ceil_cld_amount_maxrnd%write_field() if (cld_base_altitude_flag) call cld_base_altitude%write_field() + if (cld_top_altitude_flag) call cld_top_altitude%write_field() if (low_cld_base_altitude_flag) call low_cld_base_altitude%write_field() if (very_low_cld_amount_flag) call very_low_cld_amount%write_field() if (low_cld_amount_flag) call low_cld_amount%write_field() diff --git a/interfaces/physics_schemes_interface/source/kernel/cld_diags_kernel_mod.F90 b/interfaces/physics_schemes_interface/source/kernel/cld_diags_kernel_mod.F90 index 9083258ec..20373add8 100644 --- a/interfaces/physics_schemes_interface/source/kernel/cld_diags_kernel_mod.F90 +++ b/interfaces/physics_schemes_interface/source/kernel/cld_diags_kernel_mod.F90 @@ -26,13 +26,14 @@ module cld_diags_kernel_mod !> type, public, extends(kernel_type) :: cld_diags_kernel_type private - type(arg_type) :: meta_args(20) = (/ & + type(arg_type) :: meta_args(21) = (/ & arg_type(GH_FIELD, GH_REAL, GH_READ, WTHETA), & ! combined_cld_amount_wth arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! cld_amount_max arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! cld_amount_rnd arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! cld_amount_maxrnd arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! ceil_cld_amount_maxrnd arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! cld_base_altitude + arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! cld_top_altitude arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! low_cld_base_altitude arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! very_low_cld_amount arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_DISCONTINUOUS_SPACE_1), & ! low_cld_amount @@ -67,6 +68,7 @@ module cld_diags_kernel_mod !> @param[in,out] cld_amount_maxrnd Cloud amount maximum-random overlap !> @param[in,out] ceil_cld_amount_maxrnd Ceilometer filtered cloud amount maximum-random overlap !> @param[in,out] cld_base_altitude Cloud base altitude wrt sea level + !> @param[in,out] cld_top_altitude Cloud top altitude wrt sea level !> @param[in,out] low_cld_base_altitude Cloud base altitude wrt sea level for very low amount of cloud !> @param[in,out] very_low_cld_amount Maximum cloud amount below 111m !> @param[in,out] low_cld_amount Maximum cloud amount between 111 and 1949m above sea level @@ -102,6 +104,7 @@ subroutine cld_diags_code( nlayers, & cld_amount_maxrnd, & ceil_cld_amount_maxrnd, & cld_base_altitude, & + cld_top_altitude, & low_cld_base_altitude, & very_low_cld_amount, & low_cld_amount, & @@ -127,6 +130,7 @@ subroutine cld_diags_code( nlayers, & map_w3 ) use science_conversions_mod, only: feet_to_metres + use missing_data_mod, only: rmdi implicit none @@ -145,6 +149,7 @@ subroutine cld_diags_code( nlayers, & real(kind=r_def), pointer, intent(inout) :: cld_amount_maxrnd(:) real(kind=r_def), pointer, intent(inout) :: ceil_cld_amount_maxrnd(:) real(kind=r_def), pointer, intent(inout) :: cld_base_altitude(:) + real(kind=r_def), pointer, intent(inout) :: cld_top_altitude(:) real(kind=r_def), pointer, intent(inout) :: low_cld_base_altitude(:) real(kind=r_def), pointer, intent(inout) :: very_low_cld_amount(:) real(kind=r_def), pointer, intent(inout) :: low_cld_amount(:) @@ -181,8 +186,8 @@ subroutine cld_diags_code( nlayers, & real(kind=r_def), parameter :: medium_to_high = 5574.0_r_def ! metres ! ... 150 hPa: real(kind=r_def), parameter :: high_to_very_high = 13608.0_r_def ! metres - ! When looking for cloud base: how much cloud cover defines cloud base. - real(kind=r_def), parameter :: cld_cover_for_cld_base = 2.5_r_def/8.0_r_def + ! When looking for cloud base or top: how much cloud cover defines cloud boundary. + real(kind=r_def), parameter :: cld_cover_for_cld_bdry = 2.5_r_def/8.0_r_def ! When looking for cloud base sometimes want much smaller amount of cloud. real(kind=r_def), parameter :: low_cld_cover_for_cld_base = 0.05_r_def ! For tracking whether cloud has been found. @@ -306,6 +311,7 @@ subroutine cld_diags_code( nlayers, & ! Find heights above sea level (asl) if required. if (.not. associated(cld_base_altitude, empty_real_data) .or. & + .not. associated(cld_top_altitude, empty_real_data) .or. & .not. associated(low_cld_base_altitude, empty_real_data) .or. & .not. associated(very_low_cld_amount, empty_real_data) .or. & .not. associated(low_cld_amount, empty_real_data) .or. & @@ -331,13 +337,26 @@ subroutine cld_diags_code( nlayers, & m_to_kfeet do k = 1, nlayers - if ( combined_cld_amount(k) >= cld_cover_for_cld_base ) then + if ( combined_cld_amount(k) >= cld_cover_for_cld_bdry ) then cld_base_altitude(map_2d(1)) = z_asl_base_of_levels(k) * m_to_kfeet exit end if end do end if + ! cld_top_altitude (in kilofeet) + if (.not. associated(cld_top_altitude, empty_real_data) ) then + ! As a default, set cloud-top to missing data + cld_top_altitude(map_2d(1)) = rmdi + + do k = nlayers-1, 1, -1 + if ( combined_cld_amount(k) >= cld_cover_for_cld_bdry ) then + cld_top_altitude(map_2d(1)) = z_asl_base_of_levels(k+1) * m_to_kfeet + exit + end if + end do + end if + ! low_cld_base_altitude (in feet) for low threshold cloud amounts if (.not. associated(low_cld_base_altitude, empty_real_data) ) then ! As a default, set cloud-base to beyond top of model