diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 083ce3b667..3f158d6275 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -5405,6 +5405,7 @@ sub write_output_files { soil_resis_inparm bgc_shared canopyfluxes_inparm aerosol clmu_inparm clm_soilstate_inparm clm_nitrogen clm_snowhydrology_inparm hillslope_hydrology_inparm hillslope_properties_inparm cnprecision_inparm clm_glacier_behavior crop_inparm irrigation_inparm + debug surfacealbedo_inparm water_tracers_inparm tillage_inparm); #@groups = qw(clm_inparm clm_canopyhydrology_inparm clm_soilhydrology_inparm diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index ef5e6919db..8eec8e0fe1 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -2797,4 +2797,13 @@ lnd/clm2/surfdata_esmf/NEON/ctsm5.4.0/surfdata_1x1_NEON_TOOL_hist_2000_78pfts_c2 .false. 0.26d00 + + + + +-999 +-999 +-999 +-999 + diff --git a/bld/namelist_files/namelist_definition.xsl b/bld/namelist_files/namelist_definition.xsl index 7917cc262f..2719d1a4ca 100644 --- a/bld/namelist_files/namelist_definition.xsl +++ b/bld/namelist_files/namelist_definition.xsl @@ -185,6 +185,19 @@ + + + + + + + + + + + +
CLM Debugging
NameTypeDescription
Valid values
+


diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 179704e518..e1936f6ac4 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -3267,4 +3267,28 @@ Toggle to use original (Graham et al. 2021) tillage logic, with bug for seasons Maximum depth to till soil (m). Default 0.26; original (Graham et al., 2021) value was unintentionally 0.32. + + + + + +Global index of patch to debug. + + + +Global index of column to debug. + + + +Global index of landunit to debug. + + + +Global index of gridcell to debug. + + diff --git a/ccs_config b/ccs_config index 39683243b4..7020eb9a16 160000 --- a/ccs_config +++ b/ccs_config @@ -1 +1 @@ -Subproject commit 39683243b4e8e5b4576fd1b828c3ec4c9e15bc6b +Subproject commit 7020eb9a16a2c1cde7b7fbb588e08dbb7b1ce85c diff --git a/cime b/cime index 51cfec52f2..d5e1e034b6 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit 51cfec52f297eb4d30dd34548bf4b69b9ab72d1e +Subproject commit d5e1e034b6b8568f02bcae1091a689212f86b382 diff --git a/components/cmeps b/components/cmeps index ebcfeafa52..480bfc1502 160000 --- a/components/cmeps +++ b/components/cmeps @@ -1 +1 @@ -Subproject commit ebcfeafa524f29181058f64809d165a58733236e +Subproject commit 480bfc1502d42ae1decdc56c731f0dd80fbf9139 diff --git a/libraries/parallelio b/libraries/parallelio index 39e5584411..1d516b8276 160000 --- a/libraries/parallelio +++ b/libraries/parallelio @@ -1 +1 @@ -Subproject commit 39e558441197b0b98f69b989708b3df22a5d7438 +Subproject commit 1d516b82768ef9d2cade524724c38ab63fbe08e4 diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index 4530fda860..65c88e75fc 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -183,6 +183,7 @@ subroutine initialize2(ni,nj, currtime) use FATESFireFactoryMod , only : scalar_lightning use dynFATESLandUseChangeMod , only : dynFatesLandUseInit use HillslopeHydrologyMod , only : InitHillslope + use debugMod , only : debugMod_init ! ! !ARGUMENTS integer, intent(in) :: ni, nj ! global grid sizes @@ -309,6 +310,9 @@ subroutine initialize2(ni,nj, currtime) call decompInit_glcp(ni, nj, glc_behavior) call t_stopf('clm_decompInit_glcp') + ! Initialize debugMod early so we can use its functions as soon as possible + call debugMod_init() + if (use_hillslope) then ! Initialize hillslope properties call InitHillslope(bounds_proc, hillslope_file) diff --git a/src/main/debugMod.F90 b/src/main/debugMod.F90 new file mode 100644 index 0000000000..330b183121 --- /dev/null +++ b/src/main/debugMod.F90 @@ -0,0 +1,254 @@ +module debugMod + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Provides a place to define gridcells, landunits, columns, and/or patches that we want debug + ! output for, as well as functions for checking whether a given g/l/c/p is being debugged. + ! + ! !USES: +#include "shr_assert.h" + use abortutils , only : endrun + use decompMod , only : subgrid_level_gridcell, subgrid_level_landunit + use decompMod , only : subgrid_level_column, subgrid_level_patch + use decompMod , only : get_global_index + ! + ! !PUBLIC TYPES: + implicit none + private + ! + ! !PUBLIC MEMBER SUBROUTINES AND FUNCTIONS: + public :: debugMod_init + public :: do_debug_patch + public :: do_debug_column + public :: do_debug_landunit + public :: do_debug_gridcell + ! + ! !PRIVATE MEMBER DATA: + + ! Global indices for objects to debug. + integer :: debug_p + integer :: debug_c + integer :: debug_l + integer :: debug_g + + character(len=*), parameter, private :: sourcefile = __FILE__ + !----------------------------------------------------------------------- + +contains + + !----------------------------------------------------------------------- + subroutine debugMod_init() + ! + ! Handle namelist variables + ! + ! !USES: + use clm_varctl , only : iulog + use spmdMod , only : masterproc, mpicom + use controlMod , only : NLFilename + use clm_nlUtilsMod , only : find_nlgroup_name + use shr_mpi_mod , only : shr_mpi_bcast + ! + ! !LOCAL VARIABLES: + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + integer :: nml_debug + !----------------------------------------------------------------------- + + namelist /debug/ & + debug_p, & + debug_c, & + debug_l, & + debug_g + + ! Default namelist variable values + debug_p = -999 + debug_c = -999 + debug_l = -999 + debug_g = -999 + + ! Read namelist + if (masterproc) then + open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call find_nlgroup_name(nu_nml, 'debug', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=debug,iostat=nml_error) + if (nml_error /= 0) then + call endrun('ERROR reading debug namelist') + end if + else + call endrun('ERROR finding debug namelist') + end if + close(nu_nml) + + ! Print values + write(iulog,*) + write(iulog,*) 'Debug settings:' + write(iulog, '(a,i8)') ' debug_p = ', debug_p + write(iulog, '(a,i8)') ' debug_c = ', debug_c + write(iulog, '(a,i8)') ' debug_l = ', debug_l + write(iulog, '(a,i8)') ' debug_g = ', debug_g + endif + call shr_mpi_bcast(debug_p, mpicom) + call shr_mpi_bcast(debug_c, mpicom) + call shr_mpi_bcast(debug_l, mpicom) + call shr_mpi_bcast(debug_g, mpicom) + + + end subroutine debugMod_init + + !----------------------------------------------------------------------- + function do_debug_patch(i_local, i_global) result(do_debug) + ! + ! !DESCRIPTION: + ! Return .true. if the given global patch index is the one we're debugging; .false. otherwise. + ! Provide only i_local or i_global. + ! + ! !ARGUMENTS: + integer, optional :: i_local ! Local patch index + integer, optional :: i_global ! Global patch index + ! + ! !RESULT: + logical :: do_debug + integer :: i ! Global patch index + !----------------------------------------------------------------------- + + ! This makes it so that compilers should build this function as a simple boolean if we haven't + ! requested any patch to be debugged, which reduces performance cost in production runs. + if (debug_p < 1) then + do_debug = .false. + return + end if + + if (present(i_global)) then + call shr_assert(.not. present(i_local), file=sourcefile, line=__LINE__) + call shr_assert(i_global >= 1, file=sourcefile, line=__LINE__) + i = i_global + else + call shr_assert(present(i_local), file=sourcefile, line=__LINE__) + i = get_global_index(subgrid_index=i_local, subgrid_level=subgrid_level_patch, & + donot_abort_on_badindex=.false.) + end if + + do_debug = i == debug_p + return + + end function do_debug_patch + + !----------------------------------------------------------------------- + function do_debug_column(i_local, i_global) result(do_debug) + ! + ! !DESCRIPTION: + ! Return .true. if the given global column index is the one we're debugging; .false. otherwise. + ! Provide only i_local or i_global. + ! + ! !ARGUMENTS: + integer, optional :: i_local ! Local column index + integer, optional :: i_global ! Global column index + ! + ! !RESULT: + logical :: do_debug + integer :: i ! Global column index + !----------------------------------------------------------------------- + + ! This makes it so that compilers should build this function as a simple boolean if we haven't + ! requested any column to be debugged, which reduces performance cost in production runs. + if (debug_c < 1) then + do_debug = .false. + return + end if + + if (present(i_global)) then + call shr_assert(.not. present(i_local), file=sourcefile, line=__LINE__) + call shr_assert(i_global >= 1, file=sourcefile, line=__LINE__) + i = i_global + else + call shr_assert(present(i_local), file=sourcefile, line=__LINE__) + i = get_global_index(subgrid_index=i_local, subgrid_level=subgrid_level_column, & + donot_abort_on_badindex=.false.) + end if + + do_debug = i == debug_c + return + + end function do_debug_column + + !----------------------------------------------------------------------- + function do_debug_landunit(i_local, i_global) result(do_debug) + ! + ! !DESCRIPTION: + ! Return .true. if the given global landunit index is the one we're debugging; .false. otherwise. + ! Provide only i_local or i_global. + ! + ! !ARGUMENTS: + integer, optional :: i_local ! Local landunit index + integer, optional :: i_global ! Global landunit index + ! + ! !RESULT: + logical :: do_debug + integer :: i ! Global landunit index + !----------------------------------------------------------------------- + + ! This makes it so that compilers should build this function as a simple boolean if we haven't + ! requested any landunit to be debugged, which reduces performance cost in production runs. + if (debug_l < 1) then + do_debug = .false. + return + end if + + if (present(i_global)) then + call shr_assert(.not. present(i_local), file=sourcefile, line=__LINE__) + call shr_assert(i_global >= 1, file=sourcefile, line=__LINE__) + i = i_global + else + call shr_assert(present(i_local), file=sourcefile, line=__LINE__) + i = get_global_index(subgrid_index=i_local, subgrid_level=subgrid_level_landunit, & + donot_abort_on_badindex=.false.) + end if + + do_debug = i == debug_l + return + + end function do_debug_landunit + + !----------------------------------------------------------------------- + function do_debug_gridcell(i_local, i_global) result(do_debug) + ! + ! !DESCRIPTION: + ! Return .true. if the given global gridcell index is the one we're debugging; .false. otherwise. + ! Provide only i_local or i_global. + ! + ! !ARGUMENTS: + integer, optional :: i_local ! Local gridcell index + integer, optional :: i_global ! Global gridcell index + ! + ! !RESULT: + logical :: do_debug + integer :: i ! Global gridcell index + !----------------------------------------------------------------------- + + ! This makes it so that compilers should build this function as a simple boolean if we haven't + ! requested any gridcell to be debugged, which reduces performance cost in production runs. + if (debug_g < 1) then + do_debug = .false. + return + end if + + if (present(i_global)) then + call shr_assert(.not. present(i_local), file=sourcefile, line=__LINE__) + call shr_assert(i_global >= 1, file=sourcefile, line=__LINE__) + i = i_global + else + call shr_assert(present(i_local), file=sourcefile, line=__LINE__) + i = get_global_index(subgrid_index=i_local, subgrid_level=subgrid_level_gridcell, & + donot_abort_on_badindex=.false.) + end if + + do_debug = i == debug_g + return + + end function do_debug_gridcell + +end module debugMod + + +