diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index b881cdbfac..592699cc2b 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -2759,8 +2759,7 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { # this check has to be here and not earlier since use_init_interp is set here and hillslope is already set above in setup_logic_hillslope if ( &value_is_true($nl->get_value($useinitvar)) && value_is_true($nl->get_value("use_hillslope")) ) { - $log->warning("WARNING: You have set use_hillslope while $useinitvar is TRUE.\n This means all hillslope columns in a gridcell will read identical values" . - " from initial conditions. If you are sure you want this behaviour:") + $log->warning("WARNING: You have set use_hillslope while $useinitvar is TRUE.\n This means all hillslope columns in a gridcell will read identical values from initial conditions, even if the initial conditions (finidat) file has hillslope information. If you are sure you want this behaviour, add -ignore_warnings to CLM_BLDNML_OPTS.") } } # end initial conditions @@ -3637,6 +3636,10 @@ sub setup_logic_hillslope { if ( (! &value_is_true($use_hillslope)) && &value_is_true($use_hillslope_routing) ) { $log->fatal_error("Cannot turn on use_hillslope_routing when use_hillslope is off\n" ); } + my $hillslope_file = $nl->get_value('hillslope_file'); + if ( &value_is_true($use_hillslope) && ( ! defined($hillslope_file) ) ) { + $log->fatal_error("You must provide hillslope_file if use_hillslope is .true.\n" ); + } } #------------------------------------------------------------------------------- diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 417444914e..4de0d3199c 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -962,6 +962,11 @@ Full pathname datafile with fates parameters Full pathname of surface data file. + +Full pathname of hillslope data file. + + SNICAR (SNow, ICe, and Aerosol Radiative model) optical data file name diff --git a/cime_config/testdefs/ExpectedTestFails.xml b/cime_config/testdefs/ExpectedTestFails.xml index 7b17d5743b..3b80016f82 100644 --- a/cime_config/testdefs/ExpectedTestFails.xml +++ b/cime_config/testdefs/ExpectedTestFails.xml @@ -245,13 +245,6 @@ - - - FAIL - #2423 - - - FAIL diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 0eb3d5012d..2b6a35f9eb 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -1773,7 +1773,7 @@ - + @@ -3511,23 +3511,24 @@ - + + - + - + - + diff --git a/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands index a2759b51b4..9cef7eb66f 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands @@ -1,7 +1,19 @@ ./xmlchange CLM_BLDNML_OPTS="-bgc sp" DIN_LOC_ROOT=$(./xmlquery --value DIN_LOC_ROOT) -meshfile=$DIN_LOC_ROOT/lnd/clm2/testdata/ESMFmesh_10x15_synthetic_cosphill_1.0.nc -./xmlchange ATM_DOMAIN_MESH=${meshfile},LND_DOMAIN_MESH=${meshfile} + +# Set hillslope_file. Needed for any grids without default hillslope_file already set by CTSM. +lnd_grid=$(./xmlquery --value LND_GRID) +if [[ ${lnd_grid} == "10x15" ]]; then + # Synthetic data + hillslope_file='$DIN_LOC_ROOT/lnd/clm2/testdata/surfdata_10x15_hist_1850_78pfts_c240216.synth_hillslopes_241001.nc' +elif [[ ${lnd_grid} == "5x5_amazon" ]]; then + # Real data + hillslope_file='/glade/derecho/scratch/samrabin/hillslopes_5x5_amazon/hand_analysis_global/combined/hilldata_5x5_amazon_hist_2000_78pfts_c240216.nc' +else + echo "ERROR: Hillslope file not found for LND_GRID=${lnd_grid}" >&2 + exit 1 +fi +echo -e "hillslope_file = '${hillslope_file}'\n" >> user_nl_clm # -ignore_warnings is needed as long as we don't allow use_hillslope and use_init_interp together ./xmlchange --append CLM_BLDNML_OPTS=-ignore_warnings diff --git a/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm index d27565d98f..e108e93d91 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm @@ -6,6 +6,4 @@ hillslope_transmissivity_method = 'LayerSum' hillslope_pft_distribution_method = 'PftLowlandUpland' hillslope_soil_profile_method = 'Uniform' -fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/surfdata_10x15_hist_2000_78pfts_c240905.synthetic_hillslopes3.nc' - use_ssre = .false. diff --git a/src/biogeophys/HillslopeHydrologyMod.F90 b/src/biogeophys/HillslopeHydrologyMod.F90 index b2866df679..8fccd762f0 100644 --- a/src/biogeophys/HillslopeHydrologyMod.F90 +++ b/src/biogeophys/HillslopeHydrologyMod.F90 @@ -168,7 +168,7 @@ end subroutine check_aquifer_layer !----------------------------------------------------------------------- - subroutine InitHillslope(bounds,fsurdat) + subroutine InitHillslope(bounds, hillslope_file) ! ! !DESCRIPTION: ! Initialize hillslope geomorphology from input dataset @@ -187,7 +187,7 @@ subroutine InitHillslope(bounds,fsurdat) ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds - character(len=*) , intent(in) :: fsurdat ! surface data file name + character(len=*) , intent(in) :: hillslope_file ! hillslope data file name integer, pointer :: ihillslope_in(:,:) ! read in - integer integer, pointer :: ncolumns_hillslope_in(:) ! read in number of columns integer, allocatable :: ncolumns_hillslope(:) ! number of hillslope columns @@ -224,9 +224,9 @@ subroutine InitHillslope(bounds,fsurdat) ! consistency check call check_aquifer_layer() - ! Open surface dataset to read in data below + ! Open hillslope dataset to read in data below - call getfil (fsurdat, locfn, 0) + call getfil (hillslope_file, locfn, 0) call ncd_pio_openfile (ncid, locfn, 0) allocate( & @@ -248,7 +248,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='nhillcolumns', flag='read', data=ncolumns_hillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: nhillcolumns not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: nhillcolumns not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -266,7 +266,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='pct_hillslope', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: pct_hillslope not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: pct_hillslope not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -278,7 +278,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_index', flag='read', data=ihillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_index not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_index not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -287,7 +287,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='column_index', flag='read', data=ihillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: column_index not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: column_index not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -296,7 +296,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='downhill_column_index', flag='read', data=ihillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: downhill_column_index not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: downhill_column_index not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -307,7 +307,7 @@ subroutine InitHillslope(bounds,fsurdat) allocate(fhillslope_in(bounds%begg:bounds%endg,max_columns_hillslope)) call ncd_io(ncid=ncid, varname='hillslope_slope', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_slope not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_slope not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl @@ -317,7 +317,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_aspect', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_aspect not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_aspect not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl @@ -327,7 +327,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_area', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_area not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_area not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -335,7 +335,7 @@ subroutine InitHillslope(bounds,fsurdat) enddo call ncd_io(ncid=ncid, varname='hillslope_distance', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_length not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_distance not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl @@ -345,7 +345,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_width', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_width not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_width not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -354,7 +354,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_elevation', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_height not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_elevation not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -380,7 +380,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_stream_depth', flag='read', data=fstream_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_stream_depth not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_stream_depth not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -389,7 +389,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_stream_width', flag='read', data=fstream_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_stream_width not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_stream_width not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -398,7 +398,7 @@ subroutine InitHillslope(bounds,fsurdat) call ncd_io(ncid=ncid, varname='hillslope_stream_slope', flag='read', data=fstream_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: hillslope_stream_slope not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_stream_slope not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -504,11 +504,11 @@ subroutine InitHillslope(bounds,fsurdat) enddo end if - ! if missing hillslope information on surface dataset, + ! if missing hillslope information on dataset, ! call endrun if (ncolumns_hillslope(l) > 0 .and. sum(hillslope_area) == 0._r8 .and. masterproc) then write(iulog,*) 'Problem with input data: nhillcolumns is non-zero, but hillslope area is zero' - write(iulog,*) 'Check surface data for gridcell at (lon/lat): ', grc%londeg(g),grc%latdeg(g) + write(iulog,*) 'Check hillslope data for gridcell at (lon/lat): ', grc%londeg(g),grc%latdeg(g) call endrun( 'ERROR:: sum of hillslope areas is zero.'//errmsg(sourcefile, __LINE__) ) end if @@ -559,7 +559,7 @@ end subroutine InitHillslope !----------------------------------------------------------------------- - subroutine SetHillslopeSoilThickness(bounds,fsurdat,soil_depth_lowland_in,soil_depth_upland_in) + subroutine SetHillslopeSoilThickness(bounds, hillslope_file, soil_depth_lowland_in, soil_depth_upland_in) ! ! !DESCRIPTION: ! Set hillslope column nbedrock values @@ -578,7 +578,7 @@ subroutine SetHillslopeSoilThickness(bounds,fsurdat,soil_depth_lowland_in,soil_d ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds - character(len=*) , intent(in) :: fsurdat ! surface data file name + character(len=*) , intent(in) :: hillslope_file ! hillslope data file name real(r8), intent(in), optional :: soil_depth_lowland_in real(r8), intent(in), optional :: soil_depth_upland_in real(r8), pointer :: fhillslope_in(:,:) ! read in - float @@ -599,14 +599,14 @@ subroutine SetHillslopeSoilThickness(bounds,fsurdat,soil_depth_lowland_in,soil_d if (soil_profile_method==soil_profile_from_file) then - ! Open surface dataset to read in data below - call getfil (fsurdat, locfn, 0) + ! Open hillslope dataset to read in data below + call getfil (hillslope_file, locfn, 0) call ncd_pio_openfile (ncid, locfn, 0) allocate(fhillslope_in(bounds%begg:bounds%endg,max_columns_hillslope)) call ncd_io(ncid=ncid, varname='hillslope_bedrock_depth', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) if (masterproc .and. .not. readvar) then - call endrun( 'ERROR:: soil_profile_method = "FromFile", but hillslope_bedrock not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: soil_profile_method = "FromFile", but hillslope_bedrock not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl g = lun%gridcell(l) @@ -896,7 +896,7 @@ end subroutine HillslopeDominantLowlandPft subroutine HillslopePftFromFile(bounds,col_pftndx) ! ! !DESCRIPTION: - ! Reassign patch type using indices from surface data file + ! Reassign patch type using indices from data file ! Assumes one patch per hillslope column ! In preparation for this reassignment of patch type, only the ! first patch was given a non-zero weight in surfrd_hillslope. diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index bf9a97ae58..e3d9eeda06 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -136,8 +136,8 @@ subroutine initialize2(ni,nj) use clm_varpar , only : surfpft_lb, surfpft_ub use clm_varpar , only : nlevsno use clm_varpar , only : natpft_size,cft_size - use clm_varctl , only : fsurdat - use clm_varctl , only : finidat, finidat_interp_source, finidat_interp_dest, fsurdat + use clm_varctl , only : fsurdat, hillslope_file + use clm_varctl , only : finidat, finidat_interp_source, finidat_interp_dest use clm_varctl , only : use_cn, use_fates, use_fates_luh use clm_varctl , only : use_crop, ndep_from_cpl, fates_spitfire_mode use clm_varctl , only : use_hillslope @@ -254,7 +254,7 @@ subroutine initialize2(ni,nj) call pftcon%Init() ! Read surface dataset and set up subgrid weight arrays - call surfrd_get_data(begg, endg, ldomain, fsurdat, actual_numcft) + call surfrd_get_data(begg, endg, ldomain, fsurdat, hillslope_file, actual_numcft) if(use_fates) then @@ -305,7 +305,7 @@ subroutine initialize2(ni,nj) if (use_hillslope) then ! Initialize hillslope properties - call InitHillslope(bounds_proc, fsurdat) + call InitHillslope(bounds_proc, hillslope_file) endif ! Set filters diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index ae83a1b31f..210cff2c2e 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -188,7 +188,7 @@ subroutine clm_instInit(bounds) ! ! !USES: use clm_varpar , only : nlevsno - use controlMod , only : nlfilename, fsurdat + use controlMod , only : nlfilename, fsurdat, hillslope_file use domainMod , only : ldomain use SoilBiogeochemDecompCascadeMIMICSMod, only : init_decompcascade_mimics use SoilBiogeochemDecompCascadeBGCMod , only : init_decompcascade_bgc @@ -280,7 +280,7 @@ subroutine clm_instInit(bounds) ! Set hillslope column bedrock values if (use_hillslope) then - call SetHillslopeSoilThickness(bounds,fsurdat, & + call SetHillslopeSoilThickness(bounds, hillslope_file, & soil_depth_lowland_in=8.5_r8,& soil_depth_upland_in =2.0_r8) call setSoilLayerClass(bounds) diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index cb7e2e3931..5fa2602e5a 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -109,6 +109,7 @@ module clm_varctl character(len=fname_len), public :: finidat = ' ' ! initial conditions file name character(len=fname_len), public :: fsurdat = ' ' ! surface data file name + character(len=fname_len), public :: hillslope_file = ' ' ! hillslope data file name character(len=fname_len), public :: paramfile = ' ' ! ASCII data file with PFT physiological constants character(len=fname_len), public :: nrevsn = ' ' ! restart data file name for branch run character(len=fname_len), public :: fsnowoptics = ' ' ! snow optical properties file name diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index f65c8c7f47..eedb678ca3 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -148,7 +148,7 @@ subroutine control_init(dtime) ! Input datasets namelist /clm_inparm/ & - fsurdat, & + fsurdat, hillslope_file, & paramfile, fsnowoptics, fsnowaging ! History, restart options @@ -736,6 +736,7 @@ subroutine control_spmd() call mpi_bcast (finidat_interp_source, len(finidat_interp_source), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (finidat_interp_dest, len(finidat_interp_dest), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fsurdat, len(fsurdat), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (hillslope_file, len(hillslope_file), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fatmlndfrc,len(fatmlndfrc),MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (paramfile, len(paramfile) , MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fsnowoptics, len(fsnowoptics), MPI_CHARACTER, 0, mpicom, ier) @@ -1021,6 +1022,11 @@ subroutine control_print () else write(iulog,*) ' surface data = ',trim(fsurdat) end if + if (hillslope_file == ' ') then + write(iulog,*) ' hillslope_file, hillslope dataset not set' + else + write(iulog,*) ' hillslope data = ',trim(hillslope_file) + end if if (fatmlndfrc == ' ') then write(iulog,*) ' fatmlndfrc not set, setting frac/mask to 1' else diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index 8ae4ace7e3..b2df9abfab 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -2328,6 +2328,7 @@ subroutine htape_create (t, histrest) use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, nlevdecomp_full, mxsowings, mxharvests use landunit_varcon , only : max_lunit use clm_varctl , only : caseid, ctitle, fsurdat, finidat, paramfile + use clm_varctl , only : hillslope_file use clm_varctl , only : version, hostname, username, conventions, source use clm_varctl , only : use_hillslope,nhillslope,max_columns_hillslope use domainMod , only : ldomain @@ -2428,6 +2429,8 @@ subroutine htape_create (t, histrest) call ncd_putatt(lnfid, ncd_global, 'case_id', trim(caseid)) str = get_filename(fsurdat) call ncd_putatt(lnfid, ncd_global, 'Surface_dataset', trim(str)) + str = get_filename(hillslope_file) + call ncd_putatt(lnfid, ncd_global, 'Hillslope_dataset', trim(str)) if (finidat == ' ') then str = 'arbitrary initialization' else diff --git a/src/main/restFileMod.F90 b/src/main/restFileMod.F90 index 6a574406fd..c7dbf0da72 100644 --- a/src/main/restFileMod.F90 +++ b/src/main/restFileMod.F90 @@ -503,6 +503,7 @@ subroutine restFile_dimset( ncid ) ! !USES: use clm_time_manager , only : get_nstep use clm_varctl , only : caseid, ctitle, version, username, hostname, fsurdat + use clm_varctl , only : hillslope_file use clm_varctl , only : conventions, source use dynSubgridControlMod , only : get_flanduse_timeseries use clm_varpar , only : numrad, nlevlak, nlevsno, nlevgrnd, nlevmaxurbgrnd, nlevcan @@ -569,6 +570,7 @@ subroutine restFile_dimset( ncid ) call ncd_putatt(ncid, NCD_GLOBAL, 'case_title' , trim(ctitle)) call ncd_putatt(ncid, NCD_GLOBAL, 'case_id' , trim(caseid)) call ncd_putatt(ncid, NCD_GLOBAL, 'surface_dataset', trim(fsurdat)) + call ncd_putatt(ncid, NCD_GLOBAL, 'hillslope_dataset', trim(hillslope_file)) call ncd_putatt(ncid, NCD_GLOBAL, 'flanduse_timeseries', trim(get_flanduse_timeseries())) call ncd_putatt(ncid, NCD_GLOBAL, 'title', 'CLM Restart information') diff --git a/src/main/surfrdMod.F90 b/src/main/surfrdMod.F90 index 88d43a09cc..4005ec7845 100644 --- a/src/main/surfrdMod.F90 +++ b/src/main/surfrdMod.F90 @@ -46,6 +46,83 @@ module surfrdMod contains + subroutine check_domain_attributes(ncid, begg, endg, ldomain, info) + ! !DESCRIPTION: + ! Checks for mismatches between the land domain and a surface or similar dataset's domain. + ! + ! !USES: + use domainMod, only : domain_type, domain_init, domain_clean + ! + ! !ARGUMENTS + type(file_desc_t), intent(inout) :: ncid ! netcdf id for input file + integer, intent(in) :: begg, endg + type(domain_type), intent(in) :: ldomain ! land domain + character(len=*), intent(in) :: info ! information to include in messages + ! + ! !LOCAL VARIABLES + type(domain_type) :: inputdata_domain ! local domain associated with input dataset + logical :: readvar ! true => variable is on dataset + logical :: istype_domain ! true => input file is of type domain + character(len=16) :: lon_var, lat_var ! names of lat/lon on dataset + logical :: isgrid2d ! true => input grid is 2d + integer :: ni, nj, ns ! domain sizes + integer :: n + real(r8) :: rmaxlon, rmaxlat ! local min/max vars + + character(len=32) :: subname = 'check_domain_attributes' ! subroutine name + + call check_var(ncid=ncid, varname='xc', readvar=readvar) + if (readvar) then + istype_domain = .true. + else + call check_var(ncid=ncid, varname='LONGXY', readvar=readvar) + if (readvar) then + istype_domain = .false. + else + call endrun( msg=' ERROR: unknown '//info//' domain type---'//errMsg(sourcefile, __LINE__)) + end if + end if + if (istype_domain) then + lon_var = 'xc' + lat_var = 'yc' + else + lon_var = 'LONGXY' + lat_var = 'LATIXY' + end if + if ( masterproc )then + write(iulog,*) trim(subname),' ',info,' lon_var = ',trim(lon_var),' lat_var =',trim(lat_var) + end if + + call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) + call domain_init(inputdata_domain, isgrid2d, ni, nj, begg, endg, subgrid_level=grlnd) + + call ncd_io(ncid=ncid, varname=lon_var, flag='read', data=inputdata_domain%lonc, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=' ERROR: lon var NOT on '//info//' dataset---'//errMsg(sourcefile, __LINE__)) + + call ncd_io(ncid=ncid, varname=lat_var, flag='read', data=inputdata_domain%latc, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=' ERROR: lat var NOT on '//info//' dataset---'//errMsg(sourcefile, __LINE__)) + + rmaxlon = 0.0_r8 + rmaxlat = 0.0_r8 + do n = begg,endg + if (ldomain%lonc(n)-inputdata_domain%lonc(n) > 300.) then + rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-inputdata_domain%lonc(n)-360._r8)) + elseif (ldomain%lonc(n)-inputdata_domain%lonc(n) < -300.) then + rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-inputdata_domain%lonc(n)+360._r8)) + else + rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-inputdata_domain%lonc(n))) + endif + rmaxlat = max(rmaxlat,abs(ldomain%latc(n)-inputdata_domain%latc(n))) + enddo + if (rmaxlon > 0.001_r8 .or. rmaxlat > 0.001_r8) then + write(iulog,*)' ERROR: '//info//' dataset vs. land domain lon/lat mismatch error', rmaxlon,rmaxlat + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + call domain_clean(inputdata_domain) + end subroutine check_domain_attributes + !----------------------------------------------------------------------- subroutine surfrd_compat_check ( lfsurdat ) ! @@ -111,7 +188,7 @@ subroutine surfrd_compat_check ( lfsurdat ) end subroutine surfrd_compat_check !----------------------------------------------------------------------- - subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) + subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, lhillslope_file, actual_numcft) ! ! !DESCRIPTION: ! Read the surface dataset and create subgrid weights. @@ -138,9 +215,10 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) use clm_varctl , only : create_crop_landunit, convert_ocean_to_land, collapse_urban, & toosmall_soil, toosmall_crop, toosmall_glacier, & toosmall_lake, toosmall_wetland, toosmall_urban, & - n_dom_landunits + n_dom_landunits, & + use_hillslope use fileutils , only : getfil - use domainMod , only : domain_type, domain_init, domain_clean + use domainMod , only : domain_type use clm_instur , only : wt_lunit, topo_glc_mec, pct_urban_max use landunit_varcon , only : max_lunit, istsoil, isturb_MIN, isturb_MAX use dynSubgridControlMod, only : get_flanduse_timeseries @@ -152,19 +230,13 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) integer, intent(in) :: begg, endg, actual_numcft type(domain_type),intent(in) :: ldomain ! land domain character(len=*), intent(in) :: lfsurdat ! surface dataset filename + character(len=*), intent(in) :: lhillslope_file ! hillslope dataset filename ! ! !LOCAL VARIABLES: - type(domain_type) :: surfdata_domain ! local domain associated with surface dataset character(len=256):: locfn ! local file name integer, parameter :: n_dom_urban = 1 ! # of dominant urban landunits - integer :: n ! loop indices - integer :: ni,nj,ns ! domain sizes - character(len=16) :: lon_var, lat_var ! names of lat/lon on dataset - logical :: readvar ! true => variable is on dataset - real(r8) :: rmaxlon,rmaxlat ! local min/max vars - type(file_desc_t) :: ncid ! netcdf id - logical :: istype_domain ! true => input file is of type domain - logical :: isgrid2d ! true => intut grid is 2d + type(file_desc_t) :: ncid ! netcdf id for lfsurdat + type(file_desc_t) :: ncid_hillslope ! netcdf id for lhillslope_file character(len=32) :: subname = 'surfrd_get_data' ! subroutine name !----------------------------------------------------------------------- @@ -175,6 +247,10 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) write(iulog,*)'lfsurdat must be specified' call endrun(msg=errMsg(sourcefile, __LINE__)) endif + if (use_hillslope .and. lhillslope_file == ' ') then + write(iulog,*)'lhillslope_file must be specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif endif wt_lunit(:,:) = 0._r8 @@ -184,71 +260,24 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) call getfil( lfsurdat, locfn, 0 ) call ncd_pio_openfile (ncid, trim(locfn), 0) - - ! Cmopare surfdat_domain attributes to ldomain attributes - - call check_var(ncid=ncid, varname='xc', readvar=readvar) - if (readvar) then - istype_domain = .true. - else - call check_var(ncid=ncid, varname='LONGXY', readvar=readvar) - if (readvar) then - istype_domain = .false. - else - call endrun( msg=' ERROR: unknown domain type'//errMsg(sourcefile, __LINE__)) - end if - end if - if (istype_domain) then - lon_var = 'xc' - lat_var = 'yc' - else - lon_var = 'LONGXY' - lat_var = 'LATIXY' - end if - if ( masterproc )then - write(iulog,*) trim(subname),' lon_var = ',trim(lon_var),' lat_var =',trim(lat_var) + if (use_hillslope) then + call getfil( lhillslope_file, locfn, 0 ) + call ncd_pio_openfile (ncid_hillslope, trim(locfn), 0) end if - call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) - call domain_init(surfdata_domain, isgrid2d, ni, nj, begg, endg, subgrid_level=grlnd) - - call ncd_io(ncid=ncid, varname=lon_var, flag='read', data=surfdata_domain%lonc, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: lon var NOT on surface dataset'//errMsg(sourcefile, __LINE__)) - - call ncd_io(ncid=ncid, varname=lat_var, flag='read', data=surfdata_domain%latc, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: lat var NOT on surface dataset'//errMsg(sourcefile, __LINE__)) - - rmaxlon = 0.0_r8 - rmaxlat = 0.0_r8 - do n = begg,endg - if (ldomain%lonc(n)-surfdata_domain%lonc(n) > 300.) then - rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-surfdata_domain%lonc(n)-360._r8)) - elseif (ldomain%lonc(n)-surfdata_domain%lonc(n) < -300.) then - rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-surfdata_domain%lonc(n)+360._r8)) - else - rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-surfdata_domain%lonc(n))) - endif - rmaxlat = max(rmaxlat,abs(ldomain%latc(n)-surfdata_domain%latc(n))) - enddo - if (rmaxlon > 0.001_r8 .or. rmaxlat > 0.001_r8) then - write(iulog,*)' ERROR: surfdata_domain/ldomain lon/lat mismatch error', rmaxlon,rmaxlat - call endrun(msg=errMsg(sourcefile, __LINE__)) + ! Compare dataset domain attributes to ldomain attributes + call check_domain_attributes(ncid, begg, endg, ldomain, 'surface') + if (use_hillslope) then + call check_domain_attributes(ncid_hillslope, begg, endg, ldomain, 'hillslope') end if - !~! TODO(SPM, 022015) - if we deallocate and clean ldomain here, then you - !~! get errors in htape_timeconst where the information is needed to write - !~! the *.h0* file - !~!call domain_clean(surfdata_domain) - ! Obtain special landunit info call surfrd_special(begg, endg, ncid, ldomain%ns) ! Obtain vegetated landunit info - call surfrd_veg_all(begg, endg, ncid, ldomain%ns, actual_numcft) + call surfrd_veg_all(begg, endg, ncid, ncid_hillslope, ldomain%ns, actual_numcft) if (use_cndv) then call surfrd_veg_dgvm(begg, endg) @@ -831,7 +860,7 @@ subroutine surfrd_pftformat( begg, endg, ncid ) end subroutine surfrd_pftformat !----------------------------------------------------------------------- - subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) + subroutine surfrd_veg_all(begg, endg, ncid, ncid_hillslope, ns, actual_numcft) ! ! !DESCRIPTION: ! Determine weight arrays for non-dynamic landuse mode @@ -848,7 +877,8 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ! !ARGUMENTS: implicit none integer, intent(in) :: begg, endg, actual_numcft - type(file_desc_t),intent(inout) :: ncid ! netcdf id + type(file_desc_t),intent(inout) :: ncid ! netcdf id for fsurdat + type(file_desc_t),intent(inout) :: ncid_hillslope ! netcdf id for hillslope_file integer ,intent(in) :: ns ! domain size ! ! !LOCAL VARIABLES: @@ -934,7 +964,7 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ! Obtain hillslope hydrology information and modify pft weights if (use_hillslope) then - call surfrd_hillslope(begg, endg, ncid, ns) + call surfrd_hillslope(begg, endg, ncid_hillslope, ns) endif ! Convert from percent to fraction