diff --git a/docs/LIS_users_guide/revision_table.adoc b/docs/LIS_users_guide/revision_table.adoc index 9f9e0fe32..8bd7a65bf 100644 --- a/docs/LIS_users_guide/revision_table.adoc +++ b/docs/LIS_users_guide/revision_table.adoc @@ -2,6 +2,7 @@ |==== |Revision | Summary of Changes | Date +|2.6 | LISF 557WW 7.5.15 release | Jun 14, 2024 |3.0 | LISF Public 7.5.0 release | Jan 11, 2024 |2.5 | LISF 557WW 7.5.9 release | Jul 05, 2023 |2.4 | LISF 557WW 7.5.8 release | Jun 30, 2023 diff --git a/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noah39.galwem17 b/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noah39.galwem17 index 2201802b8..dd1731a9c 100644 --- a/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noah39.galwem17 +++ b/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noah39.galwem17 @@ -25,16 +25,16 @@ Output data format: netcdf Output naming style: "WMO convention" Enable output statistics: .false. Start mode: restart -Starting year: 2022 -Starting month: 08 -Starting day: 01 -Starting hour: 0 +Starting year: 2024 +Starting month: 06 +Starting day: 11 +Starting hour: 12 Starting minute: 0 Starting second: 0 -Ending year: 2022 -Ending month: 08 -Ending day: 01 -Ending hour: 12 +Ending year: 2024 +Ending month: 06 +Ending day: 12 +Ending hour: 00 Ending minute: 5 Ending second: 0 Undefined value: -9999 @@ -95,8 +95,10 @@ Bias estimation restart file: none #Perturbation options Perturbations start mode: restart restart restart +#Perturbations start mode: coldstart coldstart coldstart + Perturbations restart output interval: 12hr 12hr 12hr -Perturbations restart filename: ./input/restarts/LIS_DAPERT_202208010000.d01.bin ./input/restarts/LIS_DAPERT_202208010000.d01.bin ./input/restarts/LIS_DAPERT_202208010000.d01.bin +Perturbations restart filename: ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin Apply perturbation bias correction: 1 1 1 Forcing perturbation algorithm: "GMAO scheme" "GMAO scheme" "GMAO scheme" @@ -235,9 +237,9 @@ AGRMET CMORPH minimum temperature threshold: 273 # Use IMERG rainfall data AGRMET use IMERG data: 1 # 1 = Use AGRMET IMERG temperature threshold: 278 -AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG/Early_V06B +AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG AGRMET IMERG product: 3B-HHR-E # Early Run -AGRMET IMERG version: V06E # V06E released 8 Nov 2023 +AGRMET IMERG version: V07B # V07B released 1 Jun 2024 AGRMET IMERG Probability Liquid Precip Threshold: 100 # Bratseth runtime settings @@ -326,6 +328,8 @@ AGRMET cloud data directory: WWMCA_GRIB # WWMCA_LE, NONE, or # Use WWMCA GRIB1 files beginning 12Z 4 Jul 2020 AGRMET WWMCA GRIB1 read option: 1 AGRMET snow distribution shape parameter: 2.6 +AGRMET radiation derived from: GALWEM_RAD # WWMCA turned off Jul 2024 +AGRMET GALWEM radiation data directory: GALWEM # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. @@ -361,7 +365,7 @@ AGRMET overcast percentage: 0.30 #-----------------------LAND SURFACE MODELS-------------------------- Noah.3.9 model timestep: 15mn Noah.3.9 restart output interval: 12hr -Noah.3.9 restart file: ./input/restarts/LIS_RST_NOAH39_202208010000.d01.nc +Noah.3.9 restart file: ./input/rstfiles/LIS_RST_NOAH39_202406111200.d01.nc Noah.3.9 restart file format: netcdf Noah.3.9 vegetation parameter table: ./input/LS_PARAMETERS/noah39_parms/VEGPARM.TBL Noah.3.9 soil parameter table: ./input/LS_PARAMETERS/noah39_parms/SOILPARM.TBL diff --git a/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noahmp401.galwem17 b/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noahmp401.galwem17 index f27cf45bf..c9c6ec58a 100644 --- a/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noahmp401.galwem17 +++ b/lis/configs/557WW-7.5-FOC/NRT_GLOBAL/lis.config.global.noahmp401.galwem17 @@ -25,16 +25,16 @@ Output data format: netcdf Output naming style: "WMO convention" Enable output statistics: .false. Start mode: restart -Starting year: 2022 -Starting month: 8 -Starting day: 1 -Starting hour: 0 +Starting year: 2024 +Starting month: 06 +Starting day: 11 +Starting hour: 12 Starting minute: 0 Starting second: 0 -Ending year: 2022 -Ending month: 8 -Ending day: 1 -Ending hour: 12 +Ending year: 2024 +Ending month: 06 +Ending day: 12 +Ending hour: 00 Ending minute: 5 Ending second: 0 Undefined value: -9999 @@ -95,9 +95,10 @@ Bias estimation restart file: none #Perturbation options Perturbations start mode: restart restart restart +#Perturbations start mode: coldstart coldstart coldstart Perturbations restart output interval: 12hr 12hr 12hr -Perturbations restart filename: ./input/restarts/LIS_DAPERT_202208010000.d01.bin ./input/restarts/LIS_DAPERT_202208010000.d01.bin ./input/restarts/LIS_DAPERT_202208010000.d01.bin +Perturbations restart filename: ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin Apply perturbation bias correction: 1 1 1 Forcing perturbation algorithm: "GMAO scheme" "GMAO scheme" "GMAO scheme" @@ -236,9 +237,9 @@ AGRMET CMORPH minimum temperature threshold: 273 # Use IMERG rainfall data AGRMET use IMERG data: 1 # 1 = Use AGRMET IMERG temperature threshold: 278 -AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG/Early_V06B +AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG AGRMET IMERG product: 3B-HHR-E # Early Run -AGRMET IMERG version: V06E # V06E released 8 Nov 2023 +AGRMET IMERG version: V07B # V07B released 1 Jun 2024 AGRMET IMERG Probability Liquid Precip Threshold: 100 # Bratseth runtime settings @@ -327,6 +328,8 @@ AGRMET cloud data directory: WWMCA_GRIB # WWMCA_LE, NONE, or # Use WWMCA GRIB1 files beginning 12Z 4 Jul 2020 AGRMET WWMCA GRIB1 read option: 1 AGRMET snow distribution shape parameter: 2.6 +AGRMET radiation derived from: GALWEM_RAD # WWMCA turned off Jul 2024 +AGRMET GALWEM radiation data directory: GALWEM # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. @@ -362,7 +365,7 @@ AGRMET overcast percentage: 0.30 #-----------------------LAND SURFACE MODELS-------------------------- Noah-MP.4.0.1 model timestep: 15mn Noah-MP.4.0.1 restart output interval: 12hr -Noah-MP.4.0.1 restart file: ./input/restarts/LIS_RST_NOAHMP401_202208010000.d01.nc +Noah-MP.4.0.1 restart file: ./input/rstfiles/LIS_RST_NOAHMP401_202406111200.d01.nc Noah-MP.4.0.1 restart file format: netcdf Noah-MP.4.0.1 soil parameter table: ./input/LS_PARAMETERS/noahmp401_parms/SOILPARM.TBL Noah-MP.4.0.1 general parameter table: ./input/LS_PARAMETERS/noahmp401_parms/GENPARM.TBL diff --git a/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noah39.rapid b/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noah39.rapid index 538c729cf..61a708604 100644 --- a/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noah39.rapid +++ b/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noah39.rapid @@ -25,15 +25,15 @@ Output data format: netcdf Output naming style: "557WW streamflow convention" Enable output statistics: .false. Start mode: restart -Starting year: 2023 -Starting month: 05 -Starting day: 31 +Starting year: 2024 +Starting month: 06 +Starting day: 11 Starting hour: 12 Starting minute: 00 Starting second: 00 -Ending year: 2023 +Ending year: 2024 Ending month: 06 -Ending day: 01 +Ending day: 12 Ending hour: 00 Ending minute: 05 Ending second: 00 @@ -97,7 +97,7 @@ Bias estimation restart file: none #Perturbation options Perturbations start mode: restart restart restart Perturbations restart output interval: 12hr 12hr 12hr -Perturbations restart filename: ./input/rstfiles/LIS_DAPERT_202305311200.d01.bin ./input/rstfiles/LIS_DAPERT_202305311200.d01.bin ./input/rstfiles/LIS_DAPERT_202305311200.d01.bin +Perturbations restart filename: ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin ./input/rstfiles/LIS_DAPERT_202406111200.d01.bin Apply perturbation bias correction: 1 1 1 Forcing perturbation algorithm: "GMAO scheme" "GMAO scheme" "GMAO scheme" @@ -116,10 +116,10 @@ Observation attributes file: ./input/attribs/usafsi_att Observation perturbation attributes file: ./input/attribs/usafsi_pertattribs.txt ./input/attribs/smops_pertattribs.txt ./input/attribs/smap_pertattribs.txt -USAFSI data directory: ./input/USAFSI +USAFSI data directory: ./input/USAF_FORCING/USAFSI USAFSI netcdf filename prefix: USAFSI -SMOPS ASCAT soil moisture data directory: ./input/SMOPS +SMOPS ASCAT soil moisture data directory: ./input/USAF_FORCING/SMOPS SMOPS ASCAT naming convention: "AGRMET ops" SMOPS ASCAT version: "date-based" SMOPS ASCAT model CDF file: ./input/cdf/noah39_cdf_200obs.nc @@ -129,7 +129,7 @@ SMOPS ASCAT use realtime data: 1 SMOPS ASCAT soil moisture use scaled standard deviation model: 0 SMOPS ASCAT CDF read option: 1 -SMAP(NRT) soil moisture data directory: ./input/SMAP +SMAP(NRT) soil moisture data directory: ./input/USAF_FORCING/SMAP SMAP(NRT) model CDF file: ./input/cdf/noah39_cdf_200obs.nc SMAP(NRT) observation CDF file: ./input/cdf/SMAP_cdf_10km_30obs.nc SMAP(NRT) soil moisture number of bins in the CDF: 100 @@ -172,11 +172,11 @@ AGRMET forcing domain upper right lon: 179.9296875 AGRMET forcing domain resolution (dx): 0.1406250 AGRMET forcing domain resolution (dy): 0.0937500 -AGRMET forcing directory: ./input/AGRMET +AGRMET forcing directory: ./input/USAF_FORCING AGRMET retrospective root filename: "/PS.AFWA_SC.U_DI.C_DC.ANLYS_GP.LIS_GR.C0P09DEG_AR.GLOBAL_PA.03-HR-SUM_DD." # Output settings -AGRMET analysis directory: Analysis_UMFG_1 # Change as appropriate +AGRMET analysis directory: ./input/Analysis_UMFG_1 # Change as appropriate AGRMET surface fields directory: SFCALC # Legacy, will eventually remove AGRMET merged precip directory: PRECIP # Legacy, will eventually remove AGRMET security classification: U @@ -235,9 +235,9 @@ AGRMET CMORPH minimum temperature threshold: 273 # Use IMERG rainfall data AGRMET use IMERG data: 1 # 1 = Use AGRMET IMERG temperature threshold: 278 -AGRMET IMERG data directory: ./input/IMERG/Early_V06B +AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG/ AGRMET IMERG product: 3B-HHR-E # Early Run -AGRMET IMERG version: V06E # V06E released 8 Nov 2023 +AGRMET IMERG version: V07B # V07B released 1 Jun 2024 AGRMET IMERG Probability Liquid Precip Threshold: 100 # Bratseth runtime settings @@ -325,6 +325,8 @@ AGRMET cloud data directory: WWMCA_GRIB # WWMCA_LE, NONE # Use WWMCA GRIB1 files beginning 12Z 4 Jul 2020 AGRMET WWMCA GRIB1 read option: 1 AGRMET snow distribution shape parameter: 2.6 +AGRMET radiation derived from: GALWEM_RAD # WWMCA turned off July 2024 +AGRMET GALWEM radiation data directory: GALWEM # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. @@ -362,7 +364,7 @@ AGRMET PPT Background bias correction option: 0 #-----------------------LAND SURFACE MODELS-------------------------- Noah.3.9 model timestep: 15mn Noah.3.9 restart output interval: 12hr -Noah.3.9 restart file: ./input/rstfiles/LIS_RST_NOAH39_202305311200.d01.nc +Noah.3.9 restart file: ./input/rstfiles/LIS_RST_NOAH39_202406111200.d01.nc Noah.3.9 restart file format: netcdf Noah.3.9 vegetation parameter table: ./input/LS_PARAMETERS/noah39_parms/VEGPARM.TBL Noah.3.9 soil parameter table: ./input/LS_PARAMETERS/noah39_parms/SOILPARM.TBL @@ -415,13 +417,13 @@ Model output attributes file: ./input/tables/MODEL_OUTPUT_LIST.TBL.noa # ROUTING MODEL: RAPID Routing model: "RAPID router" -RAPID routing model time step: "3hr" # must match 'Surface model output interval:' -RAPID river routing time step: "15mn" # must match 'LSM model timestep:' +RAPID routing model time step: "3hr" # Must match 'Surface model output interval:' +RAPID river routing time step: "15mn" # less than routing model time step RAPID routing model output interval: "3hr" RAPID routing model restart interval: "12hr" RAPID routing model start mode: restart -RAPID routing model restart file: ./input/rstfiles/LIS_RST_RAPID_router_202305311200.d01.nc +RAPID routing model restart file: ./input/rstfiles/LIS_RST_RAPID_router_202406111200.d01.nc RAPID run in ensemble mode: 1 # 0=open loop; 1=ensemble mean; 2(not support)=ensemble # Runtime option diff --git a/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noahmp401.rapid b/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noahmp401.rapid index cf5bbc581..961336e9a 100644 --- a/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noahmp401.rapid +++ b/lis/configs/557WW-7.5-FOC/NRT_STREAMFLOW/lis.config.nrt_streamflow.noahmp401.rapid @@ -25,15 +25,15 @@ Output data format: netcdf Output naming style: "557WW streamflow convention" Enable output statistics: .false. Start mode: restart -Starting year: 2023 -Starting month: 05 -Starting day: 31 +Starting year: 2024 +Starting month: 06 +Starting day: 11 Starting hour: 12 Starting minute: 00 Starting second: 00 -Ending year: 2023 +Ending year: 2024 Ending month: 06 -Ending day: 01 +Ending day: 12 Ending hour: 00 Ending minute: 05 Ending second: 0 @@ -95,7 +95,7 @@ Bias estimation restart file: none #Perturbation options Perturbations start mode: restart restart restart Perturbations restart output interval: 12hr 12hr 12hr -Perturbations restart filename: input/rstfiles/LIS_DAPERT_202305311200.d01.bin input/rstfiles/LIS_DAPERT_202305311200.d01.bin input/rstfiles/LIS_DAPERT_202305311200.d01.bin +Perturbations restart filename: input/rstfiles/LIS_DAPERT_202406111200.d01.bin input/rstfiles/LIS_DAPERT_202406111200.d01.bin input/rstfiles/LIS_DAPERT_202406111200.d01.bin Apply perturbation bias correction: 1 1 1 Forcing perturbation algorithm: "GMAO scheme" "GMAO scheme" "GMAO scheme" @@ -113,10 +113,10 @@ Observation perturbation frequency: 6hr Observation attributes file: ./input/attribs/usafsi_attribs.txt ./input/attribs/smops_attribs.txt ./input/attribs/smap_attribs.txt Observation perturbation attributes file: ./input/attribs/usafsi_pertattribs.txt ./input/attribs/smops_pertattribs.txt ./input/attribs/smap_pertattribs.txt -USAFSI data directory: ./input/USAFSI +USAFSI data directory: ./input/USAF_FORCING/USAFSI USAFSI netcdf filename prefix: USAFSI -SMOPS ASCAT soil moisture data directory: ./input/SMOPS +SMOPS ASCAT soil moisture data directory: ./input/USAF_FORCING/SMOPS SMOPS ASCAT naming convention: "AGRMET ops" SMOPS ASCAT version: "date-based" SMOPS ASCAT model CDF file: ./input/cdf/noahmp401_cdf_200obs.nc @@ -126,7 +126,7 @@ SMOPS ASCAT use realtime data: 1 SMOPS ASCAT soil moisture use scaled standard deviation model: 0 SMOPS ASCAT CDF read option: 1 -SMAP(NRT) soil moisture data directory: ./input/SMAP +SMAP(NRT) soil moisture data directory: ./input/USAF_FORCING/SMAP SMAP(NRT) model CDF file: ./input/cdf/noahmp401_cdf_200obs.nc SMAP(NRT) observation CDF file: ./input/cdf/SMAP_cdf_10km_30obs.nc SMAP(NRT) soil moisture number of bins in the CDF: 100 @@ -171,11 +171,11 @@ AGRMET forcing domain resolution (dx): 0.1406250 AGRMET forcing domain resolution (dy): 0.0937500 # Input settings -AGRMET forcing directory: ./input/AGRMET +AGRMET forcing directory: ./input/USAF_FORCING AGRMET retrospective root filename: "/PS.AFWA_SC.U_DI.C_DC.ANLYS_GP.LIS_GR.C0P09DEG_AR.GLOBAL_PA.03-HR-SUM_DD." # Output settings -AGRMET analysis directory: Analysis_UMFG_1 # Change as appropriate +AGRMET analysis directory: input/Analysis_UMFG_1 # Change as appropriate AGRMET surface fields directory: SFCALC # Legacy, will eventually remove AGRMET merged precip directory: PRECIP # Legacy, will eventually remove AGRMET security classification: U @@ -234,9 +234,9 @@ AGRMET CMORPH minimum temperature threshold: 273 # Use IMERG rainfall data AGRMET use IMERG data: 1 # 1 = Use AGRMET IMERG temperature threshold: 278 -AGRMET IMERG data directory: ./input/IMERG/Early_V06B +AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG AGRMET IMERG product: 3B-HHR-E # Early Run -AGRMET IMERG version: V06E # V06E released 8 Nov 2023 +AGRMET IMERG version: V07B # V07B released 1 Jun 2024 AGRMET IMERG Probability Liquid Precip Threshold: 100 # Bratseth runtime settings @@ -324,6 +324,8 @@ AGRMET cloud data directory: WWMCA_GRIB # WWMCA_LE, NONE, or WWMC # Use WWMCA GRIB1 files beginning 12Z 4 Jul 2020 AGRMET WWMCA GRIB1 read option: 1 AGRMET snow distribution shape parameter: 2.6 +AGRMET radiation derived from: GALWEM_RAD # WWMCA turned off July 2024 +AGRMET GALWEM radiation data directory: GALWEM # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. @@ -361,7 +363,7 @@ AGRMET PPT Background bias correction option: 0 #-----------------------LAND SURFACE MODELS-------------------------- Noah-MP.4.0.1 model timestep: 15mn Noah-MP.4.0.1 restart output interval: 12hr -Noah-MP.4.0.1 restart file: ./input/rstfiles/LIS_RST_NOAHMP401_202305311200.d01.nc +Noah-MP.4.0.1 restart file: ./input/rstfiles/LIS_RST_NOAHMP401_202406111200.d01.nc Noah-MP.4.0.1 restart file format: netcdf Noah-MP.4.0.1 soil parameter table: ./input/LS_PARAMETERS/noahmp401_parms/SOILPARM.TBL Noah-MP.4.0.1 general parameter table: ./input/LS_PARAMETERS/noahmp401_parms/GENPARM.TBL @@ -416,13 +418,13 @@ Model output attributes file: ./input/tables/MODEL_OUTPUT_LIST.TBL.noa # ROUTING MODEL: RAPID Routing model: "RAPID router" -RAPID routing model time step: "3hr" # must match 'Surface model output interval:' -RAPID river routing time step: "15mn" # must match 'LSM model timestep:' +RAPID routing model time step: "3hr" # must match 'Surface model output interval:' +RAPID river routing time step: "15mn" # less than routing model time step RAPID routing model output interval: "3hr" RAPID routing model restart interval: "12hr" RAPID routing model start mode: restart -RAPID routing model restart file: ./input/rstfiles/LIS_RST_RAPID_router_202305311200.d01.nc +RAPID routing model restart file: ./input/rstfiles/LIS_RST_RAPID_router_202406111200.d01.nc RAPID run in ensemble mode: 1 # 0=open loop; 1=ensemble mean; 2(not support)=ensemble # Runtime option diff --git a/lis/configs/lis.config.adoc b/lis/configs/lis.config.adoc index 39cb41f6c..ccba77b24 100644 --- a/lis/configs/lis.config.adoc +++ b/lis/configs/lis.config.adoc @@ -5453,16 +5453,20 @@ Note that if you wish to use the first guess precip, then it must match the first guess source. `AGRMET radiation derived from:` specifies how to compute -shortwave and longwave radiation. Defaults to "`cloud types`". +shortwave and longwave radiation. Acceptable values are: |==== |Value | Description |"`cloud types`" | use cloud types -|"`cloud optical depth`" | use cloud optical depth +|"`cod properties`" | use cloud optical depth properties +|"`GALWEM_RAD`" | use radiation fields from GALWEM |==== +`AGRMET GALWEM radiation data directory:` specifies the location of the GALWEM +radiation data files. + .Example _lis.config_ entry .... AGRMET forcing directory: ./FORCING/ @@ -5534,7 +5538,8 @@ AGRMET CMORPH dx: AGRMET CMORPH dy: AGRMET use GFS precip: 1 AGRMET use GALWEM precip: 0 -AGRMET radiation derived from: 'cloud types' +AGRMET radiation derived from: 'GALWEM_RAD' +AGRMET GALWEM radiation data directory: GALWEM_Rad .... diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 b/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 index a6bc95603..7ccd94c6d 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 @@ -37,6 +37,7 @@ ! 8 May 2013 Sujay Kumar; initial specification ! 28 Sep 2017: Mahdi Navari; Updated to read ASCAT from SMOPS V3 ! 1 Apr 2019 Yonghwan Kwon: Upated for reading monthy CDF for the current month +! 08 May 2024: Mahdi Navari; Updated to read ASCAT Metop-B and C from SMOPS V4 ! module SMOPS_ASCATsm_Mod ! !USES: @@ -83,7 +84,7 @@ module SMOPS_ASCATsm_Mod integer :: nbins integer :: ntimes - real*8 :: version2_time, version3_time + real*8 :: version2_time, version3_time, version4_time character(len=17) :: version character(len=10) :: conv @@ -601,6 +602,11 @@ subroutine SMOPS_ASCATsm_setup(k, OBS_State, OBS_Pert_State) yr1 = 2017; mo1 = 8; da1 = 24; hr1 = 12; mn1 = 0; ss1 = 0 call LIS_date2time(SMOPS_ASCATsm_struc(n)%version3_time,updoy,upgmt,& yr1,mo1,da1,hr1,mn1,ss1) + + yr1 = 2024; mo1 = 4; da1 = 25; hr1 = 0; mn1 = 0; ss1 = 0 + call LIS_date2time(SMOPS_ASCATsm_struc(n)%version4_time,updoy,upgmt,& + yr1,mo1,da1,hr1,mn1,ss1) + endif gridDesci = 0 diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_GRIB2_Tables_NESDIS.txt b/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_GRIB2_Tables_NESDIS.txt index 9b80995f6..a69c1ef44 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_GRIB2_Tables_NESDIS.txt +++ b/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_GRIB2_Tables_NESDIS.txt @@ -102,3 +102,38 @@ SMOPS V3.0 GRIB Table: { 2, 0, 7, 1, 3, 248, "SMAPSMQA", "NASA SMAP Liquid Volumetric Soil Moisture QA", "-"}, { 2, 0, 7, 1, 3, 249, "RESSM1QA", "Reserved Liquid Volumetric Soil Moisture 1 QA", "-"}, +SMPOS V4.0 belnded product table: +NPR-SMOPS-CMAP-6hrly_v4r0_blend_syyyymmddhh00000_eyyyymmddxxxxxxx_cyyyymmddxxxxxxx.grib2 +210 = blended soil moisture (Blended_SM) +214 = ASCAT_B soil moisture (ASCAT_B_SM) +250 = ASCAT_C soil moisture (ASCAT_C_SM) +215 = AMSR2 soil moisture (AMSR2_SM) +216 = GMI SM (GMI_SM) +217 = NRT SMAP SM (NSMAP_SM) +218 = SMAP SM (SMAP_SM) +219 = Blended SM SD (Blended_SM_SD) +220 = Hour for blended soil moisture (Blended_hour) +221 = Minute for blended soil moisture (Blended_minute) +228 = Hour for ASCAT_B soil moisture (ASCAT_B_hour) +229 = Minute for ASCAT_B soil moisture (ASCAT_B_minute) +251 = Hour for ASCAT_C soil moisture (ASCAT_C_hour) +252 = Minute for ASCAT_C soil moisture (ASCAT_C_minute) +230 = Hour for AMSR2 soil moisture (AMSR2_hour) +231 = Minute for AMSR2 soil moisture (AMSR2_minute) +232 = Hour for GMI SM (GMI_hour) +233 = Minute for GMI SM (GMI_minute) +234 = Hour for NSMAP SM (NSMAP_hour) +235 = Minute for NSMAP SM (NSMAP_minute) +236 = Hour for SMAP SM (SMAP_hour) +237 = Minute for SMAP SM (SMAP_minute) +238 = Hour for spare 1 (Blended_SM_SD_hour) +239 = Minute for spare 1 (Blended_SM_SD_minute) +240 = QA for blended soil moisture (Blended_QA) +244 = QA for ASCAT_B soil moisture (ASCAT_B_QA) +253 = QA for ASCAT_C soil moisture (ASCAT_C_QA) +245 = QA for AMSR2 soil moisture (AMSR2_QA) +246 = QA for GMI SM (GMI_QA) +247 = QA for NSMAP (NSMAP_QA) +248 = QA for SMAP SM (SMAP_QA) +249 = QA for spare 1 (Blended_SM_SD_QA) + diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 index c1f382176..f4b4cdf26 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 @@ -23,6 +23,8 @@ ! 01 Apr 2019: Yonghwan Kwon: Upated for reading monthy CDF for the current ! month. ! 25 Mar 2022: Eric Kemp; Modified read_SMOPS_ASCATsm to be fault tolerant. +! 10 May 2024: Mahdi Navari; Updated to read ASCAT Metop-B and C from SMOPS V4 +! ! !INTERFACE: subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) ! !USES: @@ -90,6 +92,7 @@ subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) real :: model_delta(LIS_rc%obs_ngrid(k)) real :: obs_delta(LIS_rc%obs_ngrid(k)) integer :: yyyy,mm,dd,hh ! EMK + integer, external :: create_filelist ! C function call ESMF_AttributeGet(OBS_State,"Data Directory",& @@ -127,19 +130,26 @@ subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) ! SMOPS_ASCATsm_struc(n)%useRealtime, & ! LIS_rc%yr, LIS_rc%mo, & ! LIS_rc%da, LIS_rc%hr, SMOPS_ASCATsm_struc(n)%conv, fname) + call create_SMOPS_ASCATsm_filename(smobsdir, & SMOPS_ASCATsm_struc(n)%useRealtime, & yyyy,mm,dd,hh, & SMOPS_ASCATsm_struc(n)%conv, fname) - inquire(file=fname,exist=file_exists) + ! EMK...Handle case where no SMOPS v4 files are available + if (fname /= 'NULL') then + inquire(file=fname,exist=file_exists) - if(file_exists) then - write(LIS_logunit,*) '[INFO] Reading ',trim(fname) - call read_SMOPS_ASCAT_data(n,k,fname,smobs,smtime) + if(file_exists) then + write(LIS_logunit,*) '[INFO] Reading ',trim(fname) + call read_SMOPS_ASCAT_data(n,k,fname,smobs,smtime) + else + write(LIS_logunit,*) '[WARN] Missing SMOPS ASCATsm', & + trim(fname) + endif else - write(LIS_logunit,*) '[WARN] Missing SMOPS ',trim(fname) - endif + write(LIS_logunit,*) '[WARN] No SMOPS ASCATsm file found' + end if SMOPS_ASCATsm_struc(n)%smobs = LIS_rc%udef SMOPS_ASCATsm_struc(n)%smtime = -1 @@ -147,7 +157,8 @@ subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) do r=1,LIS_rc%obs_lnr(k) do c=1,LIS_rc%obs_lnc(k) grid_index = LIS_obs_domain(n,k)%gindex(c,r) - if(grid_index.ne.-1) then + + if(grid_index.ne.-1) then if(smobs(c+(r-1)*LIS_rc%obs_lnc(k)).ne.-9999.0) then SMOPS_ASCATsm_struc(n)%smobs(c,r) = & smobs(c+(r-1)*LIS_rc%obs_lnc(k)) @@ -186,6 +197,7 @@ subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) sm_current(c,r) = & SMOPS_ASCATsm_struc(n)%smobs(c,r) fnd = 1 + endif endif endif @@ -316,7 +328,6 @@ subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) !------------------------------------------------------------------------- ! Depending on data update flag... !------------------------------------------------------------------------- - if(data_upd) then do t=1,LIS_rc%obs_ngrid(k) @@ -458,6 +469,9 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) integer :: param_ASCAT_B, param_ASCAT_B_qa integer :: param_ASCAT_B_hr, param_ASCAT_B_mn + integer :: param_ASCAT_C, param_ASCAT_C_qa + integer :: param_ASCAT_C_hr, param_ASCAT_C_mn + real :: sm_ASCAT_A(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) real :: sm_ASCAT_A_t(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) real :: sm_ASCAT_A_hr(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) @@ -468,14 +482,23 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) real :: sm_ASCAT_B_hr(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) real :: sm_ASCAT_B_mn(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_ASCAT_C(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_ASCAT_C_t(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_ASCAT_C_hr(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_ASCAT_C_mn(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_ASCAT_A_qa(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) integer*2 :: sm_ASCAT_A_qa_t(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) real :: sm_ASCAT_B_qa(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) integer*2 :: sm_ASCAT_B_qa_t(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_ASCAT_C_qa(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + integer*2 :: sm_ASCAT_C_qa_t(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_time_ASCAT_A(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) real :: sm_time_ASCAT_B(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) + real :: sm_time_ASCAT_C(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) real :: sm_time(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) real :: sm_data(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) logical*1 :: sm_data_b(SMOPS_ASCATsm_struc(n)%nc*SMOPS_ASCATsm_struc(n)%nr) @@ -493,6 +516,7 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) integer :: imsg character(len=512) :: message(20) integer, save :: alert_number = 0 + logical :: a_exist,b_exist,c_exist #if(defined USE_GRIBAPI) ! When we are reading the 6-hourly datasets, we read the file HR+6 @@ -502,7 +526,7 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) ! Otherwise, when reading the daily datasets, there is no need to ! adjust time. if ( SMOPS_ASCATsm_struc(n)%useRealtime == 1 ) then - offset = 6 + offset = 6 ! EJ only for version 3! else offset = 0 endif @@ -517,10 +541,15 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) yr1 = LIS_rc%yr mo1 = LIS_rc%mo da1 = LIS_rc%da - hr1 = LIS_rc%hr + offset + hr1 = LIS_rc%hr mn1 = LIS_rc%mn ss1 = 0 call LIS_date2time(file_time,updoy,upgmt,yr1,mo1,da1,hr1,mn1,ss1) + if ( file_time >= SMOPS_ASCATsm_struc(n)%version3_time .and. & + file_time < SMOPS_ASCATsm_struc(n)%version4_time ) then + hr1 = LIS_rc%hr+offset + call LIS_date2time(file_time,updoy,upgmt,yr1,mo1,da1,hr1,mn1,ss1) + endif endif if ( file_time < SMOPS_ASCATsm_struc(n)%version3_time ) then @@ -529,17 +558,29 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) param_ASCAT_A_hr = 223; param_ASCAT_A_mn = 224 param_ASCAT_B = 214; param_ASCAT_B_qa = 235 param_ASCAT_B_hr = 225; param_ASCAT_B_mn = 226 + a_exist = .true.; b_exist = .true.; c_exist = .false. write(LIS_logunit,*) '[MSG] Reading SMOPS ASCAT dataset '//& 'as SMOPS version 1.3/2.0' - else ! ( file_time >= SMOPS_ASCATsm_struc(n)%version3_time ) then + elseif ( file_time >= SMOPS_ASCATsm_struc(n)%version3_time .and. & + file_time < SMOPS_ASCATsm_struc(n)%version4_time ) then ! SMOPS version 3.0 param_ASCAT_A = 213; param_ASCAT_A_qa = 243 param_ASCAT_A_hr = 226; param_ASCAT_A_mn = 227 param_ASCAT_B = 214; param_ASCAT_B_qa = 244 param_ASCAT_B_hr = 228; param_ASCAT_B_mn = 229 + a_exist = .true.; b_exist = .true.; c_exist = .false. write(LIS_logunit,*) '[MSG] Reading SMOPS ASCAT dataset '//& 'as SMOPS version 3.0' + else + ! SMOPS version 4.0 + param_ASCAT_B = 214; param_ASCAT_B_qa = 244 + param_ASCAT_B_hr = 228; param_ASCAT_B_mn = 229 + param_ASCAT_C = 250; param_ASCAT_C_qa = 253 + param_ASCAT_C_hr = 251; param_ASCAT_C_mn = 252 + a_exist = .false.; b_exist = .true.; c_exist = .true. + write(LIS_logunit,*) '[MSG] Reading SMOPS ASCAT dataset '//& + 'as SMOPS version 4.0' endif call grib_open_file(ftn, trim(fname), 'r', iret) @@ -568,145 +609,218 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) end if var_found = .false. - if (param_num .eq. param_ASCAT_A) then - var_found = .true. - endif - if (var_found) then - call grib_get(igrib, 'values', sm_ASCAT_A, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading values for ASCAT_A' - call grib_release(igrib, iret) - imsg = -1 - exit - end if - do r = 1, SMOPS_ASCATsm_struc(n)%nr - do c = 1, SMOPS_ASCATsm_struc(n)%nc - sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & - sm_ASCAT_A(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc) - enddo - enddo - endif - - var_found = .false. - if (param_num .eq. param_ASCAT_A_qa) then - var_found = .true. - endif - if (var_found) then - call grib_get(igrib, 'values', sm_ASCAT_A_qa, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading QA values for ASCAT_A' - call grib_release(igrib, iret) - imsg = -1 - exit - end if - do r = 1, SMOPS_ASCATsm_struc(n)%nr - do c = 1, SMOPS_ASCATsm_struc(n)%nc - sm_ASCAT_A_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & - INT(sm_ASCAT_A_qa(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc)) - enddo - enddo - endif - - var_found = .false. - if (param_num .eq. param_ASCAT_A_hr) then - var_found = .true. - endif - if (var_found) then - call grib_get(igrib, 'values', sm_ASCAT_A_hr, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading hr values for ASCAT_A' - call grib_release(igrib, iret) - imsg = -1 - exit - end if - endif - - var_found = .false. - if (param_num .eq. param_ASCAT_A_mn) then - var_found = .true. - endif - if (var_found) then - call grib_get(igrib, 'values', sm_ASCAT_A_mn, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading mn values for ASCAT_A' - call grib_release(igrib, iret) - imsg = -1 - exit - end if - endif - - var_found = .false. - if (param_num .eq. param_ASCAT_B) then - var_found = .true. - endif - if (var_found) then - call grib_get(igrib, 'values', sm_ASCAT_B, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading values for ASCAT_B' - call grib_release(igrib, iret) - imsg = -1 - exit - end if - do r = 1, SMOPS_ASCATsm_struc(n)%nr - do c = 1, SMOPS_ASCATsm_struc(n)%nc - sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & - sm_ASCAT_B(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc) - enddo - enddo - endif - - var_found = .false. - if (param_num .eq. param_ASCAT_B_qa) then - var_found = .true. - endif - if (var_found) then - call grib_get(igrib, 'values', sm_ASCAT_B_qa, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading QA values for ASCAT_B' - call grib_release(igrib, iret) - imsg = -1 - exit - end if - do r = 1, SMOPS_ASCATsm_struc(n)%nr - do c = 1, SMOPS_ASCATsm_struc(n)%nc - sm_ASCAT_B_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & - INT(sm_ASCAT_B_qa(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc)) - enddo - enddo - endif - - var_found = .false. - if (param_num .eq. param_ASCAT_B_hr) then - var_found = .true. + if (a_exist) then + if(param_num .eq. param_ASCAT_A) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_A, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading values for ASCAT_A' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + do r = 1, SMOPS_ASCATsm_struc(n)%nr + do c = 1, SMOPS_ASCATsm_struc(n)%nc + sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & + sm_ASCAT_A(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc) + enddo + enddo + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_A_qa) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_A_qa, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading QA values for ASCAT_A' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + do r = 1, SMOPS_ASCATsm_struc(n)%nr + do c = 1, SMOPS_ASCATsm_struc(n)%nc + sm_ASCAT_A_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & + INT(sm_ASCAT_A_qa(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + enddo + enddo + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_A_hr) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_A_hr, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading hr values for ASCAT_A' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_A_mn) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_A_mn, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading mn values for ASCAT_A' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + endif endif - if(var_found) then - call grib_get(igrib, 'values', sm_ASCAT_B_hr, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading hr values for ASCAT_B' - call grib_release(igrib, iret) - imsg = -1 - exit - end if - endif - - var_found = .false. - if (param_num .eq. param_ASCAT_B_mn) then - var_found = .true. + if (b_exist) then + var_found = .false. + if (param_num .eq. param_ASCAT_B) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_B, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading values for ASCAT_B' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + do r = 1, SMOPS_ASCATsm_struc(n)%nr + do c = 1, SMOPS_ASCATsm_struc(n)%nc + sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & + sm_ASCAT_B(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc) + enddo + enddo + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_B_qa) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_B_qa, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading QA values for ASCAT_B' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + do r = 1, SMOPS_ASCATsm_struc(n)%nr + do c = 1, SMOPS_ASCATsm_struc(n)%nc + sm_ASCAT_B_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & + INT(sm_ASCAT_B_qa(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + enddo + enddo + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_B_hr) then + var_found = .true. + endif + if(var_found) then + call grib_get(igrib, 'values', sm_ASCAT_B_hr, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading hr values for ASCAT_B' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_B_mn) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_B_mn, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading mn values for ASCAT_B' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + endif endif - if (var_found) then - call grib_get(igrib, 'values', sm_ASCAT_B_mn, iret) - if (iret .ne. 0) then - write(LIS_logunit,*)'[WARN] Problem reading mn values for ASCAT_B' - call grib_release(igrib, iret) - imsg = -1 - exit - end if + if (c_exist) then + var_found = .false. + if (param_num .eq. param_ASCAT_C) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_C, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading values for ASCAT_C' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + do r = 1, SMOPS_ASCATsm_struc(n)%nr + do c = 1, SMOPS_ASCATsm_struc(n)%nc + sm_ASCAT_C_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & + sm_ASCAT_C(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc) + enddo + enddo + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_C_qa) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_C_qa, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading QA values for ASCAT_C' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + do r = 1, SMOPS_ASCATsm_struc(n)%nr + do c = 1, SMOPS_ASCATsm_struc(n)%nc + sm_ASCAT_C_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = & + INT(sm_ASCAT_C_qa(c+((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + enddo + enddo + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_C_hr) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_C_hr, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading hr values for ASCAT_C' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + endif + + var_found = .false. + if (param_num .eq. param_ASCAT_C_mn) then + var_found = .true. + endif + if (var_found) then + call grib_get(igrib, 'values', sm_ASCAT_C_mn, iret) + if (iret .ne. 0) then + write(LIS_logunit,*)'[WARN] Problem reading mn values for ASCAT_C' + call grib_release(igrib, iret) + imsg = -1 + exit + end if + endif endif - call grib_release(igrib, iret) if (iret .ne. 0) then write(LIS_logunit,*)'[WARN] Problem releasing from ', trim(fname) @@ -755,82 +869,132 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) ! Meaning estimated error is get_byte1, and quality is get_byte2. sm_time_ASCAT_A = LIS_rc%udef sm_time_ASCAT_B = LIS_rc%udef + sm_time_ASCAT_C = LIS_rc%udef sm_data = LIS_rc%udef sm_data_b = .false. + + if (a_exist) then + do r=1, SMOPS_ASCATsm_struc(n)%nr + do c=1, SMOPS_ASCATsm_struc(n)%nc + qavalue = sm_ASCAT_A_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) + if ( qavalue .ne. 9999 ) then + !estimated error + err = get_byte1(qavalue) + !quality flag - not used currently + ql = get_byte2(qavalue) + + if(err.lt.err_threshold) then + hr_val = nint(sm_ASCAT_A_hr(c+& + ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + mn_val = nint(sm_ASCAT_A_mn(c+& + ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + call LIS_get_timeoffset_sec(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & + hr_val, mn_val, 0, julss) + sm_time_ASCAT_A(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = julss + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .true. + else + sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. + endif + else + sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. + endif + if(sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc).lt.0.001) then + sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. + endif + enddo + enddo + endif + if (b_exist) then + do r=1, SMOPS_ASCATsm_struc(n)%nr + do c=1, SMOPS_ASCATsm_struc(n)%nc + qavalue = sm_ASCAT_B_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) + if ( qavalue .ne. 9999 ) then + !estimated error + err = get_byte1(qavalue) + !quality flag - not used currently + ql = get_byte2(qavalue) + + if(err.lt.err_threshold) then + hr_val = nint(sm_ASCAT_B_hr(c+& + ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + mn_val = nint(sm_ASCAT_B_mn(c+& + ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + call LIS_get_timeoffset_sec(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & + hr_val, mn_val, 0, julss) + sm_time_ASCAT_B(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = julss + else + sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + endif + else + sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + endif + if(sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc).lt.0.001) then + sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + endif + enddo + enddo + endif + if (c_exist) then + do r=1, SMOPS_ASCATsm_struc(n)%nr + do c=1, SMOPS_ASCATsm_struc(n)%nc + qavalue = sm_ASCAT_C_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) + if ( qavalue .ne. 9999 ) then + !estimated error + err = get_byte1(qavalue) + !quality flag - not used currently + ql = get_byte2(qavalue) + + if(err.lt.err_threshold) then + hr_val = nint(sm_ASCAT_C_hr(c+& + ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + mn_val = nint(sm_ASCAT_C_mn(c+& + ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& + SMOPS_ASCATsm_struc(n)%nc)) + call LIS_get_timeoffset_sec(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & + hr_val, mn_val, 0, julss) + sm_time_ASCAT_C(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = julss + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .true. + else + sm_ASCAT_C_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. + endif + else + sm_ASCAT_C_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. + endif + if(sm_ASCAT_C_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc).lt.0.001) then + sm_ASCAT_C_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef + sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. + endif + enddo + enddo + endif - do r=1, SMOPS_ASCATsm_struc(n)%nr - do c=1, SMOPS_ASCATsm_struc(n)%nc - qavalue = sm_ASCAT_A_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) - if ( qavalue .ne. 9999 ) then - !estimated error - err = get_byte1(qavalue) - !quality flag - not used currently - ql = get_byte2(qavalue) - - if(err.lt.err_threshold) then - hr_val = nint(sm_ASCAT_A_hr(c+& - ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc)) - mn_val = nint(sm_ASCAT_A_mn(c+& - ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc)) - call LIS_get_timeoffset_sec(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & - hr_val, mn_val, 0, julss) - sm_time_ASCAT_A(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = julss - sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .true. - else - sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef - sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. - endif - else - sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef - sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. - endif - if(sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc).lt.0.001) then - sm_ASCAT_A_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef - sm_data_b(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = .false. - endif - enddo - enddo - - do r=1, SMOPS_ASCATsm_struc(n)%nr - do c=1, SMOPS_ASCATsm_struc(n)%nc - qavalue = sm_ASCAT_B_qa_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) - if ( qavalue .ne. 9999 ) then - !estimated error - err = get_byte1(qavalue) - !quality flag - not used currently - ql = get_byte2(qavalue) - - if(err.lt.err_threshold) then - hr_val = nint(sm_ASCAT_B_hr(c+& - ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc)) - mn_val = nint(sm_ASCAT_B_mn(c+& - ((SMOPS_ASCATsm_struc(n)%nr-r+1)-1)*& - SMOPS_ASCATsm_struc(n)%nc)) - call LIS_get_timeoffset_sec(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & - hr_val, mn_val, 0, julss) - sm_time_ASCAT_B(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = julss - else - sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef - endif - else - sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef - endif - if(sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc).lt.0.001) then - sm_ASCAT_B_t(c+(r-1)*SMOPS_ASCATsm_struc(n)%nc) = LIS_rc%udef - endif - enddo - enddo - - sm_data = sm_ASCAT_A_t - sm_time = sm_time_ASCAT_A - where ( sm_ASCAT_B_t /= LIS_rc%udef ) + if ( file_time < SMOPS_ASCATsm_struc(n)%version4_time ) then + sm_data = sm_ASCAT_A_t + sm_time = sm_time_ASCAT_A + where ( sm_ASCAT_B_t /= LIS_rc%udef ) + sm_data = sm_ASCAT_B_t + sm_time = sm_time_ASCAT_B + sm_data_b = .true. + endwhere + else sm_data = sm_ASCAT_B_t sm_time = sm_time_ASCAT_B - sm_data_b = .true. - endwhere + where ( sm_ASCAT_C_t /= LIS_rc%udef ) + sm_data = sm_ASCAT_C_t + sm_time = sm_time_ASCAT_C + sm_data_b = .true. + endwhere + endif !-------------------------------------------------------------------------- ! Interpolate to the LIS running domain @@ -897,8 +1061,11 @@ end subroutine read_SMOPS_ASCAT_data subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filename) ! !USES: use ESMF + use LIS_mpiMod + use LIS_logMod + use LIS_coreMod,only : LIS_masterproc use LIS_timeMgrMod, only : LIS_calendar - + use LIS_constantsMod, only : LIS_CONST_PATH_LEN implicit none ! !ARGUMENTS: character(len=*) :: filename @@ -906,6 +1073,7 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen integer :: yr, mo, da, hr character (len=*) :: ndir character (len=*) :: conv + integer, external :: create_filelist ! C function ! ! !DESCRIPTION: ! This subroutine creates the SMOPS filename based on the time and date @@ -936,9 +1104,13 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen logical, save :: first_time=.true. type(ESMF_Time), save :: naming3_time + type(ESMF_Time), save :: Ver4_blended_time type(ESMF_Time) :: file_time type(ESMF_TimeInterval) :: six_hours integer :: rc + character*8 :: yyyymmdd + character(len=LIS_CONST_PATH_LEN) :: list_files + integer :: ftn, ierr if ( first_time ) then call ESMF_TimeSet(naming3_time, & @@ -950,6 +1122,17 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen s = 0, & calendar = LIS_calendar, & rc = rc) + + call ESMF_TimeSet(Ver4_blended_time, & + yy = 2024, & + mm = 4, & + dd = 25, & + h = 0, & + m = 0, & + s = 0, & + calendar = LIS_calendar, & + rc = rc) + first_time = .false. endif @@ -964,7 +1147,9 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen s = 0, & calendar = LIS_calendar, & rc = rc) - file_time = file_time + six_hours + if ( file_time >= naming3_time .and. file_time < Ver4_blended_time) then + file_time = file_time+six_hours + endif call ESMF_TimeGet(file_time, & yy = yr, & mm = mo, & @@ -977,15 +1162,53 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen write(unit=fmo, fmt='(i2.2)') mo write(unit=fda, fmt='(i2.2)') da write(unit=fhr, fmt='(i2.2)') hr + write(yyyymmdd,'(i4.4,2i2.2)') yr,mo,da if(useRT.eq.1) then if ( conv == "LIS" ) then filename = trim(ndir)//'/'//trim(fyr)//'/NPR_SMOPS_CMAP_D' & //trim(fyr)//trim(fmo)//trim(fda)//trim(fhr)//'.gr2' else - if ( file_time >= naming3_time) then + if ( file_time >= naming3_time .and. file_time < Ver4_blended_time) then filename = trim(ndir)//'/'//'/NPR_SMOPS_CMAP_D' & //trim(fyr)//trim(fmo)//trim(fda)//trim(fhr)//'.gr2' + elseif (file_time >= Ver4_blended_time) then + ! NPR-SMOPS-CMAP-6hrly_v4r0_blend_s202404250600000_e202404251159599_c202404251440470.grib2 + !filename = trim(ndir)//'/'//'/NPR-SMOPS-CMAP-6hrly_v4r0_blend_s' & + ! //trim(yyyymmdd)//'00000_e'//trim(yyyymmdd)//'*_c'//trim(yyyymmdd)//'*.grib2' + filename = 'NULL' ! EMK Initialize + if (LIS_masterproc) then + list_files = trim(ndir)//'/'//'NPR-SMOPS-CMAP-6hrly_v4r0_blend_s' & + //trim(yyyymmdd)//trim(fhr)//'*.grib2' + + write(LIS_logunit,*) & + '[INFO] Searching for ',trim(list_files) + rc = create_filelist(trim(list_files)//char(0), & + "SMOPS_ASCAT_filelist.sm.dat"//char(0)) + if (rc .ne. 0) then + write(LIS_logunit,*) & + '[WARN] Problem encountered when searching for SMOPS_ASCAT files' + write(LIS_logunit,*) & + 'Was searching for ',trim(list_files) + write(LIS_logunit,*) & + 'LIS will continue...' + endif + end if +#if (defined SPMD) + call mpi_barrier(lis_mpi_comm,ierr) +#endif + + ftn = LIS_getNextUnitNumber() + open(ftn,file="./SMOPS_ASCAT_filelist.sm.dat",status='old',iostat=ierr) + ! We do not need do while.Only one file should be available for the selected date + do while(ierr.eq.0) + read(ftn,'(a)',iostat=ierr) filename + if(ierr.ne.0) then + exit + endif + enddo + !write(LIS_logunit,*) '[INFO] Will read ',trim(filename) + call LIS_releaseUnitNumber(ftn) else filename = trim(ndir)//'/smops_d' & //trim(fyr)//trim(fmo)//trim(fda)//'_s'//trim(fhr)//'0000_cness.gr2' diff --git a/lis/metforcing/usaf/AGRMET_forcingMod.F90 b/lis/metforcing/usaf/AGRMET_forcingMod.F90 index 2c7f074f8..32172d6f2 100644 --- a/lis/metforcing/usaf/AGRMET_forcingMod.F90 +++ b/lis/metforcing/usaf/AGRMET_forcingMod.F90 @@ -343,6 +343,9 @@ module AGRMET_forcingMod character*100 :: geodir character*100 :: gfsdir character*100 :: galwemdir +! TEMP -- KRA + character*180 :: galwemraddir +! TEMP -- KRA character*100 :: cdmsdir character*100 :: cmordir character*100 :: analysisdir @@ -556,8 +559,9 @@ module AGRMET_forcingMod ! EMK END integer :: lastSfcalcHour integer :: lastPcpHour + integer :: lastRadHour !new - integer :: ncol, nrow + integer :: ncol, nrow integer, allocatable :: n11_1_gfs(:) integer, allocatable :: n12_1_gfs(:) integer, allocatable :: n21_1_gfs(:) @@ -2145,6 +2149,8 @@ subroutine init_AGRMET(findex) agrmet_struc(n)%pcp_ready = .false. agrmet_struc(n)%lastSfcalcHour = 0 agrmet_struc(n)%lastPcpHour = 0 + agrmet_struc(n)%lastRadHour = 0 + call AGRMET_read_pcpclimodata(n) agrmet_struc(n)%albAlarmTime = 0.0 diff --git a/lis/metforcing/usaf/AGRMET_getpcpobs.F90 b/lis/metforcing/usaf/AGRMET_getpcpobs.F90 index e629d87fa..80427b01d 100644 --- a/lis/metforcing/usaf/AGRMET_getpcpobs.F90 +++ b/lis/metforcing/usaf/AGRMET_getpcpobs.F90 @@ -33,6 +33,8 @@ ! 11 May 11 Store obs from 3,9,15,& 21Z for India and Sri Lanka in a ! new array and pass to processobs............Chris Franks/16WS/WXE/SEMS ! 29 Aug 23 Call LIS_alert if a preobs file is missing..............Eric Kemp/NASA +! 23 May 24 Updated calls to AGRMET_storeobs and +! AGRMET_storeobs_offhour.......................Eric Kemp/NASA ! ! !INTERFACE: subroutine AGRMET_getpcpobs(n, j6hr, month, prcpwe, & @@ -361,7 +363,7 @@ subroutine AGRMET_getpcpobs(n, j6hr, month, prcpwe, & call AGRMET_storeobs(nsize, nsize3, agrmet_struc(n)%max_pcpobs, & obs, obs3, ilat, ilon, & mscprc, sixprc, twfprc, network, plat_id, cdms_flag, bsn, & - duration, j3hr, stncnt) + duration, j3hr, stncnt, alert_number, filename) else @@ -371,7 +373,7 @@ subroutine AGRMET_getpcpobs(n, j6hr, month, prcpwe, & call AGRMET_storeobs_offhour(nsize, agrmet_struc(n)%max_pcpobs, & obs3, ilat, ilon, & mscprc, sixprc, twfprc, network, plat_id, cdms_flag, bsn, & - duration, nsize3) + duration, nsize3, alert_number, filename) end if diff --git a/lis/metforcing/usaf/AGRMET_sfcalc.F90 b/lis/metforcing/usaf/AGRMET_sfcalc.F90 index d68826d26..52e549ab6 100644 --- a/lis/metforcing/usaf/AGRMET_sfcalc.F90 +++ b/lis/metforcing/usaf/AGRMET_sfcalc.F90 @@ -230,9 +230,9 @@ subroutine AGRMET_sfcalc(n) call LIS_get_julhr(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,& 0,0,jultmp) - if(jultmp .gt.agrmet_struc(n)%lastSfcalcHour) then + if(jultmp .gt. agrmet_struc(n)%lastSfcalcHour) then timeToReadGFS = .true. - else + else timeToReadGFS = .false. endif diff --git a/lis/metforcing/usaf/AGRMET_storeobs.F90 b/lis/metforcing/usaf/AGRMET_storeobs.F90 index 16c708a44..9eb050c7b 100644 --- a/lis/metforcing/usaf/AGRMET_storeobs.F90 +++ b/lis/metforcing/usaf/AGRMET_storeobs.F90 @@ -20,11 +20,20 @@ ! block stn number.............Chris Franks/16WS/WXE/SEMS ! 11 may 11 improve processing of obs from India and Sri Lanka ! .............................Chris Franks/16WS/WXE/SEMS +! 23 May 24 Check network of each report to ensure it is recognized; +! reject if unknown; keep track of unknown networks +! encountered during the run; and write alert file as a +! new unknown network is encountered..........Eric Kemp/NASA ! ! !INTERFACE: subroutine AGRMET_storeobs(nsize, nsize3, isize, obs, obs3, ilat, ilon, & mscprc, sixprc, twfprc, network, plat_id, cdms_flag, bsn, & - duration, julhr, stncnt) + duration, julhr, stncnt, alert_number, filename) + + ! Imports + use LIS_coreMod, only: LIS_masterproc ! EMK 20240523 + use LIS_logMod, only: LIS_logunit, LIS_alert ! EMK 20240523 + use USAF_bratsethMod, only: USAF_is_gauge ! EMK 20240523 implicit none @@ -43,7 +52,8 @@ subroutine AGRMET_storeobs(nsize, nsize3, isize, obs, obs3, ilat, ilon, & integer, intent(in) :: julhr integer, intent(inout) :: stncnt integer, intent(in) :: twfprc(isize) - + integer, intent(inout) :: alert_number ! EMK 20240523 + character(*), intent(in) :: filename ! EMK 20240523 ! ! !DESCRIPTION: ! performs some preprocessing on the raw observations and stores @@ -165,6 +175,32 @@ subroutine AGRMET_storeobs(nsize, nsize3, isize, obs, obs3, ilat, ilon, & type(rain_obs), intent(inout) :: obs(isize) type(rain_obs), intent(in) :: obs3(isize) + ! EMK 20240523 + character(255) :: message(20) + integer, parameter :: MAX_NEW_NETWORKS = 20 + character(10), save :: new_networks(MAX_NEW_NETWORKS) = & + (/"NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL "/) + integer :: i + ! ------------------------------------------------------------------ ! If observations were retrieved from CDMS use 6-digit BSN limits ! for the specially processed regions @@ -214,7 +250,36 @@ subroutine AGRMET_storeobs(nsize, nsize3, isize, obs, obs3, ilat, ilon, & else cycle RECORD end if - + + ! EMK 20240523...Skip report if network is not recognized. Issue an + ! alert. Keep track of unknown networks to avoid redundant alerts. + if (.not. USAF_is_gauge(network(irecord))) then + do i = 1, MAX_NEW_NETWORKS + if (new_networks(i) == network(irecord)) then + cycle RECORD + else if (new_networks(i) == "NULL") then + new_networks(i) = network(irecord) + write(LIS_logunit,*)'[WARN] Found unrecognized network ', & + trim(network(irecord)) + write(LIS_logunit,*)'[WARN] Will skip report in preobs file' + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine: AGRMET_storeobs' + message(3) = ' Found unrecognized network in '// & + trim(filename) + message(4) = ' Network '//trim(network(irecord)) + message(5) = ' Contact NASA developers to add this network' + if (LIS_masterproc) then + call LIS_alert('LIS.AGRMET_storeobs', & + alert_number, message) + alert_number = alert_number + 1 + end if + cycle RECORD + end if + end do + if (i > MAX_NEW_NETWORKS) cycle RECORD + end if + ! ------------------------------------------------------------------ ! If bsn is not zero either the observations came from CDMS or they ! came from JMOBS and this is a WMO observation. Set the flag to diff --git a/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 b/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 index 4d1733cac..13e7047c4 100644 --- a/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 +++ b/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 @@ -14,14 +14,23 @@ ! ! !REVISION HISTORY: ! 11 may 11 Adapted from AGRMET_storeobs...Chris Franks/16WS/WXE/SEMS +! 23 May 24 Check network of each report to ensure it is recognized; +! reject if unknown; keep track of unknown networks +! encountered during the run; and write alert file as a +! new unknown network is encountered..........Eric Kemp/NASA ! ! !INTERFACE: subroutine AGRMET_storeobs_offhour(nsize, isize, obs, ilat, ilon, & mscprc, sixprc, twfprc, network, plat_id, cdms_flag, bsn, & - duration, stncnt) + duration, stncnt, alert_number, filename) + + ! Imports + use LIS_coreMod, only: LIS_masterproc ! EMK 20240523 + use LIS_logMod, only: LIS_logunit, LIS_alert ! EMK 20240523 + use USAF_bratsethMod, only: USAF_is_gauge ! EMK 20240523 implicit none - + integer, intent(in) :: isize character*10, intent(in) :: network(isize) character*10, intent(in) :: plat_id(isize) @@ -34,8 +43,9 @@ subroutine AGRMET_storeobs_offhour(nsize, isize, obs, ilat, ilon, & integer, intent(in) :: nsize integer, intent(in) :: sixprc(isize) integer, intent(inout) :: stncnt - integer, intent(in) :: twfprc(isize) - + integer, intent(in) :: twfprc(isize) + integer, intent(inout) :: alert_number ! EMK 20240523 + character(*), intent(in) :: filename ! EMK 20240523 ! ! !DESCRIPTION: ! performs some preprocessing on raw 3-hourly observations for @@ -130,6 +140,32 @@ subroutine AGRMET_storeobs_offhour(nsize, isize, obs, ilat, ilon, & type(rain_obs), intent(inout) :: obs(isize) + ! EMK 20240523 + character(255) :: message(20) + integer, parameter :: MAX_NEW_NETWORKS = 20 + character(10), save :: new_networks(MAX_NEW_NETWORKS) = & + (/"NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL ", & + "NULL "/) + integer :: i + ! ------------------------------------------------------------------ ! If observations were retrieved from CDMS use 6-digit BSN limits ! for the specially processed regions @@ -176,7 +212,36 @@ subroutine AGRMET_storeobs_offhour(nsize, isize, obs, ilat, ilon, & else cycle RECORD end if - + + ! EMK 20240523...Skip report if network is not recognized. Issue an + ! alert. Keep track of unknown networks to avoid redundant alerts. + if (.not. USAF_is_gauge(network(irecord))) then + do i = 1, MAX_NEW_NETWORKS + if (new_networks(i) == network(irecord)) then + cycle RECORD + else if (new_networks(i) == "NULL") then + new_networks(i) = network(irecord) + write(LIS_logunit,*)'[WARN] Found unrecognized network ', & + trim(network(irecord)) + write(LIS_logunit,*)'[WARN] Will skip report in preobs file' + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine: AGRMET_storeobs_offhour' + message(3) = ' Found unrecognized network in '// & + trim(filename) + message(4) = ' Network '//trim(network(irecord)) + message(5) = ' Contact NASA developers to add this network' + if (LIS_masterproc) then + call LIS_alert('LIS.AGRMET_storeobs_offhour', & + alert_number, message) + alert_number = alert_number + 1 + end if + cycle RECORD + end if + end do + if (i > MAX_NEW_NETWORKS) cycle RECORD + end if + ! ------------------------------------------------------------------ ! check for valid wmo block station number (bsn) and valid ! precipitation totals. if they exist, process this ob. diff --git a/lis/metforcing/usaf/USAF_bratsethMod.F90 b/lis/metforcing/usaf/USAF_bratsethMod.F90 index e79a25ffa..e0bff13a2 100644 --- a/lis/metforcing/usaf/USAF_bratsethMod.F90 +++ b/lis/metforcing/usaf/USAF_bratsethMod.F90 @@ -26,6 +26,8 @@ ! 21 Mar 2024 Changed internal BackQC and SuperstatQC logic to only ! skip for IMERG. This allows use with T, RH, and wind ! speed analyses..........................Eric Kemp/SSAI/NASA +! 23 May 2024 Export USAF_is_gauge function, and add HADS and +! NWSLI gage networks.....................Eric Kemp/SSAI/NASA ! ! DESCRIPTION: ! @@ -139,6 +141,8 @@ module USAF_bratsethMod public :: USAF_snowDepthQC public :: USAF_backQC public :: USAF_superstatQC + ! EMK 20240523 + public :: USAF_is_gauge ! A simple linked list type that can be used in a hash table. Intended ! to store indices of arrays in the USAF_obsData type for efficient look-up. @@ -1673,7 +1677,7 @@ subroutine USAF_analyzePrecip(precipAll,nest,back,hourindex,mrgp,precipOBA) call calc_invDataDensities(precipAll,sigmaBSqr,nest, & agrmet_struc(nest)%bratseth_precip_max_dist, & agrmet_struc(nest)%bratseth_precip_back_err_scale_length, & - is_gauge, & + USAF_is_gauge, & invDataDensities) ! Run Bratseth analysis at observation points, and collect the sum of @@ -1684,7 +1688,7 @@ subroutine USAF_analyzePrecip(precipAll,nest,back,hourindex,mrgp,precipOBA) call calc_obsAnalysis(precipAll,sigmaBSqr,nobs,invDataDensities,nest,& agrmet_struc(nest)%bratseth_precip_max_dist, & agrmet_struc(nest)%bratseth_precip_back_err_scale_length, & - convergeThresh, is_gauge, sumObsEstimates, & + convergeThresh, USAF_is_gauge, sumObsEstimates, & npasses, precipOBA) ! Calculate analysis at grid points. @@ -2967,6 +2971,7 @@ subroutine fldbld_precip_nwp(nest,findex,julhr,src,fc_hr, & yr_2d = mod(yr1,100) if (yr_2d.eq.0) yr_2d = 100 + if (src .eq. "GFS") then ! EMK...Added support for new GFS filename convention call getAVNfilename(gribfile, agrmet_struc(nest)%agrmetdir,& @@ -4280,22 +4285,24 @@ end subroutine USAF_backQC !--------------------------------------------------------------------------- ! Checks if observation network is recognized as a gauge. - logical function is_gauge(net) + logical function USAF_is_gauge(net) implicit none character(len=32), intent(in) :: net logical :: answer answer = .false. - if (trim(net) .eq. "AMIL") answer = .true. - if (trim(net) .eq. "CANA") answer = .true. - if (trim(net) .eq. "FAA") answer = .true. - if (trim(net) .eq. "ICAO") answer = .true. - if (trim(net) .eq. "WMO") answer = .true. - if (trim(net) .eq. "MOBL") answer = .true. - if (trim(net) .eq. "SUPERGAGE") answer = .true. + if (net .eq. "AMIL") answer = .true. + if (net .eq. "CANA") answer = .true. + if (net .eq. "FAA") answer = .true. + if (net .eq. "HADS") answer = .true. ! EMK 20240523 + if (net .eq. "ICAO") answer = .true. + if (net .eq. "NWSLI") answer = .true. ! EMK 20240523 + if (net .eq. "WMO") answer = .true. + if (net .eq. "MOBL") answer = .true. + if (net .eq. "SUPERGAGE") answer = .true. ! Handle reformatted CDMS data that are missing the network type. - if (trim(net) .eq. "CDMS") answer = .true. - is_gauge = answer - end function is_gauge + if (net .eq. "CDMS") answer = .true. + USAF_is_gauge = answer + end function USAF_is_gauge !--------------------------------------------------------------------------- ! Dummy function for establishing a surface station is uncorrelated. diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 new file mode 100644 index 000000000..f1b921ad4 --- /dev/null +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -0,0 +1,170 @@ +!-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- +! NASA Goddard Space Flight Center +! Land Information System Framework (LISF) +! Version 7.4 +! +! Copyright (c) 2022 United States Government as represented by the +! Administrator of the National Aeronautics and Space Administration. +! All Rights Reserved. +!-------------------------END NOTICE -- DO NOT EDIT----------------------- +#include "LIS_misc.h" +!BOP +! +! !ROUTINE: USAF_fldbld_radflux +! \label{USAF_fldbld_radflux} +! +! !REVISION HISTORY: +! 14 Jun 2016 Refactor into simple caller; see USAF_fldbld_radflux_gfs +! .........................................James Geiger/NASA +! 11 Oct 2017 Added logic to switch from GALWEM to GFS in emergency +! .........................................Eric Kemp/GSFC +! 23 Oct 2017 Reorganized code.........................Eric Kemp/GSFC +! 28 May 2024 Generated reader for radiation fluxese...K. Arsenault/SAIC +! +! !INTERFACE: +subroutine USAF_fldbld_radflux(n,swdown,longwv) + +! !USES: + use AGRMET_forcingMod, only : agrmet_struc + use LIS_coreMod, only : LIS_rc, LIS_masterproc + use LIS_logMod, only : LIS_logunit, LIS_endrun, LIS_abort,& + LIS_alert + use LIS_timeMgrMod, only : LIS_julhr_date, LIS_get_julhr + +#if (defined USE_GRIBAPI) + use grib_api +#endif + + implicit none +! !ARGUMENTS: + integer, intent(in) :: n + real, intent(out) :: swdown(LIS_rc%lnc(n), LIS_rc%lnr(n)) + real, intent(out) :: longwv(LIS_rc%lnc(n), LIS_rc%lnr(n)) + +! +! !DESCRIPTION: +! This routine calls the appropriate first guess forcing based on +! the source of the first guess forcing data. +! +! The arguments and variables are: +! \begin{description} +! \item[n] +! index of the nest +! \end{description} +! +! The routines invoked are: +! \begin{description} +! \item[agrmet\_fldbld\_gfs](\ref{agrmet_fldbld_gfs}) \newline +! read avn or nogaps data in grib format +! \item[agrmet\_fldbld\_galwem](\ref{agrmet_fldbld_galwem}) \newline +! read UK Unified Model (GALWEM) data in GRIB2 format +! \end{description} +!EOP + + integer :: rc + character(len=255) :: message(20) + character(len=10) :: yyyymmddhh + integer :: julhr + integer :: istart + integer :: julend + integer :: ierr + + ! External subroutines + external :: AGRMET_julhr_date10 + external :: USAF_fldbld_radflux_galwem + external :: USAF_fldbld_radflux_gfs + + ! Sanity check + if ( agrmet_struc(n)%first_guess_source .ne. 'GALWEM' .and. & + agrmet_struc(n)%first_guess_source .ne. "GFS") then + write(LIS_logunit,*) '[ERR] NWP radiation source is not correctly defined.' + call LIS_endrun + end if + ! EMK 12 Jun 2024...GFS radiation option is disabled pending discussion + ! with 557 WW and testing. + if ( agrmet_struc(n)%first_guess_source .ne. 'GALWEM' ) then + write(LIS_logunit,*)'[ERR] NWP radiation source must be GALWEM!' + call LIS_endrun + end if + +!------------------------------------------------------------------ +! Find the time to start the processing from +!------------------------------------------------------------------ + call LIS_get_julhr(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & + LIS_rc%hr, 0, 0, istart) + + julend = istart + + agrmet_struc(n)%lastRadHour = julend + + ! Generate 10-digit Year-Month-Day-Hour for "julhr": + call AGRMET_julhr_date10(julend, yyyymmddhh) + write(LIS_logunit,*) " " + write(LIS_logunit,*) & + '[INFO] Searching for NWP radiation fields, valid ',yyyymmddhh + + ! Try fetching GALWEM, if requested + ierr = 0 + if ( agrmet_struc(n)%first_guess_source == 'GALWEM' ) then + + julhr = julend + call USAF_fldbld_radflux_galwem(n,julhr,swdown,longwv,rc) + ierr = rc + + if (rc .ne. 0) then + call AGRMET_julhr_date10(julhr, yyyymmddhh) + write(LIS_logunit,*) & + '[ERR] No GALWEM radiation found for ',yyyymmddhh + write(LIS_logunit,*) '[ERR] ABORTING!' + flush(LIS_logunit) + message(:) = '' + message(1) = '[ERR] Program: LIS' + message(2) = ' Routine: USAF_fldbld_radflux.' + message(3) = ' GALWEM radiation data not available for '//& + yyyymmddhh + if (LIS_masterproc) then + call LIS_alert( 'LIS.USAF_fldbld_radflux.', 1, & + message ) + call LIS_abort( message) + endif + end if + + end if + + + ! EMK 12 Jun 2024...GFS option is disabled. + ! ! Try fetching GFS, if requested, or if GALWEM is not available. + ! if ( agrmet_struc(n)%first_guess_source == "GFS" .or. & + ! ierr .ne. 0) then + ! if (ierr .ne. 0) then + ! write(LIS_logunit,*)'[WARN] Unable to find GALWEM data!' + ! write(LIS_logunit,*)'[WARN] Rolling back to GFS...' + ! end if + + ! call USAF_fldbld_radflux_gfs(n, julhr, swdown, longwv, rc) + + ! if (rc .ne. 0) then + ! call AGRMET_julhr_date10(julhr, yyyymmddhh) + ! if (ierr .ne. 0) then + ! write(LIS_logunit,*) & + ! '[ERR] No GALWEM or GFS background found for ',yyyymmddhh + ! else + ! write(LIS_logunit,*) & + ! '[ERR] No GFS background found for ',yyyymmddhh + ! end if + ! write(LIS_logunit,*) '[ERR] ABORTING!' + ! flush(LIS_logunit) + ! message(:) = '' + ! message(1) = '[ERR] Program: LIS' + ! message(2) = ' Routine: USAF_fldbld_radflux.' + ! message(3) = ' GALWEM and GFS GRIB data not available for '//& + ! yyyymmddhh + ! if (LIS_masterproc) then + ! call LIS_alert( 'LIS.USAF_fldbld_radflux.', 1, & + ! message ) + ! call LIS_abort( message) + ! endif + ! end if + ! end if + +end subroutine USAF_fldbld_radflux diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 new file mode 100644 index 000000000..1da1b50ce --- /dev/null +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -0,0 +1,921 @@ +!-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- +! NASA Goddard Space Flight Center +! Land Information System Framework (LISF) +! Version 7.4 +! +! Copyright (c) 2022 United States Government as represented by the +! Administrator of the National Aeronautics and Space Administration. +! All Rights Reserved. +!-------------------------END NOTICE -- DO NOT EDIT----------------------- +#include "LIS_misc.h" +!BOP +! +! !ROUTINE: USAF_fldbld_radflux_galwem +! \label{USAF_fldbld_radflux_galwem} +! +! !REVISION HISTORY: +! 11 Aug 2016 Initial specification based on AGRMET_fldbld_precip_gfs +! ...........................................James Geiger/NASA +! 29 May 2024 Added reading in GALWEM radiation fluxes +! ...........................................K. Arsenault/SAIC +! +! !INTERFACE: +subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) + +! !USES: + use AGRMET_forcingMod, only : agrmet_struc + use LIS_coreMod, only : LIS_rc, LIS_masterproc + use LIS_logMod, only : LIS_logunit, LIS_abort, LIS_alert, & + LIS_verify, LIS_endrun + use LIS_timeMgrMod, only : LIS_julhr_date + +#if (defined USE_GRIBAPI) + use grib_api +#endif + + implicit none + +! !ARGUMENTS: + integer, intent(in) :: n + integer :: julhr + real, intent(out) :: fg_swdata(LIS_rc%lnc(n), LIS_rc%lnr(n)) + real, intent(out) :: fg_lwdata(LIS_rc%lnc(n), LIS_rc%lnr(n)) + integer, intent(out):: rc + +! +! !DESCRIPTION: +! This routine reads in the GALWEM downward short- +! and long-wave radiation flux data and interpolates +! to the USAF/AGRMET grid. +! +! The arguments and variables are: +! \begin{description} +! \item[n] +! index of the nest +! \item[fc\_hr] +! forecast hour or the difference between reference and valid time +! \item[fg\_swdata] +! array of galwem shortwave radiation data +! \item[fg\_lwdata] +! array of galwem longwave radiation data +! +! \item[ftn] +! file unit number +! \item[igrib] +! GRIB message handle +! \item[yr1, mo1, da1, hr1] +! date/time +! \item[avnfile] +! name of the 3 hour forecast file +! \item[avnfile2] +! name of the 6 hour forecast file +! \item[message] +! error message +! \item[iginfo] +! array of grid information from a grib record +! \item[gridres] +! the resolution, in degrees, of the first +! guess grid +! \item[fg\_swdown] +! SWdown radiation flux data to be interpolated to lis grid +! \item[fg\_lwdown] +! LWdown radiation flux data to be interpolated to lis grid +! \item[fg\_swdown1] +! 3 hour forecast swdown radiation flux data +! \item[fg\_lwdown1] +! 3 hour forecast lwdown radiation flux data +! \item[alert\_number] +! number of alerts that occur in the program +! \item[ifguess] +! east/west dimension of first guess grid +! \item[jfguess] +! north/south dimension of first guess grid +! \item[center] +! meteorological center that produced the first +! guess data (7-NCEP, 57-AFGWC, 58-FNMOC) +! \item[ierr] +! error code +! \item[yr\_2d] +! 2 digit year for comparison with GRIB header +! \item[found] +! logical flag set true when an input file with the correct valid +! time is found +! \item[file\_julhr] +! julian hour used to determine names of forecast files from previous cycles +! \item[getsixhr] +! indicates whether to get data from the 6 hour forecast file +! \item[dataDate] +! date of values in the GRIB message +! \item[dataTime] +! time of values in the GRIB message +! \item[gtype] +! type of grid determined by querying GRIB message +! \end{description} +! +! The routines invoked are: +! \begin{description} +! \item[julhr\_date] (\ref{LIS_julhr_date}) \newline +! converts the julian hour to a date format +! \item[AGRMET_getGALWEMfilename](\ref{AGRMET_getGALWEMfilename}) \newline +! generates the first guess GALWEM filename +! \item[AGRMET\_fldbld\_read\_radflux\_galwem] +! (\ref{USAF_fldbld_read_radflux_galwem}) \newline +! read GALWEM radiation flux data in grib format +! \item[interp\_galwem\_first\_guess](\ref{interp_galwem_first_guess}) \newline +! interpolate first guess data to the USAF/AGRMET grid +! \item[LIS\_abort](\ref{LIS_abort}) \newline +! abort in case of error +! \end{description} +!EOP + character(255) :: message(20) + integer :: ftn, igrib + character*250 :: avnfile + integer :: yr1, mo1, da1, hr1 + integer :: fc_hr + integer :: iginfo ( 2 ) + real :: gridres + integer, save :: alert_number = 1 + real, allocatable :: fg_swdown1 ( : , : ) + real, allocatable :: fg_lwdown1 ( : , : ) + integer :: ifguess, jfguess + integer :: center + integer :: ierr + logical*1 :: found + logical :: first_time + integer :: yr_2d + integer :: file_julhr + integer :: dataDate, dataTime + character*100 :: gtype + logical :: found_inq + + ! External functions + external :: AGRMET_getGALWEMfilename + external :: interp_galwem_first_guess + external :: USAF_fldbld_read_radflux_galwem + + ! --------------------------------------------------- + + ! Initialize return code to "no error". We will change it below if + ! necessary. + rc = 0 + + ! Will search previous GALWEM cycles every six hours, up to 24 hours, + ! until we find an acceptable file. + fc_hr = 0 ! Incremented below + file_julhr = julhr ! Decremented below + call LIS_julhr_date(file_julhr,yr1,mo1,da1,hr1) + + if (hr1 == 1 .or. hr1 == 7 .or. hr1 == 13 .or. hr1 == 19) then + fc_hr = 1 + else if (hr1 == 2 .or. hr1 == 8 .or. hr1 == 14 .or. hr1 == 20) then + fc_hr = 2 + else if (hr1 == 3 .or. hr1 == 9 .or. hr1 == 15 .or. hr1 == 21) then + fc_hr = 3 + else if (hr1 == 4 .or. hr1 == 10 .or. hr1 == 16 .or. hr1 == 22) then + fc_hr = 4 + else if (hr1 == 5 .or. hr1 == 11 .or. hr1 == 17 .or. hr1 == 23) then + fc_hr = 5 + end if + file_julhr = file_julhr - fc_hr + + found = .FALSE. + first_time = .true. + do while ( .not. found ) + + ! Make sure we start with the previous GALWEM cycle. + if ( (.not. first_time) .or. & + (first_time .and. fc_hr < 6)) then + fc_hr = fc_hr + 6 + if (fc_hr > 30) exit ! Give up + + file_julhr = file_julhr - 6 + call LIS_julhr_date(file_julhr,yr1,mo1,da1,hr1) + end if + first_time = .false. + + yr_2d = mod(yr1,100) + if(yr_2d.eq.0) yr_2d = 100 + + call AGRMET_getGALWEMfilename(avnfile, agrmet_struc(n)%agrmetdir,& + agrmet_struc(n)%galwemraddir, agrmet_struc(n)%use_timestamp,& + agrmet_struc(n)%galwem_res, yr1,mo1,da1,hr1,fc_hr) + +! ------------------------------------------------------------------ +! open first guess grib data using library utility. just read +! the first file only, as all data will be of the same type +! (avn or nogaps) because the search script ensures that it is. +! ------------------------------------------------------------------ + inquire(file=trim(avnfile),exist=found_inq) + if (.not. found_inq) then + write(LIS_logunit,*) '[WARN] Cannot find file '//trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = ' Cannot find file ' // trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + cycle + end if + +#if (defined USE_GRIBAPI) + + ! EMK...Before using ECCODES/GRIB_API, see if the GRIB file exists + ! using a simple inquire statement. This avoids ECCODES/GRIB_API + ! writing error messages to stdout/stderr, which may lead to runtime + ! problems. + + call grib_open_file(ftn,trim(avnfile),'r',ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Failed to open GALWEM radiation file ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = ' Cannot open file ' // trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + cycle + end if + + call grib_new_from_file(ftn,igrib,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Failed file read check '//trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = ' Failed to read field from ' // trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib,'centre',center,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grib_get: centre in ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = ' Failed to read centre from ' // trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + end if + + call grib_get(igrib,'gridType',gtype,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get: gridType in ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = ' Failed to read gridType from ' // trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib,'Ni',iginfo(1),ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:Ni in ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = ' Failed to read Ni from ' // trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib,'Nj',iginfo(2),ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:Nj in ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = ' Failed to read Nj from ' // trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib,'jDirectionIncrementInDegrees',gridres,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + 'error in grid_get:jDirectionIncrementInDegrees in ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = & + ' Failed to read jDirectionIncrementInDegrees from ' // & + trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib,'dataDate',dataDate,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:dataDate in ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = & + ' Failed to read dataDate from ' // & + trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib,'dataTime',dataTime,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:dataTime in ' // & + trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = & + ' Failed to read dataTime from ' // & + trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + if ( yr1*10000+mo1*100+da1 /= dataDate .or. & + hr1*100 /= dataTime ) then + write(LIS_logunit,*) & + '[WARN] Bad time found in ', trim(avnfile) + write(LIS_logunit,*) & + '[WARN] Found: ', dataDate, dataTime + write(LIS_logunit,*) & + '[WARN] Expected ', (yr1*10000+mo1*100+da1), & + (hr1*100) + flush(LIS_logunit) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = & + ' Bad date and time from ' // & + trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + if ( gtype /= "regular_ll" ) then + write(LIS_logunit,*) & + '[WARN] Did not find lat/long data in ', trim(avnfile) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_radflux_galwem.' + message(3) = & + ' Lat/lon grid not found in ' // & + trim(avnfile) + call LIS_alert( 'USAF_fldbld_radflux_galwem', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + cycle + endif + + call grib_release(igrib,ierr) + call grib_close_file(ftn) + +#else + write(LIS_logunit,*) '[ERR]: USAF_fldbld_radflux_galwem requires GRIB-API' + write(LIS_logunit,*) '[ERR]: please recompile LIS' + call LIS_endrun +#endif + + write(LIS_logunit,*) & + '[INFO] Using NWP Radiation fields from ',trim(avnfile) + rc = 0 + + write(LIS_logunit,*)'[INFO] FIRST GUESS DATA IS ON A ', gridres,& + ' DEGREE LAT/LON GRID' + ifguess = iginfo(1) + jfguess = iginfo(2) + + if (center .eq. 57) then + write(LIS_logunit,*) & + '[INFO] RADIATION DATA IS FROM UK UM (GALWEM) MODEL' + else + write(LIS_logunit,*)'[INFO] UNKNOWN SOURCE FOR RADIATION' + end if + +! ------------------------------------------------------------------ +! allocate first guess grid-specific variables. +! ------------------------------------------------------------------ + allocate ( fg_swdown1 (ifguess, jfguess) ) + allocate ( fg_lwdown1 (ifguess, jfguess) ) + +! ------------------------------------------------------------------ +! read in first guess data for this julian hour. +! ------------------------------------------------------------------ + call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& + fg_swdown1, fg_lwdown1, rc) + + if (rc /= 0) then + deallocate ( fg_swdown1 ) + deallocate ( fg_lwdown1 ) + cycle + end if + + ! Interpolate + call interp_galwem_first_guess(n, ifguess, jfguess, .true., & + fg_swdown1, fg_swdata) + call interp_galwem_first_guess(n, ifguess, jfguess, .true., & + fg_lwdown1, fg_lwdata) + deallocate ( fg_swdown1 ) + deallocate ( fg_lwdown1 ) + + ! At this point, we are done. + found = .true. + if (found) exit + + enddo ! Loop through cycles and forecast hours + + ! Give up if no acceptable GALWEM file was found + if (.not. found) then + write(LIS_logunit,*)'[WARN] No matching GALWEM Radiation file found!' + rc = 1 + return + end if + +end subroutine USAF_fldbld_radflux_galwem + + +!BOP +! +! !ROUTINE: USAF_fldbld_read_radflux_galwem +! \label{USAF_fldbld_read_radflux_galwem} +! +! !REVISION HISTORY: +! 11 Aug 2016 Initial specification based on AGRMET_fldbld_read_precip_gfs +! ...........................................James Geiger/NASA +! 29 May 2024 Added reading in GALWEM radiation fluxes +! ...........................................K. Arsenault/SAIC +! +! !INTERFACE: +subroutine USAF_fldbld_read_radflux_galwem(fg_filename, & + ifguess, jfguess, fg_swdown, fg_lwdown, rc ) + + ! !USES: + use LIS_coreMod, only : LIS_masterproc + use LIS_logMod, only : LIS_logunit, LIS_abort, LIS_alert, LIS_verify + +#if (defined USE_GRIBAPI) + use grib_api +#endif + + implicit none + +! !ARGUMENTS: + character(len=*), intent(in) :: fg_filename + integer, intent(in) :: ifguess + integer, intent(in) :: jfguess + real, intent(out) :: fg_swdown ( ifguess,jfguess ) + real, intent(out) :: fg_lwdown ( ifguess,jfguess ) + integer, intent(out) :: rc +! +! !DESCRIPTION: +! +! Read UK Unified Model (GALWEM) radiation data in GRIB-2 format. +! +! \textbf{Method} \newline +! +! - open file and allocate variables. \newline +! - read in each grib record. \newline +! - retrieve section 1 information. \newline +! - if data is what we need, store it in the proper arrays. \newline +! also, keep track of what has been read in using \newline +! counter variables. \newline +! - check forecast hour of data, if it is not the 3 or \newline +! or 6 hour forecast, then send an alert message \newline +! to warn of possible degradation. \newline +! - check counter variables. if data is missing abort. \newline +! +! +! \begin{description} +! \item[fg\_filename] +! name, including path, of the first guess file +! being read in +! \item[ifguess] +! east-west dimension of first guess grid +! \item[jfguess] +! north-south dimension of first guess grid +! \item[fg\_swdown] +! SWdown radiation flux read in from galwem file +! \item[fg\_lwdown] +! LWdown radiation flux read in from galwem file +! \item[alert\_number] +! counts number of alert messages sent +! \item[cstat] +! I/O status, character +! \item[message] +! Error message +! \item[count\_swdown] +! counts number of SWdown radiation flux +! levels read in from first guess file +! \item[count\_lwdown] +! counts number of LWdown radiation flux +! levels read in from first guess file +! \item[i,j,k] +! looping and indexing variables +! \item[ierr,istat1] +! error status +! \item[dum1d] +! dummy array +! \end{description} +! +!EOP + character(255) :: message(20) + integer, save :: alert_number = 1 + integer :: count_swdown + integer :: count_lwdown + integer :: ierr + integer :: k + integer :: ftn, igrib, nvars + integer :: param_disc_val, param_cat_val, & + param_num_val, forecasttime_val + real, allocatable :: dum1d ( : ) + logical :: found_inq + integer :: productDefinitionTemplateNumber + +! ------------------------------------------------------------------ + + rc = 0 + +! ------------------------------------------------------------------ +! read in grib file. +! ------------------------------------------------------------------ + + ! EMK...Before using ECCODES/GRIB_API, see if the GRIB file exists + ! using a simple inquire statement. This avoids ECCODES/GRIB_API + ! writing error messages to stdout/stderr, which may lead to runtime + ! problems. + + inquire(file=trim(fg_filename),exist=found_inq) + if (.not. found_inq) then + write(LIS_logunit,*)'[WARN] Cannot find ' // trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = ' Cannot find file ' // trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + rc = 1 + return + end if + +#if (defined USE_GRIBAPI) + call grib_open_file(ftn, trim(fg_filename), 'r', ierr) + if (ierr /= 0) then + write(LIS_logunit,*)'[WARN] Cannot open ' // trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = ' Cannot open file ' // trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + rc = 1 + return + end if + + write(LIS_logunit,*)' ' + write(LIS_logunit,*) & + '[INFO] Reading GALWEM radiation fluxes ' + write(LIS_logunit,*) trim(fg_filename) + + call grib_count_in_file(ftn, nvars, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Problem counting GRIB messages in ' //trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = ' Problem counting GRIB messages in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_close_file(ftn) + rc = 1 + return + end if + + allocate ( dum1d (ifguess*jfguess) ) + count_swdown = 0 + count_lwdown = 0 + + do k = 1, nvars + + call grib_new_from_file(ftn, igrib, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get GRIB message in ' // trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = ' Cannot get GRIB message in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + rc = 1 + exit + end if + + call grib_get(igrib, 'discipline', param_disc_val, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get discipline in ' // trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = ' Cannot read discipline in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_release(igrib, ierr) + rc = 1 + exit + end if + + call grib_get(igrib,'parameterCategory',param_cat_val,ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get parameterCategory in ' // & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = ' Cannot read parameterCategory in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_release(igrib, ierr) + rc = 1 + exit + end if + + call grib_get(igrib, 'parameterNumber', param_num_val, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get parameterNumber in ' // & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = ' Cannot read parameterNumber in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_release(igrib, ierr) + rc = 1 + exit + end if + + call grib_get(igrib, 'productDefinitionTemplateNumber', & + productDefinitionTemplateNumber, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get productDefinitionTemplateNumber in ' // & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = & + ' Cannot read productDefinitionTemplateNumber in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_release(igrib, ierr) + rc = 1 + exit + end if + + call grib_get(igrib, 'forecastTime', forecasttime_val, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get forecastTime in ' // & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = & + ' Cannot read forecastTime in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_release(igrib, ierr) + rc = 1 + exit + end if + + ! Instantaneous SW Down Radiation flux: + if ( param_disc_val == 0 .and. param_cat_val == 4 .and. & + param_num_val == 7 .and. & + productDefinitionTemplateNumber == 0) then + + call grib_get(igrib, 'values', dum1d, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get values in ' // & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = & + ' Cannot read values in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_release(igrib,ierr) + rc = 1 + exit + end if + fg_swdown = reshape(dum1d, (/ifguess,jfguess/)) + count_swdown = count_swdown + 1 + end if + + ! Instantaneous LW Down Radiation flux: + if ( param_disc_val == 0 .and. param_cat_val == 5 .and. & + param_num_val == 3 .and. & + productDefinitionTemplateNumber == 0) then + + call grib_get(igrib, 'values', dum1d, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot get values in ' // & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = & + ' Cannot read values in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + call grib_release(igrib, ierr) + rc = 1 + exit + end if + fg_lwdown = reshape(dum1d, (/ifguess,jfguess/)) + count_lwdown = count_lwdown + 1 + end if + + ! Done with this GRIB message + call grib_release(igrib, ierr) + if (ierr /= 0) then + write(LIS_logunit,*) & + '[WARN] Cannot release GRIB message from ' // & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = & + ' Cannot release GRIB message from ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + rc = 1 + exit + end if + + ! Break out of loop if we have what we need. + if (count_swdown > 0 .and. & + count_lwdown > 0) exit + enddo + + call grib_close_file(ftn) + + deallocate ( dum1d ) + +!------------------------------------------------------------------ +! See if we have everything. if not, abort. +!------------------------------------------------------------------ + + if (count_swdown == 0) then + write(LIS_logunit,*)'[WARN] Missing downward SW radiation in ', & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = & + ' Missing downward SW radiation in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + rc = 1 + end if + if (count_lwdown == 0) then + write(LIS_logunit,*)'[WARN] Missing downward LW radiation in ', & + trim(fg_filename) + if (LIS_masterproc) then + message(:) = '' + message(1) = '[WARN] Program: LIS' + message(2) = ' Routine USAF_fldbld_read_radflux_galwem.' + message(3) = & + ' Missing downward LW radiation in ' // & + trim(fg_filename) + call LIS_alert( 'USAF_fldbld_read_radflux_galwem.', & + alert_number, message) + alert_number = alert_number + 1 + end if + rc = 1 + end if + +#endif + +end subroutine USAF_fldbld_read_radflux_galwem diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 new file mode 100644 index 000000000..920b5242f --- /dev/null +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 @@ -0,0 +1,623 @@ +!-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- +! NASA Goddard Space Flight Center +! Land Information System Framework (LISF) +! Version 7.4 +! +! Copyright (c) 2022 United States Government as represented by the +! Administrator of the National Aeronautics and Space Administration. +! All Rights Reserved. +!-------------------------END NOTICE -- DO NOT EDIT----------------------- +#include "LIS_misc.h" + +subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & + fg_lwdata, rc) + + ! Imports + use AGRMET_forcingMod, only : agrmet_struc + use LIS_coreMod, only : LIS_rc + use LIS_logMod, only : LIS_logunit, LIS_abort, LIS_alert, & + LIS_verify, LIS_endrun + use LIS_timeMgrMod, only : LIS_julhr_date +#if (defined USE_GRIBAPI) + use grib_api +#endif + + ! Defaults + implicit none + + ! Arguments + integer, intent(in) :: n + integer, intent(in) :: julhr + real, intent(out) :: fg_swdata(LIS_rc%lnc(n), LIS_rc%lnr(n)) + real, intent(out) :: fg_lwdata(LIS_rc%lnc(n), LIS_rc%lnr(n)) + integer, intent(out):: rc + + ! Locals + integer :: ftn, ftn2 + integer :: igrib, igrib2 + character*250 :: avnfile, avnfile2 + integer :: yr1, mo1, da1, hr1 + integer :: fc_hr + character*255 :: message ( 20 ) + integer :: iginfo(2), iginfo2(2) + real :: gridres, gridres2 + integer :: alert_number + real, allocatable :: fg_swdown1(:,:), fg_swdown2(:,:) + real, allocatable :: fg_lwdown1(:,:), fg_lwdown2(:,:) + integer :: ifguess, ifguess2 + integer :: jfguess, jfguess2 + integer :: center, center2 + integer :: ierr, ierr2 + logical*1 :: found, found2 + logical :: first_time + integer :: yr_2d + integer :: file_julhr + integer :: dataDate, dataDate2 + integer :: dataTime, dataTime2 + character*100 :: gtype, gtype2 + logical :: found_inq, found_inq2 + integer :: getsixhr + + ! External subroutines + external :: AGRMET_fg2lis + external :: getAVNfilename, getAVNfilename2 + external :: USAF_fldbld_read_radflux_gfs + + ! Initialize return code to "no error". We will change it below if + ! necessary. + rc = 0 + + ! Will search previous GFS cycles every six hours, up to 30 hours, + ! until we find an acceptable file. + fc_hr = 0 ! Incremented below + file_julhr = julhr ! Decremented below + call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) + + ! GFS is only available 3-hrly in NCEI archive, so we will use that here. + ! Also, files contain time averaged radiation, with the time average + ! *ending* at the forecast hour. This creates an eastward bias in the + ! position of the Sun. We account for that here. + if (hr1 == 0 .or. hr1 == 6 .or. hr1 == 12 .or. hr1 == 18) then + fc_hr = 9 + file_julhr = file_julhr - 6 + else if (hr1 == 1 .or. hr1 == 7 .or. hr1 == 13 .or. hr1 == 19) then + fc_hr = 9 + file_julhr = file_julhr - 7 + else if (hr1 == 2 .or. hr1 == 8 .or. hr1 == 14 .or. hr1 == 20) then + fc_hr = 9 + file_julhr = file_julhr - 8 + else if (hr1 == 3 .or. hr1 == 9 .or. hr1 == 15 .or. hr1 == 21) then + fc_hr = 12 + file_julhr = file_julhr - 9 + else if (hr1 == 4 .or. hr1 == 10 .or. hr1 == 16 .or. hr1 == 22) then + fc_hr = 12 + file_julhr = file_julhr - 10 + else if (hr1 == 5 .or. hr1 == 11 .or. hr1 == 17 .or. hr1 == 23) then + fc_hr = 12 + file_julhr = file_julhr - 11 + end if + + ! Some GFS files have 6-hr time averages of radiation instead of 3-hr. + ! This requires taking a weighted difference to estimate the most + ! recent 3-hr time average. (Equivalent to multiplying average values + ! by 6 or 3 hours to get "accumulations", differencing the + ! "accumulations", and then dividing by 3 hours.) + if (mod(fc_hr,12) .eq. 0) then + getsixhr = 1 + found2 = .false. + else + getsixhr = 0 + found2 = .true. + end if + call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) + + found = .false. + first_time = .true. + do while ( .not. found ) + + ! Make sure we start with the previous GFS cycle. + if ( (.not. first_time) .or. & + (first_time .and. fc_hr < 6)) then + fc_hr = fc_hr + 6 + if (fc_hr > 30) exit ! Give up + file_julhr = file_julhr - 6 + call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) + end if + first_time = .false. + + yr_2d = mod(yr1, 100) + if (yr_2d == 0) yr_2d = 100 + + call getAVNfilename(avnfile, agrmet_struc(n)%agrmetdir,& + agrmet_struc(n)%gfsdir, agrmet_struc(n)%use_timestamp,& + agrmet_struc(n)%gfs_timestamp, & + agrmet_struc(n)%gfs_filename_version, & + yr1, mo1, da1, hr1, fc_hr) + if (getsixhr.eq.1) then + call getAVNfilename(avnfile2, agrmet_struc(n)%agrmetdir,& + agrmet_struc(n)%gfsdir, agrmet_struc(n)%use_timestamp,& + agrmet_struc(n)%gfs_timestamp, & + agrmet_struc(n)%gfs_filename_version, & + yr1, mo1, da1, hr1, fc_hr-3) + end if + + ! See if the GRIB file exists before calling ECCODES. + inquire(file=trim(avnfile), exist=found_inq) + if (.not. found_inq) then + write(LIS_logunit,*) '[WARN] Cannot find file ' // trim(avnfile) + cycle + end if + if (getsixhr .eq. 1) then + inquire(file=trim(avnfile2), exist=found_inq2) + if (.not. found_inq2) then + write(LIS_logunit,*) & + '[WARN] Cannot find file ' // trim(avnfile2) + cycle + end if + end if + +#if (defined USE_GRIBAPI) + call grib_open_file(ftn, trim(avnfile), 'r', ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed to open first guess - ', & + trim(avnfile) + flush(LIS_logunit) + call grib_close_file(ftn) + cycle + end if + if (getsixhr .eq. 1) then + call grib_open_file(ftn2, trim(avnfile2), 'r', ierr2) + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed to open first guess - ', & + trim(avnfile2) + call grib_close_file(ftn2) + flush(LIS_logunit) + cycle + end if + end if + + ! Extract some information + call grib_new_from_file(ftn, igrib, ierr) + ierr2 = 0 + if (getsixhr .eq. 1) call grib_new_from_file(ftn2, igrib2, ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed file read check - ' // & + trim(avnfile) + flush(LIS_logunit) + end if + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed file read check - ' // & + trim(avnfile2) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if (getsixhr .eq. 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + end if + cycle + endif + + call grib_get(igrib, 'centre', center, ierr) + ierr2 = 0 + if (getsixhr .eq. 1) call grib_get(igrib2, 'centre', center2, ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: centre in ' // & + trim(avnfile) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: centre in ' // & + trim(avnfile2) + flush(LIS_logunit) + end if + if (getsixhr == 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + endif + cycle + endif + + call grib_get(igrib, 'gridType', gtype, ierr) + ierr2 = 0 + if (getsixhr .eq. 1) call grib_get(igrib2, 'gridType', gtype2, ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: gridType in ' // & + trim(avnfile) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: gridType in ' // & + trim(avnfile2) + flush(LIS_logunit) + end if + if (getsixhr == 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + end if + cycle + end if + + call grib_get(igrib, 'Ni', iginfo(1), ierr) + ierr2 = 0 + if (getsixhr == 1) call grib_get(igrib2, 'Ni', iginfo2(1), ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: Ni in ' // & + trim(avnfile) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if (ierr2 /= 0) then + write(LIS_logunit,*) '[WARN] Cannot read: Ni in ' // & + trim(avnfile2) + flush(LIS_logunit) + end if + if (getsixhr == 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + end if + cycle + end if + + call grib_get(igrib, 'Nj', iginfo(2), ierr) + ierr2 = 0 + if (getsixhr == 1) call grib_get(igrib2, 'Nj', iginfo2(2), ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: Nj in ' // & + trim(avnfile) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: Nj in ' // & + 'USAF_fldbld_radflux_gfs' + flush(LIS_logunit) + end if + if (getsixhr == 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + endif + cycle + end if + + + call grib_get(igrib, 'jDirectionIncrementInDegrees', gridres, & + ierr) + ierr2 = 0 + if (getsixhr == 1) call grib_get(igrib2, & + 'jDirectionIncrementInDegrees', gridres2, ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: jDirectionIncrementInDegrees in ' // & + trim(avnfile) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: jDirectionIncrementInDegrees in ' // & + trim(avnfile2) + flush(LIS_logunit) + end if + if (getsixhr == 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + endif + cycle + end if + + call grib_get(igrib, 'dataDate', dataDate, ierr) + ierr2 = 0 + if (getsixhr == 1) call grib_get(igrib2, 'dataDate', dataDate2, ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: dataDate in ' // & + trim(avnfile) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: dataDate in ' // & + trim(avnfile2) + flush(LIS_logunit) + end if + if (getsixhr == 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + endif + cycle + end if + + call grib_get(igrib, 'dataTime', dataTime, ierr) + ierr2 = 0 + if (getsixhr == 1) call grib_get(igrib2, 'dataTime', dataTime2, ierr2) + if (ierr /= 0 .or. ierr2 /= 0) then + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: dataTime in ' // & + trim(avnfile) + flush(LIS_logunit) + end if + call grib_release(igrib, ierr) + call grib_close_file(ftn) + if ( ierr2 /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: dataTime in ' // & + trim(avnfile2) + flush(LIS_logunit) + end if + if (getsixhr == 1) then + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + end if + cycle + end if + + if ( yr1*10000+mo1*100+da1 == dataDate .and. & + hr1*100 == dataTime ) then + found = .TRUE. + if ( gtype /= "regular_ll" ) then + message(1) = 'program: LIS' + message(2) = ' Subroutine: USAF_fldbld_radflux_gfs' + message(3) = ' First guess source is not a lat/lon grid' + message(4) = ' USAF_fldbld_radflux_gfs expects lat/lon data' + call lis_abort(message) + endif + endif + call grib_release(igrib, ierr) + call grib_close_file(ftn) + + if (getsixhr == 1) then + if ( yr1*10000+mo1*100+da1 == dataDate2 .and. & + hr1*100 == dataTime2 ) then + found2 = .TRUE. + if ( gtype2 /= "regular_ll" ) then + message(1) = 'program: LIS' + message(2) = ' Subroutine: USAF_fldbld_radflux_gfs' + message(3) = ' First guess source is not a lat/lon grid' + message(4) = ' USAF_fldbld_radflux_gfs expects lat/lon data' + call lis_abort(message) + endif + endif + call grib_release(igrib2, ierr2) + call grib_close_file(ftn2) + end if + + ! Make sure grids match + if (getsixhr == 1) then + if ((iginfo(1) .ne. iginfo2(1)) .or. & + (iginfo(2) .ne. iginfo2(2)) .or. & + (gridres .ne. gridres2) .or. & + (center .ne. center2)) then + write(LIS_logunit,*) '[ERR]: Grid mismatch between ', & + trim(avnfile), ' and ', trim(avnfile2) + message(1) = 'program: LIS' + message(2) = ' Subroutine: USAF_fldbld_radflux_gfs' + message(3) = ' First guess source is not a lat/lon grid' + message(4) = ' USAF_fldbld_radflux_gfs expects lat/lon data' + call lis_abort(message) + end if + end if + +#else + write(LIS_logunit,*) '[ERR]: USAF_fldbld_radflux_gfs requires GRIB-API' + write(LIS_logunit,*) '[ERR]: please recompile LIS' + call LIS_endrun +#endif + + ! At this point, we have everything we need. + found = .true. + if (found) exit + end do ! Loop through cycles and forecast hours + + ! Give up if no acceptable GFS file was found + if (.not. found) then + write(LIS_logunit,*)'[WARN] No matching GFS Radiation file found!' + rc = 1 + return + end if + + write(LIS_logunit,*) & + '[INFO] Using time-averaged NWP Radiation fields from ',trim(avnfile) + if (getsixhr == 1) then + write(LIS_logunit,*) & + '[INFO] Also using NWP Radiation fields from ',trim(avnfile2) + end if + rc = 0 + + if (center == 7) then + write(LIS_logunit,*) '[INFO] Data are from GFS model' + end if + + write(LIS_logunit,*)'[INFO] GFS RADIATION DATA ARE ON A ', gridres,& + ' DEGREE LAT/LON GRID' + ifguess = iginfo(1) + jfguess = iginfo(2) + allocate ( fg_swdown1 (ifguess, jfguess) ) + allocate ( fg_lwdown1 (ifguess, jfguess) ) + + if (getsixhr == 1) then + ifguess2 = iginfo2(1) + jfguess2 = iginfo2(2) + allocate ( fg_swdown2 (ifguess2, jfguess2) ) + allocate ( fg_lwdown2 (ifguess2, jfguess2) ) + end if + + ! Get radiation for this julian hour + alert_number = 0 + call USAF_fldbld_read_radflux_gfs(avnfile, ifguess, jfguess, & + fg_swdown1, fg_lwdown1, alert_number) + if (getsixhr == 1) then + call USAF_fldbld_read_radflux_gfs(avnfile2, ifguess2, jfguess2, & + fg_swdown2, fg_lwdown2, alert_number) + end if + + ! Estimate time-averaged radiation from last 3 hours. + ! Some GFS files have 6-hr time averages of radiation instead of 3-hr. + ! This requires taking a weighted difference to estimate the most + ! recent 3-hr time average. (Equivalent to multiplying average values + ! by 6 or 3 hours to get "accumulations", differencing the + ! "accumulations", and then dividing by 3 hours.) + if (getsixhr == 1) then + write(LIS_logunit,*) & + '[INFO] Estimating 3-hr time averaged radiation...' + fg_swdown1 = 2*fg_swdown1 - fg_swdown2 + fg_lwdown1 = 2*fg_lwdown1 - fg_lwdown2 + end if + + ! Interpolate to the LIS grid + call AGRMET_fg2lis(n, ifguess, jfguess, fg_swdown1, fg_swdata) + call AGRMET_fg2lis(n, ifguess, jfguess, fg_lwdown1, fg_lwdata) + + ! Clean up + deallocate(fg_swdown1) + deallocate(fg_lwdown1) + if (getsixhr == 1) then + deallocate(fg_swdown2) + deallocate(fg_lwdown2) + end if + +end subroutine USAF_fldbld_radflux_gfs + +subroutine USAF_fldbld_read_radflux_gfs(fg_filename, ifguess, jfguess, & + fg_swdown, fg_lwdown, alert_number ) + + ! Imports + use LIS_logMod, only : LIS_logunit, LIS_abort, LIS_alert, LIS_verify +#if (defined USE_GRIBAPI) + use grib_api +#endif + + ! Defaults + implicit none + + ! Arguments + character(len=*), intent(in) :: fg_filename + integer, intent(in) :: ifguess + integer, intent(in) :: jfguess + real, intent(out) :: fg_swdown (ifguess,jfguess) + real, intent(out) :: fg_lwdown (ifguess,jfguess) + integer, intent(inout) :: alert_number + + ! Locals + character*255 :: message ( 20 ) + integer :: count_swdown + integer :: count_lwdown + integer :: ierr + integer :: k + integer :: ftn, igrib, nvars + integer :: param_disc_val, param_cat_val, & + param_num_val + real, allocatable :: dum1d ( : ) + logical :: found_inq + + ! Make sure file exists before opening with GRIB_API + inquire(file=trim(fg_filename), exist=found_inq) + if (.not. found_inq) then + ierr = 1 + else + ierr = 0 + end if + call LIS_verify(ierr, '[ERR] FILE NOT FOUND - ' // trim(fg_filename)) + +#if (defined USE_GRIBAPI) + call grib_open_file(ftn, trim(fg_filename), 'r', ierr) + call LIS_verify(ierr,'[ERR] Failed to open in read routine - ' // & + trim(fg_filename)) + + if ( ierr == 0 ) then + allocate ( dum1d (ifguess*jfguess) ) + count_swdown = 0 + count_lwdown = 0 + + write(LIS_logunit,*)' ' + write(LIS_logunit,*) & + '[INFO] Reading time-averaged GFS radiation fluxes' + write(LIS_logunit,*) trim(fg_filename) + + call grib_count_in_file(ftn, nvars, ierr) + call LIS_verify(ierr, 'error in grib_count_in_file in ' // & + 'USAF_fldbld_read_radflux_gfs') + + do k = 1, nvars + call grib_new_from_file(ftn, igrib, ierr) + call LIS_verify(ierr, & + '[ERR] failed to read - '// trim(fg_filename)) + + call grib_get(igrib, 'discipline', param_disc_val, ierr) + call LIS_verify(ierr, & + 'error in grib_get: parameterNumber in ' // & + 'USAF_fldbld_read_radflux_gfs') + + call grib_get(igrib, 'parameterCategory', param_cat_val, ierr) + call LIS_verify(ierr, & + 'error in grib_get: parameterCategory in ' // & + 'USAF_fldbld_read_radflux_gfs') + + call grib_get(igrib, 'parameterNumber', param_num_val, ierr) + call LIS_verify(ierr, & + 'error in grib_get: parameterNumber in ' // & + 'USAF_fldbld_read_radflux_gfs') + + ! SW Down Radiation flux: + if ( param_disc_val == 0 .and. param_cat_val == 4 .and. & + param_num_val == 192 ) then + + call grib_get(igrib, 'values', dum1d, ierr) + call LIS_verify(ierr, & + 'error in grib_get: SWdown values in ' // & + 'USAF_fldbld_read_radflux_gfs') + fg_swdown = reshape(dum1d, (/ifguess,jfguess/)) + count_swdown = count_swdown + 1 + end if + + ! LW Down Radiation flux: + if ( param_disc_val == 0 .and. param_cat_val == 5 .and. & + param_num_val == 192 ) then + call grib_get(igrib,'values',dum1d,ierr) + call LIS_verify(ierr, & + 'error in grib_get: LWdown values in ' // & + 'USAF_fldbld_read_radflux_gfs') + fg_lwdown = reshape(dum1d, (/ifguess,jfguess/)) + count_lwdown = count_lwdown + 1 + end if + + call grib_release(igrib, ierr) + end do ! k + + call grib_close_file(ftn) + + deallocate( dum1d) + + ! See if we have everything. If not, abort. + if ( count_swdown == 0 .or. count_lwdown == 0 ) then + message(1) = 'Program: LIS' + message(2) = ' Subroutine: USAF_fldbld_read_radflux_gfs.' + message(3) = ' Error reading first guess file:' + message(4) = ' ' // trim(fg_filename) + message(5) = ' File does not contain all data that fldbld needs.' + if ( allocated(dum1d) ) deallocate(dum1d) + call LIS_abort( message) + endif + end if +#endif + +end subroutine USAF_fldbld_read_radflux_gfs + diff --git a/lis/metforcing/usaf/get_agrmet.F90 b/lis/metforcing/usaf/get_agrmet.F90 index 00a2d2d72..1978d4755 100644 --- a/lis/metforcing/usaf/get_agrmet.F90 +++ b/lis/metforcing/usaf/get_agrmet.F90 @@ -44,10 +44,10 @@ subroutine get_agrmet(n, findex) ! The strategy for missing data is to go backwards up to 10 days to get ! forcing at the same time of day. This entry point code also ! calls different routines based on the running mode. The AGRMET -! mode will generate the surface analysis, merged precipitaition, +! mode will generate the surface analysis, merged precipitation, ! whereas the analysis mode will simply use the previously generated ! data. -!. +! ! The arguments are: ! \begin{description} ! \item[n] diff --git a/lis/metforcing/usaf/readagrmetforcing.F90 b/lis/metforcing/usaf/readagrmetforcing.F90 index 2025fd88c..33b226395 100644 --- a/lis/metforcing/usaf/readagrmetforcing.F90 +++ b/lis/metforcing/usaf/readagrmetforcing.F90 @@ -25,20 +25,24 @@ ! 13Dec2007: Marv Freimund, Do NOT abort for missing 10 files ! 31Dec2007: Marv Freimund, simplify file creation code; use trim on filenames ! 1 Aug2008: Switched processing from PS to a generic cartesian grid with -! built-in implicit parallelism -! 10 MAR 2010 Added some variables to pass in calls to interp_agrmet, loadcloud, +! built-in implicit parallelism +! 10MAR2010: Added some variables to pass in calls to interp_agrmet, loadcloud, ! tr_coeffs.................................Michael Shaw/WXE +! 28MAY2024: Implemented GALWEM / GFS radiation flux options ... K. Arsenault/SAIC ! ! !INTERFACE: subroutine readagrmetforcing(n,findex, order) ! !USES: - use LIS_coreMod, only : LIS_rc, LIS_domain, LIS_localPet + use LIS_coreMod, only : LIS_rc, LIS_domain, LIS_localPet, & + LIS_masterproc use LIS_timeMgrMod,only : LIS_get_julhr,LIS_tick,LIS_time2date use LIS_LMLCMod, only : LIS_LMLC use LIS_albedoMod, only : LIS_alb use LIS_vegDataMod, only : LIS_gfrac use LIS_snowMod, only : LIS_snow_struc use LIS_logMod, only : LIS_logunit + use LIS_logMod, only : LIS_logunit, LIS_abort, LIS_endrun, & + LIS_alert use AGRMET_forcingMod, only : agrmet_struc use LIS_mpiMod @@ -193,24 +197,28 @@ subroutine readagrmetforcing(n,findex, order) real,allocatable :: rlh(:,:) integer :: ip integer :: julhr - real,allocatable :: cldamt(:,:,:) - integer,allocatable :: cldamt_nh( :,:,:) - integer,allocatable :: cldtyp_nh( :,:,:) - integer,allocatable :: cldamt_sh( :,:,:) - integer,allocatable :: cldtyp_sh( :,:,:) - logical,allocatable :: fog_nh( :,:) - logical,allocatable :: fog_sh( :,:) + character(len=255) :: message(20) + + real,allocatable :: cldamt(:,:,:) + integer,allocatable :: cldamt_nh( :,:,:) + integer,allocatable :: cldtyp_nh( :,:,:) + integer,allocatable :: cldamt_sh( :,:,:) + integer,allocatable :: cldtyp_sh( :,:,:) + logical,allocatable :: fog_nh( :,:) + logical,allocatable :: fog_sh( :,:) integer :: thres(5) !needs to be read in. real :: q2sat real :: e,esat real :: udef integer :: doy1,yr1,mo1,da1,hr1,mn1,ss1,try + integer :: istart + integer :: julend real*8 :: backtime1 real :: gmt1,ts1 logical :: fog, bare - real,allocatable :: albedo(:) - real,allocatable :: albedo_tmp(:) - integer,allocatable :: ncount(:) + real,allocatable :: albedo(:) + real,allocatable :: albedo_tmp(:) + integer,allocatable :: ncount(:) real :: snup(24) integer :: dindex @@ -234,15 +242,16 @@ subroutine readagrmetforcing(n,findex, order) .040, .080, .080, .080, .080, .080, .080, .080, & .040, .080, .025, .040, .040, .040, .025, .025/ - data THRES /12600, 12300, 12000, 11700, 11400/ +! ___________________________________________________________ TRACE_ENTER("agrmet_readforc") - allocate(longwv(LIS_rc%lnc(n), LIS_rc%lnr(n))) allocate(varfield(LIS_rc%lnc(n),LIS_rc%lnr(n))) allocate(tair(LIS_rc%lnc(n),LIS_rc%lnr(n))) allocate(psurf(LIS_rc%lnc(n), LIS_rc%lnr(n))) allocate(rlh(LIS_rc%lnc(n),LIS_rc%lnr(n))) + allocate(longwv(LIS_rc%lnc(n), LIS_rc%lnr(n))) + allocate(swdown(LIS_rc%lnc(n),LIS_rc%lnr(n))) allocate(coszen_ps(2,agrmet_struc(n)%imax,agrmet_struc(n)%jmax)) allocate(coszen(LIS_rc%lnc(n),LIS_rc%lnr(n))) @@ -270,7 +279,8 @@ subroutine readagrmetforcing(n,findex, order) allocate(t1_ps(2,agrmet_struc(n)%imax,agrmet_struc(n)%jmax)) allocate(t2_ps(2,agrmet_struc(n)%imax,agrmet_struc(n)%jmax)) allocate(t3_ps(2,agrmet_struc(n)%imax,agrmet_struc(n)%jmax)) - else + + elseif ( agrmet_struc(n)%compute_radiation == 'cod properties' ) then allocate(cod(3, LIS_rc%lnc(n), LIS_rc%lnr(n))) endif @@ -278,17 +288,21 @@ subroutine readagrmetforcing(n,findex, order) allocate(albedo_tmp(LIS_rc%ntiles(n))) allocate(ncount(LIS_rc%ngrid(n))) + ! AGRMET SFCALC: Main routine that generates the surface fields: + ! temperature, pressure, winds and relative humidity + ! Calls to model background fields (e.g., GALWEM, GFS) + ! are also made within this main routine. call AGRMET_sfcalc(n) call find_agrsfc_dataindex(LIS_rc%hr,dindex) - ! open(100,file='tmp.bin',form='unformatted') ! write(100) agrmet_struc(n)%sfctmp(dindex,:,:) ! close(100) ! print*, 'Finished with SFCALC ' ! stop + if(LIS_rc%run_model) then tair = agrmet_struc(n)%sfctmp(dindex,:,:) @@ -315,6 +329,7 @@ subroutine readagrmetforcing(n,findex, order) ! print*,'EMK: minval(agrmet_struc(n)%sfcrlh(dindex,:,:) = ', & ! minval(agrmet_struc(n)%sfcrlh(dindex,:,:)) + ! Humidity field: do c =1, LIS_rc%lnc(n) do r = 1,LIS_rc%lnr(n) if (LIS_domain(n)%gindex(c,r).ne. -1) then @@ -334,13 +349,6 @@ subroutine readagrmetforcing(n,findex, order) enddo enddo - if ( agrmet_struc(n)%compute_radiation == 'cloud types' ) then - call compute_type_based_clouds(n, cldamt_nh, cldamt_sh, cldamt, & - cldtyp_nh, cldtyp_sh, fog_nh, fog_sh) - else - call compute_cod_based_clouds(n, cod, cldamt) - endif - yr1 = LIS_rc%yr mo1 = LIS_rc%mo da1 = LIS_rc%da @@ -348,21 +356,44 @@ subroutine readagrmetforcing(n,findex, order) mn1 = LIS_rc%mn ss1 = LIS_rc%ss - do r=1,LIS_rc%lnr(n) - do c=1,LIS_rc%lnc(n) + ! Downward Longwave + Shortwave Radiation, read in from GALWEM / GFS: + ! -- KRA: Initial setup + if ( agrmet_struc(n)%compute_radiation == 'GALWEM_RAD' ) then + + ! Call to the NWP Radiation Flux main routines: + ! Target fields: swdown(lnc,lnr), longwv(lnc,lnr) + call USAF_fldbld_radflux(n,swdown,longwv) + + endif + + ! Read in cloud amount, type or COD information: + if ( agrmet_struc(n)%compute_radiation == 'cloud types' ) then + call compute_type_based_clouds(n, cldamt_nh, cldamt_sh, cldamt, & + cldtyp_nh, cldtyp_sh, fog_nh, fog_sh) + elseif ( agrmet_struc(n)%compute_radiation == 'cod properties' ) then + call compute_cod_based_clouds(n, cod, cldamt) + endif + + ! Downward Longwave Radiation calculation, based on cloud amounts: + if ( agrmet_struc(n)%compute_radiation .ne. 'GALWEM_RAD' ) then + do r=1,LIS_rc%lnr(n) + do c=1,LIS_rc%lnc(n) ! EMK...Calculate for all valid grid indices ! if(LIS_LMLC(n)%landmask(c,r).eq.1) then if ( LIS_domain(n)%gindex(c,r) /= -1 ) then - call AGRMET_svp(q2sat,esat,& - psurf(c,r), tair(c,r)) + call AGRMET_svp(q2sat, esat, & + psurf(c,r), tair(c,r)) e = esat*rlh(c,r) - call AGRMET_longwv(tair(c,r),e,cldamt(:,c,r),longwv(c,r)) + call AGRMET_longwv(tair(c,r), e, cldamt(:,c,r),& + longwv(c,r)) else longwv(c,r) = LIS_rc%udef endif - enddo - enddo + enddo + enddo + endif + ! Downward Longwave Radiation: write out final field to metdata array: do r=1,LIS_rc%lnr(n) do c=1,LIS_rc%lnc(n) if(LIS_domain(n)%gindex(c,r).ne.-1) then @@ -371,6 +402,7 @@ subroutine readagrmetforcing(n,findex, order) enddo enddo + ! Surface albedo: Preparing for effects on solar radiation field fog = .false. if(agrmet_struc(n)%findtime1.eq.1.and.agrmet_struc(n)%findtime2.eq.1) then #if 0 @@ -378,11 +410,11 @@ subroutine readagrmetforcing(n,findex, order) do c=1,LIS_rc%lnc(n) if(LIS_domain(n)%gindex(c,r).ne.-1) then t = LIS_domain(n)%gindex(c,r) -! The snup value is looked up from a table based on the vegtype. -! This is a little tricky when subgrid tiling is used since each tile -! in a gridcell has a different vegtype. For now proceeding with a -! simple 1st tile lookup. -! + ! The snup value is looked up from a table based on the vegtype. + ! This is a little tricky when subgrid tiling is used since each tile + ! in a gridcell has a different vegtype. For now proceeding with a + ! simple 1st tile lookup. + ! if (LIS_domain(n)%tile(t)%vegt .eq. LIS_rc%bareclass .or. & LIS_domain(n)%tile(t)%vegt .eq. LIS_rc%urbanclass .or. & LIS_domain(n)%tile(t)%vegt .eq. LIS_rc%snowclass) then @@ -401,6 +433,7 @@ subroutine readagrmetforcing(n,findex, order) enddo LIS_alb(n)%albedo(:) = albedo(:) #endif + ! Calculate surface albedo: do t=1,LIS_rc%ntiles(n) sftype = LIS_domain(n)%tile(t)%sftype if(sftype.eq.1) then @@ -418,9 +451,9 @@ subroutine readagrmetforcing(n,findex, order) snup(LIS_domain(n)%tile(t)%vegt),& agrmet_struc(n)%salp, bare) else -!ocean - set a fixed albedo -!for small zenith angle 0.03-0.10 -! for large zenith angle 0.10 -1.0 + ! Ocean - set a fixed albedo + ! for small zenith angle 0.03-0.10 + ! for large zenith angle 0.10 -1.0 albedo_tmp(t) = 0.10 endif enddo @@ -447,6 +480,11 @@ subroutine readagrmetforcing(n,findex, order) endif enddo + ! Downward Shortwave Radiation Field estimates: + + ! WWMCA Cloud properties used to derive solar downward radiation fields: + !write(LIS_logunit,*)'EMK2: maxval(swdown) = ', maxval(swdown) + !write(LIS_logunit,*)'EMK2: maxval(longwv) = ', maxval(longwv) if ( agrmet_struc(n)%compute_radiation == 'cloud types' ) then r1_ps = 0.0 @@ -493,7 +531,10 @@ subroutine readagrmetforcing(n,findex, order) call interp_agrmetvar(n,ip,t3_ps,0.0,t3,agrmet_struc(n)%imax,agrmet_struc(n)%jmax) call interp_agrmetvar(n,ip,coszen_ps,-1.0,coszen,agrmet_struc(n)%imax,agrmet_struc(n)%jmax) - else + + ! COD-based routines used for deriving solar downward radiation fields: + elseif ( agrmet_struc(n)%compute_radiation == 'cod properties' ) then + call compute_tr_from_cod(n, t1, r1, cod(1,:,:)) call compute_tr_from_cod(n, t2, r2, cod(2,:,:)) call compute_tr_from_cod(n, t3, r3, cod(3,:,:)) @@ -533,10 +574,14 @@ subroutine readagrmetforcing(n,findex, order) endwhere endif - allocate(swdown(LIS_rc%lnc(n),LIS_rc%lnr(n))) + !write(LIS_logunit,*)'EMK3: maxval(swdown) = ', maxval(swdown) + !write(LIS_logunit,*)'EMK3: maxval(longwv) = ', maxval(longwv) + + ! Downward Shortwave Radiation - Calculation from cloud data: + if ( agrmet_struc(n)%compute_radiation .ne. 'GALWEM_RAD' ) then + do r=1,LIS_rc%lnr(n) + do c=1,LIS_rc%lnc(n) - do r=1,LIS_rc%lnr(n) - do c=1,LIS_rc%lnc(n) if ( LIS_domain(n)%gindex(c,r) /= -1 ) then t = LIS_domain(n)%gindex(c,r) if(r1(c,r).eq.LIS_rc%udef) r1(c,r) = 0.0 @@ -553,9 +598,15 @@ subroutine readagrmetforcing(n,findex, order) else swdown(c,r) = LIS_rc%udef endif - enddo - enddo + enddo + enddo + endif + + !write(LIS_logunit,*)'EMK4: maxval(swdown) = ', maxval(swdown) + !write(LIS_logunit,*)'EMK4: maxval(longwv) = ', maxval(longwv) + + ! Downward Shortwave Radiation: write out final field to metdata array: do r=1,LIS_rc%lnr(n) do c=1,LIS_rc%lnc(n) if(LIS_domain(n)%gindex(c,r).ne.-1) then @@ -597,7 +648,7 @@ subroutine readagrmetforcing(n,findex, order) deallocate(t1_ps) deallocate(t2_ps) deallocate(t3_ps) - else + elseif ( agrmet_struc(n)%compute_radiation == 'cod properties' ) then deallocate(cod) endif @@ -607,6 +658,7 @@ subroutine readagrmetforcing(n,findex, order) end if TRACE_EXIT("agrmet_readforc") end subroutine readagrmetforcing + !BOP ! ! !ROUTINE: agrmet_cdfs_pcts_filename diff --git a/lis/metforcing/usaf/readcrd_agrmet.F90 b/lis/metforcing/usaf/readcrd_agrmet.F90 index ebac8311a..debd77669 100644 --- a/lis/metforcing/usaf/readcrd_agrmet.F90 +++ b/lis/metforcing/usaf/readcrd_agrmet.F90 @@ -508,11 +508,31 @@ subroutine readcrd_agrmet() call ESMF_ConfigGetAttribute(LIS_config,agrmet_struc(n)%retroFileRoot,rc=rc) enddo + ! KRA/EMK 4 Jun 2024 New AGRMET radiation option call ESMF_ConfigFindLabel(LIS_config,"AGRMET radiation derived from:",rc=rc) + call LIS_verify(rc, & + '[ERR] AGRMET radiation derived from: option not specified in the config file') do n=1,LIS_rc%nnest - call ESMF_ConfigGetAttribute(LIS_config,agrmet_struc(n)%compute_radiation,default="cloud types", rc=rc) + call ESMF_ConfigGetAttribute(LIS_config, & + agrmet_struc(n)%compute_radiation, rc=rc) + call LIS_verify(rc, & + '[ERR] AGRMET radiation derived from: option not specified in the config file') + if (agrmet_struc(n)%compute_radiation .ne. "cloud types" .and. & + agrmet_struc(n)%compute_radiation .ne. "cod properties" .and. & + agrmet_struc(n)%compute_radiation .ne. "GALWEM_RAD") then + call LIS_verify(1, & + '[ERR] AGRMET radiation derived from: invalid option, must be "cloud types", "cod properties", or "GALWEM_RAD"') + end if enddo +! KRA/EMK 4 Jun 2024 GALWEM RADIATION FILE READER: + call ESMF_ConfigFindLabel(LIS_config,"AGRMET GALWEM radiation data directory:",rc=rc) + do n=1,LIS_rc%nnest + call ESMF_ConfigGetAttribute(LIS_config,agrmet_struc(n)%galwemraddir,rc=rc) + enddo + + + call ESMF_ConfigGetAttribute(LIS_config,LIS_rc%security_class,& label="AGRMET security classification:",rc=rc) diff --git a/lis/utils/usaf/s2s/for_discover/lis/lis.config.s2sglobal.noahmp401_12mem.hymap2.DARun b/lis/utils/usaf/s2s/for_discover/lis/lis.config.s2sglobal.noahmp401_12mem.hymap2.DARun index 52fe644f6..82bf188df 100755 --- a/lis/utils/usaf/s2s/for_discover/lis/lis.config.s2sglobal.noahmp401_12mem.hymap2.DARun +++ b/lis/utils/usaf/s2s/for_discover/lis/lis.config.s2sglobal.noahmp401_12mem.hymap2.DARun @@ -339,6 +339,8 @@ AGRMET cloud data directory: WWMCA # WWMCA_LE, NONE, or # Use WWMCA GRIB1 files beginning 12Z 4 Jul 2020 AGRMET WWMCA GRIB1 read option: 1 AGRMET snow distribution shape parameter: 2.6 +AGRMET radiation derived from: "cloud types" +AGRMET GALWEM radiation data directory: WWMCA_GRIB # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. diff --git a/lis/utils/usaf/s2s/global_usaf_forc/input/lis.config.template b/lis/utils/usaf/s2s/global_usaf_forc/input/lis.config.template index 74a2bf7a2..4a945aaf0 100755 --- a/lis/utils/usaf/s2s/global_usaf_forc/input/lis.config.template +++ b/lis/utils/usaf/s2s/global_usaf_forc/input/lis.config.template @@ -22,6 +22,7 @@ Forcing variables list file: ./input/forcing_variables.txt Output methodology: "2d gridspace" Output model restart files: 1 Output data format: grib1 +#Output data format: netcdf #Required for GRIB1 output Output GRIB Table Version: 128 @@ -33,19 +34,19 @@ Output GRIB Packing Type: grid_simple Output naming style: "WMO convention" Enable output statistics: .false. -Start mode: restart -Starting year: 2022 -Starting month: 08 -Starting day: 01 -Starting hour: 0 -Starting minute: 0 -Starting second: 0 -Ending year: 2022 -Ending month: 08 -Ending day: 02 -Ending hour: 0 -Ending minute: 5 -Ending second: 0 +Start mode: restart +Starting year: 2024 +Starting month: 6 +Starting day: 1 +Starting hour: 0 +Starting minute: 0 +Starting second: 0 +Ending year: 2024 +Ending month: 6 +Ending day: 2 +Ending hour: 0 +Ending minute: 5 +Ending second: 0 Undefined value: -9999 Output directory: ./output Diagnostic output file: ./output/logs/lislog @@ -103,9 +104,12 @@ Bias estimation start mode: none Bias estimation restart file: none none none #Perturbation options -Perturbations start mode: restart restart restart +#Perturbations start mode: restart # restart restart +# NOTE: In Ops, use restart mode with appropriate restart files. +Perturbations start mode: coldstart coldstart coldstart + Perturbations restart output interval: 12hr 12hr 12hr -Perturbations restart filename: ./input/restarts/LIS_DAPERT_202104130000.d01.bin ./input/restarts/LIS_DAPERT_202104130000.d01.bin ./input/restarts/LIS_DAPERT_202104130000.d01.bin +Perturbations restart filename: ./input/rstfiles/LIS_DAPERT_202104130000.d01.bin ./input/rstfiles/LIS_DAPERT_202104130000.d01.bin ./input/rstfiles/LIS_DAPERT_202104130000.d01.bin Apply perturbation bias correction: 1 1 1 Forcing perturbation algorithm: none none none @@ -246,9 +250,12 @@ AGRMET CMORPH minimum temperature threshold: 273 # Use IMERG rainfall data AGRMET use IMERG data: 1 # 1 = Use AGRMET IMERG temperature threshold: 278 -AGRMET IMERG data directory: ./input/IMERG +AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG AGRMET IMERG product: 3B-HHR-E # Early Run -AGRMET IMERG version: V06E # V06E started 8 Nov 2023 +## S2S June-2024 forecast – use the following option: +#AGRMET IMERG version: V06E # FOR MAY-2024 dates +## S2S July-2024 forecast and after – use the following option: +AGRMET IMERG version: V07B # V07B started 1 June 2024 AGRMET IMERG Probability Liquid Precip Threshold: 100 # Bratseth runtime settings @@ -336,6 +343,23 @@ AGRMET cloud data directory: WWMCA_GRIB # Use WWMCA GRIB1 files beginning 12Z 4 Jul 2020 AGRMET WWMCA GRIB1 read option: 1 AGRMET snow distribution shape parameter: 2.6 +# S2S AGRMET/Bratseth forcing generation step guidance: +## FOR JUNE-2024 S2S Forecast – use following options up to June 1, 2024, 00Z: +AGRMET radiation derived from: "cloud types" +AGRMET cloud data directory: WWMCA_GRIB # Original input WWMCA GRIB-1 files +# +## FOR JULY-2024 S2S Forecast – use following options up to June 24, 2024, 00Z: +#AGRMET radiation derived from: "cloud types" +#AGRMET cloud data directory: WWMCA_GRIB # Original input WWMCA GRIB-1 files +# -- June 24, 00Z to July 2, 2024, 00Z +#AGRMET radiation derived from: "cloud types" +#AGRMET cloud data directory: WWMCA_GRIB_LOOKALIKE # WWMCA GRIB Look-alike files target directory +# +## FOR AUG-2024 and after S2S Forecast runs – use the following options: +# -- July 2, 2024, 00Z and onward: +#AGRMET radiation derived from: "GALWEM_RAD" # GALWEM Radiation files +#AGRMET cloud data directory: GALWEM # GALWEM forcing directory +AGRMET GALWEM radiation data directory: GALWEM # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. @@ -371,7 +395,7 @@ AGRMET overcast percentage: 0.30 #-----------------------LAND SURFACE MODELS-------------------------- Noah.3.9 model timestep: 15mn Noah.3.9 restart output interval: 12hr -Noah.3.9 restart file: ./input/restarts/LIS_RST_NOAH39_202208010000.d01.nc +Noah.3.9 restart file: ./input/rstfiles/LIS_RST_NOAH39_202406010000.d01.nc Noah.3.9 restart file format: netcdf Noah.3.9 vegetation parameter table: ./input/noah39_parms/VEGPARM.TBL diff --git a/lis/utils/usaf/s2s/s2s_app/s2s_config_global_fcast b/lis/utils/usaf/s2s/s2s_app/s2s_config_global_fcast index 74dad8d17..2c84085fc 100755 --- a/lis/utils/usaf/s2s/s2s_app/s2s_config_global_fcast +++ b/lis/utils/usaf/s2s/s2s_app/s2s_config_global_fcast @@ -85,4 +85,4 @@ POST: var_tair_max_list: [Tair_f_max] var_tair_min_list: [Tair_f_min] const_list: [lat, lon, ensemble, soil_layer, soil_layer_thickness, atime, Landmask_inst, LANDMASK, Landcover_inst, Soiltype_inst, Elevation_inst, Greenness_inst] - metric_vars: [RZSM, SFCSM, TWS, Precip, AirT, ET, Streamflow] + metric_vars: [RZSM, TOP40SM, SFCSM, TWS, Precip, AirT, ET, Streamflow] diff --git a/lis/utils/usaf/s2s/s2s_modules/lis_darun/template_files/lis.config_template.GLOBAL b/lis/utils/usaf/s2s/s2s_modules/lis_darun/template_files/lis.config_template.GLOBAL index 65115d747..31c6bb4c6 100755 --- a/lis/utils/usaf/s2s/s2s_modules/lis_darun/template_files/lis.config_template.GLOBAL +++ b/lis/utils/usaf/s2s/s2s_modules/lis_darun/template_files/lis.config_template.GLOBAL @@ -313,6 +313,8 @@ AGRMET cloud data directory: WWMCA # WWMCA_LE, NONE, or # Use WWMCA GRIB1 files beginning 12Z 4 Jul 2020 AGRMET WWMCA GRIB1 read option: 1 AGRMET snow distribution shape parameter: 2.6 +AGRMET radiation derived from: "cloud types" +AGRMET GALWEM radiation data directory: WWMCA_GRIB # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. diff --git a/lis/utils/usaf/s2s/s2s_modules/s2smetric/convert_s2s_anom_cf.py b/lis/utils/usaf/s2s/s2s_modules/s2smetric/convert_s2s_anom_cf.py index 820168093..e636f1c1b 100644 --- a/lis/utils/usaf/s2s/s2s_modules/s2smetric/convert_s2s_anom_cf.py +++ b/lis/utils/usaf/s2s/s2s_modules/s2smetric/convert_s2s_anom_cf.py @@ -47,6 +47,7 @@ # Units for variable anomalies. Standardized anomalies will be dimensionless. _UNITS_ANOM = { "RZSM" : "m3 m-3", + "TOP40SM" : "m3 m-3", "SFCSM" : "m3 m-3", "TWS" : "mm", "Precip" : "kg m-2", @@ -56,6 +57,7 @@ } _LONG_NAMES_SANOM = { "RZSM" : "Root zone soil moisture standardized anomaly", + "TOP40SM" : "Top 0-40 cm soil moisture standardized anomaly", "SFCSM" : "Surface soil moisture standardized anomaly", "TWS" : "Terrestrial water storage standardized anomaly", "Precip" : "Total precipitation amount standardized anomaly", @@ -65,6 +67,7 @@ } _LONG_NAMES_ANOM = { "RZSM" : "Root zone soil moisture anomaly", + "TOP40SM" : "Top 0-40 cm soil moisture anomaly", "SFCSM" : "Surface soil moisture anomaly", "TWS" : "Terrestrial water storage anomaly", "Precip" : "Total precipitation amount anomaly", diff --git a/lis/utils/usaf/s2s/s2s_modules/s2smetric/metrics_library/metricslib.py b/lis/utils/usaf/s2s/s2s_modules/s2smetric/metrics_library/metricslib.py index 7574ddf2f..84498ac61 100644 --- a/lis/utils/usaf/s2s/s2s_modules/s2smetric/metrics_library/metricslib.py +++ b/lis/utils/usaf/s2s/s2s_modules/s2smetric/metrics_library/metricslib.py @@ -60,6 +60,15 @@ def sel_var(sel_cim_data, var_name, model): print(f"[ERR] Unknown model {model}") sys.exit(1) + elif var_name == "TOP40SM": + if model in ('NOAHMP', 'NoahMP'): + term1 = sel_cim_data.SoilMoist_tavg.isel(soil_layer=0) * 0.1 + term2 = sel_cim_data.SoilMoist_tavg.isel(soil_layer=1) * 0.3 + var_sel_clim_data = term1 + term2 + else: + print(f"[ERR] Unknown model {model}") + sys.exit(1) + elif var_name == 'Total-SM': if model == 'CLSM': # for clsm the total soil moisture is in the third layer diff --git a/lis/utils/usaf/s2s/s2s_modules/shared/utils.py b/lis/utils/usaf/s2s/s2s_modules/shared/utils.py index 562a1bd62..07bf45fca 100644 --- a/lis/utils/usaf/s2s/s2s_modules/shared/utils.py +++ b/lis/utils/usaf/s2s/s2s_modules/shared/utils.py @@ -71,6 +71,8 @@ def job_script(s2s_configfile, jobfile, job_name, ntasks, hours, cwd, in_command # _f.write('#SBATCH --cluster-constraint=green' + '\n') _f.write('#SBATCH --cluster-constraint=' + cfg['SETUP']['CONSTRAINT'] + '\n') _f.write('#SBATCH --partition=batch' + '\n') + _f.write('#SBATCH --exclusive' + '\n') + _f.write('#SBATCH --mem=0' + '\n') _f.write('#SBATCH --job-name=' + job_name + '\n') _f.write('#SBATCH --output ' + cwd + '/' + job_name + '%j.out' + '\n') _f.write('#SBATCH --error ' + cwd + '/' + job_name + '%j.err' + '\n') @@ -207,6 +209,8 @@ def job_script_lis(s2s_configfile, jobfile, job_name, cwd, hours=None, in_comman # _f.write('#SBATCH --cluster-constraint=green' + '\n') _f.write('#SBATCH --cluster-constraint=' + cfg['SETUP']['CONSTRAINT'] + '\n') _f.write('#SBATCH --partition=batch' + '\n') + _f.write('#SBATCH --exclusive' + '\n') + _f.write('#SBATCH --mem=0' + '\n') if datatype == 'hindcast': _f.write('#SBATCH --ntasks=' + ntasks + '\n') else: @@ -256,8 +260,8 @@ def get_domain_info (s2s_configfile, extent=None, coord=None): if extent is not None: lon = np.array(ldt['lon']) lat = np.array(ldt['lat']) - return np.int(np.floor(np.min(lat[:,0]))), np.int(np.ceil(np.max(lat[:,0]))), \ - np.int(np.floor(np.min(lon[0,:]))), np.int(np.ceil(np.max(lon[0,:]))) + return int(np.floor(np.min(lat[:,0]))), int(np.ceil(np.max(lat[:,0]))), \ + int(np.floor(np.min(lon[0,:]))), int(np.ceil(np.max(lon[0,:]))) if coord is not None: lon = np.array(ldt['lon'])