Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamical lakes and new lake cover map #1073

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b2fc572
added dynlakeFileMod to account for lake area changes
Ivanderkelen Feb 20, 2019
c7566b2
Add computation of lake heat itself in ComputeHeatMod and pass it to …
Feb 22, 2019
8862554
Make lake heat output variable of LakeTemperatureMod.F90 and print is…
Mar 1, 2019
939fa4d
Made handle do_transient_lakes to use in namelist for enabling the dy…
Mar 8, 2019
be2b7dd
TEMP: added hydrolakes lake pct dataset on temp location
Ivanderkelen Jun 6, 2019
8e45295
Added PCT Lake to landuse.timeseries output, based on MODIS data
Ivanderkelen Jun 17, 2019
60c0aaf
dynamical pct lake read from own files (new namelist variable created…
Ivanderkelen Jun 20, 2019
6bb40cd
Upload manually adjusted namelist and .txt file dynamical lake pct
Ivanderkelen Jul 16, 2019
d7296c8
Added lake landunit initialisation for gridcells which will grow lake
Ivanderkelen Aug 1, 2019
66a8ba6
uploaded mksurfdat namelist files
Ivanderkelen Aug 1, 2019
dc6c885
update gitignore
Ivanderkelen Aug 1, 2019
2ea9eee
Add lake water and heat content to gridcell total water and heat comp…
Ivanderkelen Sep 16, 2019
b807404
Set initial subgrid weights for aspects that are read from file: add …
Ivanderkelen Sep 19, 2019
bada0c9
Fix arguments to account for total lake heat and water content
Ivanderkelen Sep 19, 2019
c55c2a5
Add baseline approach for lake dynamical land units
Ivanderkelen Sep 19, 2019
dbefee7
Removed heat_liquid and cv_liquid calculation for lakes --still to ad…
Ivanderkelen Sep 20, 2019
e444c81
Added description for AccumulateLakeHeat
Ivanderkelen Sep 20, 2019
f2b3363
Updated comments to apply to lakes and removed redundant file
Ivanderkelen Oct 3, 2019
bf7c23c
Updated comments in AccumulateHeatLake and some little fixes
Ivanderkelen Oct 3, 2019
c1b2dd9
Finetune option to run without dynamical lakes
Ivanderkelen Mar 16, 2020
57ee483
updated raw input files of dynamical lake area to span period 1850-2015
Ivanderkelen Mar 16, 2020
bcbff4a
Clean up namelist in mksurfdat tool
Ivanderkelen Mar 16, 2020
94fa892
Update argument lists of subroutines
Ivanderkelen Jul 8, 2020
4b7c985
Add line break to fix compilation error
billsacks Jul 17, 2020
5e2e25a
Fix data type of haslake variable
billsacks Jul 22, 2020
61cba6b
Add new runtime consistency checks for do_transient_lakes
billsacks Aug 12, 2020
485571e
do_transient_lakes in namelist: set default value and do error checks
billsacks Aug 12, 2020
05f1d9e
Minor cleanup
billsacks Aug 12, 2020
565c42f
Remove unnecessary comment
billsacks Aug 13, 2020
29af7cf
Get do_transient_lakes default from namelist_defaults
billsacks Aug 13, 2020
7fb5ce9
Revert src and bld to dev101 versions
billsacks Aug 17, 2020
2abb68c
Merge pull request #2 from billsacks/dynlakes_master
Ivanderkelen Aug 24, 2020
55a0fb4
Move adjustment of lakepct if >100% from normalizencheck_landuse to t…
Ivanderkelen Aug 28, 2020
60fce7f
Remove extra whitespace in namelist file
Ivanderkelen Aug 28, 2020
5499c66
Revert "Remove extra whitespace in namelist file"
Ivanderkelen Aug 28, 2020
0a38f6d
Remove extra whitespace in namelist
Ivanderkelen Aug 28, 2020
75c482e
Merge remote-tracking branch 'escomp/master' into dynlakes_master
Ivanderkelen Aug 30, 2020
d8b85af
Move to normalizencheck_landuse
Ivanderkelen Aug 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

332 changes: 0 additions & 332 deletions tools/mksurfdata_map/landuse_timeseries_hist_78pfts_simyr1850-2015.txt

This file was deleted.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tools/mksurfdata_map/mksurfdata_map.namelist
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
map_fch4 = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_360x720_cruncep_to_10x15_nomask_aave_da_c130326.nc'
mksrf_fsoitex = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_soitex.10level.c010119.nc'
mksrf_forganic = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_organic_10level_5x5min_ISRIC-WISE-NCSCD_nlev7_c120830.nc'
mksrf_flakwat = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_LakePnDepth_3x3min_simyr2004_csplk_c151015.nc'
mksrf_flakwat = '/glade/u/home/ivanderk/clm5.0/own_inputfile/mksurf_LakePnDepth_3x3min_simyr2009_csplk_c190603.nc'
mksrf_fwetlnd = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_lanwat.050425.nc'
mksrf_fmax = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_fmax_3x3min_USGS_c120911.nc'
mksrf_fglacier = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_glacier_3x3min_simyr2000.c120926.nc'
Expand Down
3 changes: 3 additions & 0 deletions tools/mksurfdata_map/src/mkfileMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,9 @@ subroutine mkfile(domain, fname, harvdata, dynlanduse)
long_name=mkharvest_longname(ind2D(j)), units=mkharvest_units(ind2D(j)) )
end do
deallocate(ind1D, ind2D)

