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
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
| jennyhickson | Jenny Hickson | Met Office | 2026-03-02 |
| Pierre-siddall | Pierre Siddall | Met Office | 2026-03-13 |
| yg460-cam | Yao Ge | University of Cambridge | 2026-04-17 |
| theabro | Nathan Luke Abraham | NCAS & University of Cambridge | 2026-03-19 |
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
6 changes: 6 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 @@ -949,6 +950,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 @@ -1179,6 +1181,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 @@ -1395,6 +1398,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 +1689,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
9 changes: 9 additions & 0 deletions src/control/core/top_level/ukca_setup_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,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 @@ -540,6 +541,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 @@ -1232,6 +1234,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
30 changes: 29 additions & 1 deletion src/science/core/chemistry/asad/asad_bimol.F90
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ MODULE asad_bimol_mod

CONTAINS

SUBROUTINE asad_bimol( n_points )
SUBROUTINE asad_bimol( n_points, stratflag_opt )

USE asad_mod, ONLY: t, t300, specf, spb, ab, rk, tnd, p, &
wp, f, peps, nbrkx, jpspb, jpcspf, jpbk
Expand All @@ -91,6 +91,8 @@ SUBROUTINE asad_bimol( n_points )
IMPLICIT NONE

INTEGER, INTENT(IN) :: n_points
! optional argument used for masking off the stratosphere
LOGICAL, INTENT(IN), OPTIONAL :: stratflag_opt(n_points)

! Local variables

Expand All @@ -112,6 +114,7 @@ SUBROUTINE asad_bimol( n_points )
INTEGER, SAVE :: ics2oh = 0
INTEGER, SAVE :: ih2o = 0
INTEGER, SAVE :: iho2no = 0
INTEGER, SAVE :: in2o5_h2o = 0
INTEGER :: jtr
INTEGER :: j
INTEGER :: jr
Expand Down Expand Up @@ -145,6 +148,10 @@ SUBROUTINE asad_bimol( n_points )
REAL :: tmp1(1:n_points)
REAL :: inv_t(1:n_points)

! logical array for masking-off the stratosphere
! default to False unless changed by stratflag_opt
LOGICAL :: stratflag(n_points)

! ErrorStatus
INTEGER :: errcode=0 ! Error flag (0 = OK)
CHARACTER(LEN=errormessagelength) :: cmessage ! Error return message
Expand All @@ -167,6 +174,12 @@ SUBROUTINE asad_bimol( n_points )
ratioa2b(:) = 0.0
ratiob2total(:) = 0.0

! set stratflag from optional argument - only True in the stratosphere
stratflag(:) = .FALSE.
IF (PRESENT(stratflag_opt)) THEN
stratflag = stratflag_opt
END IF

! 1. Calculate bimolecular rate coefficients
! --------- ----------- ---- ------------

Expand Down Expand Up @@ -255,6 +268,14 @@ SUBROUTINE asad_bimol( n_points )
iho2no = asad_findreaction( r1, r2, prods, 1, spb, nbrkx, &
jpbk+1, jpspb )

! Find B85: N2O5 + H2O -> HONO2 + HONO2.
r1 = 'N2O5 '
r2 = 'H2O '
prods(1) = 'HONO2 '
prods(2) = 'HONO2 '
in2o5_h2o = asad_findreaction( r1, r2, prods, 2, spb, nbrkx, &
jpbk+1, jpspb )


IF (ukca_config%l_ukca_chem_aero) THEN
r1 = 'DMS '
Expand Down Expand Up @@ -408,6 +429,13 @@ SUBROUTINE asad_bimol( n_points )
8.53e-4*(1e-2*p(1:n_points))-1.73)/100.0
END IF

! Keep B85 (N2O5 + H2O) in the troposphere only when fix is enabled.
IF (ukca_config%l_fix_ukca_n2o5_h2o .AND. in2o5_h2o > 0) THEN
WHERE (stratflag(1:n_points))
rk(1:n_points,in2o5_h2o) = 0.0
END WHERE
END IF

! SO3 + H2O: 2nd H2O molecule dealt with here by multiplying rate by [H2O]
IF ( ih2o /= 0 .AND. iso3h2o /= 0 ) THEN
! water is an advected tracer
Expand Down
2 changes: 1 addition & 1 deletion src/science/core/chemistry/asad/asad_cdrive.F90
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ SUBROUTINE asad_cdrive(ftr, pp, pt, pq, co2_1d, cld_f, cld_l, &
! 4. Calculate reaction rate coefficients
! --------- -------- ---- ------------

CALL asad_bimol (n_points)
CALL asad_bimol (n_points, stratflag)
CALL asad_trimol(n_points)

! Calculate aqueous-phase SO2 oxdn. and tropospheric heterogeneous rates
Expand Down
28 changes: 25 additions & 3 deletions src/science/core/chemistry/ukca_hetero_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -490,9 +490,18 @@ SUBROUTINE ukca_hetero(n_points, have_nat, stratflag)
rk(:,n_hocl_hcl) = hk(:,3)
END IF

! Optionally filter N2O5+H2O by stratflag to prevent double-counting.
IF (n_n2o5_h2o > 0) THEN
! 4. N2O5 + H2O -> 2 HNO3
rk(:,n_n2o5_h2o) = hk(:,4)
IF (ukca_config%l_fix_ukca_n2o5_h2o) THEN
WHERE (stratflag)
rk(:,n_n2o5_h2o) = hk(:,4)
ELSE WHERE
rk(:,n_n2o5_h2o) = 0.0
END WHERE
ELSE
rk(:,n_n2o5_h2o) = hk(:,4)
END IF
END IF

IF (n_n2o5_hcl > 0) THEN
Expand Down Expand Up @@ -659,14 +668,27 @@ SUBROUTINE ukca_hetero(n_points, have_nat, stratflag)

WHERE ( zh2o > peps )
rk(:,n_clono2_h2o) = kpsc(:,2) / zh2o
rk(:,n_n2o5_h2o) = kpsc(:,4) / zh2o
rk(:,n_brono2_h2o) = kpsc(:,8) / zh2o
ELSE WHERE
rk(:,n_clono2_h2o) = 0.0
rk(:,n_n2o5_h2o) = 0.0
rk(:,n_brono2_h2o) = 0.0
END WHERE

! Optionally filter N2O5+H2O by stratflag to prevent double-counting.
IF (ukca_config%l_fix_ukca_n2o5_h2o) THEN
WHERE ( zh2o > peps .AND. stratflag )
rk(:,n_n2o5_h2o) = kpsc(:,4) / zh2o
ELSE WHERE
rk(:,n_n2o5_h2o) = 0.0
END WHERE
ELSE
WHERE ( zh2o > peps )
rk(:,n_n2o5_h2o) = kpsc(:,4) / zh2o
ELSE WHERE
rk(:,n_n2o5_h2o) = 0.0
END WHERE
END IF

WHERE ( zhbr > peps )
rk(:,n_hobr_hbr) = kpsc(:,9) / zhbr
rk(:,n_hocl_hbr) = kpsc(:,10) / zhbr
Expand Down