From 2afdcd9649dc5081a526d2372ccf32d55e89b23f Mon Sep 17 00:00:00 2001 From: Keith Oleson Date: Tue, 2 May 2023 10:59:31 -0600 Subject: [PATCH 1/3] Change nextsw_cday calculation for CAM7 in cplhist mode. Note that cplhist_nextsw_cday_calc is intended to be a namelist parameter but is not yet implemented here. --- datm/atm_comp_nuopc.F90 | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index c84e10f79..c0f60a5c3 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -872,10 +872,18 @@ real(R8) function getNextRadCDay( julday, tod, stepno, dtime, iradsw ) if (liradsw > 1) then delta_radsw = liradsw * dtime - if (mod(tod+dtime,delta_radsw) == 0 .and. stepno > 0) then - nextsw_cday = julday + 2*dtime/shr_const_cday + if (trim(cplhist_nextsw_cday_calc) == 'cam7' ) then + if (mod(tod,delta_radsw) == 0 .and. stepno > 0) then + nextsw_cday = julday + 1*dtime/shr_const_cday + else + nextsw_cday = -1._r8 + end if else - nextsw_cday = -1._r8 + if (mod(tod+dtime,delta_radsw) == 0 .and. stepno > 0) then + nextsw_cday = julday + 2*dtime/shr_const_cday + else + nextsw_cday = -1._r8 + end if end if else nextsw_cday = julday + dtime/shr_const_cday From 11d937e3c7db0bae9e6f61744186a006a4ad31b8 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 29 Oct 2024 18:30:20 -0600 Subject: [PATCH 2/3] Add a namelist flag controlling the nextsw_cday calculation --- datm/atm_comp_nuopc.F90 | 22 ++++++++++++++++++- datm/cime_config/namelist_definition_datm.xml | 20 +++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index 2a86b7687..bdec303e4 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -127,6 +127,7 @@ module cdeps_datm_comp character(CL) :: model_meshfile = nullstr ! full pathname to model meshfile character(CL) :: model_maskfile = nullstr ! full pathname to obtain mask from integer :: iradsw = 0 ! radiation interval (input namelist) + logical :: nextsw_cday_calc_cam7 ! true => use logic appropriate to cam7 (and later) for calculating nextsw_cday character(CL) :: factorFn_mesh = 'null' ! file containing correction factors mesh character(CL) :: factorFn_data = 'null' ! file containing correction factors data logical :: flds_presaero = .false. ! true => send valid prescribed aero fields to mediator @@ -230,6 +231,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) integer :: nu ! unit number integer :: ierr ! error code integer :: bcasttmp(10) + character(CL) :: nextsw_cday_calc type(ESMF_VM) :: vm character(len=*),parameter :: subname=trim(modName) // ':(InitializeAdvertise) ' character(*) ,parameter :: F00 = "('(" // trim(modName) // ") ',8a)" @@ -245,6 +247,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ny_global, & restfilm, & iradsw, & + nextsw_cday_calc, & factorFn_data, & factorFn_mesh, & flds_presaero, & @@ -259,6 +262,9 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) rc = ESMF_SUCCESS + ! Initialize locally-declared namelist items to default values + nextsw_cday_calc = nullstr + call NUOPC_CompAttributeGet(gcomp, name='case_name', value=case_name, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -318,6 +324,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, restfilm, CL, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, nextsw_cday_calc, CL, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, bcasttmp, 10, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return nx_global = bcasttmp(1) @@ -331,6 +339,14 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) skip_restart_read = (bcasttmp(9) == 1) export_all = (bcasttmp(10) == 1) + if (nextsw_cday_calc == 'cam7') then + nextsw_cday_calc_cam7 = .true. + else if (nextsw_cday_calc == 'cam6') then + nextsw_cday_calc_cam7 = .false. + else + call shr_sys_abort(' ERROR illegal datm nextsw_cday_calc = '//trim(nextsw_cday_calc)) + end if + ! write namelist input to standard out if (my_task == main_task) then write(logunit,F00)' case_name = ',trim(case_name) @@ -341,6 +357,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) write(logunit,F01)' ny_global = ',ny_global write(logunit,F00)' restfilm = ',trim(restfilm) write(logunit,F01)' iradsw = ',iradsw + write(logunit,F00)' nextsw_cday_calc = ', trim(nextsw_cday_calc) write(logunit,F00)' factorFn_data = ',trim(factorFn_data) write(logunit,F00)' factorFn_mesh = ',trim(factorFn_mesh) write(logunit,F02)' flds_presaero = ',flds_presaero @@ -905,7 +922,10 @@ real(R8) function getNextRadCDay( julday, tod, stepno, dtime, iradsw ) if (liradsw > 1) then delta_radsw = liradsw * dtime - if (trim(cplhist_nextsw_cday_calc) == 'cam7' ) then + if (nextsw_cday_calc_cam7) then + ! The logic in this block is consistent with the driver ordering in CAM7 and + ! later. So this is appropriate when using cplhist forcings generated from CAM7 + ! or later. if (mod(tod,delta_radsw) == 0 .and. stepno > 0) then nextsw_cday = julday + 1*dtime/shr_const_cday else diff --git a/datm/cime_config/namelist_definition_datm.xml b/datm/cime_config/namelist_definition_datm.xml index 3c2be3995..afe3a40d7 100644 --- a/datm/cime_config/namelist_definition_datm.xml +++ b/datm/cime_config/namelist_definition_datm.xml @@ -346,6 +346,26 @@ + + char + datm + datm_nml + cam6,cam7 + + Logic to use for calculating nextsw_cday. For CPLHIST cases, this should agree with + the version of CAM (or other atmosphere model) used to generate the CPLHIST + forcings; the valid values for this variable are based on this: 'cam6' is + appropriate for cases generated with the driver ordering in CAM6 and earlier, and + 'cam7' is appropriate for cases generated with the driver ordering in CAM7 and + later. This variable also applies for non-CPLHIST cases, but we currently assume (by + default) that non-CPLHIST cases follow the logic that was used in CAM6 and earlier. + + + cam6 + cam7 + + + char datm From 1f317a3c03badd4e3e11ddd455cf5bd6d6e9c9d6 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 31 Oct 2024 15:10:10 -0600 Subject: [PATCH 3/3] Improve documentation of nextsw_cday_calc and iradsw --- datm/atm_comp_nuopc.F90 | 17 +++++---- datm/cime_config/namelist_definition_datm.xml | 35 +++++++++++-------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index bdec303e4..4ac13b744 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -885,15 +885,14 @@ end subroutine datm_comp_run real(R8) function getNextRadCDay( julday, tod, stepno, dtime, iradsw ) ! Return the calendar day of the next radiation time-step. - ! General Usage: nextswday = getNextRadCDay(curr_date) iradsw is - ! the frequency to update the next shortwave. in number of steps - ! (or hours if negative) Julian date. - ! -- values greater than 1 set - ! the next radiation to the present time plus 2 timesteps every iradsw - ! -- values less than 0 turn set the next radiation to the present time - ! plus two timesteps every -iradsw hours. - ! -- if iradsw is zero, the next radiation time is the - ! present time plus 1 timestep. + ! General Usage: nextswday = getNextRadCDay(curr_date). iradsw is + ! the frequency to update the next shortwave in number of steps + ! (or hours if negative). + ! -- values greater than 1 set the next radiation to the present time plus either 1 or + ! 2 timesteps (depending on the value of nextsw_cday_calc_cam7) every iradsw timesteps. + ! -- values less than 0 set the next radiation to the present time plus either 1 or 2 + ! timesteps (depending on the value of nextsw_cday_calc_cam7) every -iradsw hours. + ! -- if iradsw is either 0 or 1, the next radiation time is the present time plus 1 timestep. ! input/output variables real(r8) , intent(in) :: julday diff --git a/datm/cime_config/namelist_definition_datm.xml b/datm/cime_config/namelist_definition_datm.xml index afe3a40d7..40935cf86 100644 --- a/datm/cime_config/namelist_definition_datm.xml +++ b/datm/cime_config/namelist_definition_datm.xml @@ -332,13 +332,15 @@ datm datm_nml - Frequency to update radiation in number of steps (or hours if negative) - irdasw is the radiation setting used to compute the next shortwave - Julian date. values greater than 1 set the next radiation to the - present time plus 2 timesteps every iradsw. values less than 0 turn - set the next radiation to the present time plus two timesteps every - -iradsw hours. if iradsw is zero, the next radiation time is the - present time plus 1 timestep. (default=0.) + Frequency to update radiation in number of steps (or hours if negative). + + irdasw is the radiation setting used to compute the next shortwave Julian date. + Values greater than 1 set the next radiation to the present time plus either 1 or 2 + timesteps (depending on the value of nextsw_cday_calc) every iradsw timesteps. + Values less than 0 set the next radiation to the present time plus either 1 or 2 + timesteps (depending on the value of nextsw_cday_calc) every -iradsw hours. If + iradsw is either 0 or 1, the next radiation time is the present time plus 1 + timestep. (default=1 for non-CPLHIST cases, and -1 for CPLHIST cases.) 1 @@ -352,13 +354,18 @@ datm_nml cam6,cam7 - Logic to use for calculating nextsw_cday. For CPLHIST cases, this should agree with - the version of CAM (or other atmosphere model) used to generate the CPLHIST - forcings; the valid values for this variable are based on this: 'cam6' is - appropriate for cases generated with the driver ordering in CAM6 and earlier, and - 'cam7' is appropriate for cases generated with the driver ordering in CAM7 and - later. This variable also applies for non-CPLHIST cases, but we currently assume (by - default) that non-CPLHIST cases follow the logic that was used in CAM6 and earlier. + Logic to use for calculating nextsw_cday. This variable has no effect when iradsw is + 0 or 1, so by default this only applies in CPLHIST cases. + + For CPLHIST cases, this should agree with the version of CAM (or other atmosphere + model) used to generate the CPLHIST forcings; the valid values for this variable are + based on this: 'cam6' is appropriate for cases generated with the driver ordering in + CAM6 and earlier, and 'cam7' is appropriate for cases generated with the driver + ordering in CAM7 and later. + + For 'cam6', the next radiation timestep is set to the present time plus 2 timesteps + when mod(tod+dtime,delta_radsw)==0. For 'cam7', the next radiation timestep is set + to the present time plus 1 timestep when mod(tod,delta_radsw)==0. cam6