FE-Project
Loading...
Searching...
No Matches
scale_atm_phy_bl_dgm_mynn_lv2 Module Reference

module FElib / Atmosphere / Physics / boundary layer turbulence More...

Functions/Subroutines

subroutine, public atm_phy_bl_dgm_mynn_lv2_init (mesh)
 Initialize a module of MYNN Level 2 PBL turbulence parameterization.
subroutine, public atm_phy_bl_dgm_mynn_lv2_final ()
 Finalize a module of MYNN Level 2 PBL turbulence parameterization.
subroutine, public atm_phy_bl_dgm_mynn_lv2_cal_vviscdiffcoef (nu, kh, tke, ddens_, momx_, momy_, momz_, drhot_, dens_hyd, pres_hyd, rtot, pres, pt, dz, lift, lmesh, elem, is_bound)

Detailed Description

module FElib / Atmosphere / Physics / boundary layer turbulence

Description
A module to provide routines to calculate turbulent diffusion coefficients based on the Mellor-Yamada-Nakanishi-Niino (MYNN) Level 2 closure.

This implementation uses the Level 2 diagnostic closure only. Prognostic turbulent kinetic energy, nonlocal mixing, and the MY Level 2.5 equations are not included.

Reference
Mellor, G. L. and T. Yamada, 1982: Development of a turbulence closure model for geophysical fluid problems. Reviews of Geophysics and Space Physics, 20, 851-875.

Nakanishi, M. and H. Niino, 2009: Development of an improved turbulence closure model for the atmospheric boundary layer. Journal of the Meteorological Society of Japan, 87, 895-912.

Blackadar, A. K., 1962: The vertical distribution of wind and turbulent exchange in a neutral atmosphere. Journal of Geophysical Research, 67, 3095-3102.

Author
Yuta Kawai, Team SCALE
NAMELIST
  • PARAM_ATMOS_PHY_BL_DGM_MYNN_LV2
    nametypedefault valuecomment
    L_INFreal(RP)100.0_RP
    L_MINreal(RP)1.0E-6_RP

History Output
No history output

Function/Subroutine Documentation

◆ atm_phy_bl_dgm_mynn_lv2_init()

subroutine, public scale_atm_phy_bl_dgm_mynn_lv2::atm_phy_bl_dgm_mynn_lv2_init ( class(meshbase3d), intent(in) mesh)

Initialize a module of MYNN Level 2 PBL turbulence parameterization.

Definition at line 104 of file scale_atm_phy_bl_dgm_mynn_lv2.F90.

105 implicit none
106 class(MeshBase3D), intent(in) :: mesh
107
108 namelist / param_atmos_phy_bl_dgm_mynn_lv2 / &
109 l_inf, l_min
110
111 integer :: ierr
112 !--------------------------------------------------------------------------------
113
114 log_newline
115 log_info("ATMOS_PHY_BL_DGM_MYNN_LV2_setup",*) 'Setup'
116 log_info("ATMOS_PHY_BL_DGM_MYNN_LV2_setup",*) 'MYNN Level 2 PBL turbulence parameterization'
117
118 !--- read namelist
119 rewind(io_fid_conf)
120 read(io_fid_conf,nml=param_atmos_phy_bl_dgm_mynn_lv2,iostat=ierr)
121 if( ierr < 0 ) then !--- missing
122 log_info("ATMOS_PHY_BL_DGM_MYNN_LV2_setup",*) 'Not found namelist. Default used.'
123 elseif( ierr > 0 ) then !--- fatal error
124 log_error("ATMOS_PHY_BL_DGM_MYNN_LV2_setup",*) 'Not appropriate names in namelist PARAM_ATMOS_PHY_BL_DGM_MYNN_LV2. Check!'
125 call prc_abort
126 endif
127 log_nml(param_atmos_phy_bl_dgm_mynn_lv2)
128
129 !-
130
131 g2 = ( 2.0_rp * a1 * ( 3.0_rp - 2.0_rp * c2 ) &
132 + b2 * ( 1.0_rp - c3 ) &
133 ) / b1
134
135 f2 = b1 * ( g1 + g2 ) &
136 - 3.0_rp * a1 * ( 1.0_rp - c2 )
137
138 rf2 = b1 * g1 / f2
139
140 rfc = g1 / ( g1 + g2 )
141 return

◆ atm_phy_bl_dgm_mynn_lv2_final()

subroutine, public scale_atm_phy_bl_dgm_mynn_lv2::atm_phy_bl_dgm_mynn_lv2_final

