Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/lint-fortran.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -----------------------------------------------------------------------------
# (C) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
# -----------------------------------------------------------------------------

name: Lint Fortran

on:
pull_request:

jobs:
fortitude-lint:
uses: MetOffice/growss/.github/workflows/fortran-lint.yaml@main
with:
runner: "ubuntu-24.04"
4 changes: 4 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
| james-bruten-mo | James Bruten | Met Office | 2025-12-09 |
| andrewcoughtrie | Andrew Coughtrie | Met Office | 2026-02-10 |
| jennyhickson | Jenny Hickson | Met Office | 2026-03-02 |
| Pierre-siddall | Pierre Siddall | Met Office | 2026-03-13 |
| JoeCartonKelly-MO | Joseph Carton-Kelly | Met Office | 2026-04-15 |
| yg460-cam | Yao Ge | University of Cambridge | 2026-04-17 |
| theabro | Nathan Luke Abraham | NCAS & University of Cambridge | 2026-03-19 |
5 changes: 5 additions & 0 deletions fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[check]
select=["E000","C031","C032","C043","C051",
"C091","C082","C141","OB011","OB021","OB051",
"OB061","MOD001","PORT011","PORT012","PORT021",
"FORT001","FORT002","FORT003","FORT004","FORT005"]
2 changes: 1 addition & 1 deletion src/control/core/diagnostics/asad_chem_flux_diags.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1412,7 +1412,7 @@ FUNCTION cd_findreaction( numprods, reactants, products, &
zhook_handle)
RETURN
END IF
CYCLE
CYCLE search_reactants
END IF

! Otherwise check the names of the products
Expand Down
29 changes: 29 additions & 0 deletions src/control/core/diagnostics/asad_flux_dat.F90
Original file line number Diff line number Diff line change
Expand Up @@ -8766,6 +8766,20 @@ MODULE asad_flux_dat
[' ',' ',' ',' ']) &
]

! Add extra het chem fluxes for both troposphere and stratosphere
! Reactions are used in both StratTrop and CRI-Strat2
! Note that B85 is a biomolecular reaction but is aping a heterogeneous one
TYPE(asad_flux_defn), PARAMETER, PUBLIC :: &
het_chem_n2o5_h2o(2) = [ &
! B85 N2O5+H2O
asad_flux_defn('RXN',50993,'B',.FALSE.,0,4, &
['N2O5 ','H2O '], &
['HONO2 ','HONO2 ',' ',' ']), &
! PSC N2O5-H2O H04
asad_flux_defn('RXN',50994,'H',.FALSE.,0,4, &
['N2O5 ','H2O '], &
['HONO2 ','HONO2 ',' ',' ']) &
]


PUBLIC :: asad_load_default_fluxes
Expand Down Expand Up @@ -8853,6 +8867,7 @@ SUBROUTINE asad_load_default_fluxes
TYPE(asad_flux_defn), ALLOCATABLE, SAVE :: aa_ch4_budget_loss(:)
TYPE(asad_flux_defn), ALLOCATABLE, SAVE :: aa_ch4_drydep(:)
TYPE(asad_flux_defn), ALLOCATABLE, SAVE :: aa_ch4_ste(:)
TYPE(asad_flux_defn), ALLOCATABLE, SAVE :: aa_het_chem_n2o5_h2o(:)

INTEGER :: p1 ! start position in asad_chemical_fluxes array
INTEGER :: p2 ! end position in asad_chemical_fluxes array
Expand Down Expand Up @@ -9025,6 +9040,9 @@ SUBROUTINE asad_load_default_fluxes
ALLOCATE(aa_ch4_ste(SIZE(asad_ch4_ste)))
aa_ch4_ste = asad_ch4_ste
END IF
! aa_het_chem_n2o5_h2o
ALLOCATE(aa_het_chem_n2o5_h2o(SIZE(het_chem_n2o5_h2o)))
aa_het_chem_n2o5_h2o = het_chem_n2o5_h2o

ELSE IF (ukca_config%l_ukca_cristrat) THEN
! Select the asad diagnostics appropriate for CRI-Strat chemistry and
Expand Down Expand Up @@ -9233,6 +9251,9 @@ SUBROUTINE asad_load_default_fluxes
ALLOCATE(aa_oxidN_wetdep(SIZE(cri_oxidN_wetdep)))
aa_oxidN_wetdep = cri_oxidN_wetdep
END IF
! aa_het_chem_n2o5_h2o
ALLOCATE(aa_het_chem_n2o5_h2o(SIZE(het_chem_n2o5_h2o)))
aa_het_chem_n2o5_h2o = het_chem_n2o5_h2o


