FV3 Bundle
fv_diagnostics_nlm.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU General Public License *
3 !* This file is a part of fvGFS. *
4 !* *
5 !* fvGFS is free software; you can redistribute it and/or modify it *
6 !* and are expected to follow the terms of the GNU General Public *
7 !* License as published by the Free Software Foundation; either *
8 !* version 2 of the License, or (at your option) any later version. *
9 !* *
10 !* fvGFS is distributed in the hope that it will be useful, but *
11 !* WITHOUT ANY WARRANTY; without even the implied warranty of *
12 !* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13 !* General Public License for more details. *
14 !* *
15 !* For the full text of the GNU General Public License, *
16 !* write to: Free Software Foundation, Inc., *
17 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
18 !* or see: http://www.gnu.org/licenses/gpl.html *
19 !***********************************************************************
21 
26  use mpp_domains_mod, only: domain2d, mpp_update_domains, dgrid_ne
27  use diag_manager_mod, only: diag_axis_init, register_diag_field, &
28  register_static_field, send_data, diag_grid_init
30  r_grid
31  !!! CLEANUP needs rem oval?
32 #ifndef MAPL_MODE
33  use fv_mapz_nlm_mod, only: e_flux, moist_cv
34 #endif
35  use fv_mp_nlm_mod, only: mp_reduce_sum, mp_reduce_min, mp_reduce_max, is_master
37  use fv_grid_utils_nlm_mod, only: g_sum
39  use fv_surf_map_nlm_mod, only: zs_g
40  use fv_sg_nlm_mod, only: qsmith
41 
44  use mpp_mod, only: mpp_error, fatal, stdlog, mpp_pe, mpp_root_pe, mpp_sum, mpp_max
46 
47  use fv_arrays_nlm_mod, only: max_step
48 
49  implicit none
50  private
51 
52 
53  real, parameter:: missing_value = -1.e10
54  real :: ginv
55  real :: pk0
56  logical master
57  character(len=3) :: gn = ''
58 
59 ! private (to this module) diag:
60 
61  type(time_type) :: fv_time
62  type(fv_diag_type), pointer :: idiag
63 
64  logical :: module_is_initialized=.false.
65  logical :: prt_minmax =.false.
66  logical :: m_calendar
67  integer sphum, liq_wat, ice_wat ! GFDL physics
69  integer :: istep
70  real :: ptop
71  real, parameter :: rad2deg = 180./pi
72 
73 ! tracers
74  character(len=128) :: tname
75  character(len=256) :: tlongname, tunits
76  real :: sphum_ll_fix = 0.
77  real :: qcly0 ! initial value for terminator test
78 
79  public :: fv_diag_init, fv_time, fv_diag, prt_mxm, prt_maxmin, range_check!, id_divg, id_te
82 
83  integer, parameter :: nplev = 31
84  integer :: levs(nplev)
85 
86 contains
87 
88  subroutine fv_diag_init(Atm, axes, Time, npx, npy, npz, p_ref)
89  type(fv_atmos_type), intent(inout), target :: atm(:)
90  integer, intent(out) :: axes(4)
91  type(time_type), intent(in) :: time
92  integer, intent(in) :: npx, npy, npz
93  real, intent(in):: p_ref
94 
95  real, allocatable :: grid_xt(:), grid_yt(:), grid_xe(:), grid_ye(:), grid_xn(:), grid_yn(:)
96  real, allocatable :: grid_x(:), grid_y(:)
97  real :: vrange(2), vsrange(2), wrange(2), trange(2), slprange(2), rhrange(2)
98  real, allocatable :: a3(:,:,:)
99  real :: pfull(npz)
100  real :: hyam(npz), hybm(npz)
101 
102  !These id_* are not needed later since they are for static data which is not used elsewhere
103  integer :: id_bk, id_pk, id_area, id_lon, id_lat, id_lont, id_latt, id_phalf, id_pfull
104  integer :: id_hyam, id_hybm
105  integer :: id_plev
106  integer :: i, j, k, n, ntileme, id_xt, id_yt, id_x, id_y, id_xe, id_ye, id_xn, id_yn
107  integer :: isc, iec, jsc, jec
108 
109  logical :: used
110 
111  character(len=64) :: plev
112  character(len=64) :: field
113  integer :: ntprog
114  integer :: unit
115 
116  integer :: ncnst
117  integer :: axe2(3)
118 
119 
120  idiag => atm(1)%idiag
121 
122 ! For total energy diagnostics:
123  idiag%steps = 0
124  idiag%efx = 0.; idiag%efx_sum = 0.
125  idiag%mtq = 0.; idiag%mtq_sum = 0.
126 
127  ncnst = atm(1)%ncnst
128  m_calendar = atm(1)%flagstruct%moist_phys
129 
130  call set_domain(atm(1)%domain) ! Set domain so that diag_manager can access tile information
131 
133  liq_wat = get_tracer_index(model_atmos, 'liq_wat')
134  ice_wat = get_tracer_index(model_atmos, 'ice_wat')
135 
136  rainwat = get_tracer_index(model_atmos, 'rainwat')
137  snowwat = get_tracer_index(model_atmos, 'snowwat')
138  graupel = get_tracer_index(model_atmos, 'graupel')
139 
140 ! valid range for some fields
141 
142 !!! This will need mods for more than 1 tile per pe !!!
143 
144  vsrange = (/ -200., 200. /) ! surface (lowest layer) winds
145 
146  vrange = (/ -330., 330. /) ! winds
147  wrange = (/ -100., 100. /) ! vertical wind
148  rhrange = (/ -10., 150. /) ! RH
149 #ifdef HIWPP
150  trange = (/ 5., 350. /) ! temperature
151 #else
152  trange = (/ 100., 350. /) ! temperature
153 #endif
154  slprange = (/800., 1200./) ! sea-level-pressure
155 
156  ginv = 1./grav
157  if (atm(1)%grid_number == 1) fv_time = time
158 
159  allocate ( idiag%phalf(npz+1) )
160  call get_eta_level(atm(1)%npz, p_ref, pfull, idiag%phalf, atm(1)%ak, atm(1)%bk, 0.01)
161 
162 ! allocate(grid_xt(npx-1), grid_yt(npy-1), grid_xe(npx), grid_ye(npy-1), grid_xn(npx-1), grid_yn(npy))
163  allocate(grid_xt(npx-1), grid_yt(npy-1))
164  grid_xt = (/ (i, i=1,npx-1) /)
165  grid_yt = (/ (j, j=1,npy-1) /)
166 ! grid_xe = (/ (i, i=1,npx) /)
167 ! grid_ye = (/ (j, j=1,npy-1) /)
168 ! grid_xn = (/ (i, i=1,npx-1) /)
169 ! grid_yn = (/ (j, j=1,npy) /)
170 
171  allocate(grid_x(npx), grid_y(npy))
172  grid_x = (/ (i, i=1,npx) /)
173  grid_y = (/ (j, j=1,npy) /)
174 
175  n=1
176  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
177  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
178 
179  ! Send diag_manager the grid informtaion
180  call diag_grid_init(domain=atm(n)%domain, &
181  & glo_lon=rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,1), &
182  & glo_lat=rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,2), &
183  & aglo_lon=rad2deg*atm(n)%gridstruct%agrid(isc-1:iec+1,jsc-1:jec+1,1), &
184  & aglo_lat=rad2deg*atm(n)%gridstruct%agrid(isc-1:iec+1,jsc-1:jec+1,2))
185 
186  ntileme = size(atm(:))
187  if (ntileme > 1) call mpp_error(fatal, "fv_diag_init can only be called with one grid at a time.")
188 
189 ! do n = 1, ntileMe
190  n = 1
191  field = 'grid'
192 
193  id_xt = diag_axis_init('grid_xt',grid_xt,'degrees_E','x','T-cell longitude', &
194  set_name=trim(field),domain2=atm(n)%Domain, tile_count=n)
195  id_yt = diag_axis_init('grid_yt',grid_yt,'degrees_N','y','T-cell latitude', &
196  set_name=trim(field), domain2=atm(n)%Domain, tile_count=n)
197 ! Don't need these right now
198 ! id_xe = diag_axis_init ('grid_xe',grid_xe,'degrees_E','x','E-cell longitude', &
199 ! set_name=trim(field),Domain2=Domain, tile_count=n)
200 ! id_ye = diag_axis_init ('grid_ye',grid_ye,'degrees_N','y','E-cell latitude', &
201 ! set_name=trim(field), Domain2=Domain, tile_count=n)
202 ! id_xn = diag_axis_init ('grid_xn',grid_xn,'degrees_E','x','N-cell longitude', &
203 ! set_name=trim(field),Domain2=Domain, aux='geolon_n, geolat_n', tile_count=n)
204 ! id_yn = diag_axis_init ('grid_yn',grid_yn,'degrees_N','y','N-cell latitude', &
205 ! set_name=trim(field), Domain2=Domain, tile_count=n)
206 
207  id_x = diag_axis_init('grid_x',grid_x,'degrees_E','x','cell corner longitude', &
208  set_name=trim(field),domain2=atm(n)%Domain, tile_count=n)
209  id_y = diag_axis_init('grid_y',grid_y,'degrees_N','y','cell corner latitude', &
210  set_name=trim(field), domain2=atm(n)%Domain, tile_count=n)
211 
212 ! end do
213 ! deallocate(grid_xt, grid_yt, grid_xe, grid_ye, grid_xn, grid_yn)
214  deallocate(grid_xt, grid_yt)
215  deallocate(grid_x, grid_y )
216 
217  id_phalf = diag_axis_init('phalf', idiag%phalf, 'mb', 'z', &
218  'ref half pressure level', direction=-1, set_name="dynamics")
219  id_pfull = diag_axis_init('pfull', pfull, 'mb', 'z', &
220  'ref full pressure level', direction=-1, set_name="dynamics", edges=id_phalf)
221 
222 !---- register static fields -------
223 
224  id_bk = register_static_field( "dynamics", 'bk', (/id_phalf/), &
225  'vertical coordinate sigma value', 'none' )
226 
227  id_pk = register_static_field( "dynamics", 'pk', (/id_phalf/), &
228  'pressure part of the hybrid coordinate', 'pascal' )
229 
230  id_hyam = register_static_field( "dynamics", 'hyam', (/id_pfull/), &
231  'vertical coordinate A value', '1E-5 Pa' )
232 
233  id_hybm = register_static_field( "dynamics", 'hybm', (/id_pfull/), &
234  'vertical coordinate B value', 'none' )
235 
236 !--- Send static data
237 
238  if ( id_bk > 0 ) used = send_data( id_bk,atm(1)%bk, time )
239  if ( id_pk > 0 ) used = send_data( id_pk,atm(1)%ak, time )
240  if ( id_hyam > 0 ) then
241  do k=1,npz
242  hyam(k) = 0.5 * ( atm(1)%ak(k) + atm(1)%ak(k+1) ) * 1.e-5
243  enddo
244  used = send_data( id_hyam, hyam, time )
245  endif
246  if ( id_hybm > 0 ) then
247  do k=1,npz
248  hybm(k) = 0.5 * ( atm(1)%bk(k) + atm(1)%bk(k+1) )
249  enddo
250  used = send_data( id_hybm, hybm, time )
251  endif
252 
253 ! Approach will need modification if we wish to write values on other than A grid.
254  axes(1) = id_xt
255  axes(2) = id_yt
256  axes(3) = id_pfull
257  axes(4) = id_phalf
258 
259 ! Selected pressure levels
260 ! SJL note: 31 is enough here; if you need more levels you should do it OFF line
261 ! do not add more to prevent the model from slowing down too much.
262  levs = (/1,2,3,5,7,10,20,30,50,70,100,150,200,250,300,350,400,450,500,550,600,650,700,750,800,850,900,925,950,975,1000/)
263 
264  id_plev = diag_axis_init('plev', levs(:)*1.0, 'mb', 'z', &
265  'actual pressure level', direction=-1, set_name="dynamics")
266 
267  axe2(1) = id_xt
268  axe2(2) = id_yt
269  axe2(3) = id_plev
270 
271 !---- register time independent fields -------
272 
273 ! do n = 1, ntileMe
274  n = 1
275  field= 'dynamics'
276  id_lon = register_static_field( trim(field), 'grid_lon', (/id_x,id_y/), &
277  'longitude', 'degrees_E' )
278  id_lat = register_static_field( trim(field), 'grid_lat', (/id_x,id_y/), &
279  'latitude', 'degrees_N' )
280  id_lont = register_static_field( trim(field), 'grid_lont', (/id_xt,id_yt/), &
281  'longitude', 'degrees_E' )
282  id_latt = register_static_field( trim(field), 'grid_latt', (/id_xt,id_yt/), &
283  'latitude', 'degrees_N' )
284  id_area = register_static_field( trim(field), 'area', axes(1:2), &
285  'cell area', 'm**2' )
286 #ifndef DYNAMICS_ZS
287  idiag%id_zsurf = register_static_field( trim(field), 'zsurf', axes(1:2), &
288  'surface height', 'm' )
289 #endif
290  idiag%id_zs = register_static_field( trim(field), 'zs', axes(1:2), &
291  'Original Mean Terrain', 'm' )
292 ! 3D hybrid_z fields:
293  idiag%id_ze = register_static_field( trim(field), 'ze', axes(1:3), &
294  'Hybrid_Z_surface', 'm' )
295  idiag%id_oro = register_static_field( trim(field), 'oro', axes(1:2), &
296  'Land/Water Mask', 'none' )
297  idiag%id_sgh = register_static_field( trim(field), 'sgh', axes(1:2), &
298  'Terrain Standard deviation', 'm' )
299 ! idiag%id_ts = register_static_field ( trim(field), 'ts', axes(1:2), &
300 ! 'Skin temperature', 'K' )
301 
302 !--------------------
303 ! Initial conditions:
304 !--------------------
305  idiag%ic_ps = register_static_field( trim(field), 'ps_ic', axes(1:2), &
306  'initial surface pressure', 'Pa' )
307  idiag%ic_ua = register_static_field( trim(field), 'ua_ic', axes(1:3), &
308  'zonal wind', 'm/sec' )
309  idiag%ic_va = register_static_field( trim(field), 'va_ic', axes(1:3), &
310  'meridional wind', 'm/sec' )
311  idiag%ic_ppt= register_static_field( trim(field), 'ppt_ic', axes(1:3), &
312  'potential temperature perturbation', 'K' )
313  idiag%ic_sphum = register_static_field( trim(field), 'sphum_ic', axes(1:2), &
314  'initial surface pressure', 'Pa' )
315 
316 ! end do
317 
318  master = (mpp_pe()==mpp_root_pe())
319 
320  n=1
321  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
322  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
323 
324  allocate ( idiag%zsurf(isc:iec,jsc:jec) )
325 
326  do j=jsc,jec
327  do i=isc,iec
328  idiag%zsurf(i,j) = ginv * atm(n)%phis(i,j)
329  enddo
330  enddo
331 
332 !--- Send time independent data
333 
334 ! do n = 1, ntileMe
335  n = 1
336  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
337  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
338  if (id_lon > 0) used = send_data(id_lon, rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,1), time)
339  if (id_lat > 0) used = send_data(id_lat, rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,2), time)
340  if (id_lont > 0) used = send_data(id_lont, rad2deg*atm(n)%gridstruct%agrid(isc:iec,jsc:jec,1), time)
341  if (id_latt > 0) used = send_data(id_latt, rad2deg*atm(n)%gridstruct%agrid(isc:iec,jsc:jec,2), time)
342  if (id_area > 0) used = send_data(id_area, atm(n)%gridstruct%area(isc:iec,jsc:jec), time)
343 #ifndef DYNAMICS_ZS
344  if (idiag%id_zsurf > 0) used = send_data(idiag%id_zsurf, idiag%zsurf, time)
345 #endif
346  if ( atm(n)%flagstruct%fv_land ) then
347  if (idiag%id_zs > 0) used = send_data(idiag%id_zs , zs_g, time)
348  if (idiag%id_oro > 0) used = send_data(idiag%id_oro, atm(n)%oro(isc:iec,jsc:jec), time)
349  if (idiag%id_sgh > 0) used = send_data(idiag%id_sgh, atm(n)%sgh(isc:iec,jsc:jec), time)
350  endif
351 
352  if ( atm(n)%flagstruct%ncep_ic ) then
353  if (idiag%id_ts > 0) used = send_data(idiag%id_ts, atm(n)%ts(isc:iec,jsc:jec), time)
354  endif
355 
356  if ( atm(n)%flagstruct%hybrid_z .and. idiag%id_ze > 0 ) &
357  used = send_data(idiag%id_ze, atm(n)%ze0(isc:iec,jsc:jec,1:npz), time)
358 
359  if (idiag%ic_ps > 0) used = send_data(idiag%ic_ps, atm(n)%ps(isc:iec,jsc:jec)*ginv, time)
360 
361  if(idiag%ic_ua > 0) used=send_data(idiag%ic_ua, atm(n)%ua(isc:iec,jsc:jec,:), time)
362  if(idiag%ic_va > 0) used=send_data(idiag%ic_va, atm(n)%va(isc:iec,jsc:jec,:), time)
363 
364  pk0 = 1000.e2 ** kappa
365  if(idiag%ic_ppt> 0) then
366 ! Potential temperature
367  allocate ( idiag%pt1(npz) )
368  allocate ( a3(isc:iec,jsc:jec,npz) )
369 #ifdef TEST_GWAVES
370  call gw_1d(npz, 1000.e2, atm(n)%ak, atm(n)%ak, atm(n)%ak(1), 10.e3, idiag%pt1)
371 #else
372  idiag%pt1 = 0.
373 #endif
374  do k=1,npz
375  do j=jsc,jec
376  do i=isc,iec
377  a3(i,j,k) = (atm(n)%pt(i,j,k)/atm(n)%pkz(i,j,k) - idiag%pt1(k)) * pk0
378  enddo
379  enddo
380  enddo
381  used=send_data(idiag%ic_ppt, a3, time)
382  deallocate ( a3 )
383  deallocate ( idiag%pt1 )
384  endif
385 ! end do
386 
387 !--------------------------------------------------------------
388 ! Register main prognostic fields: ps, (u,v), t, omega (dp/dt)
389 !--------------------------------------------------------------
390 
391  allocate(idiag%id_tracer(ncnst))
392  allocate(idiag%id_tracer_dmmr(ncnst))
393  allocate(idiag%id_tracer_dvmr(ncnst))
394  allocate(idiag%w_mr(ncnst))
395  idiag%id_tracer(:) = 0
396  idiag%id_tracer_dmmr(:) = 0
397  idiag%id_tracer_dvmr(:) = 0
398  idiag%w_mr(:) = 0.e0
399 
400  allocate(idiag%id_u(nplev))
401  allocate(idiag%id_v(nplev))
402  allocate(idiag%id_t(nplev))
403  allocate(idiag%id_h(nplev))
404  allocate(idiag%id_q(nplev))
405  allocate(idiag%id_omg(nplev))
406  idiag%id_u(:) = 0
407  idiag%id_v(:) = 0
408  idiag%id_t(:) = 0
409  idiag%id_h(:) = 0
410  idiag%id_q(:) = 0
411  idiag%id_omg(:) = 0
412 
413 ! do n = 1, ntileMe
414  n = 1
415  field= 'dynamics'
416 
417 #ifdef DYNAMICS_ZS
418  idiag%id_zsurf = register_diag_field( trim(field), 'zsurf', axes(1:2), time, &
419  'surface height', 'm')
420 #endif
421 !-------------------
422 ! Surface pressure
423 !-------------------
424  idiag%id_ps = register_diag_field( trim(field), 'ps', axes(1:2), time, &
425  'surface pressure', 'Pa', missing_value=missing_value )
426 
427 !-------------------
428 ! Mountain torque
429 !-------------------
430  idiag%id_mq = register_diag_field( trim(field), 'mq', axes(1:2), time, &
431  'mountain torque', 'Hadleys per unit area', missing_value=missing_value )
432 !-------------------
433 ! Angular momentum
434 !-------------------
435  idiag%id_aam = register_diag_field( trim(field), 'aam', axes(1:2), time, &
436  'angular momentum', 'kg*m^2/s', missing_value=missing_value )
437  idiag%id_amdt = register_diag_field( trim(field), 'amdt', axes(1:2), time, &
438  'angular momentum error', 'kg*m^2/s^2', missing_value=missing_value )
439 
440 !
441  do i=1,nplev
442  write(plev,'(I5)') levs(i)
443 ! Height:
444  idiag%id_h(i) = register_diag_field(trim(field), 'z'//trim(adjustl(plev)), axes(1:2), time, &
445  trim(adjustl(plev))//'-mb height', 'm', missing_value=missing_value)
446 ! u-wind:
447  idiag%id_u(i) = register_diag_field(trim(field), 'u'//trim(adjustl(plev)), axes(1:2), time, &
448  trim(adjustl(plev))//'-mb u', 'm/s', missing_value=missing_value)
449 ! v-wind:
450  idiag%id_v(i) = register_diag_field(trim(field), 'v'//trim(adjustl(plev)), axes(1:2), time, &
451  trim(adjustl(plev))//'-mb v', 'm/s', missing_value=missing_value)
452 ! Temperature (K):
453  idiag%id_t(i) = register_diag_field(trim(field), 't'//trim(adjustl(plev)), axes(1:2), time, &
454  trim(adjustl(plev))//'-mb temperature', 'K', missing_value=missing_value)
455 ! specific humidity:
456  idiag%id_q(i) = register_diag_field(trim(field), 'q'//trim(adjustl(plev)), axes(1:2), time, &
457  trim(adjustl(plev))//'-mb specific humidity', 'kg/kg', missing_value=missing_value)
458 ! Omega (Pa/sec)
459  idiag%id_omg(i) = register_diag_field(trim(field), 'omg'//trim(adjustl(plev)), axes(1:2), time, &
460  trim(adjustl(plev))//'-mb omega', 'Pa/s', missing_value=missing_value)
461  enddo
462 
463  idiag%id_u_plev = register_diag_field( trim(field), 'u_plev', axe2(1:3), time, &
464  'zonal wind', 'm/sec', missing_value=missing_value, range=vrange )
465  idiag%id_v_plev = register_diag_field( trim(field), 'v_plev', axe2(1:3), time, &
466  'meridional wind', 'm/sec', missing_value=missing_value, range=vrange )
467  idiag%id_t_plev = register_diag_field( trim(field), 't_plev', axe2(1:3), time, &
468  'temperature', 'K', missing_value=missing_value, range=trange )
469  idiag%id_h_plev = register_diag_field( trim(field), 'h_plev', axe2(1:3), time, &
470  'height', 'm', missing_value=missing_value )
471  idiag%id_q_plev = register_diag_field( trim(field), 'q_plev', axe2(1:3), time, &
472  'specific humidity', 'kg/kg', missing_value=missing_value )
473  idiag%id_omg_plev = register_diag_field( trim(field), 'omg_plev', axe2(1:3), time, &
474  'omega', 'Pa/s', missing_value=missing_value )
475 
476  ! flag for calculation of geopotential
477  if ( all(idiag%id_h(minloc(abs(levs-10)))>0) .or. all(idiag%id_h(minloc(abs(levs-50)))>0) .or. &
478  all(idiag%id_h(minloc(abs(levs-100)))>0) .or. all(idiag%id_h(minloc(abs(levs-200)))>0) .or. &
479  all(idiag%id_h(minloc(abs(levs-250)))>0) .or. all(idiag%id_h(minloc(abs(levs-300)))>0) .or. &
480  all(idiag%id_h(minloc(abs(levs-500)))>0) .or. all(idiag%id_h(minloc(abs(levs-700)))>0) .or. &
481  all(idiag%id_h(minloc(abs(levs-850)))>0) .or. all(idiag%id_h(minloc(abs(levs-1000)))>0) ) then
482  idiag%id_hght = 1
483  else
484  idiag%id_hght = 0
485  endif
486 !-----------------------------
487 ! mean temp between 300-500 mb
488 !-----------------------------
489  idiag%id_tm = register_diag_field(trim(field), 'tm', axes(1:2), time, &
490  'mean 300-500 mb temp', 'K', missing_value=missing_value )
491 
492 !-------------------
493 ! Sea-level-pressure
494 !-------------------
495  idiag%id_slp = register_diag_field(trim(field), 'slp', axes(1:2), time, &
496  'sea-level pressure', 'mb', missing_value=missing_value, &
497  range=slprange )
498 !----------------------------------
499 ! Bottom level pressure for masking
500 !----------------------------------
501  idiag%id_pmask = register_diag_field(trim(field), 'pmask', axes(1:2), time, &
502  'masking pressure at lowest level', 'mb', &
504 !------------------------------------------
505 ! Fix for Bottom level pressure for masking
506 !------------------------------------------
507  idiag%id_pmaskv2 = register_diag_field(trim(field), 'pmaskv2', axes(1:2), time,&
508  & 'masking pressure at lowest level', 'mb', missing_value=missing_value)
509 
510 !-------------------
511 ! Hurricane scales:
512 !-------------------
513 ! Net effects: ~ intensity * freq
514  idiag%id_c15 = register_diag_field(trim(field), 'cat15', axes(1:2), time, &
515  'de-pression < 1000', 'mb', missing_value=missing_value)
516  idiag%id_c25 = register_diag_field(trim(field), 'cat25', axes(1:2), time, &
517  'de-pression < 980', 'mb', missing_value=missing_value)
518  idiag%id_c35 = register_diag_field(trim(field), 'cat35', axes(1:2), time, &
519  'de-pression < 964', 'mb', missing_value=missing_value)
520  idiag%id_c45 = register_diag_field(trim(field), 'cat45', axes(1:2), time, &
521  'de-pression < 944', 'mb', missing_value=missing_value)
522 ! Frequency:
523  idiag%id_f15 = register_diag_field(trim(field), 'f15', axes(1:2), time, &
524  'Cat15 frequency', 'none', missing_value=missing_value)
525  idiag%id_f25 = register_diag_field(trim(field), 'f25', axes(1:2), time, &
526  'Cat25 frequency', 'none', missing_value=missing_value)
527  idiag%id_f35 = register_diag_field(trim(field), 'f35', axes(1:2), time, &
528  'Cat35 frequency', 'none', missing_value=missing_value)
529  idiag%id_f45 = register_diag_field(trim(field), 'f45', axes(1:2), time, &
530  'Cat45 frequency', 'none', missing_value=missing_value)
531 !-------------------
532 ! A grid winds (lat-lon)
533 !-------------------
534  idiag%id_ua = register_diag_field( trim(field), 'ucomp', axes(1:3), time, &
535  'zonal wind', 'm/sec', missing_value=missing_value, range=vrange )
536  idiag%id_va = register_diag_field( trim(field), 'vcomp', axes(1:3), time, &
537  'meridional wind', 'm/sec', missing_value=missing_value, range=vrange)
538  if ( .not. atm(n)%flagstruct%hydrostatic ) &
539  idiag%id_w = register_diag_field( trim(field), 'w', axes(1:3), time, &
540  'vertical wind', 'm/sec', missing_value=missing_value, range=wrange )
541 
542  idiag%id_pt = register_diag_field( trim(field), 'temp', axes(1:3), time, &
543  'temperature', 'K', missing_value=missing_value, range=trange )
544  idiag%id_ppt = register_diag_field( trim(field), 'ppt', axes(1:3), time, &
545  'potential temperature perturbation', 'K', missing_value=missing_value )
546  idiag%id_theta_e = register_diag_field( trim(field), 'theta_e', axes(1:3), time, &
547  'theta_e', 'K', missing_value=missing_value )
548  idiag%id_omga = register_diag_field( trim(field), 'omega', axes(1:3), time, &
549  'omega', 'Pa/s', missing_value=missing_value )
550  idiag%id_divg = register_diag_field( trim(field), 'divg', axes(1:3), time, &
551  'mean divergence', '1/s', missing_value=missing_value )
552 
553  idiag%id_rh = register_diag_field( trim(field), 'rh', axes(1:3), time, &
554  'Relative Humidity', '%', missing_value=missing_value )
555 ! 'Relative Humidity', '%', missing_value=missing_value, range=rhrange )
556 ! Total energy (only when moist_phys = .T.)
557  idiag%id_te = register_diag_field( trim(field), 'te', axes(1:2), time, &
558  'Total Energy', 'J/kg', missing_value=missing_value )
559 ! Total Kinetic energy
560  idiag%id_ke = register_diag_field( trim(field), 'ke', axes(1:2), time, &
561  'Total KE', 'm^2/s^2', missing_value=missing_value )
562  idiag%id_delp = register_diag_field( trim(field), 'delp', axes(1:3), time, &
563  'pressure thickness', 'pa', missing_value=missing_value )
564  if ( .not. atm(n)%flagstruct%hydrostatic ) &
565  idiag%id_delz = register_diag_field( trim(field), 'delz', axes(1:3), time, &
566  'height thickness', 'm', missing_value=missing_value )
567  if( atm(n)%flagstruct%hydrostatic ) then
568  idiag%id_pfhy = register_diag_field( trim(field), 'pfhy', axes(1:3), time, &
569  'hydrostatic pressure', 'pa', missing_value=missing_value )
570  else
571  idiag%id_pfnh = register_diag_field( trim(field), 'pfnh', axes(1:3), time, &
572  'non-hydrostatic pressure', 'pa', missing_value=missing_value )
573  endif
574  idiag%id_zratio = register_diag_field( trim(field), 'zratio', axes(1:3), time, &
575  'nonhydro_ratio', 'n/a', missing_value=missing_value )
576  idiag%id_ws = register_diag_field( trim(field), 'ws', axes(1:2), time, &
577  'Terrain W', 'm/s', missing_value=missing_value )
578 !--------------------
579 ! 3D Condensate
580 !--------------------
581  idiag%id_qn = register_diag_field( trim(field), 'qn', axes(1:3), time, &
582  'cloud condensate', 'kg/m/s^2', missing_value=missing_value )
583  idiag%id_qp = register_diag_field( trim(field), 'qp', axes(1:3), time, &
584  'precip condensate', 'kg/m/s^2', missing_value=missing_value )
585 ! fast moist phys tendencies:
586  idiag%id_mdt = register_diag_field( trim(field), 'mdt', axes(1:3), time, &
587  'DT/Dt: fast moist phys', 'deg/sec', missing_value=missing_value )
588  idiag%id_qdt = register_diag_field( trim(field), 'qdt', axes(1:3), time, &
589  'Dqv/Dt: fast moist phys', 'kg/kg/sec', missing_value=missing_value )
590  idiag%id_dbz = register_diag_field( trim(field), 'reflectivity', axes(1:3), time, &
591  'Stoelinga simulated reflectivity', 'dBz', missing_value=missing_value)
592  idiag%id_maxdbz = register_diag_field( trim(field), 'max_reflectivity', axes(1:2), time, &
593  'Stoelinga simulated maximum (composite) reflectivity', 'dBz', missing_value=missing_value)
594  idiag%id_basedbz = register_diag_field( trim(field), 'base_reflectivity', axes(1:2), time, &
595  'Stoelinga simulated base (1 km AGL) reflectivity', 'dBz', missing_value=missing_value)
596  idiag%id_dbz4km = register_diag_field( trim(field), '4km_reflectivity', axes(1:2), time, &
597  'Stoelinga simulated base reflectivity', 'dBz', missing_value=missing_value)
598 
599 !--------------------
600 ! Relative vorticity
601 !--------------------
602  idiag%id_vort = register_diag_field( trim(field), 'vort', axes(1:3), time, &
603  'vorticity', '1/s', missing_value=missing_value )
604 !--------------------
605 ! Potential vorticity
606 !--------------------
607  idiag%id_pv = register_diag_field( trim(field), 'pv', axes(1:3), time, &
608  'potential vorticity', '1/s', missing_value=missing_value )
609 
610 !--------------------------
611 ! Extra surface diagnistics:
612 !--------------------------
613 ! Surface (lowest layer) vorticity: for tropical cyclones diag.
614  idiag%id_vorts = register_diag_field( trim(field), 'vorts', axes(1:2), time, &
615  'surface vorticity', '1/s', missing_value=missing_value )
616  idiag%id_us = register_diag_field( trim(field), 'us', axes(1:2), time, &
617  'surface u-wind', 'm/sec', missing_value=missing_value, range=vsrange )
618  idiag%id_vs = register_diag_field( trim(field), 'vs', axes(1:2), time, &
619  'surface v-wind', 'm/sec', missing_value=missing_value, range=vsrange )
620  idiag%id_tq = register_diag_field( trim(field), 'tq', axes(1:2), time, &
621  'Total water path', 'kg/m**2', missing_value=missing_value )
622  idiag%id_iw = register_diag_field( trim(field), 'iw', axes(1:2), time, &
623  'Ice water path', 'kg/m**2', missing_value=missing_value )
624  idiag%id_lw = register_diag_field( trim(field), 'lw', axes(1:2), time, &
625  'Liquid water path', 'kg/m**2', missing_value=missing_value )
626  idiag%id_ts = register_diag_field( trim(field), 'ts', axes(1:2), time, &
627  'Skin temperature', 'K' )
628  idiag%id_tb = register_diag_field( trim(field), 'tb', axes(1:2), time, &
629  'lowest layer temperature', 'K' )
630  idiag%id_ctt = register_diag_field( trim(field), 'ctt', axes(1:2), time, &
631  'cloud_top temperature', 'K' )
632  idiag%id_ctp = register_diag_field( trim(field), 'ctp', axes(1:2), time, &
633  'cloud_top pressure', 'hPa' )
634 #ifdef HIWPP
635  idiag%id_acl = register_diag_field( trim(field), 'acl', axes(1:2), time, &
636  'Column-averaged Cl mixing ratio', 'kg/kg', missing_value=missing_value )
637  idiag%id_acl2 = register_diag_field( trim(field), 'acl2', axes(1:2), time, &
638  'Column-averaged Cl2 mixing ratio', 'kg/kg', missing_value=missing_value )
639  idiag%id_acly = register_diag_field( trim(field), 'acly', axes(1:2), time, &
640  'Column-averaged total chlorine mixing ratio', 'kg/kg', missing_value=missing_value )
641 #endif
642 
643 !--------------------------
644 ! 850-mb vorticity
645 !--------------------------
646  idiag%id_vort850 = register_diag_field( trim(field), 'vort850', axes(1:2), time, &
647  '850-mb vorticity', '1/s', missing_value=missing_value )
648 
649  if ( .not. atm(n)%flagstruct%hydrostatic ) &
650  idiag%id_w200 = register_diag_field( trim(field), 'w200', axes(1:2), time, &
651  '200-mb w-wind', 'm/s', missing_value=missing_value )
652 
653  idiag%id_vort200 = register_diag_field( trim(field), 'vort200', axes(1:2), time, &
654  '200-mb vorticity', '1/s', missing_value=missing_value )
655 
656 ! Cubed_2_latlon interpolation is more accurate, particularly near the poles, using
657 ! winds speed (a scalar), rather than wind vectors or kinetic energy directly.
658  idiag%id_s200 = register_diag_field( trim(field), 's200', axes(1:2), time, &
659  '200-mb wind_speed', 'm/s', missing_value=missing_value )
660  idiag%id_sl12 = register_diag_field( trim(field), 'sl12', axes(1:2), time, &
661  '12th L wind_speed', 'm/s', missing_value=missing_value )
662  idiag%id_sl13 = register_diag_field( trim(field), 'sl13', axes(1:2), time, &
663  '13th L wind_speed', 'm/s', missing_value=missing_value )
664 ! Selceted (HIWPP) levels of non-precip condensates:
665  idiag%id_qn200 = register_diag_field( trim(field), 'qn200', axes(1:2), time, &
666  '200mb condensate', 'kg/m/s^2', missing_value=missing_value )
667  idiag%id_qn500 = register_diag_field( trim(field), 'qn500', axes(1:2), time, &
668  '500mb condensate', 'kg/m/s^2', missing_value=missing_value )
669  idiag%id_qn850 = register_diag_field( trim(field), 'qn850', axes(1:2), time, &
670  '850mb condensate', 'kg/m/s^2', missing_value=missing_value )
671 
672  if( .not. atm(n)%flagstruct%hydrostatic ) &
673  idiag%id_w500 = register_diag_field( trim(field), 'w500', axes(1:2), time, &
674  '500-mb w-wind', 'm/s', missing_value=missing_value )
675  idiag%id_vort500 = register_diag_field( trim(field), 'vort500', axes(1:2), time, &
676  '500-mb vorticity', '1/s', missing_value=missing_value )
677 
678  idiag%id_w700 = register_diag_field( trim(field), 'w700', axes(1:2), time, &
679  '700-mb w-wind', 'm/s', missing_value=missing_value )
680 
681  if( .not. atm(n)%flagstruct%hydrostatic ) &
682  idiag%id_w850 = register_diag_field( trim(field), 'w850', axes(1:2), time, &
683  '850-mb w-wind', 'm/s', missing_value=missing_value )
684 !--------------------------
685 ! 5km:
686 !--------------------------
687  idiag%id_rain5km = register_diag_field( trim(field), 'rain5km', axes(1:2), time, &
688  '5-km AGL liquid water', 'kg/kg', missing_value=missing_value )
689  if( .not. atm(n)%flagstruct%hydrostatic ) then
690  idiag%id_w5km = register_diag_field( trim(field), 'w5km', axes(1:2), time, &
691  '5-km AGL w-wind', 'm/s', missing_value=missing_value )
692  idiag%id_w2500m = register_diag_field( trim(field), 'w2500m', axes(1:2), time, &
693  '2.5-km AGL w-wind', 'm/s', missing_value=missing_value )
694  endif
695 
696 ! helicity
697  idiag%id_x850 = register_diag_field( trim(field), 'x850', axes(1:2), time, &
698  '850-mb vertical comp. of helicity', 'm/s**2', missing_value=missing_value )
699 ! idiag%id_x03 = register_diag_field ( trim(field), 'x03', axes(1:2), Time, &
700 ! '0-3 km vertical comp. of helicity', 'm**2/s**2', missing_value=missing_value )
701 ! idiag%id_x25 = register_diag_field ( trim(field), 'x25', axes(1:2), Time, &
702 ! '2-5 km vertical comp. of helicity', 'm**2/s**2', missing_value=missing_value )
703 
704 ! Storm Relative Helicity
705  idiag%id_srh = register_diag_field( trim(field), 'srh', axes(1:2), time, &
706  '0-3 km Storm Relative Helicity', 'm/s**2', missing_value=missing_value )
707  idiag%id_srh25 = register_diag_field( trim(field), 'srh25', axes(1:2), time, &
708  '2-5 km Storm Relative Helicity', 'm/s**2', missing_value=missing_value )
709  idiag%id_srh01 = register_diag_field( trim(field), 'srh01', axes(1:2), time, &
710  '0-1 km Storm Relative Helicity', 'm/s**2', missing_value=missing_value )
711 
712  if( .not. atm(n)%flagstruct%hydrostatic ) then
713  idiag%id_uh03 = register_diag_field( trim(field), 'uh03', axes(1:2), time, &
714  '0-3 km Updraft Helicity', 'm/s**2', missing_value=missing_value )
715  idiag%id_uh25 = register_diag_field( trim(field), 'uh25', axes(1:2), time, &
716  '2-5 km Updraft Helicity', 'm/s**2', missing_value=missing_value )
717  endif
718 ! TC test winds at 100 m
719  if( .not. atm(n)%flagstruct%hydrostatic ) &
720  idiag%id_w100m = register_diag_field( trim(field), 'w100m', axes(1:2), time, &
721  '100-m AGL w-wind', 'm/s', missing_value=missing_value )
722 !--------------------------
723 ! relative humidity (physics definition):
724 !--------------------------
725  idiag%id_rh10 = register_diag_field( trim(field), 'rh10', axes(1:2), time, &
726  '10-mb relative humidity', '%', missing_value=missing_value )
727  idiag%id_rh50 = register_diag_field( trim(field), 'rh50', axes(1:2), time, &
728  '50-mb relative humidity', '%', missing_value=missing_value )
729  idiag%id_rh100 = register_diag_field( trim(field), 'rh100', axes(1:2), time, &
730  '100-mb relative humidity', '%', missing_value=missing_value )
731  idiag%id_rh200 = register_diag_field( trim(field), 'rh200', axes(1:2), time, &
732  '200-mb relative humidity', '%', missing_value=missing_value )
733  idiag%id_rh250 = register_diag_field( trim(field), 'rh250', axes(1:2), time, &
734  '250-mb relative humidity', '%', missing_value=missing_value )
735  idiag%id_rh300 = register_diag_field( trim(field), 'rh300', axes(1:2), time, &
736  '300-mb relative humidity', '%', missing_value=missing_value )
737  idiag%id_rh500 = register_diag_field( trim(field), 'rh500', axes(1:2), time, &
738  '500-mb relative humidity', '%', missing_value=missing_value )
739  idiag%id_rh700 = register_diag_field( trim(field), 'rh700', axes(1:2), time, &
740  '700-mb relative humidity', '%', missing_value=missing_value )
741  idiag%id_rh850 = register_diag_field( trim(field), 'rh850', axes(1:2), time, &
742  '850-mb relative humidity', '%', missing_value=missing_value )
743  idiag%id_rh925 = register_diag_field( trim(field), 'rh925', axes(1:2), time, &
744  '925-mb relative humidity', '%', missing_value=missing_value )
745  idiag%id_rh1000 = register_diag_field( trim(field), 'rh1000', axes(1:2), time, &
746  '1000-mb relative humidity', '%', missing_value=missing_value )
747 !--------------------------
748 ! relative humidity (CMIP definition):
749 !--------------------------
750  idiag%id_rh10_cmip = register_diag_field( trim(field), 'rh10_cmip', axes(1:2), time, &
751  '10-mb relative humidity (CMIP)', '%', missing_value=missing_value )
752  idiag%id_rh50_cmip = register_diag_field( trim(field), 'rh50_cmip', axes(1:2), time, &
753  '50-mb relative humidity (CMIP)', '%', missing_value=missing_value )
754  idiag%id_rh100_cmip = register_diag_field( trim(field), 'rh100_cmip', axes(1:2), time, &
755  '100-mb relative humidity (CMIP)', '%', missing_value=missing_value )
756  idiag%id_rh250_cmip = register_diag_field( trim(field), 'rh250_cmip', axes(1:2), time, &
757  '250-mb relative humidity (CMIP)', '%', missing_value=missing_value )
758  idiag%id_rh300_cmip = register_diag_field( trim(field), 'rh300_cmip', axes(1:2), time, &
759  '300-mb relative humidity (CMIP)', '%', missing_value=missing_value )
760  idiag%id_rh500_cmip = register_diag_field( trim(field), 'rh500_cmip', axes(1:2), time, &
761  '500-mb relative humidity (CMIP)', '%', missing_value=missing_value )
762  idiag%id_rh700_cmip = register_diag_field( trim(field), 'rh700_cmip', axes(1:2), time, &
763  '700-mb relative humidity (CMIP)', '%', missing_value=missing_value )
764  idiag%id_rh850_cmip = register_diag_field( trim(field), 'rh850_cmip', axes(1:2), time, &
765  '850-mb relative humidity (CMIP)', '%', missing_value=missing_value )
766  idiag%id_rh925_cmip = register_diag_field( trim(field), 'rh925_cmip', axes(1:2), time, &
767  '925-mb relative humidity (CMIP)', '%', missing_value=missing_value )
768  idiag%id_rh1000_cmip = register_diag_field( trim(field), 'rh1000_cmip', axes(1:2), time, &
769  '1000-mb relative humidity (CMIP)', '%', missing_value=missing_value )
770 
771  do i=1, ncnst
772 !--------------------
773 ! Tracer diagnostics:
774 !--------------------
776  idiag%id_tracer(i) = register_diag_field( field, trim(tname), &
777  axes(1:3), time, trim(tlongname), &
779  if (master) then
780  if (idiag%id_tracer(i) > 0) then
781  unit = stdlog()
782  write(unit,'(a,a,a,a)') &
783  & 'Diagnostics available for tracer ',trim(tname), &
784  ' in module ', trim(field)
785  end if
786  endif
787 !----------------------------------
788 ! ESM Tracer dmmr/dvmr diagnostics:
789 ! for specific elements only
790 !----------------------------------
791 !---co2
792  if (trim(tname).eq.'co2') then
793  idiag%w_mr(:) = wtmco2
794  idiag%id_tracer_dmmr(i) = register_diag_field( field, trim(tname)//'_dmmr', &
795  axes(1:3), time, trim(tlongname)//" (dry mmr)", &
797  idiag%id_tracer_dvmr(i) = register_diag_field( field, trim(tname)//'_dvmr', &
798  axes(1:3), time, trim(tlongname)//" (dry vmr)", &
799  'mol/mol', missing_value=missing_value)
800  if (master) then
801  unit = stdlog()
802  if (idiag%id_tracer_dmmr(i) > 0) then
803  write(unit,'(a,a,a,a)') 'Diagnostics available for '//trim(tname)//' dry mmr ', &
804  trim(tname)//'_dmmr', ' in module ', trim(field)
805  end if
806  if (idiag%id_tracer_dvmr(i) > 0) then
807  write(unit,'(a,a,a,a)') 'Diagnostics available for '//trim(tname)//' dry vmr ', &
808  trim(tname)//'_dvmr', ' in module ', trim(field)
809  end if
810  endif
811  endif
812 !---end co2
813 
814  enddo
815 
816  if ( atm(1)%flagstruct%consv_am .or. idiag%id_mq > 0 .or. idiag%id_amdt > 0 ) then
817  allocate ( idiag%zxg(isc:iec,jsc:jec) )
818 ! Initialize gradient of terrain for mountain torque computation:
819  call init_mq(atm(n)%phis, atm(n)%gridstruct, &
820  npx, npy, isc, iec, jsc, jec, atm(n)%ng)
821  endif
822 
823 ! end do
824 
825 
826 #ifdef TEST_TRACER
827  call prt_mass(npz, atm(n)%ncnst, isc, iec, jsc, jec, atm(n)%ng, max(1,atm(n)%flagstruct%nwat), &
828  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
829 #else
830  call prt_mass(npz, atm(n)%ncnst, isc, iec, jsc, jec, atm(n)%ng, atm(n)%flagstruct%nwat, &
831  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
832 #endif
833 
834  call nullify_domain() ! Nullify set_domain info
835 
836  module_is_initialized=.true.
837  istep = 0
838  end subroutine fv_diag_init
839 
840 
841  subroutine init_mq(phis, gridstruct, npx, npy, is, ie, js, je, ng)
842  integer, intent(in):: npx, npy, is, ie, js, je, ng
843  real, intent(in):: phis(is-ng:ie+ng, js-ng:je+ng)
844  type(fv_grid_type), intent(IN), target :: gridstruct
845 
846 ! local:
847  real zs(is-ng:ie+ng, js-ng:je+ng)
848  real zb(is-ng:ie+ng, js-ng:je+ng)
849  real pdx(3,is:ie,js:je+1)
850  real pdy(3,is:ie+1,js:je)
851  integer i, j, n
852 
853  real, pointer :: rarea(:,:)
854  real, pointer, dimension(:,:) :: dx, dy
855  real(kind=R_GRID), pointer, dimension(:,:,:) :: en1, en2, vlon, vlat
856  real, pointer, dimension(:,:,:) :: agrid
857 
858  rarea => gridstruct%rarea
859  dx => gridstruct%dx
860  dy => gridstruct%dy
861  en1 => gridstruct%en1
862  en2 => gridstruct%en2
863  agrid => gridstruct%agrid
864  vlon => gridstruct%vlon
865  vlat => gridstruct%vlat
866 
867 ! do j=js,je
868 ! do i=is,ie
869  do j=js-ng,je+ng
870  do i=is-ng,ie+ng
871  zs(i,j) = phis(i,j) / grav
872  enddo
873  enddo
874 ! call mpp_update_domains( zs, domain )
875 
876 ! call a2b_ord2(zs, zb, gridstruct, npx, npy, is, ie, js, je, ng)
877  call a2b_ord4(zs, zb, gridstruct, npx, npy, is, ie, js, je, ng)
878 
879  do j=js,je+1
880  do i=is,ie
881  do n=1,3
882  pdx(n,i,j) = 0.5*(zb(i,j)+zb(i+1,j))*dx(i,j)*en1(n,i,j)
883  enddo
884  enddo
885  enddo
886  do j=js,je
887  do i=is,ie+1
888  do n=1,3
889  pdy(n,i,j) = 0.5*(zb(i,j)+zb(i,j+1))*dy(i,j)*en2(n,i,j)
890  enddo
891  enddo
892  enddo
893 
894 ! Compute "volume-mean" gradient by Green's theorem
895  do j=js,je
896  do i=is,ie
897  idiag%zxg(i,j) = vlon(i,j,1)*(pdx(1,i,j+1)-pdx(1,i,j)-pdy(1,i,j)+pdy(1,i+1,j)) &
898  + vlon(i,j,2)*(pdx(2,i,j+1)-pdx(2,i,j)-pdy(2,i,j)+pdy(2,i+1,j)) &
899  + vlon(i,j,3)*(pdx(3,i,j+1)-pdx(3,i,j)-pdy(3,i,j)+pdy(3,i+1,j))
900 ! dF/d(lamda) = radius*cos(agrid(i,j,2)) * dF/dx, F is a scalar
901 ! ________________________
902  idiag%zxg(i,j) = idiag%zxg(i,j)*rarea(i,j) * radius*cos(agrid(i,j,2))
903 ! ^^^^^^^^^^^^^^^^^^^^^^^^
904  enddo
905  enddo
906 
907  end subroutine init_mq
908 
909  subroutine fv_diag(Atm, zvir, Time, print_freq)
911  type(fv_atmos_type), intent(inout) :: atm(:)
912  type(time_type), intent(in) :: time
913  real, intent(in):: zvir
914  integer, intent(in):: print_freq
915 
916  integer :: isc, iec, jsc, jec, n, ntileme
917  integer :: isd, ied, jsd, jed, npz, itrac
918  integer :: ngc, nwater
919 
920  real, allocatable :: a2(:,:),a3(:,:,:), wk(:,:,:), wz(:,:,:), ucoor(:,:,:), vcoor(:,:,:)
921  real, allocatable :: slp(:,:), depress(:,:), ws_max(:,:), tc_count(:,:)
922  real, allocatable :: u2(:,:), v2(:,:), x850(:,:), var1(:,:), var2(:,:), var3(:,:)
923  real, allocatable :: dmmr(:,:,:), dvmr(:,:,:)
924  real height(2)
925  real:: plevs(nplev), pout(nplev)
926  integer:: idg(nplev), id1(nplev)
927  real :: tot_mq, tmp, sar, slon, slat
928  real :: t_gb, t_nh, t_sh, t_eq, area_gb, area_nh, area_sh, area_eq
929  logical :: do_cs_intp
930  logical :: used
931  logical :: bad_range
932  integer i,j,k, yr, mon, dd, hr, mn, days, seconds, nq, theta_d
933  character(len=128) :: tname
934  real, parameter:: ws_0 = 16. ! minimum max_wind_speed within the 7x7 search box
935  real, parameter:: ws_1 = 20.
936  real, parameter:: vort_c0= 2.2e-5
937  logical, allocatable :: storm(:,:), cat_crt(:,:)
938  real :: tmp2, pvsum, e2, einf, qm, mm, maxdbz, allmax, rgrav
939  integer :: cl, cl2
940 
941  !!! CLEANUP: does it really make sense to have this routine loop over Atm% anymore? We assume n=1 below anyway
942 
943 ! cat15: SLP<1000; srf_wnd>ws_0; vort>vort_c0
944 ! cat25: SLP< 980; srf_wnd>ws_1; vort>vort_c0
945 ! cat35: SLP< 964; srf_wnd>ws_1; vort>vort_c0
946 ! cat45: SLP< 944; srf_wnd>ws_1; vort>vort_c0
947 
948  height(1) = 5.e3 ! for computing 5-km "pressure"
949  height(2) = 0. ! for sea-level pressure
950 
951  do i=1,nplev
952  pout(i) = levs(i) * 1.e2
953  plevs(i) = log( pout(i) )
954  enddo
955 
956  ntileme = size(atm(:))
957  n = 1
958  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
959  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
960  ngc = atm(n)%ng
961  npz = atm(n)%npz
962  ptop = atm(n)%ak(1)
963  nq = size (atm(n)%q,4)
964 
965  isd = atm(n)%bd%isd; ied = atm(n)%bd%ied
966  jsd = atm(n)%bd%jsd; jed = atm(n)%bd%jed
967 
968  if( idiag%id_c15>0 ) then
969  allocate ( storm(isc:iec,jsc:jec) )
970  allocate ( depress(isc:iec,jsc:jec) )
971  allocate ( ws_max(isc:iec,jsc:jec) )
972  allocate ( cat_crt(isc:iec,jsc:jec) )
973  allocate (tc_count(isc:iec,jsc:jec) )
974  endif
975 
976  if( idiag%id_x850>0 ) then
977  allocate ( x850(isc:iec,jsc:jec) )
978  endif
979 
980  fv_time = time
981  call set_domain(atm(1)%domain)
982 
983  if ( m_calendar ) then
984  call get_date(fv_time, yr, mon, dd, hr, mn, seconds)
985  if( print_freq == 0 ) then
986  prt_minmax = .false.
987  elseif( print_freq < 0 ) then
988  istep = istep + 1
989  prt_minmax = mod(istep, -print_freq) == 0
990  else
991  prt_minmax = mod(hr, print_freq) == 0 .and. mn==0 .and. seconds==0
992  endif
993  else
994  call get_time (fv_time, seconds, days)
995  if( print_freq == 0 ) then
996  prt_minmax = .false.
997  elseif( print_freq < 0 ) then
998  istep = istep + 1
999  prt_minmax = mod(istep, -print_freq) == 0
1000  else
1001  prt_minmax = mod(seconds, 3600*print_freq) == 0
1002  endif
1003  endif
1004 
1005  if(prt_minmax) then
1006  if ( m_calendar ) then
1007  if(master) write(*,*) yr, mon, dd, hr, mn, seconds
1008  else
1009  if(master) write(*,*) days, seconds
1010  endif
1011  endif
1012 
1013  allocate ( a2(isc:iec,jsc:jec) )
1014 
1015  if( prt_minmax ) then
1016 
1017  call prt_mxm('ZS', idiag%zsurf, isc, iec, jsc, jec, 0, 1, 1.0, atm(n)%gridstruct%area_64, atm(n)%domain)
1018  call prt_maxmin('PS', atm(n)%ps, isc, iec, jsc, jec, ngc, 1, 0.01)
1019 
1020 #ifdef HIWPP
1021  allocate(var2(isc:iec,jsc:jec))
1022  !hemispheric max/min pressure
1023  do j=jsc,jec
1024  do i=isc,iec
1025  slat = rad2deg*atm(n)%gridstruct%agrid(i,j,2)
1026  if (slat >= 0.) then
1027  a2(i,j) = atm(n)%ps(i,j)
1028  var2(i,j) = 101300.
1029  else
1030  a2(i,j) = 101300.
1031  var2(i,j) = atm(n)%ps(i,j)
1032  endif
1033  enddo
1034  enddo
1035  call prt_maxmin('NH PS', a2, isc, iec, jsc, jec, 0, 1, 0.01)
1036  call prt_maxmin('SH PS', var2, isc, iec, jsc, jec, 0, 1, 0.01)
1037 
1038  deallocate(var2)
1039 #endif
1040 
1041 #ifdef TEST_TRACER
1042  call prt_mass(npz, nq, isc, iec, jsc, jec, ngc, max(1,atm(n)%flagstruct%nwat), &
1043  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
1044 #else
1045  call prt_mass(npz, nq, isc, iec, jsc, jec, ngc, atm(n)%flagstruct%nwat, &
1046  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
1047 #endif
1048 
1049 #ifndef MAPL_MODE
1050 #ifndef SW_DYNAMICS
1051  if (atm(n)%flagstruct%consv_te > 1.e-5) then
1052  idiag%steps = idiag%steps + 1
1053  idiag%efx_sum = idiag%efx_sum + e_flux
1054  if ( idiag%steps <= max_step ) idiag%efx(idiag%steps) = e_flux
1055  if (master) then
1056  write(*,*) 'ENG Deficit (W/m**2)', trim(gn), '=', e_flux
1057  endif
1058 
1059 
1060  endif
1061  if ( .not. atm(n)%flagstruct%hydrostatic ) &
1062  call nh_total_energy(isc, iec, jsc, jec, isd, ied, jsd, jed, npz, &
1063  atm(n)%w, atm(n)%delz, atm(n)%pt, atm(n)%delp, &
1064  atm(n)%q, atm(n)%phis, atm(n)%gridstruct%area, atm(n)%domain, &
1065  sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, atm(n)%flagstruct%nwat, &
1066  atm(n)%ua, atm(n)%va, atm(n)%flagstruct%moist_phys, a2)
1067 #endif
1068 #endif
1069  call prt_maxmin('UA_top', atm(n)%ua(isc:iec,jsc:jec,1), &
1070  isc, iec, jsc, jec, 0, 1, 1.)
1071  call prt_maxmin('UA', atm(n)%ua, isc, iec, jsc, jec, ngc, npz, 1.)
1072  call prt_maxmin('VA', atm(n)%va, isc, iec, jsc, jec, ngc, npz, 1.)
1073 
1074  if ( .not. atm(n)%flagstruct%hydrostatic ) then
1075  call prt_maxmin('W ', atm(n)%w , isc, iec, jsc, jec, ngc, npz, 1.)
1076  call prt_maxmin('Bottom w', atm(n)%w(isc:iec,jsc:jec,npz), isc, iec, jsc, jec, 0, 1, 1.)
1077  do j=jsc,jec
1078  do i=isc,iec
1079  a2(i,j) = -atm(n)%w(i,j,npz)/atm(n)%delz(i,j,npz)
1080  enddo
1081  enddo
1082  call prt_maxmin('Bottom: w/dz', a2, isc, iec, jsc, jec, 0, 1, 1.)
1083 
1084  if ( atm(n)%flagstruct%hybrid_z ) call prt_maxmin('Hybrid_ZTOP (km)', atm(n)%ze0(isc:iec,jsc:jec,1), &
1085  isc, iec, jsc, jec, 0, 1, 1.e-3)
1086  call prt_maxmin('DZ (m)', atm(n)%delz(isc:iec,jsc:jec,1:npz), &
1087  isc, iec, jsc, jec, 0, npz, 1.)
1088  call prt_maxmin('Bottom DZ (m)', atm(n)%delz(isc:iec,jsc:jec,npz), &
1089  isc, iec, jsc, jec, 0, 1, 1.)
1090 ! call prt_maxmin('Top DZ (m)', Atm(n)%delz(isc:iec,jsc:jec,1), &
1091 ! isc, iec, jsc, jec, 0, 1, 1.)
1092  endif
1093 
1094 #ifndef SW_DYNAMICS
1095  call prt_maxmin('TA', atm(n)%pt, isc, iec, jsc, jec, ngc, npz, 1.)
1096 ! call prt_maxmin('Top: TA', Atm(n)%pt(isc:iec,jsc:jec, 1), isc, iec, jsc, jec, 0, 1, 1.)
1097 ! call prt_maxmin('Bot: TA', Atm(n)%pt(isc:iec,jsc:jec,npz), isc, iec, jsc, jec, 0, 1, 1.)
1098  call prt_maxmin('OM', atm(n)%omga, isc, iec, jsc, jec, ngc, npz, 1.)
1099 #endif
1100 
1101  elseif ( atm(n)%flagstruct%range_warn ) then
1102  call range_check('DELP', atm(n)%delp, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1103  0.01*ptop, 200.e2, bad_range)
1104  call range_check('UA', atm(n)%ua, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1105  -250., 250., bad_range)
1106  call range_check('VA', atm(n)%va, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1107  -250., 250., bad_range)
1108 #ifndef SW_DYNAMICS
1109  call range_check('TA', atm(n)%pt, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1110 #ifdef HIWPP
1111  130., 350., bad_range) !DCMIP ICs have very low temperatures
1112 #else
1113  150., 350., bad_range)
1114 #endif
1115 #endif
1116 
1117  endif
1118 
1119  allocate ( u2(isc:iec,jsc:jec) )
1120  allocate ( v2(isc:iec,jsc:jec) )
1121  allocate ( wk(isc:iec,jsc:jec,npz) )
1122  if ( any(idiag%id_tracer_dmmr > 0) .or. any(idiag%id_tracer_dvmr > 0) ) then
1123  allocate ( dmmr(isc:iec,jsc:jec,1:npz) )
1124  allocate ( dvmr(isc:iec,jsc:jec,1:npz) )
1125  endif
1126 
1127 ! do n = 1, ntileMe
1128  n = 1
1129 
1130 #ifdef DYNAMICS_ZS
1131  if(idiag%id_zsurf > 0) used=send_data(idiag%id_zsurf, idiag%zsurf, time)
1132 #endif
1133  if(idiag%id_ps > 0) used=send_data(idiag%id_ps, atm(n)%ps(isc:iec,jsc:jec), time)
1134 
1135  if(idiag%id_c15>0 .or. idiag%id_c25>0 .or. idiag%id_c35>0 .or. idiag%id_c45>0) then
1136  call wind_max(isc, iec, jsc, jec ,isd, ied, jsd, jed, atm(n)%ua(isc:iec,jsc:jec,npz), &
1137  atm(n)%va(isc:iec,jsc:jec,npz), ws_max, atm(n)%domain)
1138  do j=jsc,jec
1139  do i=isc,iec
1140  if( abs(atm(n)%gridstruct%agrid(i,j,2)*rad2deg)<45.0 .and. &
1141  atm(n)%phis(i,j)*ginv<500.0 .and. ws_max(i,j)>ws_0 ) then
1142  storm(i,j) = .true.
1143  else
1144  storm(i,j) = .false.
1145  endif
1146  enddo
1147  enddo
1148  endif
1149 
1150  if ( idiag%id_vort200>0 .or. idiag%id_vort500>0 .or. idiag%id_vort850>0 .or. idiag%id_vorts>0 &
1151  .or. idiag%id_vort>0 .or. idiag%id_pv>0 .or. idiag%id_rh>0 .or. idiag%id_x850>0 .or. &
1152  idiag%id_uh03>0 .or. idiag%id_uh25>0) then
1153  call get_vorticity(isc, iec, jsc, jec, isd, ied, jsd, jed, npz, atm(n)%u, atm(n)%v, wk, &
1154  atm(n)%gridstruct%dx, atm(n)%gridstruct%dy, atm(n)%gridstruct%rarea)
1155 
1156  if(idiag%id_vort >0) used=send_data(idiag%id_vort, wk, time)
1157  if(idiag%id_vorts>0) used=send_data(idiag%id_vorts, wk(isc:iec,jsc:jec,npz), time)
1158 
1159  if(idiag%id_c15>0) then
1160  do j=jsc,jec
1161  do i=isc,iec
1162  if ( storm(i,j) ) &
1163  storm(i,j) = (atm(n)%gridstruct%agrid(i,j,2)>0. .and. wk(i,j,npz)> vort_c0) .or. &
1164  (atm(n)%gridstruct%agrid(i,j,2)<0. .and. wk(i,j,npz)<-vort_c0)
1165  enddo
1166  enddo
1167  endif
1168 
1169  if( idiag%id_vort200>0 ) then
1170  call interpolate_vertical(isc, iec, jsc, jec, npz, &
1171  200.e2, atm(n)%peln, wk, a2)
1172  used=send_data(idiag%id_vort200, a2, time)
1173  endif
1174  if( idiag%id_vort500>0 ) then
1175  call interpolate_vertical(isc, iec, jsc, jec, npz, &
1176  500.e2, atm(n)%peln, wk, a2)
1177  used=send_data(idiag%id_vort500, a2, time)
1178  endif
1179 
1180  if(idiag%id_vort850>0 .or. idiag%id_c15>0 .or. idiag%id_x850>0) then
1181  call interpolate_vertical(isc, iec, jsc, jec, npz, &
1182  850.e2, atm(n)%peln, wk, a2)
1183  used=send_data(idiag%id_vort850, a2, time)
1184  if ( idiag%id_x850>0 ) x850(:,:) = a2(:,:)
1185 
1186  if(idiag%id_c15>0) then
1187  do j=jsc,jec
1188  do i=isc,iec
1189  if ( storm(i,j) ) &
1190  storm(i,j) = (atm(n)%gridstruct%agrid(i,j,2)>0. .and. a2(i,j)> vort_c0) .or. &
1191  (atm(n)%gridstruct%agrid(i,j,2)<0. .and. a2(i,j)<-vort_c0)
1192  enddo
1193  enddo
1194  endif
1195 
1196  endif
1197 
1198  if( .not. atm(n)%flagstruct%hydrostatic ) then
1199 
1200  if ( idiag%id_uh03 > 0 ) then
1201  call updraft_helicity(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1202  atm(n)%w, wk, atm(n)%delz, atm(n)%q, &
1203  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 0., 3.e3)
1204  used = send_data( idiag%id_uh03, a2, time )
1205  if(prt_minmax) then
1206  do j=jsc,jec
1207  do i=isc,iec
1208  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
1209  tmp2 = rad2deg * atm(n)%gridstruct%agrid(i,j,2)
1210  if ( tmp2<25. .or. tmp2>50. &
1211  .or. tmp<235. .or. tmp>300. ) then
1212  a2(i,j) = 0.
1213  endif
1214  enddo
1215  enddo
1216  call prt_maxmin('UH over CONUS', a2, isc, iec, jsc, jec, 0, 1, 1.)
1217  endif
1218  endif
1219  if ( idiag%id_uh25 > 0 ) then
1220  call updraft_helicity(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1221  atm(n)%w, wk, atm(n)%delz, atm(n)%q, &
1222  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 2.e3, 5.e3)
1223  used = send_data( idiag%id_uh25, a2, time )
1224  endif
1225  endif
1226 
1227 
1228  if ( idiag%id_pv > 0 ) then
1229 ! Note: this is expensive computation.
1230  call pv_entropy(isc, iec, jsc, jec, ngc, npz, wk, &
1231  atm(n)%gridstruct%f0, atm(n)%pt, atm(n)%pkz, atm(n)%delp, grav)
1232  used = send_data( idiag%id_pv, wk, time )
1233  if (prt_minmax) call prt_maxmin('PV', wk, isc, iec, jsc, jec, 0, 1, 1.)
1234  endif
1235 
1236  endif
1237 
1238 
1239 
1240  if ( idiag%id_srh > 0 ) then
1241  call helicity_relative(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1242  atm(n)%ua, atm(n)%va, atm(n)%delz, atm(n)%q, &
1243  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 0., 3.e3)
1244  used = send_data( idiag%id_srh, a2, time )
1245  if(prt_minmax) then
1246  do j=jsc,jec
1247  do i=isc,iec
1248  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
1249  tmp2 = rad2deg * atm(n)%gridstruct%agrid(i,j,2)
1250  if ( tmp2<25. .or. tmp2>50. &
1251  .or. tmp<235. .or. tmp>300. ) then
1252  a2(i,j) = 0.
1253  endif
1254  enddo
1255  enddo
1256  call prt_maxmin('SRH over CONUS', a2, isc, iec, jsc, jec, 0, 1, 1.)
1257  endif
1258  endif
1259 
1260  if ( idiag%id_srh25 > 0 ) then
1261  call helicity_relative(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1262  atm(n)%ua, atm(n)%va, atm(n)%delz, atm(n)%q, &
1263  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 2.e3, 5.e3)
1264  used = send_data( idiag%id_srh25, a2, time )
1265  endif
1266  if ( idiag%id_srh01 > 0 ) then
1267  call helicity_relative(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1268  atm(n)%ua, atm(n)%va, atm(n)%delz, atm(n)%q, &
1269  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 0.e3, 1.e3)
1270  used = send_data( idiag%id_srh01, a2, time )
1271  endif
1272 
1273 
1274  ! Relative Humidity
1275  if ( idiag%id_rh > 0 ) then
1276  ! Compute FV mean pressure
1277  do k=1,npz
1278  do j=jsc,jec
1279  do i=isc,iec
1280  a2(i,j) = atm(n)%delp(i,j,k)/(atm(n)%peln(i,k+1,j)-atm(n)%peln(i,k,j))
1281  enddo
1282  enddo
1283  call qsmith(iec-isc+1, jec-jsc+1, 1, atm(n)%pt(isc:iec,jsc:jec,k), &
1284  a2, atm(n)%q(isc:iec,jsc:jec,k,sphum), wk(isc,jsc,k))
1285  do j=jsc,jec
1286  do i=isc,iec
1287  wk(i,j,k) = 100.*atm(n)%q(i,j,k,sphum)/wk(i,j,k)
1288  enddo
1289  enddo
1290  enddo
1291  used = send_data( idiag%id_rh, wk, time )
1292  if(prt_minmax) then
1293  call prt_maxmin('RH_sf (%)', wk(isc:iec,jsc:jec,npz), isc, iec, jsc, jec, 0, 1, 1.)
1294  call prt_maxmin('RH_3D (%)', wk, isc, iec, jsc, jec, 0, npz, 1.)
1295  endif
1296  endif
1297 
1298  ! rel hum from physics at selected press levels (for IPCC)
1299  if (idiag%id_rh50>0 .or. idiag%id_rh100>0 .or. idiag%id_rh200>0 .or. idiag%id_rh250>0 .or. &
1300  idiag%id_rh300>0 .or. idiag%id_rh500>0 .or. idiag%id_rh700>0 .or. idiag%id_rh850>0 .or. &
1301  idiag%id_rh925>0 .or. idiag%id_rh1000>0) then
1302  ! compute mean pressure
1303  do k=1,npz
1304  do j=jsc,jec
1305  do i=isc,iec
1306  a2(i,j) = atm(n)%delp(i,j,k)/(atm(n)%peln(i,k+1,j)-atm(n)%peln(i,k,j))
1307  enddo
1308  enddo
1309  call rh_calc (a2, atm(n)%pt(isc:iec,jsc:jec,k), &
1310  atm(n)%q(isc:iec,jsc:jec,k,sphum), wk(isc:iec,jsc:jec,k))
1311  enddo
1312  if (idiag%id_rh50>0) then
1313  call interpolate_vertical(isc, iec, jsc, jec, npz, 50.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1314  used=send_data(idiag%id_rh50, a2, time)
1315  endif
1316  if (idiag%id_rh100>0) then
1317  call interpolate_vertical(isc, iec, jsc, jec, npz, 100.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1318  used=send_data(idiag%id_rh100, a2, time)
1319  endif
1320  if (idiag%id_rh200>0) then
1321  call interpolate_vertical(isc, iec, jsc, jec, npz, 200.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1322  used=send_data(idiag%id_rh200, a2, time)
1323  endif
1324  if (idiag%id_rh250>0) then
1325  call interpolate_vertical(isc, iec, jsc, jec, npz, 250.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1326  used=send_data(idiag%id_rh250, a2, time)
1327  endif
1328  if (idiag%id_rh300>0) then
1329  call interpolate_vertical(isc, iec, jsc, jec, npz, 300.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1330  used=send_data(idiag%id_rh300, a2, time)
1331  endif
1332  if (idiag%id_rh500>0) then
1333  call interpolate_vertical(isc, iec, jsc, jec, npz, 500.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1334  used=send_data(idiag%id_rh500, a2, time)
1335  endif
1336  if (idiag%id_rh700>0) then
1337  call interpolate_vertical(isc, iec, jsc, jec, npz, 700.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1338  used=send_data(idiag%id_rh700, a2, time)
1339  endif
1340  if (idiag%id_rh850>0) then
1341  call interpolate_vertical(isc, iec, jsc, jec, npz, 850.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1342  used=send_data(idiag%id_rh850, a2, time)
1343  endif
1344  if (idiag%id_rh925>0) then
1345  call interpolate_vertical(isc, iec, jsc, jec, npz, 925.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1346  used=send_data(idiag%id_rh925, a2, time)
1347  endif
1348  if (idiag%id_rh1000>0) then
1349  call interpolate_vertical(isc, iec, jsc, jec, npz, 1000.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1350  used=send_data(idiag%id_rh1000, a2, time)
1351  endif
1352  endif
1353 
1354  ! rel hum (CMIP definition) at selected press levels (for IPCC)
1355  if (idiag%id_rh10_cmip>0 .or. idiag%id_rh50_cmip>0 .or. idiag%id_rh100_cmip>0 .or. &
1356  idiag%id_rh250_cmip>0 .or. idiag%id_rh300_cmip>0 .or. idiag%id_rh500_cmip>0 .or. &
1357  idiag%id_rh700_cmip>0 .or. idiag%id_rh850_cmip>0 .or. idiag%id_rh925_cmip>0 .or. &
1358  idiag%id_rh1000_cmip>0) then
1359  ! compute mean pressure
1360  do k=1,npz
1361  do j=jsc,jec
1362  do i=isc,iec
1363  a2(i,j) = atm(n)%delp(i,j,k)/(atm(n)%peln(i,k+1,j)-atm(n)%peln(i,k,j))
1364  enddo
1365  enddo
1366  call rh_calc (a2, atm(n)%pt(isc:iec,jsc:jec,k), &
1367  atm(n)%q(isc:iec,jsc:jec,k,sphum), wk(isc:iec,jsc:jec,k), do_cmip=.true.)
1368  enddo
1369  if (idiag%id_rh10_cmip>0) then
1370  call interpolate_vertical(isc, iec, jsc, jec, npz, 10.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1371  used=send_data(idiag%id_rh10_cmip, a2, time)
1372  endif
1373  if (idiag%id_rh50_cmip>0) then
1374  call interpolate_vertical(isc, iec, jsc, jec, npz, 50.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1375  used=send_data(idiag%id_rh50_cmip, a2, time)
1376  endif
1377  if (idiag%id_rh100_cmip>0) then
1378  call interpolate_vertical(isc, iec, jsc, jec, npz, 100.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1379  used=send_data(idiag%id_rh100_cmip, a2, time)
1380  endif
1381  if (idiag%id_rh250_cmip>0) then
1382  call interpolate_vertical(isc, iec, jsc, jec, npz, 250.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1383  used=send_data(idiag%id_rh250_cmip, a2, time)
1384  endif
1385  if (idiag%id_rh300_cmip>0) then
1386  call interpolate_vertical(isc, iec, jsc, jec, npz, 300.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1387  used=send_data(idiag%id_rh300_cmip, a2, time)
1388  endif
1389  if (idiag%id_rh500_cmip>0) then
1390  call interpolate_vertical(isc, iec, jsc, jec, npz, 500.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1391  used=send_data(idiag%id_rh500_cmip, a2, time)
1392  endif
1393  if (idiag%id_rh700_cmip>0) then
1394  call interpolate_vertical(isc, iec, jsc, jec, npz, 700.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1395  used=send_data(idiag%id_rh700_cmip, a2, time)
1396  endif
1397  if (idiag%id_rh850_cmip>0) then
1398  call interpolate_vertical(isc, iec, jsc, jec, npz, 850.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1399  used=send_data(idiag%id_rh850_cmip, a2, time)
1400  endif
1401  if (idiag%id_rh925_cmip>0) then
1402  call interpolate_vertical(isc, iec, jsc, jec, npz, 925.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1403  used=send_data(idiag%id_rh925_cmip, a2, time)
1404  endif
1405  if (idiag%id_rh1000_cmip>0) then
1406  call interpolate_vertical(isc, iec, jsc, jec, npz, 1000.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1407  used=send_data(idiag%id_rh1000_cmip, a2, time)
1408  endif
1409  endif
1410 
1411  if(idiag%id_c25>0 .or. idiag%id_c35>0 .or. idiag%id_c45>0) then
1412  do j=jsc,jec
1413  do i=isc,iec
1414  if ( storm(i,j) .and. ws_max(i,j)>ws_1 ) then
1415  cat_crt(i,j) = .true.
1416  else
1417  cat_crt(i,j) = .false.
1418  endif
1419  enddo
1420  enddo
1421  endif
1422 
1423 
1424 
1425  if( idiag%id_slp>0 .or. idiag%id_tm>0 .or. idiag%id_hght>0 .or. idiag%id_c15>0 ) then
1426 
1427  allocate ( wz(isc:iec,jsc:jec,npz+1) )
1428  call get_height_field(isc, iec, jsc, jec, ngc, npz, atm(n)%flagstruct%hydrostatic, atm(n)%delz, &
1429  wz, atm(n)%pt, atm(n)%q, atm(n)%peln, zvir)
1430  if( prt_minmax ) &
1431  call prt_mxm('ZTOP',wz(isc:iec,jsc:jec,1), isc, iec, jsc, jec, 0, 1, 1.e-3, atm(n)%gridstruct%area_64, atm(n)%domain)
1432 ! call prt_maxmin('ZTOP', wz(isc:iec,jsc:jec,1), isc, iec, jsc, jec, 0, 1, 1.E-3)
1433 
1434  if(idiag%id_slp > 0) then
1435 ! Cumpute SLP (pressure at height=0)
1436  allocate ( slp(isc:iec,jsc:jec) )
1437  call get_pressure_given_height(isc, iec, jsc, jec, ngc, npz, wz, 1, height(2), &
1438  atm(n)%pt(:,:,npz), atm(n)%peln, slp, 0.01)
1439  used = send_data(idiag%id_slp, slp, time)
1440  if( prt_minmax ) then
1441  call prt_maxmin('SLP', slp, isc, iec, jsc, jec, 0, 1, 1.)
1442 ! US Potential Landfall TCs (PLT):
1443  do j=jsc,jec
1444  do i=isc,iec
1445  a2(i,j) = 1015.
1446  slon = rad2deg*atm(n)%gridstruct%agrid(i,j,1)
1447  slat = rad2deg*atm(n)%gridstruct%agrid(i,j,2)
1448  if ( slat>15. .and. slat<40. .and. slon>270. .and. slon<290. ) then
1449  a2(i,j) = slp(i,j)
1450  endif
1451  enddo
1452  enddo
1453  call prt_maxmin('ATL SLP', a2, isc, iec, jsc, jec, 0, 1, 1.)
1454  endif
1455  endif
1456 
1457 ! Compute H3000 and/or H500
1458  if( idiag%id_tm>0 .or. idiag%id_hght>0 .or. idiag%id_ppt>0) then
1459 
1460  allocate( a3(isc:iec,jsc:jec,nplev) )
1461 
1462  idg(:) = idiag%id_h(:)
1463 
1464  if ( idiag%id_tm>0 ) then
1465  idg(minloc(abs(levs-300))) = 1 ! 300-mb
1466  idg(minloc(abs(levs-500))) = 1 ! 500-mb
1467  else
1468  idg(minloc(abs(levs-300))) = idiag%id_h(minloc(abs(levs-300)))
1469  idg(minloc(abs(levs-500))) = idiag%id_h(minloc(abs(levs-500)))
1470  endif
1471 
1472  call get_height_given_pressure(isc, iec, jsc, jec, ngc, npz, wz, nplev, idg, plevs, atm(n)%peln, a3)
1473  ! reset
1474  idg(minloc(abs(levs-300))) = idiag%id_h(minloc(abs(levs-300)))
1475  idg(minloc(abs(levs-500))) = idiag%id_h(minloc(abs(levs-500)))
1476 
1477  do i=1,nplev
1478  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
1479  enddo
1480 
1481  if (idiag%id_h_plev>0) then
1482  id1(:) = 1
1483  call get_height_given_pressure(isc, iec, jsc, jec, ngc, npz, wz, nplev, id1, plevs, atm(n)%peln, a3)
1484  used=send_data(idiag%id_h_plev, a3(isc:iec,jsc:jec,:), time)
1485  endif
1486 
1487  if( prt_minmax ) then
1488 
1489  if(all(idiag%id_h(minloc(abs(levs-100)))>0)) &
1490  call prt_mxm('Z100',a3(isc:iec,jsc:jec,11),isc,iec,jsc,jec,0,1,1.e-3,atm(n)%gridstruct%area_64,atm(n)%domain)
1491 
1492  if(all(idiag%id_h(minloc(abs(levs-500)))>0)) then
1493 ! call prt_mxm('Z500',a3(isc:iec,jsc:jec,19),isc,iec,jsc,jec,0,1,1.,Atm(n)%gridstruct%area_64,Atm(n)%domain)
1494  if (.not. atm(n)%neststruct%nested) then
1495  t_eq = 0. ; t_nh = 0.; t_sh = 0.; t_gb = 0.
1496  area_eq = 0.; area_nh = 0.; area_sh = 0.; area_gb = 0.
1497  do j=jsc,jec
1498  do i=isc,iec
1499  slat = atm(n)%gridstruct%agrid(i,j,2)*rad2deg
1500  area_gb = area_gb + atm(n)%gridstruct%area(i,j)
1501  t_gb = t_gb + a3(i,j,19)*atm(n)%gridstruct%area(i,j)
1502  if( (slat>-20. .and. slat<20.) ) then
1503 ! Tropics:
1504  area_eq = area_eq + atm(n)%gridstruct%area(i,j)
1505  t_eq = t_eq + a3(i,j,19)*atm(n)%gridstruct%area(i,j)
1506  elseif( slat>=20. .and. slat<80. ) then
1507 ! NH
1508  area_nh = area_nh + atm(n)%gridstruct%area(i,j)
1509  t_nh = t_nh + a3(i,j,19)*atm(n)%gridstruct%area(i,j)
1510  elseif( slat<=-20. .and. slat>-80. ) then
1511 ! SH
1512  area_sh = area_sh + atm(n)%gridstruct%area(i,j)
1513  t_sh = t_sh + a3(i,j,19)*atm(n)%gridstruct%area(i,j)
1514  endif
1515  enddo
1516  enddo
1517  call mp_reduce_sum(area_gb)
1518  call mp_reduce_sum( t_gb)
1519  call mp_reduce_sum(area_nh)
1520  call mp_reduce_sum( t_nh)
1521  call mp_reduce_sum(area_sh)
1522  call mp_reduce_sum( t_sh)
1523  call mp_reduce_sum(area_eq)
1524  call mp_reduce_sum( t_eq)
1525  if (master) write(*,*) 'Z500 GB_NH_SH_EQ=', t_gb/area_gb, t_nh/area_nh, t_sh/area_sh, t_eq/area_eq
1526  endif
1527  endif
1528 
1529  endif
1530 
1531  ! mean virtual temp 300mb to 500mb
1532  if( idiag%id_tm>0 ) then
1533  do j=jsc,jec
1534  do i=isc,iec
1535  a2(i,j) = grav*(a3(i,j,15)-a3(i,j,19))/(rdgas*(plevs(19)-plevs(15)))
1536  enddo
1537  enddo
1538  used = send_data( idiag%id_tm, a2, time )
1539  endif
1540 
1541  if(idiag%id_c15>0 .or. idiag%id_c25>0 .or. idiag%id_c35>0 .or. idiag%id_c45>0) then
1542  do j=jsc,jec
1543  do i=isc,iec
1544 ! Minimum warm core:
1545  if ( storm(i,j) ) then
1546  if( a2(i,j)<254.0 .or. atm(n)%pt(i,j,npz)<281.0 ) Then
1547  storm(i,j) = .false.
1548  cat_crt(i,j) = .false.
1549  endif
1550  endif
1551  enddo
1552  enddo
1553 ! Cat 1-5:
1554  do j=jsc,jec
1555  do i=isc,iec
1556  if ( storm(i,j) .and. slp(i,j)<1000.0 ) then
1557  depress(i,j) = 1000. - slp(i,j)
1558  tc_count(i,j) = 1.
1559  else
1560  depress(i,j) = 0.
1561  tc_count(i,j) = 0.
1562  endif
1563  enddo
1564  enddo
1565  used = send_data(idiag%id_c15, depress, time)
1566  if(idiag%id_f15>0) used = send_data(idiag%id_f15, tc_count, time)
1567  if(prt_minmax) then
1568  do j=jsc,jec
1569  do i=isc,iec
1570  slon = rad2deg*atm(n)%gridstruct%agrid(i,j,1)
1571  slat = rad2deg*atm(n)%gridstruct%agrid(i,j,2)
1572 ! Western Pac: negative; positive elsewhere
1573  if ( slat>0. .and. slat<40. .and. slon>110. .and. slon<180. ) then
1574  depress(i,j) = -depress(i,j)
1575  endif
1576  enddo
1577  enddo
1578  call prt_maxmin('Depress', depress, isc, iec, jsc, jec, 0, 1, 1.)
1579  do j=jsc,jec
1580  do i=isc,iec
1581  if ( atm(n)%gridstruct%agrid(i,j,2)<0.) then
1582 ! Excluding the SH cyclones
1583  depress(i,j) = 0.
1584  endif
1585  enddo
1586  enddo
1587  call prt_maxmin('NH Deps', depress, isc, iec, jsc, jec, 0, 1, 1.)
1588 
1589 ! ATL basin cyclones
1590  do j=jsc,jec
1591  do i=isc,iec
1592  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
1593  if ( tmp<280. ) then
1594  depress(i,j) = 0.
1595  endif
1596  enddo
1597  enddo
1598  call prt_maxmin('ATL Deps', depress, isc, iec, jsc, jec, 0, 1, 1.)
1599  endif
1600  endif
1601 
1602 ! Cat 2-5:
1603  if(idiag%id_c25>0) then
1604  do j=jsc,jec
1605  do i=isc,iec
1606  if ( cat_crt(i,j) .and. slp(i,j)<980.0 ) then
1607  depress(i,j) = 980. - slp(i,j)
1608  tc_count(i,j) = 1.
1609  else
1610  depress(i,j) = 0.
1611  tc_count(i,j) = 0.
1612  endif
1613  enddo
1614  enddo
1615  used = send_data(idiag%id_c25, depress, time)
1616  if(idiag%id_f25>0) used = send_data(idiag%id_f25, tc_count, time)
1617  endif
1618 
1619 ! Cat 3-5:
1620  if(idiag%id_c35>0) then
1621  do j=jsc,jec
1622  do i=isc,iec
1623  if ( cat_crt(i,j) .and. slp(i,j)<964.0 ) then
1624  depress(i,j) = 964. - slp(i,j)
1625  tc_count(i,j) = 1.
1626  else
1627  depress(i,j) = 0.
1628  tc_count(i,j) = 0.
1629  endif
1630  enddo
1631  enddo
1632  used = send_data(idiag%id_c35, depress, time)
1633  if(idiag%id_f35>0) used = send_data(idiag%id_f35, tc_count, time)
1634  endif
1635 
1636 ! Cat 4-5:
1637  if(idiag%id_c45>0) then
1638  do j=jsc,jec
1639  do i=isc,iec
1640  if ( cat_crt(i,j) .and. slp(i,j)<944.0 ) then
1641  depress(i,j) = 944. - slp(i,j)
1642  tc_count(i,j) = 1.
1643  else
1644  depress(i,j) = 0.
1645  tc_count(i,j) = 0.
1646  endif
1647  enddo
1648  enddo
1649  used = send_data(idiag%id_c45, depress, time)
1650  if(idiag%id_f45>0) used = send_data(idiag%id_f45, tc_count, time)
1651  endif
1652 
1653  if (idiag%id_c15>0) then
1654  deallocate(depress)
1655  deallocate(cat_crt)
1656  deallocate(storm)
1657  deallocate(ws_max)
1658  deallocate(tc_count)
1659  endif
1660 
1661  if(idiag%id_slp>0 ) deallocate( slp )
1662 
1663 ! deallocate( a3 )
1664  endif
1665 
1666 ! deallocate ( wz )
1667  endif
1668 
1669 ! Temperature:
1670  idg(:) = idiag%id_t(:)
1671 
1672  do_cs_intp = .false.
1673  do i=1,nplev
1674  if ( idg(i)>0 ) then
1675  do_cs_intp = .true.
1676  exit
1677  endif
1678  enddo
1679 
1680  if ( do_cs_intp ) then ! log(pe) as the coordinaite for temp re-construction
1681  if(.not. allocated (a3) ) allocate( a3(isc:iec,jsc:jec,nplev) )
1682  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%pt(isc:iec,jsc:jec,:), nplev, &
1683  plevs, wz, atm(n)%peln, idg, a3, 1)
1684  do i=1,nplev
1685  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
1686  enddo
1687  if ( all(idiag%id_t(minloc(abs(levs-100)))>0) .and. prt_minmax ) then
1688  call prt_mxm('T100:', a3(isc:iec,jsc:jec,11), isc, iec, jsc, jec, 0, 1, 1., &
1689  atm(n)%gridstruct%area_64, atm(n)%domain)
1690  if (.not. atm(n)%neststruct%nested) then
1691  tmp = 0.
1692  sar = 0.
1693  ! Compute mean temp at 100 mb near EQ
1694  do j=jsc,jec
1695  do i=isc,iec
1696  slat = atm(n)%gridstruct%agrid(i,j,2)*rad2deg
1697  if( (slat>-10.0 .and. slat<10.) ) then
1698  sar = sar + atm(n)%gridstruct%area(i,j)
1699  tmp = tmp + a3(i,j,11)*atm(n)%gridstruct%area(i,j)
1700  endif
1701  enddo
1702  enddo
1703  call mp_reduce_sum(sar)
1704  call mp_reduce_sum(tmp)
1705  if ( sar > 0. ) then
1706  if (master) write(*,*) 'Tropical [10s,10n] mean T100 =', tmp/sar
1707  else
1708  if (master) write(*,*) 'Warning: problem computing tropical mean T100'
1709  endif
1710  endif
1711  endif
1712  if ( all(idiag%id_t(minloc(abs(levs-200)))>0) .and. prt_minmax ) then
1713  call prt_mxm('T200:', a3(isc:iec,jsc:jec,13), isc, iec, jsc, jec, 0, 1, 1., &
1714  atm(n)%gridstruct%area_64, atm(n)%domain)
1715  if (.not. atm(n)%neststruct%nested) then
1716  tmp = 0.
1717  sar = 0.
1718  do j=jsc,jec
1719  do i=isc,iec
1720  slat = atm(n)%gridstruct%agrid(i,j,2)*rad2deg
1721  if( (slat>-20 .and. slat<20) ) then
1722  sar = sar + atm(n)%gridstruct%area(i,j)
1723  tmp = tmp + a3(i,j,13)*atm(n)%gridstruct%area(i,j)
1724  endif
1725  enddo
1726  enddo
1727  call mp_reduce_sum(sar)
1728  call mp_reduce_sum(tmp)
1729  if ( sar > 0. ) then
1730  if (master) write(*,*) 'Tropical [-20.,20.] mean T200 =', tmp/sar
1731  endif
1732  endif
1733  endif
1734  deallocate( a3 )
1735  endif
1736 
1737  if (idiag%id_t_plev>0) then
1738  if(.not. allocated (a3) ) allocate( a3(isc:iec,jsc:jec,nplev) )
1739  id1(:) = 1
1740  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%pt(isc:iec,jsc:jec,:), nplev, &
1741  plevs, wz, atm(n)%peln, id1, a3, 1)
1742  used=send_data(idiag%id_t_plev, a3(isc:iec,jsc:jec,:), time)
1743  deallocate( a3 )
1744  endif
1745 
1746  if(idiag%id_mq > 0) then
1747  do j=jsc,jec
1748  do i=isc,iec
1749 ! zxg * surface pressure * 1.e-18--> Hadleys per unit area
1750 ! Unit Hadley = 1.E18 kg m**2 / s**2
1751  a2(i,j) = -1.e-18 * atm(n)%ps(i,j)*idiag%zxg(i,j)
1752  enddo
1753  enddo
1754  used = send_data(idiag%id_mq, a2, time)
1755  if( prt_minmax ) then
1756  tot_mq = g_sum( atm(n)%domain, a2, isc, iec, jsc, jec, ngc, atm(n)%gridstruct%area_64, 0)
1757  idiag%mtq_sum = idiag%mtq_sum + tot_mq
1758  if ( idiag%steps <= max_step ) idiag%mtq(idiag%steps) = tot_mq
1759  if(master) write(*,*) 'Total (global) mountain torque (Hadleys)=', tot_mq
1760  endif
1761  endif
1762 
1763  if (idiag%id_ts > 0) used = send_data(idiag%id_ts, atm(n)%ts(isc:iec,jsc:jec), time)
1764 
1765  if ( idiag%id_tq>0 ) then
1766  nwater = atm(1)%flagstruct%nwat
1767  a2 = 0.
1768  do k=1,npz
1769  do j=jsc,jec
1770  do i=isc,iec
1771 ! a2(i,j) = a2(i,j) + Atm(n)%q(i,j,k,1)*Atm(n)%delp(i,j,k)
1772  a2(i,j) = a2(i,j) + sum(atm(n)%q(i,j,k,1:nwater))*atm(n)%delp(i,j,k)
1773  enddo
1774  enddo
1775  enddo
1776  used = send_data(idiag%id_tq, a2*ginv, time)
1777  endif
1778 #ifdef HIWPP
1779  cl = get_tracer_index(model_atmos, 'Cl')
1780  cl2 = get_tracer_index(model_atmos, 'Cl2')
1781  if (cl > 0 .and. cl2 > 0) then
1782  allocate(var2(isc:iec,jsc:jec))
1783  var2 = 0.
1784  do k=1,npz
1785  do j=jsc,jec
1786  do i=isc,iec
1787  var2(i,j) = var2(i,j) + atm(n)%delp(i,j,k)
1788  enddo
1789  enddo
1790  enddo
1791 
1792  if ( idiag%id_acl > 0 ) then
1793  a2 = 0.
1794  einf = 0.
1795  qm = 0.
1796  do k=1,npz
1797  do j=jsc,jec
1798  do i=isc,iec
1799  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,cl)*atm(n)%delp(i,j,k) ! moist mass
1800  enddo
1801  enddo
1802  enddo
1803  !Convert to mean mixing ratio
1804  do j=jsc,jec
1805  do i=isc,iec
1806  a2(i,j) = a2(i,j) / var2(i,j)
1807  enddo
1808  enddo
1809  used = send_data(idiag%id_acl, a2, time)
1810  endif
1811  if ( idiag%id_acl2 > 0 ) then
1812  a2 = 0.
1813  einf = 0.
1814  qm = 0.
1815  do k=1,npz
1816  do j=jsc,jec
1817  do i=isc,iec
1818  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,cl2)*atm(n)%delp(i,j,k) ! moist mass
1819  enddo
1820  enddo
1821  enddo
1822  !Convert to mean mixing ratio
1823  do j=jsc,jec
1824  do i=isc,iec
1825  a2(i,j) = a2(i,j) / var2(i,j)
1826  enddo
1827  enddo
1828  used = send_data(idiag%id_acl2, a2, time)
1829  endif
1830  if ( idiag%id_acly > 0 ) then
1831  a2 = 0.
1832  einf = 0.
1833  qm = 0.
1834  e2 = 0.
1835  do k=1,npz
1836  do j=jsc,jec
1837  do i=isc,iec
1838  mm = (atm(n)%q(i,j,k,cl)+2.*atm(n)%q(i,j,k,cl2))*atm(n)%delp(i,j,k) ! moist mass
1839  a2(i,j) = a2(i,j) + mm
1840  qm = qm + mm*atm(n)%gridstruct%area_64(i,j)
1841  enddo
1842  enddo
1843  enddo
1844  !Convert to mean mixing ratio
1845  do j=jsc,jec
1846  do i=isc,iec
1847  a2(i,j) = a2(i,j) / var2(i,j)
1848  enddo
1849  enddo
1850  used = send_data(idiag%id_acly, a2, time)
1851  do j=jsc,jec
1852  do i=isc,iec
1853  e2 = e2 + ((a2(i,j) - qcly0)**2)*atm(n)%gridstruct%area_64(i,j)
1854  einf = max(einf, abs(a2(i,j) - qcly0))
1855  enddo
1856  enddo
1857  if (prt_minmax .and. .not. atm(n)%neststruct%nested) then
1858  call mp_reduce_sum(qm)
1859  call mp_reduce_max(einf)
1860  call mp_reduce_sum(e2)
1861  if (master) then
1862  write(*,*) ' TERMINATOR TEST: '
1863  write(*,*) ' chlorine mass: ', real(qm)/(4.*pi*radius*radius)
1864  write(*,*) ' L2 err: ', sqrt(e2)/sqrt(4.*pi*radius*radius)/qcly0
1865  write(*,*) ' max err: ', einf/qcly0
1866  endif
1867  endif
1868  endif
1869 
1870  deallocate(var2)
1871 
1872  endif
1873 #endif
1874  if ( idiag%id_iw>0 ) then
1875  a2 = 0.
1876  if (ice_wat > 0) then
1877  do k=1,npz
1878  do j=jsc,jec
1879  do i=isc,iec
1880  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k) * &
1881  atm(n)%q(i,j,k,ice_wat)
1882  enddo
1883  enddo
1884  enddo
1885  endif
1886  if (snowwat > 0) then
1887  do k=1,npz
1888  do j=jsc,jec
1889  do i=isc,iec
1890  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k) * &
1891  atm(n)%q(i,j,k,snowwat)
1892  enddo
1893  enddo
1894  enddo
1895  endif
1896  if (graupel > 0) then
1897  do k=1,npz
1898  do j=jsc,jec
1899  do i=isc,iec
1900  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k) * &
1901  atm(n)%q(i,j,k,graupel)
1902  enddo
1903  enddo
1904  enddo
1905  endif
1906  used = send_data(idiag%id_iw, a2*ginv, time)
1907  endif
1908  if ( idiag%id_lw>0 ) then
1909  a2 = 0.
1910  if (liq_wat > 0) then
1911  do k=1,npz
1912  do j=jsc,jec
1913  do i=isc,iec
1914  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,liq_wat)*atm(n)%delp(i,j,k)
1915  enddo
1916  enddo
1917  enddo
1918  endif
1919  if (rainwat > 0) then
1920  do k=1,npz
1921  do j=jsc,jec
1922  do i=isc,iec
1923  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,rainwat)*atm(n)%delp(i,j,k)
1924  enddo
1925  enddo
1926  enddo
1927  endif
1928  used = send_data(idiag%id_lw, a2*ginv, time)
1929  endif
1930 
1931 ! Cloud top temperature & cloud top press:
1932  if ( (idiag%id_ctt>0 .or. idiag%id_ctp>0).and. atm(n)%flagstruct%nwat==6) then
1933  allocate ( var1(isc:iec,jsc:jec) )
1934 !$OMP parallel do default(shared) private(tmp)
1935  do j=jsc,jec
1936  do i=isc,iec
1937  do k=2,npz
1938  tmp = atm(n)%q(i,j,k,liq_wat)+atm(n)%q(i,j,k,rainwat)+atm(n)%q(i,j,k,ice_wat)+ &
1939  atm(n)%q(i,j,k,snowwat)+atm(n)%q(i,j,k,graupel)
1940  if( tmp>5.e-6 ) then
1941  a2(i,j) = atm(n)%pt(i,j,k)
1942  var1(i,j) = 0.01*atm(n)%pe(i,k,j)
1943  exit
1944  elseif( k==npz ) then
1945  a2(i,j) = atm(n)%pt(i,j,k)
1946  var1(i,j) = 0.01*atm(n)%pe(i,k+1,j) ! surface pressure
1947  endif
1948  enddo
1949  enddo
1950  enddo
1951  if ( idiag%id_ctt>0 ) then
1952  used = send_data(idiag%id_ctt, a2, time)
1953  if(prt_minmax) call prt_maxmin('Cloud_top_T (K)', a2, isc, iec, jsc, jec, 0, 1, 1.)
1954  endif
1955  if ( idiag%id_ctp>0 ) then
1956  used = send_data(idiag%id_ctp, var1, time)
1957  if(prt_minmax) call prt_maxmin('Cloud_top_P (mb)', var1, isc, iec, jsc, jec, 0, 1, 1.)
1958  endif
1959  deallocate ( var1 )
1960  endif
1961 
1962 ! Condensates:
1963  if ( idiag%id_qn>0 .or. idiag%id_qn200>0 .or. idiag%id_qn500>0 .or. idiag%id_qn850>0 ) then
1964 !$OMP parallel do default(shared)
1965  do k=1,npz
1966  do j=jsc,jec
1967  do i=isc,iec
1968  wk(i,j,k) = 0.
1969  enddo
1970  enddo
1971  enddo
1972  if (liq_wat > 0) then
1973 !$OMP parallel do default(shared)
1974  do k=1,npz
1975  do j=jsc,jec
1976  do i=isc,iec
1977  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,liq_wat)*atm(n)%delp(i,j,k)
1978  enddo
1979  enddo
1980  enddo
1981  endif
1982  if (ice_wat > 0) then
1983 !$OMP parallel do default(shared)
1984  do k=1,npz
1985  do j=jsc,jec
1986  do i=isc,iec
1987  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,ice_wat)*atm(n)%delp(i,j,k)
1988  enddo
1989  enddo
1990  enddo
1991  endif
1992  if ( idiag%id_qn>0 ) used = send_data(idiag%id_qn, wk, time)
1993  if ( idiag%id_qn200>0 ) then
1994  call interpolate_vertical(isc, iec, jsc, jec, npz, 200.e2, atm(n)%peln, wk, a2)
1995  used=send_data(idiag%id_qn200, a2, time)
1996  endif
1997  if ( idiag%id_qn500>0 ) then
1998  call interpolate_vertical(isc, iec, jsc, jec, npz, 500.e2, atm(n)%peln, wk, a2)
1999  used=send_data(idiag%id_qn500, a2, time)
2000  endif
2001  if ( idiag%id_qn850>0 ) then
2002  call interpolate_vertical(isc, iec, jsc, jec, npz, 850.e2, atm(n)%peln, wk, a2)
2003  used=send_data(idiag%id_qn850, a2, time)
2004  endif
2005  endif
2006 ! Total 3D condensates
2007  if ( idiag%id_qp>0 ) then
2008 !$OMP parallel do default(shared)
2009  do k=1,npz
2010  do j=jsc,jec
2011  do i=isc,iec
2012  wk(i,j,k) = 0.
2013  enddo
2014  enddo
2015  enddo
2016  if (rainwat > 0) then
2017 !$OMP parallel do default(shared)
2018  do k=1,npz
2019  do j=jsc,jec
2020  do i=isc,iec
2021  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,rainwat)*atm(n)%delp(i,j,k)
2022  enddo
2023  enddo
2024  enddo
2025  endif
2026  if (snowwat > 0) then
2027 !$OMP parallel do default(shared)
2028  do k=1,npz
2029  do j=jsc,jec
2030  do i=isc,iec
2031  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,snowwat)*atm(n)%delp(i,j,k)
2032  enddo
2033  enddo
2034  enddo
2035  endif
2036  if (graupel > 0) then
2037 !$OMP parallel do default(shared)
2038  do k=1,npz
2039  do j=jsc,jec
2040  do i=isc,iec
2041  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,graupel)*atm(n)%delp(i,j,k)
2042  enddo
2043  enddo
2044  enddo
2045  endif
2046  used = send_data(idiag%id_qp, wk, time)
2047  endif
2048 
2049  if(idiag%id_us > 0 .and. idiag%id_vs > 0) then
2050  u2(:,:) = atm(n)%ua(isc:iec,jsc:jec,npz)
2051  v2(:,:) = atm(n)%va(isc:iec,jsc:jec,npz)
2052  do j=jsc,jec
2053  do i=isc,iec
2054  a2(i,j) = sqrt(u2(i,j)**2 + v2(i,j)**2)
2055  enddo
2056  enddo
2057  used=send_data(idiag%id_us, u2, time)
2058  used=send_data(idiag%id_vs, v2, time)
2059  if(prt_minmax) call prt_maxmin('Surf_wind_speed', a2, isc, iec, jsc, jec, 0, 1, 1.)
2060  endif
2061 
2062  if(idiag%id_tb > 0) then
2063  a2(:,:) = atm(n)%pt(isc:iec,jsc:jec,npz)
2064  used=send_data(idiag%id_tb, a2, time)
2065  if( prt_minmax ) &
2066  call prt_mxm('T_bot:', a2, isc, iec, jsc, jec, 0, 1, 1., atm(n)%gridstruct%area_64, atm(n)%domain)
2067  endif
2068 
2069  if(idiag%id_ua > 0) used=send_data(idiag%id_ua, atm(n)%ua(isc:iec,jsc:jec,:), time)
2070  if(idiag%id_va > 0) used=send_data(idiag%id_va, atm(n)%va(isc:iec,jsc:jec,:), time)
2071 
2072  if(idiag%id_ke > 0) then
2073  a2(:,:) = 0.
2074  do k=1,npz
2075  do j=jsc,jec
2076  do i=isc,iec
2077  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k)*(atm(n)%ua(i,j,k)**2+atm(n)%va(i,j,k)**2)
2078  enddo
2079  enddo
2080  enddo
2081 ! Mass weighted KE
2082  do j=jsc,jec
2083  do i=isc,iec
2084  a2(i,j) = 0.5*a2(i,j)/(atm(n)%ps(i,j)-ptop)
2085  enddo
2086  enddo
2087  used=send_data(idiag%id_ke, a2, time)
2088  if(prt_minmax) then
2089  tot_mq = g_sum( atm(n)%domain, a2, isc, iec, jsc, jec, ngc, atm(n)%gridstruct%area_64, 1)
2090  if (master) write(*,*) 'SQRT(2.*KE; m/s)=', sqrt(2.*tot_mq)
2091  endif
2092  endif
2093 
2094 
2095 #ifdef GFS_PHYS
2096  if(idiag%id_delp > 0 .or. ((.not. atm(n)%flagstruct%hydrostatic) .and. idiag%id_pfnh > 0)) then
2097  do k=1,npz
2098  do j=jsc,jec
2099  do i=isc,iec
2100  if ( atm(n)%flagstruct%nwat .eq. 2) then
2101  wk(i,j,k) = atm(n)%delp(i,j,k)*(1.-atm(n)%q(i,j,k,liq_wat))
2102  elseif ( atm(n)%flagstruct%nwat .eq. 6) then
2103  wk(i,j,k) = atm(n)%delp(i,j,k)*(1.-atm(n)%q(i,j,k,liq_wat)-&
2104  atm(n)%q(i,j,k,ice_wat)-&
2105  atm(n)%q(i,j,k,rainwat)-&
2106  atm(n)%q(i,j,k,snowwat)-&
2107  atm(n)%q(i,j,k,graupel))
2108  endif
2109  enddo
2110  enddo
2111  enddo
2112  if (idiag%id_delp > 0) used=send_data(idiag%id_delp, wk, time)
2113  endif
2114 
2115  if( (.not. atm(n)%flagstruct%hydrostatic) .and. idiag%id_pfnh > 0) then
2116  do k=1,npz
2117  do j=jsc,jec
2118  do i=isc,iec
2119  wk(i,j,k) = -wk(i,j,k)/(atm(n)%delz(i,j,k)*grav)*rdgas* &
2120  atm(n)%pt(i,j,k)*(1.+zvir*atm(n)%q(i,j,k,sphum))
2121  enddo
2122  enddo
2123  enddo
2124 ! if (prt_minmax) then
2125 ! call prt_maxmin(' PFNH (mb)', wk(isc:iec,jsc:jec,1), isc, iec, jsc, jec, 0, npz, 1.E-2)
2126 ! endif
2127  used=send_data(idiag%id_pfnh, wk, time)
2128  endif
2129 #else
2130  if(idiag%id_delp > 0) used=send_data(idiag%id_delp, atm(n)%delp(isc:iec,jsc:jec,:), time)
2131 
2132  if( (.not. atm(n)%flagstruct%hydrostatic) .and. idiag%id_pfnh > 0) then
2133  do k=1,npz
2134  do j=jsc,jec
2135  do i=isc,iec
2136  wk(i,j,k) = -atm(n)%delp(i,j,k)/(atm(n)%delz(i,j,k)*grav)*rdgas* &
2137  atm(n)%pt(i,j,k)*(1.+zvir*atm(n)%q(i,j,k,sphum))
2138  enddo
2139  enddo
2140  enddo
2141  used=send_data(idiag%id_pfnh, wk, time)
2142  endif
2143 #endif
2144 
2145  if((.not. atm(n)%flagstruct%hydrostatic) .and. idiag%id_delz > 0) then
2146  do k=1,npz
2147  do j=jsc,jec
2148  do i=isc,iec
2149  wk(i,j,k) = -atm(n)%delz(i,j,k)
2150  enddo
2151  enddo
2152  enddo
2153  used=send_data(idiag%id_delz, wk, time)
2154  endif
2155 
2156  if( atm(n)%flagstruct%hydrostatic .and. idiag%id_pfhy > 0 ) then
2157  do k=1,npz
2158  do j=jsc,jec
2159  do i=isc,iec
2160  wk(i,j,k) = 0.5 *(atm(n)%pe(i,k,j)+atm(n)%pe(i,k+1,j))
2161  enddo
2162  enddo
2163  enddo
2164  used=send_data(idiag%id_pfhy, wk, time)
2165  endif
2166 
2167 
2168 ! pressure for masking p-level fields
2169 ! incorrectly defines a2 to be ps (in mb).
2170  if (idiag%id_pmask>0) then
2171  do j=jsc,jec
2172  do i=isc,iec
2173  a2(i,j) = exp((atm(n)%peln(i,npz+1,j)+atm(n)%peln(i,npz+1,j))*0.5)*0.01
2174  !a2(i,j) = Atm(n)%delp(i,j,k)/(Atm(n)%peln(i,k+1,j)-Atm(n)%peln(i,k,j))*0.01
2175  enddo
2176  enddo
2177  used=send_data(idiag%id_pmask, a2, time)
2178  endif
2179 ! fix for pressure for masking p-level fields
2180 ! based on lowest-level pfull
2181 ! define pressure at lowest level the same as interpolate_vertical (in mb)
2182  if (idiag%id_pmaskv2>0) then
2183  do j=jsc,jec
2184  do i=isc,iec
2185  a2(i,j) = exp((atm(n)%peln(i,npz,j)+atm(n)%peln(i,npz+1,j))*0.5)*0.01
2186  enddo
2187  enddo
2188  used=send_data(idiag%id_pmaskv2, a2, time)
2189  endif
2190 
2191  if ( idiag%id_u100m>0 .or. idiag%id_v100m>0 .or. idiag%id_w100m>0 .or. idiag%id_w5km>0 .or. idiag%id_w2500m>0 .or. idiag%id_basedbz>0 .or. idiag%id_dbz4km>0) then
2192  if (.not.allocated(wz)) allocate ( wz(isc:iec,jsc:jec,npz+1) )
2193  if ( atm(n)%flagstruct%hydrostatic) then
2194  rgrav = 1. / grav
2195 !$OMP parallel do default(none) shared(isc,iec,jsc,jec,wz,npz,Atm,n,rgrav)
2196  do j=jsc,jec
2197  do i=isc,iec
2198  wz(i,j,npz+1) = 0.
2199 ! wz(i,j,npz+1) = Atm(n)%phis(i,j)/grav
2200  enddo
2201  do k=npz,1,-1
2202  do i=isc,iec
2203  wz(i,j,k) = wz(i,j,k+1) - (rdgas*rgrav)*atm(n)%pt(i,j,k)*(atm(n)%peln(i,k,j) - atm(n)%peln(i,k+1,j))
2204  enddo
2205  enddo
2206  enddo
2207  else
2208 !$OMP parallel do default(none) shared(isc,iec,jsc,jec,wz,npz,Atm,n)
2209  do j=jsc,jec
2210  do i=isc,iec
2211  wz(i,j,npz+1) = 0.
2212 ! wz(i,j,npz+1) = Atm(n)%phis(i,j)/grav
2213  enddo
2214  do k=npz,1,-1
2215  do i=isc,iec
2216  wz(i,j,k) = wz(i,j,k+1) - atm(n)%delz(i,j,k)
2217  enddo
2218  enddo
2219  enddo
2220  endif
2221  if( prt_minmax ) &
2222  call prt_maxmin('ZTOP', wz(isc:iec,jsc:jec,1)+atm(n)%phis(isc:iec,jsc:jec)/grav, isc, iec, jsc, jec, 0, 1, 1.e-3)
2223  endif
2224 
2225  if ( idiag%id_rain5km>0 ) then
2226  rainwat = get_tracer_index(model_atmos, 'rainwat')
2227  call interpolate_z(isc, iec, jsc, jec, npz, 5.e3, wz, atm(n)%q(isc:iec,jsc:jec,:,rainwat), a2)
2228  used=send_data(idiag%id_rain5km, a2, time)
2229  if(prt_minmax) call prt_maxmin('rain5km', a2, isc, iec, jsc, jec, 0, 1, 1.)
2230  endif
2231  if ( idiag%id_w5km>0 ) then
2232  call interpolate_z(isc, iec, jsc, jec, npz, 5.e3, wz, atm(n)%w(isc:iec,jsc:jec,:), a2)
2233  used=send_data(idiag%id_w5km, a2, time)
2234  if(prt_minmax) call prt_maxmin('W5km', a2, isc, iec, jsc, jec, 0, 1, 1.)
2235  endif
2236  if ( idiag%id_w2500m>0 ) then
2237  call interpolate_z(isc, iec, jsc, jec, npz, 2.5e3, wz, atm(n)%w(isc:iec,jsc:jec,:), a2)
2238  used=send_data(idiag%id_w2500m, a2, time)
2239  if(prt_minmax) call prt_maxmin('W2500m', a2, isc, iec, jsc, jec, 0, 1, 1.)
2240  endif
2241  if ( idiag%id_w100m>0 ) then
2242  call interpolate_z(isc, iec, jsc, jec, npz, 100., wz, atm(n)%w(isc:iec,jsc:jec,:), a2)
2243  used=send_data(idiag%id_w100m, a2, time)
2244  if(prt_minmax) call prt_maxmin('w100m', a2, isc, iec, jsc, jec, 0, 1, 1.)
2245  endif
2246  if ( idiag%id_u100m>0 ) then
2247  call interpolate_z(isc, iec, jsc, jec, npz, 100., wz, atm(n)%ua(isc:iec,jsc:jec,:), a2)
2248  used=send_data(idiag%id_u100m, a2, time)
2249  if(prt_minmax) call prt_maxmin('u100m', a2, isc, iec, jsc, jec, 0, 1, 1.)
2250  endif
2251  if ( idiag%id_v100m>0 ) then
2252  call interpolate_z(isc, iec, jsc, jec, npz, 100., wz, atm(n)%va(isc:iec,jsc:jec,:), a2)
2253  used=send_data(idiag%id_v100m, a2, time)
2254  if(prt_minmax) call prt_maxmin('v100m', a2, isc, iec, jsc, jec, 0, 1, 1.)
2255  endif
2256 
2257  if ( rainwat > 0 .and. (idiag%id_dbz>0 .or. idiag%id_maxdbz>0 .or. idiag%id_basedbz>0 .or. idiag%id_dbz4km>0)) then
2258 
2259  if (.not. allocated(a3)) allocate(a3(isc:iec,jsc:jec,npz))
2260 
2261  call dbzcalc(atm(n)%q, atm(n)%pt, atm(n)%delp, atm(n)%peln, atm(n)%delz, &
2262  a3, a2, allmax, atm(n)%bd, npz, atm(n)%ncnst, atm(n)%flagstruct%hydrostatic, &
2263  zvir, .false., .false., .false., .true. ) ! Lin MP has constant N_0 intercept
2264 
2265  if (idiag%id_dbz > 0) then
2266  used=send_data(idiag%id_dbz, a3, time)
2267  endif
2268  if (idiag%id_maxdbz > 0) then
2269  used=send_data(idiag%id_maxdbz, a2, time)
2270  endif
2271  if (idiag%id_basedbz > 0) then
2272  !interpolate to 1km dbz
2273  call interpolate_z(isc, iec, jsc, jec, npz, 1000., wz, a3, a2)
2274  used=send_data(idiag%id_basedbz, a2, time)
2275  endif
2276  if (idiag%id_dbz4km > 0) then
2277  !interpolate to 1km dbz
2278  call interpolate_z(isc, iec, jsc, jec, npz, 4000., wz, a3, a2)
2279  used=send_data(idiag%id_dbz4km, a2, time)
2280  endif
2281 
2282  if (prt_minmax) then
2283  call mpp_max(allmax)
2284  if (master) write(*,*) 'max reflectivity = ', allmax, ' dBZ'
2285  endif
2286 
2287  deallocate(a3)
2288  endif
2289  if( allocated(wz) ) deallocate (wz)
2290 
2291 
2292 !-------------------------------------------------------
2293 ! Applying cubic-spline as the intepolator for (u,v,T,q)
2294 !-------------------------------------------------------
2295  if(.not. allocated(a3)) allocate( a3(isc:iec,jsc:jec,nplev) )
2296 ! u-winds:
2297  idg(:) = idiag%id_u(:)
2298 
2299  do_cs_intp = .false.
2300  do i=1,nplev
2301  if ( idg(i)>0 ) then
2302  do_cs_intp = .true.
2303  exit
2304  endif
2305  enddo
2306 
2307  if ( do_cs_intp ) then
2308  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%ua(isc:iec,jsc:jec,:), nplev, &
2309  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, -1)
2310 ! plevs, Atm(n)%peln, idg, a3, -1)
2311  do i=1,nplev
2312  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
2313  enddo
2314  endif
2315 
2316  if (idiag%id_u_plev>0) then
2317  id1(:) = 1
2318  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%ua(isc:iec,jsc:jec,:), nplev, &
2319  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, -1)
2320  used=send_data(idiag%id_u_plev, a3(isc:iec,jsc:jec,:), time)
2321  endif
2322 
2323 ! v-winds:
2324  idg(:) = idiag%id_v(:)
2325 
2326  do_cs_intp = .false.
2327  do i=1,nplev
2328  if ( idg(i)>0 ) then
2329  do_cs_intp = .true.
2330  exit
2331  endif
2332  enddo
2333 
2334  if ( do_cs_intp ) then
2335  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%va(isc:iec,jsc:jec,:), nplev, &
2336  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, -1)
2337 ! plevs, Atm(n)%peln, idg, a3, -1)
2338  do i=1,nplev
2339  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
2340  enddo
2341  endif
2342 
2343  if (idiag%id_v_plev>0) then
2344  id1(:) = 1
2345  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%va(isc:iec,jsc:jec,:), nplev, &
2346  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, -1)
2347  used=send_data(idiag%id_v_plev, a3(isc:iec,jsc:jec,:), time)
2348  endif
2349 
2350 ! Specific humidity
2351  idg(:) = idiag%id_q(:)
2352 
2353  do_cs_intp = .false.
2354  do i=1,nplev
2355  if ( idg(i)>0 ) then
2356  do_cs_intp = .true.
2357  exit
2358  endif
2359  enddo
2360 
2361  if ( do_cs_intp ) then
2362  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%q(isc:iec,jsc:jec,:,sphum), nplev, &
2363  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, 0)
2364 ! plevs, Atm(n)%peln, idg, a3, 0)
2365  do i=1,nplev
2366  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
2367  enddo
2368  endif
2369 
2370  if (idiag%id_q_plev>0) then
2371  id1(:) = 1
2372  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%q(isc:iec,jsc:jec,:,sphum), nplev, &
2373  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, 0)
2374  used=send_data(idiag%id_q_plev, a3(isc:iec,jsc:jec,:), time)
2375  endif
2376 
2377 ! Omega
2378  idg(:) = idiag%id_omg(:)
2379 
2380  do_cs_intp = .false.
2381  do i=1,nplev
2382  if ( idg(i)>0 ) then
2383  do_cs_intp = .true.
2384  exit
2385  endif
2386  enddo
2387  if ( do_cs_intp ) then
2388  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%omga(isc:iec,jsc:jec,:), nplev, &
2389  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, -1)
2390 ! plevs, Atm(n)%peln, idg, a3)
2391  do i=1,nplev
2392  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
2393  enddo
2394  endif
2395 
2396  if (idiag%id_omg_plev>0) then
2397  id1(:) = 1
2398  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%omga(isc:iec,jsc:jec,:), nplev, &
2399  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, -1)
2400  used=send_data(idiag%id_omg_plev, a3(isc:iec,jsc:jec,:), time)
2401  endif
2402 
2403  if( allocated(a3) ) deallocate (a3)
2404 ! *** End cs_intp
2405 
2406  if ( idiag%id_sl12>0 ) then ! 13th level wind speed (~ 222 mb for the 32L setup)
2407  do j=jsc,jec
2408  do i=isc,iec
2409  a2(i,j) = sqrt(atm(n)%ua(i,j,12)**2 + atm(n)%va(i,j,12)**2)
2410  enddo
2411  enddo
2412  used=send_data(idiag%id_sl12, a2, time)
2413  endif
2414  if ( idiag%id_sl13>0 ) then ! 13th level wind speed (~ 222 mb for the 32L setup)
2415  do j=jsc,jec
2416  do i=isc,iec
2417  a2(i,j) = sqrt(atm(n)%ua(i,j,13)**2 + atm(n)%va(i,j,13)**2)
2418  enddo
2419  enddo
2420  used=send_data(idiag%id_sl13, a2, time)
2421  endif
2422 
2423  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w200>0 ) then
2424  call interpolate_vertical(isc, iec, jsc, jec, npz, &
2425  200.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
2426  used=send_data(idiag%id_w200, a2, time)
2427  endif
2428 ! 500-mb
2429  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w500>0 ) then
2430  call interpolate_vertical(isc, iec, jsc, jec, npz, &
2431  500.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
2432  used=send_data(idiag%id_w500, a2, time)
2433  endif
2434  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w700>0 ) then
2435  call interpolate_vertical(isc, iec, jsc, jec, npz, &
2436  700.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
2437  used=send_data(idiag%id_w700, a2, time)
2438  endif
2439  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w850>0 .or. idiag%id_x850>0) then
2440  call interpolate_vertical(isc, iec, jsc, jec, npz, &
2441  850.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
2442  used=send_data(idiag%id_w850, a2, time)
2443 
2444  if ( idiag%id_x850>0 .and. idiag%id_vort850>0 ) then
2445  x850(:,:) = x850(:,:)*a2(:,:)
2446  used=send_data(idiag%id_x850, x850, time)
2447  deallocate ( x850 )
2448  endif
2449  endif
2450 
2451 
2452  if ( .not.atm(n)%flagstruct%hydrostatic .and. idiag%id_w>0 ) then
2453  used=send_data(idiag%id_w, atm(n)%w(isc:iec,jsc:jec,:), time)
2454  endif
2455 
2456  if(idiag%id_pt > 0) used=send_data(idiag%id_pt , atm(n)%pt (isc:iec,jsc:jec,:), time)
2457  if(idiag%id_omga > 0) used=send_data(idiag%id_omga, atm(n)%omga(isc:iec,jsc:jec,:), time)
2458 
2459  allocate( a3(isc:iec,jsc:jec,npz) )
2460  if(idiag%id_theta_e > 0) then
2461 
2462  if ( atm(n)%flagstruct%adiabatic .and. atm(n)%flagstruct%kord_tm>0 ) then
2463  do k=1,npz
2464  do j=jsc,jec
2465  do i=isc,iec
2466  a3(i,j,k) = atm(n)%pt(i,j,k)
2467  enddo
2468  enddo
2469  enddo
2470  else
2471 ! DH*
2472 ! The argument Atm(n)%q(isd,jsd,1,sphum) causes a compile-time error with gfortran:
2473 ! Error: Element of assumed-shaped or pointer array passed to array dummy argument 'q' at (1)
2474 ! In our configuration, this section of the code is not executed; hence the correct behavior
2475 ! of passing in the entire Atm(n)%q array for gfortran has not been tested
2476 #ifdef __GFORTRAN__
2477  write (0,*) 'Attention - calling eqv_pot with Atm(n)%q instead of Atm(n)%q(isd,jsd,1,sphum) for gfortran has not been tested!'
2478  call eqv_pot(a3, atm(n)%pt, atm(n)%delp, atm(n)%delz, atm(n)%peln, atm(n)%pkz, atm(n)%q, &
2479  isc, iec, jsc, jec, ngc, npz, atm(n)%flagstruct%hydrostatic, atm(n)%flagstruct%moist_phys)
2480 #else
2481  call eqv_pot(a3, atm(n)%pt, atm(n)%delp, atm(n)%delz, atm(n)%peln, atm(n)%pkz, atm(n)%q(isd,jsd,1,sphum), &
2482  isc, iec, jsc, jec, ngc, npz, atm(n)%flagstruct%hydrostatic, atm(n)%flagstruct%moist_phys)
2483 #endif
2484 ! *DH
2485  endif
2486 
2487  if( prt_minmax ) call prt_maxmin('Theta_E', a3, isc, iec, jsc, jec, 0, npz, 1.)
2488  used=send_data(idiag%id_theta_e, a3, time)
2489  theta_d = get_tracer_index(model_atmos, 'theta_d')
2490  if ( theta_d>0 ) then
2491 !
2492  if( prt_minmax ) then
2493 ! Check level-34 ~ 300 mb
2494  a2(:,:) = 0.
2495  do k=1,npz
2496  do j=jsc,jec
2497  do i=isc,iec
2498  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k)*(atm(n)%q(i,j,k,theta_d)-a3(i,j,k))**2
2499  enddo
2500  enddo
2501  enddo
2502  call prt_mxm('PT_SUM', a2, isc, iec, jsc, jec, 0, 1, 1.e-5, atm(n)%gridstruct%area_64, atm(n)%domain)
2503 
2504  do k=1,npz
2505  do j=jsc,jec
2506  do i=isc,iec
2507  a3(i,j,k) = atm(n)%q(i,j,k,theta_d)/a3(i,j,k) - 1.
2508  enddo
2509  enddo
2510  enddo
2511  call prt_maxmin('Theta_Err (%)', a3, isc, iec, jsc, jec, 0, npz, 100.)
2512 ! if ( master ) write(*,*) 'PK0=', pk0, 'KAPPA=', kappa
2513  endif
2514  endif
2515  endif
2516 
2517  if(idiag%id_ppt> 0) then
2518 ! Potential temperature perturbation for gravity wave test_case
2519  allocate ( idiag%pt1(npz) )
2520  if( .not. allocated(a3) ) allocate ( a3(isc:iec,jsc:jec,npz) )
2521 #ifdef TEST_GWAVES
2522  call gw_1d(npz, 1000.e2, atm(n)%ak, atm(n)%ak, atm(n)%ak(1), 10.e3, idiag%pt1)
2523 #else
2524  idiag%pt1 = 0.
2525 #endif
2526  do k=1,npz
2527  do j=jsc,jec
2528  do i=isc,iec
2529 ! wk(i,j,k) = (Atm(n)%pt(i,j,k)-300.)/Atm(n)%pkz(i,j,k) * pk0
2530  wk(i,j,k) = (atm(n)%pt(i,j,k)/atm(n)%pkz(i,j,k) - idiag%pt1(k)) * pk0
2531  enddo
2532  enddo
2533  enddo
2534  used=send_data(idiag%id_ppt, wk, time)
2535 
2536  if( prt_minmax ) then
2537  call prt_maxmin('PoTemp', wk, isc, iec, jsc, jec, 0, npz, 1.)
2538  endif
2539 
2540  if( allocated(a3) ) deallocate ( a3 )
2541  deallocate ( idiag%pt1 )
2542  endif
2543 
2544 
2545 #ifndef SW_DYNAMICS
2546  do itrac=1, atm(n)%ncnst
2547  call get_tracer_names (model_atmos, itrac, tname)
2548  if (idiag%id_tracer(itrac) > 0 .and. itrac.gt.nq) then
2549  used = send_data(idiag%id_tracer(itrac), atm(n)%qdiag(isc:iec,jsc:jec,:,itrac), time )
2550  else
2551  used = send_data(idiag%id_tracer(itrac), atm(n)%q(isc:iec,jsc:jec,:,itrac), time )
2552  endif
2553  if (itrac .le. nq) then
2554  if( prt_minmax ) call prt_maxmin(trim(tname), atm(n)%q(:,:,1,itrac), &
2555  isc, iec, jsc, jec, ngc, npz, 1.)
2556  else
2557  if( prt_minmax ) call prt_maxmin(trim(tname), atm(n)%qdiag(:,:,1,itrac), &
2558  isc, iec, jsc, jec, ngc, npz, 1.)
2559  endif
2560 !-------------------------------
2561 ! ESM TRACER diagnostics output:
2562 ! jgj: per SJ email (jul 17 2008): q_dry = q_moist/(1-sphum)
2563 ! mass mixing ratio: q_dry = mass_tracer/mass_dryair = mass_tracer/(mass_air - mass_water) ~ q_moist/(1-sphum)
2564 ! co2_mmr = (wco2/wair) * co2_vmr
2565 ! Note: There is a check to ensure tracer number one is sphum
2566 
2567  if (idiag%id_tracer_dmmr(itrac) > 0 .or. idiag%id_tracer_dvmr(itrac) > 0) then
2568  if (itrac .gt. nq) then
2569  dmmr(:,:,:) = atm(n)%qdiag(isc:iec,jsc:jec,1:npz,itrac) &
2570  /(1.0-atm(n)%q(isc:iec,jsc:jec,1:npz,1))
2571  else
2572  dmmr(:,:,:) = atm(n)%q(isc:iec,jsc:jec,1:npz,itrac) &
2573  /(1.0-atm(n)%q(isc:iec,jsc:jec,1:npz,1))
2574  endif
2575  dvmr(:,:,:) = dmmr(isc:iec,jsc:jec,1:npz) * wtmair/idiag%w_mr(itrac)
2576  used = send_data(idiag%id_tracer_dmmr(itrac), dmmr, time )
2577  used = send_data(idiag%id_tracer_dvmr(itrac), dvmr, time )
2578  if( prt_minmax ) then
2579  call prt_maxmin(trim(tname)//'_dmmr', dmmr, &
2580  isc, iec, jsc, jec, 0, npz, 1.)
2581  call prt_maxmin(trim(tname)//'_dvmr', dvmr, &
2582  isc, iec, jsc, jec, 0, npz, 1.)
2583  endif
2584  endif
2585  enddo
2586 
2587 
2588 
2589 #endif
2590 
2591  ! enddo ! end ntileMe do-loop
2592 
2593  deallocate ( a2 )
2594  deallocate ( u2 )
2595  deallocate ( v2 )
2596  deallocate ( wk )
2597 
2598  if (allocated(a3)) deallocate(a3)
2599  if (allocated(wz)) deallocate(wz)
2600  if (allocated(dmmr)) deallocate(dmmr)
2601  if (allocated(dvmr)) deallocate(dvmr)
2602 
2603  call nullify_domain()
2604 
2605 
2606  end subroutine fv_diag
2607 
2608  subroutine wind_max(isc, iec, jsc, jec ,isd, ied, jsd, jed, us, vs, ws_max, domain)
2609  integer isc, iec, jsc, jec
2610  integer isd, ied, jsd, jed
2611  real, intent(in), dimension(isc:iec,jsc:jec):: us, vs
2612  real, intent(out) :: ws_max(isc:iec,jsc:jec)
2613  type(domain2d), intent(INOUT) :: domain
2614 ! Local
2615  real :: wx(isc:iec,jsd:jed), ws(isd:ied,jsd:jed)
2616  integer:: i,j
2617 
2618  ws = 0. ! fill corners with zeros
2619  do j=jsc,jec
2620  do i=isc,iec
2621  ws(i,j) = sqrt(us(i,j)**2 + vs(i,j)**2)
2622  enddo
2623  enddo
2624 
2625  call mpp_update_domains( ws, domain )
2626 
2627  do j=jsd,jed
2628  do i=isc,iec
2629  wx(i,j) = max(ws(i-3,j), ws(i-2,j), ws(i-1,j), ws(i,j), ws(i+1,j), ws(i+2,j), ws(i+3,j))
2630  enddo
2631  enddo
2632 
2633  do j=jsc,jec
2634  do i=isc,iec
2635  ws_max(i,j) = max(wx(i,j-3), wx(i,j-2), wx(i,j-1), wx(i,j), wx(i,j+1), wx(i,j+2), wx(i,j+3))
2636  enddo
2637  enddo
2638 
2639  end subroutine wind_max
2640 
2641 
2642  subroutine get_vorticity(isc, iec, jsc, jec ,isd, ied, jsd, jed, npz, u, v, vort, dx, dy, rarea)
2643  integer isd, ied, jsd, jed, npz
2644  integer isc, iec, jsc, jec
2645  real, intent(in) :: u(isd:ied, jsd:jed+1, npz), v(isd:ied+1, jsd:jed, npz)
2646  real, intent(out) :: vort(isc:iec, jsc:jec, npz)
2647  real, intent(IN) :: dx(isd:ied,jsd:jed+1)
2648  real, intent(IN) :: dy(isd:ied+1,jsd:jed)
2649  real, intent(IN) :: rarea(isd:ied,jsd:jed)
2650 ! Local
2651  real :: utmp(isc:iec, jsc:jec+1), vtmp(isc:iec+1, jsc:jec)
2652  integer :: i,j,k
2653 
2654  do k=1,npz
2655  do j=jsc,jec+1
2656  do i=isc,iec
2657  utmp(i,j) = u(i,j,k)*dx(i,j)
2658  enddo
2659  enddo
2660  do j=jsc,jec
2661  do i=isc,iec+1
2662  vtmp(i,j) = v(i,j,k)*dy(i,j)
2663  enddo
2664  enddo
2665 
2666  do j=jsc,jec
2667  do i=isc,iec
2668  vort(i,j,k) = rarea(i,j)*(utmp(i,j)-utmp(i,j+1)-vtmp(i,j)+vtmp(i+1,j))
2669  enddo
2670  enddo
2671  enddo
2672 
2673  end subroutine get_vorticity
2674 
2675 
2676  subroutine get_height_field(is, ie, js, je, ng, km, hydrostatic, delz, wz, pt, q, peln, zvir)
2677  integer, intent(in):: is, ie, js, je, km, ng
2678  real, intent(in):: peln(is:ie,km+1,js:je)
2679  real, intent(in):: pt(is-ng:ie+ng,js-ng:je+ng,km)
2680  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*) ! water vapor
2681  real, intent(in):: delz(is-ng:,js-ng:,1:)
2682  real, intent(in):: zvir
2683  logical, intent(in):: hydrostatic
2684  real, intent(out):: wz(is:ie,js:je,km+1)
2685 !
2686  integer i,j,k
2687  real gg
2688 
2689  gg = rdgas * ginv
2690 
2691  do j=js,je
2692  do i=is,ie
2693  wz(i,j,km+1) = idiag%zsurf(i,j)
2694  enddo
2695  if (hydrostatic ) then
2696  do k=km,1,-1
2697  do i=is,ie
2698  wz(i,j,k) = wz(i,j,k+1) + gg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum)) &
2699  *(peln(i,k+1,j)-peln(i,k,j))
2700  enddo
2701  enddo
2702  else
2703  do k=km,1,-1
2704  do i=is,ie
2705  wz(i,j,k) = wz(i,j,k+1) - delz(i,j,k)
2706  enddo
2707  enddo
2708  endif
2709  enddo
2710 
2711  end subroutine get_height_field
2712 
2713  subroutine range_check(qname, q, is, ie, js, je, n_g, km, pos, q_low, q_hi, bad_range)
2714  character(len=*), intent(in):: qname
2715  integer, intent(in):: is, ie, js, je
2716  integer, intent(in):: n_g, km
2717  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2718  real, intent(in):: pos(is-n_g:ie+n_g, js-n_g:je+n_g,2)
2719  real, intent(in):: q_low, q_hi
2720  logical, optional, intent(out):: bad_range
2721 !
2722  real qmin, qmax
2723  integer i,j,k
2724 
2725  if ( present(bad_range) ) bad_range = .false.
2726  qmin = q(is,js,1)
2727  qmax = qmin
2728 
2729  do k=1,km
2730  do j=js,je
2731  do i=is,ie
2732  if( q(i,j,k) < qmin ) then
2733  qmin = q(i,j,k)
2734  elseif( q(i,j,k) > qmax ) then
2735  qmax = q(i,j,k)
2736  endif
2737  enddo
2738  enddo
2739  enddo
2740 
2741  call mp_reduce_min(qmin)
2742  call mp_reduce_max(qmax)
2743 
2744  if( qmin<q_low .or. qmax>q_hi ) then
2745  if(master) write(*,*) 'Range_check Warning:', qname, ' max = ', qmax, ' min = ', qmin
2746  if ( present(bad_range) ) then
2747  bad_range = .true.
2748  endif
2749  endif
2750 
2751  if ( present(bad_range) ) then
2752 ! Print out where the bad value(s) is (are)
2753  if ( bad_range .EQV. .false. ) return
2754  do k=1,km
2755  do j=js,je
2756  do i=is,ie
2757  if( q(i,j,k)<q_low .or. q(i,j,k)>q_hi ) then
2758  write(*,*) 'Crash_K=',k,'(i,j)=',i,j, pos(i,j,1)*rad2deg, pos(i,j,2)*rad2deg, q(i,j,k)
2759  if ( k/= 1 ) write(*,*) k-1, q(i,j,k-1)
2760  if ( k/=km ) write(*,*) k+1, q(i,j,k+1)
2761  endif
2762  enddo
2763  enddo
2764  enddo
2765  call mpp_error(fatal,'==> Error from range_check: data out of bound')
2766  endif
2767 
2768  end subroutine range_check
2769 
2770  subroutine prt_maxmin(qname, q, is, ie, js, je, n_g, km, fac)
2771  character(len=*), intent(in):: qname
2772  integer, intent(in):: is, ie, js, je
2773  integer, intent(in):: n_g, km
2774  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2775  real, intent(in):: fac
2776 
2777  real qmin, qmax
2778  integer i,j,k
2779  !mpp_root_pe doesn't appear to recognize nested grid
2780  master = (mpp_pe()==mpp_root_pe()) .or. is_master()
2781 
2782  qmin = q(is,js,1)
2783  qmax = qmin
2784 
2785  do k=1,km
2786  do j=js,je
2787  do i=is,ie
2788 ! qmin = min(qmin, q(i,j,k))
2789 ! qmax = max(qmax, q(i,j,k))
2790  if( q(i,j,k) < qmin ) then
2791  qmin = q(i,j,k)
2792  elseif( q(i,j,k) > qmax ) then
2793  qmax = q(i,j,k)
2794  endif
2795  enddo
2796  enddo
2797  enddo
2798 
2799  call mp_reduce_min(qmin)
2800  call mp_reduce_max(qmax)
2801 
2802  if(master) then
2803  write(*,*) qname//trim(gn), ' max = ', qmax*fac, ' min = ', qmin*fac
2804  endif
2805 
2806  end subroutine prt_maxmin
2807 
2808  subroutine prt_mxm(qname, q, is, ie, js, je, n_g, km, fac, area, domain)
2809  character(len=*), intent(in):: qname
2810  integer, intent(in):: is, ie, js, je
2811  integer, intent(in):: n_g, km
2812  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2813  real, intent(in):: fac
2814 ! BUG !!!
2815 ! real, intent(IN):: area(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2816  real(kind=R_GRID), intent(IN):: area(is-3:ie+3, js-3:je+3)
2817  type(domain2d), intent(INOUT) :: domain
2818 !
2819  real qmin, qmax, gmean
2820  integer i,j,k
2821 
2822  !mpp_root_pe doesn't appear to recognize nested grid
2823  master = (mpp_pe()==mpp_root_pe()) .or. is_master()
2824  qmin = q(is,js,1)
2825  qmax = qmin
2826  gmean = 0.
2827 
2828  do k=1,km
2829  do j=js,je
2830  do i=is,ie
2831 ! qmin = min(qmin, q(i,j,k))
2832 ! qmax = max(qmax, q(i,j,k))
2833  if( q(i,j,k) < qmin ) then
2834  qmin = q(i,j,k)
2835  elseif( q(i,j,k) > qmax ) then
2836  qmax = q(i,j,k)
2837  endif
2838  enddo
2839  enddo
2840  enddo
2841 
2842  call mp_reduce_min(qmin)
2843  call mp_reduce_max(qmax)
2844 
2845 ! SJL: BUG!!!
2846 ! gmean = g_sum(domain, q(is,js,km), is, ie, js, je, 3, area, 1)
2847  gmean = g_sum(domain, q(is:ie,js:je,km), is, ie, js, je, 3, area, 1)
2848 
2849  if(master) write(6,*) qname, gn, qmax*fac, qmin*fac, gmean*fac
2850 
2851  end subroutine prt_mxm
2852 
2853  !Added nwat == 1 case for water vapor diagnostics
2854  subroutine prt_mass(km, nq, is, ie, js, je, n_g, nwat, ps, delp, q, area, domain)
2856  integer, intent(in):: is, ie, js, je
2857  integer, intent(in):: nq, n_g, km, nwat
2858  real, intent(in):: ps(is-n_g:ie+n_g, js-n_g:je+n_g)
2859  real, intent(in):: delp(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2860  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km, nq)
2861  real(kind=R_GRID), intent(IN):: area(is-n_g:ie+n_g,js-n_g:je+n_g)
2862  type(domain2d), intent(INOUT) :: domain
2863 ! Local:
2864  real psq(is:ie,js:je,nwat), psqv(is:ie,js:je)
2865  real q_strat(is:ie,js:je)
2866  real qtot(nwat), qwat
2867  real psmo, totw, psdry
2868  integer k, n, kstrat
2869 
2870 !Needed when calling prt_mass in fv_restart?
2871  sphum = get_tracer_index(model_atmos, 'sphum')
2872  liq_wat = get_tracer_index(model_atmos, 'liq_wat')
2873  ice_wat = get_tracer_index(model_atmos, 'ice_wat')
2874 
2875  rainwat = get_tracer_index(model_atmos, 'rainwat')
2876  snowwat = get_tracer_index(model_atmos, 'snowwat')
2877  graupel = get_tracer_index(model_atmos, 'graupel')
2878 
2879  if ( nwat==0 ) then
2880  psmo = g_sum(domain, ps(is:ie,js:je), is, ie, js, je, n_g, area, 1)
2881  if( master ) write(*,*) 'Total surface pressure (mb)', trim(gn), ' = ', 0.01*psmo
2882  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,1 ), psqv(is,js))
2883  return
2884  endif
2885 
2886  psq(:,:,:) = 0.
2887  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,sphum ), psq(is,js,sphum ))
2888 
2889  if (liq_wat > 0) &
2890  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,liq_wat), psq(is,js,liq_wat))
2891 
2892  if (rainwat > 0) &
2893  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,rainwat), psq(is,js,rainwat))
2894 
2895 !nwat == 4 => KESSLER, ice is probably garbage...
2896  if (ice_wat > 0) &
2897  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,ice_wat), psq(is,js,ice_wat))
2898 
2899  if (snowwat > 0) &
2900  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,snowwat), psq(is,js,snowwat))
2901  if (graupel > 0) &
2902  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,graupel), psq(is,js,graupel))
2903 
2904 
2905 ! Mean water vapor in the "stratosphere" (75 mb and above):
2906  if ( idiag%phalf(2)< 75. ) then
2907  kstrat = 1
2908  do k=1,km
2909  if ( idiag%phalf(k+1) > 75. ) exit
2910  kstrat = k
2911  enddo
2912  call z_sum(is, ie, js, je, kstrat, n_g, delp, q(is-n_g,js-n_g,1,sphum), q_strat(is,js))
2913  psmo = g_sum(domain, q_strat(is,js), is, ie, js, je, n_g, area, 1) * 1.e6 &
2914  / p_sum(is, ie, js, je, kstrat, n_g, delp, area, domain)
2915  if(master) write(*,*) 'Mean specific humidity (mg/kg) above 75 mb', trim(gn), '=', psmo
2916  endif
2917 
2918 
2919 !-------------------
2920 ! Check global means
2921 !-------------------
2922  psmo = g_sum(domain, ps(is:ie,js:je), is, ie, js, je, n_g, area, 1)
2923 
2924  do n=1,nwat
2925  qtot(n) = g_sum(domain, psq(is,js,n), is, ie, js, je, n_g, area, 1)
2926  enddo
2927 
2928  totw = sum(qtot(1:nwat))
2929  psdry = psmo - totw
2930 
2931  if( master ) then
2932  write(*,*) 'Total surface pressure (mb)', trim(gn), ' = ', 0.01*psmo
2933  write(*,*) 'mean dry surface pressure', trim(gn), ' = ', 0.01*psdry
2934  write(*,*) 'Total Water Vapor (kg/m**2)', trim(gn), ' =', qtot(sphum)*ginv
2935  if ( nwat> 2 ) then
2936  write(*,*) '--- Micro Phys water substances (kg/m**2) ---'
2937  write(*,*) 'Total cloud water', trim(gn), '=', qtot(liq_wat)*ginv
2938  if (rainwat > 0) &
2939  write(*,*) 'Total rain water', trim(gn), '=', qtot(rainwat)*ginv
2940  if (ice_wat > 0) &
2941  write(*,*) 'Total cloud ice ', trim(gn), '=', qtot(ice_wat)*ginv
2942  if (snowwat > 0) &
2943  write(*,*) 'Total snow ', trim(gn), '=', qtot(snowwat)*ginv
2944  if (graupel > 0) &
2945  write(*,*) 'Total graupel ', trim(gn), '=', qtot(graupel)*ginv
2946  write(*,*) '---------------------------------------------'
2947  elseif ( nwat==2 ) then
2948  write(*,*) 'GFS condensate (kg/m^2)', trim(gn), '=', qtot(liq_wat)*ginv
2949  endif
2950  endif
2951 
2952  end subroutine prt_mass
2953 
2954 
2955  subroutine z_sum(is, ie, js, je, km, n_g, delp, q, sum2)
2956  integer, intent(in):: is, ie, js, je, n_g, km
2957  real, intent(in):: delp(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2958  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2959  real, intent(out):: sum2(is:ie,js:je)
2960 
2961  integer i,j,k
2962 
2963  do j=js,je
2964  do i=is,ie
2965  sum2(i,j) = delp(i,j,1)*q(i,j,1)
2966  enddo
2967  do k=2,km
2968  do i=is,ie
2969  sum2(i,j) = sum2(i,j) + delp(i,j,k)*q(i,j,k)
2970  enddo
2971  enddo
2972  enddo
2973 
2974  end subroutine z_sum
2975 
2976 
2977  real function p_sum(is, ie, js, je, km, n_g, delp, area, domain)
2978  integer, intent(in):: is, ie, js, je, n_g, km
2979  real, intent(in):: delp(is-n_g:ie+n_g, js-n_g:je+n_g, km)
2980  real(kind=R_GRID), intent(IN) :: area(is-n_g:ie+n_g, js-n_g:je+n_g)
2981  real :: sum2(is:ie,js:je)
2982  integer i,j,k
2983  type(domain2d), intent(INOUT) :: domain
2984 
2985 !$OMP parallel do default(none) shared(is,ie,js,je,km,sum2,delp)
2986  do j=js,je
2987  do i=is,ie
2988  sum2(i,j) = delp(i,j,1)
2989  enddo
2990  do k=2,km
2991  do i=is,ie
2992  sum2(i,j) = sum2(i,j) + delp(i,j,k)
2993  enddo
2994  enddo
2995  enddo
2996  p_sum = g_sum(domain, sum2, is, ie, js, je, n_g, area, 1)
2997 
2998  end function p_sum
2999 
3000 
3001 
3002  subroutine get_pressure_given_height(is, ie, js, je, ng, km, wz, kd, height, &
3003  ts, peln, a2, fac)
3005  integer, intent(in):: is, ie, js, je, km, ng
3006  integer, intent(in):: kd ! vertical dimension of the ouput height
3007  real, intent(in):: wz(is:ie,js:je,km+1)
3008  real, intent(in):: ts(is-ng:ie+ng,js-ng:je+ng)
3009  real, intent(in):: peln(is:ie,km+1,js:je)
3010  real, intent(in):: height(kd) ! must be monotonically decreasing with increasing k
3011  real, intent(out):: a2(is:ie,js:je,kd) ! pressure (pa)
3012  real, optional, intent(in):: fac
3013 
3014 ! local:
3015  integer n, i,j,k
3016  real ptmp, tm
3017 
3018 
3019  do n=1,kd
3020 
3021 !$OMP parallel do default(none) shared(is,ie,js,je,n,height,wz,km,peln,a2,ginv,ts,fac) &
3022 !$OMP private(ptmp, tm)
3023  do j=js,je
3024 
3025  do 1000 i=is,ie
3026 
3027  if ( height(n) >= wz(i,j,km+1) ) then
3028 !---------------------
3029 ! Search from top down
3030 !---------------------
3031  do k=1,km
3032  if( height(n) < wz(i,j,k) .and. height(n) >= wz(i,j,k+1) ) then
3033 ! Found it!
3034  ptmp = peln(i,k,j) + (peln(i,k+1,j)-peln(i,k,j)) * &
3035  (wz(i,j,k)-height(n)) / (wz(i,j,k)-wz(i,j,k+1))
3036  a2(i,j,n) = exp(ptmp)
3037  go to 500
3038  endif
3039  enddo
3040 
3041  else
3042 !-----------------------------------------
3043 ! xtrapolation: mean laspe rate 6.5 deg/km
3044 !-----------------------------------------
3045  tm = rdgas*ginv*(ts(i,j) + 3.25e-3*(wz(i,j,km)-height(n)))
3046  a2(i,j,n) = exp( peln(i,km+1,j) + (wz(i,j,km+1) - height(n))/tm )
3047  endif
3048 500 if ( present(fac) ) a2(i,j,n) = fac * a2(i,j,n)
3049 1000 continue
3050  enddo
3051  enddo
3052 
3053  end subroutine get_pressure_given_height
3054 
3055  subroutine get_height_given_pressure(is, ie, js, je, ng, km, wz, kd, id, log_p, peln, a2)
3056  integer, intent(in):: is, ie, js, je, ng, km
3057  integer, intent(in):: kd ! vertical dimension of the ouput height
3058  integer, intent(in):: id(kd)
3059  real, intent(in):: log_p(kd) ! must be monotonically increasing with increasing k
3060  ! log (p)
3061  real, intent(in):: wz(is:ie,js:je,km+1)
3062  real, intent(in):: peln(is:ie,km+1,js:je)
3063  real, intent(out):: a2(is:ie,js:je,kd) ! height (m)
3064 ! local:
3065  integer n,i,j,k, k1
3066 
3067 !$OMP parallel do default(none) shared(is,ie,js,je,km,kd,id,log_p,peln,a2,wz) &
3068 !$OMP private(i,j,n,k,k1)
3069  do j=js,je
3070  do i=is,ie
3071  k1 = 1
3072  do 1000 n=1,kd
3073  if( id(n)<0 ) goto 1000
3074  do k=k1,km
3075  if( log_p(n) <= peln(i,k+1,j) .and. log_p(n) >= peln(i,k,j) ) then
3076  a2(i,j,n) = wz(i,j,k) + (wz(i,j,k+1) - wz(i,j,k)) * &
3077  (log_p(n)-peln(i,k,j)) / (peln(i,k+1,j)-peln(i,k,j) )
3078  k1 = k
3079  go to 1000
3080  endif
3081  enddo
3082 ! a2(i,j,n) = missing_value
3083 ! Extrapolation into ground: use lowest 4-layer mean
3084  a2(i,j,n) = wz(i,j,km+1) + (wz(i,j,km+1) - wz(i,j,km-3)) * &
3085  (log_p(n)-peln(i,km+1,j)) / (peln(i,km+1,j)-peln(i,km-3,j) )
3086  k1 = km
3087 1000 continue
3088  enddo
3089  enddo
3090 
3091  end subroutine get_height_given_pressure
3092 
3093  subroutine cs3_interpolator(is, ie, js, je, km, qin, kd, pout, wz, pe, id, qout, iv)
3094 ! iv =-1: winds
3095 ! iv = 0: positive definite scalars
3096 ! iv = 1: temperature
3097  integer, intent(in):: is, ie, js, je, km, iv
3098  integer, intent(in):: kd ! vertical dimension of the ouput height
3099  integer, intent(in):: id(kd)
3100  real, intent(in):: pout(kd) ! must be monotonically increasing with increasing k
3101  real, intent(in):: pe(is:ie,km+1,js:je)
3102  real, intent(in):: qin(is:ie,js:je,km)
3103  real, intent(in):: wz(is:ie,js:je,km+1)
3104  real, intent(out):: qout(is:ie,js:je,kd)
3105 ! local:
3106  real, parameter:: gcp = grav / cp_air
3107  real:: qe(is:ie,km+1)
3108  real, dimension(is:ie,km):: q2, dp
3109  real:: s0, a6
3110  integer:: i,j,k, n, k1
3111 
3112 !$OMP parallel do default(none) shared(iv,id,is,ie,js,je,km,kd,pout,qin,qout,pe,wz) &
3113 !$OMP private(k1,s0,a6,q2,dp,qe)
3114  do j=js,je
3115 
3116  do i=is,ie
3117  do k=1,km
3118  dp(i,k) = pe(i,k+1,j) - pe(i,k,j)
3119  q2(i,k) = qin(i,j,k)
3120  enddo
3121  enddo
3122 
3123  call cs_prof(q2, dp, qe, km, is, ie, iv)
3124 
3125  do i=is,ie
3126  k1 = 1
3127  do n=1,kd
3128  if ( id(n) > 0 ) then
3129  if( pout(n) <= pe(i,1,j) ) then
3130 ! Higher than the top:
3131  qout(i,j,n) = qe(i,1)
3132  elseif ( pout(n) >= pe(i,km+1,j) ) then
3133 ! lower than the bottom surface:
3134  if ( iv==1 ) then ! Temperature
3135 ! lower than the bottom surface:
3136 ! mean (hydro) potential temp based on lowest 2-3 layers (NCEP method)
3137 ! temp = ptm * p**cappa = ptm * exp(cappa*log(pout))
3138  qout(i,j,n) = gcp*exp(kappa*pout(n)) * (wz(i,j,km-2) - wz(i,j,km)) / &
3139  ( exp(kappa*pe(i,km,j)) - exp(kappa*pe(i,km-2,j)) )
3140  else
3141  qout(i,j,n) = qe(i,km+1)
3142  endif
3143  else
3144  do k=k1,km
3145  if ( pout(n)>=pe(i,k,j) .and. pout(n) <= pe(i,k+1,j) ) then
3146 ! PPM distribution: f(s) = AL + s*[(AR-AL) + A6*(1-s)] ( 0 <= s <= 1 )
3147  a6 = 3.*(2.*q2(i,k) - (qe(i,k)+qe(i,k+1)))
3148  s0 = (pout(n)-pe(i,k,j)) / dp(i,k)
3149  qout(i,j,n) = qe(i,k) + s0*(qe(i,k+1)-qe(i,k)+a6*(1.-s0))
3150  k1 = k ! next level
3151  go to 500
3152  endif
3153  enddo
3154  endif
3155 500 if ( iv==0 ) qout(i,j,n) = max(0., qout(i,j,n))
3156  endif
3157  enddo
3158  enddo
3159  enddo
3160 
3161 ! Send_data here
3162 
3163  end subroutine cs3_interpolator
3164 
3165  subroutine cs_interpolator(is, ie, js, je, km, qin, kd, pout, pe, id, qout, iv)
3166 ! This is the old-style linear in log-p interpolation
3167  integer, intent(in):: is, ie, js, je, km
3168  integer, intent(in):: kd ! vertical dimension of the ouput height
3169  integer, intent(in):: id(kd)
3170  integer, optional, intent(in):: iv
3171  real, intent(in):: pout(kd) ! must be monotonically increasing with increasing k
3172  real, intent(in):: pe(is:ie,km+1,js:je)
3173  real, intent(in):: qin(is:ie,js:je,km)
3174  real, intent(out):: qout(is:ie,js:je,kd)
3175 ! local:
3176  real:: pm(km)
3177  integer i,j,k, n, k1
3178 
3179 !$OMP parallel do default(none) shared(id,is,ie,js,je,km,kd,pout,qin,qout,pe) &
3180 !$OMP private(k1,pm)
3181  do j=js,je
3182  do i=is,ie
3183  do k=1,km
3184 ! consider using true log(p) here for non-hydro?
3185  pm(k) = 0.5*(pe(i,k,j)+pe(i,k+1,j))
3186  enddo
3187 
3188  k1 = 1
3189  do n=1,kd
3190  if ( id(n) < 0 ) go to 500
3191  if( pout(n) <= pm(1) ) then
3192 ! Higher than the top: using constant value
3193  qout(i,j,n) = qin(i,j,1)
3194  elseif ( pout(n) >= pm(km) ) then
3195 ! lower than the bottom surface:
3196  qout(i,j,n) = qin(i,j,km)
3197  else
3198  do k=k1,km-1
3199  if ( pout(n)>=pm(k) .and. pout(n) <= pm(k+1) ) then
3200  qout(i,j,n) = qin(i,j,k) + (qin(i,j,k+1)-qin(i,j,k))*(pout(n)-pm(k))/(pm(k+1)-pm(k))
3201  k1 = k ! next level
3202  go to 500
3203  endif
3204  enddo
3205  endif
3206 500 continue
3207  enddo
3208  enddo
3209  enddo
3210 
3211  end subroutine cs_interpolator
3212 
3213  subroutine cs_prof(q2, delp, q, km, i1, i2, iv)
3214 ! Latest: Dec 2015 S.-J. Lin, NOAA/GFDL
3215  integer, intent(in):: i1, i2, km
3216  integer, intent(in):: iv
3217  real, intent(in) :: q2(i1:i2,km)
3218  real, intent(in) :: delp(i1:i2,km) ! layer pressure thickness
3219  real, intent(out):: q(i1:i2,km+1)
3220 !-----------------------------------------------------------------------
3221  real gam(i1:i2,km)
3222  real d4(i1:i2)
3223  real bet, a_bot, grat
3224  integer i, k
3225 
3226  do i=i1,i2
3227  grat = delp(i,2) / delp(i,1) ! grid ratio
3228  bet = grat*(grat+0.5)
3229  q(i,1) = ( (grat+grat)*(grat+1.)*q2(i,1) + q2(i,2) ) / bet
3230  gam(i,1) = ( 1. + grat*(grat+1.5) ) / bet
3231  enddo
3232 
3233  do k=2,km
3234  do i=i1,i2
3235  d4(i) = delp(i,k-1) / delp(i,k)
3236  bet = 2. + d4(i) + d4(i) - gam(i,k-1)
3237  q(i,k) = ( 3.*(q2(i,k-1)+d4(i)*q2(i,k)) - q(i,k-1) )/bet
3238  gam(i,k) = d4(i) / bet
3239  enddo
3240  enddo
3241 
3242  do i=i1,i2
3243  a_bot = 1. + d4(i)*(d4(i)+1.5)
3244  q(i,km+1) = (2.*d4(i)*(d4(i)+1.)*q2(i,km)+q2(i,km-1)-a_bot*q(i,km)) &
3245  / ( d4(i)*(d4(i)+0.5) - a_bot*gam(i,km) )
3246  enddo
3247 
3248  do k=km,1,-1
3249  do i=i1,i2
3250  q(i,k) = q(i,k) - gam(i,k)*q(i,k+1)
3251  enddo
3252  enddo
3253 
3254 ! Apply *large-scale* constraints
3255  do i=i1,i2
3256  q(i,2) = min( q(i,2), max(q2(i,1), q2(i,2)) )
3257  q(i,2) = max( q(i,2), min(q2(i,1), q2(i,2)) )
3258  enddo
3259 
3260  do k=2,km
3261  do i=i1,i2
3262  gam(i,k) = q2(i,k) - q2(i,k-1)
3263  enddo
3264  enddo
3265 
3266 ! Interior:
3267  do k=3,km-1
3268  do i=i1,i2
3269  if ( gam(i,k-1)*gam(i,k+1)>0. ) then
3270 ! Apply large-scale constraint to ALL fields if not local max/min
3271  q(i,k) = min( q(i,k), max(q2(i,k-1),q2(i,k)) )
3272  q(i,k) = max( q(i,k), min(q2(i,k-1),q2(i,k)) )
3273  else
3274  if ( gam(i,k-1) > 0. ) then
3275 ! There exists a local max
3276  q(i,k) = max(q(i,k), min(q2(i,k-1),q2(i,k)))
3277  else
3278 ! There exists a local min
3279  q(i,k) = min(q(i,k), max(q2(i,k-1),q2(i,k)))
3280  if ( iv==0 ) q(i,k) = max(0., q(i,k))
3281  endif
3282  endif
3283  enddo
3284  enddo
3285 
3286 ! Bottom:
3287  do i=i1,i2
3288  q(i,km) = min( q(i,km), max(q2(i,km-1), q2(i,km)) )
3289  q(i,km) = max( q(i,km), min(q2(i,km-1), q2(i,km)) )
3290  enddo
3291 
3292  end subroutine cs_prof
3293 
3294 
3295  subroutine interpolate_vertical(is, ie, js, je, km, plev, peln, a3, a2)
3297  integer, intent(in):: is, ie, js, je, km
3298  real, intent(in):: peln(is:ie,km+1,js:je)
3299  real, intent(in):: a3(is:ie,js:je,km)
3300  real, intent(in):: plev
3301  real, intent(out):: a2(is:ie,js:je)
3302 ! local:
3303  real pm(km)
3304  real logp
3305  integer i,j,k
3306 
3307  logp = log(plev)
3308 
3309 !$OMP parallel do default(none) shared(is,ie,js,je,km,peln,logp,a2,a3) &
3310 !$OMP private(pm)
3311  do j=js,je
3312  do 1000 i=is,ie
3313 
3314  do k=1,km
3315  pm(k) = 0.5*(peln(i,k,j)+peln(i,k+1,j))
3316  enddo
3317 
3318  if( logp <= pm(1) ) then
3319  a2(i,j) = a3(i,j,1)
3320  elseif ( logp >= pm(km) ) then
3321  a2(i,j) = a3(i,j,km)
3322  else
3323  do k=1,km-1
3324  if( logp <= pm(k+1) .and. logp >= pm(k) ) then
3325  a2(i,j) = a3(i,j,k) + (a3(i,j,k+1)-a3(i,j,k))*(logp-pm(k))/(pm(k+1)-pm(k))
3326  go to 1000
3327  endif
3328  enddo
3329  endif
3330 1000 continue
3331  enddo
3332 
3333  end subroutine interpolate_vertical
3334 
3335 
3336  subroutine interpolate_z(is, ie, js, je, km, zl, hght, a3, a2)
3338  integer, intent(in):: is, ie, js, je, km
3339  real, intent(in):: hght(is:ie,js:je,km+1) ! hght(k) > hght(k+1)
3340  real, intent(in):: a3(is:ie,js:je,km)
3341  real, intent(in):: zl
3342  real, intent(out):: a2(is:ie,js:je)
3343 ! local:
3344  real zm(km)
3345  integer i,j,k
3346 
3347 
3348 !$OMP parallel do default(none) shared(is,ie,js,je,km,hght,zl,a2,a3) private(zm)
3349  do j=js,je
3350  do 1000 i=is,ie
3351  do k=1,km
3352  zm(k) = 0.5*(hght(i,j,k)+hght(i,j,k+1))
3353  enddo
3354  if( zl >= zm(1) ) then
3355  a2(i,j) = a3(i,j,1)
3356  elseif ( zl <= zm(km) ) then
3357  a2(i,j) = a3(i,j,km)
3358  else
3359  do k=1,km-1
3360  if( zl <= zm(k) .and. zl >= zm(k+1) ) then
3361  a2(i,j) = a3(i,j,k) + (a3(i,j,k+1)-a3(i,j,k))*(zm(k)-zl)/(zm(k)-zm(k+1))
3362  go to 1000
3363  endif
3364  enddo
3365  endif
3366 1000 continue
3367  enddo
3368 
3369  end subroutine interpolate_z
3370 
3371  subroutine helicity_relative(is, ie, js, je, ng, km, zvir, sphum, srh, &
3372  ua, va, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
3373 ! !INPUT PARAMETERS:
3374  integer, intent(in):: is, ie, js, je, ng, km, sphum
3375  real, intent(in):: grav, zvir, z_bot, z_top
3376  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt, ua, va
3377  real, intent(in):: delz(is-ng:ie+ng,js-ng:je+ng,km)
3378  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
3379  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
3380  real, intent(in):: peln(is:ie,km+1,js:je)
3381  logical, intent(in):: hydrostatic
3382  real, intent(out):: srh(is:ie,js:je) ! unit: (m/s)**2
3383 ! real, parameter:: z_crit = 3.e3 ! lowest 3-km
3384 !---------------------------------------------------------------------------------
3385 ! SRH = 150-299 ... supercells possible with weak tornadoes
3386 ! SRH = 300-449 ... very favourable to supercells development and strong tornadoes
3387 ! SRH > 450 ... violent tornadoes
3388 !---------------------------------------------------------------------------------
3389 ! if z_top = 1E3, the threshold for supercells is 100 (m/s)**2
3390 ! Coded by S.-J. Lin for CONUS regional climate simulations
3391 !
3392  real:: rdg
3393  real, dimension(is:ie):: zh, uc, vc, dz, zh0
3394  integer i, j, k, k0, k1
3395  logical below(is:ie)
3396 
3397  rdg = rdgas / grav
3398 
3399 !$OMP parallel do default(none) shared(is,ie,js,je,km,hydrostatic,rdg,pt,zvir,sphum, &
3400 !$OMP peln,delz,ua,va,srh,z_bot,z_top) &
3401 !$OMP private(zh,uc,vc,dz,k0,k1,zh0,below)
3402  do j=js,je
3403 
3404  do i=is,ie
3405  uc(i) = 0.
3406  vc(i) = 0.
3407  zh(i) = 0.
3408  srh(i,j) = 0.
3409  below(i) = .true.
3410  zh0(i) = 0.
3411 
3412 ! if ( phis(i,j)/grav < 1.E3 ) then
3413  do k=km,1,-1
3414  if ( hydrostatic ) then
3415  dz(i) = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
3416  else
3417  dz(i) = - delz(i,j,k)
3418  endif
3419  zh(i) = zh(i) + dz(i)
3420  if (zh(i) <= z_bot ) continue
3421  if (zh(i) > z_bot .and. below(i)) then
3422  uc(i) = ua(i,j,k)*dz(i)
3423  vc(i) = va(i,j,k)*dz(i)
3424  zh0(i) = zh(i) - dz(i)
3425  k1 = k
3426  below(i) = .false.
3427 ! Compute mean winds below z_top
3428  elseif ( zh(i) < z_top ) then
3429  uc(i) = uc(i) + ua(i,j,k)*dz(i)
3430  vc(i) = vc(i) + va(i,j,k)*dz(i)
3431  k0 = k
3432  else
3433  uc(i) = uc(i) / (zh(i)-dz(i) - zh0(i))
3434  vc(i) = vc(i) / (zh(i)-dz(i) - zh0(i))
3435  goto 123
3436  endif
3437  enddo
3438 123 continue
3439 
3440 ! Lowest layer wind shear computed betw top edge and mid-layer
3441  k = k1
3442  srh(i,j) = 0.5*(va(i,j,k1)-vc(i))*(ua(i,j,k1-1)-ua(i,j,k1)) - &
3443  0.5*(ua(i,j,k1)-uc(i))*(va(i,j,k1-1)-va(i,j,k1))
3444  do k=k0, k1-1
3445  srh(i,j) = srh(i,j) + 0.5*(va(i,j,k)-vc(i))*(ua(i,j,k-1)-ua(i,j,k+1)) - &
3446  0.5*(ua(i,j,k)-uc(i))*(va(i,j,k-1)-va(i,j,k+1))
3447  enddo
3448 ! endif
3449  enddo ! i-loop
3450  enddo ! j-loop
3451 
3452  end subroutine helicity_relative
3453 
3454  subroutine updraft_helicity(is, ie, js, je, ng, km, zvir, sphum, uh, &
3455  w, vort, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
3456 ! !INPUT PARAMETERS:
3457  integer, intent(in):: is, ie, js, je, ng, km, sphum
3458  real, intent(in):: grav, zvir, z_bot, z_top
3459  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt, w
3460  real, intent(in), dimension(is:ie,js:je,km):: vort
3461  real, intent(in):: delz(is-ng:ie+ng,js-ng:je+ng,km)
3462  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
3463  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
3464  real, intent(in):: peln(is:ie,km+1,js:je)
3465  logical, intent(in):: hydrostatic
3466  real, intent(out):: uh(is:ie,js:je) ! unit: (m/s)**2
3467 ! Coded by S.-J. Lin for CONUS regional climate simulations
3468 ! Modified for UH by LMH
3469 !
3470  real:: rdg
3471  real, dimension(is:ie):: zh, dz, zh0
3472  integer i, j, k
3473  logical below(is:ie)
3474 
3475  rdg = rdgas / grav
3476 
3477 !$OMP parallel do default(none) shared(is,ie,js,je,km,hydrostatic,rdg,pt,zvir,sphum, &
3478 !$OMP peln,delz,w,vort,uh,z_bot,z_top) &
3479 !$OMP private(zh,dz,zh0,below)
3480  do j=js,je
3481 
3482  do i=is,ie
3483  zh(i) = 0.
3484  uh(i,j) = 0.
3485  below(i) = .true.
3486  zh0(i) = 0.
3487 
3488 ! if ( phis(i,j)/grav < 1.E3 ) then
3489  do k=km,1,-1
3490  if ( hydrostatic ) then
3491  dz(i) = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
3492  else
3493  dz(i) = - delz(i,j,k)
3494  endif
3495  zh(i) = zh(i) + dz(i)
3496  if (zh(i) <= z_bot ) continue
3497  if (zh(i) > z_bot .and. below(i)) then
3498  uh(i,j) = vort(i,j,k)*w(i,j,k)*(zh(i) - z_bot)
3499  below(i) = .false.
3500 ! Compute mean winds below z_top
3501  elseif ( zh(i) < z_top ) then
3502  uh(i,j) = uh(i,j) + vort(i,j,k)*w(i,j,k)*dz(i)
3503  else
3504  uh(i,j) = uh(i,j) + vort(i,j,k)*w(i,j,k)*(z_top - (zh(i)-dz(i)) )
3505  goto 123
3506  endif
3507  enddo
3508 123 continue
3509 
3510  enddo ! i-loop
3511  enddo ! j-loop
3512 
3513  end subroutine updraft_helicity
3514 
3515 
3516 
3517  subroutine pv_entropy(is, ie, js, je, ng, km, vort, f_d, pt, pkz, delp, grav)
3519 ! !INPUT PARAMETERS:
3520  integer, intent(in):: is, ie, js, je, ng, km
3521  real, intent(in):: grav
3522  real, intent(in):: pt(is-ng:ie+ng,js-ng:je+ng,km)
3523  real, intent(in):: pkz(is:ie,js:je,km)
3524  real, intent(in):: delp(is-ng:ie+ng,js-ng:je+ng,km)
3525  real, intent(in):: f_d(is-ng:ie+ng,js-ng:je+ng)
3526 
3527 ! vort is relative vorticity as input. Becomes PV on output
3528  real, intent(inout):: vort(is:ie,js:je,km)
3529 
3530 ! !DESCRIPTION:
3531 ! EPV = 1/r * (vort+f_d) * d(S)/dz; where S is a conservative scalar
3532 ! r the fluid density, and S is chosen to be the entropy here: S = log(pt)
3533 ! pt == potential temperature.
3534 ! Computation are performed assuming the input is on "x-y-z" Cartesian coordinate.
3535 ! The approximation made here is that the relative vorticity computed on constant
3536 ! z-surface is not that different from the hybrid sigma-p coordinate.
3537 ! See page 39, Pedlosky 1979: Geophysical Fluid Dynamics
3538 !
3539 ! The follwoing simplified form is strictly correct only if vort is computed on
3540 ! constant z surfaces. In addition hydrostatic approximation is made.
3541 ! EPV = - GRAV * (vort+f_d) / del(p) * del(pt) / pt
3542 ! where del() is the vertical difference operator.
3543 !
3544 ! programmer: S.-J. Lin, shian-jiann.lin@noaa.gov
3545 !
3546 !EOP
3547 !---------------------------------------------------------------------
3548 !BOC
3549  real w3d(is:ie,js:je,km)
3550  real te(is:ie,js:je,km+1), t2(is:ie,km), delp2(is:ie,km)
3551  real te2(is:ie,km+1)
3552  integer i, j, k
3553 
3554 #ifdef SW_DYNAMICS
3555 !$OMP parallel do default(none) shared(is,ie,js,je,vort,grav,f_d,delp)
3556  do j=js,je
3557  do i=is,ie
3558  vort(i,j,1) = grav * (vort(i,j,1)+f_d(i,j)) / delp(i,j,1)
3559  enddo
3560  enddo
3561 #else
3562 ! Compute PT at layer edges.
3563 !$OMP parallel do default(none) shared(is,ie,js,je,km,pt,pkz,w3d,delp,te2,te) &
3564 !$OMP private(t2, delp2)
3565  do j=js,je
3566  do k=1,km
3567  do i=is,ie
3568  t2(i,k) = pt(i,j,k) / pkz(i,j,k)
3569  w3d(i,j,k) = t2(i,k)
3570  delp2(i,k) = delp(i,j,k)
3571  enddo
3572  enddo
3573 
3574  call ppme(t2, te2, delp2, ie-is+1, km)
3575 
3576  do k=1,km+1
3577  do i=is,ie
3578  te(i,j,k) = te2(i,k)
3579  enddo
3580  enddo
3581  enddo
3582 
3583 !$OMP parallel do default(none) shared(is,ie,js,je,km,vort,f_d,te,w3d,delp,grav)
3584  do k=1,km
3585  do j=js,je
3586  do i=is,ie
3587 ! Entropy is the thermodynamic variable in the following form
3588  vort(i,j,k) = (vort(i,j,k)+f_d(i,j)) * ( te(i,j,k)-te(i,j,k+1) ) &
3589  / ( w3d(i,j,k)*delp(i,j,k) ) * grav
3590  enddo
3591  enddo
3592  enddo
3593 #endif
3594 
3595  end subroutine pv_entropy
3596 
3597 
3598  subroutine ppme(p,qe,delp,im,km)
3600  integer, intent(in):: im, km
3601  real, intent(in):: p(im,km)
3602  real, intent(in):: delp(im,km)
3603  real, intent(out)::qe(im,km+1)
3604 
3605 ! local arrays.
3606  real dc(im,km),delq(im,km), a6(im,km)
3607  real c1, c2, c3, tmp, qmax, qmin
3608  real a1, a2, s1, s2, s3, s4, ss3, s32, s34, s42
3609  real a3, b2, sc, dm, d1, d2, f1, f2, f3, f4
3610  real qm, dq
3611  integer i, k, km1
3612 
3613  km1 = km - 1
3614 
3615  do 500 k=2,km
3616  do 500 i=1,im
3617 500 a6(i,k) = delp(i,k-1) + delp(i,k)
3618 
3619  do 1000 k=1,km1
3620  do 1000 i=1,im
3621  delq(i,k) = p(i,k+1) - p(i,k)
3622 1000 continue
3623 
3624  do 1220 k=2,km1
3625  do 1220 i=1,im
3626  c1 = (delp(i,k-1)+0.5*delp(i,k))/a6(i,k+1)
3627  c2 = (delp(i,k+1)+0.5*delp(i,k))/a6(i,k)
3628  tmp = delp(i,k)*(c1*delq(i,k) + c2*delq(i,k-1)) / &
3629  (a6(i,k)+delp(i,k+1))
3630  qmax = max(p(i,k-1),p(i,k),p(i,k+1)) - p(i,k)
3631  qmin = p(i,k) - min(p(i,k-1),p(i,k),p(i,k+1))
3632  dc(i,k) = sign(min(abs(tmp),qmax,qmin), tmp)
3633 1220 continue
3634 
3635 !****6***0*********0*********0*********0*********0*********0**********72
3636 ! 4th order interpolation of the provisional cell edge value
3637 !****6***0*********0*********0*********0*********0*********0**********72
3638 
3639  do k=3,km1
3640  do i=1,im
3641  c1 = delq(i,k-1)*delp(i,k-1) / a6(i,k)
3642  a1 = a6(i,k-1) / (a6(i,k) + delp(i,k-1))
3643  a2 = a6(i,k+1) / (a6(i,k) + delp(i,k))
3644  qe(i,k) = p(i,k-1) + c1 + 2./(a6(i,k-1)+a6(i,k+1)) * &
3645  ( delp(i,k)*(c1*(a1 - a2)+a2*dc(i,k-1)) - &
3646  delp(i,k-1)*a1*dc(i,k ) )
3647  enddo
3648  enddo
3649 
3650 ! three-cell parabolic subgrid distribution at model top
3651 
3652  do i=1,im
3653 ! three-cell PP-distribution
3654 ! Compute a,b, and c of q = aP**2 + bP + c using cell averages and delp
3655 ! a3 = a / 3
3656 ! b2 = b / 2
3657  s1 = delp(i,1)
3658  s2 = delp(i,2) + s1
3659 !
3660  s3 = delp(i,2) + delp(i,3)
3661  s4 = s3 + delp(i,4)
3662  ss3 = s3 + s1
3663  s32 = s3*s3
3664  s42 = s4*s4
3665  s34 = s3*s4
3666 ! model top
3667  a3 = (delq(i,2) - delq(i,1)*s3/s2) / (s3*ss3)
3668 !
3669  if(abs(a3) .gt. 1.e-14) then
3670  b2 = delq(i,1)/s2 - a3*(s1+s2)
3671  sc = -b2/(3.*a3)
3672  if(sc .lt. 0. .or. sc .gt. s1) then
3673  qe(i,1) = p(i,1) - s1*(a3*s1 + b2)
3674  else
3675  qe(i,1) = p(i,1) - delq(i,1)*s1/s2
3676  endif
3677  else
3678 ! Linear
3679  qe(i,1) = p(i,1) - delq(i,1)*s1/s2
3680  endif
3681  dc(i,1) = p(i,1) - qe(i,1)
3682 ! compute coef. for the off-centered area preserving cubic poly.
3683  dm = delp(i,1) / (s34*ss3*(delp(i,2)+s3)*(s4+delp(i,1)))
3684  f1 = delp(i,2)*s34 / ( s2*ss3*(s4+delp(i,1)) )
3685  f2 = (delp(i,2)+s3) * (ss3*(delp(i,2)*s3+s34+delp(i,2)*s4) &
3686  + s42*(delp(i,2)+s3+s32/s2))
3687  f3 = -delp(i,2)*( ss3*(s32*(s3+s4)/(s4-delp(i,2)) &
3688  + (delp(i,2)*s3+s34+delp(i,2)*s4)) &
3689  + s42*(delp(i,2)+s3) )
3690  f4 = ss3*delp(i,2)*s32*(delp(i,2)+s3) / (s4-delp(i,2))
3691  qe(i,2) = f1*p(i,1)+(f2*p(i,2)+f3*p(i,3)+f4*p(i,4))*dm
3692  enddo
3693 
3694 ! Bottom
3695 ! Area preserving cubic with 2nd deriv. = 0 at the surface
3696  do i=1,im
3697  d1 = delp(i,km)
3698  d2 = delp(i,km1)
3699  qm = (d2*p(i,km)+d1*p(i,km1)) / (d1+d2)
3700  dq = 2.*(p(i,km1)-p(i,km)) / (d1+d2)
3701  c1 = (qe(i,km1)-qm-d2*dq) / (d2*(2.*d2*d2+d1*(d2+3.*d1)))
3702  c3 = dq - 2.0*c1*(d2*(5.*d1+d2)-3.*d1**2)
3703  qe(i,km ) = qm - c1*d1*d2*(d2+3.*d1)
3704  qe(i,km+1) = d1*(8.*c1*d1**2-c3) + qe(i,km)
3705  enddo
3706 
3707  end subroutine ppme
3708 
3709 !#######################################################################
3710 
3711 subroutine rh_calc (pfull, t, qv, rh, do_cmip)
3713  real, intent (in), dimension(:,:) :: pfull, t, qv
3714  real, intent (out), dimension(:,:) :: rh
3715  real, dimension(size(t,1),size(t,2)) :: esat
3716  logical, intent(in), optional :: do_cmip
3717 
3718  real, parameter :: d622 = rdgas/rvgas
3719  real, parameter :: d378 = 1.-d622
3720 
3721  logical :: do_simple = .false.
3722 
3723 ! because Betts-Miller uses a simplified scheme for calculating the relative humidity
3724 
3725  if (do_simple) then
3726  call lookup_es (t, esat)
3727  rh(:,:) = pfull(:,:)
3728  rh(:,:) = max(rh(:,:),esat(:,:)) !limit where pfull ~ esat
3729  rh(:,:)=100.*qv(:,:)/(d622*esat(:,:)/rh(:,:))
3730  else
3731  if (present(do_cmip)) then
3732  call compute_qs (t, pfull, rh, q=qv, es_over_liq_and_ice = .true.)
3733  rh(:,:)=100.*qv(:,:)/rh(:,:)
3734  else
3735  call compute_qs (t, pfull, rh, q=qv)
3736  rh(:,:)=100.*qv(:,:)/rh(:,:)
3737  endif
3738  endif
3739 
3740 end subroutine rh_calc
3741 
3742 subroutine eqv_pot(theta_e, pt, delp, delz, peln, pkz, q, is, ie, js, je, ng, npz, &
3743  hydrostatic, moist)
3744 ! calculate the equvalent potential temperature
3745 ! author: Xi.Chen@noaa.gov
3746 ! created on: 07/28/2015
3747 ! Modified by SJL
3748  integer, intent(in):: is,ie,js,je,ng,npz
3749  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,npz):: pt, delp, q
3750  real, intent(in), dimension(is-ng: ,js-ng: ,1: ):: delz
3751  real, intent(in), dimension(is:ie,npz+1,js:je):: peln
3752  real, intent(in):: pkz(is:ie,js:je,npz)
3753  logical, intent(in):: hydrostatic, moist
3754 ! Output:
3755  real, dimension(is:ie,js:je,npz), intent(out) :: theta_e !< eqv pot
3756 ! local
3757  real, parameter:: cv_vap = cp_vapor - rvgas ! 1384.5
3758  real, parameter:: cappa_b = 0.2854
3759  real(kind=R_GRID):: cv_air, cappa, zvir
3760  real(kind=R_GRID):: p_mb(is:ie)
3761  real(kind=R_GRID) :: r, e, t_l, rdg, capa
3762  integer :: i,j,k
3763 
3764  cv_air = cp_air - rdgas
3765  rdg = -rdgas/grav
3766  if ( moist ) then
3767  zvir = rvgas/rdgas - 1.
3768  else
3769  zvir = 0.
3770  endif
3771 
3772 !$OMP parallel do default(none) shared(moist,pk0,pkz,cv_air,zvir,rdg,is,ie,js,je,npz,pt,q,delp,peln,delz,theta_e,hydrostatic) &
3773 !$OMP private(cappa,p_mb, r, e, t_l, capa)
3774  do k = 1,npz
3775  cappa = cappa_b
3776  do j = js,je
3777 ! get pressure in mb
3778  if ( hydrostatic ) then
3779  do i=is,ie
3780  p_mb(i) = 0.01*delp(i,j,k) / (peln(i,k+1,j) - peln(i,k,j))
3781  enddo
3782  else
3783  do i=is,ie
3784  p_mb(i) = 0.01*rdg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k)*(1.+zvir*q(i,j,k))
3785  enddo
3786  endif
3787  if ( moist ) then
3788  do i = is,ie
3789  cappa = rdgas/(rdgas+((1.-q(i,j,k))*cv_air+q(i,j,k)*cv_vap)/(1.+zvir*q(i,j,k)))
3790 ! get "dry" mixing ratio of m_vapor/m_tot in g/kg
3791  r = q(i,j,k)/(1.-q(i,j,k))*1000.
3792  r = max(1.e-10, r)
3793 ! get water vapor pressure
3794  e = p_mb(i)*r/(622.+r)
3795 ! get temperature at the lifting condensation level
3796 ! eq. 21 of Bolton 1980
3797  t_l = 2840./(3.5*log(pt(i,j,k))-log(e)-4.805)+55.
3798 ! get the equivalent potential temperature
3799 ! theta_e(i,j,k) = pt(i,j,k)*exp( (cappa*(1.-0.28e-3*r)*log(1000./p_mb(i))) * &
3800 ! exp( (3.376/t_l-0.00254)*r*(1.+0.81e-3*r) )
3801  capa = cappa*(1. - r*0.28e-3)
3802  theta_e(i,j,k) = exp( (3.376/t_l-0.00254)*r*(1.+r*0.81e-3) )*pt(i,j,k)*(1000./p_mb(i))**capa
3803  enddo
3804  else
3805  if ( hydrostatic ) then
3806  do i = is,ie
3807  theta_e(i,j,k) = pt(i,j,k)*pk0/pkz(i,j,k)
3808  enddo
3809  else
3810  do i = is,ie
3811  theta_e(i,j,k) = pt(i,j,k)*exp( kappa*log(1000./p_mb(i)) )
3812  enddo
3813  endif
3814  endif
3815  enddo ! j-loop
3816  enddo ! k-loop
3817 
3818 end subroutine eqv_pot
3819 
3820 
3821 #ifndef MAPL_MODE
3822  subroutine nh_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, &
3823  w, delz, pt, delp, q, hs, area, domain, &
3824  sphum, liq_wat, rainwat, ice_wat, &
3825  snowwat, graupel, nwat, ua, va, moist_phys, te)
3826 !------------------------------------------------------
3827 ! Compute vertically integrated total energy per column
3828 !------------------------------------------------------
3829 ! !INPUT PARAMETERS:
3830  integer, intent(in):: km, is, ie, js, je, isd, ied, jsd, jed
3831  integer, intent(in):: nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel
3832  real, intent(in), dimension(isd:ied,jsd:jed,km):: ua, va, pt, delp, w, delz
3833  real, intent(in), dimension(isd:ied,jsd:jed,km,nwat):: q
3834  real, intent(in):: hs(isd:ied,jsd:jed) ! surface geopotential
3835  real, intent(in):: area(isd:ied, jsd:jed)
3836  logical, intent(in):: moist_phys
3837  type(domain2d), intent(INOUT) :: domain
3838  real, intent(out):: te(is:ie,js:je) ! vertically integrated TE
3839 ! Local
3840  real, parameter:: c_liq = 4190. ! heat capacity of water at 0C
3841  real(kind=R_Grid) :: area_l(isd:ied, jsd:jed)
3842  real, parameter:: cv_vap = cp_vapor - rvgas ! 1384.5
3843  real phiz(is:ie,km+1)
3844  real, dimension(is:ie):: cvm, qc
3845  real cv_air, psm
3846  integer i, j, k
3847 
3848  area_l = area
3849  cv_air = cp_air - rdgas
3850 
3851 !$OMP parallel do default(none) shared(te,nwat,is,ie,js,je,isd,ied,jsd,jed,km,ua,va, &
3852 !$OMP w,q,pt,delp,delz,hs,cv_air,moist_phys,sphum,liq_wat,rainwat,ice_wat,snowwat,graupel) &
3853 !$OMP private(phiz,cvm, qc)
3854  do j=js,je
3855 
3856  do i=is,ie
3857  te(i,j) = 0.
3858  phiz(i,km+1) = hs(i,j)
3859  enddo
3860 
3861  do i=is,ie
3862  do k=km,1,-1
3863  phiz(i,k) = phiz(i,k+1) - grav*delz(i,j,k)
3864  enddo
3865  enddo
3866 
3867  if ( moist_phys ) then
3868  do k=1,km
3869  call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, &
3870  ice_wat, snowwat, graupel, q, qc, cvm)
3871  do i=is,ie
3872  te(i,j) = te(i,j) + delp(i,j,k)*( cvm(i)*pt(i,j,k) + hlv*q(i,j,k,sphum) + &
3873  0.5*(phiz(i,k)+phiz(i,k+1)+ua(i,j,k)**2+va(i,j,k)**2+w(i,j,k)**2) )
3874  enddo
3875  enddo
3876  else
3877  do k=1,km
3878  do i=is,ie
3879  te(i,j) = te(i,j) + delp(i,j,k)*( cv_air*pt(i,j,k) + &
3880  0.5*(phiz(i,k)+phiz(i,k+1)+ua(i,j,k)**2+va(i,j,k)**2+w(i,j,k)**2) )
3881  enddo
3882  enddo
3883  endif
3884 ! Unit: kg*(m/s)^2/m^2 = Joule/m^2
3885  do i=is,ie
3886  te(i,j) = te(i,j)/grav
3887  enddo
3888  enddo
3889 
3890  psm = g_sum(domain, te, is, ie, js, je, 3, area_l, 1)
3891  if( master ) write(*,*) 'TE ( Joule/m^2 * E9) =', psm * 1.e-9
3892 
3893  end subroutine nh_total_energy
3894 #endif
3895 
3896  subroutine dbzcalc(q, pt, delp, peln, delz, &
3897  dbz, maxdbz, allmax, bd, npz, ncnst, &
3898  hydrostatic, zvir, in0r, in0s, in0g, iliqskin)
3900  !Code from Mark Stoelinga's dbzcalc.f from the RIP package.
3901  !Currently just using values taken directly from that code, which is
3902  ! consistent for the MM5 Reisner-2 microphysics. From that file:
3903 
3904 ! This routine computes equivalent reflectivity factor (in dBZ) at
3905 ! each model grid point. In calculating Ze, the RIP algorithm makes
3906 ! assumptions consistent with those made in an early version
3907 ! (ca. 1996) of the bulk mixed-phase microphysical scheme in the MM5
3908 ! model (i.e., the scheme known as "Resiner-2"). For each species:
3909 !
3910 ! 1. Particles are assumed to be spheres of constant density. The
3911 ! densities of rain drops, snow particles, and graupel particles are
3912 ! taken to be rho_r = rho_l = 1000 kg m^-3, rho_s = 100 kg m^-3, and
3913 ! rho_g = 400 kg m^-3, respectively. (l refers to the density of
3914 ! liquid water.)
3915 !
3916 ! 2. The size distribution (in terms of the actual diameter of the
3917 ! particles, rather than the melted diameter or the equivalent solid
3918 ! ice sphere diameter) is assumed to follow an exponential
3919 ! distribution of the form N(D) = N_0 * exp( lambda*D ).
3920 !
3921 ! 3. If in0X=0, the intercept parameter is assumed constant (as in
3922 ! early Reisner-2), with values of 8x10^6, 2x10^7, and 4x10^6 m^-4,
3923 ! for rain, snow, and graupel, respectively. Various choices of
3924 ! in0X are available (or can be added). Currently, in0X=1 gives the
3925 ! variable intercept for each species that is consistent with
3926 ! Thompson, Rasmussen, and Manning (2004, Monthly Weather Review,
3927 ! Vol. 132, No. 2, pp. 519-542.)
3928 !
3929 ! 4. If iliqskin=1, frozen particles that are at a temperature above
3930 ! freezing are assumed to scatter as a liquid particle.
3931 !
3932 ! More information on the derivation of simulated reflectivity in RIP
3933 ! can be found in Stoelinga (2005, unpublished write-up). Contact
3934 ! Mark Stoelinga (stoeling@atmos.washington.edu) for a copy.
3935 
3936 ! 22sep16: Modifying to use the Lin MP parameters. If doing so remember
3937 ! that the Lin MP assumes a constant intercept (in0X = .false.)
3938 ! Ferrier-Aligo has an option for fixed slope (rather than fixed intercept).
3939 ! Thompson presumably is an extension of Reisner MP.
3940 
3941  type(fv_grid_bounds_type), intent(IN) :: bd
3942  integer, intent(IN) :: npz, ncnst
3943  real, intent(IN), dimension(bd%isd:bd%ied, bd%jsd:bd%jed, npz) :: pt, delp, delz
3944  real, intent(IN), dimension(bd%isd:bd%ied, bd%jsd:bd%jed, npz, ncnst) :: q
3945  real, intent(IN), dimension(bd%is :bd%ie, npz+1, bd%js:bd%je) :: peln
3946  real, intent(OUT), dimension(bd%is :bd%ie, bd%js :bd%je , npz) :: dbz
3947  real, intent(OUT), dimension(bd%is :bd%ie, bd%js :bd%je) :: maxdbz
3948  logical, intent(IN) :: hydrostatic, in0r, in0s, in0g, iliqskin
3949  real, intent(IN) :: zvir
3950  real, intent(OUT) :: allmax
3951 
3952  !Parameters for constant intercepts (in0[rsg] = .false.)
3953  !Using Lin MP values
3954  real, parameter :: rn0_r = 8.e6 ! m^-4
3955  real, parameter :: rn0_s = 3.e6 ! m^-4
3956  real, parameter :: rn0_g = 4.e6 ! m^-4
3957 
3958  !Constants for variable intercepts
3959  !Will need to be changed based on MP scheme
3960  real, parameter :: r1=1.e-15
3961  real, parameter :: ron=8.e6
3962  real, parameter :: ron2=1.e10
3963  real, parameter :: son=2.e7
3964  real, parameter :: gon=5.e7
3965  real, parameter :: ron_min = 8.e6
3966  real, parameter :: ron_qr0 = 0.00010
3967  real, parameter :: ron_delqr0 = 0.25*ron_qr0
3968  real, parameter :: ron_const1r = (ron2-ron_min)*0.5
3969  real, parameter :: ron_const2r = (ron2+ron_min)*0.5
3970 
3971  !Other constants
3972  real, parameter :: gamma_seven = 720.
3973  real, parameter :: koch_correction = 161.3
3974  !The following values are also used in Lin-Lin MP
3975  real, parameter :: rho_r = 1.0e3 ! LFO83
3976  real, parameter :: rho_s = 100. ! kg m^-3
3977  real, parameter :: rho_g = 400. ! kg m^-3
3978  real, parameter :: alpha = 0.224
3979  real, parameter :: factor_r = gamma_seven * 1.e18 * (1./(pi*rho_r))**1.75
3980  real, parameter :: factor_s = koch_correction * 1.e18 * (1./(pi*rho_s))**1.75 &
3981  * (rho_s/rho_r)**2 * alpha
3982  real, parameter :: factor_g = koch_correction * 1.e18 * (1./(pi*rho_g))**1.75 &
3983  * (rho_g/rho_r)**2 * alpha
3984 !!$ real, parameter :: factor_s = gamma_seven * 1.e18 * (1./(pi*rho_s))**1.75 &
3985 !!$ * (rho_s/rho_r)**2 * alpha
3986 !!$ real, parameter :: factor_g = gamma_seven * 1.e18 * (1./(pi*rho_g))**1.75 &
3987 !!$ * (rho_g/rho_r)**2 * alpha
3988  real, parameter :: tice = 273.16
3989 
3990  integer :: i,j,k
3991  real :: factorb_s, factorb_g, rhoair
3992  real :: temp_c, pres, sonv, gonv, ronv, z_e
3993  real :: qr1, qs1, qg1
3994 
3995  integer :: is, ie, js, je
3996 
3997  is = bd%is
3998  ie = bd%ie
3999  js = bd%js
4000  je = bd%je
4001 
4002  maxdbz(:,:) = -20. !Minimum value
4003  allmax = -20.
4004 
4005  if (rainwat < 1) return
4006 
4007  do k=1, npz
4008  do j=js, je
4009  do i=is, ie
4010 
4011  if (hydrostatic) then
4012  rhoair = delp(i,j,k)/( (peln(i,k+1,j)-peln(i,k,j)) * rdgas * pt(i,j,k) * ( 1. + zvir*q(i,j,k,sphum) ) )
4013  else
4014  rhoair = -delp(i,j,k)/(grav*delz(i,j,k)) ! air density
4015  endif
4016 
4017  ! Adjust factor for brightband, where snow or graupel particle
4018  ! scatters like liquid water (alpha=1.0) because it is assumed to
4019  ! have a liquid skin.
4020 
4021  !lmh: celkel in dbzcalc.f presumably freezing temperature
4022  if (iliqskin .and. pt(i,j,k) .gt. tice) then
4023  factorb_s=factor_s/alpha
4024  factorb_g=factor_g/alpha
4025  else
4026  factorb_s=factor_s
4027  factorb_g=factor_g
4028  endif
4029 
4030  !Calculate variable intercept parameters if necessary
4031  ! using definitions from Thompson et al
4032  if (in0s) then
4033  temp_c = min(-0.001, pt(i,j,k) - tice)
4034  sonv = min(2.0e8, 2.0e6*exp(-0.12*temp_c))
4035  else
4036  sonv = rn0_s
4037  end if
4038 
4039  qr1 = max(0., q(i,j,k,rainwat))
4040  if (graupel > 0) then
4041  qg1 = max(0., q(i,j,k,graupel))
4042  else
4043  qg1 = 0.
4044  endif
4045  if (snowwat > 0) then
4046  qs1 = max(0., q(i,j,k,snowwat))
4047  else
4048  qs1 = 0.
4049  endif
4050 
4051  if (in0g) then
4052  gonv = gon
4053  if ( qg1 > r1) then
4054  gonv = 2.38 * (pi * rho_g / (rhoair*qg1))**0.92
4055  gonv = max(1.e4, min(gonv,gon))
4056  end if
4057  else
4058  gonv = rn0_g
4059  end if
4060 
4061  if (in0r) then
4062  ronv = ron2
4063  if (qr1 > r1 ) then
4064  ronv = ron_const1r * tanh((ron_qr0-qr1)/ron_delqr0) + ron_const2r
4065  end if
4066  else
4067  ronv = rn0_r
4068  end if
4069 
4070  !Total equivalent reflectivity: mm^6 m^-3
4071  z_e = factor_r * (rhoair*qr1)**1.75 / ronv**.75 & ! rain
4072  + factorb_s * (rhoair*qs1)**1.75 / sonv**.75 & ! snow
4073  + factorb_g * (rhoair*qg1)**1.75 / gonv**.75 ! graupel
4074 
4075  !Minimum allowed dbz is -20
4076  z_e = max(z_e,0.01)
4077  dbz(i,j,k) = 10. * log10(z_e)
4078 
4079  maxdbz(i,j) = max(dbz(i,j,k), maxdbz(i,j))
4080  allmax = max(dbz(i,j,k), allmax)
4081 
4082  enddo
4083  enddo
4084  enddo
4085 
4086  end subroutine dbzcalc
4087 
4088 !#######################################################################
4089 
4090 subroutine fv_diag_init_gn(Atm)
4091  type(fv_atmos_type), intent(inout), target :: atm
4092 
4093  if (atm%grid_Number > 1) then
4094  write(gn,"(A2,I1)") " g", atm%grid_number
4095  else
4096  gn = ""
4097  end if
4098 
4099 end subroutine fv_diag_init_gn
4100 end module fv_diagnostics_nlm_mod
subroutine, public eqv_pot(theta_e, pt, delp, delz, peln, pkz, q, is, ie, js, je, ng, npz, hydrostatic, moist)
subroutine cs_prof(q2, delp, q, km, i1, i2, iv)
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
subroutine updraft_helicity(is, ie, js, je, ng, km, zvir, sphum, uh, w, vort, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
real, parameter, public radius
Radius of the Earth [m].
Definition: constants.F90:72
subroutine, public set_domain(Domain2)
Definition: fms_io.F90:7401
subroutine, public fv_diag_init(Atm, axes, Time, npx, npy, npz, p_ref)
integer, parameter, public model_atmos
type(fv_diag_type), pointer idiag
subroutine cs_interpolator(is, ie, js, je, km, qin, kd, pout, pe, id, qout, iv)
real, dimension(:,:), allocatable, public zs_g
subroutine cs3_interpolator(is, ie, js, je, km, qin, kd, pout, wz, pe, id, qout, iv)
character(len=3), public gn
real, parameter, public omega
Rotation rate of the Earth [1/s].
Definition: constants.F90:75
subroutine pv_entropy(is, ie, js, je, ng, km, vort, f_d, pt, pkz, delp, grav)
subroutine, public moist_cv(is, ie, isd, ied, jsd, jed, km, j, k, nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, q, qd, cvm, t1)
real(kind=8), parameter, public pi_8
Ratio of circle circumference to diameter [N/A].
Definition: constants.F90:73
integer, parameter nplev
subroutine, public prt_mass(km, nq, is, ie, js, je, n_g, nwat, ps, delp, q, area, domain)
subroutine, public interpolate_vertical(is, ie, js, je, km, plev, peln, a3, a2)
real, parameter, public wtmair
Molecular weight of air [AMU].
Definition: constants.F90:101
real, parameter, public hlv
Latent heat of evaporation [J/kg].
Definition: constants.F90:80
character(len=256) tunits
integer function, public register_static_field(module_name, field_name, axes, long_name, units, missing_value, range, mask_variant, standard_name, DYNAMIC, do_not_log, interp_method, tile_count, area, volume, realm)
real, parameter, public rdgas
Gas constant for dry air [J/kg/deg].
Definition: constants.F90:77
subroutine, public get_number_tracers(model, num_tracers, num_prog, num_diag, num_family)
subroutine, public gw_1d(km, p0, ak, bk, ptop, ztop, pt1)
real, parameter, public cp_vapor
Specific heat capacity of water vapor at constant pressure [J/kg/deg].
Definition: constants.F90:89
subroutine, public get_eta_level(npz, p_s, pf, ph, ak, bk, pscale)
subroutine get_pressure_given_height(is, ie, js, je, ng, km, wz, kd, height, ts, peln, a2, fac)
Definition: mpp.F90:39
subroutine dbzcalc(q, pt, delp, peln, delz, dbz, maxdbz, allmax, bd, npz, ncnst, hydrostatic, zvir, in0r, in0s, in0g, iliqskin)
void a2b_ord2(int nx, int ny, const double *qin, const double *edge_w, const double *edge_e, const double *edge_s, const double *edge_n, double *qout, int on_west_edge, int on_east_edge, int on_south_edge, int on_north_edge)
Definition: gradient_c2l.c:119
character(len=256) tlongname
integer, parameter max_step
subroutine, public fv_diag(Atm, zvir, Time, print_freq)
real, parameter, public rvgas
Gas constant for water vapor [J/kg/deg].
Definition: constants.F90:78
integer, dimension(nplev) levs
subroutine, public a2b_ord4(qin, qout, gridstruct, npx, npy, is, ie, js, je, ng, replace)
subroutine wind_max(isc, iec, jsc, jec, isd, ied, jsd, jed, us, vs, ws_max, domain)
subroutine get_vorticity(isc, iec, jsc, jec, isd, ied, jsd, jed, npz, u, v, vort, dx, dy, rarea)
subroutine, public nullify_domain()
Definition: fms_io.F90:7421
real, parameter, public cp_air
Specific heat capacity of dry air at constant pressure [J/kg/deg].
Definition: constants.F90:83
subroutine, public z_sum(is, ie, js, je, km, n_g, delp, q, sum2)
integer, parameter, public r_grid
subroutine, public fv_diag_init_gn(Atm)
subroutine, public qsmith(im, km, k1, t, p, q, qs, dqdt)
Definition: fv_sg_nlm.F90:1005
subroutine, public rh_calc(pfull, t, qv, rh, do_cmip)
subroutine, public get_height_given_pressure(is, ie, js, je, ng, km, wz, kd, id, log_p, peln, a2)
subroutine nh_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, w, delz, pt, delp, q, hs, area, domain, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, nwat, ua, va, moist_phys, te)
real, parameter, public grav
Acceleration due to gravity [m/s^2].
Definition: constants.F90:76
real function, public g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
subroutine, public get_height_field(is, ie, js, je, ng, km, hydrostatic, delz, wz, pt, q, peln, zvir)
subroutine interpolate_z(is, ie, js, je, km, zl, hght, a3, a2)
#define max(a, b)
Definition: mosaic_util.h:33
subroutine, public get_tracer_names(model, n, name, longname, units, err_msg)
subroutine init_mq(phis, gridstruct, npx, npy, is, ie, js, je, ng)
subroutine, public prt_mxm(qname, q, is, ie, js, je, n_g, km, fac, area, domain)
subroutine, public prt_maxmin(qname, q, is, ie, js, je, n_g, km, fac)
real(kind=4), public e_flux
Definition: fv_mapz_nlm.F90:52
subroutine helicity_relative(is, ie, js, je, ng, km, zvir, sphum, srh, ua, va, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
subroutine, public ppme(p, qe, delp, im, km)
real function p_sum(is, ie, js, je, km, n_g, delp, area, domain)
real, parameter, public wtmco2
Molecular weight of carbon dioxide [AMU].
Definition: constants.F90:105
#define min(a, b)
Definition: mosaic_util.h:32
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
character(len=128) tname
real, parameter, public kappa
RDGAS / CP_AIR [dimensionless].
Definition: constants.F90:82
subroutine, public range_check(qname, q, is, ie, js, je, n_g, km, pos, q_low, q_hi, bad_range)
type(time_type), public fv_time
real(fp), parameter, public pi