Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Changed effective radius in MieQuery.H to remove in place units scaling; made
corresponding change in Chem_SettlingSimple
- Updated optics lookup tables to accommodate area and effective radius calculation
- Check userRC in ESMF_GridCompRun in GOCART2G gridcomp
I- Check userRC in ESMF_GridCompRun in GOCART2G gridcomp
- The pressure lid change associated with the introduction of run0 to set 0 above the lid
- Fwet value in dust modified from 0.8 to 1.0
- Dust and Sea salt Emission scale factors updated for L181
Expand All @@ -38,6 +38,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed erroneous/extraneous friendly attributes to internal state for DU and NI
when in data_driven mode
- typo in filepath for BR optics file
- Units error for dust and sea salt radius in NIheterogenousChem in Process Library corrected.
- stochiometric coefficent correction for heterogenous production diagnostic NI_phet
in NIheterogenousChem in Process Library.
- corrected references for RH factor for hno3 uptake on dust in NIheterogenousChem in Process Library.
- units error for external data hno3 corrected in NI instance file and in Process Library.
- corrected units error for hno3 column diagnostic in Process Library.



### Added

Expand All @@ -46,6 +54,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
coupling of GMI OH, NO3, H2O2 to sulfur chemistry mechanism
- Added a callback to allow a chemistry module to call for optical properties needed
for photolysis calculation; currently used for GMI with CloudJ
- Added 3d diagnostics for nitrate production.
- Added logic in NI2G_GridCompMod.F90 through NI2G_instance_NI.rc to allow two-way
coupling of GMI HNO3 to nitrate chemistry mechanism.

## [v2.4.3] - 2025-07-21

Expand Down
75 changes: 54 additions & 21 deletions ESMF/GOCART2G_GridComp/NI2G_GridComp/NI2G_GridCompMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ module NI2G_GridCompMod
real, allocatable :: fnumDU(:), fnumSS(:) ! DU and SS particles per kg mass
type(ThreadWorkspace), allocatable :: workspaces(:)
type(ESMF_Alarm) :: alarm
logical :: using_GMI !CM: logic for hno3 GMI coupling
end type NI2G_GridComp

type wrap_
Expand Down Expand Up @@ -138,6 +139,9 @@ subroutine SetServices ( GC, RC )
! process generic config items
call self%GA_Environment%load_from_config( cfg, universal_cfg, __RC__)

! process NI specific items
call ESMF_ConfigGetAttribute(cfg, self%using_GMI, label='using_GMI:', __RC__)

! Is NI data driven?
! ------------------
call determine_data_driven (COMP_NAME, data_driven, __RC__)
Expand Down Expand Up @@ -232,6 +236,16 @@ subroutine SetServices ( GC, RC )
restart=MAPL_RestartOptional, __RC__)
end if ! (data_driven)

if(self%using_GMI) then

call MAPL_AddImportSpec(GC, &
SHORT_NAME = 'GMI_HNO3', &
LONG_NAME = 'nitric_acid', &
UNITS = 'mol/mol', &
DIMS = MAPL_DimsHorzVert, &
VLOCATION = MAPL_VLocationCenter, &
RESTART = MAPL_RestartSkip, __RC__)
endif

! Import, Export, Internal states for computational instance
! ----------------------------------------------------------
Expand Down Expand Up @@ -827,45 +841,64 @@ subroutine Run2 (GC, import, export, clock, RC)
allocate(dqa, mold=lwi, __STAT__)
allocate(drydepositionfrequency, mold=lwi, __STAT__)

alarm_is_ringing = ESMF_AlarmIsRinging(self%alarm, _RC)
#ifdef DEBUG
if (alarm_is_ringing) then

if(self%using_GMI) then
xhno3 = GMI_HNO3
call MAPL_MaxMin ( 'GMI:HNO3 ', xhno3)

else
alarm_is_ringing = ESMF_AlarmIsRinging(self%alarm, _RC)
#ifdef DEBUG
if (alarm_is_ringing) then
if (MAPL_Am_I_Root()) then
print *,'DEBUG:: NI replenish alarm is ringing'
end if
end if
#endif

