Skip to content

Commit

Permalink
Merge PR #2315 (Fix bugs in PDER, OCPISOA, and TotalOC)
Browse files Browse the repository at this point in the history
This merge brings PR #2315 (ix bugs in PDER, OCPISOA and TotalOC in
complexSOA, by @yuanjianz) into the GEOS-Chem 14.5.0 development stream.

This PR fixes several minor bugs in the complex SOA scheme as described
in issues #2314 and #2321.

Signed-off-by: Bob Yantosca <yantosca@seas.harvard.edu>
  • Loading branch information
yantosca committed Jul 16, 2024
2 parents e61a510 + eabf06c commit ef2ea60
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 68 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Fixed
- In `Headers/roundoff_mod.F90`, first cast and then only round off if `places > 0`
- Typo in `setCommonRunSettings.sh` that made GCHP always choose mass fluxes for meteorology
- Simplified SOA representations and fixed related AOD and TotalOA/OC calculations in benchmark.

## [14.4.1] - 2024-06-28
### Added
Expand All @@ -39,6 +40,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Removed MPI broadcasts in CESM-only UCX code; MPI broadcast done at coupler level
- Remove enabling O-server in GCHP for high core counts

### Fixed
- In `Headers/roundoff_mod.F90`, first cast and then only round off if `places > 0`

