From a432fc3f8e4da3b8df3a7a7036c23e23067b2f23 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Thu, 18 Mar 2021 14:53:39 -0500 Subject: [PATCH 01/13] Incorporated Tim Supinie's updates to handle a hail category (nwat=7) --- model/fv_arrays.F90 | 2 +- model/fv_dynamics.F90 | 63 +++++- model/fv_mapz.F90 | 68 +++++-- model/fv_nesting.F90 | 37 ++-- model/fv_regional_bc.F90 | 51 ++++- model/fv_sg.F90 | 410 +++++++++++++++++++++++++++++++++++++-- model/fv_update_phys.F90 | 10 +- tools/external_ic.F90 | 1 + tools/fv_diagnostics.F90 | 48 ++++- 9 files changed, 626 insertions(+), 64 deletions(-) diff --git a/model/fv_arrays.F90 b/model/fv_arrays.F90 index 8590cade1..bf212fc29 100644 --- a/model/fv_arrays.F90 +++ b/model/fv_arrays.F90 @@ -56,7 +56,7 @@ module fv_arrays_mod integer :: id_ws, id_te, id_amdt, id_mdt, id_divg, id_aam logical :: initialized = .false. real sphum, liq_wat, ice_wat ! GFDL physics - real rainwat, snowwat, graupel + real rainwat, snowwat, graupel, hailwat real :: efx(max_step), efx_sum, efx_nest(max_step), efx_sum_nest, mtq(max_step), mtq_sum integer :: steps diff --git a/model/fv_dynamics.F90 b/model/fv_dynamics.F90 index b4802524d..56fce75b7 100644 --- a/model/fv_dynamics.F90 +++ b/model/fv_dynamics.F90 @@ -95,6 +95,10 @@ module fv_dynamics_mod ! neg_adj2 ! ! +! fv_sg_mod +! neg_adj4 +! +! ! fv_timing_mod ! timing_on, timing_off ! @@ -115,6 +119,10 @@ module fv_dynamics_mod ! neg_adj3 ! ! +! fv_sg_mod +! neg_adj4 +! +! ! tracer_manager_mod ! get_tracer_index ! @@ -136,7 +144,7 @@ module fv_dynamics_mod use mpp_mod, only: mpp_pe use field_manager_mod, only: MODEL_ATMOS use tracer_manager_mod, only: get_tracer_index - use fv_sg_mod, only: neg_adj3, neg_adj2 + use fv_sg_mod, only: neg_adj3, neg_adj2, neg_adj4 use fv_nesting_mod, only: setup_nested_grid_BCs use fv_regional_mod, only: regional_boundary_update, set_regional_BCs use fv_regional_mod, only: dump_field, H_STAGGER, U_STAGGER, V_STAGGER @@ -271,7 +279,7 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, integer:: kord_tracer(ncnst) integer :: i,j,k, n, iq, n_map, nq, nr, nwat, k_split integer :: sphum, liq_wat = -999, ice_wat = -999 ! GFDL physics - integer :: rainwat = -999, snowwat = -999, graupel = -999, cld_amt = -999 + integer :: rainwat = -999, snowwat = -999, graupel = -999, hailwat = -999, cld_amt = -999 integer :: theta_d = -999 logical used, do_omega integer, parameter :: max_packs=13 @@ -379,6 +387,7 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') cld_amt = get_tracer_index (MODEL_ATMOS, 'cld_amt') endif @@ -404,12 +413,12 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, #else !$OMP parallel do default(none) shared(is,ie,js,je,isd,ied,jsd,jed,npz,dp1,zvir,nwat,q,q_con,sphum,liq_wat, & #endif -!$OMP rainwat,ice_wat,snowwat,graupel) private(cvm,i,j,k) +!$OMP rainwat,ice_wat,snowwat,graupel,hailwat) private(cvm,i,j,k) do k=1,npz do j=js,je #ifdef USE_COND call moist_cp(is,ie,isd,ied,jsd,jed, npz, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, q_con(is:ie,j,k), cvm) + ice_wat, snowwat, graupel, hailwat, q, q_con(is:ie,j,k), cvm) #endif do i=is,ie dp1(i,j,k) = zvir*q(i,j,k,sphum) @@ -437,7 +446,7 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, do j=js,je #ifdef MOIST_CAPPA call moist_cv(is,ie,isd,ied,jsd,jed, npz, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, q_con(is:ie,j,k), cvm) + ice_wat, snowwat, graupel, hailwat, q, q_con(is:ie,j,k), cvm) #endif do i=is,ie #ifdef MULTI_GASES @@ -502,7 +511,7 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, gridstruct%rsin2, gridstruct%cosa_s, & zvir, cp_air, rdgas, hlv, te_2d, ua, va, teq, & flagstruct%moist_phys, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, hydrostatic, idiag%id_te) + ice_wat, snowwat, graupel, hailwat, hydrostatic, idiag%id_te) if( idiag%id_te>0 ) then used = send_data(idiag%id_te, teq, fv_time) ! te_den=1.E-9*g_sum(teq, is, ie, js, je, ng, area, 0)/(grav*4.*pi*radius**2) @@ -705,6 +714,9 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, call fill2D(is, ie, js, je, ng, npz, q(isd,jsd,1,snowwat), delp, gridstruct%area, domain, gridstruct%bounded_domain, npx, npy) if ( graupel > 0 ) & call fill2D(is, ie, js, je, ng, npz, q(isd,jsd,1,graupel), delp, gridstruct%area, domain, gridstruct%bounded_domain, npx, npy) + if ( hailwat > 0 ) & + call fill2D(is, ie, js, je, ng, npz, q(isd,jsd,1,hailwat), delp, gridstruct%area, domain, gridstruct%bounded_domain, npx, npy) + call timing_off('Fill2D') endif #endif @@ -816,7 +828,44 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, used = send_data(idiag%id_mdt, dtdt_m, fv_time) endif - if( nwat==6 ) then + if( nwat==7 ) then + if (cld_amt > 0) then + call neg_adj4(is, ie, js, je, ng, npz, & + flagstruct%hydrostatic, & + peln, delz, & + pt, delp, q(isd,jsd,1,sphum), & + q(isd,jsd,1,liq_wat), & + q(isd,jsd,1,rainwat), & + q(isd,jsd,1,ice_wat), & + q(isd,jsd,1,snowwat), & + q(isd,jsd,1,graupel), & + q(isd,jsd,1,hailwat), & + q(isd,jsd,1,cld_amt), flagstruct%check_negative) + else + call neg_adj4(is, ie, js, je, ng, npz, & + flagstruct%hydrostatic, & + peln, delz, & + pt, delp, q(isd,jsd,1,sphum), & + q(isd,jsd,1,liq_wat), & + q(isd,jsd,1,rainwat), & + q(isd,jsd,1,ice_wat), & + q(isd,jsd,1,snowwat), & + q(isd,jsd,1,graupel), & + q(isd,jsd,1,hailwat), check_negative=flagstruct%check_negative) + endif + if ( flagstruct%fv_debug ) then + call prt_mxm('T_dyn_a3', pt, is, ie, js, je, ng, npz, 1., gridstruct%area_64, domain) + call prt_mxm('SPHUM_dyn', q(isd,jsd,1,sphum ), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + call prt_mxm('liq_wat_dyn', q(isd,jsd,1,liq_wat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + call prt_mxm('rainwat_dyn', q(isd,jsd,1,rainwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + call prt_mxm('ice_wat_dyn', q(isd,jsd,1,ice_wat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + call prt_mxm('snowwat_dyn', q(isd,jsd,1,snowwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + call prt_mxm('graupel_dyn', q(isd,jsd,1,graupel), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + call prt_mxm('hailwat_dyn', q(isd,jsd,1,hailwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + endif + endif + + if( nwat == 6 ) then if (cld_amt > 0) then call neg_adj3(is, ie, js, je, ng, npz, & flagstruct%hydrostatic, & diff --git a/model/fv_mapz.F90 b/model/fv_mapz.F90 index 56617eedf..1f26559d4 100644 --- a/model/fv_mapz.F90 +++ b/model/fv_mapz.F90 @@ -226,7 +226,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & real rcp, rg, rrg, bkh, dtmp, k1k integer:: i,j,k integer:: kdelz - integer:: nt, liq_wat, ice_wat, rainwat, snowwat, cld_amt, graupel, ccn_cm3, iq, n, kp, k_next + integer:: nt, liq_wat, ice_wat, rainwat, snowwat, cld_amt, graupel, hailwat, ccn_cm3, iq, n, kmp, kp, k_next integer :: ierr ccpp_associate: associate( fast_mp_consv => CCPP_interstitial%fast_mp_consv, & @@ -242,6 +242,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') cld_amt = get_tracer_index (MODEL_ATMOS, 'cld_amt') ccn_cm3 = get_tracer_index (MODEL_ATMOS, 'ccn_cm3') @@ -251,7 +252,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & !$OMP parallel do default(none) shared(is,ie,js,je,km,pe,ptop,kord_tm,hydrostatic, & !$OMP pt,pk,rg,peln,q,nwat,liq_wat,rainwat,ice_wat,snowwat, & -!$OMP graupel,q_con,sphum,cappa,r_vir,rcp,k1k,delp, & +!$OMP graupel,hailwat,q_con,sphum,cappa,r_vir,rcp,k1k,delp, & !$OMP delz,akap,pkz,te,u,v,ps, gridstruct, last_step, & !$OMP ak,bk,nq,isd,ied,jsd,jed,kord_tr,fill, adiabatic, & #ifdef MULTI_GASES @@ -294,7 +295,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & do k=1,km #ifdef MOIST_CAPPA call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, gz, cvm) + ice_wat, snowwat, graupel, hailwat, q, gz, cvm) do i=is,ie q_con(i,j,k) = gz(i) #ifdef MULTI_GASES @@ -545,7 +546,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & do k=1,km #ifdef MOIST_CAPPA call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, gz, cvm) + ice_wat, snowwat, graupel, hailwat, q, gz, cvm) do i=is,ie q_con(i,j,k) = gz(i) #ifdef MULTI_GASES @@ -667,7 +668,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & !$OMP parallel default(none) shared(is,ie,js,je,km,ptop,u,v,pe,ua,va,isd,ied,jsd,jed,kord_mt, & !$OMP te_2d,te,delp,hydrostatic,hs,rg,pt,peln, adiabatic, & !$OMP cp,delz,nwat,rainwat,liq_wat,ice_wat,snowwat, & -!$OMP graupel,q_con,r_vir,sphum,w,pk,pkz,last_step,consv, & +!$OMP graupel,hailwat,q_con,r_vir,sphum,w,pk,pkz,last_step,consv, & !$OMP do_adiabatic_init,zsum1,zsum0,te0_2d,domain, & !$OMP ng,gridstruct,E_Flux,pdt,dtmp,reproduce_sum,q, & !$OMP mdt,cld_amt,cappa,dtdt,out_dt,rrg,akap,do_sat_adj, & @@ -682,7 +683,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & !$OMP parallel default(none) shared(is,ie,js,je,km,kmp,ptop,u,v,pe,ua,va,isd,ied,jsd,jed,kord_mt, & !$OMP te_2d,te,delp,hydrostatic,hs,rg,pt,peln, adiabatic, & !$OMP cp,delz,nwat,rainwat,liq_wat,ice_wat,snowwat, & -!$OMP graupel,q_con,r_vir,sphum,w,pk,pkz,last_step,consv, & +!$OMP graupel,hailwat,q_con,r_vir,sphum,w,pk,pkz,last_step,consv, & !$OMP do_adiabatic_init,zsum1,zsum0,te0_2d,domain, & !$OMP ng,gridstruct,E_Flux,pdt,dtmp,reproduce_sum,q, & !$OMP mdt,cld_amt,cappa,dtdt,out_dt,rrg,akap,do_sat_adj, & @@ -744,7 +745,7 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & do k=1,km #ifdef MOIST_CAPPA call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, gz, cvm) + ice_wat, snowwat, graupel, hailwat, q, gz, cvm) do i=is,ie ! KE using 3D winds: q_con(i,j,k) = gz(i) @@ -874,11 +875,20 @@ subroutine Lagrangian_to_Eulerian(last_step, consv, ps, pe, delp, pkz, pk, & pt(i,j,k) = (pt(i,j,k)+dtmp*pkz(i,j,k))/ virq(q(i,j,k,1:num_gas)) #else pt(i,j,k) = (pt(i,j,k)+dtmp*pkz(i,j,k))/((1.+r_vir*q(i,j,k,sphum))*(1.-gz(i))) +#endif + enddo + elseif ( nwat==7 ) then + do i=is,ie + gz(i) = q(i,j,k,liq_wat)+q(i,j,k,rainwat)+q(i,j,k,ice_wat)+q(i,j,k,snowwat)+q(i,j,k,graupel)+q(i,j,k,hailwat) +#ifdef MULTI_GASES + pt(i,j,k) = (pt(i,j,k)+dtmp*pkz(i,j,k))/ virq(q(i,j,k,1:num_gas)) +#else + pt(i,j,k) = (pt(i,j,k)+dtmp*pkz(i,j,k))/((1.+r_vir*q(i,j,k,sphum))*(1.-gz(i))) #endif enddo else call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, gz, cvm) + ice_wat, snowwat, graupel, hailwat, q, gz, cvm) do i=is,ie #ifdef MULTI_GASES pt(i,j,k) = (pt(i,j,k)+dtmp*pkz(i,j,k)) / virq(q(i,j,k,1:num_gas)) @@ -925,13 +935,13 @@ subroutine compute_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, & u, v, w, delz, pt, delp, q, qc, pe, peln, hs, & rsin2_l, cosa_s_l, & r_vir, cp, rg, hlv, te_2d, ua, va, teq, & - moist_phys, nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, hydrostatic, id_te) + moist_phys, nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, hailwat, hydrostatic, id_te) !------------------------------------------------------ ! Compute vertically integrated total energy per column !------------------------------------------------------ ! !INPUT PARAMETERS: integer, intent(in):: km, is, ie, js, je, isd, ied, jsd, jed, id_te - integer, intent(in):: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, nwat + integer, intent(in):: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat, nwat real, intent(inout), dimension(isd:ied,jsd:jed,km):: ua, va real, intent(in), dimension(isd:ied,jsd:jed,km):: pt, delp real, intent(in), dimension(isd:ied,jsd:jed,km,*):: q @@ -966,7 +976,7 @@ subroutine compute_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, & #ifdef MULTI_GASES !$OMP num_gas, & #endif -!$OMP q,nwat,liq_wat,rainwat,ice_wat,snowwat,graupel,sphum) & +!$OMP q,nwat,liq_wat,rainwat,ice_wat,snowwat,graupel,hailwat,sphum) & !$OMP private(phiz, tv, cvm, qd) do j=js,je @@ -1012,7 +1022,7 @@ subroutine compute_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, & do k=1,km #ifdef MOIST_CAPPA call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, qd, cvm) + ice_wat, snowwat, graupel, hailwat, q, qd, cvm) #endif do i=is,ie #ifdef MOIST_CAPPA @@ -3408,9 +3418,9 @@ end subroutine mappm !! including the heating capacity of water vapor and condensates. !>@details See \cite emanuel1994atmospheric for information on variable heat capacities. subroutine moist_cv(is,ie, isd,ied, jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, qd, cvm, t1) + ice_wat, snowwat, graupel, hailwat, q, qd, cvm, t1) integer, intent(in):: is, ie, isd,ied, jsd,jed, km, nwat, j, k - integer, intent(in):: sphum, liq_wat, rainwat, ice_wat, snowwat, graupel + integer, intent(in):: sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, hailwat #ifdef MULTI_GASES real, intent(in), dimension(isd:ied,jsd:jed,km,num_gas):: q #else @@ -3499,6 +3509,18 @@ subroutine moist_cv(is,ie, isd,ied, jsd,jed, km, j, k, nwat, sphum, liq_wat, rai cvm(i) = (1.-(qv(i)+qd(i)))*cv_air*vicvqd(q(i,j,k,1:num_gas)) + qv(i)*cv_vap + ql(i)*c_liq + qs(i)*c_ice #else cvm(i) = (1.-(qv(i)+qd(i)))*cv_air + qv(i)*cv_vap + ql(i)*c_liq + qs(i)*c_ice +#endif + enddo + case(7) + do i=is,ie + qv(i) = q(i,j,k,sphum) + ql(i) = q(i,j,k,liq_wat) + q(i,j,k,rainwat) + qs(i) = q(i,j,k,ice_wat) + q(i,j,k,snowwat) + q(i,j,k,graupel) + q(i,j,k,hailwat) + qd(i) = ql(i) + qs(i) +#ifdef MULTI_GASES + cvm(i) = (1.-(qv(i)+qd(i)))*cv_air*vicvqd(q(i,j,k,1:num_gas)) + qv(i)*cv_vap + ql(i)*c_liq + qs(i)*c_ice +#else + cvm(i) = (1.-(qv(i)+qd(i)))*cv_air + qv(i)*cv_vap + ql(i)*c_liq + qs(i)*c_ice #endif enddo case default @@ -3518,10 +3540,10 @@ end subroutine moist_cv !>@brief The subroutine 'moist_cp' computes the FV3-consistent moist heat capacity under constant pressure, !! including the heating capacity of water vapor and condensates. subroutine moist_cp(is,ie, isd,ied, jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, qd, cpm, t1) + ice_wat, snowwat, graupel, hailwat, q, qd, cpm, t1) integer, intent(in):: is, ie, isd,ied, jsd,jed, km, nwat, j, k - integer, intent(in):: sphum, liq_wat, rainwat, ice_wat, snowwat, graupel + integer, intent(in):: sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, hailwat real, intent(in), dimension(isd:ied,jsd:jed,km,nwat):: q real, intent(out), dimension(is:ie):: cpm, qd real, intent(in), optional:: t1(is:ie) @@ -3613,6 +3635,20 @@ subroutine moist_cp(is,ie, isd,ied, jsd,jed, km, j, k, nwat, sphum, liq_wat, rai cpm(i) = (1.-(qv(i)+qd(i)))*cp_air + qv(i)*cp_vapor + ql(i)*c_liq + qs(i)*c_ice #endif enddo + + case(7) + do i=is,ie + qv(i) = q(i,j,k,sphum) + ql(i) = q(i,j,k,liq_wat) + q(i,j,k,rainwat) + qs(i) = q(i,j,k,ice_wat) + q(i,j,k,snowwat) + q(i,j,k,graupel) + q(i,j,k,hailwat) + qd(i) = ql(i) + qs(i) +#ifdef MULTI_GASES + cpm(i) = (1.-(qv(i)+qd(i)))*cp_air*vicpqd(q(i,j,k,:)) + qv(i)*cp_vapor + ql(i)*c_liq + qs(i)*c_ice +#else + cpm(i) = (1.-(qv(i)+qd(i)))*cp_air + qv(i)*cp_vapor + ql(i)*c_liq + qs(i)*c_ice +#endif + enddo + case default !call mpp_error (NOTE, 'fv_mapz::moist_cp - using default cp_air') do i=is,ie diff --git a/model/fv_nesting.F90 b/model/fv_nesting.F90 index 92124963f..c41dd3e9c 100644 --- a/model/fv_nesting.F90 +++ b/model/fv_nesting.F90 @@ -1416,15 +1416,15 @@ subroutine setup_pt_NH_BC(pt_BC, delp_BC, delz_BC, sphum_BC, q_BC, nq, & real, parameter:: c_ice = 1972. !< heat capacity of ice at 0C: c=c_ice+7.3*(T-Tice) real, parameter:: cv_vap = cp_vapor - rvgas !< 1384.5 - real, dimension(:,:,:), pointer :: liq_watBC_west, ice_watBC_west, rainwatBC_west, snowwatBC_west, graupelBC_west - real, dimension(:,:,:), pointer :: liq_watBC_east, ice_watBC_east, rainwatBC_east, snowwatBC_east, graupelBC_east - real, dimension(:,:,:), pointer :: liq_watBC_north, ice_watBC_north, rainwatBC_north, snowwatBC_north, graupelBC_north - real, dimension(:,:,:), pointer :: liq_watBC_south, ice_watBC_south, rainwatBC_south, snowwatBC_south, graupelBC_south + real, dimension(:,:,:), pointer :: liq_watBC_west, ice_watBC_west, rainwatBC_west, snowwatBC_west, graupelBC_west, hailwatBC_west + real, dimension(:,:,:), pointer :: liq_watBC_east, ice_watBC_east, rainwatBC_east, snowwatBC_east, graupelBC_east, hailwatBC_east + real, dimension(:,:,:), pointer :: liq_watBC_north, ice_watBC_north, rainwatBC_north, snowwatBC_north, graupelBC_north, hailwatBC_north + real, dimension(:,:,:), pointer :: liq_watBC_south, ice_watBC_south, rainwatBC_south, snowwatBC_south, graupelBC_south, hailwatBC_south real :: dp1, q_liq, q_sol, q_con = 0., cvm, pkz, rdg, cv_air integer :: i,j,k, istart, iend - integer :: liq_wat, ice_wat, rainwat, snowwat, graupel + integer :: liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat real, parameter:: tice = 273.16 !< For GFS Partitioning real, parameter:: t_i0 = 15. @@ -1557,11 +1557,22 @@ subroutine setup_pt_NH_BC(pt_BC, delp_BC, delz_BC, sphum_BC, q_BC, nq, & graupelBC_north => dum_north graupelBC_south => dum_south endif + if (hailwat > 0) then + hailwatBC_west => q_BC(hailwat)%west_t1 + hailwatBC_east => q_BC(hailwat)%east_t1 + hailwatBC_north => q_BC(hailwat)%north_t1 + hailwatBC_south => q_BC(hailwat)%south_t1 + else + hailwatBC_west => dum_west + hailwatBC_east => dum_east + hailwatBC_north => dum_north + hailwatBC_south => dum_south + endif if (is == 1) then call setup_pt_NH_BC_k(pt_BC%west_t1, sphum_BC%west_t1, delp_BC%west_t1, delz_BC%west_t1, & - liq_watBC_west, rainwatBC_west, ice_watBC_west, snowwatBC_west, graupelBC_west, & + liq_watBC_west, rainwatBC_west, ice_watBC_west, snowwatBC_west, graupelBC_west, hailwatBC_west, & #ifdef USE_COND q_con_BC%west_t1, & #ifdef MOIST_CAPPA @@ -1585,7 +1596,7 @@ subroutine setup_pt_NH_BC(pt_BC, delp_BC, delz_BC, sphum_BC, q_BC, nq, & end if call setup_pt_NH_BC_k(pt_BC%south_t1, sphum_BC%south_t1, delp_BC%south_t1, delz_BC%south_t1, & - liq_watBC_south, rainwatBC_south, ice_watBC_south, snowwatBC_south, graupelBC_south, & + liq_watBC_south, rainwatBC_south, ice_watBC_south, snowwatBC_south, graupelBC_south, hailwatBC_south, & #ifdef USE_COND q_con_BC%south_t1, & #ifdef MOIST_CAPPA @@ -1599,7 +1610,7 @@ subroutine setup_pt_NH_BC(pt_BC, delp_BC, delz_BC, sphum_BC, q_BC, nq, & if (ie == npx-1) then call setup_pt_NH_BC_k(pt_BC%east_t1, sphum_BC%east_t1, delp_BC%east_t1, delz_BC%east_t1, & - liq_watBC_east, rainwatBC_east, ice_watBC_east, snowwatBC_east, graupelBC_east, & + liq_watBC_east, rainwatBC_east, ice_watBC_east, snowwatBC_east, graupelBC_east, hailwatBC_east, & #ifdef USE_COND q_con_BC%east_t1, & #ifdef MOIST_CAPPA @@ -1622,7 +1633,7 @@ subroutine setup_pt_NH_BC(pt_BC, delp_BC, delz_BC, sphum_BC, q_BC, nq, & end if call setup_pt_NH_BC_k(pt_BC%north_t1, sphum_BC%north_t1, delp_BC%north_t1, delz_BC%north_t1, & - liq_watBC_north, rainwatBC_north, ice_watBC_north, snowwatBC_north, graupelBC_north, & + liq_watBC_north, rainwatBC_north, ice_watBC_north, snowwatBC_north, graupelBC_north, hailwatBC_north, & #ifdef USE_COND q_con_BC%north_t1, & #ifdef MOIST_CAPPA @@ -1636,7 +1647,7 @@ end subroutine setup_pt_NH_BC subroutine setup_pt_NH_BC_k(ptBC,sphumBC,delpBC,delzBC, & - liq_watBC,rainwatBC,ice_watBC,snowwatBC,graupelBC, & + liq_watBC,rainwatBC,ice_watBC,snowwatBC,graupelBC,hailwatBC, & #ifdef USE_COND q_conBC, & #ifdef MOIST_CAPPA @@ -1648,7 +1659,7 @@ subroutine setup_pt_NH_BC_k(ptBC,sphumBC,delpBC,delzBC, & integer, intent(IN) :: isd_BC, ied_BC, istart, iend, jstart, jend, npz real, intent(OUT), dimension(isd_BC:ied_BC,jstart:jend,npz) :: ptBC real, intent(IN), dimension(isd_BC:ied_BC,jstart:jend,npz) :: sphumBC, delpBC, delzBC - real, intent(IN), dimension(isd_BC:ied_BC,jstart:jend,npz) :: liq_watBC,rainwatBC,ice_watBC,snowwatBC,graupelBC + real, intent(IN), dimension(isd_BC:ied_BC,jstart:jend,npz) :: liq_watBC,rainwatBC,ice_watBC,snowwatBC,graupelBC,hailwatBC #ifdef USE_COND real, intent(OUT), dimension(isd_BC:ied_BC,jstart:jend,npz) :: q_conBC #ifdef MOIST_CAPPA @@ -1669,7 +1680,7 @@ subroutine setup_pt_NH_BC_k(ptBC,sphumBC,delpBC,delzBC, & rdg = -rdgas / grav cv_air = cp_air - rdgas -!$OMP parallel do default(none) shared(istart,iend,jstart,jend,npz,zvir,ptBC,sphumBC,delpBC,delzBC,liq_watBC,rainwatBC,ice_watBC,snowwatBC,graupelBC, & +!$OMP parallel do default(none) shared(istart,iend,jstart,jend,npz,zvir,ptBC,sphumBC,delpBC,delzBC,liq_watBC,rainwatBC,ice_watBC,snowwatBC,graupelBC,hailwatBC, & #ifdef USE_COND !$OMP q_conBC, & #ifdef MOIST_CAPPA @@ -1684,7 +1695,7 @@ subroutine setup_pt_NH_BC_k(ptBC,sphumBC,delpBC,delzBC, & dp1 = zvir*sphumBC(i,j,k) #ifdef USE_COND q_liq = liq_watBC(i,j,k) + rainwatBC(i,j,k) - q_sol = ice_watBC(i,j,k) + snowwatBC(i,j,k) + graupelBC(i,j,k) + q_sol = ice_watBC(i,j,k) + snowwatBC(i,j,k) + graupelBC(i,j,k) + hailwatBC(i,j,k) q_con = q_liq + q_sol q_conBC(i,j,k) = q_con #ifdef MOIST_CAPPA diff --git a/model/fv_regional_bc.F90 b/model/fv_regional_bc.F90 index 8c1323fa4..223b14fef 100644 --- a/model/fv_regional_bc.F90 +++ b/model/fv_regional_bc.F90 @@ -137,6 +137,7 @@ module fv_regional_mod ! integer,save :: cld_amt_index & !<-- ,graupel_index & ! + ,hailwat_index & ! ,ice_water_index & ! Locations of ,liq_water_index & ! tracer vbls ,o3mr_index & ! in the tracers @@ -741,6 +742,7 @@ subroutine setup_regional_BC(Atm & rain_water_index = get_tracer_index(MODEL_ATMOS, 'rainwat') snow_water_index = get_tracer_index(MODEL_ATMOS, 'snowwat') graupel_index = get_tracer_index(MODEL_ATMOS, 'graupel') + hailwat_index = get_tracer_index(MODEL_ATMOS, 'hailwat') cld_amt_index = get_tracer_index(MODEL_ATMOS, 'cld_amt') o3mr_index = get_tracer_index(MODEL_ATMOS, 'o3mr') ! write(0,*)' setup_regional_bc' @@ -3492,7 +3494,7 @@ subroutine remap_scalar_nggps_regional_bc(Atm & real(kind=R_GRID):: pst !!! High-precision integer i,ie,is,j,je,js,k,l,m, k2,iq - integer sphum, o3mr, liq_wat, ice_wat, rainwat, snowwat, graupel, cld_amt + integer sphum, o3mr, liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat, cld_amt ! !--------------------------------------------------------------------------------- ! @@ -3502,6 +3504,7 @@ subroutine remap_scalar_nggps_regional_bc(Atm & rainwat = rain_water_index snowwat = snow_water_index graupel = graupel_index + hailwat = hailwat_index cld_amt = cld_amt_index o3mr = o3mr_index @@ -3808,7 +3811,51 @@ subroutine remap_scalar_nggps_regional_bc(Atm & enddo enddo endif - endif ! data source /= FV3GFS GAUSSIAN NEMSIO/NETCDF and GRIB2 FILE + if ( Atm%flagstruct%nwat .eq. 7 ) then + do k=1,npz + do i=is,ie + qn1(i,k) = BC_side%q_BC(i,j,k,liq_wat) + BC_side%q_BC(i,j,k,rainwat) = 0. + BC_side%q_BC(i,j,k,snowwat) = 0. + BC_side%q_BC(i,j,k,graupel) = 0. + BC_side%q_BC(i,j,k,hailwat) = 0. + if ( BC_side%pt_BC(i,j,k) > 273.16 ) then ! > 0C all liq_wat + BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k) + BC_side%q_BC(i,j,k,ice_wat) = 0. +#ifdef ORIG_CLOUDS_PART + else if ( BC_side%pt_BC(i,j,k) < 258.16 ) then ! < -15C all ice_wat + BC_side%q_BC(i,j,k,liq_wat) = 0. + BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) + else ! between -15~0C: linear interpolation + BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k)*((BC_side%pt_BC(i,j,k)-258.16)/15.) + BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - BC_side%q_BC(i,j,k,liq_wat) + endif +#else + else if ( BC_side%pt_BC(i,j,k) < 233.16 ) then ! < -40C all ice_wat + BC_side%q_BC(i,j,k,liq_wat) = 0. + BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) + else + if ( k.eq.1 ) then ! between [-40,0]: linear interpolation + BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k)*((BC_side%pt_BC(i,j,k)-233.16)/40.) + BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - BC_side%q_BC(i,j,k,liq_wat) + else + if (BC_side%pt_BC(i,j,k)<258.16 .and. BC_side%q_BC(i,j,k-1,ice_wat)>1.e-5 ) then + BC_side%q_BC(i,j,k,liq_wat) = 0. + BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) + else ! between [-40,0]: linear interpolation + BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k)*((BC_side%pt_BC(i,j,k)-233.16)/40.) + BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - BC_side%q_BC(i,j,k,liq_wat) + endif + endif + endif +#endif + call mp_auto_conversion(BC_side%q_BC(i,j,k,liq_wat), BC_side%q_BC(i,j,k,rainwat), & + BC_side%q_BC(i,j,k,ice_wat), BC_side%q_BC(i,j,k,snowwat) ) + enddo + enddo + endif + + endif ! data source /= FV3GFS GAUSSIAN NEMSIO FILE ! ! For GFS spectral input, omega in pa/sec is stored as w in the input data so actual w(m/s) is calculated ! For GFS nemsio input, omega is 0, so best not to use for input since boundary data will not exist for w diff --git a/model/fv_sg.F90 b/model/fv_sg.F90 index 06b401dbf..3226a0302 100644 --- a/model/fv_sg.F90 +++ b/model/fv_sg.F90 @@ -68,7 +68,7 @@ module fv_sg_mod implicit none private -public fv_subgrid_z, qsmith, neg_adj3, neg_adj2 +public fv_subgrid_z, qsmith, neg_adj3, neg_adj2, neg_adj4 real, parameter:: esl = 0.621971831 real, parameter:: tice = 273.16 @@ -147,7 +147,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & integer i, j, k, kk, n, m, iq, km1, im, kbot, l real, parameter:: ustar2 = 1.E-4 real:: cv_air, xvir - integer :: sphum, liq_wat, rainwat, snowwat, graupel, ice_wat, cld_amt + integer :: sphum, liq_wat, rainwat, snowwat, graupel, hailwat, ice_wat, cld_amt cv_air = cp_air - rdgas ! = rdgas * (7/2-1) = 2.5*rdgas=717.68 rk = cp_air/rdgas + 1. @@ -188,6 +188,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') cld_amt = get_tracer_index (MODEL_ATMOS, 'cld_amt') endif @@ -200,7 +201,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & !$OMP parallel do default(none) shared(im,is,ie,js,je,nq,kbot,qa,ta,sphum,ua,va,delp,peln, & !$OMP hydrostatic,pe,delz,g2,w,liq_wat,rainwat,ice_wat, & -!$OMP snowwat,cv_air,m,graupel,pkz,rk,rz,fra, t_max, t_min, & +!$OMP snowwat,cv_air,m,graupel,hailwat,pkz,rk,rz,fra, t_max, t_min, & #ifdef MULTI_GASES !$OMP u_dt,rdt,v_dt,xvir,nwat,km) & #else @@ -308,7 +309,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - elseif ( nwat==5 ) then + elseif ( nwat >= 5 ) then do i=is,ie q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) @@ -320,10 +321,13 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - else + elseif ( nwat >= 6 ) then do i=is,ie q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) + IF ( nwat == 7 ) THEN + q_sol = q_sol + q0(i,k,hailwat) + ENDIF #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -456,9 +460,12 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & elseif ( nwat==5 ) then ! K_warm_rain scheme with fake ice qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + & q0(i,km1,snowwat) + q0(i,km1,rainwat) - else + elseif ( nwat==6 ) then qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + & q0(i,km1,snowwat) + q0(i,km1,rainwat) + q0(i,km1,graupel) + elseif ( nwat==7 ) then + qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + & + q0(i,km1,snowwat) + q0(i,km1,rainwat) + q0(i,km1,graupel) + q0(i,km1,hailwat) endif ! u: h0 = mc*(u0(i,k)-u0(i,k-1)) @@ -595,10 +602,13 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - else + elseif ( nwat >= 6 ) THEN do i=is,ie q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat) q_sol = q0(i,kk,ice_wat) + q0(i,kk,snowwat) + q0(i,kk,graupel) + IF ( nwat == 7 ) THEN + q_sol = q_sol + q0(i,kk,hailwat) + ENDIF #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -715,7 +725,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & integer i, j, k, kk, n, m, iq, km1, im, kbot real, parameter:: ustar2 = 1.E-4 real:: cv_air, xvir - integer :: sphum, liq_wat, rainwat, snowwat, graupel, ice_wat, cld_amt + integer :: sphum, liq_wat, rainwat, snowwat, graupel, hailwat, ice_wat, cld_amt cv_air = cp_air - rdgas ! = rdgas * (7/2-1) = 2.5*rdgas=717.68 rk = cp_air/rdgas + 1. @@ -745,6 +755,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') cld_amt = get_tracer_index (MODEL_ATMOS, 'cld_amt') endif @@ -757,7 +768,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & !$OMP parallel do default(none) shared(im,is,ie,js,je,nq,kbot,qa,ta,sphum,ua,va,delp,peln, & !$OMP hydrostatic,pe,delz,g2,w,liq_wat,rainwat,ice_wat, & -!$OMP snowwat,cv_air,m,graupel,pkz,rk,rz,fra,cld_amt, & +!$OMP snowwat,cv_air,m,graupel,hailwat,pkz,rk,rz,fra,cld_amt, & !$OMP u_dt,rdt,v_dt,xvir,nwat) & !$OMP private(kk,lcp2,icp2,tcp3,dh,dq,den,qs,qsw,dqsdt,qcon,q0, & !$OMP t0,u0,v0,w0,h0,pm,gzh,tvm,tmp,cpm,cvm, q_liq,q_sol,& @@ -874,10 +885,13 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - else + elseif ( nwat >= 6 ) THEN do i=is,ie q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) + IF ( nwat == 7 ) THEN + q_sol = q_sol + q0(i,k,hailwat) + ENDIF #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -1005,9 +1019,12 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & elseif ( nwat==5 ) then qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + & q0(i,km1,snowwat) + q0(i,km1,rainwat) - else + elseif ( nwat==6 ) then qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + & q0(i,km1,snowwat) + q0(i,km1,rainwat) + q0(i,km1,graupel) + elseif ( nwat==7 ) then + qcon(i,km1) = q0(i,km1,liq_wat) + q0(i,km1,ice_wat) + & + q0(i,km1,snowwat) + q0(i,km1,rainwat) + q0(i,km1,graupel) + q0(i,km1,hailwat) endif ! u: h0 = mc*(u0(i,k)-u0(i,k-1)) @@ -1143,10 +1160,13 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - else + elseif ( nwat >= 6 ) THEN do i=is,ie q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat) q_sol = q0(i,kk,ice_wat) + q0(i,kk,snowwat) + q0(i,kk,graupel) + IF ( nwat == 7 ) THEN + q_sol = q_sol + q0(i,kk,hailwat) + ENDIF #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -1199,7 +1219,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & ! Saturation adjustment !---------------------- #ifndef GFS_PHYS - if ( nwat > 5 ) then + if ( nwat >= 6 ) then do k=1, kbot if ( hydrostatic ) then do i=is, ie @@ -1211,6 +1231,9 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & #endif q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) + IF ( nwat == 7 ) THEN + q_sol = q_sol + q0(i,k,hailwat) + ENDIF #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice #else @@ -1224,6 +1247,9 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & den(i,k) = -delp(i,j,k)/(grav*delz(i,j,k)) q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) + IF ( nwat == 7 ) THEN + q_sol = q_sol + q0(i,k,hailwat) + ENDIF #ifdef MULTI_GASES cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #else @@ -1878,6 +1904,364 @@ subroutine neg_adj3(is, ie, js, je, ng, kbot, hydrostatic, peln, delz, pt, dp, end subroutine neg_adj3 +! TAS: XXX check to make sure this doesn't need any modifications vs neg_adj2 or neg_adj3 + subroutine neg_adj4(is, ie, js, je, ng, kbot, hydrostatic, & + peln, delz, pt, dp, qv, ql, qr, qi, qs, qg, qh, qa, check_negative) + +! This is designed for 7-class micro-physics schemes + integer, intent(in):: is, ie, js, je, ng, kbot + logical, intent(in):: hydrostatic + real, intent(in):: dp(is-ng:ie+ng,js-ng:je+ng,kbot) ! total delp-p + real, intent(in):: delz(is:,js:,1:) + real, intent(in):: peln(is:ie,kbot+1,js:je) ! ln(pe) + logical, intent(in), OPTIONAL :: check_negative + real, intent(inout), dimension(is-ng:ie+ng,js-ng:je+ng,kbot):: & + pt, qv, ql, qr, qi, qs, qg, qh + real, intent(inout), OPTIONAL, dimension(is-ng:ie+ng,js-ng:je+ng,kbot):: qa +! Local: + logical:: sat_adj = .false. + real, parameter :: t48 = tice - 48. + real, dimension(is:ie,kbot):: dpk, q2 +real, dimension(is:ie,js:je):: pt2, qv2, ql2, qi2, qs2, qr2, qg2, qh2, dp2, p2, icpk, lcpk + real:: cv_air + real:: dq, qsum, dq1, q_liq, q_sol, cpm, sink, qsw, dwsdt + integer i, j, k + + cv_air = cp_air - rdgas ! = rdgas * (7/2-1) = 2.5*rdgas=717.68 + + if ( present(check_negative) ) then + if ( check_negative ) then + call prt_negative('Temperature', pt, is, ie, js, je, ng, kbot, 165.) + call prt_negative('sphum', qv, is, ie, js, je, ng, kbot, -1.e-8) + call prt_negative('liq_wat', ql, is, ie, js, je, ng, kbot, -1.e-7) + call prt_negative('rainwat', qr, is, ie, js, je, ng, kbot, -1.e-7) + call prt_negative('ice_wat', qi, is, ie, js, je, ng, kbot, -1.e-7) + call prt_negative('snowwat', qs, is, ie, js, je, ng, kbot, -1.e-7) + call prt_negative('graupel', qg, is, ie, js, je, ng, kbot, -1.e-7) + call prt_negative('hailwat', qh, is, ie, js, je, ng, kbot, -1.e-7) + endif + endif + + if ( hydrostatic ) then + d0_vap = cp_vapor - c_liq + else + d0_vap = cv_vap - c_liq + endif + lv00 = hlv0 - d0_vap*t_ice + +!$OMP parallel do default(none) shared(is,ie,js,je,kbot,qv,ql,qi,qs,qr,qg,qh,dp,pt, & +!$OMP lv00, d0_vap,hydrostatic,peln,delz,cv_air,sat_adj) & +!$OMP private(dq,dq1,qsum,dp2,p2,pt2,qv2,ql2,qi2,qs2,qg2,qh2,qr2, & +!$OMP lcpk,icpk,qsw,dwsdt,sink,q_liq,q_sol,cpm) + do k=1, kbot + do j=js, je + do i=is, ie + qv2(i,j) = qv(i,j,k) + ql2(i,j) = ql(i,j,k) + qi2(i,j) = qi(i,j,k) + qs2(i,j) = qs(i,j,k) + qr2(i,j) = qr(i,j,k) + qg2(i,j) = qg(i,j,k) + qh2(i,j) = qh(i,j,k) + dp2(i,j) = dp(i,j,k) + pt2(i,j) = pt(i,j,k) + enddo + enddo + + if ( hydrostatic ) then + do j=js, je + do i=is, ie + p2(i,j) = dp2(i,j)/(peln(i,k+1,j)-peln(i,k,j)) + q_liq = max(0., ql2(i,j) + qr2(i,j)) + q_sol = max(0., qi2(i,j) + qs2(i,j)) + cpm = (1.-(qv2(i,j)+q_liq+q_sol))*cp_air + qv2(i,j)*cp_vapor + q_liq*c_liq + q_sol*c_ice + lcpk(i,j) = hlv / cpm + icpk(i,j) = hlf / cpm + enddo + enddo + else + do j=js, je + do i=is, ie + p2(i,j) = -dp2(i,j)/(grav*delz(i,j,k))*rdgas*pt2(i,j)*(1.+zvir*qv2(i,j)) + q_liq = max(0., ql2(i,j) + qr2(i,j)) + q_sol = max(0., qi2(i,j) + qs2(i,j)) + cpm = (1.-(qv2(i,j)+q_liq+q_sol))*cv_air + qv2(i,j)*cv_vap + q_liq*c_liq + q_sol*c_ice + lcpk(i,j) = (lv00+d0_vap*pt2(i,j)) / cpm + icpk(i,j) = (Li0+dc_ice*pt2(i,j)) / cpm + enddo + enddo + endif + +! Fix the negatives: +!----------- +! Ice-phase: +!----------- + do j=js, je + do i=is, ie + qsum = qi2(i,j) + qs2(i,j) + if ( qsum > 0. ) then + if ( qi2(i,j) < 0. ) then + qi2(i,j) = 0. + qs2(i,j) = qsum + elseif ( qs2(i,j) < 0. ) then + qs2(i,j) = 0. + qi2(i,j) = qsum + endif + else +! borrow froom graupel + qi2(i,j) = 0. + qs2(i,j) = 0. + qg2(i,j) = qg2(i,j) + qsum + endif + +! At this stage qi and qs should be positive definite +! If graupel < 0 then borrow from qs then qi + if ( qg2(i,j) < 0. ) then + dq = min( qs2(i,j), -qg2(i,j) ) + qs2(i,j) = qs2(i,j) - dq + qg2(i,j) = qg2(i,j) + dq + if ( qg2(i,j) < 0. ) then +! if qg is still negative + dq = min( qi2(i,j), -qg2(i,j) ) + qi2(i,j) = qi2(i,j) - dq + qg2(i,j) = qg2(i,j) + dq + endif + endif + +! If qg is still negative then borrow from rain water: phase change + if ( qg2(i,j)<0. .and. qr2(i,j)>0. ) then + dq = min( qr2(i,j), -qg2(i,j) ) + qg2(i,j) = qg2(i,j) + dq + qr2(i,j) = qr2(i,j) - dq + pt2(i,j) = pt2(i,j) + dq*icpk(i,j) ! conserve total energy + endif +! If qg is still negative then borrow from cloud water: phase change + if ( qg2(i,j)<0. .and. ql2(i,j)>0. ) then + dq = min( ql2(i,j), -qg2(i,j) ) + qg2(i,j) = qg2(i,j) + dq + ql2(i,j) = ql2(i,j) - dq + pt2(i,j) = pt2(i,j) + dq*icpk(i,j) + endif +! Last resort; borrow from water vapor + if ( qg2(i,j)<0. .and. qv2(i,j)>0. ) then + dq = min( 0.999*qv2(i,j), -qg2(i,j) ) + qg2(i,j) = qg2(i,j) + dq + qv2(i,j) = qv2(i,j) - dq + pt2(i,j) = pt2(i,j) + dq*(icpk(i,j)+lcpk(i,j)) + endif + +!-------------- +! Liquid phase: +!-------------- + qsum = ql2(i,j) + qr2(i,j) + if ( qsum > 0. ) then + if ( qr2(i,j) < 0. ) then + qr2(i,j) = 0. + ql2(i,j) = qsum + elseif ( ql2(i,j) < 0. ) then + ql2(i,j) = 0. + qr2(i,j) = qsum + endif + else + ql2(i,j) = 0. + qr2(i,j) = qsum ! rain water is still negative +! fill negative rain with qg first + dq = min( max(0.0, qg2(i,j)), -qr2(i,j) ) + qr2(i,j) = qr2(i,j) + dq + qg2(i,j) = qg2(i,j) - dq + pt2(i,j) = pt2(i,j) - dq*icpk(i,j) + if ( qr(i,j,k) < 0. ) then +! fill negative rain with available qi & qs (cooling) + dq = min( qi2(i,j)+qs2(i,j), -qr2(i,j) ) + qr2(i,j) = qr2(i,j) + dq + dq1 = min( dq, qs2(i,j) ) + qs2(i,j) = qs2(i,j) - dq1 + qi2(i,j) = qi2(i,j) + dq1 - dq + pt2(i,j) = pt2(i,j) - dq*icpk(i,j) + endif +! fix negative rain water with available vapor + if ( qr2(i,j)<0. .and. qv2(i,j)>0. ) then + dq = min( 0.999*qv2(i,j), -qr2(i,j) ) + qv2(i,j) = qv2(i,j) - dq + qr2(i,j) = qr2(i,j) + dq + pt2(i,j) = pt2(i,j) + dq*lcpk(i,j) + endif + endif + enddo + enddo + +!****************************************** +! Fast moist physics: Saturation adjustment +!****************************************** +#ifndef GFS_PHYS + if ( sat_adj ) then + + do j=js, je + do i=is, ie +! Melting of cloud ice into cloud water ******** + if ( qi2(i,j)>1.e-8 .and. pt2(i,j) > tice ) then + sink = min( qi2(i,j), (pt2(i,j)-tice)/icpk(i,j) ) + ql2(i,j) = ql2(i,j) + sink + qi2(i,j) = qi2(i,j) - sink + pt2(i,j) = pt2(i,j) - sink*icpk(i,j) + endif + +! vapor <---> liquid water -------------------------------- + qsw = wqsat2_moist(pt2(i,j), qv2(i,j), p2(i,j), dwsdt) + sink = min( ql2(i,j), (qsw-qv2(i,j))/(1.+lcpk(i,j)*dwsdt) ) + qv2(i,j) = qv2(i,j) + sink + ql2(i,j) = ql2(i,j) - sink + pt2(i,j) = pt2(i,j) - sink*lcpk(i,j) +!----------------------------------------------------------- + +! freezing of cloud water ******** + if( ql2(i,j)>1.e-8 .and. pt2(i,j) < t48 ) then +! Enforce complete freezing below t_00 (-48 C) + sink = min( ql2(i,j), (t48-pt2(i,j))/icpk(i,j) ) + ql2(i,j) = ql2(i,j) - sink + qi2(i,j) = qi2(i,j) + sink + pt2(i,j) = pt2(i,j) + sink*icpk(i,j) + endif ! significant ql existed + enddo + enddo + endif +#endif + +!---------------------------------------------------------------- +! Update fields: + do j=js, je + do i=is, ie + qv(i,j,k) = qv2(i,j) + ql(i,j,k) = ql2(i,j) + qi(i,j,k) = qi2(i,j) + qs(i,j,k) = qs2(i,j) + qr(i,j,k) = qr2(i,j) + qg(i,j,k) = qg2(i,j) + pt(i,j,k) = pt2(i,j) + enddo + enddo + + enddo + +!$OMP parallel do default(none) shared(is,ie,js,je,kbot,dp,qg,qr) & +!$OMP private(dpk, q2) + do j=js, je +! Graupel: + do k=1,kbot + do i=is,ie + dpk(i,k) = dp(i,j,k) + q2(i,k) = qg(i,j,k) + enddo + enddo + call fillq(ie-is+1, kbot, q2, dpk) + do k=1,kbot + do i=is,ie + qg(i,j,k) = q2(i,k) + enddo + enddo +! Rain water: + do k=1,kbot + do i=is,ie + q2(i,k) = qr(i,j,k) + enddo + enddo + call fillq(ie-is+1, kbot, q2, dpk) + do k=1,kbot + do i=is,ie + qr(i,j,k) = q2(i,k) + enddo + enddo + enddo + +!----------------------------------- +! Fix water vapor +!----------------------------------- +! Top layer: borrow from below + k = 1 +!$OMP parallel do default(none) shared(is,ie,js,je,k,qv,dp) + do j=js, je + do i=is, ie + if( qv(i,j,k) < 0. ) then + qv(i,j,k+1) = qv(i,j,k+1) + qv(i,j,k)*dp(i,j,k)/dp(i,j,k+1) + qv(i,j,k ) = 0. + endif + enddo + enddo + +! this OpenMP do-loop cannot be parallelized with recursion on k/k-1 +!$OMP parallel do default(none) shared(is,ie,js,je,kbot,qv,dp) & +!$OMP private(dq) + do j=js, je + do k=2,kbot-1 + do i=is, ie + if( qv(i,j,k) < 0. .and. qv(i,j,k-1) > 0. ) then + dq = min(-qv(i,j,k)*dp(i,j,k), qv(i,j,k-1)*dp(i,j,k-1)) + qv(i,j,k-1) = qv(i,j,k-1) - dq/dp(i,j,k-1) + qv(i,j,k ) = qv(i,j,k ) + dq/dp(i,j,k ) + endif + if( qv(i,j,k) < 0. ) then + qv(i,j,k+1) = qv(i,j,k+1) + qv(i,j,k)*dp(i,j,k)/dp(i,j,k+1) + qv(i,j,k ) = 0. + endif + enddo + enddo + enddo + +! Bottom layer; Borrow from above +!$OMP parallel do default(none) shared(is,ie,js,je,kbot,qv,dp) private(dq) + do j=js, je + do i=is, ie + if( qv(i,j,kbot) < 0. ) then + do k=kbot-1,1,-1 + if ( qv(i,j,kbot)>=0. ) goto 123 + if ( qv(i,j,k) > 0. ) then + dq = min(-qv(i,j,kbot)*dp(i,j,kbot), qv(i,j,k)*dp(i,j,k)) + qv(i,j,k ) = qv(i,j,k ) - dq/dp(i,j,k) + qv(i,j,kbot) = qv(i,j,kbot) + dq/dp(i,j,kbot) + endif + enddo ! k-loop +123 continue + endif + enddo ! i-loop + enddo ! j-loop + + + if (present(qa)) then +!----------------------------------- +! Fix negative cloud fraction +!----------------------------------- +! this OpenMP do-loop cannot be parallelized by the recursion on k/k+1 +!$OMP parallel do default(none) shared(is,ie,js,je,kbot,qa,dp) + do j=js, je + do k=1,kbot-1 + do i=is, ie + if( qa(i,j,k) < 0. ) then + qa(i,j,k+1) = qa(i,j,k+1) + qa(i,j,k)*dp(i,j,k)/dp(i,j,k+1) + qa(i,j,k ) = 0. + endif + enddo + enddo + enddo + +! Bottom layer; Borrow from above +!$OMP parallel do default(none) shared(is,ie,js,je,qa,kbot,dp) & +!$OMP private(dq) + do j=js, je + do i=is, ie + if( qa(i,j,kbot) < 0. .and. qa(i,j,kbot-1)>0.) then + dq = min(-qa(i,j,kbot)*dp(i,j,kbot), qa(i,j,kbot-1)*dp(i,j,kbot-1)) + qa(i,j,kbot-1) = qa(i,j,kbot-1) - dq/dp(i,j,kbot-1) + qa(i,j,kbot ) = qa(i,j,kbot ) + dq/dp(i,j,kbot ) + endif +! if qa is still < 0 + qa(i,j,kbot) = max(0., qa(i,j,kbot)) + enddo + enddo + + endif + + end subroutine neg_adj4 + subroutine neg_adj2(is, ie, js, je, ng, kbot, hydrostatic, & peln, delz, pt, dp, qv, ql, qr, qi, qs, qa, check_negative) diff --git a/model/fv_update_phys.F90 b/model/fv_update_phys.F90 index f9979f560..31d7649bb 100644 --- a/model/fv_update_phys.F90 +++ b/model/fv_update_phys.F90 @@ -223,6 +223,7 @@ subroutine fv_update_phys ( dt, is, ie, js, je, isd, ied, jsd, jed, ng, nq, integer i, j, k, m, n, nwat integer sphum, liq_wat, ice_wat, cld_amt ! GFDL AM physics integer rainwat, snowwat, graupel ! GFDL Cloud Microphysics + integer hailwat ! NSSL Cloud Microphysics integer w_diff ! w-tracer for PBL diffusion real:: qstar, dbk, rdg, zvir, p_fac, cv_air, gama_dt, tbad logical :: bad_range @@ -265,6 +266,7 @@ subroutine fv_update_phys ( dt, is, ie, js, je, isd, ied, jsd, jed, ng, nq, rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') cld_amt = get_tracer_index (MODEL_ATMOS, 'cld_amt') if ( .not. hydrostatic ) then @@ -324,7 +326,7 @@ subroutine fv_update_phys ( dt, is, ie, js, je, isd, ied, jsd, jed, ng, nq, !$OMP parallel do default(none) & !$OMP shared(is,ie,js,je,npz,flagstruct,pfull,q_dt,sphum,q,qdiag, & !$OMP nq,w_diff,dt,nwat,liq_wat,rainwat,ice_wat,snowwat, & -!$OMP graupel,delp,cld_amt,hydrostatic,pt,t_dt,delz,adj_vmr,& +!$OMP graupel,hailwat,delp,cld_amt,hydrostatic,pt,t_dt,delz,adj_vmr,& !$OMP gama_dt,cv_air,ua,u_dt,va,v_dt,isd,ied,jsd,jed, & #ifdef MULTI_GASES !$OMP nn, nm, & @@ -435,7 +437,7 @@ subroutine fv_update_phys ( dt, is, ie, js, je, isd, ied, jsd, jed, ng, nq, if ( hydrostatic ) then do j=js,je call moist_cp(is,ie,isd,ied,jsd,jed, npz, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, qc, cvm, pt(is:ie,j,k) ) + ice_wat, snowwat, graupel, hailwat, q, qc, cvm, pt(is:ie,j,k) ) do i=is,ie pt(i,j,k) = pt(i,j,k) + t_dt(i,j,k)*dt*con_cp/cvm(i) enddo @@ -445,7 +447,7 @@ subroutine fv_update_phys ( dt, is, ie, js, je, isd, ied, jsd, jed, ng, nq, ! Constant pressure do j=js,je call moist_cp(is,ie,isd,ied,jsd,jed, npz, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, qc, cvm, pt(is:ie,j,k) ) + ice_wat, snowwat, graupel, hailwat, q, qc, cvm, pt(is:ie,j,k) ) do i=is,ie delz(i,j,k) = delz(i,j,k) / pt(i,j,k) pt(i,j,k) = pt(i,j,k) + t_dt(i,j,k)*dt*con_cp/cvm(i) @@ -463,7 +465,7 @@ subroutine fv_update_phys ( dt, is, ie, js, je, isd, ied, jsd, jed, ng, nq, else do j=js,je call moist_cv(is,ie,isd,ied,jsd,jed, npz, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, qc, cvm, pt(is:ie,j,k)) + ice_wat, snowwat, graupel, hailwat, q, qc, cvm, pt(is:ie,j,k)) do i=is,ie pt(i,j,k) = pt(i,j,k) + t_dt(i,j,k)*dt*con_cp/cvm(i) enddo diff --git a/tools/external_ic.F90 b/tools/external_ic.F90 index 616175c8d..b4a0a6bee 100644 --- a/tools/external_ic.F90 +++ b/tools/external_ic.F90 @@ -4368,3 +4368,4 @@ end subroutine get_staggered_grid end module external_ic_mod + diff --git a/tools/fv_diagnostics.F90 b/tools/fv_diagnostics.F90 index 4d55eca27..58647a3e8 100644 --- a/tools/fv_diagnostics.F90 +++ b/tools/fv_diagnostics.F90 @@ -171,7 +171,7 @@ module fv_diagnostics_mod logical :: prt_minmax =.false. logical :: m_calendar integer sphum, liq_wat, ice_wat, cld_amt ! GFDL physics - integer rainwat, snowwat, graupel, o3mr + integer rainwat, snowwat, graupel, hailwat, o3mr integer :: istep, mp_top real :: ptop real, parameter :: rad2deg = 180./pi @@ -277,6 +277,7 @@ subroutine fv_diag_init(Atm, axes, Time, npx, npy, npz, p_ref) rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') o3mr = get_tracer_index (MODEL_ATMOS, 'o3mr') cld_amt = get_tracer_index (MODEL_ATMOS, 'cld_amt') @@ -1656,7 +1657,7 @@ subroutine fv_diag(Atm, zvir, Time, print_freq) call nh_total_energy(isc, iec, jsc, jec, isd, ied, jsd, jed, npz, & Atm(n)%w, Atm(n)%delz, Atm(n)%pt, Atm(n)%delp, & Atm(n)%q, Atm(n)%phis, Atm(n)%gridstruct%area, Atm(n)%domain, & - sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, Atm(n)%flagstruct%nwat, & + sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, hailwat, Atm(n)%flagstruct%nwat, & Atm(n)%ua, Atm(n)%va, Atm(n)%flagstruct%moist_phys, a2) #endif call prt_maxmin('UA_top', Atm(n)%ua(isc:iec,jsc:jec,1), & @@ -2688,6 +2689,17 @@ subroutine fv_diag(Atm, zvir, Time, print_freq) enddo enddo endif + if (hailwat > 0) then + do k=1,npz + do j=jsc,jec + do i=isc,iec + a2(i,j) = a2(i,j) + Atm(n)%delp(i,j,k) * & + Atm(n)%q(i,j,k,hailwat) + enddo + enddo + enddo + endif + used = send_data(id_iw, a2*ginv, Time) endif if ( id_lw>0 ) then @@ -2796,7 +2808,8 @@ subroutine fv_diag(Atm, zvir, Time, print_freq) endif ! Cloud top temperature & cloud top press: - if ( (id_ctt>0 .or. id_ctp>0 .or. id_ctz>0).and. Atm(n)%flagstruct%nwat==6) then + if ( (id_ctt>0 .or. id_ctp>0 .or. id_ctz>0) & + .and. (Atm(n)%flagstruct%nwat==6 .or. Atm(n)%flagstruct%nwat==7)) then allocate ( var1(isc:iec,jsc:jec) ) allocate ( var2(isc:iec,jsc:jec) ) !$OMP parallel do default(shared) private(tmp) @@ -2805,6 +2818,9 @@ subroutine fv_diag(Atm, zvir, Time, print_freq) do k=2,npz tmp = atm(n)%q(i,j,k,liq_wat)+atm(n)%q(i,j,k,rainwat)+atm(n)%q(i,j,k,ice_wat)+ & atm(n)%q(i,j,k,snowwat)+atm(n)%q(i,j,k,graupel) + IF ( Atm(n)%flagstruct%nwat==7) THEN + tmp = tmp + atm(n)%q(i,j,k,hailwat) + ENDIF if( tmp>5.e-6 ) then a2(i,j) = Atm(n)%pt(i,j,k) var1(i,j) = 0.01*Atm(n)%pe(i,k,j) @@ -2918,6 +2934,16 @@ subroutine fv_diag(Atm, zvir, Time, print_freq) enddo enddo endif + if (hailwat > 0) then +!$OMP parallel do default(shared) + do k=1,npz + do j=jsc,jec + do i=isc,iec + wk(i,j,k) = wk(i,j,k) + Atm(n)%q(i,j,k,hailwat)*Atm(n)%delp(i,j,k) + enddo + enddo + enddo + endif used = send_data(id_qp, wk, Time) endif @@ -2961,7 +2987,7 @@ subroutine fv_diag(Atm, zvir, Time, print_freq) do j=jsc,jec #ifdef USE_COND call moist_cv(isc,iec,isd,ied,jsd,jed,npz,j,k,Atm(n)%flagstruct%nwat,sphum,liq_wat,rainwat, & - ice_wat,snowwat,graupel,Atm(n)%q,Atm(n)%q_con(isc:iec,j,k),cvm) + ice_wat,snowwat,graupel,hailwat,Atm(n)%q,Atm(n)%q_con(isc:iec,j,k),cvm) do i=isc,iec a3(i,j,k) = Atm(n)%pt(i,j,k)*cvm(i)*wk(i,j,k) enddo @@ -4289,6 +4315,7 @@ subroutine prt_mass(km, nq, is, ie, js, je, n_g, nwat, ps, delp, q, area, domain rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') if ( nwat==0 ) then psmo = g_sum(domain, ps(is:ie,js:je), is, ie, js, je, n_g, area, 1) @@ -4314,6 +4341,8 @@ subroutine prt_mass(km, nq, is, ie, js, je, n_g, nwat, ps, delp, q, area, domain call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,snowwat), psq(is,js,snowwat)) if (graupel > 0) & call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,graupel), psq(is,js,graupel)) + if (hailwat > 0) & + call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,hailwat), psq(is,js,hailwat)) ! Mean water vapor in the "stratosphere" (75 mb and above): @@ -4357,6 +4386,9 @@ subroutine prt_mass(km, nq, is, ie, js, je, n_g, nwat, ps, delp, q, area, domain write(*,*) 'Total snow ', trim(gn), '=', qtot(snowwat)*ginv if (graupel > 0) & write(*,*) 'Total graupel ', trim(gn), '=', qtot(graupel)*ginv + if (hailwat > 0) & + write(*,*) 'Total hailwat ', trim(gn), '=', qtot(hailwat)*ginv + write(*,*) '---------------------------------------------' elseif ( nwat==2 ) then write(*,*) 'GFS condensate (kg/m^2)', trim(gn), '=', qtot(liq_wat)*ginv @@ -5684,13 +5716,13 @@ end subroutine eqv_pot subroutine nh_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, & w, delz, pt, delp, q, hs, area, domain, & sphum, liq_wat, rainwat, ice_wat, & - snowwat, graupel, nwat, ua, va, moist_phys, te) + snowwat, graupel, hailwat, nwat, ua, va, moist_phys, te) !------------------------------------------------------ ! Compute vertically integrated total energy per column !------------------------------------------------------ ! !INPUT PARAMETERS: integer, intent(in):: km, is, ie, js, je, isd, ied, jsd, jed - integer, intent(in):: nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel + integer, intent(in):: nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, hailwat real, intent(in), dimension(isd:ied,jsd:jed,km):: ua, va, pt, delp, w real, intent(in), dimension(is:ie,js:je,km) :: delz real, intent(in), dimension(isd:ied,jsd:jed,km,nwat):: q @@ -5714,7 +5746,7 @@ subroutine nh_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, & #ifdef MULTI_GASES !$OMP num_gas, & #endif -!$OMP w,q,pt,delp,delz,hs,cv_air,moist_phys,sphum,liq_wat,rainwat,ice_wat,snowwat,graupel) & +!$OMP w,q,pt,delp,delz,hs,cv_air,moist_phys,sphum,liq_wat,rainwat,ice_wat,snowwat,graupel,hailwat) & !$OMP private(phiz,cvm, qc) do j=js,je @@ -5732,7 +5764,7 @@ subroutine nh_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, & if ( moist_phys ) then do k=1,km call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, & - ice_wat, snowwat, graupel, q, qc, cvm) + ice_wat, snowwat, graupel, hailwat, q, qc, cvm) do i=is,ie te(i,j) = te(i,j) + delp(i,j,k)*( cvm(i)*pt(i,j,k) + hlv*q(i,j,k,sphum) + & 0.5*(phiz(i,k)+phiz(i,k+1)+ua(i,j,k)**2+va(i,j,k)**2+w(i,j,k)**2) ) From a55a2fa5cd0138ee3c519f0b76814f2df27b49c5 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Thu, 18 Mar 2021 15:20:11 -0500 Subject: [PATCH 02/13] Added print for hail max/min (non-debug section) --- model/fv_dynamics.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/model/fv_dynamics.F90 b/model/fv_dynamics.F90 index 56fce75b7..31d7ebd9b 100644 --- a/model/fv_dynamics.F90 +++ b/model/fv_dynamics.F90 @@ -768,6 +768,7 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, if (ice_wat > 0) call prt_mxm('ice_wat_dyn', q(isd,jsd,1,ice_wat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) if (snowwat > 0) call prt_mxm('snowwat_dyn', q(isd,jsd,1,snowwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) if (graupel > 0) call prt_mxm('graupel_dyn', q(isd,jsd,1,graupel), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + if (hailwat > 0) call prt_mxm('hailwat_dyn', q(isd,jsd,1,hailwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) endif #ifdef AVEC_TIMERS call avec_timer_stop(6) @@ -861,7 +862,7 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, call prt_mxm('ice_wat_dyn', q(isd,jsd,1,ice_wat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) call prt_mxm('snowwat_dyn', q(isd,jsd,1,snowwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) call prt_mxm('graupel_dyn', q(isd,jsd,1,graupel), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) - call prt_mxm('hailwat_dyn', q(isd,jsd,1,hailwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) + IF ( hailwat > 0 ) call prt_mxm('hailwat_dyn', q(isd,jsd,1,hailwat), is, ie, js, je, ng, npz, 1.,gridstruct%area_64, domain) endif endif From 67370793510738f5ca39f0d8a6eed1a7aac2c68c Mon Sep 17 00:00:00 2001 From: Larissa Reames <52886575+LarissaReames-NOAA@users.noreply.github.com> Date: Thu, 25 Mar 2021 11:03:13 -0500 Subject: [PATCH 03/13] Add hallwat to !OMP shared variables in main loop Addresses compile failure when OMP is turned on (e.g., on Hera) --- model/fv_dynamics.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/fv_dynamics.F90 b/model/fv_dynamics.F90 index 31d7ebd9b..61b9dceff 100644 --- a/model/fv_dynamics.F90 +++ b/model/fv_dynamics.F90 @@ -431,7 +431,7 @@ subroutine fv_dynamics(npx, npy, npz, nq_tot, ng, bdt, consv_te, fill, #else !$OMP parallel do default(none) shared(is,ie,js,je,isd,ied,jsd,jed,npz,dp1,zvir,q,q_con,sphum,liq_wat, & #endif -!$OMP rainwat,ice_wat,snowwat,graupel,pkz,flagstruct, & +!$OMP rainwat,ice_wat,snowwat,graupel,hailwat,pkz,flagstruct, & #ifdef MULTI_GASES !$OMP kapad, & #endif From 4537e0b7d26c1acff4f0d78a72069f467a4773cc Mon Sep 17 00:00:00 2001 From: LarissaReames-NOAA Date: Mon, 14 Jun 2021 15:07:32 +0000 Subject: [PATCH 04/13] Update to states as used in SFE2021 (Removed SFE code for now) --- driver/fvGFS/fv_nggps_diag.F90 | 293 +++++- model/fv_arrays.F90 | 4 + tools/module_diag_hailcast.F90 | 1637 ++++++++++++++++++++++++++++++++ 3 files changed, 1926 insertions(+), 8 deletions(-) create mode 100644 tools/module_diag_hailcast.F90 diff --git a/driver/fvGFS/fv_nggps_diag.F90 b/driver/fvGFS/fv_nggps_diag.F90 index 8e68b2e44..de117b2d2 100644 --- a/driver/fvGFS/fv_nggps_diag.F90 +++ b/driver/fvGFS/fv_nggps_diag.F90 @@ -62,7 +62,7 @@ module fv_nggps_diags_mod ! ! - use mpp_mod, only: mpp_pe, mpp_root_pe,FATAL,mpp_error + use mpp_mod, only: mpp_pe, mpp_root_pe,FATAL,mpp_error,NOTE, stdlog, input_nml_file use constants_mod, only: grav, rdgas use time_manager_mod, only: time_type, get_time use diag_manager_mod, only: register_diag_field, send_data @@ -99,11 +99,18 @@ module fv_nggps_diags_mod integer :: id_wmaxup,id_wmaxdn,kstt_wup, kend_wup,kstt_wdn,kend_wdn integer :: id_uhmax03,id_uhmin03,id_uhmax25,id_uhmin25,id_maxvort01 integer :: id_maxvorthy1,kstt_maxvorthy1,kstt_maxvort01,id_ustm + integer :: id_hailcast_dhail + integer :: id_hailcast_dhail1, id_hailcast_dhail2, id_hailcast_dhail3, id_hailcast_dhail4, id_hailcast_dhail5, id_hailcast_wdur, id_hailcast_wup_mask + integer :: id_hailcast_diam_mean, id_hailcast_diam_std integer :: kend_maxvorthy1,kend_maxvort01,id_vstm,id_srh01,id_srh03 integer :: kstt_uhmax03,kstt_uhmin03,kend_uhmax03,kend_uhmin03 integer :: kstt_uhmax25,kstt_uhmin25,kend_uhmax25,kend_uhmin25 integer :: kstt_ustm,kstt_vstm,kend_ustm,kend_vstm,kstt_srh01 integer :: kstt_srh03,kend_srh01,kend_srh03 + integer :: kstt_hc, kend_hc + integer :: kstt_hc1,kstt_hc2,kstt_hc3,kstt_hc4,kstt_hc5 + integer :: kend_hc1,kend_hc2,kend_hc3,kend_hc4,kend_hc5 + integer :: kstt_hcd, kend_hcd, kstt_hcm, kend_hcm integer :: id_maxvort02,kstt_maxvort02,kend_maxvort02 integer :: isco, ieco, jsco, jeco, npzo, ncnsto integer :: isdo, iedo, jsdo, jedo @@ -138,6 +145,12 @@ module fv_nggps_diags_mod real, dimension(:,:),allocatable :: up2,dn2,uhmax03,uhmin03 real, dimension(:,:),allocatable :: uhmax25,uhmin25,maxvort01 real, dimension(:,:),allocatable :: maxvorthy1,maxvort02 + + real, allocatable :: hailcast_dhail1(:,:), hailcast_dhail2(:,:), hailcast_dhail3(:,:), hailcast_dhail4(:,:), hailcast_dhail5(:,:) !hailstone diameters (mm) + real, allocatable :: hailcast_dhail1_max(:,:), hailcast_dhail2_max(:,:), hailcast_dhail3_max(:,:), hailcast_dhail4_max(:,:), hailcast_dhail5_max(:,:) !hailstone diameters (mm) + real, allocatable :: hailcast_diam_mean(:,:), hailcast_diam_std(:,:) !mean and standard deviation of five hailstones (mm) + real, allocatable :: hailcast_wdur(:,:), hailcast_wup_mask(:,:) !persistent arrays for updraft duration (s) and mask + public :: fv_nggps_diag_init, fv_nggps_diag, fv_nggps_tavg #ifdef use_WRTCOMP public :: fv_dyn_bundle_setup @@ -150,6 +163,32 @@ subroutine fv_nggps_diag_init(Atm, axes, Time) integer, intent(in) :: axes(4) type(time_type), intent(in) :: Time integer :: n, i, j, nz + logical :: do_hailcast = .true. !This controls whether hailcast is used + namelist /fv_diagnostics_nml/ do_hailcast + integer :: ios, ierr + integer :: unit + + !namelist file for hailcast +#ifdef INTERNAL_FILE_NML + ! Read Main namelist + read (input_nml_file,fv_diagnostics_nml,iostat=ios) + ierr = check_nml_error(ios,'fv_diagnostics_nml') +#else + f_unit=open_namelist_file() + rewind (f_unit) + ! Read Main namelist + read (f_unit,fv_diagnostics_nml,iostat=ios) + ierr = check_nml_error(ios,'fv_diagnostics_nml') + call close_file(f_unit) +#endif + + unit = stdlog() + write(unit, nml=fv_diagnostics_nml) + !end hailcast nml + + if (mpp_pe() == mpp_root_pe()) then + print*, 'do_hailcast = ', do_hailcast + end if n = 1 ncnsto = Atm(1)%ncnst @@ -415,7 +454,97 @@ subroutine fv_nggps_diag_init(Atm, axes, Time) enddo ! if(mpp_pe()==mpp_root_pe())print *,'in fv_dyn bundle,lat=',lat(isco,jsco),lat(ieco-2:ieco,jeco-2:jeco)*180./3.14157 endif + + endif + + !register hailcast arrays + if (do_hailcast) then + id_hailcast_dhail = register_diag_field ( trim(file_name), 'hailcast_dhail_max', axes(1:2), Time, & + 'hourly max hail diameter', 'mm', missing_value=missing_value ) + id_hailcast_dhail1 = register_diag_field ( trim(file_name), 'hailcast_dhail1_max', axes(1:2), Time, & + 'hourly max hail diameter (embryo 1)', 'mm', missing_value=missing_value ) + id_hailcast_dhail2 = register_diag_field ( trim(file_name), 'hailcast_dhail2_max', axes(1:2), Time, & + 'hourly max hail diameter (embryo 2)', 'mm', missing_value=missing_value ) + id_hailcast_dhail3 = register_diag_field ( trim(file_name), 'hailcast_dhail3_max', axes(1:2), Time, & + 'hourly max hail diameter (embryo 3)', 'mm', missing_value=missing_value ) + id_hailcast_dhail4 = register_diag_field ( trim(file_name), 'hailcast_dhail4_max', axes(1:2), Time, & + 'hourly max hail diameter (embryo 4)', 'mm', missing_value=missing_value ) + id_hailcast_dhail5 = register_diag_field ( trim(file_name), 'hailcast_dhail5_max', axes(1:2), Time, & + 'hourly max hail diameter (embryo 5)', 'mm', missing_value=missing_value ) + id_hailcast_diam_mean = register_diag_field ( trim(file_name), 'hailcast_diam_mean', axes(1:2), Time, & + 'mean hail diameter', 'mm', missing_value=missing_value ) + id_hailcast_diam_std = register_diag_field ( trim(file_name), 'hailcast_diam_std', axes(1:2), Time, & + 'standard deviation of hail diameter', 'mm', missing_value=missing_value ) + id_hailcast_wdur = register_diag_field ( trim(file_name), 'hailcast_wdur', axes(1:2), Time, & + 'updraft duration', 's', missing_value=missing_value ) + id_hailcast_wup_mask = register_diag_field ( trim(file_name), 'hailcast_wup_mask', axes(1:2), Time, & + 'updraft mask', '', missing_value=missing_value ) + + if (id_hailcast_dhail > 0) then + kstt_hc = nlevs+1; kend_hc = nlevs+1 + nlevs = nlevs + 1 + endif + + if (id_hailcast_dhail1 > 0) then + kstt_hc1 = nlevs+1; kend_hc1 = nlevs+1 + nlevs = nlevs + 1 + endif + if (id_hailcast_dhail2 > 0) then + kstt_hc2 = nlevs+1; kend_hc2 = nlevs+1 + nlevs = nlevs + 1 + endif + if (id_hailcast_dhail3 > 0) then + kstt_hc3 = nlevs+1; kend_hc3 = nlevs+1 + nlevs = nlevs + 1 + endif + if (id_hailcast_dhail4 > 0) then + kstt_hc4 = nlevs+1; kend_hc4 = nlevs+1 + nlevs = nlevs + 1 + endif + if (id_hailcast_dhail5 > 0) then + kstt_hc5 = nlevs+1; kend_hc5 = nlevs+1 + nlevs = nlevs + 1 + endif + if (id_hailcast_wdur > 0) then + kstt_hcd = nlevs+1; kend_hcd = nlevs+1 + nlevs = nlevs + 1 + endif + if (id_hailcast_wup_mask > 0) then + kstt_hcm = nlevs+1; kend_hcm = nlevs+1 + nlevs = nlevs + 1 + endif + + if (.not.allocated(hailcast_dhail1)) then + allocate(hailcast_dhail1(isco:ieco,jsco:jeco), & + hailcast_dhail2(isco:ieco,jsco:jeco), & + hailcast_dhail3(isco:ieco,jsco:jeco), & + hailcast_dhail4(isco:ieco,jsco:jeco), & + hailcast_dhail5(isco:ieco,jsco:jeco), & + hailcast_diam_mean(isco:ieco,jsco:jeco), & + hailcast_diam_std(isco:ieco,jsco:jeco)) + allocate ( hailcast_dhail1_max(isco:ieco,jsco:jeco) ) + allocate ( hailcast_dhail2_max(isco:ieco,jsco:jeco) ) + allocate ( hailcast_dhail3_max(isco:ieco,jsco:jeco) ) + allocate ( hailcast_dhail4_max(isco:ieco,jsco:jeco) ) + allocate ( hailcast_dhail5_max(isco:ieco,jsco:jeco) ) + + do i=isco,ieco + do j=jsco,jeco + hailcast_dhail1(i,j)=0; hailcast_dhail2(i,j)=0; hailcast_dhail3(i,j)=0; hailcast_dhail4(i,j)=0; hailcast_dhail5(i,j)=0 + hailcast_dhail1_max(i,j)=0; hailcast_dhail2_max(i,j)=0; hailcast_dhail3_max(i,j)=0; hailcast_dhail4_max(i,j)=0; hailcast_dhail5_max(i,j)=0 + enddo + enddo + endif + if (.not.allocated(hailcast_wdur)) then + allocate(hailcast_wdur(isdo:iedo,jsdo:jedo),hailcast_wup_mask(isdo:iedo,jsdo:jedo)) + do i=isdo,iedo + do j=jsdo,jedo + hailcast_wdur(i,j)=0;hailcast_wup_mask(i,j)=0 + enddo + enddo + endif endif + ! !------------------------------------ ! use wrte grid component for output @@ -435,8 +564,7 @@ subroutine fv_nggps_diag(Atm, zvir, Time) logical :: bad_range real :: ptop, allmax real, allocatable :: wk(:,:,:), wk2(:,:,:) - real, dimension(:,:),allocatable :: ustm,vstm,srh01,srh03 - + real, dimension(:,:),allocatable :: ustm,vstm,srh01,srh03,hailcast_dhail_max n = 1 ngc = Atm(n)%ng ptop = Atm(n)%ak(1) @@ -758,17 +886,17 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) kdtt=0 endif nsteps_per_reset = nint(avg_max_length/first_time) + if(mod(kdtt,nsteps_per_reset)==0)then do j=jsco,jeco do i=isco,ieco - if(mod(kdtt,nsteps_per_reset)==0)then up2(i,j) = -999. dn2(i,j) = 999. maxvorthy1(i,j)= 0. maxvort01(i,j)= 0. maxvort02(i,j)= 0. - endif enddo enddo + endif call get_vorticity(isco,ieco,jsco,jeco,isdo,iedo,jsdo,jedo, & npzo,Atm(n)%u,Atm(n)%v,vort, & Atm(n)%gridstruct%dx,Atm(n)%gridstruct%dy,& @@ -786,16 +914,16 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) vort,maxvort02,0., 2.e3) if( .not.Atm(n)%flagstruct%hydrostatic ) then call max_vv(isco,ieco,jsco,jeco,npzo,ngc,up2,dn2,Atm(n)%pe,Atm(n)%w) + if(mod(kdtt,nsteps_per_reset)==0)then do j=jsco,jeco do i=isco,ieco - if(mod(kdtt,nsteps_per_reset)==0)then uhmax03(i,j)= 0. uhmin03(i,j)= 0. uhmax25(i,j)= 0. uhmin25(i,j)= 0. - endif enddo enddo + endif call max_uh(isco,ieco,jsco,jeco,ngc,npzo,zvir, & sphum,uhmax03,uhmin03,Atm(n)%w,vort,Atm(n)%delz, & @@ -808,7 +936,6 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) Atm(n)%pt,Atm(n)%peln,Atm(n)%phis,grav, & 2.e3, 5.e3) endif - kdtt=kdtt+1 deallocate (vort) else print *,'Missing max/min hourly field in diag_table' @@ -818,6 +945,92 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) stop endif endif + + !allocate hailcast met field arrays + if (id_hailcast_dhail>0 .or. id_hailcast_dhail1>0 .or. id_hailcast_dhail2>0 .or. id_hailcast_dhail3>0 & + .or. id_hailcast_dhail4>0 .or. id_hailcast_dhail5>0 .or. id_hailcast_diam_mean>0 & + .or. id_hailcast_diam_std>0) then + + do j=jsco,jeco + do i=isco,ieco + if(mod(kdtt,nsteps_per_reset)==0)then + hailcast_dhail1_max(i,j) = 0. + hailcast_dhail2_max(i,j) = 0. + hailcast_dhail3_max(i,j) = 0. + hailcast_dhail4_max(i,j) = 0. + hailcast_dhail5_max(i,j) = 0. + endif + + hailcast_dhail1(i,j) = 0 + hailcast_dhail2(i,j) = 0 + hailcast_dhail3(i,j) = 0 + hailcast_dhail4(i,j) = 0 + hailcast_dhail5(i,j) = 0 + enddo + enddo + + + if (.not. allocated(rhoair_layer)) allocate(rhoair_layer(isco:ieco,jsco:jeco,1:npzo)) !layer 3-D air density + if (.not. allocated(z)) allocate(z(1:npzo+1)) !interace levels + if (.not. allocated(z_layer)) allocate(z_layer(isco:ieco,jsco:jeco,1:npzo)) !layer 3-D height ASL + if (.not. allocated(p_layer)) allocate(p_layer(isco:ieco,jsco:jeco,1:npzo)) !layer 3-D pressure + if (.not. allocated(zsfc)) allocate(zsfc(isco:ieco,jsco:jeco)) !terrain height + + do k=npzo,1,-1 + do j=jsco, jeco + if (Atm(n)%flagstruct%hydrostatic) then + call mpp_error(FATAL, 'HAILCAST can only be run with non-hydrostatic FV3') + !do i=is, ie + !rhoair(i,j,k) = Atm(n)%delp(i,j,k)/( ( Atm(n)%peln(i,k+1,j)- Atm(n)%peln(i,k,j)) & + ! * rdgas * Atm(n)%pt(i,j,k) * ( 1. + zvir*q(i,j,k,sphum))) + !enddo + else !non-hydrostatic + do i=isco, ieco + if (k==npzo) then + zsfc(i,j)=Atm(n)%phis(i,j) / grav + z(npzo+1)=zsfc(i,j) + endif + rhoair_layer(i,j,k) = -Atm(n)%delp(i,j,k)/(grav*Atm(n)%delz(i,j,k)) + !height of interfaces and layer height + z(k)=z(k+1)-Atm(n)%delz(i,j,k) + z_layer(i,j,k)=(z(k+1)+z(k))/2 + p_layer(i,j,k)=Atm(n)%delp(i,j,k)*(1.-sum(Atm(n)%q(i,j,k,2:Atm(n)%flagstruct%nwat)))/& + (-Atm(n)%delz(i,j,k)*grav)*rdgas*Atm(n)%pt(i,j,k)*(1.+zvir*Atm(n)%q(i,j,k,sphum)) + enddo + endif + enddo !j loop + enddo !k loop + + !call hailcast diagnostic driver once per time step and provide three-dimensional met fields + call hailcast_diagnostic_driver(Atm(n)%pt(isco:ieco,jsco:jeco,1:npzo), Atm(n)%w(isco:ieco,jsco:jeco,1:npzo), p_layer, z_layer, rhoair_layer, Atm(n)%q(isco:ieco,jsco:jeco,1:npzo,:), & !3D fields + Atm(n)%flagstruct%nwat, sphum,liq_wat,ice_wat,rainwat,snowwat,graupel, & !number of tracer indices, indices + isco,ieco,jsco,jeco,isdo,iedo,jsdo,jedo, & !grid dimensions data array (with halo) and physical grid dimensions + 1,npzo, zsfc, & !vertical dimensions, terrain height + first_time, Atm(n)%domain, & !call hailcast every model step and info for updating haloes + hailcast_dhail1,hailcast_dhail2,hailcast_dhail3,hailcast_dhail4,hailcast_dhail5, & !hailcast embryos sizes + hailcast_diam_mean, hailcast_diam_std, & !hailcast embryo mean/std + hailcast_wdur, hailcast_wup_mask) !persistent updraft duration and mask + + do j=jsco,jeco + do i=isco,ieco + hailcast_dhail1_max(i,j) = max(hailcast_dhail1_max(i,j), hailcast_dhail1(i,j)) + hailcast_dhail2_max(i,j) = max(hailcast_dhail2_max(i,j), hailcast_dhail2(i,j)) + hailcast_dhail3_max(i,j) = max(hailcast_dhail3_max(i,j), hailcast_dhail3(i,j)) + hailcast_dhail4_max(i,j) = max(hailcast_dhail4_max(i,j), hailcast_dhail4(i,j)) + hailcast_dhail5_max(i,j) = max(hailcast_dhail5_max(i,j), hailcast_dhail5(i,j)) + enddo + enddo + + + !deallocate hailcast met variables + deallocate(p_layer) + deallocate(z_layer) + deallocate(rhoair_layer) + deallocate(z) + deallocate(zsfc) + endif + + kdtt=kdtt+1 end subroutine fv_nggps_tavg ! subroutine store_data(id, work, Time, nstt, nend) @@ -1323,6 +1536,70 @@ subroutine fv_dyn_bundle_setup(axes, dyn_bundle, fcst_grid, quilting, rc) if(rc==0) num_field_dyn=num_field_dyn+1 endif + if( .not.hydrostatico .and. id_hailcast_dhail > 0 ) then + call find_outputname(trim(file_name),'hailcast_dhail_max',output_name) + if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter, output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter', 'mm', "time: point", & + axes(1:2), fcst_grid, kstt_hc,kend_hc, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + + if( .not.hydrostatico .and. id_hailcast_dhail1 > 0 ) then + call find_outputname(trim(file_name),'hailcast_dhail1_max',output_name) + if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 1), output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 1)', 'mm', "time: point", & + axes(1:2), fcst_grid, kstt_hc1,kend_hc1, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + + if( .not.hydrostatico .and. id_hailcast_dhail2 > 0 ) then + call find_outputname(trim(file_name),'hailcast_dhail2_max',output_name) + if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 2), output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 2)', 'mm', "time: point", & + axes(1:2), fcst_grid, kstt_hc2,kend_hc2, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + + if( .not.hydrostatico .and. id_hailcast_dhail3 > 0 ) then + call find_outputname(trim(file_name),'hailcast_dhail3_max',output_name) + if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 3), output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 3)', 'mm', "time: point", & + axes(1:2), fcst_grid, kstt_hc3,kend_hc3, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + + if( .not.hydrostatico .and. id_hailcast_dhail4 > 0 ) then + call find_outputname(trim(file_name),'hailcast_dhail4_max',output_name) + if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 4), output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 4)', 'mm', "time: point", & + axes(1:2), fcst_grid, kstt_hc4,kend_hc4, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + + if( .not.hydrostatico .and. id_hailcast_dhail5 > 0 ) then + call find_outputname(trim(file_name),'hailcast_dhail5_max',output_name) + if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 5), output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 5)', 'mm', "time: point", & + axes(1:2), fcst_grid, kstt_hc5,kend_hc5, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + + if( .not.hydrostatico .and. id_hailcast_wdur > 0 ) then + call find_outputname(trim(file_name),'hailcast_wdur',output_name) + if(mpp_pe()==mpp_root_pe())print *,'hailcast updraft duration, output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Hailcast updraft duration', 's', "time: point", & + axes(1:2), fcst_grid, kstt_hcd,kend_hcd, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + + if( .not.hydrostatico .and. id_hailcast_wup_mask > 0 ) then + call find_outputname(trim(file_name),'hailcast_wup_mask',output_name) + if(mpp_pe()==mpp_root_pe())print *,'hailcast updraft mask, output name=',trim(output_name) + call add_field_to_bundle(trim(output_name),'Hailcast updraft mask', '', "time: point", & + axes(1:2), fcst_grid, kstt_hcm,kend_hcm, dyn_bundle, output_file, rcd=rc) + if(rc==0) num_field_dyn=num_field_dyn+1 + endif + !jwtest: ! call ESMF_FieldBundleGet(dyn_bundle, fieldCount=fieldCount, rc=rc) ! print *,'in dyn_bundle_setup, fieldCount=',fieldCount diff --git a/model/fv_arrays.F90 b/model/fv_arrays.F90 index bf212fc29..4b27eaaf5 100644 --- a/model/fv_arrays.F90 +++ b/model/fv_arrays.F90 @@ -61,6 +61,10 @@ module fv_arrays_mod real :: efx(max_step), efx_sum, efx_nest(max_step), efx_sum_nest, mtq(max_step), mtq_sum integer :: steps + !for hailcast + integer :: id_hailcast_dhail1, id_hailcast_dhail2, id_hailcast_dhail3, id_hailcast_dhail4, id_hailcast_dhail5 + integer :: id_hailcast_diam_mean, id_hailcast_diam_std + end type fv_diag_type diff --git a/tools/module_diag_hailcast.F90 b/tools/module_diag_hailcast.F90 new file mode 100644 index 000000000..6eafe456a --- /dev/null +++ b/tools/module_diag_hailcast.F90 @@ -0,0 +1,1637 @@ +!Hailcase diagnostic driver +!John Henderson AER 20190425 +!time management handling from WRF is preserved but commented out + +!MODULE module_diag_hailcast +!CONTAINS +! SUBROUTINE diag_hailcast_stub +! END SUBROUTINE diag_hailcast_stub +!END MODULE module_diag_hailcast + +MODULE module_diag_hailcast + +CONTAINS + +! SUBROUTINE hailcast_diagnostic_driver ( grid , config_flags & +! , moist & +! , rho & +! , ids, ide, jds, jde, kds, kde & +! , ims, ime, jms, jme, kms, kme & +! , ips, ipe, jps, jpe, kps, kpe & +! , its, ite, jts, jte & +! , k_start, k_end & +! , dt, itimestep & +! , haildt,curr_secs & +! , haildtacttime ) + SUBROUTINE hailcast_diagnostic_driver ( t, w, p, z, rho, q, & ! 3D temperature, updraft, pressure, height, density and moisture tracers + moist_count,sphum,liq_wat,ice_wat,rainwat,snowwat,graupel, & ! tracer indices + is,ie,js,je,ishalo,iehalo,jshalo,jehalo, & ! i,j halo data array dimensions and physical grid dimensions (2 smaller on each end) + k_start, k_end, terr_z, & ! bottom and top z indices and terrain height + dt, domainid, & ! call frequency of hailcast = model time step = physics + hailcast_dhail1,hailcast_dhail2,hailcast_dhail3,hailcast_dhail4,hailcast_dhail5, hailcast_diam_mean, hailcast_diam_std, hailcast_wdur, hailcast_wup_mask) !hailcast persistent variables + +! USE module_domain, ONLY : domain , domain_clock_get +! USE module_configure, ONLY : grid_config_rec_type, model_config_rec +! USE module_state_description +! USE module_model_constants +! USE module_utility +! USE module_streams, ONLY: history_alarm, auxhist2_alarm +!#ifdef DM_PARALLEL +! USE module_dm, ONLY: wrf_dm_sum_real, wrf_dm_maxval +! #endif + + use constants_mod, only: grav, rdgas, rvgas, pi=>pi_8, radius, kappa, WTMAIR, WTMCO2, & + omega, hlv, cp_air, cp_vapor + use fms_mod, only: write_version_number + use fms_io_mod, only: set_domain, nullify_domain, write_version_number + use time_manager_mod, only: time_type, get_date, get_time + use mpp_domains_mod, only: domain2d, mpp_update_domains, DGRID_NE + use diag_manager_mod, only: diag_axis_init, register_diag_field, & + register_static_field, send_data, diag_grid_init + use fv_arrays_mod, only: fv_atmos_type, fv_grid_type, fv_diag_type, fv_grid_bounds_type, & + R_GRID + use tracer_manager_mod, only: get_tracer_names, get_number_tracers, get_tracer_index + use field_manager_mod, only: MODEL_ATMOS + use fv_mp_mod, only: mp_reduce_sum, mp_reduce_min, mp_reduce_max, is_master + use mpp_mod, only: mpp_error, FATAL, stdlog, mpp_pe, mpp_root_pe, mpp_sum, mpp_max, NOTE + use sat_vapor_pres_mod, only: compute_qs, lookup_es + + use fv_arrays_mod, only: max_step + + + IMPLICIT NONE + +! TYPE ( domain ), INTENT(INOUT) :: grid +! TYPE ( grid_config_rec_type ), INTENT(IN) :: config_flags +! type(fv_atmos_type), intent(inout) :: grid +!!!! type(time_type), intent(in) :: Time !will not compile + INTEGER:: ishalo, iehalo, jshalo, jehalo, k_start, k_end !dimensions of halo data array + INTEGER:: is, ie, js, je + +! INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde, & +! ims, ime, jms, jme, kms, kme, & +! ips, ipe, jps, jpe, kps, kpe + + logical :: master + INTEGER :: moist_count,sphum,rainwat,snowwat,graupel,liq_wat,ice_wat + + REAL, DIMENSION( is:ie, js:je, k_start: k_end, moist_count), & + INTENT(IN ) :: q !all 3D moisture fields + + REAL, DIMENSION( is:ie, js:je, k_start: k_end), & + INTENT(IN ) :: t, w, p, z, rho !3D non-moisture fields + + REAL, DIMENSION( is:ie, js:je), & + INTENT(IN ) :: terr_z + + REAL, DIMENSION( is:ie, js:je), & + INTENT(INOUT) :: hailcast_dhail1, hailcast_dhail2, & + hailcast_dhail3, hailcast_dhail4, & + hailcast_dhail5, & + hailcast_diam_mean, hailcast_diam_std + + REAL, DIMENSION( ishalo:iehalo, jshalo:jehalo), & + INTENT(INOUT) :: hailcast_wdur, hailcast_wup_mask + +! REAL, INTENT(IN ),OPTIONAL :: haildt +! REAL, INTENT(IN ),OPTIONAL :: curr_secs +! REAL, INTENT(INOUT),OPTIONAL :: haildtacttime +! INTEGER, INTENT(IN ) :: itimestep + REAL, INTENT(IN ) :: dt + TYPE(domain2d), INTENT(INOUT ) :: domainid + + + ! Local + ! ----- + CHARACTER*512 :: message + CHARACTER*256 :: timestr + INTEGER :: i,j,k, numlevs + REAL, DIMENSION( is:ie, js:je, k_start:k_end ) :: qr & + , qs & + , qg & + , qv & + , qc & + , qi & + , ptot + + REAL, DIMENSION( ishalo:iehalo, jshalo:jehalo) :: wdur_prev, wup_mask_prev + + REAL :: dhail1,dhail2,dhail3,dhail4,dhail5 + +! ! Timing +! ! ------ +! TYPE(WRFU_Time) :: hist_time, aux2_time, CurrTime, StartTime +! TYPE(WRFU_TimeInterval) :: dtint, histint, aux2int +! LOGICAL :: is_after_history_dump, is_output_timestep, is_first_timestep +! LOGICAL :: doing_adapt_dt, run_param, decided +! INTEGER :: stephail, itimestep_basezero + + +! ! Chirp the routine name for debugging purposes +! ! --------------------------------------------- +! write ( message, * ) 'inside hailcast_diagnostics_driver' +! CALL wrf_debug( 100 , message ) + +! ! Get timing info +! ! Want to know if when the last history output was +! ! Check history and auxhist2 alarms to check last ring time and how often +! ! they are set to ring +! ! ----------------------------------------------------------------------- +! CALL WRFU_ALARMGET( grid%alarms( HISTORY_ALARM ), prevringtime=hist_time, & +! ringinterval=histint) +! CALL WRFU_ALARMGET( grid%alarms( AUXHIST2_ALARM ), prevringtime=aux2_time, & +! ringinterval=aux2int) + +! ! Get domain clock +! ! ---------------- +! CALL domain_clock_get ( grid, current_time=CurrTime, & +! simulationStartTime=StartTime, & +! current_timestr=timestr, time_step=dtint ) + +! ! Set some booleans for use later +! ! Following uses an overloaded .lt. +! ! --------------------------------- +! is_after_history_dump = ( Currtime .lt. hist_time + dtint ) + +! ! Following uses an overloaded .ge. +! ! --------------------------------- +! is_output_timestep = (Currtime .ge. hist_time + histint - dtint .or. & +! Currtime .ge. aux2_time + aux2int - dtint ) +! write ( message, * ) 'is output timestep? ', is_output_timestep +! CALL wrf_debug( 100 , message ) + +! ! Following uses an overloaded .eq. +! ! --------------------------------- +! is_first_timestep = ( Currtime .eq. StartTime + dtint ) + + master = (mpp_pe()==mpp_root_pe()) .or. is_master() + + !FV3: No need to reset arrays to zero at dump time, thus no need to keep track of dump times + ! + ! After each history dump, reset max/min value arrays + ! ---------------------------------------------------------------------- +! IF ( is_after_history_dump ) THEN + !! DO j = jsc, jec !jts, jte + !! DO i = isc, iec !its, ite + !! hailcast_dhail1(i,j) = 0. + !! hailcast_dhail2(i,j) = 0. + !! hailcast_dhail3(i,j) = 0. + !!! hailcast_dhail4(i,j) = 0. + !! hailcast_dhail5(i,j) = 0. + !! ENDDO + !! ENDDO + !ENDIF ! is_after_history_dump + + ! We need to do some neighboring gridpoint comparisons for the updraft + ! duration calculations; set i,j start and end values so we don't go off + ! the edges of the domain. Updraft duration on domain edges will always be 0. + ! ---------------------------------------------------------------------- + +! !WRF config_flags contains: open_xs, specified, nested,open_xe,open_yx,open_ye,periodic_x +! IF ( config_flags%open_xs .OR. config_flags%specified .OR. & +! config_flags%nested) i_start = MAX( ids+1, its ) +! IF ( config_flags%open_xe .OR. config_flags%specified .OR. & +! config_flags%nested) i_end = MIN( ide-2, ite ) !-1 +! IF ( config_flags%open_ys .OR. config_flags%specified .OR. & +! config_flags%nested) j_start = MAX( jds+1, jts ) +! IF ( config_flags%open_ye .OR. config_flags%specified .OR. & +! config_flags%nested) j_end = MIN( jde-2, jte ) !-1 +! IF ( config_flags%periodic_x ) i_start = its +! IF ( config_flags%periodic_x ) i_end = ite + + + ! Make a copy of the updraft duration, mask variables + ! --------------------------------------------------- + !from WRF: + !!wdur_prev(:,:) = grid%hailcast_wdur(:,:) + !!wup_mask_prev(:,:) = grid%hailcast_wup_mask(:,:) + !DO j = MAX( jts-1 , jds ), MIN( jte+1 , jde-1 ) + ! DO i = MAX( its-1 , ids ), MIN( ite+1 , ide-1) + DO j = jshalo, jehalo + DO i = ishalo, iehalo + wdur_prev(i,j) = hailcast_wdur(i,j) + wup_mask_prev(i,j) = hailcast_wup_mask(i,j) + ENDDO + ENDDO + !update halo: + call mpp_update_domains(wup_mask_prev,domainid) + call mpp_update_domains(wdur_prev,domainid) + + ! Determine updraft mask (where updraft greater than some threshold) + ! --------------------------------------------------- + DO j = js, je + DO i = is, ie + hailcast_wup_mask(i,j) = 0 + hailcast_wdur(i,j) = 0 + + DO k = k_start, k_end + IF ( w(i,j,k) .ge. 10. ) THEN + hailcast_wup_mask(i,j) = 1 + ENDIF + ENDDO + ENDDO + ENDDO + + ! Determine updraft duration; make sure not to call point outside the domain + ! --------------------------------------------------- + DO j = js,je + DO i = is,ie + + ! Determine updraft duration using updraft masks + ! --------------------------------------------------- + IF ( (hailcast_wup_mask(i,j).eq.1) .OR. & + (MAXVAL(wup_mask_prev(i-1:i+1,j-1:j+1)).eq.1) ) THEN + hailcast_wdur(i,j) = MAXVAL(wdur_prev(i-1:i+1,j-1:j+1)) + dt + ENDIF + ENDDO + ENDDO + + !from WRF dealing with calling frequency and adaptive time step; call hailcast every timestep for FV3 + ! + ! Only run the scheme every "haildt" seconds as set in the namelist. + ! Code borrowed from module_pbl_driver, although here haildt is + ! in seconds, not minutes (bldt is in minutes). + ! --------------------------------------------------- + +! ! Are we using adaptive timestepping? +! doing_adapt_dt = .FALSE. +! IF ( (config_flags%use_adaptive_time_step) .and. & +! ( (.not. grid%nested) .or. & +! ( (grid%nested) .and. (abs(grid%dtbc) < 0.0001) ) ) )THEN +! doing_adapt_dt = .TRUE. +! IF ( haildtacttime .eq. 0. ) THEN +! haildtacttime = CURR_SECS + haildt +! END IF +! END IF + +! ! Calculate STEPHAIL +! stephail = NINT(haildt / dt) +! stephail = MAX(stephail,1) + +! ! itimestep starts at 1 - we want it to start at 0 so correctly +! ! divisibile by stephail. +! itimestep_basezero = itimestep -1 + + +! ! Do we run through this scheme or not? +! ! Test 1: If this is the initial model time, then yes. +! ! ITIMESTEP=1 +! ! Test 2: If the user asked for hailcast to be run every time step, then yes. +! ! HAILDT=0 or STEPHAIL=1 +! ! Test 3: If not adaptive dt, and this is on the requested hail frequency, +! ! then yes. +! ! MOD(ITIMESTEP,STEPHAIL)=0 +! ! Test 4: If using adaptive dt and the current time is past the last +! ! requested activate hailcast time, then yes. +! ! CURR_SECS >= HAILDTACTTIME + +! ! If we do run through the scheme, we set the flag run_param to TRUE and we set +! ! the decided flag to TRUE. The decided flag says that one of these tests was +! ! able to say "yes", run the scheme. We only proceed to other tests if the +! ! previous tests all have left decided as FALSE. If we set run_param to TRUE +! ! and this is adaptive time stepping, we set the time to the next hailcast run. + +! run_param = .FALSE. +! decided = .FALSE. +! IF ( ( .NOT. decided ) .AND. & +! ( itimestep_basezero .EQ. 0 ) ) THEN +! run_param = .TRUE. +! decided = .TRUE. +! END IF + +! IF ( PRESENT(haildt) )THEN +! IF ( ( .NOT. decided ) .AND. & +! ( ( haildt .EQ. 0. ) .OR. ( stephail .EQ. 1 ) ) ) THEN +! run_param = .TRUE. +! decided = .TRUE. +! END IF +! ELSE +! IF ( ( .NOT. decided ) .AND. & +! ( stephail .EQ. 1 ) ) THEN +! run_param = .TRUE. +! decided = .TRUE. +! END IF +! END IF + +! IF ( ( .NOT. decided ) .AND. & +! ( .NOT. doing_adapt_dt ) .AND. & +! ( MOD(itimestep_basezero,stephail) .EQ. 0 ) ) THEN +! run_param = .TRUE. +! decided = .TRUE. +! END IF + +! IF ( ( .NOT. decided ) .AND. & +! ( doing_adapt_dt ) .AND. & +! ( curr_secs .GE. haildtacttime ) ) THEN +! run_param = .TRUE. +! decided = .TRUE. +! haildtacttime = curr_secs + haildt +! END IF + +! write ( message, * ) 'timestep to run HAILCAST? ', run_param +! CALL wrf_debug( 100 , message ) + +! IF (run_param) THEN + + ! 3-D arrays for moisture variables + ! --------------------------------- + numlevs=k_end-k_start+1 + DO i=is, ie + DO k=1, numlevs + DO j=js, je + qv(i,j,k)=0;qr(i,j,k)=0;qs(i,j,k)=0;qg(i,j,k)=0;qc(i,j,k)=0;qi(i,j,k)=0 + qv(i,j,k) = q(i,j,k,sphum) + qr(i,j,k) = q(i,j,k,rainwat) + qs(i,j,k) = q(i,j,k,snowwat) + qg(i,j,k) = q(i,j,k,graupel) + qc(i,j,k) = q(i,j,k,liq_wat) + qi(i,j,k) = q(i,j,k,ice_wat) + ENDDO + ENDDO + ENDDO + + ! Hail diameter in millimeters (HAILCAST) + ! --------------------------------------------------- + DO j = js, je + DO i = is, ie + ! Only call hailstone driver if updraft has been + ! around longer than 15 min + ! ---------------------------------------------- + IF (hailcast_wdur(i,j) .gt. 900) THEN + dhail1=0;dhail2=0;dhail3=0;dhail4=0;dhail5=0 + CALL hailstone_driver (i,j, t(i,j,k_end:k_start:-1), & + z(i,j,k_end:k_start:-1), & + terr_z(i,j), & + p(i,j,k_end:k_start:-1), & + rho(i,j,k_end:k_start:-1), & + qv(i,j,k_end:k_start:-1), & + qi(i,j,k_end:k_start:-1), & + qc(i,j,k_end:k_start:-1), & + qr(i,j,k_end:k_start:-1), & + qs(i,j,k_end:k_start:-1), & + qg(i,j,k_end:k_start:-1), & + w(i,j,k_end:k_start:-1), & + hailcast_wdur(i,j), & + numlevs, & + dhail1, dhail2, & + dhail3, dhail4, & + dhail5 ) + + !diag_table should select largest value of these variables during requested period + !thus do not need to accumulate largest value between data dumps + !IF (dhail1 .gt. hailcast_dhail1(i,j)) THEN + hailcast_dhail1(i,j) = dhail1 + !ENDIF + !IF (dhail2 .gt. hailcast_dhail2(i,j)) THEN + hailcast_dhail2(i,j) = dhail2 + !ENDIF + !IF (dhail3 .gt. hailcast_dhail3(i,j)) THEN + hailcast_dhail3(i,j) = dhail3 + !ENDIF + !IF (dhail4 .gt. hailcast_dhail4(i,j)) THEN + hailcast_dhail4(i,j) = dhail4 + !ENDIF + !IF (dhail5 .gt. hailcast_dhail5(i,j)) THEN + hailcast_dhail5(i,j) = dhail5 + !ENDIF + ENDIF + ENDDO + ENDDO + + ! Calculate the mean and standard deviation of the hail diameter + ! distribution over different embryo sizes + ! ---------------------------------------- + DO j = js, je + DO i = is, ie + !mean + hailcast_diam_mean(i,j)=(hailcast_dhail1(i,j)+& + hailcast_dhail2(i,j) +hailcast_dhail3(i,j)+& + hailcast_dhail4(i,j) +hailcast_dhail5(i,j))/5. + !max + !hailcast_diam_max(i,j)=MAX(hailcast_dhail1(i,j),& + ! hailcast_dhail2(i,j), hailcast_dhail3(i,j),& + ! hailcast_dhail4(i,j), hailcast_dhail5(i,j)) + !sample standard deviation + hailcast_diam_std(i,j) = SQRT( ( & + (hailcast_dhail1(i,j)-hailcast_diam_mean(i,j))**2.+& + (hailcast_dhail2(i,j)-hailcast_diam_mean(i,j))**2.+& + (hailcast_dhail3(i,j)-hailcast_diam_mean(i,j))**2.+& + (hailcast_dhail4(i,j)-hailcast_diam_mean(i,j))**2.+& + (hailcast_dhail5(i,j)-hailcast_diam_mean(i,j))**2.)& + / 4.0) + ENDDO + ENDDO + if (hailcast_diam_mean(i,j).ne.0.0 .and. hailcast_diam_std(i,j).ne.0.0) print*,'jmh mean std=',i,j,hailcast_diam_mean(i,j),hailcast_diam_std(i,j) + !END IF + +END SUBROUTINE hailcast_diagnostic_driver + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!! +!!!! Hailstone driver, adapted from hailstone subroutine in HAILCAST +!!!! Inputs: +!!!! 1-d (nz) +!!!! TCA temperature (K) +!!!! h1d height above sea level (m) +!!!! PA total pressure (Pa) +!!!! rho1d density (kg/m3) +!!!! RA vapor mixing ratio (kg/kg) +!!!! qi1d cloud ice mixing ratio (kg/kg) +!!!! qc1d cloud water mixing ratio (kg/kg) +!!!! qr1d rain water mixing ratio (kg/kg) +!!!! qg1d graupel mixing ratio (kg/kg) +!!!! qs1d snow mixing ratio (kg/kg) +!!!! VUU updraft speed at each level (m/s) +!!!! Float +!!!! ht terrain height (m) +!!!! wdur duration of any updraft > 10 m/s within 1 surrounding +!!!! gridpoint +!!!! Integer +!!!! nz number of vertical levels +!!!! +!!!! Output: +!!!! dhail hail diameter in mm +!!!! 1st-5th rank-ordered hail diameters returned +!!!! +!!!! 13 Aug 2013 .................................Becky Adams-Selin AER +!!!! adapted from hailstone subroutine in SPC's HAILCAST +!!!! 18 Mar 2014 .................................Becky Adams-Selin AER +!!!! added variable rime layer density, per Ziegler et al. (1983) +!!!! 4 Jun 2014 ..................................Becky Adams-Selin AER +!!!! removed initial embryo size dependency on microphysics scheme +!!!! 5 Jun 2014 ..................................Becky Adams-Selin AER +!!!! used smaller initial embryo sizes +!!!! 25 Jun 2015..................................Becky Adams-Selin AER +!!!! Significant revamping. Fixed units bug in HEATBUD that caused +!!!! hailstone temperature instabilities. Similar issue fixed in BREAKUP +!!!! subroutine. Removed graupel from ice content. Changed initial +!!!! embryo size and location to better match literature. Added +!!!! enhanced melting when hailstone collides with liquid water +!!!! in regions above freezing. Final diameter returned is ice diameter +!!!! only. Added hailstone temperature averaging over previous timesteps +!!!! to decrease initial temperature instability at small embyro diameters. +!!!! 3 Sep 2015...................................Becky Adams-Selin AER +!!!! Insert embryos at -13C; interpret pressure and other variables to +!!!! that exact temperature level. +!!!! 16 Nov 2015...................................Becky Adams-Selin AER +!!!! Hailstone travels horizontally through updraft instead of being +!!!! locked in the center. +!!!! 9 Jul 2016...................................Becky Adams-Selin AER +!!!! Uses an adiabatic liquid cloud water profile generated from +!!!! the saturation vapor pressure using the model temperature +!!!! profile. +!!!! 04 Feb 2017...................................Becky Adams-Selin AER +!!!! Added adaptive time-stepping option. +!!!! ***Don't set any higher than 60 seconds*** +!!!! 06 May 2017...................................Becky Adams-Selin AER +!!!! Bug fixes for some memory issues in the adiabatic liquid +!!!! water profile code. +!!!! +!!!! See Adams-Selin and Ziegler 2016, MWR for further documentation. +!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + SUBROUTINE hailstone_driver ( ii,jj,TCA, h1d, ht, PA, rho1d,& + RA, qi1d,qc1d,qr1d,qs1d,qg1d, & + VUU, wdur, & + nz,dhail1,dhail2,dhail3,dhail4, & + dhail5 ) + IMPLICIT NONE + INTEGER, INTENT(IN ) :: nz, ii,jj + + REAL, DIMENSION( nz ), & + INTENT(IN ) :: TCA & ! temperature (K) + , rho1d & + , h1d & + , PA & ! pressure (Pa) + , RA & ! vapor mixing ratio (kg/kg) + , VUU & ! updraft speed (m/s) + , qi1d,qc1d,qr1d & + , qs1d,qg1d + + REAL, INTENT(IN ) :: ht & + , wdur + + !Output: 1st-5th rank-ordered hail diameters returned + REAL, INTENT(INOUT) :: dhail1 & ! hail diameter (mm); + , dhail2 & + , dhail3 & + , dhail4 & + , dhail5 + !Local variables + REAL ZBAS, TBAS, WBASP ! height, temp, pressure of cloud base + REAL RBAS ! mix ratio of cloud base + REAL cwitot ! total cloud water, ice mix ratio + INTEGER KBAS ! k of cloud base + REAL tk_embryo ! temperature at which initial embryo is inserted + REAL ZFZL, TFZL, WFZLP ! height, temp, pressure of embryo start point + REAL RFZL ! mix ratio of embryo start point + REAL VUFZL, DENSAFZL ! updraft speed, density of embryo start point + INTEGER KFZL ! k of embryo start point + INTEGER nofroze ! keeps track if hailstone has ever been frozen + INTEGER CLOUDON ! use to zero out cloud water, ice once past updraft duration + REAL RTIME ! real updraft duration (sec) + REAL TAU, TAU_1, TAU_2 ! upper time limit of simulation (sec) + REAL delTAU ! difference between TAU_2 and TAU_1 (sec) + REAL g ! gravity (m/s) + REAL r_d ! constant + !hailstone parameters + REAL*8 DD, D, D_ICE ! hail diameter (m) + REAL VT ! terminal velocity (m/s) + REAL V ! actual stone velocity (m/s) + REAL TS ! hailstone temperature (K) + !HAILSTONE temperature differencing + REAL TSm1, TSm2 ! hailstone temperature at previous 3 timesteps + REAL FW ! fraction of stone that is liquid + REAL WATER ! mass of stone that is liquid + REAL CRIT ! critical water mass allowed on stone surface + REAL DENSE ! hailstone density (kg/m3) + INTEGER ITYPE ! wet (2) or dry (1) growth regime + !1-d column arrays of updraft parameters + REAL, DIMENSION( nz ) :: & + RIA, & ! frozen content mix ratio (kg/kg) + RWA, & ! liquid content mix ratio (kg/kg) + VUU_pert ! perturbed updraft profile (m/s) + !1-d column arrays of updraft characteristics for adiabatic water profile + REAL, DIMENSION( nz ) :: & + RWA_adiabat, & ! adiabatic liquid content mixing ratio (kg/kg) + RWA_new, & + ESVA, & ! saturation vapor pressure + RSA ! saturation mixing ratio + !in-cloud updraft parameters at location of hailstone + REAL P ! in-cloud pressure (Pa) + REAL RS ! in-cloud saturation mixing ratio + REAL RI, RW ! ice, liquid water mix. ratio (kg/kg) + REAL XI, XW ! ice, liquid water content (kg/m3 air) + REAL PC ! in-cloud fraction of frozen water + REAL TC ! in-cloud temperature (K) + REAL VU ! in-cloud updraft speed (m/s) + REAL VUMAX ! in-cloud updraft speed read from WRF (max allowed) + REAL VUCORE ! perturbed in-cloud updraft speed + REAL DENSA ! in-cloud updraft density (kg/m3) + REAL Z ! height of hailstone (m) + REAL DELRW ! diff in sat vap. dens. between hail and air (kg/m3) + REAL, DIMENSION(5) :: dhails !hail diameters from 5 different embryo size + !mean sub-cloud layer variables + REAL TLAYER,RLAYER,PLAYER ! mean sub-cloud temp, mix ratio, pres + REAL TSUM,RSUM,PSUM ! sub-cloud layer T, R, P sums + REAL LDEPTH ! layer depth + !internal function variables + REAL GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DGMV,DI,ANU,RE,AE + REAL dum, icefactor, adiabatic_factor + + REAL sec, secdel ! time step, increment in seconds + INTEGER i, j, k, IFOUT, ind(1) + CHARACTER*256 :: message + + secdel = 5.0 + g=9.81 + r_d = 287. + + !!!!!!!!!!!!!!!! 1. UPDRAFT PROPERTIES !!!!!!!!!!!!!!!!!!!!!!! + !!! DEFINE UPDRAFT PROPERTIES !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! Upper limit of simulation in seconds + TAU = 7200. !simulation ends + + !Set initial updraft strength - you could reduce to simulate the embryo + ! hovering around the edges of the updraft, as in Heymsfield and Musil (1982) + DO i=1,nz + VUU_pert(i) = VUU(i) * 1. + ENDDO + + +! Initialize diameters to 0. + DO i=1,5 + dhails(i) = 0. + ENDDO + +! Cap updraft lifetime at 2000 sec. + IF (wdur .GT. 2000) THEN + RTIME = 2000. + ELSE + RTIME = wdur + ENDIF + + + !!!!!!!!!!!!!!!! 2. INITIAL EMBRYO !!!!!!!!!!!!!!!!!!!!!!!!!!! + !!! FIND PROPERTIES OF INITIAL EMBRYO LOCATION !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !Find the cloud base for end-of-algorithm purposes. + KBAS=nz + !KFZL=nz + DO k=1,nz + cwitot = qi1d(k) + qc1d(k) + !No longer include graupel in in-cloud ice amounts + !RIA(k) = qi1d(k) + qs1d(k) + qg1d(k) + RIA(k) = qi1d(k) + qs1d(k) + !RWA(k) = qc1d(k) + qr1d(k) + RWA(k) = qc1d(k) + !IF ((RIA(k) .ge. 0.0001) .and. (TCA(k).lt.260.155) .and. & + ! (k .lt. KFZL)) THEN + ! KFZL = k + !ENDIF + IF ((cwitot .ge. 1.E-12) .and. (k .lt. KBAS)) THEN + KBAS = k + ENDIF + ENDDO + !QC - our embryo can't start below the cloud base. + !IF (KFZL .lt. KBAS) THEN + ! KFZL = KBAS + !ENDIF + + !Pull heights, etc. of these levels out of 1-d arrays. + ZBAS = h1d(KBAS) + TBAS = TCA(KBAS) + WBASP = PA(KBAS) + RBAS = RA(KBAS) + + !At coarser resolutions WRF underestimates liquid water aloft. + !A fairer estimate is of the adiabatic liquid water profile, or + !the difference between the saturation mixing ratio at each level + !and the cloud base water vapor mixing ratio + DO k=1,nz + RWA_new(k) = RWA(k) + IF (k.LT.KBAS) THEN + RWA_adiabat(k) = 0. + CYCLE + ENDIF + !saturation vapor pressure + !ESVA(k) = 6.112*exp((2.453E6/461)*(1./273. - 1./TCA(k))) !hPa + ESVA(k) = 611.2*exp(17.67*(TCA(k)-273.155)/(TCA(k)-29.655)) !Pa + !saturation vapor mixing ratio + RSA(k) = 0.62197 * ESVA(k) / (PA(k) - ESVA(k)) + !Up above -31, start converting to ice, entirely by -38 + !(Rosenfeld and Woodley 2000) + IF (TCA(k).gt.242.155) THEN + icefactor = 1. + ELSE IF ((TCA(k).LE.242.155).AND.(TCA(k).GT.235.155)) THEN + icefactor = (1-(242.155-TCA(k))/5.) + ELSE + icefactor = 0. + ENDIF + !Don't want any negative liquid water values + IF (RBAS.GT.RSA(k)) THEN + RWA_adiabat(k) = (RBAS - RSA(k))*icefactor + ELSE + RWA_adiabat(k) = RWA(k) + ENDIF + !Remove cloud liquid water outputted at previous lower levels + ! -- bug fix 170506 -- ! + IF (k.eq.KBAS) THEN + RWA_new(k) = RWA_adiabat(k) + ELSE IF ((k.ge.KBAS+1).AND.(RWA_adiabat(k).ge.1.E-12)) THEN + RWA_new(k) = RWA_adiabat(k)*(h1d(k)-h1d(k-1)) - RWA_new(k-1) + IF (RWA_new(k).LT.0) RWA_new(k) = 0. + ENDIF + ! - old code - ! + !IF (k.eq.KBAS+1) THEN + ! RWA_new(k) = RWA_adiabat(k)*(h1d(k)-h1d(k-1)) + !ELSE IF ((k.ge.KBAS+2).AND.(RWA_adiabat(k).ge.1.E-12)) THEN + ! RWA_new(k) = RWA_adiabat(k)*(h1d(k)-h1d(k-1)) - RWA_new(k-1) + ! IF (RWA_new(k).LT.0) RWA_new(k) = 0. + !ENDIF + ENDDO + !remove the height factor from RWA_new + DO k=KBAS,nz + RWA_new(k) = RWA_new(k) / (h1d(k)-h1d(k-1)) + ENDDO + + + + !!!!!!!!!!!!!!!! 3. INITIAL EMBRYO SIZE !!!!!!!!!!!!!!!!!!!!! + !!! SET CONSTANT RANGE OF INITIAL EMBRYO SIZES !!! + !!! START LOOP !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! See Adams-Selin and Ziegler 2016 MWR for explanation of why + ! these sizes were picked. + !Run each initial embryo size perturbation + DO i=1,5 + SELECT CASE (i) + CASE (1) + !Initial hail embryo diameter in m, at cloud base + DD = 5.E-3 + tk_embryo = 265.155 !-8C + CASE (2) + DD = 7.5E-3 + tk_embryo = 265.155 !-8C + CASE (3) + DD = 5.E-3 + tk_embryo = 260.155 !-13C + CASE (4) + DD = 7.5E-3 + tk_embryo = 260.155 !-13C + CASE (5) + tk_embryo = 260.155 !-13C + DD = 1.E-2 + END SELECT + + + RTIME = 2000. + IF (wdur .LT. RTIME) RTIME = wdur + + TFZL = tk_embryo + CALL INTERPP(PA, WFZLP, TCA, tk_embryo, IFOUT, nz) + CALL INTERP(h1d, ZFZL, WFZLP, IFOUT, PA, nz) + CALL INTERP(RA, RFZL, WFZLP, IFOUT, PA, nz) + CALL INTERP(VUU_pert, VUFZL, WFZLP, IFOUT, PA, nz) + CALL INTERP(rho1d, DENSAFZL, WFZLP, IFOUT, PA, nz) + + !Begin hail simulation time (seconds) + sec = 0. + + + !!!!!!!!!!!!!!!!!! 4. INITIAL PARAMETERS !!!!!!!!!!!!!!!!! + !!! PUT INITIAL PARAMETERS IN VARIABLES !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !Set initial values for parameters at freezing level + P = WFZLP + RS = RFZL + TC = TFZL + VU = VUFZL + Z = ZFZL - ht + LDEPTH = Z + DENSA = DENSAFZL + + !Set initial hailstone parameters + nofroze=1 !Set test for embryo: 0 for never been frozen; 1 frozen + TS = TC + TSm1 = TS + TSm2 = TS + D = DD !hailstone diameter in m + FW = 0.0 + DENSE = 500. !kg/m3 + ITYPE=1. !Assume starts in dry growth. + CLOUDON=1 !we'll eventually turn cloud "off" once updraft past time limit + + !Start time loop. + DO WHILE (sec .lt. TAU) + sec = sec + secdel + + !!!!!!!!!!!!!!!!!! 5. CALCULATE PARAMETERS !!!!!!!!!!!!!!!!! + !!! CALCULATE UPDRAFT PROPERTIES !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !Intepolate vertical velocity to our new pressure level + CALL INTERP(VUU_pert,VUMAX,P,IFOUT,PA,nz) + !print *, 'INTERP VU: ', VU, P + + !Outside pressure levels? If so, exit loop + IF (IFOUT.EQ.1) GOTO 100 + + !Sine wave multiplier on updraft strength + IF (SEC .GT. 0.0 .AND. SEC .LT. RTIME) THEN + VUCORE = VUMAX * (0.5*SIN((3.14159*SEC)/(RTIME))+0.5)*1.2 + VU = VUCORE + ELSEIF (SEC .GE. RTIME) THEN + VU = 0.0 + CLOUDON = 0 + ENDIF + + !Calculate terminal velocity of the hailstone + ! (use previous values) + CALL TERMINL(DENSA,DENSE,D,VT,TC) + + !Actual velocity of hailstone (upwards positive) + V = VU - VT + + !Use hydrostatic eq'n to calc height of next level + P = P - DENSA*g*V*secdel + Z = Z + V*secdel + + !Interpolate cloud temp, qvapor at new p-level + CALL INTERP(TCA,TC,P,IFOUT,PA,nz) + CALL INTERP(RA,RS,P,IFOUT,PA,nz) + + !New density of in-cloud air + DENSA=P/(r_d*(1.+0.609*RS/(1.+RS))*TC) + + !Interpolate liquid, frozen water mix ratio at new level + CALL INTERP(RIA,RI,P,IFOUT,PA,nz) + CALL INTERP(RWA_new,RW,P,IFOUT,PA,nz) + XI = RI * DENSA * CLOUDON + XW = RW * DENSA * CLOUDON + IF( (XW+XI).GT.0) THEN + PC = XI / (XW+XI) + ELSE + PC = 1. + ENDIF + + + ! SATURATION VAPOUR DENSITY DIFFERENCE BETWTEEN STONE AND CLOUD + CALL VAPORCLOSE(DELRW,PC,TS,TC,ITYPE) + + + !!!!!!!!!!!!!!!!!! 6. STONE'S MASS GROWTH !!!!!!!!!!!!!!!!!!!! + CALL MASSAGR(D,GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DGMV,DI,ANU,RE,AE,& + TC,TS,P,DENSE,DENSA,FW,VT,XW,XI,secdel,ITYPE,DELRW) + + + !!!!!!!!!!!!!!!!!! 7. HEAT BUDGET OF HAILSTONE !!!!!!!!!!!!!!! + CALL HEATBUD(TS,TSm1,TSm2,FW,TC,VT,DELRW,D,DENSA,GM1,GM,DGM,DGMW, & + DGMV,DGMI,GMW,GMI,DI,ANU,RE,AE,secdel,ITYPE,P) + + + !!!!! 8. TEST DIAMETER OF STONE AND HEIGHT ABOVE GROUND !!!!!!! + !!! TEST IF DIAMETER OF STONE IS GREATER THAN CRITICAL LIMIT, IF SO + !!! BREAK UP + WATER=FW*GM !KG + ! CRTICAL MASS CAPABLE OF BEING "SUPPORTED" ON THE STONE'S SURFACE + CRIT = 2.0E-4 + IF (WATER.GT.CRIT)THEN + CALL BREAKUP(DENSE,D,GM,FW,CRIT) + ENDIF + + !!! Has stone reached below cloud base? + !IF (Z .LE. 0) GOTO 200 + IF (Z .LE. ZBAS) then + GOTO 200 + endif + + !calculate ice-only diameter size + D_ICE = ( (6*GM*(1.-FW)) / (3.141592654*DENSE) )**0.33333333 + + !Has the stone entirely melted and it's below the freezing level? + IF ((D_ICE .LT. 1.E-8) .AND. (TC.GT.273.155)) GOTO 300 + + !move values to previous timestep value + TSm1 = TS + TSm2 = TSm1 + + ENDDO !end cloud lifetime loop + +100 CONTINUE !outside pressure levels in model +200 CONTINUE !stone reached surface +300 CONTINUE !stone has entirely melted and is below freezing level + + !!!!!!!!!!!!!!!!!! 9. MELT STONE BELOW CLOUD !!!!!!!!!!!!!!!!!!!! + !Did the stone shoot out the top of the storm? + !Then let's assume it's lost in the murky "outside storm" world. + IF (P.lt.PA(nz)) THEN + D=0.0 + !Is the stone entirely water? Then set D=0 and exit. + ELSE IF(ABS(FW - 1.0).LT.0.001) THEN + D=0.0 + ELSE IF (Z.GT.0) THEN + !If still frozen, then use melt routine to melt below cloud + ! based on mean below-cloud conditions. + + !Calculate mean sub-cloud layer conditions + TSUM = 0. + RSUM = 0. + PSUM = 0. + DO k=1,KBAS + TSUM = TSUM + TCA(k) + PSUM = PSUM + PA(k) + RSUM = RSUM + RA(k) + ENDDO + TLAYER = TSUM / KBAS + PLAYER = PSUM / KBAS + RLAYER = RSUM / KBAS + + !MELT is expecting a hailstone of only ice. At the surface + !we're only interested in the actual ice diameter of the hailstone, + !so let's shed any excess water now. + D_ICE = ( (6*GM*(1.-FW)) / (3.141592654*DENSE) )**0.33333333 + D = D_ICE + CALL MELT(D,TLAYER,PLAYER,RLAYER,LDEPTH,VT) + + ENDIF !end check for melting call + + !Check to make sure embryo didn’t just immediately fall out + IF (sec .LT. 60) D=0.0 + + !Check to make sure something hasn't gone horribly wrong + IF (D.GT.0.254) D = 0. !just consider missing for now if > 10 in + + !assign hail size in mm for output + !dhails(i) = D * 1000 + dhails(i) = D + + ENDDO !end embryo size loop + + + dhail1 = dhails(1) + dhail2 = dhails(2) + dhail3 = dhails(3) + dhail4 = dhails(4) + dhail5 = dhails(5) + + !Testing diagnostics that can be commented out, but please keep + if (0.eq.1) then + print*,'jmh KBAS,ZBAS,TBAS',ii,jj,KBAS,ZBAS,TBAS + print*,'jmh WBASP,RBAS=',ii,jj,WBASP,RBAS + print*,'jmh embryo sizes: ',ii,jj,dhail1,dhail2,dhail3,dhail4,dhail5 + if (ii.eq. 847 .and. jj.eq.394) then + print*,'jmh i=847,j=394 TCA:',ii,jj,TCA(1:nz) + print*,'jmh i=847,j=394 h1d:',ii,jj,h1d(1:nz) + print*,'jmh i=847,j=394 ht:',ii,jj,ht + print*,'jmh i=847,j=394 PA:',ii,jj,PA(1:nz) + print*,'jmh i=847,j=394 rho1d:',ii,jj,rho1d(1:nz) + print*,'jmh i=847,j=394 RA:',ii,jj,RA(1:nz) + print*,'jmh i=847,j=394 qi1d:',ii,jj,qi1d(1:nz) + print*,'jmh i=847,j=394 qc1d:',ii,jj,qc1d(1:nz) + print*,'jmh i=847,j=394 qr1d:',ii,jj,qr1d(1:nz) + print*,'jmh i=847,j=394 qs1d:',ii,jj,qs1d(1:nz) + print*,'jmh i=847,j=394 qg1d:',ii,jj,qg1d(1:nz) + print*,'jmh i=847,j=394 VUU:',ii,jj,VUU(1:nz) + print*,'jmh i=847,j=394 wdur:',ii,jj,wdur + print*,'jmh i=847,j=394 nz:',ii,jj,nz + endif + if (KBAS .gt. 30) then + print*,'jmh KBAS>30 TCA:',ii,jj,TCA(1:nz) + print*,'jmh KBAS>30 h1d:',ii,jj,h1d(1:nz) + print*,'jmh KBAS>30 ht:',ii,jj,ht + print*,'jmh KBAS>30 PA:',ii,jj,PA(1:nz) + print*,'jmh KBAS>30 rho1d:',ii,jj,rho1d(1:nz) + print*,'jmh KBAS>30 RA:',ii,jj,RA(1:nz) + print*,'jmh KBAS>30 qi1d:',ii,jj,qi1d(1:nz) + print*,'jmh KBAS>30 qc1d:',ii,jj,qc1d(1:nz) + print*,'jmh KBAS>30 qr1d:',ii,jj,qr1d(1:nz) + print*,'jmh KBAS>30 qs1d:',ii,jj,qs1d(1:nz) + print*,'jmh KBAS>30 qg1d:',ii,jj,qg1d(1:nz) + print*,'jmh KBAS>30 VUU:',ii,jj,VUU(1:nz) + print*,'jmh KBAS>30 wdur:',ii,jj,wdur + print*,'jmh KBAS>30 nz:',ii,jj,nz + endif + print*,'jmh ------end of hailstone driver------- jmh' + endif + END SUBROUTINE hailstone_driver + + + SUBROUTINE INTERPP(PA,PVAL,TA,TVAL,IFOUT,ITEL) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!!! + !!!! INTERP: to linearly interpolate value of pval at temperature tval + !!!! between two levels of pressure array pa and temperatures ta + !!!! + !!!! INPUT: PA 1D array of pressure, to be interpolated + !!!! TA 1D array of temperature + !!!! TVAL temperature value at which we want to calculate pressure + !!!! IFOUT set to 0 if TVAL outside range of TA + !!!! ITEL number of vertical levels + !!!! OUTPUT: PVAL interpolated pressure variable at temperature tval + !!!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + IMPLICIT NONE + + REAL PVAL, TVAL + REAL, DIMENSION( ITEL) :: TA, PA + INTEGER ITEL, IFOUT + !local variables + INTEGER I + REAL FRACT + + IFOUT=1 + + DO I=1,ITEL-1 + IF ( (TVAL .LT. TA(I) .AND. TVAL .GE. TA(I+1)) .or. & ! dT/dz < 0 + (TVAL .GT. TA(I) .AND. TVAL .LE. TA(I+1)) ) THEN ! dT/dz > 0 + + FRACT = (TA(I) - TVAL) / (TA(I) - TA(I+1)) + !.... compute the pressure value pval at temperature tval + PVAL = ((1.0 - FRACT) * PA(I)) + (FRACT * PA(I+1)) + + !End loop + IFOUT=0 + EXIT + ENDIF + ENDDO + + END SUBROUTINE INTERPP + + + + SUBROUTINE INTERP(AA,A,P,IFOUT,PA,ITEL) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!!! + !!!! INTERP: to linearly interpolate values of A at level P + !!!! between two levels of AA (at levels PA) + !!!! + !!!! INPUT: AA 1D array of variable + !!!! PA 1D array of pressure + !!!! P new pressure level we want to calculate A at + !!!! IFOUT set to 0 if P outside range of PA + !!!! ITEL number of vertical levels + !!!! OUTPUT: A variable at pressure level P + !!!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + IMPLICIT NONE + + REAL A, P + REAL, DIMENSION( ITEL) :: AA, PA + INTEGER ITEL, IFOUT + !local variables + INTEGER I + REAL PDIFF, VDIFF, RDIFF, VERH, ADIFF + + IFOUT=1 + + DO I=1,ITEL-1 + IF (P.LE.PA(I) .AND. P.GT.PA(I+1)) THEN + !Calculate ratio between vdiff and pdiff + PDIFF = PA(I)-PA(I+1) + VDIFF = PA(I)-P + VERH = VDIFF/PDIFF + + !Calculate the difference between the 2 A values + RDIFF = AA(I+1) - AA(I) + + !Calculate new value + A = AA(I) + RDIFF*VERH + + !End loop + IFOUT=0 + EXIT + ENDIF + ENDDO + + END SUBROUTINE INTERP + + + SUBROUTINE TERMINL(DENSA,DENSE,D,VT,TC) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!!! + !!!! INTERP: Calculate terminal velocity of the hailstone + !!!! + !!!! INPUT: DENSA density of updraft air (kg/m3) + !!!! DENSE density of hailstone + !!!! D diameter of hailstone (m) + !!!! TC updraft temperature (K) + !!!! OUTPUT:VT hailstone terminal velocity (m/s) + !!!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + IMPLICIT NONE + + REAL*8 D + REAL DENSA, DENSE, TC, VT + REAL GMASS, GX, RE, W, Y + REAL, PARAMETER :: PI = 3.141592654, G = 9.78956 + REAL ANU + + !Mass of stone in kg + GMASS = (DENSE * PI * (D**3.)) / 6. + + !Dynamic viscosity + ANU = (0.00001718)*(273.155+120.)/(TC+120.)*(TC/273.155)**(1.5) + + !CALC THE BEST NUMBER, X AND REYNOLDS NUMBER, RE + GX=(8.0*GMASS*G*DENSA)/(PI*(ANU*ANU)) + RE=(GX/0.6)**0.5 + + !SELECT APPROPRIATE EQUATIONS FOR TERMINAL VELOCITY DEPENDING ON + !THE BEST NUMBER + IF (GX.LT.550) THEN + W=LOG10(GX) + Y= -1.7095 + 1.33438*W - 0.11591*(W**2.0) + RE=10**Y + VT=ANU*RE/(D*DENSA) + ELSE IF (GX.GE.550.AND.GX.LT.1800) THEN + W=LOG10(GX) + Y= -1.81391 + 1.34671*W - 0.12427*(W**2.0) + 0.0063*(W**3.0) + RE=10**Y + VT=ANU*RE/(D*DENSA) + ELSE IF (GX.GE.1800.AND.GX.LT.3.45E08) THEN + RE=0.4487*(GX**0.5536) + VT=ANU*RE/(D*DENSA) + ELSE + RE=(GX/0.6)**0.5 + VT=ANU*RE/(D*DENSA) + ENDIF + + END SUBROUTINE TERMINL + + + + SUBROUTINE VAPORCLOSE(DELRW,PC,TS,TC,ITYPE) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!! VAPORCLOSE: CALC THE DIFFERENCE IN SATURATION VAPOUR DENSITY + !!! BETWEEN THAT OVER THE HAILSTONE'S SURFACE AND THE IN-CLOUD + !!! AIR, DEPENDS ON THE WATER/ICE RATIO OF THE UPDRAFT, + !!! AND IF THE STONE IS IN WET OR DRY GROWTH REGIME + !!! + !!! INPUT: PC fraction of updraft water that is frozen + !!! TS temperature of hailstone (K) + !!! TC temperature of updraft air (K) + !!! ITYPE wet (2) or dry (1) growth regime + !!! OUTPUT: DELRW difference in sat vap. dens. between hail and air + !!! (kg/m3) + !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + IMPLICIT NONE + REAL DELRW, PC, TS, TC + INTEGER ITYPE + !local variables + REAL RV, ALV, ALS, RATIO + DATA RV/461.48/,ALV/2500000./,ALS/2836050./ + REAL ESAT, RHOKOR, ESATW, RHOOMGW, ESATI, RHOOMGI, RHOOMG + + !!! FOR HAILSTONE: FIRST TEST IF STONE IS IN WET OR DRY GROWTH + RATIO = 1./273.155 + IF(ITYPE.EQ.2) THEN !!WET GROWTH + ESAT=611.*EXP(ALV/RV*(RATIO-1./TS)) + ELSE !!DRY GROWTH + ESAT=611.*EXP(ALS/RV*(RATIO-1./TS)) + ENDIF + RHOKOR=ESAT/(RV*TS) + + !!! NOW FOR THE AMBIENT/IN-CLOUD CONDITIONS + ESATW=611.*EXP(ALV/RV*(RATIO-1./TC)) + RHOOMGW=ESATW/(RV*TC) + ESATI=611.*EXP(ALS/RV*(RATIO-1./TC)) + RHOOMGI=ESATI/(RV*TC) + !RHOOMG=PC*(RHOOMGI-RHOOMGW)+RHOOMGW + RHOOMG = RHOOMGI !done as in hailtraj.f + + !!! CALC THE DIFFERENCE(KG/M3): <0 FOR CONDENSATION, + !!! >0 FOR EVAPORATION + DELRW=(RHOKOR-RHOOMG) + + END SUBROUTINE VAPORCLOSE + + + + SUBROUTINE MASSAGR(D,GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DGMV,DI,ANU,RE,AE,& + TC,TS,P,DENSE,DENSA,FW,VT,XW,XI,SEKDEL,ITYPE,DELRW) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!! CALC THE STONE'S INCREASE IN MASS + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + IMPLICIT NONE + REAL*8 D + REAL GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DI,ANU,RE,AE, & + TC,TS,P,DENSE,DENSA,FW,VT,XW,XI,SEKDEL,DELRW + INTEGER ITYPE + !local variables + REAL PI, D0, GMW2, GMI2, EW, EI,DGMV + REAL DENSEL, DENSELI, DENSELW + REAL DC !MEAN CLOUD DROPLET DIAMETER (MICRONS, 1E-6M) + REAL VOLL, VOLT !VOLUME OF NEW LAYER, TOTAL (M3) + REAL VOL1, DGMW_NOSOAK, SOAK, SOAKM + REAL DENSAC, E, AFACTOR, NS, TSCELSIUS, VIMP, W + PI=3.141592654 + + !!! CALCULATE THE DIFFUSIVITY DI (m2/s) + D0=0.226*1.E-4 ! change to m2/s, not cm2/s + DI=D0*(TC/273.155)**1.81*(100000./P) + + !!! COLLECTION EFFICIENCY FOR WATER AND ICE + !EW=1.0 + !!!! IF TS WARMER THAN -5C THEN ACCRETE ALL THE ICE (EI=1.0) + !!!! OTHERWISE EI=0.21 + !IF(TS.GE.268.15)THEN + ! EI=1.00 + !ELSE + ! EI=0.21 + !ENDIF + + !!! COLLECTION EFFICIENCY FOR WATER AND ICE + EW=1.0 + !!! Linear function for ice accretion efficiency + IF (TC .GE. 273.155) THEN + EI=1.00 + ELSE IF (TC.GE.233.155) THEN + EI= 1.0 - ( (273.155 - TS) / 40. ) + ELSE !cooler than -40C + EI = 0.0 + ENDIF + + !!! CALCULATE THE VENTILATION COEFFICIENT - NEEDED FOR GROWTH FROM VAPOR + !The coefficients in the ventilation coefficient equations have been + !experimentally derived, and are expecting cal-C-g units. Do some conversions. + DENSAC = DENSA * (1.E3) * (1.E-6) + !dynamic viscosity + ANU=1.717E-4*(393.0/(TC+120.0))*(TC/273.155)**1.5 + !!! CALCULATE THE REYNOLDS NUMBER - unitless + RE=D*VT*DENSAC/ANU + E=(0.60)**(0.333333333)*(RE**0.50) !ventilation coefficient vapor (fv) + !!! SELECT APPROPRIATE VALUES OF AE ACCORDING TO RE + IF(RE.LT.6000.0)THEN + AE=0.78+0.308*E + ELSEIF(RE.GE.6000.0.AND.RE.LT.20000.0)THEN + AE=0.76*E + ELSEIF(RE.GE.20000.0) THEN + AE=(0.57+9.0E-6*RE)*E + ENDIF + + + !!! CALC HAILSTONE'S MASS (GM), MASS OF WATER (GMW) AND THE + !!! MASS OF ICE IN THE STONE (GMI) + GM=PI/6.*(D**3.)*DENSE + GMW=FW*GM + GMI=GM-GMW + + !!! STORE THE MASS + GM1=GM + + !!! NEW MASS GROWTH CALCULATIONS WITH VARIABLE RIME + !!! LAYER DENSITY BASED ON ZIEGLER ET AL. (1983) + + !!! CALCULATE INCREASE IN MASS DUE INTERCEPTED CLD WATER, USE + !!! ORIGINAL DIAMETER + GMW2=GMW+SEKDEL*(PI/4.*D**2.*VT*XW*EW) + DGMW=GMW2-GMW + GMW=GMW2 + + !!! CALCULATE THE INCREASE IN MASS DUE INTERCEPTED CLOUD ICE + GMI2=GMI+SEKDEL*(PI/4.*D**2.*VT*XI*EI) + DGMI=GMI2-GMI + GMI=GMI2 + + !!! CALCULATE INCREASE IN MASS DUE TO SUBLIMATION/CONDENSATION OF + !!! WATER VAPOR + DGMV = SEKDEL*2*PI*D*AE*DI*DELRW + IF (DGMV .LT. 0) DGMV=0 + + !!! CALCULATE THE TOTAL MASS CHANGE + DGM=DGMW+DGMI+DGMV + !Dummy arguments in the event of no water, vapor, or ice growth + DENSELW = 900. + DENSELI = 700. + !!! CALCULATE DENSITY OF NEW LAYER, DEPENDS ON FW AND ITYPE + IF (ITYPE.EQ.1) THEN !DRY GROWTH + !If hailstone encountered supercooled water, calculate new layer density + ! using Macklin form + IF ((DGMW.GT.0).OR.(DGMV.GT.0)) THEN + !MEAN CLOUD DROPLET RADIUS, ASSUME CLOUD DROPLET CONC OF 3E8 M-3 (300 CM-3) + DC = (0.74*XW / (3.14159*1000.*3.E8))**0.33333333 * 1.E6 !MICRONS + !!! FIND THE STOKES NUMBER (rasmussen heymsfield 1985) + NS = 2*VT*100.*(DC*1.E-4)**2. / (9*ANU*D*50) !need hail radius in cm + !!! FIND IMPACT VELOCITY (rasmussen heymsfield 1985) + IF (NS.LT.0.1)THEN + W=-1. + ELSE + W = LOG10(NS) + ENDIF + IF (RE.GT.200) THEN + IF (NS.LT.0.1) THEN + VIMP = 0.0 + ELSEIF ((NS.GE.0.1).AND.(NS.LE.10)) THEN + VIMP = (0.356 + 0.4738*W - 0.1233*W**2. & + -0.1618*W**3. + 0.0807*W**4.)*VT + ELSEIF (NS.GT.10) THEN + VIMP = 0.63*VT + ENDIF + ELSEIF ((RE.GT.65).AND.(RE.LE.200)) THEN + IF (NS.LT.0.1) THEN + VIMP = 0.0 + ELSEIF ((NS.GE.0.1).AND.(NS.LE.10)) THEN + VIMP = (0.3272 + 0.4907*W - 0.09452*W**2. & + -0.1906*W**3. + 0.07105*W**4.)*VT + ELSEIF (NS.GT.10) THEN + VIMP = 0.61*VT + ENDIF + ELSEIF ((RE.GT.20).AND.(RE.LE.65)) THEN + IF (NS.LT.0.1) THEN + VIMP = 0.0 + ELSEIF ((NS.GE.0.1).AND.(NS.LE.10)) THEN + VIMP = (0.2927 + 0.5085*W - 0.03453*W**2. & + -0.2184*W**3. + 0.03595*W**4.)*VT + ELSEIF (NS.GT.10) THEN + VIMP = 0.59*VT + ENDIF + ELSEIF (RE.LE.20) THEN + IF (NS.LT.0.4) THEN + VIMP = 0.0 + ELSEIF ((NS.GE.0.4).AND.(NS.LE.10)) THEN + VIMP = (0.1701 + 0.7246*W + 0.2257*W**2. & + -1.13*W**3. + 0.5756*W**4.)*VT + ELSEIF (NS.GT.10) THEN + VIMP = 0.57*VT + ENDIF + ENDIF + + !RIME LAYER DENSITY, HEYMSFIELD AND PFLAUM 1985 FORM + TSCELSIUS = TS - 273.16 + AFACTOR = -DC*VIMP/TSCELSIUS + IF ((TSCELSIUS.LE.-5.).OR.(AFACTOR.GE.-1.60)) THEN + DENSELW = 0.30*(AFACTOR)**0.44 + ELSEIF (TSCELSIUS.GT.-5.) THEN + DENSELW = EXP(-0.03115 - 1.7030*AFACTOR + & + 0.9116*AFACTOR**2. - 0.1224*AFACTOR**3.) + ENDIF + + DENSELW = DENSELW * 1000. !KG M-3 + !BOUND POSSIBLE DENSITIES + IF (DENSELW.LT.100) DENSELW=100 + IF (DENSELW.GT.900) DENSELW=900 + !WRITE(12,*) 'MASSAGR, PFLAUM, MACKLIN: ', DENSELW, & + ! MACKLIN_DENSELW + ENDIF + IF (DGMI.GT.0) THEN + !Ice collection main source of growth, so set new density layer + DENSELI = 700. + ENDIF + + !All liquid water contributes to growth, none is soaked into center. + DGMW_NOSOAK = DGMW !All liquid water contributes to growth, + ! none of it is soaked into center. + + ELSE !WET GROWTH + !Collected liquid water can soak into the stone before freezing, + ! increasing mass and density but leaving volume constant. + !Volume of current drop, before growth + VOL1 = GM/DENSE + !Difference b/w mass of stone if density is 900 kg/m3, and + ! current mass + SOAK = 900*VOL1 - GM + !Liquid mass available + SOAKM = DGMW + !Soak up as much liquid as we can, up to a density of 900 kg/m3 + IF (SOAKM.GT.SOAK) SOAKM=SOAK + GM = GM+SOAKM !Mass of current drop, plus soaking + !New density of current drop, including soaking but before growth + DENSE = GM/VOL1 + !Mass increment of liquid water growth that doesn't + ! include the liquid water we just soaked into the stone. + DGMW_NOSOAK = DGMW - SOAKM + + !Whatever growth does occur has high density + DENSELW = 900. !KG M-3 + DENSELI = 900. + + ENDIF + + !!!VOLUME OF NEW LAYER + !VOLL = (DGM) / DENSEL + !VOLL = (DGMI+DGMV+DGMW_NOSOAK) / DENSEL + !VOLL = (DGMI) / DENSELI + (DGMW_NOSOAK+DGMV) / DENSELW + IF (DGMI.LE.0) THEN + VOLL = (DGMW_NOSOAK+DGMV) / DENSELW + ELSE IF (DGMW.LE.0) THEN + VOLL = (DGMI) / DENSELI + ELSE + VOLL = (DGMI) / DENSELI + (DGMW_NOSOAK+DGMV) / DENSELW + ENDIF + + !!!NEW TOTAL VOLUME, DENSITY, DIAMETER + VOLT = VOLL + GM/DENSE + !DENSE = (GM+DGM) / VOLT + DENSE = (GM+DGMI+DGMV+DGMW_NOSOAK) / VOLT + !D=D+SEKDEL*0.5*VT/DENSE*(XW*EW+XI*EI) + GM = GM+DGMI+DGMW_NOSOAK+DGMV + D = ( (6*GM) / (PI*DENSE) )**0.33333333 + + END SUBROUTINE MASSAGR + + + + SUBROUTINE HEATBUD(TS,TSm1,TSm2,FW,TC,VT,DELRW,D,DENSA,GM1,GM,DGM,DGMW, & + DGMV,DGMI,GMW,GMI,DI,ANU,RE,AE,SEKDEL,ITYPE,P) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!! CALCULATE HAILSTONE'S HEAT BUDGET + !!! See Rasmussen and Heymsfield 1987; JAS + !!! Original Hailcast's variable units + !!! TS - Celsius + !!! FW - unitless, between 0 and 1 + !!! TC - Celsius + !!! VT - m/s + !!! D - m + !!! DELRW - g/cm3 (per comment) + !!! DENSA - g/cm3 (per comment) + !!! GM1, DMG, DGMW, DGMV, DGMI, GMW, GMI - should all be kg + !!! DI - cm2 / sec + !!! P - hPa + !!! Original HAILCAST HEATBUD subroutine uses c-g-s units, so do some conversions + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + IMPLICIT NONE + REAL*8 D + REAL TS,TSm1,TSm2,FW,TC,VT,DELRW,DENSA,GM1,GM,DGM,DGMW,DGMV, & + DGMI,GMW,GMI,DI,ANU,RE,AE,SEKDEL,P + INTEGER ITYPE + + REAL RV, RD, G, PI, ALF, ALV, ALS, CI, CW, AK + REAL H, AH, TCC, TSC, DELRWC, DENSAC, TDIFF + REAL DMLT + REAL TSCm1, TSCm2 + DATA RV/461.48/,RD/287.04/,G/9.78956/ + DATA PI/3.141592654/,ALF/79.7/,ALV/597.3/ + DATA ALS/677.0/,CI/0.5/,CW/1./ + + !Convert values to non-SI units here + TSC = TS - 273.155 + TSCm1 = TSm1 - 273.155 + TSCm2 = TSm2 - 273.155 + TCC = TC - 273.155 + DELRWC = DELRW * (1.E3) * (1.E-6) + DENSAC = DENSA * (1.E3) * (1.E-6) + !DI still in cm2/sec + + + !!! CALCULATE THE CONSTANTS + AK=(5.8+0.0184*TCC)*1.E-5 !thermal conductivity - cal/(cm*sec*K) + !dynamic viscosity - calculated in MASSAGR + !ANU=1.717E-4*(393.0/(TC+120.0))*(TC/273.155)**1.5 + + !!! CALCULATE THE REYNOLDS NUMBER - unitless + !RE=D*VT*DENSAC/ANU - calculated in MASSAGR + + H=(0.71)**(0.333333333)*(RE**0.50) !ventilation coefficient heat (fh) + !E=(0.60)**(0.333333333)*(RE**0.50) !ventilation coefficient vapor (fv) + + !!! SELECT APPROPRIATE VALUES OF AH AND AE ACCORDING TO RE + IF(RE.LT.6000.0)THEN + AH=0.78+0.308*H + !AE=0.78+0.308*E + ELSEIF(RE.GE.6000.0.AND.RE.LT.20000.0)THEN + AH=0.76*H + !AE=0.76*E + ELSEIF(RE.GE.20000.0) THEN + AH=(0.57+9.0E-6*RE)*H + !AE=(0.57+9.0E-6*RE)*E calculated in MASSAGR + ENDIF + + !!! FOR DRY GROWTH FW=0, CALCULATE NEW TS, ITIPE=1 + !!! FOR WET GROWTH TS=0, CALCULATE NEW FW, ITIPE=2 + + + IF(ITYPE.EQ.1) THEN + !!! DRY GROWTH; CALC NEW TEMP OF THE STONE + !Original Hailcast algorithm (no time differencing) + !TSC=TSC-TSC*DGM/GM1+SEKDEL/(GM1*CI)* & + ! (2.*PI*D*(AH*AK*(TCC-TSC)-AE*ALS*DI*DELRWC)+ & + ! DGMW/SEKDEL*(ALF+CW*TCC)+DGMI/SEKDEL*CI*TCC) + TSC=0.6*(TSC-TSC*DGM/GM1+SEKDEL/(GM1*CI)* & + (2.*PI*D*(AH*AK*(TCC-TSC)-AE*ALS*DI*DELRWC)+ & + DGMW/SEKDEL*(ALF+CW*TCC)+DGMI/SEKDEL*CI*TCC)) + & + 0.2*TSCm1 + 0.2*TSCm2 + + TS = TSC+273.155 + IF (TS.GE.273.155) THEN + TS=273.155 + ENDIF + TDIFF = ABS(TS-273.155) + IF (TDIFF.LE.1.E-6) ITYPE=2 !NOW IN WET GROWTH + + ELSE IF (ITYPE.EQ.2) THEN + !!! WET GROWTH; CALC NEW FW + + IF (TCC.LT.0.) THEN + !Original Hailcast algorithm + FW=FW-FW*DGM/GM1+SEKDEL/(GM1*ALF)* & + (2.*PI*D*(AH*AK*TCC-AE*ALV*DI*DELRWC)+ & + DGMW/SEKDEL*(ALF+CW*TCC)+DGMI/SEKDEL*CI*TCC) + ELSE + !Calculate decrease in ice mass due to melting + DMLT = (2.*PI*D*AH*AK*TCC + 2.*PI*D*AE*ALV*DI*DELRWC + & + DGMW/SEKDEL*CW*TCC) / ALF + FW = (FW*GM + DMLT) / GM + ENDIF + + IF(FW.GT.1.)FW=1. + IF(FW.LT.0.)FW=0. + + !IF ALL OUR ACCRETED WATER WAS FROZEN, WE ARE BACK IN DRY GROWTH + IF(FW.LE.1.E-6) THEN + ITYPE=1 + ENDIF + + ENDIF + + END SUBROUTINE HEATBUD + + + + SUBROUTINE BREAKUP(DENSE,D,GM,FW,CRIT) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!! TEST IF AMOUNT OF WATER ON SURFACE EXCEEDS CRTICAL LIMIT- + !!! IF SO INVOKE SHEDDING SCHEME + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + IMPLICIT NONE + REAL*8 D + REAL DENSE, GM, FW, CRIT + !local variables + REAL WATER, GMI, WAT, PI + DATA PI/3.141592654/ + + WATER=FW*GM !KG + !GMI=(GM-WATER) !KG + !REMAIN = CRIT*GM + + ! CALC CRTICAL MASS CAPABLE OF BEING "SUPPORTED" ON THE STONE'S + ! SURFACE + !CRIT=0.268+0.1389*GMI + !CRIT=0.268*1.E-3 + 0.1389*1.E-3*GMI !mass now in kg instead of g + !CRIT = 1.0E-10 + !CRIT - now passed from main subroutine + + WAT=WATER-CRIT + GM=GM-WAT + FW=(CRIT)/GM + + IF(FW.GT.1.0) FW=1.0 + IF(FW.LT.0.0) FW=0.0 + + ! RECALCULATE DIAMETER AFTER SHEDDING + ! Assume density remains the same + D=(6.*GM/(PI*DENSE))**(0.333333333) + END SUBROUTINE BREAKUP + + + SUBROUTINE MELT(D,TLAYER,PLAYER,RLAYER,LDEPTH,VT) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !!! This is a spherical hail melting estimate based on the Goyer + !!! et al. (1969) eqn (3). The depth of the warm layer, estimated + !!! terminal velocity, and mean temperature of the warm layer are + !!! used. DRB. 11/17/2003. + !!! + !!! INPUT: TLAYER mean sub-cloud layer temperature (K) + !!! PLAYER mean sub-cloud layer pressure (Pa) + !!! RLAYER mean sub-cloud layer mixing ratio (kg/kg) + !!! VT terminal velocity of stone (m/s) + !!! OUTPUT: D diameter (m) + !!! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + IMPLICIT NONE + + REAL*8 D + REAL TLAYER, PLAYER, RLAYER, LDEPTH, VT + REAL eenv, delta, ewet, de, der, wetold, wetbulb, wetbulbk + REAL tdclayer, tclayer, eps, b, hplayer + REAL*8 a + REAL sd, lt, ka, lf, lv, t0, dv, pi, rv, rhoice, & + tres, re, delt, esenv, rhosenv, essfc, rhosfc, dsig, & + dmdt, mass, massorg, newmass, gamma, r, rho + INTEGER wcnt + + !Convert temp to Celsius, calculate dewpoint in celsius + eps = 0.622 + tclayer = TLAYER - 273.155 + a = 2.53E11 + b = 5.42E3 + tdclayer = b / LOG(a*eps / (rlayer*player)) + hplayer = player / 100. + + !Calculate partial vapor pressure + eenv = (player*rlayer) / (rlayer+eps) + eenv = eenv / 100. !convert to mb + + !Estimate wet bulb temperature (C) + gamma = 6.6E-4*player + delta = (4098.0*eenv)/((tdclayer+237.7)*(tdclayer+237.7)) + wetbulb = ((gamma*tclayer)+(delta*tdclayer))/(gamma+delta) + + !Iterate to get exact wet bulb + wcnt = 0 + DO WHILE (wcnt .lt. 11) + ewet = 6.108*(exp((17.27*wetbulb)/(237.3 + wetbulb))) + de = (0.0006355*hplayer*(tclayer-wetbulb))-(ewet-eenv) + der= (ewet*(.0091379024 - (6106.396/(273.155+wetbulb)**2))) & + - (0.0006355*hplayer) + wetold = wetbulb + wetbulb = wetbulb - de/der + wcnt = wcnt + 1 + IF ((abs(wetbulb-wetold)/wetbulb.gt.0.0001)) THEN + EXIT + ENDIF + ENDDO + + wetbulbk = wetbulb + 273.155 !convert to K + ka = .02 ! thermal conductivity of air + lf = 3.34e5 ! latent heat of melting/fusion + lv = 2.5e6 ! latent heat of vaporization + t0 = 273.155 ! temp of ice/water melting interface + dv = 0.25e-4 ! diffusivity of water vapor (m2/s) + pi = 3.1415927 + rv = 1004. - 287. ! gas constant for water vapor + rhoice = 917.0 ! density of ice (kg/m**3) + r = D/2. ! radius of stone (m) + + !Compute residence time in warm layer + tres = LDEPTH / VT + + !Calculate dmdt based on eqn (3) of Goyer et al. (1969) + !Reynolds number...from pg 317 of Atmo Physics (Salby 1996) + !Just use the density of air at 850 mb...close enough. + rho = 85000./(287.*TLAYER) + re = rho*r*VT*.01/1.7e-5 + + !Temperature difference between environment and hailstone surface + delt = wetbulb !- 0.0 !assume stone surface is at 0C + !wetbulb is in Celsius + + !Difference in vapor density of air stream and equil vapor + !density at the sfc of the hailstone + esenv = 610.8*(exp((17.27*wetbulb)/ & + (237.3 + wetbulb))) ! es environment in Pa + rhosenv = esenv/(rv*wetbulbk) + essfc = 610.8*(exp((17.27*(t0-273.155))/ & + (237.3 + (t0-273.155)))) ! es environment in Pa + rhosfc = essfc/(rv*t0) + dsig = rhosenv - rhosfc + + !Calculate new mass growth + dmdt = (-1.7*pi*r*(re**0.5)/lf)*((ka*delt)+((lv-lf)*dv*dsig)) + IF (dmdt.gt.0.) dmdt = 0 + mass = dmdt*tres + + !Find the new hailstone diameter + massorg = 1.33333333*pi*r*r*r*rhoice + newmass = massorg + mass + if (newmass.lt.0.0) newmass = 0.0 + D = 2.*(0.75*newmass/(pi*rhoice))**0.333333333 + END SUBROUTINE MELT + + +END MODULE module_diag_hailcast + From 17b1ddf028a0aeeb86b0c435335177a349329624 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Fri, 15 Oct 2021 17:46:51 -0500 Subject: [PATCH 05/13] Cleanup after rebase --- driver/fvGFS/atmosphere.F90 | 10 + driver/fvGFS/fv_nggps_diag.F90 | 293 +-------------------------- model/fv_arrays.F90 | 4 - model/fv_regional_bc.F90 | 11 +- tools/coarse_grained_diagnostics.F90 | 10 +- 5 files changed, 33 insertions(+), 295 deletions(-) diff --git a/driver/fvGFS/atmosphere.F90 b/driver/fvGFS/atmosphere.F90 index 503eecc11..3fb22c2d6 100644 --- a/driver/fvGFS/atmosphere.F90 +++ b/driver/fvGFS/atmosphere.F90 @@ -472,8 +472,18 @@ subroutine atmosphere_init (Time_init, Time, Time_step, Grid_box, area) ! First, read atmos_model_nml namelist section - this is a workaround to avoid ! unnecessary additional changes to the input namelists, in anticipation of the ! implementation of a generic interface for GFDL and CCPP fast physics soon +#ifdef INTERNAL_FILE_NML read(input_nml_file, nml=atmos_model_nml, iostat=io) ierr = check_nml_error(io, 'atmos_model_nml') +#else + unit = open_namelist_file ( ) + ierr=1 + do while (ierr /= 0) + read (unit, nml=atmos_model_nml, iostat=io, end=10) + ierr = check_nml_error(io,'atmos_model_nml') + enddo +10 call close_file (unit) +#endif !write(0,'(a)') "It's me, and my physics suite is '" // trim(ccpp_suite) // "'" ! *DH 20210326 diff --git a/driver/fvGFS/fv_nggps_diag.F90 b/driver/fvGFS/fv_nggps_diag.F90 index de117b2d2..8e68b2e44 100644 --- a/driver/fvGFS/fv_nggps_diag.F90 +++ b/driver/fvGFS/fv_nggps_diag.F90 @@ -62,7 +62,7 @@ module fv_nggps_diags_mod ! ! - use mpp_mod, only: mpp_pe, mpp_root_pe,FATAL,mpp_error,NOTE, stdlog, input_nml_file + use mpp_mod, only: mpp_pe, mpp_root_pe,FATAL,mpp_error use constants_mod, only: grav, rdgas use time_manager_mod, only: time_type, get_time use diag_manager_mod, only: register_diag_field, send_data @@ -99,18 +99,11 @@ module fv_nggps_diags_mod integer :: id_wmaxup,id_wmaxdn,kstt_wup, kend_wup,kstt_wdn,kend_wdn integer :: id_uhmax03,id_uhmin03,id_uhmax25,id_uhmin25,id_maxvort01 integer :: id_maxvorthy1,kstt_maxvorthy1,kstt_maxvort01,id_ustm - integer :: id_hailcast_dhail - integer :: id_hailcast_dhail1, id_hailcast_dhail2, id_hailcast_dhail3, id_hailcast_dhail4, id_hailcast_dhail5, id_hailcast_wdur, id_hailcast_wup_mask - integer :: id_hailcast_diam_mean, id_hailcast_diam_std integer :: kend_maxvorthy1,kend_maxvort01,id_vstm,id_srh01,id_srh03 integer :: kstt_uhmax03,kstt_uhmin03,kend_uhmax03,kend_uhmin03 integer :: kstt_uhmax25,kstt_uhmin25,kend_uhmax25,kend_uhmin25 integer :: kstt_ustm,kstt_vstm,kend_ustm,kend_vstm,kstt_srh01 integer :: kstt_srh03,kend_srh01,kend_srh03 - integer :: kstt_hc, kend_hc - integer :: kstt_hc1,kstt_hc2,kstt_hc3,kstt_hc4,kstt_hc5 - integer :: kend_hc1,kend_hc2,kend_hc3,kend_hc4,kend_hc5 - integer :: kstt_hcd, kend_hcd, kstt_hcm, kend_hcm integer :: id_maxvort02,kstt_maxvort02,kend_maxvort02 integer :: isco, ieco, jsco, jeco, npzo, ncnsto integer :: isdo, iedo, jsdo, jedo @@ -145,12 +138,6 @@ module fv_nggps_diags_mod real, dimension(:,:),allocatable :: up2,dn2,uhmax03,uhmin03 real, dimension(:,:),allocatable :: uhmax25,uhmin25,maxvort01 real, dimension(:,:),allocatable :: maxvorthy1,maxvort02 - - real, allocatable :: hailcast_dhail1(:,:), hailcast_dhail2(:,:), hailcast_dhail3(:,:), hailcast_dhail4(:,:), hailcast_dhail5(:,:) !hailstone diameters (mm) - real, allocatable :: hailcast_dhail1_max(:,:), hailcast_dhail2_max(:,:), hailcast_dhail3_max(:,:), hailcast_dhail4_max(:,:), hailcast_dhail5_max(:,:) !hailstone diameters (mm) - real, allocatable :: hailcast_diam_mean(:,:), hailcast_diam_std(:,:) !mean and standard deviation of five hailstones (mm) - real, allocatable :: hailcast_wdur(:,:), hailcast_wup_mask(:,:) !persistent arrays for updraft duration (s) and mask - public :: fv_nggps_diag_init, fv_nggps_diag, fv_nggps_tavg #ifdef use_WRTCOMP public :: fv_dyn_bundle_setup @@ -163,32 +150,6 @@ subroutine fv_nggps_diag_init(Atm, axes, Time) integer, intent(in) :: axes(4) type(time_type), intent(in) :: Time integer :: n, i, j, nz - logical :: do_hailcast = .true. !This controls whether hailcast is used - namelist /fv_diagnostics_nml/ do_hailcast - integer :: ios, ierr - integer :: unit - - !namelist file for hailcast -#ifdef INTERNAL_FILE_NML - ! Read Main namelist - read (input_nml_file,fv_diagnostics_nml,iostat=ios) - ierr = check_nml_error(ios,'fv_diagnostics_nml') -#else - f_unit=open_namelist_file() - rewind (f_unit) - ! Read Main namelist - read (f_unit,fv_diagnostics_nml,iostat=ios) - ierr = check_nml_error(ios,'fv_diagnostics_nml') - call close_file(f_unit) -#endif - - unit = stdlog() - write(unit, nml=fv_diagnostics_nml) - !end hailcast nml - - if (mpp_pe() == mpp_root_pe()) then - print*, 'do_hailcast = ', do_hailcast - end if n = 1 ncnsto = Atm(1)%ncnst @@ -454,97 +415,7 @@ subroutine fv_nggps_diag_init(Atm, axes, Time) enddo ! if(mpp_pe()==mpp_root_pe())print *,'in fv_dyn bundle,lat=',lat(isco,jsco),lat(ieco-2:ieco,jeco-2:jeco)*180./3.14157 endif - - endif - - !register hailcast arrays - if (do_hailcast) then - id_hailcast_dhail = register_diag_field ( trim(file_name), 'hailcast_dhail_max', axes(1:2), Time, & - 'hourly max hail diameter', 'mm', missing_value=missing_value ) - id_hailcast_dhail1 = register_diag_field ( trim(file_name), 'hailcast_dhail1_max', axes(1:2), Time, & - 'hourly max hail diameter (embryo 1)', 'mm', missing_value=missing_value ) - id_hailcast_dhail2 = register_diag_field ( trim(file_name), 'hailcast_dhail2_max', axes(1:2), Time, & - 'hourly max hail diameter (embryo 2)', 'mm', missing_value=missing_value ) - id_hailcast_dhail3 = register_diag_field ( trim(file_name), 'hailcast_dhail3_max', axes(1:2), Time, & - 'hourly max hail diameter (embryo 3)', 'mm', missing_value=missing_value ) - id_hailcast_dhail4 = register_diag_field ( trim(file_name), 'hailcast_dhail4_max', axes(1:2), Time, & - 'hourly max hail diameter (embryo 4)', 'mm', missing_value=missing_value ) - id_hailcast_dhail5 = register_diag_field ( trim(file_name), 'hailcast_dhail5_max', axes(1:2), Time, & - 'hourly max hail diameter (embryo 5)', 'mm', missing_value=missing_value ) - id_hailcast_diam_mean = register_diag_field ( trim(file_name), 'hailcast_diam_mean', axes(1:2), Time, & - 'mean hail diameter', 'mm', missing_value=missing_value ) - id_hailcast_diam_std = register_diag_field ( trim(file_name), 'hailcast_diam_std', axes(1:2), Time, & - 'standard deviation of hail diameter', 'mm', missing_value=missing_value ) - id_hailcast_wdur = register_diag_field ( trim(file_name), 'hailcast_wdur', axes(1:2), Time, & - 'updraft duration', 's', missing_value=missing_value ) - id_hailcast_wup_mask = register_diag_field ( trim(file_name), 'hailcast_wup_mask', axes(1:2), Time, & - 'updraft mask', '', missing_value=missing_value ) - - if (id_hailcast_dhail > 0) then - kstt_hc = nlevs+1; kend_hc = nlevs+1 - nlevs = nlevs + 1 - endif - - if (id_hailcast_dhail1 > 0) then - kstt_hc1 = nlevs+1; kend_hc1 = nlevs+1 - nlevs = nlevs + 1 - endif - if (id_hailcast_dhail2 > 0) then - kstt_hc2 = nlevs+1; kend_hc2 = nlevs+1 - nlevs = nlevs + 1 - endif - if (id_hailcast_dhail3 > 0) then - kstt_hc3 = nlevs+1; kend_hc3 = nlevs+1 - nlevs = nlevs + 1 - endif - if (id_hailcast_dhail4 > 0) then - kstt_hc4 = nlevs+1; kend_hc4 = nlevs+1 - nlevs = nlevs + 1 - endif - if (id_hailcast_dhail5 > 0) then - kstt_hc5 = nlevs+1; kend_hc5 = nlevs+1 - nlevs = nlevs + 1 - endif - if (id_hailcast_wdur > 0) then - kstt_hcd = nlevs+1; kend_hcd = nlevs+1 - nlevs = nlevs + 1 - endif - if (id_hailcast_wup_mask > 0) then - kstt_hcm = nlevs+1; kend_hcm = nlevs+1 - nlevs = nlevs + 1 - endif - - if (.not.allocated(hailcast_dhail1)) then - allocate(hailcast_dhail1(isco:ieco,jsco:jeco), & - hailcast_dhail2(isco:ieco,jsco:jeco), & - hailcast_dhail3(isco:ieco,jsco:jeco), & - hailcast_dhail4(isco:ieco,jsco:jeco), & - hailcast_dhail5(isco:ieco,jsco:jeco), & - hailcast_diam_mean(isco:ieco,jsco:jeco), & - hailcast_diam_std(isco:ieco,jsco:jeco)) - allocate ( hailcast_dhail1_max(isco:ieco,jsco:jeco) ) - allocate ( hailcast_dhail2_max(isco:ieco,jsco:jeco) ) - allocate ( hailcast_dhail3_max(isco:ieco,jsco:jeco) ) - allocate ( hailcast_dhail4_max(isco:ieco,jsco:jeco) ) - allocate ( hailcast_dhail5_max(isco:ieco,jsco:jeco) ) - - do i=isco,ieco - do j=jsco,jeco - hailcast_dhail1(i,j)=0; hailcast_dhail2(i,j)=0; hailcast_dhail3(i,j)=0; hailcast_dhail4(i,j)=0; hailcast_dhail5(i,j)=0 - hailcast_dhail1_max(i,j)=0; hailcast_dhail2_max(i,j)=0; hailcast_dhail3_max(i,j)=0; hailcast_dhail4_max(i,j)=0; hailcast_dhail5_max(i,j)=0 - enddo - enddo - endif - if (.not.allocated(hailcast_wdur)) then - allocate(hailcast_wdur(isdo:iedo,jsdo:jedo),hailcast_wup_mask(isdo:iedo,jsdo:jedo)) - do i=isdo,iedo - do j=jsdo,jedo - hailcast_wdur(i,j)=0;hailcast_wup_mask(i,j)=0 - enddo - enddo - endif endif - ! !------------------------------------ ! use wrte grid component for output @@ -564,7 +435,8 @@ subroutine fv_nggps_diag(Atm, zvir, Time) logical :: bad_range real :: ptop, allmax real, allocatable :: wk(:,:,:), wk2(:,:,:) - real, dimension(:,:),allocatable :: ustm,vstm,srh01,srh03,hailcast_dhail_max + real, dimension(:,:),allocatable :: ustm,vstm,srh01,srh03 + n = 1 ngc = Atm(n)%ng ptop = Atm(n)%ak(1) @@ -886,17 +758,17 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) kdtt=0 endif nsteps_per_reset = nint(avg_max_length/first_time) - if(mod(kdtt,nsteps_per_reset)==0)then do j=jsco,jeco do i=isco,ieco + if(mod(kdtt,nsteps_per_reset)==0)then up2(i,j) = -999. dn2(i,j) = 999. maxvorthy1(i,j)= 0. maxvort01(i,j)= 0. maxvort02(i,j)= 0. + endif enddo enddo - endif call get_vorticity(isco,ieco,jsco,jeco,isdo,iedo,jsdo,jedo, & npzo,Atm(n)%u,Atm(n)%v,vort, & Atm(n)%gridstruct%dx,Atm(n)%gridstruct%dy,& @@ -914,16 +786,16 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) vort,maxvort02,0., 2.e3) if( .not.Atm(n)%flagstruct%hydrostatic ) then call max_vv(isco,ieco,jsco,jeco,npzo,ngc,up2,dn2,Atm(n)%pe,Atm(n)%w) - if(mod(kdtt,nsteps_per_reset)==0)then do j=jsco,jeco do i=isco,ieco + if(mod(kdtt,nsteps_per_reset)==0)then uhmax03(i,j)= 0. uhmin03(i,j)= 0. uhmax25(i,j)= 0. uhmin25(i,j)= 0. + endif enddo enddo - endif call max_uh(isco,ieco,jsco,jeco,ngc,npzo,zvir, & sphum,uhmax03,uhmin03,Atm(n)%w,vort,Atm(n)%delz, & @@ -936,6 +808,7 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) Atm(n)%pt,Atm(n)%peln,Atm(n)%phis,grav, & 2.e3, 5.e3) endif + kdtt=kdtt+1 deallocate (vort) else print *,'Missing max/min hourly field in diag_table' @@ -945,92 +818,6 @@ subroutine fv_nggps_tavg(Atm, Time_step_atmos,avg_max_length,zvir) stop endif endif - - !allocate hailcast met field arrays - if (id_hailcast_dhail>0 .or. id_hailcast_dhail1>0 .or. id_hailcast_dhail2>0 .or. id_hailcast_dhail3>0 & - .or. id_hailcast_dhail4>0 .or. id_hailcast_dhail5>0 .or. id_hailcast_diam_mean>0 & - .or. id_hailcast_diam_std>0) then - - do j=jsco,jeco - do i=isco,ieco - if(mod(kdtt,nsteps_per_reset)==0)then - hailcast_dhail1_max(i,j) = 0. - hailcast_dhail2_max(i,j) = 0. - hailcast_dhail3_max(i,j) = 0. - hailcast_dhail4_max(i,j) = 0. - hailcast_dhail5_max(i,j) = 0. - endif - - hailcast_dhail1(i,j) = 0 - hailcast_dhail2(i,j) = 0 - hailcast_dhail3(i,j) = 0 - hailcast_dhail4(i,j) = 0 - hailcast_dhail5(i,j) = 0 - enddo - enddo - - - if (.not. allocated(rhoair_layer)) allocate(rhoair_layer(isco:ieco,jsco:jeco,1:npzo)) !layer 3-D air density - if (.not. allocated(z)) allocate(z(1:npzo+1)) !interace levels - if (.not. allocated(z_layer)) allocate(z_layer(isco:ieco,jsco:jeco,1:npzo)) !layer 3-D height ASL - if (.not. allocated(p_layer)) allocate(p_layer(isco:ieco,jsco:jeco,1:npzo)) !layer 3-D pressure - if (.not. allocated(zsfc)) allocate(zsfc(isco:ieco,jsco:jeco)) !terrain height - - do k=npzo,1,-1 - do j=jsco, jeco - if (Atm(n)%flagstruct%hydrostatic) then - call mpp_error(FATAL, 'HAILCAST can only be run with non-hydrostatic FV3') - !do i=is, ie - !rhoair(i,j,k) = Atm(n)%delp(i,j,k)/( ( Atm(n)%peln(i,k+1,j)- Atm(n)%peln(i,k,j)) & - ! * rdgas * Atm(n)%pt(i,j,k) * ( 1. + zvir*q(i,j,k,sphum))) - !enddo - else !non-hydrostatic - do i=isco, ieco - if (k==npzo) then - zsfc(i,j)=Atm(n)%phis(i,j) / grav - z(npzo+1)=zsfc(i,j) - endif - rhoair_layer(i,j,k) = -Atm(n)%delp(i,j,k)/(grav*Atm(n)%delz(i,j,k)) - !height of interfaces and layer height - z(k)=z(k+1)-Atm(n)%delz(i,j,k) - z_layer(i,j,k)=(z(k+1)+z(k))/2 - p_layer(i,j,k)=Atm(n)%delp(i,j,k)*(1.-sum(Atm(n)%q(i,j,k,2:Atm(n)%flagstruct%nwat)))/& - (-Atm(n)%delz(i,j,k)*grav)*rdgas*Atm(n)%pt(i,j,k)*(1.+zvir*Atm(n)%q(i,j,k,sphum)) - enddo - endif - enddo !j loop - enddo !k loop - - !call hailcast diagnostic driver once per time step and provide three-dimensional met fields - call hailcast_diagnostic_driver(Atm(n)%pt(isco:ieco,jsco:jeco,1:npzo), Atm(n)%w(isco:ieco,jsco:jeco,1:npzo), p_layer, z_layer, rhoair_layer, Atm(n)%q(isco:ieco,jsco:jeco,1:npzo,:), & !3D fields - Atm(n)%flagstruct%nwat, sphum,liq_wat,ice_wat,rainwat,snowwat,graupel, & !number of tracer indices, indices - isco,ieco,jsco,jeco,isdo,iedo,jsdo,jedo, & !grid dimensions data array (with halo) and physical grid dimensions - 1,npzo, zsfc, & !vertical dimensions, terrain height - first_time, Atm(n)%domain, & !call hailcast every model step and info for updating haloes - hailcast_dhail1,hailcast_dhail2,hailcast_dhail3,hailcast_dhail4,hailcast_dhail5, & !hailcast embryos sizes - hailcast_diam_mean, hailcast_diam_std, & !hailcast embryo mean/std - hailcast_wdur, hailcast_wup_mask) !persistent updraft duration and mask - - do j=jsco,jeco - do i=isco,ieco - hailcast_dhail1_max(i,j) = max(hailcast_dhail1_max(i,j), hailcast_dhail1(i,j)) - hailcast_dhail2_max(i,j) = max(hailcast_dhail2_max(i,j), hailcast_dhail2(i,j)) - hailcast_dhail3_max(i,j) = max(hailcast_dhail3_max(i,j), hailcast_dhail3(i,j)) - hailcast_dhail4_max(i,j) = max(hailcast_dhail4_max(i,j), hailcast_dhail4(i,j)) - hailcast_dhail5_max(i,j) = max(hailcast_dhail5_max(i,j), hailcast_dhail5(i,j)) - enddo - enddo - - - !deallocate hailcast met variables - deallocate(p_layer) - deallocate(z_layer) - deallocate(rhoair_layer) - deallocate(z) - deallocate(zsfc) - endif - - kdtt=kdtt+1 end subroutine fv_nggps_tavg ! subroutine store_data(id, work, Time, nstt, nend) @@ -1536,70 +1323,6 @@ subroutine fv_dyn_bundle_setup(axes, dyn_bundle, fcst_grid, quilting, rc) if(rc==0) num_field_dyn=num_field_dyn+1 endif - if( .not.hydrostatico .and. id_hailcast_dhail > 0 ) then - call find_outputname(trim(file_name),'hailcast_dhail_max',output_name) - if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter, output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter', 'mm', "time: point", & - axes(1:2), fcst_grid, kstt_hc,kend_hc, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - - if( .not.hydrostatico .and. id_hailcast_dhail1 > 0 ) then - call find_outputname(trim(file_name),'hailcast_dhail1_max',output_name) - if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 1), output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 1)', 'mm', "time: point", & - axes(1:2), fcst_grid, kstt_hc1,kend_hc1, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - - if( .not.hydrostatico .and. id_hailcast_dhail2 > 0 ) then - call find_outputname(trim(file_name),'hailcast_dhail2_max',output_name) - if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 2), output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 2)', 'mm', "time: point", & - axes(1:2), fcst_grid, kstt_hc2,kend_hc2, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - - if( .not.hydrostatico .and. id_hailcast_dhail3 > 0 ) then - call find_outputname(trim(file_name),'hailcast_dhail3_max',output_name) - if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 3), output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 3)', 'mm', "time: point", & - axes(1:2), fcst_grid, kstt_hc3,kend_hc3, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - - if( .not.hydrostatico .and. id_hailcast_dhail4 > 0 ) then - call find_outputname(trim(file_name),'hailcast_dhail4_max',output_name) - if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 4), output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 4)', 'mm', "time: point", & - axes(1:2), fcst_grid, kstt_hc4,kend_hc4, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - - if( .not.hydrostatico .and. id_hailcast_dhail5 > 0 ) then - call find_outputname(trim(file_name),'hailcast_dhail5_max',output_name) - if(mpp_pe()==mpp_root_pe())print *,'max hourly hailcast hail diameter (embryo 5), output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Max hourly hailcast hail diameter (embryo 5)', 'mm', "time: point", & - axes(1:2), fcst_grid, kstt_hc5,kend_hc5, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - - if( .not.hydrostatico .and. id_hailcast_wdur > 0 ) then - call find_outputname(trim(file_name),'hailcast_wdur',output_name) - if(mpp_pe()==mpp_root_pe())print *,'hailcast updraft duration, output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Hailcast updraft duration', 's', "time: point", & - axes(1:2), fcst_grid, kstt_hcd,kend_hcd, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - - if( .not.hydrostatico .and. id_hailcast_wup_mask > 0 ) then - call find_outputname(trim(file_name),'hailcast_wup_mask',output_name) - if(mpp_pe()==mpp_root_pe())print *,'hailcast updraft mask, output name=',trim(output_name) - call add_field_to_bundle(trim(output_name),'Hailcast updraft mask', '', "time: point", & - axes(1:2), fcst_grid, kstt_hcm,kend_hcm, dyn_bundle, output_file, rcd=rc) - if(rc==0) num_field_dyn=num_field_dyn+1 - endif - !jwtest: ! call ESMF_FieldBundleGet(dyn_bundle, fieldCount=fieldCount, rc=rc) ! print *,'in dyn_bundle_setup, fieldCount=',fieldCount diff --git a/model/fv_arrays.F90 b/model/fv_arrays.F90 index 4b27eaaf5..bf212fc29 100644 --- a/model/fv_arrays.F90 +++ b/model/fv_arrays.F90 @@ -61,10 +61,6 @@ module fv_arrays_mod real :: efx(max_step), efx_sum, efx_nest(max_step), efx_sum_nest, mtq(max_step), mtq_sum integer :: steps - !for hailcast - integer :: id_hailcast_dhail1, id_hailcast_dhail2, id_hailcast_dhail3, id_hailcast_dhail4, id_hailcast_dhail5 - integer :: id_hailcast_diam_mean, id_hailcast_diam_std - end type fv_diag_type diff --git a/model/fv_regional_bc.F90 b/model/fv_regional_bc.F90 index 223b14fef..38da5887f 100644 --- a/model/fv_regional_bc.F90 +++ b/model/fv_regional_bc.F90 @@ -6799,12 +6799,19 @@ subroutine get_data_source(data_source_fv3gfs,regional) allocate(pes(mpp_npes())) call mpp_get_current_pelist(pes) - if (open_file(Gfs_data , 'INPUT/gfs_data.nc', "read", pelist=pes) .or. & - open_file(Gfs_data , 'INPUT/gfs_data.tile1.nc', "read", pelist=pes)) then + if (regional) then + if (open_file(Gfs_data , 'INPUT/gfs_data.nc', "read", pelist=pes)) then lstatus = global_att_exists(Gfs_data, "source") if(lstatus) call get_global_attribute(Gfs_data, "source", source) call close_file(Gfs_data) endif + else + if (open_file(Gfs_data , 'INPUT/gfs_data.tile1.nc', "read", pelist=pes)) then + lstatus = global_att_exists(Gfs_data, "source") + if(lstatus) call get_global_attribute(Gfs_data, "source", source) + call close_file(Gfs_data) + endif + endif deallocate(pes) if (.not. lstatus) then diff --git a/tools/coarse_grained_diagnostics.F90 b/tools/coarse_grained_diagnostics.F90 index 8f910abdd..a133812a7 100644 --- a/tools/coarse_grained_diagnostics.F90 +++ b/tools/coarse_grained_diagnostics.F90 @@ -1214,17 +1214,18 @@ subroutine compute_cvm(q, pt, isc, iec, jsc, jec, npz, isd, ied, jsd, jed, nwat, real, dimension(isd:ied,jsd:jed,1:npz), intent(in) :: pt real, dimension(isc:iec,jsc:jec,1:npz), intent(out) :: cvm real, dimension(isc:iec) :: qc, cvm_tmp - integer :: j, k, sphum, liq_wat, ice_wat, rainwat, snowwat, graupel + integer :: j, k, sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat sphum = get_tracer_index (MODEL_ATMOS, 'sphum') liq_wat = get_tracer_index (MODEL_ATMOS, 'liq_wat') ice_wat = get_tracer_index (MODEL_ATMOS, 'ice_wat') rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') do j = jsc, jec do k = 1, npz call moist_cv(isc, iec, isd, ied, jsd, jed, npz, j, k, nwat, sphum, & - liq_wat, rainwat, ice_wat, snowwat, graupel, & + liq_wat, rainwat, ice_wat, snowwat, graupel, hailwat, & q, qc, cvm_tmp, pt(isc:iec,j,k)) cvm(isc:iec,j,k) = cvm_tmp enddo @@ -1237,17 +1238,18 @@ subroutine compute_cpm(q, pt, isc, iec, jsc, jec, npz, isd, ied, jsd, jed, nwat, real, dimension(isd:ied,jsd:jed,1:npz), intent(in) :: pt real, dimension(isc:iec,jsc:jec,1:npz), intent(out) :: cpm real, dimension(isc:iec) :: qc, cpm_tmp - integer :: j, k, sphum, liq_wat, ice_wat, rainwat, snowwat, graupel + integer :: j, k, sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat sphum = get_tracer_index (MODEL_ATMOS, 'sphum') liq_wat = get_tracer_index (MODEL_ATMOS, 'liq_wat') ice_wat = get_tracer_index (MODEL_ATMOS, 'ice_wat') rainwat = get_tracer_index (MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index (MODEL_ATMOS, 'snowwat') graupel = get_tracer_index (MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index (MODEL_ATMOS, 'hailwat') do j = jsc, jec do k = 1, npz call moist_cp(isc, iec, isd, ied, jsd, jed, npz, j, k, nwat, sphum, & - liq_wat, rainwat, ice_wat, snowwat, graupel, & + liq_wat, rainwat, ice_wat, snowwat, graupel, hailwat, & q, qc, cpm_tmp, pt(isc:iec,j,k)) cpm(isc:iec,j,k) = cpm_tmp enddo From fae67a7381efd2a7e59eabd09164e6609f10d906 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Fri, 15 Oct 2021 18:00:31 -0500 Subject: [PATCH 06/13] Redo removal of alt. namelist read --- driver/fvGFS/atmosphere.F90 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/driver/fvGFS/atmosphere.F90 b/driver/fvGFS/atmosphere.F90 index 3fb22c2d6..503eecc11 100644 --- a/driver/fvGFS/atmosphere.F90 +++ b/driver/fvGFS/atmosphere.F90 @@ -472,18 +472,8 @@ subroutine atmosphere_init (Time_init, Time, Time_step, Grid_box, area) ! First, read atmos_model_nml namelist section - this is a workaround to avoid ! unnecessary additional changes to the input namelists, in anticipation of the ! implementation of a generic interface for GFDL and CCPP fast physics soon -#ifdef INTERNAL_FILE_NML read(input_nml_file, nml=atmos_model_nml, iostat=io) ierr = check_nml_error(io, 'atmos_model_nml') -#else - unit = open_namelist_file ( ) - ierr=1 - do while (ierr /= 0) - read (unit, nml=atmos_model_nml, iostat=io, end=10) - ierr = check_nml_error(io,'atmos_model_nml') - enddo -10 call close_file (unit) -#endif !write(0,'(a)') "It's me, and my physics suite is '" // trim(ccpp_suite) // "'" ! *DH 20210326 From 7540b9d18ac58d960a34a914666462c00b1e45f0 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Fri, 15 Oct 2021 18:14:47 -0500 Subject: [PATCH 07/13] Removed tools/module_diag_hailcast.F90 --- tools/module_diag_hailcast.F90 | 1637 -------------------------------- 1 file changed, 1637 deletions(-) delete mode 100644 tools/module_diag_hailcast.F90 diff --git a/tools/module_diag_hailcast.F90 b/tools/module_diag_hailcast.F90 deleted file mode 100644 index 6eafe456a..000000000 --- a/tools/module_diag_hailcast.F90 +++ /dev/null @@ -1,1637 +0,0 @@ -!Hailcase diagnostic driver -!John Henderson AER 20190425 -!time management handling from WRF is preserved but commented out - -!MODULE module_diag_hailcast -!CONTAINS -! SUBROUTINE diag_hailcast_stub -! END SUBROUTINE diag_hailcast_stub -!END MODULE module_diag_hailcast - -MODULE module_diag_hailcast - -CONTAINS - -! SUBROUTINE hailcast_diagnostic_driver ( grid , config_flags & -! , moist & -! , rho & -! , ids, ide, jds, jde, kds, kde & -! , ims, ime, jms, jme, kms, kme & -! , ips, ipe, jps, jpe, kps, kpe & -! , its, ite, jts, jte & -! , k_start, k_end & -! , dt, itimestep & -! , haildt,curr_secs & -! , haildtacttime ) - SUBROUTINE hailcast_diagnostic_driver ( t, w, p, z, rho, q, & ! 3D temperature, updraft, pressure, height, density and moisture tracers - moist_count,sphum,liq_wat,ice_wat,rainwat,snowwat,graupel, & ! tracer indices - is,ie,js,je,ishalo,iehalo,jshalo,jehalo, & ! i,j halo data array dimensions and physical grid dimensions (2 smaller on each end) - k_start, k_end, terr_z, & ! bottom and top z indices and terrain height - dt, domainid, & ! call frequency of hailcast = model time step = physics - hailcast_dhail1,hailcast_dhail2,hailcast_dhail3,hailcast_dhail4,hailcast_dhail5, hailcast_diam_mean, hailcast_diam_std, hailcast_wdur, hailcast_wup_mask) !hailcast persistent variables - -! USE module_domain, ONLY : domain , domain_clock_get -! USE module_configure, ONLY : grid_config_rec_type, model_config_rec -! USE module_state_description -! USE module_model_constants -! USE module_utility -! USE module_streams, ONLY: history_alarm, auxhist2_alarm -!#ifdef DM_PARALLEL -! USE module_dm, ONLY: wrf_dm_sum_real, wrf_dm_maxval -! #endif - - use constants_mod, only: grav, rdgas, rvgas, pi=>pi_8, radius, kappa, WTMAIR, WTMCO2, & - omega, hlv, cp_air, cp_vapor - use fms_mod, only: write_version_number - use fms_io_mod, only: set_domain, nullify_domain, write_version_number - use time_manager_mod, only: time_type, get_date, get_time - use mpp_domains_mod, only: domain2d, mpp_update_domains, DGRID_NE - use diag_manager_mod, only: diag_axis_init, register_diag_field, & - register_static_field, send_data, diag_grid_init - use fv_arrays_mod, only: fv_atmos_type, fv_grid_type, fv_diag_type, fv_grid_bounds_type, & - R_GRID - use tracer_manager_mod, only: get_tracer_names, get_number_tracers, get_tracer_index - use field_manager_mod, only: MODEL_ATMOS - use fv_mp_mod, only: mp_reduce_sum, mp_reduce_min, mp_reduce_max, is_master - use mpp_mod, only: mpp_error, FATAL, stdlog, mpp_pe, mpp_root_pe, mpp_sum, mpp_max, NOTE - use sat_vapor_pres_mod, only: compute_qs, lookup_es - - use fv_arrays_mod, only: max_step - - - IMPLICIT NONE - -! TYPE ( domain ), INTENT(INOUT) :: grid -! TYPE ( grid_config_rec_type ), INTENT(IN) :: config_flags -! type(fv_atmos_type), intent(inout) :: grid -!!!! type(time_type), intent(in) :: Time !will not compile - INTEGER:: ishalo, iehalo, jshalo, jehalo, k_start, k_end !dimensions of halo data array - INTEGER:: is, ie, js, je - -! INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde, & -! ims, ime, jms, jme, kms, kme, & -! ips, ipe, jps, jpe, kps, kpe - - logical :: master - INTEGER :: moist_count,sphum,rainwat,snowwat,graupel,liq_wat,ice_wat - - REAL, DIMENSION( is:ie, js:je, k_start: k_end, moist_count), & - INTENT(IN ) :: q !all 3D moisture fields - - REAL, DIMENSION( is:ie, js:je, k_start: k_end), & - INTENT(IN ) :: t, w, p, z, rho !3D non-moisture fields - - REAL, DIMENSION( is:ie, js:je), & - INTENT(IN ) :: terr_z - - REAL, DIMENSION( is:ie, js:je), & - INTENT(INOUT) :: hailcast_dhail1, hailcast_dhail2, & - hailcast_dhail3, hailcast_dhail4, & - hailcast_dhail5, & - hailcast_diam_mean, hailcast_diam_std - - REAL, DIMENSION( ishalo:iehalo, jshalo:jehalo), & - INTENT(INOUT) :: hailcast_wdur, hailcast_wup_mask - -! REAL, INTENT(IN ),OPTIONAL :: haildt -! REAL, INTENT(IN ),OPTIONAL :: curr_secs -! REAL, INTENT(INOUT),OPTIONAL :: haildtacttime -! INTEGER, INTENT(IN ) :: itimestep - REAL, INTENT(IN ) :: dt - TYPE(domain2d), INTENT(INOUT ) :: domainid - - - ! Local - ! ----- - CHARACTER*512 :: message - CHARACTER*256 :: timestr - INTEGER :: i,j,k, numlevs - REAL, DIMENSION( is:ie, js:je, k_start:k_end ) :: qr & - , qs & - , qg & - , qv & - , qc & - , qi & - , ptot - - REAL, DIMENSION( ishalo:iehalo, jshalo:jehalo) :: wdur_prev, wup_mask_prev - - REAL :: dhail1,dhail2,dhail3,dhail4,dhail5 - -! ! Timing -! ! ------ -! TYPE(WRFU_Time) :: hist_time, aux2_time, CurrTime, StartTime -! TYPE(WRFU_TimeInterval) :: dtint, histint, aux2int -! LOGICAL :: is_after_history_dump, is_output_timestep, is_first_timestep -! LOGICAL :: doing_adapt_dt, run_param, decided -! INTEGER :: stephail, itimestep_basezero - - -! ! Chirp the routine name for debugging purposes -! ! --------------------------------------------- -! write ( message, * ) 'inside hailcast_diagnostics_driver' -! CALL wrf_debug( 100 , message ) - -! ! Get timing info -! ! Want to know if when the last history output was -! ! Check history and auxhist2 alarms to check last ring time and how often -! ! they are set to ring -! ! ----------------------------------------------------------------------- -! CALL WRFU_ALARMGET( grid%alarms( HISTORY_ALARM ), prevringtime=hist_time, & -! ringinterval=histint) -! CALL WRFU_ALARMGET( grid%alarms( AUXHIST2_ALARM ), prevringtime=aux2_time, & -! ringinterval=aux2int) - -! ! Get domain clock -! ! ---------------- -! CALL domain_clock_get ( grid, current_time=CurrTime, & -! simulationStartTime=StartTime, & -! current_timestr=timestr, time_step=dtint ) - -! ! Set some booleans for use later -! ! Following uses an overloaded .lt. -! ! --------------------------------- -! is_after_history_dump = ( Currtime .lt. hist_time + dtint ) - -! ! Following uses an overloaded .ge. -! ! --------------------------------- -! is_output_timestep = (Currtime .ge. hist_time + histint - dtint .or. & -! Currtime .ge. aux2_time + aux2int - dtint ) -! write ( message, * ) 'is output timestep? ', is_output_timestep -! CALL wrf_debug( 100 , message ) - -! ! Following uses an overloaded .eq. -! ! --------------------------------- -! is_first_timestep = ( Currtime .eq. StartTime + dtint ) - - master = (mpp_pe()==mpp_root_pe()) .or. is_master() - - !FV3: No need to reset arrays to zero at dump time, thus no need to keep track of dump times - ! - ! After each history dump, reset max/min value arrays - ! ---------------------------------------------------------------------- -! IF ( is_after_history_dump ) THEN - !! DO j = jsc, jec !jts, jte - !! DO i = isc, iec !its, ite - !! hailcast_dhail1(i,j) = 0. - !! hailcast_dhail2(i,j) = 0. - !! hailcast_dhail3(i,j) = 0. - !!! hailcast_dhail4(i,j) = 0. - !! hailcast_dhail5(i,j) = 0. - !! ENDDO - !! ENDDO - !ENDIF ! is_after_history_dump - - ! We need to do some neighboring gridpoint comparisons for the updraft - ! duration calculations; set i,j start and end values so we don't go off - ! the edges of the domain. Updraft duration on domain edges will always be 0. - ! ---------------------------------------------------------------------- - -! !WRF config_flags contains: open_xs, specified, nested,open_xe,open_yx,open_ye,periodic_x -! IF ( config_flags%open_xs .OR. config_flags%specified .OR. & -! config_flags%nested) i_start = MAX( ids+1, its ) -! IF ( config_flags%open_xe .OR. config_flags%specified .OR. & -! config_flags%nested) i_end = MIN( ide-2, ite ) !-1 -! IF ( config_flags%open_ys .OR. config_flags%specified .OR. & -! config_flags%nested) j_start = MAX( jds+1, jts ) -! IF ( config_flags%open_ye .OR. config_flags%specified .OR. & -! config_flags%nested) j_end = MIN( jde-2, jte ) !-1 -! IF ( config_flags%periodic_x ) i_start = its -! IF ( config_flags%periodic_x ) i_end = ite - - - ! Make a copy of the updraft duration, mask variables - ! --------------------------------------------------- - !from WRF: - !!wdur_prev(:,:) = grid%hailcast_wdur(:,:) - !!wup_mask_prev(:,:) = grid%hailcast_wup_mask(:,:) - !DO j = MAX( jts-1 , jds ), MIN( jte+1 , jde-1 ) - ! DO i = MAX( its-1 , ids ), MIN( ite+1 , ide-1) - DO j = jshalo, jehalo - DO i = ishalo, iehalo - wdur_prev(i,j) = hailcast_wdur(i,j) - wup_mask_prev(i,j) = hailcast_wup_mask(i,j) - ENDDO - ENDDO - !update halo: - call mpp_update_domains(wup_mask_prev,domainid) - call mpp_update_domains(wdur_prev,domainid) - - ! Determine updraft mask (where updraft greater than some threshold) - ! --------------------------------------------------- - DO j = js, je - DO i = is, ie - hailcast_wup_mask(i,j) = 0 - hailcast_wdur(i,j) = 0 - - DO k = k_start, k_end - IF ( w(i,j,k) .ge. 10. ) THEN - hailcast_wup_mask(i,j) = 1 - ENDIF - ENDDO - ENDDO - ENDDO - - ! Determine updraft duration; make sure not to call point outside the domain - ! --------------------------------------------------- - DO j = js,je - DO i = is,ie - - ! Determine updraft duration using updraft masks - ! --------------------------------------------------- - IF ( (hailcast_wup_mask(i,j).eq.1) .OR. & - (MAXVAL(wup_mask_prev(i-1:i+1,j-1:j+1)).eq.1) ) THEN - hailcast_wdur(i,j) = MAXVAL(wdur_prev(i-1:i+1,j-1:j+1)) + dt - ENDIF - ENDDO - ENDDO - - !from WRF dealing with calling frequency and adaptive time step; call hailcast every timestep for FV3 - ! - ! Only run the scheme every "haildt" seconds as set in the namelist. - ! Code borrowed from module_pbl_driver, although here haildt is - ! in seconds, not minutes (bldt is in minutes). - ! --------------------------------------------------- - -! ! Are we using adaptive timestepping? -! doing_adapt_dt = .FALSE. -! IF ( (config_flags%use_adaptive_time_step) .and. & -! ( (.not. grid%nested) .or. & -! ( (grid%nested) .and. (abs(grid%dtbc) < 0.0001) ) ) )THEN -! doing_adapt_dt = .TRUE. -! IF ( haildtacttime .eq. 0. ) THEN -! haildtacttime = CURR_SECS + haildt -! END IF -! END IF - -! ! Calculate STEPHAIL -! stephail = NINT(haildt / dt) -! stephail = MAX(stephail,1) - -! ! itimestep starts at 1 - we want it to start at 0 so correctly -! ! divisibile by stephail. -! itimestep_basezero = itimestep -1 - - -! ! Do we run through this scheme or not? -! ! Test 1: If this is the initial model time, then yes. -! ! ITIMESTEP=1 -! ! Test 2: If the user asked for hailcast to be run every time step, then yes. -! ! HAILDT=0 or STEPHAIL=1 -! ! Test 3: If not adaptive dt, and this is on the requested hail frequency, -! ! then yes. -! ! MOD(ITIMESTEP,STEPHAIL)=0 -! ! Test 4: If using adaptive dt and the current time is past the last -! ! requested activate hailcast time, then yes. -! ! CURR_SECS >= HAILDTACTTIME - -! ! If we do run through the scheme, we set the flag run_param to TRUE and we set -! ! the decided flag to TRUE. The decided flag says that one of these tests was -! ! able to say "yes", run the scheme. We only proceed to other tests if the -! ! previous tests all have left decided as FALSE. If we set run_param to TRUE -! ! and this is adaptive time stepping, we set the time to the next hailcast run. - -! run_param = .FALSE. -! decided = .FALSE. -! IF ( ( .NOT. decided ) .AND. & -! ( itimestep_basezero .EQ. 0 ) ) THEN -! run_param = .TRUE. -! decided = .TRUE. -! END IF - -! IF ( PRESENT(haildt) )THEN -! IF ( ( .NOT. decided ) .AND. & -! ( ( haildt .EQ. 0. ) .OR. ( stephail .EQ. 1 ) ) ) THEN -! run_param = .TRUE. -! decided = .TRUE. -! END IF -! ELSE -! IF ( ( .NOT. decided ) .AND. & -! ( stephail .EQ. 1 ) ) THEN -! run_param = .TRUE. -! decided = .TRUE. -! END IF -! END IF - -! IF ( ( .NOT. decided ) .AND. & -! ( .NOT. doing_adapt_dt ) .AND. & -! ( MOD(itimestep_basezero,stephail) .EQ. 0 ) ) THEN -! run_param = .TRUE. -! decided = .TRUE. -! END IF - -! IF ( ( .NOT. decided ) .AND. & -! ( doing_adapt_dt ) .AND. & -! ( curr_secs .GE. haildtacttime ) ) THEN -! run_param = .TRUE. -! decided = .TRUE. -! haildtacttime = curr_secs + haildt -! END IF - -! write ( message, * ) 'timestep to run HAILCAST? ', run_param -! CALL wrf_debug( 100 , message ) - -! IF (run_param) THEN - - ! 3-D arrays for moisture variables - ! --------------------------------- - numlevs=k_end-k_start+1 - DO i=is, ie - DO k=1, numlevs - DO j=js, je - qv(i,j,k)=0;qr(i,j,k)=0;qs(i,j,k)=0;qg(i,j,k)=0;qc(i,j,k)=0;qi(i,j,k)=0 - qv(i,j,k) = q(i,j,k,sphum) - qr(i,j,k) = q(i,j,k,rainwat) - qs(i,j,k) = q(i,j,k,snowwat) - qg(i,j,k) = q(i,j,k,graupel) - qc(i,j,k) = q(i,j,k,liq_wat) - qi(i,j,k) = q(i,j,k,ice_wat) - ENDDO - ENDDO - ENDDO - - ! Hail diameter in millimeters (HAILCAST) - ! --------------------------------------------------- - DO j = js, je - DO i = is, ie - ! Only call hailstone driver if updraft has been - ! around longer than 15 min - ! ---------------------------------------------- - IF (hailcast_wdur(i,j) .gt. 900) THEN - dhail1=0;dhail2=0;dhail3=0;dhail4=0;dhail5=0 - CALL hailstone_driver (i,j, t(i,j,k_end:k_start:-1), & - z(i,j,k_end:k_start:-1), & - terr_z(i,j), & - p(i,j,k_end:k_start:-1), & - rho(i,j,k_end:k_start:-1), & - qv(i,j,k_end:k_start:-1), & - qi(i,j,k_end:k_start:-1), & - qc(i,j,k_end:k_start:-1), & - qr(i,j,k_end:k_start:-1), & - qs(i,j,k_end:k_start:-1), & - qg(i,j,k_end:k_start:-1), & - w(i,j,k_end:k_start:-1), & - hailcast_wdur(i,j), & - numlevs, & - dhail1, dhail2, & - dhail3, dhail4, & - dhail5 ) - - !diag_table should select largest value of these variables during requested period - !thus do not need to accumulate largest value between data dumps - !IF (dhail1 .gt. hailcast_dhail1(i,j)) THEN - hailcast_dhail1(i,j) = dhail1 - !ENDIF - !IF (dhail2 .gt. hailcast_dhail2(i,j)) THEN - hailcast_dhail2(i,j) = dhail2 - !ENDIF - !IF (dhail3 .gt. hailcast_dhail3(i,j)) THEN - hailcast_dhail3(i,j) = dhail3 - !ENDIF - !IF (dhail4 .gt. hailcast_dhail4(i,j)) THEN - hailcast_dhail4(i,j) = dhail4 - !ENDIF - !IF (dhail5 .gt. hailcast_dhail5(i,j)) THEN - hailcast_dhail5(i,j) = dhail5 - !ENDIF - ENDIF - ENDDO - ENDDO - - ! Calculate the mean and standard deviation of the hail diameter - ! distribution over different embryo sizes - ! ---------------------------------------- - DO j = js, je - DO i = is, ie - !mean - hailcast_diam_mean(i,j)=(hailcast_dhail1(i,j)+& - hailcast_dhail2(i,j) +hailcast_dhail3(i,j)+& - hailcast_dhail4(i,j) +hailcast_dhail5(i,j))/5. - !max - !hailcast_diam_max(i,j)=MAX(hailcast_dhail1(i,j),& - ! hailcast_dhail2(i,j), hailcast_dhail3(i,j),& - ! hailcast_dhail4(i,j), hailcast_dhail5(i,j)) - !sample standard deviation - hailcast_diam_std(i,j) = SQRT( ( & - (hailcast_dhail1(i,j)-hailcast_diam_mean(i,j))**2.+& - (hailcast_dhail2(i,j)-hailcast_diam_mean(i,j))**2.+& - (hailcast_dhail3(i,j)-hailcast_diam_mean(i,j))**2.+& - (hailcast_dhail4(i,j)-hailcast_diam_mean(i,j))**2.+& - (hailcast_dhail5(i,j)-hailcast_diam_mean(i,j))**2.)& - / 4.0) - ENDDO - ENDDO - if (hailcast_diam_mean(i,j).ne.0.0 .and. hailcast_diam_std(i,j).ne.0.0) print*,'jmh mean std=',i,j,hailcast_diam_mean(i,j),hailcast_diam_std(i,j) - !END IF - -END SUBROUTINE hailcast_diagnostic_driver - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!!!! -!!!! Hailstone driver, adapted from hailstone subroutine in HAILCAST -!!!! Inputs: -!!!! 1-d (nz) -!!!! TCA temperature (K) -!!!! h1d height above sea level (m) -!!!! PA total pressure (Pa) -!!!! rho1d density (kg/m3) -!!!! RA vapor mixing ratio (kg/kg) -!!!! qi1d cloud ice mixing ratio (kg/kg) -!!!! qc1d cloud water mixing ratio (kg/kg) -!!!! qr1d rain water mixing ratio (kg/kg) -!!!! qg1d graupel mixing ratio (kg/kg) -!!!! qs1d snow mixing ratio (kg/kg) -!!!! VUU updraft speed at each level (m/s) -!!!! Float -!!!! ht terrain height (m) -!!!! wdur duration of any updraft > 10 m/s within 1 surrounding -!!!! gridpoint -!!!! Integer -!!!! nz number of vertical levels -!!!! -!!!! Output: -!!!! dhail hail diameter in mm -!!!! 1st-5th rank-ordered hail diameters returned -!!!! -!!!! 13 Aug 2013 .................................Becky Adams-Selin AER -!!!! adapted from hailstone subroutine in SPC's HAILCAST -!!!! 18 Mar 2014 .................................Becky Adams-Selin AER -!!!! added variable rime layer density, per Ziegler et al. (1983) -!!!! 4 Jun 2014 ..................................Becky Adams-Selin AER -!!!! removed initial embryo size dependency on microphysics scheme -!!!! 5 Jun 2014 ..................................Becky Adams-Selin AER -!!!! used smaller initial embryo sizes -!!!! 25 Jun 2015..................................Becky Adams-Selin AER -!!!! Significant revamping. Fixed units bug in HEATBUD that caused -!!!! hailstone temperature instabilities. Similar issue fixed in BREAKUP -!!!! subroutine. Removed graupel from ice content. Changed initial -!!!! embryo size and location to better match literature. Added -!!!! enhanced melting when hailstone collides with liquid water -!!!! in regions above freezing. Final diameter returned is ice diameter -!!!! only. Added hailstone temperature averaging over previous timesteps -!!!! to decrease initial temperature instability at small embyro diameters. -!!!! 3 Sep 2015...................................Becky Adams-Selin AER -!!!! Insert embryos at -13C; interpret pressure and other variables to -!!!! that exact temperature level. -!!!! 16 Nov 2015...................................Becky Adams-Selin AER -!!!! Hailstone travels horizontally through updraft instead of being -!!!! locked in the center. -!!!! 9 Jul 2016...................................Becky Adams-Selin AER -!!!! Uses an adiabatic liquid cloud water profile generated from -!!!! the saturation vapor pressure using the model temperature -!!!! profile. -!!!! 04 Feb 2017...................................Becky Adams-Selin AER -!!!! Added adaptive time-stepping option. -!!!! ***Don't set any higher than 60 seconds*** -!!!! 06 May 2017...................................Becky Adams-Selin AER -!!!! Bug fixes for some memory issues in the adiabatic liquid -!!!! water profile code. -!!!! -!!!! See Adams-Selin and Ziegler 2016, MWR for further documentation. -!!!! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - SUBROUTINE hailstone_driver ( ii,jj,TCA, h1d, ht, PA, rho1d,& - RA, qi1d,qc1d,qr1d,qs1d,qg1d, & - VUU, wdur, & - nz,dhail1,dhail2,dhail3,dhail4, & - dhail5 ) - IMPLICIT NONE - INTEGER, INTENT(IN ) :: nz, ii,jj - - REAL, DIMENSION( nz ), & - INTENT(IN ) :: TCA & ! temperature (K) - , rho1d & - , h1d & - , PA & ! pressure (Pa) - , RA & ! vapor mixing ratio (kg/kg) - , VUU & ! updraft speed (m/s) - , qi1d,qc1d,qr1d & - , qs1d,qg1d - - REAL, INTENT(IN ) :: ht & - , wdur - - !Output: 1st-5th rank-ordered hail diameters returned - REAL, INTENT(INOUT) :: dhail1 & ! hail diameter (mm); - , dhail2 & - , dhail3 & - , dhail4 & - , dhail5 - !Local variables - REAL ZBAS, TBAS, WBASP ! height, temp, pressure of cloud base - REAL RBAS ! mix ratio of cloud base - REAL cwitot ! total cloud water, ice mix ratio - INTEGER KBAS ! k of cloud base - REAL tk_embryo ! temperature at which initial embryo is inserted - REAL ZFZL, TFZL, WFZLP ! height, temp, pressure of embryo start point - REAL RFZL ! mix ratio of embryo start point - REAL VUFZL, DENSAFZL ! updraft speed, density of embryo start point - INTEGER KFZL ! k of embryo start point - INTEGER nofroze ! keeps track if hailstone has ever been frozen - INTEGER CLOUDON ! use to zero out cloud water, ice once past updraft duration - REAL RTIME ! real updraft duration (sec) - REAL TAU, TAU_1, TAU_2 ! upper time limit of simulation (sec) - REAL delTAU ! difference between TAU_2 and TAU_1 (sec) - REAL g ! gravity (m/s) - REAL r_d ! constant - !hailstone parameters - REAL*8 DD, D, D_ICE ! hail diameter (m) - REAL VT ! terminal velocity (m/s) - REAL V ! actual stone velocity (m/s) - REAL TS ! hailstone temperature (K) - !HAILSTONE temperature differencing - REAL TSm1, TSm2 ! hailstone temperature at previous 3 timesteps - REAL FW ! fraction of stone that is liquid - REAL WATER ! mass of stone that is liquid - REAL CRIT ! critical water mass allowed on stone surface - REAL DENSE ! hailstone density (kg/m3) - INTEGER ITYPE ! wet (2) or dry (1) growth regime - !1-d column arrays of updraft parameters - REAL, DIMENSION( nz ) :: & - RIA, & ! frozen content mix ratio (kg/kg) - RWA, & ! liquid content mix ratio (kg/kg) - VUU_pert ! perturbed updraft profile (m/s) - !1-d column arrays of updraft characteristics for adiabatic water profile - REAL, DIMENSION( nz ) :: & - RWA_adiabat, & ! adiabatic liquid content mixing ratio (kg/kg) - RWA_new, & - ESVA, & ! saturation vapor pressure - RSA ! saturation mixing ratio - !in-cloud updraft parameters at location of hailstone - REAL P ! in-cloud pressure (Pa) - REAL RS ! in-cloud saturation mixing ratio - REAL RI, RW ! ice, liquid water mix. ratio (kg/kg) - REAL XI, XW ! ice, liquid water content (kg/m3 air) - REAL PC ! in-cloud fraction of frozen water - REAL TC ! in-cloud temperature (K) - REAL VU ! in-cloud updraft speed (m/s) - REAL VUMAX ! in-cloud updraft speed read from WRF (max allowed) - REAL VUCORE ! perturbed in-cloud updraft speed - REAL DENSA ! in-cloud updraft density (kg/m3) - REAL Z ! height of hailstone (m) - REAL DELRW ! diff in sat vap. dens. between hail and air (kg/m3) - REAL, DIMENSION(5) :: dhails !hail diameters from 5 different embryo size - !mean sub-cloud layer variables - REAL TLAYER,RLAYER,PLAYER ! mean sub-cloud temp, mix ratio, pres - REAL TSUM,RSUM,PSUM ! sub-cloud layer T, R, P sums - REAL LDEPTH ! layer depth - !internal function variables - REAL GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DGMV,DI,ANU,RE,AE - REAL dum, icefactor, adiabatic_factor - - REAL sec, secdel ! time step, increment in seconds - INTEGER i, j, k, IFOUT, ind(1) - CHARACTER*256 :: message - - secdel = 5.0 - g=9.81 - r_d = 287. - - !!!!!!!!!!!!!!!! 1. UPDRAFT PROPERTIES !!!!!!!!!!!!!!!!!!!!!!! - !!! DEFINE UPDRAFT PROPERTIES !!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -! Upper limit of simulation in seconds - TAU = 7200. !simulation ends - - !Set initial updraft strength - you could reduce to simulate the embryo - ! hovering around the edges of the updraft, as in Heymsfield and Musil (1982) - DO i=1,nz - VUU_pert(i) = VUU(i) * 1. - ENDDO - - -! Initialize diameters to 0. - DO i=1,5 - dhails(i) = 0. - ENDDO - -! Cap updraft lifetime at 2000 sec. - IF (wdur .GT. 2000) THEN - RTIME = 2000. - ELSE - RTIME = wdur - ENDIF - - - !!!!!!!!!!!!!!!! 2. INITIAL EMBRYO !!!!!!!!!!!!!!!!!!!!!!!!!!! - !!! FIND PROPERTIES OF INITIAL EMBRYO LOCATION !!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !Find the cloud base for end-of-algorithm purposes. - KBAS=nz - !KFZL=nz - DO k=1,nz - cwitot = qi1d(k) + qc1d(k) - !No longer include graupel in in-cloud ice amounts - !RIA(k) = qi1d(k) + qs1d(k) + qg1d(k) - RIA(k) = qi1d(k) + qs1d(k) - !RWA(k) = qc1d(k) + qr1d(k) - RWA(k) = qc1d(k) - !IF ((RIA(k) .ge. 0.0001) .and. (TCA(k).lt.260.155) .and. & - ! (k .lt. KFZL)) THEN - ! KFZL = k - !ENDIF - IF ((cwitot .ge. 1.E-12) .and. (k .lt. KBAS)) THEN - KBAS = k - ENDIF - ENDDO - !QC - our embryo can't start below the cloud base. - !IF (KFZL .lt. KBAS) THEN - ! KFZL = KBAS - !ENDIF - - !Pull heights, etc. of these levels out of 1-d arrays. - ZBAS = h1d(KBAS) - TBAS = TCA(KBAS) - WBASP = PA(KBAS) - RBAS = RA(KBAS) - - !At coarser resolutions WRF underestimates liquid water aloft. - !A fairer estimate is of the adiabatic liquid water profile, or - !the difference between the saturation mixing ratio at each level - !and the cloud base water vapor mixing ratio - DO k=1,nz - RWA_new(k) = RWA(k) - IF (k.LT.KBAS) THEN - RWA_adiabat(k) = 0. - CYCLE - ENDIF - !saturation vapor pressure - !ESVA(k) = 6.112*exp((2.453E6/461)*(1./273. - 1./TCA(k))) !hPa - ESVA(k) = 611.2*exp(17.67*(TCA(k)-273.155)/(TCA(k)-29.655)) !Pa - !saturation vapor mixing ratio - RSA(k) = 0.62197 * ESVA(k) / (PA(k) - ESVA(k)) - !Up above -31, start converting to ice, entirely by -38 - !(Rosenfeld and Woodley 2000) - IF (TCA(k).gt.242.155) THEN - icefactor = 1. - ELSE IF ((TCA(k).LE.242.155).AND.(TCA(k).GT.235.155)) THEN - icefactor = (1-(242.155-TCA(k))/5.) - ELSE - icefactor = 0. - ENDIF - !Don't want any negative liquid water values - IF (RBAS.GT.RSA(k)) THEN - RWA_adiabat(k) = (RBAS - RSA(k))*icefactor - ELSE - RWA_adiabat(k) = RWA(k) - ENDIF - !Remove cloud liquid water outputted at previous lower levels - ! -- bug fix 170506 -- ! - IF (k.eq.KBAS) THEN - RWA_new(k) = RWA_adiabat(k) - ELSE IF ((k.ge.KBAS+1).AND.(RWA_adiabat(k).ge.1.E-12)) THEN - RWA_new(k) = RWA_adiabat(k)*(h1d(k)-h1d(k-1)) - RWA_new(k-1) - IF (RWA_new(k).LT.0) RWA_new(k) = 0. - ENDIF - ! - old code - ! - !IF (k.eq.KBAS+1) THEN - ! RWA_new(k) = RWA_adiabat(k)*(h1d(k)-h1d(k-1)) - !ELSE IF ((k.ge.KBAS+2).AND.(RWA_adiabat(k).ge.1.E-12)) THEN - ! RWA_new(k) = RWA_adiabat(k)*(h1d(k)-h1d(k-1)) - RWA_new(k-1) - ! IF (RWA_new(k).LT.0) RWA_new(k) = 0. - !ENDIF - ENDDO - !remove the height factor from RWA_new - DO k=KBAS,nz - RWA_new(k) = RWA_new(k) / (h1d(k)-h1d(k-1)) - ENDDO - - - - !!!!!!!!!!!!!!!! 3. INITIAL EMBRYO SIZE !!!!!!!!!!!!!!!!!!!!! - !!! SET CONSTANT RANGE OF INITIAL EMBRYO SIZES !!! - !!! START LOOP !!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ! See Adams-Selin and Ziegler 2016 MWR for explanation of why - ! these sizes were picked. - !Run each initial embryo size perturbation - DO i=1,5 - SELECT CASE (i) - CASE (1) - !Initial hail embryo diameter in m, at cloud base - DD = 5.E-3 - tk_embryo = 265.155 !-8C - CASE (2) - DD = 7.5E-3 - tk_embryo = 265.155 !-8C - CASE (3) - DD = 5.E-3 - tk_embryo = 260.155 !-13C - CASE (4) - DD = 7.5E-3 - tk_embryo = 260.155 !-13C - CASE (5) - tk_embryo = 260.155 !-13C - DD = 1.E-2 - END SELECT - - - RTIME = 2000. - IF (wdur .LT. RTIME) RTIME = wdur - - TFZL = tk_embryo - CALL INTERPP(PA, WFZLP, TCA, tk_embryo, IFOUT, nz) - CALL INTERP(h1d, ZFZL, WFZLP, IFOUT, PA, nz) - CALL INTERP(RA, RFZL, WFZLP, IFOUT, PA, nz) - CALL INTERP(VUU_pert, VUFZL, WFZLP, IFOUT, PA, nz) - CALL INTERP(rho1d, DENSAFZL, WFZLP, IFOUT, PA, nz) - - !Begin hail simulation time (seconds) - sec = 0. - - - !!!!!!!!!!!!!!!!!! 4. INITIAL PARAMETERS !!!!!!!!!!!!!!!!! - !!! PUT INITIAL PARAMETERS IN VARIABLES !!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !Set initial values for parameters at freezing level - P = WFZLP - RS = RFZL - TC = TFZL - VU = VUFZL - Z = ZFZL - ht - LDEPTH = Z - DENSA = DENSAFZL - - !Set initial hailstone parameters - nofroze=1 !Set test for embryo: 0 for never been frozen; 1 frozen - TS = TC - TSm1 = TS - TSm2 = TS - D = DD !hailstone diameter in m - FW = 0.0 - DENSE = 500. !kg/m3 - ITYPE=1. !Assume starts in dry growth. - CLOUDON=1 !we'll eventually turn cloud "off" once updraft past time limit - - !Start time loop. - DO WHILE (sec .lt. TAU) - sec = sec + secdel - - !!!!!!!!!!!!!!!!!! 5. CALCULATE PARAMETERS !!!!!!!!!!!!!!!!! - !!! CALCULATE UPDRAFT PROPERTIES !!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !Intepolate vertical velocity to our new pressure level - CALL INTERP(VUU_pert,VUMAX,P,IFOUT,PA,nz) - !print *, 'INTERP VU: ', VU, P - - !Outside pressure levels? If so, exit loop - IF (IFOUT.EQ.1) GOTO 100 - - !Sine wave multiplier on updraft strength - IF (SEC .GT. 0.0 .AND. SEC .LT. RTIME) THEN - VUCORE = VUMAX * (0.5*SIN((3.14159*SEC)/(RTIME))+0.5)*1.2 - VU = VUCORE - ELSEIF (SEC .GE. RTIME) THEN - VU = 0.0 - CLOUDON = 0 - ENDIF - - !Calculate terminal velocity of the hailstone - ! (use previous values) - CALL TERMINL(DENSA,DENSE,D,VT,TC) - - !Actual velocity of hailstone (upwards positive) - V = VU - VT - - !Use hydrostatic eq'n to calc height of next level - P = P - DENSA*g*V*secdel - Z = Z + V*secdel - - !Interpolate cloud temp, qvapor at new p-level - CALL INTERP(TCA,TC,P,IFOUT,PA,nz) - CALL INTERP(RA,RS,P,IFOUT,PA,nz) - - !New density of in-cloud air - DENSA=P/(r_d*(1.+0.609*RS/(1.+RS))*TC) - - !Interpolate liquid, frozen water mix ratio at new level - CALL INTERP(RIA,RI,P,IFOUT,PA,nz) - CALL INTERP(RWA_new,RW,P,IFOUT,PA,nz) - XI = RI * DENSA * CLOUDON - XW = RW * DENSA * CLOUDON - IF( (XW+XI).GT.0) THEN - PC = XI / (XW+XI) - ELSE - PC = 1. - ENDIF - - - ! SATURATION VAPOUR DENSITY DIFFERENCE BETWTEEN STONE AND CLOUD - CALL VAPORCLOSE(DELRW,PC,TS,TC,ITYPE) - - - !!!!!!!!!!!!!!!!!! 6. STONE'S MASS GROWTH !!!!!!!!!!!!!!!!!!!! - CALL MASSAGR(D,GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DGMV,DI,ANU,RE,AE,& - TC,TS,P,DENSE,DENSA,FW,VT,XW,XI,secdel,ITYPE,DELRW) - - - !!!!!!!!!!!!!!!!!! 7. HEAT BUDGET OF HAILSTONE !!!!!!!!!!!!!!! - CALL HEATBUD(TS,TSm1,TSm2,FW,TC,VT,DELRW,D,DENSA,GM1,GM,DGM,DGMW, & - DGMV,DGMI,GMW,GMI,DI,ANU,RE,AE,secdel,ITYPE,P) - - - !!!!! 8. TEST DIAMETER OF STONE AND HEIGHT ABOVE GROUND !!!!!!! - !!! TEST IF DIAMETER OF STONE IS GREATER THAN CRITICAL LIMIT, IF SO - !!! BREAK UP - WATER=FW*GM !KG - ! CRTICAL MASS CAPABLE OF BEING "SUPPORTED" ON THE STONE'S SURFACE - CRIT = 2.0E-4 - IF (WATER.GT.CRIT)THEN - CALL BREAKUP(DENSE,D,GM,FW,CRIT) - ENDIF - - !!! Has stone reached below cloud base? - !IF (Z .LE. 0) GOTO 200 - IF (Z .LE. ZBAS) then - GOTO 200 - endif - - !calculate ice-only diameter size - D_ICE = ( (6*GM*(1.-FW)) / (3.141592654*DENSE) )**0.33333333 - - !Has the stone entirely melted and it's below the freezing level? - IF ((D_ICE .LT. 1.E-8) .AND. (TC.GT.273.155)) GOTO 300 - - !move values to previous timestep value - TSm1 = TS - TSm2 = TSm1 - - ENDDO !end cloud lifetime loop - -100 CONTINUE !outside pressure levels in model -200 CONTINUE !stone reached surface -300 CONTINUE !stone has entirely melted and is below freezing level - - !!!!!!!!!!!!!!!!!! 9. MELT STONE BELOW CLOUD !!!!!!!!!!!!!!!!!!!! - !Did the stone shoot out the top of the storm? - !Then let's assume it's lost in the murky "outside storm" world. - IF (P.lt.PA(nz)) THEN - D=0.0 - !Is the stone entirely water? Then set D=0 and exit. - ELSE IF(ABS(FW - 1.0).LT.0.001) THEN - D=0.0 - ELSE IF (Z.GT.0) THEN - !If still frozen, then use melt routine to melt below cloud - ! based on mean below-cloud conditions. - - !Calculate mean sub-cloud layer conditions - TSUM = 0. - RSUM = 0. - PSUM = 0. - DO k=1,KBAS - TSUM = TSUM + TCA(k) - PSUM = PSUM + PA(k) - RSUM = RSUM + RA(k) - ENDDO - TLAYER = TSUM / KBAS - PLAYER = PSUM / KBAS - RLAYER = RSUM / KBAS - - !MELT is expecting a hailstone of only ice. At the surface - !we're only interested in the actual ice diameter of the hailstone, - !so let's shed any excess water now. - D_ICE = ( (6*GM*(1.-FW)) / (3.141592654*DENSE) )**0.33333333 - D = D_ICE - CALL MELT(D,TLAYER,PLAYER,RLAYER,LDEPTH,VT) - - ENDIF !end check for melting call - - !Check to make sure embryo didn’t just immediately fall out - IF (sec .LT. 60) D=0.0 - - !Check to make sure something hasn't gone horribly wrong - IF (D.GT.0.254) D = 0. !just consider missing for now if > 10 in - - !assign hail size in mm for output - !dhails(i) = D * 1000 - dhails(i) = D - - ENDDO !end embryo size loop - - - dhail1 = dhails(1) - dhail2 = dhails(2) - dhail3 = dhails(3) - dhail4 = dhails(4) - dhail5 = dhails(5) - - !Testing diagnostics that can be commented out, but please keep - if (0.eq.1) then - print*,'jmh KBAS,ZBAS,TBAS',ii,jj,KBAS,ZBAS,TBAS - print*,'jmh WBASP,RBAS=',ii,jj,WBASP,RBAS - print*,'jmh embryo sizes: ',ii,jj,dhail1,dhail2,dhail3,dhail4,dhail5 - if (ii.eq. 847 .and. jj.eq.394) then - print*,'jmh i=847,j=394 TCA:',ii,jj,TCA(1:nz) - print*,'jmh i=847,j=394 h1d:',ii,jj,h1d(1:nz) - print*,'jmh i=847,j=394 ht:',ii,jj,ht - print*,'jmh i=847,j=394 PA:',ii,jj,PA(1:nz) - print*,'jmh i=847,j=394 rho1d:',ii,jj,rho1d(1:nz) - print*,'jmh i=847,j=394 RA:',ii,jj,RA(1:nz) - print*,'jmh i=847,j=394 qi1d:',ii,jj,qi1d(1:nz) - print*,'jmh i=847,j=394 qc1d:',ii,jj,qc1d(1:nz) - print*,'jmh i=847,j=394 qr1d:',ii,jj,qr1d(1:nz) - print*,'jmh i=847,j=394 qs1d:',ii,jj,qs1d(1:nz) - print*,'jmh i=847,j=394 qg1d:',ii,jj,qg1d(1:nz) - print*,'jmh i=847,j=394 VUU:',ii,jj,VUU(1:nz) - print*,'jmh i=847,j=394 wdur:',ii,jj,wdur - print*,'jmh i=847,j=394 nz:',ii,jj,nz - endif - if (KBAS .gt. 30) then - print*,'jmh KBAS>30 TCA:',ii,jj,TCA(1:nz) - print*,'jmh KBAS>30 h1d:',ii,jj,h1d(1:nz) - print*,'jmh KBAS>30 ht:',ii,jj,ht - print*,'jmh KBAS>30 PA:',ii,jj,PA(1:nz) - print*,'jmh KBAS>30 rho1d:',ii,jj,rho1d(1:nz) - print*,'jmh KBAS>30 RA:',ii,jj,RA(1:nz) - print*,'jmh KBAS>30 qi1d:',ii,jj,qi1d(1:nz) - print*,'jmh KBAS>30 qc1d:',ii,jj,qc1d(1:nz) - print*,'jmh KBAS>30 qr1d:',ii,jj,qr1d(1:nz) - print*,'jmh KBAS>30 qs1d:',ii,jj,qs1d(1:nz) - print*,'jmh KBAS>30 qg1d:',ii,jj,qg1d(1:nz) - print*,'jmh KBAS>30 VUU:',ii,jj,VUU(1:nz) - print*,'jmh KBAS>30 wdur:',ii,jj,wdur - print*,'jmh KBAS>30 nz:',ii,jj,nz - endif - print*,'jmh ------end of hailstone driver------- jmh' - endif - END SUBROUTINE hailstone_driver - - - SUBROUTINE INTERPP(PA,PVAL,TA,TVAL,IFOUT,ITEL) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!!! - !!!! INTERP: to linearly interpolate value of pval at temperature tval - !!!! between two levels of pressure array pa and temperatures ta - !!!! - !!!! INPUT: PA 1D array of pressure, to be interpolated - !!!! TA 1D array of temperature - !!!! TVAL temperature value at which we want to calculate pressure - !!!! IFOUT set to 0 if TVAL outside range of TA - !!!! ITEL number of vertical levels - !!!! OUTPUT: PVAL interpolated pressure variable at temperature tval - !!!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - IMPLICIT NONE - - REAL PVAL, TVAL - REAL, DIMENSION( ITEL) :: TA, PA - INTEGER ITEL, IFOUT - !local variables - INTEGER I - REAL FRACT - - IFOUT=1 - - DO I=1,ITEL-1 - IF ( (TVAL .LT. TA(I) .AND. TVAL .GE. TA(I+1)) .or. & ! dT/dz < 0 - (TVAL .GT. TA(I) .AND. TVAL .LE. TA(I+1)) ) THEN ! dT/dz > 0 - - FRACT = (TA(I) - TVAL) / (TA(I) - TA(I+1)) - !.... compute the pressure value pval at temperature tval - PVAL = ((1.0 - FRACT) * PA(I)) + (FRACT * PA(I+1)) - - !End loop - IFOUT=0 - EXIT - ENDIF - ENDDO - - END SUBROUTINE INTERPP - - - - SUBROUTINE INTERP(AA,A,P,IFOUT,PA,ITEL) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!!! - !!!! INTERP: to linearly interpolate values of A at level P - !!!! between two levels of AA (at levels PA) - !!!! - !!!! INPUT: AA 1D array of variable - !!!! PA 1D array of pressure - !!!! P new pressure level we want to calculate A at - !!!! IFOUT set to 0 if P outside range of PA - !!!! ITEL number of vertical levels - !!!! OUTPUT: A variable at pressure level P - !!!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - IMPLICIT NONE - - REAL A, P - REAL, DIMENSION( ITEL) :: AA, PA - INTEGER ITEL, IFOUT - !local variables - INTEGER I - REAL PDIFF, VDIFF, RDIFF, VERH, ADIFF - - IFOUT=1 - - DO I=1,ITEL-1 - IF (P.LE.PA(I) .AND. P.GT.PA(I+1)) THEN - !Calculate ratio between vdiff and pdiff - PDIFF = PA(I)-PA(I+1) - VDIFF = PA(I)-P - VERH = VDIFF/PDIFF - - !Calculate the difference between the 2 A values - RDIFF = AA(I+1) - AA(I) - - !Calculate new value - A = AA(I) + RDIFF*VERH - - !End loop - IFOUT=0 - EXIT - ENDIF - ENDDO - - END SUBROUTINE INTERP - - - SUBROUTINE TERMINL(DENSA,DENSE,D,VT,TC) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!!! - !!!! INTERP: Calculate terminal velocity of the hailstone - !!!! - !!!! INPUT: DENSA density of updraft air (kg/m3) - !!!! DENSE density of hailstone - !!!! D diameter of hailstone (m) - !!!! TC updraft temperature (K) - !!!! OUTPUT:VT hailstone terminal velocity (m/s) - !!!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - IMPLICIT NONE - - REAL*8 D - REAL DENSA, DENSE, TC, VT - REAL GMASS, GX, RE, W, Y - REAL, PARAMETER :: PI = 3.141592654, G = 9.78956 - REAL ANU - - !Mass of stone in kg - GMASS = (DENSE * PI * (D**3.)) / 6. - - !Dynamic viscosity - ANU = (0.00001718)*(273.155+120.)/(TC+120.)*(TC/273.155)**(1.5) - - !CALC THE BEST NUMBER, X AND REYNOLDS NUMBER, RE - GX=(8.0*GMASS*G*DENSA)/(PI*(ANU*ANU)) - RE=(GX/0.6)**0.5 - - !SELECT APPROPRIATE EQUATIONS FOR TERMINAL VELOCITY DEPENDING ON - !THE BEST NUMBER - IF (GX.LT.550) THEN - W=LOG10(GX) - Y= -1.7095 + 1.33438*W - 0.11591*(W**2.0) - RE=10**Y - VT=ANU*RE/(D*DENSA) - ELSE IF (GX.GE.550.AND.GX.LT.1800) THEN - W=LOG10(GX) - Y= -1.81391 + 1.34671*W - 0.12427*(W**2.0) + 0.0063*(W**3.0) - RE=10**Y - VT=ANU*RE/(D*DENSA) - ELSE IF (GX.GE.1800.AND.GX.LT.3.45E08) THEN - RE=0.4487*(GX**0.5536) - VT=ANU*RE/(D*DENSA) - ELSE - RE=(GX/0.6)**0.5 - VT=ANU*RE/(D*DENSA) - ENDIF - - END SUBROUTINE TERMINL - - - - SUBROUTINE VAPORCLOSE(DELRW,PC,TS,TC,ITYPE) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!! VAPORCLOSE: CALC THE DIFFERENCE IN SATURATION VAPOUR DENSITY - !!! BETWEEN THAT OVER THE HAILSTONE'S SURFACE AND THE IN-CLOUD - !!! AIR, DEPENDS ON THE WATER/ICE RATIO OF THE UPDRAFT, - !!! AND IF THE STONE IS IN WET OR DRY GROWTH REGIME - !!! - !!! INPUT: PC fraction of updraft water that is frozen - !!! TS temperature of hailstone (K) - !!! TC temperature of updraft air (K) - !!! ITYPE wet (2) or dry (1) growth regime - !!! OUTPUT: DELRW difference in sat vap. dens. between hail and air - !!! (kg/m3) - !!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - IMPLICIT NONE - REAL DELRW, PC, TS, TC - INTEGER ITYPE - !local variables - REAL RV, ALV, ALS, RATIO - DATA RV/461.48/,ALV/2500000./,ALS/2836050./ - REAL ESAT, RHOKOR, ESATW, RHOOMGW, ESATI, RHOOMGI, RHOOMG - - !!! FOR HAILSTONE: FIRST TEST IF STONE IS IN WET OR DRY GROWTH - RATIO = 1./273.155 - IF(ITYPE.EQ.2) THEN !!WET GROWTH - ESAT=611.*EXP(ALV/RV*(RATIO-1./TS)) - ELSE !!DRY GROWTH - ESAT=611.*EXP(ALS/RV*(RATIO-1./TS)) - ENDIF - RHOKOR=ESAT/(RV*TS) - - !!! NOW FOR THE AMBIENT/IN-CLOUD CONDITIONS - ESATW=611.*EXP(ALV/RV*(RATIO-1./TC)) - RHOOMGW=ESATW/(RV*TC) - ESATI=611.*EXP(ALS/RV*(RATIO-1./TC)) - RHOOMGI=ESATI/(RV*TC) - !RHOOMG=PC*(RHOOMGI-RHOOMGW)+RHOOMGW - RHOOMG = RHOOMGI !done as in hailtraj.f - - !!! CALC THE DIFFERENCE(KG/M3): <0 FOR CONDENSATION, - !!! >0 FOR EVAPORATION - DELRW=(RHOKOR-RHOOMG) - - END SUBROUTINE VAPORCLOSE - - - - SUBROUTINE MASSAGR(D,GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DGMV,DI,ANU,RE,AE,& - TC,TS,P,DENSE,DENSA,FW,VT,XW,XI,SEKDEL,ITYPE,DELRW) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!! CALC THE STONE'S INCREASE IN MASS - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - IMPLICIT NONE - REAL*8 D - REAL GM,GM1,GMW,GMI,DGM,DGMW,DGMI,DI,ANU,RE,AE, & - TC,TS,P,DENSE,DENSA,FW,VT,XW,XI,SEKDEL,DELRW - INTEGER ITYPE - !local variables - REAL PI, D0, GMW2, GMI2, EW, EI,DGMV - REAL DENSEL, DENSELI, DENSELW - REAL DC !MEAN CLOUD DROPLET DIAMETER (MICRONS, 1E-6M) - REAL VOLL, VOLT !VOLUME OF NEW LAYER, TOTAL (M3) - REAL VOL1, DGMW_NOSOAK, SOAK, SOAKM - REAL DENSAC, E, AFACTOR, NS, TSCELSIUS, VIMP, W - PI=3.141592654 - - !!! CALCULATE THE DIFFUSIVITY DI (m2/s) - D0=0.226*1.E-4 ! change to m2/s, not cm2/s - DI=D0*(TC/273.155)**1.81*(100000./P) - - !!! COLLECTION EFFICIENCY FOR WATER AND ICE - !EW=1.0 - !!!! IF TS WARMER THAN -5C THEN ACCRETE ALL THE ICE (EI=1.0) - !!!! OTHERWISE EI=0.21 - !IF(TS.GE.268.15)THEN - ! EI=1.00 - !ELSE - ! EI=0.21 - !ENDIF - - !!! COLLECTION EFFICIENCY FOR WATER AND ICE - EW=1.0 - !!! Linear function for ice accretion efficiency - IF (TC .GE. 273.155) THEN - EI=1.00 - ELSE IF (TC.GE.233.155) THEN - EI= 1.0 - ( (273.155 - TS) / 40. ) - ELSE !cooler than -40C - EI = 0.0 - ENDIF - - !!! CALCULATE THE VENTILATION COEFFICIENT - NEEDED FOR GROWTH FROM VAPOR - !The coefficients in the ventilation coefficient equations have been - !experimentally derived, and are expecting cal-C-g units. Do some conversions. - DENSAC = DENSA * (1.E3) * (1.E-6) - !dynamic viscosity - ANU=1.717E-4*(393.0/(TC+120.0))*(TC/273.155)**1.5 - !!! CALCULATE THE REYNOLDS NUMBER - unitless - RE=D*VT*DENSAC/ANU - E=(0.60)**(0.333333333)*(RE**0.50) !ventilation coefficient vapor (fv) - !!! SELECT APPROPRIATE VALUES OF AE ACCORDING TO RE - IF(RE.LT.6000.0)THEN - AE=0.78+0.308*E - ELSEIF(RE.GE.6000.0.AND.RE.LT.20000.0)THEN - AE=0.76*E - ELSEIF(RE.GE.20000.0) THEN - AE=(0.57+9.0E-6*RE)*E - ENDIF - - - !!! CALC HAILSTONE'S MASS (GM), MASS OF WATER (GMW) AND THE - !!! MASS OF ICE IN THE STONE (GMI) - GM=PI/6.*(D**3.)*DENSE - GMW=FW*GM - GMI=GM-GMW - - !!! STORE THE MASS - GM1=GM - - !!! NEW MASS GROWTH CALCULATIONS WITH VARIABLE RIME - !!! LAYER DENSITY BASED ON ZIEGLER ET AL. (1983) - - !!! CALCULATE INCREASE IN MASS DUE INTERCEPTED CLD WATER, USE - !!! ORIGINAL DIAMETER - GMW2=GMW+SEKDEL*(PI/4.*D**2.*VT*XW*EW) - DGMW=GMW2-GMW - GMW=GMW2 - - !!! CALCULATE THE INCREASE IN MASS DUE INTERCEPTED CLOUD ICE - GMI2=GMI+SEKDEL*(PI/4.*D**2.*VT*XI*EI) - DGMI=GMI2-GMI - GMI=GMI2 - - !!! CALCULATE INCREASE IN MASS DUE TO SUBLIMATION/CONDENSATION OF - !!! WATER VAPOR - DGMV = SEKDEL*2*PI*D*AE*DI*DELRW - IF (DGMV .LT. 0) DGMV=0 - - !!! CALCULATE THE TOTAL MASS CHANGE - DGM=DGMW+DGMI+DGMV - !Dummy arguments in the event of no water, vapor, or ice growth - DENSELW = 900. - DENSELI = 700. - !!! CALCULATE DENSITY OF NEW LAYER, DEPENDS ON FW AND ITYPE - IF (ITYPE.EQ.1) THEN !DRY GROWTH - !If hailstone encountered supercooled water, calculate new layer density - ! using Macklin form - IF ((DGMW.GT.0).OR.(DGMV.GT.0)) THEN - !MEAN CLOUD DROPLET RADIUS, ASSUME CLOUD DROPLET CONC OF 3E8 M-3 (300 CM-3) - DC = (0.74*XW / (3.14159*1000.*3.E8))**0.33333333 * 1.E6 !MICRONS - !!! FIND THE STOKES NUMBER (rasmussen heymsfield 1985) - NS = 2*VT*100.*(DC*1.E-4)**2. / (9*ANU*D*50) !need hail radius in cm - !!! FIND IMPACT VELOCITY (rasmussen heymsfield 1985) - IF (NS.LT.0.1)THEN - W=-1. - ELSE - W = LOG10(NS) - ENDIF - IF (RE.GT.200) THEN - IF (NS.LT.0.1) THEN - VIMP = 0.0 - ELSEIF ((NS.GE.0.1).AND.(NS.LE.10)) THEN - VIMP = (0.356 + 0.4738*W - 0.1233*W**2. & - -0.1618*W**3. + 0.0807*W**4.)*VT - ELSEIF (NS.GT.10) THEN - VIMP = 0.63*VT - ENDIF - ELSEIF ((RE.GT.65).AND.(RE.LE.200)) THEN - IF (NS.LT.0.1) THEN - VIMP = 0.0 - ELSEIF ((NS.GE.0.1).AND.(NS.LE.10)) THEN - VIMP = (0.3272 + 0.4907*W - 0.09452*W**2. & - -0.1906*W**3. + 0.07105*W**4.)*VT - ELSEIF (NS.GT.10) THEN - VIMP = 0.61*VT - ENDIF - ELSEIF ((RE.GT.20).AND.(RE.LE.65)) THEN - IF (NS.LT.0.1) THEN - VIMP = 0.0 - ELSEIF ((NS.GE.0.1).AND.(NS.LE.10)) THEN - VIMP = (0.2927 + 0.5085*W - 0.03453*W**2. & - -0.2184*W**3. + 0.03595*W**4.)*VT - ELSEIF (NS.GT.10) THEN - VIMP = 0.59*VT - ENDIF - ELSEIF (RE.LE.20) THEN - IF (NS.LT.0.4) THEN - VIMP = 0.0 - ELSEIF ((NS.GE.0.4).AND.(NS.LE.10)) THEN - VIMP = (0.1701 + 0.7246*W + 0.2257*W**2. & - -1.13*W**3. + 0.5756*W**4.)*VT - ELSEIF (NS.GT.10) THEN - VIMP = 0.57*VT - ENDIF - ENDIF - - !RIME LAYER DENSITY, HEYMSFIELD AND PFLAUM 1985 FORM - TSCELSIUS = TS - 273.16 - AFACTOR = -DC*VIMP/TSCELSIUS - IF ((TSCELSIUS.LE.-5.).OR.(AFACTOR.GE.-1.60)) THEN - DENSELW = 0.30*(AFACTOR)**0.44 - ELSEIF (TSCELSIUS.GT.-5.) THEN - DENSELW = EXP(-0.03115 - 1.7030*AFACTOR + & - 0.9116*AFACTOR**2. - 0.1224*AFACTOR**3.) - ENDIF - - DENSELW = DENSELW * 1000. !KG M-3 - !BOUND POSSIBLE DENSITIES - IF (DENSELW.LT.100) DENSELW=100 - IF (DENSELW.GT.900) DENSELW=900 - !WRITE(12,*) 'MASSAGR, PFLAUM, MACKLIN: ', DENSELW, & - ! MACKLIN_DENSELW - ENDIF - IF (DGMI.GT.0) THEN - !Ice collection main source of growth, so set new density layer - DENSELI = 700. - ENDIF - - !All liquid water contributes to growth, none is soaked into center. - DGMW_NOSOAK = DGMW !All liquid water contributes to growth, - ! none of it is soaked into center. - - ELSE !WET GROWTH - !Collected liquid water can soak into the stone before freezing, - ! increasing mass and density but leaving volume constant. - !Volume of current drop, before growth - VOL1 = GM/DENSE - !Difference b/w mass of stone if density is 900 kg/m3, and - ! current mass - SOAK = 900*VOL1 - GM - !Liquid mass available - SOAKM = DGMW - !Soak up as much liquid as we can, up to a density of 900 kg/m3 - IF (SOAKM.GT.SOAK) SOAKM=SOAK - GM = GM+SOAKM !Mass of current drop, plus soaking - !New density of current drop, including soaking but before growth - DENSE = GM/VOL1 - !Mass increment of liquid water growth that doesn't - ! include the liquid water we just soaked into the stone. - DGMW_NOSOAK = DGMW - SOAKM - - !Whatever growth does occur has high density - DENSELW = 900. !KG M-3 - DENSELI = 900. - - ENDIF - - !!!VOLUME OF NEW LAYER - !VOLL = (DGM) / DENSEL - !VOLL = (DGMI+DGMV+DGMW_NOSOAK) / DENSEL - !VOLL = (DGMI) / DENSELI + (DGMW_NOSOAK+DGMV) / DENSELW - IF (DGMI.LE.0) THEN - VOLL = (DGMW_NOSOAK+DGMV) / DENSELW - ELSE IF (DGMW.LE.0) THEN - VOLL = (DGMI) / DENSELI - ELSE - VOLL = (DGMI) / DENSELI + (DGMW_NOSOAK+DGMV) / DENSELW - ENDIF - - !!!NEW TOTAL VOLUME, DENSITY, DIAMETER - VOLT = VOLL + GM/DENSE - !DENSE = (GM+DGM) / VOLT - DENSE = (GM+DGMI+DGMV+DGMW_NOSOAK) / VOLT - !D=D+SEKDEL*0.5*VT/DENSE*(XW*EW+XI*EI) - GM = GM+DGMI+DGMW_NOSOAK+DGMV - D = ( (6*GM) / (PI*DENSE) )**0.33333333 - - END SUBROUTINE MASSAGR - - - - SUBROUTINE HEATBUD(TS,TSm1,TSm2,FW,TC,VT,DELRW,D,DENSA,GM1,GM,DGM,DGMW, & - DGMV,DGMI,GMW,GMI,DI,ANU,RE,AE,SEKDEL,ITYPE,P) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!! CALCULATE HAILSTONE'S HEAT BUDGET - !!! See Rasmussen and Heymsfield 1987; JAS - !!! Original Hailcast's variable units - !!! TS - Celsius - !!! FW - unitless, between 0 and 1 - !!! TC - Celsius - !!! VT - m/s - !!! D - m - !!! DELRW - g/cm3 (per comment) - !!! DENSA - g/cm3 (per comment) - !!! GM1, DMG, DGMW, DGMV, DGMI, GMW, GMI - should all be kg - !!! DI - cm2 / sec - !!! P - hPa - !!! Original HAILCAST HEATBUD subroutine uses c-g-s units, so do some conversions - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - IMPLICIT NONE - REAL*8 D - REAL TS,TSm1,TSm2,FW,TC,VT,DELRW,DENSA,GM1,GM,DGM,DGMW,DGMV, & - DGMI,GMW,GMI,DI,ANU,RE,AE,SEKDEL,P - INTEGER ITYPE - - REAL RV, RD, G, PI, ALF, ALV, ALS, CI, CW, AK - REAL H, AH, TCC, TSC, DELRWC, DENSAC, TDIFF - REAL DMLT - REAL TSCm1, TSCm2 - DATA RV/461.48/,RD/287.04/,G/9.78956/ - DATA PI/3.141592654/,ALF/79.7/,ALV/597.3/ - DATA ALS/677.0/,CI/0.5/,CW/1./ - - !Convert values to non-SI units here - TSC = TS - 273.155 - TSCm1 = TSm1 - 273.155 - TSCm2 = TSm2 - 273.155 - TCC = TC - 273.155 - DELRWC = DELRW * (1.E3) * (1.E-6) - DENSAC = DENSA * (1.E3) * (1.E-6) - !DI still in cm2/sec - - - !!! CALCULATE THE CONSTANTS - AK=(5.8+0.0184*TCC)*1.E-5 !thermal conductivity - cal/(cm*sec*K) - !dynamic viscosity - calculated in MASSAGR - !ANU=1.717E-4*(393.0/(TC+120.0))*(TC/273.155)**1.5 - - !!! CALCULATE THE REYNOLDS NUMBER - unitless - !RE=D*VT*DENSAC/ANU - calculated in MASSAGR - - H=(0.71)**(0.333333333)*(RE**0.50) !ventilation coefficient heat (fh) - !E=(0.60)**(0.333333333)*(RE**0.50) !ventilation coefficient vapor (fv) - - !!! SELECT APPROPRIATE VALUES OF AH AND AE ACCORDING TO RE - IF(RE.LT.6000.0)THEN - AH=0.78+0.308*H - !AE=0.78+0.308*E - ELSEIF(RE.GE.6000.0.AND.RE.LT.20000.0)THEN - AH=0.76*H - !AE=0.76*E - ELSEIF(RE.GE.20000.0) THEN - AH=(0.57+9.0E-6*RE)*H - !AE=(0.57+9.0E-6*RE)*E calculated in MASSAGR - ENDIF - - !!! FOR DRY GROWTH FW=0, CALCULATE NEW TS, ITIPE=1 - !!! FOR WET GROWTH TS=0, CALCULATE NEW FW, ITIPE=2 - - - IF(ITYPE.EQ.1) THEN - !!! DRY GROWTH; CALC NEW TEMP OF THE STONE - !Original Hailcast algorithm (no time differencing) - !TSC=TSC-TSC*DGM/GM1+SEKDEL/(GM1*CI)* & - ! (2.*PI*D*(AH*AK*(TCC-TSC)-AE*ALS*DI*DELRWC)+ & - ! DGMW/SEKDEL*(ALF+CW*TCC)+DGMI/SEKDEL*CI*TCC) - TSC=0.6*(TSC-TSC*DGM/GM1+SEKDEL/(GM1*CI)* & - (2.*PI*D*(AH*AK*(TCC-TSC)-AE*ALS*DI*DELRWC)+ & - DGMW/SEKDEL*(ALF+CW*TCC)+DGMI/SEKDEL*CI*TCC)) + & - 0.2*TSCm1 + 0.2*TSCm2 - - TS = TSC+273.155 - IF (TS.GE.273.155) THEN - TS=273.155 - ENDIF - TDIFF = ABS(TS-273.155) - IF (TDIFF.LE.1.E-6) ITYPE=2 !NOW IN WET GROWTH - - ELSE IF (ITYPE.EQ.2) THEN - !!! WET GROWTH; CALC NEW FW - - IF (TCC.LT.0.) THEN - !Original Hailcast algorithm - FW=FW-FW*DGM/GM1+SEKDEL/(GM1*ALF)* & - (2.*PI*D*(AH*AK*TCC-AE*ALV*DI*DELRWC)+ & - DGMW/SEKDEL*(ALF+CW*TCC)+DGMI/SEKDEL*CI*TCC) - ELSE - !Calculate decrease in ice mass due to melting - DMLT = (2.*PI*D*AH*AK*TCC + 2.*PI*D*AE*ALV*DI*DELRWC + & - DGMW/SEKDEL*CW*TCC) / ALF - FW = (FW*GM + DMLT) / GM - ENDIF - - IF(FW.GT.1.)FW=1. - IF(FW.LT.0.)FW=0. - - !IF ALL OUR ACCRETED WATER WAS FROZEN, WE ARE BACK IN DRY GROWTH - IF(FW.LE.1.E-6) THEN - ITYPE=1 - ENDIF - - ENDIF - - END SUBROUTINE HEATBUD - - - - SUBROUTINE BREAKUP(DENSE,D,GM,FW,CRIT) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!! TEST IF AMOUNT OF WATER ON SURFACE EXCEEDS CRTICAL LIMIT- - !!! IF SO INVOKE SHEDDING SCHEME - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - IMPLICIT NONE - REAL*8 D - REAL DENSE, GM, FW, CRIT - !local variables - REAL WATER, GMI, WAT, PI - DATA PI/3.141592654/ - - WATER=FW*GM !KG - !GMI=(GM-WATER) !KG - !REMAIN = CRIT*GM - - ! CALC CRTICAL MASS CAPABLE OF BEING "SUPPORTED" ON THE STONE'S - ! SURFACE - !CRIT=0.268+0.1389*GMI - !CRIT=0.268*1.E-3 + 0.1389*1.E-3*GMI !mass now in kg instead of g - !CRIT = 1.0E-10 - !CRIT - now passed from main subroutine - - WAT=WATER-CRIT - GM=GM-WAT - FW=(CRIT)/GM - - IF(FW.GT.1.0) FW=1.0 - IF(FW.LT.0.0) FW=0.0 - - ! RECALCULATE DIAMETER AFTER SHEDDING - ! Assume density remains the same - D=(6.*GM/(PI*DENSE))**(0.333333333) - END SUBROUTINE BREAKUP - - - SUBROUTINE MELT(D,TLAYER,PLAYER,RLAYER,LDEPTH,VT) - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !!! This is a spherical hail melting estimate based on the Goyer - !!! et al. (1969) eqn (3). The depth of the warm layer, estimated - !!! terminal velocity, and mean temperature of the warm layer are - !!! used. DRB. 11/17/2003. - !!! - !!! INPUT: TLAYER mean sub-cloud layer temperature (K) - !!! PLAYER mean sub-cloud layer pressure (Pa) - !!! RLAYER mean sub-cloud layer mixing ratio (kg/kg) - !!! VT terminal velocity of stone (m/s) - !!! OUTPUT: D diameter (m) - !!! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - IMPLICIT NONE - - REAL*8 D - REAL TLAYER, PLAYER, RLAYER, LDEPTH, VT - REAL eenv, delta, ewet, de, der, wetold, wetbulb, wetbulbk - REAL tdclayer, tclayer, eps, b, hplayer - REAL*8 a - REAL sd, lt, ka, lf, lv, t0, dv, pi, rv, rhoice, & - tres, re, delt, esenv, rhosenv, essfc, rhosfc, dsig, & - dmdt, mass, massorg, newmass, gamma, r, rho - INTEGER wcnt - - !Convert temp to Celsius, calculate dewpoint in celsius - eps = 0.622 - tclayer = TLAYER - 273.155 - a = 2.53E11 - b = 5.42E3 - tdclayer = b / LOG(a*eps / (rlayer*player)) - hplayer = player / 100. - - !Calculate partial vapor pressure - eenv = (player*rlayer) / (rlayer+eps) - eenv = eenv / 100. !convert to mb - - !Estimate wet bulb temperature (C) - gamma = 6.6E-4*player - delta = (4098.0*eenv)/((tdclayer+237.7)*(tdclayer+237.7)) - wetbulb = ((gamma*tclayer)+(delta*tdclayer))/(gamma+delta) - - !Iterate to get exact wet bulb - wcnt = 0 - DO WHILE (wcnt .lt. 11) - ewet = 6.108*(exp((17.27*wetbulb)/(237.3 + wetbulb))) - de = (0.0006355*hplayer*(tclayer-wetbulb))-(ewet-eenv) - der= (ewet*(.0091379024 - (6106.396/(273.155+wetbulb)**2))) & - - (0.0006355*hplayer) - wetold = wetbulb - wetbulb = wetbulb - de/der - wcnt = wcnt + 1 - IF ((abs(wetbulb-wetold)/wetbulb.gt.0.0001)) THEN - EXIT - ENDIF - ENDDO - - wetbulbk = wetbulb + 273.155 !convert to K - ka = .02 ! thermal conductivity of air - lf = 3.34e5 ! latent heat of melting/fusion - lv = 2.5e6 ! latent heat of vaporization - t0 = 273.155 ! temp of ice/water melting interface - dv = 0.25e-4 ! diffusivity of water vapor (m2/s) - pi = 3.1415927 - rv = 1004. - 287. ! gas constant for water vapor - rhoice = 917.0 ! density of ice (kg/m**3) - r = D/2. ! radius of stone (m) - - !Compute residence time in warm layer - tres = LDEPTH / VT - - !Calculate dmdt based on eqn (3) of Goyer et al. (1969) - !Reynolds number...from pg 317 of Atmo Physics (Salby 1996) - !Just use the density of air at 850 mb...close enough. - rho = 85000./(287.*TLAYER) - re = rho*r*VT*.01/1.7e-5 - - !Temperature difference between environment and hailstone surface - delt = wetbulb !- 0.0 !assume stone surface is at 0C - !wetbulb is in Celsius - - !Difference in vapor density of air stream and equil vapor - !density at the sfc of the hailstone - esenv = 610.8*(exp((17.27*wetbulb)/ & - (237.3 + wetbulb))) ! es environment in Pa - rhosenv = esenv/(rv*wetbulbk) - essfc = 610.8*(exp((17.27*(t0-273.155))/ & - (237.3 + (t0-273.155)))) ! es environment in Pa - rhosfc = essfc/(rv*t0) - dsig = rhosenv - rhosfc - - !Calculate new mass growth - dmdt = (-1.7*pi*r*(re**0.5)/lf)*((ka*delt)+((lv-lf)*dv*dsig)) - IF (dmdt.gt.0.) dmdt = 0 - mass = dmdt*tres - - !Find the new hailstone diameter - massorg = 1.33333333*pi*r*r*r*rhoice - newmass = massorg + mass - if (newmass.lt.0.0) newmass = 0.0 - D = 2.*(0.75*newmass/(pi*rhoice))**0.333333333 - END SUBROUTINE MELT - - -END MODULE module_diag_hailcast - From 191760c387801343aa1be0978d3db3df0a3b154e Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Tue, 26 Oct 2021 13:55:07 -0500 Subject: [PATCH 08/13] Fixes from Jili Dong --- model/fv_sg.F90 | 2 +- tools/coarse_grained_diagnostics.F90 | 17 +++++++++++++++++ tools/external_ic.F90 | 4 ++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/model/fv_sg.F90 b/model/fv_sg.F90 index 3226a0302..1e5ef4bf8 100644 --- a/model/fv_sg.F90 +++ b/model/fv_sg.F90 @@ -309,7 +309,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - elseif ( nwat >= 5 ) then + elseif ( nwat == 5 ) then do i=is,ie q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) diff --git a/tools/coarse_grained_diagnostics.F90 b/tools/coarse_grained_diagnostics.F90 index a133812a7..b0f02e734 100644 --- a/tools/coarse_grained_diagnostics.F90 +++ b/tools/coarse_grained_diagnostics.F90 @@ -228,6 +228,14 @@ subroutine populate_coarse_diag_type(Atm, coarse_diagnostics) coarse_diagnostics(index)%units = 'kg/kg/s' coarse_diagnostics(index)%reduction_method = MASS_WEIGHTED + index = index + 1 + coarse_diagnostics(index)%axes = 3 + coarse_diagnostics(index)%module_name = DYNAMICS + coarse_diagnostics(index)%name = 'qh_dt_phys_coarse' + coarse_diagnostics(index)%description = 'coarse-grained hail tracer tendency from physics' + coarse_diagnostics(index)%units = 'kg/kg/s' + coarse_diagnostics(index)%reduction_method = MASS_WEIGHTED + index = index + 1 coarse_diagnostics(index)%axes = 3 coarse_diagnostics(index)%module_name = DYNAMICS @@ -366,6 +374,15 @@ subroutine populate_coarse_diag_type(Atm, coarse_diagnostics) coarse_diagnostics(index)%vertically_integrated = .true. coarse_diagnostics(index)%reduction_method = AREA_WEIGHTED + index = index + 1 + coarse_diagnostics(index)%axes = 2 + coarse_diagnostics(index)%module_name = DYNAMICS + coarse_diagnostics(index)%name = 'int_qh_dt_phys_coarse' + coarse_diagnostics(index)%description = 'coarse-grained vertically integrated hail tracer tendency from physics' + coarse_diagnostics(index)%units = 'kg/m**2/s' + coarse_diagnostics(index)%vertically_integrated = .true. + coarse_diagnostics(index)%reduction_method = AREA_WEIGHTED + index = index + 1 coarse_diagnostics(index)%axes = 2 coarse_diagnostics(index)%module_name = DYNAMICS diff --git a/tools/external_ic.F90 b/tools/external_ic.F90 index b4a0a6bee..97974f804 100644 --- a/tools/external_ic.F90 +++ b/tools/external_ic.F90 @@ -938,7 +938,7 @@ subroutine read_gfs_ic() ! prognostic tracers do nt = 1, ntracers - q(:,:,:,nt) = -999.99 +! q(:,:,:,nt) = -999.99 call get_tracer_names(MODEL_ATMOS, nt, tracer_name) call register_restart_field(GFS_restart, trim(tracer_name), q(:,:,:,nt), dim_names_3d3, is_optional=.true.) enddo @@ -3084,7 +3084,7 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) ! map tracers do iq=1,ncnst - if (floor(qa(is,j,1,iq)) == -1000) cycle !skip missing scalars [floor(-999.99) is -1000] +! if (floor(qa(is,j,1,iq)) == -1000) cycle !skip missing scalars [floor(-999.99) is -1000] do k=1,km do i=is,ie qp(i,k) = qa(i,j,k,iq) From 84ff530bf0cf7baad994b2582c41ccbf1493f311 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Thu, 27 Jan 2022 11:14:47 -0600 Subject: [PATCH 09/13] Add hailwat to tools/external_ic.F90 --- tools/external_ic.F90 | 57 +++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/tools/external_ic.F90 b/tools/external_ic.F90 index 8ad6c4f06..d9af533b7 100644 --- a/tools/external_ic.F90 +++ b/tools/external_ic.F90 @@ -220,7 +220,7 @@ subroutine get_external_ic( Atm, fv_domain, cold_start ) integer :: is, ie, js, je integer :: isd, ied, jsd, jed, ng - integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, sgs_tke, cld_amt + integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat, sgs_tke, cld_amt integer :: liq_aero, ice_aero #ifdef MULTI_GASES integer :: spo, spo2, spo3 @@ -318,6 +318,7 @@ subroutine get_external_ic( Atm, fv_domain, cold_start ) rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat') graupel = get_tracer_index(MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index(MODEL_ATMOS, 'hailwat') #ifdef MULTI_GASES spo = get_tracer_index(MODEL_ATMOS, 'spo') spo2 = get_tracer_index(MODEL_ATMOS, 'spo2') @@ -340,6 +341,8 @@ subroutine get_external_ic( Atm, fv_domain, cold_start ) call prt_maxmin('snowwat', Atm%q(:,:,:,snowwat), is, ie, js, je, ng, Atm%npz, 1.) if ( graupel > 0 ) & call prt_maxmin('graupel', Atm%q(:,:,:,graupel), is, ie, js, je, ng, Atm%npz, 1.) + if ( hailwat > 0 ) & + call prt_maxmin('hailwat', Atm%q(:,:,:,hailwat), is, ie, js, je, ng, Atm%npz, 1.) #ifdef MULTI_GASES if ( spo > 0 ) & call prt_maxmin('SPO', Atm%q(:,:,:,spo), is, ie, js, je, ng, Atm%npz, 1.) @@ -489,7 +492,7 @@ subroutine get_nggps_ic (Atm, fv_domain) real(kind=R_GRID), dimension(2):: p1, p2, p3 real(kind=R_GRID), dimension(3):: e1, e2, ex, ey integer:: i,j,k,nts, ks, naxis_dims - integer:: liq_wat, ice_wat, rainwat, snowwat, graupel, tke, ntclamt + integer:: liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat, tke, ntclamt namelist /external_ic_nml/ filtered_terrain, levp, gfs_dwinds, & checker_tr, nt_checker @@ -788,6 +791,7 @@ subroutine get_nggps_ic (Atm, fv_domain) rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat') graupel = get_tracer_index(MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index(MODEL_ATMOS, 'hailwat') ntclamt = get_tracer_index(MODEL_ATMOS, 'cld_amt') if (data_source_fv3gfs) then do k=1,npz @@ -800,6 +804,13 @@ subroutine get_nggps_ic (Atm, fv_domain) Atm%q(i,j,k,rainwat) + & Atm%q(i,j,k,snowwat) + & Atm%q(i,j,k,graupel))) + elseif ( Atm%flagstruct%nwat == 7 ) then ! may not need this. 'else' should cover both 6 and 7? + qt = wt/(1. - (Atm%q(i,j,k,liq_wat) + & + Atm%q(i,j,k,ice_wat) + & + Atm%q(i,j,k,rainwat) + & + Atm%q(i,j,k,snowwat) + & + Atm%q(i,j,k,graupel) + & + Atm%q(i,j,k,hailwat))) else ! all other values of nwat qt = wt/(1. - sum(Atm%q(i,j,k,2:Atm%flagstruct%nwat))) endif @@ -821,6 +832,13 @@ subroutine get_nggps_ic (Atm, fv_domain) Atm%q(i,j,k,rainwat) + & Atm%q(i,j,k,snowwat) + & Atm%q(i,j,k,graupel)) + elseif ( Atm%flagstruct%nwat == 7 ) then ! may not need this. 'else' should cover both 6 and 7? + qt = wt*(1. + Atm%q(i,j,k,liq_wat) + & + Atm%q(i,j,k,ice_wat) + & + Atm%q(i,j,k,rainwat) + & + Atm%q(i,j,k,snowwat) + & + Atm%q(i,j,k,graupel) + & + Atm%q(i,j,k,hailwat)) else ! all other values of nwat qt = wt*(1. + sum(Atm%q(i,j,k,2:Atm%flagstruct%nwat))) endif @@ -938,7 +956,12 @@ subroutine read_gfs_ic() ! prognostic tracers do nt = 1, ntracers - q(:,:,:,nt) = -999.99 + IF ( nt <= 6 ) THEN + q(:,:,:,nt) = -999.99 + ELSE + q(:,:,:,nt) = 0 ! nonzero values can cause problems for tracers not in the input (like hail mixing ratio) + ENDIF + call get_tracer_names(MODEL_ATMOS, nt, tracer_name) call register_restart_field(GFS_restart, trim(tracer_name), q(:,:,:,nt), dim_names_3d3, is_optional=.true.) enddo @@ -1018,7 +1041,7 @@ subroutine get_hrrr_ic (Atm, fv_domain) real(kind=R_GRID), dimension(2):: p1, p2, p3 real(kind=R_GRID), dimension(3):: e1, e2, ex, ey integer:: i,j,k,nts, ks - integer:: liq_wat, ice_wat, rainwat, snowwat, graupel, tke, ntclamt + integer:: liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat, tke, ntclamt namelist /external_ic_nml/ filtered_terrain, levp, gfs_dwinds, & checker_tr, nt_checker ! variables for reading the dimension from the hrrr_ctrl @@ -1949,7 +1972,7 @@ subroutine get_ecmwf_ic( Atm, fv_domain ) logical:: found integer :: is, ie, js, je integer :: isd, ied, jsd, jed - integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, sgs_tke, cld_amt + integer :: sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat, sgs_tke, cld_amt #ifdef MULTI_GASES integer :: spo, spo2, spo3 #else @@ -1999,6 +2022,7 @@ subroutine get_ecmwf_ic( Atm, fv_domain ) rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat') graupel = get_tracer_index(MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index(MODEL_ATMOS, 'hailwat') #ifdef MULTI_GASES spo = get_tracer_index(MODEL_ATMOS, 'spo') spo2 = get_tracer_index(MODEL_ATMOS, 'spo2') @@ -2012,11 +2036,14 @@ subroutine get_ecmwf_ic( Atm, fv_domain ) if (is_master()) then print *, 'sphum = ', sphum print *, 'liq_wat = ', liq_wat - if ( Atm%flagstruct%nwat .eq. 6 ) then + if ( Atm%flagstruct%nwat .ge. 6 ) then print *, 'rainwat = ', rainwat print *, 'iec_wat = ', ice_wat print *, 'snowwat = ', snowwat print *, 'graupel = ', graupel + IF ( Atm%flagstruct%nwat == 7 ) then + print *, 'hailwat = ', hailwat + ENDIF endif #ifdef MULTI_GASES print *, ' spo3 = ', spo3 @@ -2363,7 +2390,8 @@ subroutine get_ecmwf_ic( Atm, fv_domain ) enddo enddo - qc(:,:,:,graupel) = 0. ! note Graupel must be tracer #6 + qc(:,:,:,graupel) = 0. ! note Graupel must be tracer #6 (hail assumed not present, + ! otherwise qc needs have dimension 7) deallocate ( qec ) if(is_master()) write(*,*) 'done interpolate tracers (qec) into cubic (qc)' @@ -2562,12 +2590,12 @@ subroutine get_ecmwf_ic( Atm, fv_domain ) wt = Atm%delp(i,j,k) if ( Atm%flagstruct%nwat .eq. 2 ) then qt = wt*(1.+Atm%q(i,j,k,liq_wat)) - elseif ( Atm%flagstruct%nwat .eq. 6 ) then + elseif ( Atm%flagstruct%nwat .eq. 6 .or. Atm%flagstruct%nwat .eq. 7 ) then qt = wt*(1. + Atm%q(i,j,k,liq_wat) + & Atm%q(i,j,k,ice_wat) + & Atm%q(i,j,k,rainwat) + & Atm%q(i,j,k,snowwat) + & - Atm%q(i,j,k,graupel)) + Atm%q(i,j,k,graupel)) ! assume hailwat is zero if nwat=7 endif m_fac = wt / qt do iq=1,ntracers @@ -2953,7 +2981,7 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) real(kind=R_GRID):: pst !!! High-precision integer i,j,k,l,m, k2,iq - integer sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, cld_amt, sgs_tke + integer sphum, liq_wat, ice_wat, rainwat, snowwat, graupel, hailwat, cld_amt, sgs_tke #ifdef MULTI_GASES integer spo, spo2, spo3 #else @@ -2972,6 +3000,7 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) rainwat = get_tracer_index(MODEL_ATMOS, 'rainwat') snowwat = get_tracer_index(MODEL_ATMOS, 'snowwat') graupel = get_tracer_index(MODEL_ATMOS, 'graupel') + hailwat = get_tracer_index(MODEL_ATMOS, 'hailwat') cld_amt = get_tracer_index(MODEL_ATMOS, 'cld_amt') #ifdef MULTI_GASES spo = get_tracer_index(MODEL_ATMOS, 'spo') @@ -2988,6 +3017,7 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) print *, 'nwat = ', Atm%flagstruct%nwat print *, 'sphum = ', sphum print *, 'clwmr = ', liq_wat + print *, 'liq_wat = ', liq_wat #ifdef MULTI_GASES print *, 'spo = ', spo print *, 'spo2 = ', spo2 @@ -2995,11 +3025,12 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) #else print *, ' o3mr = ', o3mr #endif - if ( Atm%flagstruct%nwat .eq. 6 ) then + if ( Atm%flagstruct%nwat .ge. 6 ) then print *, 'rainwat = ', rainwat print *, 'ice_wat = ', ice_wat print *, 'snowwat = ', snowwat print *, 'graupel = ', graupel + IF ( Atm%flagstruct%nwat == 7 ) print *, 'hailwat = ', hailwat endif print *, 'sgs_tke = ', sgs_tke print *, 'cld_amt = ', cld_amt @@ -3016,7 +3047,7 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) #endif !$OMP parallel do default(none) & -!$OMP shared(sphum,liq_wat,rainwat,ice_wat,snowwat,graupel,data_source_fv3gfs,& +!$OMP shared(sphum,liq_wat,rainwat,ice_wat,snowwat,graupel,hailwat,data_source_fv3gfs,& !$OMP cld_amt,ncnst,npz,is,ie,js,je,km,k2,ak0,bk0,psc,zh,omga,qa,Atm,z500,t_in) & !$OMP private(l,m,pst,pn,gz,pe0,pn0,pe1,pn1,dp2,qp,qn1,gz_fv) @@ -3234,7 +3265,7 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) endif #endif - if (Atm%flagstruct%nwat .eq. 6 ) then + if (Atm%flagstruct%nwat .eq. 6) then ! no need to check for nwat=7 (hail) since only nwat=3,6 treated here Atm%q(i,j,k,rainwat) = 0. Atm%q(i,j,k,snowwat) = 0. Atm%q(i,j,k,graupel) = 0. From 5fb5512dd9a48f030fab357865b25228bf340763 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Thu, 27 Jan 2022 12:41:40 -0600 Subject: [PATCH 10/13] Set logic in fv_regional_bc.F90 to match current code; Change logic in external_ic.F90 to check value of nwat --- model/fv_regional_bc.F90 | 11 ++--------- tools/external_ic.F90 | 6 ++++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/model/fv_regional_bc.F90 b/model/fv_regional_bc.F90 index 24c153ca6..222a02f58 100644 --- a/model/fv_regional_bc.F90 +++ b/model/fv_regional_bc.F90 @@ -6799,19 +6799,12 @@ subroutine get_data_source(data_source_fv3gfs,regional) allocate(pes(mpp_npes())) call mpp_get_current_pelist(pes) - if (regional) then - if (open_file(Gfs_data , 'INPUT/gfs_data.nc', "read", pelist=pes)) then + if (open_file(Gfs_data , 'INPUT/gfs_data.nc', "read", pelist=pes) .or. & + open_file(Gfs_data , 'INPUT/gfs_data.tile1.nc', "read", pelist=pes)) then lstatus = global_att_exists(Gfs_data, "source") if(lstatus) call get_global_attribute(Gfs_data, "source", source) call close_file(Gfs_data) endif - else - if (open_file(Gfs_data , 'INPUT/gfs_data.tile1.nc', "read", pelist=pes)) then - lstatus = global_att_exists(Gfs_data, "source") - if(lstatus) call get_global_attribute(Gfs_data, "source", source) - call close_file(Gfs_data) - endif - endif deallocate(pes) if (.not. lstatus) then diff --git a/tools/external_ic.F90 b/tools/external_ic.F90 index d9af533b7..893aa7c2b 100644 --- a/tools/external_ic.F90 +++ b/tools/external_ic.F90 @@ -955,11 +955,13 @@ subroutine read_gfs_ic() if (data_source_fv3gfs) call register_restart_field(GFS_restart, 't', temp, dim_names_3d3, is_optional=.true.) ! prognostic tracers + do nt = 1, ntracers - IF ( nt <= 6 ) THEN + + IF ( .not. ( nt == Atm%flagstruct%nwat .and. Atm%flagstruct%nwat == 7 ) ) THEN q(:,:,:,nt) = -999.99 ELSE - q(:,:,:,nt) = 0 ! nonzero values can cause problems for tracers not in the input (like hail mixing ratio) + q(:,:,:,nt) = 0 ! nonzero values can cause problems for water mass tracers not in the input (like hail mixing ratio; hailwat not defined at this point) ENDIF call get_tracer_names(MODEL_ATMOS, nt, tracer_name) From 5e04e628750a489fbeaae901e6075bcbb2cf9087 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Mon, 31 Jan 2022 13:15:39 -0600 Subject: [PATCH 11/13] Recommended changes --- model/fv_regional_bc.F90 | 48 ++++------------------------------------ tools/external_ic.F90 | 20 +---------------- 2 files changed, 5 insertions(+), 63 deletions(-) diff --git a/model/fv_regional_bc.F90 b/model/fv_regional_bc.F90 index 222a02f58..779cba36f 100644 --- a/model/fv_regional_bc.F90 +++ b/model/fv_regional_bc.F90 @@ -3768,7 +3768,10 @@ subroutine remap_scalar_nggps_regional_bc(Atm & ! and may not provide a very good result ! if ( .not. data_source_fv3gfs ) then - if ( Atm%flagstruct%nwat .eq. 6 ) then + if ( Atm%flagstruct%nwat .eq. 6 .or. Atm%flagstruct%nwat .eq. 7 ) then + if ( Atm%flagstruct%nwat .eq. 7 ) then + BC_side%q_BC(is:ie,j,1:npz,hailwat) = 0. + endif do k=1,npz do i=is,ie qn1(i,k) = BC_side%q_BC(i,j,k,liq_wat) @@ -3805,49 +3808,6 @@ subroutine remap_scalar_nggps_regional_bc(Atm & endif endif endif -#endif - call mp_auto_conversion(BC_side%q_BC(i,j,k,liq_wat), BC_side%q_BC(i,j,k,rainwat), & - BC_side%q_BC(i,j,k,ice_wat), BC_side%q_BC(i,j,k,snowwat) ) - enddo - enddo - endif - if ( Atm%flagstruct%nwat .eq. 7 ) then - do k=1,npz - do i=is,ie - qn1(i,k) = BC_side%q_BC(i,j,k,liq_wat) - BC_side%q_BC(i,j,k,rainwat) = 0. - BC_side%q_BC(i,j,k,snowwat) = 0. - BC_side%q_BC(i,j,k,graupel) = 0. - BC_side%q_BC(i,j,k,hailwat) = 0. - if ( BC_side%pt_BC(i,j,k) > 273.16 ) then ! > 0C all liq_wat - BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k) - BC_side%q_BC(i,j,k,ice_wat) = 0. -#ifdef ORIG_CLOUDS_PART - else if ( BC_side%pt_BC(i,j,k) < 258.16 ) then ! < -15C all ice_wat - BC_side%q_BC(i,j,k,liq_wat) = 0. - BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - else ! between -15~0C: linear interpolation - BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k)*((BC_side%pt_BC(i,j,k)-258.16)/15.) - BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - BC_side%q_BC(i,j,k,liq_wat) - endif -#else - else if ( BC_side%pt_BC(i,j,k) < 233.16 ) then ! < -40C all ice_wat - BC_side%q_BC(i,j,k,liq_wat) = 0. - BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - else - if ( k.eq.1 ) then ! between [-40,0]: linear interpolation - BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k)*((BC_side%pt_BC(i,j,k)-233.16)/40.) - BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - BC_side%q_BC(i,j,k,liq_wat) - else - if (BC_side%pt_BC(i,j,k)<258.16 .and. BC_side%q_BC(i,j,k-1,ice_wat)>1.e-5 ) then - BC_side%q_BC(i,j,k,liq_wat) = 0. - BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - else ! between [-40,0]: linear interpolation - BC_side%q_BC(i,j,k,liq_wat) = qn1(i,k)*((BC_side%pt_BC(i,j,k)-233.16)/40.) - BC_side%q_BC(i,j,k,ice_wat) = qn1(i,k) - BC_side%q_BC(i,j,k,liq_wat) - endif - endif - endif #endif call mp_auto_conversion(BC_side%q_BC(i,j,k,liq_wat), BC_side%q_BC(i,j,k,rainwat), & BC_side%q_BC(i,j,k,ice_wat), BC_side%q_BC(i,j,k,snowwat) ) diff --git a/tools/external_ic.F90 b/tools/external_ic.F90 index 893aa7c2b..56cd554f7 100644 --- a/tools/external_ic.F90 +++ b/tools/external_ic.F90 @@ -804,13 +804,6 @@ subroutine get_nggps_ic (Atm, fv_domain) Atm%q(i,j,k,rainwat) + & Atm%q(i,j,k,snowwat) + & Atm%q(i,j,k,graupel))) - elseif ( Atm%flagstruct%nwat == 7 ) then ! may not need this. 'else' should cover both 6 and 7? - qt = wt/(1. - (Atm%q(i,j,k,liq_wat) + & - Atm%q(i,j,k,ice_wat) + & - Atm%q(i,j,k,rainwat) + & - Atm%q(i,j,k,snowwat) + & - Atm%q(i,j,k,graupel) + & - Atm%q(i,j,k,hailwat))) else ! all other values of nwat qt = wt/(1. - sum(Atm%q(i,j,k,2:Atm%flagstruct%nwat))) endif @@ -832,13 +825,6 @@ subroutine get_nggps_ic (Atm, fv_domain) Atm%q(i,j,k,rainwat) + & Atm%q(i,j,k,snowwat) + & Atm%q(i,j,k,graupel)) - elseif ( Atm%flagstruct%nwat == 7 ) then ! may not need this. 'else' should cover both 6 and 7? - qt = wt*(1. + Atm%q(i,j,k,liq_wat) + & - Atm%q(i,j,k,ice_wat) + & - Atm%q(i,j,k,rainwat) + & - Atm%q(i,j,k,snowwat) + & - Atm%q(i,j,k,graupel) + & - Atm%q(i,j,k,hailwat)) else ! all other values of nwat qt = wt*(1. + sum(Atm%q(i,j,k,2:Atm%flagstruct%nwat))) endif @@ -958,11 +944,7 @@ subroutine read_gfs_ic() do nt = 1, ntracers - IF ( .not. ( nt == Atm%flagstruct%nwat .and. Atm%flagstruct%nwat == 7 ) ) THEN q(:,:,:,nt) = -999.99 - ELSE - q(:,:,:,nt) = 0 ! nonzero values can cause problems for water mass tracers not in the input (like hail mixing ratio; hailwat not defined at this point) - ENDIF call get_tracer_names(MODEL_ATMOS, nt, tracer_name) call register_restart_field(GFS_restart, trim(tracer_name), q(:,:,:,nt), dim_names_3d3, is_optional=.true.) @@ -3117,7 +3099,7 @@ subroutine remap_scalar(Atm, km, npz, ncnst, ak0, bk0, psc, qa, zh, omga, t_in) ! map tracers do iq=1,ncnst -! if (floor(qa(is,j,1,iq)) == -1000) cycle !skip missing scalars [floor(-999.99) is -1000] + if (floor(qa(is,j,1,iq)) == -1000) cycle !skip missing scalars [floor(-999.99) is -1000] do k=1,km do i=is,ie qp(i,k) = qa(i,j,k,iq) From 1aa30980229763d5aa2abe72bdeb329bcce4cbc4 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Mon, 31 Jan 2022 17:36:12 -0600 Subject: [PATCH 12/13] Check actual index (hailwat) instead of assuming a positive value based on 'nwat' value --- model/fv_regional_bc.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/fv_regional_bc.F90 b/model/fv_regional_bc.F90 index 779cba36f..8e876d58e 100644 --- a/model/fv_regional_bc.F90 +++ b/model/fv_regional_bc.F90 @@ -3769,7 +3769,7 @@ subroutine remap_scalar_nggps_regional_bc(Atm & ! if ( .not. data_source_fv3gfs ) then if ( Atm%flagstruct%nwat .eq. 6 .or. Atm%flagstruct%nwat .eq. 7 ) then - if ( Atm%flagstruct%nwat .eq. 7 ) then + if ( hailwat > 0 ) then BC_side%q_BC(is:ie,j,1:npz,hailwat) = 0. endif do k=1,npz From f3d071f35020f23eb706fe0c8760117e0935aab6 Mon Sep 17 00:00:00 2001 From: Ted Mansell Date: Fri, 4 Feb 2022 14:52:12 -0600 Subject: [PATCH 13/13] Split nwat=7 bits into separate loops (see if it affects nwat=6) --- model/fv_sg.F90 | 82 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/model/fv_sg.F90 b/model/fv_sg.F90 index 1e5ef4bf8..2446b1144 100644 --- a/model/fv_sg.F90 +++ b/model/fv_sg.F90 @@ -321,13 +321,22 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - elseif ( nwat >= 6 ) then + elseif ( nwat == 6 ) then do i=is,ie q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) - IF ( nwat == 7 ) THEN - q_sol = q_sol + q0(i,k,hailwat) - ENDIF +#ifdef MULTI_GASES + cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#else + cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#endif + enddo + elseif ( nwat == 7 ) then + do i=is,ie + q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) + q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) + q0(i,k,hailwat) #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -602,13 +611,22 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - elseif ( nwat >= 6 ) THEN + elseif ( nwat == 6 ) THEN do i=is,ie q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat) q_sol = q0(i,kk,ice_wat) + q0(i,kk,snowwat) + q0(i,kk,graupel) - IF ( nwat == 7 ) THEN - q_sol = q_sol + q0(i,kk,hailwat) - ENDIF +#ifdef MULTI_GASES + cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#else + cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#endif + enddo + elseif ( nwat == 7 ) THEN + do i=is,ie + q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat) + q_sol = q0(i,kk,ice_wat) + q0(i,kk,snowwat) + q0(i,kk,graupel) + q0(i,kk,hailwat) #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -885,13 +903,22 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - elseif ( nwat >= 6 ) THEN + elseif ( nwat == 6 ) THEN do i=is,ie q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) - IF ( nwat == 7 ) THEN - q_sol = q_sol + q0(i,k,hailwat) - ENDIF +#ifdef MULTI_GASES + cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#else + cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#endif + enddo + elseif ( nwat == 7 ) THEN + do i=is,ie + q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) + q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) + q0(i,k,hailwat) #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -1160,13 +1187,22 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #endif enddo - elseif ( nwat >= 6 ) THEN + elseif ( nwat == 6 ) THEN do i=is,ie q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat) q_sol = q0(i,kk,ice_wat) + q0(i,kk,snowwat) + q0(i,kk,graupel) - IF ( nwat == 7 ) THEN - q_sol = q_sol + q0(i,kk,hailwat) - ENDIF +#ifdef MULTI_GASES + cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#else + cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice + cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice +#endif + enddo + elseif ( nwat == 7 ) THEN + do i=is,ie + q_liq = q0(i,kk,liq_wat) + q0(i,kk,rainwat) + q_sol = q0(i,kk,ice_wat) + q0(i,kk,snowwat) + q0(i,kk,graupel) + q0(i,kk,hailwat) #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,kk,:)) + q0(i,kk,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice cvm(i) = (1.-(q0(i,kk,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,kk,:)) + q0(i,kk,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice @@ -1219,7 +1255,7 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & ! Saturation adjustment !---------------------- #ifndef GFS_PHYS - if ( nwat >= 6 ) then + if ( nwat == 6 ) then do k=1, kbot if ( hydrostatic ) then do i=is, ie @@ -1231,9 +1267,9 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & #endif q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) - IF ( nwat == 7 ) THEN - q_sol = q_sol + q0(i,k,hailwat) - ENDIF +! IF ( nwat == 7 ) THEN +! q_sol = q_sol + q0(i,k,hailwat) +! ENDIF #ifdef MULTI_GASES cpm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cp_air*vicpqd(q0(i,k,:)) + q0(i,k,sphum)*cp_vapor + q_liq*c_liq + q_sol*c_ice #else @@ -1247,9 +1283,9 @@ subroutine fv_subgrid_z( isd, ied, jsd, jed, is, ie, js, je, km, nq, dt, & den(i,k) = -delp(i,j,k)/(grav*delz(i,j,k)) q_liq = q0(i,k,liq_wat) + q0(i,k,rainwat) q_sol = q0(i,k,ice_wat) + q0(i,k,snowwat) + q0(i,k,graupel) - IF ( nwat == 7 ) THEN - q_sol = q_sol + q0(i,k,hailwat) - ENDIF +! IF ( nwat == 7 ) THEN +! q_sol = q_sol + q0(i,k,hailwat) +! ENDIF #ifdef MULTI_GASES cvm(i) = (1.-(q0(i,k,sphum)+q_liq+q_sol))*cv_air*vicvqd(q0(i,k,:)) + q0(i,k,sphum)*cv_vap + q_liq*c_liq + q_sol*c_ice #else