Skip to content

Commit 604d76b

Browse files
committed
update compute_frontogenesis for zgrad correction
1 parent d1f9d94 commit 604d76b

File tree

2 files changed

+66
-46
lines changed

2 files changed

+66
-46
lines changed

components/eam/src/dynamics/se/dp_coupling.F90

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
3838
use cam_abortutils, only: endrun
3939
use gravity_waves_sources, only: gws_src_fnct
4040
use dyn_comp, only: frontgf_idx, frontga_idx, hvcoord
41-
use phys_control, only: use_gw_front, use_fgf_pgrad_correction
41+
use phys_control, only: use_gw_front, use_fgf_pgrad_correction, use_fgf_zgrad_correction
4242
use dyn_comp, only: dom_mt
4343
use gllfvremap_mod, only: gfr_dyn_to_fv_phys
4444

@@ -107,7 +107,10 @@ subroutine d_p_coupling(phys_state, phys_tend, pbuf2d, dyn_out)
107107
elem => dyn_out%elem
108108
tl_f = TimeLevel%n0 ! time split physics (with forward-in-time RK)
109109

110-
if (use_gw_front) call gws_src_fnct(elem, tl_f, nphys, use_fgf_pgrad_correction, frontgf, frontga)
110+
if (use_gw_front) call gws_src_fnct(elem, tl_f, nphys, &
111+
use_fgf_pgrad_correction, &
112+
use_fgf_zgrad_correction, &
113+
frontgf, frontga)
111114

112115
if (fv_nphys > 0) then
113116
!-----------------------------------------------------------------------

components/eam/src/dynamics/se/gravity_waves_sources.F90

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ subroutine gws_init(elem)
3838