Finalize a module of MYNN Level 2 PBL turbulence parameterization.

Definition at line 146 of file scale_atm_phy_bl_dgm_mynn_lv2.F90.

147 implicit none
148 !--------------------------------------------------------------------------------
149 return

◆ atm_phy_bl_dgm_mynn_lv2_cal_vviscdiffcoef()

subroutine, public scale_atm_phy_bl_dgm_mynn_lv2::atm_phy_bl_dgm_mynn_lv2_cal_vviscdiffcoef ( real(rp), dimension(elem%np,lmesh%nea), intent(out) nu,
real(rp), dimension(elem%np,lmesh%nea), intent(out) kh,
real(rp), dimension(elem%np,lmesh%nea), intent(out) tke,
real(rp), dimension(elem%np,lmesh%nea), intent(in) ddens_,
real(rp), dimension (elem%np,lmesh%nea), intent(in) momx_,
real(rp), dimension (elem%np,lmesh%nea), intent(in) momy_,
real(rp), dimension (elem%np,lmesh%nea), intent(in) momz_,
real(rp), dimension(elem%np,lmesh%nea), intent(in) drhot_,
real(rp), dimension(elem%np,lmesh%nea), intent(in) dens_hyd,
real(rp), dimension(elem%np,lmesh%nea), intent(in) pres_hyd,
real(rp), dimension(elem%np,lmesh%nea), intent(in) rtot,
real(rp), dimension(elem%np,lmesh%nea), intent(in) pres,
real(rp), dimension(elem%np,lmesh%nea), intent(in) pt,
type(sparsemat), intent(in) dz,
type(sparsemat), intent(in) lift,
class(localmesh3d), intent(in) lmesh,
class(elementbase3d), intent(in) elem,
logical, dimension(elem%nfptot,lmesh%ne), intent(in) is_bound )
Parameters
[out]nuVertical eddy viscosity
[out]khVertical eddy diffusivity
[out]tkeTurbulent kinetic energy
[in]ddens_Density perturbation
[in]momx_Momentum in x1 direction
[in]momy_Momentum in x2 direction
[in]momz_Momentum in x3 direction
[in]drhot_Density x potential temperature perturbation
[in]dens_hydReference density in hydrostatic balance
[in]pres_hydReference pressure in hydrostatic balance
[in]rtotGas constant
[in]presPressure
[in]ptPotential temperature
[in]is_boundFlag whether nodes are located at domain boundaries

Definition at line 153 of file scale_atm_phy_bl_dgm_mynn_lv2.F90.

