From d58c0eadada9ce4edd2c54dd47c9a5d2c97044ad Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Wed, 18 Sep 2019 15:55:51 -0600 Subject: [PATCH 1/2] update SCM version of GFS_time_vary_pre.F90 (matches FV3 version except for a comment) --- physics/GFS_time_vary_pre.scm.F90 | 126 ++++++++++++----- physics/GFS_time_vary_pre.scm.meta | 211 ++++++++++++++++++++++++++++- 2 files changed, 297 insertions(+), 40 deletions(-) diff --git a/physics/GFS_time_vary_pre.scm.F90 b/physics/GFS_time_vary_pre.scm.F90 index 790cf0d1a..2fa352710 100644 --- a/physics/GFS_time_vary_pre.scm.F90 +++ b/physics/GFS_time_vary_pre.scm.F90 @@ -30,7 +30,7 @@ subroutine GFS_time_vary_pre_init (errmsg, errflg) errflg = 0 if (is_initialized) return - + !--- Call gfuncphys (funcphys.f) to compute all physics function tables. call gfuncphys () @@ -65,20 +65,38 @@ end subroutine GFS_time_vary_pre_finalize !> \section arg_table_GFS_time_vary_pre_run Argument Table !! \htmlinclude GFS_time_vary_pre_run.html !! - subroutine GFS_time_vary_pre_run (Model, errmsg, errflg) + subroutine GFS_time_vary_pre_run (jdat, idat, dtp, lsm, lsm_noahmp, nsswr, & + nslwr, idate, debug, me, master, nscyc, sec, phour, zhour, fhour, kdt, & + julian, yearlen, ipt, lprnt, lssav, lsswr, lslwr, solhr, errmsg, errflg) use machine, only: kind_phys - use GFS_typedefs, only: GFS_control_type implicit none - - type(GFS_control_type), intent(inout) :: Model + + integer, intent(in) :: idate(4) + integer, intent(in) :: jdat(1:8), idat(1:8) + integer, intent(in) :: lsm, lsm_noahmp, & + nsswr, nslwr, me, & + master, nscyc + logical, intent(in) :: debug + real(kind=kind_phys), intent(in) :: dtp + + integer, intent(out) :: kdt, yearlen, ipt + logical, intent(out) :: lprnt, lssav, lsswr, & + lslwr + real(kind=kind_phys), intent(out) :: sec, phour, zhour, & + fhour, julian, solhr + character(len=*), intent(out) :: errmsg integer, intent(out) :: errflg real(kind=kind_phys), parameter :: con_24 = 24.0_kind_phys real(kind=kind_phys), parameter :: con_hr = 3600.0_kind_phys real(kind=kind_phys) :: rinc(5) + + integer :: iw3jdn + integer :: jd0, jd1 + real :: fjd ! Initialize CCPP error handling variables errmsg = '' @@ -86,47 +104,87 @@ subroutine GFS_time_vary_pre_run (Model, errmsg, errflg) ! Check initialization status if (.not.is_initialized) then - write(errmsg,'(*(a))') "Logic error: GFS_time_vary_pre_run called before GFS_time_vary_pre_init" + write(errmsg,'(*(a))') "Logic error: GFS_time_vary_pre_run called & + &before GFS_time_vary_pre_init" errflg = 1 return end if - !--- Model%jdat is being updated directly inside of FV3GFS_cap.F90 + !--- jdat is being updated directly inside of the time integration + !--- loop of gmtb_scm.F90 !--- update calendars and triggers rinc(1:5) = 0 - call w3difdat(Model%jdat,Model%idat,4,rinc) - Model%sec = rinc(4) - Model%phour = Model%sec/con_hr + call w3difdat(jdat,idat,4,rinc) + sec = rinc(4) + phour = sec/con_hr !--- set current bucket hour - Model%zhour = Model%phour - Model%fhour = (Model%sec + Model%dtp)/con_hr - Model%kdt = nint((Model%sec + Model%dtp)/Model%dtp) - - Model%ipt = 1 - Model%lprnt = .false. - Model%lssav = .true. + zhour = phour + fhour = (sec + dtp)/con_hr + kdt = nint((sec + dtp)/dtp) + + if(lsm == lsm_noahmp) then + !GJF* These calculations were originally in GFS_physics_driver.F90 for + ! NoahMP. They were moved to this routine since they only depends + ! on time (not space). Note that this code is included as-is from + ! GFS_physics_driver.F90, but it may be simplified by using more + ! NCEP W3 library calls (e.g., see W3DOXDAT, W3FS13 for Julian day + ! of year and W3DIFDAT to determine the integer number of days in + ! a given year). *GJF + ! Julian day calculation (fcst day of the year) + ! we need yearln and julian to + ! pass to noah mp sflx, idate is init, jdat is fcst;idate = jdat when kdt=1 + ! jdat is changing + ! + + jd1 = iw3jdn(jdat(1),jdat(2),jdat(3)) + jd0 = iw3jdn(jdat(1),1,1) + fjd = float(jdat(5))/24.0 + float(jdat(6))/1440.0 + + julian = float(jd1-jd0) + fjd + + ! + ! Year length + ! + ! what if the integration goes from one year to another? + ! iyr or jyr ? from 365 to 366 or from 366 to 365 + ! + ! is this against model's noleap yr assumption? + if (mod(jdat(1),4) == 0) then + yearlen = 366 + if (mod(jdat(1),100) == 0) then + yearlen = 365 + if (mod(jdat(1),400) == 0) then + yearlen = 366 + endif + endif + endif + endif + + ipt = 1 + lprnt = .false. + lssav = .true. !--- radiation triggers - Model%lsswr = (mod(Model%kdt, Model%nsswr) == 1) - Model%lslwr = (mod(Model%kdt, Model%nslwr) == 1) + lsswr = (mod(kdt, nsswr) == 1) + lslwr = (mod(kdt, nslwr) == 1) !--- allow for radiation to be called on every physics time step, if needed - if (Model%nsswr == 1) Model%lsswr = .true. - if (Model%nslwr == 1) Model%lslwr = .true. + if (nsswr == 1) lsswr = .true. + if (nslwr == 1) lslwr = .true. !--- set the solar hour based on a combination of phour and time initial hour - Model%solhr = mod(Model%phour+Model%idate(1),con_24) - - if ((Model%debug) .and. (Model%me == Model%master)) then - print *,' sec ', Model%sec - print *,' kdt ', Model%kdt - print *,' nsswr ', Model%nsswr - print *,' nslwr ', Model%nslwr - print *,' nscyc ', Model%nscyc - print *,' lsswr ', Model%lsswr - print *,' lslwr ', Model%lslwr - print *,' fhour ', Model%fhour - print *,' phour ', Model%phour - print *,' solhr ', Model%solhr + solhr = mod(phour+idate(1),con_24) + + if ((debug) .and. (me == master)) then + print *,' sec ', sec + print *,' kdt ', kdt + print *,' nsswr ', nsswr + print *,' nslwr ', nslwr + print *,' nscyc ', nscyc + print *,' lsswr ', lsswr + print *,' lslwr ', lslwr + print *,' fhour ', fhour + print *,' phour ', phour + print *,' solhr ', solhr endif end subroutine GFS_time_vary_pre_run diff --git a/physics/GFS_time_vary_pre.scm.meta b/physics/GFS_time_vary_pre.scm.meta index c4312790f..3dc91952e 100644 --- a/physics/GFS_time_vary_pre.scm.meta +++ b/physics/GFS_time_vary_pre.scm.meta @@ -45,13 +45,212 @@ [ccpp-arg-table] name = GFS_time_vary_pre_run type = scheme -[Model] - standard_name = GFS_control_type_instance - long_name = Fortran DDT containing FV3-GFS model control parameters - units = DDT +[jdat] + standard_name = forecast_date_and_time + long_name = current forecast date and time + units = none + dimensions = (8) + type = integer + intent = in + optional = F +[idat] + standard_name = date_and_time_at_model_initialization + long_name = initialization date and time + units = none + dimensions = (8) + type = integer + intent = in + optional = F +[dtp] + standard_name = time_step_for_physics + long_name = physics timestep + units = s dimensions = () - type = GFS_control_type - intent = inout + type = real + kind = kind_phys + intent = in + optional = F +[lsm] + standard_name = flag_for_land_surface_scheme + long_name = flag for land surface model + units = flag + dimensions = () + type = integer + intent = in + optional = F +[lsm_noahmp] + standard_name = flag_for_noahmp_land_surface_scheme + long_name = flag for NOAH MP land surface model + units = flag + dimensions = () + type = integer + intent = in + optional = F +[nsswr] + standard_name = number_of_timesteps_between_shortwave_radiation_calls + long_name = number of timesteps between shortwave radiation calls + units = + dimensions = () + type = integer + intent = in + optional = F +[nslwr] + standard_name = number_of_timesteps_between_longwave_radiation_calls + long_name = number of timesteps between longwave radiation calls + units = + dimensions = () + type = integer + intent = in + optional = F +[idate] + standard_name = date_and_time_at_model_initialization_reordered + long_name = initial date with different size and ordering + units = none + dimensions = (4) + type = integer + intent = in + optional = F +[debug] + standard_name = flag_debug + long_name = control flag for debug + units = flag + dimensions = () + type = logical + intent = in + optional = F +[me] + standard_name = mpi_rank + long_name = current MPI-rank + units = index + dimensions = () + type = integer + intent = in + optional = F +[master] + standard_name = mpi_root + long_name = master MPI-rank + units = index + dimensions = () + type = integer + intent = in + optional = F +[nscyc] + standard_name = number_of_timesteps_between_surface_cycling_calls + long_name = number of timesteps between surface cycling calls + units = + dimensions = () + type = integer + intent = in + optional = F +[sec] + standard_name = seconds_elapsed_since_model_initialization + long_name = seconds elapsed since model initialization + units = s + dimensions = () + type = real + kind = kind_phys + intent = out + optional = F +[phour] + standard_name = forecast_time_at_previous_timestep + long_name = forecast time at the previous timestep + units = h + dimensions = () + type = real + kind = kind_phys + intent = out + optional = F +[zhour] + standard_name = time_since_diagnostics_zeroed + long_name = time since diagnostics variables have been zeroed + units = h + dimensions = () + type = real + kind = kind_phys + intent = out + optional = F +[fhour] + standard_name = forecast_time + long_name = current forecast time + units = h + dimensions = () + type = real + kind = kind_phys + intent = out + optional = F +[kdt] + standard_name = index_of_time_step + long_name = current forecast iteration + units = index + dimensions = () + type = integer + intent = out + optional = F +[julian] + standard_name = julian_day + long_name = julian day + units = days + dimensions = () + type = real + kind = kind_phys + intent = out + optional = F +[yearlen] + standard_name = number_of_days_in_year + long_name = number of days in a year + units = days + dimensions = () + type = integer + intent = out + optional = F +[ipt] + standard_name = index_for_diagnostic_printout + long_name = horizontal index for point used for diagnostic printout + units = + dimensions = () + type = integer + intent = out + optional = F +[lprnt] + standard_name = flag_print + long_name = control flag for diagnostic print out + units = flag + dimensions = () + type = logical + intent = out + optional = F +[lssav] + standard_name = flag_diagnostics + long_name = logical flag for storing diagnostics + units = flag + dimensions = () + type = logical + intent = out + optional = F +[lsswr] + standard_name = flag_to_calc_sw + long_name = logical flags for sw radiation calls + units = flag + dimensions = () + type = logical + intent = out + optional = F +[lslwr] + standard_name = flag_to_calc_lw + long_name = logical flags for lw radiation calls + units = flag + dimensions = () + type = logical + intent = out + optional = F +[solhr] + standard_name = forecast_hour_of_the_day + long_name = time in hours after 00z at the current timestep + units = h + dimensions = () + type = real + kind = kind_phys + intent = out optional = F [errmsg] standard_name = ccpp_error_message From 3db21442fbdd7ae61779e6768bae8466008bff28 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Fri, 20 Sep 2019 09:48:54 -0600 Subject: [PATCH 2/2] add calculation of snow cover in GFS_phys_time_vary.scm.F90 to match FV3 version; this is ifdefed out and may not be necessary for the SCM --- physics/GFS_phys_time_vary.scm.F90 | 35 ++++++++++++++++++++++++++--- physics/GFS_phys_time_vary.scm.meta | 8 +++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/physics/GFS_phys_time_vary.scm.F90 b/physics/GFS_phys_time_vary.scm.F90 index 6905b9277..d8ca39ba3 100644 --- a/physics/GFS_phys_time_vary.scm.F90 +++ b/physics/GFS_phys_time_vary.scm.F90 @@ -15,6 +15,11 @@ module GFS_phys_time_vary use iccn_def, only : ciplin, ccnin, ci_pres use iccninterp, only : read_cidata, setindxci, ciinterpol +#if 0 + !--- variables needed for calculating 'sncovr' + use namelist_soilveg, only: salp_data, snupx +#endif + implicit none private @@ -220,7 +225,7 @@ end subroutine GFS_phys_time_vary_finalize !> \section arg_table_GFS_phys_time_vary_run Argument Table !! \htmlinclude GFS_phys_time_vary_run.html !! - subroutine GFS_phys_time_vary_run (Grid, Statein, Model, Tbd, Sfcprop, Cldprop, Diag, errmsg, errflg) + subroutine GFS_phys_time_vary_run (Grid, Statein, Model, Tbd, Sfcprop, Cldprop, Diag, first_time_step, errmsg, errflg) use mersenne_twister, only: random_setseed, random_number use machine, only: kind_phys @@ -238,6 +243,7 @@ subroutine GFS_phys_time_vary_run (Grid, Statein, Model, Tbd, Sfcprop, Cldprop, type(GFS_sfcprop_type), intent(inout) :: Sfcprop type(GFS_cldprop_type), intent(inout) :: Cldprop type(GFS_diag_type), intent(inout) :: Diag + logical, intent(in) :: first_time_step character(len=*), intent(out) :: errmsg integer, intent(out) :: errflg @@ -245,8 +251,8 @@ subroutine GFS_phys_time_vary_run (Grid, Statein, Model, Tbd, Sfcprop, Cldprop, real(kind=kind_phys), parameter :: con_99 = 99.0_kind_phys real(kind=kind_phys), parameter :: con_100 = 100.0_kind_phys - integer :: i, j, k, iseed, iskip, ix, nb, kdt_rad - real(kind=kind_phys) :: sec_zero + integer :: i, j, k, iseed, iskip, ix, nb, kdt_rad, vegtyp + real(kind=kind_phys) :: sec_zero, rsnow real(kind=kind_phys) :: wrk(1) real(kind=kind_phys) :: rannie(Model%cny) real(kind=kind_phys) :: rndval(Model%cnx*Model%cny*Model%nrcm) @@ -362,6 +368,29 @@ subroutine GFS_phys_time_vary_run (Grid, Statein, Model, Tbd, Sfcprop, Cldprop, !!!! THIS IS THE POINT AT WHICH DIAG%ZHOUR NEEDS TO BE UPDATED endif endif + +#if 0 + !Calculate sncovr if it was read in but empty (from FV3/io/FV3GFS_io.F90/sfc_prop_restart_read) + if (first_time_step) then + if (nint(Sfcprop%sncovr(1)) == -9999) then + !--- compute sncovr from existing variables + !--- code taken directly from read_fix.f + do ix = 1, Model%blksz(nb) + Sfcprop%sncovr(ix) = 0.0 + if (Sfcprop%slmsk(ix) > 0.001) then + vegtyp = Sfcprop%vtype(ix) + if (vegtyp == 0) vegtyp = 7 + rsnow = 0.001*Sfcprop%weasd(ix)/snupx(vegtyp) + if (0.001*Sfcprop%weasd(ix) < snupx(vegtyp)) then + Sfcprop%sncovr(ix) = 1.0 - (exp(-salp_data*rsnow) - rsnow*exp(-salp_data)) + else + Sfcprop%sncovr(ix) = 1.0 + endif + endif + enddo + endif + endif +#endif end subroutine GFS_phys_time_vary_run diff --git a/physics/GFS_phys_time_vary.scm.meta b/physics/GFS_phys_time_vary.scm.meta index 4fc643d29..57a82ecb0 100644 --- a/physics/GFS_phys_time_vary.scm.meta +++ b/physics/GFS_phys_time_vary.scm.meta @@ -133,6 +133,14 @@ type = GFS_diag_type intent = inout optional = F +[first_time_step] + standard_name = flag_for_first_time_step + long_name = flag for first time step for time integration loop (cold/warmstart) + units = flag + dimensions = () + type = logical + intent = in + optional = F [errmsg] standard_name = ccpp_error_message long_name = error message for error handling in CCPP