diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ba96b2a4..01e484d93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] - TBD ### Added - Added allocate guards for arrays in `pressure_mod` +- Added `State_Diag%SatDiagnEdgeCount` counter for the `SatDiagnEdge` collection +- Added `State_Diag%Archive_SatDiagnEdgeCount` field +- Added `State_Diag%Archive_SatDiagnEdge` field +- Added routine `SatDiagn_or_SatDiagnEdge` in `History/history_utils_mod.F90` ### Changed - Renamed `Emiss_Carbon_Gases` to `CO2_Production` in `carbon_gases_mod.F90` - Updated start date and restart file for CO2 and tagCO simulations for consistency with carbon simulations +- Allocated `State_Diag%SatDiagnPEDGE` ffield with vertical dimension `State_Grid%NZ+1` ### Fixed - Added a fix to skip the call to KPP when only CO2 is defined in the carbon simulation @@ -19,6 +24,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Fixed entries for CO2 emissions in `ExtData.rc.carbon` - Fixed metals simulation name in config file template comments - Fixed bug in `download_data.py` which caused script to fail if log filename contained uppercase characters. +- Fixed the satellite diagnostics counters from being inadvertently being reset ## [14.5.0] - 2024-11-07 ### Added diff --git a/GeosCore/diagnostics_mod.F90 b/GeosCore/diagnostics_mod.F90 index f84a107a7..74375ca21 100644 --- a/GeosCore/diagnostics_mod.F90 +++ b/GeosCore/diagnostics_mod.F90 @@ -1466,13 +1466,18 @@ SUBROUTINE Do_Archive_SatDiagn( Input_Opt, State_Chm, State_Diag, & locTime <= State_Diag%SatDiagn_EndHr ) good = 1.0_fp !--------------------------------------------------------------------- - ! SatDiagnCount: Count number of local times + ! SatDiagnCount and SatDiagnEdgeCount: Count number of local times !--------------------------------------------------------------------- IF ( State_Diag%Archive_SatDiagnCount ) THEN State_Diag%SatDiagnCount(I,:,:) = & State_Diag%SatDiagnCount(I,:,:) + good ENDIF + IF ( State_Diag%Archive_SatDiagnEdgeCount ) THEN + State_Diag%SatDiagnEdgeCount(I,:,:) = & + State_Diag%SatDiagnEdgeCount(I,:,:) + good + ENDIF + !--------------------------------------------------------------------- ! SatDiagnOH: OH concentration [molec/cm3]: !--------------------------------------------------------------------- @@ -1510,8 +1515,7 @@ SUBROUTINE Do_Archive_SatDiagn( Input_Opt, State_Chm, State_Diag, & ! Pressure edges [hPa]: !--------------------------------------------------------------------- IF ( State_Diag%Archive_SatDiagnPEdge ) THEN - State_Diag%SatDiagnPEdge(I,:,:) = & - State_Met%PEDGE(I,:,1:State_Grid%NZ) * good + State_Diag%SatDiagnPEdge(I,:,:) = State_Met%PEDGE(I,:,:) * good ENDIF !--------------------------------------------------------------------- diff --git a/Headers/state_diag_mod.F90 b/Headers/state_diag_mod.F90 index 209d31734..35607a42d 100644 --- a/Headers/state_diag_mod.F90 +++ b/Headers/state_diag_mod.F90 @@ -268,6 +268,7 @@ MODULE State_Diag_Mod TYPE(DgnMap), POINTER :: Map_SatDiagnDryDep LOGICAL :: Archive_SatDiagnDryDep LOGICAL :: Archive_SatDiagn + LOGICAL :: Archive_SatDiagnEdge REAL(f4), POINTER :: SatDiagnDryDepVel(:,:,:) TYPE(DgnMap), POINTER :: Map_SatDiagnDryDepVel @@ -914,6 +915,9 @@ MODULE State_Diag_Mod REAL(f8), POINTER :: SatDiagnCount(:,:,:) LOGICAL :: Archive_SatDiagnCount + + REAL(f8), POINTER :: SatDiagnEdgeCount(:,:,:) + LOGICAL :: Archive_SatDiagnEdgeCount REAL(f8), POINTER :: SatDiagnConc(:,:,:,:) TYPE(DgnMap), POINTER :: Map_SatDiagnConc @@ -2381,6 +2385,9 @@ SUBROUTINE Zero_State_Diag( State_Diag, RC ) State_Diag%SatDiagnCount => NULL() State_Diag%Archive_SatDiagnCount = .FALSE. + + State_Diag%SatDiagnEdgeCount => NULL() + State_Diag%Archive_SatDiagnEdgeCount = .FALSE. State_Diag%SatDiagnConc => NULL() State_Diag%Map_SatDiagnConc => NULL() @@ -5208,7 +5215,7 @@ SUBROUTINE Init_State_Diag( Input_Opt, State_Chm, State_Grid, & ENDIF !------------------------------------------------------------------------ - ! Set a single logical for SatDiagn output + ! Set logicals for SatDiagn and/or SatDiagnEdge output ! For ease of comparison, place fields in alphabetical order !------------------------------------------------------------------------ State_Diag%Archive_SatDiagn = ( & @@ -5218,7 +5225,6 @@ SUBROUTINE Init_State_Diag( Input_Opt, State_Chm, State_Grid, & State_Diag%Archive_SatDiagnConc .or. & State_Diag%Archive_SatDiagnDryDep .or. & State_Diag%Archive_SatDiagnDryDepVel .or. & - State_Diag%Archive_SatDiagnPEdge .or. & State_Diag%Archive_SatDiagnTROPP .or. & State_Diag%Archive_SatDiagnTropLev .or. & State_Diag%Archive_SatDiagnPBLHeight .or. & @@ -5238,7 +5244,6 @@ SUBROUTINE Init_State_Diag( Input_Opt, State_Chm, State_Grid, & State_Diag%Archive_SatDiagnPBLHeight .or. & State_Diag%Archive_SatDiagnPBLTop .or. & State_Diag%Archive_SatDiagnPBLTopL .or. & - State_Diag%Archive_SatDiagnPEdge .or. & State_Diag%Archive_SatDiagnPRECTOT .or. & State_Diag%Archive_SatDiagnProd .or. & State_Diag%Archive_SatDiagnRH .or. & @@ -5252,21 +5257,32 @@ SUBROUTINE Init_State_Diag( Input_Opt, State_Chm, State_Grid, & State_Diag%Archive_SatDiagnWetLossLS .or. & State_Diag%Archive_SatDiagnWetLossConv ) + State_Diag%Archive_SatDiagnEdge = ( & + State_Diag%Archive_SatDiagnPEdge ) + !------------------------------------------------------------------------ - ! Satellite diagnostic: Counter + ! Satellite diagnostic: Counters !------------------------------------------------------------------------ IF ( State_Diag%Archive_SatDiagn ) THEN - - ! Array to contain the satellite diagnostic weights ALLOCATE( State_Diag%SatDiagnCount( State_Grid%NX, & State_Grid%NY, & State_Grid%NZ ), STAT=RC ) - CALL GC_CheckVar( 'State_Diag%DiagnCount', 0, RC ) + CALL GC_CheckVar( 'State_Diag%SatDiagnCount', 0, RC ) IF ( RC /= GC_SUCCESS ) RETURN State_Diag%SatDiagnCount = 0.0_f4 State_Diag%Archive_SatDiagnCount = .TRUE. ENDIF + IF ( State_Diag%Archive_SatDiagnEdge ) THEN + ALLOCATE( State_Diag%SatDiagnEdgeCount( State_Grid%NX, & + State_Grid%NY, & + State_Grid%NZ+1 ), STAT=RC ) + CALL GC_CheckVar( 'State_Diag%SatDiagnEdgeCount', 0, RC ) + IF ( RC /= GC_SUCCESS ) RETURN + State_Diag%SatDiagnEdgeCount = 0.0_f4 + State_Diag%Archive_SatDiagnEdgeCount = .TRUE. + ENDIF + !======================================================================= ! The following diagnostic quantities are only relevant for: ! @@ -12985,6 +13001,16 @@ SUBROUTINE Cleanup_State_Diag( State_Diag, RC ) ! State_Diag%WashFracLS => NULL() ! ENDIF + CALL Finalize( diagId = 'SatDiagnCount', & + Ptr2Data = State_Diag%SatDiagnCount, & + RC = RC ) + IF ( RC /= GC_SUCCESS ) RETURN + + CALL Finalize( diagId = 'SatDiagnEdgeCount', & + Ptr2Data = State_Diag%SatDiagnEdgeCount, & + RC = RC ) + IF ( RC /= GC_SUCCESS ) RETURN + CALL Finalize( diagId = 'SatDiagnConc', & Ptr2Data = State_Diag%SatDiagnConc, & mapData = State_Diag%Map_SatDiagnConc, & @@ -15178,7 +15204,7 @@ SUBROUTINE Get_Metadata_State_Diag( am_I_Root, metadataID, Found, & IF ( isDesc ) Desc = 'Pressure edges' IF ( isUnits ) Units = 'hPa' IF ( isRank ) Rank = 3 - !IF ( isVLoc ) VLoc = VLocationEdge + IF ( isVLoc ) VLoc = VLocationEdge ELSE IF ( TRIM( Name_AllCaps ) == 'SATDIAGNTROPP' ) THEN IF ( isDesc ) Desc = 'Tropopause pressure' @@ -20104,9 +20130,10 @@ SUBROUTINE Init_and_Register_R8_3D( Input_Opt, State_Chm, & ! ! !USES: ! - USE Input_Opt_Mod, ONLY : OptInput - USE State_Chm_Mod, ONLY : ChmState - USE State_Grid_Mod, ONLY : GrdState + USE Input_Opt_Mod, ONLY : OptInput + USE State_Chm_Mod, ONLY : ChmState + USE State_Grid_Mod, ONLY : GrdState + USE Registry_Params_Mod, ONLY : VLocationEdge ! ! !INPUT PARAMETERS: ! @@ -20142,7 +20169,7 @@ SUBROUTINE Init_and_Register_R8_3D( Input_Opt, State_Chm, & ! Scalars LOGICAL :: alwaysDefine, found INTEGER :: NX, NY, NZ - INTEGER :: NW, numSlots + INTEGER :: NW, numSlots, vLoc ! Strings CHARACTER(LEN=1) :: indFlag @@ -20159,6 +20186,7 @@ SUBROUTINE Init_and_Register_R8_3D( Input_Opt, State_Chm, & RC = GC_SUCCESS numSlots = -1 found = .FALSE. + vLoc = .FALSE. arrayID = 'State_Diag%' // TRIM( diagId ) errMsg = '' thisLoc = & @@ -20225,6 +20253,15 @@ SUBROUTINE Init_and_Register_R8_3D( Input_Opt, State_Chm, & NY = State_Grid%NY NZ = State_Grid%NZ + ! Determine if the array is defined on level edges + ! NOTE: This is only needed for the SatDiagnPEDGE field + CALL Get_Metadata_State_Diag( am_I_Root = Input_Opt%amIRoot, & + metadataId = diagId, & + found = found, & + vLoc = vLoc, & + RC = RC ) + IF ( vLoc == vLocationEdge ) NZ = NZ + 1 + ! Allocate array IF ( numSlots > 0 ) THEN ALLOCATE( Ptr2Data( NX, NY, numSlots ), STAT=RC ) diff --git a/History/history_mod.F90 b/History/history_mod.F90 index 16556c151..7f11d419b 100644 --- a/History/history_mod.F90 +++ b/History/history_mod.F90 @@ -2880,6 +2880,8 @@ SUBROUTINE History_Write( Input_Opt, State_Chm, State_Diag, RC ) LOGICAL :: DoWrite LOGICAL :: isBndCond LOGICAL :: isRestart + LOGICAL :: isSatDiagn + LOGICAL :: isSatDiagnEdge INTEGER :: S, N ! Strings @@ -3083,6 +3085,29 @@ SUBROUTINE History_Write( Input_Opt, State_Chm, State_Diag, RC ) RETURN ENDIF ENDIF + + !----------------------------------------------------------------- + ! SPECIAL HANDLING FOR SATELLITE DIAGNOSTIC COLLECTIONS + ! + ! If we have called History_Netcdf_Write (i.e. DoWrite == T), + ! then reset the satellite diagnostics counters, as we have now + ! entered the next diagnostic interval. We need to do this here + ! instead of in History_Netcdf_Write as there are multiple + ! satellite diagnostic collections (SatDiagn, SatDiagnEdge). + !----------------------------------------------------------------- + + ! Test container name + CALL SatDiagn_or_SatDiagnEdge( cName, isSatDiagn, isSatDiagnEdge ) + + ! Zero SatDiagn counter + IF ( isSatDiagn .and. State_Diag%Archive_SatDiagnCount ) THEN + State_Diag%SatDiagnCount = 0.0_f8 + ENDIF + + ! Zero SatDiagnEdge counter + IF ( isSatDiagnEdge .and. State_Diag%Archive_SatDiagnEdgeCount ) THEN + State_Diag%SatDiagnEdgeCount = 0.0_f8 + ENDIF ENDIF ! Skip to the next collection @@ -3095,15 +3120,6 @@ SUBROUTINE History_Write( Input_Opt, State_Chm, State_Diag, RC ) ! Cleanup & quit !======================================================================= - ! If we have called History_Netcdf_Write (i.e. DoWrite == T), then - ! reset the satellite diagnostics counter, as we have now entered the - ! next diagnostic interval. We need to do this here instead of in - ! History_Netcdf_Write as there are multiple satellite diagnostic - ! collections (SatDiagn, SatDiagnEdge). - IF ( State_Diag%Archive_SatDiagnCount .and. DoWrite ) THEN - State_Diag%SatDiagnCount = 0.0_f8 - ENDIF - ! Free pointers Container => NULL() Collection => NULL() diff --git a/History/history_netcdf_mod.F90 b/History/history_netcdf_mod.F90 index 9b3bd39c4..fc7e462a6 100644 --- a/History/history_netcdf_mod.F90 +++ b/History/history_netcdf_mod.F90 @@ -715,7 +715,8 @@ SUBROUTINE History_Netcdf_Write( Input_Opt, State_Diag, Container, RC ) ! !LOCAL VARIABLES: ! ! Scalars - LOGICAL :: output4Bytes, isSatDiagn + LOGICAL :: output4Bytes + LOGICAL :: isSatDiagnEdge, isSatDiagn INTEGER :: NcFileId, NcVarId INTEGER :: Dim1, Dim2, Dim3 @@ -765,8 +766,8 @@ SUBROUTINE History_Netcdf_Write( Input_Opt, State_Diag, Container, RC ) ThisLoc = & ' -> at History_Netcdf_Write (in History/history_netcdf_mod.F90)' - ! Test if this is the SatDiagn or SatDiagnEdge container - isSatDiagn = (INDEX(To_UpperCase(TRIM(Container%Name)), 'SATDIAGN' ) > 0) + ! Test if this is the SatDiagn or SatDiagnEdge collection + CALL SatDiagn_or_SatDiagnEdge( Container%Name, isSatDiagn, isSatDiagnEdge ) !======================================================================== ! Compute time elapsed since the reference time @@ -856,7 +857,7 @@ SUBROUTINE History_Netcdf_Write( Input_Opt, State_Diag, Container, RC ) Dim2 = SIZE( Item%Data_3d, 2 ) Dim3 = SIZE( Item%Data_3d, 3 ) - ! Get average for satellite diagnostic: + ! Get average for satellite diagnostic (vertical centers) IF ( isSatDiagn ) THEN WHERE ( State_Diag%SatDiagnCount > 0.0_f8 ) Item%Data_3d = Item%Data_3d / State_Diag%SatDiagnCount @@ -866,6 +867,16 @@ SUBROUTINE History_Netcdf_Write( Input_Opt, State_Diag, Container, RC ) Item%nUpdates = 1.0_f8 ENDIF + ! Get average for satellite diagnostic (vertical edges) + IF ( isSatDiagnEdge ) THEN + WHERE ( State_Diag%SatDiagnEdgeCount > 0.0_f8 ) + Item%Data_3d = Item%Data_3d / State_Diag%SatDiagnEdgeCount + ELSEWHERE + Item%Data_3d = MISSING_DBLE + ENDWHERE + Item%nUpdates = 1.0_f8 + ENDIF + ! Allocate the 4-byte or 8-byte output array ! Need a singleton 4th dimension for netCDF-F90 IF ( output4bytes ) THEN diff --git a/History/history_util_mod.F90 b/History/history_util_mod.F90 index 9384d3cde..b49c5b507 100644 --- a/History/history_util_mod.F90 +++ b/History/history_util_mod.F90 @@ -25,6 +25,7 @@ MODULE History_Util_Mod PUBLIC :: Compute_Julian_Date PUBLIC :: Compute_Elapsed_Time PUBLIC :: Compute_DeltaYmdHms_For_End + PUBLIC :: SatDiagn_or_SatDiagnEdge ! ! !DEFINED PARAMETERS: ! @@ -299,4 +300,50 @@ SUBROUTINE Compute_DeltaYmdHms_For_End( yyyymmdd, hhmmss, & END SUBROUTINE Compute_DeltaYmdHms_For_End !EOC +!------------------------------------------------------------------------------ +! GEOS-Chem Global Chemical Transport Model ! +!------------------------------------------------------------------------------ +!BOP +! +! !IROUTINE: Is_SatDiagn_or_SatDiagnEdge +! +! !DESCRIPTION: Tests a container name to determine if it is one of the +! satellite diagnostic collections (SatDiagn, SatDiagnEdge) +!\\ +!\\ +! !INTERFACE: +! + SUBROUTINE SatDiagn_or_SatDiagnEdge( cName, isSatDiagn, isSatDiagnEdge ) +! +! !USES: +! + USE CharPak_Mod, ONLY : To_Uppercase +! +! !INPUT PARAMETERS: +! + CHARACTER(LEN=*), INTENT(IN) :: cName ! Container name +! +! !OUTPUT PARAMETERS: +! + LOGICAL, INTENT(OUT) :: isSatDiagn + LOGICAL, INTENT(OUT) :: isSatDiagnEdge +! +! !REVISION HISTORY: +! 31 Oct 2024 - R. Yantosca - Initial version +! See the subsequent Git history with the gitk browser! +!EOP +!------------------------------------------------------------------------------ +!BOC + + ! Test if this is the SatDiagnEdge container + isSatDiagnEdge = ( & + INDEX( To_UpperCase( TRIM( cName) ), 'SATDIAGNEDGE' ) > 0 ) + + ! Test if this is the SatDiagn container + isSatDiagn = ( & + .not. isSatDiagnEdge .and. & + INDEX( To_UpperCase( TRIM( cName ) ), 'SATDIAGN' ) > 0 ) + + END SUBROUTINE SatDiagn_or_SatDiagnEdge +!EOC END MODULE History_Util_Mod