From 63b2c81f2a1962ae37aed0d9f8d444e2d3a358a4 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 16 Aug 2019 15:19:13 -0600 Subject: [PATCH 01/17] Changes from @olyson to fix #780 --- src/biogeochem/CNFireLi2016Mod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/biogeochem/CNFireLi2016Mod.F90 b/src/biogeochem/CNFireLi2016Mod.F90 index 328fa95c06..aafaaf41bc 100644 --- a/src/biogeochem/CNFireLi2016Mod.F90 +++ b/src/biogeochem/CNFireLi2016Mod.F90 @@ -607,7 +607,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ end if lh = pot_hmn_ign_counts_alpha*6.8_r8*hdmlf**(0.43_r8)/30._r8/24._r8 fs = 1._r8-(0.01_r8+0.98_r8*exp(-0.025_r8*hdmlf)) - ig = (lh+this%forc_lnfm(g)/(5.16_r8+2.16_r8*cos(3*min(60._r8,abs(grc%latdeg(g)))))*0.22_r8) & + ig = (lh+this%forc_lnfm(g)/(5.16_r8+2.16_r8*cos(SHR_CONST_PI/180._r8*3*min(60._r8,abs(grc%latdeg(g)))))*0.22_r8) & *(1._r8-fs)*(1._r8-cropf_col(c)) nfire(c) = ig/secsphr*fb*fire_m*lgdp_col(c) !fire counts/km2/sec Lb_lf = 1._r8+10._r8*(1._r8-EXP(-0.06_r8*forc_wind(g))) From 3e5856aabf0e869d88d573d067ec9e1bbf32b11d Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sun, 25 Aug 2019 18:54:19 -0600 Subject: [PATCH 02/17] Allow users to specify snow layer structure in namelist Instead of hardcoding, we now make dzmin(1) = dzmin_1 dzmax_l(1) = dzmax_l dzmax_u(1) = dzmax_u where the right-hand-side variables get namelist-defined values and the model calculates dzmin and dzmax_* for the remaining snow layers. The calculation is based on formulas written out in a file titled "A firn model for CLM" that has been linked to #729. --- src/biogeophys/SnowHydrologyMod.F90 | 68 ++++++++++++++++++++--------- src/main/clm_varcon.F90 | 8 +++- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index 3dd555ccfb..8c53dd81e6 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -24,6 +24,7 @@ module SnowHydrologyMod use clm_varpar , only : nlevsno, nlevsoi, nlevgrnd use clm_varctl , only : iulog, use_subgrid_fluxes use clm_varcon , only : namec, h2osno_max, hfus, denice, rpi, spval, tfrz + use clm_varcon, only: dzmin, dzmax_l, dzmax_u use atm2lndType , only : atm2lnd_type use AerosolMod , only : aerosol_type use TemperatureType , only : temperature_type @@ -100,20 +101,6 @@ module SnowHydrologyMod integer, parameter, public :: LoTmpDnsSlater2017 = 2 ! For temperature below -15C use equation from Slater 2017 integer, parameter, public :: LoTmpDnsTruncatedAnderson1976 = 1 ! Truncate low temp. snow density from the Anderson-1976 version at -15C - ! Definition of snow pack vertical structure - ! Hardcoded maximum of 12 snowlayers, this is checked elsewhere (controlMod.F90) - ! The bottom layer has no limit on thickness, hence the last element of the dzmax_* - ! arrays is 'huge'. - real(r8), parameter :: dzmin(12) = & ! minimum of top snow layer - (/ 0.010_r8, 0.015_r8, 0.025_r8, 0.055_r8, 0.115_r8, 0.235_r8, & - 0.475_r8, 0.955_r8, 1.915_r8, 3.835_r8, 7.675_r8, 15.355_r8 /) - real(r8), parameter :: dzmax_l(12) = & ! maximum thickness of layer when no layers beneath - (/ 0.03_r8, 0.07_r8, 0.18_r8, 0.41_r8, 0.88_r8, 1.83_r8, & - 3.74_r8, 7.57_r8, 15.24_r8, 30.59_r8, 61.3_r8, huge(1._r8) /) - real(r8), parameter :: dzmax_u(12) = & ! maximum thickness of layer when layers beneath - (/ 0.02_r8, 0.05_r8, 0.11_r8, 0.23_r8, 0.47_r8, 0.95_r8, & - 1.91_r8, 3.83_r8, 7.67_r8, 15.35_r8, 30.71_r8, huge(1._r8) /) - ! ! !PRIVATE DATA MEMBERS: @@ -123,6 +110,7 @@ module SnowHydrologyMod ! If true, the density of new snow depends on wind speed, and there is also ! wind-dependent snow compaction logical :: wind_dependent_snow_density ! If snow density depends on wind or not + real(r8) :: dzmin_1, dzmax_l_1, dzmax_u_1 ! namelist-defined top snow layer information integer :: overburden_compaction_method = -1 integer :: new_snow_density = LoTmpDnsSlater2017 ! Snow density type real(r8) :: upplim_destruct_metamorph = 100.0_r8 ! Upper Limit on Destructive Metamorphism Compaction [kg/m3] @@ -187,11 +175,15 @@ subroutine SnowHydrology_readnl( NLFilename) wind_dependent_snow_density, snow_overburden_compaction_method, & lotmp_snowdensity_method, upplim_destruct_metamorph, & overburden_compress_Tfactor, min_wind_snowcompact, & - reset_snow, reset_snow_glc, reset_snow_glc_ela + reset_snow, reset_snow_glc, reset_snow_glc_ela, dzmin_1, dzmax_l_1, & + dzmax_u_1 ! Initialize options to default values, in case they are not specified in the namelist wind_dependent_snow_density = .false. snow_overburden_compaction_method = ' ' + dzmin_1 = 0.01_r8 + dzmax_l_1 = 0.03_r8 + dzmax_u_1 = 0.02_r8 if (masterproc) then unitn = getavu() @@ -218,6 +210,9 @@ subroutine SnowHydrology_readnl( NLFilename) call shr_mpi_bcast (reset_snow , mpicom) call shr_mpi_bcast (reset_snow_glc , mpicom) call shr_mpi_bcast (reset_snow_glc_ela , mpicom) + call shr_mpi_bcast (dzmin_1, mpicom) + call shr_mpi_bcast (dzmax_l_1, mpicom) + call shr_mpi_bcast (dzmax_u_1, mpicom) if (masterproc) then write(iulog,*) ' ' @@ -243,6 +238,19 @@ subroutine SnowHydrology_readnl( NLFilename) errMsg(sourcefile, __LINE__)) end if + if (dzmin_1 < 0.01_r8) then + call endrun(msg="ERROR dzmin_1 cannot be less than 0.01"// & + errMsg(sourcefile, __LINE__)) + end if + if (dzmax_l_1 < 0.03_r8) then + call endrun(msg="ERROR dzmax_l_1 cannot be less than 0.03"// & + errMsg(sourcefile, __LINE__)) + end if + if (dzmax_u_1 < 0.02_r8) then + call endrun(msg="ERROR dzmax_2_1 cannot be less than 0.02"// & + errMsg(sourcefile, __LINE__)) + end if + end subroutine SnowHydrology_readnl !----------------------------------------------------------------------- @@ -800,12 +808,12 @@ subroutine BuildFilter_SnowpackInitialized(bounds, num_c, filter_c, & ! maintain answers as before. snowpack_initialized(c) = ( & snl(c) == 0 .and. & - frac_sno_eff(c)*snow_depth(c) >= (0.01_r8 + lsadz) .and. & + frac_sno_eff(c)*snow_depth(c) >= (dzmin(1) + lsadz) .and. & qflx_snow_grnd(c) > 0.0_r8) else snowpack_initialized(c) = ( & snl(c) == 0 .and. & - frac_sno_eff(c)*snow_depth(c) >= 0.01_r8) + frac_sno_eff(c)*snow_depth(c) >= dzmin(1)) end if end do @@ -1496,7 +1504,7 @@ subroutine CombineSnowLayers(bounds, num_snowc, filter_snowc, & real(r8):: h2osno_total(bounds%begc:bounds%endc) ! total snow water (mm H2O) real(r8):: zwice(bounds%begc:bounds%endc) ! total ice mass in snow real(r8):: zwliq (bounds%begc:bounds%endc) ! total liquid water in snow - real(r8):: dzminloc(size(dzmin)) ! minimum of top snow layer (local) + real(r8):: dzminloc(nlevsno) ! minimum of top snow layer (local) real(r8):: dtime !land model time step (sec) !----------------------------------------------------------------------- @@ -1680,8 +1688,8 @@ subroutine CombineSnowLayers(bounds, num_snowc, filter_snowc, & c = filter_snowc(fc) l = col%landunit(c) if (snow_depth(c) > 0._r8) then - if ((ltype(l) == istdlak .and. snow_depth(c) < 0.01_r8 + lsadz ) .or. & - ((ltype(l) /= istdlak) .and. ((frac_sno_eff(c)*snow_depth(c) < 0.01_r8) & + if ((ltype(l) == istdlak .and. snow_depth(c) < dzmin(1) + lsadz ) .or. & + ((ltype(l) /= istdlak) .and. ((frac_sno_eff(c)*snow_depth(c) < dzmin(1)) & .or. (h2osno_total(c)/(frac_sno_eff(c)*snow_depth(c)) < 50._r8)))) then snl(c) = 0 @@ -2234,6 +2242,26 @@ subroutine InitSnowLayers (bounds, snow_depth) zi => col%zi & ! Output: [real(r8) (:,:) ] interface level below a "z" level (m) (-nlevsno+0:nlevgrnd) ) + ! These three variables determine the vertical structure of the snow pack: + ! dzmin: minimum of top snow layer + ! dzmax_l: maximum thickness of layer when no layers beneath + ! dzmax_u: maximum thickness of layer when layers beneath + dzmin(1) = dzmin_1 ! set in the namelist with default or user-defined value + dzmax_l(1) = dzmax_l_1 ! same comment + dzmax_u(1) = dzmax_u_1 ! same comment + do j = 2, nlevsno + dzmin(j) = dzmax_u(j-1) * 0.5_r8 + if (dzmin(j) <= dzmin(j-1)) then + dzmin(j) = (dzmin(j-1) + dzmax_u(j-1)) * 0.5_r8 + end if + dzmax_u(j) = 2._r8 * dzmax_u(j-1) + 0.01_r8 + if (j == 2) then + dzmax_l(j) = dzmax_u(j) + dzmax_l(j-1) - 0.01_r8 + else + dzmax_l(j) = dzmax_u(j) + dzmax_l(j-1) + end if + end do + loop_columns: do c = bounds%begc,bounds%endc l = col%landunit(c) diff --git a/src/main/clm_varcon.F90 b/src/main/clm_varcon.F90 index 8baa37f771..abf3787652 100644 --- a/src/main/clm_varcon.F90 +++ b/src/main/clm_varcon.F90 @@ -213,6 +213,9 @@ module clm_varcon ! The values for the following arrays are set in routine iniTimeConst !------------------------------------------------------------------ + real(r8), public, allocatable :: dzmin(:) !min of top snow layer + real(r8), public, allocatable :: dzmax_l(:) !max snow thickness of layer when no layers beneath + real(r8), public, allocatable :: dzmax_u(:) !max snow thickness of layer when layers beneath real(r8), public, allocatable :: zlak(:) !lake z (layers) real(r8), public, allocatable :: dzlak(:) !lake dz (thickness) real(r8), public, allocatable :: zsoi(:) !soil z (layers) @@ -266,7 +269,7 @@ subroutine clm_varcon_init( is_simple_buildtemp ) ! MUST be called after clm_varpar_init. ! ! !USES: - use clm_varpar, only: nlevgrnd, nlevlak, nlevdecomp_full, nlevsoifl, nlayer + use clm_varpar, only: nlevsno, nlevgrnd, nlevlak, nlevdecomp_full, nlevsoifl, nlayer ! ! !ARGUMENTS: implicit none @@ -276,6 +279,9 @@ subroutine clm_varcon_init( is_simple_buildtemp ) ! Created by E. Kluzek !------------------------------------------------------------------------------ + allocate( dzmin(1:nlevsno )) + allocate( dzmax_l(1:nlevsno )) + allocate( dzmax_u(1:nlevsno )) allocate( zlak(1:nlevlak )) allocate( dzlak(1:nlevlak )) allocate( zsoi(1:nlevgrnd )) From 7f67efc6bb6ba43ca6a421464d1122aec6d4373f Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 28 Aug 2019 16:33:05 -0600 Subject: [PATCH 03/17] Remove the commit to update the params file, which shouldn't be done on this branch --- bld/namelist_files/namelist_defaults_ctsm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 0b7359796e..e318284e43 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -365,7 +365,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -lnd/clm2/paramdata/clm5_params.c190729.nc +lnd/clm2/paramdata/clm5_params.c190529.nc lnd/clm2/paramdata/clm_params.c190518.nc From b2cf3a64fa46af5fd0870eed6aa8b0c7ef69ff76 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Mon, 2 Sep 2019 15:48:24 -0600 Subject: [PATCH 04/17] Changes for #787 for dwt_slash_flux --- src/biogeochem/CNVegCarbonFluxType.F90 | 63 +++++++++++++++------- src/biogeochem/dynConsBiogeochemMod.F90 | 70 ++++++++++++++----------- 2 files changed, 84 insertions(+), 49 deletions(-) diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index 9e6298db60..cef09fba8c 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -263,7 +263,8 @@ module CNVegCarbonFluxType real(r8), pointer :: dwt_conv_cflux_dribbled_grc (:) ! (gC/m2/s) dwt_conv_cflux_grc dribbled evenly throughout the year real(r8), pointer :: dwt_wood_productc_gain_patch (:) ! (gC/m2/s) addition to wood product pools from landcover change; although this is a patch-level flux, it is expressed per unit GRIDCELL area real(r8), pointer :: dwt_crop_productc_gain_patch (:) ! (gC/m2/s) addition to crop product pools from landcover change; although this is a patch-level flux, it is expressed per unit GRIDCELL area - real(r8), pointer :: dwt_slash_cflux_col (:) ! (gC/m2/s) conversion slash flux due to landcover change + real(r8), pointer :: dwt_slash_cflux_patch (:) ! (gC/m2/s) conversion slash flux due to landcover change + real(r8), pointer :: dwt_slash_cflux_grc (:) ! (gC/m2/s) dwt_slash_cflux_patch summed to the gridcell-level real(r8), pointer :: dwt_frootc_to_litr_met_c_col (:,:) ! (gC/m3/s) fine root to litter due to landcover change real(r8), pointer :: dwt_frootc_to_litr_cel_c_col (:,:) ! (gC/m3/s) fine root to litter due to landcover change real(r8), pointer :: dwt_frootc_to_litr_lig_c_col (:,:) ! (gC/m3/s) fine root to litter due to landcover change @@ -629,7 +630,8 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%harvest_c_to_litr_lig_c_col (begc:endc,1:nlevdecomp_full)); this%harvest_c_to_litr_lig_c_col (:,:)=nan allocate(this%harvest_c_to_cwdc_col (begc:endc,1:nlevdecomp_full)); this%harvest_c_to_cwdc_col (:,:)=nan - allocate(this%dwt_slash_cflux_col (begc:endc)) ; this%dwt_slash_cflux_col (:) =nan + allocate(this%dwt_slash_cflux_patch (begp:endp)) ; this%dwt_slash_cflux_patch (:) =nan + allocate(this%dwt_slash_cflux_grc (begg:endg)) ; this%dwt_slash_cflux_grc (:) =nan allocate(this%dwt_frootc_to_litr_met_c_col (begc:endc,1:nlevdecomp_full)); this%dwt_frootc_to_litr_met_c_col (:,:)=nan allocate(this%dwt_frootc_to_litr_cel_c_col (begc:endc,1:nlevdecomp_full)); this%dwt_frootc_to_litr_cel_c_col (:,:)=nan allocate(this%dwt_frootc_to_litr_lig_c_col (begc:endc,1:nlevdecomp_full)); this%dwt_frootc_to_litr_lig_c_col (:,:)=nan @@ -2876,10 +2878,19 @@ subroutine InitHistory(this, bounds, carbon_type) '(per-area-gridcell; only makes sense with dov2xy=.false.)', & ptr_patch=this%dwt_wood_productc_gain_patch, default='inactive') - this%dwt_slash_cflux_col(begc:endc) = spval - call hist_addfld1d (fname='DWT_SLASH_CFLUX', units='gC/m^2/s', & - avgflag='A', long_name='slash C flux to litter and CWD due to land use', & - ptr_col=this%dwt_slash_cflux_col) + this%dwt_slash_cflux_grc(begg:endg) = spval + call hist_addfld1d (fname='DWT_SLASH_CFLUX', units='gC/m^2/s', & + avgflag='A', & + long_name='slash C flux (to litter diagnostic only) (0 at all times except first timestep of year)', & + ptr_gcell=this%dwt_slash_cflux_grc) + + this%dwt_slash_cflux_patch(begp:endp) = spval + call hist_addfld1d (fname='DWT_SLASH_CFLUX_PATCH', units='gC/m^2/s', & + avgflag='A', & + long_name='patch-level slash C flux (to litter diagnostic only) ' // & + '(0 at all times except first timestep of year) ' // & + '(per-area-gridcell; only makes sense with dov2xy=.false.)', & + ptr_patch=this%dwt_slash_cflux_patch, default='inactive') this%dwt_frootc_to_litr_met_c_col(begc:endc,:) = spval call hist_addfld_decomp (fname='DWT_FROOTC_TO_LITR_MET_C', units='gC/m^2/s', type2d='levdcmp', & @@ -3050,10 +3061,19 @@ subroutine InitHistory(this, bounds, carbon_type) long_name='C13 conversion C flux (immediate loss to atm), dribbled throughout the year', & ptr_gcell=this%dwt_conv_cflux_dribbled_grc, default='inactive') - this%dwt_slash_cflux_col(begc:endc) = spval - call hist_addfld1d (fname='C13_DWT_SLASH_CFLUX', units='gC/m^2/s', & - avgflag='A', long_name='C13 slash C flux to litter and CWD due to land use', & - ptr_col=this%dwt_slash_cflux_col, default='inactive') + this%dwt_slash_cflux_grc(begg:endg) = spval + call hist_addfld1d (fname='C13_DWT_SLASH_CFLUX', units='gC13/m^2/s', & + avgflag='A', long_name='C13 slash C flux (to litter diagnostic only)' // & + '(0 at all times except first timestep of year)', & + ptr_gcell=this%dwt_slash_cflux_grc, default='inactive') + + this%dwt_slash_cflux_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_DWT_SLASH_CFLUX_PATCH', units='gC13/m^2/s', & + avgflag='A', & + long_name='patch-level C13 slash C flux (to litter diagnostic only) ' // & + '(0 at all times except first timestep of year) ' // & + '(per-area-gridcell; only makes sense with dov2xy=.false.)', & + ptr_patch=this%dwt_slash_cflux_patch, default='inactive') this%dwt_frootc_to_litr_met_c_col(begc:endc,:) = spval call hist_addfld_decomp (fname='C13_DWT_FROOTC_TO_LITR_MET_C', units='gC13/m^2/s', type2d='levdcmp', & @@ -3206,10 +3226,19 @@ subroutine InitHistory(this, bounds, carbon_type) long_name='C14 conversion C flux (immediate loss to atm), dribbled throughout the year', & ptr_gcell=this%dwt_conv_cflux_dribbled_grc, default='inactive') - this%dwt_slash_cflux_col(begc:endc) = spval - call hist_addfld1d (fname='C14_DWT_SLASH_CFLUX', units='gC/m^2/s', & - avgflag='A', long_name='C14 slash C flux to litter and CWD due to land use', & - ptr_col=this%dwt_slash_cflux_col, default='inactive') + this%dwt_slash_cflux_grc(begg:endg) = spval + call hist_addfld1d (fname='C14_DWT_SLASH_CFLUX', units='gC14/m^2/s', & + avgflag='A', long_name='C14 slash C flux (to litter diagnostic only)' // & + '(0 at all times except first timestep of year)', & + ptr_gcell=this%dwt_slash_cflux_grc, default='inactive') + + this%dwt_slash_cflux_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_DWT_SLASH_CFLUX_PATCH', units='gC14/m^2/s', & + avgflag='A', & + long_name='patch-level C14 slash C flux (to litter diagnostic only)' // & + '(0 at all times except first timestep of year) ' // & + '(per-area-gridcell; only makes sense with dov2xy=.false.)', & + ptr_patch=this%dwt_slash_cflux_patch, default='inactive') this%dwt_frootc_to_litr_met_c_col(begc:endc,:) = spval call hist_addfld_decomp (fname='C14_DWT_FROOTC_TO_LITR_MET_C', units='gC14/m^2/s', type2d='levdcmp', & @@ -3364,7 +3393,6 @@ subroutine InitCold(this, bounds) ! also initialize dynamic landcover fluxes so that they have ! real values on first timestep, prior to calling pftdyn_cnbal if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then - this%dwt_slash_cflux_col(c) = 0._r8 do j = 1, nlevdecomp_full this%dwt_frootc_to_litr_met_c_col(c,j) = 0._r8 this%dwt_frootc_to_litr_cel_c_col(c,j) = 0._r8 @@ -3965,10 +3993,7 @@ subroutine ZeroDwt( this, bounds ) this%dwt_seedc_to_leaf_grc(g) = 0._r8 this%dwt_seedc_to_deadstem_grc(g) = 0._r8 this%dwt_conv_cflux_grc(g) = 0._r8 - end do - - do c = bounds%begc,bounds%endc - this%dwt_slash_cflux_col(c) = 0._r8 + this%dwt_slash_cflux_grc(g) = 0._r8 end do do j = 1, nlevdecomp_full diff --git a/src/biogeochem/dynConsBiogeochemMod.F90 b/src/biogeochem/dynConsBiogeochemMod.F90 index eca6c376d8..32cd2b9577 100644 --- a/src/biogeochem/dynConsBiogeochemMod.F90 +++ b/src/biogeochem/dynConsBiogeochemMod.F90 @@ -587,36 +587,6 @@ subroutine dyn_cnbal_patch(bounds, & end do - ! calculate patch-to-column slash fluxes into litter and CWD pools - do p = bounds%begp, bounds%endp - c = patch%column(p) - - ! fine and coarse root to litter and CWD slash carbon fluxes - cnveg_carbonflux_inst%dwt_slash_cflux_col(c) = & - cnveg_carbonflux_inst%dwt_slash_cflux_col(c) + & - dwt_frootc_to_litter(p)/dt + & - dwt_livecrootc_to_litter(p)/dt + & - dwt_deadcrootc_to_litter(p)/dt - - if ( use_c13 ) then - c13_cnveg_carbonflux_inst%dwt_slash_cflux_col(c) = & - c13_cnveg_carbonflux_inst%dwt_slash_cflux_col(c) + & - dwt_frootc13_to_litter(p)/dt + & - dwt_livecrootc13_to_litter(p)/dt + & - dwt_deadcrootc13_to_litter(p)/dt - endif - - if ( use_c14 ) then - c14_cnveg_carbonflux_inst%dwt_slash_cflux_col(c) = & - c14_cnveg_carbonflux_inst%dwt_slash_cflux_col(c) + & - dwt_frootc14_to_litter(p)/dt + & - dwt_livecrootc14_to_litter(p)/dt + & - dwt_deadcrootc14_to_litter(p)/dt - endif - - end do - - ! calculate patch-to-column for fluxes into litter and CWD pools do j = 1, nlevdecomp do p = bounds%begp, bounds%endp @@ -787,6 +757,46 @@ subroutine dyn_cnbal_patch(bounds, & end do + ! calculate patch-to-gridcell slash fluxes into litter and CWD pools + ! Note that patch-level fluxes are stored per unit GRIDCELL area - thus, we don't + ! need to multiply by the patch's gridcell weight when translating patch-level + ! fluxes into gridcell-level fluxes. + + do p = bounds%begp, bounds%endp + g = patch%gridcell(p) + + ! fine and coarse root to litter and CWD slash carbon fluxes + cnveg_carbonflux_inst%dwt_slash_cflux_patch(p) = & + dwt_frootc_to_litter(p)/dt + & + dwt_livecrootc_to_litter(p)/dt + & + dwt_deadcrootc_to_litter(p)/dt + cnveg_carbonflux_inst%dwt_slash_cflux_grc(g) = & + cnveg_carbonflux_inst%dwt_slash_cflux_grc(g) + & + cnveg_carbonflux_inst%dwt_slash_cflux_patch(p) + + if ( use_c13 ) then + c13_cnveg_carbonflux_inst%dwt_slash_cflux_patch(p) = & + dwt_frootc13_to_litter(p)/dt + & + dwt_livecrootc13_to_litter(p)/dt + & + dwt_deadcrootc13_to_litter(p)/dt + c13_cnveg_carbonflux_inst%dwt_slash_cflux_grc(g) = & + c13_cnveg_carbonflux_inst%dwt_slash_cflux_grc(g) + & + c13_cnveg_carbonflux_inst%dwt_slash_cflux_patch(p) + endif + + if ( use_c14 ) then + c14_cnveg_carbonflux_inst%dwt_slash_cflux_patch(p) = & + dwt_frootc14_to_litter(p)/dt + & + dwt_livecrootc14_to_litter(p)/dt + & + dwt_deadcrootc14_to_litter(p)/dt + c14_cnveg_carbonflux_inst%dwt_slash_cflux_grc(g) = & + c14_cnveg_carbonflux_inst%dwt_slash_cflux_grc(g) + & + c14_cnveg_carbonflux_inst%dwt_slash_cflux_patch(p) + endif + + end do + + ! Deallocate patch-level flux arrays deallocate(dwt) deallocate(dwt_leafc_seed) From f293334ed8736e5d9fdd7f19d6fb291dd60ace00 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Mon, 2 Sep 2019 17:05:37 -0600 Subject: [PATCH 05/17] Make sure urbantv is set for clm4_5 #175 --- bld/namelist_files/namelist_defaults_ctsm.xml | 39 ++++++++----------- .../use_cases/1850-2100_rcp2.6_transient.xml | 4 ++ .../use_cases/1850-2100_rcp4.5_transient.xml | 4 ++ .../use_cases/1850-2100_rcp6_transient.xml | 4 ++ .../use_cases/1850-2100_rcp8.5_transient.xml | 4 ++ bld/namelist_files/use_cases/1850_control.xml | 3 ++ .../use_cases/2000-2100_rcp8.5_transient.xml | 4 ++ bld/namelist_files/use_cases/2000_control.xml | 3 ++ .../use_cases/20thC_transient.xml | 4 ++ 9 files changed, 47 insertions(+), 22 deletions(-) diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 88e5a48507..34a6ae2ca4 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -1105,36 +1105,31 @@ lnd/clm2/surfdata_map/surfdata_ne120np4_78pfts_CMIP6_simyr1850_c170824.ncnn -2000 -2000 +2000 +2000 -2000 -2000 +1850 +1850 -1850 -1850 +2000 +2000 -2000 -2000 +2000 +2000 -2000 -2000 +2000 +2000 -2000 -2000 +1850 +2106 -1850 -2106 +1850 +2106 -1850 -2106 +1850 +2106 -1850 -2106 - -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc - -lnd/clm2/urbandata/CLM45_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc +lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc nn diff --git a/bld/namelist_files/use_cases/1850-2100_rcp2.6_transient.xml b/bld/namelist_files/use_cases/1850-2100_rcp2.6_transient.xml index 6ed679db84..4252c1e64f 100644 --- a/bld/namelist_files/use_cases/1850-2100_rcp2.6_transient.xml +++ b/bld/namelist_files/use_cases/1850-2100_rcp2.6_transient.xml @@ -40,6 +40,10 @@ 2010 1850 +1850 +2100 +1850 + 1850 2100 1850 diff --git a/bld/namelist_files/use_cases/1850-2100_rcp4.5_transient.xml b/bld/namelist_files/use_cases/1850-2100_rcp4.5_transient.xml index d185e09085..09541a7b86 100644 --- a/bld/namelist_files/use_cases/1850-2100_rcp4.5_transient.xml +++ b/bld/namelist_files/use_cases/1850-2100_rcp4.5_transient.xml @@ -40,6 +40,10 @@ 2010 1850 +1850 +2100 +1850 + 1850 2100 1850 diff --git a/bld/namelist_files/use_cases/1850-2100_rcp6_transient.xml b/bld/namelist_files/use_cases/1850-2100_rcp6_transient.xml index 68a085b6f4..4ee8db473e 100644 --- a/bld/namelist_files/use_cases/1850-2100_rcp6_transient.xml +++ b/bld/namelist_files/use_cases/1850-2100_rcp6_transient.xml @@ -41,6 +41,10 @@ 2010 1850 +1850 +2100 +1850 + 1850 2100 1850 diff --git a/bld/namelist_files/use_cases/1850-2100_rcp8.5_transient.xml b/bld/namelist_files/use_cases/1850-2100_rcp8.5_transient.xml index 682e3c6034..c649101306 100644 --- a/bld/namelist_files/use_cases/1850-2100_rcp8.5_transient.xml +++ b/bld/namelist_files/use_cases/1850-2100_rcp8.5_transient.xml @@ -40,6 +40,10 @@ 2010 1850 +1850 +2100 +1850 + 1850 2100 1850 diff --git a/bld/namelist_files/use_cases/1850_control.xml b/bld/namelist_files/use_cases/1850_control.xml index 00b7adca1f..bafb1e2774 100644 --- a/bld/namelist_files/use_cases/1850_control.xml +++ b/bld/namelist_files/use_cases/1850_control.xml @@ -23,6 +23,9 @@ 1850 1850 +1850 +1850 + 1850 1850 diff --git a/bld/namelist_files/use_cases/2000-2100_rcp8.5_transient.xml b/bld/namelist_files/use_cases/2000-2100_rcp8.5_transient.xml index ad0e9f910e..bff9ef7f0f 100644 --- a/bld/namelist_files/use_cases/2000-2100_rcp8.5_transient.xml +++ b/bld/namelist_files/use_cases/2000-2100_rcp8.5_transient.xml @@ -39,6 +39,10 @@ 2010 2000 +2000 +2100 +2000 + 2000 2100 2000 diff --git a/bld/namelist_files/use_cases/2000_control.xml b/bld/namelist_files/use_cases/2000_control.xml index 756f19c719..f829e97772 100644 --- a/bld/namelist_files/use_cases/2000_control.xml +++ b/bld/namelist_files/use_cases/2000_control.xml @@ -24,6 +24,9 @@ 2000 2000 +2000 +2000 + 2000 2000 diff --git a/bld/namelist_files/use_cases/20thC_transient.xml b/bld/namelist_files/use_cases/20thC_transient.xml index 3cf2be85b7..8dfa8fc1a6 100644 --- a/bld/namelist_files/use_cases/20thC_transient.xml +++ b/bld/namelist_files/use_cases/20thC_transient.xml @@ -34,6 +34,10 @@ 2016 1850 +1850 +2106 +1850 + 1850 2106 1850 From f49dac114951737593c39eed41356be464d799d1 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 2 Sep 2019 17:14:04 -0600 Subject: [PATCH 06/17] Revisions in response to @billsacks code review Includes: - Adding the 3 additional namelist variables needed for 2nd snow layer - Renaming all 6 new namelist variables (1st & 2nd snow layer's vars) - Moving the default values to namelist_defaults_ctsm.xml - Adding error checks in CLMBuildNamelist.pm and SnowHydrologyMod.F90 - Reverting changes in clm_varcon.F90 and making the dzmin and dzmax_* variables local to SnowHydrologyMod.F90 - Temporary testing code for review and for testing on Hobart, to be removed when done testing --- bld/CLMBuildNamelist.pm | 42 +++++ bld/namelist_files/namelist_defaults_ctsm.xml | 7 + .../namelist_definition_ctsm.xml | 27 ++++ src/biogeophys/SnowHydrologyMod.F90 | 150 +++++++++++++----- src/main/clm_varcon.F90 | 8 +- 5 files changed, 190 insertions(+), 44 deletions(-) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 599d860887..d871bc7e34 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -3538,6 +3538,48 @@ sub setup_logic_snowpack { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'reset_snow'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'reset_snow_glc'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'reset_snow_glc_ela'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_dzmin_1'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_dzmin_2'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_dzmax_l_1'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_dzmax_l_2'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_dzmax_u_1'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_dzmax_u_2'); + + my $dzmin1 = $nl->get_value('snow_dzmin_1'); + my $dzmin2 = $nl->get_value('snow_dzmin_2'); + my $dzmax_l1 = $nl->get_value('snow_dzmax_l_1'); + my $dzmax_l2 = $nl->get_value('snow_dzmax_l_2'); + my $dzmax_u1 = $nl->get_value('snow_dzmax_u_1'); + my $dzmax_u2 = $nl->get_value('snow_dzmax_u_2'); + + if ($dzmin1 != 0.01 || $dzmin2 != 0.015 || $dzmax_u1 != 0.02 || $dzmax_u2 != 0.05 || $dzmax_l1 != 0.03 || $dzmax_l2 != 0.07) { + $log->warning("Setting any of the following namelist variables to NON DEFAULT values remains untested as of Sep 1, 2019: snow_dzmin_1 & 2, snow_dzmax_u_1 & 2, snow_dzmax_l_1 & 2." ); + $log->warning("Leave these variables unspecified in user_nl_clm in order to use the default values." ); + } + if ($dzmin1 <= 0.0 || $dzmin2 <= 0.0 || $dzmax_u1 <= 0.0 || $dzmax_u2 <= 0.0 || $dzmax_l1 <= 0.0 || $dzmax_l2 <= 0.0) { + $log->fatal_error('One or more of the snow_dzmin_* and/or snow_dzmax_* were set incorrectly to be <= 0'); + } + if ($dzmin2 <= $dzmin1) { + $log->fatal_error('snow_dzmin_2 was set incorrectly to be <= snow_dzmin_1'); + } + if ($dzmax_l2 <= $dzmax_l1) { + $log->fatal_error('snow_dzmax_l_2 was set incorrectly to be <= snow_dzmax_l_1'); + } + if ($dzmax_u2 <= $dzmax_u1) { + $log->fatal_error('snow_dzmax_u_2 was set incorrectly to be <= snow_dzmax_u_1'); + } + if ($dzmin1 >= $dzmax_u1) { + $log->fatal_error('snow_dzmin_1 was set incorrectly to be >= snow_dzmax_u_1'); + } + if ($dzmin2 >= $dzmax_u2) { + $log->fatal_error('snow_dzmin_2 was set incorrectly to be >= snow_dzmax_u_2'); + } + if ($dzmax_u1 >= $dzmax_l1) { + $log->fatal_error('snow_dzmax_u_1 was set incorrectly to be >= snow_dzmax_l_1'); + } + if ($dzmax_u2 >= $dzmax_l2) { + $log->fatal_error('snow_dzmax_u_2 was set incorrectly to be >= snow_dzmax_l_2'); + } if (remove_leading_and_trailing_quotes($nl->get_value('snow_overburden_compaction_method')) eq 'Vionnet2012') { # overburden_compress_tfactor isn't used if we're using the Vionnet2012 diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index e318284e43..d5eb042cba 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -298,6 +298,13 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 5000.0 1000.0 +0.010d00 +0.015d00 +0.03d00 +0.07d00 +0.02d00 +0.05d00 + 2000. 1.e30 diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 3d5ca6dd87..2f4dba64bb 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -2454,6 +2454,33 @@ Changes in this value should possibly be accompanied by changes in: glc_snow_persistence_max_days > 0. + +Min snow thickness of layer 1 + + +Min snow thickness of layer 2 + + + +Max snow thickness of layer 1 when no layers beneath + + +Max snow thickness of layer 2 when no layers beneath + + + +Max snow thickness of layer 1 when layers beneath + + +Max snow thickness of layer 2 when layers beneath + + Limit applied to integrated snowfall when determining changes in snow-covered fraction during melt diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index 8c53dd81e6..2f877394f6 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -24,7 +24,6 @@ module SnowHydrologyMod use clm_varpar , only : nlevsno, nlevsoi, nlevgrnd use clm_varctl , only : iulog, use_subgrid_fluxes use clm_varcon , only : namec, h2osno_max, hfus, denice, rpi, spval, tfrz - use clm_varcon, only: dzmin, dzmax_l, dzmax_u use atm2lndType , only : atm2lnd_type use AerosolMod , only : aerosol_type use TemperatureType , only : temperature_type @@ -110,7 +109,17 @@ module SnowHydrologyMod ! If true, the density of new snow depends on wind speed, and there is also ! wind-dependent snow compaction logical :: wind_dependent_snow_density ! If snow density depends on wind or not - real(r8) :: dzmin_1, dzmax_l_1, dzmax_u_1 ! namelist-defined top snow layer information + real(r8) :: snow_dzmin_1, snow_dzmax_l_1, snow_dzmax_u_1 ! namelist-defined top snow layer information + real(r8) :: snow_dzmin_2, snow_dzmax_l_2, snow_dzmax_u_2 ! namelist-defined 2nd snow layer information + real(r8), private, allocatable :: dzmin(:) !min snow thickness of layer + real(r8), private, allocatable :: dzmax_l(:) !max snow thickness of layer when no layers beneath + real(r8), private, allocatable :: dzmax_u(:) !max snow thickness of layer when layers beneath + + ! FOR TEMPORARY TESTING. DELETE WHEN DONE. slevis diag + real(r8), private, allocatable :: dzmin_orig(:) + real(r8), private, allocatable :: dzmax_l_orig(:) + real(r8), private, allocatable :: dzmax_u_orig(:) + integer :: overburden_compaction_method = -1 integer :: new_snow_density = LoTmpDnsSlater2017 ! Snow density type real(r8) :: upplim_destruct_metamorph = 100.0_r8 ! Upper Limit on Destructive Metamorphism Compaction [kg/m3] @@ -158,6 +167,7 @@ subroutine SnowHydrology_readnl( NLFilename) use shr_nl_mod , only : shr_nl_find_group_name use spmdMod , only : masterproc, mpicom use shr_mpi_mod , only : shr_mpi_bcast + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) ! ! !ARGUMENTS: character(len=*), intent(in) :: NLFilename ! Namelist filename @@ -175,15 +185,19 @@ subroutine SnowHydrology_readnl( NLFilename) wind_dependent_snow_density, snow_overburden_compaction_method, & lotmp_snowdensity_method, upplim_destruct_metamorph, & overburden_compress_Tfactor, min_wind_snowcompact, & - reset_snow, reset_snow_glc, reset_snow_glc_ela, dzmin_1, dzmax_l_1, & - dzmax_u_1 + reset_snow, reset_snow_glc, reset_snow_glc_ela, & + snow_dzmin_1, snow_dzmax_l_1, snow_dzmax_u_1, & + snow_dzmin_2, snow_dzmax_l_2, snow_dzmax_u_2 ! Initialize options to default values, in case they are not specified in the namelist wind_dependent_snow_density = .false. snow_overburden_compaction_method = ' ' - dzmin_1 = 0.01_r8 - dzmax_l_1 = 0.03_r8 - dzmax_u_1 = 0.02_r8 + snow_dzmin_1 = nan + snow_dzmin_2 = nan + snow_dzmax_l_1 = nan + snow_dzmax_l_2 = nan + snow_dzmax_u_1 = nan + snow_dzmax_u_2 = nan if (masterproc) then unitn = getavu() @@ -210,9 +224,12 @@ subroutine SnowHydrology_readnl( NLFilename) call shr_mpi_bcast (reset_snow , mpicom) call shr_mpi_bcast (reset_snow_glc , mpicom) call shr_mpi_bcast (reset_snow_glc_ela , mpicom) - call shr_mpi_bcast (dzmin_1, mpicom) - call shr_mpi_bcast (dzmax_l_1, mpicom) - call shr_mpi_bcast (dzmax_u_1, mpicom) + call shr_mpi_bcast (snow_dzmin_1, mpicom) + call shr_mpi_bcast (snow_dzmin_2, mpicom) + call shr_mpi_bcast (snow_dzmax_l_1, mpicom) + call shr_mpi_bcast (snow_dzmax_l_2, mpicom) + call shr_mpi_bcast (snow_dzmax_u_1, mpicom) + call shr_mpi_bcast (snow_dzmax_u_2, mpicom) if (masterproc) then write(iulog,*) ' ' @@ -238,19 +255,6 @@ subroutine SnowHydrology_readnl( NLFilename) errMsg(sourcefile, __LINE__)) end if - if (dzmin_1 < 0.01_r8) then - call endrun(msg="ERROR dzmin_1 cannot be less than 0.01"// & - errMsg(sourcefile, __LINE__)) - end if - if (dzmax_l_1 < 0.03_r8) then - call endrun(msg="ERROR dzmax_l_1 cannot be less than 0.03"// & - errMsg(sourcefile, __LINE__)) - end if - if (dzmax_u_1 < 0.02_r8) then - call endrun(msg="ERROR dzmax_2_1 cannot be less than 0.02"// & - errMsg(sourcefile, __LINE__)) - end if - end subroutine SnowHydrology_readnl !----------------------------------------------------------------------- @@ -1504,7 +1508,7 @@ subroutine CombineSnowLayers(bounds, num_snowc, filter_snowc, & real(r8):: h2osno_total(bounds%begc:bounds%endc) ! total snow water (mm H2O) real(r8):: zwice(bounds%begc:bounds%endc) ! total ice mass in snow real(r8):: zwliq (bounds%begc:bounds%endc) ! total liquid water in snow - real(r8):: dzminloc(nlevsno) ! minimum of top snow layer (local) + real(r8):: dzminloc(nlevsno) ! minimum thickness of snow layer (local) real(r8):: dtime !land model time step (sec) !----------------------------------------------------------------------- @@ -2222,6 +2226,7 @@ subroutine InitSnowLayers (bounds, snow_depth) ! ! !USES: use clm_varcon , only : spval + use spmdMod, only : masterproc ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -2242,25 +2247,96 @@ subroutine InitSnowLayers (bounds, snow_depth) zi => col%zi & ! Output: [real(r8) (:,:) ] interface level below a "z" level (m) (-nlevsno+0:nlevgrnd) ) + allocate(dzmin(1:nlevsno)) + allocate(dzmax_l(1:nlevsno)) + allocate(dzmax_u(1:nlevsno)) + + ! FOR TEMPORARY TESTING. DELETE WHEN DONE. slevis diag + allocate(dzmin_orig(1:nlevsno)) + allocate(dzmax_l_orig(1:nlevsno)) + allocate(dzmax_u_orig(1:nlevsno)) + ! These three variables determine the vertical structure of the snow pack: - ! dzmin: minimum of top snow layer - ! dzmax_l: maximum thickness of layer when no layers beneath - ! dzmax_u: maximum thickness of layer when layers beneath - dzmin(1) = dzmin_1 ! set in the namelist with default or user-defined value - dzmax_l(1) = dzmax_l_1 ! same comment - dzmax_u(1) = dzmax_u_1 ! same comment - do j = 2, nlevsno + ! dzmin: minimum snow thickness of layer + ! dzmax_l: maximum snow thickness of layer when no layers beneath + ! dzmax_u: maximum snow thickness of layer when layers beneath + dzmin(1) = snow_dzmin_1 ! default or user-defined value from namelist + dzmax_l(1) = snow_dzmax_l_1 ! same comment + dzmax_u(1) = snow_dzmax_u_1 ! same comment + dzmin(2) = snow_dzmin_2 ! default or user-defined value from namelist + dzmax_l(2) = snow_dzmax_l_2 ! same comment + dzmax_u(2) = snow_dzmax_u_2 ! same comment + do j = 3, nlevsno dzmin(j) = dzmax_u(j-1) * 0.5_r8 + dzmax_u(j) = 2._r8 * dzmax_u(j-1) + 0.01_r8 + dzmax_l(j) = dzmax_u(j) + dzmax_l(j-1) + ! error checks if (dzmin(j) <= dzmin(j-1)) then - dzmin(j) = (dzmin(j-1) + dzmax_u(j-1)) * 0.5_r8 + write(iulog,*) 'ERROR at snow layer j =', j, ' because dzmin(j) =', dzmin(j), ' and dzmin(j-1) =', dzmin(j-1) + call endrun(msg="ERROR dzmin(j) cannot be <= dzmin(j-1)"// & + errMsg(sourcefile, __LINE__)) end if - dzmax_u(j) = 2._r8 * dzmax_u(j-1) + 0.01_r8 - if (j == 2) then - dzmax_l(j) = dzmax_u(j) + dzmax_l(j-1) - 0.01_r8 - else - dzmax_l(j) = dzmax_u(j) + dzmax_l(j-1) + if (dzmax_u(j) <= dzmax_u(j-1)) then + write(iulog,*) 'ERROR at snow layer j =', j, ' because dzmax_u(j) =', dzmax_u(j), ' and dzmax_u(j-1) =', dzmax_u(j-1) + call endrun(msg="ERROR dzmax_u(j) cannot be <= dzmax_u(j-1)"// & + errMsg(sourcefile, __LINE__)) + end if + if (dzmax_l(j) <= dzmax_l(j-1)) then + write(iulog,*) 'ERROR at snow layer j =', j, ' because dzmax_l(j) =', dzmax_l(j), ' and dzmax_l(j-1) =', dzmax_l(j-1) + call endrun(msg="ERROR dzmax_l(j) cannot be <= dzmax_l(j-1)"// & + errMsg(sourcefile, __LINE__)) + end if + if (dzmin(j) >= dzmax_u(j)) then + write(iulog,*) 'ERROR at snow layer j =', j, ' because dzmin(j) =', dzmin(j), ' and dzmax_u(j) =', dzmax_u(j) + call endrun(msg="ERROR dzmin(j) cannot be >= dzmax_u(j)"// & + errMsg(sourcefile, __LINE__)) + end if + if (dzmax_u(j) >= dzmax_l(j)) then + write(iulog,*) 'ERROR at snow layer j =', j, ' because dzmax_u(j) =', dzmax_u(j), ' and dzmax_l(j) =', dzmax_l(j) + call endrun(msg="ERROR dzmax_u(j) cannot be >= dzmax_l(j)"// & + errMsg(sourcefile, __LINE__)) end if end do + if (nlevsno >= 12) then ! max nlevsno is 12 + dzmax_u(nlevsno) = huge(1._r8) ! the original code set layer 12 to huge + dzmax_l(nlevsno) = huge(1._r8) ! same comment + end if + + if (masterproc) then + write(iulog,*) 'dzmin =', dzmin + write(iulog,*) 'dzmax_l =', dzmax_l + write(iulog,*) 'dzmax_u =', dzmax_u + end if + + ! BEGIN TEMPORARY TESTING. DELETE WHEN DONE. slevis diag + dzmin_orig = (/ 0.01_r8, 0.015_r8, 0.025_r8, 0.055_r8, 0.115_r8, 0.235_r8, & + 0.475_r8, 0.955_r8, 1.915_r8, 3.835_r8, 7.675_r8, 15.355_r8 /) + if (maxval(abs(dzmin(1:nlevsno) - dzmin_orig(1:nlevsno))) > 1.e-13_r8) then + write(iulog,*) 'dzmin_orig =', dzmin_orig + call endrun(msg="ERROR dzmin_orig /= dzmin"// & + errMsg(sourcefile, __LINE__)) + else + dzmin(1:nlevsno) = dzmin_orig(1:nlevsno) + end if + dzmax_u_orig = (/ 0.02_r8, 0.05_r8, 0.11_r8, 0.23_r8, 0.47_r8, 0.95_r8, & + 1.91_r8, 3.83_r8, 7.67_r8, 15.35_r8, 30.71_r8, huge(1._r8) /) + if (maxval(abs(dzmax_u(1:nlevsno) - dzmax_u_orig(1:nlevsno))) > 1.e-13_r8) then + write(iulog,*) 'dzmax_u_orig =', dzmax_u_orig + call endrun(msg="ERROR dzmax_u_orig /= dzmax_u"// & + errMsg(sourcefile, __LINE__)) + else + dzmax_u(1:nlevsno) = dzmax_u_orig(1:nlevsno) + end if + dzmax_l_orig = (/ 0.03_r8, 0.07_r8, 0.18_r8, 0.41_r8, 0.88_r8, 1.83_r8, & + 3.74_r8, 7.57_r8, 15.24_r8, 30.59_r8, 61.30_r8, huge(1._r8) /) + if (maxval(abs(dzmax_l(1:nlevsno) - dzmax_l_orig(1:nlevsno))) > 1.e-13_r8) then + write(iulog,*) 'dzmax_l_orig =', dzmax_l_orig + call endrun(msg="ERROR dzmax_l_orig /= dzmax_l"// & + errMsg(sourcefile, __LINE__)) + else + dzmax_l(1:nlevsno) = dzmax_l_orig(1:nlevsno) + end if + ! END TEMPORARY TESTING slevis diag loop_columns: do c = bounds%begc,bounds%endc l = col%landunit(c) diff --git a/src/main/clm_varcon.F90 b/src/main/clm_varcon.F90 index abf3787652..8baa37f771 100644 --- a/src/main/clm_varcon.F90 +++ b/src/main/clm_varcon.F90 @@ -213,9 +213,6 @@ module clm_varcon ! The values for the following arrays are set in routine iniTimeConst !------------------------------------------------------------------ - real(r8), public, allocatable :: dzmin(:) !min of top snow layer - real(r8), public, allocatable :: dzmax_l(:) !max snow thickness of layer when no layers beneath - real(r8), public, allocatable :: dzmax_u(:) !max snow thickness of layer when layers beneath real(r8), public, allocatable :: zlak(:) !lake z (layers) real(r8), public, allocatable :: dzlak(:) !lake dz (thickness) real(r8), public, allocatable :: zsoi(:) !soil z (layers) @@ -269,7 +266,7 @@ subroutine clm_varcon_init( is_simple_buildtemp ) ! MUST be called after clm_varpar_init. ! ! !USES: - use clm_varpar, only: nlevsno, nlevgrnd, nlevlak, nlevdecomp_full, nlevsoifl, nlayer + use clm_varpar, only: nlevgrnd, nlevlak, nlevdecomp_full, nlevsoifl, nlayer ! ! !ARGUMENTS: implicit none @@ -279,9 +276,6 @@ subroutine clm_varcon_init( is_simple_buildtemp ) ! Created by E. Kluzek !------------------------------------------------------------------------------ - allocate( dzmin(1:nlevsno )) - allocate( dzmax_l(1:nlevsno )) - allocate( dzmax_u(1:nlevsno )) allocate( zlak(1:nlevlak )) allocate( dzlak(1:nlevlak )) allocate( zsoi(1:nlevgrnd )) From d31b2eeb3f8db489b1ea3895993f1747a569e5c2 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 4 Sep 2019 16:35:14 -0600 Subject: [PATCH 07/17] Fix urbantv to point to different file for clm4_5 than clm5_0 as it should --- bld/namelist_files/namelist_defaults_ctsm.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 34a6ae2ca4..f20a5970d0 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -1129,7 +1129,11 @@ lnd/clm2/surfdata_map/surfdata_ne120np4_78pfts_CMIP6_simyr1850_c170824.nc1850 2106 -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc +lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc + +lnd/clm2/urbandata/CLM45_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc nn From ffe027c1ed0def31d5826611d67d8761eb64effc Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 5 Sep 2019 19:21:36 -0600 Subject: [PATCH 08/17] Remove DWT_SLASH_* from output usermod at scales finer than gridcell, since it's now gridcell only --- cime_config/usermods_dirs/output_bgc/user_nl_clm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cime_config/usermods_dirs/output_bgc/user_nl_clm b/cime_config/usermods_dirs/output_bgc/user_nl_clm index de136ad4b4..0c0bcd52ff 100644 --- a/cime_config/usermods_dirs/output_bgc/user_nl_clm +++ b/cime_config/usermods_dirs/output_bgc/user_nl_clm @@ -11,7 +11,7 @@ hist_fincl2 += 'GPP', 'NPP', 'AGNPP', 'TOTVEGC', 'NPP_NUPTAKE', 'AR', 'HR', 'HTO ! h2 stream (monthly average, landunit-level) ! TOT_WOODPRODC:I, CROPPROD1C:I, and NEE are not available at the landunit level -hist_fincl3 += 'GPP', 'NPP', 'AR', 'HR', 'DWT_CONV_CFLUX_PATCH', 'WOOD_HARVESTC', 'DWT_WOOD_PRODUCTC_GAIN_PATCH', 'SLASH_HARVESTC', 'COL_FIRE_CLOSS', 'DWT_SLASH_CFLUX', 'FROOTC:I', 'HTOP' +hist_fincl3 += 'GPP', 'NPP', 'AR', 'HR', 'DWT_CONV_CFLUX_PATCH', 'WOOD_HARVESTC', 'DWT_WOOD_PRODUCTC_GAIN_PATCH', 'SLASH_HARVESTC', 'COL_FIRE_CLOSS', 'FROOTC:I', 'HTOP' ! h3 stream (yearly average, gridcell-level) hist_fincl4 += 'SOILC_vr', 'SOILN_vr', 'CWDC_vr', 'LITR1C_vr', 'LITR2C_vr', 'LITR3C_vr', 'LITR1N_vr', 'LITR2N_vr', 'LITR3N_vr','CWDN_vr', 'TOTLITC:I', 'TOT_WOODPRODC:I', 'TOTSOMC:I','TOTVEGC:I' From ec4d91a38babc3cd93095f004c97dfedcba23d2f Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Thu, 5 Sep 2019 21:28:09 -0600 Subject: [PATCH 09/17] Update changelog --- doc/ChangeLog | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/ChangeSum | 1 + 2 files changed, 122 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index a962ec67e3..1352bf8dd2 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,125 @@ =============================================================== +Tag name: ctsm1.0.dev063 +Originator(s): erik (Erik Kluzek) +Date: Thu Sep 5 21:28:02 MDT 2019 +One-line Summary: Two answer changing fixes (fire, DWT_SLASH) and fix for urban streams for Clm45 + +Purpose of changes +------------------ + +Fire bug fix and DWT_SLASH change and fix urban stream years for clm4_5. +The latitude used in an expression for Bgc-Fire model Li2016 (used in Clm50) +had latitude in degrees rather than in radians as it should have been. The +term is used for ignition and the cosine was being taken in degrees rather +than radians, hence the spatial pattern for ignition with latitude was incorrect. + +The history field DWT_SLASH_CFLUX was being calculated on the column, but +really should have been a patch level variable. In the same way other fields +were handled we made DWT_SLASH_CFLUX a grid-cell variable, and added +DWT_SLASH_CFLUX_PATCH on the patch level that could be added to output. The same +is true of the C13_ and C14_ versions of it. + +Clm45 was setting urbantv to year 2000, rather than 1850 or historical as it should +have. The urbantv file for Clm45 doesn't actually change, so this doesn't actually +make a difference. But, it does make the namelist look wrong. + +Note, that SP cases, Vic cases and Fates cases do NOT change answers. Or if fire is +off, or certain single-point cases. Some cold-start cases don't seem to be sensitive +to it either. + +Bugs fixed or introduced +------------------------ + +Issues fixed (include CTSM Issue #): #175, #787, #780 + fixes #175 urban stream years for clm4_5 + fixes #787 DWT_SLASH field + fixes #780 Bug in CN Fire Li 2016 which used latitude in degrees rather than radians + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): None + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): None + +Changes made to namelist defaults (e.g., changed parameter values): Defaults for urbantv for clm4_5 + +Changes to the datasets (e.g., parameter, surface or initial files): None + +Substantial timing or memory changes: None + +Notes of particular relevance for developers: (including Code reviews and testing) +--------------------------------------------- +NOTE: Be sure to review the steps in README.CHECKLIST.master_tags as well as the coding style in the Developers Guide + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): None + +Changes to tests or testing: None + +Code reviewed by: self, @olywon + + +CTSM testing: regular + + [PASS means all tests PASS and OK means tests PASS other than expected fails.] + + build-namelist tests: + + cheyenne - PASS (62 compare fail due to namelist changes) + + regular tests (aux_clm): + + cheyenne ---- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: previous + + +Answer changes +-------------- + +Changes answers relative to baseline: Yes! + + Summarize any changes to answers, i.e., + - what code configurations: Clm50Bgc and some Clm45Bgc cases + - what platforms/compilers: All + - nature of change: similar climate (but fire ignition pattern changes by latitude) + DWT_SLASH_* history fields change because moved to gridcell quantity (so change is relatively minor) + + If this tag changes climate describe the run(s) done to evaluate the new + climate (put details of the simulations in the experiment database) + - casename: + oleson/clm50_cesm20R_2deg_GSWP3V1_issue780_hist (for the fire change) + + URL for LMWG diagnostics output used to validate new climate: +http://webext.cgd.ucar.edu/I20TR/clm50_cesm20R_2deg_GSWP3V1_issue780_hist/lnd/clm50_cesm20R_2deg_GSWP3V1_issue780_hist.1995_2014-clm50_cesm20R_2deg_GSWP3V1_hist.1995_2014/setsIndex.html + + +Detailed list of changes +------------------------ + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): None + +Pull Requests that document the changes (include PR ids): #802 +(https://github.com/ESCOMP/ctsm/pull) + #802 -- Three answer changing fixes (fire, DWT_SLASH, urban streams for clm4_5) + +=============================================================== +=============================================================== Tag name: ctsm1.0.dev062 Originator(s): sacks (Bill Sacks) Date: Tue Sep 3 16:04:28 MDT 2019 diff --git a/doc/ChangeSum b/doc/ChangeSum index b00c6f1bf3..23a8fa90de 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm1.0.dev063 erik 09/05/2019 Two answer changing fixes (fire, DWT_SLASH) and fix for urban streams for Clm45 ctsm1.0.dev062 sacks 09/03/2019 Move hobart tests to izumi ctsm1.0.dev061 erik 09/01/2019 Simple b4b fixes: new params file, remove override_nsrest/anoxia_wtsat, DV deprecated ctsm1.0.dev060 sacks 08/29/2019 In SnowWater, truncate small h2osoi residuals From e00da7c0175d7f29c3fcf27e2d0677f4d2c4d379 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 6 Sep 2019 23:22:06 -0600 Subject: [PATCH 10/17] Revisions in response to code review --- bld/CLMBuildNamelist.pm | 2 +- .../namelist_definition_ctsm.xml | 12 +++++------ src/biogeophys/SnowHydrologyMod.F90 | 21 ++++++++++++------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 27a8247771..ae58cbaf12 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -3536,7 +3536,7 @@ sub setup_logic_snowpack { my $dzmax_u2 = $nl->get_value('snow_dzmax_u_2'); if ($dzmin1 != 0.01 || $dzmin2 != 0.015 || $dzmax_u1 != 0.02 || $dzmax_u2 != 0.05 || $dzmax_l1 != 0.03 || $dzmax_l2 != 0.07) { - $log->warning("Setting any of the following namelist variables to NON DEFAULT values remains untested as of Sep 1, 2019: snow_dzmin_1 & 2, snow_dzmax_u_1 & 2, snow_dzmax_l_1 & 2." ); + $log->warning("Setting any of the following namelist variables to NON DEFAULT values remains untested as of Sep 6, 2019: snow_dzmin_1 & 2, snow_dzmax_u_1 & 2, snow_dzmax_l_1 & 2." ); $log->warning("Leave these variables unspecified in user_nl_clm in order to use the default values." ); } if ($dzmin1 <= 0.0 || $dzmin2 <= 0.0 || $dzmax_u1 <= 0.0 || $dzmax_u2 <= 0.0 || $dzmax_l1 <= 0.0 || $dzmax_l2 <= 0.0) { diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 3639f40fe1..83502c5f32 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -2442,29 +2442,29 @@ Changes in this value should possibly be accompanied by changes in: -Min snow thickness of layer 1 +Min snow thickness of layer 1 (top snow layer); values other than the default 0.01 have not been tested as of Sep 6, 2019 -Min snow thickness of layer 2 +Min snow thickness of layer 2; values other than the default 0.015 have not been tested as of Sep 6, 2019; snow_dzmin of remaining layers is generated with the following recursive formula: dzmin(j) = dzmax_u(j-1) * 0.5_r8 -Max snow thickness of layer 1 when no layers beneath +Max snow thickness of layer 1 (top snow layer) when no layers beneath; values other than the default 0.03 have not been tested as of Sep 6, 2019 -Max snow thickness of layer 2 when no layers beneath +Max snow thickness of layer 2 when no layers beneath; values other than the default 0.07 have not been tested as of Sep 6, 2019; snow_dzmax_l of remaining layers is generated with the following recursive formula: dzmax_l(j) = dzmax_u(j) + dzmax_l(j-1) -Max snow thickness of layer 1 when layers beneath +Max snow thickness of layer 1 (top snow layer) when layers beneath; values other than the default 0.02 have not been tested as of Sep 6, 2019 -Max snow thickness of layer 2 when layers beneath +Max snow thickness of layer 2 when layers beneath; values other than the default 0.05 have not been tested as of Sep 6, 2019; snow_dzmax_u of remaining layers is generated with the following recursive formula: dzmax_u(j) = 2._r8 * dzmax_u(j-1) + 0.01_r8 roundoff because I now set + dzmax_l(nlevsno) = dzmax_u(nlevsno) = huge(1._r8) which differs + significantly from their original values. Overwriting these with their + original values also returns bit-for-bit same answers. + +Detailed list of changes +------------------------ + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): none + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/792 + +=============================================================== +=============================================================== Tag name: ctsm1.0.dev063 Originator(s): erik (Erik Kluzek) Date: Thu Sep 5 21:28:02 MDT 2019 diff --git a/doc/ChangeSum b/doc/ChangeSum index 23a8fa90de..bbef06b216 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm1.0.dev064 slevis 09/06/2019 User defined top-two snow layers ctsm1.0.dev063 erik 09/05/2019 Two answer changing fixes (fire, DWT_SLASH) and fix for urban streams for Clm45 ctsm1.0.dev062 sacks 09/03/2019 Move hobart tests to izumi ctsm1.0.dev061 erik 09/01/2019 Simple b4b fixes: new params file, remove override_nsrest/anoxia_wtsat, DV deprecated From e4782446abec62cef8bfa182e28f923a0183d89f Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 7 Sep 2019 17:14:10 -0600 Subject: [PATCH 12/17] Updated temporary test code checking bit-for-bit --- src/biogeophys/SnowHydrologyMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index 76d175e4ed..c15f3e2ec9 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -2316,8 +2316,8 @@ subroutine InitSnowLayers (bounds, snow_depth) dzmax_u(j) = 2._r8 * dzmax_u(j-1) + 0.01_r8 dzmax_l(j) = dzmax_u(j) + dzmax_l(j-1) if (j == nlevsno) then - dzmax_u(j) = huge(1._r8) ! The original code set layer 12 to huge... - dzmax_l(j) = huge(1._r8) ! ...now we set the bottom layer to huge + dzmax_u(j) = huge(1._r8) + dzmax_l(j) = huge(1._r8) end if end do @@ -2386,7 +2386,7 @@ subroutine InitSnowLayers (bounds, snow_depth) call endrun(msg="ERROR dzmax_l_orig /= dzmax_l"// & errMsg(sourcefile, __LINE__)) else - dzmax_l(1:nlevsno) = dzmax_l_orig(1:nlevsno) + dzmax_l(1:nlevsno-1) = dzmax_l_orig(1:nlevsno-1) end if ! END TEMPORARY TESTING slevis diag From db4bb807f70a93c581a8aa86b308d1e171ffccd4 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 7 Sep 2019 17:31:43 -0600 Subject: [PATCH 13/17] Updated temporary test code checking bit-for-bit (part 2) Repeated a clm4.5 test and got PASS. This commit includes updated wording in the ChangeLog. --- doc/ChangeLog | 37 +++++++++-------------------- src/biogeophys/SnowHydrologyMod.F90 | 2 +- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index efef699eee..ef16662b62 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,7 @@ =============================================================== Tag name: ctsm1.0.dev064 Originator(s): slevis (Samuel Levis,SLevis Consulting LLC,303-665-1310) -Date: Fri Sep 6 23:52:03 MDT 2019 +Date: Sat Sep 7 17:19:17 MDT 2019 One-line Summary: User defined top-two snow layers Purpose of changes @@ -40,9 +40,9 @@ Does this tag change answers significantly for any of the following physics conf [ ] clm5_0 -[x] ctsm5_0-nwp +[ ] ctsm5_0-nwp -[x] clm4_5 +[ ] clm4_5 Notes of particular relevance for users --------------------------------------- @@ -56,7 +56,7 @@ Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): Changes made to namelist defaults (e.g., changed parameter values): Introduced default values for the new parameters so as to maintain - bit-for-bit same answers in cases with nlevsno = 12 + bit-for-bit same answers Changes to the datasets (e.g., parameter, surface or initial files): none @@ -75,18 +75,6 @@ Code reviewed by: @billsacks CTSM testing: -[... Remove before making master tag. Available test levels: - - a) regular (must be run before handing off a tag to SEs and must be run - before committing a tag) - b) build_namelist (if namelists and/or build_system changed)) - c) tools (only if tools are modified and no CTSM source is modified) - d) short (for use during development and in rare cases where only a small - change with known behavior is added ... eg. a minor bug fix) - e) doc (no source testing required) - -... ] - [PASS means all tests PASS and OK means tests PASS other than expected fails.] build-namelist tests: @@ -119,20 +107,17 @@ Answer changes Changes answers relative to baseline: Summarize any changes to answers, i.e., - - what code configurations: nlevsno < 12 + - what code configurations: all - what platforms/compilers: all - - nature of change: roundoff for nlevsno = 12; larger than roundoff/same climate for nlevsno < 12 + - nature of change: roundoff If bitwise differences were observed, how did you show they were no worse than roundoff? - For snow layers < nlevsno, I introduced temporary code to overwrite - dzmin(j), dzmax_l(j), and dzmax_u(j) with their original values when - different by less than 1e-13 from their original values; this resulted - in bit-for-bit same answers when nlevsno = 12. For nlevsno < 12 we get - differences > roundoff because I now set - dzmax_l(nlevsno) = dzmax_u(nlevsno) = huge(1._r8) which differs - significantly from their original values. Overwriting these with their - original values also returns bit-for-bit same answers. + Introduced temporary code to overwrite dzmin(j), dzmax_l(j), and + dzmax_u(j) with their original values when different by less than + 1e-13 from their original values for all but the bottom snow layer. + The bottom layer was left as dzmax_l = dzmax_u(j) = huge(1._8), i.e. + the new value. The test resulted in bit-for-bit same answers. Detailed list of changes ------------------------ diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index c15f3e2ec9..6baf716f05 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -2377,7 +2377,7 @@ subroutine InitSnowLayers (bounds, snow_depth) call endrun(msg="ERROR dzmax_u_orig /= dzmax_u"// & errMsg(sourcefile, __LINE__)) else - dzmax_u(1:nlevsno) = dzmax_u_orig(1:nlevsno) + dzmax_u(1:nlevsno-1) = dzmax_u_orig(1:nlevsno-1) end if dzmax_l_orig = (/ 0.03_r8, 0.07_r8, 0.18_r8, 0.41_r8, 0.88_r8, 1.83_r8, & 3.74_r8, 7.57_r8, 15.24_r8, 30.59_r8, 61.30_r8, huge(1._r8) /) From 97cef7838534cdfa559a484ec4bace874ad0fb05 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Sat, 7 Sep 2019 17:40:59 -0600 Subject: [PATCH 14/17] Removing temporary test code --- src/biogeophys/SnowHydrologyMod.F90 | 40 ----------------------------- 1 file changed, 40 deletions(-) diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index 6baf716f05..fb29889ac7 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -116,11 +116,6 @@ module SnowHydrologyMod real(r8), private, allocatable :: dzmax_l(:) !max snow thickness of layer when no layers beneath real(r8), private, allocatable :: dzmax_u(:) !max snow thickness of layer when layers beneath - ! FOR TEMPORARY TESTING. DELETE WHEN DONE. slevis diag - real(r8), private, allocatable :: dzmin_orig(:) - real(r8), private, allocatable :: dzmax_l_orig(:) - real(r8), private, allocatable :: dzmax_u_orig(:) - integer :: overburden_compaction_method = -1 integer :: new_snow_density = LoTmpDnsSlater2017 ! Snow density type real(r8) :: upplim_destruct_metamorph = 100.0_r8 ! Upper Limit on Destructive Metamorphism Compaction [kg/m3] @@ -2296,11 +2291,6 @@ subroutine InitSnowLayers (bounds, snow_depth) allocate(dzmax_l(1:nlevsno)) allocate(dzmax_u(1:nlevsno)) - ! FOR TEMPORARY TESTING. DELETE WHEN DONE. slevis diag - allocate(dzmin_orig(1:nlevsno)) - allocate(dzmax_l_orig(1:nlevsno)) - allocate(dzmax_u_orig(1:nlevsno)) - ! These three variables determine the vertical structure of the snow pack: ! dzmin: minimum snow thickness of layer ! dzmax_l: maximum snow thickness of layer when no layers beneath @@ -2360,36 +2350,6 @@ subroutine InitSnowLayers (bounds, snow_depth) write(iulog,*) 'dzmax_u =', dzmax_u end if - ! BEGIN TEMPORARY TESTING. DELETE WHEN DONE. slevis diag - dzmin_orig = (/ 0.01_r8, 0.015_r8, 0.025_r8, 0.055_r8, 0.115_r8, 0.235_r8, & - 0.475_r8, 0.955_r8, 1.915_r8, 3.835_r8, 7.675_r8, 15.355_r8 /) - if (maxval(abs(dzmin(1:nlevsno) - dzmin_orig(1:nlevsno))) > 1.e-13_r8) then - write(iulog,*) 'dzmin_orig =', dzmin_orig - call endrun(msg="ERROR dzmin_orig /= dzmin"// & - errMsg(sourcefile, __LINE__)) - else - dzmin(1:nlevsno) = dzmin_orig(1:nlevsno) - end if - dzmax_u_orig = (/ 0.02_r8, 0.05_r8, 0.11_r8, 0.23_r8, 0.47_r8, 0.95_r8, & - 1.91_r8, 3.83_r8, 7.67_r8, 15.35_r8, 30.71_r8, huge(1._r8) /) - if (maxval(abs(dzmax_u(1:nlevsno-1) - dzmax_u_orig(1:nlevsno-1))) > 1.e-13_r8) then - write(iulog,*) 'dzmax_u_orig =', dzmax_u_orig - call endrun(msg="ERROR dzmax_u_orig /= dzmax_u"// & - errMsg(sourcefile, __LINE__)) - else - dzmax_u(1:nlevsno-1) = dzmax_u_orig(1:nlevsno-1) - end if - dzmax_l_orig = (/ 0.03_r8, 0.07_r8, 0.18_r8, 0.41_r8, 0.88_r8, 1.83_r8, & - 3.74_r8, 7.57_r8, 15.24_r8, 30.59_r8, 61.30_r8, huge(1._r8) /) - if (maxval(abs(dzmax_l(1:nlevsno-1) - dzmax_l_orig(1:nlevsno-1))) > 1.e-13_r8) then - write(iulog,*) 'dzmax_l_orig =', dzmax_l_orig - call endrun(msg="ERROR dzmax_l_orig /= dzmax_l"// & - errMsg(sourcefile, __LINE__)) - else - dzmax_l(1:nlevsno-1) = dzmax_l_orig(1:nlevsno-1) - end if - ! END TEMPORARY TESTING slevis diag - loop_columns: do c = bounds%begc,bounds%endc l = col%landunit(c) From bd7f647c7e562278c679412fee796d03a8a12b61 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 9 Sep 2019 13:02:32 -0600 Subject: [PATCH 15/17] Updates needed for snowhydrology unit tests to pass --- src/biogeophys/SnowHydrologyMod.F90 | 23 +++++++++++++++++++ .../test_SnowHydrology_initSnowLayers.pf | 3 +++ 2 files changed, 26 insertions(+) diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index fb29889ac7..cad47e2858 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -47,6 +47,7 @@ module SnowHydrologyMod private ! ! !PUBLIC MEMBER FUNCTIONS: + public :: SnowHydrologyClean ! Deallocate variables for unit testing public :: SnowHydrology_readnl ! Read namelist public :: UpdateQuantitiesForNewSnow ! Update various snow-related quantities to account for new snow public :: RemoveSnowFromThawedWetlands ! Remove snow from thawed wetlands @@ -3012,7 +3013,29 @@ subroutine SnowHydrologySetControlForTesting( set_winddep_snowdensity, set_new_s if (present(set_reset_snow_glc_ela)) then reset_snow_glc_ela = set_reset_snow_glc_ela end if + snow_dzmin_1 = 0.010_r8 ! The same default values specified in... + snow_dzmin_2 = 0.015_r8 ! /bld/namelist_files/namelist_defaults_ctsm.xml + snow_dzmax_l_1 = 0.03_r8 ! and used when alternate values do not + snow_dzmax_l_2 = 0.07_r8 ! get set in + snow_dzmax_u_1 = 0.02_r8 ! user_nl_clm + snow_dzmax_u_2 = 0.05_r8 end subroutine SnowHydrologySetControlForTesting + !----------------------------------------------------------------------- + subroutine SnowHydrologyClean() + ! + ! !DESCRIPTION: + ! Deallocate memory + ! + ! !LOCAL VARIABLES: + character(len=*), parameter :: subname = 'Clean' + !----------------------------------------------------------------------- + + deallocate(dzmin) + deallocate(dzmax_l) + deallocate(dzmax_u) + + end subroutine SnowHydrologyClean + end module SnowHydrologyMod diff --git a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf index 2d6dcee480..ab1ab810fb 100644 --- a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf +++ b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf @@ -28,6 +28,7 @@ contains subroutine tearDown(this) class(TestSnowHydrology), intent(inout) :: this call unittest_subgrid_teardown() + call SnowHydrologyClean() end subroutine tearDown @Test @@ -37,6 +38,7 @@ contains ! Setup nlevsno = 5 + call SnowHydrologySetControlForTesting() call setup_single_veg_patch(pft_type = 1) allocate(snow_depth(bounds%begc:bounds%endc)) snow_depth(:) = 0._r8 @@ -57,6 +59,7 @@ contains ! Setup nlevsno = 5 + call SnowHydrologySetControlForTesting() call setup_single_veg_patch(pft_type = 1) allocate(snow_depth(bounds%begc:bounds%endc)) snow_depth(:) = 1._r8 From 4c19afcc688d016628e76d353a0d8125d745fc83 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 9 Sep 2019 13:22:22 -0600 Subject: [PATCH 16/17] Updated ChangeLog/Sum --- doc/ChangeLog | 17 +++++++++-------- doc/ChangeSum | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index ef16662b62..e34cf34c86 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,7 @@ =============================================================== Tag name: ctsm1.0.dev064 Originator(s): slevis (Samuel Levis,SLevis Consulting LLC,303-665-1310) -Date: Sat Sep 7 17:19:17 MDT 2019 +Date: Mon Sep 9 13:14:51 MDT 2019 One-line Summary: User defined top-two snow layers Purpose of changes @@ -18,10 +18,11 @@ Purpose of changes where the right-hand-side variables get namelist-defined values and the model calculates dzmin and dzmax_* for the remaining snow layers using - recursive formulas. The calculation is intended to match the hardcoded - values, except for the bottom snow layer when nlevsno < 12. The bottom - layer now always gets dzmax_* = huge(1._r8). The formulas appear in a - document titled "A firn model for CLM" that has been linked to #729. + recursive formulas. The calculation is intended to match the previously + hardcoded values, except for the bottom snow layer when nlevsno < 12. + The bottom layer now always gets dzmax_* = huge(1._r8). The formulas + appear in a document titled "A firn model for CLM" that is linked to + #729. Bugs fixed or introduced @@ -56,7 +57,7 @@ Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): Changes made to namelist defaults (e.g., changed parameter values): Introduced default values for the new parameters so as to maintain - bit-for-bit same answers + same answers to within roundoff Changes to the datasets (e.g., parameter, surface or initial files): none @@ -95,8 +96,8 @@ CTSM testing: regular tests (aux_clm): - cheyenne ---- - izumi ------- + cheyenne ---- OK + izumi ------- OK If the tag used for baseline comparisons was NOT the previous tag, note that here: diff --git a/doc/ChangeSum b/doc/ChangeSum index bbef06b216..0021654c7c 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,6 +1,6 @@ Tag Who Date Summary ============================================================================================================================ - ctsm1.0.dev064 slevis 09/06/2019 User defined top-two snow layers + ctsm1.0.dev064 slevis 09/09/2019 User defined top-two snow layers ctsm1.0.dev063 erik 09/05/2019 Two answer changing fixes (fire, DWT_SLASH) and fix for urban streams for Clm45 ctsm1.0.dev062 sacks 09/03/2019 Move hobart tests to izumi ctsm1.0.dev061 erik 09/01/2019 Simple b4b fixes: new params file, remove override_nsrest/anoxia_wtsat, DV deprecated From 1d5ea12775c282eefeea444a6e007bb25d03ac58 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Mon, 9 Sep 2019 16:04:54 -0600 Subject: [PATCH 17/17] Minor edit in ChangeLog --- doc/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index e34cf34c86..4a30c34c9e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -105,7 +105,7 @@ If the tag used for baseline comparisons was NOT the previous tag, note that her Answer changes -------------- -Changes answers relative to baseline: +Changes answers relative to baseline: YES Summarize any changes to answers, i.e., - what code configurations: all