1414! 13 May 2019 Eric Kemp Initial version
1515! 13 Dec 2019 Eric Kemp Changed to USAFSI.
1616! 09 Oct 2020 Eric Kemp Added legacy SNODEP files.
17+ ! 14 Jul 2021 Eric Kemp Fixed bug in creating GRIB output directory.
1718!
1819! DESCRIPTION:
1920! Source code for reading USAFSI netCDF file, writing back out in GRIB,
@@ -396,8 +397,25 @@ subroutine output_grib2(this)
396397 integer :: ftn, rc, status2
397398 character (len= 255 ) :: msg
398399 real , allocatable :: go(:)
400+ logical :: found
399401 integer :: c, r
400402
403+ integer , external :: LVT_create_subdirs
404+
405+ ! Make sure output directory exists
406+ inquire (file= trim (LVT_rc% output_dir), &
407+ exist= found)
408+ if (.not. found) then
409+ rc = LVT_create_subdirs(len_trim (LVT_rc% output_dir), &
410+ trim (LVT_rc% output_dir))
411+ if (rc .ne. 0 ) then
412+ write (LVT_logunit,* )' [ERR] Cannot create directory ' , &
413+ trim (LVT_rc% output_dir)
414+ write (LVT_logunit,* )' [ERR] Program will stop'
415+ call LVT_endrun()
416+ end if
417+ end if
418+
401419 ! Set the USAFSI grid description
402420 call set_griddesci(this, griddesci)
403421
@@ -445,7 +463,7 @@ subroutine output_grib2(this)
445463 end do ! r
446464 call write_grib2(ftn, griddesci, this% nc, this% nr, go, &
447465 dspln= 10 , cat= 2 , num= 0 , typegenproc= 12 , fcsttime= 0 )
448-
466+
449467 ! Handle icemask
450468 do r = 1 , this% nr
451469 do c = 1 , this% nc
@@ -455,7 +473,7 @@ subroutine output_grib2(this)
455473 ! FIXME: Find parameter number for ice mask
456474 call write_grib2(ftn, griddesci, this% nc, this% nr, go, &
457475 dspln= 10 , cat= 2 , num= 192 , typegenproc= 12 , fcsttime= 0 )
458-
476+
459477 ! Handle iceage
460478 do r = 1 , this% nr
461479 do c = 1 , this% nc
@@ -509,10 +527,10 @@ subroutine interp_and_output_grib1(this, gridID)
509527 real , allocatable :: w11_bin(:)
510528 real , allocatable :: w12_bin(:)
511529 real , allocatable :: w21_bin(:)
512- real , allocatable :: w22_bin(:)
530+ real , allocatable :: w22_bin(:)
513531 integer , allocatable :: n11_neighbor(:)
514532 real , allocatable :: rlat_neighbor(:)
515- real , allocatable :: rlon_neighbor(:)
533+ real , allocatable :: rlon_neighbor(:)
516534 logical * 1 , allocatable :: li(:), lo(:), lo_bin(:), lo_neighbor(:)
517535 real , allocatable :: gi(:), go(:), go_bin(:), go_neighbor(:)
518536 real , allocatable :: go2d(:,:)
@@ -528,6 +546,23 @@ subroutine interp_and_output_grib1(this, gridID)
528546 integer :: grid_definition
529547 logical :: write_fullgrib_file
530548 logical :: write_snodep_file
549+ logical :: found
550+
551+ integer , external :: LVT_create_subdirs
552+
553+ ! Make sure output directory exists
554+ inquire (file= trim (LVT_rc% output_dir), &
555+ exist= found)
556+ if (.not. found) then
557+ rc = LVT_create_subdirs(len_trim (LVT_rc% output_dir), &
558+ trim (LVT_rc% output_dir))
559+ if (rc .ne. 0 ) then
560+ write (LVT_logunit,* )' [ERR] Cannot create directory ' , &
561+ trim (LVT_rc% output_dir)
562+ write (LVT_logunit,* )' [ERR] Program will stop'
563+ call LVT_endrun()
564+ end if
565+ end if
531566
532567 ! Sanity check the gridID.
533568 call check_gridID(gridID)
@@ -540,9 +575,9 @@ subroutine interp_and_output_grib1(this, gridID)
540575
541576 ! Set the output grid description
542577 if (trim (gridID) .eq. trim (GLOBAL_LL0P25)) then
543- call set_griddesco_global_ll0p25(this, griddesco)
578+ call set_griddesco_global_ll0p25(this, griddesco)
544579 else if (trim (gridID) .eq. trim (NH_PS16)) then
545- call set_griddesco_nh_ps16(this, griddesco)
580+ call set_griddesco_nh_ps16(this, griddesco)
546581 else if (trim (gridID) .eq. trim (SH_PS16)) then
547582 call set_griddesco_sh_ps16(this, griddesco)
548583 end if
@@ -597,7 +632,7 @@ subroutine interp_and_output_grib1(this, gridID)
597632 allocate (w11_bin(nc_out* nr_out))
598633 allocate (w12_bin(nc_out* nr_out))
599634 allocate (w21_bin(nc_out* nr_out))
600- allocate (w22_bin(nc_out* nr_out))
635+ allocate (w22_bin(nc_out* nr_out))
601636 call bilinear_interp_input_usaf(griddesci, griddesco, &
602637 (nc_out* nr_out), &
603638 rlat_bin, rlon_bin, &
@@ -688,7 +723,7 @@ subroutine interp_and_output_grib1(this, gridID)
688723 gi(c + (r-1 )* this% nc) = LVT_rc% udef
689724 else
690725 li(c + (r-1 )* this% nc) = .true.
691- gi(c + (r-1 )* this% nc) = this% snoanl(c,r)
726+ gi(c + (r-1 )* this% nc) = this% snoanl(c,r)
692727 end if
693728 end do ! c
694729 end do ! r
@@ -1161,7 +1196,7 @@ subroutine build_filename_g2(output_dir, yyyymmddhh, filename)
11611196 ! Imports
11621197 use LVT_coreMod, only: LVT_rc
11631198
1164- ! Defaults
1199+ ! Defaults
11651200 implicit none
11661201
11671202 ! Arguments
@@ -1180,7 +1215,7 @@ subroutine build_filename_g2(output_dir, yyyymmddhh, filename)
11801215 // yyyymmddhh(9 :10 )// ' 00_DF.GR2'
11811216
11821217 end subroutine build_filename_g2
1183-
1218+
11841219 ! Build the grib1 filename
11851220 subroutine build_filename_g1 (gridID , output_dir , yyyymmddhh , filename )
11861221
@@ -1218,7 +1253,7 @@ subroutine build_filename_g1(gridID, output_dir, yyyymmddhh, filename)
12181253 trim (area) // ' _PA.SNODEP_DD.' // &
12191254 trim (yyyymmdd) // ' _DT.' // &
12201255 trim (hh) // ' 00_DF.GR1'
1221-
1256+
12221257 end subroutine build_filename_g1
12231258
12241259 ! Build the grib1 filename just for snodep
@@ -1320,7 +1355,7 @@ subroutine set_griddesco_global_ll0p25(this, griddesco)
13201355 griddesco(38 ) = 179.875000
13211356 griddesco(39 ) = 0.250000
13221357 griddesco(40 ) = 0.250000
1323-
1358+
13241359 end subroutine set_griddesco_global_ll0p25
13251360
13261361 ! Internal subroutine for setting griddesco for Northern Hemisphere 16th
@@ -1343,7 +1378,7 @@ subroutine set_griddesco_nh_ps16(this, griddesco)
13431378 xmesh = 23.813 ! Per 557WW GRIB1 manual
13441379 xpnmcaf = 513
13451380 ypnmcaf = 513
1346- orient = 100.0
1381+ orient = 100.0
13471382
13481383 ! We need to use the USAF code to calculate the lat/lon. However,
13491384 ! the Air Force grid specifies the origin in the upper-left corner,
@@ -1395,7 +1430,7 @@ subroutine set_griddesco_sh_ps16(this, griddesco)
13951430 xmesh = 23.813 ! Per 557WW GRIB1 manual
13961431 xpnmcaf = 513
13971432 ypnmcaf = 513
1398- orient = 100 .
1433+ orient = 100 .
13991434
14001435 ! We need to use the USAF code to calculate the lat/lon. However,
14011436 ! the Air Force grid specifies the origin in the upper-left corner,
@@ -1417,7 +1452,7 @@ subroutine set_griddesco_sh_ps16(this, griddesco)
14171452 griddesco(10 ) = - 60.0
14181453 griddesco(11 ) = orient
14191454 griddesco(20 ) = 64
1420-
1455+
14211456 ! Stash away the upper-left lat/lon for later use
14221457 call pstoll(2 , 1 , float(1 ), float(1 ), 16 , alat, alon)
14231458 griddesco(30 ) = alat
@@ -1429,7 +1464,7 @@ end subroutine set_griddesco_sh_ps16
14291464 subroutine write_grib2 (ftn , griddesco , &
14301465 nc_out , nr_out , go , dspln , cat , num , typegenproc , fcsttime )
14311466
1432- ! Imports
1467+ ! Imports
14331468 use grib_api
14341469 use LVT_coreMod, only: LVT_rc
14351470 use LVT_gribWrapperMod, only: LVT_grib_set
@@ -1566,7 +1601,7 @@ subroutine write_grib2(ftn, griddesco, &
15661601 abs (1000 * griddesco(9 )))
15671602 if (griddesco(4 ) < 0 ) then
15681603 call LVT_grib_set(igrib, ' projectionCentreFlag' , 0 )
1569- else
1604+ else
15701605 call LVT_grib_set(igrib, ' projectionCentreFlag' , 1 )
15711606 end if
15721607 call LVT_grib_set(igrib, ' scanningMode' , 0 )
@@ -1590,7 +1625,7 @@ subroutine write_grib2(ftn, griddesco, &
15901625 ! Octet 15-17 is skipped
15911626 ! Octet 18...Use hours
15921627 call LVT_grib_set(igrib, ' indicatorOfUnitOfTimeRange' , 1 )
1593- ! Octets 19-22
1628+ ! Octets 19-22
15941629 call LVT_grib_set(igrib, ' forecastTime' , fcsttime)
15951630 ! Octets 23-34...Ground or water surface
15961631 call LVT_grib_set(igrib, ' typeOfFirstFixedSurface' , 1 )
@@ -1630,7 +1665,7 @@ subroutine write_grib1(ftn, griddesco, &
16301665 nc_out , nr_out , go , param , decimal_scale_factor , &
16311666 bits_per_value , grid_definition )
16321667
1633- ! Imports
1668+ ! Imports
16341669 use grib_api
16351670 use LVT_coreMod, only: LVT_rc
16361671 use LVT_gribWrapperMod, only: LVT_grib_set
@@ -1656,7 +1691,7 @@ subroutine write_grib1(ftn, griddesco, &
16561691 character (len= 4 ) :: cyyyy
16571692 character (len= 2 ) :: cmm, cdd, chh
16581693 integer :: iyyyy, imm, idd, ihh, iyear, iyoc, ic
1659-
1694+
16601695#if (defined USE_ECCODES)
16611696 call grib_new_from_samples(igrib, " GRIB1" , rc)
16621697 if (rc .ne. GRIB_SUCCESS) then
@@ -1786,7 +1821,7 @@ subroutine write_grib1(ftn, griddesco, &
17861821 abs (1000 * griddesco(9 )))
17871822 if (griddesco(4 ) < 0 ) then
17881823 call LVT_grib_set(igrib, ' projectionCentreFlag' , 0 )
1789- else
1824+ else
17901825 call LVT_grib_set(igrib, ' projectionCentreFlag' , 128 )
17911826 end if
17921827 call LVT_grib_set(igrib, ' scanningMode' , 0 )
@@ -1819,7 +1854,7 @@ subroutine write_grib1(ftn, griddesco, &
18191854 write (LVT_logunit,* )' [ERR] LVT will stop'
18201855 call LVT_endrun()
18211856 end if
1822-
1857+
18231858 end subroutine write_grib1
18241859
18251860 ! Internal subroutine for writing global lat/lon output in netCDF.
@@ -1830,7 +1865,7 @@ subroutine write_netcdf_latlon(griddesco, nc_out, nr_out, go)
18301865 use LVT_coreMod, only: LVT_rc
18311866 use LVT_logMod, only: LVT_logunit, LVT_verify, LVT_endrun
18321867 use netcdf
1833-
1868+
18341869 ! Defaults
18351870 implicit none
18361871
@@ -1886,7 +1921,7 @@ subroutine write_netcdf_latlon(griddesco, nc_out, nr_out, go)
18861921 swlon = gridDesco(5 )
18871922 nelat = gridDesco(7 )
18881923 nelon = gridDesco(8 )
1889-
1924+
18901925 call LVT_verify(nf90_put_att(ncid,nf90_global,&
18911926 " MAP_PROJECTION" , " EQUIDISTANT CYLINDRICAL" ), &
18921927 ' [ERR] nf90_put_att failed' )
@@ -1908,7 +1943,7 @@ subroutine write_netcdf_latlon(griddesco, nc_out, nr_out, go)
19081943 call LVT_verify(nf90_put_att(ncid,nf90_global, &
19091944 " DY" ,dlat), &
19101945 ' [ERR] nf90_put_att failed' )
1911-
1946+
19121947 case default
19131948 write (LVT_logunit,* ) &
19141949 ' [ERR] Only latlon map projection supported!'
@@ -1919,7 +1954,7 @@ subroutine write_netcdf_latlon(griddesco, nc_out, nr_out, go)
19191954 call LVT_verify(nf90_put_att(ncid,nf90_global, &
19201955 " INC_WATER_PTS" ," true" ), &
19211956 ' [ERR] nf90_put_att failed' )
1922-
1957+
19231958 ! Construct the longitudes
19241959 ! FIXME: Add support for other map projections
19251960 call LVT_verify(nf90_def_var(ncid," lon" ,nf90_float,dim_ids(1 ), &
@@ -1953,7 +1988,7 @@ subroutine write_netcdf_latlon(griddesco, nc_out, nr_out, go)
19531988 call LVT_verify(nf90_put_att(ncid,lat_varid, &
19541989 " standard_name" ," latitude" ),&
19551990 ' [ERR] nf90_put_att failed' )
1956-
1991+
19571992 ! Define the time array. The valid time will be written as an
19581993 ! attribute.
19591994 call LVT_verify(nf90_def_var(ncid,' time' ,nf90_double,&
@@ -1970,9 +2005,9 @@ subroutine write_netcdf_latlon(griddesco, nc_out, nr_out, go)
19702005 " units" ,trim (time_units)),&
19712006 ' [ERR] nf90_put_att failed' )
19722007 call LVT_verify(nf90_put_att(ncid,time_varid, &
1973- " long_name" ," time" ),&
2008+ " long_name" ," time" ),&
19742009 ' [ERR] nf90_put_att failed' )
1975-
2010+
19762011 ! Define the snow depth analysis
19772012 call LVT_verify(nf90_def_var(ncid," snoanl" ,nf90_float, &
19782013 dimids= dim_ids, &
@@ -2010,7 +2045,7 @@ subroutine write_netcdf_latlon(griddesco, nc_out, nr_out, go)
20102045 ! Miscellaneous header information
20112046 call LVT_verify(nf90_put_att(ncid,nf90_global," Conventions" , &
20122047 " CF-1.7" ), &
2013- ' [ERR] nf90_put_att failed' )
2048+ ' [ERR] nf90_put_att failed' )
20142049
20152050 ! We are ready to write the actual data. This requires taking NETCDF
20162051 ! out of define mode.
@@ -2071,7 +2106,7 @@ subroutine write_netcdf_ps(griddesco, nc_out, nr_out, go)
20712106 use LVT_coreMod, only: LVT_rc
20722107 use LVT_logMod, only: LVT_logunit, LVT_verify, LVT_endrun
20732108 use netcdf
2074-
2109+
20752110 ! Defaults
20762111 implicit none
20772112
@@ -2190,7 +2225,7 @@ subroutine write_netcdf_ps(griddesco, nc_out, nr_out, go)
21902225 ! Miscellaneous header information
21912226 call LVT_verify(nf90_put_att(ncid,nf90_global," Conventions" , &
21922227 " CF-1.7" ), &
2193- ' [ERR] nf90_put_att failed' )
2228+ ' [ERR] nf90_put_att failed' )
21942229
21952230 ! We are ready to write the actual data. This requires taking NETCDF
21962231 ! out of define mode.
@@ -2252,7 +2287,7 @@ end subroutine write_netcdf_ps
22522287 ! mesh polar stereographic grids.
22532288 subroutine bilinear_interp_input_usaf (gridDesci , gridDesco , npts , &
22542289 rlat , rlon , n11 , n12 , n21 , n22 , w11 , w12 , w21 , w22 , afwa_grid )
2255-
2290+
22562291 ! Defaults
22572292 implicit none
22582293
@@ -2298,7 +2333,7 @@ subroutine bilinear_interp_input_usaf(gridDesci, gridDesco, npts, &
22982333 i1= xi
22992334 i2= i1+1
23002335 j1= yi
2301- j2= j1+1
2336+ j2= j1+1
23022337 xf= xi- i1
23032338 yf= yi- j1
23042339 n11(n)= get_fieldpos(i1, j1, gridDesci)
@@ -2323,7 +2358,7 @@ subroutine bilinear_interp_input_usaf(gridDesci, gridDesco, npts, &
23232358 n22(n)= 0
23242359 endif
23252360 enddo
2326-
2361+
23272362 end subroutine bilinear_interp_input_usaf
23282363
23292364 ! Internal subroutine to set up weights for neighbor interpolation.
@@ -2334,7 +2369,7 @@ subroutine neighbor_interp_input_usaf(griddesci, griddesco, npts, &
23342369
23352370 ! Defaults
23362371 implicit none
2337-
2372+
23382373 ! Arguments
23392374 real , intent (in ) :: griddesci(50 )
23402375 real , intent (in ) :: griddesco(50 )
@@ -2346,7 +2381,7 @@ subroutine neighbor_interp_input_usaf(griddesci, griddesco, npts, &
23462381
23472382 ! Local variables
23482383 integer :: n
2349- integer :: mo, nv
2384+ integer :: mo, nv
23502385 real :: xpts(npts), ypts(npts)
23512386 integer :: i1, j1
23522387 real :: xi, yi
@@ -2374,7 +2409,7 @@ subroutine neighbor_interp_input_usaf(griddesci, griddesco, npts, &
23742409 n112(n) = 0
23752410 endif
23762411 enddo
2377-
2412+
23782413 end subroutine neighbor_interp_input_usaf
23792414
23802415 ! Internal function for setting GRIB1 grid definition
0 commit comments