diff --git a/CMakeLists.txt b/CMakeLists.txt index 519a17200..38bcfb5ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,7 @@ find_package(nemsio 2.5.0 REQUIRED) find_package(sigio 2.3.0 REQUIRED) find_package(sp 2.3.3 REQUIRED) find_package(ip 3.3.3 REQUIRED) -find_package(g2 3.4.0 REQUIRED) +find_package(g2 3.4.3 REQUIRED) find_package(wgrib2 2.0.8 REQUIRED) find_package(sigio 2.3.0 REQUIRED) diff --git a/modulefiles/build.hera.gnu.lua b/modulefiles/build.hera.gnu.lua index 88aa5ef57..90bca87ae 100644 --- a/modulefiles/build.hera.gnu.lua +++ b/modulefiles/build.hera.gnu.lua @@ -28,7 +28,7 @@ load(pathJoin("esmf", esmf_ver)) bacio_ver=os.getenv("bacio_ver") or "2.4.1" load(pathJoin("bacio", bacio_ver)) -g2_ver=os.getenv("g2_ver") or "3.4.1" +g2_ver=os.getenv("g2_ver") or "3.4.3" load(pathJoin("g2", g2_ver)) ip_ver=os.getenv("ip_ver") or "3.3.3" diff --git a/modulefiles/build.hera.intel.lua b/modulefiles/build.hera.intel.lua index 319d7b3ed..48335e748 100644 --- a/modulefiles/build.hera.intel.lua +++ b/modulefiles/build.hera.intel.lua @@ -22,7 +22,7 @@ load(pathJoin("hpc-impi", impi_ver)) bacio_ver=os.getenv("bacio_ver") or "2.4.1" load(pathJoin("bacio", bacio_ver)) -g2_ver=os.getenv("g2_ver") or "3.4.1" +g2_ver=os.getenv("g2_ver") or "3.4.3" load(pathJoin("g2", g2_ver)) ip_ver=os.getenv("ip_ver") or "3.3.3" diff --git a/modulefiles/build.jet.intel.lua b/modulefiles/build.jet.intel.lua index 260fda2cc..50f23bb96 100644 --- a/modulefiles/build.jet.intel.lua +++ b/modulefiles/build.jet.intel.lua @@ -52,7 +52,7 @@ load(pathJoin("sfcio", sfcio_ver)) nemsio_ver=os.getenv("nemsio_ver") or "2.5.2" load(pathJoin("nemsio", nemsio_ver)) -g2_ver=os.getenv("g2_ver") or "3.4.1" +g2_ver=os.getenv("g2_ver") or "3.4.3" load(pathJoin("g2", g2_ver)) wgrib2_ver=os.getenv("wgrib2_ver") or "2.0.8" diff --git a/modulefiles/build.orion.intel.lua b/modulefiles/build.orion.intel.lua index 0fabb4ebc..d641cdaf5 100644 --- a/modulefiles/build.orion.intel.lua +++ b/modulefiles/build.orion.intel.lua @@ -19,7 +19,7 @@ load(pathJoin("hpc-impi", impi_ver)) bacio_ver=os.getenv("bacio_ver") or "2.4.1" load(pathJoin("bacio", bacio_ver)) -g2_ver=os.getenv("g2_ver") or "3.4.1" +g2_ver=os.getenv("g2_ver") or "3.4.3" load(pathJoin("g2", g2_ver)) ip_ver=os.getenv("ip_ver") or "3.3.3" diff --git a/modulefiles/build.wcoss_cray.intel b/modulefiles/build.wcoss_cray.intel index 5be5083b3..7ae0c107f 100644 --- a/modulefiles/build.wcoss_cray.intel +++ b/modulefiles/build.wcoss_cray.intel @@ -18,7 +18,6 @@ module load cray-hdf5/1.8.14 module use /usrx/local/nceplibs/NCEPLIBS/cmake/install/NCEPLIBS-v1.3.0/modules module load bacio/2.4.1 -module load g2/3.4.1 module load ip/3.3.3 module load nemsio/2.5.2 module load sp/2.3.3 @@ -31,7 +30,11 @@ setenv ZLIB_ROOT /usrx/local/prod/zlib/1.2.7/intel/haswell setenv PNG_ROOT /usrx/local/prod/png/1.2.49/intel/haswell setenv Jasper_ROOT /usrx/local/prod/jasper/1.900.1/intel/haswell +module use /usrx/local/nceplibs/NCEPLIBS/cmake/install/NCEPLIBS-v1.4.0/modules +module load g2/3.4.5 + module load esmf/820 + setenv NETCDF /opt/cray/netcdf/4.3.3.1/INTEL/14.0 module rm gcc module load gcc/6.3.0 diff --git a/modulefiles/build.wcoss_dell_p3.intel.lua b/modulefiles/build.wcoss_dell_p3.intel.lua index 427692697..0c0f3955e 100644 --- a/modulefiles/build.wcoss_dell_p3.intel.lua +++ b/modulefiles/build.wcoss_dell_p3.intel.lua @@ -43,7 +43,7 @@ load(pathJoin("esmf", esmf_ver)) bacio_ver=os.getenv("bacio_ver") or "2.4.1" load(pathJoin("bacio", bacio_ver)) -g2_ver=os.getenv("g2_ver") or "3.4.2" +g2_ver=os.getenv("g2_ver") or "3.4.5" load(pathJoin("g2", g2_ver)) ip_ver=os.getenv("ip_ver") or "3.3.3" diff --git a/reg_tests/chgres_cube/driver.wcoss_dell_p3.sh b/reg_tests/chgres_cube/driver.wcoss_dell_p3.sh index 04ab66c72..6f4e8e821 100755 --- a/reg_tests/chgres_cube/driver.wcoss_dell_p3.sh +++ b/reg_tests/chgres_cube/driver.wcoss_dell_p3.sh @@ -76,7 +76,7 @@ bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres01 -W 0:05 -x LOG_FILE=consistency.log02 export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres02 -W 0:07 -x -n 6 \ +bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres02 -W 0:10 -x -n 6 \ -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/3km.conus.hrrr.gfssdf.grib2.sh" #----------------------------------------------------------------------------- @@ -103,7 +103,7 @@ bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres04 -W 0:05 -x LOG_FILE=consistency.log05 export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres05 -W 0:05 -x -n 6 \ +bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres05 -W 0:10 -x -n 6 \ -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/13km.conus.rap.grib2.sh" #----------------------------------------------------------------------------- diff --git a/sorc/chgres_cube.fd/CMakeLists.txt b/sorc/chgres_cube.fd/CMakeLists.txt index 7b6ad9388..c148cfb8c 100644 --- a/sorc/chgres_cube.fd/CMakeLists.txt +++ b/sorc/chgres_cube.fd/CMakeLists.txt @@ -42,6 +42,7 @@ target_include_directories(chgres_cube_lib INTERFACE ${mod_dir}) target_link_libraries( chgres_cube_lib PUBLIC + g2::g2_d nemsio::nemsio sfcio::sfcio sigio::sigio diff --git a/sorc/chgres_cube.fd/input_data.F90 b/sorc/chgres_cube.fd/input_data.F90 index 965c37df1..420b92955 100644 --- a/sorc/chgres_cube.fd/input_data.F90 +++ b/sorc/chgres_cube.fd/input_data.F90 @@ -384,8 +384,6 @@ subroutine read_input_sfc_data(localpet) integer, intent(in) :: localpet - integer :: rc - call init_sfc_esmf_fields() !------------------------------------------------------------------------------- @@ -2458,7 +2456,7 @@ end subroutine read_input_atm_tiled_history_file subroutine read_input_atm_grib2_file(localpet) use mpi - use wgrib2api + use grib_mod use grib2_util, only : rh2spfh, rh2spfh_gfs, convert_omega @@ -2467,34 +2465,39 @@ subroutine read_input_atm_grib2_file(localpet) integer, intent(in) :: localpet integer, parameter :: ntrac_max=14 + integer, parameter :: max_levs=1000 character(len=300) :: the_file - character(len=20) :: vlevtyp, vname, lvl_str,lvl_str_space, & - trac_names_grib_1(ntrac_max), & - trac_names_grib_2(ntrac_max), & + character(len=20) :: vname, & trac_names_vmap(ntrac_max), & - tracers_input_grib_1(num_tracers_input), & - tracers_input_grib_2(num_tracers_input), & tmpstr, & method, tracers_input_vmap(num_tracers_input), & - tracers_default(ntrac_max), vname2 - character (len=500) :: metadata + tracers_default(ntrac_max) - integer :: i, j, k, n, lvl_str_space_len + integer :: i, j, k, n integer :: ii,jj integer :: rc, clb(3), cub(3) - integer :: vlev, iret,varnum - integer :: all_empty, o3n - integer :: len_str - integer :: is_missing, intrp_ier, done_print + integer :: vlev, iret,varnum, o3n + integer :: intrp_ier, done_print + integer :: trac_names_oct10(ntrac_max) + integer :: tracers_input_oct10(num_tracers_input) + integer :: trac_names_oct11(ntrac_max) + integer :: tracers_input_oct11(num_tracers_input) + integer :: lugb, lugi, jdisc, jpdt(200), jgdt(200), iscale + integer :: jids(200), jpdtn, jgdtn, octet23, octet29 + integer :: count_spfh, count_rh, count_icmr, count_scliwc + integer :: count_cice, count_rwmr, count_scllwc, count - logical :: lret logical :: conv_omega=.false., & hasspfh=.true., & isnative=.false., & - use_rh=.false. + use_rh=.false. , unpack, & + all_empty, is_missing + + real(esmf_kind_r8), allocatable :: dum2d_1(:,:) + real(esmf_kind_r8) :: rlevs_hold(max_levs) real(esmf_kind_r8), allocatable :: rlevs(:) real(esmf_kind_r4), allocatable :: dummy2d(:,:) real(esmf_kind_r8), allocatable :: dummy3d(:,:,:), dummy2d_8(:,:),& @@ -2509,20 +2512,18 @@ subroutine read_input_atm_grib2_file(localpet) real(esmf_kind_r4), parameter :: lev_no_tr_fill = 20000.0 real(esmf_kind_r4), parameter :: lev_no_o3_fill = 40000.0 + type(gribfield) :: gfld tracers(:) = "NULL" - !trac_names_grib = (/":SPFH:",":CLWR:", "O3MR",":CICE:", ":RWMR:",":SNMR:",":GRLE:", & - ! ":TCDC:", ":NCCICE:",":SPNCR:", ":NCONCD:",":PMTF:",":PMTC:",":TKE:"/) - trac_names_grib_1 = (/":var0_2", ":var0_2", ":var0_2", ":var0_2", ":var0_2",":var0_2", \ - ":var0_2", ":var0_2", ":var0_2", ":var0_2", ":var0_2",":var0_2", \ - ":var0_2", ":var0_2"/) - trac_names_grib_2 = (/"_1_0: ", "_1_22: ", "_14_192:", "_1_23: ", "_1_24: ","_1_25: ", \ - "_1_32: ", "_6_1: ", "_6_29: ", "_1_100: ", "_6_28: ","_13_193:", \ - "_13_192:", "_2_2: "/) + + trac_names_oct10 = (/1, 1, 14, 1, 1, 1, 1, 6, 6, 1, 6, 13, 13, 2 /) + trac_names_oct11 = (/0, 22, 192, 23, 24, 25, 32, 1, 29, 100, 28, 193, 192, 2 /) + trac_names_vmap = (/"sphum ", "liq_wat ", "o3mr ", "ice_wat ", & "rainwat ", "snowwat ", "graupel ", "cld_amt ", "ice_nc ", & "rain_nc ", "water_nc", "liq_aero", "ice_aero", & "sgs_tke "/) + tracers_default = (/"sphum ", "liq_wat ", "o3mr ", "ice_wat ", & "rainwat ", "snowwat ", "graupel ", "cld_amt ", "ice_nc ", & "rain_nc ", "water_nc", "liq_aero", "ice_aero", & @@ -2531,153 +2532,294 @@ subroutine read_input_atm_grib2_file(localpet) the_file = trim(data_dir_input_grid) // "/" // trim(grib2_file_input_grid) print*,"- READ ATMOS DATA FROM GRIB2 FILE: ", trim(the_file) - print*,"- USE INVENTORY FILE ", inv_file - print*,"- OPEN FILE." - inquire(file=the_file,exist=lret) - if (.not.lret) call error_handler("OPENING GRIB2 ATM FILE.", iret) + if (localpet == 0) then + + lugb=14 + lugi=0 + call baopenr(lugb,the_file,iret) + if (iret /= 0) call error_handler("ERROR OPENING GRIB2 FILE.", iret) + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdt = -9999 ! Array of values in product definition template, set to wildcard + jids = -9999 ! Array of values in identification section, set to wildcard + jgdt = -9999 ! Array of values in grid definition template, set to wildcard + jgdtn = -1 ! Search for any grid definition number. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + +! First, check for the vertical coordinate. If temperture at the 10 hybrid +! level is found, hybrid coordinates are assumed. Otherwise, data is on +! isobaric levels. + + jpdt(1) = 0 ! Sect4/oct 10 - param category - temperature field + jpdt(2) = 0 ! Sect4/oct 11 - param number - temperature + jpdt(10) = 105 ! Sect4/oct 23 - type of level - hybrid + jpdt(12) = 10 ! oct 23 - type of level - value of hybrid level + unpack=.false. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then ! data is on hybrid levels + octet23 = 105 + octet29 = 255 + isnative=.true. + else ! data is on isobaric levels + octet23 = 100 + octet29 = 255 + endif + +! Now count the number of vertical levels by searching for u-wind. +! Store the value of each level. + + rlevs_hold = -999.9 + lev_input = 0 + iret = 0 + j = 0 + jpdt = -9999 + + do + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) exit + + if (gfld%discipline == 0) then ! Discipline - meteorological products + if (gfld%ipdtnum == 0) then ! Product definition template number - + ! analysis or forecast at single level. + if (gfld%ipdtmpl(1) == 2 .and. gfld%ipdtmpl(2) == 2) then ! u-wind + ! Sect4/octs 10 and 11. + if (gfld%ipdtmpl(10) == octet23 .and. gfld%ipdtmpl(13) == octet29) then + ! Sect4 octs 23 and 29. + ! Hybrid or isobaric. + lev_input = lev_input + 1 + iscale = 10 ** gfld%ipdtmpl(11) + rlevs_hold(lev_input) = float(gfld%ipdtmpl(12))/float(iscale) + endif + endif + endif + endif + + j = k + enddo - print*,"- READ VERTICAL COORDINATE." - iret = grb2_inq(the_file,inv_file,":var0_2","_0_0:",":10 hybrid level:") - - if (iret <= 0) then - lvl_str = "mb:" - lvl_str_space = " mb:" - lvl_str_space_len = 4 - isnative = .false. - iret = grb2_inq(the_file,inv_file,":UGRD:",lvl_str_space) - lev_input=iret - if (localpet == 0) print*,"- DATA IS ON ", lev_input, " ISOBARIC LEVELS." - else - lvl_str = " level:" - lvl_str_space = " hybrid " - lvl_str_space_len = 7 - isnative = .true. - iret = grb2_inq(the_file,inv_file,":UGRD:",lvl_str_space, " level:") - if (iret < 0) call error_handler("READING VERTICAL LEVEL TYPE.", iret) - lev_input=iret endif + call mpi_barrier(MPI_COMM_WORLD, iret) + call MPI_BCAST(isnative,1,MPI_LOGICAL,0,MPI_COMM_WORLD,iret) + call MPI_BCAST(lev_input,1,MPI_INTEGER,0,MPI_COMM_WORLD,iret) + call MPI_BCAST(rlevs_hold, max_levs, MPI_INTEGER,0,MPI_COMM_WORLD,iret) + allocate(slevs(lev_input)) allocate(rlevs(lev_input)) allocate(dummy3d_col_in(lev_input)) allocate(dummy3d_col_out(lev_input)) levp1_input = lev_input + 1 - -! Get the vertical levels, and search string by sequential reads - - do i = 1,lev_input - iret=grb2_inq(the_file,inv_file,':UGRD:',trim(lvl_str),sequential=i-1,desc=metadata) - if (iret.ne.1) call error_handler(" IN SEQUENTIAL FILE READ.", iret) - - j = index(metadata,':UGRD:') + len(':UGRD:') - k = index(metadata,trim(lvl_str_space)) + len(trim(lvl_str_space))-1 - read(metadata(j:k),*) rlevs(i) +! Jili Dong add sort to re-order isobaric levels. - slevs(i) = metadata(j-1:k) - if (.not. isnative) rlevs(i) = rlevs(i) * 100.0 - if (localpet==0) print*, "- LEVEL = ", slevs(i) + do i = 1, lev_input + rlevs(i) = rlevs_hold(i) enddo -! Jili Dong add sort to re-order isobaric levels. - call quicksort(rlevs,1,lev_input) - if (.not. isnative) then + do i = 1, lev_input + if (isnative) then + write(slevs(i), '(i6)') nint(rlevs(i)) + slevs(i) = trim(slevs(i)) // " hybrid" + else + write(slevs(i), '(f11.2)') rlevs(i) + slevs(i) = trim(slevs(i)) // " Pa" + endif + enddo + + if(localpet == 0) then do i = 1,lev_input - write(slevs(i),"(F20.10)") rlevs(i)/100.0 - len_str = len_trim(slevs(i)) + print*, "- LEVEL AFTER SORT = ",trim(slevs(i)) + enddo + endif - do while (slevs(i)(len_str:len_str) .eq. '0') - slevs(i) = slevs(i)(:len_str-1) - len_str = len_str - 1 - end do +! Check to see if specfic humidity exists at all the same levels as ugrd. + + if (localpet == 0) then + + jpdt = -9999 + jpdt(1) = 1 ! Sect4/oct 10 - param category - moisture + jpdt(2) = 0 ! Sect4/oct 11 - param number - specific humidity + if (isnative) then + jpdt(10) = 105 ! Sect4/oct 23 - type of level - hybrid + else + jpdt(10) = 100 ! Sect4/oct 23 - type of level - isobaric + endif + unpack=.false. + + count_spfh=0 - if (slevs(i)(len_str:len_str) .eq. '.') then - slevs(i) = slevs(i)(:len_str-1) - len_str = len_str - 1 - end if + do vlev = 1, lev_input + j = 0 + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) - slevs(i) = trim(slevs(i)) + if (iret == 0) then + count_spfh = count_spfh + 1 + endif - slevs(i) = ":"//trim(adjustl(slevs(i)))//" mb:" - if (localpet==0) print*, "- LEVEL AFTER SORT = ",slevs(i) enddo - endif -! Is SPFH on full levels Jili Dong - do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,':SPFH:',slevs(vlev)) - if (iret <= 0) then - use_rh = .TRUE. - if (localpet == 0) print*, ':SPFH on level '//trim(slevs(vlev))//' does not exist. & - Will read in RH and convert to SPFH instead.' - exit - end if - end do + jpdt(1) = 1 ! Sec4/oct 10 - param category - moisture + jpdt(2) = 1 ! Sec4/oct 11 - param number - rel humidity + count_rh=0 - - if (localpet == 0) print*,"- FIND SPFH OR RH IN FILE" - iret = grb2_inq(the_file,inv_file,trim(trac_names_grib_1(1)),trac_names_grib_2(1),lvl_str_space) - - if (iret <= 0 .or. use_rh) then - iret = grb2_inq(the_file,inv_file, ':var0_2','_1_1:',lvl_str_space) - if (iret <= 0) call error_handler("READING ATMOSPHERIC WATER VAPOR VARIABLE.", iret) - hasspfh = .false. - trac_names_grib_2(1)='_1_1:' - if (localpet == 0) print*,"- FILE CONTAINS RH." - else - if (localpet == 0) print*,"- FILE CONTAINS SPFH." - endif - - if (localpet == 0) print*,"- FIND ICMR, SCLIWC, OR CICE IN FILE" - iret = grb2_inq(the_file,inv_file,trac_names_grib_1(4),trac_names_grib_2(4),lvl_str_space) + do vlev = 1, lev_input + j = 0 + jpdt(12) = nint(rlevs(vlev)) - if (iret <= 0) then - vname = trac_names_vmap(4) - print*, "vname = ", vname - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - this_field_var_name=tmpstr,loc=varnum) - iret = grb2_inq(the_file,inv_file, ':var0_2','_1_84:',lvl_str_space) - if (iret <= 0) then - iret = grb2_inq(the_file,inv_file, ':var0_2','_6_0:',lvl_str_space) - if (iret <= 0 ) then - call handle_grib_error(vname, slevs(1),method,value,varnum,rc,var=dummy2d) - else - trac_names_grib_2(4) = '_6_0' - if (localpet == 0) print*,"- FILE CONTAINS CICE." - endif + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_rh = count_rh + 1 + endif + enddo + + if (count_spfh /= lev_input) then + use_rh = .true. + endif + + if (count_spfh == 0 .or. use_rh) then + if (count_rh == 0) then + call error_handler("READING ATMOSPHERIC WATER VAPOR VARIABLE.", 2) + endif + hasspfh = .false. ! Will read rh and convert to specific humidity. + trac_names_oct10(1) = 1 + trac_names_oct11(1) = 1 + print*,"- FILE CONTAINS RH." else - trac_names_grib_2(4)='_1_84:' - if (localpet == 0) print*,"- FILE CONTAINS SCLIWC." + print*,"- FILE CONTAINS SPFH." endif - else - if (localpet == 0) print*,"- FILE CONTAINS ICMR." + endif + + call MPI_BARRIER(MPI_COMM_WORLD, rc) + call MPI_BCAST(hasspfh,1,MPI_LOGICAL,0,MPI_COMM_WORLD,rc) - if (localpet == 0) print*,"- FIND CLWMR or SCLLWC IN FILE" - iret = grb2_inq(the_file,inv_file,trac_names_grib_1(5),trac_names_grib_2(5),lvl_str_space) +! Search for and count the number of tracers in the file. - if (iret <= 0) then - vname = trac_names_vmap(5) - print*, "vname = ", vname - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - this_field_var_name=tmpstr,loc=varnum) - iret = grb2_inq(the_file,inv_file, ':var0_2','_1_83:',lvl_str_space) - if (iret <= 0) then - call handle_grib_error(vname, slevs(1),method,value,varnum,rc,var=dummy2d) - elseif (iret <=0 .and. rc .ne. 1) then - call error_handler("READING CLOUD WATER VARIABLE.", iret) + if (localpet == 0) then + + jpdt = -9999 + if (isnative) then + jpdt(10) = 105 ! Sect4/oct 23 - type of level - hybrid else - trac_names_grib_2(4)='_1_83:' - if (localpet == 0) print*,"- FILE CONTAINS SCLLWC." + jpdt(10) = 100 ! Sect4/oct 23 - type of level - isobaric endif - else - if (localpet == 0) print*,"- FILE CONTAINS CLWMR." - endif + unpack=.false. + + count_icmr=0 + count_scliwc=0 + count_cice=0 + count_rwmr=0 + count_scllwc=0 + + do vlev = 1, lev_input + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - param category - moisture + jpdt(2) = 23 ! Sect4/oct 11 - param number - ice water mixing ratio + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_icmr = count_icmr + 1 + endif + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - param category - moisture + jpdt(2) = 84 ! Sect4/oct 11 - param number - cloud ice water content. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_scliwc = count_scliwc + 1 + endif + + j = 0 + jpdt(1) = 6 ! Sect4/oct 10 - param category - clouds + jpdt(2) = 0 ! Sect4/oct 11 - param number - cloud ice + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_cice = count_cice + 1 + endif + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - param category - moisture + jpdt(2) = 24 ! Sect4/oct 11 - param number - rain mixing ratio + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_rwmr = count_rwmr + 1 + endif + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - param category - moisture + jpdt(2) = 83 ! Sect4/oct 11 - param number - specific cloud liquid + ! water content. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_scllwc = count_scllwc + 1 + endif + + enddo + + if (count_icmr == 0) then + if (count_scliwc == 0) then + if (count_cice == 0) then + print*,'- FILE DOES NOT CONTAIN CICE.' + else + trac_names_oct10(4) = 6 ! Sect4/oct 10 - param category - clouds + trac_names_oct11(4) = 0 ! Sect4/oct 11 - param number - cloud ice + print*,"- FILE CONTAINS CICE." + endif + else + trac_names_oct10(4) = 1 ! Sect4/oct 10 - param category - moisture + trac_names_oct11(4) = 84 ! Sect4/oct 11 - param number - cloud ice water content. + print*,"- FILE CONTAINS SCLIWC." + endif + else + print*,"- FILE CONTAINS ICMR." + endif ! count of icmr + + if (count_rwmr == 0) then + if (count_scllwc == 0) then + print*,"- FILE DOES NOT CONTAIN SCLLWC." + else + trac_names_oct10(4) = 1 ! Sect4/oct 10 - param category - moisture + trac_names_oct11(4) = 83 ! Sect4/oct 11 - param number - specific cloud liquid + ! water content. + print*,"- FILE CONTAINS SCLLWC." + endif + else + print*,"- FILE CONTAINS CLWMR." + endif + + endif ! count of tracers/localpet = 0 + call MPI_BARRIER(MPI_COMM_WORLD, rc) + call MPI_BCAST(trac_names_oct10,ntrac_max,MPI_INTEGER,0,MPI_COMM_WORLD,rc) + call MPI_BCAST(trac_names_oct11,ntrac_max,MPI_INTEGER,0,MPI_COMM_WORLD,rc) + print*,"- COUNT NUMBER OF TRACERS TO BE READ IN BASED ON PHYSICS SUITE TABLE" do n = 1, num_tracers_input @@ -2685,17 +2827,14 @@ subroutine read_input_atm_grib2_file(localpet) i = maxloc(merge(1.,0.,trac_names_vmap == vname),dim=1) - tracers_input_grib_1(n) = trac_names_grib_1(i) - tracers_input_grib_2(n) = trac_names_grib_2(i) tracers_input_vmap(n)=trac_names_vmap(i) tracers(n)=tracers_default(i) if(trim(tracers(n)) .eq. "o3mr") o3n = n - enddo + tracers_input_oct10(n) = trac_names_oct10(i) + tracers_input_oct11(n) = trac_names_oct11(i) - if (localpet==0) then - print*, "- NUMBER OF TRACERS IN THE INPUT FILE = ", num_tracers_input - endif + enddo !--------------------------------------------------------------------------- ! Initialize esmf atmospheric fields. @@ -2707,10 +2846,12 @@ subroutine read_input_atm_grib2_file(localpet) allocate(dummy2d(i_input,j_input)) allocate(dummy2d_8(i_input,j_input)) allocate(dummy3d(i_input,j_input,lev_input)) + allocate(dum2d_1(i_input,j_input)) else allocate(dummy2d(0,0)) allocate(dummy2d_8(0,0)) allocate(dummy3d(0,0,0)) + allocate(dum2d_1(0,0)) endif !---------------------------------------------------------------------------------- @@ -2720,98 +2861,171 @@ subroutine read_input_atm_grib2_file(localpet) !---------------------------------------------------------------------------------- if (localpet == 0) then + print*,"- READ TEMPERATURE." - vname = ":TMP:" - do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,slevs(vlev),data2=dummy2d) - if (iret<=0) then - call error_handler("READING IN TEMPERATURE AT LEVEL "//trim(slevs(vlev)),iret) - endif - dummy3d(:,:,vlev) = real(dummy2d,esmf_kind_r8) - print*,'temp check after read ',vlev, dummy3d(1,1,vlev) - enddo - endif + + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + jpdt(1) = 0 ! Sect 4/oct 10 - param category - temperature + jpdt(2) = 0 ! Sect 4/oct 11 - param number - temperature + + if (isnative) then + jpdt(10) = 105 ! Sect 4/oct 23 - type of level - hybrid + else + jpdt(10) = 100 ! Sect 4/oct 23 - type of level - isobaric + endif + + unpack=.true. + + do vlev = 1, lev_input + + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) then + call error_handler("READING IN TEMPERATURE AT LEVEL "//trim(slevs(vlev)),iret) + endif + + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) + + dummy3d(:,:,vlev) = dum2d_1 + + enddo + + endif ! Read of temperature if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter", rc) +! Read tracers + do n = 1, num_tracers_input if (localpet == 0) print*,"- READ ", trim(tracers_input_vmap(n)) + vname = tracers_input_vmap(n) call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & this_field_var_name=tmpstr,loc=varnum) + if (n==1 .and. .not. hasspfh) then - print*,"- CALL FieldGather TEMPERATURE." - call ESMF_FieldGather(temp_input_grid,dummy3d,rootPet=0, tile=1, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) + print*,"- CALL FieldGather TEMPERATURE." + call ESMF_FieldGather(temp_input_grid,dummy3d,rootPet=0, tile=1, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) endif if (localpet == 0) then - vname = trim(tracers_input_grib_1(n)) - vname2 = trim(tracers_input_grib_2(n)) - iret = grb2_inq(the_file,inv_file,vname,lvl_str_space,vname2) + + jdisc = 0 ! search for discipline - meteorological products + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + unpack = .false. + if (isnative) then + jpdt(10) = 105 ! Sect4/oct 23 - type of level - hybrid + else + jpdt(10) = 100 ! Sect4/oct 23 - type of level - isobaric + endif + + count = 0 + + do vlev = 1, lev_input + + j = 0 + jpdt(1) = tracers_input_oct10(n) + jpdt(2) = tracers_input_oct11(n) + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count = count + 1 + endif + + enddo + iret=count ! Check to see if file has any data for this tracer if (iret == 0) then - all_empty = 1 + all_empty = .true. else - all_empty = 0 + all_empty = .false. endif - is_missing = 0 + is_missing = .false. + do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,slevs(vlev),vname2,data2=dummy2d) - - if (iret <= 0) then - if (trim(method) .eq. 'intrp' .and. all_empty == 0) then + + unpack=.true. + j = 0 + jpdt(1) = tracers_input_oct10(n) + jpdt(2) = tracers_input_oct11(n) + jpdt(12) = nint(rlevs(vlev) ) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then ! found data + dummy2d = reshape(gfld%fld, (/i_input,j_input/) ) + else ! did not find data. + if (trim(method) .eq. 'intrp' .and. .not.all_empty) then dummy2d = intrp_missing - is_missing = 1 + is_missing = .true. else ! Abort if input data has some data for current tracer, but has ! missing data below 200 mb/ above 400mb - if (all_empty == 0 .and. n == o3n) then + if (.not.all_empty .and. n == o3n) then if (rlevs(vlev) .lt. lev_no_o3_fill) & call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev))//& ". SET MISSING VARIABLE CONDITION TO 'INTRP' TO AVOID THIS ERROR", 1) - elseif (all_empty == 0 .and. n .ne. o3n) then + elseif (.not.all_empty .and. n .ne. o3n) then if (rlevs(vlev) .gt. lev_no_tr_fill) & call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev))//& ". SET MISSING VARIABLE CONDITION TO 'INTRP' TO AVOID THIS ERROR.", 1) endif ! If entire array is empty and method is set to intrp, switch method to fill - if (trim(method) .eq. 'intrp' .and. all_empty == 1) method='set_to_fill' + if (trim(method) .eq. 'intrp' .and. all_empty) method='set_to_fill' call handle_grib_error(vname, slevs(vlev),method,value,varnum,iret,var=dummy2d) if (iret==1) then ! missing_var_method == skip or no entry - if (trim(vname2)=="_1_0:" .or. trim(vname2) == "_1_1:" .or. & - trim(vname2) == ":14:192:") then + if ( (tracers_input_oct10(n) == 1 .and. tracers_input_oct11(n) == 0) .or. & ! spec humidity + (tracers_input_oct10(n) == 1 .and. tracers_input_oct11(n) == 1) .or. & ! rel humidity + (tracers_input_oct10(n) == 14 .and. tracers_input_oct11(n) == 192) ) then ! ozone call error_handler("READING IN "//trim(tracers(n))//" AT LEVEL "//trim(slevs(vlev))& //". SET A FILL VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) endif endif endif ! method intrp endif !iret<=0 - + if (n==1 .and. .not. hasspfh) then if (trim(external_model) .eq. 'GFS') then - print *,'CALRH GFS' + print *,'- CALL CALRH GFS' call rh2spfh_gfs(dummy2d,rlevs(vlev),dummy3d(:,:,vlev)) else - print *,'CALRH non-GFS' + print *,'- CALL CALRH non-GFS' call rh2spfh(dummy2d,rlevs(vlev),dummy3d(:,:,vlev)) end if endif - print*,'tracer ',vlev, maxval(dummy2d),minval(dummy2d) dummy3d(:,:,vlev) = real(dummy2d,esmf_kind_r8) + enddo !vlev + ! Jili Dong interpolation for missing levels - if (is_missing .gt. 0 .and. trim(method) .eq. 'intrp') then - print *,'intrp tracer '//trim(tracers(n)) + if (is_missing .and. trim(method) .eq. 'intrp') then + print *,'- INTERPOLATE TRACER '//trim(tracers(n)) done_print = 0 do jj = 1, j_input do ii = 1, i_input @@ -2841,7 +3055,7 @@ subroutine read_input_atm_grib2_file(localpet) endif ! intrp_missing ! zero out negative tracers from interpolation/extrapolation where(dummy3d(:,:,vlev) .lt. 0.0) dummy3d(:,:,vlev) = 0.0 - print*,'tracer af intrp',vlev, maxval(dummy3d(:,:,vlev)),minval(dummy3d(:,:,vlev)) +! print*,'tracer af intrp',vlev, maxval(dummy3d(:,:,vlev)),minval(dummy3d(:,:,vlev)) end do !nlevs do end if !if intrp endif !localpet == 0 @@ -2855,7 +3069,7 @@ subroutine read_input_atm_grib2_file(localpet) deallocate(dummy3d_col_in, dummy3d_col_out) -call read_winds(the_file,inv_file,u_tmp_3d,v_tmp_3d, localpet) + call read_winds(u_tmp_3d,v_tmp_3d,localpet,isnative,rlevs,lugb) if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT U-WIND." call ESMF_FieldScatter(u_input_grid, u_tmp_3d, rootpet=0, rc=rc) @@ -2868,47 +3082,90 @@ subroutine read_input_atm_grib2_file(localpet) call error_handler("IN FieldScatter", rc) if (localpet == 0) then + print*,"- READ SURFACE PRESSURE." - vname = ":var0_2" - vname2 = "_3_0:" - vlevtyp = ":surface:" - iret = grb2_inq(the_file,inv_file,vname,vname2,vlevtyp,data2=dummy2d) - if (iret <= 0) call error_handler("READING SURFACE PRESSURE RECORD.", iret) - dummy2d_8 = real(dummy2d,esmf_kind_r8) - endif + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + jpdt(1) = 3 ! Sect4/oct 10 - param category - mass + jpdt(2) = 0 ! Sect4/oct 11 - param number - pressure + jpdt(10) = 1 ! Sect4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) call error_handler("READING SURFACE PRESSURE RECORD.", iret) + + dummy2d_8 = reshape(gfld%fld, (/i_input,j_input/) ) + + endif ! Read surface pressure if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID SURFACE PRESSURE." call ESMF_FieldScatter(ps_input_grid, dummy2d_8, rootpet=0, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter", rc) +! Read dzdt. + if (localpet == 0) then + print*,"- READ DZDT." vname = "dzdt" call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & loc=varnum) - vname = ":var0_2" - vname2 = "_2_9:" + + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + jpdt(1) = 2 ! Sect4/oct 10 - param category - momentum + jpdt(2) = 9 ! Sect4/oct 11 - param number - dzdt + + if (isnative) then + jpdt(10) = 105 ! Sect4/oct 23 - type of level - hybrid + else + jpdt(10) = 100 ! Sect4/oct 23 - type of level - isobaric + endif + + unpack=.true. + do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,vname2,slevs(vlev),data2=dummy2d) - if (iret <= 0 ) then + + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) then ! dzdt not found, look for omega. print*,"DZDT not available at level ", trim(slevs(vlev)), " so checking for VVEL" - vname2 = "_2_8:" - iret = grb2_inq(the_file,inv_file,vname,vname2,slevs(vlev),data2=dummy2d) - if (iret <= 0) then - call handle_grib_error(vname, slevs(vlev),method,value,varnum,iret,var=dummy2d) - if (iret==1) then ! missing_var_method == skip - cycle - endif + jpdt(2) = 8 ! Sect4/oct 11 - parameter number - omega + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) then + call handle_grib_error(vname, slevs(vlev),method,value,varnum,iret,var8=dum2d_1) + if (iret==1) then ! missing_var_method == skip + cycle + endif else - conv_omega = .true. + conv_omega = .true. + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) endif - + else ! found dzdt + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) endif - print*,'dzdt ',vlev, maxval(dummy2d),minval(dummy2d) - dummy3d(:,:,vlev) = dummy2d + + dummy3d(:,:,vlev) = dum2d_1 + enddo - endif + + endif ! Read of dzdt call mpi_bcast(conv_omega,1,MPI_LOGICAL,0,MPI_COMM_WORLD,rc) @@ -2917,15 +3174,30 @@ subroutine read_input_atm_grib2_file(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter", rc) +! Read terrain + if (localpet == 0) then + print*,"- READ TERRAIN." - vname = ":var0_2" - vname2 = "_3_5:" - vlevtyp = ":surface:" - iret = grb2_inq(the_file,inv_file,vname,vname2,vlevtyp,data2=dummy2d) - if (iret <= 0) call error_handler("READING TERRAIN HEIGHT RECORD.", iret) - dummy2d_8 = real(dummy2d,esmf_kind_r8) - endif + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + jpdt(1) = 3 ! Sect4/oct 10 - param category - mass + jpdt(2) = 5 ! Sect4/oct 11 - param number - geopotential height + jpdt(10) = 1 ! Sect4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) call error_handler("READING TERRAIN HEIGHT RECORD.", iret) + + dummy2d_8 = reshape(gfld%fld, (/i_input,j_input/) ) + + endif ! read of terrain. if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN." call ESMF_FieldScatter(terrain_input_grid, dummy2d_8, rootpet=0, rc=rc) @@ -2935,6 +3207,7 @@ subroutine read_input_atm_grib2_file(localpet) deallocate(dummy2d, dummy2d_8) if (.not. isnative) then + !--------------------------------------------------------------------------- ! Flip 'z' indices to all 3-d variables. Data is read in from model ! top to surface. This program expects surface to model top. @@ -3018,27 +3291,51 @@ subroutine read_input_atm_grib2_file(localpet) lev_input)),minval(presptr(clb(1):cub(1),clb(2):cub(2),lev_input)) endif -else - ! For native files, read in pressure field directly from file but don't flip levels +else ! is native coordinate (hybrid). + +! For native files, read in pressure field directly from file but don't flip levels + if (localpet == 0) then + print*,"- READ PRESSURE." - vname = ":PRES:" + + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + jpdt(1) = 3 ! Sect4/oct 10 - param category - mass + jpdt(2) = 0 ! Sect4/oct 11 - param number - pressure + jpdt(10) = 105 ! Sect4/oct 23 - type of level - hybrid + unpack=.true. + do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,slevs(vlev),data2=dummy2d) - if (iret<=0) then + + jpdt(12) = nint(rlevs(vlev)) + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) then call error_handler("READING IN PRESSURE AT LEVEL "//trim(slevs(vlev)),iret) endif - dummy3d(:,:,vlev) = real(dummy2d,esmf_kind_r8) - print*,'pres check after read ',vlev, dummy3d(1,1,vlev) + + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) + + dummy3d(:,:,vlev) = dum2d_1 + enddo - endif + + endif ! localpet == 0 if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID PRESSURE." call ESMF_FieldScatter(pres_input_grid, dummy3d, rootpet=0, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter", rc) + endif - deallocate(dummy3d) + + deallocate(dummy3d, dum2d_1) !--------------------------------------------------------------------------- ! Convert from 2-d to 3-d component winds. @@ -3089,6 +3386,8 @@ subroutine read_input_atm_grib2_file(localpet) endif + if (localpet == 0) call baclose(lugb, rc) + end subroutine read_input_atm_grib2_file !> Read input grid surface data from a spectral gfs gaussian sfcio @@ -4700,55 +4999,100 @@ end subroutine read_input_sfc_netcdf_file !! @author Larissa Reames subroutine read_input_sfc_grib2_file(localpet) - use wgrib2api + use mpi + use grib_mod use program_setup, only : vgtyp_from_climo, sotyp_from_climo use model_grid, only : input_grid_type use search_util - implicit none integer, intent(in) :: localpet character(len=250) :: the_file character(len=250) :: geo_file - character(len=20) :: vname, vname_file,slev + character(len=20) :: vname, vname_file, slev character(len=50) :: method character(len=20) :: to_upper integer :: rc, varnum, iret, i, j,k integer :: ncid2d, varid, varsize + integer :: lugb, lugi + integer :: jdisc, jgdtn, jpdtn + integer :: jids(200), jgdt(200), jpdt(200) - logical :: exist, rap_latlon + logical :: rap_latlon, unpack real(esmf_kind_r4) :: value - - real(esmf_kind_r4), allocatable :: dummy2d(:,:),icec_save(:,:) + real(esmf_kind_r4), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: icec_save(:,:) real(esmf_kind_r4), allocatable :: dummy1d(:) real(esmf_kind_r8), allocatable :: dummy2d_8(:,:),dummy2d_82(:,:),tsk_save(:,:) real(esmf_kind_r8), allocatable :: dummy3d(:,:,:), dummy3d_stype(:,:,:) integer(esmf_kind_i4), allocatable :: slmsk_save(:,:) integer(esmf_kind_i8), allocatable :: dummy2d_i(:,:) + type(gribfield) :: gfld rap_latlon = trim(to_upper(external_model))=="RAP" .and. trim(input_grid_type) == "rotated_latlon" the_file = trim(data_dir_input_grid) // "/" // trim(grib2_file_input_grid) geo_file = trim(geogrid_file_input_grid) - print*,"- READ SFC DATA FROM GRIB2 FILE: ", trim(the_file) - inquire(file=the_file,exist=exist) - if (.not.exist) then - iret = 1 - call error_handler("OPENING GRIB2 FILE.", iret) - end if - - lsoil_input = grb2_inq(the_file, inv_file, ':TSOIL:',' below ground:') - print*, "- FILE HAS ", lsoil_input, " SOIL LEVELS" - if (lsoil_input <= 0) call error_handler("COUNTING SOIL LEVELS.", rc) - - !We need to recreate the soil fields if we have something other than 4 levels + +! Determine the number of soil layers in file. + + if (localpet == 0) then + + lugb=12 + call baopenr(lugb,the_file,rc) + if (rc /= 0) call error_handler("ERROR OPENING GRIB2 FILE.", rc) + + j = 0 ! search at beginning of file + lugi = 0 ! no grib index file + jdisc = -1 ! search for any discipline + jpdtn = -1 ! search for any product definition template number + jgdtn = -1 ! search for any grid definition template number + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jpdt = -9999 ! array of values in product definition template, set to wildcard + unpack = .false. ! unpack data + + lsoil_input = 0 + do + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) exit + + if (gfld%discipline == 2) then ! discipline - land products + if (gfld%ipdtnum == 0) then ! prod template number - analysis or forecast at single level. + if (gfld%ipdtmpl(1) == 0 .and. gfld%ipdtmpl(2) == 2) then ! soil temp + ! Sect4/octs 10 and 11 + if (gfld%ipdtmpl(10) == 106 .and. gfld%ipdtmpl(13) == 106) then ! Sect4/octs 23/29. + ! Layer below ground. + lsoil_input = lsoil_input + 1 + endif + endif + endif + endif + + j = k + + enddo + + print*, "- FILE HAS ", lsoil_input, " SOIL LEVELS." + if (lsoil_input == 0) call error_handler("COUNTING SOIL LEVELS.", rc) + + endif ! localpet == 0 + + call MPI_BARRIER(MPI_COMM_WORLD, rc) + call MPI_BCAST(lsoil_input,1,MPI_INTEGER,0,MPI_COMM_WORLD,rc) + + ! We need to recreate the soil fields if we have something other than 4 levels + if (lsoil_input /= 4) then call ESMF_FieldDestroy(soil_temp_input_grid, rc=rc) @@ -4783,56 +5127,81 @@ subroutine read_input_sfc_grib2_file(localpet) call error_handler("IN FieldCreate", rc) endif - - if (localpet == 0) then - allocate(dummy2d(i_input,j_input)) - allocate(slmsk_save(i_input,j_input)) - allocate(dummy2d_i(i_input,j_input)) - allocate(tsk_save(i_input,j_input)) - allocate(icec_save(i_input,j_input)) - allocate(dummy2d_8(i_input,j_input)) - allocate(dummy2d_82(i_input,j_input)) - allocate(dummy3d(i_input,j_input,lsoil_input)) - allocate(dummy3d_stype(i_input,j_input,16)) - allocate(dummy1d(16)) - else - allocate(dummy3d(0,0,0)) - allocate(dummy2d_8(0,0)) - allocate(dummy2d_82(0,0)) - allocate(dummy2d(0,0)) - allocate(slmsk_save(0,0)) - endif + + if (localpet == 0) then + allocate(dummy2d(i_input,j_input)) + allocate(slmsk_save(i_input,j_input)) + allocate(tsk_save(i_input,j_input)) + allocate(icec_save(i_input,j_input)) + allocate(dummy2d_8(i_input,j_input)) + allocate(dummy2d_82(i_input,j_input)) + allocate(dummy3d(i_input,j_input,lsoil_input)) + else + allocate(dummy3d(0,0,0)) + allocate(dummy2d_8(0,0)) + allocate(dummy2d_82(0,0)) + allocate(dummy2d(0,0)) + allocate(slmsk_save(0,0)) + endif !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! These variables are always in grib files, or are required, so no need to check for them ! in the varmap table. If they can't be found in the input file, then stop the program. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - if (localpet == 0) then - print*,"- READ TERRAIN." - rc = grb2_inq(the_file, inv_file, ':HGT:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING TERRAIN.", rc) - print*,'orog ',maxval(dummy2d),minval(dummy2d) - endif + if (localpet == 0) then - print*,"- CALL FieldScatter FOR INPUT TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- READ TERRAIN." + + j = 0 + jdisc = 0 ! Search for discipline 0 - meteorological products + jpdt = -9999 ! array of values in product definition template, set to wildcard. + jpdtn = 0 ! search for product definition template number 0 - anl or fcst. + jpdt(1) = 3 ! Sec4/oct 10 - param cat - mass field + jpdt(2) = 5 ! Sec4/oct 11 - param number - geopotential height + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING TERRAIN.", rc) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) +! print*,'orog ', maxval(dummy2d_8),minval(dummy2d_8) + + endif + + print*,"- CALL FieldScatter FOR INPUT TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) -if (localpet == 0) then - print*,"- READ SEAICE FRACTION." - rc = grb2_inq(the_file, inv_file, ':ICEC:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING SEAICE FRACTION.", rc) - !dummy2d = dummy2d(i_input:1:-1,j_input:1:-1) - print*,'icec ',maxval(dummy2d),minval(dummy2d) - icec_save = dummy2d - endif + if (localpet == 0) then - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." - call ESMF_FieldScatter(seaice_fract_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- READ SEAICE FRACTION." + + jdisc = 10 ! Search for discipline - ocean products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Array of values in Sec 4 product definition template; + ! Initialize to wildcard. + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - ice + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - ice cover + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING SEAICE FRACTION.", rc) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) +! print*,'icec ', maxval(dummy2d_8),minval(dummy2d_8) + + icec_save = dummy2d_8 + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." + call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) !---------------------------------------------------------------------------------- ! GFS v14 and v15.2 grib data has two land masks. LANDN is created by @@ -4842,46 +5211,89 @@ subroutine read_input_sfc_grib2_file(localpet) ! '2' based on ice concentration. !---------------------------------------------------------------------------------- - if (localpet == 0) then - print*,"- READ LANDSEA MASK." - rc = grb2_inq(the_file, inv_file, ':LANDN:',':surface:', data2=dummy2d) + if (localpet == 0) then - if (rc /= 1) then - rc = grb2_inq(the_file, inv_file, ':LAND:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING LANDSEA MASK.", rc) - endif + print*,"- READ LANDSEA MASK." - do j = 1, j_input - do i = 1, i_input - if(dummy2d(i,j) < 0.5_esmf_kind_r4) dummy2d(i,j)=0.0_esmf_kind_r4 - if(icec_save(i,j) > 0.15_esmf_kind_r4) then - !if (dummy2d(i,j) == 0.0_esmf_kind_r4) print*, "CONVERTING WATER TO SEA/LAKE ICE AT ", i, j - dummy2d(i,j) = 2.0_esmf_kind_r4 - endif + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec 4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 218 ! Sec4/oct 11 - parameter number - land nearest neighbor + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc == 0) then + + print*,'landnn ', maxval(gfld%fld),minval(gfld%fld) + + else + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec 4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - land cover (fraction) + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING LANDSEA MASK.", rc) + +! print*,'land ', maxval(gfld%fld),minval(gfld%fld) + + endif + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + do j = 1, j_input + do i = 1, i_input + if(dummy2d_8(i,j) < 0.5_esmf_kind_r8) dummy2d_8(i,j)=0.0 + if(icec_save(i,j) > 0.15_esmf_kind_r8) then + dummy2d_8(i,j) = 2.0_esmf_kind_r8 + endif + enddo enddo - enddo - slmsk_save = nint(dummy2d) - - deallocate(icec_save) - endif ! localpet == 0 + slmsk_save = nint(dummy2d_8) - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + deallocate(icec_save) - if (localpet == 0) then - print*,"- READ SEAICE SKIN TEMPERATURE." - rc = grb2_inq(the_file, inv_file, ':TMP:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING SEAICE SKIN TEMP.", rc) - print*,'ti ',maxval(dummy2d),minval(dummy2d) - endif + endif ! read land mask - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." - call ESMF_FieldScatter(seaice_skin_temp_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SEAICE SKIN TEMPERATURE." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - temperature + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - temperature + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING SEAICE SKIN TEMP.", rc) + +! print*,'ti ',maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." + call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) !---------------------------------------------------------------------------------- ! Read snow fields. Zero out at non-land points and undefined points (points @@ -4889,145 +5301,250 @@ subroutine read_input_sfc_grib2_file(localpet) ! in mm. !---------------------------------------------------------------------------------- - if (localpet == 0) then - print*,"- READ SNOW LIQUID EQUIVALENT." - rc = grb2_inq(the_file, inv_file, ':WEASD:',':surface:',':anl:',data2=dummy2d) - if (rc /= 1) then - rc = grb2_inq(the_file, inv_file, ':WEASD:',':surface:','hour fcst:',data2=dummy2d) - if (rc /= 1) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) + if (localpet == 0) then + + print*,"- READ SNOW LIQUID EQUIVALENT." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 1 ! Sec4/oct 10 - parameter category - moisture + jpdt(2) = 13 ! Sec4/oct 11 - parameter number - liquid equiv snow depth + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) + +! print*,'weasd ', maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + do j = 1, j_input + do i = 1, i_input + if(slmsk_save(i,j) == 0) dummy2d_8(i,j) = 0.0 + enddo + enddo + endif - do j = 1, j_input + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." + call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SNOW DEPTH." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 1 ! Sec4/oct 10 - parameter category - moisture + jpdt(2) = 11 ! Sec4/oct 11 - parameter number - snow depth + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) then + call error_handler("READING SNOW DEPTH.", rc) + else + gfld%fld = gfld%fld * 1000.0 +! print*,'snod ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + endif + + do j = 1, j_input do i = 1, i_input - if(slmsk_save(i,j) == 0) dummy2d(i,j) = 0.0_esmf_kind_r4 - if(dummy2d(i,j) == grb2_UNDEFINED) dummy2d(i,j) = 0.0_esmf_kind_r4 + if(slmsk_save(i,j) == 0) dummy2d_8(i,j) = 0.0 + enddo enddo - enddo - print*,'weasd ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." - call ESMF_FieldScatter(snow_liq_equiv_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - if (localpet == 0) then - print*,"- READ SNOW DEPTH." - rc = grb2_inq(the_file, inv_file, ':SNOD:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING SNOW DEPTH.", rc) - where(dummy2d == grb2_UNDEFINED) dummy2d = 0.0_esmf_kind_r4 - dummy2d = dummy2d*1000.0 ! Grib2 files have snow depth in (m), fv3 expects it in mm - where(slmsk_save == 0) dummy2d = 0.0_esmf_kind_r4 - print*,'snod ',maxval(dummy2d),minval(dummy2d) - endif + endif - print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." - call ESMF_FieldScatter(snow_depth_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." + call ESMF_FieldScatter(snow_depth_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - if (localpet == 0) then - print*,"- READ T2M." - rc = grb2_inq(the_file, inv_file, ':TMP:',':2 m above ground:',data2=dummy2d) - if (rc <= 0) call error_handler("READING T2M.", rc) + if (localpet == 0) then - print*,'t2m ',maxval(dummy2d),minval(dummy2d) - endif + print*,"- READ T2M." - print*,"- CALL FieldScatter FOR INPUT GRID T2M." - call ESMF_FieldScatter(t2m_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0,rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - temperature + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - temperature + jpdt(10) = 103 ! Sec4/oct 23 - type of level - height above ground surface + jpdt(12) = 2 ! Sec4/octs 25-28 - 2 meters above ground. + unpack=.true. - if (localpet == 0) then - print*,"- READ Q2M." - rc = grb2_inq(the_file, inv_file, ':SPFH:',':2 m above ground:',data2=dummy2d) - if (rc <=0) call error_handler("READING Q2M.", rc) - print*,'q2m ',maxval(dummy2d),minval(dummy2d) - endif + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) - print*,"- CALL FieldScatter FOR INPUT GRID Q2M." - call ESMF_FieldScatter(q2m_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0,rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + if (rc /= 0) call error_handler("READING T2M.", rc) +! print*,'t2m ', maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID T2M." + call ESMF_FieldScatter(t2m_input_grid, dummy2d_8, rootpet=0,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ Q2M." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 1 ! Sec4/oct 10 - parameter category - moisture + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - specific humidity + jpdt(10) = 103 ! Sec4/oct 23 - type of level - height above ground surface + jpdt(12) = 2 ! Sec4/octs 25-28 - 2 meters above ground. + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /=0) call error_handler("READING Q2M.", rc) + +! print*,'q2m ',maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Q2M." + call ESMF_FieldScatter(q2m_input_grid,dummy2d_8, rootpet=0,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - if (localpet == 0) then - print*,"- READ SKIN TEMPERATURE." - rc = grb2_inq(the_file, inv_file, ':TMP:',':surface:', data2=dummy2d) - if (rc <= 0 ) call error_handler("READING SKIN TEMPERATURE.", rc) - tsk_save(:,:) = real(dummy2d,esmf_kind_r8) - dummy2d_8 = real(dummy2d,esmf_kind_r8) - do j = 1, j_input - do i = 1, i_input - if(slmsk_save(i,j) == 0 .and. dummy2d(i,j) < 271.2) then -! print*,'too cool SST ',i,j,dummy2d(i,j) - dummy2d(i,j) = 271.2 - endif - if(slmsk_save(i,j) == 0 .and. dummy2d(i,j) > 310.) then -! print*,'too hot SST ',i,j,dummy2d(i,j) - dummy2d(i,j) = 310.0 - endif + if (localpet == 0) then + + print*,"- READ SKIN TEMPERATURE." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - temperature + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - temperature + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) call error_handler("READING SKIN TEMPERATURE.", rc) +! print*,'skint ', maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + tsk_save(:,:) = dummy2d_8 + + do j = 1, j_input + do i = 1, i_input + if(slmsk_save(i,j) == 0 .and. dummy2d_8(i,j) < 271.2) then +! print*,'too cool SST ',i,j,dummy2d_8(i,j) + dummy2d_8(i,j) = 271.2 + endif + if(slmsk_save(i,j) == 0 .and. dummy2d_8(i,j) > 310.) then +! print*,'too hot SST ',i,j,dummy2d_8(i,j) + dummy2d_8(i,j) = 310.0 + endif + enddo enddo - enddo - endif - print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" - call ESMF_FieldScatter(skin_temp_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" + call ESMF_FieldScatter(skin_temp_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - if (localpet == 0) dummy2d = 0.0 +! srflag not in files. Set to zero. + + if (localpet == 0) dummy2d_8 = 0.0 - print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" - call ESMF_FieldScatter(srflag_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0,rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" + call ESMF_FieldScatter(srflag_input_grid,dummy2d_8, rootpet=0,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - if (localpet == 0) then - print*,"- READ SOIL TYPE." - slev=":surface:" - vname=":SOTYP:" - rc = grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - !failed => rc = 0 - if (rc <= 0 .and. (trim(to_upper(external_model))=="HRRR" .or. rap_latlon) .and. geo_file .ne. "NULL") then + if (localpet == 0) then + + print*,"- READ SOIL TYPE." + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 3 ! Sec4/oct 10 - parameter category - soil products + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - soil type + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc == 0 ) then +! print*,'soil type ', maxval(gfld%fld),minval(gfld%fld) + dummy2d = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + if (rc /= 0 .and. (trim(to_upper(external_model))=="HRRR" .or. rap_latlon) .and. geo_file .ne. "NULL") then ! Some HRRR and RAP files don't have dominant soil type in the output, but the geogrid files ! do, so this gives users the option to provide the geogrid file and use input soil ! type - print*, "OPEN GEOGRID FILE ", trim(geo_file) - rc = nf90_open(geo_file,NF90_NOWRITE,ncid2d) - call netcdf_err(rc,"READING GEOGRID FILE") + print*, "OPEN GEOGRID FILE ", trim(geo_file) + rc = nf90_open(geo_file,NF90_NOWRITE,ncid2d) + call netcdf_err(rc,"READING GEOGRID FILE") - print*, "INQURE ABOUT DIM IDS" - rc = nf90_inq_dimid(ncid2d,"west_east",varid) - call netcdf_err(rc,"READING west_east DIMENSION FROM GEOGRID FILE") + print*, "INQURE ABOUT DIM IDS" + rc = nf90_inq_dimid(ncid2d,"west_east",varid) + call netcdf_err(rc,"READING west_east DIMENSION FROM GEOGRID FILE") - rc = nf90_inquire_dimension(ncid2d,varid,len=varsize) - call netcdf_err(rc,"READING west_east DIMENSION SIZE") - if (varsize .ne. i_input) call error_handler ("GEOGRID FILE GRID SIZE DIFFERS FROM INPUT DATA.", -1) + rc = nf90_inquire_dimension(ncid2d,varid,len=varsize) + call netcdf_err(rc,"READING west_east DIMENSION SIZE") + if (varsize .ne. i_input) call error_handler ("GEOGRID FILE GRID SIZE DIFFERS FROM INPUT DATA.", -1) - print*, "INQUIRE ABOUT SOIL TYPE FROM GEOGRID FILE" - rc = nf90_inq_varid(ncid2d,"SCT_DOM",varid) - call netcdf_err(rc,"FINDING SCT_DOM IN GEOGRID FILE") + print*, "INQUIRE ABOUT SOIL TYPE FROM GEOGRID FILE" + rc = nf90_inq_varid(ncid2d,"SCT_DOM",varid) + call netcdf_err(rc,"FINDING SCT_DOM IN GEOGRID FILE") - print*, "READ SOIL TYPE FROM GEOGRID FILE " - rc = nf90_get_var(ncid2d,varid,dummy2d) - call netcdf_err(rc,"READING SCT_DOM FROM FILE") + print*, "READ SOIL TYPE FROM GEOGRID FILE " + rc = nf90_get_var(ncid2d,varid,dummy2d) + call netcdf_err(rc,"READING SCT_DOM FROM FILE") - print*, "INQUIRE ABOUT SOIL TYPE FRACTIONS FROM GEOGRID FILE" - rc = nf90_inq_varid(ncid2d,"SOILCTOP",varid) - call netcdf_err(rc,"FINDING SOILCTOP IN GEOGRID FILE") + print*, "INQUIRE ABOUT SOIL TYPE FRACTIONS FROM GEOGRID FILE" + rc = nf90_inq_varid(ncid2d,"SOILCTOP",varid) + call netcdf_err(rc,"FINDING SOILCTOP IN GEOGRID FILE") - print*, "READ SOIL TYPE FRACTIONS FROM GEOGRID FILE " - rc = nf90_get_var(ncid2d,varid,dummy3d_stype) - call netcdf_err(rc,"READING SCT_DOM FROM FILE") + allocate(dummy3d_stype(i_input,j_input,16)) + print*, "READ SOIL TYPE FRACTIONS FROM GEOGRID FILE " + rc = nf90_get_var(ncid2d,varid,dummy3d_stype) + call netcdf_err(rc,"READING SCT_DOM FROM FILE") - print*, "CLOSE GEOGRID FILE " - iret = nf90_close(ncid2d) - + print*, "CLOSE GEOGRID FILE " + iret = nf90_close(ncid2d) ! There's an issue with the geogrid file containing soil type water at land points. ! This correction replaces the soil type at these points with the soil type with ! the next highest fractional coverage. - do j = 1, j_input + allocate(dummy1d(16)) + do j = 1, j_input do i = 1, i_input if(dummy2d(i,j) == 14.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) then dummy1d(:) = dummy3d_stype(i,j,:) @@ -5035,396 +5552,501 @@ subroutine read_input_sfc_grib2_file(localpet) dummy2d(i,j) = real(MAXLOC(dummy1d, 1),esmf_kind_r4) endif enddo - enddo - deallocate(dummy1d) - endif ! localpet == 0 + enddo + deallocate(dummy1d) + deallocate(dummy3d_stype) + endif ! failed - if ((rc <= 0 .and. trim(to_upper(external_model)) /= "HRRR" .and. .not. rap_latlon) & - .or. (rc < 0 .and. (trim(to_upper(external_model)) == "HRRR" .or. rap_latlon))) then - if (.not. sotyp_from_climo) then - call error_handler("COULD NOT FIND SOIL TYPE IN FILE. PLEASE SET SOTYP_FROM_CLIMO=.TRUE. . EXITING", rc) - else - vname = "sotyp" - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - loc=varnum) - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc == 1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. WILL NOT "//& - "SCALE SOIL MOISTURE FOR DIFFERENCES IN SOIL TYPE. " - dummy2d(:,:) = -99999.0_esmf_kind_r4 + if ((rc /= 0 .and. trim(to_upper(external_model)) /= "HRRR" .and. .not. rap_latlon) & + .or. (rc /= 0 .and. (trim(to_upper(external_model)) == "HRRR" .or. rap_latlon))) then + if (.not. sotyp_from_climo) then + call error_handler("COULD NOT FIND SOIL TYPE IN FILE. PLEASE SET SOTYP_FROM_CLIMO=.TRUE. . EXITING", rc) + else + vname = "sotyp" + slev = "surface" + call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & + loc=varnum) + call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) + if (rc == 1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. WILL NOT "//& + "SCALE SOIL MOISTURE FOR DIFFERENCES IN SOIL TYPE. " + dummy2d(:,:) = -99999.0_esmf_kind_r4 + endif endif endif - endif ! In the event that the soil type on the input grid still contains mismatches between ! soil type and landmask, this correction is a last-ditch effort to replace these points ! with soil type from a nearby land point. - if (.not. sotyp_from_climo) then - do j = 1, j_input - do i = 1, i_input - if(dummy2d(i,j) == 14.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) dummy2d(i,j) = -99999.9 - enddo - enddo - - dummy2d_8 = real(dummy2d,esmf_kind_r8) - dummy2d_i(:,:) = 0 - where(slmsk_save == 1) dummy2d_i = 1 + + if (.not. sotyp_from_climo) then + do j = 1, j_input + do i = 1, i_input + if(dummy2d(i,j) == 14.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) dummy2d(i,j) = -99999.9 + enddo + enddo + + allocate(dummy2d_i(i_input,j_input)) + dummy2d_8 = real(dummy2d,esmf_kind_r8) + dummy2d_i(:,:) = 0 + where(slmsk_save == 1) dummy2d_i = 1 - call search(dummy2d_8,dummy2d_i,i_input,j_input,1,230) - else - dummy2d_8=real(dummy2d,esmf_kind_r8) - endif + call search(dummy2d_8,dummy2d_i,i_input,j_input,1,230) + deallocate(dummy2d_i) + else + dummy2d_8=real(dummy2d,esmf_kind_r8) + endif - print*,'sotype ',maxval(dummy2d_8),minval(dummy2d_8) - deallocate(dummy2d_i) - deallocate(dummy3d_stype) - endif ! localpet == 0 + print*,'sotype ',maxval(dummy2d_8),minval(dummy2d_8) + + endif ! read of soil type + print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + deallocate(dummy2d) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! Begin variables whose presence in grib2 files varies, but no climatological ! data is available, so we have to account for values in the varmap table !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - if (.not. vgfrc_from_climo) then - if (localpet == 0) then - print*,"- READ VEG FRACTION." - vname="vfrac" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - loc=varnum) - !! Changing these for GSD internal runs using new HRRR files - vname=":VEG:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - - if (rc > 1) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1105:', data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1101:', data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1151:', data2=dummy2d) - if (rc <= 0) call error_handler("COULD NOT DETERMINE VEGETATION FRACTION IN FILE. & - RECORD NUMBERS MAY HAVE CHANGED. PLEASE SET VGFRC_FROM_CLIMO=.TRUE. EXITING", rc) - endif - endif - elseif (rc <= 0) then - call error_handler("COULD NOT FIND VEGETATION FRACTION IN FILE. & + if (.not. vgfrc_from_climo) then + + if (localpet == 0) then + + print*,"- READ VEG FRACTION." + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 4 ! Sec4/oct 11 - parameter number - vegetation + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 )then + call error_handler("COULD NOT FIND VEGETATION FRACTION IN FILE. & PLEASE SET VGFRC_FROM_CLIMO=.TRUE. EXITING", rc) - endif - if(maxval(dummy2d) > 2.0) dummy2d = dummy2d / 100.0_esmf_kind_r4 - print*,'vfrac ',maxval(dummy2d),minval(dummy2d) + else + if (maxval(gfld%fld) > 2.0) gfld%fld = gfld%fld / 100.0 +! print*,'vfrac ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + endif ! localpet 0 + + print*,"- CALL FieldScatter FOR INPUT GRID VEG GREENNESS." + call ESMF_FieldScatter(veg_greenness_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + endif + if (.not. minmax_vgfrc_from_climo) then + + if (localpet == 0) then + + print*,"- READ MIN VEG FRACTION." + + jdisc = 2 ! Search for discipline - land products + j = 1105 ! grib2 file does not distinguish between the various veg + ! fractions. Need to search using record number. + jpdtn = 0 ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 4 ! Sec4/oct 11 - parameter number - vegetation + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) then + j = 1101 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + j = 1151 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc/=0) call error_handler("COULD NOT FIND MIN VEGETATION FRACTION IN FILE. & + PLEASE SET MINMAX_VGFRC_FROM_CLIMO=.TRUE. . EXITING",rc) + endif + endif + + if (maxval(gfld%fld) > 2.0) gfld%fld = gfld%fld / 100.0 + print*,'vfrac min ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif ! localpet == 0 + + print*,"- CALL FieldScatter FOR INPUT GRID MIN VEG GREENNESS." + call ESMF_FieldScatter(min_veg_greenness_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ MAX VEG FRACTION." + + jdisc = 2 ! Search for discipline - land products + j = 1106 ! Have to search by record number. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 4 ! Sec4/oct 11 - parameter number - vegetation + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + j = 1102 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + j = 1152 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc <= 0) call error_handler("COULD NOT FIND MAX VEGETATION FRACTION IN FILE. & + PLEASE SET MINMAX_VGFRC_FROM_CLIMO=.TRUE. . EXITING",rc) + endif + endif + + if (maxval(gfld%fld) > 2.0) gfld%fld = gfld%fld / 100.0 +! print*,'vfrac max ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif !localpet==0 + + print*,"- CALL FieldScatter FOR INPUT GRID MAX VEG GREENNESS." + call ESMF_FieldScatter(max_veg_greenness_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + endif !minmax_vgfrc_from_climo - print*,"- CALL FieldScatter FOR INPUT GRID VEG GREENNESS." - call ESMF_FieldScatter(veg_greenness_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - endif + if (.not. lai_from_climo) then + + if (localpet == 0) then + + print*,"- READ LAI." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 7 ! Sec4/oct 10 - parameter category - thermo stability indices + jpdt(2) = 198 ! Sec4/oct 11 - parameter number - leaf area index + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) call error_handler("COULD NOT FIND LAI IN FILE. & + PLEASE SET LAI_FROM_CLIMO=.TRUE. . EXITING",rc) + +! print*,'lai ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif !localpet==0 + + print*,"- CALL FieldScatter FOR INPUT GRID LAI." + call ESMF_FieldScatter(lai_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + endif ! lai - if (.not. minmax_vgfrc_from_climo) then if (localpet == 0) then - print*,"- READ MIN VEG FRACTION." - vname="vfrac_min" - slev=":surface:" + + print*,"- READ SEAICE DEPTH." + vname="hice" + slev=":surface:" call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":VEG:" - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1106:',data2=dummy2d) - - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1102:',data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1152:',data2=dummy2d) - if (rc<=0) call error_handler("COULD NOT FIND MIN VEGETATION FRACTION IN FILE. & - PLEASE SET MINMAX_VGFRC_FROM_CLIMO=.TRUE. . EXITING",rc) + loc=varnum) + + jdisc = 10 ! Search for discipline - ocean products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - ice + jpdt(2) = 1 ! Sec4/oct 11 - parameter number - thickness + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then + call handle_grib_error(vname, slev ,method,value,varnum,rc,var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& + " REPLACED WITH CLIMO. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8(:,:) = 0.0 endif + else +! print*,'hice ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) endif - if(maxval(dummy2d) > 2.0) dummy2d = dummy2d / 100.0_esmf_kind_r4 - print*,'vfrac min',maxval(dummy2d),minval(dummy2d) - endif + endif - print*,"- CALL FieldScatter FOR INPUT GRID MIN VEG GREENNESS." - call ESMF_FieldScatter(min_veg_greenness_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0, rc=rc) + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." + call ESMF_FieldScatter(seaice_depth_input_grid,dummy2d_8, rootpet=0, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& call error_handler("IN FieldScatter", rc) - + if (localpet == 0) then - print*,"- READ MAX VEG FRACTION." - vname="vfrac_max" - slev=":surface:" + + print*,"- READ TPRCP." + vname="tprcp" + slev=":surface:" call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - - vname=":VEG:" - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1107:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1103:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1153:',data2=dummy2d) - if (rc <= 0) call error_handler("COULD NOT FIND MAX VEGETATION FRACTION IN FILE. & - PLEASE SET MINMAX_VGFRC_FROM_CLIMO=.TRUE. . EXITING",rc) - endif + loc=varnum) + +! No test data contained this field. So could not test with g2 library. + rc = 1 + if (rc /= 0) then + call handle_grib_error(vname, slev ,method,value,varnum,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& + " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8 = 0.0 + endif endif - if(maxval(dummy2d) > 2.0) dummy2d = dummy2d / 100.0_esmf_kind_r4 - print*,'vfrac max',maxval(dummy2d),minval(dummy2d) + print*,'tprcp ',maxval(dummy2d_8),minval(dummy2d_8) - endif !localpet==0 + endif ! tprcp - print*,"- CALL FieldScatter FOR INPUT GRID MAX VEG GREENNESS." - call ESMF_FieldScatter(max_veg_greenness_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) + print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." + call ESMF_FieldScatter(tprcp_input_grid,dummy2d_8, rootpet=0, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& call error_handler("IN FieldScatter", rc) - endif !minmax_vgfrc_from_climo - if (.not. lai_from_climo) then if (localpet == 0) then - print*,"- READ LAI." - vname="lai" - slev=":surface:" + + print*,"- READ FFMM." + vname="ffmm" + slev=":surface:" call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":var0_7_198:" - rc= grb2_inq(the_file, inv_file, vname,slev,':n=1108:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,':n=1104:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,':n=1154:',data2=dummy2d) - if (rc <= 0) call error_handler("COULD NOT FIND LAI IN FILE. & - PLEASE SET LAI_FROM_CLIMO=.TRUE. . EXITING",rc) + loc=varnum) + +! No sample data contained this field, so could not test g2lib. + rc = 1 + if (rc /= 0) then + call handle_grib_error(vname, slev ,method,value,varnum,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& + " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8(:,:) = 0.0 endif endif - print*,'lai',maxval(dummy2d),minval(dummy2d) - endif !localpet==0 + print*,'ffmm ',maxval(dummy2d_8),minval(dummy2d_8) - print*,"- CALL FieldScatter FOR INPUT GRID LAI." - call ESMF_FieldScatter(lai_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) + endif ! ffmm + + print*,"- CALL FieldScatter FOR INPUT GRID FFMM" + call ESMF_FieldScatter(ffmm_input_grid,dummy2d_8, rootpet=0, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& call error_handler("IN FieldScatter", rc) - - endif - if (localpet == 0) then - print*,"- READ SEAICE DEPTH." - vname="hice" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":ICETK:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& - " REPLACED WITH CLIMO. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'hice ',maxval(dummy2d),minval(dummy2d) - - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." - call ESMF_FieldScatter(seaice_depth_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - if (localpet == 0) then - print*,"- READ TPRCP." - vname="tprcp" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":TPRCP:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& - " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'tprcp ',maxval(dummy2d),minval(dummy2d) - endif + if (localpet == 0) then - print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." - call ESMF_FieldScatter(tprcp_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ FFMM." - vname="ffmm" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + print*,"- READ USTAR." + vname="fricv" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & loc=varnum) - vname=":FFMM:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& - " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'ffmm ',maxval(dummy2d),minval(dummy2d) - endif - print*,"- CALL FieldScatter FOR INPUT GRID FFMM" - call ESMF_FieldScatter(ffmm_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ USTAR." - vname="fricv" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":FRICV:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL "//& + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - momentum + jpdt(2) = 30 ! Sec4/oct 11 - parameter number - friction velocity + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + jpdt(2) = 197 ! oct 11 - param number - friction vel. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + endif + + if (rc == 0) then +! print*,'fricv ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + else + call handle_grib_error(vname, slev ,method,value,varnum,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL "//& "REPLACED WITH CLIMO. SET A FILL "// & "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'fricv ',maxval(dummy2d),minval(dummy2d) - endif + dummy2d_8(:,:) = 0.0 + endif + endif - print*,"- CALL FieldScatter FOR INPUT GRID USTAR" - call ESMF_FieldScatter(ustar_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + endif ! ustar - if (localpet == 0) then - print*,"- READ F10M." - vname="f10m" - slev=":10 m above ground:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + print*,"- CALL FieldScatter FOR INPUT GRID USTAR" + call ESMF_FieldScatter(ustar_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ F10M." + vname="f10m" + slev=":10 m above ground:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & loc=varnum) - vname=":F10M:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& + + rc = -1 ! None of the test cases have this record. Can't test with g2lib. + if (rc /= 0) then + call handle_grib_error(vname, slev ,method,value,varnum,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'f10m ',maxval(dummy2d),minval(dummy2d) - endif + dummy2d_8(:,:) = 0.0 + endif + endif + print*,'f10m ',maxval(dummy2d_8),minval(dummy2d_8) - print*,"- CALL FieldScatter FOR INPUT GRID F10M." - call ESMF_FieldScatter(f10m_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + endif - if (localpet == 0) then - print*,"- READ CANOPY MOISTURE CONTENT." - vname="cnwat" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + print*,"- CALL FieldScatter FOR INPUT GRID F10M." + call ESMF_FieldScatter(f10m_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ CANOPY MOISTURE CONTENT." + vname="cnwat" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & loc=varnum) - vname=":CNWAT:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL"//& + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search from beginning of file + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 13 ! Sec4/oct 11 - parameter number - canopy water + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then + jpdt(2) = 196 ! Sec4/oct 11 - param number - canopy water + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + endif + + if (rc == 0 ) then + print*,'cnwat ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + call check_cnwat(dummy2d_8) + else + call handle_grib_error(vname, slev ,method,value,varnum,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL"//& " REPLACED WITH CLIMO. SET A FILL "// & "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - call check_cnwat(dummy2d) - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'cnwat ',maxval(dummy2d),minval(dummy2d) - endif + dummy2d_8 = 0.0 + endif + endif - print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." - call ESMF_FieldScatter(canopy_mc_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + endif - if (localpet == 0) then - print*,"- READ Z0." - vname="sfcr" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." + call ESMF_FieldScatter(canopy_mc_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ Z0." + vname="sfcr" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & loc=varnum) - vname=":SFCR:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search from beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 1 ! Sec4/oct 11 - parameter number - surface roughness + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then + call handle_grib_error(vname, slev ,method,value,varnum,rc, var8= dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& " REPLACED WITH CLIMO. SET A FILL "// & "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - else - ! Grib files have z0 (m), but fv3 expects z0(cm) - dummy2d(:,:) = dummy2d(:,:)*10.0 - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'sfcr ',maxval(dummy2d),minval(dummy2d) - - endif + dummy2d_8(:,:) = 0.0 + endif + else + gfld%fld = gfld%fld * 10.0 ! Grib files have z0 (m), but fv3 expects z0(cm) +! print*,'sfcr ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + endif - print*,"- CALL FieldScatter FOR INPUT GRID Z0." - call ESMF_FieldScatter(z0_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Z0." + call ESMF_FieldScatter(z0_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - if (localpet == 0) then - print*,"- READ LIQUID SOIL MOISTURE." - vname = "soill" - vname_file = ":SOILL:" - call read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) !!! NEEDTO HANDLE - !!! SOIL LEVELS - print*,'soill ',maxval(dummy3d),minval(dummy3d) - endif + if (localpet == 0) then + print*,"- READ LIQUID SOIL MOISTURE." + vname = "soill" + vname_file = ":SOILL:" + call read_grib_soil(vname,vname_file,lugb, dummy3d) !!! NEED TO HANDLE + !!! SOIL LEVELS + endif - print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." - call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." + call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - if (localpet == 0) then - print*,"- READ TOTAL SOIL MOISTURE." - vname = "soilw" - !vname_file = "var2_2_1_7_0_192" !Some files don't recognize this as soilw,so use - vname_file = "var2_2_1_" ! the var number instead - call read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) - print*,'soilm ',maxval(dummy3d),minval(dummy3d) - endif + if (localpet == 0) then + print*,"- READ TOTAL SOIL MOISTURE." + vname = "soilw" + vname_file = "var2_2_1_" ! the var number instead + call read_grib_soil(vname,vname_file,lugb,dummy3d) + endif - print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." - call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." + call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) !---------------------------------------------------------------------------------------- ! Vegetation type is not available in some files. However, it is needed to identify @@ -5432,75 +6054,82 @@ subroutine read_input_sfc_grib2_file(localpet) ! '1'. Use this flag as a temporary solution. !---------------------------------------------------------------------------------------- - print*, "- CALL FieldGather for INPUT SOIL TYPE." - call ESMF_FieldGather(soil_type_input_grid, dummy2d_82, rootPet=0, tile=1, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - if (localpet == 0) then - print*,"- READ VEG TYPE." - vname="vtype" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - loc=varnum) - !Note: sometimes the grib files don't have this one named. Searching for this string - ! ensures that the data is found when it exists - - vname="var2_2" - rc= grb2_inq(the_file, inv_file, vname,"_0_198:",slev,' hour fcst:', data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,"_0_198:",slev,':anl:', data2=dummy2d) - if (rc <= 0) then + print*, "- CALL FieldGather for INPUT SOIL TYPE." + call ESMF_FieldGather(soil_type_input_grid, dummy2d_82, rootPet=0, tile=1, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather", rc) + + if (localpet == 0) then + + print*,"- READ VEG TYPE." + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search from beginning of file. + jpdtn = 0 ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 198 ! Sec4/oct 11 - parameter number - vegetation type + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then if (.not. vgtyp_from_climo) then call error_handler("COULD NOT FIND VEGETATION TYPE IN FILE. PLEASE SET VGTYP_FROM_CLIMO=.TRUE. . EXITING", rc) - else - do j = 1, j_input - do i = 1, i_input - dummy2d(i,j) = 0.0_esmf_kind_r4 - if(slmsk_save(i,j) == 1 .and. dummy3d(i,j,1) > 0.99) & - dummy2d(i,j) = real(veg_type_landice_input,esmf_kind_r4) - enddo - enddo - endif ! replace_vgtyp - endif !not find :anl: - endif !not find hour fcst: - - if (trim(external_model) .ne. "GFS") then - do j = 1, j_input - do i = 1,i_input - if (dummy2d(i,j) == 15.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) then - if (dummy3d(i,j,1) < 0.6) then - dummy2d(i,j) = real(veg_type_landice_input,esmf_kind_r4) - elseif (dummy3d(i,j,1) > 0.99) then - slmsk_save(i,j) = 0 - dummy2d(i,j) = 0.0_esmf_kind_r4 - dummy2d_82(i,j) = 0.0_esmf_kind_r8 + else ! Set input veg type at land ice from soil moisture flag (1.0). + do j = 1, j_input + do i = 1, i_input + dummy2d_8(i,j) = 0.0 + if(slmsk_save(i,j) == 1 .and. dummy3d(i,j,1) > 0.99) & ! land ice indicated by + ! soil moisture flag of '1'. + dummy2d_8(i,j) = real(veg_type_landice_input,esmf_kind_r8) + enddo + enddo endif - elseif (dummy2d(i,j) == 17.0_esmf_kind_r4 .and. slmsk_save(i,j)==0) then - dummy2d(i,j) = 0.0_esmf_kind_r4 + else ! found vtype in file. + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) endif - enddo - enddo - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'vgtyp ',maxval(dummy2d),minval(dummy2d) - endif !localpet - deallocate(dummy2d) - print*,"- CALL FieldScatter FOR INPUT VEG TYPE." - call ESMF_FieldScatter(veg_type_input_grid, dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - print*,"- CALL FieldScatter FOR INPUT SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid, dummy2d_82, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + if (trim(external_model) .ne. "GFS") then + do j = 1, j_input + do i = 1,i_input + if (dummy2d_8(i,j) == 15.0_esmf_kind_r8 .and. slmsk_save(i,j) == 1) then + if (dummy3d(i,j,1) < 0.6) then + dummy2d_8(i,j) = real(veg_type_landice_input,esmf_kind_r8) + elseif (dummy3d(i,j,1) > 0.99) then + slmsk_save(i,j) = 0 + dummy2d_8(i,j) = 0.0_esmf_kind_r8 + dummy2d_82(i,j) = 0.0_esmf_kind_r8 + endif + elseif (dummy2d_8(i,j) == 17.0_esmf_kind_r8 .and. slmsk_save(i,j)==0) then + dummy2d_8(i,j) = 0.0_esmf_kind_r8 + endif + enddo + enddo + endif - deallocate(dummy2d_82) +! print*,'vgtyp ',maxval(dummy2d_8),minval(dummy2d_8) - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid,real(slmsk_save,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + endif ! read veg type + + print*,"- CALL FieldScatter FOR INPUT VEG TYPE." + call ESMF_FieldScatter(veg_type_input_grid, dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + print*,"- CALL FieldScatter FOR INPUT SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid, dummy2d_82, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d_82) + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid,real(slmsk_save,esmf_kind_r8),rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) !--------------------------------------------------------------------------------- ! At open water (slmsk==0), the soil temperature array is not used and set @@ -5509,27 +6138,27 @@ subroutine read_input_sfc_grib2_file(localpet) ! in the grib data, so set to a default value. !--------------------------------------------------------------------------------- - if (localpet == 0) then - print*,"- READ SOIL TEMPERATURE." - vname = "soilt" - vname_file = ":TSOIL:" - call read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) - call check_soilt(dummy3d,slmsk_save,tsk_save) - print*,'soilt ',maxval(dummy3d),minval(dummy3d) - - deallocate(tsk_save) - endif + if (localpet == 0) then + print*,"- READ SOIL TEMPERATURE." + vname = "soilt" + vname_file = ":TSOIL:" + call read_grib_soil(vname,vname_file,lugb,dummy3d) + call check_soilt(dummy3d,slmsk_save,tsk_save) + deallocate(tsk_save) + endif - deallocate(slmsk_save) + deallocate(slmsk_save) - print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." - call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." + call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) - deallocate(dummy3d) - deallocate(dummy2d_8) + deallocate(dummy3d) + deallocate(dummy2d_8) + if (localpet == 0) call baclose(lugb, rc) + end subroutine read_input_sfc_grib2_file !> Read nst data from these netcdf formatted fv3 files: tiled history, @@ -6137,39 +6766,47 @@ END SUBROUTINE READ_FV3_GRID_DATA_NETCDF !> Read winds from a grib2 file. Rotate winds !! to be earth relative if necessary. !! -!! @param [in] file grib2 file to be read -!! @param [in] inv grib2 inventory file !! @param [inout] u u-component wind !! @param [inout] v v-component wind !! @param[in] localpet ESMF local persistent execution thread +!! @param[in] isnative When true, data on hybrid levels. Otherwise +!! data is on isobaric levels. +!! @param[in] rlevs Array of atmospheric level values +!! @param[in] lugb Logical unit number of GRIB2 file. !! @author Larissa Reames - subroutine read_winds(file,inv,u,v,localpet) + subroutine read_winds(u,v,localpet,isnative,rlevs,lugb) + + use grib_mod + use program_setup, only : get_var_cond - use wgrib2api - use netcdf - use program_setup, only : get_var_cond, fix_dir_input_grid - use model_grid, only : input_grid_type implicit none - character(len=250), intent(in) :: file - character(len=10), intent(in) :: inv - integer, intent(in) :: localpet - real(esmf_kind_r8), intent(inout), allocatable :: u(:,:,:),v(:,:,:) + integer, intent(in) :: localpet, lugb + + logical, intent(in) :: isnative + + real(esmf_kind_r8), intent(inout), allocatable :: u(:,:,:),v(:,:,:) + real(esmf_kind_r8), intent(in), dimension(lev_input) :: rlevs real(esmf_kind_r4), dimension(i_input,j_input) :: alpha real(esmf_kind_r8), dimension(i_input,j_input) :: lon, lat real(esmf_kind_r4), allocatable :: u_tmp(:,:),v_tmp(:,:) + real(esmf_kind_r8), allocatable :: dum2d(:,:) real(esmf_kind_r4), dimension(i_input,j_input) :: ws,wd real(esmf_kind_r4) :: value_u, value_v,lov,latin1,latin2 real(esmf_kind_r8) :: d2r - integer :: varnum_u, varnum_v, vlev, & !ncid, id_var, & - error, iret, istr + integer :: varnum_u, varnum_v, vlev, & + error, iret + integer :: j, k, lugi, jgdtn, jpdtn + integer :: jdisc, jids(200), jgdt(200), jpdt(200) character(len=20) :: vname character(len=50) :: method_u, method_v - character(len=250) :: file_coord - character(len=10000) :: temp_msg + + logical :: unpack + + type(gribfield) :: gfld d2r=acos(-1.0_esmf_kind_r8) / 180.0_esmf_kind_r8 if (localpet==0) then @@ -6180,8 +6817,6 @@ subroutine read_winds(file,inv,u,v,localpet) allocate(v(0,0,0)) endif - file_coord = trim(fix_dir_input_grid)//"/latlon_grid3.32769.nc" - vname = "u" call get_var_cond(vname,this_miss_var_method=method_u, this_miss_var_value=value_u, & loc=varnum_u) @@ -6189,90 +6824,107 @@ subroutine read_winds(file,inv,u,v,localpet) call get_var_cond(vname,this_miss_var_method=method_v, this_miss_var_value=value_v, & loc=varnum_v) - if (trim(input_grid_type)=="rotated_latlon") then - print*,"- CALL FieldGather FOR INPUT GRID LONGITUDE" - call ESMF_FieldGather(longitude_input_grid, lon, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", error) - print*,"- CALL FieldGather FOR INPUT GRID LATITUDE" - call ESMF_FieldGather(latitude_input_grid, lat, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + print*,"- CALL FieldGather FOR INPUT GRID LONGITUDE" + call ESMF_FieldGather(longitude_input_grid, lon, rootPet=0, tile=1, rc=error) + if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather", error) - if (localpet==0) then - print*,"- CALCULATE ROTATION ANGLE FOR ROTATED_LATLON INPUT GRID" - error = grb2_inq(file, inv,grid_desc=temp_msg) - !1:0:grid_template=32769:winds(grid): - ! I am not an Arakawa E-grid. - ! I am rotated but have no rotation angle. - ! I am staggered. What am I? - ! (953 x 834) units 1e-06 input WE:SN output WE:SN res 56 - ! lat0 -10.590603 lat-center 54.000000 dlat 121.813000 - ! lon0 220.914154 lon-center 254.000000 dlon 121.813000 #points=794802 - - istr = index(temp_msg, "lat-center ") + len("lat_center ") - read(temp_msg(istr:istr+9),"(F8.5)") latin1 - istr = index(temp_msg, "lon-center ") + len("lon-center ") - read(temp_msg(istr:istr+10),"(F9.6)") lov - - print*, "- CALL CALCALPHA_ROTLATLON with center lat,lon = ",latin1,lov - call calcalpha_rotlatlon(lat,lon,latin1,lov,alpha) - print*, " alpha min/max = ",MINVAL(alpha),MAXVAL(alpha) - endif - elseif (trim(input_grid_type) == "lambert") then - !# NG this has been edited to correctly calculate gridrot for Lambert grids - ! Previously was incorrectly using polar-stereographic formation - print*,"- CALL FieldGather FOR INPUT GRID LONGITUDE" - call ESMF_FieldGather(longitude_input_grid, lon, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + print*,"- CALL FieldGather FOR INPUT GRID LATITUDE" + call ESMF_FieldGather(latitude_input_grid, lat, rootPet=0, tile=1, rc=error) + if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather", error) - if (localpet==0) then - error = grb2_inq(file, inv,grid_desc=temp_msg) - !1:0:grid_template=30:winds(grid): - ! Lambert Conformal: (1799 x 1059) input WE:SN output WE:SN res 8 - ! Lat1 21.138123 Lon1 237.280472 LoV 262.500000 - ! LatD 38.500000 Latin1 38.500000 Latin2 38.500000 - ! LatSP 0.000000 LonSP 0.000000 - ! North Pole (1799 x 1059) Dx 3000.000000 m Dy 3000.000000 m mode 8 - - istr = index(temp_msg, "LoV ") + len("LoV ") - read(temp_msg(istr:istr+10),"(F9.6)") lov - istr = index(temp_msg, "Latin1 ") + len("Latin1 ") - read(temp_msg(istr:istr+9),"(F8.5)") latin1 - istr = index(temp_msg, "Latin2 ") + len("Latin2 ") - read(temp_msg(istr:istr+9),"(F8.5)") latin2 + if (localpet==0) then + + lugi = 0 ! index file unit number + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + unpack=.false. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) call error_handler("ERROR READING GRIB2 FILE.", iret) + + if (gfld%igdtnum == 32769) then ! grid definition template number - rotated lat/lon grid + + latin1 = float(gfld%igdtmpl(15))/1.0E6 + lov = float(gfld%igdtmpl(16))/1.0E6 + + print*, "- CALL CALCALPHA_ROTLATLON with center lat,lon = ",latin1,lov + call calcalpha_rotlatlon(lat,lon,latin1,lov,alpha) + + elseif (gfld%igdtnum == 30) then ! grid definition template number - lambert conformal grid. + + lov = float(gfld%igdtmpl(14))/1.0E6 + latin1 = float(gfld%igdtmpl(19))/1.0E6 + latin2 = float(gfld%igdtmpl(20))/1.0E6 print*, "- CALL GRIDROT for LC grid with lov,latin1/2 = ",lov,latin1,latin2 call gridrot(lov,latin1,latin2,lon,alpha) - print*, " alpha min/max = ",MINVAL(alpha),MAXVAL(alpha) + endif - endif - if (localpet==0) then + if (isnative) then + jpdt(10) = 105 ! Sec4/oct 23 - type of level - hybrid + else + jpdt(10) = 100 ! Sec4/oct 23 - type of level - isobaric + endif + + unpack=.true. + + allocate(dum2d(i_input,j_input)) + allocate(u_tmp(i_input,j_input)) + allocate(v_tmp(i_input,j_input)) + do vlev = 1, lev_input vname = ":UGRD:" - iret = grb2_inq(file,inv,vname,slevs(vlev),data2=u_tmp) - if (iret <= 0) then + + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - momentum + jpdt(2) = 2 ! Sec4/oct 11 - parameter number - u-wind + jpdt(12) = nint(rlevs(vlev)) ! Sect4/octs 25-28 - scaled value of fixed surface. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) then call handle_grib_error(vname, slevs(vlev),method_u,value_u,varnum_u,iret,var=u_tmp) if (iret==1) then ! missing_var_method == skip call error_handler("READING IN U AT LEVEL "//trim(slevs(vlev))//". SET A FILL "// & "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) endif + else + dum2d = reshape(gfld%fld, (/i_input,j_input/) ) + u_tmp(:,:) = dum2d endif vname = ":VGRD:" - iret = grb2_inq(file,inv,vname,slevs(vlev),data2=v_tmp) - if (iret <= 0) then + + jpdt(2) = 3 ! Sec4/oct 11 - parameter number - v-wind + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) then call handle_grib_error(vname, slevs(vlev),method_v,value_v,varnum_v,iret,var=v_tmp) if (iret==1) then ! missing_var_method == skip call error_handler("READING IN V AT LEVEL "//trim(slevs(vlev))//". SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) + "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) endif - endif + else + dum2d = reshape(gfld%fld, (/i_input,j_input/) ) + v_tmp(:,:) = dum2d + endif - if (trim(input_grid_type) == "latlon") then + deallocate(dum2d) + + if (gfld%igdtnum == 0) then ! grid definition template number - lat/lon grid if (external_model == 'UKMET') then u(:,:,vlev) = u_tmp v(:,:,vlev) = (v_tmp(:,2:jp1_input) + v_tmp(:,1:j_input))/2 @@ -6280,7 +6932,7 @@ subroutine read_winds(file,inv,u,v,localpet) u(:,:,vlev) = u_tmp v(:,:,vlev) = v_tmp endif - else if (trim(input_grid_type) == "rotated_latlon") then + else if (gfld%igdtnum == 32769) then ! grid definition template number - rotated lat/lon grid ws = sqrt(u_tmp**2 + v_tmp**2) wd = atan2(-u_tmp,-v_tmp) / d2r ! calculate grid-relative wind direction wd = wd + alpha + 180.0 ! Rotate from grid- to earth-relative direction @@ -6498,13 +7150,13 @@ subroutine handle_grib_error(vname,lev,method,value,varnum, iret,var,var8,var3d) read_from_input(varnum) = .false. iret = 1 elseif (trim(method) == "set_to_fill") then - print*, "WARNING: ,", trim(vname), " NOT AVILABLE AT LEVEL ", trim(lev), & + print*, "WARNING: ,", trim(vname), " NOT AVAILABLE AT LEVEL ", trim(lev), & ". SETTING EQUAL TO FILL VALUE OF ", value if(present(var)) var(:,:) = value if(present(var8)) var8(:,:) = value if(present(var3d)) var3d(:,:,:) = value elseif (trim(method) == "set_to_NaN") then - print*, "WARNING: ,", trim(vname), " NOT AVILABLE AT LEVEL ", trim(lev), & + print*, "WARNING: ,", trim(vname), " NOT AVAILABLE AT LEVEL ", trim(lev), & ". SETTING EQUAL TO NaNs" if(present(var)) var(:,:) = ieee_value(var,IEEE_QUIET_NAN) if(present(var8)) var8(:,:) = ieee_value(var8,IEEE_QUIET_NAN) @@ -6527,67 +7179,104 @@ end subroutine handle_grib_error !> Read soil temperature and soil moisture fields from a GRIB2 file. !! -!! @param [in] the_file grib2 file name -!! @param [in] inv_file grib2 inventory file name !! @param [in] vname variable name in varmap table !! @param [in] vname_file variable name in grib2 file +!! @param [in] lugb logical unit number for surface grib2 file !! @param [inout] dummy3d array of soil data -!! @param [out] rc read error status code !! @author George Gayno NCEP/EMC -subroutine read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) - - use wgrib2api - implicit none + subroutine read_grib_soil(vname, vname_file, lugb, dummy3d) - character(len=*), intent(in) :: the_file, inv_file - character(len=20), intent(in) :: vname,vname_file + use grib_mod + + implicit none - integer, intent(out) :: rc + character(len=20), intent(in) :: vname,vname_file - real(esmf_kind_r8), intent(inout) :: dummy3d(:,:,:) + integer, intent(in) :: lugb + + real(esmf_kind_r8), intent(inout) :: dummy3d(:,:,:) - real(esmf_kind_r4), allocatable :: dummy2d(:,:) - real(esmf_kind_r4) :: value - integer :: varnum,i - character(len=50) :: slevs(lsoil_input) - character(len=50) :: method + character(len=50) :: slevs(lsoil_input) + character(len=50) :: method + + integer :: varnum, i, j, k, rc, rc2 + integer :: jdisc, jgdtn, jpdtn, lugi + integer :: jids(200), jgdt(200), jpdt(200) + integer :: iscale1, iscale2 + + logical :: unpack + + real(esmf_kind_r4), allocatable :: dummy2d(:,:) + real(esmf_kind_r4) :: value + + type(gribfield) :: gfld - allocate(dummy2d(i_input,j_input)) + allocate(dummy2d(i_input,j_input)) - if(lsoil_input == 4) then + if(lsoil_input == 4) then slevs = (/character(24)::':0-0.1 m below ground:', ':0.1-0.4 m below ground:', & ':0.4-1 m below ground:', ':1-2 m below ground:'/) - elseif(lsoil_input == 9) then + elseif(lsoil_input == 9) then slevs = (/character(26)::':0-0 m below ground',':0.01-0.01 m below ground:',':0.04-0.04 m below ground:', & ':0.1-0.1 m below ground:',':0.3-0.3 m below ground:',':0.6-0.6 m below ground:', & ':1-1 m below ground:',':1.6-1.6 m below ground:',':3-3 m below ground:'/) - else + else rc = -1 call error_handler("reading soil levels. File must have 4 or 9 soil levels.", rc) - endif + endif - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & loc=varnum) - do i = 1,lsoil_input - if (vname_file=="var2_2_1_") then - rc = grb2_inq(the_file,inv_file,vname_file,"_0_192:",slevs(i),data2=dummy2d) - else - rc = grb2_inq(the_file,inv_file,vname_file,slevs(i),data2=dummy2d) - endif - if (rc <= 0) then - call handle_grib_error(vname_file, slevs(i),method,value,varnum,rc,var=dummy2d) - if (rc==1 .and. trim(vname) /= "soill") then - ! missing_var_method == skip or no entry in varmap table - call error_handler("READING IN "//trim(vname)//". SET A FILL "// & + + lugi = 0 ! unit number for index file + jdisc = 2 ! search for discipline - land products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template 4.n + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template 3.m + jgdtn = -1 ! search for any grid definition number. + jpdtn = 0 ! search for product def template number 0 - anl or fcst. + jpdt(1) = 0 ! oct 10 - param cat - veg/biomass + if (trim(vname) == 'soilt') jpdt(2) = 2 ! oct 11 - param number - soil temp + if (trim(vname) == 'soilw') jpdt(2) = 192 ! oct 11 - param number - total soilm + if (trim(vname) == 'soill') then + jpdt(1) = 3 ! oct 10 - soil products + jpdt(2) = 192 ! oct 11 - param number - liquid soilm + endif + jpdt(10) = 106 ! oct 23 - depth below ground + jpdt(13) = 106 ! oct 29 - depth below ground + unpack=.true. + + do i = 1,lsoil_input + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc2) + + if (rc2 /= 0) then ! record not found. + call handle_grib_error(vname_file, slevs(i),method,value,varnum,rc,var=dummy2d) + if (rc==1 .and. trim(vname) /= "soill") then + ! missing_var_method == skip or no entry in varmap table + call error_handler("READING IN "//trim(vname)//". SET A FILL "// & "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",rc) - elseif (rc==1) then - dummy3d(:,:,:) = 0.0_esmf_kind_r8 - exit - endif - endif + elseif (rc==1) then + dummy3d(:,:,:) = 0.0_esmf_kind_r8 + return + endif + endif + + if (rc2 == 0) then ! record found. + iscale1 = 10 ** gfld%ipdtmpl(11) + iscale2 = 10 ** gfld%ipdtmpl(14) +! print*,'getgb2 top of soil layer in m ', float(gfld%ipdtmpl(12))/float(iscale1) +! print*,'getgb2 bot of soil layer in m ', float(gfld%ipdtmpl(15))/float(iscale2) + dummy2d = reshape(gfld%fld, (/i_input,j_input/) ) + endif - dummy3d(:,:,i) = real(dummy2d,esmf_kind_r8) - end do + j = k + + dummy3d(:,:,i) = real(dummy2d,esmf_kind_r8) + + enddo deallocate(dummy2d) @@ -6776,15 +7465,15 @@ end subroutine check_soilt subroutine check_cnwat(cnwat) implicit none - real(esmf_kind_r4), intent(inout) :: cnwat(i_input,j_input) + real(esmf_kind_r8), intent(inout) :: cnwat(i_input,j_input) - real(esmf_kind_r4) :: max_cnwat = 0.5 + real(esmf_kind_r8) :: max_cnwat = 0.5 integer :: i, j do i = 1,i_input do j = 1,j_input - if (cnwat(i,j) .gt. max_cnwat) cnwat(i,j) = 0.0_esmf_kind_r4 + if (cnwat(i,j) .gt. max_cnwat) cnwat(i,j) = 0.0_esmf_kind_r8 enddo enddo end subroutine check_cnwat diff --git a/sorc/chgres_cube.fd/model_grid.F90 b/sorc/chgres_cube.fd/model_grid.F90 index 028693f35..0cf0257a2 100644 --- a/sorc/chgres_cube.fd/model_grid.F90 +++ b/sorc/chgres_cube.fd/model_grid.F90 @@ -700,8 +700,12 @@ subroutine define_input_grid_gfs_grib2(localpet, npets) longitude(i,:) = real(lon4(i,:),kind=esmf_kind_r8) enddo +! Flip the poles, to be consistent with how the g2lib degribs +! gfs data. + do i = 1, j_input - latitude(:,i) = real(lat4(:,i),kind=esmf_kind_r8) + latitude(:,i) = real(lat4(:,j_input-i+1),kind=esmf_kind_r8) +! if (localpet == 0) print*,'gfs lat ',i,latitude(1,i) enddo deallocate(lat4, lon4) @@ -783,11 +787,11 @@ subroutine define_input_grid_gfs_grib2(localpet, npets) lon_corner_src_ptr(i,j) = longitude(i,1) - (0.5_esmf_kind_r8*deltalon) if (lon_corner_src_ptr(i,j) > 360.0_esmf_kind_r8) lon_corner_src_ptr(i,j) = lon_corner_src_ptr(i,j) - 360.0_esmf_kind_r8 if (j == 1) then - lat_corner_src_ptr(i,j) = -90.0_esmf_kind_r8 + lat_corner_src_ptr(i,j) = +90.0_esmf_kind_r8 cycle endif if (j == jp1_input) then - lat_corner_src_ptr(i,j) = +90.0_esmf_kind_r8 + lat_corner_src_ptr(i,j) = -90.0_esmf_kind_r8 cycle endif lat_corner_src_ptr(i,j) = 0.5_esmf_kind_r8 * (latitude(i,j-1)+ latitude(i,j)) diff --git a/tests/chgres_cube/CMakeLists.txt b/tests/chgres_cube/CMakeLists.txt index adcf0621b..73274ca76 100644 --- a/tests/chgres_cube/CMakeLists.txt +++ b/tests/chgres_cube/CMakeLists.txt @@ -42,6 +42,18 @@ add_executable(ftst_utils ftst_utils.F90) add_test(NAME chgres_cube-ftst_utils COMMAND ftst_utils) target_link_libraries(ftst_utils chgres_cube_lib) +add_executable(ftst_read_atm_grib2 ftst_read_atm_grib2.F90) +target_link_libraries(ftst_read_atm_grib2 chgres_cube_lib) +add_mpi_test(chgres_cube-ftst_read_atm_grib2 + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/ftst_read_atm_grib2 + NUMPROCS 1 TIMEOUT 60) + +add_executable(ftst_read_sfc_grib2 ftst_read_sfc_grib2.F90) +target_link_libraries(ftst_read_sfc_grib2 chgres_cube_lib) +add_mpi_test(chgres_cube-ftst_read_sfc_grib2 + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/ftst_read_sfc_grib2 + NUMPROCS 1 TIMEOUT 60) + add_executable(ftst_program_setup ftst_program_setup.F90) target_link_libraries(ftst_program_setup chgres_cube_lib) add_mpi_test(chgres_cube-ftst_program_setup diff --git a/tests/chgres_cube/LSanSuppress.supp b/tests/chgres_cube/LSanSuppress.supp index 7c73079ce..61404b2a9 100644 --- a/tests/chgres_cube/LSanSuppress.supp +++ b/tests/chgres_cube/LSanSuppress.supp @@ -2,4 +2,5 @@ leak:ESMCI leak:ESMC leak:esmc leak:esmf +leak:g2 leak:std::vector diff --git a/tests/chgres_cube/data/files.txt b/tests/chgres_cube/data/files.txt index de82305d7..e214957a4 100644 --- a/tests/chgres_cube/data/files.txt +++ b/tests/chgres_cube/data/files.txt @@ -3,3 +3,4 @@ https://ftp.emc.ncep.noaa.gov/static_files/public/UFS/ufs_utils/unit_tests/chgre https://ftp.emc.ncep.noaa.gov/static_files/public/UFS/ufs_utils/unit_tests/chgres_cube/gfs.v16.atm.history.nc https://ftp.emc.ncep.noaa.gov/static_files/public/UFS/ufs_utils/unit_tests/chgres_cube/gfs.v14.sfc.history.nemsio https://ftp.emc.ncep.noaa.gov/static_files/public/UFS/ufs_utils/unit_tests/chgres_cube/gfs.v15.sfc.history.nemsio +https://ftp.emc.ncep.noaa.gov/static_files/public/UFS/ufs_utils/unit_tests/chgres_cube/gfs.t00z.pgrb2.0p50.f000 diff --git a/tests/chgres_cube/ftst_read_atm_grib2.F90 b/tests/chgres_cube/ftst_read_atm_grib2.F90 new file mode 100644 index 000000000..b9a030974 --- /dev/null +++ b/tests/chgres_cube/ftst_read_atm_grib2.F90 @@ -0,0 +1,256 @@ + program read_atm_grib2 + +! Unit test for the "read_input_atm_grib2_file" +! routine of chgres_cube. +! +! Reads a 0.5-degree GFS GRIB2 file. The data read +! from the file is compared to expected values as +! determined from the 'wgrib2' stand-alone utility. +! +! Author George Gayno + + use esmf + + use input_data, only : read_input_atm_data, & + lev_input, & + levp1_input, & + temp_input_grid, tracers_input_grid, & + dzdt_input_grid, pres_input_grid, & + ps_input_grid, wind_input_grid, & + terrain_input_grid + + use program_setup, only : input_type, data_dir_input_grid, & + grib2_file_input_grid, & + read_varmap, varmap_file, & + num_tracers, num_tracers_input, & + tracers, tracers_input, external_model + + use model_grid, only : input_grid, & + i_input, j_input, & + latitude_input_grid, & + longitude_input_grid + + implicit none + + type(esmf_vm) :: vm + + type(esmf_polekind_flag) :: polekindflag(2) + + integer, parameter :: EXPECTED_LEV_INPUT=31 ! Number of vertical layers. + integer, parameter :: EXPECTED_LEVP1_INPUT=32 ! Number of vertical layer + ! interfaces. + + integer, parameter :: NUM_VALUES=2 ! Number of values compared per record. + + real, parameter :: EPSILON=0.0001 + real, parameter :: EPSILON_SMALL=0.0000001 + + integer :: rc, localpet, n, npets + integer :: i_check(NUM_VALUES), j_check(NUM_VALUES), k_check(NUM_VALUES) + + real(esmf_kind_r8), allocatable :: latitude(:,:) + real(esmf_kind_r8), allocatable :: longitude(:,:) + real(esmf_kind_r8), allocatable :: data_one_tile(:,:) + real(esmf_kind_r8), allocatable :: data3d_one_tile(:,:,:) + real(esmf_kind_r8), allocatable :: data4d_one_tile(:,:,:,:) + + real :: expected_values_tmp(NUM_VALUES) + real :: expected_values_sphum(NUM_VALUES) + real :: expected_values_liq_wat(NUM_VALUES) + real :: expected_values_o3mr(NUM_VALUES) + real :: expected_values_icewat(NUM_VALUES) + real :: expected_values_rainwat(NUM_VALUES) + real :: expected_values_snowwat(NUM_VALUES) + real :: expected_values_graupel(NUM_VALUES) + real :: expected_values_dzdt(NUM_VALUES) + real :: expected_values_pres(NUM_VALUES) + real :: expected_values_ps(NUM_VALUES) + real :: expected_values_terrain(NUM_VALUES) + real :: expected_values_xwind(NUM_VALUES) + real :: expected_values_ywind(NUM_VALUES) + real :: expected_values_zwind(NUM_VALUES) + +! The expected values were determined by the checking +! the input GRIB2 file using stand-alone 'wgrib2'. + + data expected_values_tmp / 300.5728, 262.8000 / ! Temperature + data expected_values_sphum / 0.01659, 0.0 / ! Specific humidity + data expected_values_liq_wat / 0.0, 0.0 / ! Cloud liquid water + data expected_values_o3mr / 6.69e-08, 4.94e-06 / ! Ozone + data expected_values_icewat / 0.0, 0.0 / ! Ice water + data expected_values_rainwat / 0.0, 0.0 / ! Rain water + data expected_values_snowwat / 0.0, 0.0 / ! Snow water + data expected_values_graupel / 0.0, 0.0 / ! Graupel + data expected_values_dzdt / 8.48e-03, 0.0 / ! Vertical velocity + data expected_values_pres / 100000.0, 100.0 / ! 3-d pressure + data expected_values_ps / 100662.9, 100662.9 / ! Surface pressure + data expected_values_terrain / 5.973e-2, 5.973e-2 / ! Terrain height + data expected_values_xwind / -6.3605, 7.3208 / ! x-component wind + data expected_values_ywind / -0.1167, -5.1422 / ! y-component wind + data expected_values_zwind / 0.0, 0.0 / ! z-component wind + + print*,"Starting test of read_atm_grib2_file." + + call mpi_init(rc) + + call ESMF_Initialize(rc=rc) + + call ESMF_VMGetGlobal(vm, rc=rc) + + call ESMF_VMGet(vm, localPet=localpet, petCount=npets, rc=rc) + + external_model="GFS" + input_type="grib2" +!data_dir_input_grid = "/scratch1/NCEPDEV/da/George.Gayno/noscrub/reg_tests/chgres_cube/input_data/gfs.grib2" + data_dir_input_grid = "data/" + grib2_file_input_grid = "gfs.t00z.pgrb2.0p50.f000" + + i_input = 720 + j_input = 361 + + polekindflag(1:2) = ESMF_POLEKIND_MONOPOLE + input_grid = ESMF_GridCreate1PeriDim(minIndex=(/1,1/), & + maxIndex=(/i_input,j_input/), & + polekindflag=polekindflag, & + periodicDim=1, & + poleDim=2, & + coordSys=ESMF_COORDSYS_SPH_DEG, & + regDecomp=(/1,npets/), & + indexflag=ESMF_INDEX_GLOBAL, rc=rc) + + + num_tracers=7 + num_tracers_input=num_tracers + + tracers_input(1)="spfh" + tracers_input(2)="clwmr" + tracers_input(3)="o3mr" + tracers_input(4)="icmr" + tracers_input(5)="rwmr" + tracers_input(6)="snmr" + tracers_input(7)="grle" + + tracers(1)="sphum" + tracers(2)="liq_wat" + tracers(3)="o3mr" + tracers(4)="ice_wat" + tracers(5)="rainwat" + tracers(6)="snowwat" + tracers(7)="graupel" + + varmap_file ="./data/GFSphys_varmap.txt" + call read_varmap + + latitude_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + name="input_grid_latitude", & + rc=rc) + + longitude_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + name="input_grid_longitude", & + rc=rc) + +! Using the north pole/greenwich simplifies the comparison +! of u/v winds. + + allocate(latitude(i_input,j_input)) + allocate(longitude(i_input,j_input)) + latitude=90.0 + longitude=0.0 + + call ESMF_FieldScatter(longitude_input_grid, longitude, rootpet=0, rc=rc) + call ESMF_FieldScatter(latitude_input_grid, latitude, rootpet=0, rc=rc) + +! Call the chgres_cube read routine. + + call read_input_atm_data(localpet) + +! Compare what was read to expected values. + + if (lev_input /= EXPECTED_LEV_INPUT) stop 2 + if (levp1_input /= EXPECTED_LEVP1_INPUT) stop 3 + + allocate(data3d_one_tile(i_input,j_input,lev_input)) + allocate(data4d_one_tile(i_input,j_input,lev_input,3)) + allocate(data_one_tile(i_input,j_input)) + +! The i/j/k of the points to be checked. + + i_check(1) = i_input/2 + j_check(1) = 182 + k_check(1) = 1 + + i_check(2) = i_input/2 + j_check(2) = 182 + k_check(2) = lev_input + + call ESMF_FieldGather(temp_input_grid, data3d_one_tile, rootPet=0, rc=rc) + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_tmp(1)) > EPSILON) stop 4 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_tmp(2)) > EPSILON) stop 5 + + do n = 1, num_tracers + call ESMF_FieldGather(tracers_input_grid(n), data3d_one_tile, rootPet=0, rc=rc) + if (trim(tracers(n)) == 'sphum') then + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_sphum(1)) > EPSILON) stop 6 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_sphum(2)) > EPSILON_SMALL) stop 7 + endif + if (trim(tracers(n)) == 'liq_wat') then + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_liq_wat(1)) > EPSILON_SMALL) stop 8 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_liq_wat(2)) > EPSILON_SMALL) stop 9 + endif + if (trim(tracers(n)) == 'o3mr') then + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_o3mr(1)) > EPSILON_SMALL) stop 10 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_o3mr(2)) > EPSILON_SMALL) stop 11 + endif + if (trim(tracers(n)) == 'ice_wat') then + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_icewat(1)) > EPSILON_SMALL) stop 12 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_icewat(2)) > EPSILON_SMALL) stop 13 + endif + if (trim(tracers(n)) == 'rainwat') then + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_rainwat(1)) > EPSILON_SMALL) stop 14 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_rainwat(2)) > EPSILON_SMALL) stop 15 + endif + if (trim(tracers(n)) == 'snowwat') then + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_snowwat(1)) > EPSILON_SMALL) stop 16 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_snowwat(2)) > EPSILON_SMALL) stop 17 + endif + if (trim(tracers(n)) == 'graupel') then + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_graupel(1)) > EPSILON_SMALL) stop 18 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_graupel(2)) > EPSILON_SMALL) stop 19 + endif + enddo + + call ESMF_FieldGather(dzdt_input_grid, data3d_one_tile, rootPet=0, rc=rc) + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_dzdt(1)) > EPSILON) stop 20 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_dzdt(2)) > EPSILON) stop 21 + + call ESMF_FieldGather(pres_input_grid, data3d_one_tile, rootPet=0, rc=rc) + if (abs(data3d_one_tile(i_check(1),j_check(1),k_check(1)) - expected_values_pres(1)) > EPSILON) stop 22 + if (abs(data3d_one_tile(i_check(2),j_check(2),k_check(2)) - expected_values_pres(2)) > EPSILON) stop 23 + + call ESMF_FieldGather(wind_input_grid, data4d_one_tile, rootPet=0, rc=rc) + if (abs(data4d_one_tile(i_check(1),j_check(1),k_check(1),1) - expected_values_xwind(1)) > EPSILON) stop 24 + if (abs(data4d_one_tile(i_check(2),j_check(2),k_check(2),1) - expected_values_xwind(2)) > EPSILON) stop 25 + if (abs(data4d_one_tile(i_check(1),j_check(1),k_check(1),2) - expected_values_ywind(1)) > EPSILON) stop 26 + if (abs(data4d_one_tile(i_check(2),j_check(2),k_check(2),2) - expected_values_ywind(2)) > EPSILON) stop 27 + if (abs(data4d_one_tile(i_check(1),j_check(1),k_check(1),3) - expected_values_zwind(1)) > EPSILON) stop 28 + if (abs(data4d_one_tile(i_check(2),j_check(2),k_check(2),3) - expected_values_zwind(2)) > EPSILON) stop 29 + + call ESMF_FieldGather(ps_input_grid, data_one_tile, rootPet=0, rc=rc) + if (abs(data_one_tile(i_check(1),j_check(1)) - expected_values_ps(1)) > EPSILON) stop 32 + + call ESMF_FieldGather(terrain_input_grid, data_one_tile, rootPet=0, rc=rc) + if (abs(data_one_tile(i_check(1),j_check(1)) - expected_values_terrain(1)) > EPSILON) stop 34 + + deallocate(latitude, longitude, data3d_one_tile, data4d_one_tile, data_one_tile) + + call ESMF_finalize(endflag=ESMF_END_KEEPMPI) + + call mpi_finalize(rc) + + print*,"SUCCESS!" + + end program read_atm_grib2 diff --git a/tests/chgres_cube/ftst_read_sfc_grib2.F90 b/tests/chgres_cube/ftst_read_sfc_grib2.F90 new file mode 100644 index 000000000..5f587912a --- /dev/null +++ b/tests/chgres_cube/ftst_read_sfc_grib2.F90 @@ -0,0 +1,352 @@ + program read_sfc_grib2 + +! Unit test for the read_input_sfc_grib2_file routine. +! +! Reads a GFS GRIB2 file and compares the output +! to expected values. +! +! Author George Gayno + + use esmf + + use input_data, only : read_input_sfc_data, & + lsoil_input, & + terrain_input_grid, & + soilm_liq_input_grid, & + soilm_tot_input_grid, & + soil_temp_input_grid, & + landsea_mask_input_grid, & + seaice_fract_input_grid, & + seaice_depth_input_grid, & + seaice_skin_temp_input_grid, & + snow_liq_equiv_input_grid, & + snow_depth_input_grid, & + veg_type_input_grid, & + soil_type_input_grid, & + t2m_input_grid, & + q2m_input_grid, & + tprcp_input_grid, & + f10m_input_grid, & + ffmm_input_grid, & + ustar_input_grid, & + srflag_input_grid, & + skin_temp_input_grid, & + canopy_mc_input_grid, & + z0_input_grid + + use program_setup, only : external_model, data_dir_input_grid, & + grib2_file_input_grid, varmap_file, & + read_varmap, input_type + + use model_grid, only : input_grid, & + i_input, j_input, & + latitude_input_grid, & + longitude_input_grid + + implicit none + + integer, parameter :: NUM_VALUES=2 + + real, parameter :: EPSILON=0.001 + + integer :: localpet, npets, rc + + real(esmf_kind_r8), allocatable :: latitude(:,:) + real(esmf_kind_r8), allocatable :: longitude(:,:) + + real(esmf_kind_r8), allocatable :: data_one_tile(:,:) + real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) + + type(esmf_vm) :: vm + + type(esmf_polekind_flag) :: polekindflag(2) + +! The expected values were determined by checking +! the input GRIB2 file using wgrib2. + + real :: landsea_mask_expected_values(NUM_VALUES) ! land-sea mask + real :: terrain_expected_values(NUM_VALUES) ! terrain height + real :: soilm_liq1_expected_values(NUM_VALUES) ! layer 1 liquid soil moisture + real :: soilm_liq2_expected_values(NUM_VALUES) ! layer 2 liquid soil moisture + real :: soilm_liq3_expected_values(NUM_VALUES) ! layer 3 liquid soil moisture + real :: soilm_liq4_expected_values(NUM_VALUES) ! layer 4 liquid soil moisture + real :: soilm_tot1_expected_values(NUM_VALUES) ! layer 1 total soil moisture + real :: soilm_tot2_expected_values(NUM_VALUES) ! layer 2 total soil moisture + real :: soilm_tot3_expected_values(NUM_VALUES) ! layer 3 total soil moisture + real :: soilm_tot4_expected_values(NUM_VALUES) ! layer 4 total soil moisture + real :: soil_temp1_expected_values(NUM_VALUES) ! layer 1 soil temperature + real :: soil_temp2_expected_values(NUM_VALUES) ! layer 2 soil temperature + real :: soil_temp3_expected_values(NUM_VALUES) ! layer 3 soil temperature + real :: soil_temp4_expected_values(NUM_VALUES) ! layer 4 soil temperature + real :: seaice_fract_expected_values(NUM_VALUES) ! sea ice fraction + real :: seaice_depth_expected_values(NUM_VALUES) ! sea ice depth + real :: seaice_skin_temp_expected_values(NUM_VALUES) ! sea ice skin temperature + real :: snow_liq_equiv_expected_values(NUM_VALUES) ! liquid equivalent snow depth + real :: snow_depth_expected_values(NUM_VALUES) ! physical snow depth + real :: veg_type_expected_values(NUM_VALUES) ! vegetation type + real :: soil_type_expected_values(NUM_VALUES) ! soil type + real :: t2m_expected_values(NUM_VALUES) ! two-meter temperature + real :: q2m_expected_values(NUM_VALUES) ! two-meter specific humidity + real :: tprcp_expected_values(NUM_VALUES) ! precipitation + real :: f10m_expected_values(NUM_VALUES) ! log((z0+10)*l/z0) + real :: ffmm_expected_values(NUM_VALUES) ! log((z0+z1)*l/z0) + real :: ustar_expected_values(NUM_VALUES) ! friction velocity + real :: srflag_expected_values(NUM_VALUES) ! snow/rain flag + real :: skin_temp_expected_values(NUM_VALUES) ! skin temperature + real :: canopy_mc_expected_values(NUM_VALUES) ! canopy moisture content + real :: z0_expected_values(NUM_VALUES) ! roughness length + + data terrain_expected_values / 2775.4197, 5.97e-02 / + data soilm_liq1_expected_values / 0.00, 0.00 / + data soilm_liq2_expected_values / 0.00, 0.00 / + data soilm_liq3_expected_values / 0.00, 0.00 / + data soilm_liq4_expected_values / 0.00, 0.00 / + data soilm_tot1_expected_values / 1.00, 0.00 / + data soilm_tot2_expected_values / 1.00, 0.00 / + data soilm_tot3_expected_values / 1.00, 0.00 / + data soilm_tot4_expected_values / 1.00, 0.00 / + data soil_temp1_expected_values / 236.1336, 265.0 / + data soil_temp2_expected_values / 228.5099, 265.0 / + data soil_temp3_expected_values / 225.7600, 265.0 / + data soil_temp4_expected_values / 228.1500, 265.0 / + data landsea_mask_expected_values / 1.0, 2.0 / + data seaice_fract_expected_values / 0.0, 1.0 / + data seaice_depth_expected_values / 1.5, 1.5/ + data seaice_skin_temp_expected_values / 235.8585, 243.8585/ + data snow_liq_equiv_expected_values / 120.0, 37.0 / + data snow_depth_expected_values / 1200.0, 110.0/ + data veg_type_expected_values / 15.0, 0.0 / + data soil_type_expected_values / -99999.0, -99999.0 / + data t2m_expected_values / 238.1991, 247.2991 / + data q2m_expected_values / 0.00016, 0.00035 / + data tprcp_expected_values / 0.0, 0.0 / + data f10m_expected_values / 0.0, 0.0/ + data ffmm_expected_values / 0.0, 0.0 / + data ustar_expected_values / 0.0, 0.0 / + data srflag_expected_values / 0.0, 0.0/ + data skin_temp_expected_values / 235.8585, 243.8585 / + data canopy_mc_expected_values / 0.0, 0.0 / + data z0_expected_values / 0.01, 0.01 / + + print*,"Starting test of read_atm_grib2_file." + + call mpi_init(rc) + + call ESMF_Initialize(rc=rc) + + call ESMF_VMGetGlobal(vm, rc=rc) + + call ESMF_VMGet(vm, localPet=localpet, petCount=npets, rc=rc) + + external_model="GFS" + input_type="grib2" +!data_dir_input_grid = "/scratch1/NCEPDEV/da/George.Gayno/noscrub/reg_tests/chgres_cube/input_data/gfs.grib2" + data_dir_input_grid = "data" + grib2_file_input_grid = "gfs.t00z.pgrb2.0p50.f000" + + i_input = 720 + j_input = 361 + + polekindflag(1:2) = ESMF_POLEKIND_MONOPOLE + input_grid = ESMF_GridCreate1PeriDim(minIndex=(/1,1/), & + maxIndex=(/i_input,j_input/), & + polekindflag=polekindflag, & + periodicDim=1, & + poleDim=2, & + coordSys=ESMF_COORDSYS_SPH_DEG, & + regDecomp=(/1,npets/), & + indexflag=ESMF_INDEX_GLOBAL, rc=rc) + + + varmap_file ="./data/GFSphys_varmap.txt" + call read_varmap + + latitude_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + name="input_grid_latitude", & + rc=rc) + + longitude_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + name="input_grid_longitude", & + rc=rc) + +! Lat/lon used in surface read. Use flag values. + + allocate(latitude(i_input,j_input)) + allocate(longitude(i_input,j_input)) + latitude=90.0 + longitude=0.0 + + call ESMF_FieldScatter(longitude_input_grid, longitude, rootpet=0, rc=rc) + call ESMF_FieldScatter(latitude_input_grid, latitude, rootpet=0, rc=rc) + +! Call the chgres_cube read routine. + + call read_input_sfc_data(localpet) + + allocate(data_one_tile(i_input,j_input)) + allocate(data_one_tile_3d(i_input,j_input,lsoil_input)) + + call ESMF_FieldGather(terrain_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - terrain_expected_values(1)) > EPSILON) stop 6 + if (abs(data_one_tile(i_input,1) - terrain_expected_values(2)) > EPSILON) stop 8 + endif + + call ESMF_FieldGather(soilm_liq_input_grid, data_one_tile_3d, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile_3d(1,j_input,1) - soilm_liq1_expected_values(1)) > EPSILON) stop 10 + if (abs(data_one_tile_3d(i_input,1,1) - soilm_liq1_expected_values(2)) > EPSILON) stop 11 + if (abs(data_one_tile_3d(1,j_input,2) - soilm_liq2_expected_values(1)) > EPSILON) stop 12 + if (abs(data_one_tile_3d(i_input,1,2) - soilm_liq2_expected_values(2)) > EPSILON) stop 13 + if (abs(data_one_tile_3d(1,j_input,3) - soilm_liq3_expected_values(1)) > EPSILON) stop 14 + if (abs(data_one_tile_3d(i_input,1,3) - soilm_liq3_expected_values(2)) > EPSILON) stop 15 + if (abs(data_one_tile_3d(1,j_input,4) - soilm_liq4_expected_values(1)) > EPSILON) stop 16 + if (abs(data_one_tile_3d(i_input,1,4) - soilm_liq4_expected_values(2)) > EPSILON) stop 17 + endif + + call ESMF_FieldGather(soilm_tot_input_grid, data_one_tile_3d, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile_3d(1,j_input,1) - soilm_tot1_expected_values(1)) > EPSILON) stop 20 + if (abs(data_one_tile_3d(i_input,1,1) - soilm_tot1_expected_values(2)) > EPSILON) stop 21 + if (abs(data_one_tile_3d(1,j_input,2) - soilm_tot2_expected_values(1)) > EPSILON) stop 22 + if (abs(data_one_tile_3d(i_input,1,2) - soilm_tot2_expected_values(2)) > EPSILON) stop 23 + if (abs(data_one_tile_3d(1,j_input,3) - soilm_tot3_expected_values(1)) > EPSILON) stop 24 + if (abs(data_one_tile_3d(i_input,1,3) - soilm_tot3_expected_values(2)) > EPSILON) stop 25 + if (abs(data_one_tile_3d(1,j_input,4) - soilm_tot4_expected_values(1)) > EPSILON) stop 26 + if (abs(data_one_tile_3d(i_input,1,4) - soilm_tot4_expected_values(2)) > EPSILON) stop 27 + endif + + call ESMF_FieldGather(soil_temp_input_grid, data_one_tile_3d, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile_3d(1,j_input,1) - soil_temp1_expected_values(1)) > EPSILON) stop 30 + if (abs(data_one_tile_3d(i_input,1,1) - soil_temp1_expected_values(2)) > EPSILON) stop 31 + if (abs(data_one_tile_3d(1,j_input,2) - soil_temp2_expected_values(1)) > EPSILON) stop 32 + if (abs(data_one_tile_3d(i_input,1,2) - soil_temp2_expected_values(2)) > EPSILON) stop 33 + if (abs(data_one_tile_3d(1,j_input,3) - soil_temp3_expected_values(1)) > EPSILON) stop 34 + if (abs(data_one_tile_3d(i_input,1,3) - soil_temp3_expected_values(2)) > EPSILON) stop 35 + if (abs(data_one_tile_3d(1,j_input,4) - soil_temp4_expected_values(1)) > EPSILON) stop 36 + if (abs(data_one_tile_3d(i_input,1,4) - soil_temp4_expected_values(2)) > EPSILON) stop 37 + endif + + call ESMF_FieldGather(landsea_mask_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - landsea_mask_expected_values(1)) > EPSILON) stop 39 + if (abs(data_one_tile(i_input,1) - landsea_mask_expected_values(2)) > EPSILON) stop 40 + endif + + call ESMF_FieldGather(seaice_fract_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - seaice_fract_expected_values(1)) > EPSILON) stop 41 + if (abs(data_one_tile(i_input,1) - seaice_fract_expected_values(2)) > EPSILON) stop 42 + endif + + call ESMF_FieldGather(seaice_depth_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - seaice_depth_expected_values(1)) > EPSILON) stop 43 + if (abs(data_one_tile(i_input,1) - seaice_depth_expected_values(2)) > EPSILON) stop 44 + endif + + call ESMF_FieldGather(seaice_skin_temp_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - seaice_skin_temp_expected_values(1)) > EPSILON) stop 45 + if (abs(data_one_tile(i_input,1) - seaice_skin_temp_expected_values(2)) > EPSILON) stop 46 + endif + + call ESMF_FieldGather(snow_liq_equiv_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - snow_liq_equiv_expected_values(1)) > EPSILON) stop 47 + if (abs(data_one_tile(i_input,1) - snow_liq_equiv_expected_values(2)) > EPSILON) stop 48 + endif + + call ESMF_FieldGather(snow_depth_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - snow_depth_expected_values(1)) > EPSILON) stop 49 + if (abs(data_one_tile(i_input,1) - snow_depth_expected_values(2)) > EPSILON) stop 50 + endif + + call ESMF_FieldGather(veg_type_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - veg_type_expected_values(1)) > EPSILON) stop 51 + if (abs(data_one_tile(i_input,1) - veg_type_expected_values(2)) > EPSILON) stop 52 + endif + + call ESMF_FieldGather(soil_type_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - soil_type_expected_values(1)) > EPSILON) stop 53 + if (abs(data_one_tile(i_input,1) - soil_type_expected_values(2)) > EPSILON) stop 54 + endif + + call ESMF_FieldGather(t2m_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - t2m_expected_values(1)) > EPSILON) stop 55 + if (abs(data_one_tile(i_input,1) - t2m_expected_values(2)) > EPSILON) stop 56 + endif + + call ESMF_FieldGather(q2m_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - q2m_expected_values(1)) > EPSILON) stop 57 + if (abs(data_one_tile(i_input,1) - q2m_expected_values(2)) > EPSILON) stop 58 + endif + + call ESMF_FieldGather(tprcp_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - tprcp_expected_values(1)) > EPSILON) stop 59 + if (abs(data_one_tile(i_input,1) - tprcp_expected_values(2)) > EPSILON) stop 60 + endif + + call ESMF_FieldGather(f10m_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - f10m_expected_values(1)) > EPSILON) stop 61 + if (abs(data_one_tile(i_input,1) - f10m_expected_values(2)) > EPSILON) stop 62 + endif + + call ESMF_FieldGather(ffmm_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - ffmm_expected_values(1)) > EPSILON) stop 63 + if (abs(data_one_tile(i_input,1) - ffmm_expected_values(2)) > EPSILON) stop 64 + endif + + call ESMF_FieldGather(ustar_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - ustar_expected_values(1)) > EPSILON) stop 65 + if (abs(data_one_tile(i_input,1) - ustar_expected_values(2)) > EPSILON) stop 66 + endif + + call ESMF_FieldGather(srflag_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - srflag_expected_values(1)) > EPSILON) stop 67 + if (abs(data_one_tile(i_input,1) - srflag_expected_values(2)) > EPSILON) stop 68 + endif + + call ESMF_FieldGather(skin_temp_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - skin_temp_expected_values(1)) > EPSILON) stop 69 + if (abs(data_one_tile(i_input,1) - skin_temp_expected_values(2)) > EPSILON) stop 70 + endif + + call ESMF_FieldGather(canopy_mc_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - canopy_mc_expected_values(1)) > EPSILON) stop 71 + if (abs(data_one_tile(i_input,1) - canopy_mc_expected_values(2)) > EPSILON) stop 72 + endif + + call ESMF_FieldGather(z0_input_grid, data_one_tile, rootPet=0, rc=rc) + if (localpet == 0) then + if (abs(data_one_tile(1,j_input) - z0_expected_values(1)) > EPSILON) stop 73 + if (abs(data_one_tile(i_input,1) - z0_expected_values(2)) > EPSILON) stop 74 + endif + + deallocate (latitude, longitude) + deallocate (data_one_tile, data_one_tile_3d) + + call ESMF_finalize(endflag=ESMF_END_KEEPMPI) + + call mpi_finalize(rc) + + print*,"SUCCESS!" + + end program read_sfc_grib2 diff --git a/tests/chgres_cube/ftst_sfc_input_data.F90 b/tests/chgres_cube/ftst_sfc_input_data.F90 index e69db1763..75bf1bf19 100644 --- a/tests/chgres_cube/ftst_sfc_input_data.F90 +++ b/tests/chgres_cube/ftst_sfc_input_data.F90 @@ -22,7 +22,7 @@ program test_sfc_input_data soilt_updated(:,:,:), & soilt_correct(:,:,:) real(esmf_kind_r8), allocatable :: skint(:,:) - real(esmf_kind_r4), allocatable :: cnwat_bad(:,:), & + real(esmf_kind_r8), allocatable :: cnwat_bad(:,:), & cnwat_updated(:,:), & cnwat_correct(:,:) diff --git a/ush/chgres_cube.sh b/ush/chgres_cube.sh index c60eba605..550439049 100755 --- a/ush/chgres_cube.sh +++ b/ush/chgres_cube.sh @@ -272,8 +272,8 @@ cat << EOF > ./fort.41 convert_sfc=$CONVERT_SFC convert_nst=$CONVERT_NST input_type="${INPUT_TYPE}" - tracers=$TRACERS_TARGET - tracers_input=$TRACERS_INPUT + tracers=${TRACERS_TARGET} + tracers_input=${TRACERS_INPUT} regional=$REGIONAL halo_bndy=$HALO_BNDY halo_blend=$HALO_BLEND