! Save local copy of HNO3 for first pass through run method regardless
thread = MAPL_get_current_thread()
workspace => self%workspaces(thread)

!if (workspace%first) then
!xhno3 = MAPL_UNDEF
!workspace%first = .false.
!end if
end if
#endif

!Save local copy of HNO3 for first pass through run method regardless
thread = MAPL_get_current_thread()
workspace => self%workspaces(thread)

!if (workspace%first) then
!xhno3 = MAPL_UNDEF
!workspace%first = .false.
!end if

! Recycle HNO3 every 3 hours
if (alarm_is_ringing) then
xhno3 = NITRATE_HNO3
end if
endif

! Recycle HNO3 every 3 hours
if (alarm_is_ringing) then
xhno3 = NITRATE_HNO3
end if

if (associated(NIPNO3AQ)) NIPNO3AQ(:,:) = 0.
if (associated(NIPNH4AQ)) NIPNH4AQ(:,:) = 0.
if (associated(NIPNH3AQ)) NIPNH3AQ(:,:) = 0.
if (associated(NIPHNO3AQ)) NIPHNO3AQ(:,:) = 0.
# 3D diag
if (associated(NIPNO3AQV)) NIPNO3AQV(:,:,:) = 0.
if (associated(NIPNH4AQV)) NIPNH4AQV(:,:,:) = 0.
if (associated(NIPNH3AQV)) NIPNH3AQV(:,:,:) = 0.
if (associated(NIPHNO3AQV)) NIPHNO3AQV(:,:,:) = 0.

call NIthermo (self%km, self%klid, self%cdt, MAPL_GRAV, delp, airdens, &
t, rh2, fMassHNO3, MAPL_AIRMW, SO4, NH3, NO3an1, NH4a, &
xhno3, NIPNO3AQ, NIPNH4AQ, NIPNH3AQ, __RC__)
xhno3, NIPNO3AQ, NIPNH4AQ, NIPNH3AQ, NIPHNO3AQ, &
NIPNO3AQV, NIPNH4AQV, NIPNH3AQV, NIPHNO3AQV, __RC__)