158 implicit none
159 class(LocalMesh3D), intent(in) :: lmesh
160 class(ElementBase3D), intent(in) :: elem
161 real(RP), intent(out) :: Nu(elem%Np,lmesh%NeA) !< Vertical eddy viscosity
162 real(RP), intent(out) :: Kh(elem%Np,lmesh%NeA) !< Vertical eddy diffusivity
163 real(RP), intent(out) :: TKE(elem%Np,lmesh%NeA) !< Turbulent kinetic energy
164 real(RP), intent(in) :: DDENS_(elem%Np,lmesh%NeA) !< Density perturbation
165 real(RP), intent(in) :: MOMX_ (elem%Np,lmesh%NeA) !< Momentum in x1 direction
166 real(RP), intent(in) :: MOMY_ (elem%Np,lmesh%NeA) !< Momentum in x2 direction
167 real(RP), intent(in) :: MOMZ_ (elem%Np,lmesh%NeA) !< Momentum in x3 direction
168 real(RP), intent(in) :: DRHOT_(elem%Np,lmesh%NeA) !< Density x potential temperature perturbation
169 real(RP), intent(in) :: DENS_hyd(elem%Np,lmesh%NeA) !< Reference density in hydrostatic balance
170 real(RP), intent(in) :: PRES_hyd(elem%Np,lmesh%NeA) !< Reference pressure in hydrostatic balance
171 real(RP), intent(in) :: Rtot(elem%Np,lmesh%NeA) !< Gas constant
172 real(RP), intent(in) :: PRES(elem%Np,lmesh%NeA) !< Pressure
173 real(RP), intent(in) :: PT(elem%Np,lmesh%NeA) !< Potential temperature
174 type(SparseMat), intent(in) :: Dz, Lift
175 logical, intent(in) :: is_bound(elem%NfpTot,lmesh%Ne) !< Flag whether nodes are located at domain boundaries
176
177 real(RP) :: Fz(elem%Np), LiftDelFlx(elem%Np)
178 real(RP) :: DENS(elem%Np), RDENS(elem%Np), RHOT(elem%Np), Q(elem%Np)
179 real(RP) :: DdensDz(elem%Np), DVelDz(elem%Np,3), DptDz(elem%Np), DrtotDz(elem%Np)
180
181 real(RP) :: del_flux_rho (elem%NfpTot,lmesh%Ne)
182 real(RP) :: del_flux_mom (elem%NfpTot,lmesh%Ne,3)
183 real(RP) :: del_flux_rhot(elem%NfpTot,lmesh%Ne)
184 real(RP) :: del_flux_Rtot(elem%NfpTot,lmesh%Ne)
185
186 real(RP) :: S2(elem%Np) ! Square of vertical shear of horizontal wind
187 real(RP) :: N2 ! Square of Brunt-Vaisala frequency
188 real(RP) :: Ri ! Richardson number
189 real(RP) :: Rf(elem%Np) ! Flux Richardson number
190
191 real(RP) :: A2_loc
192 real(RP) :: F1
193 real(RP) :: Rf1
194 real(RP) :: AF12
195 real(RP) :: discriminant
196 real(RP) :: denom_h
197 real(RP) :: denom_m
198 real(RP) :: S_M(elem%Np), S_H(elem%Np) ! Stability functions for momentum and heat
199
200 real(RP) :: mixlen(elem%Np) ! Mixing length
201 real(RP) :: zsfc(elem%Nnode_h1D**2,lmesh%Ne2D) ! Surface height
202 real(RP) :: dz1(elem%Nnode_h1D**2,lmesh%Ne2D) ! Vertical grid spacing at the first layer
203 integer :: HSlice_b(elem%Nnode_h1D**2)
204 integer :: HSlice_t(elem%Nnode_h1D**2)
205
206 real(RP) :: kz
207
208 integer :: ke, ke2D
209 integer :: p, ph, pz
210 class(LocalMesh2D), pointer :: lmesh2D
211 class(ElementBase2D), pointer :: elem2D
212
213 real(RP), parameter :: EPS_RF = 1.0e-10_rp
214 real(RP), parameter :: EPS_DISC = 1.0e-14_rp
215 !--------------------------------------------------------------------------------
216
217 ! For standard case of NN2009, these parameter are independent of Ri.
218 ! If we will implement the K2010 correction in the future,
219 ! these parameter should be calculated in the ke loop because they depend on Ri (i.e., A2_loc = A_2/(1+Ri)).
220 a2_loc = a2
221
222 f1 = b1 * ( g1 - c1 ) &
223 + 2.0_rp * a1 * ( 3.0_rp - 2.0_rp * c2 ) &
224 + 3.0_rp * a2_loc * ( 1.0_rp - c3 ) * ( 1.0_rp - c5 )
225
226 rf1 = b1 * ( g1 - c1 ) / f1
227
228 af12 = a1 * f1 / ( a2_loc * f2 )
229
230 lmesh2d => lmesh%lcmesh2D
231 elem2d => lmesh2d%refElem2D
232
233 hslice_b(:) = elem%Hslice(:,1)
234 hslice_t(:) = elem%Hslice(:,elem%Nnode_v)
235
236 !---------------------------------
237
238 call cal_del_flux_grad( del_flux_rho, del_flux_mom, del_flux_rhot, del_flux_rtot, & ! (out)
239 ddens_, momx_, momy_, momz_, drhot_, rtot, dens_hyd, pres_hyd, pt, & ! (in)
240 lmesh%normal_fn(:,:,3), lmesh%Fscale, lmesh%vmapM, lmesh%vmapP, & ! (in)
241 lmesh, elem, is_bound ) ! (in)
242
243 !$omp parallel &
244 !$omp private( ke2D, Fz, LiftDelFlx, DENS, RDENS, RHOT, Q, DdensDz, DVelDz, DptDz, DrtotDz, &
245 !$omp N2, S2, Ri, Rf, discriminant, denom_m, denom_h, S_M, S_H, mixlen, kz )
246
247 !$omp do
248 do ke2d=lmesh2d%NeS, lmesh2d%NeE
249 zsfc(:,ke2d) = lmesh%zlev(hslice_b,ke2d)
250 dz1(:,ke2d) = ( lmesh%zlev(hslice_t,ke2d) - lmesh%zlev(hslice_b,ke2d) ) / real(elem%Nnode_v,kind=rp) * 0.5_rp
251 end do
252 !$omp end do
253 !$omp do
254 do ke=lmesh%NeS, lmesh%NeE
255 dens(:) = dens_hyd(:,ke) + ddens_(:,ke)
256 rdens(:) = 1.0_rp / dens(:)
257 rhot(:) = dens(:) * pt(:,ke)
258
259 ! gradient of density
260 call sparsemat_matmul( dz, dens, fz )
261 call sparsemat_matmul( lift, del_flux_rho(:,ke), liftdelflx )
262 ddensdz(:) = lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:)
263
264 ! gradient of u
265 q(:) = momx_(:,ke) * rdens(:)
266 call sparsemat_matmul( dz, momx_(:,ke), fz )
267 call sparsemat_matmul( lift, del_flux_mom(:,ke,1), liftdelflx )
268 dveldz(:,1) = ( lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:) - q(:) * ddensdz(:) ) * rdens(:)
269
270 ! gradient of v
271 q(:) = momy_(:,ke) * rdens(:)
272 call sparsemat_matmul( dz, momy_(:,ke), fz )
273 call sparsemat_matmul( lift, del_flux_mom(:,ke,2), liftdelflx )
274 dveldz(:,2) = ( lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:) - q(:) * ddensdz(:) ) * rdens(:)
275
276 ! gradient of pt
277 q(:) = rhot(:) * rdens(:)
278 call sparsemat_matmul( dz, rhot(:) , fz )
279 call sparsemat_matmul( lift, del_flux_rhot(:,ke), liftdelflx )
280 dptdz(:) = ( lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:) - q(:) * ddensdz(:) ) * rdens(:)
281
282 ! gradient of Rtot
283 call sparsemat_matmul( dz, rtot(:,ke), fz )
284 call sparsemat_matmul( lift, del_flux_rtot(:,ke), liftdelflx )
285 drtotdz(:) = lmesh%Escale(:,ke,3,3) * fz(:) + liftdelflx(:)
286
287 ! Calculate flux Richardson number: Rf
288 do p=1, elem%Np
289 n2 = grav * ( dptdz(p) / pt(p,ke) + drtotdz(p) / rtot(p,ke) )
290
291 s2(p) = dveldz(p,1)**2 + dveldz(p,2)**2
292 ri = n2 / max(s2(p), eps)
293
294 discriminant = ri * ri &
295 + 2.0_rp * af12 * ( rf1 - 2.0_rp * rf2 ) * ri &
296 + ( af12 * rf1 )**2
297 discriminant = max( discriminant, 0.0_rp )
298
299 rf(p) = 0.5_rp / af12 * ( ri + af12 * rf1 - sqrt(discriminant) )
300 rf(p) = min( rf(p), rfc - eps_rf )
301 end do
302
303 ! Calculate stability function: S_M and S_H
304 do p=1, elem%Np
305 denom_h = max( 1.0_rp - rf(p), eps_rf )
306 s_h(p) = 3.0_rp * a2_loc * ( g1 + g2 ) * ( rfc - rf(p) ) / denom_h
307
308 denom_m = rf2 - rf(p)
309 if ( abs(denom_m) < eps_rf ) then
310 denom_m = sign(eps_rf, denom_m)
311 end if
312 s_m(p) = s_h(p) * af12 * ( rf1 - rf(p) ) / denom_m
313
314 s_m(p) = max( s_m(p), 0.0_rp )
315 s_h(p) = max( s_h(p), 0.0_rp )
316 end do
317
318 ! Calculate mixing length
319
320 ke2d = lmesh%EMap3Dto2D(ke)
321 do pz=1, elem%Nnode_v
322 do ph=1, elem%Nnode_h1D**2
323 p = ph + (pz-1)*elem%Nnode_h1D**2
324 kz = karman * max( lmesh%zlev(p,ke) - zsfc(ph,ke2d), dz1(ph,ke2d) )
325
326 mixlen(p) = kz * l_inf / max( kz + l_inf, l_min )
327 end do
328 end do
329
330 ! Calculate eddy viscosity and diffusivity
331 do p=1, elem%Np
332 ! q^2
333 q(p) = b1 * mixlen(p)**2 &
334 * s_m(p) * max( 1.0_rp - rf(p), 0.0_rp ) * s2(p)
335 tke(p,ke) = 0.5_rp * max( q(p), 0.0_rp )
336
337 q(p) = sqrt( 2.0_rp * tke(p,ke) )
338 kh(p,ke) = mixlen(p) * q(p) * s_h(p)
339 nu(p,ke) = mixlen(p) * q(p) * s_m(p)
340 end do
341 end do
342 !$omp end do
343 !$omp end parallel
344
345 return