From 81912e0a640470034d55315585bcefd3c98994d2 Mon Sep 17 00:00:00 2001 From: "yuanjian.z" Date: Sat, 8 Jun 2024 02:02:24 -0500 Subject: [PATCH 1/9] Simplified and removed unnecessary codes - use AerMass in OCPISOA to avoid unnecessary recalculation - removed unnecessary OCPI reference when SVPOA is activated --- GeosCore/aerosol_mod.F90 | 45 ++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/GeosCore/aerosol_mod.F90 b/GeosCore/aerosol_mod.F90 index b8dc32b59..f909567ae 100644 --- a/GeosCore/aerosol_mod.F90 +++ b/GeosCore/aerosol_mod.F90 @@ -763,39 +763,29 @@ 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) + ! Moved here (yzhang, 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) @@ -825,13 +815,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 + ! 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 ! Particulate matter < 10um [kg/m3] State_Chm%AerMass%PM10(I,J,L) = State_Chm%AerMass%PM25(I,J,L) + & ! PM2.5 From f79c9463daa1883a7eb26b26ddff55d286ee866c Mon Sep 17 00:00:00 2001 From: "yuanjian.z" Date: Sat, 8 Jun 2024 02:15:09 -0500 Subject: [PATCH 2/9] Supported SVPOA in SNAOM parameterized effective radius - replace verbose representation of SOA and OCPI with OCPISOA --- GeosCore/aerosol_mod.F90 | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/GeosCore/aerosol_mod.F90 b/GeosCore/aerosol_mod.F90 index f909567ae..d4d6d27ee 100644 --- a/GeosCore/aerosol_mod.F90 +++ b/GeosCore/aerosol_mod.F90 @@ -876,19 +876,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 ; From 2592c6d285de8f9bbb15f47307b8d1acdfa5aad6 Mon Sep 17 00:00:00 2001 From: "yuanjian.z" Date: Tue, 11 Jun 2024 23:49:54 -0500 Subject: [PATCH 3/9] Fixed bug only including Isoprene SOA OC for TotalOC in complexSOA_nonSVPOA - also includes some rewrites for better readability --- GeosCore/aerosol_mod.F90 | 25 ++++++++----------- GeosCore/diagnostics_mod.F90 | 47 ++++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/GeosCore/aerosol_mod.F90 b/GeosCore/aerosol_mod.F90 index d4d6d27ee..e8a554a5d 100644 --- a/GeosCore/aerosol_mod.F90 +++ b/GeosCore/aerosol_mod.F90 @@ -783,7 +783,9 @@ SUBROUTINE AEROSOL_CONC( Input_Opt, State_Chm, State_Diag, & ! Add mechanistic isoprene OA (eam, 08/2015) ! Skip adding this for Simple SOA (jaf, clh, bmy, 5/17/18) - ! Moved here (yzhang, 8 Jun 2024) + ! 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 @@ -828,13 +830,6 @@ SUBROUTINE AEROSOL_CONC( Input_Opt, State_Chm, State_Diag, & State_Chm%AerMass%OCPI(I,J,L) * ORG_GROWTH 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 - ! Include either simple SOA (default) or Complex SOA in ! PM2.5 calculation. In simulations where both Simple SOA and ! Complex SOA species are carried (i.e. "benchmark"), then @@ -842,7 +837,6 @@ 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) + & @@ -850,19 +844,20 @@ SUBROUTINE AEROSOL_CONC( Input_Opt, State_Chm, State_Diag, & 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 ) diff --git a/GeosCore/diagnostics_mod.F90 b/GeosCore/diagnostics_mod.F90 index 6ea561f4b..40c1c9e12 100644 --- a/GeosCore/diagnostics_mod.F90 +++ b/GeosCore/diagnostics_mod.F90 @@ -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 @@ -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 @@ -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 @@ -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 ) + & From 006d012540076a38788ab9612558ef2c513e351c Mon Sep 17 00:00:00 2001 From: "yuanjian.z" Date: Sun, 14 Jul 2024 17:50:37 -0500 Subject: [PATCH 4/9] Updated CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b1b11d39..0df7c50a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ This file documents all notable changes to the GEOS-Chem repository starting in The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### Changed +- Simplified SOA representations and fixed related AOD and TotalOA/OC calculations in benchmark. + ## [14.4.1] - 2024-06-28 ### Added - Added initialization of PHOTDELTA in `ucx_h2so4phot` to avoid run-time error in CESM From efa425ccc595f552bd7ccd8e3d06ca2bbd0cf5fc Mon Sep 17 00:00:00 2001 From: Bob Yantosca Date: Tue, 2 Jul 2024 10:56:24 -0400 Subject: [PATCH 5/9] Add KPP_AbsTol and KPP_RelTol to species_database.yml run/shared/species_database.yml run/shared/species_database_hg.yml - Allow for KPP_AbsTol and KPP_RelTol tags. - Set KPP_AbsTol to 1.0e25 for all dummy species, in order to prevent these from being considered when computing the error norm. Headers/species_mod.F90 - Add KPP_AbsTol and KPP_RelTol to the Species derived type Headers/species_database_mod.F90 - Add "KPP_AbsTol" and "KPP_RelTol" to the tags array - Add code to parse KPP_AbsTol and KPP_RelTol tags - Remove the "places" keyword and just pass the number of decimal places, for a consistent appearance - Trimmed trailing whitespace - Updated comments Headers/state_chem_mod.F90 - Add KPP_AbsTol and KPP_RelTol 1-D arrays. These are initialized at the same time as the Map_KppVar mapping array. This will allow us to replace missing values at initialization, and just copy the values to ATOL and RTOL each timestep. This is more efficient. GeosCore/fullchem_mod.F90 GeosCore/mercury_mod.F90 - Replace missing values in State_Chm%KPP_AbsTol and State_Chm%KPP_RelTol with default values. This preserves the absolute and relative tolerances for species that were specified in species_database.yml. - Copy State_Chm%KPP_AbsTol to the KPP ATOL array - Copy State_Chm%KPP_RelTol to the KPP RTOL array Signed-off-by: Bob Yantosca --- GeosCore/fullchem_mod.F90 | 20 +++++++++++--- GeosCore/mercury_mod.F90 | 16 ++++++++++-- Headers/species_database_mod.F90 | 42 +++++++++++++++++++----------- Headers/species_mod.F90 | 9 +++++++ Headers/state_chm_mod.F90 | 33 +++++++++++++++++++++++ run/shared/species_database.yml | 16 ++++++++++++ run/shared/species_database_hg.yml | 5 ++++ 7 files changed, 120 insertions(+), 21 deletions(-) diff --git a/GeosCore/fullchem_mod.F90 b/GeosCore/fullchem_mod.F90 index 0bbe52b9a..ba9517c74 100644 --- a/GeosCore/fullchem_mod.F90 +++ b/GeosCore/fullchem_mod.F90 @@ -44,7 +44,7 @@ MODULE FullChem_Mod INTEGER :: id_NK05, id_NK08, id_NK10, id_NK20 #endif #ifdef MODEL_GEOS - INTEGER :: id_O3 +< INTEGER :: id_O3 INTEGER :: id_A3O2, id_ATO2, id_B3O2, id_BRO2 INTEGER :: id_ETO2, id_LIMO2, id_MO2, id_PIO2, id_PO2 INTEGER :: id_PRN1, id_R4N1, id_R4O2, id_TRO2, id_XRO2 @@ -468,10 +468,10 @@ SUBROUTINE Do_FullChem( Input_Opt, State_Chm, State_Diag, & !%%%%% CONVERGENCE CRITERIA %%%%% ! Absolute tolerance - ATOL = 1e-2_dp + ATOL = State_Chm%KPP_AbsTol ! Relative tolerance - RTOL = 0.5e-2_dp + RTOL = State_Chm%KPP_RelTol !======================================================================= ! %%%%% SOLVE CHEMISTRY -- This is the main KPP solver loop %%%%% @@ -2822,6 +2822,19 @@ SUBROUTINE Init_FullChem( Input_Opt, State_Chm, State_Diag, RC ) State_Diag%Archive_O1DconcAfterChem .or. & State_Diag%Archive_O3PconcAfterChem ) + + !======================================================================= + ! Assign default values for KPP absolute and relative tolerances + ! for species where these have not been explicitly defined. + !======================================================================= + WHERE( State_Chm%KPP_AbsTol == MISSING_DBLE ) + State_Chm%KPP_AbsTol = 1.0e-2_f8 + ENDWHERE + + WHERE( State_Chm%KPP_RelTol == MISSING_DBLE ) + State_Chm%KPP_RelTol = 0.5e-2_f8 + ENDWHERE + !======================================================================= ! Save physical parameters from the species database into KPP arrays ! in gckpp_Global.F90. These are for the hetchem routines. @@ -2835,7 +2848,6 @@ SUBROUTINE Init_FullChem( Input_Opt, State_Chm, State_Diag, RC ) HENRY_CR(KppId) = State_Chm%SpcData(N)%Info%Henry_CR ENDIF ENDDO - !======================================================================= ! Allocate arrays !======================================================================= diff --git a/GeosCore/mercury_mod.F90 b/GeosCore/mercury_mod.F90 index 741879cf1..68aa04a32 100644 --- a/GeosCore/mercury_mod.F90 +++ b/GeosCore/mercury_mod.F90 @@ -969,10 +969,10 @@ SUBROUTINE ChemMercury( Input_Opt, State_Chm, State_Diag, & !%%%%% CONVERGENCE CRITERIA %%%%% ! Absolute tolerance - ATOL = 1e-2_dp + ATOL = State_Chm%KPP_AbsTol ! Relative tolerance - RTOL = 1e-2_dp + RTOL = State_Chm%KPP_RelTol !%%%%% SOLVER OPTIONS %%%%% @@ -3886,6 +3886,18 @@ SUBROUTINE Init_Mercury( Input_Opt, State_Grid, State_Chm, State_Diag, RC ) ENDIF ENDDO + !======================================================================= + ! Assign default values for KPP absolute and relative tolerances + ! for species where these have not been explicitly defined. + !======================================================================= + WHERE( State_Chm%KPP_AbsTol == MISSING_DBLE ) + State_Chm%KPP_AbsTol = 1.0e-2_f8 + ENDWHERE + + WHERE( State_Chm%KPP_RelTol == MISSING_DBLE ) + State_Chm%KPP_RelTol = 1.0e-2_f8 + ENDWHERE + !======================================================================== ! Various Settings (not sure how many of these still work) !======================================================================== diff --git a/Headers/species_database_mod.F90 b/Headers/species_database_mod.F90 index abc0c08c6..36357df61 100644 --- a/Headers/species_database_mod.F90 +++ b/Headers/species_database_mod.F90 @@ -157,7 +157,7 @@ SUBROUTINE Init_Species_Database( Input_Opt, SpcData, SpcCount, RC ) REAL(f4) :: wd_rainouteff_luo(3) ! String arrays - CHARACTER(LEN=17) :: tags(64) + CHARACTER(LEN=17) :: tags(66) CHARACTER(LEN=QFYAML_StrLen):: a_str(2) ! Objects @@ -208,6 +208,11 @@ SUBROUTINE Init_Species_Database( Input_Opt, SpcData, SpcCount, RC ) "Density ", & "Formula ", & "FullName ", & + "Henry_CR ", & + "Henry_CR_Luo ", & + "Henry_K0 ", & + "Henry_K0_Luo ", & + "Henry_pKa ", & "Is_Aerosol ", & "Is_DryAlt ", & "Is_DryDep ", & @@ -218,13 +223,10 @@ SUBROUTINE Init_Species_Database( Input_Opt, SpcData, SpcCount, RC ) "Is_HgP ", & "Is_Photolysis ", & "Is_RadioNuclide ", & - "Is_Tracer ", & "Is_WetDep ", & - "Henry_CR ", & - "Henry_CR_Luo ", & - "Henry_K0 ", & - "Henry_K0_Luo ", & - "Henry_pKa ", & + "Is_Tracer ", & + "KPP_AbsTol ", & + "KPP_RelTol ", & "MP_SizeResAer ", & "MP_SizeResNum ", & "MW_g ", & @@ -611,6 +613,16 @@ SUBROUTINE Init_Species_Database( Input_Opt, SpcData, SpcCount, RC ) ThisSpc%Is_WetDep = v_bool ENDIF + ELSE IF ( INDEX( key, "%KPP_AbsTol" ) > 0 ) THEN + CALL QFYAML_Add_Get( yml, key, v_str, "", RC ) + IF ( RC /= GC_SUCCESS ) GOTO 999 + ThisSpc%KPP_AbsTol = Cast_and_RoundOff( v_str, -1 ) + + ELSE IF ( INDEX( key, "%KPP_RelTol" ) > 0 ) THEN + CALL QFYAML_Add_Get( yml, key, v_real, "", RC ) + IF ( RC /= GC_SUCCESS ) GOTO 999 + ThisSpc%KPP_RelTol = Cast_and_RoundOff( v_str, -1 ) + ELSE IF ( INDEX( key, "%MP_SizeResAer" ) > 0 ) THEN CALL QFYAML_Add_Get( yml, key, v_bool, "", RC ) IF ( RC /= GC_SUCCESS ) GOTO 999 @@ -640,8 +652,8 @@ SUBROUTINE Init_Species_Database( Input_Opt, SpcData, SpcCount, RC ) a_str = MISSING_STR CALL QFYAML_Add_Get( yml, TRIM( key ), a_str, "", RC ) IF ( RC /= GC_SUCCESS ) GOTO 999 - ThisSpc%Snk_LatMin = Cast_and_RoundOff( a_str(1), places=4 ) - ThisSpc%Snk_LatMax = Cast_and_RoundOff( a_str(2), places=4 ) + ThisSpc%Snk_LatMin = Cast_and_RoundOff( a_str(1), 4 ) + ThisSpc%Snk_LatMax = Cast_and_RoundOff( a_str(2), 4 ) ELSE IF ( INDEX( key, "%Snk_Mode" ) > 0 ) THEN CALL QFYAML_Add_Get( yml, key, v_str, "", RC ) @@ -677,8 +689,8 @@ SUBROUTINE Init_Species_Database( Input_Opt, SpcData, SpcCount, RC ) a_str = MISSING_STR CALL QFYAML_Add_Get( yml, TRIM( key ), a_str, "", RC ) IF ( RC /= GC_SUCCESS ) GOTO 999 - ThisSpc%Src_LatMin = Cast_and_RoundOff( a_str(1), places=4 ) - ThisSpc%Src_LatMax = Cast_and_RoundOff( a_str(2), places=4 ) + ThisSpc%Src_LatMin = Cast_and_RoundOff( a_str(1), 4 ) + ThisSpc%Src_LatMax = Cast_and_RoundOff( a_str(2), 4 ) ELSE IF ( INDEX( key, "%Src_Mode" ) > 0 ) THEN CALL QFYAML_Add_Get( yml, key, v_str, "", RC ) @@ -689,8 +701,8 @@ SUBROUTINE Init_Species_Database( Input_Opt, SpcData, SpcCount, RC ) a_str = MISSING_STR CALL QFYAML_Add_Get( yml, TRIM( key ), a_str, "", RC ) IF ( RC /= GC_SUCCESS ) GOTO 999 - ThisSpc%Src_PresMin = Cast_and_RoundOff( a_str(1), places=4 ) - ThisSpc%Src_PresMax = Cast_and_RoundOff( a_str(2), places=4 ) + ThisSpc%Src_PresMin = Cast_and_RoundOff( a_str(1), 4 ) + ThisSpc%Src_PresMax = Cast_and_RoundOff( a_str(2), 4 ) ELSE IF ( INDEX( key, "%Src_Units" ) > 0 ) THEN CALL QFYAML_Add_Get( yml, key, v_str, "", RC ) @@ -1359,8 +1371,8 @@ SUBROUTINE Unique_Species_Names( Input_Opt, nSpecies, RC ) ENDDO !======================================================================= - ! For specialty simulations, we do not have KPP species. Thus, the - ! of species is just the list of advected species from geoschem_config.yml + ! For speciality simulations that do not use KPP-built mechanisms, + ! we can just use the advected species list from geoschem_config.yml !======================================================================= ELSE diff --git a/Headers/species_mod.F90 b/Headers/species_mod.F90 index ebcbfb2fe..46a6ba7c1 100644 --- a/Headers/species_mod.F90 +++ b/Headers/species_mod.F90 @@ -194,6 +194,10 @@ MODULE Species_Mod LOGICAL :: Is_Hg2 ! Is a Hg2 species? LOGICAL :: Is_HgP ! Is a HgP species? + ! KPP solver parameters + REAL(f8) :: KPP_AbsTol ! Absolute tolerance + REAL(f8) :: KPP_RelTol ! Relative tolerance + END TYPE Species ! ! !DEFINED PARAMETERS: @@ -454,6 +458,8 @@ SUBROUTINE Spc_Zero( Spc ) Spc%Henry_CR = MISSING_DBLE Spc%Henry_K0 = MISSING_DBLE Spc%Henry_PKA = MISSING_DBLE + Spc%KPP_AbsTol = MISSING_DBLE + Spc%KPP_RelTol = MISSING_DBLE ! Strings Spc%Formula = MISSING_STR @@ -597,6 +603,9 @@ SUBROUTINE Spc_Print( Input_Opt, ThisSpc, RC ) WRITE( 6, 130 ) "Is_FixedChem ", ThisSpc%Is_FixedChem WRITE( 6, 100 ) "KppFixId ", ThisSpc%KppFixId ENDIF + + WRITE( 6, 120 ) "KPP_AbsTol ", ThisSpc%KPP_AbsTol + WRITE( 6, 120 ) "KPP_RelTol ", ThisSpc%KPP_RelTol ENDIF !-------------------------------------------------------------------- diff --git a/Headers/state_chm_mod.F90 b/Headers/state_chm_mod.F90 index 4a013f1a6..206b71eb8 100644 --- a/Headers/state_chm_mod.F90 +++ b/Headers/state_chm_mod.F90 @@ -91,6 +91,8 @@ MODULE State_Chm_Mod !----------------------------------------------------------------------- ! Mapping vectors to subset types of species !----------------------------------------------------------------------- + REAL(f8), POINTER :: KPP_AbsTol (: ) ! KPP absolute tolerance + REAL(f8), POINTER :: KPP_RelTol (: ) ! KPP relative tolerance INTEGER, POINTER :: Map_Advect (: ) ! Advected species IDs INTEGER, POINTER :: Map_Aero (: ) ! Aerosol species IDs INTEGER, POINTER :: Map_All (: ) ! All species IDs @@ -644,6 +646,10 @@ SUBROUTINE Zero_State_Chm( State_Chm, RC ) State_Chm%PSO4_SO2APM2 => NULL() #endif + ! KPP integrator quantities + State_Chm%KPP_AbsTol => NULL() + State_Chm%KPP_RelTol => NULL() + END SUBROUTINE Zero_State_Chm !EOC !------------------------------------------------------------------------------ @@ -2525,6 +2531,17 @@ SUBROUTINE Init_Mapping_Vectors( Input_Opt, State_Chm, RC ) CALL GC_CheckVar( 'State_Chm%Map_KppVar', 0, RC ) IF ( RC /= GC_SUCCESS ) RETURN State_Chm%Map_KppVar = 0 + + ! + ALLOCATE( State_Chm%KPP_AbsTol( N ), STAT=RC ) + CALL GC_CheckVar( 'State_Chm%KppAbsTol', 0, RC ) + IF ( RC /= GC_SUCCESS ) RETURN + State_Chm%KPP_AbsTol = 0.0_f8 + + ALLOCATE( State_Chm%KPP_RelTol( N ), STAT=RC ) + CALL GC_CheckVar( 'State_Chm%KppRelTol', 0, RC ) + IF ( RC /= GC_SUCCESS ) RETURN + State_Chm%KPP_RelTol = 0.0_f8 ENDIF N = State_Chm%nKppFix + State_Chm%nOmitted @@ -2683,6 +2700,8 @@ SUBROUTINE Init_Mapping_Vectors( Input_Opt, State_Chm, RC ) IF ( ThisSpc%Is_ActiveChem ) THEN C = ThisSpc%KppVarId State_Chm%Map_KppVar(C) = ThisSpc%ModelId + State_Chm%KPP_AbsTol(C) = ThisSpc%KPP_AbsTol + State_Chm%KPP_RelTol(C) = ThisSpc%KPP_RelTol ENDIF !--------------------------------------------------------------------- @@ -3088,6 +3107,20 @@ SUBROUTINE Cleanup_State_Chm( State_Chm, RC ) State_Chm%Phot => NULL() ENDIF + IF ( ASSOCIATED( State_Chm%KPP_AbsTol ) ) THEN + DEALLOCATE( State_Chm%KPP_AbsTol, STAT=RC ) + CALL GC_CheckVar( 'State_Chm%KPP_AbsTol', 2, RC ) + IF ( RC /= GC_SUCCESS ) RETURN + State_Chm%KPP_AbsTol => NULL() + ENDIF + + IF ( ASSOCIATED( State_Chm%KPP_RelTol ) ) THEN + DEALLOCATE( State_Chm%KPP_RelTol, STAT=RC ) + CALL GC_CheckVar( 'State_Chm%KPP_RelTol', 2, RC ) + IF ( RC /= GC_SUCCESS ) RETURN + State_Chm%KPP_RelTol => NULL() + ENDIF + IF ( ASSOCIATED( State_Chm%Map_Advect ) ) THEN DEALLOCATE( State_Chm%Map_Advect, STAT=RC ) CALL GC_CheckVar( 'State_Chm%Map_Advect', 2, RC ) diff --git a/run/shared/species_database.yml b/run/shared/species_database.yml index 7788822fb..146e6036c 100644 --- a/run/shared/species_database.yml +++ b/run/shared/species_database.yml @@ -2760,18 +2760,22 @@ LBRO2H: FullName: Dummy species to track oxidation of BRO2 by HO2 Is_Gas: true MW_g: 159.13 + KPP_AbsTol: 1.0e+25_8 LBRO2N: FullName: Dummy species to track oxidation of BRO2 by NO Is_Gas: true MW_g: 159.13 + KPP_AbsTol: 1.0e+25 LCH4: FullName: Dummy species to track loss rate of CH4 Is_Gas: true MW_g: 16.04 + KPP_AbsTol: 1.0e+25 LCO: FullName: Dummy species to track loss rate of CO Is_Gas: true MW_g: 28.01 + KPP_AbsTol: 1.0e+25 LIMO: DD_F0: 0.0 DD_Hstar: 7.0e-2 @@ -2794,14 +2798,17 @@ LISOPNO3: FullName: Dummy species to track oxidation of ISOP by NO3 Is_Gas: true MW_g: 68.13 + KPP_AbsTol: 1.0e+25 LISOPOH: FullName: Dummy species to track oxidation of ISOP by OH Is_Gas: true MW_g: 68.13 + KPP_AbsTol: 1.0e+25 LNRO2H: FullName: Dummy species to track oxidation of NRO2 by HO2 Is_Gas: true MW_g: 159.17 + KPP_AbsTol: 1.0e+25 LNRO2N: FullName: Dummy species to track oxidation of NRO2 by NO Is_Gas: true @@ -2810,14 +2817,17 @@ LOx: FullName: Dummy species to track loss rate of Ox Is_Gas: true MW_g: 48.00 + KPP_AbsTol: 1.0e+25 LTRO2H: FullName: Dummy species to track oxidation of TRO2 by HO2 Is_Gas: true MW_g: 173.16 + KPP_AbsTol: 1.0e+25 LTRO2N: FullName: Dummy species to track oxidation of TRO2 by NO Is_Gas: true MW_g: 173.16 + KPP_AbsTol: 1.0e+25 LVOC: DD_F0: 1.0 DD_Hstar: 1.0e+8 @@ -2850,10 +2860,12 @@ LXRO2H: FullName: Dummy species to track oxidation of XRO2 by HO2 Is_Gas: true MW_g: 187.19 + KPP_AbsTol: 1.0e+25 LXRO2N: FullName: Dummy species to track oxidation of XRO2 by NO Is_Gas: true MW_g: 187.19 + KPP_AbsTol: 1.0e+25 MACR: DD_F0: 1.0 DD_Hstar: 6.5 @@ -3818,6 +3830,7 @@ PCO: FullName: Dummy species to track production rate of CO Is_Gas: true MW_g: 28.01 + KPP_AbsTol: 1.0e+25 pFe: DD_F0: 0.0 DD_Hstar: 0.0 @@ -3836,6 +3849,7 @@ PH2O2: FullName: Dummy species to track production rate of H2O2 Is_Gas: true MW_g: 34.02 + KPP_AbsTol: 1.0e+25 PH2SO4: FullName: SO4 from gas-phase chemistry Is_Gas: true @@ -4136,6 +4150,7 @@ POx: FullName: Dummy species to track production rate of Ox Is_Gas: true MW_g: 48.00 + KPP_AbsTol: 1.0e+25 PP: DD_F0: 1.0 DD_Hstar: 2.94e+2 @@ -4210,6 +4225,7 @@ PSO4: FullName: Dummy species to track production of SO4 Is_Gas: true MW_g: 96.06 + KPP_AbsTol: 1.0e+25 PSO4AQ: FullName: SO4 from cloud chemistry Is_Gas: true diff --git a/run/shared/species_database_hg.yml b/run/shared/species_database_hg.yml index 3245b80b2..c69094c72 100644 --- a/run/shared/species_database_hg.yml +++ b/run/shared/species_database_hg.yml @@ -251,19 +251,24 @@ PHg2: FullName: Gross production of gaseous oxidized Hg Is_Gas: true MW_g: 200.59 # Use mol wt of atomic Hg + KPP_AbsTol: 1.0e+25 PHg0: FullName: Gross production of Hg2 Is_Gas: true MW_g: 200.59 # Use mol wt of atomic Hg + KPP_AbsTol: 1.0e+25 PHg2Br: FullName: Gaseous oxidized Hg production from Br Is_Gas: true MW_g: 200.59 # Use mol wt of atomic Hg + KPP_AbsTol: 1.0e+25 PHg2OH: FullName: Gaseous oxidized Hg production from OH Is_Gas: true MW_g: 200.59 # Use mol wt of atomic Hg + KPP_AbsTol: 1.0e+25 PHg2Cl: FullName: Gaseous oxidized Hg production from Cl Is_Gas: true MW_g: 200.59 # Use mol wt of atomic Hg + KPP_AbsTol: 1.0e25 From 8129a609b617ff089ad25c57e93bd607d4077cc2 Mon Sep 17 00:00:00 2001 From: Bob Yantosca Date: Tue, 2 Jul 2024 11:00:58 -0400 Subject: [PATCH 6/9] Update CHANGELOG for KPP_AbsTol and KPP_RelTol updates CHANGELOG.md - Added notes describing how we can now define KPP absolute and relative tolerances for species in species_database.yml Signed-off-by: Bob Yantosca --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0df7c50a5..88efd3022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,13 @@ This file documents all notable changes to the GEOS-Chem repository starting in The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - TBD +### Added +- Set `KPP_AbsTol` to 1e5 for dummy species in `species_database.yml` and `species_database_hg.yml` +- Vectors `State_Chm%KPP_AbsTol` and `State_Chm%KPP_RelTol` + ### Changed +- Copy values from `State_Chm%KPP_AbsTol` to `ATOL` and `State_Chm%KPP_RelTol` to `RTOL` for fullchem and Hg simulations - Simplified SOA representations and fixed related AOD and TotalOA/OC calculations in benchmark. ## [14.4.1] - 2024-06-28 From fd5541ab75ea65011a22ef895f14613beb7b4fb4 Mon Sep 17 00:00:00 2001 From: Bob Yantosca Date: Tue, 2 Jul 2024 12:10:38 -0400 Subject: [PATCH 7/9] In roundoff_mod.F90, cast first, then round off if places > 0 Headers/roundoff_mod.F90 - Bug fix: First cast to dble or flex. Then round off if the places argument is > 0. This allows us to just cast w/o rounding off if needed. run/shared/species_database_mod.F90 - Changed 1.0e+25_8 to 1.0e+25 in for KPP_AbsTol (LBRO2H) CHANGELOG.md - Updated accordingly Signed-off-by: Bob Yantosca --- CHANGELOG.md | 3 +++ Headers/roundoff_mod.F90 | 5 ++++- run/shared/species_database.yml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88efd3022..989cab7b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,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 diff --git a/Headers/roundoff_mod.F90 b/Headers/roundoff_mod.F90 index c1730e7f3..d1d7172fa 100644 --- a/Headers/roundoff_mod.F90 +++ b/Headers/roundoff_mod.F90 @@ -167,7 +167,10 @@ FUNCTION Cast_and_RoundOff_Real2Dble( v_real, places ) RESULT( v_dble ) ENDIF ! Cast to real*8 and roundoff (if the number isn't too large) - v_dble = RoundOff( DBLE( v_real ), places ) + v_dble = DBLE( v_real ) + IF ( places > 0 ) THEN + v_dble = RoundOff( v_dble, places ) + ENDIF END FUNCTION Cast_And_RoundOff_Real2Dble !EOC diff --git a/run/shared/species_database.yml b/run/shared/species_database.yml index 146e6036c..a80b954e6 100644 --- a/run/shared/species_database.yml +++ b/run/shared/species_database.yml @@ -2760,7 +2760,7 @@ LBRO2H: FullName: Dummy species to track oxidation of BRO2 by HO2 Is_Gas: true MW_g: 159.13 - KPP_AbsTol: 1.0e+25_8 + KPP_AbsTol: 1.0e+25 LBRO2N: FullName: Dummy species to track oxidation of BRO2 by NO Is_Gas: true From b0ec470b6babac6cb5cb141ce8f850418ecf4362 Mon Sep 17 00:00:00 2001 From: Bob Yantosca Date: Tue, 2 Jul 2024 12:17:10 -0400 Subject: [PATCH 8/9] Fixed typo in fullchem_mod.F90 GeosCore/fullchem_mod.F90 - Removed extraneous "<" character Signed-off-by: Bob Yantosca --- GeosCore/fullchem_mod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GeosCore/fullchem_mod.F90 b/GeosCore/fullchem_mod.F90 index ba9517c74..ecdda088d 100644 --- a/GeosCore/fullchem_mod.F90 +++ b/GeosCore/fullchem_mod.F90 @@ -44,7 +44,7 @@ MODULE FullChem_Mod INTEGER :: id_NK05, id_NK08, id_NK10, id_NK20 #endif #ifdef MODEL_GEOS -< INTEGER :: id_O3 + INTEGER :: id_O3 INTEGER :: id_A3O2, id_ATO2, id_B3O2, id_BRO2 INTEGER :: id_ETO2, id_LIMO2, id_MO2, id_PIO2, id_PO2 INTEGER :: id_PRN1, id_R4N1, id_R4O2, id_TRO2, id_XRO2 From eabf06c88167f680d2ae932a139852fa3a42d55d Mon Sep 17 00:00:00 2001 From: Lee Murray Date: Thu, 4 Jul 2024 11:47:42 -0400 Subject: [PATCH 9/9] Update setCommonRunSettings.sh.template Fix typo for MassFlux_Entry --- run/GCHP/setCommonRunSettings.sh.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run/GCHP/setCommonRunSettings.sh.template b/run/GCHP/setCommonRunSettings.sh.template index 667ab8615..9a610e116 100644 --- a/run/GCHP/setCommonRunSettings.sh.template +++ b/run/GCHP/setCommonRunSettings.sh.template @@ -386,7 +386,7 @@ fi #### Mass flux checks for grid resolution and domain decomposition MassFlux_Entry=$(grep "MFXC" ExtData.rc || echo "missing") -if [[ ${MassFluxEntry} != "missing" ]]; then +if [[ ${MassFlux_Entry} != "missing" ]]; then #### Get met grid res (assume GEOS-IT and GEOS-FP are the only options) C180_Entry=$(grep "MFXC.*C180x180x6" ExtData.rc || echo "missing")