ELSE IF (ukca_config%l_ukca_offline .OR. ukca_config%l_ukca_offline_be) THEN
Expand Down Expand Up @@ -9306,6 +9327,8 @@ SUBROUTINE asad_load_default_fluxes
n_chemical_fluxes = n_chemical_fluxes + SIZE(aa_ch4_drydep)
IF (ALLOCATED(aa_ch4_ste)) &
n_chemical_fluxes = n_chemical_fluxes + SIZE(aa_ch4_ste)
IF (ALLOCATED(aa_het_chem_n2o5_h2o)) &
n_chemical_fluxes = n_chemical_fluxes + SIZE(aa_het_chem_n2o5_h2o)

ALLOCATE(asad_chemical_fluxes(n_chemical_fluxes))

Expand Down Expand Up @@ -9449,6 +9472,11 @@ SUBROUTINE asad_load_default_fluxes
asad_chemical_fluxes(p1:p2) = aa_ch4_ste(:)
p1 = p2 + 1
END IF
IF (ALLOCATED(aa_het_chem_n2o5_h2o)) THEN
p2 = p1 + SIZE(aa_het_chem_n2o5_h2o) - 1
asad_chemical_fluxes(p1:p2) = aa_het_chem_n2o5_h2o(:)
p1 = p2 + 1
END IF

IF (p2 /= n_chemical_fluxes) THEN
cmessage = ' n_chemical_fluxes and p2 are different'
Expand Down Expand Up @@ -9502,6 +9530,7 @@ SUBROUTINE asad_load_default_fluxes
END IF

! Deallocate the generic arrays
IF (ALLOCATED(aa_het_chem_n2o5_h2o)) DEALLOCATE(aa_het_chem_n2o5_h2o)
IF (ALLOCATED(aa_ch4_ste)) DEALLOCATE(aa_ch4_ste)
IF (ALLOCATED(aa_ch4_drydep)) DEALLOCATE(aa_ch4_drydep)
IF (ALLOCATED(aa_ch4_budget_loss)) DEALLOCATE(aa_ch4_budget_loss)
Expand Down
15 changes: 15 additions & 0 deletions src/control/core/interface/ukca_config_specification_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ MODULE ukca_config_specification_mod
! B-E Offline Oxidants scheme
LOGICAL :: l_fix_ukca_h2so4_ystore ! True to fix storage of H2SO4 in ASAD
! N-R schemes for updating in GLOMAP
LOGICAL :: l_fix_ukca_n2o5_h2o ! True to filter N2O5+H2O to strat and trop only

! Settings for managing photolysis environmental driver
! requirements on behalf of external UKCA Photolysis code
Expand Down Expand Up @@ -443,6 +444,10 @@ MODULE ukca_config_specification_mod
REAL :: acc_cor_scav_scaling ! Scaling factor for scavenging
! parameters for the accumulation and
! coarse modes
REAL :: solinsol_hygro_ratio(4) ! SOL/INSOL hygroscopicity ratios
! cp_su, cp_cl, cp_bc, cp_oc
! This ratio only affects the wet
! part of the aerosol

! -- GLOMAP deposition configuration options --
LOGICAL :: l_ddepaer ! True for aerosol dry deposition
Expand Down Expand Up @@ -949,6 +954,7 @@ SUBROUTINE init_ukca_configuration()
ukca_config%l_fix_drydep_so2_water = .FALSE.
ukca_config%l_fix_ukca_offox_h2o_fac = .FALSE.
ukca_config%l_fix_ukca_h2so4_ystore = .FALSE.
ukca_config%l_fix_ukca_n2o5_h2o = .FALSE.

! -- Settings for managing Photolysis driver requirements
ukca_config%i_photol_scheme = imdi
Expand Down Expand Up @@ -996,6 +1002,7 @@ SUBROUTINE init_ukca_configuration()
glomap_config%l_dust_mp_ageing = .FALSE.
glomap_config%dry_depvel_acc_scaling = rmdi
glomap_config%acc_cor_scav_scaling = rmdi
glomap_config%solinsol_hygro_ratio(:) = rmdi