call ncd_def_spatial_var(ncid=ncid, varname='PCT_LAKE', xtype=xtype, &
lev1name="time", long_name='percent lake', units='unitless')

end if ! .not. dynlanduse

Expand Down
183 changes: 109 additions & 74 deletions tools/mksurfdata_map/src/mksurfdat.F90
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ program mksurfdat
integer :: k,m,n ! indices
integer :: ni,nj,ns_o ! indices
integer :: ier ! error status
integer :: ndiag,nfdyn ! unit numbers
integer :: ndiag,nfdyn,nfdynlak ! unit numbers
integer :: ncid ! netCDF id
integer :: omode ! netCDF output mode
integer :: varid ! netCDF variable id
Expand All @@ -80,6 +80,7 @@ program mksurfdat
character(len=256) :: fdyndat ! dynamic landuse data file name
character(len=256) :: fname ! generic filename
character(len=256) :: fhrvname ! generic harvest filename
character(len=256) :: flakname ! generic lake filename
character(len=256) :: string ! string read in
integer :: t1 ! timer
real(r8),parameter :: p5 = 0.5_r8 ! constant
Expand Down Expand Up @@ -134,7 +135,10 @@ program mksurfdat
real(r8), allocatable :: vic_dsmax(:) ! VIC Dsmax parameter (mm/day)
real(r8), allocatable :: vic_ds(:) ! VIC Ds parameter (unitless)
real(r8), allocatable :: lakedepth(:) ! lake depth (m)

real(r8), allocatable :: pctlak_orig(:) ! percent lake of gridcell before dynamic land use adjustments
real(r8), allocatable :: pctwet_orig(:) ! percent wetland of gridcell before dynamic land use adjustments
real(r8), allocatable :: pcturb_orig(:) ! percent urban of gridcell before dynamic land use adjustments
real(r8), allocatable :: pctgla_orig(:) ! percent glacier of gridcell before dynamic land use adjustments
real(r8) :: std_elev = -999.99_r8 ! Standard deviation of elevation (m) to use for entire grid

integer, allocatable :: harvind1D(:) ! Indices of 1D harvest fields
Expand All @@ -150,11 +154,11 @@ program mksurfdat
type(harvestDataType) :: harvdata

namelist /clmexp/ &
mksrf_fgrid, &
mksrf_gridtype, &
mksrf_fgrid, &
mksrf_gridtype, &
mksrf_fvegtyp, &
mksrf_fhrvtyp, &
mksrf_fsoitex, &
mksrf_fsoitex, &
mksrf_forganic, &
mksrf_fsoicol, &
mksrf_fvocef, &
Expand All @@ -167,6 +171,7 @@ program mksurfdat
mksrf_furban, &
mksrf_flai, &
mksrf_fdynuse, &
mksrf_fdynlak, &
mksrf_fgdp, &
mksrf_fpeat, &
mksrf_fsoildepth, &
Expand Down Expand Up @@ -278,6 +283,7 @@ program mksurfdat
! Optionally specify setting for:
! ======================================
! mksrf_fdynuse ----- ASCII text file that lists each year of pft files to use
! mksrf_fdynlak ----- ASCII text file that list each year of dynlake files to use
! mksrf_gridtype ---- Type of grid (default is 'global')
! outnc_double ------ If output should be in double precision
! outnc_large_files - If output should be in NetCDF large file format
Expand Down Expand Up @@ -459,7 +465,11 @@ program mksurfdat
vic_dsmax(ns_o) , &
vic_ds(ns_o) , &
lakedepth(ns_o) , &
glacier_region(ns_o) )
glacier_region(ns_o) , &
pctlak_orig(ns_o) , &
pctwet_orig(ns_o) , &
pcturb_orig(ns_o) , &
pctgla_orig(ns_o) )
landfrac_pft(:) = spval
pctlnd_pft(:) = spval
pftdata_mask(:) = -999
Expand Down Expand Up @@ -709,62 +719,12 @@ program mksurfdat

