From d9a4b8469199755d27e70d41151b885d6a491fec Mon Sep 17 00:00:00 2001 From: Mahdi Navari Date: Mon, 13 May 2024 16:01:07 -0400 Subject: [PATCH 01/31] Updated LIS to read ASCAT Metop-B and C from SMOPS V4 --- .../obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 | 12 +- .../SMOPS_GRIB2_Tables_NESDIS.txt | 35 +++ .../obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 | 218 +++++++++++++++++- 3 files changed, 253 insertions(+), 12 deletions(-) diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 b/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 index bcd2e8bab..7ccd94c6d 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/SMOPS_ASCATsm_Mod.F90 @@ -1,9 +1,9 @@ !-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- ! NASA Goddard Space Flight Center ! Land Information System Framework (LISF) -! Version 7.4 +! Version 7.5 ! -! Copyright (c) 2022 United States Government as represented by the +! Copyright (c) 2024 United States Government as represented by the ! Administrator of the National Aeronautics and Space Administration. ! All Rights Reserved. !-------------------------END NOTICE -- DO NOT EDIT----------------------- @@ -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 6ab989ec9..7fe095ec0 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 @@ -1,9 +1,9 @@ !-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- ! NASA Goddard Space Flight Center ! Land Information System Framework (LISF) -! Version 7.4 +! Version 7.5 ! -! Copyright (c) 2022 United States Government as represented by the +! Copyright (c) 2024 United States Government as represented by the ! Administrator of the National Aeronautics and Space Administration. ! All Rights Reserved. !-------------------------END NOTICE -- DO NOT EDIT----------------------- @@ -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,6 +130,7 @@ 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, & @@ -458,6 +462,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 +475,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) @@ -532,7 +548,8 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) 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 @@ -540,6 +557,14 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) param_ASCAT_B_hr = 228; param_ASCAT_B_mn = 229 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 + write(LIS_logunit,*) '[MSG] Reading SMOPS ASCAT dataset '//& + 'as SMOPS version 4.0' endif call grib_open_file(ftn, trim(fname), 'r', iret) @@ -713,6 +738,77 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) imsg = -1 exit end if + + 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 + enddo call grib_close_file(ftn) @@ -755,6 +851,7 @@ 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. @@ -824,13 +921,59 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) enddo enddo - sm_data = sm_ASCAT_A_t - sm_time = sm_time_ASCAT_A - where ( sm_ASCAT_B_t /= LIS_rc%udef ) + 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 + + + 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 +1040,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 +1052,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 +1083,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 +1101,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 = 2224, & + mm = 4, & + dd = 25, & + h = 0, & + m = 0, & + s = 0, & + calendar = LIS_calendar, & + rc = rc) + first_time = .false. endif @@ -977,6 +1139,7 @@ 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 @@ -986,6 +1149,43 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen if ( file_time >= naming3_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' + + 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 + !write(LIS_logunit,*) '[INFO] reading ',trim(filename) + enddo + call LIS_releaseUnitNumber(ftn) else filename = trim(ndir)//'/smops_d' & //trim(fyr)//trim(fmo)//trim(fda)//'_s'//trim(fhr)//'0000_cness.gr2' From 5a63b8680cf694781fa86ee512c0fef237fe83d1 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Thu, 23 May 2024 10:00:53 -0400 Subject: [PATCH 02/31] Bug fixs to handle unrecognized gage networks. --- lis/metforcing/usaf/AGRMET_getpcpobs.F90 | 6 +- lis/metforcing/usaf/AGRMET_storeobs.F90 | 71 +++++++++++++++++- .../usaf/AGRMET_storeobs_offhour.F90 | 75 +++++++++++++++++-- lis/metforcing/usaf/USAF_bratsethMod.F90 | 18 +++-- 4 files changed, 154 insertions(+), 16 deletions(-) diff --git a/lis/metforcing/usaf/AGRMET_getpcpobs.F90 b/lis/metforcing/usaf/AGRMET_getpcpobs.F90 index 5ff482c9f..58eb0b7b6 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_storeobs.F90 b/lis/metforcing/usaf/AGRMET_storeobs.F90 index b10e751c5..45ec30f69 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 (trim(new_networks(i)) == trim(network(irecord))) then + cycle RECORD + else if (trim(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 ad95cd589..1eecdc92c 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 (trim(new_networks(i)) == trim(network(irecord))) then + cycle RECORD + else if (trim(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 b6dedf826..9343de7f6 100644 --- a/lis/metforcing/usaf/USAF_bratsethMod.F90 +++ b/lis/metforcing/usaf/USAF_bratsethMod.F90 @@ -20,6 +20,8 @@ ! ........................................Eric Kemp/SSAI/NASA ! 03 Jun 2020 Removed Box-Cox transform in precipitation analysis ! ........................................Eric Kemp/SSAI/NASA +! 23 May 2024 Export USAF_is_gauge function, and add HADS and +! NWSLI gage networks.....................Eric Kemp/SSAI/NASA ! ! DESCRIPTION: ! @@ -133,6 +135,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. @@ -1617,7 +1621,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 @@ -1628,7 +1632,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. @@ -3306,7 +3310,7 @@ subroutine USAF_superstatQC(this,nest,new_name,network,silent_rejects) if (.not. is_imerg(this%net(j))) cycle end if else ! Gauges - if (.not. is_gauge(this%net(j))) cycle + if (.not. USAF_is_gauge(this%net(j))) cycle end if ! Now see which LIS grid box this is in. First, handle latitude. @@ -4067,7 +4071,7 @@ 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=10), intent(in) :: net logical :: answer @@ -4075,14 +4079,16 @@ logical function is_gauge(net) 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. "HADS") answer = .true. ! EMK 20240523 if (trim(net) .eq. "ICAO") answer = .true. + if (trim(net) .eq. "NWSLI") answer = .true. ! EMK 20240523 if (trim(net) .eq. "WMO") answer = .true. if (trim(net) .eq. "MOBL") answer = .true. if (trim(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 + USAF_is_gauge = answer + end function USAF_is_gauge !--------------------------------------------------------------------------- ! Dummy function for establishing a surface station is uncorrelated. From a7357f5d37f2794dacb776ce269e6ff3cc6e94dd Mon Sep 17 00:00:00 2001 From: Ehsan Jalilvand Date: Tue, 28 May 2024 18:34:20 -0400 Subject: [PATCH 03/31] Update SMOPS_ASCAT subroutines - In 'create_SMOPS_ASCATsm_filename' subroutine: - Update the 'Ver4_blended_time' year to 2024 from 2224. - Update the if statement to select the file version based on the date. - In 'read_SMOPS_ASCAT_data' subroutine: - Move the immature GRIB message release to after checking for SMOPS Metop-C data. - Add logical variables 'a_exist', 'b_exist', and 'c_exist' to check the existence of Metop-A, B, or C based on the file version. - Add a condition to read SMOPS Metop-A and B data for version 3 and before, and SMOPS Metop-B and C for version 4. - Add a condition to read SMOPS Metop-A and B QA data for version 3 and before, and SMOPS Metop-B and C QA data for version 4. --- .../obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 | 631 +++++++++--------- 1 file changed, 320 insertions(+), 311 deletions(-) diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 index 7fe095ec0..6bcba69c5 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 @@ -509,6 +509,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 @@ -545,6 +546,7 @@ 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' @@ -555,6 +557,7 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) 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 @@ -563,6 +566,7 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) 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 @@ -593,222 +597,224 @@ 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. + 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_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. - 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) imsg = -1 exit end if - - 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 - enddo call grib_close_file(ftn) @@ -854,108 +860,111 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) sm_time_ASCAT_C = LIS_rc%udef sm_data = LIS_rc%udef sm_data_b = .false. - - 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 - - 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 - + + 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 if ( file_time < SMOPS_ASCATsm_struc(n)%version4_time ) then sm_data = sm_ASCAT_A_t @@ -1103,7 +1112,7 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen rc = rc) call ESMF_TimeSet(Ver4_blended_time, & - yy = 2224, & + yy = 2024, & mm = 4, & dd = 25, & h = 0, & @@ -1146,7 +1155,7 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen 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 From 190a1544b74085ca0f05d12a8830b4299a22bbe8 Mon Sep 17 00:00:00 2001 From: "Kristi R. Arsenault" Date: Wed, 29 May 2024 12:59:27 -0400 Subject: [PATCH 04/31] GALWEM Radiation Reader This is the initial commit for including the GALWEM radiation fields and reader in the LIS AGRMET / USAF (Bratseth) main code. New lis.config file entries: # GALWEM Radiation settings: AGRMET radiation derived from: "GALWEM_RAD" AGRMET GALWEM radiation data directory: "GALWEM_Rad" # WWMCA Cloud radiation settings (commented out): #AGRMET radiation derived from: "cloud types" --- lis/metforcing/usaf/AGRMET_forcingMod.F90 | 3 + lis/metforcing/usaf/AGRMET_sfcalc.F90 | 2 +- lis/metforcing/usaf/USAF_fldbld_radflux.F90 | 126 ++++++++++++++++++++ lis/metforcing/usaf/readagrmetforcing.F90 | 106 +++++++++++----- lis/metforcing/usaf/readcrd_agrmet.F90 | 10 ++ 5 files changed, 215 insertions(+), 32 deletions(-) create mode 100644 lis/metforcing/usaf/USAF_fldbld_radflux.F90 diff --git a/lis/metforcing/usaf/AGRMET_forcingMod.F90 b/lis/metforcing/usaf/AGRMET_forcingMod.F90 index 4a707ac24..fe408fdff 100644 --- a/lis/metforcing/usaf/AGRMET_forcingMod.F90 +++ b/lis/metforcing/usaf/AGRMET_forcingMod.F90 @@ -341,6 +341,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 diff --git a/lis/metforcing/usaf/AGRMET_sfcalc.F90 b/lis/metforcing/usaf/AGRMET_sfcalc.F90 index cd45f7a3e..034ed947f 100644 --- a/lis/metforcing/usaf/AGRMET_sfcalc.F90 +++ b/lis/metforcing/usaf/AGRMET_sfcalc.F90 @@ -229,7 +229,7 @@ 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 timeToReadGFS = .false. diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 new file mode 100644 index 000000000..3e87c1ffc --- /dev/null +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -0,0 +1,126 @@ +!-----------------------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,order,julhr) + +! !USES: + use AGRMET_forcingMod, only : agrmet_struc + use LIS_coreMod, only : LIS_masterproc + use LIS_logMod, only : LIS_logunit, LIS_endrun, LIS_abort,& + LIS_alert + use LIS_timeMgrMod, only : LIS_julhr_date + +#if (defined USE_GRIBAPI) + use grib_api +#endif + + implicit none +! !ARGUMENTS: + integer, intent(in) :: n + integer, intent(in) :: order + integer, intent(inout) :: julhr +! +! !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 +! \item[order] +! flag to indicate which data is to be read \newline +! 1 = end time \newline +! 2 = start time +! \item[julhr] +! julian hour used to determine names of forecast files from previous cycles +! \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 :: ierr + + ! 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] First guess source is not correctly defined.' + call LIS_endrun + end if + + call AGRMET_julhr_date10(julhr, yyyymmddhh) + 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 +! call USAF_fldbld_radflux_galwem(n,order,julhr,rc) + ierr = rc + end if + + ! 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,order,julhr,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,*) ' 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/readagrmetforcing.F90 b/lis/metforcing/usaf/readagrmetforcing.F90 index 9cbb80d7a..3fbc8bf5d 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,6 +197,8 @@ subroutine readagrmetforcing(n,findex, order) real,allocatable :: rlh(:,:) integer :: ip integer :: julhr + character(len=255) :: message(20) + real,allocatable :: cldamt(:,:,:) integer,allocatable :: cldamt_nh( :,:,:) integer,allocatable :: cldtyp_nh( :,:,:) @@ -205,6 +211,8 @@ subroutine readagrmetforcing(n,findex, order) 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 @@ -234,7 +242,6 @@ 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") @@ -270,7 +277,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 +286,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,:,:) @@ -334,13 +346,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,8 +353,33 @@ 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: + if ( agrmet_struc(n)%compute_radiation == 'GALWEM_RAD' ) then + call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) + julend = istart+6 + call USAF_fldbld_radflux(n,order,julend) + if(LIS_masterproc) then + print *, "READ IN GALWEM RADIATION FIELDS -- ", yr1, mo1, da1, hr1 + print *, "order :: ",order + print *, "istart, julend :: ",istart,julend + + call LIS_endrun + + endif + 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 @@ -360,9 +390,11 @@ subroutine readagrmetforcing(n,findex, order) 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 +403,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 +411,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 +434,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 +452,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,7 +481,9 @@ subroutine readagrmetforcing(n,findex, order) endif enddo + ! Downward Shortwave Radiation Field estimates: + ! WWMCA Cloud properties used to derive solar downward radiation fields: if ( agrmet_struc(n)%compute_radiation == 'cloud types' ) then r1_ps = 0.0 r2_ps = 0.0 @@ -493,7 +529,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,:,:)) @@ -535,8 +574,10 @@ subroutine readagrmetforcing(n,findex, order) allocate(swdown(LIS_rc%lnc(n),LIS_rc%lnr(n))) - do r=1,LIS_rc%lnr(n) - do c=1,LIS_rc%lnc(n) + ! 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) 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 +594,11 @@ subroutine readagrmetforcing(n,findex, order) else swdown(c,r) = LIS_rc%udef endif - enddo - enddo + enddo + enddo + endif + ! 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 +640,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 +650,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 05452a3a4..b8bb7cd77 100644 --- a/lis/metforcing/usaf/readcrd_agrmet.F90 +++ b/lis/metforcing/usaf/readcrd_agrmet.F90 @@ -448,11 +448,21 @@ subroutine readcrd_agrmet() call ESMF_ConfigGetAttribute(LIS_config,agrmet_struc(n)%retroFileRoot,rc=rc) enddo + ! New AGRMET radiation option -- GALWEM-based inputs (KRA) = GALWEM_RAD: call ESMF_ConfigFindLabel(LIS_config,"AGRMET radiation derived from:",rc=rc) do n=1,LIS_rc%nnest call ESMF_ConfigGetAttribute(LIS_config,agrmet_struc(n)%compute_radiation,default="cloud types", rc=rc) + ! "cloud types" is default for WWMCA Grib files: enddo +! -- TEMPORARY -- KRA -- 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 +! -- TEMPORARY -- + + call ESMF_ConfigGetAttribute(LIS_config,LIS_rc%security_class,& label="AGRMET security classification:",rc=rc) From 174dc891c7be96d0c6b0615f240f57e0a6368325 Mon Sep 17 00:00:00 2001 From: "Kristi R. Arsenault" Date: Thu, 30 May 2024 21:02:21 -0400 Subject: [PATCH 05/31] USAF GALWEM Radiation flux reader updates - Made additional updates to the USAF met reader with GALWEM radiation files and fluxes. - Some temporary code placeholders in place while testing is underway (clean-up will follow). --- lis/metforcing/usaf/USAF_bratsethMod.F90 | 1 + lis/metforcing/usaf/USAF_fldbld_radflux.F90 | 13 +- .../usaf/USAF_fldbld_radflux_galwem.F90 | 717 ++++++++++++++++++ lis/metforcing/usaf/readagrmetforcing.F90 | 22 +- .../land/noah.3.9/noah39_readrst.F90 | 2 +- 5 files changed, 744 insertions(+), 11 deletions(-) create mode 100644 lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 diff --git a/lis/metforcing/usaf/USAF_bratsethMod.F90 b/lis/metforcing/usaf/USAF_bratsethMod.F90 index b6dedf826..991bcaca4 100644 --- a/lis/metforcing/usaf/USAF_bratsethMod.F90 +++ b/lis/metforcing/usaf/USAF_bratsethMod.F90 @@ -2805,6 +2805,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,& diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 index 3e87c1ffc..eedd4cece 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -22,11 +22,11 @@ ! 28 May 2024 Generated reader for radiation fluxese...K. Arsenault/SAIC ! ! !INTERFACE: -subroutine USAF_fldbld_radflux(n,order,julhr) +subroutine USAF_fldbld_radflux(n,order,julhr,swdown,longwv) ! !USES: use AGRMET_forcingMod, only : agrmet_struc - use LIS_coreMod, only : LIS_masterproc + 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 @@ -40,6 +40,8 @@ subroutine USAF_fldbld_radflux(n,order,julhr) integer, intent(in) :: n integer, intent(in) :: order integer, intent(inout) :: julhr + 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 @@ -69,6 +71,7 @@ subroutine USAF_fldbld_radflux(n,order,julhr) integer :: rc character(len=255) :: message(20) character(len=10) :: yyyymmddhh + integer :: fc_hr integer :: ierr ! Sanity check @@ -85,7 +88,11 @@ subroutine USAF_fldbld_radflux(n,order,julhr) ! Try fetching GALWEM, if requested ierr = 0 if ( agrmet_struc(n)%first_guess_source == 'GALWEM' ) then -! call USAF_fldbld_radflux_galwem(n,order,julhr,rc) + + fc_hr = LIS_rc%hr ! KRA - TEMPORARY PLACEHOLDER FOR FC_HR ... + write(LIS_logunit,*) '[INFO] NWP radiation fc_hr: ',fc_hr + + call USAF_fldbld_radflux_galwem(n,julhr,fc_hr,swdown,longwv,rc) ierr = rc end if 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..cb14d4ca2 --- /dev/null +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -0,0 +1,717 @@ +!-----------------------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,fc_hr,fg_swdata,fg_lwdata,rc) + +! !USES: + 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 + use AGRMET_forcingMod, only : agrmet_struc + +#if (defined USE_GRIBAPI) + use grib_api +#endif + + implicit none +! !ARGUMENTS: + integer, intent(in) :: n + integer :: julhr + integer :: fc_hr + 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 interpolates the GALWEM radiation flux +! data 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\_data] +! array of galwem rain rate 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\_ewdown] +! 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\_swdown2] +! 6 hour forecast swdown radiation flux data +! \item[fg\_lwdown1] +! 3 hour forecast lwdown radiation flux data +! \item[fg\_lwdown2] +! 6 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[found2] +! 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 + integer :: ftn, igrib + character*250 :: avnfile, avnfile2 + integer :: yr1, mo1, da1, hr1 +! integer :: julhr + character*255 :: message ( 20 ) + integer :: iginfo ( 2 ) + real :: gridres + integer :: alert_number + real, allocatable :: fg_swdown ( : , : ) + real, allocatable :: fg_swdown1 ( : , : ) + real, allocatable :: fg_swdown2 ( : , : ) + real, allocatable :: fg_lwdown ( : , : ) + real, allocatable :: fg_lwdown1 ( : , : ) + real, allocatable :: fg_lwdown2 ( : , : ) + integer :: ifguess, jfguess + integer :: center + integer :: ierr + logical*1 :: found, found2 + integer :: yr_2d + integer :: file_julhr + integer :: getsixhr + integer :: dataDate, dataTime + character*100 :: gtype + logical :: found_inq +! --------------------------------------------------- + + rc = 0 + + found = .false. + found2 = .false. + call LIS_julhr_date(julhr,yr1,mo1,da1,hr1) + file_julhr = julhr + +! ------------------------------------------------------------------ +! Need to process the current and previous 6 hour instances +! Search for an analysis or forecast file for upto 24 hours with +! the needed valid time +! ------------------------------------------------------------------ + + do while( ((.not.found) .or. (.not.found2)) .and. (fc_hr <= 12)) + found = .false. + +! -------------------------------------------------------------------- +! determine if we need the 6 hour forecast file +! -------------------------------------------------------------------- + if (mod(fc_hr,6) .eq. 0) then + getsixhr=1 + found2=.false. + else + getsixhr=0 + found2=.true. + endif + + yr_2d = mod(yr1,100) + if(yr_2d.eq.0) yr_2d = 100 + + !EMK...Added support for 10-km GALWEM + 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) + + if (getsixhr.eq.1) then + call AGRMET_getGALWEMfilename(avnfile2, agrmet_struc(n)%agrmetdir,& + agrmet_struc(n)%galwemraddir,agrmet_struc(n)%use_timestamp,& + agrmet_struc(n)%galwem_res, yr1,mo1,da1,hr1,fc_hr-3) + endif + +! ------------------------------------------------------------------ +! 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. +! ------------------------------------------------------------------ + +#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) + inquire(file=trim(avnfile),exist=found_inq) + if (found_inq) then + call grib_open_file(ftn,trim(avnfile),'r',ierr) + else + ierr = 1 + end if + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed to open - ',trim(avnfile) + else + ! ------------------------------------------------------------------ + ! read in the first grib record, unpack the header and extract + ! section 1 and section 2 information. + ! ------------------------------------------------------------------ + call grib_new_from_file(ftn,igrib,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed to read - '//trim(avnfile) + endif + + call grib_get(igrib,'centre',center,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grib_get: centre in ' // & + 'USAF_fldbld_radflux_galwem' + endif + + call grib_get(igrib,'gridType',gtype,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get: gridtype in ' // & + 'USAF_fldbld_radflux_galwem' + endif + + call grib_get(igrib,'Ni',iginfo(1),ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:Ni in ' // & + 'USAF_fldbld_radflux_galwem' + endif + + call grib_get(igrib,'Nj',iginfo(2),ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:Nj in ' // & + 'USAF_fldbld_radflux_galwem' + endif + + call grib_get(igrib,'jDirectionIncrementInDegrees',gridres,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + 'error in grid_get:jDirectionIncrementInDegrees in ' // & + 'USAF_fldbld_radflux_galwem' + endif + + call grib_get(igrib,'dataDate',dataDate,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:dataDate in ' // & + 'USAF_fldbld_radflux_galwem' + endif + + call grib_get(igrib,'dataTime',dataTime,ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) 'error in grid_get:dataTime in ' // & + 'USAF_fldbld_radflux_galwem' + endif + + 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: agrmet_sfcalc' + message(3) = ' First guess source is not a lat/lon grid' + message(4) = ' agrmet_sfcalc expects lat/lon data' + call lis_abort(message) + endif + endif + + call grib_release(igrib,ierr) + call grib_close_file(ftn) + endif +#else + write(LIS_logunit,*) 'ERR: USAF_fldbld_radflux_galwem requires GRIB-API' + write(LIS_logunit,*) 'ERR: please recompile LIS' + call LIS_endrun +#endif + +! ------------------------------------------------------------------- +! if we need to get the six hour forecast file, repeat steps above +! for that file +! ------------------------------------------------------------------- + if (getsixhr.eq.1) then + +#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. + + inquire(file=trim(avnfile2),exist=found_inq) + if (found_inq) then + call grib_open_file(ftn,trim(avnfile2),'r',ierr) + else + ierr = 1 + end if + if(ierr.ne.0) then + write(LIS_logunit,*) '[WARN] Failed to open - ', trim(avnfile2) + else + ! ------------------------------------------------------------------ + ! read in the first grib record, unpack the header and extract + ! section 1 and section 2 information. + ! ------------------------------------------------------------------ + call grib_new_from_file(ftn,igrib,ierr) + call LIS_verify(ierr, 'failed to read - '//trim(avnfile2)) + + call grib_get(igrib,'centre',center,ierr) + call LIS_verify(ierr, 'error in grib_get: centre in ' // & + 'USAF_fldbld_radflux_galwem') + + call grib_get(igrib,'gridType',gtype,ierr) + call LIS_verify(ierr, 'error in grid_get: gridtype in ' // & + 'USAF_fldbld_radflux_galwem') + + call grib_get(igrib,'Ni',iginfo(1),ierr) + call LIS_verify(ierr, 'error in grid_get:Ni in ' // & + 'USAF_fldbld_radflux_galwem') + + call grib_get(igrib,'Nj',iginfo(2),ierr) + call LIS_verify(ierr, 'error in grid_get:Nj in ' // & + 'USAF_fldbld_radflux_galwem') + + call grib_get(igrib,'jDirectionIncrementInDegrees',gridres,ierr) + call LIS_verify(ierr, & + 'error in grid_get:jDirectionIncrementInDegrees in ' // & + 'USAF_fldbld_radflux_galwem') + + call grib_get(igrib,'dataDate',dataDate,ierr) + call LIS_verify(ierr, 'error in grid_get:dataDate in ' // & + 'USAF_fldbld_radflux_galwem') + + call grib_get(igrib,'dataTime',dataTime,ierr) + call LIS_verify(ierr, 'error in grid_get:dataTime in ' // & + 'USAF_fldbld_radflux_galwem') + + if ( yr1*10000+mo1*100+da1 == dataDate .and. & + hr1*100 == dataTime ) then + found2 = .TRUE. + if ( gtype /= "regular_ll" ) then + message(1) = 'program: LIS' + message(2) = ' Subroutine: agrmet_sfcalc' + message(3) = ' First guess source is not a lat/lon grid' + message(4) = ' agrmet_sfcalc expects lat/lon data' + call lis_abort(message) + endif + endif + + call grib_release(igrib,ierr) + call grib_close_file(ftn) + endif +#endif + endif + + +! ------------------------------------------------------------------ +! If the correct valid time is not found: +! Increment forecast hour by 6. +! Decrement file_julhr by 6 and get the new filename elements. +! ------------------------------------------------------------------ + + if ((.not. found).or.(.not. found2)) then + fc_hr = fc_hr + 6 + file_julhr = file_julhr - 6 + call LIS_julhr_date(file_julhr,yr1,mo1,da1,hr1) + endif + enddo + + + if ((found) .and. (found2)) then + write(LIS_logunit,*)'- 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,*)'- FIRST GUESS DATA IS FROM UK UM (GALWEM) MODEL' + else + write(LIS_logunit,*)'- UNKNOWN SOURCE FOR FIRST GUESS DATA' + end if + +! ------------------------------------------------------------------ +! allocate first guess grid-specific variables. +! ------------------------------------------------------------------ + allocate ( fg_swdown1 (ifguess, jfguess) ) + allocate ( fg_lwdown1 (ifguess, jfguess) ) + + if (getsixhr.eq.1) allocate ( fg_swdown2 (ifguess, jfguess) ) + if (getsixhr.eq.1) allocate ( fg_lwdown2 (ifguess, jfguess) ) + + +! ------------------------------------------------------------------ +! read in first guess data for this julian hour. +! ------------------------------------------------------------------ + alert_number = 0 + + call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& + fg_swdown1, fg_lwdown1, alert_number) + if (getsixhr.eq.1) & + call USAF_fldbld_read_radflux_galwem(avnfile2, ifguess, jfguess,& + fg_swdown2, fg_lwdown2, alert_number) + + allocate ( fg_swdown (ifguess, jfguess) ) + allocate ( fg_lwdown (ifguess, jfguess) ) + +! ----------------------------------------------------------------------- +! if we need 6 hour radiation data, subtract from 3 hour radiation data +! since the data are originally for the 0-6 hour forecast. +! ----------------------------------------------------------------------- + if (getsixhr.eq.1) then + fg_swdown = fg_swdown1 - fg_swdown2 + fg_lwdown = fg_lwdown1 - fg_lwdown2 + else + fg_swdown = fg_swdown1 + fg_lwdown = fg_lwdown1 + endif + +! ----------------------------------------------------------------------- +! sometimes the subtraction of 3 hour radiation from 6 hour rad fluxes causes +! slightly negative radiation values, set back to 0 +! ----------------------------------------------------------------------- + where (fg_swdown .lt. 0) + fg_swdown=0 + endwhere + where (fg_lwdown .lt. 0) + fg_lwdown=0 + endwhere + + call interp_galwem_first_guess(n, ifguess, jfguess, .true., & + fg_swdown, fg_swdata) + + call interp_galwem_first_guess(n, ifguess, jfguess, .true., & + fg_lwdown, fg_lwdata) + + deallocate ( fg_swdown, fg_swdown1 ) + deallocate ( fg_lwdown, fg_lwdown1 ) + if (getsixhr.eq.1) deallocate ( fg_swdown2, fg_lwdown2 ) + + else + write(LIS_logunit,*)'- ** GALWEM RADIATION FLUX data not available **' + + message(1) = 'Program: LIS' + message(2) = ' Routine: fldbld_radflux.' + message(3) = ' galwem Radiation flux data not available, ' // & + 'possible degradation.' + alert_number = alert_number + 1 + if(LIS_masterproc) then + call LIS_alert( 'fldbld ', alert_number, message ) + endif + endif + +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, alert_number ) +! !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(inout) :: alert_number +! +! !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*9 :: cstat + character*255 :: message ( 20 ) + integer :: count_swdown + integer :: count_lwdown + integer :: i + integer :: ierr + integer :: istat1 + integer :: j + integer :: k, c, r + integer :: ftn, igrib, nvars + integer :: param_disc_val, param_cat_val, & + param_num_val, forecasttime_val + real, allocatable :: dum1d ( : ) + logical :: found_inq + +! ------------------------------------------------------------------ +! executable code begins here ... +! ------------------------------------------------------------------ + +! ------------------------------------------------------------------ +! 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 + ierr = 1 + else + ierr = 0 + end if + call LIS_verify(ierr,'[WARN] Failed to open - '//trim(fg_filename)) + +#if (defined USE_GRIBAPI) + call grib_open_file(ftn,trim(fg_filename),'r',ierr) + call LIS_verify(ierr,'[WARN] Failed to open - '//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 first guess GALWEM 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_galwem') + + do k = 1, nvars + + call grib_new_from_file(ftn,igrib,ierr) + call LIS_verify(ierr, '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_galwem') + + call grib_get(igrib,'parameterCategory',param_cat_val,ierr) + call LIS_verify(ierr, 'error in grib_get: parameterCategory in ' // & + 'USAF_fldbld_read_radflux_galwem') + + call grib_get(igrib,'parameterNumber',param_num_val,ierr) + call LIS_verify(ierr, 'error in grib_get: parameterNumber in ' // & + 'USAF_fldbld_read_radflux_galwem') + + call grib_get(igrib,'forecastTime',forecasttime_val,ierr) + call LIS_verify(ierr, 'error in grib_get: forecastTime in ' // & + 'USAF_fldbld_read_radflux_galwem') + + ! SW Down Radiation flux: + if ( param_disc_val == 0 .and. param_cat_val == 4 .and. & + param_num_val == 7 .and. forecasttime_val == 0 ) then + + call grib_get(igrib,'values',dum1d,ierr) + call LIS_verify(ierr, 'error in grib_get: SWdown values in ' // & + 'USAF_fldbld_read_radflux_galwem') + if ( ierr == 0 ) then +! ------------------------------------------------------------------ +! store SW radiation flux to the fg_swdown array. +! ------------------------------------------------------------------ + fg_swdown = reshape(dum1d, (/ifguess,jfguess/)) + count_swdown = count_swdown + 1 + ! found swdown; clean up and break out of do-loop. +! call grib_release(igrib,ierr) +! exit + else + write(cstat,'(i9)',iostat=istat1) ierr + message(1) = 'Program: LIS' + message(2) = ' Subroutine: AGRMET_fldbld_read.' + message(3) = ' Error reading first guess file:' + message(4) = ' ' // trim(fg_filename) + if( istat1 .eq. 0 )then + message(5) = ' Status = ' // trim(cstat) + endif + if ( allocated(dum1d) ) deallocate(dum1d) + call LIS_abort( message) + endif + endif ! SWdown + + ! LW Down Radiation flux: + if ( param_disc_val == 0 .and. param_cat_val == 5 .and. & + param_num_val == 3 .and. forecasttime_val == 0 ) then + + call grib_get(igrib,'values',dum1d,ierr) + call LIS_verify(ierr, 'error in grib_get: LWdown values in ' // & + 'USAF_fldbld_read_radflux_galwem') + if ( ierr == 0 ) then +! ------------------------------------------------------------------ +! store LW radiation flux to the fg_lwdown array. +! ------------------------------------------------------------------ + fg_lwdown = reshape(dum1d, (/ifguess,jfguess/)) + count_lwdown = count_lwdown + 1 + else + write(cstat,'(i9)',iostat=istat1) ierr + message(1) = 'Program: LIS' + message(2) = ' Subroutine: AGRMET_fldbld_read.' + message(3) = ' Error reading first guess file:' + message(4) = ' ' // trim(fg_filename) + if( istat1 .eq. 0 )then + message(5) = ' Status = ' // trim(cstat) + endif + if ( allocated(dum1d) ) deallocate(dum1d) + call LIS_abort( message) + endif + endif ! LWdown + + call grib_release(igrib,ierr) + enddo + + 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_galwem.' + 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 + + else + write(cstat,'(i9)',iostat=istat1) ierr + message(1) = 'Program: LIS' + message(2) = ' Subroutine: USAF_fldbld_read_radflux_galwem.' + message(3) = ' Error opening first guess file:' + message(4) = ' ' // trim(fg_filename) + if ( istat1 == 0 ) then + message(5) = ' Status = ' // trim(cstat) + endif + call LIS_abort(message) + endif +#endif + +end subroutine USAF_fldbld_read_radflux_galwem diff --git a/lis/metforcing/usaf/readagrmetforcing.F90 b/lis/metforcing/usaf/readagrmetforcing.F90 index 3fbc8bf5d..c6adac056 100644 --- a/lis/metforcing/usaf/readagrmetforcing.F90 +++ b/lis/metforcing/usaf/readagrmetforcing.F90 @@ -245,11 +245,12 @@ subroutine readagrmetforcing(n,findex, order) 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))) @@ -355,17 +356,24 @@ subroutine readagrmetforcing(n,findex, order) ! Downward Longwave + Shortwave Radiation, read in from GALWEM / GFS: if ( agrmet_struc(n)%compute_radiation == 'GALWEM_RAD' ) then + call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) julend = istart+6 - call USAF_fldbld_radflux(n,order,julend) + if(LIS_masterproc) then print *, "READ IN GALWEM RADIATION FIELDS -- ", yr1, mo1, da1, hr1 print *, "order :: ",order print *, "istart, julend :: ",istart,julend - - call LIS_endrun - +! call LIS_endrun endif + + ! Target fields: swdown(lnc,lnr), longwv(lnc,lnr) + longwv = 200. ! KRA - Just testing a sample value ... + swdown = 100. ! KRA - Just testing a sample value ... + + ! Call to the NWP Radiation Flux main routines: + call USAF_fldbld_radflux(n,order,julend,swdown,longwv) + endif ! Read in cloud amount, type or COD information: @@ -572,12 +580,11 @@ subroutine readagrmetforcing(n,findex, order) endwhere endif - allocate(swdown(LIS_rc%lnc(n),LIS_rc%lnr(n))) - ! 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) + 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 @@ -594,6 +601,7 @@ subroutine readagrmetforcing(n,findex, order) else swdown(c,r) = LIS_rc%udef endif + enddo enddo endif diff --git a/lis/surfacemodels/land/noah.3.9/noah39_readrst.F90 b/lis/surfacemodels/land/noah.3.9/noah39_readrst.F90 index d5c716aa1..5d0c2aa11 100644 --- a/lis/surfacemodels/land/noah.3.9/noah39_readrst.F90 +++ b/lis/surfacemodels/land/noah.3.9/noah39_readrst.F90 @@ -108,7 +108,7 @@ subroutine noah39_readrst() endif write(LIS_logunit,*) & - '[INFO] Noah-3.9 restart file used: ',noah39_struc(n)%rfile + '[INFO] Noah-3.9 restart file used: ',trim(noah39_struc(n)%rfile) if(wformat.eq."binary") then ftn = LIS_getNextUnitNumber() From 6d77327e17e55019a2dfd14ac8b19bf05a5ce6c0 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Fri, 31 May 2024 07:10:20 -0400 Subject: [PATCH 06/31] Removed unnecessary TRIM calls. --- lis/metforcing/usaf/AGRMET_storeobs.F90 | 4 ++-- .../usaf/AGRMET_storeobs_offhour.F90 | 4 ++-- lis/metforcing/usaf/USAF_bratsethMod.F90 | 20 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lis/metforcing/usaf/AGRMET_storeobs.F90 b/lis/metforcing/usaf/AGRMET_storeobs.F90 index 45ec30f69..061f0f2f5 100644 --- a/lis/metforcing/usaf/AGRMET_storeobs.F90 +++ b/lis/metforcing/usaf/AGRMET_storeobs.F90 @@ -255,9 +255,9 @@ subroutine AGRMET_storeobs(nsize, nsize3, isize, obs, obs3, ilat, ilon, & ! 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 (trim(new_networks(i)) == trim(network(irecord))) then + if (new_networks(i) == network(irecord)) then cycle RECORD - else if (trim(new_networks(i)) == "NULL") then + else if (new_networks(i) == "NULL") then new_networks(i) = network(irecord) write(LIS_logunit,*)'[WARN] Found unrecognized network ', & trim(network(irecord)) diff --git a/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 b/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 index 1eecdc92c..bdcdb10ca 100644 --- a/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 +++ b/lis/metforcing/usaf/AGRMET_storeobs_offhour.F90 @@ -217,9 +217,9 @@ subroutine AGRMET_storeobs_offhour(nsize, isize, obs, ilat, ilon, & ! 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 (trim(new_networks(i)) == trim(network(irecord))) then + if (new_networks(i) == network(irecord)) then cycle RECORD - else if (trim(new_networks(i)) == "NULL") then + else if (new_networks(i) == "NULL") then new_networks(i) = network(irecord) write(LIS_logunit,*)'[WARN] Found unrecognized network ', & trim(network(irecord)) diff --git a/lis/metforcing/usaf/USAF_bratsethMod.F90 b/lis/metforcing/usaf/USAF_bratsethMod.F90 index 9343de7f6..227c1ab07 100644 --- a/lis/metforcing/usaf/USAF_bratsethMod.F90 +++ b/lis/metforcing/usaf/USAF_bratsethMod.F90 @@ -4076,17 +4076,17 @@ logical function USAF_is_gauge(net) character(len=10), 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. "HADS") answer = .true. ! EMK 20240523 - if (trim(net) .eq. "ICAO") answer = .true. - if (trim(net) .eq. "NWSLI") answer = .true. ! EMK 20240523 - 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. + if (net .eq. "CDMS") answer = .true. USAF_is_gauge = answer end function USAF_is_gauge From 85131829af16d668a87117b91ef99e836b43ff99 Mon Sep 17 00:00:00 2001 From: "Kristi R. Arsenault" Date: Fri, 31 May 2024 20:24:46 -0400 Subject: [PATCH 07/31] Updates to the GALWEM radiation flux reader - Made minor modifications, including lis log file messages, - removing dependence on forecast time grib2 entry for swdown, lwdown for grib2 parameter identifiers --- .../usaf/USAF_fldbld_radflux_galwem.F90 | 120 +++++++++--------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 index cb14d4ca2..2c35cc0d3 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -44,8 +44,9 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! ! !DESCRIPTION: -! This routine interpolates the GALWEM radiation flux -! data to the USAF/AGRMET grid. +! 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} @@ -53,8 +54,10 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! index of the nest ! \item[fc\_hr] ! forecast hour or the difference between reference and valid time -! \item[fg\_data] -! array of galwem rain rate data +! \item[fg\_swdata] +! array of galwem shortwave radiation data +! \item[fg\_lwdata] +! array of galwem longwave radiation data ! ! \item[ftn] ! file unit number @@ -73,18 +76,18 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! \item[gridres] ! the resolution, in degrees, of the first ! guess grid -! \item[fg\_ewdown] -! SWdown radiation flux data to be interpolated to lis 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 +! LWdown radiation flux data to be interpolated to lis grid ! \item[fg\_swdown1] -! 3 hour forecast swdown radiation flux data +! 3 hour forecast swdown radiation flux data ! \item[fg\_swdown2] -! 6 hour forecast swdown radiation flux data +! 6 hour forecast swdown radiation flux data ! \item[fg\_lwdown1] -! 3 hour forecast lwdown radiation flux data +! 3 hour forecast lwdown radiation flux data ! \item[fg\_lwdown2] -! 6 hour forecast lwdown radiation flux data +! 6 hour forecast lwdown radiation flux data ! \item[alert\_number] ! number of alerts that occur in the program ! \item[ifguess] @@ -107,13 +110,13 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! \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 +! indicates whether to get data from the 6 hour forecast file ! \item[dataDate] -! date of values in the GRIB message +! date of values in the GRIB message ! \item[dataTime] -! time of values in the GRIB message +! time of values in the GRIB message ! \item[gtype] -! type of grid determined by querying GRIB message +! type of grid determined by querying GRIB message ! \end{description} ! ! The routines invoked are: @@ -124,11 +127,11 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! 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 +! 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 +! interpolate first guess data to the USAF/AGRMET grid ! \item[LIS\_abort](\ref{LIS_abort}) \newline -! abort in case of error +! abort in case of error ! \end{description} !EOP integer :: ftn, igrib @@ -154,7 +157,7 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) integer :: getsixhr integer :: dataDate, dataTime character*100 :: gtype - logical :: found_inq + logical :: found_inq ! --------------------------------------------------- rc = 0 @@ -164,11 +167,11 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) call LIS_julhr_date(julhr,yr1,mo1,da1,hr1) file_julhr = julhr -! ------------------------------------------------------------------ -! Need to process the current and previous 6 hour instances +! ------------------------------------------------------------------ +! Need to process the current and previous 6 hour instances ! Search for an analysis or forecast file for upto 24 hours with ! the needed valid time -! ------------------------------------------------------------------ +! ------------------------------------------------------------------ do while( ((.not.found) .or. (.not.found2)) .and. (fc_hr <= 12)) found = .false. @@ -210,7 +213,7 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! 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) + inquire(file=trim(avnfile),exist=found_inq) if (found_inq) then call grib_open_file(ftn,trim(avnfile),'r',ierr) @@ -218,7 +221,7 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ierr = 1 end if if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] Failed to open - ',trim(avnfile) + write(LIS_logunit,*) '[WARN] (1) Failed to open first guess - ',trim(avnfile) else ! ------------------------------------------------------------------ ! read in the first grib record, unpack the header and extract @@ -226,7 +229,7 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! ------------------------------------------------------------------ call grib_new_from_file(ftn,igrib,ierr) if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] Failed to read - '//trim(avnfile) + write(LIS_logunit,*) '[WARN] (1) Failed file read check - '//trim(avnfile) endif call grib_get(igrib,'centre',center,ierr) @@ -276,9 +279,9 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) found = .TRUE. if ( gtype /= "regular_ll" ) then message(1) = 'program: LIS' - message(2) = ' Subroutine: agrmet_sfcalc' + message(2) = ' Subroutine: USAF_fldbld_radflux_galwem' message(3) = ' First guess source is not a lat/lon grid' - message(4) = ' agrmet_sfcalc expects lat/lon data' + message(4) = ' USAF_fldbld_radflux_galwem expects lat/lon data' call lis_abort(message) endif endif @@ -287,9 +290,9 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) call grib_close_file(ftn) endif #else - write(LIS_logunit,*) 'ERR: USAF_fldbld_radflux_galwem requires GRIB-API' - write(LIS_logunit,*) 'ERR: please recompile LIS' - call LIS_endrun + write(LIS_logunit,*) '[ERR]: USAF_fldbld_radflux_galwem requires GRIB-API' + write(LIS_logunit,*) '[ERR]: please recompile LIS' + call LIS_endrun #endif ! ------------------------------------------------------------------- @@ -311,7 +314,7 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ierr = 1 end if if(ierr.ne.0) then - write(LIS_logunit,*) '[WARN] Failed to open - ', trim(avnfile2) + write(LIS_logunit,*) '[WARN] (2) Failed to open 6-hr fcst file - ', trim(avnfile2) else ! ------------------------------------------------------------------ ! read in the first grib record, unpack the header and extract @@ -354,9 +357,9 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) found2 = .TRUE. if ( gtype /= "regular_ll" ) then message(1) = 'program: LIS' - message(2) = ' Subroutine: agrmet_sfcalc' + message(2) = ' Subroutine: USAF_fldbld_radflux_galwem' message(3) = ' First guess source is not a lat/lon grid' - message(4) = ' agrmet_sfcalc expects lat/lon data' + message(4) = ' USAF_fldbld_radflux_galwem expects lat/lon data' call lis_abort(message) endif endif @@ -367,19 +370,17 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) #endif endif - ! ------------------------------------------------------------------ ! If the correct valid time is not found: ! Increment forecast hour by 6. ! Decrement file_julhr by 6 and get the new filename elements. ! ------------------------------------------------------------------ - if ((.not. found).or.(.not. found2)) then fc_hr = fc_hr + 6 file_julhr = file_julhr - 6 call LIS_julhr_date(file_julhr,yr1,mo1,da1,hr1) endif - enddo + enddo ! End while loop if ((found) .and. (found2)) then @@ -394,9 +395,9 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) write(LIS_logunit,*)'- UNKNOWN SOURCE FOR FIRST GUESS DATA' end if -! ------------------------------------------------------------------ -! allocate first guess grid-specific variables. -! ------------------------------------------------------------------ +! ------------------------------------------------------------------ +! allocate first guess grid-specific variables. +! ------------------------------------------------------------------ allocate ( fg_swdown1 (ifguess, jfguess) ) allocate ( fg_lwdown1 (ifguess, jfguess) ) @@ -404,9 +405,9 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) if (getsixhr.eq.1) allocate ( fg_lwdown2 (ifguess, jfguess) ) -! ------------------------------------------------------------------ -! read in first guess data for this julian hour. -! ------------------------------------------------------------------ +! ------------------------------------------------------------------ +! read in first guess data for this julian hour. +! ------------------------------------------------------------------ alert_number = 0 call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& @@ -441,6 +442,7 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) fg_lwdown=0 endwhere + ! Spatially interpolate native grid to target domain grid: call interp_galwem_first_guess(n, ifguess, jfguess, .true., & fg_swdown, fg_swdata) @@ -452,11 +454,11 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) if (getsixhr.eq.1) deallocate ( fg_swdown2, fg_lwdown2 ) else - write(LIS_logunit,*)'- ** GALWEM RADIATION FLUX data not available **' + write(LIS_logunit,*)'[WARN] ** GALWEM RADIATION FLUX data not available **' message(1) = 'Program: LIS' - message(2) = ' Routine: fldbld_radflux.' - message(3) = ' galwem Radiation flux data not available, ' // & + message(2) = ' Routine: USAF_fldbld_radflux_galwem.' + message(3) = ' galwem radiation flux data not available, ' // & 'possible degradation.' alert_number = alert_number + 1 if(LIS_masterproc) then @@ -550,7 +552,7 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& ! !EOP character*9 :: cstat - character*255 :: message ( 20 ) + character*255 :: message ( 20 ) integer :: count_swdown integer :: count_lwdown integer :: i @@ -561,16 +563,14 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& integer :: ftn, igrib, nvars integer :: param_disc_val, param_cat_val, & param_num_val, forecasttime_val - real, allocatable :: dum1d ( : ) - logical :: found_inq + real, allocatable :: dum1d ( : ) + logical :: found_inq -! ------------------------------------------------------------------ -! executable code begins here ... -! ------------------------------------------------------------------ +! ------------------------------------------------------------------ -! ------------------------------------------------------------------ -! read in grib file. -! ------------------------------------------------------------------ +! ------------------------------------------------------------------ +! 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 @@ -583,11 +583,11 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& else ierr = 0 end if - call LIS_verify(ierr,'[WARN] Failed to open - '//trim(fg_filename)) + call LIS_verify(ierr,'[WARN] FILE NOT FOUND - '//trim(fg_filename)) #if (defined USE_GRIBAPI) call grib_open_file(ftn,trim(fg_filename),'r',ierr) - call LIS_verify(ierr,'[WARN] Failed to open - '//trim(fg_filename)) + call LIS_verify(ierr,'[WARN] (3) Failed to open in read routine - '//trim(fg_filename)) if ( ierr == 0 ) then allocate ( dum1d (ifguess*jfguess) ) @@ -625,7 +625,8 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& ! SW Down Radiation flux: if ( param_disc_val == 0 .and. param_cat_val == 4 .and. & - param_num_val == 7 .and. forecasttime_val == 0 ) then + param_num_val == 7 ) then +! param_num_val == 7 .and. forecasttime_val == 0 ) then call grib_get(igrib,'values',dum1d,ierr) call LIS_verify(ierr, 'error in grib_get: SWdown values in ' // & @@ -655,7 +656,8 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& ! LW Down Radiation flux: if ( param_disc_val == 0 .and. param_cat_val == 5 .and. & - param_num_val == 3 .and. forecasttime_val == 0 ) then + param_num_val == 3 ) then +! param_num_val == 3 .and. forecasttime_val == 0 ) then call grib_get(igrib,'values',dum1d,ierr) call LIS_verify(ierr, 'error in grib_get: LWdown values in ' // & @@ -669,7 +671,7 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& else write(cstat,'(i9)',iostat=istat1) ierr message(1) = 'Program: LIS' - message(2) = ' Subroutine: AGRMET_fldbld_read.' + message(2) = ' Subroutine: USAF_fldbld_read_radflux_galwem.' message(3) = ' Error reading first guess file:' message(4) = ' ' // trim(fg_filename) if( istat1 .eq. 0 )then From 987d5cfe9cb4ca0198cb676b15c441ee3725a35c Mon Sep 17 00:00:00 2001 From: "Kristi R. Arsenault" Date: Mon, 3 Jun 2024 13:59:26 -0400 Subject: [PATCH 08/31] Latest GALWEM Reader Updates - Made updates to the cycle / forecast hour estimation and generation for reading in the GALWEM radiation fields (lwdown and swdown). - Issues in reading in the GALWEM radiation fields arose with updates to getting the right target cycle and initial forecast hour (6 hours out from 0 forecast hr). Working towards addressing GitHub issue: #1548. --- lis/metforcing/usaf/AGRMET_forcingMod.F90 | 5 +- lis/metforcing/usaf/AGRMET_sfcalc.F90 | 2 +- lis/metforcing/usaf/USAF_fldbld_radflux.F90 | 144 +++++++++---- .../usaf/USAF_fldbld_radflux_galwem.F90 | 198 +++++------------- lis/metforcing/usaf/get_agrmet.F90 | 4 +- lis/metforcing/usaf/readagrmetforcing.F90 | 45 ++-- 6 files changed, 177 insertions(+), 221 deletions(-) diff --git a/lis/metforcing/usaf/AGRMET_forcingMod.F90 b/lis/metforcing/usaf/AGRMET_forcingMod.F90 index fe408fdff..394f7bafc 100644 --- a/lis/metforcing/usaf/AGRMET_forcingMod.F90 +++ b/lis/metforcing/usaf/AGRMET_forcingMod.F90 @@ -555,8 +555,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(:) @@ -2108,6 +2109,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_sfcalc.F90 b/lis/metforcing/usaf/AGRMET_sfcalc.F90 index 034ed947f..f73853cc6 100644 --- a/lis/metforcing/usaf/AGRMET_sfcalc.F90 +++ b/lis/metforcing/usaf/AGRMET_sfcalc.F90 @@ -231,7 +231,7 @@ subroutine AGRMET_sfcalc(n) 0,0,jultmp) if(jultmp .gt. agrmet_struc(n)%lastSfcalcHour) then timeToReadGFS = .true. - else + else timeToReadGFS = .false. endif diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 index eedd4cece..c78502cbf 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -22,14 +22,15 @@ ! 28 May 2024 Generated reader for radiation fluxese...K. Arsenault/SAIC ! ! !INTERFACE: -subroutine USAF_fldbld_radflux(n,order,julhr,swdown,longwv) +!subroutine USAF_fldbld_radflux(n,order,julhr,swdown,longwv) +subroutine USAF_fldbld_radflux(n,order,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 + use LIS_timeMgrMod, only : LIS_julhr_date, LIS_get_julhr #if (defined USE_GRIBAPI) use grib_api @@ -39,7 +40,7 @@ subroutine USAF_fldbld_radflux(n,order,julhr,swdown,longwv) ! !ARGUMENTS: integer, intent(in) :: n integer, intent(in) :: order - integer, intent(inout) :: julhr +! integer, intent(inout) :: julhr real, intent(out) :: swdown(LIS_rc%lnc(n), LIS_rc%lnr(n)) real, intent(out) :: longwv(LIS_rc%lnc(n), LIS_rc%lnr(n)) ! @@ -70,9 +71,15 @@ subroutine USAF_fldbld_radflux(n,order,julhr,swdown,longwv) integer :: rc character(len=255) :: message(20) - character(len=10) :: yyyymmddhh - integer :: fc_hr - integer :: ierr + character(len=10) :: yyyymmddhh + integer :: julhr + integer :: jultmp + integer :: istart + integer :: julend + integer :: ordertmp ! Temporary placeholder +! integer :: fc_hr + integer :: ierr + logical :: timetoReadRad ! Sanity check if ( agrmet_struc(n)%first_guess_source .ne. 'GALWEM' .and. & @@ -81,53 +88,98 @@ subroutine USAF_fldbld_radflux(n,order,julhr,swdown,longwv) call LIS_endrun end if - call AGRMET_julhr_date10(julhr, yyyymmddhh) - write(LIS_logunit,*) & + ! Estimate julian hour to trigger reading of radiation fields: + 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)%lastRadHour) then + timeToReadRad = .true. + else + timeToReadRad = .false. + endif + + if(timeToReadRad) then +!------------------------------------------------------------------ +! Find the time to start the processing from +!------------------------------------------------------------------ + call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) + + julend = istart+6 + + agrmet_struc(n)%lastRadHour = julend + +! ------------------------------------------------------------------ +! check if the current instance is a restart or continuation of a run +! if the run is a cold start, read current and previous 6 hour data +! else copy the current to previous and read the new current data. +! ------------------------------------------------------------------ + if(agrmet_struc(n)%findtime1.eq.1.and.agrmet_struc(n)%findtime2.eq.1) then + ordertmp = 2 +! order = 2 +! call AGRMET_fldbld(n,order,istart) + +! order = 1 +! call AGRMET_fldbld(n,order,julend) + else + ordertmp = 1 +! order = 1 +! call AGRMET_fldbld(n,order,julend) + endif + + ! 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 + ! Try fetching GALWEM, if requested + ierr = 0 + if ( agrmet_struc(n)%first_guess_source == 'GALWEM' ) then - fc_hr = LIS_rc%hr ! KRA - TEMPORARY PLACEHOLDER FOR FC_HR ... - write(LIS_logunit,*) '[INFO] NWP radiation fc_hr: ',fc_hr + julhr = julend ! KRA -- Temporary placeholder - call USAF_fldbld_radflux_galwem(n,julhr,fc_hr,swdown,longwv,rc) - ierr = rc - end if +! fc_hr = LIS_rc%hr ! KRA - TEMPORARY PLACEHOLDER FOR FC_HR ... +! write(LIS_logunit,*) '[INFO] NWP radiation fc_hr: ',fc_hr - ! 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...' +! call USAF_fldbld_radflux_galwem(n,julhr,fc_hr,swdown,longwv,rc) + call USAF_fldbld_radflux_galwem(n,julhr,swdown,longwv,rc) + ierr = rc end if -! call USAF_fldbld_radflux_gfs(n,order,julhr,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,*) ' 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 '//& + ! 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,order,julhr,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,*) ' 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 + if(LIS_masterproc) then + call LIS_alert( 'LIS.USAF_fldbld_radflux.', 1, & + message ) + call LIS_abort( message) + endif + end if + end if + + endif ! End to timeToReadRad check 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 index 2c35cc0d3..0234b10c7 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -20,7 +20,8 @@ ! ...........................................K. Arsenault/SAIC ! ! !INTERFACE: -subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) +!subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) +subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) ! !USES: use LIS_coreMod, only : LIS_rc, LIS_masterproc @@ -37,7 +38,7 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! !ARGUMENTS: integer, intent(in) :: n integer :: julhr - integer :: fc_hr +! integer :: fc_hr 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 @@ -82,12 +83,8 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! LWdown radiation flux data to be interpolated to lis grid ! \item[fg\_swdown1] ! 3 hour forecast swdown radiation flux data -! \item[fg\_swdown2] -! 6 hour forecast swdown radiation flux data ! \item[fg\_lwdown1] ! 3 hour forecast lwdown radiation flux data -! \item[fg\_lwdown2] -! 6 hour forecast lwdown radiation flux data ! \item[alert\_number] ! number of alerts that occur in the program ! \item[ifguess] @@ -137,75 +134,69 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) integer :: ftn, igrib character*250 :: avnfile, avnfile2 integer :: yr1, mo1, da1, hr1 -! integer :: julhr + integer :: fc_hr character*255 :: message ( 20 ) integer :: iginfo ( 2 ) real :: gridres integer :: alert_number real, allocatable :: fg_swdown ( : , : ) real, allocatable :: fg_swdown1 ( : , : ) - real, allocatable :: fg_swdown2 ( : , : ) real, allocatable :: fg_lwdown ( : , : ) real, allocatable :: fg_lwdown1 ( : , : ) - real, allocatable :: fg_lwdown2 ( : , : ) integer :: ifguess, jfguess integer :: center integer :: ierr logical*1 :: found, found2 + logical :: first_time integer :: yr_2d integer :: file_julhr - integer :: getsixhr +! integer :: getsixhr integer :: dataDate, dataTime character*100 :: gtype logical :: found_inq ! --------------------------------------------------- + ! Initialize return code to "no error". We will change it below if + ! necessary. rc = 0 - found = .false. - found2 = .false. - call LIS_julhr_date(julhr,yr1,mo1,da1,hr1) - file_julhr = julhr + ! 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) -! ------------------------------------------------------------------ -! Need to process the current and previous 6 hour instances -! Search for an analysis or forecast file for upto 24 hours with -! the needed valid time -! ------------------------------------------------------------------ - - do while( ((.not.found) .or. (.not.found2)) .and. (fc_hr <= 12)) - found = .false. + found = .FALSE. + first_time = .true. + do while ( .not. found ) -! -------------------------------------------------------------------- -! determine if we need the 6 hour forecast file -! -------------------------------------------------------------------- - if (mod(fc_hr,6) .eq. 0) then - getsixhr=1 - found2=.false. - else - getsixhr=0 - found2=.true. - endif + ! 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 > 24) 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 - !EMK...Added support for 10-km GALWEM call AGRMET_getGALWEMfilename(avnfile, agrmet_struc(n)%agrmetdir,& - agrmet_struc(n)%galwemraddir,agrmet_struc(n)%use_timestamp,& + agrmet_struc(n)%galwemraddir, agrmet_struc(n)%use_timestamp,& agrmet_struc(n)%galwem_res, yr1,mo1,da1,hr1,fc_hr) - if (getsixhr.eq.1) then - call AGRMET_getGALWEMfilename(avnfile2, agrmet_struc(n)%agrmetdir,& - agrmet_struc(n)%galwemraddir,agrmet_struc(n)%use_timestamp,& - agrmet_struc(n)%galwem_res, yr1,mo1,da1,hr1,fc_hr-3) - endif - ! ------------------------------------------------------------------ ! 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) + cycle + end if #if (defined USE_GRIBAPI) @@ -214,7 +205,6 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) ! writing error messages to stdout/stderr, which may lead to runtime ! problems. - inquire(file=trim(avnfile),exist=found_inq) if (found_inq) then call grib_open_file(ftn,trim(avnfile),'r',ierr) else @@ -290,100 +280,30 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) call grib_close_file(ftn) endif #else - write(LIS_logunit,*) '[ERR]: USAF_fldbld_radflux_galwem requires GRIB-API' - write(LIS_logunit,*) '[ERR]: please recompile LIS' - call LIS_endrun + write(LIS_logunit,*) '[ERR]: USAF_fldbld_radflux_galwem requires GRIB-API' + write(LIS_logunit,*) '[ERR]: please recompile LIS' + call LIS_endrun #endif -! ------------------------------------------------------------------- -! if we need to get the six hour forecast file, repeat steps above -! for that file -! ------------------------------------------------------------------- - if (getsixhr.eq.1) then + ! At this point, we have everything we need. + found = .true. + if (found) exit -#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. - - inquire(file=trim(avnfile2),exist=found_inq) - if (found_inq) then - call grib_open_file(ftn,trim(avnfile2),'r',ierr) - else - ierr = 1 - end if - if(ierr.ne.0) then - write(LIS_logunit,*) '[WARN] (2) Failed to open 6-hr fcst file - ', trim(avnfile2) - else - ! ------------------------------------------------------------------ - ! read in the first grib record, unpack the header and extract - ! section 1 and section 2 information. - ! ------------------------------------------------------------------ - call grib_new_from_file(ftn,igrib,ierr) - call LIS_verify(ierr, 'failed to read - '//trim(avnfile2)) - - call grib_get(igrib,'centre',center,ierr) - call LIS_verify(ierr, 'error in grib_get: centre in ' // & - 'USAF_fldbld_radflux_galwem') - - call grib_get(igrib,'gridType',gtype,ierr) - call LIS_verify(ierr, 'error in grid_get: gridtype in ' // & - 'USAF_fldbld_radflux_galwem') - - call grib_get(igrib,'Ni',iginfo(1),ierr) - call LIS_verify(ierr, 'error in grid_get:Ni in ' // & - 'USAF_fldbld_radflux_galwem') - - call grib_get(igrib,'Nj',iginfo(2),ierr) - call LIS_verify(ierr, 'error in grid_get:Nj in ' // & - 'USAF_fldbld_radflux_galwem') - - call grib_get(igrib,'jDirectionIncrementInDegrees',gridres,ierr) - call LIS_verify(ierr, & - 'error in grid_get:jDirectionIncrementInDegrees in ' // & - 'USAF_fldbld_radflux_galwem') - - call grib_get(igrib,'dataDate',dataDate,ierr) - call LIS_verify(ierr, 'error in grid_get:dataDate in ' // & - 'USAF_fldbld_radflux_galwem') - - call grib_get(igrib,'dataTime',dataTime,ierr) - call LIS_verify(ierr, 'error in grid_get:dataTime in ' // & - 'USAF_fldbld_radflux_galwem') - - if ( yr1*10000+mo1*100+da1 == dataDate .and. & - hr1*100 == dataTime ) then - found2 = .TRUE. - if ( gtype /= "regular_ll" ) then - message(1) = 'program: LIS' - message(2) = ' Subroutine: USAF_fldbld_radflux_galwem' - message(3) = ' First guess source is not a lat/lon grid' - message(4) = ' USAF_fldbld_radflux_galwem expects lat/lon data' - call lis_abort(message) - endif - endif + enddo ! Loop through cycles and forecast hours - call grib_release(igrib,ierr) - call grib_close_file(ftn) - endif -#endif - endif + ! 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 -! ------------------------------------------------------------------ -! If the correct valid time is not found: -! Increment forecast hour by 6. -! Decrement file_julhr by 6 and get the new filename elements. -! ------------------------------------------------------------------ - if ((.not. found).or.(.not. found2)) then - fc_hr = fc_hr + 6 - file_julhr = file_julhr - 6 - call LIS_julhr_date(file_julhr,yr1,mo1,da1,hr1) - endif - enddo ! End while loop + write(LIS_logunit,*) & + '[INFO] Using NWP Radiation fields from ',trim(avnfile) + rc = 0 - if ((found) .and. (found2)) then + if( found ) then write(LIS_logunit,*)'- FIRST GUESS DATA IS ON A ', gridres,& ' DEGREE LAT/LON GRID' ifguess = iginfo(1) @@ -401,36 +321,17 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) allocate ( fg_swdown1 (ifguess, jfguess) ) allocate ( fg_lwdown1 (ifguess, jfguess) ) - if (getsixhr.eq.1) allocate ( fg_swdown2 (ifguess, jfguess) ) - if (getsixhr.eq.1) allocate ( fg_lwdown2 (ifguess, jfguess) ) - - ! ------------------------------------------------------------------ -! read in first guess data for this julian hour. +! read in first guess data for this julian hour. ! ------------------------------------------------------------------ alert_number = 0 call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& fg_swdown1, fg_lwdown1, alert_number) - if (getsixhr.eq.1) & - call USAF_fldbld_read_radflux_galwem(avnfile2, ifguess, jfguess,& - fg_swdown2, fg_lwdown2, alert_number) allocate ( fg_swdown (ifguess, jfguess) ) allocate ( fg_lwdown (ifguess, jfguess) ) -! ----------------------------------------------------------------------- -! if we need 6 hour radiation data, subtract from 3 hour radiation data -! since the data are originally for the 0-6 hour forecast. -! ----------------------------------------------------------------------- - if (getsixhr.eq.1) then - fg_swdown = fg_swdown1 - fg_swdown2 - fg_lwdown = fg_lwdown1 - fg_lwdown2 - else - fg_swdown = fg_swdown1 - fg_lwdown = fg_lwdown1 - endif - ! ----------------------------------------------------------------------- ! sometimes the subtraction of 3 hour radiation from 6 hour rad fluxes causes ! slightly negative radiation values, set back to 0 @@ -451,7 +352,6 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) deallocate ( fg_swdown, fg_swdown1 ) deallocate ( fg_lwdown, fg_lwdown1 ) - if (getsixhr.eq.1) deallocate ( fg_swdown2, fg_lwdown2 ) else write(LIS_logunit,*)'[WARN] ** GALWEM RADIATION FLUX data not available **' diff --git a/lis/metforcing/usaf/get_agrmet.F90 b/lis/metforcing/usaf/get_agrmet.F90 index 422e7434a..9f9af7f02 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 c6adac056..d4158d94a 100644 --- a/lis/metforcing/usaf/readagrmetforcing.F90 +++ b/lis/metforcing/usaf/readagrmetforcing.F90 @@ -199,13 +199,13 @@ subroutine readagrmetforcing(n,findex, order) integer :: julhr 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( :,:) + 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 @@ -216,9 +216,9 @@ subroutine readagrmetforcing(n,findex, order) 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 @@ -243,6 +243,7 @@ subroutine readagrmetforcing(n,findex, order) .040, .080, .025, .040, .040, .040, .025, .025/ data THRES /12600, 12300, 12000, 11700, 11400/ +! ___________________________________________________________ TRACE_ENTER("agrmet_readforc") allocate(varfield(LIS_rc%lnc(n),LIS_rc%lnr(n))) @@ -328,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 @@ -355,24 +357,22 @@ subroutine readagrmetforcing(n,findex, order) ss1 = LIS_rc%ss ! Downward Longwave + Shortwave Radiation, read in from GALWEM / GFS: + ! -- KRA: Initial setup if ( agrmet_struc(n)%compute_radiation == 'GALWEM_RAD' ) then - call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) - julend = istart+6 +! call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) +! julend = istart+6 if(LIS_masterproc) then print *, "READ IN GALWEM RADIATION FIELDS -- ", yr1, mo1, da1, hr1 print *, "order :: ",order - print *, "istart, julend :: ",istart,julend -! call LIS_endrun +! print *, "istart, julend :: ",istart,julend endif - ! Target fields: swdown(lnc,lnr), longwv(lnc,lnr) - longwv = 200. ! KRA - Just testing a sample value ... - swdown = 100. ! KRA - Just testing a sample value ... - ! Call to the NWP Radiation Flux main routines: - call USAF_fldbld_radflux(n,order,julend,swdown,longwv) + ! Target fields: swdown(lnc,lnr), longwv(lnc,lnr) +! call USAF_fldbld_radflux(n,order,julend,swdown,longwv) + call USAF_fldbld_radflux(n,order,swdown,longwv) endif @@ -391,10 +391,11 @@ subroutine readagrmetforcing(n,findex, order) ! 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 From a94c08bc652d45ecd04121a21a74ee3d2561fffa Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Fri, 7 Jun 2024 11:51:31 -0400 Subject: [PATCH 09/31] Bug fixes for GALWEM radiation. * Force radiation option to be specified in lis.config. * Revised time-handling code for fetching GALWEM GRIB2 files. * Fixed plumbing to return radiation fields from GALWEM RAD reader. --- lis/metforcing/usaf/USAF_fldbld_radflux.F90 | 29 +++++++---- .../usaf/USAF_fldbld_radflux_galwem.F90 | 51 ++++++++++++++----- lis/metforcing/usaf/readagrmetforcing.F90 | 19 +++++-- lis/metforcing/usaf/readcrd_agrmet.F90 | 20 ++++++-- 4 files changed, 85 insertions(+), 34 deletions(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 index c78502cbf..46ff0d943 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -43,6 +43,7 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) ! integer, intent(inout) :: julhr 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 @@ -80,6 +81,9 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) ! integer :: fc_hr integer :: ierr logical :: timetoReadRad + real*8 :: time + integer :: doy + real :: gmt ! Sanity check if ( agrmet_struc(n)%first_guess_source .ne. 'GALWEM' .and. & @@ -89,22 +93,27 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) end if ! Estimate julian hour to trigger reading of radiation fields: - call LIS_get_julhr(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,& - 0,0,jultmp) +! 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)%lastRadHour) then +! timeToReadRad = .true. +! else +! timeToReadRad = .false. +! endif - if(jultmp .gt. agrmet_struc(n)%lastRadHour) then - timeToReadRad = .true. - else - timeToReadRad = .false. - endif + timeToReadRad = .true. ! EMK TEST if(timeToReadRad) then !------------------------------------------------------------------ ! Find the time to start the processing from !------------------------------------------------------------------ - call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) - - julend = istart+6 + !call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) + call LIS_get_julhr(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & + LIS_rc%hr, 0, 0, istart) + + !julend = istart+6 + julend = istart agrmet_struc(n)%lastRadHour = julend diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 index 0234b10c7..7f95aa9fc 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -166,6 +166,19 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) 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 ) @@ -329,29 +342,39 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& fg_swdown1, fg_lwdown1, alert_number) - allocate ( fg_swdown (ifguess, jfguess) ) - allocate ( fg_lwdown (ifguess, jfguess) ) + !write(LIS_logunit,*)'EMK: maxval(fg_swdown1) = ', maxval(fg_swdown1) + !write(LIS_logunit,*)'EMK: maxval(fg_lwdown1) = ', maxval(fg_lwdown1) + + !allocate ( fg_swdown (ifguess, jfguess) ) + !allocate ( fg_lwdown (ifguess, jfguess) ) ! ----------------------------------------------------------------------- ! sometimes the subtraction of 3 hour radiation from 6 hour rad fluxes causes ! slightly negative radiation values, set back to 0 ! ----------------------------------------------------------------------- - where (fg_swdown .lt. 0) - fg_swdown=0 - endwhere - where (fg_lwdown .lt. 0) - fg_lwdown=0 - endwhere + !where (fg_swdown .lt. 0) + ! fg_swdown=0 + !endwhere + !where (fg_lwdown .lt. 0) + ! fg_lwdown=0 + !endwhere + !fg_swdown=0 + !fg_lwdown=0 ! Spatially interpolate native grid to target domain grid: - call interp_galwem_first_guess(n, ifguess, jfguess, .true., & - fg_swdown, fg_swdata) + !call interp_galwem_first_guess(n, ifguess, jfguess, .true., & + ! fg_swdown, fg_swdata) + !call interp_galwem_first_guess(n, ifguess, jfguess, .true., & + ! fg_lwdown, fg_lwdata) + !deallocate ( fg_swdown, fg_swdown1 ) + !deallocate ( fg_lwdown, fg_lwdown1 ) call interp_galwem_first_guess(n, ifguess, jfguess, .true., & - fg_lwdown, fg_lwdata) - - deallocate ( fg_swdown, fg_swdown1 ) - deallocate ( fg_lwdown, fg_lwdown1 ) + fg_swdown1, fg_swdata) + call interp_galwem_first_guess(n, ifguess, jfguess, .true., & + fg_lwdown1, fg_lwdata) + deallocate ( fg_swdown1 ) + deallocate ( fg_lwdown1 ) else write(LIS_logunit,*)'[WARN] ** GALWEM RADIATION FLUX data not available **' diff --git a/lis/metforcing/usaf/readagrmetforcing.F90 b/lis/metforcing/usaf/readagrmetforcing.F90 index d4158d94a..6f61f1835 100644 --- a/lis/metforcing/usaf/readagrmetforcing.F90 +++ b/lis/metforcing/usaf/readagrmetforcing.F90 @@ -363,11 +363,8 @@ subroutine readagrmetforcing(n,findex, order) ! call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) ! julend = istart+6 - if(LIS_masterproc) then - print *, "READ IN GALWEM RADIATION FIELDS -- ", yr1, mo1, da1, hr1 - print *, "order :: ",order -! print *, "istart, julend :: ",istart,julend - endif + !write(LIS_logunit,*) "EMK: READ IN GALWEM RADIATION FIELDS -- ", yr1, mo1, da1, hr1 + !write(LIS_logunit,*) "EMK: order = ", order ! Call to the NWP Radiation Flux main routines: ! Target fields: swdown(lnc,lnr), longwv(lnc,lnr) @@ -376,6 +373,9 @@ subroutine readagrmetforcing(n,findex, order) endif + !write(LIS_logunit,*)'EMK1: maxval(swdown) = ', maxval(swdown) + !write(LIS_logunit,*)'EMK1: maxval(longwv) = ', maxval(longwv) + ! 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, & @@ -493,6 +493,9 @@ subroutine readagrmetforcing(n,findex, order) ! 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 r2_ps = 0.0 @@ -581,6 +584,9 @@ subroutine readagrmetforcing(n,findex, order) endwhere endif + !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) @@ -607,6 +613,9 @@ subroutine readagrmetforcing(n,findex, order) 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) diff --git a/lis/metforcing/usaf/readcrd_agrmet.F90 b/lis/metforcing/usaf/readcrd_agrmet.F90 index b8bb7cd77..cefd59aec 100644 --- a/lis/metforcing/usaf/readcrd_agrmet.F90 +++ b/lis/metforcing/usaf/readcrd_agrmet.F90 @@ -448,19 +448,29 @@ subroutine readcrd_agrmet() call ESMF_ConfigGetAttribute(LIS_config,agrmet_struc(n)%retroFileRoot,rc=rc) enddo - ! New AGRMET radiation option -- GALWEM-based inputs (KRA) = GALWEM_RAD: + ! 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) - ! "cloud types" is default for WWMCA Grib files: + 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 -! -- TEMPORARY -- KRA -- GALWEM RADIATION FILE READER: +! 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 -! -- TEMPORARY -- + call ESMF_ConfigGetAttribute(LIS_config,LIS_rc%security_class,& From 163135c4c393b4e5df3ab21f317d49cf1acf9032 Mon Sep 17 00:00:00 2001 From: Ehsan Jalilvand Date: Fri, 7 Jun 2024 15:45:45 -0400 Subject: [PATCH 10/31] Fixed issues by removing unnecessary six-hour offset in file time for SMOPS version 4. Added an if statments to conditionally apply the offset based on the file version --- .../obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 index 6bcba69c5..7a0280eb2 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 @@ -144,14 +144,15 @@ subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) else write(LIS_logunit,*) '[WARN] Missing SMOPS ',trim(fname) endif - + SMOPS_ASCATsm_struc(n)%smobs = LIS_rc%udef SMOPS_ASCATsm_struc(n)%smtime = -1 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)) @@ -190,6 +191,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 @@ -320,7 +322,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) @@ -519,7 +520,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 @@ -534,10 +535,14 @@ 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 + file_time = file_time+offset + endif endif if ( file_time < SMOPS_ASCATsm_struc(n)%version3_time ) then @@ -1135,7 +1140,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, & From 3f78b58be384812673940ff252eb026b554ee2e1 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Fri, 7 Jun 2024 15:47:46 -0400 Subject: [PATCH 11/31] Increased "give up" forecast hour to 30. This allows LIS to search for 4 GALWEM cycles for almost all hourly time steps. For the very last time step for Ops (12 hours), this will allow LIS to check 5 GALWEM cycles. --- lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 index 7f95aa9fc..4cbfa5e4d 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -187,7 +187,9 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) if ( (.not. first_time) .or. & (first_time .and. fc_hr < 6)) then fc_hr = fc_hr + 6 - if (fc_hr > 24) exit ! Give up + !if (fc_hr > 24) exit ! Give up + if (fc_hr > 30) exit ! Give up + file_julhr = file_julhr - 6 call LIS_julhr_date(file_julhr,yr1,mo1,da1,hr1) end if From 17edc57fdc343672402012b9b12672c6e6633d14 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Fri, 7 Jun 2024 17:18:43 -0400 Subject: [PATCH 12/31] First cut at GFS radiation reader. Code compiles, but has not been run yet. KNOWN ISSUE: Reader expects hourly GFS files, but it may only be 3-hourly. --- lis/metforcing/usaf/USAF_fldbld_radflux.F90 | 4 +- .../usaf/USAF_fldbld_radflux_gfs.F90 | 390 ++++++++++++++++++ 2 files changed, 392 insertions(+), 2 deletions(-) create mode 100644 lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 index 46ff0d943..a601f7e4f 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -163,7 +163,7 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) write(LIS_logunit,*)'[WARN] Rolling back to GFS...' end if -! call USAF_fldbld_radflux_gfs(n,order,julhr,rc) + call USAF_fldbld_radflux_gfs(n, julhr, swdown, longwv, rc) if (rc .ne. 0) then call AGRMET_julhr_date10(julhr, yyyymmddhh) @@ -190,5 +190,5 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) end if endif ! End to timeToReadRad check - + end subroutine USAF_fldbld_radflux 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..07c5dfe2d --- /dev/null +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 @@ -0,0 +1,390 @@ +!-----------------------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, 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 + + ! 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, igrib + character*250 :: avnfile, avnfile2 + integer :: yr1, mo1, da1, hr1 + integer :: fc_hr + character*255 :: message ( 20 ) + integer :: iginfo ( 2 ) + real :: gridres + integer :: alert_number + real, allocatable :: fg_swdown ( : , : ) + real, allocatable :: fg_swdown1 ( : , : ) + real, allocatable :: fg_lwdown ( : , : ) + real, allocatable :: fg_lwdown1 ( : , : ) + integer :: ifguess, jfguess + integer :: center + integer :: ierr + logical*1 :: found, found2 + logical :: first_time + integer :: yr_2d + integer :: file_julhr + integer :: dataDate, dataTime + character*100 :: gtype + logical :: found_inq + + ! 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) + + 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 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) + + ! 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 (defined USE_GRIBAPI) + if (found_inq) then + call grib_open_file(ftn, trim(avnfile), 'r', ierr) + else + ierr = 1 + end if + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed to open first guess - ', & + trim(avnfile) + else + ! Extract some information + call grib_new_from_file(ftn, igrib, ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Failed file read check - ' // & + trim(avnfile) + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib, 'centre', center, ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: centre in ' // & + 'USAF_fldbld_radflux_gfs' + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib, 'gridType', gtype, ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: gridType in ' // & + 'USAF_fldbld_radflux_gfs' + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib, 'Ni', iginfo(1), ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: Ni in ' // & + 'USAF_fldbld_radflux_gfs' + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib, 'Nj', iginfo(2), ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) '[WARN] Cannot read: Nj in ' // & + 'USAF_fldbld_radflux_gfs' + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib, 'jDirectionIncrementInDegrees', gridres, & + ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: jDirectionIncrementInDegrees in ' // & + 'USAF_fldbld_radflux_gfs' + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib, 'dataDate', dataDate, ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: dataDate in ' // & + 'USAF_fldbld_radflux_gfs' + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + call grib_get(igrib, 'dataTime', dataTime, ierr) + if ( ierr /= 0 ) then + write(LIS_logunit,*) & + '[WARN] Cannot read: dataTime in ' // & + 'USAF_fldbld_radflux_gfs' + call grib_release(igrib, ierr) + call grib_close_file(ftn) + cycle + endif + + 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) + endif +#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 NWP Radiation fields from ',trim(avnfile) + rc = 0 + + if (center == 7) then + write(LIS_logunit,*) '[INFO] Data is from GFS model' + end if + + write(LIS_logunit,*)'- FIRST GUESS DATA IS ON A ', gridres,& + ' DEGREE LAT/LON GRID' + ifguess = iginfo(1) + jfguess = iginfo(2) + + allocate ( fg_swdown1 (ifguess, jfguess) ) + allocate ( fg_lwdown1 (ifguess, jfguess) ) + + ! Get radiation for this julian hour + alert_number = 0 + call USAF_fldbld_read_radflux_gfs(avnfile, ifguess, jfguess, & + fg_swdown1, fg_lwdown1, alert_number) + + ! 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) +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_coreMod, only : LIS_masterproc + 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*9 :: cstat + character*255 :: message ( 20 ) + integer :: count_swdown + integer :: count_lwdown + integer :: i + integer :: ierr + integer :: istat1 + integer :: j + integer :: k, c, r + integer :: ftn, igrib, nvars + integer :: param_disc_val, param_cat_val, & + param_num_val, forecasttime_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 first guess 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 + From b5639a145c05cd12cb7281d24f613a70b9d0f2cc Mon Sep 17 00:00:00 2001 From: Ehsan Jalilvand Date: Fri, 7 Jun 2024 17:19:16 -0400 Subject: [PATCH 13/31] add offset hours for version 3.0 through LIS_date2time subroutine instead of direct addition to the file_time --- lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 index 7a0280eb2..205522304 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 @@ -541,7 +541,8 @@ subroutine read_SMOPS_ASCAT_data(n, k, fname, smobs_ip, smtime_ip) 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 - file_time = file_time+offset + hr1 = LIS_rc%hr+offset + call LIS_date2time(file_time,updoy,upgmt,yr1,mo1,da1,hr1,mn1,ss1) endif endif From 71311cefa2b8847f1968bee3ac29ccfd88c1b9d1 Mon Sep 17 00:00:00 2001 From: "Kristi R. Arsenault" Date: Mon, 10 Jun 2024 09:26:15 -0400 Subject: [PATCH 14/31] Add new top-40cm layer soil moisture s2s metric Added new top-40cm layer soil moisture s2s metric product to the s2smetric postprocessing step of the S2S E2ES. - Updates made to two python scripts and addition in the Python config file: s2s_config_global_fcast - Top two soil layers are integrated, similar to the root-zone soil moisture layer (which is done for the top 1-meter). - Calculates the anomaly and standardized anomaly metrics and written to *TIF files and added to the *NC files. This is for the next LIS support 7.5.x patch. --- lis/utils/usaf/s2s/s2s_app/s2s_config_global_fcast | 2 +- .../s2s/s2s_modules/s2smetric/convert_s2s_anom_cf.py | 3 +++ .../s2s_modules/s2smetric/metrics_library/metricslib.py | 9 +++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) 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/s2smetric/convert_s2s_anom_cf.py b/lis/utils/usaf/s2s/s2s_modules/s2smetric/convert_s2s_anom_cf.py index 81fbeefcd..9bedeba61 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 From 27ed65426eddffa1fa96161741219d5a806da716 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Mon, 10 Jun 2024 15:10:15 -0400 Subject: [PATCH 15/31] Revisions to time logic for GFS radiation. GFS files are assumed to only be available every 3 hours. Each file will be applied +/- 1 hour from valid time. Tests do show radiation is being remapped and used, and appears to agree with contents of GFS GRIB2 file. More testing underway. --- .../usaf/USAF_fldbld_radflux_gfs.F90 | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 index 07c5dfe2d..6337f11ed 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 @@ -66,18 +66,32 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & file_julhr = julhr ! Decremented below call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) + !write(LIS_logunit,*)'EMK1: yr1, mo1, da1, hr1 = ', & + ! yr1, mo1, da1, hr1 + + ! GFS is only available 3-hrly in NCEI archive, so we will use that + ! here if (hr1 == 1 .or. hr1 == 7 .or. hr1 == 13 .or. hr1 == 19) then - fc_hr = 1 + fc_hr = 0 + file_julhr = file_julhr - 1 else if (hr1 == 2 .or. hr1 == 8 .or. hr1 == 14 .or. hr1 == 20) then - fc_hr = 2 + fc_hr = 3 + file_julhr = file_julhr - 2 else if (hr1 == 3 .or. hr1 == 9 .or. hr1 == 15 .or. hr1 == 21) then fc_hr = 3 + file_julhr = file_julhr - 3 else if (hr1 == 4 .or. hr1 == 10 .or. hr1 == 16 .or. hr1 == 22) then - fc_hr = 4 + fc_hr = 3 + file_julhr = file_julhr - 4 else if (hr1 == 5 .or. hr1 == 11 .or. hr1 == 17 .or. hr1 == 23) then - fc_hr = 5 + fc_hr = 6 + file_julhr = file_julhr - 5 end if - file_julhr = file_julhr - fc_hr + !file_julhr = file_julhr - fc_hr + + call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) + !write(LIS_logunit,*)'EMK2: yr1, mo1, da1, hr1 = ', & + ! yr1, mo1, da1, hr1 found = .false. first_time = .true. @@ -90,6 +104,9 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & if (fc_hr > 30) exit ! Give up file_julhr = file_julhr - 6 call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) + !write(LIS_logunit,*)'EMK3: yr1, mo1, da1, hr1 = ', & + ! yr1, mo1, da1, hr1 + end if first_time = .false. From 50e2c7e2fc5c6d6cf31908a63c369d128c1a139d Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Mon, 10 Jun 2024 18:06:00 -0400 Subject: [PATCH 16/31] Code clean-up. Compiles, but have not rerun yet. --- lis/metforcing/usaf/USAF_fldbld_radflux.F90 | 161 ++++++---------- .../usaf/USAF_fldbld_radflux_galwem.F90 | 181 +++++++----------- .../usaf/USAF_fldbld_radflux_gfs.F90 | 39 ++-- lis/metforcing/usaf/readagrmetforcing.F90 | 12 +- 4 files changed, 141 insertions(+), 252 deletions(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 index a601f7e4f..f60b3a195 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -22,8 +22,7 @@ ! 28 May 2024 Generated reader for radiation fluxese...K. Arsenault/SAIC ! ! !INTERFACE: -!subroutine USAF_fldbld_radflux(n,order,julhr,swdown,longwv) -subroutine USAF_fldbld_radflux(n,order,swdown,longwv) +subroutine USAF_fldbld_radflux(n,swdown,longwv) ! !USES: use AGRMET_forcingMod, only : agrmet_struc @@ -39,8 +38,6 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) implicit none ! !ARGUMENTS: integer, intent(in) :: n - integer, intent(in) :: order -! integer, intent(inout) :: julhr real, intent(out) :: swdown(LIS_rc%lnc(n), LIS_rc%lnr(n)) real, intent(out) :: longwv(LIS_rc%lnc(n), LIS_rc%lnr(n)) @@ -53,12 +50,6 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) ! \begin{description} ! \item[n] ! index of the nest -! \item[order] -! flag to indicate which data is to be read \newline -! 1 = end time \newline -! 2 = start time -! \item[julhr] -! julian hour used to determine names of forecast files from previous cycles ! \end{description} ! ! The routines invoked are: @@ -74,16 +65,14 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) character(len=255) :: message(20) character(len=10) :: yyyymmddhh integer :: julhr - integer :: jultmp integer :: istart integer :: julend - integer :: ordertmp ! Temporary placeholder -! integer :: fc_hr integer :: ierr - logical :: timetoReadRad - real*8 :: time - integer :: doy - real :: gmt + + ! 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. & @@ -92,103 +81,63 @@ subroutine USAF_fldbld_radflux(n,order,swdown,longwv) call LIS_endrun end if - ! Estimate julian hour to trigger reading of radiation fields: -! 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)%lastRadHour) then -! timeToReadRad = .true. -! else -! timeToReadRad = .false. -! endif - - timeToReadRad = .true. ! EMK TEST - - if(timeToReadRad) then !------------------------------------------------------------------ ! Find the time to start the processing from !------------------------------------------------------------------ - !call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) - call LIS_get_julhr(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & - LIS_rc%hr, 0, 0, istart) - - !julend = istart+6 - julend = istart - - agrmet_struc(n)%lastRadHour = julend - -! ------------------------------------------------------------------ -! check if the current instance is a restart or continuation of a run -! if the run is a cold start, read current and previous 6 hour data -! else copy the current to previous and read the new current data. -! ------------------------------------------------------------------ - if(agrmet_struc(n)%findtime1.eq.1.and.agrmet_struc(n)%findtime2.eq.1) then - ordertmp = 2 -! order = 2 -! call AGRMET_fldbld(n,order,istart) - -! order = 1 -! call AGRMET_fldbld(n,order,julend) - else - ordertmp = 1 -! order = 1 -! call AGRMET_fldbld(n,order,julend) - endif - - ! 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 + call LIS_get_julhr(LIS_rc%yr, LIS_rc%mo, LIS_rc%da, & + LIS_rc%hr, 0, 0, istart) + + julend = istart - ! Try fetching GALWEM, if requested - ierr = 0 - if ( agrmet_struc(n)%first_guess_source == 'GALWEM' ) then + agrmet_struc(n)%lastRadHour = julend - julhr = julend ! KRA -- Temporary placeholder + ! 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 -! fc_hr = LIS_rc%hr ! KRA - TEMPORARY PLACEHOLDER FOR FC_HR ... -! write(LIS_logunit,*) '[INFO] NWP radiation fc_hr: ',fc_hr + julhr = julend + call USAF_fldbld_radflux_galwem(n,julhr,swdown,longwv,rc) + ierr = rc + end if -! call USAF_fldbld_radflux_galwem(n,julhr,fc_hr,swdown,longwv,rc) - call USAF_fldbld_radflux_galwem(n,julhr,swdown,longwv,rc) - ierr = rc + ! 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 - ! 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,*) ' 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 '//& + 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 - - endif ! End to timeToReadRad check - + 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 index 4cbfa5e4d..f15f5281d 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -20,25 +20,24 @@ ! ...........................................K. Arsenault/SAIC ! ! !INTERFACE: -!subroutine USAF_fldbld_radflux_galwem(n,julhr,fc_hr,fg_swdata,fg_lwdata,rc) 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 - use AGRMET_forcingMod, only : agrmet_struc #if (defined USE_GRIBAPI) use grib_api #endif implicit none + ! !ARGUMENTS: integer, intent(in) :: n integer :: julhr -! integer :: fc_hr 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 @@ -101,9 +100,6 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) ! \item[found] ! logical flag set true when an input file with the correct valid ! time is found -! \item[found2] -! 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] @@ -132,29 +128,32 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) ! \end{description} !EOP integer :: ftn, igrib - character*250 :: avnfile, avnfile2 + character*250 :: avnfile integer :: yr1, mo1, da1, hr1 integer :: fc_hr character*255 :: message ( 20 ) integer :: iginfo ( 2 ) real :: gridres integer :: alert_number - real, allocatable :: fg_swdown ( : , : ) real, allocatable :: fg_swdown1 ( : , : ) - real, allocatable :: fg_lwdown ( : , : ) real, allocatable :: fg_lwdown1 ( : , : ) integer :: ifguess, jfguess integer :: center integer :: ierr - logical*1 :: found, found2 + logical*1 :: found logical :: first_time integer :: yr_2d integer :: file_julhr -! integer :: getsixhr 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. @@ -318,78 +317,38 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) rc = 0 - if( found ) then - write(LIS_logunit,*)'- FIRST GUESS DATA IS ON A ', gridres,& - ' DEGREE LAT/LON GRID' - ifguess = iginfo(1) - jfguess = iginfo(2) + 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,*)'- FIRST GUESS DATA IS FROM UK UM (GALWEM) MODEL' - else - write(LIS_logunit,*)'- UNKNOWN SOURCE FOR FIRST GUESS DATA' - end if + if (center .eq. 57) then + write(LIS_logunit,*) & + '[INFO FIRST GUESS DATA IS FROM UK UM (GALWEM) MODEL' + else + write(LIS_logunit,*)'[INFO UNKNOWN SOURCE FOR FIRST GUESS DATA' + 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. -! ------------------------------------------------------------------ - alert_number = 0 - - call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& - fg_swdown1, fg_lwdown1, alert_number) - - !write(LIS_logunit,*)'EMK: maxval(fg_swdown1) = ', maxval(fg_swdown1) - !write(LIS_logunit,*)'EMK: maxval(fg_lwdown1) = ', maxval(fg_lwdown1) - - !allocate ( fg_swdown (ifguess, jfguess) ) - !allocate ( fg_lwdown (ifguess, jfguess) ) - -! ----------------------------------------------------------------------- -! sometimes the subtraction of 3 hour radiation from 6 hour rad fluxes causes -! slightly negative radiation values, set back to 0 -! ----------------------------------------------------------------------- - !where (fg_swdown .lt. 0) - ! fg_swdown=0 - !endwhere - !where (fg_lwdown .lt. 0) - ! fg_lwdown=0 - !endwhere - !fg_swdown=0 - !fg_lwdown=0 - - ! Spatially interpolate native grid to target domain grid: - !call interp_galwem_first_guess(n, ifguess, jfguess, .true., & - ! fg_swdown, fg_swdata) - !call interp_galwem_first_guess(n, ifguess, jfguess, .true., & - ! fg_lwdown, fg_lwdata) - !deallocate ( fg_swdown, fg_swdown1 ) - !deallocate ( fg_lwdown, fg_lwdown1 ) - - 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 ) +! ------------------------------------------------------------------ +! allocate first guess grid-specific variables. +! ------------------------------------------------------------------ + allocate ( fg_swdown1 (ifguess, jfguess) ) + allocate ( fg_lwdown1 (ifguess, jfguess) ) - else - write(LIS_logunit,*)'[WARN] ** GALWEM RADIATION FLUX data not available **' - - message(1) = 'Program: LIS' - message(2) = ' Routine: USAF_fldbld_radflux_galwem.' - message(3) = ' galwem radiation flux data not available, ' // & - 'possible degradation.' - alert_number = alert_number + 1 - if(LIS_masterproc) then - call LIS_alert( 'fldbld ', alert_number, message ) - endif - endif +! ------------------------------------------------------------------ +! read in first guess data for this julian hour. +! ------------------------------------------------------------------ + alert_number = 0 + call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& + fg_swdown1, fg_lwdown1, alert_number) + + ! 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 ) end subroutine USAF_fldbld_radflux_galwem @@ -406,10 +365,10 @@ end subroutine USAF_fldbld_radflux_galwem ! ...........................................K. Arsenault/SAIC ! ! !INTERFACE: -subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& - fg_swdown, fg_lwdown, alert_number ) +subroutine USAF_fldbld_read_radflux_galwem(fg_filename, & + ifguess, jfguess, fg_swdown, fg_lwdown, alert_number ) + ! !USES: - use LIS_coreMod, only : LIS_masterproc use LIS_logMod, only : LIS_logunit, LIS_abort, LIS_alert, LIS_verify #if (defined USE_GRIBAPI) @@ -417,6 +376,7 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& #endif implicit none + ! !ARGUMENTS: character(len=*), intent(in) :: fg_filename integer, intent(in) :: ifguess @@ -480,11 +440,9 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& character*255 :: message ( 20 ) integer :: count_swdown integer :: count_lwdown - integer :: i integer :: ierr integer :: istat1 - integer :: j - integer :: k, c, r + integer :: k integer :: ftn, igrib, nvars integer :: param_disc_val, param_cat_val, & param_num_val, forecasttime_val @@ -511,8 +469,9 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& call LIS_verify(ierr,'[WARN] FILE NOT FOUND - '//trim(fg_filename)) #if (defined USE_GRIBAPI) - call grib_open_file(ftn,trim(fg_filename),'r',ierr) - call LIS_verify(ierr,'[WARN] (3) Failed to open in read routine - '//trim(fg_filename)) + call grib_open_file(ftn, trim(fg_filename), 'r', ierr) + call LIS_verify(ierr, & + '[WARN] Failed to open in read routine - '//trim(fg_filename)) if ( ierr == 0 ) then allocate ( dum1d (ifguess*jfguess) ) @@ -520,7 +479,8 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& count_lwdown = 0 write(LIS_logunit,*)' ' - write(LIS_logunit,*)'[INFO] Reading first guess GALWEM radiation fluxes ' + write(LIS_logunit,*) & + '[INFO] Reading first guess GALWEM radiation fluxes ' write(LIS_logunit,*) trim(fg_filename) call grib_count_in_file(ftn,nvars,ierr) @@ -533,17 +493,20 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& call LIS_verify(ierr, '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_galwem') + call LIS_verify(ierr, & + 'error in grib_get: parameterNumber in ' // & + 'USAF_fldbld_read_radflux_galwem') call grib_get(igrib,'parameterCategory',param_cat_val,ierr) - call LIS_verify(ierr, 'error in grib_get: parameterCategory in ' // & - 'USAF_fldbld_read_radflux_galwem') + call LIS_verify(ierr, & + 'error in grib_get: parameterCategory in ' // & + 'USAF_fldbld_read_radflux_galwem') call grib_get(igrib,'parameterNumber',param_num_val,ierr) - call LIS_verify(ierr, 'error in grib_get: parameterNumber in ' // & - 'USAF_fldbld_read_radflux_galwem') - + call LIS_verify(ierr, & + 'error in grib_get: parameterNumber in ' // & + 'USAF_fldbld_read_radflux_galwem') + call grib_get(igrib,'forecastTime',forecasttime_val,ierr) call LIS_verify(ierr, 'error in grib_get: forecastTime in ' // & 'USAF_fldbld_read_radflux_galwem') @@ -551,20 +514,17 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& ! SW Down Radiation flux: if ( param_disc_val == 0 .and. param_cat_val == 4 .and. & param_num_val == 7 ) then -! param_num_val == 7 .and. forecasttime_val == 0 ) then - call grib_get(igrib,'values',dum1d,ierr) - call LIS_verify(ierr, 'error in grib_get: SWdown values in ' // & - 'USAF_fldbld_read_radflux_galwem') - if ( ierr == 0 ) then + call grib_get(igrib, 'values', dum1d, ierr) + call LIS_verify(ierr, & + 'error in grib_get: SWdown values in ' // & + 'USAF_fldbld_read_radflux_galwem') + if ( ierr == 0 ) then ! ------------------------------------------------------------------ ! store SW radiation flux to the fg_swdown array. ! ------------------------------------------------------------------ fg_swdown = reshape(dum1d, (/ifguess,jfguess/)) count_swdown = count_swdown + 1 - ! found swdown; clean up and break out of do-loop. -! call grib_release(igrib,ierr) -! exit else write(cstat,'(i9)',iostat=istat1) ierr message(1) = 'Program: LIS' @@ -582,11 +542,11 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& ! LW Down Radiation flux: if ( param_disc_val == 0 .and. param_cat_val == 5 .and. & param_num_val == 3 ) then -! param_num_val == 3 .and. forecasttime_val == 0 ) then - call grib_get(igrib,'values',dum1d,ierr) - call LIS_verify(ierr, 'error in grib_get: LWdown values in ' // & - 'USAF_fldbld_read_radflux_galwem') + call grib_get(igrib, 'values', dum1d, ierr) + call LIS_verify(ierr, & + 'error in grib_get: LWdown values in ' // & + 'USAF_fldbld_read_radflux_galwem') if ( ierr == 0 ) then ! ------------------------------------------------------------------ ! store LW radiation flux to the fg_lwdown array. @@ -596,7 +556,8 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, ifguess, jfguess,& else write(cstat,'(i9)',iostat=istat1) ierr message(1) = 'Program: LIS' - message(2) = ' Subroutine: USAF_fldbld_read_radflux_galwem.' + message(2) = & + ' Subroutine: USAF_fldbld_read_radflux_galwem.' message(3) = ' Error reading first guess file:' message(4) = ' ' // trim(fg_filename) if( istat1 .eq. 0 )then diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 index 6337f11ed..faf7f1ec7 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 @@ -14,7 +14,7 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & ! Imports use AGRMET_forcingMod, only : agrmet_struc - use LIS_coreMod, only : LIS_rc, LIS_masterproc + 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 @@ -33,22 +33,20 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & integer, intent(out):: rc ! Locals - integer :: ftn, igrib - character*250 :: avnfile, avnfile2 + integer :: ftn, igrib + character*250 :: avnfile integer :: yr1, mo1, da1, hr1 integer :: fc_hr character*255 :: message ( 20 ) integer :: iginfo ( 2 ) real :: gridres integer :: alert_number - real, allocatable :: fg_swdown ( : , : ) real, allocatable :: fg_swdown1 ( : , : ) - real, allocatable :: fg_lwdown ( : , : ) real, allocatable :: fg_lwdown1 ( : , : ) integer :: ifguess, jfguess integer :: center integer :: ierr - logical*1 :: found, found2 + logical*1 :: found logical :: first_time integer :: yr_2d integer :: file_julhr @@ -56,6 +54,11 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & character*100 :: gtype logical :: found_inq + ! External subroutines + external :: AGRMET_fg2lis + external :: getAVNfilename + external :: USAF_fldbld_read_radflux_gfs + ! Initialize return code to "no error". We will change it below if ! necessary. rc = 0 @@ -66,9 +69,6 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & file_julhr = julhr ! Decremented below call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) - !write(LIS_logunit,*)'EMK1: yr1, mo1, da1, hr1 = ', & - ! yr1, mo1, da1, hr1 - ! GFS is only available 3-hrly in NCEI archive, so we will use that ! here if (hr1 == 1 .or. hr1 == 7 .or. hr1 == 13 .or. hr1 == 19) then @@ -87,11 +87,8 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & fc_hr = 6 file_julhr = file_julhr - 5 end if - !file_julhr = file_julhr - fc_hr call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) - !write(LIS_logunit,*)'EMK2: yr1, mo1, da1, hr1 = ', & - ! yr1, mo1, da1, hr1 found = .false. first_time = .true. @@ -104,9 +101,6 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & if (fc_hr > 30) exit ! Give up file_julhr = file_julhr - 6 call LIS_julhr_date(file_julhr, yr1, mo1, da1, hr1) - !write(LIS_logunit,*)'EMK3: yr1, mo1, da1, hr1 = ', & - ! yr1, mo1, da1, hr1 - end if first_time = .false. @@ -253,8 +247,8 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & if (center == 7) then write(LIS_logunit,*) '[INFO] Data is from GFS model' end if - - write(LIS_logunit,*)'- FIRST GUESS DATA IS ON A ', gridres,& + + write(LIS_logunit,*)'[INFO] FIRST GUESS DATA IS ON A ', gridres,& ' DEGREE LAT/LON GRID' ifguess = iginfo(1) jfguess = iginfo(2) @@ -280,7 +274,6 @@ subroutine USAF_fldbld_read_radflux_gfs(fg_filename, ifguess, jfguess, & fg_swdown, fg_lwdown, alert_number ) ! Imports - 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 @@ -298,18 +291,14 @@ subroutine USAF_fldbld_read_radflux_gfs(fg_filename, ifguess, jfguess, & integer, intent(inout) :: alert_number ! Locals - character*9 :: cstat character*255 :: message ( 20 ) integer :: count_swdown integer :: count_lwdown - integer :: i integer :: ierr - integer :: istat1 - integer :: j - integer :: k, c, r + integer :: k integer :: ftn, igrib, nvars integer :: param_disc_val, param_cat_val, & - param_num_val, forecasttime_val + param_num_val real, allocatable :: dum1d ( : ) logical :: found_inq @@ -371,7 +360,7 @@ subroutine USAF_fldbld_read_radflux_gfs(fg_filename, ifguess, jfguess, & 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 diff --git a/lis/metforcing/usaf/readagrmetforcing.F90 b/lis/metforcing/usaf/readagrmetforcing.F90 index 6f61f1835..c05483657 100644 --- a/lis/metforcing/usaf/readagrmetforcing.F90 +++ b/lis/metforcing/usaf/readagrmetforcing.F90 @@ -360,22 +360,12 @@ subroutine readagrmetforcing(n,findex, order) ! -- KRA: Initial setup if ( agrmet_struc(n)%compute_radiation == 'GALWEM_RAD' ) then -! call find_agrfld_starttime(LIS_rc%yr,LIS_rc%mo,LIS_rc%da,LIS_rc%hr,istart) -! julend = istart+6 - - !write(LIS_logunit,*) "EMK: READ IN GALWEM RADIATION FIELDS -- ", yr1, mo1, da1, hr1 - !write(LIS_logunit,*) "EMK: order = ", order - ! Call to the NWP Radiation Flux main routines: ! Target fields: swdown(lnc,lnr), longwv(lnc,lnr) -! call USAF_fldbld_radflux(n,order,julend,swdown,longwv) - call USAF_fldbld_radflux(n,order,swdown,longwv) + call USAF_fldbld_radflux(n,swdown,longwv) endif - !write(LIS_logunit,*)'EMK1: maxval(swdown) = ', maxval(swdown) - !write(LIS_logunit,*)'EMK1: maxval(longwv) = ', maxval(longwv) - ! 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, & From 6f2bc4a9f190358eabc382ad8914f0e79a4b62b5 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Tue, 11 Jun 2024 17:02:15 -0400 Subject: [PATCH 17/31] Revised GFS radiation reader to handle time-averaged fields. Further work is halted. It is what it is. --- .../usaf/USAF_fldbld_radflux_gfs.F90 | 485 +++++++++++++----- 1 file changed, 356 insertions(+), 129 deletions(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 index faf7f1ec7..920b5242f 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_gfs.F90 @@ -33,30 +33,34 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & integer, intent(out):: rc ! Locals - integer :: ftn, igrib - character*250 :: avnfile + 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 ) - real :: gridres + integer :: iginfo(2), iginfo2(2) + real :: gridres, gridres2 integer :: alert_number - real, allocatable :: fg_swdown1 ( : , : ) - real, allocatable :: fg_lwdown1 ( : , : ) - integer :: ifguess, jfguess - integer :: center - integer :: ierr - logical*1 :: found + 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, dataTime - character*100 :: gtype - logical :: found_inq + integer :: dataDate, dataDate2 + integer :: dataTime, dataTime2 + character*100 :: gtype, gtype2 + logical :: found_inq, found_inq2 + integer :: getsixhr ! External subroutines external :: AGRMET_fg2lis - external :: getAVNfilename + external :: getAVNfilename, getAVNfilename2 external :: USAF_fldbld_read_radflux_gfs ! Initialize return code to "no error". We will change it below if @@ -69,25 +73,42 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & 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 - if (hr1 == 1 .or. hr1 == 7 .or. hr1 == 13 .or. hr1 == 19) then - fc_hr = 0 - file_julhr = file_julhr - 1 + ! 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 = 3 - file_julhr = file_julhr - 2 + fc_hr = 9 + file_julhr = file_julhr - 8 else if (hr1 == 3 .or. hr1 == 9 .or. hr1 == 15 .or. hr1 == 21) then - fc_hr = 3 - file_julhr = file_julhr - 3 + fc_hr = 12 + file_julhr = file_julhr - 9 else if (hr1 == 4 .or. hr1 == 10 .or. hr1 == 16 .or. hr1 == 22) then - fc_hr = 3 - file_julhr = file_julhr - 4 + fc_hr = 12 + file_julhr = file_julhr - 10 else if (hr1 == 5 .or. hr1 == 11 .or. hr1 == 17 .or. hr1 == 23) then - fc_hr = 6 - file_julhr = file_julhr - 5 + 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. @@ -112,6 +133,13 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & 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) @@ -119,109 +147,275 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & 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) - if (found_inq) then - call grib_open_file(ftn, trim(avnfile), 'r', ierr) - else - ierr = 1 - end if + call grib_open_file(ftn, trim(avnfile), 'r', ierr) if ( ierr /= 0 ) then write(LIS_logunit,*) '[WARN] Failed to open first guess - ', & trim(avnfile) - else - ! Extract some information - call grib_new_from_file(ftn, igrib, ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] Failed file read check - ' // & - trim(avnfile) - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - call grib_get(igrib, 'centre', center, ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] Cannot read: centre in ' // & - 'USAF_fldbld_radflux_gfs' - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - call grib_get(igrib, 'gridType', gtype, ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] Cannot read: gridType in ' // & - 'USAF_fldbld_radflux_gfs' - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - call grib_get(igrib, 'Ni', iginfo(1), ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] Cannot read: Ni in ' // & - 'USAF_fldbld_radflux_gfs' - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - call grib_get(igrib, 'Nj', iginfo(2), ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] Cannot read: Nj in ' // & - 'USAF_fldbld_radflux_gfs' - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - call grib_get(igrib, 'jDirectionIncrementInDegrees', gridres, & - ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) & - '[WARN] Cannot read: jDirectionIncrementInDegrees in ' // & - 'USAF_fldbld_radflux_gfs' - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - call grib_get(igrib, 'dataDate', dataDate, ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) & - '[WARN] Cannot read: dataDate in ' // & - 'USAF_fldbld_radflux_gfs' - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - call grib_get(igrib, 'dataTime', dataTime, ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) & - '[WARN] Cannot read: dataTime in ' // & - 'USAF_fldbld_radflux_gfs' - call grib_release(igrib, ierr) - call grib_close_file(ftn) - cycle - endif - - 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) + flush(LIS_logunit) call grib_close_file(ftn) - endif + 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' @@ -241,25 +435,52 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & end if write(LIS_logunit,*) & - '[INFO] Using NWP Radiation fields from ',trim(avnfile) + '[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 is from GFS model' + write(LIS_logunit,*) '[INFO] Data are from GFS model' end if - write(LIS_logunit,*)'[INFO] FIRST GUESS DATA IS ON A ', gridres,& + 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) @@ -268,6 +489,11 @@ subroutine USAF_fldbld_radflux_gfs(n, julhr, fg_swdata, & ! 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, & @@ -322,7 +548,8 @@ subroutine USAF_fldbld_read_radflux_gfs(fg_filename, ifguess, jfguess, & count_lwdown = 0 write(LIS_logunit,*)' ' - write(LIS_logunit,*)'[INFO] Reading first guess GFS radiation fluxes' + write(LIS_logunit,*) & + '[INFO] Reading time-averaged GFS radiation fluxes' write(LIS_logunit,*) trim(fg_filename) call grib_count_in_file(ftn, nvars, ierr) From 045fe91f197874a728aff9bd302ef2a71690946e Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Wed, 12 Jun 2024 12:22:23 -0400 Subject: [PATCH 18/31] Revisions to improve fault tolerance. Also, add alert files. --- .../usaf/USAF_fldbld_radflux_galwem.F90 | 805 ++++++++++++------ 1 file changed, 561 insertions(+), 244 deletions(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 index f15f5281d..299893b4e 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -127,14 +127,14 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) ! 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 - character*255 :: message ( 20 ) integer :: iginfo ( 2 ) real :: gridres - integer :: alert_number + integer, save :: alert_number = 1 real, allocatable :: fg_swdown1 ( : , : ) real, allocatable :: fg_lwdown1 ( : , : ) integer :: ifguess, jfguess @@ -186,7 +186,6 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) if ( (.not. first_time) .or. & (first_time .and. fc_hr < 6)) then fc_hr = fc_hr + 6 - !if (fc_hr > 24) exit ! Give up if (fc_hr > 30) exit ! Give up file_julhr = file_julhr - 6 @@ -209,6 +208,15 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) 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 @@ -219,87 +227,262 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) ! writing error messages to stdout/stderr, which may lead to runtime ! problems. - if (found_inq) then - call grib_open_file(ftn,trim(avnfile),'r',ierr) - else - ierr = 1 + 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] (1) Failed to open first guess - ',trim(avnfile) - else - ! ------------------------------------------------------------------ - ! read in the first grib record, unpack the header and extract - ! section 1 and section 2 information. - ! ------------------------------------------------------------------ - call grib_new_from_file(ftn,igrib,ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) '[WARN] (1) Failed file read check - '//trim(avnfile) - endif - - call grib_get(igrib,'centre',center,ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) 'error in grib_get: centre in ' // & - 'USAF_fldbld_radflux_galwem' - endif - - call grib_get(igrib,'gridType',gtype,ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) 'error in grid_get: gridtype in ' // & - 'USAF_fldbld_radflux_galwem' - endif - - call grib_get(igrib,'Ni',iginfo(1),ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) 'error in grid_get:Ni in ' // & - 'USAF_fldbld_radflux_galwem' - endif - - call grib_get(igrib,'Nj',iginfo(2),ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) 'error in grid_get:Nj in ' // & - 'USAF_fldbld_radflux_galwem' - endif - - call grib_get(igrib,'jDirectionIncrementInDegrees',gridres,ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) & - 'error in grid_get:jDirectionIncrementInDegrees in ' // & - 'USAF_fldbld_radflux_galwem' - endif - - call grib_get(igrib,'dataDate',dataDate,ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) 'error in grid_get:dataDate in ' // & - 'USAF_fldbld_radflux_galwem' - endif - - call grib_get(igrib,'dataTime',dataTime,ierr) - if ( ierr /= 0 ) then - write(LIS_logunit,*) 'error in grid_get:dataTime in ' // & - 'USAF_fldbld_radflux_galwem' - endif - - 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_galwem' - message(3) = ' First guess source is not a lat/lon grid' - message(4) = ' USAF_fldbld_radflux_galwem expects lat/lon data' - call lis_abort(message) - endif - endif - - call grib_release(igrib,ierr) + 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 - ! At this point, we have everything we need. + 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. +! ------------------------------------------------------------------ + alert_number = 0 + 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 @@ -312,44 +495,6 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) return end if - 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 FIRST GUESS DATA IS FROM UK UM (GALWEM) MODEL' - else - write(LIS_logunit,*)'[INFO UNKNOWN SOURCE FOR FIRST GUESS DATA' - 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. -! ------------------------------------------------------------------ - alert_number = 0 - call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& - fg_swdown1, fg_lwdown1, alert_number) - - ! 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 ) - end subroutine USAF_fldbld_radflux_galwem @@ -366,9 +511,10 @@ end subroutine USAF_fldbld_radflux_galwem ! ! !INTERFACE: subroutine USAF_fldbld_read_radflux_galwem(fg_filename, & - ifguess, jfguess, fg_swdown, fg_lwdown, alert_number ) + ifguess, jfguess, fg_swdown, fg_lwdown, rc ) -! !USES: + ! !USES: + use LIS_coreMod, only : LIS_masterproc use LIS_logMod, only : LIS_logunit, LIS_abort, LIS_alert, LIS_verify #if (defined USE_GRIBAPI) @@ -383,7 +529,7 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, & integer, intent(in) :: jfguess real, intent(out) :: fg_swdown ( ifguess,jfguess ) real, intent(out) :: fg_lwdown ( ifguess,jfguess ) - integer, intent(inout) :: alert_number + integer, intent(out) :: rc ! ! !DESCRIPTION: ! @@ -436,21 +582,23 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, & ! \end{description} ! !EOP - character*9 :: cstat - character*255 :: message ( 20 ) + character(255) :: message(20) + integer, save :: alert_number = 1 integer :: count_swdown integer :: count_lwdown integer :: ierr - integer :: istat1 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. ! ------------------------------------------------------------------ @@ -462,144 +610,313 @@ subroutine USAF_fldbld_read_radflux_galwem(fg_filename, & inquire(file=trim(fg_filename),exist=found_inq) if (.not. found_inq) then - ierr = 1 - else - ierr = 0 + 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 - call LIS_verify(ierr,'[WARN] FILE NOT FOUND - '//trim(fg_filename)) #if (defined USE_GRIBAPI) call grib_open_file(ftn, trim(fg_filename), 'r', ierr) - call LIS_verify(ierr, & - '[WARN] Failed to open in read routine - '//trim(fg_filename)) + 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 - if ( ierr == 0 ) then - allocate ( dum1d (ifguess*jfguess) ) - count_swdown = 0 - count_lwdown = 0 + write(LIS_logunit,*)' ' + write(LIS_logunit,*) & + '[INFO] Reading GALWEM radiation fluxes ' + write(LIS_logunit,*) trim(fg_filename) - write(LIS_logunit,*)' ' + call grib_count_in_file(ftn, nvars, ierr) + if (ierr /= 0) then write(LIS_logunit,*) & - '[INFO] Reading first guess GALWEM 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_galwem') - - do k = 1, nvars - - call grib_new_from_file(ftn,igrib,ierr) - call LIS_verify(ierr, '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_galwem') - - call grib_get(igrib,'parameterCategory',param_cat_val,ierr) - call LIS_verify(ierr, & - 'error in grib_get: parameterCategory in ' // & - 'USAF_fldbld_read_radflux_galwem') - - call grib_get(igrib,'parameterNumber',param_num_val,ierr) - call LIS_verify(ierr, & - 'error in grib_get: parameterNumber in ' // & - 'USAF_fldbld_read_radflux_galwem') - - call grib_get(igrib,'forecastTime',forecasttime_val,ierr) - call LIS_verify(ierr, 'error in grib_get: forecastTime in ' // & - 'USAF_fldbld_read_radflux_galwem') - - ! SW Down Radiation flux: - if ( param_disc_val == 0 .and. param_cat_val == 4 .and. & - param_num_val == 7 ) then - - call grib_get(igrib, 'values', dum1d, ierr) - call LIS_verify(ierr, & - 'error in grib_get: SWdown values in ' // & - 'USAF_fldbld_read_radflux_galwem') - if ( ierr == 0 ) then -! ------------------------------------------------------------------ -! store SW radiation flux to the fg_swdown array. -! ------------------------------------------------------------------ - fg_swdown = reshape(dum1d, (/ifguess,jfguess/)) - count_swdown = count_swdown + 1 - else - write(cstat,'(i9)',iostat=istat1) ierr - message(1) = 'Program: LIS' - message(2) = ' Subroutine: AGRMET_fldbld_read.' - message(3) = ' Error reading first guess file:' - message(4) = ' ' // trim(fg_filename) - if( istat1 .eq. 0 )then - message(5) = ' Status = ' // trim(cstat) - endif - if ( allocated(dum1d) ) deallocate(dum1d) - call LIS_abort( message) - endif - endif ! SWdown - - ! LW Down Radiation flux: - if ( param_disc_val == 0 .and. param_cat_val == 5 .and. & - param_num_val == 3 ) then - - call grib_get(igrib, 'values', dum1d, ierr) - call LIS_verify(ierr, & - 'error in grib_get: LWdown values in ' // & - 'USAF_fldbld_read_radflux_galwem') - if ( ierr == 0 ) then -! ------------------------------------------------------------------ -! store LW radiation flux to the fg_lwdown array. -! ------------------------------------------------------------------ - fg_lwdown = reshape(dum1d, (/ifguess,jfguess/)) - count_lwdown = count_lwdown + 1 - else - write(cstat,'(i9)',iostat=istat1) ierr - message(1) = 'Program: LIS' - message(2) = & - ' Subroutine: USAF_fldbld_read_radflux_galwem.' - message(3) = ' Error reading first guess file:' - message(4) = ' ' // trim(fg_filename) - if( istat1 .eq. 0 )then - message(5) = ' Status = ' // trim(cstat) - endif - if ( allocated(dum1d) ) deallocate(dum1d) - call LIS_abort( message) - endif - endif ! LWdown - - call grib_release(igrib,ierr) - enddo - + '[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 - deallocate ( dum1d ) + 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 -! ------------------------------------------------------------------ -! see if we have everything. if not, abort. -! ------------------------------------------------------------------ + 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 - if ( count_swdown == 0 .or. count_lwdown == 0 ) then - message(1) = 'Program: LIS' - message(2) = ' Subroutine: USAF_fldbld_read_radflux_galwem.' - 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 + 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 - else - write(cstat,'(i9)',iostat=istat1) ierr - message(1) = 'Program: LIS' - message(2) = ' Subroutine: USAF_fldbld_read_radflux_galwem.' - message(3) = ' Error opening first guess file:' - message(4) = ' ' // trim(fg_filename) - if ( istat1 == 0 ) then - message(5) = ' Status = ' // trim(cstat) - endif - call LIS_abort(message) - endif #endif end subroutine USAF_fldbld_read_radflux_galwem From e5b3a08e8fd7efb6b8a0a4a1c9e3c015de286f34 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Wed, 12 Jun 2024 13:51:05 -0400 Subject: [PATCH 19/31] Disabled GFS radiation option. --- lis/metforcing/usaf/USAF_fldbld_radflux.F90 | 69 ++++++++++++++------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 index f60b3a195..f1b921ad4 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux.F90 @@ -77,9 +77,15 @@ subroutine USAF_fldbld_radflux(n,swdown,longwv) ! 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] First guess source is not correctly defined.' + write(LIS_logunit,*) '[ERR] NWP radiation source is not correctly defined.' call LIS_endrun - end if + 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 @@ -104,33 +110,17 @@ subroutine USAF_fldbld_radflux(n,swdown,longwv) julhr = julend call USAF_fldbld_radflux_galwem(n,julhr,swdown,longwv,rc) ierr = rc - end if - - ! 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] 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 and GFS GRIB data not available for '//& + message(3) = ' GALWEM radiation data not available for '//& yyyymmddhh if (LIS_masterproc) then call LIS_alert( 'LIS.USAF_fldbld_radflux.', 1, & @@ -138,6 +128,43 @@ subroutine USAF_fldbld_radflux(n,swdown,longwv) 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 From c43e8c36f5bba4e91ab6334aa7b5b159c080f164 Mon Sep 17 00:00:00 2001 From: "James V. Geiger" Date: Thu, 13 Jun 2024 16:19:14 -0400 Subject: [PATCH 20/31] Update documentation wrt 'AGRMET radiation derived from:' setting --- lis/configs/lis.config.adoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lis/configs/lis.config.adoc b/lis/configs/lis.config.adoc index 72d6cf6f0..841a653f9 100644 --- a/lis/configs/lis.config.adoc +++ b/lis/configs/lis.config.adoc @@ -5384,14 +5384,15 @@ 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 |==== .Example _lis.config_ entry From 8a10f99aaea35243ebf8d845d947e642e3f3d921 Mon Sep 17 00:00:00 2001 From: "James V. Geiger" Date: Fri, 14 Jun 2024 08:49:52 -0400 Subject: [PATCH 21/31] Change build scripts to explicitly use Python 3 --- ldt/make/makedep.py | 2 +- lis/make/makedep.py | 2 +- lis/make/plugins.py | 2 +- lvt/make/makedep.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ldt/make/makedep.py b/ldt/make/makedep.py index a7d033e9c..ffaa79a55 100755 --- a/ldt/make/makedep.py +++ b/ldt/make/makedep.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 #-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- # NASA Goddard Space Flight Center diff --git a/lis/make/makedep.py b/lis/make/makedep.py index a7d033e9c..ffaa79a55 100755 --- a/lis/make/makedep.py +++ b/lis/make/makedep.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 #-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- # NASA Goddard Space Flight Center diff --git a/lis/make/plugins.py b/lis/make/plugins.py index a9b163790..15ecb5e98 100755 --- a/lis/make/plugins.py +++ b/lis/make/plugins.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 #-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- # NASA Goddard Space Flight Center diff --git a/lvt/make/makedep.py b/lvt/make/makedep.py index a7d033e9c..ffaa79a55 100755 --- a/lvt/make/makedep.py +++ b/lvt/make/makedep.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 #-----------------------BEGIN NOTICE -- DO NOT EDIT----------------------- # NASA Goddard Space Flight Center From df75ab89462148793ce4ea52b2765e9a9ddc2eef Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Mon, 17 Jun 2024 14:18:38 -0400 Subject: [PATCH 22/31] Code updates to handle when SMOPS ASCAT v4 file is missing. --- .../obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 index 205522304..f4b4cdf26 100755 --- a/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 +++ b/lis/dataassim/obs/SMOPS_ASCATsm/read_SMOPS_ASCATsm.F90 @@ -136,15 +136,21 @@ subroutine read_SMOPS_ASCATsm(n, k, OBS_State, OBS_Pert_State) 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 @@ -1170,7 +1176,7 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen ! 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' @@ -1200,8 +1206,8 @@ subroutine create_SMOPS_ASCATsm_filename(ndir, useRT, yr, mo,da, hr, conv, filen if(ierr.ne.0) then exit endif - !write(LIS_logunit,*) '[INFO] reading ',trim(filename) enddo + !write(LIS_logunit,*) '[INFO] Will read ',trim(filename) call LIS_releaseUnitNumber(ftn) else filename = trim(ndir)//'/smops_d' & From 15376ff7a44e7d6001535a1b0182539fd952a23f Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Fri, 21 Jun 2024 09:07:12 -0400 Subject: [PATCH 23/31] Updated FOC settings for latest patches. * Updates IMERG version and radiation settings. --- .../lis.config.global.noah39.galwem17 | 28 ++++++++------- .../lis.config.global.noahmp401.galwem17 | 27 +++++++------- .../lis.config.nrt_streamflow.noah39.rapid | 36 ++++++++++--------- .../lis.config.nrt_streamflow.noahmp401.rapid | 36 ++++++++++--------- .../input/lis.config.template | 35 +++++++++--------- 5 files changed, 88 insertions(+), 74 deletions(-) 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/utils/usaf/s2s/global_usaf_forc/input/lis.config.template b/lis/utils/usaf/s2s/global_usaf_forc/input/lis.config.template index 74a2bf7a2..57fac88d0 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: 11 +Starting hour: 12 +Starting minute: 0 +Starting second: 0 +Ending year: 2024 +Ending month: 6 +Ending day: 12 +Ending hour: 00 +Ending minute: 5 +Ending second: 0 Undefined value: -9999 Output directory: ./output Diagnostic output file: ./output/logs/lislog @@ -246,9 +247,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 +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 +AGRMET IMERG version: V07B # V07B started 1 June 2024 AGRMET IMERG Probability Liquid Precip Threshold: 100 # Bratseth runtime settings @@ -336,6 +337,8 @@ 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 +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. @@ -371,7 +374,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/restarts/LIS_RST_NOAH39_202406111200.d01.nc Noah.3.9 restart file format: netcdf Noah.3.9 vegetation parameter table: ./input/noah39_parms/VEGPARM.TBL From 9b61d889056630e633f7d1d9ae267f1df2bfb396 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Fri, 21 Jun 2024 12:40:15 -0400 Subject: [PATCH 24/31] Fixed reset of alert_number. This change prevents alert numbers from being reused when reporting missing GALWEM radiation files. Thus, it provides the user with a more accurate record of which GALWEM files are missing (alert files are not overwritten). --- lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 index 299893b4e..1da1b50ce 100644 --- a/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 +++ b/lis/metforcing/usaf/USAF_fldbld_radflux_galwem.F90 @@ -464,7 +464,6 @@ subroutine USAF_fldbld_radflux_galwem(n,julhr,fg_swdata,fg_lwdata,rc) ! ------------------------------------------------------------------ ! read in first guess data for this julian hour. ! ------------------------------------------------------------------ - alert_number = 0 call USAF_fldbld_read_radflux_galwem(avnfile, ifguess, jfguess,& fg_swdown1, fg_lwdown1, rc) From 88d5c75b35974c18a8a686d001b9c797ebfd2745 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Mon, 24 Jun 2024 14:18:47 -0400 Subject: [PATCH 25/31] Updated name of restart directory for consistency with other FOC files. --- lis/utils/usaf/s2s/global_usaf_forc/input/lis.config.template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 57fac88d0..d36e8d7c2 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 @@ -106,7 +106,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/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 @@ -374,7 +374,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_202406111200.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/noah39_parms/VEGPARM.TBL From 8682c9c9954b1b6c108ca4c2ef11264ea8ceab81 Mon Sep 17 00:00:00 2001 From: Eric Kemp Date: Mon, 24 Jun 2024 14:27:02 -0400 Subject: [PATCH 26/31] Updated perturbation restart settings. --- .../usaf/s2s/global_usaf_forc/input/lis.config.template | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 d36e8d7c2..13a158462 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 @@ -104,7 +104,10 @@ 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/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 From 9acc000fc53af0f297b688c416548cc512b9bcda Mon Sep 17 00:00:00 2001 From: "James V. Geiger" Date: Mon, 24 Jun 2024 14:40:25 -0400 Subject: [PATCH 27/31] Update LIS Users Guide for LISF 557WW 7.5.15 release --- docs/LIS_users_guide/LIS_users_guide.adoc | 4 ++-- docs/LIS_users_guide/revision_table.adoc | 1 + lis/configs/lis.config.adoc | 6 +++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/LIS_users_guide/LIS_users_guide.adoc b/docs/LIS_users_guide/LIS_users_guide.adoc index 0a53e6f1a..0dd368a82 100644 --- a/docs/LIS_users_guide/LIS_users_guide.adoc +++ b/docs/LIS_users_guide/LIS_users_guide.adoc @@ -1,6 +1,6 @@ = Land Information System (LIS): LIS {lisfrevision} Users`' Guide -:revnumber: 2.5 -:revdate: 05 Jul 2023 +:revnumber: 2.6 +:revdate: 14 Jun 2024 :doctype: book :sectnums: :toc: diff --git a/docs/LIS_users_guide/revision_table.adoc b/docs/LIS_users_guide/revision_table.adoc index 8671fe499..03d2334b6 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 |2.5 | LISF 557WW 7.5.9 release | Jul 05, 2023 |2.4 | LISF 557WW 7.5.8 release | Jun 30, 2023 |2.3 | LISF 557WW 7.5.5 release | Jun 20, 2023 diff --git a/lis/configs/lis.config.adoc b/lis/configs/lis.config.adoc index 841a653f9..2644c7335 100644 --- a/lis/configs/lis.config.adoc +++ b/lis/configs/lis.config.adoc @@ -5395,6 +5395,9 @@ Acceptable values are: |"`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/ @@ -5466,7 +5469,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 .... From be21e1aea0e9922585cccff6344decbcf97cd96c Mon Sep 17 00:00:00 2001 From: Sarith Mahanama Date: Tue, 25 Jun 2024 13:54:46 -0400 Subject: [PATCH 28/31] a quick patch for 16WW --- lis/utils/usaf/s2s/s2s_modules/shared/utils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lis/utils/usaf/s2s/s2s_modules/shared/utils.py b/lis/utils/usaf/s2s/s2s_modules/shared/utils.py index aab68a57a..c8741965c 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']) From 7cad02f0bf02cd92763a97c3a2b5950a92653206 Mon Sep 17 00:00:00 2001 From: "James V. Geiger" Date: Thu, 27 Jun 2024 12:42:33 -0400 Subject: [PATCH 29/31] Add new AGRMET related runtime configuration settings This adds: AGRMET radiation derived from: AGRMET GALWEM radiation data directory: --- ...fig.s2sglobal.noahmp401_12mem.hymap2.DARun | 2 + .../input/lis.config.template | 37 ++++++++++++++----- .../template_files/lis.config_template.GLOBAL | 2 + 3 files changed, 31 insertions(+), 10 deletions(-) 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 13a158462..9a8801963 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 @@ -36,15 +36,15 @@ Output naming style: "WMO convention" Enable output statistics: .false. Start mode: restart Starting year: 2024 -Starting month: 6 -Starting day: 11 -Starting hour: 12 +Starting month: 6 +Starting day: 1 +Starting hour: 0 Starting minute: 0 Starting second: 0 Ending year: 2024 -Ending month: 6 -Ending day: 12 -Ending hour: 00 +Ending month: 6 +Ending day: 2 +Ending hour: 0 Ending minute: 5 Ending second: 0 Undefined value: -9999 @@ -252,7 +252,10 @@ AGRMET use IMERG data: 1 # 1 = Use AGRMET IMERG temperature threshold: 278 AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG AGRMET IMERG product: 3B-HHR-E # Early Run -AGRMET IMERG version: V07B # V07B started 1 June 2024 +## 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 @@ -340,8 +343,22 @@ 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 -AGRMET radiation derived from: GALWEM_RAD # WWMCA turned off July 2024 -AGRMET GALWEM radiation data directory: GALWEM +# 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 1, 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 # Legacy AGRMET settings. Eventually these will be removed, # but for now keep these settings. @@ -377,7 +394,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/rstfiles/LIS_RST_NOAH39_202406111200.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_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. From f043be5b83095c16f859dcc16abac0bcc2fb0d46 Mon Sep 17 00:00:00 2001 From: "James V. Geiger" Date: Thu, 27 Jun 2024 15:07:34 -0400 Subject: [PATCH 30/31] Incorporate Kristi's comments --- .../usaf/s2s/global_usaf_forc/input/lis.config.template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 9a8801963..5591cdaca 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 @@ -253,9 +253,9 @@ AGRMET IMERG temperature threshold: 278 AGRMET IMERG data directory: ./input/USAF_FORCING/IMERG AGRMET IMERG product: 3B-HHR-E # Early Run ## S2S June-2024 forecast – use the following option: -AGRMET IMERG version: V06E # FOR MAY-2024 dates +#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 version: V07B # V07B started 1 June 2024 AGRMET IMERG Probability Liquid Precip Threshold: 100 # Bratseth runtime settings @@ -351,7 +351,7 @@ AGRMET cloud data directory: WWMCA_GRIB # Original i ## 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 1, 2024, 00Z +# -- 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 # From 89433a4d4c1611665f5d99ba02f5c76bc9ad25d0 Mon Sep 17 00:00:00 2001 From: "James V. Geiger" Date: Thu, 27 Jun 2024 15:52:46 -0400 Subject: [PATCH 31/31] Add missing AGRMET related runtime configuration --- lis/utils/usaf/s2s/global_usaf_forc/input/lis.config.template | 1 + 1 file changed, 1 insertion(+) 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 5591cdaca..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 @@ -359,6 +359,7 @@ AGRMET cloud data directory: WWMCA_GRIB # Original i # -- 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.