diff --git a/driver_cpl/bld/build-namelist b/driver_cpl/bld/build-namelist index f1157ec508f0..8359a4aed32a 100755 --- a/driver_cpl/bld/build-namelist +++ b/driver_cpl/bld/build-namelist @@ -398,6 +398,7 @@ add_default($nl, 'bfbflag', 'BFBFLAG'=>"$xmlvars{'BFBFLAG'}"); add_default($nl, 'do_budgets','BUDGETS'=>"$xmlvars{'BUDGETS'}"); add_default($nl, 'flux_diurnal'); +add_default($nl, 'gust_fac'); add_default($nl, 'flux_albav'); add_default($nl, 'flux_epbal'); add_default($nl, 'info_debug'); diff --git a/driver_cpl/bld/namelist_files/namelist_defaults_drv.xml b/driver_cpl/bld/namelist_files/namelist_defaults_drv.xml index 43cfff2f8fee..f40569182159 100644 --- a/driver_cpl/bld/namelist_files/namelist_defaults_drv.xml +++ b/driver_cpl/bld/namelist_files/namelist_defaults_drv.xml @@ -104,6 +104,7 @@ -1.0 month .false. +0.0D0 .true. .false. diff --git a/driver_cpl/bld/namelist_files/namelist_definition_drv.xml b/driver_cpl/bld/namelist_files/namelist_definition_drv.xml index d485b37f69a6..6a8b7888d6ec 100644 --- a/driver_cpl/bld/namelist_files/namelist_definition_drv.xml +++ b/driver_cpl/bld/namelist_files/namelist_definition_drv.xml @@ -451,6 +451,16 @@ If true, turn on diurnal cycle in computing atm/ocn fluxes default: false + +wind gustiness factor +default: 0.0D0 + + + ocn is prognostic logical :: flux_diurnal ! .true. => turn on diurnal cycle in atm/ocn fluxes @@ -868,8 +875,9 @@ subroutine seq_flux_atmocnexch_mct( infodata, atm, ocn, fractions_a, fractions_o dead_comps=dead_comps, & atm_nx=atm_nx, atm_ny=atm_ny, & ocn_nx=ocn_nx, ocn_ny=ocn_ny, & - ocn_prognostic=ocn_prognostic, & - flux_diurnal=flux_diurnal) + ocn_prognostic=ocn_prognostic, & + flux_diurnal=flux_diurnal, & + gust_fac = gust_fac ) if (dead_comps) then do n = 1,nloc_a2o @@ -934,7 +942,7 @@ subroutine seq_flux_atmocnexch_mct( infodata, atm, ocn, fractions_a, fractions_o cskin, cskin_night, tod, dt, & duu10n,ustar, re , ssq , missval = 0.0_r8 ) else - call shr_flux_atmocn (nloc_a2o , zbot , ubot, vbot, thbot, & + call shr_flux_atmocn (nloc_a2o , zbot , ubot, vbot, thbot, prec_gust, gust_fac, & shum , dens , tbot, uocn, vocn , & tocn , emask, sen , lat , lwup , & evap , taux , tauy, tref, qref , & @@ -1103,6 +1111,7 @@ subroutine seq_flux_atmocn_mct(infodata, tod, dt, a2x, o2x, xao) real(r8) :: avsdr ! albedo: visible , direct real(r8) :: anidf ! albedo: near infrared, diffuse real(r8) :: avsdf ! albedo: visible , diffuse + real(r8) :: gust_fac = huge(1.0_r8) !wind gust factor integer(in) :: nloc, nloca, nloco ! number of gridcells integer(in) :: ID ! comm ID logical :: first_call = .true. @@ -1119,7 +1128,8 @@ subroutine seq_flux_atmocn_mct(infodata, tod, dt, a2x, o2x, xao) flux_albav=flux_albav, & dead_comps=dead_comps, & ocn_prognostic=ocn_prognostic, & - flux_diurnal=flux_diurnal) + flux_diurnal=flux_diurnal, & + gust_fac = gust_fac ) if (first_call) then index_xao_So_tref = mct_aVect_indexRA(xao,'So_tref') @@ -1211,6 +1221,7 @@ subroutine seq_flux_atmocn_mct(infodata, tod, dt, a2x, o2x, xao) uGust(n)= 0.0_r8 lwdn(n) = 0.0_r8 prec(n) = 0.0_r8 + prec_gust(n) = 0.0_r8 fswpen(n)= 0.0_r8 ocnsal(n)= 0.0_r8 @@ -1262,6 +1273,7 @@ subroutine seq_flux_atmocn_mct(infodata, tod, dt, a2x, o2x, xao) & + a2x%rAttr(index_a2x_Faxa_rainl,n) & & + a2x%rAttr(index_a2x_Faxa_snowc,n) & & + a2x%rAttr(index_a2x_Faxa_snowl,n) + prec_gust (n) = a2x%rAttr(index_a2x_Faxa_rainc,n) fswpen(n)= o2x%rAttr(index_o2x_So_fswpen ,n) ocnsal(n)= o2x%rAttr(index_o2x_So_s ,n) @@ -1308,7 +1320,7 @@ subroutine seq_flux_atmocn_mct(infodata, tod, dt, a2x, o2x, xao) !consistent with mrgx2a fraction !duu10n,ustar, re , ssq, missval = 0.0_r8 ) else - call shr_flux_atmocn (nloc , zbot , ubot, vbot, thbot, & + call shr_flux_atmocn (nloc , zbot , ubot, vbot, thbot, prec_gust, gust_fac, & shum , dens , tbot, uocn, vocn , & tocn , emask, sen , lat , lwup , & evap , taux , tauy, tref, qref , & diff --git a/driver_cpl/shr/seq_infodata_mod.F90 b/driver_cpl/shr/seq_infodata_mod.F90 index 492330d89073..88c58f299615 100644 --- a/driver_cpl/shr/seq_infodata_mod.F90 +++ b/driver_cpl/shr/seq_infodata_mod.F90 @@ -106,6 +106,7 @@ MODULE seq_infodata_mod character(SHR_KIND_CL) :: flux_epbal ! selects E,P,R adjustment technique logical :: flux_albav ! T => no diurnal cycle in ocn albedos logical :: flux_diurnal ! T => diurnal cycle in atm/ocn fluxes + real(SHR_KIND_R8) :: gust_fac ! wind gustiness factor real(SHR_KIND_R8) :: wall_time_limit ! force stop time limit (hours) character(SHR_KIND_CS) :: force_stop_at ! when to force a stop (month, day, etc) character(SHR_KIND_CL) :: atm_gnam ! atm grid @@ -312,6 +313,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid) character(SHR_KIND_CL) :: flux_epbal ! selects E,P,R adjustment technique logical :: flux_albav ! T => no diurnal cycle in ocn albedos logical :: flux_diurnal ! T => diurnal cycle in atm/ocn fluxes + real(SHR_KIND_R8) :: gust_fac ! wind gustiness factor real(SHR_KIND_R8) :: wall_time_limit ! force stop time limit (hours) character(SHR_KIND_CS) :: force_stop_at ! when to force a stop (month, day, etc) character(SHR_KIND_CL) :: atm_gnam ! atm grid @@ -373,7 +375,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid) brnch_retain_casename, info_debug, bfbflag, & restart_pfile, restart_file, run_barriers, & single_column, scmlat, force_stop_at, & - scmlon, logFilePostFix, outPathRoot, flux_diurnal,& + scmlon, logFilePostFix, outPathRoot, flux_diurnal, gust_fac, & perpetual, perpetual_ymd, flux_epbal, flux_albav, & orb_iyear_align, orb_mode, wall_time_limit, & orb_iyear, orb_obliq, orb_eccen, orb_mvelp, & @@ -447,6 +449,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid) flux_epbal = 'off' flux_albav = .false. flux_diurnal = .false. + gust_fac = huge(1.0_SHR_KIND_R8) wall_time_limit = -1.0 force_stop_at = 'month' atm_gnam = 'undefined' @@ -549,6 +552,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid) infodata%flux_epbal = flux_epbal infodata%flux_albav = flux_albav infodata%flux_diurnal = flux_diurnal + infodata%gust_fac = gust_fac infodata%wall_time_limit = wall_time_limit infodata%force_stop_at = force_stop_at infodata%atm_gnam = atm_gnam @@ -832,7 +836,7 @@ SUBROUTINE seq_infodata_GetData( infodata, case_name, case_desc, timing_dir, & shr_map_dopole, vect_map, aoflux_grid, flux_epbalfact, & nextsw_cday, precip_fact, flux_epbal, flux_albav, glcrun_alarm, & glc_g2lupdate, atm_aero, run_barriers, esmf_map_flag, & - do_budgets, do_histinit, drv_threading, flux_diurnal, & + do_budgets, do_histinit, drv_threading, flux_diurnal, gust_fac, & budget_inst, budget_daily, budget_month, wall_time_limit, & budget_ann, budget_ltann, budget_ltend , force_stop_at, & histaux_a2x , histaux_a2x3hr, histaux_a2x3hrp , histaux_l2x1yr, & @@ -897,6 +901,7 @@ SUBROUTINE seq_infodata_GetData( infodata, case_name, case_desc, timing_dir, & character(len=*) ,optional, intent(OUT) :: flux_epbal ! selects E,P,R adjustment technique logical ,optional, intent(OUT) :: flux_albav ! T => no diurnal cycle in ocn albedos logical ,optional, intent(OUT) :: flux_diurnal ! T => diurnal cycle in atm/ocn flux + real(SHR_KIND_R8) ,optional, intent(OUT) :: gust_fac ! wind gustiness factor real(SHR_KIND_R8) ,optional, intent(OUT) :: wall_time_limit ! force stop wall time (hours) character(len=*) ,optional, intent(OUT) :: force_stop_at ! force stop at next (month, day, etc) character(len=*) ,optional, intent(OUT) :: atm_gnam ! atm grid @@ -1054,6 +1059,7 @@ SUBROUTINE seq_infodata_GetData( infodata, case_name, case_desc, timing_dir, & if ( present(flux_epbal) ) flux_epbal = infodata%flux_epbal if ( present(flux_albav) ) flux_albav = infodata%flux_albav if ( present(flux_diurnal) ) flux_diurnal = infodata%flux_diurnal + if ( present(gust_fac) ) gust_fac = infodata%gust_fac if ( present(wall_time_limit)) wall_time_limit= infodata%wall_time_limit if ( present(force_stop_at) ) force_stop_at = infodata%force_stop_at if ( present(atm_gnam) ) atm_gnam = infodata%atm_gnam @@ -1201,7 +1207,7 @@ SUBROUTINE seq_infodata_PutData( infodata, case_name, case_desc, timing_dir, & shr_map_dopole, vect_map, aoflux_grid, run_barriers, & nextsw_cday, precip_fact, flux_epbal, flux_albav, glcrun_alarm, & glc_g2lupdate, atm_aero, esmf_map_flag, wall_time_limit, & - do_budgets, do_histinit, drv_threading, flux_diurnal, & + do_budgets, do_histinit, drv_threading, flux_diurnal, gust_fac, & budget_inst, budget_daily, budget_month, force_stop_at, & budget_ann, budget_ltann, budget_ltend , & histaux_a2x , histaux_a2x3hr, histaux_a2x3hrp , histaux_l2x1yr, & @@ -1266,6 +1272,7 @@ SUBROUTINE seq_infodata_PutData( infodata, case_name, case_desc, timing_dir, & character(len=*) ,optional, intent(IN) :: flux_epbal ! selects E,P,R adjustment technique logical ,optional, intent(IN) :: flux_albav ! T => no diurnal cycle in ocn albedos logical ,optional, intent(IN) :: flux_diurnal ! T => diurnal cycle in atm/ocn flux + real(SHR_KIND_R8) ,optional, intent(IN) :: gust_fac ! wind gustiness factor real(SHR_KIND_R8) ,optional, intent(IN) :: wall_time_limit ! force stop wall time (hours) character(len=*) ,optional, intent(IN) :: force_stop_at ! force a stop at next (month, day, etc) character(len=*) ,optional, intent(IN) :: atm_gnam ! atm grid @@ -1421,6 +1428,7 @@ SUBROUTINE seq_infodata_PutData( infodata, case_name, case_desc, timing_dir, & if ( present(flux_epbal) ) infodata%flux_epbal = flux_epbal if ( present(flux_albav) ) infodata%flux_albav = flux_albav if ( present(flux_diurnal) ) infodata%flux_diurnal = flux_diurnal + if ( present(gust_fac) ) infodata%gust_fac = gust_fac if ( present(wall_time_limit)) infodata%wall_time_limit= wall_time_limit if ( present(force_stop_at) ) infodata%force_stop_at = force_stop_at if ( present(atm_gnam) ) infodata%atm_gnam = atm_gnam @@ -1599,6 +1607,7 @@ subroutine seq_infodata_bcast(infodata,mpicom) call shr_mpi_bcast(infodata%flux_epbal, mpicom) call shr_mpi_bcast(infodata%flux_albav, mpicom) call shr_mpi_bcast(infodata%flux_diurnal, mpicom) + call shr_mpi_bcast(infodata%gust_fac, mpicom) call shr_mpi_bcast(infodata%wall_time_limit, mpicom) call shr_mpi_bcast(infodata%force_stop_at, mpicom) call shr_mpi_bcast(infodata%atm_gnam, mpicom) @@ -2231,6 +2240,7 @@ SUBROUTINE seq_infodata_print( infodata ) write(logunit,F0A) subname,'flux_epbal = ', trim(infodata%flux_epbal) write(logunit,F0L) subname,'flux_albav = ', infodata%flux_albav write(logunit,F0L) subname,'flux_diurnal = ', infodata%flux_diurnal + write(logunit,F0R) subname,'gust_fac = ', infodata%gust_fac write(logunit,F0R) subname,'wall_time_limit = ', infodata%wall_time_limit write(logunit,F0A) subname,'force_stop_at = ', trim(infodata%force_stop_at) write(logunit,F0A) subname,'atm_gridname = ', trim(infodata%atm_gnam) diff --git a/share/csm_share/shr/shr_flux_mod.F90 b/share/csm_share/shr/shr_flux_mod.F90 index 3279e13c9ab9..c1808f86543a 100644 --- a/share/csm_share/shr/shr_flux_mod.F90 +++ b/share/csm_share/shr/shr_flux_mod.F90 @@ -117,7 +117,7 @@ end subroutine shr_flux_adjust_constants ! ! !INTERFACE: ------------------------------------------------------------------ -SUBROUTINE shr_flux_atmOcn(nMax ,zbot ,ubot ,vbot ,thbot , & +SUBROUTINE shr_flux_atmOcn(nMax ,zbot ,ubot ,vbot ,thbot ,prec_gust, gust_fac, & & qbot ,rbot ,tbot ,us ,vs , & & ts ,mask ,sen ,lat ,lwup , & & evap ,taux ,tauy ,tref ,qref , & @@ -143,6 +143,8 @@ SUBROUTINE shr_flux_atmOcn(nMax ,zbot ,ubot ,vbot ,thbot , & real(R8) ,intent(in) :: us (nMax) ! ocn u-velocity (m/s) real(R8) ,intent(in) :: vs (nMax) ! ocn v-velocity (m/s) real(R8) ,intent(in) :: ts (nMax) ! ocn temperature (K) + real(R8) ,intent(in) :: prec_gust (nMax) ! atm precip for convective gustiness (kg/m^3) + real(R8) ,intent(in) :: gust_fac ! wind gustiness factor !--- output arguments ------------------------------- real(R8),intent(out) :: sen (nMax) ! heat flux: sensible (W/m^2) @@ -206,14 +208,23 @@ SUBROUTINE shr_flux_atmOcn(nMax ,zbot ,ubot ,vbot ,thbot , & real(R8) :: cdn ! function: neutral drag coeff at 10m real(R8) :: psimhu ! function: unstable part of psimh real(R8) :: psixhu ! function: unstable part of psimx + real(R8) :: ugust ! function: gustiness as a function of convective rainfall real(R8) :: Umps ! dummy arg ~ wind velocity (m/s) real(R8) :: Tk ! dummy arg ~ temperature (K) real(R8) :: xd ! dummy arg ~ ? + real(R8) :: gprec ! dummy arg ~ ? qsat(Tk) = 640380.0_R8 / exp(5107.4_R8/Tk) cdn(Umps) = 0.0027_R8 / Umps + 0.000142_R8 + 0.0000764_R8 * Umps psimhu(xd) = log((1.0_R8+xd*(2.0_R8+xd))*(1.0_R8+xd*xd)/8.0_R8) - 2.0_R8*atan(xd) + 1.571_R8 psixhu(xd) = 2.0_R8 * log((1.0_R8 + xd*xd)/2.0_R8) + + ! Convective gustiness appropriate for input precipitation. + ! Following Redelsperger et al. (2000, J. Clim) + ! Ug = log(1.0+6.69R-0.476R^2) + ! Coefficients X by 8640 for mm/s (from cam) -> cm/day (for above forumla) + ugust(gprec) = gust_fac*log(1._R8+57801.6_R8*gprec-3.55332096e7_R8*(gprec**2.0_R8)) + !--- formats ---------------------------------------- character(*),parameter :: subName = '(shr_flux_atmOcn) ' @@ -251,7 +262,9 @@ SUBROUTINE shr_flux_atmOcn(nMax ,zbot ,ubot ,vbot ,thbot , & if (mask(n) /= 0) then !--- compute some needed quantities --- - vmag = max(umin, sqrt( (ubot(n)-us(n))**2 + (vbot(n)-vs(n))**2) ) + !--- vmag+ugust (convective gustiness) Limit to a max precip 6 cm/day = 0.00069444 mm/s. + vmag = max(umin, sqrt( (ubot(n)-us(n))**2 + (vbot(n)-vs(n))**2) + ugust(min(prec_gust(n),6.94444e-4_R8))) + thvbot = thbot(n) * (1.0_R8 + loc_zvir * qbot(n)) ! virtual temp (K) ssq = 0.98_R8 * qsat(ts(n)) / rbot(n) ! sea surf hum (kg/kg) delt = thbot(n) - ts(n) ! pot temp diff (K)