3939
end subroutine gws_init
4040
!-------------------------------------------------------------------------------------------------
41-
subroutine gws_src_fnct(elem, tl, nphys, use_fgf_pgrad_correction, frontgf, frontga)
41+
subroutine gws_src_fnct(elem, tl, nphys, use_fgf_pgrad_correction, use_fgf_zgrad_correction, frontgf, frontga)
4242
use dimensions_mod, only : npsq, nelemd
4343
use dof_mod, only : UniquePoints
4444
use dyn_comp, only : dom_mt
@@ -52,6 +52,7 @@ subroutine gws_src_fnct(elem, tl, nphys, use_fgf_pgrad_correction, frontgf, fron
5252
integer, intent(in ) :: tl
5353
integer, intent(in ) :: nphys
5454
logical, intent(in ) :: use_fgf_pgrad_correction
55+
logical, intent(in ) :: use_fgf_zgrad_correction
5556
real (kind=real_kind), intent(out ) :: frontgf(nphys*nphys,pver,nelemd)
5657
real (kind=real_kind), intent(out ) :: frontga(nphys*nphys,pver,nelemd)
5758

@@ -68,7 +69,10 @@ subroutine gws_src_fnct(elem, tl, nphys, use_fgf_pgrad_correction, frontgf, fron
6869
hybrid = hybrid_create(par,ithr,hthreads)
6970
allocate(frontgf_thr(nphys,nphys,nlev,nets:nete))
7071
allocate(frontga_thr(nphys,nphys,nlev,nets:nete))
71-
call compute_frontogenesis(frontgf_thr,frontga_thr,tl,use_fgf_pgrad_correction,elem,hybrid,nets,nete,nphys)
72+
call compute_frontogenesis( frontgf_thr, frontga_thr, tl, &
73+
use_fgf_pgrad_correction, &
74+
use_fgf_zgrad_correction, &
75+
elem, hybrid, nets, nete, nphys )
7276
if (fv_nphys>0) then
7377
do ie = nets,nete
7478
do k = 1,nlev
@@ -89,7 +93,10 @@ subroutine gws_src_fnct(elem, tl, nphys, use_fgf_pgrad_correction, frontgf, fron
8993

9094
end subroutine gws_src_fnct
9195
!-------------------------------------------------------------------------------------------------
92-
subroutine compute_frontogenesis(frontgf,frontga,tl,use_fgf_pgrad_correction,elem,hybrid,nets,nete,nphys)
96+
subroutine compute_frontogenesis( frontgf, frontga, tl, &
97+
use_fgf_pgrad_correction, &
98+
use_fgf_zgrad_correction, &
99+
elem, hybrid, nets, nete, nphys )
93100
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
94101
! compute frontogenesis function F
95102
! F = -gradth dot C
@@ -109,14 +116,14 @@ subroutine compute_frontogenesis(frontgf,frontga,tl,use_fgf_pgrad_correction,ele
109116
! added pressure gradient correction
110117
!
111118
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
112-
use physical_constants, only: kappa
119+
use physical_constants, only: kappa, g
113120
use derivative_mod, only: gradient_sphere, ugradv_sphere
114121
use edge_mod, only: edge_g, edgevpack_nlyr, edgevunpack_nlyr
115122
use bndry_mod, only: bndry_exchangev
116123
use dyn_comp, only: hvcoord
117124
use spmd_utils, only: iam
118125
use parallel_mod, only: par
119-
use element_ops, only: get_temperature, get_hydro_pressure
126+
use element_ops, only: get_temperature, get_hydro_pressure, get_phi
120127
use dyn_grid, only: fv_nphys
121128
use prim_driver_mod, only: deriv1
122129
use gllfvremap_mod, only: gfr_g2f_scalar, gfr_g2f_vector
@@ -126,24 +133,27 @@ subroutine compute_frontogenesis(frontgf,frontga,tl,use_fgf_pgrad_correction,ele
126133
integer, intent(in ) :: nets,nete,nphys
127134
integer, intent(in ) :: tl ! timelevel to use
128135
logical, intent(in ) :: use_fgf_pgrad_correction
136+
logical, intent(in ) :: use_fgf_zgrad_correction
129137
real(kind=real_kind), intent(out ) :: frontgf(nphys,nphys,nlev,nets:nete)
130138
real(kind=real_kind), intent(out ) :: frontga(nphys,nphys,nlev,nets:nete)
131139

132140
! local
133141
integer :: k,kptr,i,j,ie,component
134142
real(kind=real_kind) :: frontgf_gll(np,np,nlev,nets:nete)
135143
real(kind=real_kind) :: gradth_gll(np,np,2,nlev,nets:nete) ! grad(theta)
136-
real(kind=real_kind) :: pmid(np,np,nlev) ! hydrostatic pressure at mid points
144+
real(kind=real_kind) :: pint(np,np,nlev) ! interface hydrostatic pressure
145+
real(kind=real_kind) :: pmid(np,np,nlev) ! mid-point hydrostatic pressure
137146
real(kind=real_kind) :: temperature(np,np,nlev) ! Temperature
138147
real(kind=real_kind) :: C(np,np,2), wf1(nphys*nphys,nlev), wf2(nphys*nphys,nlev)
139148

140-
! variables needed for eta to pressure surface correction
141-
real(kind=real_kind) :: gradp_gll(np,np,2) ! grad(pressure)
142149
real(kind=real_kind) :: theta(np,np,nlev) ! potential temperature at mid points
143-
real(kind=real_kind) :: dtheta_dp(np,np,nlev) ! d(theta)/dp for eta to pressure surface correction
144150
real(kind=real_kind) :: dum_grad(np,np,2) ! temporary variable for spherical gradient calcualtions
145151
real(kind=real_kind) :: dum_cart(np,np,3,nlev) ! temporary variable for cartesian gradient calcualtions
146-
real(kind=real_kind) :: ddp_dum_cart(np,np,3,nlev) ! vertical pressure derivative of dum_cart
152+
153+
! variables needed for eta to pressure surface correction
154+
real(kind=real_kind) :: grad_vert_gll(np,np,2,nlev) ! grad(vertical coordinate) - either pressure or geopotential
155+
real(kind=real_kind) :: theta_dvert(np,np,nlev) ! d(theta)/dp for eta to pressure surface correction
156+
real(kind=real_kind) :: dum_cart_dvert(np,np,3,nlev)! vertical pressure derivative of dum_cart
147157

148158
!---------------------------------------------------------------------------
149159
!
@@ -178,23 +188,34 @@ subroutine compute_frontogenesis(frontgf,frontga,tl,use_fgf_pgrad_correction,ele
178188

179189
do ie = nets,nete
180190

181-
if (use_fgf_pgrad_correction) then
191+
if (use_fgf_pgrad_correction .or. use_fgf_zgrad_correction) then
182192

183-
! compute pressure at mid points
184-
call get_hydro_pressure(pmid,elem(ie)%state%dp3d(:,:,:,tl),hvcoord)
193+
! compute pressure at interfaces and mid-points
194+
call get_hydro_pressure_interface(pint,elem(ie)%state%dp3d(:,:,:,tl),hvcoord)
185195

186196
call get_temperature(elem(ie),temperature,hvcoord,tl)
197+
198+
! calculate pmid and potential temperature: theta = T (p/p0)^kappa
187199
do k = 1,nlev
188-
! potential temperature: theta = T (p/p0)^kappa
200+
pmid(:,:,k) = pint(:,:,k) + elem(ie)%state%dp3d(:,:,k,tl)/2
189201
theta(:,:,k) = temperature(:,:,k)*(psurf_ref / pmid(:,:,k))**kappa
190202
end do
191-
call compute_vertical_derivative(tl,ie,elem,theta,dtheta_dp)
203+
204+
if (use_fgf_pgrad_correction) call compute_vertical_derivative(pint,theta,theta_dvert)
205+
206+
if (use_fgf_zgrad_correction) then
207+
call get_phi(elem(ie),phi_mid,phi_int,hvcoord,tl)
208+
zmid(:,:,:) = phi_mid(:,:,:)/g
209+
zint(:,:,:) = phi_int(:,:,:)/g
210+
call compute_vertical_derivative(zint,theta,theta_dvert)
211+
end if
192212

193213
do k = 1,nlev
194214
gradth_gll(:,:,:,k,ie) = gradient_sphere(theta(:,:,k),deriv1,elem(ie)%Dinv)
195-
gradp_gll(:,:,:) = gradient_sphere(pmid(:,:,k),deriv1,elem(ie)%Dinv)
215+
if (use_fgf_pgrad_correction) grad_vert_gll(:,:,:,k) = gradient_sphere(pmid(:,:,k),deriv1,elem(ie)%Dinv)
216+
if (use_fgf_zgrad_correction) grad_vert_gll(:,:,:,k) = gradient_sphere(zmid(:,:,k),deriv1,elem(ie)%Dinv)
196217
do component=1,2
197-
gradth_gll(:,:,component,k,ie) = gradth_gll(:,:,component,k,ie) - dtheta_dp(:,:,k) * gradp_gll(:,:,component)
218+
gradth_gll(:,:,component,k,ie) = gradth_gll(:,:,component,k,ie) - theta_dvert(:,:,k) * grad_vert_gll(:,:,component,k)
198219
end do
199220
end do
200221

@@ -206,16 +227,15 @@ subroutine compute_frontogenesis(frontgf,frontga,tl,use_fgf_pgrad_correction,ele
206227
end do
207228

208229
do component=1,3
209-
call compute_vertical_derivative(tl,ie,elem,dum_cart(:,:,component,:),ddp_dum_cart(:,:,component,:))
230+
call compute_vertical_derivative(tl,ie,elem,dum_cart(:,:,component,:),dum_cart_dvert(:,:,component,:))
210231
end do
211232

212233
do k = 1,nlev
213-
gradp_gll(:,:,:) = gradient_sphere(pmid(:,:,k),deriv1,elem(ie)%Dinv)
214234
! Do ugradv on the cartesian components - Dot u with the gradient of each component
215235
do component=1,3
216236
dum_grad(:,:,:) = gradient_sphere(dum_cart(:,:,component,k),deriv1,elem(ie)%Dinv)
217237
do i=1,2
218-
dum_grad(:,:,i) = dum_grad(:,:,i) - ddp_dum_cart(:,:,component,k) * gradp_gll(:,:,i)
238+
dum_grad(:,:,i) = dum_grad(:,:,i) - dum_cart_dvert(:,:,component,k) * grad_vert_gll(:,:,i,k)
219239
end do
220240
dum_cart(:,:,component,k) = sum( gradth_gll(:,:,:,k,ie) * dum_grad ,3)
221241
enddo
@@ -291,39 +311,36 @@ subroutine compute_frontogenesis(frontgf,frontga,tl,use_fgf_pgrad_correction,ele
291311

292312
end subroutine compute_frontogenesis
293313
!-------------------------------------------------------------------------------------------------
294-
subroutine compute_vertical_derivative(tl,ie,elem,data,ddata_dp)
295-
use dyn_comp, only: hvcoord
314+
subroutine compute_vertical_derivative(vert_int, data_mid, ddata_dvert)
296315
!---------------------------------------------------------------------------
297-
integer, intent(in ) :: tl ! timelevel to use
298-
integer, intent(in ) :: ie ! current element index
299-
type(element_t),target, intent(inout) :: elem(:)
300-
real(kind=real_kind), intent(in ) :: data(np,np,nlev)
301-
real(kind=real_kind), intent(out) :: ddata_dp(np,np,nlev)
316+
real(kind=real_kind), intent(in ) :: vert_int(np,np,nlev) ! vertical coord on interfaces (i.e. pint or zint)
317+
real(kind=real_kind), intent(in ) :: data_mid(np,np,nlev) ! input data in mid-points
318+
real(kind=real_kind), intent(out) :: ddata_dvert(np,np,nlev) ! vertical derivative of data
302319
!---------------------------------------------------------------------------
303320
integer :: k
304-
real(kind=real_kind) :: pint_above(np,np) ! pressure interpolated to interface above the current k mid-point
305-
real(kind=real_kind) :: pint_below(np,np) ! pressure interpolated to interface below the current k mid-point
306-
real(kind=real_kind) :: dint_above(np,np) ! data interpolated to interface above the current k mid-point
307-
real(kind=real_kind) :: dint_below(np,np) ! data interpolated to interface below the current k mid-point
321+
real(kind=real_kind) :: vert_above(np,np) ! pressure interpolated to interface above the current k mid-point
322+
real(kind=real_kind) :: vert_below(np,np) ! pressure interpolated to interface below the current k mid-point
323+
real(kind=real_kind) :: data_above(np,np) ! data interpolated to interface above the current k mid-point
324+
real(kind=real_kind) :: data_below(np,np) ! data interpolated to interface below the current k mid-point
308325
!---------------------------------------------------------------------------
309326
do k = 1,nlev
310327
if (k==1) then
311-
pint_above = hvcoord%hyam(k+0)*hvcoord%ps0 + hvcoord%hybm(k+0)*elem(ie)%state%ps_v(:,:,tl)
312-
pint_below = hvcoord%hyai(k+1)*hvcoord%ps0 + hvcoord%hybi(k+1)*elem(ie)%state%ps_v(:,:,tl)
313-
dint_above = data(:,:,k)
314-
dint_below = ( data(:,:,k+1) + data(:,:,k) ) / 2.0
328+
data_above = data_mid(:,:,k)
329+
data_below = ( data_mid(:,:,k+1) + data_mid(:,:,k) ) / 2.0 ! interpolate to interface k+1
330+
vert_above = ( vert_int(:,:,k+1) + vert_int(:,:,k) ) / 2.0 ! interpolate to mid-point k
331+
vert_below = vert_int(:,:,k+1)
315332
elseif (k==nlev) then
316-
pint_above = hvcoord%hyai(k+0)*hvcoord%ps0 + hvcoord%hybi(k+0)*elem(ie)%state%ps_v(:,:,tl)
317-
pint_below = hvcoord%hyam(k+0)*hvcoord%ps0 + hvcoord%hybm(k+0)*elem(ie)%state%ps_v(:,:,tl)
318-
dint_above = ( data(:,:,k-1) + data(:,:,k) ) / 2.0
319-
dint_below = data(:,:,k)
333+
data_above = ( data_mid(:,:,k-1) + data_mid(:,:,k) ) / 2.0 ! interpolate to interface
334+
data_below = data_mid(:,:,k)
335+
vert_above = vert_int(:,:,k)
336+
vert_below = ( vert_int(:,:,k+1) + vert_int(:,:,k) ) / 2.0 ! interpolate to mid-point k
320337
else
321-
pint_above = hvcoord%hyai(k+0)*hvcoord%ps0 + hvcoord%hybi(k+0)*elem(ie)%state%ps_v(:,:,tl)
322-
pint_below = hvcoord%hyai(k+1)*hvcoord%ps0 + hvcoord%hybi(k+1)*elem(ie)%state%ps_v(:,:,tl)
323-
dint_above = ( data(:,:,k-1) + data(:,:,k) ) / 2.0
324-
dint_below = ( data(:,:,k+1) + data(:,:,k) ) / 2.0
338+
data_above = ( data_mid(:,:,k-1) + data_mid(:,:,k) ) / 2.0 ! interpolate to interface k
339+
data_below = ( data_mid(:,:,k+1) + data_mid(:,:,k) ) / 2.0 ! interpolate to interface k+1
340+
vert_above = pint(:,:,k)
341+
vert_below = pint(:,:,k+1)
325342
end if
326-
ddata_dp(:,:,k) = ( dint_above - dint_below ) / ( pint_above - pint_below )
343+
ddata_dvert(:,:,k) = ( data_above - data_below ) / ( vert_above - vert_below )
327344
end do
328345
end subroutine compute_vertical_derivative
329346
!-------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)