From bdf6b329fce4d72f8944019410aac37855e6ba4e Mon Sep 17 00:00:00 2001 From: Keith Oleson Date: Thu, 1 Jun 2023 11:02:53 -0600 Subject: [PATCH 01/27] Changes to remove 0th timestep --- src/biogeochem/CNPhenologyMod.F90 | 6 +++++- src/biogeochem/CNVegetationFacade.F90 | 12 ++++++++++-- src/biogeochem/CropType.F90 | 6 +++++- src/biogeochem/dynCNDVMod.F90 | 6 +++++- src/biogeophys/WaterStateType.F90 | 1 + src/cpl/nuopc/lnd_comp_nuopc.F90 | 19 ++++++++++++++----- src/main/accumulMod.F90 | 7 ++++++- src/main/clm_driver.F90 | 6 ++++-- src/main/histFileMod.F90 | 16 ++++++++++------ src/unit_test_shr/unittestTimeManagerMod.F90 | 3 +++ src/utils/AnnualFluxDribbler.F90 | 6 +++++- src/utils/clm_time_manager.F90 | 11 ++++++++++- 12 files changed, 78 insertions(+), 21 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index ec04fcbf54..7ce359aa53 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -378,7 +378,11 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & ! all restart files having been generated with ! https://github.com/ESCOMP/CTSM/issues/1623 resolved, or we stop having a time ! step 0 (https://github.com/ESCOMP/CTSM/issues/925). - if (num_pcropp > 0 .and. .not. is_first_step()) then +!KO if (num_pcropp > 0 .and. .not. is_first_step()) then +!KO + ! Unknown if all restart files have been generated with 1623 resolved but we no longer have a time step 0 + if (num_pcropp > 0) then +!KO call CropPhenology(num_pcropp, filter_pcropp, & waterdiagnosticbulk_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90 index cc625e2a36..5c91950ca5 100644 --- a/src/biogeochem/CNVegetationFacade.F90 +++ b/src/biogeochem/CNVegetationFacade.F90 @@ -1229,7 +1229,11 @@ subroutine EndOfTimeStepVegDynamics(this, bounds, num_natvegp, filter_natvegp, & ! Call dv (dynamic vegetation) at last time step of year call t_startf('d2dgvm') - if (is_end_curr_year() .and. .not. is_first_step()) then +!KO if (is_end_curr_year() .and. .not. is_first_step()) then +!KO + ! is_first_step check no longer necessary since there is no nstep=0 + if (is_end_curr_year()) then +!KO ! Get date info. kyr is used in lpj(). At end of first year, kyr = 2. call get_curr_date(yr, mon, day, sec) @@ -1281,7 +1285,11 @@ subroutine WriteHistory(this, bounds) ! Write to CNDV history buffer if appropriate if (use_cndv) then - if (is_end_curr_year() .and. .not. is_first_step()) then +!KO if (is_end_curr_year() .and. .not. is_first_step()) then +!KO + ! is_first_step check no longer necessary since there is no nstep=0 + if (is_end_curr_year()) then +!KO call t_startf('clm_drv_io_hdgvm') call CNDVHist( bounds, this%dgvs_inst ) if (masterproc) write(iulog,*) 'Annual CNDV calculations are complete' diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 6ceeccf7e3..22a38e9c30 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -763,7 +763,11 @@ subroutine CropIncrementYear (this, num_pcropp, filter_pcropp) ! Update nyrs when it's the end of the year (unless it's the very start of the ! run). This assumes that, if this patch is active at the end of the year, then it was ! active for the whole year. - if ((kmo == 1 .and. kda == 1 .and. mcsec == 0) .and. .not. is_first_step()) then +!KO if ((kmo == 1 .and. kda == 1 .and. mcsec == 0) .and. .not. is_first_step()) then +!KO + ! is_first_step check no longer necessary since there is no nstep=0 + if ((kmo == 1 .and. kda == 1 .and. mcsec == 0)) then +!KO do fp = 1, num_pcropp p = filter_pcropp(fp) diff --git a/src/biogeochem/dynCNDVMod.F90 b/src/biogeochem/dynCNDVMod.F90 index 76382d175b..57e90d8917 100644 --- a/src/biogeochem/dynCNDVMod.F90 +++ b/src/biogeochem/dynCNDVMod.F90 @@ -99,7 +99,11 @@ subroutine dynCNDV_interp( bounds, dgvs_inst) patch%wtcol(p) = dgvs_inst%fpcgrid_patch(p) + & wt1 * (dgvs_inst%fpcgridold_patch(p) - dgvs_inst%fpcgrid_patch(p)) - if (mon==1 .and. day==1 .and. sec==dtime .and. nstep>0) then +!KO ! I don't think this is necessary since there no longer an nstep=0 +!KO if (mon==1 .and. day==1 .and. sec==dtime .and. nstep>0) then +!KO + if (mon==1 .and. day==1 .and. sec==dtime) then +!KO dgvs_inst%fpcgridold_patch(p) = dgvs_inst%fpcgrid_patch(p) end if end if diff --git a/src/biogeophys/WaterStateType.F90 b/src/biogeophys/WaterStateType.F90 index 751f633875..90e48f0834 100644 --- a/src/biogeophys/WaterStateType.F90 +++ b/src/biogeophys/WaterStateType.F90 @@ -652,6 +652,7 @@ subroutine Restart(this, bounds, ncid, flag, & ! If initial run -- ensure that water is properly bounded (read only) if (flag == 'read' ) then +!KO ! I think leaving this in here is still necessary even though is_first_step is now based on nstep=1 if ( is_first_step() .and. bound_h2osoi) then do c = bounds%begc, bounds%endc l = col%landunit(c) diff --git a/src/cpl/nuopc/lnd_comp_nuopc.F90 b/src/cpl/nuopc/lnd_comp_nuopc.F90 index 3852a1bf1b..90ec0fcb0a 100644 --- a/src/cpl/nuopc/lnd_comp_nuopc.F90 +++ b/src/cpl/nuopc/lnd_comp_nuopc.F90 @@ -823,9 +823,10 @@ subroutine ModelAdvance(gcomp, rc) ! TODO: This is currently hard-wired - is there a better way for nuopc? ! Note that the model clock is updated at the end of the time step not at the beginning nstep = get_nstep() - if (nstep > 0) then +!KO ! I don't think this is necessary anymore since there is no longer an nstep=0 +!KO if (nstep > 0) then dosend = .true. - end if +!KO end if !-------------------------------- ! Determine doalb based on nextsw_cday sent from atm model @@ -833,13 +834,21 @@ subroutine ModelAdvance(gcomp, rc) caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.) - if (nstep == 0) then - doalb = .false. - else if (nstep == 1) then +!KO if (nstep == 0) then +!KO doalb = .false. +!KO else if (nstep == 1) then +!KO doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) +!KO else +!KO doalb = (nextsw_cday >= -0.5_r8) +!KO end if +!KO +!KO ! Removed the nstep=0 check + if (nstep == 1) then doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) else doalb = (nextsw_cday >= -0.5_r8) end if +!KO call update_rad_dtime(doalb) !-------------------------------- diff --git a/src/main/accumulMod.F90 b/src/main/accumulMod.F90 index e328632501..3a26c630fb 100644 --- a/src/main/accumulMod.F90 +++ b/src/main/accumulMod.F90 @@ -583,7 +583,12 @@ subroutine update_accum_field_timeavg(this, level, nstep, field) ! time average field: reset every accumulation period; normalize at end of ! accumulation period - if ((mod(nstep,this%period) == 1 .or. this%period == 1) .and. (nstep /= 0))then +!KO ! Since this is equivalent to .not. is_first_step when it was keyed off of nstep=0 +!KO ! I think this can be removed. It seems to be related to the "real" first time step +!KO if ((mod(nstep,this%period) == 1 .or. this%period == 1) .and. (nstep /= 0))then +!KO + if (mod(nstep,this%period) == 1 .or. this%period == 1)then +!KO do k = begi,endi if (this%active(k)) then this%val(k,level) = 0._r8 diff --git a/src/main/clm_driver.F90 b/src/main/clm_driver.F90 index ae178b226c..9ecc77e694 100644 --- a/src/main/clm_driver.F90 +++ b/src/main/clm_driver.F90 @@ -204,6 +204,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! are passed to CLM in initialization, then this code block can be removed. ! ======================================================================== +!KO I think leaving this in here is still necessary even though is_first_step is now based on nstep=1 need_glacier_initialization = is_first_step() if (need_glacier_initialization) then @@ -1364,7 +1365,8 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! FIX(SPM, 082814) - in the fates branch RF and I commented out the if(.not. ! use_fates) then statement ... double check if this is required and why - if (nstep > 0) then +! I don't think this is necessary since there no longer an nstep=0 +!KO if (nstep > 0) then call t_startf('accum') call atm2lnd_inst%UpdateAccVars(bounds_proc) @@ -1397,7 +1399,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro end if call t_stopf('accum') - end if +!KO end if ! ============================================================================ ! Update history buffer diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index d5175342f0..8f91da7774 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -2606,7 +2606,10 @@ subroutine htape_timeconst3D(t, & ! !DESCRIPTION: ! Write time constant 3D variables to history tapes. ! Only write out when this subroutine is called (normally only for - ! primary history files at very first time-step, nstep=0). +!KO ! primary history files at very first time-step, nstep=0). +!KO + ! primary history files at very first time-step, nstep=1). +!KO ! Issue the required netcdf wrapper calls to define the history file ! contents. ! @@ -4009,11 +4012,12 @@ subroutine hist_htapes_wrapup( rstwr, nlend, bounds, & cycle end if - ! Skip nstep=0 if monthly average - - if (nstep==0 .and. tape(t)%nhtfrq==0) then - cycle - end if +!KO ! Should no longer be needed +!KO ! Skip nstep=0 if monthly average +!KO +!KO if (nstep==0 .and. tape(t)%nhtfrq==0) then +!KO cycle +!KO end if ! Determine if end of history interval tape(t)%is_endhist = .false. diff --git a/src/unit_test_shr/unittestTimeManagerMod.F90 b/src/unit_test_shr/unittestTimeManagerMod.F90 index 44109d5b86..efc60ec786 100644 --- a/src/unit_test_shr/unittestTimeManagerMod.F90 +++ b/src/unit_test_shr/unittestTimeManagerMod.F90 @@ -177,6 +177,9 @@ subroutine unittest_timemgr_set_nstep(nstep) ! !DESCRIPTION: ! Set the time step number ! +!KO + ! Comment not needed now? +!KO ! Note that the starting time step number is 0, so calling this with nstep = 1 ! advances the time step beyond the starting time step. ! diff --git a/src/utils/AnnualFluxDribbler.F90 b/src/utils/AnnualFluxDribbler.F90 index c7a3b792fe..a6a880d16e 100644 --- a/src/utils/AnnualFluxDribbler.F90 +++ b/src/utils/AnnualFluxDribbler.F90 @@ -258,7 +258,11 @@ subroutine set_curr_delta(this, bounds, delta) do i = beg_index, end_index this%amount_from_this_timestep(i) = delta(i) end do - if (.not. this%allows_non_annual_delta .and. .not. is_first_step()) then +!KO if (.not. this%allows_non_annual_delta .and. .not. is_first_step()) then +!KO + ! is_first_step check no longer necessary since there is no nstep=0 + if (.not. this%allows_non_annual_delta) then +!KO do i = beg_index, end_index if (this%amount_from_this_timestep(i) /= 0._r8) then write(iulog,*) subname//' ERROR: found unexpected non-zero delta mid-year' diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index b8d9930b24..31e9b30927 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -235,6 +235,11 @@ subroutine timemgr_init( ) tm_perp_date = TimeSetymd( perpetual_ymd, 0, "tm_perp_date" ) end if +!KO + ! Advance time step to start at nstep=1 (instead of nstep=0) + call advance_timestep() +!KO + ! Print configuration summary to log file (stdout). if (masterproc) call timemgr_print() @@ -675,6 +680,7 @@ subroutine advance_timestep() call ESMF_ClockAdvance( tm_clock, rc=rc ) call chkrc(rc, sub//': error return from ESMF_ClockAdvance') +!KO Do we want to do this? tm_first_restart_step = .false. end subroutine advance_timestep @@ -1714,7 +1720,10 @@ logical function is_first_step() call ESMF_ClockGet( tm_clock, advanceCount=step_no, rc=rc ) call chkrc(rc, sub//': error return from ESMF_ClockGet') nstep = step_no - is_first_step = (nstep == 0) +!KO is_first_step = (nstep == 0) +!KO + is_first_step = (nstep == 1) +!KO end function is_first_step !========================================================================================= From a9eb1e72b743a731743059b271997d1f8c3cf527 Mon Sep 17 00:00:00 2001 From: Keith Oleson Date: Tue, 25 Jul 2023 12:52:31 -0600 Subject: [PATCH 02/27] Changes for lilac --- src/cpl/lilac/lnd_comp_esmf.F90 | 24 ++++++++++++++++++------ src/cpl/nuopc/lnd_comp_nuopc.F90 | 3 +++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/cpl/lilac/lnd_comp_esmf.F90 b/src/cpl/lilac/lnd_comp_esmf.F90 index 298aa730c0..dbb9c26f73 100644 --- a/src/cpl/lilac/lnd_comp_esmf.F90 +++ b/src/cpl/lilac/lnd_comp_esmf.F90 @@ -631,9 +631,13 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) ! ! See also https://github.com/ESCOMP/CTSM/issues/925 nstep = get_nstep() - if (nstep > 0) then +!KO ! TODO (KWO 07-25-2023) +!KO ! I don't think this is necessary anymore since there is no longer an nstep=0 +!KO ! In fact, according to the comment above we should be able to remove this +!KO ! do while loop and the dosend variable. +!KO if (nstep > 0) then dosend = .true. - end if +!KO end if !-------------------------------- ! Determine calendar day info @@ -680,15 +684,23 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) ! Determine doalb based on nextsw_cday sent from atm model !-------------------------------- - if (nstep == 0) then - doalb = .false. - nextsw_cday = caldayp1 - else if (nstep == 1) then +!KO if (nstep == 0) then +!KO doalb = .false. +!KO nextsw_cday = caldayp1 +!KO else if (nstep == 1) then +!KO !doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) +!KO doalb = .false. +!KO else +!KO doalb = (nextsw_cday >= -0.5_r8) +!KO end if +!KO ! Removed the nstep=0 check + if (nstep == 1) then !doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) doalb = .false. else doalb = (nextsw_cday >= -0.5_r8) end if +!KO if (masterproc) then write(iulog,*) '------------ LILAC ----------------' diff --git a/src/cpl/nuopc/lnd_comp_nuopc.F90 b/src/cpl/nuopc/lnd_comp_nuopc.F90 index 90ec0fcb0a..ef645a10e8 100644 --- a/src/cpl/nuopc/lnd_comp_nuopc.F90 +++ b/src/cpl/nuopc/lnd_comp_nuopc.F90 @@ -823,7 +823,10 @@ subroutine ModelAdvance(gcomp, rc) ! TODO: This is currently hard-wired - is there a better way for nuopc? ! Note that the model clock is updated at the end of the time step not at the beginning nstep = get_nstep() +!KO ! TODO (KWO 07-25-2023) !KO ! I don't think this is necessary anymore since there is no longer an nstep=0 +!KO ! In fact, according to the following comment in src/cpl/lilac/lnd_comp_esmf.F90 we should +!KO ! be able to remove this do while loop and the dosend variable. !KO if (nstep > 0) then dosend = .true. !KO end if From b8be204f5ce92085142ede21b492aca6e73103d1 Mon Sep 17 00:00:00 2001 From: Keith Oleson Date: Tue, 25 Jul 2023 16:30:15 -0600 Subject: [PATCH 03/27] Remove do while loop and dosend variable. --- src/cpl/lilac/lnd_comp_esmf.F90 | 26 ++++++++++++++------------ src/cpl/nuopc/lnd_comp_nuopc.F90 | 13 ++++++------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/cpl/lilac/lnd_comp_esmf.F90 b/src/cpl/lilac/lnd_comp_esmf.F90 index dbb9c26f73..b959dbabb7 100644 --- a/src/cpl/lilac/lnd_comp_esmf.F90 +++ b/src/cpl/lilac/lnd_comp_esmf.F90 @@ -554,7 +554,7 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) integer :: nstep ! time step index logical :: rstwr ! .true. ==> write restart file before returning logical :: nlend ! .true. ==> last time-step - logical :: dosend ! true => send data back to driver +!KO logical :: dosend ! true => send data back to driver logical :: doalb ! .true. ==> do albedo calculation on this time step real(r8) :: nextsw_cday ! calday from clock of next radiation computation real(r8) :: caldayp1 ! ctsm calday plus dtime offset @@ -621,22 +621,24 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) !-------------------------------- dtime = get_step_size() - dosend = .false. - do while(.not. dosend) +!KO dosend = .false. +!KO do while(.not. dosend) - ! We assume that the land model time step matches the coupling interval. However, - ! we still need this while loop to handle the initial time step (time 0). We may - ! want to get rid of this time step 0 in the lilac coupling, at which point we - ! should be able to remove this while loop and dosend variable. +!KO ! We assume that the land model time step matches the coupling interval. However, +!KO ! we still need this while loop to handle the initial time step (time 0). We may +!KO ! want to get rid of this time step 0 in the lilac coupling, at which point we +!KO ! should be able to remove this while loop and dosend variable. +!KO + ! We assume that the land model time step matches the coupling interval. +!KO ! - ! See also https://github.com/ESCOMP/CTSM/issues/925 +!KO ! See also https://github.com/ESCOMP/CTSM/issues/925 nstep = get_nstep() -!KO ! TODO (KWO 07-25-2023) !KO ! I don't think this is necessary anymore since there is no longer an nstep=0 !KO ! In fact, according to the comment above we should be able to remove this -!KO ! do while loop and the dosend variable. +!KO ! do while loop and the dosend variable. I've done that here. !KO if (nstep > 0) then - dosend = .true. +!KO dosend = .true. !KO end if !-------------------------------- @@ -787,7 +789,7 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) call advance_timestep() - end do +!KO end do !-------------------------------- ! Check that internal clock is in sync with lilac driver clock diff --git a/src/cpl/nuopc/lnd_comp_nuopc.F90 b/src/cpl/nuopc/lnd_comp_nuopc.F90 index ef645a10e8..82e386c6da 100644 --- a/src/cpl/nuopc/lnd_comp_nuopc.F90 +++ b/src/cpl/nuopc/lnd_comp_nuopc.F90 @@ -741,7 +741,7 @@ subroutine ModelAdvance(gcomp, rc) integer :: localPeCount ! Number of local Processors logical :: rstwr ! .true. ==> write restart file before returning logical :: nlend ! .true. ==> last time-step - logical :: dosend ! true => send data back to driver +!KO logical :: dosend ! true => send data back to driver logical :: doalb ! .true. ==> do albedo calculation on this time step real(r8) :: nextsw_cday ! calday from clock of next radiation computation real(r8) :: caldayp1 ! ctsm calday plus dtime offset @@ -817,18 +817,17 @@ subroutine ModelAdvance(gcomp, rc) !-------------------------------- dtime = get_step_size() - dosend = .false. - do while(.not. dosend) +!KO dosend = .false. +!KO do while(.not. dosend) ! TODO: This is currently hard-wired - is there a better way for nuopc? ! Note that the model clock is updated at the end of the time step not at the beginning nstep = get_nstep() -!KO ! TODO (KWO 07-25-2023) !KO ! I don't think this is necessary anymore since there is no longer an nstep=0 !KO ! In fact, according to the following comment in src/cpl/lilac/lnd_comp_esmf.F90 we should -!KO ! be able to remove this do while loop and the dosend variable. +!KO ! be able to remove this do while loop and the dosend variable. I've done that here. !KO if (nstep > 0) then - dosend = .true. +!KO dosend = .true. !KO end if !-------------------------------- @@ -934,7 +933,7 @@ subroutine ModelAdvance(gcomp, rc) call advance_timestep() call t_stopf ('lc_ctsm2_adv_timestep') - end do +!KO end do ! Check that internal clock is in sync with master clock ! Note that the driver clock has not been updated yet - so at this point From 7f38c07983cef12c5d86213059bff6cb4a12452d Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 25 Jul 2023 17:03:42 -0600 Subject: [PATCH 04/27] Fix unit tests for nstep starting at 1 instead of 0 --- src/unit_test_shr/unittestTimeManagerMod.F90 | 8 +------- .../test/clm_time_manager_test/test_clm_time_manager.pf | 8 ++++---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/unit_test_shr/unittestTimeManagerMod.F90 b/src/unit_test_shr/unittestTimeManagerMod.F90 index efc60ec786..8e1cdb3f36 100644 --- a/src/unit_test_shr/unittestTimeManagerMod.F90 +++ b/src/unit_test_shr/unittestTimeManagerMod.F90 @@ -177,12 +177,6 @@ subroutine unittest_timemgr_set_nstep(nstep) ! !DESCRIPTION: ! Set the time step number ! -!KO - ! Comment not needed now? -!KO - ! Note that the starting time step number is 0, so calling this with nstep = 1 - ! advances the time step beyond the starting time step. - ! ! !USES: use clm_time_manager, only : advance_timestep ! @@ -195,7 +189,7 @@ subroutine unittest_timemgr_set_nstep(nstep) character(len=*), parameter :: subname = 'unittest_timemgr_set_nstep' !----------------------------------------------------------------------- - do n = 1, nstep + do n = 2, nstep call advance_timestep() end do diff --git a/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf b/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf index 435d795e50..239f9924cf 100644 --- a/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf +++ b/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf @@ -277,7 +277,7 @@ contains end subroutine getPrevYearfrac_leapYearAtYearBoundary_returnsCorrectValue @Test - subroutine getNstep_step0(this) + subroutine getNstep_step1(this) class(TestTimeManager), intent(inout) :: this integer :: nstep @@ -285,8 +285,8 @@ contains nstep = get_nstep() - @assertEqual(0, nstep) - end subroutine getNstep_step0 + @assertEqual(1, nstep) + end subroutine getNstep_step1 @Test subroutine getNstep_step3(this) @@ -378,7 +378,7 @@ contains call unittest_timemgr_setup(dtime=dtime) - call set_nstep(1) + call set_nstep(2) is_first = is_first_step() From 750ed1d20e04778470f8b2c11cedc7f9d7e93b64 Mon Sep 17 00:00:00 2001 From: Keith Oleson Date: Thu, 27 Jul 2023 10:10:51 -0600 Subject: [PATCH 05/27] Cleanup. --- src/cpl/lilac/lnd_comp_esmf.F90 | 266 ++++++++++++++----------------- src/cpl/nuopc/lnd_comp_nuopc.F90 | 186 ++++++++++----------- 2 files changed, 201 insertions(+), 251 deletions(-) diff --git a/src/cpl/lilac/lnd_comp_esmf.F90 b/src/cpl/lilac/lnd_comp_esmf.F90 index b959dbabb7..3d4b90bfba 100644 --- a/src/cpl/lilac/lnd_comp_esmf.F90 +++ b/src/cpl/lilac/lnd_comp_esmf.F90 @@ -554,7 +554,6 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) integer :: nstep ! time step index logical :: rstwr ! .true. ==> write restart file before returning logical :: nlend ! .true. ==> last time-step -!KO logical :: dosend ! true => send data back to driver logical :: doalb ! .true. ==> do albedo calculation on this time step real(r8) :: nextsw_cday ! calday from clock of next radiation computation real(r8) :: caldayp1 ! ctsm calday plus dtime offset @@ -621,175 +620,146 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) !-------------------------------- dtime = get_step_size() -!KO dosend = .false. -!KO do while(.not. dosend) - -!KO ! We assume that the land model time step matches the coupling interval. However, -!KO ! we still need this while loop to handle the initial time step (time 0). We may -!KO ! want to get rid of this time step 0 in the lilac coupling, at which point we -!KO ! should be able to remove this while loop and dosend variable. -!KO - ! We assume that the land model time step matches the coupling interval. -!KO - ! -!KO ! See also https://github.com/ESCOMP/CTSM/issues/925 - nstep = get_nstep() -!KO ! I don't think this is necessary anymore since there is no longer an nstep=0 -!KO ! In fact, according to the comment above we should be able to remove this -!KO ! do while loop and the dosend variable. I've done that here. -!KO if (nstep > 0) then -!KO dosend = .true. -!KO end if - - !-------------------------------- - ! Determine calendar day info - !-------------------------------- - - calday = get_curr_calday(reuse_day_365_for_day_366=.true.) - caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.) - - !-------------------------------- - ! Get time of next atmospheric shortwave calculation - !-------------------------------- - - ! TODO(NS): nextsw_cday should come directly from atmosphere! - ! For now I am setting nextsw_cday to be the same caldayp1 - ! - ! See also https://github.com/ESCOMP/CTSM/issues/860 - - nextsw_cday = calday - if (masterproc) then - write(iulog,*) trim(subname) // '... nextsw_cday is : ', nextsw_cday - end if - !-------------------------------- - ! Obtain orbital values - !-------------------------------- - - call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf ) - call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf ) - - if (masterproc) then - write(iulog,*) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' - write(iulog,F02) 'nextsw_cday is : ', nextsw_cday - write(iulog,F02) 'calday is : ', calday - write(iulog,F02) 'eccen is : ', eccen - write(iulog,F02) 'mvelpp is : ', mvelpp - write(iulog,F02) 'lambm0 is : ', lambm0 - write(iulog,F02) 'obliqr is : ', obliqr - write(iulog,F02) 'declin is : ', declin - write(iulog,F02) 'declinp1 is : ', declinp1 - write(iulog,* ) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' - end if + ! We assume that the land model time step matches the coupling interval. + nstep = get_nstep() - !-------------------------------- - ! Determine doalb based on nextsw_cday sent from atm model - !-------------------------------- - -!KO if (nstep == 0) then -!KO doalb = .false. -!KO nextsw_cday = caldayp1 -!KO else if (nstep == 1) then -!KO !doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) -!KO doalb = .false. -!KO else -!KO doalb = (nextsw_cday >= -0.5_r8) -!KO end if -!KO ! Removed the nstep=0 check - if (nstep == 1) then - !doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) - doalb = .false. - else - doalb = (nextsw_cday >= -0.5_r8) - end if -!KO - - if (masterproc) then - write(iulog,*) '------------ LILAC ----------------' - write(iulog,*) 'nstep : ', nstep - write(iulog,*) 'calday : ', calday - write(iulog,*) 'caldayp1 : ', caldayp1 - write(iulog,*) 'nextsw_cday : ', nextsw_cday - write(iulog,*) 'doalb : ', doalb - write(iulog,*) '-------------------------------------' - end if + !-------------------------------- + ! Determine calendar day info + !-------------------------------- - call update_rad_dtime(doalb) + calday = get_curr_calday(reuse_day_365_for_day_366=.true.) + caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.) - !-------------------------------- - ! Determine if time to write restart - !-------------------------------- + !-------------------------------- + ! Get time of next atmospheric shortwave calculation + !-------------------------------- - call ESMF_ClockGetAlarm(clock, alarmname='lilac_restart_alarm', alarm=alarm, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! TODO(NS): nextsw_cday should come directly from atmosphere! + ! For now I am setting nextsw_cday to be the same caldayp1 + ! + ! See also https://github.com/ESCOMP/CTSM/issues/860 - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - rstwr = .true. - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - else - rstwr = .false. - endif - if (masterproc) then - write(iulog,*)' restart alarm is ',rstwr - end if + nextsw_cday = calday + if (masterproc) then + write(iulog,*) trim(subname) // '... nextsw_cday is : ', nextsw_cday + end if + + !-------------------------------- + ! Obtain orbital values + !-------------------------------- - !-------------------------------- - ! Determine if time to stop - !-------------------------------- + call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf ) + call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf ) - call ESMF_ClockGetAlarm(clock, alarmname='lilac_stop_alarm', alarm=alarm, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (masterproc) then + write(iulog,*) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + write(iulog,F02) 'nextsw_cday is : ', nextsw_cday + write(iulog,F02) 'calday is : ', calday + write(iulog,F02) 'eccen is : ', eccen + write(iulog,F02) 'mvelpp is : ', mvelpp + write(iulog,F02) 'lambm0 is : ', lambm0 + write(iulog,F02) 'obliqr is : ', obliqr + write(iulog,F02) 'declin is : ', declin + write(iulog,F02) 'declinp1 is : ', declinp1 + write(iulog,* ) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + end if - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - nlend = .true. - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - else - nlend = .false. - endif - if (masterproc) then - write(iulog,*)' stop alarm is ',nlend - end if + !-------------------------------- + ! Determine doalb based on nextsw_cday sent from atm model + !-------------------------------- - !-------------------------------- - ! Run CTSM - !-------------------------------- + if (nstep == 1) then + !doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) + doalb = .false. + else + doalb = (nextsw_cday >= -0.5_r8) + end if - call t_barrierf('sync_ctsm_run1', mpicom) + if (masterproc) then + write(iulog,*) '------------ LILAC ----------------' + write(iulog,*) 'nstep : ', nstep + write(iulog,*) 'calday : ', calday + write(iulog,*) 'caldayp1 : ', caldayp1 + write(iulog,*) 'nextsw_cday : ', nextsw_cday + write(iulog,*) 'doalb : ', doalb + write(iulog,*) '-------------------------------------' + end if + + call update_rad_dtime(doalb) + + !-------------------------------- + ! Determine if time to write restart + !-------------------------------- - ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of - ! the timestep and is preferred for restart file names - ! TODO: is this correct for lilac? + call ESMF_ClockGetAlarm(clock, alarmname='lilac_restart_alarm', alarm=alarm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc) + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_TimeGet(nexttime, yy=yr_lilac, mm=mon_lilac, dd=day_lilac, s=tod_lilac, rc=rc) + rstwr = .true. + call ESMF_AlarmRingerOff( alarm, rc=rc ) if (ChkErr(rc,__LINE__,u_FILE_u)) return - write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_lilac, mon_lilac, day_lilac, tod_lilac + else + rstwr = .false. + endif + if (masterproc) then + write(iulog,*)' restart alarm is ',rstwr + end if - call t_startf ('ctsm_run') - call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic=.false.) - call t_stopf ('ctsm_run') + !-------------------------------- + ! Determine if time to stop + !-------------------------------- - !-------------------------------- - ! Pack export state - !-------------------------------- + call ESMF_ClockGetAlarm(clock, alarmname='lilac_stop_alarm', alarm=alarm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return - call t_startf ('lc_lnd_export') - call export_fields(export_state, bounds, rc) + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then + if (ChkErr(rc,__LINE__,u_FILE_u)) return + nlend = .true. + call ESMF_AlarmRingerOff( alarm, rc=rc ) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call t_stopf ('lc_lnd_export') + else + nlend = .false. + endif + if (masterproc) then + write(iulog,*)' stop alarm is ',nlend + end if + + !-------------------------------- + ! Run CTSM + !-------------------------------- + + call t_barrierf('sync_ctsm_run1', mpicom) + + ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of + ! the timestep and is preferred for restart file names + ! TODO: is this correct for lilac? + + call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TimeGet(nexttime, yy=yr_lilac, mm=mon_lilac, dd=day_lilac, s=tod_lilac, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_lilac, mon_lilac, day_lilac, tod_lilac - !-------------------------------- - ! Advance ctsm time step - !-------------------------------- + call t_startf ('ctsm_run') + call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic=.false.) + call t_stopf ('ctsm_run') - call advance_timestep() + !-------------------------------- + ! Pack export state + !-------------------------------- + + call t_startf ('lc_lnd_export') + call export_fields(export_state, bounds, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call t_stopf ('lc_lnd_export') + + !-------------------------------- + ! Advance ctsm time step + !-------------------------------- -!KO end do + call advance_timestep() !-------------------------------- ! Check that internal clock is in sync with lilac driver clock diff --git a/src/cpl/nuopc/lnd_comp_nuopc.F90 b/src/cpl/nuopc/lnd_comp_nuopc.F90 index 82e386c6da..a6c97f617b 100644 --- a/src/cpl/nuopc/lnd_comp_nuopc.F90 +++ b/src/cpl/nuopc/lnd_comp_nuopc.F90 @@ -741,7 +741,6 @@ subroutine ModelAdvance(gcomp, rc) integer :: localPeCount ! Number of local Processors logical :: rstwr ! .true. ==> write restart file before returning logical :: nlend ! .true. ==> last time-step -!KO logical :: dosend ! true => send data back to driver logical :: doalb ! .true. ==> do albedo calculation on this time step real(r8) :: nextsw_cday ! calday from clock of next radiation computation real(r8) :: caldayp1 ! ctsm calday plus dtime offset @@ -817,123 +816,104 @@ subroutine ModelAdvance(gcomp, rc) !-------------------------------- dtime = get_step_size() -!KO dosend = .false. -!KO do while(.not. dosend) - - ! TODO: This is currently hard-wired - is there a better way for nuopc? - ! Note that the model clock is updated at the end of the time step not at the beginning - nstep = get_nstep() -!KO ! I don't think this is necessary anymore since there is no longer an nstep=0 -!KO ! In fact, according to the following comment in src/cpl/lilac/lnd_comp_esmf.F90 we should -!KO ! be able to remove this do while loop and the dosend variable. I've done that here. -!KO if (nstep > 0) then -!KO dosend = .true. -!KO end if - - !-------------------------------- - ! Determine doalb based on nextsw_cday sent from atm model - !-------------------------------- - - caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.) - -!KO if (nstep == 0) then -!KO doalb = .false. -!KO else if (nstep == 1) then -!KO doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) -!KO else -!KO doalb = (nextsw_cday >= -0.5_r8) -!KO end if -!KO -!KO ! Removed the nstep=0 check - if (nstep == 1) then - doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) - else - doalb = (nextsw_cday >= -0.5_r8) - end if -!KO - call update_rad_dtime(doalb) - !-------------------------------- - ! Determine if time to stop - !-------------------------------- + ! TODO: This is currently hard-wired - is there a better way for nuopc? + ! Note that the model clock is updated at the end of the time step not at the beginning + nstep = get_nstep() - call ESMF_ClockGetAlarm(clock, alarmname='alarm_stop', alarm=alarm, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + !-------------------------------- + ! Determine doalb based on nextsw_cday sent from atm model + !-------------------------------- - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - nlend = .true. - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - else - nlend = .false. - endif + caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.) - !-------------------------------- - ! Determine if time to write restart - !-------------------------------- - rstwr = .false. - if (nlend .and. write_restart_at_endofrun) then - rstwr = .true. - else - call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ESMF_AlarmIsCreated(alarm, rc=rc)) then - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - rstwr = .true. - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - endif - endif - end if + if (nstep == 1) then + doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) + else + doalb = (nextsw_cday >= -0.5_r8) + end if - !-------------------------------- - ! Run CTSM - !-------------------------------- + call update_rad_dtime(doalb) - ! call ESMF_VMBarrier(vm, rc=rc) - ! if (ChkErr(rc,__LINE__,u_FILE_u)) return + !-------------------------------- + ! Determine if time to stop + !-------------------------------- - call t_startf ('shr_orb_decl') - ! Note - the orbital inquiries set the values in clm_varorb via the module use statements - call clm_orbital_update(clock, iulog, masterproc, eccen, obliqr, lambm0, mvelpp, rc) + call ESMF_ClockGetAlarm(clock, alarmname='alarm_stop', alarm=alarm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then if (ChkErr(rc,__LINE__,u_FILE_u)) return - calday = get_curr_calday(reuse_day_365_for_day_366=.true.) - call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf ) - call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf ) - call t_stopf ('shr_orb_decl') - - call t_startf ('ctsm_run') - ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of - ! the timestep and is preferred for restart file names - call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc) + nlend = .true. + call ESMF_AlarmRingerOff( alarm, rc=rc ) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_TimeGet(nexttime, yy=yr_sync, mm=mon_sync, dd=day_sync, s=tod_sync, rc=rc) + else + nlend = .false. + endif + + !-------------------------------- + ! Determine if time to write restart + !-------------------------------- + rstwr = .false. + if (nlend .and. write_restart_at_endofrun) then + rstwr = .true. + else + call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_sync, mon_sync, day_sync, tod_sync - call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic) - call t_stopf ('ctsm_run') + if (ESMF_AlarmIsCreated(alarm, rc=rc)) then + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rstwr = .true. + call ESMF_AlarmRingerOff( alarm, rc=rc ) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + endif + endif + end if - !-------------------------------- - ! Pack export state - !-------------------------------- + !-------------------------------- + ! Run CTSM + !-------------------------------- - call t_startf ('lc_lnd_export') - call export_fields(gcomp, bounds, glc_present, rof_prognostic, & - water_inst%waterlnd2atmbulk_inst, lnd2atm_inst, lnd2glc_inst, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call t_stopf ('lc_lnd_export') + ! call ESMF_VMBarrier(vm, rc=rc) + ! if (ChkErr(rc,__LINE__,u_FILE_u)) return - !-------------------------------- - ! Advance ctsm time step - !-------------------------------- + call t_startf ('shr_orb_decl') + ! Note - the orbital inquiries set the values in clm_varorb via the module use statements + call clm_orbital_update(clock, iulog, masterproc, eccen, obliqr, lambm0, mvelpp, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + calday = get_curr_calday(reuse_day_365_for_day_366=.true.) + call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf ) + call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf ) + call t_stopf ('shr_orb_decl') + + call t_startf ('ctsm_run') + ! Restart File - use nexttimestr rather than currtimestr here since that is the time at the end of + ! the timestep and is preferred for restart file names + call ESMF_ClockGetNextTime(clock, nextTime=nextTime, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TimeGet(nexttime, yy=yr_sync, mm=mon_sync, dd=day_sync, s=tod_sync, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_sync, mon_sync, day_sync, tod_sync + call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic) + call t_stopf ('ctsm_run') + + !-------------------------------- + ! Pack export state + !-------------------------------- + + call t_startf ('lc_lnd_export') + call export_fields(gcomp, bounds, glc_present, rof_prognostic, & + water_inst%waterlnd2atmbulk_inst, lnd2atm_inst, lnd2glc_inst, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call t_stopf ('lc_lnd_export') - call t_startf ('lc_ctsm2_adv_timestep') - call advance_timestep() - call t_stopf ('lc_ctsm2_adv_timestep') + !-------------------------------- + ! Advance ctsm time step + !-------------------------------- -!KO end do + call t_startf ('lc_ctsm2_adv_timestep') + call advance_timestep() + call t_stopf ('lc_ctsm2_adv_timestep') ! Check that internal clock is in sync with master clock ! Note that the driver clock has not been updated yet - so at this point From caa384b75ce962e2fa1d7c4fc22f92fc45ffd4a4 Mon Sep 17 00:00:00 2001 From: Keith Oleson Date: Tue, 1 Aug 2023 11:36:15 -0600 Subject: [PATCH 06/27] Remove comment. --- src/utils/clm_time_manager.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index 31e9b30927..da8c73ed43 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -680,7 +680,6 @@ subroutine advance_timestep() call ESMF_ClockAdvance( tm_clock, rc=rc ) call chkrc(rc, sub//': error return from ESMF_ClockAdvance') -!KO Do we want to do this? tm_first_restart_step = .false. end subroutine advance_timestep From 0dfd9018c7cd7581127c7ee4fee51554b00f196d Mon Sep 17 00:00:00 2001 From: Keith Oleson Date: Thu, 3 Aug 2023 12:42:27 -0600 Subject: [PATCH 07/27] Remove BACKWARD COMPATIBILITY comment. --- src/biogeochem/CNPhenologyMod.F90 | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index 7ce359aa53..4f5323b888 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -366,21 +366,8 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & soilstate_inst, temperature_inst, atm2lnd_inst, wateratm2lndbulk_inst, cnveg_state_inst, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) - ! BACKWARDS_COMPATIBILITY(wjs, 2022-02-03) Old restart files generated at the end - ! of the year can indicate that a crop was panted on Jan 1, because that used to be - ! the time given to the last time step of the year. This would cause problems if we - ! ran CropPhenology in time step 0, because now time step 0 is labeled as Dec 31, - ! so CropPhenology would see the crop as having been planted 364 days ago, and so - ! would want to harvest this newly-planted crop. To avoid this situation, we avoid - ! calling CropPhenology on time step 0. - ! - ! This .not. is_first_step() condition can be removed either when we can rely on - ! all restart files having been generated with - ! https://github.com/ESCOMP/CTSM/issues/1623 resolved, or we stop having a time - ! step 0 (https://github.com/ESCOMP/CTSM/issues/925). !KO if (num_pcropp > 0 .and. .not. is_first_step()) then !KO - ! Unknown if all restart files have been generated with 1623 resolved but we no longer have a time step 0 if (num_pcropp > 0) then !KO call CropPhenology(num_pcropp, filter_pcropp, & From c9c89a80b5c0706c74b4f7dafa10fe0b8e5cee1e Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 1 Nov 2023 15:27:03 -0600 Subject: [PATCH 08/27] Correct a comment. --- python/ctsm/crop_calendars/generate_gdds_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index cb05f1920d..b677423173 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -217,7 +217,7 @@ def import_and_process_1yr( else: chunks = None - # Get h2 file (list) + # Get h1 file (list) h1_pattern = os.path.join(indir, "*h1.*.nc") h1_filelist = glob.glob(h1_pattern) if not h1_filelist: From d0592208e9cdd9579a0ace44b994fcf77dec1c33 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 1 Nov 2023 15:35:39 -0600 Subject: [PATCH 09/27] Print error()s to console, not just log file. --- python/ctsm/crop_calendars/generate_gdds_functions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index b677423173..e741b59bb7 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -45,6 +45,7 @@ def log(logger, string): def error(logger, string): + print(string) logger.error(string) raise RuntimeError(string) From b311d1d35b34eb05ad12e9276832404ca64f8562 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 1 Nov 2023 15:27:44 -0600 Subject: [PATCH 10/27] Rearrange search for h2 files in import_and_process_1yr(). --- .../ctsm/crop_calendars/generate_gdds_functions.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index e741b59bb7..74207c6e2c 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -478,13 +478,14 @@ def import_and_process_1yr( log(logger, f" Importing accumulated GDDs...") clm_gdd_var = "GDDACCUM" myVars = [clm_gdd_var, "GDDHARV"] - pattern = os.path.join(indir, f"*h2.{thisYear-1}-01-01*.nc") - h2_files = glob.glob(pattern) - if not h2_files: - pattern = os.path.join(indir, f"*h2.{thisYear-1}-01-01*.nc.base") + patterns = [f"*h2.{thisYear-1}-01-01*.nc", f"*h2.{thisYear-1}-01-01*.nc.base"] + for p in patterns: + pattern = os.path.join(indir, p) h2_files = glob.glob(pattern) - if not h2_files: - error(logger, f"No files found matching pattern '*h2.{thisYear-1}-01-01*.nc(.base)'") + if h2_files: + break + if not h2_files: + error(logger, f"No files found matching patterns: {patterns}") h2_ds = utils.import_ds( h2_files, myVars=myVars, From fa843e5ee095431bd5faf1930be8c764fb392f8e Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Wed, 1 Nov 2023 15:36:15 -0600 Subject: [PATCH 11/27] Fix h2 file patterns in import_and_process_1yr(). --- python/ctsm/crop_calendars/generate_gdds_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index 74207c6e2c..bc197cd429 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -478,7 +478,7 @@ def import_and_process_1yr( log(logger, f" Importing accumulated GDDs...") clm_gdd_var = "GDDACCUM" myVars = [clm_gdd_var, "GDDHARV"] - patterns = [f"*h2.{thisYear-1}-01-01*.nc", f"*h2.{thisYear-1}-01-01*.nc.base"] + patterns = [f"*h2.{thisYear-1}-01*.nc", f"*h2.{thisYear-1}-01*.nc.base"] for p in patterns: pattern = os.path.join(indir, p) h2_files = glob.glob(pattern) From 258792e9c2ecf34d5e7dd58b556b34330edd0884 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 28 Mar 2024 17:27:56 -0600 Subject: [PATCH 12/27] If avgflag /= 'I', time_bounds is present and time = mid of time_bounds ...and other mods that I'm preserving from closed PR #2019, such as - changes to long_names and - treating avgflag as a tape (not field) trait for 'I' and 'L' tapes --- src/main/histFileMod.F90 | 65 +++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index 863bf6e987..eb3d42348f 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -1170,6 +1170,7 @@ subroutine htape_addfld (t, f, avgflag) integer :: beg1d,end1d ! beginning and ending indices for this field (assume already set) integer :: num1d_out ! history output 1d size type(bounds_type) :: bounds + character(len=avgflag_strlen) :: avgflag_temp ! local copy of hist_avgflag_pertape(t) character(len=*),parameter :: subname = 'htape_addfld' !----------------------------------------------------------------------- @@ -1300,6 +1301,19 @@ subroutine htape_addfld (t, f, avgflag) tape(t)%hlist(n)%avgflag = avgflag end if + ! Override this tape's avgflag if nhtfrq == 1 + if (tape(t)%nhtfrq == 1) then ! output is instantaneous + hist_avgflag_pertape(t) = 'I' + end if + ! Override this field's avgflag if the namelist or the previous line + ! has set this tape to + ! - instantaneous (I) or + ! - local time (L) + avgflag_temp = hist_avgflag_pertape(t) + if (avgflag_temp == 'I' .or. avgflag_temp(1:1) == 'L') then + tape(t)%hlist(n)%avgflag = avgflag_temp + end if + end subroutine htape_addfld !----------------------------------------------------------------------- @@ -3093,6 +3107,7 @@ subroutine htape_timeconst(t, mode) integer :: mcdate ! current date integer :: yr,mon,day,nbsec ! year,month,day,seconds components of a date integer :: hours,minutes,secs ! hours,minutes,seconds of hh:mm:ss + character(len= 12) :: step_or_bounds ! string used in long_name of several time variables character(len= 10) :: basedate ! base date (yyyymmdd) character(len= 8) :: basesec ! base seconds character(len= 8) :: cdate ! system date @@ -3352,8 +3367,18 @@ subroutine htape_timeconst(t, mode) dim1id(1) = time_dimid str = 'days since ' // basedate // " " // basesec - call ncd_defvar(nfid(t), 'time', tape(t)%ncprec, 1, dim1id, varid, & - long_name='time',units=str) + if (tape(t)%hlist(1)%avgflag /= 'I') then ! NOT instantaneous fields tape + step_or_bounds = 'time_bounds' + long_name = 'time at exact middle of ' // step_or_bounds + call ncd_defvar(nfid(t), 'time', tape(t)%ncprec, 1, dim1id, varid, & + long_name=long_name, units=str) + call ncd_putatt(nfid(t), varid, 'bounds', 'time_bounds') + else ! instantaneous fields tape + step_or_bounds = 'time step' + long_name = 'time at end of ' // step_or_bounds + call ncd_defvar(nfid(t), 'time', tape(t)%ncprec, 1, dim1id, varid, & + long_name=long_name, units=str) + end if cal = get_calendar() if ( trim(cal) == NO_LEAP_C )then caldesc = "noleap" @@ -3361,11 +3386,11 @@ subroutine htape_timeconst(t, mode) caldesc = "gregorian" end if call ncd_putatt(nfid(t), varid, 'calendar', caldesc) - call ncd_putatt(nfid(t), varid, 'bounds', 'time_bounds') dim1id(1) = time_dimid + long_name = 'current date (YYYYMMDD) at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mcdate', ncd_int, 1, dim1id , varid, & - long_name = 'current date (YYYYMMDD)') + long_name = long_name) ! ! add global attribute time_period_freq ! @@ -3392,18 +3417,23 @@ subroutine htape_timeconst(t, mode) call ncd_putatt(nfid(t), ncd_global, 'time_period_freq', & trim(time_period_freq)) + long_name = 'current seconds of current date at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mcsec' , ncd_int, 1, dim1id , varid, & - long_name = 'current seconds of current date', units='s') + long_name = long_name, units='s') + long_name = 'current day (from base day) at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mdcur' , ncd_int, 1, dim1id , varid, & - long_name = 'current day (from base day)') + long_name = long_name) + long_name = 'current seconds of current day at end of ' // step_or_bounds call ncd_defvar(nfid(t) , 'mscur' , ncd_int, 1, dim1id , varid, & - long_name = 'current seconds of current day') + long_name = long_name) call ncd_defvar(nfid(t) , 'nstep' , ncd_int, 1, dim1id , varid, & long_name = 'time step') dim2id(1) = hist_interval_dimid; dim2id(2) = time_dimid - call ncd_defvar(nfid(t), 'time_bounds', ncd_double, 2, dim2id, varid, & - long_name = 'history time interval endpoints') + if (tape(t)%hlist(1)%avgflag /= 'I') then ! NOT instantaneous fields tape + call ncd_defvar(nfid(t), 'time_bounds', ncd_double, 2, dim2id, varid, & + long_name = 'history time interval endpoints') + end if dim2id(1) = strlen_dimid; dim2id(2) = time_dimid call ncd_defvar(nfid(t), 'date_written', ncd_char, 2, dim2id, varid) @@ -3431,13 +3461,16 @@ subroutine htape_timeconst(t, mode) call ncd_io('mscur' , mscur , 'write', nfid(t), nt=tape(t)%ntimes) call ncd_io('nstep' , nstep , 'write', nfid(t), nt=tape(t)%ntimes) - time = mdcur + mscur/secspday + timedata(1) = tape(t)%begtime ! beginning time + timedata(2) = mdcur + mscur/secspday ! end time + if (tape(t)%hlist(1)%avgflag /= 'I') then ! NOT instantaneous fields tape + time = (timedata(1) + timedata(2)) * 0.5_r8 + call ncd_io('time_bounds', timedata, 'write', nfid(t), nt=tape(t)%ntimes) + else + time = timedata(2) + end if call ncd_io('time' , time , 'write', nfid(t), nt=tape(t)%ntimes) - timedata(1) = tape(t)%begtime - timedata(2) = time - call ncd_io('time_bounds', timedata, 'write', nfid(t), nt=tape(t)%ntimes) - call getdatetime (cdate, ctime) call ncd_io('date_written', cdate, 'write', nfid(t), nt=tape(t)%ntimes) @@ -5254,6 +5287,10 @@ character(len=max_length_filename) function set_hist_filename (hist_freq, hist_m write(cdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr,mon,day,sec endif write(hist_index,'(i1.1)') hist_file - 1 + ! TODO slevis: After hist_index add "i" or "a" + ! For guidance on how to split the files, search for + ! maxsplitfiles in https://github.com/ESCOMP/CAM/pull/903/files + ! See CAM#1003 for a bug-fix in monthly avged output set_hist_filename = "./"//trim(caseid)//"."//trim(compname)//trim(inst_suffix)//& ".h"//hist_index//"."//trim(cdate)//".nc" From 1e81456204eeb0032c7f2514171c8c2396f709f8 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Thu, 17 Oct 2024 17:59:47 -0600 Subject: [PATCH 13/27] Remove a comment unrelated to these modifications --- src/main/histFileMod.F90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index bebc40f733..e449714e3c 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -5278,10 +5278,6 @@ character(len=max_length_filename) function set_hist_filename (hist_freq, hist_m write(cdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr,mon,day,sec endif write(hist_index,'(i1.1)') hist_file - 1 - ! TODO slevis: After hist_index add "i" or "a" - ! For guidance on how to split the files, search for - ! maxsplitfiles in https://github.com/ESCOMP/CAM/pull/903/files - ! See CAM#1003 for a bug-fix in monthly avged output set_hist_filename = "./"//trim(caseid)//"."//trim(compname)//trim(inst_suffix)//& ".h"//hist_index//"."//trim(cdate)//".nc" From d07fd9d4271cc86cb3b02e24458d72b9585e649d Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Mon, 11 Nov 2024 17:59:56 -0700 Subject: [PATCH 14/27] Removed comments with prefix !KO --- src/biogeochem/CNPhenologyMod.F90 | 3 -- src/biogeochem/CNVegetationFacade.F90 | 8 ----- src/biogeochem/CropType.F90 | 4 --- src/biogeochem/dynCNDVMod.F90 | 4 --- src/biogeophys/WaterStateType.F90 | 1 - src/main/clm_driver.F90 | 50 ++++++++++++--------------- src/main/histFileMod.F90 | 10 ------ src/utils/AnnualFluxDribbler.F90 | 3 -- src/utils/clm_time_manager.F90 | 7 +--- 9 files changed, 24 insertions(+), 66 deletions(-) diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index d1024e350f..5ad4fb1157 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -392,10 +392,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & soilstate_inst, temperature_inst, atm2lnd_inst, wateratm2lndbulk_inst, cnveg_state_inst, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) -!KO if (num_pcropp > 0 .and. .not. is_first_step()) then -!KO if (num_pcropp > 0) then -!KO call CropPhenology(num_pcropp, filter_pcropp, & waterdiagnosticbulk_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90 index 74a49f16a0..dd20ce50a2 100644 --- a/src/biogeochem/CNVegetationFacade.F90 +++ b/src/biogeochem/CNVegetationFacade.F90 @@ -1285,11 +1285,7 @@ subroutine EndOfTimeStepVegDynamics(this, bounds, num_natvegp, filter_natvegp, & ! Call dv (dynamic vegetation) at last time step of year call t_startf('d2dgvm') -!KO if (is_end_curr_year() .and. .not. is_first_step()) then -!KO - ! is_first_step check no longer necessary since there is no nstep=0 if (is_end_curr_year()) then -!KO ! Get date info. kyr is used in lpj(). At end of first year, kyr = 2. call get_curr_date(yr, mon, day, sec) @@ -1341,11 +1337,7 @@ subroutine WriteHistory(this, bounds) ! Write to CNDV history buffer if appropriate if (use_cndv) then -!KO if (is_end_curr_year() .and. .not. is_first_step()) then -!KO - ! is_first_step check no longer necessary since there is no nstep=0 if (is_end_curr_year()) then -!KO call t_startf('clm_drv_io_hdgvm') call CNDVHist( bounds, this%dgvs_inst ) if (masterproc) write(iulog,*) 'Annual CNDV calculations are complete' diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 9279347a44..54395c4668 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -930,11 +930,7 @@ subroutine CropIncrementYear (this, num_pcropp, filter_pcropp) ! Update nyrs when it's the end of the year (unless it's the very start of the ! run). This assumes that, if this patch is active at the end of the year, then it was ! active for the whole year. -!KO if ((kmo == 1 .and. kda == 1 .and. mcsec == 0) .and. .not. is_first_step()) then -!KO - ! is_first_step check no longer necessary since there is no nstep=0 if ((kmo == 1 .and. kda == 1 .and. mcsec == 0)) then -!KO do fp = 1, num_pcropp p = filter_pcropp(fp) diff --git a/src/biogeochem/dynCNDVMod.F90 b/src/biogeochem/dynCNDVMod.F90 index 57e90d8917..d95313772a 100644 --- a/src/biogeochem/dynCNDVMod.F90 +++ b/src/biogeochem/dynCNDVMod.F90 @@ -99,11 +99,7 @@ subroutine dynCNDV_interp( bounds, dgvs_inst) patch%wtcol(p) = dgvs_inst%fpcgrid_patch(p) + & wt1 * (dgvs_inst%fpcgridold_patch(p) - dgvs_inst%fpcgrid_patch(p)) -!KO ! I don't think this is necessary since there no longer an nstep=0 -!KO if (mon==1 .and. day==1 .and. sec==dtime .and. nstep>0) then -!KO if (mon==1 .and. day==1 .and. sec==dtime) then -!KO dgvs_inst%fpcgridold_patch(p) = dgvs_inst%fpcgrid_patch(p) end if end if diff --git a/src/biogeophys/WaterStateType.F90 b/src/biogeophys/WaterStateType.F90 index 15763c47a7..35441d65d9 100644 --- a/src/biogeophys/WaterStateType.F90 +++ b/src/biogeophys/WaterStateType.F90 @@ -810,7 +810,6 @@ subroutine Restart(this, bounds, ncid, flag, & ! If initial run -- ensure that water is properly bounded (read only) if (flag == 'read' ) then -!KO ! I think leaving this in here is still necessary even though is_first_step is now based on nstep=1 if ( is_first_step() .and. bound_h2osoi) then do c = bounds%begc, bounds%endc l = col%landunit(c) diff --git a/src/main/clm_driver.F90 b/src/main/clm_driver.F90 index e3f57afc8c..f93143d9e3 100644 --- a/src/main/clm_driver.F90 +++ b/src/main/clm_driver.F90 @@ -206,7 +206,6 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! are passed to CLM in initialization, then this code block can be removed. ! ======================================================================== -!KO I think leaving this in here is still necessary even though is_first_step is now based on nstep=1 need_glacier_initialization = is_first_step() if (need_glacier_initialization) then @@ -1369,41 +1368,38 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! FIX(SPM, 082814) - in the fates branch RF and I commented out the if(.not. ! use_fates) then statement ... double check if this is required and why -! I don't think this is necessary since there no longer an nstep=0 -!KO if (nstep > 0) then - call t_startf('accum') + call t_startf('accum') - call atm2lnd_inst%UpdateAccVars(bounds_proc) + call atm2lnd_inst%UpdateAccVars(bounds_proc) - call temperature_inst%UpdateAccVars(bounds_proc, crop_inst) + call temperature_inst%UpdateAccVars(bounds_proc, crop_inst) - call canopystate_inst%UpdateAccVars(bounds_proc) + call canopystate_inst%UpdateAccVars(bounds_proc) - call water_inst%UpdateAccVars(bounds_proc) + call water_inst%UpdateAccVars(bounds_proc) - call energyflux_inst%UpdateAccVars(bounds_proc) + call energyflux_inst%UpdateAccVars(bounds_proc) - ! COMPILER_BUG(wjs, 2014-11-30, pgi 14.7) For pgi 14.7 to be happy when - ! compiling this threaded, I needed to change the dummy arguments to be - ! pointers, and get rid of the explicit bounds in the subroutine call. - ! call bgc_vegetation_inst%UpdateAccVars(bounds_proc, & - ! t_a10_patch=temperature_inst%t_a10_patch(bounds_proc%begp:bounds_proc%endp), & - ! t_ref2m_patch=temperature_inst%t_ref2m_patch(bounds_proc%begp:bounds_proc%endp)) - call bgc_vegetation_inst%UpdateAccVars(bounds_proc, & - t_a10_patch=temperature_inst%t_a10_patch, & - t_ref2m_patch=temperature_inst%t_ref2m_patch) + ! COMPILER_BUG(wjs, 2014-11-30, pgi 14.7) For pgi 14.7 to be happy when + ! compiling this threaded, I needed to change the dummy arguments to be + ! pointers, and get rid of the explicit bounds in the subroutine call. + ! call bgc_vegetation_inst%UpdateAccVars(bounds_proc, & + ! t_a10_patch=temperature_inst%t_a10_patch(bounds_proc%begp:bounds_proc%endp), & + ! t_ref2m_patch=temperature_inst%t_ref2m_patch(bounds_proc%begp:bounds_proc%endp)) + call bgc_vegetation_inst%UpdateAccVars(bounds_proc, & + t_a10_patch=temperature_inst%t_a10_patch, & + t_ref2m_patch=temperature_inst%t_ref2m_patch) - if (use_crop) then - call crop_inst%CropUpdateAccVars(bounds_proc, & - temperature_inst%t_ref2m_patch, temperature_inst%t_soisno_col) - end if + if (use_crop) then + call crop_inst%CropUpdateAccVars(bounds_proc, & + temperature_inst%t_ref2m_patch, temperature_inst%t_soisno_col) + end if - if(use_fates) then - call clm_fates%UpdateAccVars(bounds_proc) - end if + if(use_fates) then + call clm_fates%UpdateAccVars(bounds_proc) + end if - call t_stopf('accum') -!KO end if + call t_stopf('accum') ! ============================================================================ ! Update history buffer diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index b98847ccc2..b51d98fa20 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -2662,10 +2662,7 @@ subroutine htape_timeconst3D(t, & ! !DESCRIPTION: ! Write time constant 3D variables to history tapes. ! Only write out when this subroutine is called (normally only for -!KO ! primary history files at very first time-step, nstep=0). -!KO ! primary history files at very first time-step, nstep=1). -!KO ! Issue the required netcdf wrapper calls to define the history file ! contents. ! @@ -4140,13 +4137,6 @@ subroutine hist_htapes_wrapup( rstwr, nlend, bounds, & cycle end if -!KO ! Should no longer be needed -!KO ! Skip nstep=0 if monthly average -!KO -!KO if (nstep==0 .and. tape(t)%nhtfrq==0) then -!KO cycle -!KO end if - ! Determine if end of history interval tape(t)%is_endhist = .false. if (tape(t)%nhtfrq==0) then !monthly average diff --git a/src/utils/AnnualFluxDribbler.F90 b/src/utils/AnnualFluxDribbler.F90 index a6a880d16e..8ea854b904 100644 --- a/src/utils/AnnualFluxDribbler.F90 +++ b/src/utils/AnnualFluxDribbler.F90 @@ -258,11 +258,8 @@ subroutine set_curr_delta(this, bounds, delta) do i = beg_index, end_index this%amount_from_this_timestep(i) = delta(i) end do -!KO if (.not. this%allows_non_annual_delta .and. .not. is_first_step()) then -!KO ! is_first_step check no longer necessary since there is no nstep=0 if (.not. this%allows_non_annual_delta) then -!KO do i = beg_index, end_index if (this%amount_from_this_timestep(i) /= 0._r8) then write(iulog,*) subname//' ERROR: found unexpected non-zero delta mid-year' diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index 924075937d..ea9d98599d 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -238,10 +238,8 @@ subroutine timemgr_init( ) tm_perp_date = TimeSetymd( perpetual_ymd, 0, "tm_perp_date" ) end if -!KO - ! Advance time step to start at nstep=1 (instead of nstep=0) + ! Advance time step to start at nstep=1 call advance_timestep() -!KO ! Print configuration summary to log file (stdout). @@ -1750,10 +1748,7 @@ logical function is_first_step() call ESMF_ClockGet( tm_clock, advanceCount=step_no, rc=rc ) call chkrc(rc, sub//': error return from ESMF_ClockGet') nstep = step_no -!KO is_first_step = (nstep == 0) -!KO is_first_step = (nstep == 1) -!KO end function is_first_step !========================================================================================= From a4b9dcff6bcc36ab64a4dd37a03df4e879d1bbba Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Nov 2024 12:07:59 -0700 Subject: [PATCH 15/27] Update docstring of is_first_step function --- src/utils/clm_time_manager.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index ea9d98599d..63f089a65e 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -1734,7 +1734,7 @@ end function is_end_curr_year logical function is_first_step() !--------------------------------------------------------------------------------- - ! Return true on first step of initial run only. + ! Return true on first step of any run. ! Local variables character(len=*), parameter :: sub = 'clm::is_first_step' From 4d0ac482f2fb26750f571b6c014e94e7c563ab5b Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Nov 2024 13:14:03 -0700 Subject: [PATCH 16/27] New update of function's docstring --- src/utils/clm_time_manager.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index 63f089a65e..be174d6a45 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -1734,7 +1734,7 @@ end function is_end_curr_year logical function is_first_step() !--------------------------------------------------------------------------------- - ! Return true on first step of any run. + ! Return true on first step of starup and hybrid runs. ! Local variables character(len=*), parameter :: sub = 'clm::is_first_step' From e578ae70e4f77fafdabbc8396712c8351ce4c921 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Nov 2024 13:16:29 -0700 Subject: [PATCH 17/27] Fix typo in comment --- src/utils/clm_time_manager.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index be174d6a45..64c5f32efc 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -1734,7 +1734,7 @@ end function is_end_curr_year logical function is_first_step() !--------------------------------------------------------------------------------- - ! Return true on first step of starup and hybrid runs. + ! Return true on first step of startup and hybrid runs. ! Local variables character(len=*), parameter :: sub = 'clm::is_first_step' From bd51b8c04edd5f394ab60ec7f84ba75b2586e073 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Nov 2024 15:17:24 -0700 Subject: [PATCH 18/27] Correct a variable name that came in with a merge conflict --- python/ctsm/crop_calendars/generate_gdds_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index 25012703d2..3e412814df 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -552,7 +552,7 @@ def import_and_process_1yr( log(logger, " Importing accumulated GDDs...") clm_gdd_var = "GDDACCUM" myVars = [clm_gdd_var, "GDDHARV"] - patterns = [f"*h2.{thisYear-1}-01*.nc", f"*h2.{thisYear-1}-01*.nc.base"] + patterns = [f"*h2.{this_year-1}-01*.nc", f"*h2.{this_year-1}-01*.nc.base"] for p in patterns: pattern = os.path.join(indir, p) h2_files = glob.glob(pattern) From e87b119d74be6c19c4f787e60ca9ec1e9eacbefd Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Tue, 12 Nov 2024 17:44:25 -0700 Subject: [PATCH 19/27] Correct another error that came in with a merge conflict --- python/ctsm/crop_calendars/generate_gdds_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index 3e412814df..42b56629f9 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -560,7 +560,7 @@ def import_and_process_1yr( break if not h2_files: error(logger, f"No files found matching patterns: {patterns}") - h2_ds = utils.import_ds( + h2_ds = import_ds( h2_files, my_vars=my_vars, my_vegtypes=crops_to_read, From c42cd12499aaa455404edf3041f611adbe9e288d Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Wed, 13 Nov 2024 12:39:32 -0700 Subject: [PATCH 20/27] Update .gitmodules to the mosart/rtm tags corresponding to this ctsm --- .gitmodules | 4 ++-- components/mosart | 2 +- components/rtm | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 225f2f75ac..36eea24b0f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -44,7 +44,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CISM-wrapper [submodule "rtm"] path = components/rtm url = https://github.com/ESCOMP/RTM -fxtag = rtm1_0_80 +fxtag = rtm1_0_82 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/RTM @@ -52,7 +52,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/RTM [submodule "mosart"] path = components/mosart url = https://github.com/ESCOMP/MOSART -fxtag = mosart1.1.02 +fxtag = mosart1.1.04 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/MOSART diff --git a/components/mosart b/components/mosart index e2ffe00004..9fe1ea8774 160000 --- a/components/mosart +++ b/components/mosart @@ -1 +1 @@ -Subproject commit e2ffe00004cc416cfc8bcfae2a949474075c1d1f +Subproject commit 9fe1ea87742f2bfee64b1d99c27467a06d87761e diff --git a/components/rtm b/components/rtm index b3dfcfbba5..1d10716e86 160000 --- a/components/rtm +++ b/components/rtm @@ -1 +1 @@ -Subproject commit b3dfcfbba58c151ac5a6ab513b3515ef3deff798 +Subproject commit 1d10716e86c6f1b5feb196e20313b881537ac851 From 71fbe09a16ffbbfb210913492343e0eb98308478 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 14 Nov 2024 15:52:52 -0700 Subject: [PATCH 21/27] cropcal_module.py import_output(): Handle "instantaneous files." --- python/ctsm/crop_calendars/cropcal_module.py | 33 +++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/python/ctsm/crop_calendars/cropcal_module.py b/python/ctsm/crop_calendars/cropcal_module.py index 719d352665..28c40e2133 100644 --- a/python/ctsm/crop_calendars/cropcal_module.py +++ b/python/ctsm/crop_calendars/cropcal_module.py @@ -443,10 +443,7 @@ def import_output( ) # Convert time axis to integer year, saving original as 'cftime' - this_ds_gs = this_ds_gs.assign_coords( - {"cftime": this_ds["time_bounds"].isel({"hist_interval": 0})} - ) - this_ds_gs = this_ds_gs.assign_coords({"time": [t.year for t in this_ds_gs["cftime"].values]}) + this_ds_gs = convert_time_to_int_year(filename, this_ds, this_ds_gs) # Get number of harvests this_ds_gs["NHARVESTS"] = (this_ds_gs["GDDHARV_PERHARV"] > 0).sum(dim="mxharvests") @@ -457,6 +454,34 @@ def import_output( return this_ds_gs, any_bad +def convert_time_to_int_year(filename, this_ds, this_ds_gs): + """ + Convert time axis to integer year, saving original as 'cftime' + """ + if "time_bounds" in this_ds: + # Always true before PR #2838, when even files with all instantaneous variables got + # time_bounds saved. After that PR (and before the segregation of instantaneous and other + # variables onto separate files), files with an instantaneous variable first in their list + # do not get time_bounds saved. + this_ds_gs = this_ds_gs.assign_coords( + {"cftime": this_ds["time_bounds"].isel({"hist_interval": 0})} + ) + this_ds_gs = this_ds_gs.assign_coords( + {"time": [t.year for t in this_ds_gs["cftime"].values]} + ) + elif this_ds["time"].attrs["long_name"] == "time at end of time step": + # This is an "instantaneous file." + this_ds_gs = this_ds_gs.assign_coords({"cftime": this_ds["time"]}) + this_ds_gs = this_ds_gs.assign_coords( + {"time": [t.year - 1 for t in this_ds_gs["cftime"].values]} + ) + else: + raise RuntimeError( + f"{filename} is neither an instantaneous nor a combined/non-instantaneous file." + ) + + return this_ds_gs + def handle_zombie_crops(this_ds): """ From a51816e0de380300b69db9fc3e2c7fa83b267b64 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 14 Nov 2024 21:10:19 -0700 Subject: [PATCH 22/27] Reformat with black. --- python/ctsm/crop_calendars/cropcal_module.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ctsm/crop_calendars/cropcal_module.py b/python/ctsm/crop_calendars/cropcal_module.py index 28c40e2133..3ea084e1d2 100644 --- a/python/ctsm/crop_calendars/cropcal_module.py +++ b/python/ctsm/crop_calendars/cropcal_module.py @@ -454,6 +454,7 @@ def import_output( return this_ds_gs, any_bad + def convert_time_to_int_year(filename, this_ds, this_ds_gs): """ Convert time axis to integer year, saving original as 'cftime' From 3220dbbdb9cd5bcf25e9325e5b0f2ea56978bdeb Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 14 Nov 2024 21:11:18 -0700 Subject: [PATCH 23/27] Add previous commit to .git-blame-ignore-revs. --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index fca4a8315b..32e53646d7 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -27,6 +27,7 @@ d866510188d26d51bcd6d37239283db690af7e82 e096358c832ab292ddfd22dd5878826c7c788968 475831f0fb0e31e97f630eac4e078c886558b61c fd5f177131d63d39e79a13918390bdfb642d781e +a51816e0de380300b69db9fc3e2c7fa83b267b64 # Ran SystemTests and python/ctsm through black python formatter 5364ad66eaceb55dde2d3d598fe4ce37ac83a93c 8056ae649c1b37f5e10aaaac79005d6e3a8b2380 From ea91981697a64d6d3905a5abb9e955543246821d Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 15 Nov 2024 13:47:15 -0700 Subject: [PATCH 24/27] Draft ChangeLog/ChangeSum --- doc/ChangeLog | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/ChangeSum | 1 + 2 files changed, 105 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 5a2a3c472e..660aed7921 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,108 @@ =============================================================== +Tag name: ctsm5.3.014 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri 15 Nov 2024 01:24:45 PM MST +One-line Summary: Change history time to be the middle of the time bounds + +Purpose and description of changes +---------------------------------- + + Making the change in order to be consistent with CAM and to make history output more intuitive. + + +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.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Partly addresses issue #1059 + +Notes of particular relevance for users +--------------------------------------- +Caveats for users (e.g., need to interpolate initial conditions): + The history time variable now equals the middle of the time bounds. + Instantaneous history tapes now do not include time bounds. + Mixed history tapes do not change the treatment of instantaneous fields or move them to separate tapes, yet. + + +Notes of particular relevance for developers: +--------------------------------------------- +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + +Changes to tests or testing: + This tag introduces changes to the mosart/rtm testlists. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + mosart + derecho ----- OK + izumi ------- OK + + rtm + derecho ----- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: Only time variable + + Summarize any changes to answers, i.e., + - what code configurations: all + - what platforms/compilers: all + - nature of change: only the time variable + + +Other details +------------- +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + rtm, mosart + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2838 + https://github.com/ESCOMP/MOSART/pull/70 + https://github.com/ESCOMP/RTM/issues/54 + https://github.com/ESCOMP/MOSART/pull/106 + https://github.com/ESCOMP/RTM/pull/39 + +=============================================================== +=============================================================== Tag name: ctsm5.3.012 Originator(s): afoster (Adrianna Foster,UCAR/TSS,303-497-1728) Date: Wed 13 Nov 2024 09:53:51 AM MST diff --git a/doc/ChangeSum b/doc/ChangeSum index 87d5709a68..25569e9108 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.3.014 slevis 11/18/2024 Change history time to be the middle of the time bounds ctsm5.3.012 afoster 11/13/2024 update fates tag ctsm5.3.011 samrabin 11/11/2024 Improve handling of cold-start finidat ctsm5.3.010 afoster 11/09/2024 Merge b4b-dev From c7e13661f2ac15cbb4845aebeff6b81389eccdcf Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 15 Nov 2024 16:41:57 -0700 Subject: [PATCH 25/27] Revert change I brought in with the conflicts --- src/main/accumulMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/accumulMod.F90 b/src/main/accumulMod.F90 index e968e2dae5..0c2462c1f8 100644 --- a/src/main/accumulMod.F90 +++ b/src/main/accumulMod.F90 @@ -595,7 +595,7 @@ subroutine update_accum_field_timeavg(this, level, nstep, field) do k = begi,endi effective_nstep = nstep - this%ndays_reset_shifted(k,level) - time_to_reset = mod(effective_nstep,this%period) == 1 .or. this%period == 1 + time_to_reset = (mod(effective_nstep,this%period) == 1 .or. this%period == 1) .and. effective_nstep /= 0 if (this%active(k) .and. (time_to_reset .or. this%reset(k,level))) then if (this%reset(k,level) .and. .not. time_to_reset) then this%ndays_reset_shifted(k,level) = this%ndays_reset_shifted(k,level) + this%nsteps(k,level) From 5148dbcb34652e58935de25239834ada7c71f22a Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 15 Nov 2024 16:46:25 -0700 Subject: [PATCH 26/27] Update .gitmodules to the mosart/rtm tags corresponding to this ctsm --- .gitmodules | 4 ++-- components/mosart | 2 +- components/rtm | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 36eea24b0f..97f70ca427 100644 --- a/.gitmodules +++ b/.gitmodules @@ -44,7 +44,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CISM-wrapper [submodule "rtm"] path = components/rtm url = https://github.com/ESCOMP/RTM -fxtag = rtm1_0_82 +fxtag = rtm1_0_83 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/RTM @@ -52,7 +52,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/RTM [submodule "mosart"] path = components/mosart url = https://github.com/ESCOMP/MOSART -fxtag = mosart1.1.04 +fxtag = mosart1.1.05 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/MOSART diff --git a/components/mosart b/components/mosart index 9fe1ea8774..99b425e618 160000 --- a/components/mosart +++ b/components/mosart @@ -1 +1 @@ -Subproject commit 9fe1ea87742f2bfee64b1d99c27467a06d87761e +Subproject commit 99b425e618a31d077935a0774141aa9bf48fcc13 diff --git a/components/rtm b/components/rtm index 1d10716e86..a2cd8249e4 160000 --- a/components/rtm +++ b/components/rtm @@ -1 +1 @@ -Subproject commit 1d10716e86c6f1b5feb196e20313b881537ac851 +Subproject commit a2cd8249e40e8c61d68fe13145c4cf9d5e098f68 From dc295f71220c939d190e4c9e7dc634eba3c47b17 Mon Sep 17 00:00:00 2001 From: Samuel Levis Date: Fri, 15 Nov 2024 16:50:08 -0700 Subject: [PATCH 27/27] Correct variable name that came in with the conflicts --- python/ctsm/crop_calendars/generate_gdds_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index 42b56629f9..988edf6d89 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -551,7 +551,7 @@ def import_and_process_1yr( log(logger, " Importing accumulated GDDs...") clm_gdd_var = "GDDACCUM" - myVars = [clm_gdd_var, "GDDHARV"] + my_vars = [clm_gdd_var, "GDDHARV"] patterns = [f"*h2.{this_year-1}-01*.nc", f"*h2.{this_year-1}-01*.nc.base"] for p in patterns: pattern = os.path.join(indir, p)