call change_landuse( ldomain, dynpft=.false. )

do n = 1,ns_o

! Truncate all percentage fields on output grid. This is needed to
! insure that wt is zero (not a very small number such as
! 1e-16) where it really should be zero

do k = 1,nlevsoi
pctsand(n,k) = float(nint(pctsand(n,k)))
pctclay(n,k) = float(nint(pctclay(n,k)))
end do
pctlak(n) = float(nint(pctlak(n)))
pctwet(n) = float(nint(pctwet(n)))
pctgla(n) = float(nint(pctgla(n)))

! Assume wetland, glacier and/or lake when dataset landmask implies ocean
! (assume medium soil color (15) and loamy texture).
! Also set pftdata_mask here

if (pctlnd_pft(n) < 1.e-6_r8) then
pftdata_mask(n) = 0
soicol(n) = 15
if (pctgla(n) < 1.e-6_r8) then
pctwet(n) = 100._r8 - pctlak(n)
pctgla(n) = 0._r8
else
pctwet(n) = max(100._r8 - pctgla(n) - pctlak(n), 0.0_r8)
end if
pcturb(n) = 0._r8
call pctnatpft(n)%set_pct_l2g(0._r8)
call pctcft(n)%set_pct_l2g(0._r8)
pctsand(n,:) = 43._r8
pctclay(n,:) = 18._r8
organic(n,:) = 0._r8
else
pftdata_mask(n) = 1
end if

! Make sure sum of land cover types does not exceed 100. If it does,
! subtract excess from most dominant land cover.

suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n)
if (suma > 250._r4) then
write (6,*) subname, ' error: sum of pctlak, pctwet,', &
'pcturb and pctgla is greater than 250%'
write (6,*)'n,pctlak,pctwet,pcturb,pctgla= ', &
n,pctlak(n),pctwet(n),pcturb(n),pctgla(n)
call abort()
else if (suma > 100._r4) then
pctlak(n) = pctlak(n) * 100._r8/suma
pctwet(n) = pctwet(n) * 100._r8/suma
pcturb(n) = pcturb(n) * 100._r8/suma
pctgla(n) = pctgla(n) * 100._r8/suma
end if

end do

! Save special land unit areas of surface dataset
pctlak_orig(:) = pctlak(:)
pctwet_orig(:) = pctwet(:)
pcturb_orig(:) = pcturb(:)
pctgla_orig(:) = pctgla(:)

call normalizencheck_landuse(ldomain)

! Write out sum of PFT's
Expand Down Expand Up @@ -1062,14 +1022,11 @@ program mksurfdat

! Deallocate arrays NOT needed for dynamic-pft section of code

deallocate ( organic )
deallocate ( ef1_btr, ef1_fet, ef1_fdt, ef1_shr, ef1_grs, ef1_crp )
deallocate ( pctglcmec, topoglcmec)
if ( outnc_3dglc ) deallocate ( pctglc_gic, pctglc_icesheet)
deallocate ( elevclass )
deallocate ( fmax )
deallocate ( pctsand, pctclay )
deallocate ( soicol )
deallocate ( gdp, fpeat, agfirepkmon )
deallocate ( soildepth )
deallocate ( topo_stddev, slope )
Expand Down Expand Up @@ -1118,7 +1075,7 @@ program mksurfdat
call check_ret(nf_put_var_int(ncid, varid, pftdata_mask), subname)

call check_ret(nf_inq_varid(ncid, 'LANDFRAC_PFT', varid), subname)
call check_ret(nf_put_var_double(ncid, varid, landfrac_pft), subname)
call check_ret(nf_put_var_double(ncid, varid, landfrac_pft), subname)

! Synchronize the disk copy of a netCDF dataset with in-memory buffers

Expand All @@ -1127,6 +1084,9 @@ program mksurfdat
! Read in each dynamic pft landuse dataset

nfdyn = getavu(); call opnfil (mksrf_fdynuse, nfdyn, 'f')

