From 661993f723f85ca4e2e845b822214bb27d6da376 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 7 Feb 2024 19:54:48 -0700 Subject: [PATCH 1/7] Initial add of code to handle dust emissions, as per the document https://docs.google.com/document/d/18nZ3LJF5W-YF9iBhqed6s_NWeKOvSSL2-k0Lye1nnLg/, HAS NOT BEEN TESTED --- cesm/nuopc_cap_share/shr_dust_emis_mod.F90 | 204 +++++++++++++++++++ cime_config/namelist_definition_drv_flds.xml | 27 +++ 2 files changed, 231 insertions(+) create mode 100644 cesm/nuopc_cap_share/shr_dust_emis_mod.F90 diff --git a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 new file mode 100644 index 000000000..0e8ce424a --- /dev/null +++ b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 @@ -0,0 +1,204 @@ +module shr_dust_emis_mod + + !======================================================================== + ! Module for handling dust emissions. + ! This module is shared by land and atmosphere models for the computation of + ! dust emissions. + !======================================================================== + + use ESMF , only : ESMF_VMGetCurrent, ESMF_VM, ESMF_VMGet, ESMF_LOGMSG_INFO + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_SUCCESS + use ESMF , only : ESMF_LogWrite, ESMF_VMBroadCast + use shr_sys_mod , only : shr_sys_abort + use shr_kind_mod , only : CS => SHR_KIND_CS + use shr_nl_mod , only : shr_nl_find_group_name + use shr_log_mod , only : shr_log_getLogUnit, errMsg => shr_log_errMsg + use nuopc_shr_methods, only : chkerr + + implicit none + private + + ! public member functions + public :: shr_dust_emis_readnl ! Read namelist + public :: shr_dust_emis_init ! Initialization of dust emissions data (needed?) + public :: is_dust_emis_zender ! If Zender_2003 dust emission method is being used + public :: is_dust_emis_leung ! If Leungr_2023 dust emission method is being used + public :: is_zender_soil_erod_from_lnd ! If Zender_2003 is being used and soil eroditability is in land + public :: is_zender_soil_erod_from_atm ! If Zender_2003 is being used and soil eroditability is in atmosphere + + ! public data members: + private :: check_if_initialized ! Check if dust emission has been initialized + + ! PRIVATE DATA: + character(len=CS) :: dust_emis_method = 'Zender_2003' ! Dust emisison method to use: Zender_2003 or Leung_2023 + character(len=CS) :: zender_soil_erod_source = 'none' ! if calculed in lnd or atm (only when Zender_2003 is used) + logical :: dust_emis_initialized=.false. ! If dust emissions have been initiatlized yet or not + + character(len=*), parameter :: u_FILE_u = & + __FILE__ + +!=============================================================================== +CONTAINS +!=============================================================================== + + subroutine shr_dust_emis_readnl(NLFilename) + + !======================================================================== + ! reads dust_emis_inparm namelist to determine how dust emissions will + ! be handled between the land and atmosphere models + !======================================================================== + + character(len=*), intent(in) :: NLFilename ! Namelist filename + + !----- local ----- + integer :: i ! Indices + integer :: unitn ! namelist unit number + integer :: ierr ! error code + logical :: exists ! if file exists or not + type(ESMF_VM) :: vm + integer :: localPet + integer :: mpicom + integer :: s_logunit + integer :: rc + character(*),parameter :: F00 = "('(shr_dust_emis_read) ',8a)" + character(*),parameter :: subName = '(shr_dust_emis_read) ' + !----------------------------------------------------------------------------- + + namelist /dust_emis_inparm/ dust_emis_method, zender_soil_erod_source + + !----------------------------------------------------------------------------- + ! Read namelist, check if namelist file exists first + !----------------------------------------------------------------------------- + call ESMF_LogWrite(subname//' start', ESMF_LOGMSG_INFO) + + rc = ESMF_SUCCESS + + !--- Open and read namelist --- + if ( len_trim(NLFilename) == 0 )then + call shr_sys_abort( subName//'ERROR: nlfilename not set' ) + end if + + call ESMF_VMGetCurrent(vm, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return + + call ESMF_VMGet(vm, localPet=localPet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return + + call shr_log_getLogUnit(s_logunit) + if (localPet==0) then + inquire( file=trim(NLFileName), exist=exists) + if ( exists ) then + open(newunit=unitn, file=trim(NLFilename), status='old' ) + write(s_logunit,F00) 'Read in dust_emis_inparm namelist from: ', trim(NLFilename) + call shr_nl_find_group_name(unitn, 'dust_emis_inparm', ierr) + if (ierr == 0) then + ! Note that ierr /= 0, no namelist is present. + read(unitn, dust_emis_inparm, iostat=ierr) + if (ierr > 0) then + call shr_sys_abort( subName//'ERROR:: problem on read of dust_emis_inparm ' & + // 'namelist in shr_dust_emis_readnl') + end if + endif + close( unitn ) + end if + end if + call ESMF_LogWrite(subname//' bcast dust_emis_method', ESMF_LOGMSG_INFO) + call ESMF_VMBroadcast(vm, dust_emis_method, CS, 0, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return + call ESMF_LogWrite(subname//' bcast zender_soil_erod_source', ESMF_LOGMSG_INFO) + call ESMF_VMBroadcast(vm, zender_soil_erod_source, CS, 0, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return + + ! Some error checking + if (trim(dust_emis_method) == 'Leung_2023') then + if ( trim(zender_soil_erod_source) /= 'none' )then + call shr_sys_abort(subName//"ERROR: zender_soil_erod_source should NOT be set, when dust_emis_method=Leung_2023 " & + //errMsg(u_FILE_u, __LINE__)) + end if + else if (trim(dust_emis_method) == 'Zender_2003') then + if ( (trim(zender_soil_erod_source) /= 'lnd') .and. (trim(zender_soil_erod_source) /= 'atm') )then + write(s_logunit,*) 'zender_soil_erod_source is NOT valid = ', trim(zender_soil_erod_source) + call shr_sys_abort(subName//"ERROR: zender_soil_erod_source can only be lnd or atm" & + //errMsg(u_FILE_u, __LINE__)) + end if + else + write(s_logunit,*) 'dust_emis_method not recognized = ', trim(dust_emis_method) + call shr_sys_abort(subName//"ERROR: dust_emis_method namelist item is not valid " & + //errMsg(u_FILE_u, __LINE__)) + end if + + call ESMF_LogWrite(subname//' done', ESMF_LOGMSG_INFO) + dust_emis_initialized = .true. + + end subroutine shr_dust_emis_readnl + +!==================================================================================== + + logical function is_dust_emis_zender() + ! is_dust_emis_zender – Logical function, true if the Zender 2003 scheme is being used + call check_if_initiatlized() + if (trim(dust_emis_method) == 'Zender_2003') then + is_dust_emis_zender = .true. + else + is_dust_emis_zender = .false. + end if + end function is_dust_emis_zender + +!=============================================================================== + + logical function is_dust_emis_leung() + ! is_dust_emis_leung – Logical function, true if the Leung 2023 scheme is being used + call check_if_initiatlized() + if (trim(dust_emis_method) == 'Leung_2023') then + is_dust_emis_leung = .true. + else + is_dust_emis_leung = .false. + end if + end function is_dust_emis_leung + +!=============================================================================== + + logical function is_zender_soil_erod_from_land() + ! is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CTSM + call check_if_initiatlized() + if is_dust_emis_zender() )then + if (trim(zender_soil_erod_source) == 'lnd') then + is_zender_soil_erod_from_land = .true. + else + is_zender_soil_erod_from_land = .false. + end if + else + is_zender_soil_erod_from_land = .false. + end if + end function is_zender_soil_erod_from_land + +!=============================================================================== + + logical function is_zender_soil_erod_from_atm() + !is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CAM + call check_if_initiatlized() + if is_dust_emis_zender() )then + if (trim(zender_soil_erod_source) == 'atm') then + is_zender_soil_erod_from_land = .true. + else + is_zender_soil_erod_from_land = .false. + end if + else + is_zender_soil_erod_from_land = .false. + end if + end function is_zender_soil_erod_from_atm + +!=============================================================================== + + subroutine check_if_initiatlized() + if ( dust_emis_initialized )then + return + else + call shr_sys_abort( 'ERROR: dust emission namelist has NOT been read in yet,' & + ' shr_dust_emis_mod is NOT initialized '//errMsg(u_FILE_u, __LINE__ ) + end if + end subroutine check_if_initiatlized + +!=============================================================================== + +end module shr_dust_emis_mod diff --git a/cime_config/namelist_definition_drv_flds.xml b/cime_config/namelist_definition_drv_flds.xml index 03b6b7c6d..4d4ab1ec3 100644 --- a/cime_config/namelist_definition_drv_flds.xml +++ b/cime_config/namelist_definition_drv_flds.xml @@ -141,6 +141,33 @@ + + + + + + char*80 + dust_emissions + dust_emis_inparm + Zender_2003,Leung_2023 + + Which dust emission method is going to be used. Either the Zender 2003 scheme or the Leung 2023 + scheme. + + + + + char*80 + dust_emissions + dust_emis_inparm + none,lnd,atm + + Option only applying for the Zender_2003 method for whether the soil erodibility file is handled + in the active LAND model or in the ATM model. + (only used when dust_emis_method is Zender_2003) + + + From e22c4eafd595964d88a1077961a809a60b794431 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Tue, 9 Apr 2024 16:12:42 -0600 Subject: [PATCH 2/7] Get to compile with nag compiler on izumi --- cesm/nuopc_cap_share/shr_dust_emis_mod.F90 | 46 ++++++++++------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 index 0e8ce424a..51bcdf0ab 100644 --- a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 +++ b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 @@ -13,17 +13,15 @@ module shr_dust_emis_mod use shr_kind_mod , only : CS => SHR_KIND_CS use shr_nl_mod , only : shr_nl_find_group_name use shr_log_mod , only : shr_log_getLogUnit, errMsg => shr_log_errMsg - use nuopc_shr_methods, only : chkerr implicit none private ! public member functions public :: shr_dust_emis_readnl ! Read namelist - public :: shr_dust_emis_init ! Initialization of dust emissions data (needed?) public :: is_dust_emis_zender ! If Zender_2003 dust emission method is being used public :: is_dust_emis_leung ! If Leungr_2023 dust emission method is being used - public :: is_zender_soil_erod_from_lnd ! If Zender_2003 is being used and soil eroditability is in land + public :: is_zender_soil_erod_from_land ! If Zender_2003 is being used and soil eroditability is in land public :: is_zender_soil_erod_from_atm ! If Zender_2003 is being used and soil eroditability is in atmosphere ! public data members: @@ -51,15 +49,13 @@ subroutine shr_dust_emis_readnl(NLFilename) character(len=*), intent(in) :: NLFilename ! Namelist filename !----- local ----- - integer :: i ! Indices integer :: unitn ! namelist unit number integer :: ierr ! error code logical :: exists ! if file exists or not - type(ESMF_VM) :: vm - integer :: localPet - integer :: mpicom - integer :: s_logunit - integer :: rc + type(ESMF_VM) :: vm ! Virtual machine + integer :: localPet ! Local processor + integer :: s_logunit ! Output log unit + integer :: rc ! Error code character(*),parameter :: F00 = "('(shr_dust_emis_read) ',8a)" character(*),parameter :: subName = '(shr_dust_emis_read) ' !----------------------------------------------------------------------------- @@ -148,7 +144,7 @@ end function is_dust_emis_zender logical function is_dust_emis_leung() ! is_dust_emis_leung – Logical function, true if the Leung 2023 scheme is being used - call check_if_initiatlized() + call check_if_initialized() if (trim(dust_emis_method) == 'Leung_2023') then is_dust_emis_leung = .true. else @@ -161,43 +157,43 @@ end function is_dust_emis_leung logical function is_zender_soil_erod_from_land() ! is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CTSM call check_if_initiatlized() - if is_dust_emis_zender() )then + if ( is_dust_emis_zender() )then if (trim(zender_soil_erod_source) == 'lnd') then is_zender_soil_erod_from_land = .true. else is_zender_soil_erod_from_land = .false. end if - else + else is_zender_soil_erod_from_land = .false. - end if + end if end function is_zender_soil_erod_from_land !=============================================================================== logical function is_zender_soil_erod_from_atm() - !is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CAM + !is_zender_soil_erod_from_atm – Logical function, true if the Zender method is being used and soil erodibility is in CAM call check_if_initiatlized() - if is_dust_emis_zender() )then - if (trim(zender_soil_erod_source) == 'atm') then - is_zender_soil_erod_from_land = .true. + if ( is_dust_emis_zender() )then + if ( trim(zender_soil_erod_source) == 'atm') then + is_zender_soil_erod_from_atm = .true. else - is_zender_soil_erod_from_land = .false. + is_zender_soil_erod_from_atm = .false. end if - else - is_zender_soil_erod_from_land = .false. - end if + else + is_zender_soil_erod_from_atm = .false. + end if end function is_zender_soil_erod_from_atm !=============================================================================== - subroutine check_if_initiatlized() + subroutine check_if_initialized() if ( dust_emis_initialized )then return else - call shr_sys_abort( 'ERROR: dust emission namelist has NOT been read in yet,' & - ' shr_dust_emis_mod is NOT initialized '//errMsg(u_FILE_u, __LINE__ ) + call shr_sys_abort( 'ERROR: dust emission namelist has NOT been read in yet,' // & + ' shr_dust_emis_mod is NOT initialized '//errMsg(u_FILE_u, __LINE__) ) end if - end subroutine check_if_initiatlized + end subroutine check_if_initialized !=============================================================================== From 22dd0745efd2b959f02c76ffb55afa994a4d3005 Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Fri, 26 Apr 2024 16:30:30 -0600 Subject: [PATCH 3/7] Remove ESMF in favor of shr_mpi_mod, it is simpler this way, this also allows me to do unit-testing easier --- cesm/nuopc_cap_share/shr_dust_emis_mod.F90 | 35 ++++++---------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 index 0e8ce424a..768e2a3e3 100644 --- a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 +++ b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 @@ -6,14 +6,10 @@ module shr_dust_emis_mod ! dust emissions. !======================================================================== - use ESMF , only : ESMF_VMGetCurrent, ESMF_VM, ESMF_VMGet, ESMF_LOGMSG_INFO - use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_SUCCESS - use ESMF , only : ESMF_LogWrite, ESMF_VMBroadCast use shr_sys_mod , only : shr_sys_abort use shr_kind_mod , only : CS => SHR_KIND_CS use shr_nl_mod , only : shr_nl_find_group_name use shr_log_mod , only : shr_log_getLogUnit, errMsg => shr_log_errMsg - use nuopc_shr_methods, only : chkerr implicit none private @@ -41,25 +37,24 @@ module shr_dust_emis_mod CONTAINS !=============================================================================== - subroutine shr_dust_emis_readnl(NLFilename) + subroutine shr_dust_emis_readnl(mpicom, NLFilename) !======================================================================== ! reads dust_emis_inparm namelist to determine how dust emissions will ! be handled between the land and atmosphere models !======================================================================== + use shr_mpi_mod, only : shr_mpi_bcast, shr_mpi_commrank character(len=*), intent(in) :: NLFilename ! Namelist filename + integer , intent(in) :: mpicom ! MPI communicator for broadcasting all all tasks !----- local ----- integer :: i ! Indices integer :: unitn ! namelist unit number integer :: ierr ! error code logical :: exists ! if file exists or not - type(ESMF_VM) :: vm - integer :: localPet - integer :: mpicom + integer :: localPet ! Local processor rank integer :: s_logunit - integer :: rc character(*),parameter :: F00 = "('(shr_dust_emis_read) ',8a)" character(*),parameter :: subName = '(shr_dust_emis_read) ' !----------------------------------------------------------------------------- @@ -69,20 +64,13 @@ subroutine shr_dust_emis_readnl(NLFilename) !----------------------------------------------------------------------------- ! Read namelist, check if namelist file exists first !----------------------------------------------------------------------------- - call ESMF_LogWrite(subname//' start', ESMF_LOGMSG_INFO) - - rc = ESMF_SUCCESS !--- Open and read namelist --- if ( len_trim(NLFilename) == 0 )then call shr_sys_abort( subName//'ERROR: nlfilename not set' ) end if - call ESMF_VMGetCurrent(vm, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return - - call ESMF_VMGet(vm, localPet=localPet, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return + call shr_mpi_commrank( mpicom, localPet ) call shr_log_getLogUnit(s_logunit) if (localPet==0) then @@ -102,12 +90,8 @@ subroutine shr_dust_emis_readnl(NLFilename) close( unitn ) end if end if - call ESMF_LogWrite(subname//' bcast dust_emis_method', ESMF_LOGMSG_INFO) - call ESMF_VMBroadcast(vm, dust_emis_method, CS, 0, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return - call ESMF_LogWrite(subname//' bcast zender_soil_erod_source', ESMF_LOGMSG_INFO) - call ESMF_VMBroadcast(vm, zender_soil_erod_source, CS, 0, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) return + call shr_mpi_bcast(dust_emis_method, mpicom) + call shr_mpi_bcast(zender_soil_erod_source, mpicom) ! Some error checking if (trim(dust_emis_method) == 'Leung_2023') then @@ -127,7 +111,6 @@ subroutine shr_dust_emis_readnl(NLFilename) //errMsg(u_FILE_u, __LINE__)) end if - call ESMF_LogWrite(subname//' done', ESMF_LOGMSG_INFO) dust_emis_initialized = .true. end subroutine shr_dust_emis_readnl @@ -161,7 +144,7 @@ end function is_dust_emis_leung logical function is_zender_soil_erod_from_land() ! is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CTSM call check_if_initiatlized() - if is_dust_emis_zender() )then + if ( is_dust_emis_zender() )then if (trim(zender_soil_erod_source) == 'lnd') then is_zender_soil_erod_from_land = .true. else @@ -177,7 +160,7 @@ end function is_zender_soil_erod_from_land logical function is_zender_soil_erod_from_atm() !is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CAM call check_if_initiatlized() - if is_dust_emis_zender() )then + if ( is_dust_emis_zender() )then if (trim(zender_soil_erod_source) == 'atm') then is_zender_soil_erod_from_land = .true. else From 492faf0014ad9d91c22bb92e2570e558a76093fe Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Mon, 29 Apr 2024 18:58:12 -0600 Subject: [PATCH 4/7] Add somethings needed for unit-testing and fix things identified there --- cesm/nuopc_cap_share/shr_dust_emis_mod.F90 | 30 +++++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 index b1a91b71a..b14148a90 100644 --- a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 +++ b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 @@ -19,10 +19,14 @@ module shr_dust_emis_mod public :: is_dust_emis_zender ! If Zender_2003 dust emission method is being used public :: is_dust_emis_leung ! If Leungr_2023 dust emission method is being used public :: is_zender_soil_erod_from_land ! If Zender_2003 is being used and soil eroditability is in land - public :: is_zender_soil_erod_from_atm ! If Zender_2003 is being used and soil eroditability is in atmosphere + public :: is_zender_soil_erod_from_atm ! If Zender/_2003 is being used and soil eroditability is in atmosphere - ! public data members: - private :: check_if_initialized ! Check if dust emission has been initialized + ! The following is only public for the sake of unit testing; it should not be called + ! directly outside this module + public :: dust_emis_set_options ! Set the namelist options directory not through the namelist + + ! private data members: (only public for unit testing) + public :: check_if_initialized ! Check if dust emission has been initialized ! PRIVATE DATA: character(len=CS) :: dust_emis_method = 'Zender_2003' ! Dust emisison method to use: Zender_2003 or Leung_2023 @@ -117,7 +121,7 @@ end subroutine shr_dust_emis_readnl logical function is_dust_emis_zender() ! is_dust_emis_zender – Logical function, true if the Zender 2003 scheme is being used - call check_if_initiatlized() + call check_if_initialized() if (trim(dust_emis_method) == 'Zender_2003') then is_dust_emis_zender = .true. else @@ -141,7 +145,7 @@ end function is_dust_emis_leung logical function is_zender_soil_erod_from_land() ! is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CTSM - call check_if_initiatlized() + call check_if_initialized() if ( is_dust_emis_zender() )then if (trim(zender_soil_erod_source) == 'lnd') then is_zender_soil_erod_from_land = .true. @@ -157,7 +161,7 @@ end function is_zender_soil_erod_from_land logical function is_zender_soil_erod_from_atm() !is_zender_soil_erod_from_atm – Logical function, true if the Zender method is being used and soil erodibility is in CAM - call check_if_initiatlized() + call check_if_initialized() if ( is_dust_emis_zender() )then if ( trim(zender_soil_erod_source) == 'atm') then is_zender_soil_erod_from_atm = .true. @@ -172,14 +176,26 @@ end function is_zender_soil_erod_from_atm !=============================================================================== subroutine check_if_initialized() + integer :: s_logunit ! Output log unit + if ( dust_emis_initialized )then return else + call shr_log_getLogUnit(s_logunit) + write(s_logunit,*) 'ERROR: '//errMsg(u_FILE_u, __LINE__) call shr_sys_abort( 'ERROR: dust emission namelist has NOT been read in yet,' // & - ' shr_dust_emis_mod is NOT initialized '//errMsg(u_FILE_u, __LINE__) ) + ' shr_dust_emis_mod is NOT initialized ' ) end if end subroutine check_if_initialized + subroutine dust_emis_set_options( dust_emis_method_in, zender_soil_erod_source_in) + character(len=CS), intent(IN) :: dust_emis_method_in ! Dust emisison method to use: Zender_2003 or Leung_2023 + character(len=CS), intent(IN) :: zender_soil_erod_source_in ! if calculed in lnd or atm (only when Zender_2003 is used) + + dust_emis_method = dust_emis_method_in + zender_soil_erod_source = zender_soil_erod_source_in + end subroutine dust_emis_set_options + !=============================================================================== end module shr_dust_emis_mod From 8d3cd2627b9ea7072ec12472612f5c32c94691fc Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Tue, 30 Apr 2024 09:18:40 -0600 Subject: [PATCH 5/7] check_if_initiatlized to is_NOT_initialized Change check_if_initiatlized to logical function to help with unit testing. --- cesm/nuopc_cap_share/shr_dust_emis_mod.F90 | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 index b14148a90..376f5dbc3 100644 --- a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 +++ b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 @@ -26,7 +26,7 @@ module shr_dust_emis_mod public :: dust_emis_set_options ! Set the namelist options directory not through the namelist ! private data members: (only public for unit testing) - public :: check_if_initialized ! Check if dust emission has been initialized + public :: is_NOT_initialized ! Check if dust emission has NOT been initialized ! PRIVATE DATA: character(len=CS) :: dust_emis_method = 'Zender_2003' ! Dust emisison method to use: Zender_2003 or Leung_2023 @@ -121,7 +121,7 @@ end subroutine shr_dust_emis_readnl logical function is_dust_emis_zender() ! is_dust_emis_zender – Logical function, true if the Zender 2003 scheme is being used - call check_if_initialized() + if ( is_NOT_initialized() ) return if (trim(dust_emis_method) == 'Zender_2003') then is_dust_emis_zender = .true. else @@ -133,7 +133,7 @@ end function is_dust_emis_zender logical function is_dust_emis_leung() ! is_dust_emis_leung – Logical function, true if the Leung 2023 scheme is being used - call check_if_initialized() + if ( is_NOT_initialized() ) return if (trim(dust_emis_method) == 'Leung_2023') then is_dust_emis_leung = .true. else @@ -145,7 +145,7 @@ end function is_dust_emis_leung logical function is_zender_soil_erod_from_land() ! is_zender_soil_erod_from_land – Logical function, true if the Zender method is being used and soil erodibility is in CTSM - call check_if_initialized() + if ( is_NOT_initialized() ) return if ( is_dust_emis_zender() )then if (trim(zender_soil_erod_source) == 'lnd') then is_zender_soil_erod_from_land = .true. @@ -161,7 +161,7 @@ end function is_zender_soil_erod_from_land logical function is_zender_soil_erod_from_atm() !is_zender_soil_erod_from_atm – Logical function, true if the Zender method is being used and soil erodibility is in CAM - call check_if_initialized() + if ( is_NOT_initialized() ) return if ( is_dust_emis_zender() )then if ( trim(zender_soil_erod_source) == 'atm') then is_zender_soil_erod_from_atm = .true. @@ -175,18 +175,23 @@ end function is_zender_soil_erod_from_atm !=============================================================================== - subroutine check_if_initialized() + logical function is_NOT_initialized() + ! Check if this is NOT initialized and return true if so (false if initialized) + ! Will abort with an error when using in the model + ! For unit testing will return the logical state integer :: s_logunit ! Output log unit if ( dust_emis_initialized )then + is_NOT_initialized = .false. return else + is_NOT_initialized = .true. call shr_log_getLogUnit(s_logunit) write(s_logunit,*) 'ERROR: '//errMsg(u_FILE_u, __LINE__) call shr_sys_abort( 'ERROR: dust emission namelist has NOT been read in yet,' // & ' shr_dust_emis_mod is NOT initialized ' ) end if - end subroutine check_if_initialized + end function is_NOT_initialized subroutine dust_emis_set_options( dust_emis_method_in, zender_soil_erod_source_in) character(len=CS), intent(IN) :: dust_emis_method_in ! Dust emisison method to use: Zender_2003 or Leung_2023 From ecb6d45aa00a4960564ea963b00754fb4c3b7d2c Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Tue, 30 Apr 2024 11:04:02 -0600 Subject: [PATCH 6/7] Fix so unit test will PASS --- cesm/nuopc_cap_share/shr_dust_emis_mod.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 index 376f5dbc3..54a914453 100644 --- a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 +++ b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 @@ -194,11 +194,12 @@ logical function is_NOT_initialized() end function is_NOT_initialized subroutine dust_emis_set_options( dust_emis_method_in, zender_soil_erod_source_in) - character(len=CS), intent(IN) :: dust_emis_method_in ! Dust emisison method to use: Zender_2003 or Leung_2023 - character(len=CS), intent(IN) :: zender_soil_erod_source_in ! if calculed in lnd or atm (only when Zender_2003 is used) + character(len=*), intent(IN) :: dust_emis_method_in ! Dust emisison method to use: Zender_2003 or Leung_2023 + character(len=*), intent(IN) :: zender_soil_erod_source_in ! if calculed in lnd or atm (only when Zender_2003 is used) dust_emis_method = dust_emis_method_in zender_soil_erod_source = zender_soil_erod_source_in + dust_emis_initialized = .true. end subroutine dust_emis_set_options !=============================================================================== From 0285eeb59605df44bc3abf38a61e8436361e7e8c Mon Sep 17 00:00:00 2001 From: Erik Kluzek Date: Wed, 1 May 2024 13:53:44 -0600 Subject: [PATCH 7/7] Spin off the option checker Make the checking of options it's own subroutine to help with unit-testing. --- cesm/nuopc_cap_share/shr_dust_emis_mod.F90 | 69 +++++++++++++--------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 index 54a914453..f70024835 100644 --- a/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 +++ b/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 @@ -23,14 +23,15 @@ module shr_dust_emis_mod ! The following is only public for the sake of unit testing; it should not be called ! directly outside this module - public :: dust_emis_set_options ! Set the namelist options directory not through the namelist - - ! private data members: (only public for unit testing) + public :: dust_emis_set_options ! Set the namelist options directory not through the namelist public :: is_NOT_initialized ! Check if dust emission has NOT been initialized + ! private data members: + private :: check_options_finish_init ! Check that the options are correct and finish initialization + ! PRIVATE DATA: character(len=CS) :: dust_emis_method = 'Zender_2003' ! Dust emisison method to use: Zender_2003 or Leung_2023 - character(len=CS) :: zender_soil_erod_source = 'none' ! if calculed in lnd or atm (only when Zender_2003 is used) + character(len=CS) :: zender_soil_erod_source = 'none' ! if calculated in lnd or atm (only when Zender_2003 is used) logical :: dust_emis_initialized=.false. ! If dust emissions have been initiatlized yet or not character(len=*), parameter :: u_FILE_u = & @@ -95,28 +96,42 @@ subroutine shr_dust_emis_readnl(mpicom, NLFilename) call shr_mpi_bcast(dust_emis_method, mpicom) call shr_mpi_bcast(zender_soil_erod_source, mpicom) - ! Some error checking - if (trim(dust_emis_method) == 'Leung_2023') then - if ( trim(zender_soil_erod_source) /= 'none' )then - call shr_sys_abort(subName//"ERROR: zender_soil_erod_source should NOT be set, when dust_emis_method=Leung_2023 " & - //errMsg(u_FILE_u, __LINE__)) - end if - else if (trim(dust_emis_method) == 'Zender_2003') then - if ( (trim(zender_soil_erod_source) /= 'lnd') .and. (trim(zender_soil_erod_source) /= 'atm') )then - write(s_logunit,*) 'zender_soil_erod_source is NOT valid = ', trim(zender_soil_erod_source) - call shr_sys_abort(subName//"ERROR: zender_soil_erod_source can only be lnd or atm" & - //errMsg(u_FILE_u, __LINE__)) - end if - else - write(s_logunit,*) 'dust_emis_method not recognized = ', trim(dust_emis_method) - call shr_sys_abort(subName//"ERROR: dust_emis_method namelist item is not valid " & - //errMsg(u_FILE_u, __LINE__)) - end if - - dust_emis_initialized = .true. + call check_options_finish_init() end subroutine shr_dust_emis_readnl +!==================================================================================== + + subroutine check_options_finish_init() + ! Some error checking and mark initialization as finished + integer :: s_logunit ! Output log unit + character(*),parameter :: subName = '(check_options_finish_init) ' + + call shr_log_getLogUnit(s_logunit) + if (trim(dust_emis_method) == 'Leung_2023') then + if ( trim(zender_soil_erod_source) /= 'none' )then + write(s_logunit,*) 'ERROR: '//errMsg(u_FILE_u, __LINE__) + call shr_sys_abort(subName//"ERROR: zender_soil_erod_source should NOT be set, when dust_emis_method=Leung_2023" ) + return + end if + else if (trim(dust_emis_method) == 'Zender_2003') then + if ( (trim(zender_soil_erod_source) /= 'lnd') .and. (trim(zender_soil_erod_source) /= 'atm') )then + write(s_logunit,*) 'zender_soil_erod_source is NOT valid = ', trim(zender_soil_erod_source) + write(s_logunit,*) 'ERROR: '//errMsg(u_FILE_u, __LINE__) + call shr_sys_abort(subName//"ERROR: zender_soil_erod_source can only be lnd or atm" ) + return + end if + else + write(s_logunit,*) 'dust_emis_method not recognized = ', trim(dust_emis_method) + write(s_logunit,*) 'ERROR: '//errMsg(u_FILE_u, __LINE__) + call shr_sys_abort(subName//"ERROR: dust_emis_method namelist item is not valid" ) + return + end if + + dust_emis_initialized = .true. + + end subroutine check_options_finish_init + !==================================================================================== logical function is_dust_emis_zender() @@ -187,7 +202,7 @@ logical function is_NOT_initialized() else is_NOT_initialized = .true. call shr_log_getLogUnit(s_logunit) - write(s_logunit,*) 'ERROR: '//errMsg(u_FILE_u, __LINE__) + write(s_logunit,*) 'ERROR: '//errMsg(u_FILE_u, __LINE__) call shr_sys_abort( 'ERROR: dust emission namelist has NOT been read in yet,' // & ' shr_dust_emis_mod is NOT initialized ' ) end if @@ -197,9 +212,9 @@ subroutine dust_emis_set_options( dust_emis_method_in, zender_soil_erod_source_i character(len=*), intent(IN) :: dust_emis_method_in ! Dust emisison method to use: Zender_2003 or Leung_2023 character(len=*), intent(IN) :: zender_soil_erod_source_in ! if calculed in lnd or atm (only when Zender_2003 is used) - dust_emis_method = dust_emis_method_in - zender_soil_erod_source = zender_soil_erod_source_in - dust_emis_initialized = .true. + dust_emis_method = dust_emis_method_in + zender_soil_erod_source = zender_soil_erod_source_in + call check_options_finish_init() end subroutine dust_emis_set_options !===============================================================================