call NIheterogenousChem (NIHT, xhno3, MAPL_UNDEF, MAPL_AVOGAD, MAPL_AIRMW, &
call NIheterogenousChem (NIHT, NIHTV, xhno3, MAPL_UNDEF, MAPL_AVOGAD, MAPL_AIRMW, &
MAPL_PI, MAPL_RUNIV/1000., airdens, t, rh2, delp, DU, &
SS, self%rmedDU*1.e-6, self%rmedSS*1.e-6, &
self%fnumDU, self%fnumSS, self%km, self%klid, &
self%cdt, MAPL_GRAV, fMassHNO3, fMassNO3, NO3an1, NO3an2, &
NO3an3, HNO3CONC, HNO3SMASS, HNO3CMASS, __RC__)
! Save local copy of HNO3 for first pass through run method regardless

! CM: update GMI_HNO3 after nitrate processes for 2way coupling.
if(self%using_GMI) then
GMI_HNO3 = xhno3
endif


! NI Settling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,8 @@ Exports:
regrid: CONSERVE
sample: NI2G_sample_0
variable: NO3AN3

GMI_HNO3:
collection: /dev/null
regrid: CONSERVE
sample: NI2G_sample_2
variable: GMI_HNO3
11 changes: 9 additions & 2 deletions ESMF/GOCART2G_GridComp/NI2G_GridComp/NI2G_StateSpecs.rc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ category: IMPORT
EMI_NH3_OC | kg m-2 s-1 | xy | N | | SKIP | ocean emissions
EMI_NH3_RE | kg m-2 s-1 | xy | N | | SKIP | resedential emissions
EMI_NH3_TR | kg m-2 s-1 | xy | N | | SKIP | transport emissions
NITRATE_HNO3 | kg m-2 s-1 | xyz | C | | SKIP | nitrate hno3 emissions
NITRATE_HNO3 | mol mol-1 | xyz | C | | SKIP | nitrate hno3 offline field
GMI_HNO3 | mol mol-1 | xyz | C | | SKIP | nitrate GMI HNO3 source
DU | kg kg-1 | xyz | C | 5 | OPT | Dust Mixing Ratio all bins
SS | kg kg-1 | xyz | C | 5 | OPT | Sea Salt Mixing Ratio all bins
SO4 | kg kg-1 | xyz | C | | OPT | Sulfate Mixing Ratio
Expand Down Expand Up @@ -64,10 +65,16 @@ category: EXPORT
NISCACOEFRH20 | m-1 | xyz | C | size(self%wavelengths_profile) | Nitrate Scattering Coefficient - fixed RH=20%
NISCACOEFRH80 | m-1 | xyz | C | size(self%wavelengths_profile) | Nitrate Scattering Coefficient - fixed RH=80%
NIBCKCOEF | m-1 sr-1 | xyz | C | size(self%wavelengths_profile) | Nitrate Backscatter Coefficient
NIPNO3AQV | kg m-2 s-1 | xyz | C | | 3D Nitrate Production from Aqueous Chemistry
NIPNH4AQV | kg m-2 s-1 | xyz | C | | 3D Ammonium production from Aqueous Chemistry
NIPNH3AQV | kg m-2 s-1 | xyz | C | | 3D Ammonia Change from Aqueous Chemistry
NIPHNO3AQV | kg m-2 s-1 | xyz | C | | 3D Nitric acid Change from Aqueous Chemistry
NIHTV | kg m-2 s-1 | xyz | C | 3 | 3D Nitrate Production from Het Chem (Bin %d)
# ............. | ............ | ..... | ..... | ........... | ..................................
NIPNO3AQ | kg m-2 s-1 | xy | N | | Nitrate Production from Aqueous Chemistry
NIPNH4AQ | kg m-2 s-1 | xy | N | | Ammonium Production from Aqueous Chemistry
NIPNH3AQ | kg m-2 s-1 | xy | N | | Ammonia Change from Aqueous Chemistry
NIPHNO3AQ | kg m-2 s-1 | xy | N | | Nitric Acid Change from Aqueous Chemistry
NIHT | kg m-2 s-1 | xy | N | 3 | Nitrate Production from Het Chem (Bin %d)
NISD | kg m-2 s-1 | xy | N | 3 | Nitrate Sedimentation (Bin %d)
NIDP | kg m-2 s-1 | xy | N | 3 | Nitrate Dry Deposition (Bin %d)
Expand Down Expand Up @@ -114,7 +121,7 @@ category: INTERNAL
NO3an1 |kg kg-1 | xyz | C | MAPL_RestartOptional | T | DYNAMICS:TURBULENCE:MOIST | Nitrate size bin 001
NO3an2 |kg kg-1 | xyz | C | MAPL_RestartOptional | T | DYNAMICS:TURBULENCE:MOIST | Nitrate size bin 002
NO3an3 |kg kg-1 | xyz | C | MAPL_RestartOptional | T | DYNAMICS:TURBULENCE:MOIST | Nitrate size bin 003
XHNO3 |kg m-2 s-1| xyz | C | | F | | buffer for NITRATE_HNO3
XHNO3 |mol mol-1 | xyz | C | | F | | buffer for NITRATE_HNO3

#********************************************************
#
Expand Down
4 changes: 4 additions & 0 deletions ESMF/GOCART2G_GridComp/NI2G_GridComp/NI2G_instance_NI.rc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ sigma: 2.0 2.0 2.0 2.0 2.0

pressure_lid_in_hPa: 40.0

# HNO3 from GMI
using_GMI: .false.


# SettlingSolver options
# Options: 'gocart' or 'ufs'
settling_scheme: 'gocart'
67 changes: 54 additions & 13 deletions Process_Library/GOCART2G_Process.F90
Original file line number Diff line number Diff line change
Expand Up @@ -5922,7 +5922,7 @@ end subroutine carbonChemLoss
! !IROUTINE: NIheterogenousChemOpt
!
! !INTERFACE:
subroutine NIheterogenousChem (NI_phet, xhno3, UNDEF, AVOGAD, AIRMW, PI, RUNIV, rhoa, tmpu, relhum, delp, &
subroutine NIheterogenousChem (NI_phet, NI_phetv, xhno3, UNDEF, AVOGAD, AIRMW, PI, RUNIV, rhoa, tmpu, relhum, delp, &
DU, SS, rmedDU, rmedSS, fnumDU, fnumSS, &
km, klid, cdt, grav, fMassHNO3, fMassNO3, nNO3an1, nNO3an2, &
nNO3an3, HNO3_conc, HNO3_sfcmass, HNO3_colmass, rc)
Expand All @@ -5945,8 +5945,8 @@ subroutine NIheterogenousChem (NI_phet, xhno3, UNDEF, AVOGAD, AIRMW, PI, RUNIV,
real, dimension(:,:,:), intent(in) :: delp ! pressure thickness [Pa]
real, pointer, dimension(:,:,:,:), intent(in) :: DU ! dust aerosol [kg/kg]
real, pointer, dimension(:,:,:,:), intent(in) :: SS ! sea salt aerosol [kg/kg]
real, dimension(:) ,intent(in) :: rmedDU ! dust aerosol radius [um]
real, dimension(:) ,intent(in) :: rmedSS ! sea salt aerosol radius [um]
real, dimension(:) ,intent(in) :: rmedDU ! dust aerosol radius [m]
real, dimension(:) ,intent(in) :: rmedSS ! sea salt aerosol radius [m]
real, dimension(:) ,intent(in) :: fnumDU ! number of dust particles per kg mass
real, dimension(:) ,intent(in) :: fnumSS ! number of sea salt particles per kg mass
integer, intent(in) :: km ! number of model levels
Expand All @@ -5958,10 +5958,11 @@ subroutine NIheterogenousChem (NI_phet, xhno3, UNDEF, AVOGAD, AIRMW, PI, RUNIV,

! !INOUTPUT PARAMETERS:
real, pointer, dimension(:,:,:), intent(inout) :: NI_phet ! Nitrate Production from Het Chem [kg/(m^2 sec)]
real, dimension(:,:,:), intent(inout) :: xhno3 ! buffer for NITRATE_HNO3 [kg/(m^2 sec)]
real, pointer, dimension(:,:,:,:), intent(inout) :: NI_phetv ! 3D Nitrate Production from Het Chem [kg/(m^2 sec)]
real, dimension(:,:,:), intent(inout) :: xhno3 ! buffer for NITRATE_HNO3 [mol mol-1]
real, pointer, dimension(:,:,:), intent(inout) :: HNO3_conc ! Nitric Acid Mass Concentration [kg/m^3]
real, pointer, dimension(:,:), intent(inout) :: HNO3_sfcmass ! Nitric Acid Surface Mass Concentration [kg/m^3]
real, pointer, dimension(:,:), intent(inout) :: HNO3_colmass ! Nitric Acid Column Mass Density [kg/m^3]
real, pointer, dimension(:,:), intent(inout) :: HNO3_colmass ! Nitric Acid Column Mass Density [kg/m^2]
real, pointer, dimension(:,:,:), intent(inout) :: nNO3an1 ! Nitrate bin 1 [kg/kg]
real, pointer, dimension(:,:,:), intent(inout) :: nNO3an2 ! Nitrate bin 2 [kg/kg]
real, pointer, dimension(:,:,:), intent(inout) :: nNO3an3 ! Nitrate bin 3 [kg/kg]
Expand Down Expand Up @@ -6080,11 +6081,18 @@ subroutine NIheterogenousChem (NI_phet, xhno3, UNDEF, AVOGAD, AIRMW, PI, RUNIV,
nNO3an3 = nNO3an3 + kan3 * deltahno3 * fMassNO3 / fMassHNO3

if(associated(NI_phet)) then
NI_phet(:,:,1) = (1.0 / (grav*cdt)) * sum(kan1*deltahno3*delp, dim=3)
NI_phet(:,:,2) = (1.0 / (grav*cdt)) * sum(kan2*deltahno3*delp, dim=3)
NI_phet(:,:,3) = (1.0 / (grav*cdt)) * sum(kan3*deltahno3*delp, dim=3)
NI_phet(:,:,1) = (1.0 / (grav*cdt)) * sum(kan1*deltahno3*(fMassNO3/fMassHNO3)*delp, dim=3)
NI_phet(:,:,2) = (1.0 / (grav*cdt)) * sum(kan2*deltahno3*(fMassNO3/fMassHNO3)*delp, dim=3)
NI_phet(:,:,3) = (1.0 / (grav*cdt)) * sum(kan3*deltahno3*(fMassNO3/fMassHNO3)*delp, dim=3)
end if

if(associated(NI_phetv)) then
NI_phetv(:,:,:,1) = (1.0 / (grav*cdt)) * kan1*deltahno3*(fMassNO3/fMassHNO3)*delp
NI_phetv(:,:,:,2) = (1.0 / (grav*cdt)) * kan2*deltahno3*(fMassNO3/fMassHNO3)*delp
NI_phetv(:,:,:,3) = (1.0 / (grav*cdt)) * kan3*deltahno3*(fMassNO3/fMassHNO3)*delp
end if


! Output diagnostic HNO3
! ----------------------
! Calculate the HNO3 mass concentration
Expand All @@ -6100,7 +6108,7 @@ subroutine NIheterogenousChem (NI_phet, xhno3, UNDEF, AVOGAD, AIRMW, PI, RUNIV,
HNO3_colmass(i1:i2,j1:j2) = 0.
do k = klid, km
HNO3_colmass(i1:i2,j1:j2) &
= HNO3_colmass(i1:i2,j1:j2) + xhno3(i1:i2,j1:j2,k)*delp(i1:i2,j1:j2,k)/grav
= HNO3_colmass(i1:i2,j1:j2) + xhno3(i1:i2,j1:j2,k) * fMassHNO3 / AIRMW * delp(i1:i2,j1:j2,k)/grav
end do
endif

Expand Down Expand Up @@ -6347,7 +6355,12 @@ function sktrs_hno3 ( tk, rh, sad, ad, radA, pi, rgas, fMassHNO3 )
p_dfkg = sqrt(3.472e-2 + 1.0/fmassHNO3)
p_avgvel = sqrt(8.0 * rgas_dp * 1000.0 / (pi_dp * fmassHNO3))

! RH factor - Figure 1 in Duncan et al. (2010)
! RH factor: rh dependent gamma for dust - references:
! Table 1 in Liu et al. J. Phys. Chem. A 2008
! doi:10.1021/jp076169h
! Figure 1 in Fairlie et al. ACP 2010
! doi:10.5194/acp-10-3999-2010

f_rh = 0.03

if (rh >= 0.1 .and. rh < 0.3) then
Expand All @@ -6364,7 +6377,6 @@ function sktrs_hno3 ( tk, rh, sad, ad, radA, pi, rgas, fMassHNO3 )
f_rh = 2.0
end if

! Following uptake coefficients of Liu et al.(2007)
gamma = gamma_hno3 * f_rh

sqrt_tk = sqrt(tk)
Expand Down Expand Up @@ -9482,7 +9494,8 @@ end subroutine get_HenrysLawCts

subroutine NIthermo (km, klid, cdt, grav, delp, rhoa, tmpu, rh, fMassHNO3, fMassAir, &
SO4, NH3, NO3an1, NH4a, xhno3, &
NI_pno3aq, NI_pnh4aq, NI_pnh3aq, rc)
NI_pno3aq, NI_pnh4aq, NI_pnh3aq, NI_phno3aq, &
NI_pno3aqv,NI_pnh4aqv, NI_pnh3aqv, NI_phno3aqv, rc)


! !USES:
Expand All @@ -9505,10 +9518,15 @@ subroutine NIthermo (km, klid, cdt, grav, delp, rhoa, tmpu, rh, fMassHNO3, fMass
real, dimension(:,:,:), intent(inout) :: NH3 ! Ammonia (NH3, gas phase) [kg kg-1]
real, dimension(:,:,:), intent(inout) :: NO3an1 ! Nitrate size bin 001 [kg kg-1]
real, dimension(:,:,:), intent(inout) :: NH4a ! Ammonium ion (NH4+, aerosol phase) [kg kg-1]
real, dimension(:,:,:), intent(inout) :: xhno3 ! buffer for NITRATE_HNO3 [kg m-2 sec-1]
real, dimension(:,:,:), intent(inout) :: xhno3 ! buffer for NITRATE_HNO3 [mol mol-1]
real, pointer, dimension(:,:), intent(inout) :: NI_pno3aq ! Nitrate Production from Aqueous Chemistry [kg m-2 s-1]
real, pointer, dimension(:,:), intent(inout) :: NI_pnh4aq ! Ammonium Production from Aqueous Chemistry [kg m-2 s-1]
real, pointer, dimension(:,:), intent(inout) :: NI_pnh3aq ! Ammonia Change from Aqueous Chemistry [kg m-2 s-1]
real, pointer, dimension(:,:), intent(inout) :: NI_phno3aq ! Nitric Acid Change from Aqueous Chemistry [kg m-2 s-1]
real, pointer, dimension(:,:,:), intent(inout) :: NI_pno3aqv ! 3D Nitrate Production from Aqueous Chemistry [kg m-2 s-1]
real, pointer, dimension(:,:,:), intent(inout) :: NI_pnh4aqv ! 3D Ammonium Production from Aqueous Chemistry [kg m-2 s-1]
real, pointer, dimension(:,:,:), intent(inout) :: NI_pnh3aqv ! 3D Ammonia Change from Aqueous Chemistry [kg m-2 s-1]
real, pointer, dimension(:,:,:), intent(inout) :: NI_phno3aqv ! 3D Nitric Acid Change from Aqueous Chemistry [kg m-2 s-1]

! !OUTPUT PARAMETERS:
integer, optional, intent(out) :: rc ! Error return code:
Expand Down Expand Up @@ -9574,6 +9592,29 @@ subroutine NIthermo (km, klid, cdt, grav, delp, rhoa, tmpu, rh, fMassHNO3, fMass
NI_pnh3aq(i,j) = NI_pnh3aq(i,j) &
+ (GNH3 / fmmr_to_conc - NH3(i,j,k)) &
* delp(i,j,k)/grav/cdt
if(associated(NI_phno3aq)) &
NI_phno3aq(i,j) = NI_phno3aq(i,j) &
+ (GNO3 / fmmr_to_conc - (xhno3(i,j,k)*fMassHNO3/fMassAir)) &
* delp(i,j,k)/grav/cdt

if(associated(NI_pno3aqv)) &
NI_pno3aqv(i,j,k) = NI_pno3aqv(i,j,k) &
+ (ANO3 / fmmr_to_conc - NO3an1(i,j,k)) &
* delp(i,j,k)/grav/cdt
if(associated(NI_pnh4aqv)) &
NI_pnh4aqv(i,j,k) = NI_pnh4aqv(i,j,k) &
+ (ANH4 / fmmr_to_conc - NH4a(i,j,k)) &
* delp(i,j,k)/grav/cdt
if(associated(NI_pnh3aqv)) &
NI_pnh3aqv(i,j,k) = NI_pnh3aqv(i,j,k) &
+ (GNH3 / fmmr_to_conc - NH3(i,j,k)) &
* delp(i,j,k)/grav/cdt
if(associated(NI_phno3aqv)) &
NI_phno3aqv(i,j,k) = NI_phno3aqv(i,j,k) &
+ (GNO3 / fmmr_to_conc - (xhno3(i,j,k)*fMassHNO3/fMassAir)) &
* delp(i,j,k)/grav/cdt



! Unit conversion back on return from thermodynamic module
NH3(i,j,k) = GNH3 / fmmr_to_conc
Expand Down