! Read in dynamic lake dataset
nfdynlak = getavu(); call opnfil (mksrf_fdynlak, nfdynlak, 'f')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the dynamic lake file isn't provided? We need a way for it to abort. We also should decide on if lakes should always be dynamic for transient conditions, or if we you pick and choose? It would probably be best to always have it on the datasets, but then decide in CTSM whether to activate it or not. We have something similar for harvest.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mention in a comment below, I'm thinking we should put the lake file names on the same file as the pft & harvest file names. @ekluzek does that make sense to you, or do you see a reason to keep them on separate files? My assumption (like yours, @ekluzek ) is that we'll always put the transient lake data on the landuse timeseries files, but this will only be activated if the flag do_transient_lakes is true. By default I think this will be false for now, while this is still an experimental setting.


pctnatpft_max = pctnatpft
pctcft_max = pctcft
Expand Down Expand Up @@ -1159,16 +1119,26 @@ program mksurfdat
call abort()
end if
end if


! Read input lake pct data
read(nfdynlak, '(A195,1x,I4)', iostat=ier) string, year
Copy link
Collaborator

@ekluzek ekluzek Aug 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Read this in as year2, and then compare to year from above and abort if they aren't the same. This is similar to the abort for harvest above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I actually wonder if we want somewhat more rework than just what @ekluzek suggested above. Specifically: the code as written assumes separate files for the year-by-year lake data vs. the year-by-year pft and harvest data. Would it make sense to put these all on the same file? (I feel like the most straightforward thing would be to change the format of this file slightly so that there is one line per year, with format: 'year pftfilename harvestfilename lakefilename'. However, that's more a comment for @ekluzek because I don't expect you (@Ivanderkelen) to do that rework unless you're actively excited about doing it. And I'm fine with sticking with the current format of having separate lines for each file, with multiple lines per year, for now.)

  • We'll also need changes in mksurfdata.pl to add the names of the dynamic lake files to the year-by-year text file(s).

How exactly we handle this will depend on whether we're going to put transient lake areas on all of our landuse timeseries files moving forward. @ekluzek do you feel we should just go ahead and do that, assuming we have the data? I'm thinking yes, but do you have thoughts on it?

if (ier /= 0) exit

flakname = string
write(6,*)'input lake dynamic dataset for year ', year, ' is : ', trim(flakname)


ntim = ntim + 1

! Create pctpft data at model resolution

call mkpft(ldomain, mapfname=map_fpft, fpft=fname, &
ndiag=ndiag, pctlnd_o=pctlnd_pft_dyn, pctnatpft_o=pctnatpft, pctcft_o=pctcft )

! Create harvesting data at model resolution

