Line data Source code
1 : module gw_drag
2 :
3 : !--------------------------------------------------------------------------
4 : ! CAM and WACCM gravity wave parameterizations were merged by Sean Patrick
5 : ! Santos in Summer 2013, and at the same time, gw_drag was split into
6 : ! various modules. This is the CAM interface and driver module. The below
7 : ! notes are for the old CAM and WACCM versions of gw_drag.
8 : !--------------------------------------------------------------------------
9 : ! This file came from wa17 and was modified by Fabrizio: 07-02-2004
10 : ! Standard gw_drag with modification (6) of latitude profile of gw spectrum
11 : !--------------------------------------------------------------------------
12 : ! Purpose:
13 : !
14 : ! Module to compute the forcing due to parameterized gravity waves. Both an
15 : ! orographic and an internal source spectrum are considered.
16 : !
17 : ! Author: Byron Boville
18 : !
19 : !--------------------------------------------------------------------------
20 : use shr_kind_mod, only: r8=>shr_kind_r8, cl=>shr_kind_cl
21 : use shr_log_mod, only: errMsg => shr_log_errMsg
22 : use shr_assert_mod, only: shr_assert
23 :
24 : use ppgrid, only: pcols, pver, begchunk, endchunk
25 : use constituents, only: pcnst
26 : use physics_types, only: physics_state, physics_ptend, physics_ptend_init
27 : use spmd_utils, only: masterproc
28 : use cam_history, only: outfld
29 : use cam_logfile, only: iulog
30 : use cam_abortutils, only: endrun
31 :
32 : use ref_pres, only: do_molec_diff, nbot_molec, press_lim_idx
33 : use physconst, only: cpair
34 :
35 : ! These are the actual switches for different gravity wave sources.
36 : use phys_control, only: use_gw_oro, use_gw_front, use_gw_front_igw, &
37 : use_gw_convect_dp, use_gw_convect_sh, &
38 : use_simple_phys
39 :
40 : use gw_common, only: GWBand
41 : use gw_convect, only: BeresSourceDesc
42 : use gw_front, only: CMSourceDesc
43 :
44 : ! Typical module header
45 : implicit none
46 : private
47 : save
48 :
49 : !
50 : ! PUBLIC: interfaces
51 : !
52 : public :: gw_drag_readnl ! Read namelist
53 : public :: gw_init ! Initialization
54 : public :: gw_tend ! interface to actual parameterization
55 :
56 : !
57 : ! PRIVATE: Rest of the data and interfaces are private to this module
58 : !
59 : real(r8), parameter :: unset_r8 = huge(1._r8)
60 :
61 : ! A mid-scale "band" with only stationary waves (l = 0).
62 : type(GWBand) :: band_oro
63 : ! Medium scale waves.
64 : type(GWBand) :: band_mid
65 : ! Long scale waves for IGWs.
66 : type(GWBand) :: band_long
67 :
68 : ! Top level for gravity waves.
69 : integer, parameter :: ktop = 1
70 : ! Bottom level for frontal waves.
71 : integer :: kbot_front
72 :
73 : ! Factor for SH orographic waves.
74 : real(r8) :: gw_oro_south_fac = 1._r8
75 :
76 : ! Frontogenesis function critical threshold.
77 : real(r8) :: frontgfc = unset_r8
78 :
79 : ! Tendency efficiencies.
80 :
81 : ! Ridge scheme.
82 : logical :: use_gw_rdg_beta = .false.
83 : integer :: n_rdg_beta = 1
84 : real(r8) :: effgw_rdg_beta = unset_r8
85 : real(r8) :: effgw_rdg_beta_max = unset_r8
86 : real(r8) :: rdg_beta_cd_llb = unset_r8 ! Low-level obstacle drag coefficient Ridge scheme.
87 : logical :: trpd_leewv_rdg_beta = .false.
88 :
89 : logical :: use_gw_rdg_gamma = .false.
90 : integer :: n_rdg_gamma = -1
91 : real(r8) :: effgw_rdg_gamma = unset_r8
92 : real(r8) :: effgw_rdg_gamma_max = unset_r8
93 : real(r8) :: rdg_gamma_cd_llb = unset_r8
94 : logical :: trpd_leewv_rdg_gamma = .false.
95 : character(len=cl) :: bnd_rdggm = 'bnd_rdggm' ! full pathname for meso-Gamma ridge dataset
96 :
97 : ! Orography.
98 : real(r8) :: effgw_oro = unset_r8
99 : ! C&M scheme.
100 : real(r8) :: effgw_cm = unset_r8
101 : ! C&M scheme (inertial waves).
102 : real(r8) :: effgw_cm_igw = unset_r8
103 : ! Beres (deep convection).
104 : real(r8) :: effgw_beres_dp = unset_r8
105 : ! Beres (shallow convection).
106 : real(r8) :: effgw_beres_sh = unset_r8
107 :
108 : ! Horzontal wavelengths [m].
109 : real(r8), parameter :: wavelength_mid = 1.e5_r8
110 : real(r8), parameter :: wavelength_long = 3.e5_r8
111 :
112 : ! Background stress source strengths.
113 : real(r8) :: taubgnd = unset_r8
114 : real(r8) :: taubgnd_igw = unset_r8
115 :
116 : ! Whether or not to use a polar taper for frontally generated waves.
117 : logical :: gw_polar_taper = .false.
118 :
119 : ! Whether or not to enforce an upper boundary condition of tau = 0.
120 : ! (Like many variables, this is only here to hold the value between
121 : ! the readnl phase and the init phase of the CAM physics; only gw_common
122 : ! should actually use it.)
123 : logical :: tau_0_ubc = .false.
124 :
125 : ! Whether or not to limit tau *before* applying any efficiency factors.
126 : logical :: gw_limit_tau_without_eff = .false.
127 :
128 : ! Whether or not to apply tendency max
129 : logical :: gw_apply_tndmax = .true.
130 :
131 : ! Files to read Beres source spectra from.
132 : character(len=256) :: gw_drag_file = ""
133 : character(len=256) :: gw_drag_file_sh = ""
134 :
135 : ! Beres settings and table.
136 : type(BeresSourceDesc) :: beres_dp_desc
137 : type(BeresSourceDesc) :: beres_sh_desc
138 :
139 : ! Frontogenesis wave settings.
140 : type(CMSourceDesc) :: cm_desc
141 : type(CMSourceDesc) :: cm_igw_desc
142 :
143 : ! Indices into pbuf
144 : integer :: kvt_idx = -1
145 : integer :: ttend_dp_idx = -1
146 : integer :: ttend_sh_idx = -1
147 : integer :: frontgf_idx = -1
148 : integer :: frontga_idx = -1
149 : integer :: sgh_idx = -1
150 :
151 : ! anisotropic ridge fields
152 : integer, parameter :: prdg = 16
153 :
154 : real(r8), allocatable, dimension(:,:), target :: &
155 : rdg_gbxar
156 :
157 : ! Meso Beta
158 : real(r8), allocatable, dimension(:,:,:), target :: &
159 : rdg_hwdth, &
160 : rdg_clngt, &
161 : rdg_mxdis, &
162 : rdg_anixy, &
163 : rdg_angll
164 :
165 : ! Meso Gamma
166 : real(r8), allocatable, dimension(:,:,:), target :: &
167 : rdg_hwdthg, &
168 : rdg_clngtg, &
169 : rdg_mxdisg, &
170 : rdg_anixyg, &
171 : rdg_angllg
172 :
173 : ! Water constituent indices for budget
174 : integer :: ixcldliq = -1
175 : integer :: ixcldice = -1
176 :
177 : ! Prefixes for history field names
178 : character(len=1), parameter :: cm_pf = " "
179 : character(len=1), parameter :: cm_igw_pf = "I"
180 : character(len=1), parameter :: beres_dp_pf = "B"
181 : character(len=1), parameter :: beres_sh_pf = "S"
182 :
183 : ! namelist
184 : logical :: history_amwg ! output the variables used by the AMWG diag package
185 : logical :: gw_lndscl_sgh = .true. ! scale SGH by land frac
186 : real(r8) :: gw_prndl = 0.25_r8
187 : real(r8) :: gw_qbo_hdepth_scaling = 1._r8 ! heating depth scaling factor
188 :
189 : ! Width of gaussian used to create frontogenesis tau profile [m/s].
190 : real(r8) :: front_gaussian_width = -huge(1._r8)
191 :
192 : logical :: gw_top_taper=.false.
193 : real(r8), pointer :: vramp(:)=>null()
194 :
195 : !==========================================================================
196 : contains
197 : !==========================================================================
198 :
199 1536 : subroutine gw_drag_readnl(nlfile)
200 :
201 : use namelist_utils, only: find_group_name
202 : use units, only: getunit, freeunit
203 : use spmd_utils, only: mpicom, mstrid=>masterprocid, mpi_real8, &
204 : mpi_character, mpi_logical, mpi_integer
205 : use gw_rdg, only: gw_rdg_readnl
206 :
207 : ! File containing namelist input.
208 : character(len=*), intent(in) :: nlfile
209 :
210 : ! Local variables
211 : integer :: unitn, ierr
212 : character(len=*), parameter :: sub = 'gw_drag_readnl'
213 :
214 : ! Maximum wave number and width of spectrum bins.
215 : integer :: pgwv = -1
216 : real(r8) :: gw_dc = unset_r8
217 : integer :: pgwv_long = -1
218 : real(r8) :: gw_dc_long = unset_r8
219 :
220 : ! fcrit2 for the mid-scale waves has been made a namelist variable to
221 : ! facilitate backwards compatibility with the CAM3 version of this
222 : ! parameterization. In CAM3, fcrit2=0.5.
223 : real(r8) :: fcrit2 = unset_r8 ! critical froude number squared
224 :
225 : namelist /gw_drag_nl/ pgwv, gw_dc, pgwv_long, gw_dc_long, tau_0_ubc, &
226 : effgw_beres_dp, effgw_beres_sh, effgw_cm, effgw_cm_igw, effgw_oro, &
227 : fcrit2, frontgfc, gw_drag_file, gw_drag_file_sh, taubgnd, &
228 : taubgnd_igw, gw_polar_taper, &
229 : use_gw_rdg_beta, n_rdg_beta, effgw_rdg_beta, effgw_rdg_beta_max, &
230 : rdg_beta_cd_llb, trpd_leewv_rdg_beta, &
231 : use_gw_rdg_gamma, n_rdg_gamma, effgw_rdg_gamma, effgw_rdg_gamma_max, &
232 : rdg_gamma_cd_llb, trpd_leewv_rdg_gamma, bnd_rdggm, &
233 : gw_oro_south_fac, gw_limit_tau_without_eff, &
234 : gw_lndscl_sgh, gw_prndl, gw_apply_tndmax, gw_qbo_hdepth_scaling, &
235 : gw_top_taper, front_gaussian_width
236 : !----------------------------------------------------------------------
237 :
238 1536 : if (use_simple_phys) return
239 :
240 1536 : if (masterproc) then
241 2 : unitn = getunit()
242 2 : open( unitn, file=trim(nlfile), status='old' )
243 2 : call find_group_name(unitn, 'gw_drag_nl', status=ierr)
244 2 : if (ierr == 0) then
245 2 : read(unitn, gw_drag_nl, iostat=ierr)
246 2 : if (ierr /= 0) then
247 0 : call endrun(sub // ':: ERROR reading namelist')
248 : end if
249 : end if
250 2 : close(unitn)
251 2 : call freeunit(unitn)
252 : end if
253 :
254 1536 : call mpi_bcast(pgwv, 1, mpi_integer, mstrid, mpicom, ierr)
255 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: pgwv")
256 1536 : call mpi_bcast(gw_dc, 1, mpi_real8, mstrid, mpicom, ierr)
257 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_dc")
258 1536 : call mpi_bcast(pgwv_long, 1, mpi_integer, mstrid, mpicom, ierr)
259 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: pgwv_long")
260 1536 : call mpi_bcast(gw_dc_long, 1, mpi_real8, mstrid, mpicom, ierr)
261 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_dc_long")
262 1536 : call mpi_bcast(tau_0_ubc, 1, mpi_logical, mstrid, mpicom, ierr)
263 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: tau_0_ubc")
264 1536 : call mpi_bcast(effgw_beres_dp, 1, mpi_real8, mstrid, mpicom, ierr)
265 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_beres_dp")
266 1536 : call mpi_bcast(effgw_beres_sh, 1, mpi_real8, mstrid, mpicom, ierr)
267 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_beres_sh")
268 1536 : call mpi_bcast(effgw_cm, 1, mpi_real8, mstrid, mpicom, ierr)
269 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_cm")
270 1536 : call mpi_bcast(effgw_cm_igw, 1, mpi_real8, mstrid, mpicom, ierr)
271 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_cm_igw")
272 1536 : call mpi_bcast(effgw_oro, 1, mpi_real8, mstrid, mpicom, ierr)
273 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_oro")
274 :
275 1536 : call mpi_bcast(use_gw_rdg_beta, 1, mpi_logical, mstrid, mpicom, ierr)
276 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: use_gw_rdg_beta")
277 1536 : call mpi_bcast(n_rdg_beta, 1, mpi_integer, mstrid, mpicom, ierr)
278 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: n_rdg_beta")
279 1536 : call mpi_bcast(effgw_rdg_beta, 1, mpi_real8, mstrid, mpicom, ierr)
280 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_beta")
281 1536 : call mpi_bcast(effgw_rdg_beta_max, 1, mpi_real8, mstrid, mpicom, ierr)
282 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_beta_max")
283 1536 : call mpi_bcast(rdg_beta_cd_llb, 1, mpi_real8, mstrid, mpicom, ierr)
284 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: rdg_beta_cd_llb")
285 1536 : call mpi_bcast(trpd_leewv_rdg_beta, 1, mpi_logical, mstrid, mpicom, ierr)
286 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: trpd_leewv_rdg_beta")
287 :
288 1536 : call mpi_bcast(use_gw_rdg_gamma, 1, mpi_logical, mstrid, mpicom, ierr)
289 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: use_gw_rdg_gamma")
290 1536 : call mpi_bcast(n_rdg_gamma, 1, mpi_integer, mstrid, mpicom, ierr)
291 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: n_rdg_gamma")
292 1536 : call mpi_bcast(effgw_rdg_gamma, 1, mpi_real8, mstrid, mpicom, ierr)
293 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_gamma")
294 1536 : call mpi_bcast(effgw_rdg_gamma_max, 1, mpi_real8, mstrid, mpicom, ierr)
295 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: effgw_rdg_gamma_max")
296 1536 : call mpi_bcast(rdg_gamma_cd_llb, 1, mpi_real8, mstrid, mpicom, ierr)
297 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: rdg_gamma_cd_llb")
298 1536 : call mpi_bcast(trpd_leewv_rdg_gamma, 1, mpi_logical, mstrid, mpicom, ierr)
299 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: trpd_leewv_rdg_gamma")
300 1536 : call mpi_bcast(bnd_rdggm, len(bnd_rdggm), mpi_character, mstrid, mpicom, ierr)
301 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: bnd_rdggm")
302 :
303 1536 : call mpi_bcast(gw_oro_south_fac, 1, mpi_real8, mstrid, mpicom, ierr)
304 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_oro_south_fac")
305 1536 : call mpi_bcast(fcrit2, 1, mpi_real8, mstrid, mpicom, ierr)
306 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: fcrit2")
307 1536 : call mpi_bcast(frontgfc, 1, mpi_real8, mstrid, mpicom, ierr)
308 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: frontgfc")
309 1536 : call mpi_bcast(taubgnd, 1, mpi_real8, mstrid, mpicom, ierr)
310 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: taubgnd")
311 1536 : call mpi_bcast(taubgnd_igw, 1, mpi_real8, mstrid, mpicom, ierr)
312 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: taubgnd_igw")
313 :
314 1536 : call mpi_bcast(gw_polar_taper, 1, mpi_logical, mstrid, mpicom, ierr)
315 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_polar_taper")
316 1536 : call mpi_bcast(gw_limit_tau_without_eff, 1, mpi_logical, mstrid, mpicom, ierr)
317 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_limit_tau_without_eff")
318 1536 : call mpi_bcast(gw_apply_tndmax, 1, mpi_logical, mstrid, mpicom, ierr)
319 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_apply_tndmax")
320 :
321 1536 : call mpi_bcast(gw_top_taper, 1, mpi_logical, mstrid, mpicom, ierr)
322 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_top_taper")
323 :
324 1536 : call mpi_bcast(gw_lndscl_sgh, 1, mpi_logical, mstrid, mpicom, ierr)
325 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_lndscl_sgh")
326 1536 : call mpi_bcast(gw_prndl, 1, mpi_real8, mstrid, mpicom, ierr)
327 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_prndl")
328 1536 : call mpi_bcast(gw_qbo_hdepth_scaling, 1, mpi_real8, mstrid, mpicom, ierr)
329 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_qbo_hdepth_scaling")
330 :
331 1536 : call mpi_bcast(gw_drag_file, len(gw_drag_file), mpi_character, mstrid, mpicom, ierr)
332 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_drag_file")
333 1536 : call mpi_bcast(gw_drag_file_sh, len(gw_drag_file_sh), mpi_character, mstrid, mpicom, ierr)
334 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: gw_drag_file_sh")
335 :
336 1536 : call mpi_bcast(front_gaussian_width, 1, mpi_real8, mstrid, mpicom, ierr)
337 1536 : if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: front_gaussian_width")
338 :
339 : ! Check if fcrit2 was set.
340 : call shr_assert(fcrit2 /= unset_r8, &
341 : "gw_drag_readnl: fcrit2 must be set via the namelist."// &
342 1536 : errMsg(__FILE__, __LINE__))
343 :
344 : ! Check if pgwv was set.
345 : call shr_assert(pgwv >= 0, &
346 : "gw_drag_readnl: pgwv must be set via the namelist and &
347 : &non-negative."// &
348 1536 : errMsg(__FILE__, __LINE__))
349 :
350 : ! Check if gw_dc was set.
351 : call shr_assert(gw_dc /= unset_r8, &
352 : "gw_drag_readnl: gw_dc must be set via the namelist."// &
353 1536 : errMsg(__FILE__, __LINE__))
354 :
355 1536 : band_oro = GWBand(0, gw_dc, fcrit2, wavelength_mid)
356 1536 : band_mid = GWBand(pgwv, gw_dc, 1.0_r8, wavelength_mid)
357 1536 : band_long = GWBand(pgwv_long, gw_dc_long, 1.0_r8, wavelength_long)
358 :
359 1536 : if (use_gw_rdg_gamma .or. use_gw_rdg_beta) then
360 1536 : call gw_rdg_readnl(nlfile)
361 : end if
362 :
363 : end subroutine gw_drag_readnl
364 :
365 : !==========================================================================
366 :
367 1536 : subroutine gw_init()
368 : !-----------------------------------------------------------------------
369 : ! Time independent initialization for multiple gravity wave
370 : ! parameterization.
371 : !-----------------------------------------------------------------------
372 :
373 : use cam_history, only: addfld, add_default, horiz_only
374 : use cam_history, only: register_vector_field
375 : use interpolate_data, only: lininterp
376 : use phys_control, only: phys_getopts
377 : use physics_buffer, only: pbuf_get_index
378 : use constituents, only: cnst_get_ind
379 :
380 : use cam_initfiles, only: topo_file_get_id
381 :
382 : ! temporary for restart with ridge scheme
383 : use cam_initfiles, only: bnd_topo
384 :
385 : use cam_pio_utils, only: cam_pio_openfile
386 : use cam_grid_support, only: cam_grid_check, cam_grid_id
387 : use cam_grid_support, only: cam_grid_get_dim_names
388 : use pio, only: file_desc_t, pio_nowrite, pio_closefile
389 : use ncdio_atm, only: infld
390 : use ioFileMod, only: getfil
391 :
392 : use ref_pres, only: pref_edge, pref_mid
393 : use physconst, only: gravit, rair, rearth
394 :
395 : use gw_common, only: gw_common_init
396 : use gw_front, only: gaussian_cm_desc
397 :
398 : !---------------------------Local storage-------------------------------
399 :
400 : integer :: i, l, k
401 : character(len=1) :: cn
402 :
403 : ! Index for levels at specific pressures.
404 : integer :: kfront
405 :
406 : ! output tendencies and state variables for CAM4 temperature,
407 : ! water vapor, cloud ice and cloud liquid budgets.
408 : logical :: history_budget
409 : ! output history file number for budget fields
410 : integer :: history_budget_histfile_num
411 : ! output variables of interest in WACCM runs
412 : logical :: history_waccm
413 :
414 : ! Interpolated Newtonian cooling coefficients.
415 : real(r8) :: alpha(pver+1)
416 :
417 : ! Levels of pre-calculated Newtonian cooling (1/day).
418 : ! The following profile is digitized from:
419 : ! Wehrbein and Leovy (JAS, 39, 1532-1544, 1982) figure 5
420 :
421 : integer, parameter :: nalph = 71
422 : real(r8) :: alpha0(nalph) = [ &
423 : 0.1_r8, 0.1_r8, 0.1_r8, 0.1_r8, &
424 : 0.1_r8, 0.1_r8, 0.1_r8, 0.1_r8, &
425 : 0.1_r8, 0.1_r8, 0.10133333_r8, 0.104_r8, &
426 : 0.108_r8, 0.112_r8, 0.116_r8, 0.12066667_r8, &
427 : 0.126_r8, 0.132_r8, 0.138_r8, 0.144_r8, &
428 : 0.15133333_r8, 0.16_r8, 0.17_r8, 0.18_r8, &
429 : 0.19_r8, 0.19933333_r8, 0.208_r8, 0.216_r8, &
430 : 0.224_r8, 0.232_r8, 0.23466667_r8, 0.232_r8, &
431 : 0.224_r8, 0.216_r8, 0.208_r8, 0.20133333_r8, &
432 : 0.196_r8, 0.192_r8, 0.188_r8, 0.184_r8, &
433 : 0.18266667_r8, 0.184_r8, 0.188_r8, 0.192_r8, &
434 : 0.196_r8, 0.19333333_r8, 0.184_r8, 0.168_r8, &
435 : 0.152_r8, 0.136_r8, 0.12133333_r8, 0.108_r8, &
436 : 0.096_r8, 0.084_r8, 0.072_r8, 0.061_r8, &
437 : 0.051_r8, 0.042_r8, 0.033_r8, 0.024_r8, &
438 : 0.017666667_r8, 0.014_r8, 0.013_r8, 0.012_r8, &
439 : 0.011_r8, 0.010333333_r8, 0.01_r8, 0.01_r8, &
440 : 0.01_r8, 0.01_r8, 0.01_r8 &
441 : ]
442 :
443 : ! Pressure levels that were used to calculate alpha0 (hPa).
444 : real(r8) :: palph(nalph) = [ &
445 : 2.06115E-06_r8, 2.74280E-06_r8, 3.64988E-06_r8, 4.85694E-06_r8, &
446 : 6.46319E-06_r8, 8.60065E-06_r8, 1.14450E-05_r8, 1.52300E-05_r8, &
447 : 2.02667E-05_r8, 2.69692E-05_r8, 3.58882E-05_r8, 4.77568E-05_r8, &
448 : 6.35507E-05_r8, 8.45676E-05_r8, 0.000112535_r8, 0.000149752_r8, &
449 : 0.000199277_r8, 0.000265180_r8, 0.000352878_r8, 0.000469579_r8, &
450 : 0.000624875_r8, 0.000831529_r8, 0.00110653_r8, 0.00147247_r8, &
451 : 0.00195943_r8, 0.00260744_r8, 0.00346975_r8, 0.00461724_r8, &
452 : 0.00614421_r8, 0.00817618_r8, 0.0108801_r8, 0.0144783_r8, &
453 : 0.0192665_r8, 0.0256382_r8, 0.0341170_r8, 0.0453999_r8, &
454 : 0.0604142_r8, 0.0803939_r8, 0.106981_r8, 0.142361_r8, &
455 : 0.189442_r8, 0.252093_r8, 0.335463_r8, 0.446404_r8, &
456 : 0.594036_r8, 0.790490_r8, 1.05192_r8, 1.39980_r8, &
457 : 1.86273_r8, 2.47875_r8, 3.29851_r8, 4.38936_r8, &
458 : 5.84098_r8, 7.77266_r8, 10.3432_r8, 13.7638_r8, &
459 : 18.3156_r8, 24.3728_r8, 32.4332_r8, 43.1593_r8, &
460 : 57.4326_r8, 76.4263_r8, 101.701_r8, 135.335_r8, &
461 : 180.092_r8, 239.651_r8, 318.907_r8, 424.373_r8, &
462 : 564.718_r8, 751.477_r8, 1000._r8 &
463 : ]
464 :
465 : ! Read data from file
466 : type(file_desc_t), pointer :: fh_topo
467 : type(file_desc_t) :: fh_rdggm
468 : integer :: grid_id
469 : character(len=8) :: dim1name, dim2name
470 : logical :: found
471 : character(len=256) :: bnd_rdggm_loc ! filepath of topo file on local disk
472 :
473 : ! Allow reporting of error messages.
474 : character(len=128) :: errstring
475 : character(len=*), parameter :: sub = 'gw_init'
476 :
477 : ! temporary workaround for restart w/ ridge scheme
478 : character(len=256) :: bnd_topo_loc ! filepath of topo file on local disk
479 :
480 : integer :: botndx,topndx
481 :
482 : !-----------------------------------------------------------------------
483 :
484 1536 : if (do_molec_diff) then
485 0 : kvt_idx = pbuf_get_index('kvt')
486 : end if
487 :
488 1536 : if (masterproc) then
489 2 : write(iulog,*) ' '
490 2 : write(iulog,*) "GW_DRAG: band_mid%ngwv = ", band_mid%ngwv
491 132 : do l = -band_mid%ngwv, band_mid%ngwv
492 : write (iulog,'(A,I0,A,F7.2)') &
493 132 : "GW_DRAG: band_mid%cref(",l,") = ",band_mid%cref(l)
494 : enddo
495 2 : write(iulog,*) 'GW_DRAG: band_mid%kwv = ', band_mid%kwv
496 2 : write(iulog,*) 'GW_DRAG: band_mid%fcrit2 = ', band_mid%fcrit2
497 2 : write(iulog,*) ' '
498 2 : write(iulog,*) "GW_DRAG: band_long%ngwv = ", band_long%ngwv
499 4 : do l = -band_long%ngwv, band_long%ngwv
500 : write (iulog,'(A,I2,A,F7.2)') &
501 4 : "GW_DRAG: band_long%cref(",l,") = ",band_long%cref(l)
502 : enddo
503 2 : write(iulog,*) 'GW_DRAG: band_long%kwv = ', band_long%kwv
504 2 : write(iulog,*) 'GW_DRAG: band_long%fcrit2 = ', band_long%fcrit2
505 2 : write(iulog,*) ' '
506 : end if
507 :
508 : ! pre-calculated newtonian damping:
509 : ! * convert to 1/s
510 : ! * ensure it is not smaller than 1e-6
511 : ! * convert palph from hpa to pa
512 :
513 110592 : do k=1,nalph
514 109056 : alpha0(k) = alpha0(k) / 86400._r8
515 109056 : alpha0(k) = max(alpha0(k), 1.e-6_r8)
516 110592 : palph(k) = palph(k)*1.e2_r8
517 : end do
518 :
519 : ! interpolate to current vertical grid and obtain alpha
520 :
521 1536 : call lininterp (alpha0 ,palph, nalph , alpha , pref_edge , pver+1)
522 1536 : if (masterproc) then
523 2 : write (iulog,*) 'gw_init: newtonian damping (1/day):'
524 2 : write (iulog,fmt='(a4,a12,a10)') ' k ',' pref_edge ', &
525 4 : ' alpha '
526 190 : do k = 1, pver+1
527 188 : write (iulog,fmt='(i4,1e12.5,1f10.2)') k,pref_edge(k), &
528 378 : alpha(k)*86400._r8
529 : end do
530 : end if
531 :
532 1536 : if (masterproc) then
533 2 : write(iulog,*) 'KTOP =',ktop
534 : end if
535 :
536 : ! Used to decide whether temperature tendencies should be output.
537 : call phys_getopts( history_budget_out = history_budget, &
538 : history_budget_histfile_num_out = history_budget_histfile_num, &
539 : history_waccm_out = history_waccm, &
540 1536 : history_amwg_out = history_amwg )
541 :
542 : ! Initialize subordinate modules.
543 : call gw_common_init(pver,&
544 : tau_0_ubc, ktop, gravit, rair, alpha, gw_prndl, &
545 1536 : gw_qbo_hdepth_scaling, errstring )
546 : call shr_assert(trim(errstring) == "", "gw_common_init: "//errstring// &
547 1536 : errMsg(__FILE__, __LINE__))
548 :
549 1536 : if ( use_gw_oro ) then
550 :
551 0 : if (effgw_oro == unset_r8) then
552 : call endrun("gw_drag_init: Orographic gravity waves enabled, &
553 0 : &but effgw_oro was not set.")
554 : end if
555 : end if
556 :
557 1536 : if (use_gw_oro .or. use_gw_rdg_beta .or. use_gw_rdg_gamma) then
558 :
559 1536 : sgh_idx = pbuf_get_index('SGH')
560 :
561 : ! Declare history variables for orographic term
562 : call addfld ('TAUAORO', (/ 'ilev' /), 'I','N/m2', &
563 3072 : 'Total stress from original OGW scheme')
564 : call addfld ('TTGWORO', (/ 'lev' /), 'A','K/s', &
565 3072 : 'T tendency - orographic gravity wave drag')
566 : call addfld ('TTGWSDFORO', (/ 'lev' /), 'A','K/s', &
567 3072 : 'T tendency - orographic gravity wave, diffusion.')
568 : call addfld ('TTGWSKEORO', (/ 'lev' /), 'A','K/s', &
569 3072 : 'T tendency - orographic gravity wave, breaking KE.')
570 : call addfld ('UTGWORO', (/ 'lev' /), 'A','m/s2', &
571 3072 : 'U tendency - orographic gravity wave drag')
572 : call addfld ('VTGWORO', (/ 'lev' /), 'A','m/s2', &
573 3072 : 'V tendency - orographic gravity wave drag')
574 1536 : call register_vector_field('UTGWORO', 'VTGWORO')
575 : call addfld ('TAUGWX', horiz_only, 'A','N/m2', &
576 1536 : 'Zonal gravity wave surface stress')
577 : call addfld ('TAUGWY', horiz_only, 'A','N/m2', &
578 1536 : 'Meridional gravity wave surface stress')
579 1536 : call register_vector_field('TAUGWX', 'TAUGWY')
580 :
581 1536 : if (history_amwg) then
582 1536 : call add_default('TAUGWX ', 1, ' ')
583 1536 : call add_default('TAUGWY ', 1, ' ')
584 : end if
585 :
586 1536 : if (history_waccm) then
587 0 : call add_default('UTGWORO ', 1, ' ')
588 0 : call add_default('VTGWORO ', 1, ' ')
589 0 : call add_default('TAUGWX ', 1, ' ')
590 0 : call add_default('TAUGWY ', 1, ' ')
591 : end if
592 :
593 : end if
594 :
595 1536 : if (use_gw_rdg_beta .or. use_gw_rdg_gamma) then
596 1536 : grid_id = cam_grid_id('physgrid')
597 1536 : if (.not. cam_grid_check(grid_id)) then
598 0 : call endrun(sub//': ERROR: no "physgrid" grid')
599 : end if
600 1536 : call cam_grid_get_dim_names(grid_id, dim1name, dim2name)
601 : end if
602 :
603 1536 : if (use_gw_rdg_beta) then
604 :
605 1536 : if (effgw_rdg_beta == unset_r8) then
606 : call endrun(sub//": ERROR: Anisotropic OGW enabled, &
607 0 : &but effgw_rdg_beta was not set.")
608 : end if
609 :
610 1536 : fh_topo => topo_file_get_id()
611 1536 : bnd_topo_loc = ' '
612 1536 : if (.not. associated(fh_topo)) then
613 :
614 : ! Try to open topo file here. This workaround will not be needed
615 : ! once the refactored initialization sequence is on trunk.
616 :
617 0 : allocate(fh_topo)
618 : ! Error exit is from getfil if file not found.
619 0 : call getfil(bnd_topo, bnd_topo_loc)
620 0 : call cam_pio_openfile(fh_topo, bnd_topo_loc, PIO_NOWRITE)
621 :
622 : end if
623 :
624 : ! Get beta ridge data
625 : allocate( &
626 0 : rdg_gbxar(pcols,begchunk:endchunk), &
627 0 : rdg_hwdth(pcols,prdg,begchunk:endchunk), &
628 0 : rdg_clngt(pcols,prdg,begchunk:endchunk), &
629 0 : rdg_mxdis(pcols,prdg,begchunk:endchunk), &
630 0 : rdg_anixy(pcols,prdg,begchunk:endchunk), &
631 13824 : rdg_angll(pcols,prdg,begchunk:endchunk) )
632 :
633 : call infld('GBXAR', fh_topo, dim1name, dim2name, 1, pcols, &
634 1536 : begchunk, endchunk, rdg_gbxar, found, gridname='physgrid')
635 1536 : if (.not. found) call endrun(sub//': ERROR: GBXAR not found on topo file')
636 106800 : rdg_gbxar = rdg_gbxar * (rearth/1000._r8)*(rearth/1000._r8) ! transform to km^2
637 :
638 : call infld('HWDTH', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
639 1536 : 1, prdg, begchunk, endchunk, rdg_hwdth, found, gridname='physgrid')
640 1536 : if (.not. found) call endrun(sub//': ERROR: HWDTH not found on topo file')
641 :
642 : call infld('CLNGT', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
643 1536 : 1, prdg, begchunk, endchunk, rdg_clngt, found, gridname='physgrid')
644 1536 : if (.not. found) call endrun(sub//': ERROR: CLNGT not found on topo file')
645 :
646 : call infld('MXDIS', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
647 1536 : 1, prdg, begchunk, endchunk, rdg_mxdis, found, gridname='physgrid')
648 1536 : if (.not. found) call endrun(sub//': ERROR: MXDIS not found on topo file')
649 :
650 : call infld('ANIXY', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
651 1536 : 1, prdg, begchunk, endchunk, rdg_anixy, found, gridname='physgrid')
652 1536 : if (.not. found) call endrun(sub//': ERROR: ANIXY not found on topo file')
653 :
654 : call infld('ANGLL', fh_topo, dim1name, 'nrdg', dim2name, 1, pcols, &
655 1536 : 1, prdg, begchunk, endchunk, rdg_angll, found, gridname='physgrid')
656 1536 : if (.not. found) call endrun(sub//': ERROR: ANGLL not found on topo file')
657 :
658 : ! close topo file only if it was opened here
659 1536 : if (len_trim(bnd_topo_loc) > 0) then
660 0 : call pio_closefile(fh_topo)
661 : end if
662 :
663 : call addfld ('WBR_HT1', horiz_only, 'I','m', &
664 1536 : 'Wave breaking height for DSW')
665 : call addfld ('TLB_HT1', horiz_only, 'I','m', &
666 1536 : 'Form drag layer height')
667 : call addfld ('BWV_HT1', horiz_only, 'I','m', &
668 1536 : 'Bottom of freely-propagating OGW regime')
669 : call addfld ('TAUDSW1', horiz_only, 'I','Nm-2', &
670 1536 : 'DSW enhanced drag')
671 : call addfld ('TAUORO1', horiz_only, 'I','Nm-2', &
672 1536 : 'lower BC on propagating wave stress')
673 : call addfld ('UBMSRC1', horiz_only, 'I','ms-1', &
674 1536 : 'below-peak-level on-ridge wind')
675 : call addfld ('USRC1', horiz_only, 'I','ms-1', &
676 1536 : 'below-peak-level Zonal wind')
677 : call addfld ('VSRC1', horiz_only, 'I','ms-1', &
678 1536 : 'below-peak-level Meridional wind')
679 : call addfld ('NSRC1', horiz_only, 'I','s-1', &
680 1536 : 'below-peak-level stratification')
681 : call addfld ('MXDIS1', horiz_only, 'I','m', &
682 1536 : 'Ridge/obstacle height')
683 : call addfld ('ANGLL1', horiz_only, 'I','degrees', &
684 1536 : 'orientation clockwise w/resp north-south')
685 : call addfld ('ANIXY1', horiz_only, 'I','1', &
686 1536 : 'Ridge quality')
687 : call addfld ('HWDTH1', horiz_only, 'I','km', &
688 1536 : 'Ridge width')
689 : call addfld ('CLNGT1', horiz_only, 'I','km', &
690 1536 : 'Ridge length')
691 : call addfld ('GBXAR1', horiz_only, 'I','km+2', &
692 1536 : 'grid box area')
693 :
694 : call addfld ('Fr1_DIAG', horiz_only, 'I','1', &
695 1536 : 'Critical Froude number for linear waves')
696 : call addfld ('Fr2_DIAG', horiz_only, 'I','1', &
697 1536 : 'Critical Froude number for blocked flow')
698 : call addfld ('Frx_DIAG', horiz_only, 'I','1', &
699 1536 : 'Obstacle Froude Number')
700 :
701 : call addfld('UEGW', (/ 'lev' /) , 'A' ,'1/s' , &
702 3072 : 'Zonal wind profile-entry to GW ' )
703 : call addfld('VEGW', (/ 'lev' /) , 'A' ,'1/s' , &
704 3072 : 'Merdional wind profile-entry to GW ' )
705 1536 : call register_vector_field('UEGW','VEGW')
706 : call addfld('TEGW', (/ 'lev' /) , 'A' ,'K' , &
707 3072 : 'Temperature profile-entry to GW ' )
708 : call addfld('ZEGW', (/ 'ilev' /) , 'A' ,'m' , &
709 3072 : 'interface geopotential heights in GW code ' )
710 : call addfld('ZMGW', (/ 'lev' /) , 'A' ,'m' , &
711 3072 : 'midlayer geopotential heights in GW code ' )
712 :
713 : call addfld('TAUM1_DIAG' , (/ 'ilev' /) , 'I' ,'N/m2' , &
714 3072 : 'Ridge based momentum flux profile')
715 : call addfld('TAU1RDGBETAM' , (/ 'ilev' /) , 'I' ,'N/m2' , &
716 3072 : 'Ridge based momentum flux profile')
717 : call addfld('UBM1BETA', (/ 'lev' /) , 'A' ,'1/s' , &
718 3072 : 'On-ridge wind profile ' )
719 : call addfld('UBT1RDGBETA' , (/ 'lev' /) , 'I' ,'m/s' , &
720 3072 : 'On-ridge wind tendency from ridge 1 ')
721 :
722 10752 : do i = 1, 6
723 9216 : write(cn, '(i1)') i
724 : call addfld('TAU'//cn//'RDGBETAY' , (/ 'ilev' /), 'I', 'N/m2', &
725 18432 : 'Ridge based momentum flux profile')
726 : call addfld('TAU'//cn//'RDGBETAX' , (/ 'ilev' /), 'I', 'N/m2', &
727 18432 : 'Ridge based momentum flux profile')
728 9216 : call register_vector_field('TAU'//cn//'RDGBETAX','TAU'//cn//'RDGBETAY')
729 : call addfld('UT'//cn//'RDGBETA', (/ 'lev' /), 'I', 'm/s', &
730 18432 : 'U wind tendency from ridge '//cn)
731 : call addfld('VT'//cn//'RDGBETA', (/ 'lev' /), 'I', 'm/s', &
732 18432 : 'V wind tendency from ridge '//cn)
733 10752 : call register_vector_field('UT'//cn//'RDGBETA','VT'//cn//'RDGBETA')
734 : end do
735 :
736 : call addfld('TAUARDGBETAY' , (/ 'ilev' /) , 'I' ,'N/m2' , &
737 3072 : 'Ridge based momentum flux profile')
738 : call addfld('TAUARDGBETAX' , (/ 'ilev' /) , 'I' ,'N/m2' , &
739 3072 : 'Ridge based momentum flux profile')
740 1536 : call register_vector_field('TAUARDGBETAX','TAUARDGBETAY')
741 :
742 1536 : if (history_waccm) then
743 0 : call add_default('TAUARDGBETAX', 1, ' ')
744 0 : call add_default('TAUARDGBETAY ', 1, ' ')
745 : end if
746 :
747 : end if
748 :
749 1536 : if (use_gw_rdg_gamma) then
750 :
751 0 : if (effgw_rdg_gamma == unset_r8) then
752 0 : call endrun(sub//": ERROR: Anisotropic OGW enabled, but effgw_rdg_gamma was not set.")
753 : end if
754 :
755 0 : call getfil(bnd_rdggm, bnd_rdggm_loc, iflag=1, lexist=found)
756 0 : if (found) then
757 0 : call cam_pio_openfile(fh_rdggm, bnd_rdggm_loc, PIO_NOWRITE)
758 : else
759 : call endrun(sub//': ERROR: file for gamma ridges not found: bnd_rdggm='// &
760 0 : trim(bnd_rdggm))
761 : end if
762 :
763 0 : if (.not. allocated(rdg_gbxar)) then
764 0 : allocate(rdg_gbxar(pcols,begchunk:endchunk))
765 : call infld('GBXAR', fh_rdggm, dim1name, dim2name, 1, pcols, &
766 0 : begchunk, endchunk, rdg_gbxar, found, gridname='physgrid')
767 0 : if (.not. found) call endrun(sub//': ERROR: GBXAR not found on bnd_rdggm')
768 0 : rdg_gbxar = rdg_gbxar * (rearth/1000._r8)*(rearth/1000._r8) ! transform to km^2
769 : end if
770 :
771 : ! Get meso-gamma ridge data
772 : allocate( &
773 0 : rdg_hwdthg(pcols,prdg,begchunk:endchunk), &
774 0 : rdg_clngtg(pcols,prdg,begchunk:endchunk), &
775 0 : rdg_mxdisg(pcols,prdg,begchunk:endchunk), &
776 0 : rdg_anixyg(pcols,prdg,begchunk:endchunk), &
777 0 : rdg_angllg(pcols,prdg,begchunk:endchunk) )
778 :
779 : call infld('HWDTH', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
780 0 : 1, prdg, begchunk, endchunk, rdg_hwdthg, found, gridname='physgrid')
781 0 : if (.not. found) call endrun(sub//': ERROR: HWDTH not found on bnd_rdggm')
782 :
783 : call infld('CLNGT', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
784 0 : 1, prdg, begchunk, endchunk, rdg_clngtg, found, gridname='physgrid')
785 0 : if (.not. found) call endrun(sub//': ERROR: CLNGT not found on bnd_rdggm')
786 :
787 : call infld('MXDIS', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
788 0 : 1, prdg, begchunk, endchunk, rdg_mxdisg, found, gridname='physgrid')
789 0 : if (.not. found) call endrun(sub//': ERROR: MXDIS not found on bnd_rdggm')
790 :
791 : call infld('ANIXY', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
792 0 : 1, prdg, begchunk, endchunk, rdg_anixyg, found, gridname='physgrid')
793 0 : if (.not. found) call endrun(sub//': ERROR: ANIXY not found on bnd_rdggm')
794 :
795 : call infld('ANGLL', fh_rdggm, dim1name, 'nrdg', dim2name, 1, pcols, &
796 0 : 1, prdg, begchunk, endchunk, rdg_angllg, found, gridname='physgrid')
797 0 : if (.not. found) call endrun(sub//': ERROR: ANGLL not found on bnd_rdggm')
798 :
799 0 : call pio_closefile(fh_rdggm)
800 :
801 : call addfld ('TAU1RDGGAMMAM' , (/ 'ilev' /) , 'I' ,'N/m2' , &
802 0 : 'Ridge based momentum flux profile')
803 : call addfld ('UBM1GAMMA', (/ 'lev' /) , 'A' ,'1/s' , &
804 0 : 'On-ridge wind profile ' )
805 : call addfld ('UBT1RDGGAMMA' , (/ 'lev' /) , 'I' ,'m/s' , &
806 0 : 'On-ridge wind tendency from ridge 1 ')
807 :
808 0 : do i = 1, 6
809 0 : write(cn, '(i1)') i
810 : call addfld('TAU'//cn//'RDGGAMMAY', (/ 'ilev' /), 'I', 'N/m2', &
811 0 : 'Ridge based momentum flux profile')
812 : call addfld('TAU'//cn//'RDGGAMMAX', (/ 'ilev' /), 'I', 'N/m2', &
813 0 : 'Ridge based momentum flux profile')
814 : call addfld('UT'//cn//'RDGGAMMA' , (/ 'lev' /), 'I', 'm/s', &
815 0 : 'U wind tendency from ridge '//cn)
816 : call addfld('VT'//cn//'RDGGAMMA' , (/ 'lev' /), 'I', 'm/s', &
817 0 : 'V wind tendency from ridge '//cn)
818 0 : call register_vector_field('UT'//cn//'RDGGAMMA','VT'//cn//'RDGGAMMA')
819 : end do
820 :
821 : call addfld ('TAUARDGGAMMAY' , (/ 'ilev' /) , 'I' ,'N/m2' , &
822 0 : 'Ridge based momentum flux profile')
823 : call addfld ('TAUARDGGAMMAX' , (/ 'ilev' /) , 'I' ,'N/m2' , &
824 0 : 'Ridge based momentum flux profile')
825 0 : call register_vector_field('TAUARDGGAMMAX','TAUARDGGAMMAY')
826 : call addfld ('TAURDGGMX', horiz_only, 'A','N/m2', &
827 0 : 'Zonal gravity wave surface stress')
828 : call addfld ('TAURDGGMY', horiz_only, 'A','N/m2', &
829 0 : 'Meridional gravity wave surface stress')
830 0 : call register_vector_field('TAURDGGMX','TAURDGGMY')
831 : call addfld ('UTRDGGM' , (/ 'lev' /) , 'I' ,'m/s' , &
832 0 : 'U wind tendency from ridge 6 ')
833 : call addfld ('VTRDGGM' , (/ 'lev' /) , 'I' ,'m/s' , &
834 0 : 'V wind tendency from ridge 6 ')
835 0 : call register_vector_field('UTRDGGM','VTRDGGM')
836 : end if
837 :
838 1536 : if (use_gw_front .or. use_gw_front_igw) then
839 :
840 1536 : frontgf_idx = pbuf_get_index('FRONTGF')
841 1536 : frontga_idx = pbuf_get_index('FRONTGA')
842 :
843 : call shr_assert(unset_r8 /= frontgfc, &
844 : "gw_drag_init: Frontogenesis enabled, but frontgfc was &
845 : & not set!"// &
846 1536 : errMsg(__FILE__, __LINE__))
847 :
848 145920 : do k = 0, pver
849 : ! Check frontogenesis at 600 hPa.
850 145920 : if (pref_edge(k+1) < 60000._r8) kfront = k+1
851 : end do
852 :
853 : ! Source waves from 500 hPa.
854 147456 : kbot_front = maxloc(pref_edge, 1, (pref_edge < 50000._r8)) - 1
855 :
856 1536 : if (masterproc) then
857 2 : write (iulog,*) 'KFRONT =',kfront
858 2 : write (iulog,*) 'KBOT_FRONT =',kbot_front
859 2 : write(iulog,*) ' '
860 : end if
861 :
862 : call addfld ('FRONTGF', (/ 'lev' /), 'A', 'K^2/M^2/S', &
863 3072 : 'Frontogenesis function at gws src level')
864 : call addfld ('FRONTGFA', (/ 'lev' /), 'A', 'K^2/M^2/S', &
865 3072 : 'Frontogenesis function at gws src level')
866 :
867 1536 : if (history_waccm) then
868 0 : call add_default('FRONTGF', 1, ' ')
869 0 : call add_default('FRONTGFA', 1, ' ')
870 : end if
871 :
872 : end if
873 :
874 1536 : if (use_gw_front) then
875 :
876 : call shr_assert(all(unset_r8 /= [ effgw_cm, taubgnd ]), &
877 : "gw_drag_init: Frontogenesis mid-scale waves enabled, but not &
878 : &all required namelist variables were set!"// &
879 4608 : errMsg(__FILE__, __LINE__))
880 :
881 1536 : if (masterproc) then
882 2 : write(iulog,*) 'gw_init: gw spectrum taubgnd, ', &
883 4 : 'effgw_cm = ',taubgnd, effgw_cm
884 2 : write(iulog,*) ' '
885 : end if
886 :
887 : cm_desc = gaussian_cm_desc(band_mid, kbot_front, kfront, frontgfc, &
888 1536 : taubgnd, front_gaussian_width)
889 :
890 : ! Output for gravity waves from frontogenesis.
891 : call gw_spec_addflds(prefix=cm_pf, scheme="C&M", band=band_mid, &
892 1536 : history_defaults=history_waccm)
893 :
894 : end if
895 :
896 1536 : if (use_gw_front_igw) then
897 :
898 : call shr_assert(all(unset_r8 /= [ effgw_cm_igw, taubgnd_igw ]), &
899 : "gw_drag_init: Frontogenesis inertial waves enabled, but not &
900 : &all required namelist variables were set!"// &
901 0 : errMsg(__FILE__, __LINE__))
902 :
903 0 : if (masterproc) then
904 0 : write(iulog,*) 'gw_init: gw spectrum taubgnd_igw, ', &
905 0 : 'effgw_cm_igw = ',taubgnd_igw, effgw_cm_igw
906 0 : write(iulog,*) ' '
907 : end if
908 :
909 : cm_igw_desc = gaussian_cm_desc(band_long, kbot_front, kfront, frontgfc, &
910 0 : taubgnd_igw, front_gaussian_width)
911 :
912 : ! Output for gravity waves from frontogenesis.
913 : call gw_spec_addflds(prefix=cm_igw_pf, scheme="C&M IGW", &
914 0 : band=band_long, history_defaults=history_waccm)
915 :
916 : end if
917 :
918 1536 : if (use_gw_convect_dp) then
919 :
920 1536 : ttend_dp_idx = pbuf_get_index('TTEND_DP')
921 :
922 : ! Set the deep scheme specification components.
923 1536 : beres_dp_desc%storm_shift = .true.
924 :
925 145920 : do k = 0, pver
926 : ! 700 hPa index
927 145920 : if (pref_edge(k+1) < 70000._r8) beres_dp_desc%k = k+1
928 : end do
929 :
930 1536 : if (masterproc) then
931 2 : write (iulog,*) 'Beres deep level =',beres_dp_desc%k
932 : end if
933 :
934 : ! Don't use deep convection heating depths below this limit.
935 : ! This is important for QBO. Bad result if left at 2.5 km.
936 1536 : beres_dp_desc%min_hdepth = 1000._r8
937 :
938 : ! Read Beres file.
939 :
940 : call shr_assert(trim(gw_drag_file) /= "", &
941 : "gw_drag_init: No gw_drag_file provided for Beres deep &
942 : &scheme. Set this via namelist."// &
943 1536 : errMsg(__FILE__, __LINE__))
944 :
945 1536 : call gw_init_beres(gw_drag_file, band_mid, beres_dp_desc)
946 :
947 : ! Output for gravity waves from the Beres scheme (deep).
948 : call gw_spec_addflds(prefix=beres_dp_pf, scheme="Beres (deep)", &
949 1536 : band=band_mid, history_defaults=history_waccm)
950 :
951 : call addfld ('NETDT',(/ 'lev' /), 'A','K/s', &
952 3072 : 'Net heating rate')
953 : call addfld ('MAXQ0',horiz_only , 'A','K/day', &
954 1536 : 'Max column heating rate')
955 : call addfld ('HDEPTH',horiz_only, 'A','km', &
956 1536 : 'Heating Depth')
957 :
958 1536 : if (history_waccm) then
959 0 : call add_default('NETDT ', 1, ' ')
960 0 : call add_default('HDEPTH ', 1, ' ')
961 0 : call add_default('MAXQ0 ', 1, ' ')
962 : end if
963 :
964 : end if
965 :
966 1536 : if (use_gw_convect_sh) then
967 :
968 0 : ttend_sh_idx = pbuf_get_index('TTEND_SH')
969 :
970 : ! Set the shallow scheme specification components.
971 0 : beres_sh_desc%storm_shift = .false.
972 :
973 0 : do k = 0, pver
974 : ! 900 hPa index
975 0 : if (pref_edge(k+1) < 90000._r8) beres_sh_desc%k = k+1
976 : end do
977 :
978 0 : if (masterproc) then
979 0 : write (iulog,*) 'Beres shallow level =',beres_sh_desc%k
980 : end if
981 :
982 : ! Use all heating depths for shallow convection.
983 0 : beres_sh_desc%min_hdepth = 0._r8
984 :
985 : ! Read Beres file.
986 :
987 : call shr_assert(trim(gw_drag_file_sh) /= "", &
988 : "gw_drag_init: No gw_drag_file_sh provided for Beres shallow &
989 : &scheme. Set this via namelist."// &
990 0 : errMsg(__FILE__, __LINE__))
991 :
992 0 : call gw_init_beres(gw_drag_file_sh, band_mid, beres_sh_desc)
993 :
994 : ! Output for gravity waves from the Beres scheme (shallow).
995 : call gw_spec_addflds(prefix=beres_sh_pf, scheme="Beres (shallow)", &
996 0 : band=band_mid, history_defaults=history_waccm)
997 :
998 : call addfld ('SNETDT',(/ 'lev' /), 'A','K/s', &
999 0 : 'Net heating rate')
1000 : call addfld ('SMAXQ0',horiz_only , 'A','K/day', &
1001 0 : 'Max column heating rate')
1002 : call addfld ('SHDEPTH',horiz_only, 'A','km', &
1003 0 : 'Heating Depth')
1004 :
1005 0 : if (history_waccm) then
1006 0 : call add_default('SNETDT ', 1, ' ')
1007 0 : call add_default('SHDEPTH ', 1, ' ')
1008 0 : call add_default('SMAXQ0 ', 1, ' ')
1009 : end if
1010 :
1011 : end if
1012 :
1013 : call addfld ('EKGW' ,(/ 'ilev' /), 'A','M2/S', &
1014 3072 : 'Effective Kzz due to diffusion by gravity waves')
1015 :
1016 1536 : if (history_waccm) then
1017 0 : call add_default('EKGW', 1, ' ')
1018 : end if
1019 :
1020 : call addfld ('UTGW_TOTAL', (/ 'lev' /), 'A','m/s2', &
1021 3072 : 'Total U tendency due to gravity wave drag')
1022 : call addfld ('VTGW_TOTAL', (/ 'lev' /), 'A','m/s2', &
1023 3072 : 'Total V tendency due to gravity wave drag')
1024 1536 : call register_vector_field('UTGW_TOTAL', 'VTGW_TOTAL')
1025 :
1026 : ! Total temperature tendency output.
1027 : call addfld ('TTGW', (/ 'lev' /), 'A', 'K/s', &
1028 3072 : 'T tendency - gravity wave drag')
1029 :
1030 : ! Water budget terms.
1031 : call addfld('QTGW',(/ 'lev' /), 'A','kg/kg/s', &
1032 3072 : 'Q tendency - gravity wave drag')
1033 : call addfld('CLDLIQTGW',(/ 'lev' /), 'A','kg/kg/s', &
1034 3072 : 'CLDLIQ tendency - gravity wave drag')
1035 : call addfld('CLDICETGW',(/ 'lev' /), 'A','kg/kg/s', &
1036 3072 : 'CLDICE tendency - gravity wave drag')
1037 :
1038 1536 : if ( history_budget ) then
1039 0 : call add_default('TTGW', history_budget_histfile_num, ' ')
1040 0 : call add_default('QTGW', history_budget_histfile_num, ' ')
1041 0 : call add_default('CLDLIQTGW', history_budget_histfile_num, ' ')
1042 0 : call add_default('CLDICETGW', history_budget_histfile_num, ' ')
1043 : end if
1044 :
1045 : ! Get indices to actually output the above.
1046 1536 : call cnst_get_ind("CLDLIQ", ixcldliq)
1047 1536 : call cnst_get_ind("CLDICE", ixcldice)
1048 :
1049 1536 : if (gw_top_taper) then
1050 0 : allocate(vramp(pver))
1051 0 : vramp(:) = 1._r8
1052 0 : topndx = 1
1053 0 : botndx = press_lim_idx( 0.6E-02_r8, top=.true. )
1054 0 : if (botndx>1) then
1055 0 : do k=botndx,topndx,-1
1056 0 : vramp(k) = vramp(k+1)/(pref_edge(k+1)/pref_edge(k))
1057 : end do
1058 0 : if (masterproc) then
1059 0 : write(iulog,'(A)') 'GW taper coef (vramp):'
1060 0 : do k=1,pver
1061 0 : write(iulog,"('k: ',I4,' taper coef,press(Pa): ',F12.8,E12.4)") k, vramp(k), pref_mid(k)
1062 : enddo
1063 : endif
1064 : endif
1065 : end if
1066 :
1067 3072 : end subroutine gw_init
1068 :
1069 : !==========================================================================
1070 :
1071 1536 : subroutine gw_init_beres(file_name, band, desc)
1072 :
1073 1536 : use ioFileMod, only: getfil
1074 : use pio, only: file_desc_t, pio_nowrite, pio_inq_varid, pio_get_var, &
1075 : pio_closefile
1076 : use cam_pio_utils, only: cam_pio_openfile
1077 :
1078 : character(len=*), intent(in) :: file_name
1079 : type(GWBand), intent(in) :: band
1080 :
1081 : type(BeresSourceDesc), intent(inout) :: desc
1082 :
1083 : type(file_desc_t) :: gw_file_desc
1084 :
1085 : ! PIO variable ids and error code.
1086 : integer :: mfccid, hdid, stat
1087 :
1088 : ! Number of wavenumbers in the input file.
1089 : integer :: ngwv_file
1090 :
1091 : ! Full path to gw_drag_file.
1092 : character(len=256) :: file_path
1093 :
1094 : character(len=256) :: msg
1095 :
1096 : !----------------------------------------------------------------------
1097 : ! read in look-up table for source spectra
1098 : !-----------------------------------------------------------------------
1099 :
1100 1536 : call getfil(file_name, file_path)
1101 1536 : call cam_pio_openfile(gw_file_desc, file_path, pio_nowrite)
1102 :
1103 : ! Get HD (heating depth) dimension.
1104 :
1105 1536 : desc%maxh = get_pio_dimlen(gw_file_desc, "HD", file_path)
1106 :
1107 : ! Get MW (mean wind) dimension.
1108 :
1109 1536 : desc%maxuh = get_pio_dimlen(gw_file_desc, "MW", file_path)
1110 :
1111 : ! Get PS (phase speed) dimension.
1112 :
1113 1536 : ngwv_file = get_pio_dimlen(gw_file_desc, "PS", file_path)
1114 :
1115 : ! Number in each direction is half of total (and minus phase speed of 0).
1116 1536 : desc%maxuh = (desc%maxuh-1)/2
1117 1536 : ngwv_file = (ngwv_file-1)/2
1118 :
1119 : call shr_assert(ngwv_file >= band%ngwv, &
1120 : "gw_beres_init: PS in lookup table file does not cover the whole &
1121 1536 : &spectrum implied by the model's ngwv.")
1122 :
1123 : ! Allocate hd and get data.
1124 :
1125 4608 : allocate(desc%hd(desc%maxh), stat=stat, errmsg=msg)
1126 :
1127 : call shr_assert(stat == 0, &
1128 : "gw_init_beres: Allocation error (hd): "//msg// &
1129 1536 : errMsg(__FILE__, __LINE__))
1130 :
1131 1536 : stat = pio_inq_varid(gw_file_desc,'HD',hdid)
1132 :
1133 : call handle_pio_error(stat, &
1134 1536 : 'Error finding HD in: '//trim(file_path))
1135 :
1136 : stat = pio_get_var(gw_file_desc, hdid, start=[1], count=[desc%maxh], &
1137 3072 : ival=desc%hd)
1138 :
1139 : call handle_pio_error(stat, &
1140 1536 : 'Error reading HD from: '//trim(file_path))
1141 :
1142 : ! While not currently documented in the file, it uses kilometers. Convert
1143 : ! to meters.
1144 32256 : desc%hd = desc%hd*1000._r8
1145 :
1146 : ! Allocate mfcc. "desc%maxh" and "desc%maxuh" are from the file, but the
1147 : ! model determines wavenumber dimension.
1148 :
1149 : allocate(desc%mfcc(desc%maxh,-desc%maxuh:desc%maxuh,&
1150 7680 : -band%ngwv:band%ngwv), stat=stat, errmsg=msg)
1151 :
1152 : call shr_assert(stat == 0, &
1153 : "gw_init_beres: Allocation error (mfcc): "//msg// &
1154 1536 : errMsg(__FILE__, __LINE__))
1155 :
1156 : ! Get mfcc data.
1157 :
1158 1536 : stat = pio_inq_varid(gw_file_desc,'mfcc',mfccid)
1159 :
1160 : call handle_pio_error(stat, &
1161 1536 : 'Error finding mfcc in: '//trim(file_path))
1162 :
1163 : stat = pio_get_var(gw_file_desc, mfccid, &
1164 0 : start=[1,1,ngwv_file-band%ngwv+1], count=shape(desc%mfcc), &
1165 10752 : ival=desc%mfcc)
1166 :
1167 : call handle_pio_error(stat, &
1168 1536 : 'Error reading mfcc from: '//trim(file_path))
1169 :
1170 1536 : call pio_closefile(gw_file_desc)
1171 :
1172 1536 : if (masterproc) then
1173 :
1174 2 : write(iulog,*) "Read in source spectra from file."
1175 2 : write(iulog,*) "mfcc max, min = ", &
1176 442524 : maxval(desc%mfcc),", ",minval(desc%mfcc)
1177 :
1178 : endif
1179 :
1180 3072 : end subroutine gw_init_beres
1181 :
1182 : !==========================================================================
1183 :
1184 : ! Utility to reduce the repetitiveness of reads during initialization.
1185 4608 : function get_pio_dimlen(file_desc, dim_name, file_path) result(dimlen)
1186 :
1187 1536 : use pio, only: file_desc_t, pio_inq_dimid, pio_inq_dimlen
1188 :
1189 : type(file_desc_t), intent(in) :: file_desc
1190 : character(len=*), intent(in) :: dim_name
1191 :
1192 : ! File path, for use in error messages only.
1193 : character(len=*), intent(in) :: file_path
1194 :
1195 : integer :: dimlen
1196 :
1197 : integer :: dimid, stat
1198 :
1199 4608 : stat = pio_inq_dimid(file_desc, dim_name, dimid)
1200 :
1201 : call handle_pio_error(stat, &
1202 4608 : "Error finding dimension "//dim_name//" in: "//file_path)
1203 :
1204 4608 : stat = pio_inq_dimlen(file_desc, dimid, dimlen)
1205 :
1206 : call handle_pio_error(stat, &
1207 4608 : "Error reading dimension "//dim_name//" from: "//file_path)
1208 :
1209 4608 : end function get_pio_dimlen
1210 :
1211 : !==========================================================================
1212 :
1213 : ! In fact, we'd usually expect PIO errors to abort the run before you can
1214 : ! even check the error code. But just in case, use this little assert.
1215 15360 : subroutine handle_pio_error(stat, message)
1216 : use pio, only: pio_noerr
1217 : integer, intent(in) :: stat
1218 : character(len=*) :: message
1219 :
1220 : call shr_assert(stat == pio_noerr, &
1221 : "PIO error in gw_init_beres: "//trim(message)// &
1222 15360 : errMsg(__FILE__, __LINE__))
1223 :
1224 15360 : end subroutine handle_pio_error
1225 :
1226 : !==========================================================================
1227 :
1228 2470608 : subroutine gw_tend(state, pbuf, dt, ptend, cam_in, flx_heat)
1229 : !-----------------------------------------------------------------------
1230 : ! Interface for multiple gravity wave drag parameterization.
1231 : !-----------------------------------------------------------------------
1232 :
1233 : use physics_types, only: physics_state_copy, set_dry_to_wet
1234 : use constituents, only: cnst_type
1235 : use physics_buffer, only: physics_buffer_desc, pbuf_get_field
1236 : use camsrfexch, only: cam_in_t
1237 : ! Location-dependent cpair
1238 : use air_composition, only: cpairv
1239 : use physconst, only: pi
1240 : use coords_1d, only: Coords1D
1241 : use gw_common, only: gw_prof, gw_drag_prof, calc_taucd
1242 : use gw_common, only: momentum_flux, momentum_fixer, energy_change
1243 : use gw_common, only: energy_fixer, coriolis_speed, adjust_inertial
1244 : use gw_oro, only: gw_oro_src
1245 : use gw_front, only: gw_cm_src
1246 : use gw_convect, only: gw_beres_src
1247 :
1248 : !------------------------------Arguments--------------------------------
1249 : type(physics_state), intent(in) :: state ! physics state structure
1250 : type(physics_buffer_desc), pointer :: pbuf(:) ! Physics buffer
1251 : real(r8), intent(in) :: dt ! time step
1252 : ! Parameterization net tendencies.
1253 : type(physics_ptend), intent(out):: ptend
1254 : type(cam_in_t), intent(in) :: cam_in
1255 : real(r8), intent(out) :: flx_heat(pcols)
1256 :
1257 : !---------------------------Local storage-------------------------------
1258 :
1259 58824 : type(physics_state) :: state1 ! Local copy of state variable
1260 :
1261 : integer :: lchnk ! chunk identifier
1262 : integer :: ncol ! number of atmospheric columns
1263 :
1264 : integer :: i, k ! loop indices
1265 :
1266 58824 : type(Coords1D) :: p ! Pressure coordinates
1267 :
1268 117648 : real(r8) :: ttgw(state%ncol,pver) ! temperature tendency
1269 117648 : real(r8) :: utgw(state%ncol,pver) ! zonal wind tendency
1270 117648 : real(r8) :: vtgw(state%ncol,pver) ! meridional wind tendency
1271 :
1272 117648 : real(r8) :: ni(state%ncol,pver+1) ! interface Brunt-Vaisalla frequency
1273 117648 : real(r8) :: nm(state%ncol,pver) ! midpoint Brunt-Vaisalla frequency
1274 117648 : real(r8) :: rhoi(state%ncol,pver+1) ! interface density
1275 58824 : real(r8), allocatable :: tau(:,:,:) ! wave Reynolds stress
1276 117648 : real(r8) :: tau0x(state%ncol) ! c=0 sfc. stress (zonal)
1277 117648 : real(r8) :: tau0y(state%ncol) ! c=0 sfc. stress (meridional)
1278 117648 : real(r8) :: ubi(state%ncol,pver+1)! projection of wind at interfaces
1279 117648 : real(r8) :: ubm(state%ncol,pver) ! projection of wind at midpoints
1280 117648 : real(r8) :: xv(state%ncol) ! unit vector of source wind (x)
1281 117648 : real(r8) :: yv(state%ncol) ! unit vector of source wind (y)
1282 :
1283 : integer :: m ! dummy integers
1284 117648 : real(r8) :: qtgw(state%ncol,pver,pcnst) ! constituents tendencies
1285 :
1286 : ! Reynolds stress for waves propagating in each cardinal direction.
1287 117648 : real(r8) :: taucd(state%ncol,pver+1,4)
1288 :
1289 : ! gravity wave wind tendency for each wave
1290 58824 : real(r8), allocatable :: gwut(:,:,:)
1291 :
1292 : ! Temperature tendencies from diffusion and kinetic energy.
1293 117648 : real(r8) :: dttdf(state%ncol,pver)
1294 117648 : real(r8) :: dttke(state%ncol,pver)
1295 :
1296 : ! Wave phase speeds for each column
1297 58824 : real(r8), allocatable :: c(:,:)
1298 :
1299 : ! Efficiency for a gravity wave source.
1300 117648 : real(r8) :: effgw(state%ncol)
1301 :
1302 : ! Coriolis characteristic speed.
1303 117648 : real(r8) :: u_coriolis(state%ncol)
1304 :
1305 : ! Adjustment for inertial gravity waves.
1306 58824 : real(r8), allocatable :: ro_adjust(:,:,:)
1307 :
1308 : ! pbuf fields
1309 : ! Molecular diffusivity
1310 58824 : real(r8), pointer :: kvt_in(:,:)
1311 117648 : real(r8) :: kvtt(state%ncol,pver+1)
1312 :
1313 : ! Frontogenesis
1314 58824 : real(r8), pointer :: frontgf(:,:)
1315 58824 : real(r8), pointer :: frontga(:,:)
1316 :
1317 : ! Temperature change due to deep convection.
1318 58824 : real(r8), pointer :: ttend_dp(:,:)
1319 : ! Temperature change due to shallow convection.
1320 58824 : real(r8), pointer :: ttend_sh(:,:)
1321 :
1322 : ! Standard deviation of orography.
1323 58824 : real(r8), pointer :: sgh(:)
1324 :
1325 : ! gridbox area
1326 58824 : real(r8), pointer :: gbxar(:)
1327 :
1328 : ! Beta ridges
1329 : ! width of ridges.
1330 58824 : real(r8), pointer :: hwdth(:,:)
1331 : ! length of ridges.
1332 58824 : real(r8), pointer :: clngt(:,:)
1333 : ! Maximum deviations of ridges.
1334 58824 : real(r8), pointer :: mxdis(:,:)
1335 : ! orientation of ridges.
1336 58824 : real(r8), pointer :: angll(:,:)
1337 : ! anisotropy of ridges.
1338 58824 : real(r8), pointer :: anixy(:,:)
1339 :
1340 : ! Gamma ridges
1341 : ! width of ridges.
1342 58824 : real(r8), pointer :: hwdthg(:,:)
1343 : ! length of ridges.
1344 58824 : real(r8), pointer :: clngtg(:,:)
1345 : ! Maximum deviations of ridges.
1346 58824 : real(r8), pointer :: mxdisg(:,:)
1347 : ! orientation of ridges.
1348 58824 : real(r8), pointer :: angllg(:,:)
1349 : ! anisotropy of ridges.
1350 58824 : real(r8), pointer :: anixyg(:,:)
1351 :
1352 : ! Indices of gravity wave source and lowest level where wind tendencies
1353 : ! are allowed.
1354 117648 : integer :: src_level(state%ncol)
1355 117648 : integer :: tend_level(state%ncol)
1356 :
1357 : ! Convective source heating depth.
1358 : ! heating depth
1359 117648 : real(r8) :: hdepth(state%ncol)
1360 : ! maximum heating rate
1361 117648 : real(r8) :: maxq0(state%ncol)
1362 :
1363 : ! Scale sgh to account for landfrac.
1364 117648 : real(r8) :: sgh_scaled(state%ncol)
1365 :
1366 : ! Parameters for the IGW polar taper.
1367 : real(r8), parameter :: degree2radian = pi/180._r8
1368 : real(r8), parameter :: al0 = 82.5_r8 * degree2radian
1369 : real(r8), parameter :: dlat0 = 5.0_r8 * degree2radian
1370 :
1371 : ! effective gw diffusivity at interfaces needed for output
1372 117648 : real(r8) :: egwdffi(state%ncol,pver+1)
1373 : ! sum from the two types of spectral GW
1374 117648 : real(r8) :: egwdffi_tot(state%ncol,pver+1)
1375 :
1376 : ! Momentum fluxes used by fixer.
1377 117648 : real(r8) :: um_flux(state%ncol), vm_flux(state%ncol)
1378 : ! Energy change used by fixer.
1379 117648 : real(r8) :: de(state%ncol)
1380 :
1381 : ! Which constituents are being affected by diffusion.
1382 : logical :: lq(pcnst)
1383 :
1384 : ! Contiguous copies of state arrays.
1385 117648 : real(r8) :: dse(state%ncol,pver)
1386 117648 : real(r8) :: t(state%ncol,pver)
1387 117648 : real(r8) :: u(state%ncol,pver)
1388 117648 : real(r8) :: v(state%ncol,pver)
1389 117648 : real(r8) :: q(state%ncol,pver,pcnst)
1390 117648 : real(r8) :: piln(state%ncol,pver+1)
1391 117648 : real(r8) :: zm(state%ncol,pver)
1392 117648 : real(r8) :: zi(state%ncol,pver+1)
1393 : !------------------------------------------------------------------------
1394 :
1395 : ! Make local copy of input state.
1396 58824 : call physics_state_copy(state, state1)
1397 :
1398 : ! constituents are all treated as wet mmr
1399 58824 : call set_dry_to_wet(state1)
1400 :
1401 58824 : lchnk = state1%lchnk
1402 58824 : ncol = state1%ncol
1403 :
1404 58824 : p = Coords1D(state1%pint(:ncol,:))
1405 :
1406 91405656 : dse = state1%s(:ncol,:)
1407 91405656 : t = state1%t(:ncol,:)
1408 91405656 : u = state1%u(:ncol,:)
1409 91405656 : v = state1%v(:ncol,:)
1410 3747690720 : q = state1%q(:ncol,:,:)
1411 92387880 : piln = state1%lnpint(:ncol,:)
1412 91405656 : zm = state1%zm(:ncol,:)
1413 92387880 : zi = state1%zi(:ncol,:)
1414 :
1415 2470608 : lq = .true.
1416 : call physics_ptend_init(ptend, state1%psetcols, "Gravity wave drag", &
1417 58824 : ls=.true., lu=.true., lv=.true., lq=lq)
1418 :
1419 : ! Profiles of background state variables
1420 58824 : call gw_prof(ncol, p, cpair, t, rhoi, nm, ni)
1421 :
1422 58824 : if (do_molec_diff) then
1423 : !--------------------------------------------------------
1424 : ! Initialize and calculate local molecular diffusivity
1425 : !--------------------------------------------------------
1426 :
1427 0 : call pbuf_get_field(pbuf, kvt_idx, kvt_in) ! kvt_in(1:pcols,1:pver+1)
1428 :
1429 : ! Set kvtt from pbuf field; kvtt still needs a factor of 1/cpairv.
1430 0 : kvtt = kvt_in(:ncol,:)
1431 :
1432 : ! Use linear extrapolation of cpairv to top interface.
1433 : kvtt(:,1) = kvtt(:,1) / &
1434 0 : (1.5_r8*cpairv(:ncol,1,lchnk) - &
1435 0 : 0.5_r8*cpairv(:ncol,2,lchnk))
1436 :
1437 : ! Interpolate cpairv to other interfaces.
1438 0 : do k = 2, nbot_molec
1439 0 : kvtt(:,k) = kvtt(:,k) / &
1440 0 : (cpairv(:ncol,k+1,lchnk)+cpairv(:ncol,k,lchnk)) * 2._r8
1441 : enddo
1442 :
1443 : else
1444 :
1445 92387880 : kvtt = 0._r8
1446 :
1447 : end if
1448 :
1449 58824 : if (use_gw_front_igw) then
1450 0 : u_coriolis = coriolis_speed(band_long, state1%lat(:ncol))
1451 : end if
1452 :
1453 : ! Totals that accumulate over different sources.
1454 92387880 : egwdffi_tot = 0._r8
1455 58824 : flx_heat = 0._r8
1456 :
1457 58824 : if (use_gw_convect_dp) then
1458 : !------------------------------------------------------------------
1459 : ! Convective gravity waves (Beres scheme, deep).
1460 : !------------------------------------------------------------------
1461 :
1462 : ! Allocate wavenumber fields.
1463 294120 : allocate(tau(ncol,-band_mid%ngwv:band_mid%ngwv,pver+1))
1464 235296 : allocate(gwut(ncol,pver,-band_mid%ngwv:band_mid%ngwv))
1465 235296 : allocate(c(ncol,-band_mid%ngwv:band_mid%ngwv))
1466 :
1467 : ! Set up heating
1468 58824 : call pbuf_get_field(pbuf, ttend_dp_idx, ttend_dp)
1469 :
1470 : ! Efficiency of gravity wave momentum transfer.
1471 : ! This is really only to remove the pole points.
1472 982224 : where (pi/2._r8 - abs(state1%lat(:ncol)) >= 4*epsilon(1._r8))
1473 : effgw = effgw_beres_dp
1474 : elsewhere
1475 : effgw = 0._r8
1476 : end where
1477 :
1478 : ! Determine wave sources for Beres deep scheme
1479 : call gw_beres_src(ncol, band_mid, beres_dp_desc, &
1480 0 : u, v, ttend_dp(:ncol,:), zm, src_level, tend_level, tau, &
1481 58824 : ubm, ubi, xv, yv, c, hdepth, maxq0)
1482 :
1483 : ! Solve for the drag profile with Beres source spectrum.
1484 : call gw_drag_prof(ncol, band_mid, p, src_level, tend_level, dt, &
1485 : t, vramp, &
1486 : piln, rhoi, nm, ni, ubm, ubi, xv, yv, &
1487 : effgw, c, kvtt, q, dse, tau, utgw, vtgw, &
1488 : ttgw, qtgw, egwdffi, gwut, dttdf, dttke, &
1489 58824 : lapply_effgw_in=gw_apply_tndmax)
1490 :
1491 : ! Project stress into directional components.
1492 58824 : taucd = calc_taucd(ncol, band_mid%ngwv, tend_level, tau, c, xv, yv, ubi)
1493 :
1494 : ! add the diffusion coefficients
1495 5588280 : do k = 1, pver+1
1496 92387880 : egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
1497 : end do
1498 :
1499 : ! Store constituents tendencies
1500 2470608 : do m=1, pcnst
1501 226766520 : do k = 1, pver
1502 3747631896 : ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
1503 : end do
1504 : end do
1505 :
1506 : ! Find momentum flux, and use it to fix the wind tendencies below
1507 : ! the gravity wave region.
1508 58824 : call momentum_flux(tend_level, taucd, um_flux, vm_flux)
1509 58824 : call momentum_fixer(tend_level, p, um_flux, vm_flux, utgw, vtgw)
1510 :
1511 : ! Add the momentum tendencies to the output tendency arrays.
1512 5529456 : do k = 1, pver
1513 91346832 : ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
1514 91405656 : ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
1515 : end do
1516 :
1517 : ! Find energy change in the current state, and use fixer to apply
1518 : ! the difference in lower levels.
1519 0 : call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
1520 91405656 : ptend%v(:ncol,:), ptend%s(:ncol,:)+ttgw, de)
1521 982224 : call energy_fixer(tend_level, p, de-flx_heat(:ncol), ttgw)
1522 :
1523 5529456 : do k = 1, pver
1524 91405656 : ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
1525 : end do
1526 :
1527 : ! Change ttgw to a temperature tendency before outputing it.
1528 91405656 : ttgw = ttgw / cpair
1529 : call gw_spec_outflds(beres_dp_pf, lchnk, ncol, band_mid, c, u, v, &
1530 0 : xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
1531 58824 : taucd)
1532 :
1533 : ! Diagnostic outputs (convert hdepth to km).
1534 58824 : call outfld('NETDT', ttend_dp, pcols, lchnk)
1535 982224 : call outfld('HDEPTH', hdepth/1000._r8, ncol, lchnk)
1536 58824 : call outfld('MAXQ0', maxq0, ncol, lchnk)
1537 :
1538 58824 : deallocate(tau, gwut, c)
1539 :
1540 : end if
1541 :
1542 58824 : if (use_gw_convect_sh) then
1543 : !------------------------------------------------------------------
1544 : ! Convective gravity waves (Beres scheme, shallow).
1545 : !------------------------------------------------------------------
1546 :
1547 : ! Allocate wavenumber fields.
1548 0 : allocate(tau(ncol,-band_mid%ngwv:band_mid%ngwv,pver+1))
1549 0 : allocate(gwut(ncol,pver,-band_mid%ngwv:band_mid%ngwv))
1550 0 : allocate(c(ncol,-band_mid%ngwv:band_mid%ngwv))
1551 :
1552 : ! Set up heating
1553 0 : call pbuf_get_field(pbuf, ttend_sh_idx, ttend_sh)
1554 :
1555 : ! Efficiency of gravity wave momentum transfer.
1556 : ! This is really only to remove the pole points.
1557 0 : where (pi/2._r8 - abs(state1%lat(:ncol)) >= 4*epsilon(1._r8))
1558 : effgw = effgw_beres_sh
1559 : elsewhere
1560 : effgw = 0._r8
1561 : end where
1562 :
1563 : ! Determine wave sources for Beres shallow scheme
1564 : call gw_beres_src(ncol, band_mid, beres_sh_desc, &
1565 0 : u, v, ttend_sh(:ncol,:), zm, src_level, tend_level, tau, &
1566 0 : ubm, ubi, xv, yv, c, hdepth, maxq0)
1567 :
1568 : ! Solve for the drag profile with Beres source spectrum.
1569 : call gw_drag_prof(ncol, band_mid, p, src_level, tend_level, dt, &
1570 : t, vramp, &
1571 : piln, rhoi, nm, ni, ubm, ubi, xv, yv, &
1572 : effgw, c, kvtt, q, dse, tau, utgw, vtgw, &
1573 : ttgw, qtgw, egwdffi, gwut, dttdf, dttke, &
1574 0 : lapply_effgw_in=gw_apply_tndmax)
1575 :
1576 : ! Project stress into directional components.
1577 0 : taucd = calc_taucd(ncol, band_mid%ngwv, tend_level, tau, c, xv, yv, ubi)
1578 :
1579 : ! add the diffusion coefficients
1580 0 : do k = 1, pver+1
1581 0 : egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
1582 : end do
1583 :
1584 : ! Store constituents tendencies
1585 0 : do m=1, pcnst
1586 0 : do k = 1, pver
1587 0 : ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
1588 : end do
1589 : end do
1590 :
1591 : ! Add the momentum tendencies to the output tendency arrays.
1592 : ! Don't calculate fixers, since we are too close to the ground to
1593 : ! spread momentum/energy differences across low layers.
1594 0 : do k = 1, pver
1595 0 : ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
1596 0 : ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
1597 0 : ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
1598 : end do
1599 :
1600 : ! Calculate energy change for output to CAM's energy checker.
1601 : ! This is sort of cheating; we don't have a good a priori idea of the
1602 : ! energy coming from surface stress, so we just integrate what we and
1603 : ! actually have so far and overwrite flx_heat with that.
1604 0 : call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
1605 0 : ptend%v(:ncol,:), ptend%s(:ncol,:), de)
1606 0 : flx_heat(:ncol) = de
1607 :
1608 : ! Change ttgw to a temperature tendency before outputing it.
1609 0 : ttgw = ttgw / cpair
1610 : call gw_spec_outflds(beres_sh_pf, lchnk, ncol, band_mid, c, u, v, &
1611 0 : xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
1612 0 : taucd)
1613 :
1614 : ! Diagnostic outputs (convert SHDEPTH to km).
1615 0 : call outfld ('SNETDT', ttend_sh, pcols, lchnk)
1616 0 : call outfld ('SHDEPTH', hdepth/1000._r8, ncol, lchnk)
1617 0 : call outfld ('SMAXQ0', maxq0, ncol, lchnk)
1618 :
1619 0 : deallocate(tau, gwut, c)
1620 :
1621 : end if
1622 :
1623 58824 : if (use_gw_front .or. use_gw_front_igw) then
1624 : ! Get frontogenesis physics buffer fields set by dynamics.
1625 58824 : call pbuf_get_field(pbuf, frontgf_idx, frontgf)
1626 58824 : call pbuf_get_field(pbuf, frontga_idx, frontga)
1627 :
1628 : ! Output for diagnostics.
1629 58824 : call outfld ('FRONTGF', frontgf, pcols, lchnk)
1630 58824 : call outfld ('FRONTGFA', frontga, pcols, lchnk)
1631 : end if
1632 :
1633 58824 : if (use_gw_front) then
1634 : !------------------------------------------------------------------
1635 : ! Frontally generated gravity waves
1636 : !------------------------------------------------------------------
1637 :
1638 : ! Allocate wavenumber fields.
1639 294120 : allocate(tau(ncol,-band_mid%ngwv:band_mid%ngwv,pver+1))
1640 235296 : allocate(gwut(ncol,pver,-band_mid%ngwv:band_mid%ngwv))
1641 235296 : allocate(c(ncol,-band_mid%ngwv:band_mid%ngwv))
1642 :
1643 : ! Efficiency of gravity wave momentum transfer.
1644 982224 : effgw = effgw_cm
1645 : ! Frontogenesis is too high at the poles (at least for the FV
1646 : ! dycore), so introduce a polar taper.
1647 58824 : if (gw_polar_taper) effgw = effgw * cos(state1%lat(:ncol))
1648 :
1649 : ! Determine the wave source for C&M background spectrum
1650 0 : call gw_cm_src(ncol, band_mid, cm_desc, u, v, frontgf(:ncol,:), &
1651 58824 : src_level, tend_level, tau, ubm, ubi, xv, yv, c)
1652 :
1653 : ! Solve for the drag profile with C&M source spectrum.
1654 : call gw_drag_prof(ncol, band_mid, p, src_level, tend_level, dt, &
1655 : t, vramp, &
1656 : piln, rhoi, nm, ni, ubm, ubi, xv, yv, &
1657 : effgw, c, kvtt, q, dse, tau, utgw, vtgw, &
1658 : ttgw, qtgw, egwdffi, gwut, dttdf, dttke, &
1659 58824 : lapply_effgw_in=gw_apply_tndmax)
1660 :
1661 : ! Project stress into directional components.
1662 58824 : taucd = calc_taucd(ncol, band_mid%ngwv, tend_level, tau, c, xv, yv, ubi)
1663 :
1664 : ! add the diffusion coefficients
1665 5588280 : do k = 1, pver+1
1666 92387880 : egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
1667 : end do
1668 :
1669 : !Add the constituent tendencies
1670 2470608 : do m=1, pcnst
1671 226766520 : do k = 1, pver
1672 3747631896 : ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
1673 : end do
1674 : end do
1675 :
1676 : ! Find momentum flux, and use it to fix the wind tendencies below
1677 : ! the gravity wave region.
1678 58824 : call momentum_flux(tend_level, taucd, um_flux, vm_flux)
1679 58824 : call momentum_fixer(tend_level, p, um_flux, vm_flux, utgw, vtgw)
1680 :
1681 : ! add the momentum tendencies to the output tendency arrays
1682 5529456 : do k = 1, pver
1683 91346832 : ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
1684 91405656 : ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
1685 : end do
1686 :
1687 : ! Find energy change in the current state, and use fixer to apply
1688 : ! the difference in lower levels.
1689 0 : call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
1690 91405656 : ptend%v(:ncol,:), ptend%s(:ncol,:)+ttgw, de)
1691 982224 : call energy_fixer(tend_level, p, de-flx_heat(:ncol), ttgw)
1692 :
1693 5529456 : do k = 1, pver
1694 91405656 : ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
1695 : end do
1696 :
1697 : ! Change ttgw to a temperature tendency before outputing it.
1698 91405656 : ttgw = ttgw / cpair
1699 : call gw_spec_outflds(cm_pf, lchnk, ncol, band_mid, c, u, v, &
1700 0 : xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
1701 58824 : taucd)
1702 :
1703 58824 : deallocate(tau, gwut, c)
1704 :
1705 : end if
1706 :
1707 58824 : if (use_gw_front_igw) then
1708 : !------------------------------------------------------------------
1709 : ! Frontally generated inertial gravity waves
1710 : !------------------------------------------------------------------
1711 :
1712 : ! Allocate wavenumber fields.
1713 0 : allocate(tau(ncol,-band_long%ngwv:band_long%ngwv,pver+1))
1714 0 : allocate(gwut(ncol,pver,-band_long%ngwv:band_long%ngwv))
1715 0 : allocate(c(ncol,-band_long%ngwv:band_long%ngwv))
1716 0 : allocate(ro_adjust(ncol,-band_long%ngwv:band_long%ngwv,pver+1))
1717 :
1718 : ! Efficiency of gravity wave momentum transfer.
1719 0 : effgw = effgw_cm_igw
1720 :
1721 : ! Frontogenesis is too high at the poles (at least for the FV
1722 : ! dycore), so introduce a polar taper.
1723 0 : if (gw_polar_taper) then
1724 0 : where (abs(state1%lat(:ncol)) <= 89._r8*degree2radian)
1725 : effgw = effgw * 0.25_r8 * &
1726 0 : (1._r8+tanh((state1%lat(:ncol)+al0)/dlat0)) * &
1727 : (1._r8-tanh((state1%lat(:ncol)-al0)/dlat0))
1728 : elsewhere
1729 : effgw = 0._r8
1730 : end where
1731 : end if
1732 :
1733 : ! Determine the wave source for C&M background spectrum
1734 0 : call gw_cm_src(ncol, band_long, cm_igw_desc, u, v, frontgf(:ncol,:), &
1735 0 : src_level, tend_level, tau, ubm, ubi, xv, yv, c)
1736 :
1737 : call adjust_inertial(band_long, tend_level, u_coriolis, c, ubi, &
1738 0 : tau, ro_adjust)
1739 :
1740 : ! Solve for the drag profile with C&M source spectrum.
1741 : call gw_drag_prof(ncol, band_long, p, src_level, tend_level, dt, &
1742 : t, vramp, &
1743 : piln, rhoi, nm, ni, ubm, ubi, xv, yv, &
1744 : effgw, c, kvtt, q, dse, tau, utgw, vtgw, &
1745 : ttgw, qtgw, egwdffi, gwut, dttdf, dttke, ro_adjust=ro_adjust, &
1746 0 : lapply_effgw_in=gw_apply_tndmax)
1747 :
1748 : ! Project stress into directional components.
1749 0 : taucd = calc_taucd(ncol, band_long%ngwv, tend_level, tau, c, xv, yv, ubi)
1750 :
1751 : ! add the diffusion coefficients
1752 0 : do k = 1, pver+1
1753 0 : egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
1754 : end do
1755 :
1756 : !Add the constituent tendencies
1757 0 : do m=1, pcnst
1758 0 : do k = 1, pver
1759 0 : ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
1760 : end do
1761 : end do
1762 :
1763 : ! Find momentum flux, and use it to fix the wind tendencies below
1764 : ! the gravity wave region.
1765 0 : call momentum_flux(tend_level, taucd, um_flux, vm_flux)
1766 0 : call momentum_fixer(tend_level, p, um_flux, vm_flux, utgw, vtgw)
1767 :
1768 : ! add the momentum tendencies to the output tendency arrays
1769 0 : do k = 1, pver
1770 0 : ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
1771 0 : ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
1772 : end do
1773 :
1774 : ! Find energy change in the current state, and use fixer to apply
1775 : ! the difference in lower levels.
1776 0 : call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
1777 0 : ptend%v(:ncol,:), ptend%s(:ncol,:)+ttgw, de)
1778 0 : call energy_fixer(tend_level, p, de-flx_heat(:ncol), ttgw)
1779 :
1780 0 : do k = 1, pver
1781 0 : ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
1782 : end do
1783 :
1784 : ! Change ttgw to a temperature tendency before outputing it.
1785 0 : ttgw = ttgw / cpair
1786 : call gw_spec_outflds(cm_igw_pf, lchnk, ncol, band_long, c, u, v, &
1787 0 : xv, yv, gwut, dttdf, dttke, tau(:,:,2:), utgw, vtgw, ttgw, &
1788 0 : taucd)
1789 :
1790 0 : deallocate(tau, gwut, c, ro_adjust)
1791 :
1792 : end if
1793 :
1794 58824 : if (use_gw_oro) then
1795 : !---------------------------------------------------------------------
1796 : ! Orographic stationary gravity waves
1797 : !---------------------------------------------------------------------
1798 :
1799 : ! Allocate wavenumber fields.
1800 0 : allocate(tau(ncol,band_oro%ngwv:band_oro%ngwv,pver+1))
1801 0 : allocate(gwut(ncol,pver,band_oro%ngwv:band_oro%ngwv))
1802 0 : allocate(c(ncol,band_oro%ngwv:band_oro%ngwv))
1803 :
1804 : ! Efficiency of gravity wave momentum transfer.
1805 : ! Take into account that wave sources are only over land.
1806 0 : call pbuf_get_field(pbuf, sgh_idx, sgh)
1807 :
1808 0 : if (gw_lndscl_sgh) then
1809 0 : where (cam_in%landfrac(:ncol) >= epsilon(1._r8))
1810 0 : effgw = effgw_oro * cam_in%landfrac(:ncol)
1811 0 : sgh_scaled = sgh(:ncol) / sqrt(cam_in%landfrac(:ncol))
1812 : elsewhere
1813 : effgw = 0._r8
1814 : sgh_scaled = 0._r8
1815 : end where
1816 :
1817 : ! Determine the orographic wave source
1818 : call gw_oro_src(ncol, band_oro, p, &
1819 : u, v, t, sgh_scaled, zm, nm, &
1820 0 : src_level, tend_level, tau, ubm, ubi, xv, yv, c)
1821 : else
1822 0 : effgw = effgw_oro
1823 :
1824 : ! Determine the orographic wave source
1825 : call gw_oro_src(ncol, band_oro, p, &
1826 0 : u, v, t, sgh(:ncol), zm, nm, &
1827 0 : src_level, tend_level, tau, ubm, ubi, xv, yv, c)
1828 : endif
1829 0 : do i = 1, ncol
1830 0 : if (state1%lat(i) < 0._r8) then
1831 0 : tau(i,:,:) = tau(i,:,:) * gw_oro_south_fac
1832 : end if
1833 : end do
1834 :
1835 : ! Solve for the drag profile with orographic sources.
1836 : call gw_drag_prof(ncol, band_oro, p, src_level, tend_level, dt, &
1837 : t, vramp, &
1838 : piln, rhoi, nm, ni, ubm, ubi, xv, yv, &
1839 : effgw,c, kvtt, q, dse, tau, utgw, vtgw, &
1840 : ttgw, qtgw, egwdffi, gwut, dttdf, dttke, &
1841 0 : lapply_effgw_in=gw_apply_tndmax)
1842 :
1843 : ! For orographic waves, don't bother with taucd, since there are no
1844 : ! momentum conservation routines or directional diagnostics.
1845 :
1846 : ! add the diffusion coefficients
1847 0 : do k = 1, pver+1
1848 0 : egwdffi_tot(:,k) = egwdffi_tot(:,k) + egwdffi(:,k)
1849 : end do
1850 :
1851 : ! Add the orographic tendencies to the spectrum tendencies.
1852 : ! Don't calculate fixers, since we are too close to the ground to
1853 : ! spread momentum/energy differences across low layers.
1854 0 : do k = 1, pver
1855 0 : ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
1856 0 : ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
1857 0 : ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
1858 : ! Convert to temperature tendency for output.
1859 0 : ttgw(:,k) = ttgw(:,k) / cpairv(:ncol, k, lchnk)
1860 : end do
1861 :
1862 : ! Calculate energy change for output to CAM's energy checker.
1863 : ! This is sort of cheating; we don't have a good a priori idea of the
1864 : ! energy coming from surface stress, so we just integrate what we and
1865 : ! actually have so far and overwrite flx_heat with that.
1866 0 : call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
1867 0 : ptend%v(:ncol,:), ptend%s(:ncol,:), de)
1868 0 : flx_heat(:ncol) = de
1869 :
1870 0 : do m = 1, pcnst
1871 0 : do k = 1, pver
1872 0 : ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
1873 : end do
1874 : end do
1875 :
1876 : ! Write output fields to history file
1877 0 : call outfld('TAUAORO', tau(:,0,:), ncol, lchnk)
1878 0 : call outfld('UTGWORO', utgw, ncol, lchnk)
1879 0 : call outfld('VTGWORO', vtgw, ncol, lchnk)
1880 0 : call outfld('TTGWORO', ttgw, ncol, lchnk)
1881 0 : call outfld('TTGWSDFORO', dttdf / cpair, ncol, lchnk)
1882 0 : call outfld('TTGWSKEORO', dttke / cpair, ncol, lchnk)
1883 0 : tau0x = tau(:,0,pver+1) * xv
1884 0 : tau0y = tau(:,0,pver+1) * yv
1885 0 : call outfld('TAUGWX', tau0x, ncol, lchnk)
1886 0 : call outfld('TAUGWY', tau0y, ncol, lchnk)
1887 :
1888 0 : deallocate(tau, gwut, c)
1889 :
1890 : end if
1891 :
1892 58824 : if (use_gw_rdg_beta) then
1893 : !---------------------------------------------------------------------
1894 : ! Orographic stationary gravity waves
1895 : !---------------------------------------------------------------------
1896 :
1897 : ! Efficiency of gravity wave momentum transfer.
1898 : ! Take into account that wave sources are only over land.
1899 :
1900 58824 : hwdth => rdg_hwdth(:ncol,:,lchnk)
1901 58824 : clngt => rdg_clngt(:ncol,:,lchnk)
1902 58824 : gbxar => rdg_gbxar(:ncol,lchnk)
1903 58824 : mxdis => rdg_mxdis(:ncol,:,lchnk)
1904 58824 : angll => rdg_angll(:ncol,:,lchnk)
1905 58824 : anixy => rdg_anixy(:ncol,:,lchnk)
1906 :
1907 15774408 : where(mxdis < 0._r8)
1908 : mxdis = 0._r8
1909 : end where
1910 :
1911 : ! Save state at top of routine
1912 : ! Useful for unit testing checks
1913 58824 : call outfld('UEGW', u , ncol, lchnk)
1914 58824 : call outfld('VEGW', v , ncol, lchnk)
1915 58824 : call outfld('TEGW', t , ncol, lchnk)
1916 58824 : call outfld('ZEGW', zi , ncol, lchnk)
1917 58824 : call outfld('ZMGW', zm , ncol, lchnk)
1918 :
1919 : call gw_rdg_calc(&
1920 : 'BETA ', ncol, lchnk, n_rdg_beta, dt, &
1921 : u, v, t, p, piln, zm, zi, &
1922 : nm, ni, rhoi, kvtt, q, dse, &
1923 : effgw_rdg_beta, effgw_rdg_beta_max, &
1924 : hwdth, clngt, gbxar, mxdis, angll, anixy, &
1925 : rdg_beta_cd_llb, trpd_leewv_rdg_beta, &
1926 58824 : ptend, flx_heat)
1927 :
1928 : end if
1929 :
1930 58824 : if (use_gw_rdg_gamma) then
1931 : !---------------------------------------------------------------------
1932 : ! Orographic stationary gravity waves
1933 : !---------------------------------------------------------------------
1934 :
1935 : ! Efficiency of gravity wave momentum transfer.
1936 : ! Take into account that wave sources are only over land.
1937 :
1938 0 : hwdthg => rdg_hwdthg(:ncol,:,lchnk)
1939 0 : clngtg => rdg_clngtg(:ncol,:,lchnk)
1940 0 : gbxar => rdg_gbxar(:ncol,lchnk)
1941 0 : mxdisg => rdg_mxdisg(:ncol,:,lchnk)
1942 0 : angllg => rdg_angllg(:ncol,:,lchnk)
1943 0 : anixyg => rdg_anixyg(:ncol,:,lchnk)
1944 :
1945 0 : where(mxdisg < 0._r8)
1946 : mxdisg = 0._r8
1947 : end where
1948 :
1949 : call gw_rdg_calc(&
1950 : 'GAMMA', ncol, lchnk, n_rdg_gamma, dt, &
1951 : u, v, t, p, piln, zm, zi, &
1952 : nm, ni, rhoi, kvtt, q, dse, &
1953 : effgw_rdg_gamma, effgw_rdg_gamma_max, &
1954 : hwdthg, clngtg, gbxar, mxdisg, angllg, anixyg, &
1955 : rdg_gamma_cd_llb, trpd_leewv_rdg_gamma, &
1956 0 : ptend, flx_heat)
1957 :
1958 : endif
1959 :
1960 : ! Convert the tendencies for the dry constituents to dry air basis.
1961 2470608 : do m = 1, pcnst
1962 2470608 : if (cnst_type(m).eq.'dry') then
1963 165883680 : do k = 1, pver
1964 2742169680 : do i = 1, ncol
1965 2740404960 : ptend%q(i,k,m) = ptend%q(i,k,m)*state1%pdel(i,k)/state1%pdeldry(i,k)
1966 : end do
1967 : end do
1968 : end if
1969 : end do
1970 :
1971 : ! Write totals to history file.
1972 58824 : call outfld('EKGW', egwdffi_tot , ncol, lchnk)
1973 93059568 : call outfld('TTGW', ptend%s/cpairv(:,:,lchnk), pcols, lchnk)
1974 :
1975 58824 : call outfld('UTGW_TOTAL', ptend%u, pcols, lchnk)
1976 58824 : call outfld('VTGW_TOTAL', ptend%v, pcols, lchnk)
1977 :
1978 58824 : call outfld('QTGW', ptend%q(:,:,1), pcols, lchnk)
1979 58824 : call outfld('CLDLIQTGW', ptend%q(:,:,ixcldliq), pcols, lchnk)
1980 58824 : call outfld('CLDICETGW', ptend%q(:,:,ixcldice), pcols, lchnk)
1981 :
1982 : ! Destroy objects.
1983 58824 : call p%finalize()
1984 :
1985 117648 : end subroutine gw_tend
1986 :
1987 : !==========================================================================
1988 :
1989 58824 : subroutine gw_rdg_calc( &
1990 0 : type, ncol, lchnk, n_rdg, dt, &
1991 58824 : u, v, t, p, piln, zm, zi, &
1992 117648 : nm, ni, rhoi, kvtt, q, dse, &
1993 : effgw_rdg, effgw_rdg_max, &
1994 58824 : hwdth, clngt, gbxar, &
1995 58824 : mxdis, angll, anixy, &
1996 : rdg_cd_llb, trpd_leewv, &
1997 : ptend, flx_heat)
1998 :
1999 58824 : use coords_1d, only: Coords1D
2000 : use gw_rdg, only: gw_rdg_src, gw_rdg_belowpeak, gw_rdg_break_trap, gw_rdg_do_vdiff
2001 : use gw_common, only: gw_drag_prof, energy_change
2002 :
2003 : character(len=5), intent(in) :: type ! BETA or GAMMA
2004 : integer, intent(in) :: ncol ! number of atmospheric columns
2005 : integer, intent(in) :: lchnk ! chunk identifier
2006 : integer, intent(in) :: n_rdg
2007 : real(r8), intent(in) :: dt ! Time step.
2008 :
2009 : real(r8), intent(in) :: u(ncol,pver) ! Midpoint zonal winds. ( m s-1)
2010 : real(r8), intent(in) :: v(ncol,pver) ! Midpoint meridional winds. ( m s-1)
2011 : real(r8), intent(in) :: t(ncol,pver) ! Midpoint temperatures. (K)
2012 : type(Coords1D), intent(in) :: p ! Pressure coordinates.
2013 : real(r8), intent(in) :: piln(ncol,pver+1) ! Log of interface pressures.
2014 : real(r8), intent(in) :: zm(ncol,pver) ! Midpoint altitudes above ground (m).
2015 : real(r8), intent(in) :: zi(ncol,pver+1) ! Interface altitudes above ground (m).
2016 : real(r8), intent(in) :: nm(ncol,pver) ! Midpoint Brunt-Vaisalla frequencies (s-1).
2017 : real(r8), intent(in) :: ni(ncol,pver+1) ! Interface Brunt-Vaisalla frequencies (s-1).
2018 : real(r8), intent(in) :: rhoi(ncol,pver+1) ! Interface density (kg m-3).
2019 : real(r8), intent(in) :: kvtt(ncol,pver+1) ! Molecular thermal diffusivity.
2020 : real(r8), intent(in) :: q(:,:,:) ! Constituent array.
2021 : real(r8), intent(in) :: dse(ncol,pver) ! Dry static energy.
2022 :
2023 :
2024 : real(r8), intent(in) :: effgw_rdg ! Tendency efficiency.
2025 : real(r8), intent(in) :: effgw_rdg_max
2026 : real(r8), intent(in) :: hwdth(ncol,prdg) ! width of ridges.
2027 : real(r8), intent(in) :: clngt(ncol,prdg) ! length of ridges.
2028 : real(r8), intent(in) :: gbxar(ncol) ! gridbox area
2029 :
2030 : real(r8), intent(in) :: mxdis(ncol,prdg) ! Height estimate for ridge (m).
2031 : real(r8), intent(in) :: angll(ncol,prdg) ! orientation of ridges.
2032 : real(r8), intent(in) :: anixy(ncol,prdg) ! Anisotropy parameter.
2033 :
2034 : real(r8), intent(in) :: rdg_cd_llb ! Drag coefficient for low-level flow
2035 : logical, intent(in) :: trpd_leewv
2036 :
2037 : type(physics_ptend), intent(inout):: ptend ! Parameterization net tendencies.
2038 :
2039 : real(r8), intent(out) :: flx_heat(pcols)
2040 :
2041 : !---------------------------Local storage-------------------------------
2042 :
2043 : integer :: k, m, nn
2044 :
2045 58824 : real(r8), allocatable :: tau(:,:,:) ! wave Reynolds stress
2046 : ! gravity wave wind tendency for each wave
2047 58824 : real(r8), allocatable :: gwut(:,:,:)
2048 : ! Wave phase speeds for each column
2049 58824 : real(r8), allocatable :: c(:,:)
2050 :
2051 : ! Isotropic source flag [anisotropic orography].
2052 117648 : integer :: isoflag(ncol)
2053 :
2054 : ! horiz wavenumber [anisotropic orography].
2055 117648 : real(r8) :: kwvrdg(ncol)
2056 :
2057 : ! Efficiency for a gravity wave source.
2058 117648 : real(r8) :: effgw(ncol)
2059 :
2060 : ! Indices of top gravity wave source level and lowest level where wind
2061 : ! tendencies are allowed.
2062 117648 : integer :: src_level(ncol)
2063 117648 : integer :: tend_level(ncol)
2064 117648 : integer :: bwv_level(ncol)
2065 117648 : integer :: tlb_level(ncol)
2066 :
2067 : ! Projection of wind at midpoints and interfaces.
2068 117648 : real(r8) :: ubm(ncol,pver)
2069 117648 : real(r8) :: ubi(ncol,pver+1)
2070 :
2071 : ! Unit vectors of source wind (zonal and meridional components).
2072 117648 : real(r8) :: xv(ncol)
2073 117648 : real(r8) :: yv(ncol)
2074 :
2075 : ! Averages over source region.
2076 117648 : real(r8) :: ubmsrc(ncol) ! On-ridge wind.
2077 117648 : real(r8) :: usrc(ncol) ! Zonal wind.
2078 117648 : real(r8) :: vsrc(ncol) ! Meridional wind.
2079 117648 : real(r8) :: nsrc(ncol) ! B-V frequency.
2080 117648 : real(r8) :: rsrc(ncol) ! Density.
2081 :
2082 : ! normalized wavenumber
2083 117648 : real(r8) :: m2src(ncol)
2084 :
2085 : ! Top of low-level flow layer.
2086 117648 : real(r8) :: tlb(ncol)
2087 :
2088 : ! Bottom of linear wave region.
2089 117648 : real(r8) :: bwv(ncol)
2090 :
2091 : ! Froude numbers for flow/drag regimes
2092 117648 : real(r8) :: Fr1(ncol)
2093 117648 : real(r8) :: Fr2(ncol)
2094 117648 : real(r8) :: Frx(ncol)
2095 :
2096 : ! Wave Reynolds stresses at source level
2097 117648 : real(r8) :: tauoro(ncol)
2098 117648 : real(r8) :: taudsw(ncol)
2099 :
2100 : ! Surface streamline displacement height for linear waves.
2101 117648 : real(r8) :: hdspwv(ncol)
2102 :
2103 : ! Surface streamline displacement height for downslope wind regime.
2104 117648 : real(r8) :: hdspdw(ncol)
2105 :
2106 : ! Wave breaking level
2107 117648 : real(r8) :: wbr(ncol)
2108 :
2109 117648 : real(r8) :: utgw(ncol,pver) ! zonal wind tendency
2110 117648 : real(r8) :: vtgw(ncol,pver) ! meridional wind tendency
2111 117648 : real(r8) :: ttgw(ncol,pver) ! temperature tendency
2112 117648 : real(r8) :: qtgw(ncol,pver,pcnst) ! constituents tendencies
2113 :
2114 : ! Effective gravity wave diffusivity at interfaces.
2115 117648 : real(r8) :: egwdffi(ncol,pver+1)
2116 :
2117 : ! Temperature tendencies from diffusion and kinetic energy.
2118 117648 : real(r8) :: dttdf(ncol,pver)
2119 117648 : real(r8) :: dttke(ncol,pver)
2120 :
2121 : ! Wave stress in zonal/meridional direction
2122 117648 : real(r8) :: taurx(ncol,pver+1)
2123 117648 : real(r8) :: taurx0(ncol,pver+1)
2124 117648 : real(r8) :: taury(ncol,pver+1)
2125 117648 : real(r8) :: taury0(ncol,pver+1)
2126 : ! Provisional absolute wave stress from gw_drag_prof
2127 117648 : real(r8) :: tau_diag(ncol,pver+1)
2128 :
2129 : ! U,V tendency accumulators
2130 117648 : real(r8) :: utrdg(ncol,pver)
2131 117648 : real(r8) :: vtrdg(ncol,pver)
2132 117648 : real(r8) :: ttrdg(ncol,pver)
2133 :
2134 : ! Energy change used by fixer.
2135 58824 : real(r8) :: de(ncol)
2136 :
2137 : character(len=1) :: cn
2138 : character(len=9) :: fname(4)
2139 : !----------------------------------------------------------------------------
2140 :
2141 : ! Allocate wavenumber fields.
2142 235296 : allocate(tau(ncol,band_oro%ngwv:band_oro%ngwv,pver+1))
2143 176472 : allocate(gwut(ncol,pver,band_oro%ngwv:band_oro%ngwv))
2144 176472 : allocate(c(ncol,band_oro%ngwv:band_oro%ngwv))
2145 :
2146 : ! initialize accumulated momentum fluxes and tendencies
2147 92387880 : taurx = 0._r8
2148 92387880 : taury = 0._r8
2149 91405656 : ttrdg = 0._r8
2150 91405656 : utrdg = 0._r8
2151 91405656 : vtrdg = 0._r8
2152 92387880 : tau_diag = -9999._r8
2153 :
2154 647064 : do nn = 1, n_rdg
2155 9822240 : kwvrdg = 0.001_r8 / ( hwdth(:,nn) + 0.001_r8 ) ! this cant be done every time step !!!
2156 9822240 : isoflag = 0
2157 9822240 : effgw = effgw_rdg * ( hwdth(1:ncol,nn)* clngt(1:ncol,nn) ) / gbxar(1:ncol)
2158 9822240 : effgw = min( effgw_rdg_max , effgw )
2159 :
2160 : call gw_rdg_src(ncol, band_oro, p, &
2161 : u, v, t, mxdis(:,nn), angll(:,nn), anixy(:,nn), kwvrdg, isoflag, zi, nm, &
2162 : src_level, tend_level, bwv_level, tlb_level, tau, ubm, ubi, xv, yv, &
2163 588240 : ubmsrc, usrc, vsrc, nsrc, rsrc, m2src, tlb, bwv, Fr1, Fr2, Frx, c)
2164 :
2165 : call gw_rdg_belowpeak(ncol, band_oro, rdg_cd_llb, &
2166 : t, mxdis(:,nn), anixy(:,nn), kwvrdg, &
2167 : zi, nm, ni, rhoi, &
2168 : src_level, tau, &
2169 : ubmsrc, nsrc, rsrc, m2src, tlb, bwv, Fr1, Fr2, Frx, &
2170 588240 : tauoro, taudsw, hdspwv, hdspdw)
2171 :
2172 :
2173 : call gw_rdg_break_trap(ncol, band_oro, &
2174 : zi, nm, ni, ubm, ubi, rhoi, kwvrdg , bwv, tlb, wbr, &
2175 : src_level, tlb_level, hdspwv, hdspdw, mxdis(:,nn), &
2176 : tauoro, taudsw, tau, &
2177 588240 : ldo_trapped_waves=trpd_leewv)
2178 :
2179 :
2180 : call gw_drag_prof(ncol, band_oro, p, src_level, tend_level, dt, &
2181 : t, vramp, &
2182 : piln, rhoi, nm, ni, ubm, ubi, xv, yv, &
2183 : effgw, c, kvtt, q, dse, tau, utgw, vtgw, &
2184 : ttgw, qtgw, egwdffi, gwut, dttdf, dttke, &
2185 : kwvrdg=kwvrdg, &
2186 588240 : satfac_in = 1._r8, lapply_vdiff=gw_rdg_do_vdiff , tau_diag=tau_diag )
2187 :
2188 : ! Add the tendencies from each ridge to the totals.
2189 55294560 : do k = 1, pver
2190 : ! diagnostics
2191 913468320 : utrdg(:,k) = utrdg(:,k) + utgw(:,k)
2192 913468320 : vtrdg(:,k) = vtrdg(:,k) + vtgw(:,k)
2193 913468320 : ttrdg(:,k) = ttrdg(:,k) + ttgw(:,k)
2194 : ! physics tendencies
2195 913468320 : ptend%u(:ncol,k) = ptend%u(:ncol,k) + utgw(:,k)
2196 913468320 : ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
2197 914056560 : ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k)
2198 : end do
2199 :
2200 24706080 : do m = 1, pcnst
2201 2267665200 : do k = 1, pver
2202 37476318960 : ptend%q(:ncol,k,m) = ptend%q(:ncol,k,m) + qtgw(:,k,m)
2203 : end do
2204 : end do
2205 :
2206 55882800 : do k = 1, pver+1
2207 923290560 : taurx0(:,k) = tau(:,0,k)*xv
2208 923290560 : taury0(:,k) = tau(:,0,k)*yv
2209 923290560 : taurx(:,k) = taurx(:,k) + taurx0(:,k)
2210 923878800 : taury(:,k) = taury(:,k) + taury0(:,k)
2211 : end do
2212 :
2213 588240 : if (nn == 1) then
2214 58824 : call outfld('BWV_HT1', bwv, ncol, lchnk)
2215 58824 : call outfld('TLB_HT1', tlb, ncol, lchnk)
2216 58824 : call outfld('WBR_HT1', wbr, ncol, lchnk)
2217 58824 : call outfld('TAUDSW1', taudsw, ncol, lchnk)
2218 58824 : call outfld('TAUORO1', tauoro, ncol, lchnk)
2219 58824 : call outfld('UBMSRC1', ubmsrc, ncol, lchnk)
2220 58824 : call outfld('USRC1', usrc, ncol, lchnk)
2221 58824 : call outfld('VSRC1', vsrc, ncol, lchnk)
2222 58824 : call outfld('NSRC1' , nsrc, ncol, lchnk)
2223 : ! Froude numbers
2224 58824 : call outfld('Fr1_DIAG' , Fr1, ncol, lchnk)
2225 58824 : call outfld('Fr2_DIAG' , Fr2, ncol, lchnk)
2226 58824 : call outfld('Frx_DIAG' , Frx, ncol, lchnk)
2227 : ! Ridge quantities - don't change. Written for convenience
2228 58824 : call outfld('MXDIS1' , mxdis(:,nn) , ncol, lchnk)
2229 58824 : call outfld('ANGLL1' , angll(:,nn) , ncol, lchnk)
2230 58824 : call outfld('ANIXY1' , anixy(:,nn) , ncol, lchnk)
2231 58824 : call outfld('HWDTH1' , hwdth(:,nn) , ncol, lchnk)
2232 58824 : call outfld('CLNGT1' , clngt(:,nn) , ncol, lchnk)
2233 58824 : call outfld('GBXAR1' , gbxar , ncol, lchnk)
2234 58824 : call outfld('TAUM1_DIAG' , tau_diag , ncol, lchnk)
2235 58824 : call outfld('TAU1RDG'//trim(type)//'M', tau(:,0,:), ncol, lchnk)
2236 58824 : call outfld('UBM1'//trim(type), ubm, ncol, lchnk)
2237 58824 : call outfld('UBT1RDG'//trim(type), gwut, ncol, lchnk)
2238 : end if
2239 :
2240 647064 : if (nn <= 6) then
2241 352944 : write(cn, '(i1)') nn
2242 352944 : call outfld('TAU'//cn//'RDG'//trim(type)//'X', taurx0, ncol, lchnk)
2243 352944 : call outfld('TAU'//cn//'RDG'//trim(type)//'Y', taury0, ncol, lchnk)
2244 352944 : call outfld('UT'//cn//'RDG'//trim(type), utgw, ncol, lchnk)
2245 352944 : call outfld('VT'//cn//'RDG'//trim(type), vtgw, ncol, lchnk)
2246 : end if
2247 :
2248 : end do ! end of loop over multiple ridges
2249 :
2250 : ! Calculate energy change for output to CAM's energy checker.
2251 0 : call energy_change(dt, p, u, v, ptend%u(:ncol,:), &
2252 58824 : ptend%v(:ncol,:), ptend%s(:ncol,:), de)
2253 982224 : flx_heat(:ncol) = de
2254 :
2255 58824 : call outfld('TAUARDG'//trim(type)//'X', taurx, ncol, lchnk)
2256 58824 : call outfld('TAUARDG'//trim(type)//'Y', taury, ncol, lchnk)
2257 :
2258 58824 : if (trim(type) == 'BETA') then
2259 58824 : fname(1) = 'TAUGWX'
2260 58824 : fname(2) = 'TAUGWY'
2261 58824 : fname(3) = 'UTGWORO'
2262 58824 : fname(4) = 'VTGWORO'
2263 0 : else if (trim(type) == 'GAMMA') then
2264 0 : fname(1) = 'TAURDGGMX'
2265 0 : fname(2) = 'TAURDGGMY'
2266 0 : fname(3) = 'UTRDGGM'
2267 0 : fname(4) = 'VTRDGGM'
2268 : else
2269 : call endrun('gw_rdg_calc: FATAL: type must be either BETA or GAMMA'&
2270 0 : //' type= '//type)
2271 : end if
2272 :
2273 58824 : call outfld(fname(1), taurx(:,pver+1), ncol, lchnk)
2274 58824 : call outfld(fname(2), taury(:,pver+1), ncol, lchnk)
2275 58824 : call outfld(fname(3), utrdg, ncol, lchnk)
2276 58824 : call outfld(fname(4), vtrdg, ncol, lchnk)
2277 91405656 : call outfld('TTGWORO', ttrdg / cpair, ncol, lchnk)
2278 :
2279 58824 : deallocate(tau, gwut, c)
2280 :
2281 58824 : end subroutine gw_rdg_calc
2282 :
2283 : !==========================================================================
2284 :
2285 : ! Add all history fields for a gravity wave spectrum source.
2286 3072 : subroutine gw_spec_addflds(prefix, scheme, band, history_defaults)
2287 : use cam_history, only: addfld, add_default, register_vector_field
2288 :
2289 : !------------------------------Arguments--------------------------------
2290 :
2291 : ! One character prefix prepended to output fields.
2292 : character(len=1), intent(in) :: prefix
2293 : ! Gravity wave scheme name prepended to output field descriptions.
2294 : character(len=*), intent(in) :: scheme
2295 : ! Wave speeds.
2296 : type(GWBand), intent(in) :: band
2297 : ! Whether or not to call add_default for fields output by WACCM.
2298 : logical, intent(in) :: history_defaults
2299 :
2300 : !---------------------------Local storage-------------------------------
2301 :
2302 : integer :: l
2303 : ! 7 chars is enough for "-100.00"
2304 : character(len=7) :: fnum
2305 : ! 10 chars is enough for "BTAUXSn32"
2306 : character(len=10) :: dumc1x, dumc1y
2307 : ! Allow 80 chars for description
2308 : character(len=80) dumc2
2309 :
2310 : !-----------------------------------------------------------------------
2311 :
2312 : ! Overall wind tendencies.
2313 : call addfld (trim(prefix)//'UTGWSPEC',(/ 'lev' /), 'A','m/s2', &
2314 6144 : trim(scheme)//' U tendency - gravity wave spectrum')
2315 : call addfld (trim(prefix)//'VTGWSPEC',(/ 'lev' /), 'A','m/s2', &
2316 6144 : trim(scheme)//' V tendency - gravity wave spectrum')
2317 3072 : call register_vector_field(trim(prefix)//'UTGWSPEC',trim(prefix)//'VTGWSPEC')
2318 :
2319 : call addfld (trim(prefix)//'TTGWSPEC',(/ 'lev' /), 'A','K/s', &
2320 6144 : trim(scheme)//' T tendency - gravity wave spectrum')
2321 :
2322 : ! Wind tendencies broken across five spectral bins.
2323 : call addfld (trim(prefix)//'UTEND1', (/ 'lev' /), 'A','m/s2', &
2324 6144 : trim(scheme)//' U tendency c < -40')
2325 : call addfld (trim(prefix)//'UTEND2', (/ 'lev' /), 'A','m/s2', &
2326 6144 : trim(scheme)//' U tendency -40 < c < -15')
2327 : call addfld (trim(prefix)//'UTEND3', (/ 'lev' /), 'A','m/s2', &
2328 6144 : trim(scheme)//' U tendency -15 < c < 15')
2329 : call addfld (trim(prefix)//'UTEND4', (/ 'lev' /), 'A','m/s2', &
2330 6144 : trim(scheme)//' U tendency 15 < c < 40')
2331 : call addfld (trim(prefix)//'UTEND5', (/ 'lev' /), 'A','m/s2', &
2332 6144 : trim(scheme)//' U tendency 40 < c ')
2333 :
2334 : ! Reynold's stress toward each cardinal direction, and net zonal stress.
2335 : call addfld (trim(prefix)//'TAUE' , (/ 'ilev' /), 'A','Pa', &
2336 6144 : trim(scheme)//' Eastward Reynolds stress')
2337 : call addfld (trim(prefix)//'TAUW' , (/ 'ilev' /), 'A','Pa', &
2338 6144 : trim(scheme)//' Westward Reynolds stress')
2339 : call addfld (trim(prefix)//'TAUNET' , (/ 'ilev' /), 'A','Pa', &
2340 6144 : trim(scheme)//' E+W Reynolds stress')
2341 : call addfld (trim(prefix)//'TAUN' , (/ 'ilev' /), 'A','Pa', &
2342 6144 : trim(scheme)//' Northward Reynolds stress')
2343 : call addfld (trim(prefix)//'TAUS' , (/ 'ilev' /), 'A','Pa', &
2344 6144 : trim(scheme)//' Southward Reynolds stress')
2345 :
2346 : ! Momentum flux in each direction.
2347 : call addfld (trim(prefix)//'EMF', (/ 'lev' /), 'A','Pa', &
2348 6144 : trim(scheme)//' Eastward MF')
2349 : call addfld (trim(prefix)//'WMF', (/ 'lev' /), 'A','Pa', &
2350 6144 : trim(scheme)//' Westward MF')
2351 : call addfld (trim(prefix)//'NMF', (/ 'lev' /), 'A','Pa', &
2352 6144 : trim(scheme)//' Northward MF')
2353 : call addfld (trim(prefix)//'SMF', (/ 'lev' /), 'A','Pa', &
2354 6144 : trim(scheme)//' Southward MF')
2355 :
2356 : ! Temperature tendency terms.
2357 : call addfld (trim(prefix)//'TTGWSDF' , (/ 'lev' /), 'A','K/s', &
2358 6144 : trim(scheme)//' t tendency - diffusion term')
2359 : call addfld (trim(prefix)//'TTGWSKE' , (/ 'lev' /), 'A','K/s', &
2360 6144 : trim(scheme)//' t tendency - kinetic energy conversion term')
2361 :
2362 : ! Gravity wave source spectra by wave number.
2363 202752 : do l=-band%ngwv,band%ngwv
2364 : ! String containing reference speed.
2365 199680 : write (fnum,fmt='(f7.2)') band%cref(l)
2366 :
2367 199680 : dumc1x = tau_fld_name(l, prefix, x_not_y=.true.)
2368 199680 : dumc1y = tau_fld_name(l, prefix, x_not_y=.false.)
2369 199680 : dumc2 = trim(scheme)//" tau at c= "//trim(fnum)//" m/s"
2370 399360 : call addfld (trim(dumc1x),(/ 'lev' /), 'A','Pa',dumc2)
2371 402432 : call addfld (trim(dumc1y),(/ 'lev' /), 'A','Pa',dumc2)
2372 :
2373 : end do
2374 :
2375 3072 : if (history_defaults) then
2376 0 : call add_default(trim(prefix)//'UTGWSPEC', 1, ' ')
2377 0 : call add_default(trim(prefix)//'VTGWSPEC', 1, ' ')
2378 0 : call add_default(trim(prefix)//'TTGWSPEC', 1, ' ')
2379 0 : call add_default(trim(prefix)//'TAUE', 1, ' ')
2380 0 : call add_default(trim(prefix)//'TAUW', 1, ' ')
2381 0 : call add_default(trim(prefix)//'TAUNET', 1, ' ')
2382 0 : call add_default(trim(prefix)//'TAUN', 1, ' ')
2383 0 : call add_default(trim(prefix)//'TAUS', 1, ' ')
2384 : end if
2385 :
2386 3072 : end subroutine gw_spec_addflds
2387 :
2388 : !==========================================================================
2389 :
2390 : ! Outputs for spectral waves.
2391 0 : subroutine gw_spec_outflds(prefix, lchnk, ncol, band, c, u, v, xv, yv, &
2392 117648 : gwut, dttdf, dttke, tau, utgw, vtgw, ttgw, taucd)
2393 :
2394 3072 : use gw_common, only: west, east, south, north
2395 :
2396 : ! One-character prefix prepended to output fields.
2397 : character(len=1), intent(in) :: prefix
2398 : ! Chunk and number of columns in the chunk.
2399 : integer, intent(in) :: lchnk
2400 : integer, intent(in) :: ncol
2401 : ! Wave speeds.
2402 : type(GWBand), intent(in) :: band
2403 : ! Wave phase speeds for each column.
2404 : real(r8), intent(in) :: c(ncol,-band%ngwv:band%ngwv)
2405 : ! Winds at cell midpoints.
2406 : real(r8), intent(in) :: u(ncol,pver)
2407 : real(r8), intent(in) :: v(ncol,pver)
2408 : ! Unit vector in the direction of wind at source level.
2409 : real(r8), intent(in) :: xv(ncol)
2410 : real(r8), intent(in) :: yv(ncol)
2411 : ! Wind tendency for each wave.
2412 : real(r8), intent(in) :: gwut(ncol,pver,-band%ngwv:band%ngwv)
2413 : ! Temperature tendencies from diffusion and kinetic energy.
2414 : real(r8) :: dttdf(ncol,pver)
2415 : real(r8) :: dttke(ncol,pver)
2416 : ! Wave Reynolds stress.
2417 : real(r8), intent(in) :: tau(ncol,-band%ngwv:band%ngwv,pver)
2418 : ! Zonal and meridional total wind tendencies.
2419 : real(r8), intent(in) :: utgw(ncol,pver)
2420 : real(r8), intent(in) :: vtgw(ncol,pver)
2421 : ! Temperature tendencies.
2422 : real(r8), intent(in) :: ttgw(ncol,pver)
2423 : ! Reynolds stress for waves propagating in each cardinal direction.
2424 : real(r8), intent(in) :: taucd(ncol,pver+1,4)
2425 :
2426 : ! Indices
2427 : integer :: i, k, l
2428 235296 : integer :: ix(ncol, -band%ngwv:band%ngwv), iy(ncol, -band%ngwv:band%ngwv)
2429 235296 : integer :: iu(ncol), iv(ncol)
2430 :
2431 : ! Zonal wind tendency, broken up into five bins.
2432 235296 : real(r8) :: utb(ncol, pver, 5)
2433 : ! Definition of the bin boundaries.
2434 : real(r8), parameter :: bounds(4) = (/ -40._r8, -15._r8, &
2435 : 15._r8, 40._r8 /)
2436 :
2437 : ! Momentum flux in the four cardinal directions.
2438 235296 : real(r8) :: mf(ncol, pver, 4)
2439 :
2440 : ! Wave stress in zonal/meridional direction
2441 235296 : real(r8) :: taux(ncol,-band%ngwv:band%ngwv,pver)
2442 235296 : real(r8) :: tauy(ncol,-band%ngwv:band%ngwv,pver)
2443 :
2444 : ! Temporaries for output
2445 235296 : real(r8) :: dummyx(ncol,pver)
2446 117648 : real(r8) :: dummyy(ncol,pver)
2447 : ! Variable names
2448 : character(len=10) :: dumc1x, dumc1y
2449 :
2450 :
2451 : ! Accumulate wind tendencies binned according to phase speed.
2452 :
2453 914174208 : utb = 0._r8
2454 :
2455 : ! Find which output bin the phase speed corresponds to.
2456 255495888 : ix = find_bin(c)
2457 :
2458 : ! Put the wind tendency in that bin.
2459 7764768 : do l = -band%ngwv, band%ngwv
2460 718946928 : do k = 1, pver
2461 11882735280 : do i = 1, ncol
2462 11875088160 : utb(i,k,ix(i,l)) = utb(i,k,ix(i,l)) + gwut(i,k,l)
2463 : end do
2464 : end do
2465 : end do
2466 :
2467 : ! Find just the zonal part.
2468 705888 : do l = 1, 5
2469 55412208 : do k = 1, pver
2470 914056560 : utb(:, k, l) = utb(:, k, l) * xv
2471 : end do
2472 : end do
2473 :
2474 117648 : call outfld(trim(prefix)//'UTEND1', utb(:,:,1), ncol, lchnk)
2475 117648 : call outfld(trim(prefix)//'UTEND2', utb(:,:,2), ncol, lchnk)
2476 117648 : call outfld(trim(prefix)//'UTEND3', utb(:,:,3), ncol, lchnk)
2477 117648 : call outfld(trim(prefix)//'UTEND4', utb(:,:,4), ncol, lchnk)
2478 117648 : call outfld(trim(prefix)//'UTEND5', utb(:,:,5), ncol, lchnk)
2479 :
2480 : ! Output temperature tendencies due to diffusion and from kinetic energy.
2481 182811312 : call outfld(trim(prefix)//'TTGWSDF', dttdf / cpair, ncol, lchnk)
2482 182811312 : call outfld(trim(prefix)//'TTGWSKE', dttke / cpair, ncol, lchnk)
2483 :
2484 :
2485 : ! Output tau broken down into zonal and meridional components.
2486 :
2487 11886147072 : taux = 0._r8
2488 11886147072 : tauy = 0._r8
2489 :
2490 : ! Project c, and convert each component to a wavenumber index.
2491 : ! These are mappings from the wavenumber index of tau to those of taux
2492 : ! and tauy, respectively.
2493 7764768 : do l=-band%ngwv,band%ngwv
2494 127689120 : ix(:,l) = c_to_l(c(:,l)*xv)
2495 127806768 : iy(:,l) = c_to_l(c(:,l)*yv)
2496 : end do
2497 :
2498 : ! Find projection of tau.
2499 11058912 : do k = 1, pver
2500 722241072 : do l = -band%ngwv,band%ngwv
2501 11886029424 : do i = 1, ncol
2502 44655624000 : taux(i,ix(i,l),k) = taux(i,ix(i,l),k) &
2503 44655624000 : + abs(tau(i,l,k)*xv(i))
2504 11163906000 : tauy(i,iy(i,l),k) = tauy(i,iy(i,l),k) &
2505 23038994160 : + abs(tau(i,l,k)*yv(i))
2506 : end do
2507 : end do
2508 : end do
2509 :
2510 7764768 : do l=-band%ngwv,band%ngwv
2511 :
2512 11882735280 : dummyx = taux(:,l,:)
2513 11882735280 : dummyy = tauy(:,l,:)
2514 :
2515 7647120 : dumc1x = tau_fld_name(l, prefix, x_not_y=.true.)
2516 7647120 : dumc1y = tau_fld_name(l, prefix, x_not_y=.false.)
2517 :
2518 7647120 : call outfld(dumc1x,dummyx,ncol,lchnk)
2519 7764768 : call outfld(dumc1y,dummyy,ncol,lchnk)
2520 :
2521 : enddo
2522 :
2523 :
2524 : ! Output momentum flux in each cardinal direction.
2525 731362896 : mf = 0._r8
2526 :
2527 11058912 : do k = 1, pver
2528 :
2529 : ! Convert wind speed components to wavenumber indices.
2530 182693664 : iu = c_to_l(u(:,k))
2531 182693664 : iv = c_to_l(v(:,k))
2532 :
2533 : ! Sum tau components in each cardinal direction.
2534 : ! Split west/east and north/south based on whether wave speed exceeds
2535 : ! wind speed.
2536 722241072 : do l = -band%ngwv, band%ngwv
2537 :
2538 57953076480 : where (iu > l)
2539 711182160 : mf(:,k,west) = mf(:,k,west) + taux(:,l,k)
2540 : elsewhere
2541 711182160 : mf(:,k,east) = mf(:,k,east) + taux(:,l,k)
2542 : end where
2543 :
2544 57964017744 : where (iv > l)
2545 711182160 : mf(:,k,south) = mf(:,k,south) + tauy(:,l,k)
2546 : elsewhere
2547 711182160 : mf(:,k,north) = mf(:,k,north) + tauy(:,l,k)
2548 : end where
2549 :
2550 : end do
2551 :
2552 : end do
2553 :
2554 117648 : call outfld(trim(prefix)//'WMF',mf(:,:,west),ncol,lchnk)
2555 117648 : call outfld(trim(prefix)//'EMF',mf(:,:,east),ncol,lchnk)
2556 117648 : call outfld(trim(prefix)//'SMF',mf(:,:,south),ncol,lchnk)
2557 117648 : call outfld(trim(prefix)//'NMF',mf(:,:,north),ncol,lchnk)
2558 :
2559 : ! Simple output fields written to history file.
2560 : ! Total wind tendencies.
2561 117648 : call outfld (trim(prefix)//'UTGWSPEC', utgw , ncol, lchnk)
2562 117648 : call outfld (trim(prefix)//'VTGWSPEC', vtgw , ncol, lchnk)
2563 117648 : call outfld (trim(prefix)//'TTGWSPEC', ttgw , ncol, lchnk)
2564 :
2565 : ! Tau in each direction.
2566 117648 : call outfld (trim(prefix)//'TAUE', taucd(:,:,east), ncol, lchnk)
2567 117648 : call outfld (trim(prefix)//'TAUW', taucd(:,:,west), ncol, lchnk)
2568 117648 : call outfld (trim(prefix)//'TAUN', taucd(:,:,north), ncol, lchnk)
2569 117648 : call outfld (trim(prefix)//'TAUS', taucd(:,:,south), ncol, lchnk)
2570 :
2571 : call outfld (trim(prefix)//'TAUNET', taucd(:,:,east)+taucd(:,:,west), &
2572 184775760 : ncol, lchnk)
2573 :
2574 : contains
2575 :
2576 : ! Given a value, finds which bin marked by "bounds" the value falls
2577 : ! into.
2578 120042000 : elemental function find_bin(val) result(idx)
2579 : real(r8), intent(in) :: val
2580 :
2581 : integer :: idx
2582 :
2583 : ! We just have to count how many bounds are exceeded.
2584 120042000 : if (val >= 0._r8) then
2585 330736605 : idx = count(val > bounds) + 1
2586 : else
2587 269473395 : idx = count(val >= bounds) + 1
2588 : end if
2589 :
2590 120042000 : end function find_bin
2591 :
2592 : ! Convert a speed to a wavenumber between -ngwv and ngwv.
2593 583588800 : elemental function c_to_l(c) result(l)
2594 : real(r8), intent(in) :: c
2595 :
2596 : integer :: l
2597 :
2598 583588800 : l = min( max(int(c/band%dc),-band%ngwv), band%ngwv )
2599 :
2600 583588800 : end function c_to_l
2601 :
2602 : end subroutine gw_spec_outflds
2603 :
2604 : !==========================================================================
2605 :
2606 : ! Generates names for tau output across the wave spectrum (e.g.
2607 : ! BTAUXSn01 or TAUYSp05).
2608 : ! Probably this should use a wavenumber dimension on one field rather
2609 : ! than creating a ton of numbered fields.
2610 15693600 : character(len=9) pure function tau_fld_name(l, prefix, x_not_y)
2611 : ! Wavenumber
2612 : integer, intent(in) :: l
2613 : ! Single-character prefix for output
2614 : character(len=1), intent(in) :: prefix
2615 : ! X or Y?
2616 : logical, intent(in) :: x_not_y
2617 :
2618 : character(len=2) :: num_str
2619 :
2620 15693600 : tau_fld_name = trim(prefix)
2621 :
2622 15693600 : tau_fld_name = trim(tau_fld_name)//"TAU"
2623 :
2624 15693600 : if (x_not_y) then
2625 7846800 : tau_fld_name = trim(tau_fld_name)//"XS"
2626 : else
2627 7846800 : tau_fld_name = trim(tau_fld_name)//"YS"
2628 : end if
2629 :
2630 15693600 : if (l < 0) then
2631 7726080 : tau_fld_name = trim(tau_fld_name)//"n"
2632 : else
2633 7967520 : tau_fld_name = trim(tau_fld_name)//"p"
2634 : end if
2635 :
2636 15693600 : write(num_str,'(I2.2)') abs(l)
2637 :
2638 15693600 : tau_fld_name = trim(tau_fld_name)//num_str
2639 :
2640 15693600 : end function tau_fld_name
2641 :
2642 : !==========================================================================
2643 :
2644 : end module gw_drag
|