diff --git a/docs/source/ufs_utils.rst b/docs/source/ufs_utils.rst
index 314c179b9..7810f3817 100644
--- a/docs/source/ufs_utils.rst
+++ b/docs/source/ufs_utils.rst
@@ -375,8 +375,13 @@ Program inputs and outputs
* grid file - the "grid" file from the make_hgrid or regional_esg programs - CRES_grid.tile#.nc - (NetCDF)
* orography file - the orography file including the 'inland' flag record from the inland program - oro.CRES.tile#.nc (NetCDF)
- * lake status code file - GlobalLakeStatus.dat (located in `./fix/fix_orog `_). See GlobalLakeStatus.txt for the defintion of each code.
- * lake depth file - GlobalLakeDepth.dat (located in `./fix/fix_orog `_). See GlobalLakeDepth.txt for a description of this file.
+ * lake status code file - One of the following files. (located in `./fix/fix_orog `_). See GlobalLakeStatus.txt for a description of the file format.
+ * GlobalLakeStatus_MOSISp.dat
+ * GlobalLakeStatus_GLDBv3release.dat
+ * GlobalLakeStatus_VIIRS.dat
+ * lake depth file - One of the following files. (located in `./fix/fix_orog `_). See GlobalLakeDepth.txt for a description of this file.
+ * GlobalLakeDepth_GLDBv3release.dat
+ * GlobalLakeDepth_GLOBathy.dat
**Output data:**
diff --git a/driver_scripts/driver_grid.hera.sh b/driver_scripts/driver_grid.hera.sh
index 63d1b872e..6975857a3 100755
--- a/driver_scripts/driver_grid.hera.sh
+++ b/driver_scripts/driver_grid.hera.sh
@@ -106,10 +106,15 @@ export soil_type_src="bnu.v3.30s" # Soil type data.
# For Beijing Norm. Univ. data
# 1) "bnu.v3.30s" for global 30s data.
+# choose dataset sources for lakefrac & lakedepth so that lake_data_srce=LakeFrac_LakeDepth;
+# available options are 'MODISP_GLDBV3', 'MODISP_GLOBATHY', 'VIIRS_GLDBV3', 'VIIRS_GLOBATHY' & 'GLDBV3'
+export lake_data_srce=MODISP_GLDBV3
+
if [ $gtype = uniform ]; then
export res=96
- export add_lake=false # Add lake frac and depth to orography data.
- export lake_cutoff=0.20 # lake frac < lake_cutoff ignored when add_lake=T
+ export add_lake=true # Add lake frac and depth to orography data.
+ export lake_cutoff=0.50 # return 0 if lake_frac < lake_cutoff & add_lake=T
+ export binary_lake=1 # return 1 if lake_frac >= lake_cutoff & add_lake=T
elif [ $gtype = stretch ]; then
export res=96
export stretch_fac=1.5 # Stretching factor for the grid
diff --git a/driver_scripts/driver_grid.jet.sh b/driver_scripts/driver_grid.jet.sh
index fe2d28dc5..8cfce4d89 100755
--- a/driver_scripts/driver_grid.jet.sh
+++ b/driver_scripts/driver_grid.jet.sh
@@ -104,10 +104,15 @@ export soil_type_src="bnu.v3.30s" # Soil type data.
# 4) "statsgo.nh.30s" for NH 30s data
# 5) "statsgo.30s" for global 30s data
+# choose dataset sources for lakefrac & lakedepth so that lake_data_srce=LakeFrac_LakeDepth;
+# available options are 'MODISP_GLDBV3', 'MODISP_GLOBATHY', 'VIIRS_GLDBV3', 'VIIRS_GLOBATHY' & 'GLDBV3'
+export lake_data_srce=MODISP_GLDBV3
+
if [ $gtype = uniform ]; then
export res=96
- export add_lake=false # Add lake frac and depth to orography data.
- export lake_cutoff=0.20 # lake frac < lake_cutoff ignored when add_lake=T
+ export add_lake=true # Add lake frac and depth to orography data.
+ export lake_cutoff=0.50 # return 0 if lake_frac < lake_cutoff & add_lake=T
+ export binary_lake=1 # return 1 if lake_frac >= lake_cutoff & add_lake=T
elif [ $gtype = stretch ]; then
export res=96
export stretch_fac=1.5 # Stretching factor for the grid
diff --git a/driver_scripts/driver_grid.orion.sh b/driver_scripts/driver_grid.orion.sh
index c0190f4d9..458abc318 100755
--- a/driver_scripts/driver_grid.orion.sh
+++ b/driver_scripts/driver_grid.orion.sh
@@ -103,10 +103,15 @@ export soil_type_src="bnu.v3.30s" # Soil type data.
# 4) "statsgo.nh.30s" for NH 30s data
# 5) "statsgo.30s" for global 30s data
+# choose dataset sources for lakefrac & lakedepth so that lake_data_srce=LakeFrac_LakeDepth;
+# available options are 'MODISP_GLDBV3', 'MODISP_GLOBATHY', 'VIIRS_GLDBV3', 'VIIRS_GLOBATHY' & 'GLDBV3'
+export lake_data_srce=MODISP_GLDBV3
+
if [ $gtype = uniform ]; then
export res=96
- export add_lake=false # Add lake frac and depth to orography data.
- export lake_cutoff=0.20 # lake frac < lake_cutoff ignored when add_lake=T
+ export add_lake=true # Add lake frac and depth to orography data.
+ export lake_cutoff=0.50 # return 0 if lake_frac < lake_cutoff & add_lake=T
+ export binary_lake=1 # return 1 if lake_frac >= lake_cutoff & add_lake=T
elif [ $gtype = stretch ]; then
export res=96
export stretch_fac=1.5 # Stretching factor for the grid
diff --git a/driver_scripts/driver_grid.wcoss2.sh b/driver_scripts/driver_grid.wcoss2.sh
index cbb5ef188..c5bb48919 100755
--- a/driver_scripts/driver_grid.wcoss2.sh
+++ b/driver_scripts/driver_grid.wcoss2.sh
@@ -102,10 +102,15 @@ export soil_type_src="bnu.v3.30s" # Soil type data
# 4) "statsgo.nh.30s" for NH 30s data
# 5) "statsgo.30s" for global 30s data
+# choose dataset sources for lakefrac & lakedepth so that lake_data_srce=LakeFrac_LakeDepth;
+# available options are 'MODISP_GLDBV3', 'MODISP_GLOBATHY', 'VIIRS_GLDBV3', 'VIIRS_GLOBATHY' & 'GLDBV3'
+export lake_data_srce=MODISP_GLDBV3
+
if [ $gtype = uniform ]; then
export res=96
- export add_lake=false # Add lake frac and depth to orography data.
- export lake_cutoff=0.20 # lake frac < lake_cutoff ignored when add_lake=T
+ export add_lake=true # Add lake frac and depth to orography data.
+ export lake_cutoff=0.50 # return 0 if lake_frac < lake_cutoff & add_lake=T
+ export binary_lake=1 # return 1 if lake_frac >= lake_cutoff & add_lake=T
elif [ $gtype = stretch ]; then
export res=96
export stretch_fac=1.5 # Stretching factor for the grid
diff --git a/reg_tests/grid_gen/c96.uniform.sh b/reg_tests/grid_gen/c96.uniform.sh
index 6811c71af..09e18c843 100755
--- a/reg_tests/grid_gen/c96.uniform.sh
+++ b/reg_tests/grid_gen/c96.uniform.sh
@@ -1,9 +1,9 @@
#!/bin/bash
#-----------------------------------------------------------------------
-# Create a C96 global uniform grid. Compare output to a set
-# of baseline files using the 'nccmp' utility. This script is
-# run by the machine specific driver script.
+# Create a C96 global uniform grid including inland lakes. Compare
+# output to a set of baseline files using the 'nccmp' utility. This
+# script is run by the machine specific driver script.
#-----------------------------------------------------------------------
set -x
@@ -13,6 +13,10 @@ export out_dir=${WORK_DIR}/c96.uniform
export res=96
export gtype=uniform
+export add_lake=true
+export lake_data_srce=MODISP_GLDBV3
+export lake_cutoff=0.50
+export binary_lake=1
NCCMP=${NCCMP:-$(which nccmp)}
diff --git a/reg_tests/grid_gen/driver.hera.sh b/reg_tests/grid_gen/driver.hera.sh
index c0211cc73..66673ab34 100755
--- a/reg_tests/grid_gen/driver.hera.sh
+++ b/reg_tests/grid_gen/driver.hera.sh
@@ -66,7 +66,7 @@ export OMP_NUM_THREADS=24
#-----------------------------------------------------------------------------
LOG_FILE1=${LOG_FILE}01
-TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \
+TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \
-o $LOG_FILE1 -e $LOG_FILE1 ./c96.uniform.sh)
#-----------------------------------------------------------------------------
diff --git a/reg_tests/grid_gen/driver.jet.sh b/reg_tests/grid_gen/driver.jet.sh
index 6641098bc..db387c9d4 100755
--- a/reg_tests/grid_gen/driver.jet.sh
+++ b/reg_tests/grid_gen/driver.jet.sh
@@ -64,7 +64,7 @@ export OMP_NUM_THREADS=24
#-----------------------------------------------------------------------------
LOG_FILE1=${LOG_FILE}01
-TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \
+TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:20:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \
--partition=xjet -o $LOG_FILE1 -e $LOG_FILE1 ./c96.uniform.sh)
#-----------------------------------------------------------------------------
diff --git a/reg_tests/grid_gen/driver.wcoss2.sh b/reg_tests/grid_gen/driver.wcoss2.sh
index 398765e1c..35c077f34 100755
--- a/reg_tests/grid_gen/driver.wcoss2.sh
+++ b/reg_tests/grid_gen/driver.wcoss2.sh
@@ -67,7 +67,7 @@ rm -fr $WORK_DIR
#-----------------------------------------------------------------------------
LOG_FILE1=${LOG_FILE}01
-TEST1=$(qsub -V -o $LOG_FILE1 -e $LOG_FILE1 -q $QUEUE -A $PROJECT_CODE -l walltime=00:10:00 \
+TEST1=$(qsub -V -o $LOG_FILE1 -e $LOG_FILE1 -q $QUEUE -A $PROJECT_CODE -l walltime=00:15:00 \
-N c96.uniform -l select=1:ncpus=30:mem=40GB $PWD/c96.uniform.sh)
#-----------------------------------------------------------------------------
diff --git a/sorc/orog_mask_tools.fd/inland.fd/inland.F90 b/sorc/orog_mask_tools.fd/inland.fd/inland.F90
index 057c648d3..66398e2b2 100644
--- a/sorc/orog_mask_tools.fd/inland.fd/inland.F90
+++ b/sorc/orog_mask_tools.fd/inland.fd/inland.F90
@@ -15,7 +15,7 @@ PROGRAM inland_mask
REAL, ALLOCATABLE :: inland(:,:,:)
REAL, ALLOCATABLE :: land_frac(:,:,:)
- INTEGER :: i_ctr, j_ctr, tile_beg, tile_end
+ INTEGER :: tile_beg, tile_end
INTEGER :: cs_res, x_res, y_res
CHARACTER(len=32) :: arg
INTEGER :: stat
@@ -23,7 +23,7 @@ PROGRAM inland_mask
REAL :: cutoff
CHARACTER(len=1) :: reg
- LOGICAL, ALLOCATABLE :: done(:,:,:)
+ LOGICAL, ALLOCATABLE :: done(:,:,:)
CALL getarg(0, arg) ! get the program name
IF (iargc() /= 3 .AND. iargc() /= 4) THEN
@@ -78,14 +78,19 @@ PROGRAM inland_mask
!! @author Ning Wang
SUBROUTINE mark_global_inland(cs_res)
INTEGER, INTENT(IN) :: cs_res
+ INTEGER :: i_seed, j_seed
ALLOCATE(done(cs_res,cs_res,6))
ALLOCATE(inland(cs_res,cs_res,6))
done = .false.
inland = 1.0
- i_ctr = cs_res/2; j_ctr = cs_res/2
- CALL mark_global_inland_rec_d(i_ctr, j_ctr, 2, 0)
+ i_seed = cs_res/2; j_seed = cs_res/2
+ CALL mark_global_inland_rec_d(i_seed, j_seed, 2, 0)
+
+! to make sure black sea is excluded
+ i_seed = REAL(cs_res)/32.0*3; j_seed = i_seed
+ CALL mark_global_inland_rec_d(i_seed, j_seed, 3, 0)
DEALLOCATE(done)
@@ -99,6 +104,7 @@ END SUBROUTINE mark_global_inland
SUBROUTINE mark_inland_reg(cs_res)
INTEGER, INTENT(IN) :: cs_res
INTEGER :: i_seed, j_seed
+ INTEGER :: i
ALLOCATE(done(x_res,y_res,1))
ALLOCATE(inland(x_res,y_res,1))
@@ -116,6 +122,30 @@ SUBROUTINE mark_inland_reg(cs_res)
i_seed = x_res/3; j_seed = 1
CALL mark_regional_inland_rec_d(i_seed, j_seed, 1, 0)
+ j_seed = 1
+ DO i = 1, x_res
+ CALL mark_regional_inland_rec_d(i, j_seed, 1, 0)
+ ENDDO
+
+ j_seed = y_res
+ DO i = x_res/2, x_res
+ CALL mark_regional_inland_rec_d(i, j_seed, 1, 0)
+ ENDDO
+
+! set up additional 3 seeds for ESG CONUS grid
+! i_seed = 1600; j_seed = 1040
+! i_seed = x_res - 10; j_seed = y_res
+! CALL mark_regional_inland_rec_d(i_seed, j_seed, 1, 0)
+
+! i_seed = x_res - 60; j_seed = y_res
+! CALL mark_regional_inland_rec_d(i_seed, j_seed, 1, 0)
+
+! i_seed = x_res - 275; j_seed = y_res
+! CALL mark_regional_inland_rec_d(i_seed, j_seed, 1, 0)
+
+! i_seed = 500; j_seed = 1
+! CALL mark_regional_inland_rec_d(i_seed, j_seed, 1, 0)
+
DEALLOCATE(done)
END SUBROUTINE mark_inland_reg
diff --git a/sorc/orog_mask_tools.fd/lake.fd/lakefrac.F90 b/sorc/orog_mask_tools.fd/lake.fd/lakefrac.F90
index 47f2fff60..ad0f6e184 100644
--- a/sorc/orog_mask_tools.fd/lake.fd/lakefrac.F90
+++ b/sorc/orog_mask_tools.fd/lake.fd/lakefrac.F90
@@ -15,7 +15,7 @@
!! - Ning Wang, Apr. 2019: Extended the program to process the same lake data
!! for FV3 stand-alone regional (SAR) model.
!!
-!! @return 0 for successful completion and for error.
+!! @return 0 for success.
!#define DIAG_N_VERBOSE
#define ADD_ATT_FOR_NEW_VAR
PROGRAM lake_frac
@@ -32,41 +32,53 @@ PROGRAM lake_frac
REAL, ALLOCATABLE :: cs_lakestatus(:), cs_lakedepth(:)
REAL, ALLOCATABLE :: src_grid_lon(:), src_grid_lat(:)
- INTEGER :: tile_req, tile_beg, tile_end
+ INTEGER :: tile_req, tile_beg, tile_end, binary_lake
REAL :: lake_cutoff
INTEGER, PARAMETER :: nlat = 21600, nlon = 43200
REAL, PARAMETER :: d2r = acos(-1.0) / 180.0
REAL, PARAMETER :: r2d = 180.0 /acos(-1.0)
REAL, PARAMETER :: pi = acos(-1.0)
- REAL*8, PARAMETER :: gppdeg = 119.99444445
- REAL*8, PARAMETER :: delta = 1.0 / 119.99444445
+ REAL*8, PARAMETER :: gppdeg = 120.0
+ REAL*8, PARAMETER :: delta = 1.0 / 120.0
- CHARACTER(len=32) :: arg
+ CHARACTER(len=32) :: arg, lakestatus_srce, lakedepth_srce
CHARACTER(len=256) :: lakedata_path
INTEGER :: stat
CALL getarg(0, arg) ! get the program name
- IF (iargc() /= 3 .AND. iargc() /= 4) THEN
+ IF (iargc() /= 5 .AND. iargc() /= 7) THEN
PRINT*, 'Usage: ', trim(arg), &
- ' [tile_num (0:all tiles, 7:regional)] [resolution (48,96, ...)] [path to lake data file]'
+ ' [tile_num (0:all tiles, 7:regional)] [resolution (48,96, ...)] &
+ [lake data path] [lake status source] [lake depth source]'
PRINT*, 'Or: ', trim(arg), &
- ' [tile_num (0:all tiles, 7:regional)] [resolution (48,96, ...)] [path to lake data file] [lake_cutoff]'
- STOP
+ ' [tile_num (0:all tiles, 7:regional)] [resolution (48,96, ...)] &
+ [lake data path] [lake status source] [lake depth source] [lake_cutoff] [binary_lake]'
+ STOP -1
ENDIF
CALL getarg(1, arg)
READ(arg,*,iostat=stat) tile_req
CALL getarg(2, arg)
READ(arg,*,iostat=stat) cs_res
CALL getarg(3, lakedata_path)
+ CALL getarg(4, lakestatus_srce)
+ CALL getarg(5, lakedepth_srce)
- IF (iargc() == 3) THEN
- lake_cutoff = 0.20
+ IF (iargc() == 5) THEN
+ lake_cutoff = 0.50
+ binary_lake = 1
ELSE
- CALL getarg(4, arg)
+ CALL getarg(6, arg)
READ(arg,*,iostat=stat) lake_cutoff
+ CALL getarg(7, arg)
+ READ(arg,*,iostat=stat) binary_lake
ENDIF
+ PRINT*, 'lake status source:', trim(lakestatus_srce)
+ PRINT*, 'lake depth source:', trim(lakedepth_srce)
+ PRINT*, 'lake cutoff:', lake_cutoff
+ PRINT*, 'binary lake:', binary_lake
+
IF (tile_req == 0) THEN
tile_beg = 1; tile_end = 6
PRINT*, 'Process tile 1 - 6 at resolution C',cs_res
@@ -91,17 +103,31 @@ PROGRAM lake_frac
ELSE
CALL read_cubed_sphere_reg_grid(cs_res, cs_grid, 3, res_x, res_y)
ENDIF
- ! compute source grid
+
+ ! allocate and compute source grid
ALLOCATE(src_grid_lon(nlon), src_grid_lat(nlat))
- DO i = 1, nlon
- src_grid_lon(i) = -180.0 + delta * (i-1)
- ENDDO
- DO i = 1, nlat
- src_grid_lat(i) = 90.0 - delta * (i-1)
- ENDDO
+
+ IF (lakestatus_srce == "GLDBV2" .OR. lakestatus_srce == "GLDBV3") THEN
+ ! GLDB data points are at the lower right corners of the grid cells
+ DO i = 1, nlon
+ src_grid_lon(i) = -180.0 + delta * i
+ ENDDO
+ DO i = 1, nlat
+ src_grid_lat(i) = 90.0 - delta * i
+ ENDDO
+ ENDIF
+
+ IF (lakestatus_srce == "MODISP" .OR. lakestatus_srce == "VIIRS") THEN
+ ! GLDB data points are at the upprt left corners of the grid cells
+ DO i = 1, nlon
+ src_grid_lon(i) = -180.0 + delta * (i-1)
+ ENDDO
+ DO i = 1, nlat
+ src_grid_lat(i) = 90.0 - delta * (i-1)
+ ENDDO
+ ENDIF
! read in lake data file
-! sfcdata_path = '/scratch1/NCEPDEV/global/glopara/fix/orog/'
lakedata_path = trim(lakedata_path) // "/"
ALLOCATE(lakestatus(nlon*nlat),lakedepth(nlon*nlat))
PRINT*, 'Read in lake data file ...'
@@ -115,7 +141,7 @@ PROGRAM lake_frac
PRINT*, 'Calculate lake fraction and average depth for cubed-sphere cells ...'
CALL cal_lake_frac_depth(lakestatus,cs_lakestatus,lakedepth,cs_lakedepth)
- ! write lake status (in terms of fraction) and lake depth(average)
+ ! write lake status (in terms of fraction) and lake depth(average, in meters)
! to a netcdf file
IF (tile_req /= 7) THEN
PRINT*, 'Write lake fraction/depth on cubed sphere grid cells to netCDF files ...'
@@ -130,7 +156,7 @@ PROGRAM lake_frac
DEALLOCATE(lakestatus,lakedepth)
DEALLOCATE(src_grid_lat, src_grid_lon)
- STOP
+ STOP 0
CONTAINS
!> Calculate lake fraction and depth on the model grid from
@@ -157,7 +183,9 @@ SUBROUTINE cal_lake_frac_depth(lakestat,cs_lakestat,lakedpth,cs_lakedpth)
INTEGER :: src_grid_lon_beg1,src_grid_lon_end1,src_grid_lon_beg2,src_grid_lon_end2
INTEGER :: grid_ct, lake_ct, co_gc, tmp
- REAL*8 :: lake_dpth_sum
+ INTEGER*1 :: lkst
+ INTEGER*2 :: lkdp
+ REAL*8 :: lake_dpth_sum, lake_avg_frac
LOGICAL :: two_section, enclosure_cnvx
IF (tile_req /= 7) THEN
@@ -234,13 +262,11 @@ SUBROUTINE cal_lake_frac_depth(lakestat,cs_lakestat,lakedpth,cs_lakedpth)
src_grid_lon_end = nint((180.0+lonmax)*gppdeg+0.5)
IF (src_grid_lat_beg > src_grid_lat_end) THEN
- print*,'switch!!!'
tmp = src_grid_lat_beg
src_grid_lat_beg = src_grid_lat_end
src_grid_lat_end = tmp
ENDIF
IF (src_grid_lon_beg > src_grid_lon_end) THEN
- print*,'switch!!!'
tmp = src_grid_lon_beg
src_grid_lon_beg = src_grid_lon_end
src_grid_lon_end = tmp
@@ -263,88 +289,65 @@ SUBROUTINE cal_lake_frac_depth(lakestat,cs_lakestat,lakedpth,cs_lakedpth)
#endif
lake_ct = 0; grid_ct = 0
lake_dpth_sum = 0.0
+ lake_avg_frac = 0.0
DO j = src_grid_lat_beg, src_grid_lat_end, stride_lat
stride_lon = int(1.0/cos(src_grid_lat(j)*d2r)*REAL(stride_lat))
#ifdef DIAG_N_VERBOSE
- IF (j == src_grid_lat_beg) THEN
- PRINT*, 'lon index range and stride', &
- src_grid_lon_beg,src_grid_lon_end,stride_lon
- PRINT*, 'lon range ', &
- src_grid_lon(src_grid_lon_beg),src_grid_lon(src_grid_lon_end)
- IF (two_section == .true.) THEN
- PRINT*, 'section1 index lon range and stride', &
- src_grid_lon_beg1,src_grid_lon_end1,stride_lon
- PRINT*, 'section1 lon range ', &
- src_grid_lon(src_grid_lon_beg1),src_grid_lon(src_grid_lon_end1)
- PRINT*, 'section2 index lon range and stride', &
- src_grid_lon_beg2,src_grid_lon_end2,stride_lon
- PRINT*, 'section2 lon range ', &
- src_grid_lon(src_grid_lon_beg2),src_grid_lon(src_grid_lon_end2)
+ IF (j == src_grid_lat_beg) THEN
+ PRINT*, 'lon index range and stride', &
+ src_grid_lon_beg,src_grid_lon_end,stride_lon
+ PRINT*, 'lon range ', &
+ src_grid_lon(src_grid_lon_beg),src_grid_lon(src_grid_lon_end)
+ IF (two_section .eqv. .true.) THEN
+ PRINT*, 'section1 index lon range and stride', &
+ src_grid_lon_beg1,src_grid_lon_end1,stride_lon
+ PRINT*, 'section1 lon range ', &
+ src_grid_lon(src_grid_lon_beg1),src_grid_lon(src_grid_lon_end1)
+ PRINT*, 'section2 index lon range and stride', &
+ src_grid_lon_beg2,src_grid_lon_end2,stride_lon
+ PRINT*, 'section2 lon range ', &
+ src_grid_lon(src_grid_lon_beg2),src_grid_lon(src_grid_lon_end2)
+ ENDIF
ENDIF
- ENDIF
#endif
- IF (two_section .EQV. .false.) THEN
+ IF (two_section .eqv. .false.) THEN
DO i = src_grid_lon_beg, src_grid_lon_end, stride_lon
p(1) = src_grid_lat(j); p(2) = src_grid_lon(i)
p(:) = p(:)*d2r
- IF(enclosure_cnvx(v, 4, p, co_gc) .EQV. .true.) THEN
+ IF(enclosure_cnvx(v, 4, p, co_gc) .eqv. .true.) THEN
grid_ct = grid_ct+1
- IF (lakestat((j-1)*nlon+i) /= 0) THEN
- lake_ct = lake_ct+1
- IF (lakedpth((j-1)*nlon+i) < 0) THEN
- IF (lakestat((j-1)*nlon+i) == 4) THEN
- lake_dpth_sum = lake_dpth_sum+30.0
- ELSE
- lake_dpth_sum = lake_dpth_sum+100.0
- ENDIF
- ELSE
- lake_dpth_sum = lake_dpth_sum+REAL(lakedpth((j-1)*nlon+i))
- ENDIF
- ENDIF
+ lkst = lakestat((j-1)*nlon+i); lkdp = lakedpth((j-1)*nlon+i)
+ CALL lake_cell_comp(lkst, lkdp, lake_ct, lake_avg_frac, lake_dpth_sum)
ENDIF
ENDDO
ELSE
DO i = src_grid_lon_beg1, src_grid_lon_end1, stride_lon
p(1) = src_grid_lat(j); p(2) = src_grid_lon(i)
p(:) = p(:)*d2r
- IF(enclosure_cnvx(v, 4, p, co_gc) .EQV. .true.) THEN
+ IF(enclosure_cnvx(v, 4, p, co_gc) .eqv. .true.) THEN
grid_ct = grid_ct+1
- IF (lakestat((j-1)*nlon+i) /= 0) THEN
- lake_ct = lake_ct+1
- IF (lakedpth((j-1)*nlon+i) < 0) THEN
- IF (lakestat((j-1)*nlon+i) == 4) THEN
- lake_dpth_sum = lake_dpth_sum+30.0
- ELSE
- lake_dpth_sum = lake_dpth_sum+100.0
- ENDIF
- ELSE
- lake_dpth_sum = lake_dpth_sum+REAL(lakedpth((j-1)*nlon+i))
- ENDIF
- ENDIF
+ lkst = lakestat((j-1)*nlon+i); lkdp = lakedpth((j-1)*nlon+i)
+ CALL lake_cell_comp(lkst, lkdp, lake_ct, lake_avg_frac, lake_dpth_sum)
ENDIF
ENDDO
DO i = src_grid_lon_beg2, src_grid_lon_end2, stride_lon
p(1) = src_grid_lat(j); p(2) = src_grid_lon(i)
p(:) = p(:)*d2r
- IF(enclosure_cnvx(v, 4, p, co_gc) .EQV. .true.) THEN
+ IF(enclosure_cnvx(v, 4, p, co_gc) .eqv. .true.) THEN
grid_ct = grid_ct+1
- IF (lakestat((j-1)*nlon+i) /= 0) THEN
- lake_ct = lake_ct+1
- IF (lakedpth((j-1)*nlon+i) < 0) THEN
- IF (lakestat((j-1)*nlon+i) == 4) THEN
- lake_dpth_sum = lake_dpth_sum+30.0
- ELSE
- lake_dpth_sum = lake_dpth_sum+100.0
- ENDIF
- ELSE
- lake_dpth_sum = lake_dpth_sum+REAL(lakedpth((j-1)*nlon+i))
- ENDIF
- ENDIF
+ lkst = lakestat((j-1)*nlon+i); lkdp = lakedpth((j-1)*nlon+i)
+ CALL lake_cell_comp(lkst, lkdp, lake_ct, lake_avg_frac, lake_dpth_sum)
ENDIF
ENDDO
ENDIF
ENDDO
- cs_lakestat(cs_data_idx)=REAL(lake_ct)/REAL(grid_ct)
+ IF (lakestatus_srce == "GLDBV3" .OR. lakestatus_srce == "GLDBV2" .OR. &
+ lakestatus_srce == "VIIRS" ) THEN
+ cs_lakestat(cs_data_idx)=REAL(lake_ct)/REAL(grid_ct)
+ ENDIF
+ IF (lakestatus_srce == "MODISP") THEN
+ cs_lakestat(cs_data_idx)=lake_avg_frac/REAL(grid_ct)
+ ENDIF
IF (lake_ct /= 0) THEN
cs_lakedpth(cs_data_idx)=lake_dpth_sum/REAL(lake_ct)/10.0 !convert to meter
ELSE
@@ -370,6 +373,44 @@ SUBROUTINE cal_lake_frac_depth(lakestat,cs_lakestat,lakedpth,cs_lakedpth)
END SUBROUTINE cal_lake_frac_depth
+!> Compute cumulatively the lake fraction and lake depth for a cell
+!!
+!! @param[in] lkst lake status value from a grid point in the source data.
+!! @param[in] lkdp lake depth value from a grid point in the source data.
+!! @param[out] lake_ct lake points number accumulated for the cell
+!! @param[out] lake_avg_frac lake fraction value accumulated for the cell.
+!! @param[out] lake_dpth_sum is the lake depth value accumulated for the cell.
+!! @author Ning Wang
+SUBROUTINE lake_cell_comp(lkst, lkdp, lake_ct, lake_avg_frac, lake_dpth_sum)
+ INTEGER*1, INTENT(IN) :: lkst
+ INTEGER*2, INTENT(IN) :: lkdp
+ INTEGER, INTENT(OUT) :: lake_ct
+ REAL*8, INTENT(OUT) :: lake_avg_frac, lake_dpth_sum
+
+ IF (lkst /= 0) THEN ! lake point
+ lake_ct = lake_ct+1
+ IF (lakestatus_srce == "GLDBV3" .OR. lakestatus_srce == "GLDBV2") THEN
+ IF (lkdp <= 0) THEN
+ IF (lkst == 4) THEN
+ lake_dpth_sum = lake_dpth_sum+30.0
+ ELSE
+ lake_dpth_sum = lake_dpth_sum+100.0
+ ENDIF
+ ELSE
+ lake_dpth_sum = lake_dpth_sum+REAL(lkdp)
+ ENDIF
+ ENDIF
+ IF (lakestatus_srce == "MODISP" .OR. lakestatus_srce == "VIIRS") THEN
+ lake_avg_frac = lake_avg_frac + REAL(lkst) / 100.0
+ IF (lkdp <= 0) THEN
+ lake_dpth_sum = lake_dpth_sum+100.0
+ ELSE
+ lake_dpth_sum = lake_dpth_sum+REAL(lkdp)
+ ENDIF
+ ENDIF
+ ENDIF
+END SUBROUTINE lake_cell_comp
+
!> Read the latitude and longitude for a cubed-sphere
!! grid from the 'grid' files. For global grids, all
!! six sides are returned.
@@ -400,7 +441,6 @@ SUBROUTINE read_cubed_sphere_grid(res, grid)
tile_beg = tile_req; tile_end = tile_req
ENDIF
WRITE(res_ch,'(I4)') res
-! gridfile_path = "/scratch1/NCEPDEV/global/glopara/fix/fix_fv3/C"//trim(adjustl(res_ch))//"/"
gridfile_path = "./"
DO i = tile_beg, tile_end
WRITE(ich, '(I1)') i
@@ -521,14 +561,38 @@ SUBROUTINE read_lakedata(lakedata_path,lake_stat,lake_dpth,nlat,nlon)
data_sz = nlon*nlat
- ! read in 30 arc seconds lake data
- lakefile = trim(lakedata_path) // "GlobalLakeStatus.dat"
- OPEN(10, file=lakefile, form='unformatted', access='direct', recl=data_sz*1)
+! read in 30 arc seconds lake data
+ ! lake fraction data
+ lakefile = trim(lakedata_path) // "GlobalLakeStatus_GLDBv3release.dat"
+ IF (lakestatus_srce == "GLDBV2") THEN
+ lakefile = trim(lakedata_path) // "GlobalLakeStatus.dat"
+ ENDIF
+ IF (lakestatus_srce == "GLDBV3") THEN
+ lakefile = trim(lakedata_path) // "GlobalLakeStatus_GLDBv3release.dat"
+ ENDIF
+ IF (lakestatus_srce == "MODISP") THEN
+! lakefile = trim(lakedata_path) // "GlobalLakeStatus_MODIS15s.dat"
+ lakefile = trim(lakedata_path) // "GlobalLakeStatus_MODISp.dat"
+ ENDIF
+ IF (lakestatus_srce == "VIIRS") THEN
+ lakefile = trim(lakedata_path) // "GlobalLakeStatus_VIIRS.dat"
+ ENDIF
+ OPEN(10, file=lakefile, form='unformatted', access='direct', status='old', recl=data_sz*1)
READ(10,rec=1) lake_stat
CLOSE(10)
- lakefile = trim(lakedata_path) // "GlobalLakeDepth.dat"
- OPEN(10, file=lakefile, form='unformatted', access='direct', recl=data_sz*2)
+ ! lake depth data
+ lakefile = trim(lakedata_path) // "GlobalLakeDepth_GLDBv3release.dat"
+ IF (lakedepth_srce == "GLDBV2") THEN
+ lakefile = trim(lakedata_path) // "GlobalLakeDepth.dat"
+ ENDIF
+ IF (lakedepth_srce == "GLDBV3") THEN
+ lakefile = trim(lakedata_path) // "GlobalLakeDepth_GLDBv3release.dat"
+ ENDIF
+ IF (lakedepth_srce == "GLOBATHY") THEN
+ lakefile = trim(lakedata_path) // "GlobalLakeDepth_GLOBathy.dat"
+ ENDIF
+ OPEN(10, file=lakefile, form='unformatted', access='direct', status='old', recl=data_sz*2)
READ(10,rec=1) lake_dpth
CLOSE(10)
@@ -552,7 +616,7 @@ SUBROUTINE write_lakedata_to_orodata(cs_res, cs_lakestat, cs_lakedpth)
INTEGER :: stat, ncid, x_dimid, y_dimid, varid, dimids(2)
INTEGER :: lake_frac_id, lake_depth_id
INTEGER :: land_frac_id, slmsk_id, inland_id, geolon_id, geolat_id
- CHARACTER(len=256) :: filename,string
+ CHARACTER(len=256) :: filename,string,lakeinfo
CHARACTER(len=1) :: ich
CHARACTER(len=4) res_ch
REAL :: lake_frac(cs_res*cs_res),lake_depth(cs_res*cs_res)
@@ -563,7 +627,6 @@ SUBROUTINE write_lakedata_to_orodata(cs_res, cs_lakestat, cs_lakedpth)
INTEGER :: i, j
-! include "netcdf.inc"
tile_sz = cs_res*cs_res
WRITE(res_ch,'(I4)') cs_res
@@ -598,28 +661,51 @@ SUBROUTINE write_lakedata_to_orodata(cs_res, cs_lakestat, cs_lakedpth)
CALL nc_opchk(stat, "nf90_put_att: lake_frac:long_name")
stat = nf90_put_att(ncid, lake_frac_id,'unit','fraction')
CALL nc_opchk(stat, "nf90_put_att: lake_frac:unit")
- write(string,'(a,f5.2)') 'based on GLDBv2 (Choulga et al. 2014); missing lakes &
- added based on land_frac in this dataset; lake_frac cutoff is',lake_cutoff
+ write(lakeinfo,'(a,f4.2,a,i1)') ' lake_frac cutoff=',lake_cutoff,'; binary_lake=',binary_lake
+ IF (lakestatus_srce == "GLDBV3") THEN
+ write(string,'(2a)') 'based on GLDBv3 (Choulga et al. 2019); missing lakes & added based on land_frac in this dataset;', &
+ trim(lakeinfo)
+ ELSE IF (lakestatus_srce == "GLDBV2") THEN
+ write(string,'(2a)') 'based on GLDBv2 (Choulga et al. 2014); missing lakes & added based on land_frac in this dataset;', &
+ trim(lakeinfo)
+ ELSE IF (lakestatus_srce == "MODISP") THEN
+ write(string,'(2a)') 'based on MODIS (2011-2015) product updated with two &
+ Landsat products: the JRC water product (2016-2020) and the GLC-FCS30 (2020); &
+ the source data set was created by Chengquan Huang of UMD;',trim(lakeinfo)
+ ELSE IF (lakestatus_srce == "VIIRS") THEN
+ write(string,'(2a)') 'based on multi-year VIIRS global surface type &
+ classification map (2012-2019); the source data set was created by &
+ Chengquan Huang of UMD and Michael Barlage of NOAA;',trim(lakeinfo)
+ ENDIF
stat = nf90_put_att(ncid, lake_frac_id,'description',trim(string))
CALL nc_opchk(stat, "nf90_put_att: lake_frac:description")
#endif
stat = nf90_def_var(ncid,"lake_depth",NF90_FLOAT,dimids,lake_depth_id)
CALL nc_opchk(stat, "nf90_def_var: lake_depth")
#ifdef ADD_ATT_FOR_NEW_VAR
- stat = nf90_put_att(ncid, lake_depth_id,'coordinates','geolon geolat')
- CALL nc_opchk(stat, "nf90_put_att: lake_depth:coordinates")
+ stat = nf90_put_att(ncid, lake_depth_id,'coordinates','geolon geolat')
+ CALL nc_opchk(stat, "nf90_put_att: lake_depth:coordinates")
stat = nf90_put_att(ncid, lake_depth_id,'long_name','lake depth')
CALL nc_opchk(stat, "nf90_put_att: lake_depth:long_name")
stat = nf90_put_att(ncid, lake_depth_id,'unit','meter')
CALL nc_opchk(stat, "nf90_put_att: lake_depth:long_name")
- stat = nf90_put_att(ncid, lake_depth_id,'description', &
+ IF (lakedepth_srce == "GLDBV3") THEN
+ stat = nf90_put_att(ncid, lake_depth_id,'description', &
+ 'based on GLDBv3 (Choulga et al. 2019); missing depth set to 10m &
+ (except to 211m in Caspian Sea); spurious large pos. depths are left unchanged.')
+ ELSE IF (lakedepth_srce == "GLDBV2") THEN
+ stat = nf90_put_att(ncid, lake_depth_id,'description', &
'based on GLDBv2 (Choulga et al. 2014); missing depth set to 10m &
(except to 211m in Caspian Sea); spurious large pos. depths are left unchanged.')
+ ELSE IF (lakedepth_srce == "GLOBATHY") THEN
+ stat = nf90_put_att(ncid, lake_depth_id,'description', &
+ 'based on GLOBathy data resampled and projected to the MODIS domain.')
+ ENDIF
CALL nc_opchk(stat, "nf90_put_att: lake_depth:description")
#endif
- write(string,'(a,es8.1)') 'land_frac and lake_frac are adjusted such that their sum '// &
- 'is 1 at points where inland=1; land_frac cutoff is',land_cutoff
+ write(string,'(a,es8.1)') 'land_frac and lake_frac are adjusted such that &
+ their sum is 1 at points where inland=1; land_frac cutoff is',land_cutoff
stat = nf90_put_att(ncid, land_frac_id,'description',trim(string))
CALL nc_opchk(stat, "nf90_put_att: land_frac:description")
@@ -660,45 +746,40 @@ SUBROUTINE write_lakedata_to_orodata(cs_res, cs_lakestat, cs_lakedpth)
lake_frac (:) = cs_lakestat ((tile_num-1)*tile_sz+1:tile_num*tile_sz)
lake_depth(:) = cs_lakedepth((tile_num-1)*tile_sz+1:tile_num*tile_sz)
-! add Caspian Sea and Aral Sea to lake_frac and lake_depth
- IF (tile_num == 2 .or. tile_num == 3) THEN
- DO i = 1, tile_sz
- IF (land_frac(i) < 0.9 .AND. lake_frac(i) < 0.1) THEN
- IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
- geolon(i) > 45.0 .AND. geolon(i) <= 55.0) THEN
- lake_frac(i) = 1.-land_frac(i)
- lake_depth(i) = 211.0
- ENDIF
- IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
- geolon(i) > 57.0 .AND. geolon(i) <= 63.0) THEN
- lake_frac(i) = 1.-land_frac(i)
- lake_depth(i) = 10.0
- ENDIF
- ENDIF
- ENDDO
+! include Caspian Sea and Aral Sea if GLDB data set is used, and
+! exclude lakes in the coastal areas of Antarctica if MODIS data set is used
+ CALL include_exclude_lakes(lake_frac,land_frac,lake_depth,geolat,geolon,tile_num)
+
+! epsil is "numerical" nonzero min for lake_frac/land_frac
+! lake_cutoff/land_cutoff is practical min for lake_frac/land_frac
+ IF (min(lake_cutoff,land_cutoff) < epsil) then
+ PRINT *,'lake_cutoff/land_cutoff cannot be smaller than epsil, reset...'
+ lake_cutoff=max(epsil,lake_cutoff)
+ land_cutoff=max(epsil,land_cutoff)
ENDIF
! adjust land_frac and lake_frac, and make sure land_frac+lake_frac=1 at inland points
DO i = 1, tile_sz
- if (lake_frac(i) >= lake_cutoff) then ! non-zero lake_frac dominates over land_frac
- land_frac(i) = max(0., min(1., 1.-lake_frac(i)))
- elseif (inland(i) == 1.) then ! land_frac dominates over lake_frac at inland points
- lake_frac(i) = max(0., min(1., 1.-land_frac(i)))
- end if
+ if (land_frac(i)< land_cutoff) land_frac(i)=0.
+ if (land_frac(i)>1.-land_cutoff) land_frac(i)=1.
-! epsil is "numerical" nonzero min for lake_frac/land_frac
-! lake_cutoff/land_cutoff is practical min for lake_frac/land_frac
- if (min(lake_cutoff,land_cutoff) < epsil) then
- print *,'lake_cutoff/land_cutoff cannot be smaller than epsil, reset...'
- lake_cutoff=max(epsil,lake_cutoff)
- land_cutoff=max(epsil,land_cutoff)
+ if (inland(i) /= 1.) then
+ lake_frac(i) = 0.
+ endif
+
+ if (lake_frac(i) < lake_cutoff) then
+ lake_frac(i)=0.
+ elseif (binary_lake == 1) then
+ lake_frac(i)=1.
end if
+ if (lake_frac(i) > 1.-epsil) lake_frac(i)=1.
+ ENDDO
- if (lake_frac(i)< lake_cutoff) lake_frac(i)=0.
- if (lake_frac(i)>1.-lake_cutoff) lake_frac(i)=1.
- if (inland(i) == 1.) land_frac(i) = 1.-lake_frac(i)
- if (land_frac(i)< land_cutoff) land_frac(i)=0.
- if (land_frac(i)>1.-land_cutoff) land_frac(i)=1.
+! finalize land_frac/slmsk based on modified lake_frac
+ DO i = 1, tile_sz
+ if (inland(i) == 1.) then
+ land_frac(i) = 1. - lake_frac(i)
+ end if
if (lake_frac(i) < lake_cutoff) then
lake_depth(i)=0.
@@ -707,6 +788,7 @@ SUBROUTINE write_lakedata_to_orodata(cs_res, cs_lakestat, cs_lakedpth)
end if
slmsk(i) = nint(land_frac(i))
ENDDO
+
! write 2 new variables
stat = nf90_put_var(ncid, lake_frac_id, lake_frac, &
start = (/ 1, 1 /), count = (/ cs_res, cs_res /) )
@@ -794,43 +876,65 @@ SUBROUTINE write_reg_lakedata_to_orodata(cs_res, tile_x_dim, tile_y_dim, cs_lake
CALL nc_opchk(stat, "nf90_redef")
IF (nf90_inq_varid(ncid, "lake_frac",lake_frac_id) /= 0) THEN
- stat = nf90_def_var(ncid,"lake_frac",NF90_FLOAT,dimids,lake_frac_id)
- CALL nc_opchk(stat, "nf90_def_var: lake_frac")
+ stat = nf90_def_var(ncid,"lake_frac",NF90_FLOAT,dimids,lake_frac_id)
+ CALL nc_opchk(stat, "nf90_def_var: lake_frac")
#ifdef ADD_ATT_FOR_NEW_VAR
- stat = nf90_put_att(ncid, lake_frac_id,'coordinates','geolon geolat')
- CALL nc_opchk(stat, "nf90_put_att: lake_frac:coordinates")
- stat = nf90_put_att(ncid, lake_frac_id,'long_name','lake fraction')
- CALL nc_opchk(stat, "nf90_put_att: lake_frac:long_name")
- stat = nf90_put_att(ncid, lake_frac_id,'unit','fraction')
- CALL nc_opchk(stat, "nf90_put_att: lake_frac:unit")
- stat = nf90_put_att(ncid, lake_frac_id,'description', &
- 'based on GLDBv2 (Choulga et al. 2014); missing lakes &
- added based on land_frac in this dataset.')
- CALL nc_opchk(stat, "nf90_put_att: lake_frac:description")
+ stat = nf90_put_att(ncid, lake_frac_id,'coordinates','geolon geolat')
+ CALL nc_opchk(stat, "nf90_put_att: lake_frac:coordinates")
+ stat = nf90_put_att(ncid, lake_frac_id,'long_name','lake fraction')
+ CALL nc_opchk(stat, "nf90_put_att: lake_frac:long_name")
+ stat = nf90_put_att(ncid, lake_frac_id,'unit','fraction')
+ CALL nc_opchk(stat, "nf90_put_att: lake_frac:unit")
+ IF (lakestatus_srce == "GLDBV3") THEN
+ write(string,'(a,es8.1)') 'based on GLDBv3 (Choulga et al. 2019); missing lakes &
+ added based on land_frac in this dataset; lake_frac cutoff:',lake_cutoff
+ ELSE IF (lakestatus_srce == "GLDBV2") THEN
+ write(string,'(a,es8.1)') 'based on GLDBv2 (Choulga et al. 2014); missing lakes &
+ added based on land_frac in this dataset; lake_frac cutoff:',lake_cutoff
+ ELSE IF (lakestatus_srce == "MODISP") THEN
+ write(string,'(a,es8.1)') 'based on MODIS (2011-2015) product updated with two &
+ Landsat products: the JRC water product (2016-2020) and the GLC-FCS30 (2020); &
+ the source data set was created by Chengquan Huang of UMD; &
+ lake_frac cutoff:',lake_cutoff
+ ELSE IF (lakestatus_srce == "VIIRS") THEN
+ write(string,'(a,es8.1)') 'based on multi-year VIIRS global surface type &
+ classification map (2012-2019); the source data set was created by &
+ Chengquan Huang of UMD and Michael Barlage of NOAA; &
+ lake_frac cutoff:',lake_cutoff
+ ENDIF
+ stat = nf90_put_att(ncid, lake_frac_id,'description',trim(string))
+ CALL nc_opchk(stat, "nf90_put_att: lake_frac:description")
#endif
ENDIF
IF (nf90_inq_varid(ncid, "lake_depth",lake_depth_id) /= 0) THEN
- stat = nf90_def_var(ncid,"lake_depth",NF90_FLOAT,dimids,lake_depth_id)
- CALL nc_opchk(stat, "nf90_def_var: lake_depth")
+ stat = nf90_def_var(ncid,"lake_depth",NF90_FLOAT,dimids,lake_depth_id)
+ CALL nc_opchk(stat, "nf90_def_var: lake_depth")
#ifdef ADD_ATT_FOR_NEW_VAR
- stat = nf90_put_att(ncid, lake_depth_id,'coordinates','geolon geolat')
- CALL nc_opchk(stat, "nf90_put_att: lake_depth:coordinates")
- stat = nf90_put_att(ncid, lake_depth_id,'long_name','lake depth')
- CALL nc_opchk(stat, "nf90_put_att: lake_depth:long_name")
- stat = nf90_put_att(ncid, lake_depth_id,'unit','meter')
- CALL nc_opchk(stat, "nf90_put_att: lake_depth:long_name")
- stat = nf90_put_att(ncid, lake_depth_id,'description', &
- 'based on GLDBv2 (Choulga et al. 2014); missing depth set to 10m &
- (except to 211m in Caspian Sea); spurious large pos. depths are left unchanged.')
- CALL nc_opchk(stat, "nf90_put_att: lake_depth:description")
-#endif
+ stat = nf90_put_att(ncid, lake_depth_id,'coordinates','geolon geolat')
+ CALL nc_opchk(stat, "nf90_put_att: lake_depth:coordinates")
+ stat = nf90_put_att(ncid, lake_depth_id,'long_name','lake depth')
+ CALL nc_opchk(stat, "nf90_put_att: lake_depth:long_name")
+ stat = nf90_put_att(ncid, lake_depth_id,'unit','meter')
+ CALL nc_opchk(stat, "nf90_put_att: lake_depth:long_name")
+ IF (lakedepth_srce == "GLDBV3") THEN
+ stat = nf90_put_att(ncid, lake_depth_id,'description', &
+ 'based on GLDBv3 (Choulga et al. 2019); missing depth set to 10m &
+ (except to 211m in Caspian Sea); spurious large pos. depths are left unchanged.')
+ ELSE IF (lakedepth_srce == "GLDBV2") THEN
+ stat = nf90_put_att(ncid, lake_depth_id,'description', &
+ 'based on GLDBv2 (Choulga et al. 2014); missing depth set to 10m &
+ (except to 211m in Caspian Sea); spurious large pos. depths are left unchanged.')
+ ELSE IF (lakedepth_srce == "GLOBATHY") THEN
+ stat = nf90_put_att(ncid, lake_depth_id,'description', &
+ 'based on GLOBathy data resampled and projected to the MODIS domain.')
+ ENDIF
+ CALL nc_opchk(stat, "nf90_put_att: lake_depth:description")
ENDIF
- write(string,'(a,es8.1)') 'land_frac and lake_frac are adjusted '// &
- 'such that their sum is 1 at points where inland=1; land_frac '// &
- 'cutoff is ',land_cutoff
+#endif
+ write(string,'(a,es8.1)') 'land_frac and lake_frac are adjusted such that &
+ their sum is 1 at points where inland=1; land_frac cutoff is',land_cutoff
stat = nf90_put_att(ncid, land_frac_id,'description',trim(string))
CALL nc_opchk(stat, "nf90_put_att: land_frac:description")
-
write(string,'(a)') 'slmsk = nint(land_frac)'
stat = nf90_put_att(ncid, slmsk_id,'description',trim(string))
CALL nc_opchk(stat, "nf90_put_att: slmsk:description")
@@ -870,44 +974,36 @@ SUBROUTINE write_reg_lakedata_to_orodata(cs_res, tile_x_dim, tile_y_dim, cs_lake
lake_frac(:) = cs_lakestat((tile_num-1)*tile_sz+1:tile_num*tile_sz)
lake_depth(:) = cs_lakedepth((tile_num-1)*tile_sz+1:tile_num*tile_sz)
-! add Caspian Sea and Aral Sea to lake_frac and lake_depth
- DO i = 1, tile_sz
- IF (land_frac(i) < 0.9 .AND. lake_frac(i) < 0.1) THEN
- IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
- geolon(i) > 45.0 .AND. geolon(i) <= 55.0) THEN
- lake_frac(i) = 1.-land_frac(i)
- lake_depth(i) = 211.0
- ENDIF
- IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
- geolon(i) > 57.0 .AND. geolon(i) <= 63.0) THEN
- lake_frac(i) = 1.-land_frac(i)
- lake_depth(i) = 10.0
- ENDIF
- ENDIF
- ENDDO
-
-! adjust land_frac and lake_frac, and make sure land_frac+lake_frac=1 at inland points
- DO i = 1, tile_sz
- if (lake_frac(i) >= lake_cutoff) then ! non-zero lake_frac dominates over land_frac
- land_frac(i) = max(0., min(1., 1.-lake_frac(i)))
- elseif (inland(i) == 1.) then ! land_frac dominates over lake_frac at inland points
- lake_frac(i) = max(0., min(1., 1.-land_frac(i)))
- end if
+! include Caspian Sea and Aral Sea if GLDB data set is used, and
+! exclude lakes in the coastal areas of Antarctica if MODIS data set is used
+ CALL include_exclude_lakes(lake_frac,land_frac,lake_depth,geolat,geolon,tile_num)
! epsil is "numerical" nonzero min for lake_frac/land_frac
! lake_cutoff/land_cutoff is practical min for lake_frac/land_frac
- if (min(lake_cutoff,land_cutoff) < epsil) then
+ IF (min(lake_cutoff,land_cutoff) < epsil) then
print *,'lake_cutoff/land_cutoff cannot be smaller than epsil, reset...'
lake_cutoff=max(epsil,lake_cutoff)
land_cutoff=max(epsil,land_cutoff)
- end if
+ ENDIF
- if (lake_frac(i)< lake_cutoff) lake_frac(i)=0.
- if (lake_frac(i)>1.-lake_cutoff) lake_frac(i)=1.
- if (inland(i) == 1.) land_frac(i) = 1.-lake_frac(i)
+! adjust land_frac and lake_frac, and make sure land_frac+lake_frac=1 at inland points
+ DO i = 1, tile_sz
if (land_frac(i)< land_cutoff) land_frac(i)=0.
if (land_frac(i)>1.-land_cutoff) land_frac(i)=1.
+ if (inland(i) /= 1.) then
+ lake_frac(i) = 0.
+ endif
+
+ if (lake_frac(i) < lake_cutoff) lake_frac(i)=0.
+ if (lake_frac(i) > 1.-epsil) lake_frac(i)=1.
+ ENDDO
+
+ DO i = 1, tile_sz
+ if (inland(i) == 1.) then
+ land_frac(i) = 1. - lake_frac(i)
+ end if
+
if (lake_frac(i) < lake_cutoff) then
lake_depth(i)=0.
elseif (lake_frac(i) >= lake_cutoff .and. lake_depth(i)==0.) then
@@ -937,12 +1033,76 @@ SUBROUTINE write_reg_lakedata_to_orodata(cs_res, tile_x_dim, tile_y_dim, cs_lake
stat = nf90_close(ncid)
CALL nc_opchk(stat, "nf90_close")
- DEALLOCATE(lake_frac, lake_depth)
- DEALLOCATE(geolon, geolat)
- DEALLOCATE(land_frac, slmsk)
-
END SUBROUTINE write_reg_lakedata_to_orodata
+!> Include Caspian Sea and Aral Sea if GLDB dataset is used, and
+!! exclude lakes in the coastal areas of Antarctica if MODIS dataset is used.
+!!
+!! @param[inout] lake_frac lake fraction array of the given tile.
+!! @param[inout] lake_depth lake depth array of the given tile.
+!! @param[in] land_frac land fraction array of the given tile.
+!! @param[in] geolat latitude array of the given tile.
+!! @param[in] geolon longitude array of the given tile.
+!! @param[in] tile_num tile number of the given tile.
+!! @author Ning Wang
+SUBROUTINE include_exclude_lakes(lake_frac,land_frac,lake_depth,geolat,geolon,tile_num)
+ REAL, INTENT(INOUT) :: lake_frac(cs_res*cs_res), lake_depth(cs_res*cs_res)
+ REAL, INTENT(IN) :: land_frac(cs_res*cs_res)
+ REAL, INTENT(IN) :: geolat(cs_res*cs_res), geolon(cs_res*cs_res)
+ INTEGER, INTENT(IN) :: tile_num
+
+ INTEGER :: tile_sz
+
+ tile_sz = cs_res*cs_res
+! add Caspian Sea and Aral Sea
+ IF (tile_num == 2 .OR. tile_num == 3 .OR. tile_num == 7) THEN
+ IF (lakedepth_srce == "GLDBV3" .OR. lakedepth_srce == "GLDBV2") THEN
+ IF (lakestatus_srce == "GLDBV3" .OR. lakestatus_srce == "GLDBV2") THEN
+ DO i = 1, tile_sz
+ IF (land_frac(i) < 0.9 .AND. lake_frac(i) < 0.1) THEN
+ IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
+ geolon(i) > 45.0 .AND. geolon(i) <= 55.0) THEN
+ lake_frac(i) = 1.-land_frac(i)
+ lake_depth(i) = 211.0
+ ENDIF
+ IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
+ geolon(i) > 57.0 .AND. geolon(i) <= 63.0) THEN
+ lake_frac(i) = 1.-land_frac(i)
+ lake_depth(i) = 10.0
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ IF (lakestatus_srce == "MODISP" .OR. lakestatus_srce == "VIIRS") THEN
+ DO i = 1, tile_sz
+ IF (land_frac(i) < 0.9) THEN
+ IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
+ geolon(i) > 45.0 .AND. geolon(i) <= 55.0) THEN
+ lake_depth(i) = 211.0
+ ENDIF
+ IF (geolat(i) > 35.0 .AND. geolat(i) <= 50.0 .AND. &
+ geolon(i) > 57.0 .AND. geolon(i) <= 63.0) THEN
+ lake_depth(i) = 10.0
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDIF
+! remove lakes below 60 deg south
+ IF (tile_num == 6) THEN
+ IF (lakestatus_srce == "MODISP" .OR. lakestatus_srce == "VIIRS") THEN
+ DO i = 1, tile_sz
+ IF (geolat(i) < -60.0) THEN
+ lake_frac(i) = 0.0
+ lake_depth(i) = 0.0
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+END SUBROUTINE include_exclude_lakes
+
!> Check NetCDF error code
!!
!! @param[in] stat Error code.
@@ -958,7 +1118,7 @@ SUBROUTINE nc_opchk(stat,opname)
IF (stat .NE.0) THEN
msg = trim(opname) // ' Error, status code and message:'
PRINT*,trim(msg), stat, nf90_strerror(stat)
- STOP
+ STOP -1
END IF
END SUBROUTINE nc_opchk
diff --git a/ush/fv3gfs_driver_grid.sh b/ush/fv3gfs_driver_grid.sh
index 9347749f0..81ac33551 100755
--- a/ush/fv3gfs_driver_grid.sh
+++ b/ush/fv3gfs_driver_grid.sh
@@ -47,9 +47,9 @@ export res=${res:-96} # resolution of tile: 48, 96, 128, 192, 384, 768
export gtype=${gtype:-uniform} # grid type: uniform, stretch, nest, regional_gfdl,
# or regional_esg
-export add_lake=${add_lake:-false} # add lake fraction and depth. uniform only.
-export lake_cutoff=${lake_cutoff:-0.20} # lake fractions less than lake_cutoff
- # are ignored.
+export add_lake=${add_lake:-false} # add lake fraction and depth. uniform only.
+export lake_cutoff=${lake_cutoff:-0.50} # return 0 if lake_frac < lake_cutoff & add_lake=T
+export binary_lake=${binary_lake:-1} # return 1 if lake_frac >= lake_cutoff & add_lake=T
export make_gsl_orog=${make_gsl_orog:-false} # when true, create GSL drag suite orog files.
diff --git a/ush/fv3gfs_make_lake.sh b/ush/fv3gfs_make_lake.sh
index cfb12aba6..f8f293587 100755
--- a/ush/fv3gfs_make_lake.sh
+++ b/ush/fv3gfs_make_lake.sh
@@ -13,6 +13,27 @@ if [ $gtype != uniform ] && [ $gtype != regional_gfdl ]; then
echo "lakefrac has only been implemented for 'uniform' and 'regional_gfdl'."
exit 0
fi
+echo "lake_data_srce = $lake_data_srce"
+if [ $lake_data_srce == MODISP_GLDBV3 ]; then
+ lakestatusrc="MODISP"
+ lakedepthsrc="GLDBV3"
+fi
+if [ $lake_data_srce == MODISP_GLOBATHY ]; then
+ lakestatusrc="MODISP"
+ lakedepthsrc="GLOBATHY"
+fi
+if [ $lake_data_srce == VIIRS_GLDBV3 ]; then
+ lakestatusrc="VIIRS"
+ lakedepthsrc="GLDBV3"
+fi
+if [ $lake_data_srce == VIIRS_GLOBATHY ]; then
+ lakestatusrc="VIIRS"
+ lakedepthsrc="GLOBATHY"
+fi
+if [ $lake_data_srce == GLDBV3 ]; then
+ lakestatusrc="GLDBV3"
+ lakedepthsrc="GLDBV3"
+fi
exe_add_lake=$exec_dir/lakefrac
if [ ! -s $exe_add_lake ]; then
@@ -54,7 +75,7 @@ if [ $gtype == uniform ]; then
done
fi
-if [ $gtype == regional_gfdl ]; then
+if [ $gtype == regional_gfdl ] || [ $gtype == regional_esg ]; then
tile_beg=7
tile_end=7
tile=7
@@ -66,7 +87,7 @@ fi
# create inland mask and save it to the orography files
-cutoff=0.99
+cutoff=0.75
rd=7
if [ $gtype == uniform ]; then
$APRUN $exe_inland $res $cutoff $rd g
@@ -74,6 +95,9 @@ fi
if [ $gtype == regional_gfdl ]; then
$APRUN $exe_inland $res $cutoff $rd r
fi
+if [ $gtype == regional_esg ]; then
+ $APRUN $exe_inland $res $cutoff $rd r
+fi
err=$?
if [ $err != 0 ]; then
set +x
@@ -81,12 +105,12 @@ if [ $err != 0 ]; then
exit $err
fi
-# create lake data for FV3 grid and save it to the orography files
+# create fractional lake data for FV3 grid and save it to the orography files
tile=$tile_beg
while [ $tile -le $tile_end ]; do
outfile=oro.C${res}.tile${tile}.nc
- $APRUN $exe_add_lake ${tile} ${res} ${indir} ${lake_cutoff}
+ $APRUN $exe_add_lake ${tile} ${res} ${indir} ${lakestatusrc} ${lakedepthsrc} ${lake_cutoff} ${binary_lake}
err=$?
if [ $err != 0 ]; then
set +x