! -- GLOMAP deposition configuration options --
glomap_config%l_ddepaer = .FALSE.
Expand Down Expand Up @@ -1122,6 +1129,7 @@ SUBROUTINE ukca_get_config( &
hno3_uptake_coeff, &
sigwmin, &
sigma_updraught_scaling, &
solinsol_hygro_ratio, &
l_cal360, &
l_ukca_chem_aero, &
l_ukca_mode, &
Expand Down Expand Up @@ -1179,6 +1187,7 @@ SUBROUTINE ukca_get_config( &
l_fix_drydep_so2_water, &
l_fix_ukca_offox_h2o_fac, &
l_fix_ukca_h2so4_ystore, &
l_fix_ukca_n2o5_h2o, &
l_ukca_chem, l_ukca_trop, l_ukca_aerchem, l_ukca_raq, l_ukca_raqaero, &
l_ukca_offline_be, l_ukca_tropisop, l_ukca_strattrop, l_ukca_strat, &
l_ukca_offline, l_ukca_cristrat, l_ukca_stratcfc, l_ukca_achem, &
Expand Down Expand Up @@ -1324,6 +1333,7 @@ SUBROUTINE ukca_get_config( &
REAL, OPTIONAL, INTENT(OUT) :: ph_fit_coeff_b
REAL, OPTIONAL, INTENT(OUT) :: ph_fit_intercept
REAL, OPTIONAL, INTENT(OUT) :: hno3_uptake_coeff
REAL, OPTIONAL, INTENT(OUT) :: solinsol_hygro_ratio(4)

LOGICAL, OPTIONAL, INTENT(OUT) :: l_cal360
LOGICAL, OPTIONAL, INTENT(OUT) :: l_ukca_chem_aero
Expand Down Expand Up @@ -1395,6 +1405,7 @@ SUBROUTINE ukca_get_config( &
LOGICAL, OPTIONAL, INTENT(OUT) :: l_fix_drydep_so2_water
LOGICAL, OPTIONAL, INTENT(OUT) :: l_fix_ukca_offox_h2o_fac
LOGICAL, OPTIONAL, INTENT(OUT) :: l_fix_ukca_h2so4_ystore
LOGICAL, OPTIONAL, INTENT(OUT) :: l_fix_ukca_n2o5_h2o
LOGICAL, OPTIONAL, INTENT(OUT) :: l_ukca_chem
LOGICAL, OPTIONAL, INTENT(OUT) :: l_ukca_trop
LOGICAL, OPTIONAL, INTENT(OUT) :: l_ukca_aerchem
Expand Down Expand Up @@ -1685,6 +1696,8 @@ SUBROUTINE ukca_get_config( &
l_fix_ukca_offox_h2o_fac = ukca_config%l_fix_ukca_offox_h2o_fac
IF (PRESENT(l_fix_ukca_h2so4_ystore)) &
l_fix_ukca_h2so4_ystore = ukca_config%l_fix_ukca_h2so4_ystore
IF (PRESENT(l_fix_ukca_n2o5_h2o)) &
l_fix_ukca_n2o5_h2o = ukca_config%l_fix_ukca_n2o5_h2o

! -- UKCA internal configuration variables
IF (PRESENT(l_ukca_chem)) l_ukca_chem = ukca_config%l_ukca_chem
Expand Down Expand Up @@ -1748,6 +1761,8 @@ SUBROUTINE ukca_get_config( &
IF (PRESENT(mode_incld_so2_rfrac)) &
mode_incld_so2_rfrac = glomap_config%mode_incld_so2_rfrac
IF (PRESENT(l_aero_rainout)) l_aero_rainout = glomap_config%l_aero_rainout
IF (PRESENT(solinsol_hygro_ratio)) solinsol_hygro_ratio(:) = &
glomap_config%solinsol_hygro_ratio(:)
IF (PRESENT(l_cv_rainout)) l_cv_rainout = glomap_config%l_cv_rainout
IF (PRESENT(i_mode_nucscav)) i_mode_nucscav = glomap_config%i_mode_nucscav
IF (PRESENT(l_impc_scav)) l_impc_scav = glomap_config%l_impc_scav
Expand Down
32 changes: 32 additions & 0 deletions src/control/core/top_level/ukca_setup_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ SUBROUTINE ukca_setup(error_code, &
ph_fit_intercept, &
sigwmin, &
sigma_updraught_scaling, &
solinsol_hygro_ratio, &
const_rmol, &
const_tfs, &
const_rho_water, &
Expand Down Expand Up @@ -207,6 +208,7 @@ SUBROUTINE ukca_setup(error_code, &
l_fix_ukca_h2dd_x, &
l_fix_ukca_offox_h2o_fac, &
l_fix_ukca_h2so4_ystore, &
l_fix_ukca_n2o5_h2o, &
l_mode_bhn_on, &
l_mode_bln_on, &
l_ddepaer, &
Expand Down Expand Up @@ -461,6 +463,7 @@ SUBROUTINE ukca_setup(error_code, &
REAL, OPTIONAL, INTENT(IN) :: sigwmin
REAL, OPTIONAL, INTENT(IN) :: hno3_uptake_coeff
REAL, OPTIONAL, INTENT(IN) :: sigma_updraught_scaling
REAL, OPTIONAL, INTENT(IN) :: solinsol_hygro_ratio(4)
REAL, OPTIONAL, INTENT(IN) :: const_rmol
REAL, OPTIONAL, INTENT(IN) :: const_tfs
REAL, OPTIONAL, INTENT(IN) :: const_rho_water
Expand Down Expand Up @@ -540,6 +543,7 @@ SUBROUTINE ukca_setup(error_code, &
LOGICAL, OPTIONAL, INTENT(IN) :: l_fix_ukca_h2dd_x
LOGICAL, OPTIONAL, INTENT(IN) :: l_fix_ukca_offox_h2o_fac
LOGICAL, OPTIONAL, INTENT(IN) :: l_fix_ukca_h2so4_ystore
LOGICAL, OPTIONAL, INTENT(IN) :: l_fix_ukca_n2o5_h2o
LOGICAL, OPTIONAL, INTENT(IN) :: l_mode_bhn_on
LOGICAL, OPTIONAL, INTENT(IN) :: l_mode_bln_on
LOGICAL, OPTIONAL, INTENT(IN) :: l_ddepaer
Expand Down Expand Up @@ -600,6 +604,8 @@ SUBROUTINE ukca_setup(error_code, &
LOGICAL :: l_strat_scheme_selected ! True if a Stratospheric scheme is
! selected for chemistry

REAL :: sum_solinsol_hygro_ratio ! Sum of solinsol hygroscopicity ratios (=1)

INTEGER (KIND=jpim), PARAMETER :: zhook_in = 0 ! DrHook tracing entry
INTEGER (KIND=jpim), PARAMETER :: zhook_out = 1 ! DrHook tracing exit
REAL (KIND=jprb) :: zhook_handle ! DrHook tracing
Expand Down Expand Up @@ -1232,6 +1238,13 @@ SUBROUTINE ukca_setup(error_code, &
ukca_config%l_fix_ukca_h2so4_ystore = l_fix_ukca_h2so4_ystore
END IF

IF (ukca_config%i_ukca_chem == i_ukca_chem_strattrop .OR. &
ukca_config%i_ukca_chem == i_ukca_chem_cristrat) THEN
ukca_config%l_fix_ukca_n2o5_h2o = .TRUE.
IF (PRESENT(l_fix_ukca_n2o5_h2o)) &
ukca_config%l_fix_ukca_n2o5_h2o = l_fix_ukca_n2o5_h2o
END IF

! Settings for managing photolysis environmental driver
! requirements on behalf of external UKCA Photolysis code

Expand Down Expand Up @@ -1313,6 +1326,9 @@ SUBROUTINE ukca_setup(error_code, &

END IF

IF (PRESENT(solinsol_hygro_ratio)) &
glomap_config%solinsol_hygro_ratio(:) = solinsol_hygro_ratio(:)

! -- GLOMAP deposition configuration options --

! Dry deposition
Expand Down Expand Up @@ -1721,6 +1737,22 @@ SUBROUTINE ukca_setup(error_code, &

END IF

! Ensure the sum of solinsol_hygro_ratio is 1
IF (ukca_config%l_ukca_mode .AND. &
glomap_config%i_mode_setup == 11) THEN
sum_solinsol_hygro_ratio = 0.0
DO i = 1,4
sum_solinsol_hygro_ratio = sum_solinsol_hygro_ratio + &
glomap_config%solinsol_hygro_ratio(i)
END DO
IF (PRESENT(solinsol_hygro_ratio)) THEN
glomap_config%solinsol_hygro_ratio(:) = &
glomap_config%solinsol_hygro_ratio(:) / sum_solinsol_hygro_ratio
ELSE
glomap_config%solinsol_hygro_ratio(:) = [1.0, 0.0, 0.0, 0.0]
END IF
END IF

! Initialise chemical definition arrays
CALL ukca_chem1_init()

Expand Down
35 changes: 26 additions & 9 deletions src/science/core/aerosols/glomap/ukca_volume_mode.F90
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ SUBROUTINE ukca_volume_mode( glomap_variables_local, nbox, nd, md, mdt, &
USE ukca_config_constants_mod, ONLY: rho_water, avogadro, rho_so4

USE ukca_mode_setup, ONLY: nmodes, nanion, ncation, &
cp_su, cp_oc, cp_cl, &
cp_so, cp_nh4, cp_no3, cp_nn
cp_su, cp_oc, cp_cl, cp_so, &
cp_nh4, cp_no3, cp_nn

USE yomhook, ONLY: lhook, dr_hook
USE parkind1, ONLY: jprb, jpim
Expand Down Expand Up @@ -240,6 +240,7 @@ SUBROUTINE ukca_volume_mode( glomap_variables_local, nbox, nd, md, mdt, &
REAL :: mmwrhow
REAL :: f_ao
REAL :: cl(nbox,-nanion:ncation) !ION CONCS (MOL/CC OF AIR)
REAL :: mdcopy(nbox,nmodes,glomap_variables_local%ncp) !Redistributes ions for solinsol

REAL :: tmp1(nbox,nmodes)
!
Expand Down Expand Up @@ -280,6 +281,7 @@ SUBROUTINE ukca_volume_mode( glomap_variables_local, nbox, nd, md, mdt, &
soluble => glomap_variables_local%soluble
x => glomap_variables_local%x


!at this point in the code, the value of RP does not matter
rp(:)=100.0e-9 ! dummy value
CALL ukca_vapour(nbox,t,pmid,s,rp,wts,rhosol_strat)
Expand All @@ -297,6 +299,7 @@ SUBROUTINE ukca_volume_mode( glomap_variables_local, nbox, nd, md, mdt, &

denom(:)=0.0 ! define on all points to avoid error
denom2(:)=0.0
mdcopy(:,:,:) = md(:,:,:) ! assigning md input values to mdcopy

! Correct relative humidities to lie within the range of 10-90%
corrh(:)=rh(:)
Expand Down Expand Up @@ -348,8 +351,21 @@ SUBROUTINE ukca_volume_mode( glomap_variables_local, nbox, nd, md, mdt, &
cl(:,i)=0.0 ! set all concentrations to zero initially
END DO

IF (component(imode,cp_su)) THEN ! assume all H2SO4 --> SO4
cl(:,-2)=md(:,imode,cp_su)/avogadro ! [SO4] in moles/cc (air)
! If SOLINSOL then redistribute sulphate md into other species
! hygro_ratio(3) is black carbon which is important to include
! in the ratio but isn't used in this routine
IF (glomap_config%i_mode_setup == 11) THEN
mdcopy(:,imode,cp_su) = glomap_config%solinsol_hygro_ratio(1)* &
(md(:,imode,cp_su))
mdcopy(:,imode,cp_cl) = glomap_config%solinsol_hygro_ratio(2)* &
(md(:,imode,cp_su))
mdcopy(:,imode,cp_oc) = glomap_config%solinsol_hygro_ratio(4)* &
(md(:,imode,cp_su))
END IF

IF (component(imode,cp_su) .OR. (glomap_config%i_mode_setup == 11)) THEN
! assume all H2SO4 --> SO4
cl(:,-2)=mdcopy(:,imode,cp_su)/avogadro ! [SO4] in moles/cc (air)
END IF

IF (component(imode,cp_so)) THEN
Expand All @@ -361,8 +377,8 @@ SUBROUTINE ukca_volume_mode( glomap_variables_local, nbox, nd, md, mdt, &
! .. whereas CL needs to be in moles of aged organic (MM=0.15kg/mol).
END IF

IF (component(imode,cp_oc)) THEN
cl(:,-2)=cl(:,-2)+(fhyg_aom/avogadro)*(md(:,imode,cp_oc)/f_ao)
IF (component(imode,cp_oc) .OR. (glomap_config%i_mode_setup == 11)) THEN
cl(:,-2)=cl(:,-2)+(fhyg_aom/avogadro)*(mdcopy(:,imode,cp_oc)/f_ao)
! .. Increment concentration of SO4 ions to represent the
! .. presence of hygroscopic aged organic aerosol mass in CP_OC.
! .. Assume it has uptake behaviour at fraction FHYG_AOM of SO4.
Expand All @@ -376,9 +392,10 @@ SUBROUTINE ukca_volume_mode( glomap_variables_local, nbox, nd, md, mdt, &
!
END IF

IF (component(imode,cp_cl)) THEN ! assume complete dissociation
cl(:,3)=md(:,imode,cp_cl)/avogadro ! [Na] in moles per cc (air)
cl(:,-4)=md(:,imode,cp_cl)/avogadro ! [Cl] in moles per cc (air)
IF (component(imode,cp_cl) .OR. (glomap_config%i_mode_setup == 11)) THEN
! assume complete dissociation
cl(:,3)=mdcopy(:,imode,cp_cl)/avogadro ! [Na] in moles per cc (air)
cl(:,-4)=mdcopy(:,imode,cp_cl)/avogadro ! [Cl] in moles per cc (air)
END IF

! Nitrate scheme
Expand Down
Loading
Loading