## [14.4.0] - 2024-05-30
### Added
- Added `SpcConc%Units` for species-specific unit conversion
Expand Down
91 changes: 39 additions & 52 deletions GeosCore/aerosol_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -763,39 +763,31 @@ SUBROUTINE AEROSOL_CONC( Input_Opt, State_Chm, State_Diag, &

! Use simple SOA by default over complex SOA in calculations
IF ( Is_SimpleSOA ) THEN
State_Chm%AerMass%OCPISOA(I,J,L) = ( Spc(id_OCPI)%Conc(I,J,L) * State_chm%AerMass%OCFOPOA(I,J) + &
Spc(id_SOAS)%Conc(I,J,L) ) / AIRVOL(I,J,L)
State_Chm%AerMass%OCPISOA(I,J,L) = State_Chm%AerMass%OCPI(I,J,L) + &
State_Chm%AerMass%SOAS(I,J,L)

ELSEIF ( Is_ComplexSOA ) THEN

State_Chm%AerMass%OCPISOA(I,J,L) = ( Spc(id_TSOA1)%Conc(I,J,L) &
+ Spc(id_TSOA2)%Conc(I,J,L) &
+ Spc(id_TSOA3)%Conc(I,J,L) &
+ Spc(id_TSOA0)%Conc(I,J,L) &
+ Spc(id_ASOAN)%Conc(I,J,L) &
+ Spc(id_ASOA1)%Conc(I,J,L) &
+ Spc(id_ASOA2)%Conc(I,J,L) &
+ Spc(id_ASOA3)%Conc(I,J,L) ) &
/ AIRVOL(I,J,L)

IF ( IS_OPOA ) THEN ! hotp 7/28/10
State_Chm%AerMass%OCPISOA(I,J,L) = State_Chm%AerMass%OCPISOA(I,J,L) + &
( Spc(id_OPOA1)%Conc(I,J,L) &
+ Spc(id_OPOA2)%Conc(I,J,L) ) &
* State_chm%AerMass%OCFOPOA(I,J) / AIRVOL(I,J,L)
ENDIF
State_Chm%AerMass%OCPISOA(I,J,L) = State_Chm%AerMass%TSOA(I,J,L) + &
State_Chm%AerMass%ASOA(I,J,L)

IF ( IS_OCPI ) THEN ! hotp 7/28/10
State_Chm%AerMass%OCPISOA(I,J,L) = State_Chm%AerMass%OCPISOA(I,J,L) + Spc(id_OCPI)%Conc(I,J,L) &
* State_chm%AerMass%OCFOPOA(I,J) / AIRVOL(I,J,L)
State_Chm%AerMass%OCPISOA(I,J,L) = State_Chm%AerMass%OCPISOA(I,J,L) + &
State_Chm%AerMass%OCPI(I,J,L)
ENDIF

ENDIF
IF ( IS_OPOA ) THEN ! hotp 7/28/10
State_Chm%AerMass%OCPISOA(I,J,L) = State_Chm%AerMass%OCPISOA(I,J,L) + &
State_Chm%AerMass%OPOA(I,J,L)
ENDIF

! Add mechanistic isoprene OA (eam, 08/2015)
! Skip adding this for Simple SOA (jaf, clh, bmy, 5/17/18)
IF ( Is_ComplexSOA ) THEN
! Add mechanistic isoprene OA (eam, 08/2015)
! Skip adding this for Simple SOA (jaf, clh, bmy, 5/17/18)
! benchmark OCPISOA follows simpleSOA and
! should exculde ISOAAQ to avoid double-counting
! (yuanjianz, 8 Jun 2024)
State_Chm%AerMass%OCPISOA(I,J,L) = State_Chm%AerMass%OCPISOA(I,J,L) + State_Chm%AerMass%ISOAAQ(I,J,L)

ENDIF

! Now avoid division by zero (bmy, 4/20/04)
Expand Down Expand Up @@ -825,20 +817,18 @@ SUBROUTINE AEROSOL_CONC( Input_Opt, State_Chm, State_Diag, &
State_Chm%AerMass%BCPI(I,J,L) + &
State_Chm%AerMass%BCPO(I,J,L) + &
State_Chm%AerMass%OCPO(I,J,L) + &
State_Chm%AerMass%OCPI(I,J,L) * ORG_GROWTH + &
State_Chm%AerMass%SALA(I,J,L) * SSA_GROWTH + &
SOILDUST(I,J,L,1) + &
SOILDUST(I,J,L,2) + &
SOILDUST(I,J,L,3) + &
SOILDUST(I,J,L,4) + &
SOILDUST(I,J,L,5) * 0.3_fp ! + 30% of DST2

! Particulate matter < 10um [kg/m3]
State_Chm%AerMass%PM10(I,J,L) = State_Chm%AerMass%PM25(I,J,L) + & ! PM2.5
SOILDUST(I,J,L,5) * 0.7_fp + & ! + 70% of DST2
SOILDUST(I,J,L,6) + & ! + 100% of DST3
SOILDUST(I,J,L,7) * 0.9_fp + & ! + 90% of DST4
State_Chm%AerMass%SALC(I,J,L) * SSA_GROWTH
! OCPI is not present in SVPOA simulation
! OCPO represents all POA intead (factor*POA)
IF ( Is_OCPI ) THEN
State_Chm%AerMass%PM25(I,J,L) = State_Chm%AerMass%PM25(I,J,L) + &
State_Chm%AerMass%OCPI(I,J,L) * ORG_GROWTH
ENDIF

! Include either simple SOA (default) or Complex SOA in
! PM2.5 calculation. In simulations where both Simple SOA and
Expand All @@ -847,27 +837,27 @@ SUBROUTINE AEROSOL_CONC( Input_Opt, State_Chm, State_Diag, &
! to avoid double-counting. (bmy, 03 Nov 2021)
IF ( Is_SimpleSOA ) THEN
State_Chm%AerMass%PM25(I,J,L) = State_Chm%AerMass%PM25(I,J,L) + ( State_Chm%AerMass%SOAS(I,J,L) * ORG_GROWTH )
State_Chm%AerMass%PM10(I,J,L) = State_Chm%AerMass%PM10(I,J,L) + ( State_Chm%AerMass%SOAS(I,J,L) * ORG_GROWTH )

ELSE IF ( Is_ComplexSOA ) THEN
State_Chm%AerMass%PM25(I,J,L) = State_Chm%AerMass%PM25(I,J,L) + &
State_Chm%AerMass%TSOA(I,J,L) * ORG_GROWTH + &
State_Chm%AerMass%ASOA(I,J,L) * ORG_GROWTH + &
State_Chm%AerMass%ISOAAQ(I,J,L) * ORG_GROWTH ! Includes SOAGX

State_Chm%AerMass%PM10(I,J,L) = State_Chm%AerMass%PM10(I,J,L) + &
State_Chm%AerMass%TSOA(I,J,L) * ORG_GROWTH + &
State_Chm%AerMass%ASOA(I,J,L) * ORG_GROWTH + &
State_Chm%AerMass%ISOAAQ(I,J,L) * ORG_GROWTH ! Includes SOAGX

! Need to add OPOA to PM2.5 for complexSOA_SVPOA simulations
! -- Maggie Marvin (15 Jul 2020)
IF ( Is_OPOA ) THEN
State_Chm%AerMass%PM25(I,J,L) = State_Chm%AerMass%PM25(I,J,L) + ( State_Chm%AerMass%OPOA(I,J,L) * ORG_GROWTH )
State_Chm%AerMass%PM10(I,J,L) = State_Chm%AerMass%PM10(I,J,L) + ( State_Chm%AerMass%OPOA(I,J,L) * ORG_GROWTH )
ENDIF
ENDIF

! Particulate matter < 10um [kg/m3]
State_Chm%AerMass%PM10(I,J,L) = State_Chm%AerMass%PM25(I,J,L) + & ! PM2.5
SOILDUST(I,J,L,5) * 0.7_fp + & ! + 70% of DST2
SOILDUST(I,J,L,6) + & ! + 100% of DST3
SOILDUST(I,J,L,7) * 0.9_fp + & ! + 90% of DST4
State_Chm%AerMass%SALC(I,J,L) * SSA_GROWTH

! Apply STP correction factor based on ideal gas law
State_Chm%AerMass%PM25(I,J,L) = State_Chm%AerMass%PM25(I,J,L) * ( 1013.25_fp / PMID(I,J,L) ) * &
( T(I,J,L) / 298.0_fp )
Expand All @@ -881,19 +871,16 @@ SUBROUTINE AEROSOL_CONC( Input_Opt, State_Chm, State_Diag, &
! Parameterized dry effective radius for SNA and OM
!===========================================================
IF ( State_Chm%AerMass%SO4_NH4_NIT(I,J,L) > 0e+0_fp ) THEN
IF ( Is_SimpleSOA ) THEN
! dry SNA and OM mass, in unit of ug/m3
State_Chm%AerMass%SNAOM(I,J,L) = ( State_Chm%AerMass%SO4_NH4_NIT(I,J,L) + State_Chm%AerMass%OCPO(I,J,L) + State_Chm%AerMass%OCPI(I,J,L) + State_Chm%AerMass%SOAS(I,J,L) )*1.0e+9_fp
! ratio between OM and SNA, unitless
State_Chm%AerMass%R_OMSNA(I,J,L) = (State_Chm%AerMass%OCPO(I,J,L) + State_Chm%AerMass%OCPI(I,J,L) + State_Chm%AerMass%SOAS(I,J,L)) / State_Chm%AerMass%SO4_NH4_NIT(I,J,L)

ELSE IF ( Is_ComplexSOA ) THEN
! dry SNA and OM mass, in unit of ug/m3
State_Chm%AerMass%SNAOM(I,J,L) = ( State_Chm%AerMass%SO4_NH4_NIT(I,J,L) + State_Chm%AerMass%OCPO(I,J,L) + State_Chm%AerMass%OCPI(I,J,L) + State_Chm%AerMass%TSOA(I,J,L) + State_Chm%AerMass%ASOA(I,J,L) + State_Chm%AerMass%ISOAAQ(I,J,L) ) * 1.0e+9_fp
! ratio between OM and SNA, unitless
State_Chm%AerMass%R_OMSNA(I,J,L) = (State_Chm%AerMass%OCPO(I,J,L) + State_Chm%AerMass%OCPI(I,J,L) + State_Chm%AerMass%TSOA(I,J,L) + State_Chm%AerMass%ASOA(I,J,L) + State_Chm%AerMass%ISOAAQ(I,J,L) )/ State_Chm%AerMass%SO4_NH4_NIT(I,J,L)

ENDIF
! dry SNA and OM mass, in unit of ug/m3
State_Chm%AerMass%SNAOM(I,J,L) = ( State_Chm%AerMass%SO4_NH4_NIT(I,J,L) + &
State_Chm%AerMass%OCPO(I,J,L) + &
State_Chm%AerMass%OCPISOA(I,J,L) ) * 1.0e+9_fp

! ratio between OM and SNA, unitless
State_Chm%AerMass%R_OMSNA(I,J,L) = ( State_Chm%AerMass%OCPO(I,J,L) + &
State_Chm%AerMass%OCPISOA(I,J,L) ) / &
State_Chm%AerMass%SO4_NH4_NIT(I,J,L)

! Parameterized dry effective radius, in unit of um
State_Chm%AerMass%PDER(I,J,L) = (exp( 4.36_fp + 0.20_fp*log(State_Chm%AerMass%SNAOM(I,J,L)) + 0.065_fp*log(State_Chm%AerMass%R_OMSNA(I,J,L)) ) *0.001_fp )/0.9_fp ;

Expand Down
47 changes: 31 additions & 16 deletions GeosCore/diagnostics_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,8 @@ SUBROUTINE Set_AerMass_Diagnostic( Input_Opt, State_Chm, State_Diag, &
!
! !USES:
!
USE Aerosol_Mod, ONLY : IS_POA, IS_OPOA
USE Aerosol_Mod, ONLY : Is_POA, Is_OPOA, Is_OCPO, Is_OCPI
USE Aerosol_Mod, ONLY : Is_ComplexSOA, Is_SimpleSOA
USE ErrCode_Mod
USE Input_Opt_Mod, ONLY : OptInput
USE Species_Mod, ONLY : Species, SpcConc
Expand Down Expand Up @@ -2087,7 +2088,7 @@ SUBROUTINE Set_AerMass_Diagnostic( Input_Opt, State_Chm, State_Diag, &
IF ( State_Diag%Archive_AerMassPOA ) THEN
IF ( Is_POA ) THEN
State_Diag%AerMassPOA(I,J,L) = OCPO(I,J,L) * kgm3_to_ugm3
ELSE
ELSEIF ( Is_OCPO ) THEN
State_Diag%AerMassPOA(I,J,L) = ( OCPI(I,J,L) + OCPO(I,J,L) ) * &
kgm3_to_ugm3
ENDIF
Expand Down Expand Up @@ -2158,12 +2159,13 @@ SUBROUTINE Set_AerMass_Diagnostic( Input_Opt, State_Chm, State_Diag, &
! PDER [nm]
!--------------------------------------
IF ( State_Diag%Archive_PDER ) THEN
State_Diag%PDER(I,J,L) = PDER(I,J,L)
State_Diag%PDER(I,J,L) = PDER(I,J,L)
ENDIF

!--------------------------------------
! Sum of all biogenic organic aerosol
!--------------------------------------
! ComplexSOA only
IF ( State_Diag%Archive_TotalBiogenicOA ) THEN
State_Diag%TotalBiogenicOA(I,J,L) = ( TSOA(I,J,L) + ISOAAQ(I,J,L) ) &
* kgm3_to_ugm3
Expand All @@ -2172,34 +2174,47 @@ SUBROUTINE Set_AerMass_Diagnostic( Input_Opt, State_Chm, State_Diag, &
!--------------------------------------
! Sum of all organic aerosol [ug/m3]
!--------------------------------------
! Now TotalOA also works for simpleSOA
IF ( State_Diag%Archive_TotalOA ) THEN
State_Diag%TotalOA(I,J,L) = ( TSOA(I,J,L) + &
ASOA(I,J,L) + &
OCPO(I,J,L) + &
OCPI(I,J,L) + &
OPOA(I,J,L) + &
ISOAAQ(I,J,L) ) * kgm3_to_ugm3
State_Diag%TotalOA(I,J,L) = ( OCPO(I,J,L) + &
OCPISOA(I,J,L) ) * kgm3_to_ugm3
ENDIF

!--------------------------------------
! Sum of all organic carbon [ug/m3]
!--------------------------------------
! ComplexSOA only
! since OM/OC ratio is not available for SOAS
! consistent with aerosol_mod.F90
IF ( State_Diag%Archive_TotalOC ) THEN

! Hydrophobic OC
IF ( Is_POA ) THEN
State_Diag%TotalOC(I,J,L) = &
( ( TSOA(I,J,L) + ASOA(I,J,L) &
+ OCPI(I,J,L) + OPOA(I,J,L) ) / OCFOPOA(I,J) &
( ( TSOA(I,J,L) + ASOA(I,J,L) ) / OCFOPOA(I,J) &
+ OCPO(I,J,L) / OCFPOA(I,J) ) * kgm3_to_ugm3

ELSE IF ( Is_OPOA ) THEN
ELSE IF ( Is_OCPO ) THEN
State_Diag%TotalOC(I,J,L) = &
( ( TSOA(I,J,L) + ASOA(I,J,L) &
+ OCPO(I,J,L) + OCPI(I,J,L) + OPOA(I,J,L) ) &
/ OCFOPOA(I,J) ) * kgm3_to_ugm3
+ OCPO(I,J,L) ) / OCFOPOA(I,J) ) * kgm3_to_ugm3
ENDIF

! Hydrophilic OC
IF (Is_OCPI) THEN
State_Diag%TotalOC(I,J,L) = State_Diag%TotalOC(I,J,L) + &
( OCPI(I,J,L) / OCFOPOA(I,J) * &
kgm3_to_ugm3 )
ENDIF

! OPOA OC
IF (Is_OPOA) THEN
State_Diag%TotalOC(I,J,L) = State_Diag%TotalOC(I,J,L) + &
( OPOA(I,J,L) / OCFOPOA(I,J) * &
kgm3_to_ugm3 )
ENDIF

IF ( Input_Opt%LSOA ) THEN
! Isoprene SOA OC
IF ( Is_ComplexSOA ) THEN
State_Diag%TotalOC(I,J,L) = State_Diag%TotalOC(I,J,L) + &
( ( Spc(id_SOAIE )%Conc(I,J,L) * Fac_SOAIE ) + &
( Spc(id_INDIOL)%Conc(I,J,L) * Fac_INDIOL ) + &
Expand Down

0 comments on commit ef2ea60

Please sign in to comment.