call mkharvest( ldomain, mapfname=map_fharvest, datfname=fhrvname, &
call mkharvest(ldomain, mapfname=map_fharvest, datfname=fhrvname, &
ndiag=ndiag, harvdata=harvdata )

! Consistency check on input land fraction
Expand All @@ -1186,9 +1156,17 @@ program mksurfdat
call abort()
end if
end do


call change_landuse(ldomain, dynpft=.true.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

! Create pctlak data at model resolution (use original mapping file from lake data)
call mklakwat (ldomain, mapfname=map_flakwat, datfname=flakname, &
ndiag=ndiag, zero_out=all_urban.or.all_veg, lake_o=pctlak)

! For landunits NOT read each year: reset to their pre-adjustment values in preparation for redoing landunit area normalization
pctwet(:) = pctwet_orig(:)
pcturb(:) = pcturb_orig(:)
pctgla(:) = pctgla_orig(:)

call normalizencheck_landuse(ldomain)

call update_max_array(pctnatpft_max,pctnatpft)
Expand All @@ -1207,6 +1185,9 @@ program mksurfdat
call ncd_put_time_slice(ncid, varid, ntim, get_pct_p2l_array(pctcft))
end if

call check_ret(nf_inq_varid(ncid, 'PCT_LAKE', varid), subname)
call ncd_put_time_slice(ncid, varid, ntim, pctlak)

call harvdata%getFieldsIdx( harvind1D, harvind2D )
do k = 1, harvdata%num1Dfields()
call check_ret(nf_inq_varid(ncid, trim(mkharvest_fieldname(harvind1D(k),constant=.false.)), varid), subname)
Expand Down Expand Up @@ -1370,13 +1351,66 @@ subroutine normalizencheck_landuse(ldomain)
character(len=32) :: subname = 'normalizencheck_landuse' ! subroutine name
!-----------------------------------------------------------------------

! ------------------------------------------------------------------------
! Normalize vegetated area so that vegetated + special area is 100%
! ------------------------------------------------------------------------
! -------------------------------------------------------------------------------
! Normalize vegetated and lake area so that vegetated + other special area is 100%
! -------------------------------------------------------------------------------

ns_o = ldomain%ns
do n = 1,ns_o

! Truncate all percentage fields on output grid. This is needed to
! insure that wt is zero (not a very small number such as
! 1e-16) where it really should be zero

do k = 1,nlevsoi
pctsand(n,k) = float(nint(pctsand(n,k)))
pctclay(n,k) = float(nint(pctclay(n,k)))
end do
pctlak(n) = float(nint(pctlak(n)))
pctwet(n) = float(nint(pctwet(n)))
pctgla(n) = float(nint(pctgla(n)))

! Assume wetland, glacier and/or lake when dataset landmask implies ocean
! (assume medium soil color (15) and loamy texture).
! Also set pftdata_mask here

if (pctlnd_pft(n) < 1.e-6_r8) then
pftdata_mask(n) = 0
soicol(n) = 15
if (pctgla(n) < 1.e-6_r8) then
pctwet(n) = 100._r8 - pctlak(n)
pctgla(n) = 0._r8
else
pctwet(n) = max(100._r8 - pctgla(n) - pctlak(n), 0.0_r8)
end if
pcturb(n) = 0._r8
call pctnatpft(n)%set_pct_l2g(0._r8)
call pctcft(n)%set_pct_l2g(0._r8)
pctsand(n,:) = 43._r8
pctclay(n,:) = 18._r8
organic(n,:) = 0._r8
else
pftdata_mask(n) = 1
end if

! Make sure sum of land cover types does not exceed 100. If it does,
! subtract excess from most dominant land cover.

suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n)
if (suma > 250._r4) then
write (6,*) subname, ' error: sum of pctlak, pctwet,', &
'pcturb and pctgla is greater than 250%'
write (6,*)'n,pctlak,pctwet,pcturb,pctgla= ', &
n,pctlak(n),pctwet(n),pcturb(n),pctgla(n)
call abort()
else if (suma > 100._r4) then
pctlak(n) = pctlak(n) * 100._r8/suma
pctwet(n) = pctwet(n) * 100._r8/suma
pcturb(n) = pcturb(n) * 100._r8/suma
pctgla(n) = pctgla(n) * 100._r8/suma
end if


! Check preconditions
if ( pctlak(n) < 0.0_r8 )then
write(6,*) subname, ' ERROR: pctlak is negative!'
Expand All @@ -1398,7 +1432,7 @@ subroutine normalizencheck_landuse(ldomain)
write(6,*) 'n, pctgla = ', n, pctgla(n)
call abort()
end if

suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n)
if (suma > (100._r8 + tol_loose)) then
write(6,*) subname, ' ERROR: pctlak + pctwet + pcturb + pctgla must be'
Expand All @@ -1408,6 +1442,7 @@ subroutine normalizencheck_landuse(ldomain)
call abort()
end if


! First normalize vegetated (natural veg + crop) cover so that the total of
! (vegetated + (special excluding urban)) is 100%. We'll deal with urban later.
!
Expand All @@ -1416,7 +1451,7 @@ subroutine normalizencheck_landuse(ldomain)
! will work properly regardless of the initial area of natural veg + crop (even if
! that initial area is 0%).

suma = pctlak(n)+pctwet(n)+pctgla(n)
suma = pctlak(n) + pctwet(n)+ pctgla(n)
new_total_veg_pct = 100._r8 - suma
! correct for rounding error:
new_total_veg_pct = max(new_total_veg_pct, 0._r8)
Expand Down
1 change: 1 addition & 0 deletions tools/mksurfdata_map/src/mkvarctl.F90
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ module mkvarctl
character(len=256), public :: mksrf_fmax = ' ' ! fmax data file name
character(len=256), public :: mksrf_flai = ' ' ! lai data filename
character(len=256), public :: mksrf_fdynuse = ' ' ! ascii file containing names of dynamic land use files
character(len=256), public :: mksrf_fdynlak = ' ' ! ascii file containing names of dynamic lake files
character(len=256), public :: mksrf_fvocef = ' ' ! VOC Emission Factor data file name
character(len=256), public :: mksrf_ftopostats = ' ' ! topography statistics data file name
character(len=256), public :: mksrf_fvic = ' ' ! VIC parameters data file name
Expand Down