FV3DYCORE  Version 2.0.0
fv_diagnostics.F90
Go to the documentation of this file.
1 
2 !***********************************************************************
3 !* GNU Lesser General Public License
4 !*
5 !* This file is part of the FV3 dynamical core.
6 !*
7 !* The FV3 dynamical core is free software: you can redistribute it
8 !* and/or modify it under the terms of the
9 !* GNU Lesser General Public License as published by the
10 !* Free Software Foundation, either version 3 of the License, or
11 !* (at your option) any later version.
12 !*
13 !* The FV3 dynamical core is distributed in the hope that it will be
14 !* useful, but WITHOUT ANYWARRANTY; without even the implied warranty
15 !* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 !* See the GNU General Public License for more details.
17 !*
18 !* You should have received a copy of the GNU Lesser General Public
19 !* License along with the FV3 dynamical core.
20 !* If not, see <http://www.gnu.org/licenses/>.
21 !***********************************************************************
22 
25 
26 ! <table>
27 ! <tr>
28 ! <th>Module Name</th>
29 ! <th>Functions Included</th>
30 ! </tr>
31 ! <tr>
32 ! <td>a2b_edge_mod</td>
33 ! <td>a2b_ord2, a2b_ord4</td>
34 ! </tr>
35 ! <tr>
36 ! <td>constants_mod</td>
37 ! <td>grav, rdgas, rvgas, pi=>pi_8, radius, kappa, WTMAIR, WTMCO2,
38 ! omega, hlv, cp_air, cp_vapor</td>
39 ! </tr>
40 ! <tr>
41 ! <td>diag_manager_mod</td>
42 ! <td>diag_axis_init, register_diag_field,
43 ! register_static_field, send_data, diag_grid_init</td>
44 ! </tr>
45 ! <tr>
46 ! <td>field_manager_mod</td>
47 ! <td>MODEL_ATMOS</td>
48 ! </tr>
49 ! <tr>
50 ! <td>fms_mod</td>
51 ! <td>write_version_number</td>
52 ! </tr>
53 ! <tr>
54 ! <td>fms_io_mod</td>
55 ! <td>set_domain, nullify_domain, write_version_number</td>
56 ! </tr>
57 ! <tr>
58 ! <td>fv_arrays_mod</td>
59 ! <td>fv_atmos_type, fv_grid_type, fv_diag_type, fv_grid_bounds_type,
60 ! R_GRIDmax_step</td>
61 ! </tr>
62 ! <tr>
63 ! <td>fv_eta_mod</td>
64 ! <td>get_eta_level, gw_1d</td>
65 ! </tr>
66 ! <tr>
67 ! <td>fv_grid_utils_mod</td>
68 ! <td> g_sum</td>
69 ! </tr>
70 ! <tr>
71 ! <td>fv_io_mod</td>
72 ! <td>fv_io_read_tracers</td>
73 ! </tr>
74 ! <tr>
75 ! <td>fv_mp_mod</td>
76 ! <td>mp_reduce_sum, mp_reduce_min, mp_reduce_max, is_master</td>
77 ! </tr>
78 ! <tr>
79 ! <td>fv_mapz_mod</td>
80 ! <td>E_Flux, moist_cv</td>
81 ! </tr>
82 ! <tr>
83 ! <td>fv_sg_mod</td>
84 ! <td>qsmith</td>
85 ! </tr>
86 ! <tr>
87 ! <td>fv_surf_map_mod</td>
88 ! <td>zs_g</td>
89 ! </tr>
90 ! <tr>
91 ! <td>fv_timing_mod</td>
92 ! <td>timing_on, timing_off</td>
93 ! </tr>
94 ! <tr>
95 ! <td>gfdl_cloud_microphys_mod</td>
96 ! <td>wqs1, qsmith_init</td>
97 ! </tr>
98 ! <tr>
99 ! <td>mpp_mod</td>
100 ! <td>mpp_error, FATAL, stdlog, mpp_pe, mpp_root_pe, mpp_sum, mpp_max, NOTE</td>
101 ! </tr>
102 ! <tr>
103 ! <td>mpp_domains_mod</td>
104 ! <td>domain2d, mpp_update_domains, DGRID_NE</td>
105 ! </tr>>
106 ! <tr>
107 ! <td>sat_vapor_pres_mod</td>
108 ! <td>compute_qs, lookup_es</td>
109 ! </tr>
110 ! <tr>
111 ! <td>time_manager_mod</td>
112 ! <td>time_type, get_date, get_time</td>
113 ! </tr>
114 ! <tr>
115 ! <td>tracer_manager_mod</td>
116 ! <td>get_tracer_names, get_number_tracers, get_tracer_index, set_tracer_profile</td>
117 ! </tr>
118 ! </table>
119 
120  use constants_mod, only: grav, rdgas, rvgas, pi=>pi_8, radius, kappa, wtmair, wtmco2, &
121  omega, hlv, cp_air, cp_vapor, tfreeze
122  use fms_mod, only: write_version_number
123  use fms_io_mod, only: set_domain, nullify_domain, write_version_number
124  use time_manager_mod, only: time_type, get_date, get_time
125  use mpp_domains_mod, only: domain2d, mpp_update_domains, dgrid_ne, east, north
126  use diag_manager_mod, only: diag_axis_init, register_diag_field, &
127  register_static_field, send_data, diag_grid_init
129  r_grid
130  use fv_mapz_mod, only: e_flux, moist_cv, moist_cp
131  use fv_mp_mod, only: mp_reduce_sum, mp_reduce_min, mp_reduce_max, is_master
132  use fv_eta_mod, only: get_eta_level, gw_1d
133  use fv_grid_utils_mod, only: g_sum
134  use a2b_edge_mod, only: a2b_ord2, a2b_ord4
135  use fv_surf_map_mod, only: zs_g
136  use fv_sg_mod, only: qsmith
137 
138  use tracer_manager_mod, only: get_tracer_names, get_number_tracers, get_tracer_index
139  use field_manager_mod, only: model_atmos
140  use mpp_mod, only: mpp_error, fatal, stdlog, mpp_pe, mpp_root_pe, mpp_sum, mpp_max, note, input_nml_file
141  use mpp_io_mod, only: mpp_flush
142  use sat_vapor_pres_mod, only: compute_qs, lookup_es
143 
144  use fv_arrays_mod, only: max_step
145 #ifndef GFS_PHYS
146  use gfdl_cloud_microphys_mod, only: wqs1, qsmith_init
147 #endif
148 
149  use column_diagnostics_mod, only: column_diagnostics_init, &
150  initialize_diagnostic_columns, &
151  column_diagnostics_header, &
152  close_column_diagnostics_units
153 
154 
155 #ifdef MULTI_GASES
157 #endif
158 
159  implicit none
160  private
161 
162  interface range_check
163  module procedure range_check_3d
164  module procedure range_check_2d
165  end interface range_check
166 
167  real, parameter:: missing_value = -1.e10
168  real, parameter:: missing_value2 = -1.e3
169  real, parameter:: missing_value3 = 1.e10
170  real :: ginv
171  real :: pk0
172  logical master
173  character(len=3) :: gn = ''
174 
175 ! private (to this module) diag:
176 
177  type(time_type) :: fv_time
178  type(fv_diag_type), pointer :: idiag
179 
180  logical :: module_is_initialized=.false.
181  logical :: prt_minmax =.false.
182  logical :: m_calendar
183  integer sphum, liq_wat, ice_wat, cld_amt ! GFDL physics
185  integer :: istep, mp_top
186  real :: ptop
187  real, parameter :: rad2deg = 180./pi
188 
189 ! tracers
190  character(len=128) :: tname
191  character(len=256) :: tlongname, tunits
192  real :: sphum_ll_fix = 0.
193  real :: qcly0 ! initial value for terminator test
194 
195  public :: fv_diag_init, fv_time, fv_diag, prt_mxm, prt_maxmin, range_check!, id_divg, id_te
198  public :: max_vv,get_vorticity,max_uh
200  public :: helicity_relative_caps
201 
202 #ifdef FEWER_PLEVS
203  integer, parameter :: nplev = 10 ! 31 ! lmh
204 #else
205  integer, parameter :: nplev = 31
206 #endif
207  integer :: levs(nplev)
208  integer :: k100, k200, k500
209 
210  integer, parameter :: max_diag_column = 100
211  logical, allocatable, dimension(:,:) :: do_debug_diag_column
212  integer, allocatable, dimension(:) :: diag_debug_units, diag_debug_i, diag_debug_j
213  real, allocatable, dimension(:) :: diag_debug_lon, diag_debug_lat
214  character(16), dimension(MAX_DIAG_COLUMN) :: diag_debug_names
215  real, dimension(MAX_DIAG_COLUMN) :: diag_debug_lon_in, diag_debug_lat_in
216 
217  logical, allocatable, dimension(:,:) :: do_sonde_diag_column
218  integer, allocatable, dimension(:) :: diag_sonde_units, diag_sonde_i, diag_sonde_j
219  real, allocatable, dimension(:) :: diag_sonde_lon, diag_sonde_lat
220  character(16), dimension(MAX_DIAG_COLUMN) :: diag_sonde_names
221  real, dimension(MAX_DIAG_COLUMN) :: diag_sonde_lon_in, diag_sonde_lat_in
222 
223  logical :: do_diag_debug = .false.
224  logical :: do_diag_sonde = .false.
225  logical :: prt_sounding = .false.
226  integer :: sound_freq = 3
227  integer :: num_diag_debug = 0
228  integer :: num_diag_sonde = 0
229  character(100) :: runname = 'test'
231 
232  real :: vrange(2), vsrange(2), wrange(2), trange(2), slprange(2), rhrange(2), skrange(2)
233 
234 
235 
236  namelist /fv_diag_column_nml/ do_diag_debug, do_diag_sonde, sound_freq, &
239 
240 ! version number of this module
241 ! Include variable "version" to be written to log file.
242 #include<file_version.h>
243 
244 contains
245 
246  subroutine fv_diag_init(Atm, axes, Time, npx, npy, npz, p_ref)
247  type(fv_atmos_type), intent(inout), target :: Atm(:)
248  integer, intent(out) :: axes(4)
249  type(time_type), intent(in) :: Time
250  integer, intent(in) :: npx, npy, npz
251  real, intent(in):: p_ref
252 
253  real, allocatable :: grid_xt(:), grid_yt(:), grid_xe(:), grid_ye(:), grid_xn(:), grid_yn(:)
254  real, allocatable :: grid_x(:), grid_y(:)
255  real, allocatable :: a3(:,:,:)
256  real :: pfull(npz)
257  real :: hyam(npz), hybm(npz)
258 
259  !These id_* are not needed later since they are for static data which is not used elsewhere
260  integer :: id_bk, id_pk, id_area, id_lon, id_lat, id_lont, id_latt, id_phalf, id_pfull
261  integer :: id_hyam, id_hybm
262  integer :: id_plev
263  integer :: i, j, k, m, n, ntileMe, id_xt, id_yt, id_x, id_y, id_xe, id_ye, id_xn, id_yn
264  integer :: isc, iec, jsc, jec
265 
266  logical :: used
267 
268  character(len=64) :: plev
269  character(len=64) :: field
270  integer :: ntprog
271  integer :: unit
272 
273  integer :: ncnst
274  integer :: axe2(3)
275 
276  character(len=64) :: errmsg
277  logical :: exists
278  integer :: nlunit, ios
279 
280  call write_version_number ( 'FV_DIAGNOSTICS_MOD', version )
281  idiag => atm(1)%idiag
282 
283 ! For total energy diagnostics:
284  idiag%steps = 0
285  idiag%efx = 0.; idiag%efx_sum = 0.
286  idiag%mtq = 0.; idiag%mtq_sum = 0.
287 
288  ncnst = atm(1)%ncnst
289  m_calendar = atm(1)%flagstruct%moist_phys
290 
291  call set_domain(atm(1)%domain) ! Set domain so that diag_manager can access tile information
292 
293  sphum = get_tracer_index(model_atmos, 'sphum')
294  liq_wat = get_tracer_index(model_atmos, 'liq_wat')
295  ice_wat = get_tracer_index(model_atmos, 'ice_wat')
296 
297  rainwat = get_tracer_index(model_atmos, 'rainwat')
298  snowwat = get_tracer_index(model_atmos, 'snowwat')
299  graupel = get_tracer_index(model_atmos, 'graupel')
300  o3mr = get_tracer_index(model_atmos, 'o3mr')
301  cld_amt = get_tracer_index(model_atmos, 'cld_amt')
302 
303 ! valid range for some fields
304 
305 !!! This will need mods for more than 1 tile per pe !!!
306 
307  vsrange = (/ -200., 200. /) ! surface (lowest layer) winds
308 
309  vrange = (/ -330., 330. /) ! winds
310  wrange = (/ -100., 100. /) ! vertical wind
311  rhrange = (/ -10., 150. /) ! RH
312 #ifdef HIWPP
313  trange = (/ 5., 350. /) ! temperature
314 #else
315  trange = (/ 100., 350. /) ! temperature
316 #endif
317  slprange = (/800., 1200./) ! sea-level-pressure
318  skrange = (/ -10000000.0, 10000000.0 /) ! dissipation estimate for SKEB
319 
320  ginv = 1./grav
321  if (atm(1)%grid_number == 1) fv_time = time
322 
323  allocate ( idiag%phalf(npz+1) )
324  call get_eta_level(atm(1)%npz, p_ref, pfull, idiag%phalf, atm(1)%ak, atm(1)%bk, 0.01)
325 
326  mp_top = 1
327  do k=1,npz
328  if ( pfull(k) > 30.e2 ) then
329  mp_top = k
330  exit
331  endif
332  enddo
333  if ( is_master() ) write(*,*) 'mp_top=', mp_top, 'pfull=', pfull(mp_top)
334 
335 ! allocate(grid_xt(npx-1), grid_yt(npy-1), grid_xe(npx), grid_ye(npy-1), grid_xn(npx-1), grid_yn(npy))
336  allocate(grid_xt(npx-1), grid_yt(npy-1))
337  grid_xt = (/ (i, i=1,npx-1) /)
338  grid_yt = (/ (j, j=1,npy-1) /)
339 ! grid_xe = (/ (i, i=1,npx) /)
340 ! grid_ye = (/ (j, j=1,npy-1) /)
341 ! grid_xn = (/ (i, i=1,npx-1) /)
342 ! grid_yn = (/ (j, j=1,npy) /)
343 
344  allocate(grid_x(npx), grid_y(npy))
345  grid_x = (/ (i, i=1,npx) /)
346  grid_y = (/ (j, j=1,npy) /)
347 
348  n=1
349  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
350  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
351 
352  ! Send diag_manager the grid informtaion
353  call diag_grid_init(domain=atm(n)%domain, &
354  & glo_lon=rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,1), &
355  & glo_lat=rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,2), &
356  & aglo_lon=rad2deg*atm(n)%gridstruct%agrid(isc-1:iec+1,jsc-1:jec+1,1), &
357  & aglo_lat=rad2deg*atm(n)%gridstruct%agrid(isc-1:iec+1,jsc-1:jec+1,2))
358 
359  ntileme = size(atm(:))
360  if (ntileme > 1) call mpp_error(fatal, "fv_diag_init can only be called with one grid at a time.")
361 
362 ! do n = 1, ntileMe
363  n = 1
364  field = 'grid'
365 
366  id_xt = diag_axis_init('grid_xt',grid_xt,'degrees_E','x','T-cell longitude', &
367  set_name=trim(field),domain2=atm(n)%Domain, tile_count=n)
368  id_yt = diag_axis_init('grid_yt',grid_yt,'degrees_N','y','T-cell latitude', &
369  set_name=trim(field), domain2=atm(n)%Domain, tile_count=n)
370 ! Don't need these right now
371 ! id_xe = diag_axis_init ('grid_xe',grid_xe,'degrees_E','x','E-cell longitude', &
372 ! set_name=trim(field),Domain2=Domain, tile_count=n)
373 ! id_ye = diag_axis_init ('grid_ye',grid_ye,'degrees_N','y','E-cell latitude', &
374 ! set_name=trim(field), Domain2=Domain, tile_count=n)
375 ! id_xn = diag_axis_init ('grid_xn',grid_xn,'degrees_E','x','N-cell longitude', &
376 ! set_name=trim(field),Domain2=Domain, aux='geolon_n, geolat_n', tile_count=n)
377 ! id_yn = diag_axis_init ('grid_yn',grid_yn,'degrees_N','y','N-cell latitude', &
378 ! set_name=trim(field), Domain2=Domain, tile_count=n)
379 
380  id_x = diag_axis_init('grid_x',grid_x,'degrees_E','x','cell corner longitude', &
381  set_name=trim(field),domain2=atm(n)%Domain, tile_count=n, domain_position=east)
382  id_y = diag_axis_init('grid_y',grid_y,'degrees_N','y','cell corner latitude', &
383  set_name=trim(field), domain2=atm(n)%Domain, tile_count=n, domain_position=north)
384 
385 ! end do
386 ! deallocate(grid_xt, grid_yt, grid_xe, grid_ye, grid_xn, grid_yn)
387  deallocate(grid_xt, grid_yt)
388  deallocate(grid_x, grid_y )
389 
390  id_phalf = diag_axis_init('phalf', idiag%phalf, 'mb', 'z', &
391  'ref half pressure level', direction=-1, set_name="dynamics")
392  id_pfull = diag_axis_init('pfull', pfull, 'mb', 'z', &
393  'ref full pressure level', direction=-1, set_name="dynamics", edges=id_phalf)
394 
395 !---- register static fields -------
396 
397  id_bk = register_static_field( "dynamics", 'bk', (/id_phalf/), &
398  'vertical coordinate sigma value', 'none' )
399 
400  id_pk = register_static_field( "dynamics", 'pk', (/id_phalf/), &
401  'pressure part of the hybrid coordinate', 'pascal' )
402 
403  id_hyam = register_static_field( "dynamics", 'hyam', (/id_pfull/), &
404  'vertical coordinate A value', '1E-5 Pa' )
405 
406  id_hybm = register_static_field( "dynamics", 'hybm', (/id_pfull/), &
407  'vertical coordinate B value', 'none' )
408 
409 !--- Send static data
410 
411  if ( id_bk > 0 ) used = send_data( id_bk,atm(1)%bk, time )
412  if ( id_pk > 0 ) used = send_data( id_pk,atm(1)%ak, time )
413  if ( id_hyam > 0 ) then
414  do k=1,npz
415  hyam(k) = 0.5 * ( atm(1)%ak(k) + atm(1)%ak(k+1) ) * 1.e-5
416  enddo
417  used = send_data( id_hyam, hyam, time )
418  endif
419  if ( id_hybm > 0 ) then
420  do k=1,npz
421  hybm(k) = 0.5 * ( atm(1)%bk(k) + atm(1)%bk(k+1) )
422  enddo
423  used = send_data( id_hybm, hybm, time )
424  endif
425 
426 ! Approach will need modification if we wish to write values on other than A grid.
427  axes(1) = id_xt
428  axes(2) = id_yt
429  axes(3) = id_pfull
430  axes(4) = id_phalf
431 
432 ! Selected pressure levels
433 ! SJL note: 31 is enough here; if you need more levels you should do it OFF line
434 ! do not add more to prevent the model from slowing down too much.
435 #ifdef FEWER_PLEVS
436  levs = (/50,100,200,250,300,500,750,850,925,1000/) ! lmh mini-levs for MJO simulations
437  k100 = 2
438  k200 = 3
439  k500 = 6
440 #else
441  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/)
442  k100 = 11
443  k200 = 13
444  k500 = 19
445 #endif
446  !
447 
448  id_plev = diag_axis_init('plev', levs(:)*1.0, 'mb', 'z', &
449  'actual pressure level', direction=-1, set_name="dynamics")
450 
451  axe2(1) = id_xt
452  axe2(2) = id_yt
453  axe2(3) = id_plev
454 
455 !---- register time independent fields -------
456 
457 ! do n = 1, ntileMe
458  n = 1
459  field= 'dynamics'
460  id_lon = register_static_field( trim(field), 'grid_lon', (/id_x,id_y/), &
461  'longitude', 'degrees_E' )
462  id_lat = register_static_field( trim(field), 'grid_lat', (/id_x,id_y/), &
463  'latitude', 'degrees_N' )
464  id_lont = register_static_field( trim(field), 'grid_lont', (/id_xt,id_yt/), &
465  'longitude', 'degrees_E' )
466  id_latt = register_static_field( trim(field), 'grid_latt', (/id_xt,id_yt/), &
467  'latitude', 'degrees_N' )
468  id_area = register_static_field( trim(field), 'area', axes(1:2), &
469  'cell area', 'm**2' )
470 #ifndef DYNAMICS_ZS
471  idiag%id_zsurf = register_static_field( trim(field), 'zsurf', axes(1:2), &
472  'surface height', 'm' )
473 #endif
474  idiag%id_zs = register_static_field( trim(field), 'zs', axes(1:2), &
475  'Original Mean Terrain', 'm' )
476 ! 3D hybrid_z fields:
477  idiag%id_ze = register_static_field( trim(field), 'ze', axes(1:3), &
478  'Hybrid_Z_surface', 'm' )
479  idiag%id_oro = register_static_field( trim(field), 'oro', axes(1:2), &
480  'Land/Water Mask', 'none' )
481  idiag%id_sgh = register_static_field( trim(field), 'sgh', axes(1:2), &
482  'Terrain Standard deviation', 'm' )
483 ! idiag%id_ts = register_static_field ( trim(field), 'ts', axes(1:2), &
484 ! 'Skin temperature', 'K' )
485 
486 !--------------------
487 ! Initial conditions:
488 !--------------------
489  idiag%ic_ps = register_static_field( trim(field), 'ps_ic', axes(1:2), &
490  'initial surface pressure', 'Pa' )
491  idiag%ic_ua = register_static_field( trim(field), 'ua_ic', axes(1:3), &
492  'zonal wind', 'm/sec' )
493  idiag%ic_va = register_static_field( trim(field), 'va_ic', axes(1:3), &
494  'meridional wind', 'm/sec' )
495  idiag%ic_ppt= register_static_field( trim(field), 'ppt_ic', axes(1:3), &
496  'potential temperature perturbation', 'K' )
497  idiag%ic_sphum = register_static_field( trim(field), 'sphum_ic', axes(1:2), &
498  'initial surface pressure', 'Pa' )
499 
500 ! end do
501 
502  master = (mpp_pe()==mpp_root_pe())
503 
504  n=1
505  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
506  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
507 
508  allocate ( idiag%zsurf(isc:iec,jsc:jec) )
509 
510  do j=jsc,jec
511  do i=isc,iec
512  idiag%zsurf(i,j) = ginv * atm(n)%phis(i,j)
513  enddo
514  enddo
515 
516 !--- Send time independent data
517 
518 ! do n = 1, ntileMe
519  n = 1
520  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
521  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
522  if (id_lon > 0) used = send_data(id_lon, rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,1), time)
523  if (id_lat > 0) used = send_data(id_lat, rad2deg*atm(n)%gridstruct%grid(isc:iec+1,jsc:jec+1,2), time)
524  if (id_lont > 0) used = send_data(id_lont, rad2deg*atm(n)%gridstruct%agrid(isc:iec,jsc:jec,1), time)
525  if (id_latt > 0) used = send_data(id_latt, rad2deg*atm(n)%gridstruct%agrid(isc:iec,jsc:jec,2), time)
526  if (id_area > 0) used = send_data(id_area, atm(n)%gridstruct%area(isc:iec,jsc:jec), time)
527 #ifndef DYNAMICS_ZS
528  if (idiag%id_zsurf > 0) used = send_data(idiag%id_zsurf, idiag%zsurf, time)
529 #endif
530  if ( atm(n)%flagstruct%fv_land ) then
531  if (idiag%id_zs > 0) used = send_data(idiag%id_zs , zs_g, time)
532  if (idiag%id_oro > 0) used = send_data(idiag%id_oro, atm(n)%oro(isc:iec,jsc:jec), time)
533  if (idiag%id_sgh > 0) used = send_data(idiag%id_sgh, atm(n)%sgh(isc:iec,jsc:jec), time)
534  endif
535 
536  if ( atm(n)%flagstruct%ncep_ic ) then
537  if (idiag%id_ts > 0) used = send_data(idiag%id_ts, atm(n)%ts(isc:iec,jsc:jec), time)
538  endif
539 
540  if ( atm(n)%flagstruct%hybrid_z .and. idiag%id_ze > 0 ) &
541  used = send_data(idiag%id_ze, atm(n)%ze0(isc:iec,jsc:jec,1:npz), time)
542 
543  if (idiag%ic_ps > 0) used = send_data(idiag%ic_ps, atm(n)%ps(isc:iec,jsc:jec)*ginv, time)
544 
545  if(idiag%ic_ua > 0) used=send_data(idiag%ic_ua, atm(n)%ua(isc:iec,jsc:jec,:), time)
546  if(idiag%ic_va > 0) used=send_data(idiag%ic_va, atm(n)%va(isc:iec,jsc:jec,:), time)
547 
548  pk0 = 1000.e2 ** kappa
549  if(idiag%ic_ppt> 0) then
550 ! Potential temperature
551  allocate ( idiag%pt1(npz) )
552  allocate ( a3(isc:iec,jsc:jec,npz) )
553 #ifdef TEST_GWAVES
554  call gw_1d(npz, 1000.e2, atm(n)%ak, atm(n)%ak, atm(n)%ak(1), 10.e3, idiag%pt1)
555 #else
556  idiag%pt1 = 0.
557 #endif
558  do k=1,npz
559  do j=jsc,jec
560  do i=isc,iec
561  a3(i,j,k) = (atm(n)%pt(i,j,k)/atm(n)%pkz(i,j,k) - idiag%pt1(k)) * pk0
562  enddo
563  enddo
564  enddo
565  used=send_data(idiag%ic_ppt, a3, time)
566  deallocate ( a3 )
567  deallocate ( idiag%pt1 )
568  endif
569 ! end do
570 
571 !--------------------------------------------------------------
572 ! Register main prognostic fields: ps, (u,v), t, omega (dp/dt)
573 !--------------------------------------------------------------
574 
575  allocate(idiag%id_tracer(ncnst))
576  allocate(idiag%id_tracer_dmmr(ncnst))
577  allocate(idiag%id_tracer_dvmr(ncnst))
578  allocate(idiag%w_mr(ncnst))
579  idiag%id_tracer(:) = 0
580  idiag%id_tracer_dmmr(:) = 0
581  idiag%id_tracer_dvmr(:) = 0
582  idiag%w_mr(:) = 0.e0
583 
584  allocate(idiag%id_u(nplev))
585  allocate(idiag%id_v(nplev))
586  allocate(idiag%id_t(nplev))
587  allocate(idiag%id_h(nplev))
588  allocate(idiag%id_q(nplev))
589  allocate(idiag%id_omg(nplev))
590  idiag%id_u(:) = 0
591  idiag%id_v(:) = 0
592  idiag%id_t(:) = 0
593  idiag%id_h(:) = 0
594  idiag%id_q(:) = 0
595  idiag%id_omg(:) = 0
596 
597 ! do n = 1, ntileMe
598  n = 1
599  field= 'dynamics'
600 
601 #ifdef DYNAMICS_ZS
602  idiag%id_zsurf = register_diag_field( trim(field), 'zsurf', axes(1:2), time, &
603  'surface height', 'm')
604 #endif
605 !-------------------
606 ! Surface pressure
607 !-------------------
608  idiag%id_ps = register_diag_field( trim(field), 'ps', axes(1:2), time, &
609  'surface pressure', 'Pa', missing_value=missing_value )
610 
611 !-------------------
612 ! Mountain torque
613 !-------------------
614  idiag%id_mq = register_diag_field( trim(field), 'mq', axes(1:2), time, &
615  'mountain torque', 'Hadleys per unit area', missing_value=missing_value )
616 !-------------------
617 ! Angular momentum
618 !-------------------
619  idiag%id_aam = register_diag_field( trim(field), 'aam', axes(1:2), time, &
620  'angular momentum', 'kg*m^2/s', missing_value=missing_value )
621  idiag%id_amdt = register_diag_field( trim(field), 'amdt', axes(1:2), time, &
622  'angular momentum error', 'kg*m^2/s^2', missing_value=missing_value )
623 
624 !-------------------
625 !! 3D Tendency terms from physics
626 !-------------------
627  if (atm(n)%flagstruct%write_3d_diags) then
628 
629  idiag%id_T_dt_phys = register_diag_field( trim(field), 'T_dt_phys', axes(1:3), time, &
630  'temperature tendency from physics', 'K/s', missing_value=missing_value )
631  if (idiag%id_T_dt_phys > 0) allocate (atm(n)%phys_diag%phys_t_dt(isc:iec,jsc:jec,npz))
632  idiag%id_u_dt_phys = register_diag_field( trim(field), 'u_dt_phys', axes(1:3), time, &
633  'zonal wind tendency from physics', 'm/s/s', missing_value=missing_value )
634  if (idiag%id_u_dt_phys > 0) allocate (atm(n)%phys_diag%phys_u_dt(isc:iec,jsc:jec,npz))
635  idiag%id_v_dt_phys = register_diag_field( trim(field), 'v_dt_phys', axes(1:3), time, &
636  'meridional wind tendency from physics', 'm/s/s', missing_value=missing_value )
637  if (idiag%id_v_dt_phys > 0) allocate (atm(n)%phys_diag%phys_v_dt(isc:iec,jsc:jec,npz))
638 
639  idiag%id_qv_dt_phys = register_diag_field( trim(field), 'qv_dt_phys', axes(1:3), time, &
640  'water vapor specific humidity tendency from physics', 'kg/kg/s', missing_value=missing_value )
641  if (idiag%id_qv_dt_phys > 0) allocate (atm(n)%phys_diag%phys_qv_dt(isc:iec,jsc:jec,npz))
642  idiag%id_ql_dt_phys = register_diag_field( trim(field), 'ql_dt_phys', axes(1:3), time, &
643  'total liquid water tendency from physics', 'kg/kg/s', missing_value=missing_value )
644  if (idiag%id_ql_dt_phys > 0) allocate (atm(n)%phys_diag%phys_ql_dt(isc:iec,jsc:jec,npz))
645  idiag%id_qi_dt_phys = register_diag_field( trim(field), 'qi_dt_phys', axes(1:3), time, &
646  'total ice water tendency from physics', 'kg/kg/s', missing_value=missing_value )
647  if (idiag%id_qi_dt_phys > 0) allocate (atm(n)%phys_diag%phys_qi_dt(isc:iec,jsc:jec,npz))
648  endif
649 
650 !
651  do i=1,nplev
652  write(plev,'(I5)') levs(i)
653 ! Height:
654  idiag%id_h(i) = register_diag_field(trim(field), 'z'//trim(adjustl(plev)), axes(1:2), time, &
655  trim(adjustl(plev))//'-mb height', 'm', missing_value=missing_value)
656 ! u-wind:
657  idiag%id_u(i) = register_diag_field(trim(field), 'u'//trim(adjustl(plev)), axes(1:2), time, &
658  trim(adjustl(plev))//'-mb u', 'm/s', missing_value=missing_value)
659 ! v-wind:
660  idiag%id_v(i) = register_diag_field(trim(field), 'v'//trim(adjustl(plev)), axes(1:2), time, &
661  trim(adjustl(plev))//'-mb v', 'm/s', missing_value=missing_value)
662 ! Temperature (K):
663  idiag%id_t(i) = register_diag_field(trim(field), 't'//trim(adjustl(plev)), axes(1:2), time, &
664  trim(adjustl(plev))//'-mb temperature', 'K', missing_value=missing_value)
665 ! specific humidity:
666  idiag%id_q(i) = register_diag_field(trim(field), 'q'//trim(adjustl(plev)), axes(1:2), time, &
667  trim(adjustl(plev))//'-mb specific humidity', 'kg/kg', missing_value=missing_value)
668 ! Omega (Pa/sec)
669  idiag%id_omg(i) = register_diag_field(trim(field), 'omg'//trim(adjustl(plev)), axes(1:2), time, &
670  trim(adjustl(plev))//'-mb omega', 'Pa/s', missing_value=missing_value)
671  enddo
672 
673  if (atm(n)%flagstruct%write_3d_diags) then
674  idiag%id_u_plev = register_diag_field( trim(field), 'u_plev', axe2(1:3), time, &
675  'zonal wind', 'm/sec', missing_value=missing_value, range=vrange )
676  idiag%id_v_plev = register_diag_field( trim(field), 'v_plev', axe2(1:3), time, &
677  'meridional wind', 'm/sec', missing_value=missing_value, range=vrange )
678  idiag%id_t_plev = register_diag_field( trim(field), 't_plev', axe2(1:3), time, &
679  'temperature', 'K', missing_value=missing_value, range=trange )
680  idiag%id_h_plev = register_diag_field( trim(field), 'h_plev', axe2(1:3), time, &
681  'height', 'm', missing_value=missing_value )
682  idiag%id_q_plev = register_diag_field( trim(field), 'q_plev', axe2(1:3), time, &
683  'specific humidity', 'kg/kg', missing_value=missing_value )
684  idiag%id_omg_plev = register_diag_field( trim(field), 'omg_plev', axe2(1:3), time, &
685  'omega', 'Pa/s', missing_value=missing_value )
686  endif
687 
688 
689  ! flag for calculation of geopotential
690  if ( all(idiag%id_h(minloc(abs(levs-10)))>0) .or. all(idiag%id_h(minloc(abs(levs-50)))>0) .or. &
691  all(idiag%id_h(minloc(abs(levs-100)))>0) .or. all(idiag%id_h(minloc(abs(levs-200)))>0) .or. &
692  all(idiag%id_h(minloc(abs(levs-250)))>0) .or. all(idiag%id_h(minloc(abs(levs-300)))>0) .or. &
693  all(idiag%id_h(minloc(abs(levs-500)))>0) .or. all(idiag%id_h(minloc(abs(levs-700)))>0) .or. &
694  all(idiag%id_h(minloc(abs(levs-850)))>0) .or. all(idiag%id_h(minloc(abs(levs-1000)))>0) ) then
695  idiag%id_any_hght = 1
696  else
697  idiag%id_any_hght = 0
698  endif
699 !-----------------------------
700 ! mean temp between 300-500 mb
701 !-----------------------------
702  idiag%id_tm = register_diag_field(trim(field), 'tm', axes(1:2), time, &
703  'mean 300-500 mb temp', 'K', missing_value=missing_value )
704 
705 !-------------------
706 ! Sea-level-pressure
707 !-------------------
708  idiag%id_slp = register_diag_field(trim(field), 'slp', axes(1:2), time, &
709  'sea-level pressure', 'mb', missing_value=missing_value, &
710  range=slprange )
711 !----------------------------------
712 ! Bottom level pressure for masking
713 !----------------------------------
714  idiag%id_pmask = register_diag_field(trim(field), 'pmask', axes(1:2), time, &
715  'masking pressure at lowest level', 'mb', &
717 !------------------------------------------
718 ! Fix for Bottom level pressure for masking
719 !------------------------------------------
720  idiag%id_pmaskv2 = register_diag_field(trim(field), 'pmaskv2', axes(1:2), time,&
721  & 'masking pressure at lowest level', 'mb', missing_value=missing_value)
722 
723 !-------------------
724 ! Hurricane scales:
725 !-------------------
726 ! Net effects: ~ intensity * freq
727  idiag%id_c15 = register_diag_field(trim(field), 'cat15', axes(1:2), time, &
728  'de-pression < 1000', 'mb', missing_value=missing_value)
729  idiag%id_c25 = register_diag_field(trim(field), 'cat25', axes(1:2), time, &
730  'de-pression < 980', 'mb', missing_value=missing_value)
731  idiag%id_c35 = register_diag_field(trim(field), 'cat35', axes(1:2), time, &
732  'de-pression < 964', 'mb', missing_value=missing_value)
733  idiag%id_c45 = register_diag_field(trim(field), 'cat45', axes(1:2), time, &
734  'de-pression < 944', 'mb', missing_value=missing_value)
735 ! Frequency:
736  idiag%id_f15 = register_diag_field(trim(field), 'f15', axes(1:2), time, &
737  'Cat15 frequency', 'none', missing_value=missing_value)
738  idiag%id_f25 = register_diag_field(trim(field), 'f25', axes(1:2), time, &
739  'Cat25 frequency', 'none', missing_value=missing_value)
740  idiag%id_f35 = register_diag_field(trim(field), 'f35', axes(1:2), time, &
741  'Cat35 frequency', 'none', missing_value=missing_value)
742  idiag%id_f45 = register_diag_field(trim(field), 'f45', axes(1:2), time, &
743  'Cat45 frequency', 'none', missing_value=missing_value)
744 !-------------------
745 ! A grid winds (lat-lon)
746 !-------------------
747  if (atm(n)%flagstruct%write_3d_diags) then
748  idiag%id_ua = register_diag_field( trim(field), 'ucomp', axes(1:3), time, &
749  'zonal wind', 'm/sec', missing_value=missing_value, range=vrange )
750  idiag%id_va = register_diag_field( trim(field), 'vcomp', axes(1:3), time, &
751  'meridional wind', 'm/sec', missing_value=missing_value, range=vrange)
752  if ( .not. atm(n)%flagstruct%hydrostatic ) &
753  idiag%id_w = register_diag_field( trim(field), 'w', axes(1:3), time, &
754  'vertical wind', 'm/sec', missing_value=missing_value, range=wrange )
755 
756  idiag%id_pt = register_diag_field( trim(field), 'temp', axes(1:3), time, &
757  'temperature', 'K', missing_value=missing_value, range=trange )
758  idiag%id_ppt = register_diag_field( trim(field), 'ppt', axes(1:3), time, &
759  'potential temperature perturbation', 'K', missing_value=missing_value )
760  idiag%id_theta_e = register_diag_field( trim(field), 'theta_e', axes(1:3), time, &
761  'theta_e', 'K', missing_value=missing_value )
762  idiag%id_omga = register_diag_field( trim(field), 'omega', axes(1:3), time, &
763  'omega', 'Pa/s', missing_value=missing_value )
764  idiag%id_divg = register_diag_field( trim(field), 'divg', axes(1:3), time, &
765  'mean divergence', '1/s', missing_value=missing_value )
766 
767  idiag%id_hght3d = register_diag_field( trim(field), 'hght', axes(1:3), time, &
768  'height', 'm', missing_value=missing_value )
769 
770  ! diagnotic output for skeb testing
771  idiag%id_diss = register_diag_field( trim(field), 'diss_est', axes(1:3), time, &
772  'random', 'none', missing_value=missing_value, range=skrange )
773 
774  idiag%id_rh = register_diag_field( trim(field), 'rh', axes(1:3), time, &
775  'Relative Humidity', '%', missing_value=missing_value )
776  ! 'Relative Humidity', '%', missing_value=missing_value, range=rhrange )
777  idiag%id_delp = register_diag_field( trim(field), 'delp', axes(1:3), time, &
778  'pressure thickness', 'pa', missing_value=missing_value )
779  if ( .not. atm(n)%flagstruct%hydrostatic ) &
780  idiag%id_delz = register_diag_field( trim(field), 'delz', axes(1:3), time, &
781  'height thickness', 'm', missing_value=missing_value )
782  if( atm(n)%flagstruct%hydrostatic ) then
783  idiag%id_pfhy = register_diag_field( trim(field), 'pfhy', axes(1:3), time, &
784  'hydrostatic pressure', 'pa', missing_value=missing_value )
785  else
786  idiag%id_pfnh = register_diag_field( trim(field), 'pfnh', axes(1:3), time, &
787  'non-hydrostatic pressure', 'pa', missing_value=missing_value )
788  endif
789  idiag%id_zratio = register_diag_field( trim(field), 'zratio', axes(1:3), time, &
790  'nonhydro_ratio', 'n/a', missing_value=missing_value )
791  !--------------------
792  ! 3D Condensate
793  !--------------------
794  idiag%id_qn = register_diag_field( trim(field), 'qn', axes(1:3), time, &
795  'cloud condensate', 'kg/m/s^2', missing_value=missing_value )
796  idiag%id_qp = register_diag_field( trim(field), 'qp', axes(1:3), time, &
797  'precip condensate', 'kg/m/s^2', missing_value=missing_value )
798  ! fast moist phys tendencies:
799  idiag%id_mdt = register_diag_field( trim(field), 'mdt', axes(1:3), time, &
800  'DT/Dt: fast moist phys', 'deg/sec', missing_value=missing_value )
801  idiag%id_qdt = register_diag_field( trim(field), 'qdt', axes(1:3), time, &
802  'Dqv/Dt: fast moist phys', 'kg/kg/sec', missing_value=missing_value )
803  idiag%id_dbz = register_diag_field( trim(field), 'reflectivity', axes(1:3), time, &
804  'Stoelinga simulated reflectivity', 'dBz', missing_value=missing_value)
805 
806  !--------------------
807  ! Relative vorticity
808  !--------------------
809  idiag%id_vort = register_diag_field( trim(field), 'vort', axes(1:3), time, &
810  'vorticity', '1/s', missing_value=missing_value )
811  !--------------------
812  ! Potential vorticity
813  !--------------------
814  idiag%id_pv = register_diag_field( trim(field), 'pv', axes(1:3), time, &
815  'potential vorticity', '1/s', missing_value=missing_value )
816 
817  ! -------------------
818  ! Vertical flux correlation terms (good for averages)
819  ! -------------------
820  idiag%id_uw = register_diag_field( trim(field), 'uw', axes(1:3), time, &
821  'vertical zonal momentum flux', 'N/m**2', missing_value=missing_value )
822  idiag%id_vw = register_diag_field( trim(field), 'vw', axes(1:3), time, &
823  'vertical meridional momentum flux', 'N/m**', missing_value=missing_value )
824  idiag%id_hw = register_diag_field( trim(field), 'hw', axes(1:3), time, &
825  'vertical heat flux', 'W/m**2', missing_value=missing_value )
826  idiag%id_qvw = register_diag_field( trim(field), 'qvw', axes(1:3), time, &
827  'vertical water vapor flux', 'kg/m**2/s', missing_value=missing_value )
828  idiag%id_qlw = register_diag_field( trim(field), 'qlw', axes(1:3), time, &
829  'vertical liquid water flux', 'kg/m**2/s', missing_value=missing_value )
830  idiag%id_qiw = register_diag_field( trim(field), 'qiw', axes(1:3), time, &
831  'vertical ice water flux', 'kg/m**2/s', missing_value=missing_value )
832  idiag%id_o3w = register_diag_field( trim(field), 'o3w', axes(1:3), time, &
833  'vertical ozone flux', 'kg/m**2/s', missing_value=missing_value )
834 
835  endif
836 
837 ! Total energy (only when moist_phys = .T.)
838  idiag%id_te = register_diag_field( trim(field), 'te', axes(1:2), time, &
839  'Total Energy', 'J/kg', missing_value=missing_value )
840 ! Total Kinetic energy
841  idiag%id_ke = register_diag_field( trim(field), 'ke', axes(1:2), time, &
842  'Total KE', 'm^2/s^2', missing_value=missing_value )
843  idiag%id_ws = register_diag_field( trim(field), 'ws', axes(1:2), time, &
844  'Terrain W', 'm/s', missing_value=missing_value )
845  idiag%id_maxdbz = register_diag_field( trim(field), 'max_reflectivity', axes(1:2), time, &
846  'Stoelinga simulated maximum (composite) reflectivity', 'dBz', missing_value=missing_value)
847  idiag%id_basedbz = register_diag_field( trim(field), 'base_reflectivity', axes(1:2), time, &
848  'Stoelinga simulated base (1 km AGL) reflectivity', 'dBz', missing_value=missing_value)
849  idiag%id_dbz4km = register_diag_field( trim(field), '4km_reflectivity', axes(1:2), time, &
850  'Stoelinga simulated base reflectivity', 'dBz', missing_value=missing_value)
851  idiag%id_dbztop = register_diag_field( trim(field), 'echo_top', axes(1:2), time, &
852  'Echo top ( <= 18.5 dBz )', 'm', missing_value=missing_value2)
853  idiag%id_dbz_m10C = register_diag_field( trim(field), 'm10C_reflectivity', axes(1:2), time, &
854  'Reflectivity at -10C level', 'm', missing_value=missing_value)
855 
856 !--------------------------
857 ! Extra surface diagnostics:
858 !--------------------------
859 ! Surface (lowest layer) vorticity: for tropical cyclones diag.
860  idiag%id_vorts = register_diag_field( trim(field), 'vorts', axes(1:2), time, &
861  'surface vorticity', '1/s', missing_value=missing_value )
862  idiag%id_us = register_diag_field( trim(field), 'us', axes(1:2), time, &
863  'surface u-wind', 'm/sec', missing_value=missing_value, range=vsrange )
864  idiag%id_vs = register_diag_field( trim(field), 'vs', axes(1:2), time, &
865  'surface v-wind', 'm/sec', missing_value=missing_value, range=vsrange )
866  idiag%id_tq = register_diag_field( trim(field), 'tq', axes(1:2), time, &
867  'Total water path', 'kg/m**2', missing_value=missing_value )
868  idiag%id_iw = register_diag_field( trim(field), 'iw', axes(1:2), time, &
869  'Ice water path', 'kg/m**2', missing_value=missing_value )
870  idiag%id_lw = register_diag_field( trim(field), 'lw', axes(1:2), time, &
871  'Liquid water path', 'kg/m**2', missing_value=missing_value )
872  idiag%id_ts = register_diag_field( trim(field), 'ts', axes(1:2), time, &
873  'Skin temperature', 'K' )
874  idiag%id_tb = register_diag_field( trim(field), 'tb', axes(1:2), time, &
875  'lowest layer temperature', 'K' )
876  idiag%id_ctt = register_diag_field( trim(field), 'ctt', axes(1:2), time, &
877  'cloud_top temperature', 'K', missing_value=missing_value3 )
878  idiag%id_ctp = register_diag_field( trim(field), 'ctp', axes(1:2), time, &
879  'cloud_top pressure', 'hPa' , missing_value=missing_value3 )
880  idiag%id_ctz = register_diag_field( trim(field), 'ctz', axes(1:2), time, &
881  'cloud_top height', 'hPa' , missing_value=missing_value2 )
882  idiag%id_cape = register_diag_field( trim(field), 'cape', axes(1:2), time, &
883  'Convective available potential energy (surface-based)', 'J/kg' , missing_value=missing_value )
884  idiag%id_cin = register_diag_field( trim(field), 'cin', axes(1:2), time, &
885  'Convective inhibition (surface-based)', 'J/kg' , missing_value=missing_value )
886 !--------------------------
887 ! Vertically integrated tracers for GFDL MP
888 !--------------------------
889  idiag%id_intqv = register_diag_field( trim(field), 'intqv', axes(1:2), time, &
890  'Vertically Integrated Water Vapor', 'kg/m**2', missing_value=missing_value )
891  idiag%id_intql = register_diag_field( trim(field), 'intql', axes(1:2), time, &
892  'Vertically Integrated Cloud Water', 'kg/m**2', missing_value=missing_value )
893  idiag%id_intqi = register_diag_field( trim(field), 'intqi', axes(1:2), time, &
894  'Vertically Integrated Cloud Ice', 'kg/m**2', missing_value=missing_value )
895  idiag%id_intqr = register_diag_field( trim(field), 'intqr', axes(1:2), time, &
896  'Vertically Integrated Rain', 'kg/m**2', missing_value=missing_value )
897  idiag%id_intqs = register_diag_field( trim(field), 'intqs', axes(1:2), time, &
898  'Vertically Integrated Snow', 'kg/m**2', missing_value=missing_value )
899  idiag%id_intqg = register_diag_field( trim(field), 'intqg', axes(1:2), time, &
900  'Vertically Integrated Graupel', 'kg/m**2', missing_value=missing_value )
901 
902 #ifdef HIWPP
903  idiag%id_acl = register_diag_field( trim(field), 'acl', axes(1:2), time, &
904  'Column-averaged Cl mixing ratio', 'kg/kg', missing_value=missing_value )
905  idiag%id_acl2 = register_diag_field( trim(field), 'acl2', axes(1:2), time, &
906  'Column-averaged Cl2 mixing ratio', 'kg/kg', missing_value=missing_value )
907  idiag%id_acly = register_diag_field( trim(field), 'acly', axes(1:2), time, &
908  'Column-averaged total chlorine mixing ratio', 'kg/kg', missing_value=missing_value )
909 #endif
910 
911 !--------------------------
912 ! 850-mb vorticity
913 !--------------------------
914  idiag%id_vort850 = register_diag_field( trim(field), 'vort850', axes(1:2), time, &
915  '850-mb vorticity', '1/s', missing_value=missing_value )
916 
917  idiag%id_vort200 = register_diag_field( trim(field), 'vort200', axes(1:2), time, &
918  '200-mb vorticity', '1/s', missing_value=missing_value )
919 
920 ! Cubed_2_latlon interpolation is more accurate, particularly near the poles, using
921 ! winds speed (a scalar), rather than wind vectors or kinetic energy directly.
922  idiag%id_s200 = register_diag_field( trim(field), 's200', axes(1:2), time, &
923  '200-mb wind_speed', 'm/s', missing_value=missing_value )
924  idiag%id_sl12 = register_diag_field( trim(field), 'sl12', axes(1:2), time, &
925  '12th L wind_speed', 'm/s', missing_value=missing_value )
926  idiag%id_sl13 = register_diag_field( trim(field), 'sl13', axes(1:2), time, &
927  '13th L wind_speed', 'm/s', missing_value=missing_value )
928 ! Selceted (HIWPP) levels of non-precip condensates:
929  idiag%id_qn200 = register_diag_field( trim(field), 'qn200', axes(1:2), time, &
930  '200mb condensate', 'kg/m/s^2', missing_value=missing_value )
931  idiag%id_qn500 = register_diag_field( trim(field), 'qn500', axes(1:2), time, &
932  '500mb condensate', 'kg/m/s^2', missing_value=missing_value )
933  idiag%id_qn850 = register_diag_field( trim(field), 'qn850', axes(1:2), time, &
934  '850mb condensate', 'kg/m/s^2', missing_value=missing_value )
935 
936  idiag%id_vort500 = register_diag_field( trim(field), 'vort500', axes(1:2), time, &
937  '500-mb vorticity', '1/s', missing_value=missing_value )
938 
939  idiag%id_rain5km = register_diag_field( trim(field), 'rain5km', axes(1:2), time, &
940  '5-km AGL liquid water', 'kg/kg', missing_value=missing_value )
941 !--------------------------
942 ! w on height or pressure levels
943 !--------------------------
944  if( .not. atm(n)%flagstruct%hydrostatic ) then
945  idiag%id_w200 = register_diag_field( trim(field), 'w200', axes(1:2), time, &
946  '200-mb w-wind', 'm/s', missing_value=missing_value )
947  idiag%id_w500 = register_diag_field( trim(field), 'w500', axes(1:2), time, &
948  '500-mb w-wind', 'm/s', missing_value=missing_value )
949  idiag%id_w700 = register_diag_field( trim(field), 'w700', axes(1:2), time, &
950  '700-mb w-wind', 'm/s', missing_value=missing_value )
951 
952  idiag%id_w850 = register_diag_field( trim(field), 'w850', axes(1:2), time, &
953  '850-mb w-wind', 'm/s', missing_value=missing_value )
954  idiag%id_w5km = register_diag_field( trim(field), 'w5km', axes(1:2), time, &
955  '5-km AGL w-wind', 'm/s', missing_value=missing_value )
956  idiag%id_w2500m = register_diag_field( trim(field), 'w2500m', axes(1:2), time, &
957  '2.5-km AGL w-wind', 'm/s', missing_value=missing_value )
958  idiag%id_w1km = register_diag_field( trim(field), 'w1km', axes(1:2), time, &
959  '1-km AGL w-wind', 'm/s', missing_value=missing_value )
960  idiag%id_wmaxup = register_diag_field( trim(field), 'wmaxup', axes(1:2), time, &
961  'column-maximum updraft', 'm/s', missing_value=missing_value )
962  idiag%id_wmaxdn = register_diag_field( trim(field), 'wmaxdn', axes(1:2), time, &
963  'column-maximum downdraft', 'm/s', missing_value=missing_value )
964 
965  endif
966 
967 ! helicity
968  idiag%id_x850 = register_diag_field( trim(field), 'x850', axes(1:2), time, &
969  '850-mb vertical comp. of helicity', 'm/s**2', missing_value=missing_value )
970 ! idiag%id_x03 = register_diag_field ( trim(field), 'x03', axes(1:2), Time, &
971 ! '0-3 km vertical comp. of helicity', 'm**2/s**2', missing_value=missing_value )
972 ! idiag%id_x25 = register_diag_field ( trim(field), 'x25', axes(1:2), Time, &
973 ! '2-5 km vertical comp. of helicity', 'm**2/s**2', missing_value=missing_value )
974 
975 ! Storm Relative Helicity
976  idiag%id_srh1 = register_diag_field( trim(field), 'srh01', axes(1:2), time, &
977  '0-1 km Storm Relative Helicity', 'm/s**2', missing_value=missing_value )
978  idiag%id_srh3 = register_diag_field( trim(field), 'srh03', axes(1:2), time, &
979  '0-3 km Storm Relative Helicity', 'm/s**2', missing_value=missing_value )
980  idiag%id_ustm = register_diag_field( trim(field), 'ustm', axes(1:2), time, &
981  'u Component of Storm Motion', 'm/s', missing_value=missing_value )
982  idiag%id_vstm = register_diag_field( trim(field), 'vstm', axes(1:2), time, &
983  'v Component of Storm Motion', 'm/s', missing_value=missing_value )
984 
985  idiag%id_srh25 = register_diag_field( trim(field), 'srh25', axes(1:2), time, &
986  '2-5 km Storm Relative Helicity', 'm/s**2', missing_value=missing_value )
987 
988  if( .not. atm(n)%flagstruct%hydrostatic ) then
989  idiag%id_uh03 = register_diag_field( trim(field), 'uh03', axes(1:2), time, &
990  '0-3 km Updraft Helicity', 'm/s**2', missing_value=missing_value )
991  idiag%id_uh25 = register_diag_field( trim(field), 'uh25', axes(1:2), time, &
992  '2-5 km Updraft Helicity', 'm/s**2', missing_value=missing_value )
993  endif
994 ! TC test winds at 100 m
995  if( .not. atm(n)%flagstruct%hydrostatic ) &
996  idiag%id_w100m = register_diag_field( trim(field), 'w100m', axes(1:2), time, &
997  '100-m AGL w-wind', 'm/s', missing_value=missing_value )
998  idiag%id_u100m = register_diag_field( trim(field), 'u100m', axes(1:2), time, &
999  '100-m AGL u-wind', 'm/s', missing_value=missing_value )
1000  idiag%id_v100m = register_diag_field( trim(field), 'v100m', axes(1:2), time, &
1001  '100-m AGL v-wind', 'm/s', missing_value=missing_value )
1002 !--------------------------
1003 ! relative humidity (physics definition):
1004 !--------------------------
1005  idiag%id_rh10 = register_diag_field( trim(field), 'rh10', axes(1:2), time, &
1006  '10-mb relative humidity', '%', missing_value=missing_value )
1007  idiag%id_rh50 = register_diag_field( trim(field), 'rh50', axes(1:2), time, &
1008  '50-mb relative humidity', '%', missing_value=missing_value )
1009  idiag%id_rh100 = register_diag_field( trim(field), 'rh100', axes(1:2), time, &
1010  '100-mb relative humidity', '%', missing_value=missing_value )
1011  idiag%id_rh200 = register_diag_field( trim(field), 'rh200', axes(1:2), time, &
1012  '200-mb relative humidity', '%', missing_value=missing_value )
1013  idiag%id_rh250 = register_diag_field( trim(field), 'rh250', axes(1:2), time, &
1014  '250-mb relative humidity', '%', missing_value=missing_value )
1015  idiag%id_rh300 = register_diag_field( trim(field), 'rh300', axes(1:2), time, &
1016  '300-mb relative humidity', '%', missing_value=missing_value )
1017  idiag%id_rh500 = register_diag_field( trim(field), 'rh500', axes(1:2), time, &
1018  '500-mb relative humidity', '%', missing_value=missing_value )
1019  idiag%id_rh700 = register_diag_field( trim(field), 'rh700', axes(1:2), time, &
1020  '700-mb relative humidity', '%', missing_value=missing_value )
1021  idiag%id_rh850 = register_diag_field( trim(field), 'rh850', axes(1:2), time, &
1022  '850-mb relative humidity', '%', missing_value=missing_value )
1023  idiag%id_rh925 = register_diag_field( trim(field), 'rh925', axes(1:2), time, &
1024  '925-mb relative humidity', '%', missing_value=missing_value )
1025  idiag%id_rh1000 = register_diag_field( trim(field), 'rh1000', axes(1:2), time, &
1026  '1000-mb relative humidity', '%', missing_value=missing_value )
1027 !--------------------------
1028 ! Dew Point
1029 !--------------------------
1030  idiag%id_dp10 = register_diag_field( trim(field), 'dp10', axes(1:2), time, &
1031  '10-mb dew point', 'K', missing_value=missing_value )
1032  idiag%id_dp50 = register_diag_field( trim(field), 'dp50', axes(1:2), time, &
1033  '50-mb dew point', 'K', missing_value=missing_value )
1034  idiag%id_dp100 = register_diag_field( trim(field), 'dp100', axes(1:2), time, &
1035  '100-mb dew point', 'K', missing_value=missing_value )
1036  idiag%id_dp200 = register_diag_field( trim(field), 'dp200', axes(1:2), time, &
1037  '200-mb dew point', 'K', missing_value=missing_value )
1038  idiag%id_dp250 = register_diag_field( trim(field), 'dp250', axes(1:2), time, &
1039  '250-mb dew point', 'K', missing_value=missing_value )
1040  idiag%id_dp300 = register_diag_field( trim(field), 'dp300', axes(1:2), time, &
1041  '300-mb dew point', 'K', missing_value=missing_value )
1042  idiag%id_dp500 = register_diag_field( trim(field), 'dp500', axes(1:2), time, &
1043  '500-mb dew point', 'K', missing_value=missing_value )
1044  idiag%id_dp700 = register_diag_field( trim(field), 'dp700', axes(1:2), time, &
1045  '700-mb dew point', 'K', missing_value=missing_value )
1046  idiag%id_dp850 = register_diag_field( trim(field), 'dp850', axes(1:2), time, &
1047  '850-mb dew point', 'K', missing_value=missing_value )
1048  idiag%id_dp925 = register_diag_field( trim(field), 'dp925', axes(1:2), time, &
1049  '925-mb dew point', 'K', missing_value=missing_value )
1050  idiag%id_dp1000 = register_diag_field( trim(field), 'dp1000', axes(1:2), time, &
1051  '1000-mb dew point', 'K', missing_value=missing_value )
1052 !--------------------------
1053 ! relative humidity (CMIP definition):
1054 !--------------------------
1055  idiag%id_rh10_cmip = register_diag_field( trim(field), 'rh10_cmip', axes(1:2), time, &
1056  '10-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1057  idiag%id_rh50_cmip = register_diag_field( trim(field), 'rh50_cmip', axes(1:2), time, &
1058  '50-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1059  idiag%id_rh100_cmip = register_diag_field( trim(field), 'rh100_cmip', axes(1:2), time, &
1060  '100-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1061  idiag%id_rh250_cmip = register_diag_field( trim(field), 'rh250_cmip', axes(1:2), time, &
1062  '250-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1063  idiag%id_rh300_cmip = register_diag_field( trim(field), 'rh300_cmip', axes(1:2), time, &
1064  '300-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1065  idiag%id_rh500_cmip = register_diag_field( trim(field), 'rh500_cmip', axes(1:2), time, &
1066  '500-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1067  idiag%id_rh700_cmip = register_diag_field( trim(field), 'rh700_cmip', axes(1:2), time, &
1068  '700-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1069  idiag%id_rh850_cmip = register_diag_field( trim(field), 'rh850_cmip', axes(1:2), time, &
1070  '850-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1071  idiag%id_rh925_cmip = register_diag_field( trim(field), 'rh925_cmip', axes(1:2), time, &
1072  '925-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1073  idiag%id_rh1000_cmip = register_diag_field( trim(field), 'rh1000_cmip', axes(1:2), time, &
1074  '1000-mb relative humidity (CMIP)', '%', missing_value=missing_value )
1075 
1076  if (atm(n)%flagstruct%write_3d_diags) then
1077  do i=1, ncnst
1078  !--------------------
1079  ! Tracer diagnostics:
1080  !--------------------
1081  call get_tracer_names ( model_atmos, i, tname, tlongname, tunits )
1082  idiag%id_tracer(i) = register_diag_field( field, trim(tname), &
1083  axes(1:3), time, trim(tlongname), &
1085  if (master) then
1086  if (idiag%id_tracer(i) > 0) then
1087  unit = stdlog()
1088  write(unit,'(a,a,a,a)') &
1089  & 'Diagnostics available for tracer ',trim(tname), &
1090  ' in module ', trim(field)
1091  end if
1092  endif
1093  !----------------------------------
1094  ! ESM Tracer dmmr/dvmr diagnostics:
1095  ! for specific elements only
1096  !----------------------------------
1097  !---co2
1098  if (trim(tname).eq.'co2') then
1099  idiag%w_mr(:) = wtmco2
1100  idiag%id_tracer_dmmr(i) = register_diag_field( field, trim(tname)//'_dmmr', &
1101  axes(1:3), time, trim(tlongname)//" (dry mmr)", &
1103  idiag%id_tracer_dvmr(i) = register_diag_field( field, trim(tname)//'_dvmr', &
1104  axes(1:3), time, trim(tlongname)//" (dry vmr)", &
1105  'mol/mol', missing_value=missing_value)
1106  if (master) then
1107  unit = stdlog()
1108  if (idiag%id_tracer_dmmr(i) > 0) then
1109  write(unit,'(a,a,a,a)') 'Diagnostics available for '//trim(tname)//' dry mmr ', &
1110  trim(tname)//'_dmmr', ' in module ', trim(field)
1111  end if
1112  if (idiag%id_tracer_dvmr(i) > 0) then
1113  write(unit,'(a,a,a,a)') 'Diagnostics available for '//trim(tname)//' dry vmr ', &
1114  trim(tname)//'_dvmr', ' in module ', trim(field)
1115  end if
1116  endif
1117  endif
1118  !---end co2
1119 
1120  enddo
1121  endif
1122 
1123  if ( atm(1)%flagstruct%consv_am .or. idiag%id_mq > 0 .or. idiag%id_amdt > 0 ) then
1124  allocate ( idiag%zxg(isc:iec,jsc:jec) )
1125  ! Initialize gradient of terrain for mountain torque computation:
1126  call init_mq(atm(n)%phis, atm(n)%gridstruct, &
1127  npx, npy, isc, iec, jsc, jec, atm(n)%ng)
1128  endif
1129 
1130 ! end do
1131 
1132 
1133 #ifdef TEST_TRACER
1134  call prt_mass(npz, atm(n)%ncnst, isc, iec, jsc, jec, atm(n)%ng, max(1,atm(n)%flagstruct%nwat), &
1135  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
1136 #else
1137  call prt_mass(npz, atm(n)%ncnst, isc, iec, jsc, jec, atm(n)%ng, atm(n)%flagstruct%nwat, &
1138  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
1139 #endif
1140 
1141 
1142  !Set up debug column diagnostics, if desired
1143  !Start by hard-coding one diagnostic column then add options for more later
1144 
1145  diag_debug_names(:) = ''
1146  diag_debug_lon_in(:) = -999.
1147  diag_debug_lat_in(:) = -999.
1148 
1149  !diag_debug_names(1:2) = (/'ORD','Princeton'/)
1150  !diag_debug_lon_in(1:2) = (/272.,285.33/)
1151  !diag_debug_lat_in(1:2) = (/42.,40.36/)
1152 
1153  diag_sonde_names(:) = ''
1154  diag_sonde_lon_in(:) = -999.
1155  diag_sonde_lat_in(:) = -999.
1156 
1157  !diag_sonde_names(1:4) = (/'OUN','MYNN','PIT', 'ORD'/)
1158  !diag_sonde_lon_in(1:4) = (/285.33,282.54,279.78,272./)
1159  !diag_sonde_lat_in(1:4) = (/35.18,25.05,40.53,42./)
1160 
1161 
1162 #ifdef INTERNAL_FILE_NML
1163  read(input_nml_file, nml=fv_diag_column_nml,iostat=ios)
1164 #else
1165  inquire (file=trim(atm(n)%nml_filename), exist=exists)
1166  if (.not. exists) then
1167  write(errmsg,*) 'fv_diag_column_nml: namelist file ',trim(atm(n)%nml_filename),' does not exist'
1168  call mpp_error(fatal, errmsg)
1169  else
1170  open (unit=nlunit, file=atm(n)%nml_filename, readonly, status='OLD', iostat=ios)
1171  endif
1172  rewind(nlunit)
1173  read (nlunit, nml=fv_diag_column_nml, iostat=ios)
1174  close (nlunit)
1175 #endif
1176 
1177  call column_diagnostics_init
1178 
1179  if (do_diag_debug) then
1180 
1181  !Determine number of debug columns
1182  do m=1,max_diag_column
1183  !if (is_master()) print*, i, diag_debug_names(m), len(trim(diag_debug_names(m))), diag_debug_lon_in(m), diag_debug_lat_in(m)
1184  if (len(trim(diag_debug_names(m))) == 0 .or. diag_debug_lon_in(m) < -180. .or. diag_debug_lat_in(m) < -90.) exit
1186  if (diag_debug_lon_in(m) < 0.) diag_debug_lon_in(m) = diag_debug_lon_in(m) + 360.
1187  enddo
1188 
1189  if (num_diag_debug == 0) do_diag_debug = .false.
1190 
1191  endif
1192 
1193  if (do_diag_debug) then
1194 
1195  allocate(do_debug_diag_column(isc:iec,jsc:jec))
1196  allocate(diag_debug_lon(num_diag_debug))
1197  allocate(diag_debug_lat(num_diag_debug))
1198  allocate(diag_debug_i(num_diag_debug))
1199  allocate(diag_debug_j(num_diag_debug))
1200  allocate(diag_debug_units(num_diag_debug))
1201 
1202 
1203  call initialize_diagnostic_columns("DEBUG", num_diag_pts_latlon=num_diag_debug, num_diag_pts_ij=0, &
1204  global_i=(/1/), global_j=(/1/), &
1205  global_lat_latlon=diag_debug_lat_in, global_lon_latlon=diag_debug_lon_in, &
1206  lonb_in=atm(n)%gridstruct%agrid(isc:iec,jsc:jec,1), latb_in=atm(n)%gridstruct%agrid(isc:iec,jsc:jec,2), &
1207  do_column_diagnostics=do_debug_diag_column, &
1208  diag_lon=diag_debug_lon, diag_lat=diag_debug_lat, diag_i=diag_debug_i, diag_j=diag_debug_j, diag_units=diag_debug_units)
1209 
1210  do m=1,num_diag_debug
1211  diag_debug_i(m) = diag_debug_i(m) + isc - 1
1212  diag_debug_j(m) = diag_debug_j(m) + jsc - 1
1213 
1214  if (diag_debug_i(m) >= isc .and. diag_debug_i(m) <= iec .and. &
1215  diag_debug_j(m) >= jsc .and. diag_debug_j(m) <= jec ) then
1216  write(*,'(A, 1x, I04, 1x, A, 4F7.2, 2I5)') 'DEBUG POINT: ', mpp_pe(), diag_debug_names(m), diag_debug_lon_in(m), diag_debug_lat_in(m), &
1217  atm(n)%gridstruct%agrid(diag_debug_i(m), diag_debug_j(m),1)*rad2deg, atm(n)%gridstruct%agrid(diag_debug_i(m), diag_debug_j(m),2)*rad2deg, &
1218  diag_debug_i(m), diag_debug_j(m)
1219  endif
1220  enddo
1221 
1222  endif
1223 
1224 
1225  !Radiosondes
1226  if (do_diag_sonde) then
1227 
1228  !Determine number of sonde columns
1229  do m=1,max_diag_column
1230  if (len(trim(diag_sonde_names(m))) == 0 .or. diag_sonde_lon_in(m) < -180. .or. diag_sonde_lat_in(m) < -90.) exit
1231  !if (is_master()) print*, i, diag_sonde_names(m), len(trim(diag_sonde_names(m))), diag_sonde_lon_in(m), diag_sonde_lat_in(m)
1233  if (diag_sonde_lon_in(m) < 0.) diag_sonde_lon_in(m) = diag_sonde_lon_in(m) + 360.
1234  enddo
1235 
1236  if (num_diag_sonde == 0) do_diag_sonde = .false.
1237 
1238  endif
1239 
1240  if (do_diag_sonde) then
1241 
1242  allocate(do_sonde_diag_column(isc:iec,jsc:jec))
1243  allocate(diag_sonde_lon(num_diag_sonde))
1244  allocate(diag_sonde_lat(num_diag_sonde))
1245  allocate(diag_sonde_i(num_diag_sonde))
1246  allocate(diag_sonde_j(num_diag_sonde))
1247  allocate(diag_sonde_units(num_diag_sonde))
1248 
1249  call initialize_diagnostic_columns("Sounding", num_diag_pts_latlon=num_diag_sonde, num_diag_pts_ij=0, &
1250  global_i=(/1/), global_j=(/1/), &
1251  global_lat_latlon=diag_sonde_lat_in, global_lon_latlon=diag_sonde_lon_in, &
1252  lonb_in=atm(n)%gridstruct%agrid(isc:iec,jsc:jec,1), latb_in=atm(n)%gridstruct%agrid(isc:iec,jsc:jec,2), &
1253  do_column_diagnostics=do_sonde_diag_column, &
1254  diag_lon=diag_sonde_lon, diag_lat=diag_sonde_lat, diag_i=diag_sonde_i, diag_j=diag_sonde_j, diag_units=diag_sonde_units)
1255 
1256  do m=1,num_diag_sonde
1257  diag_sonde_i(m) = diag_sonde_i(m) + isc - 1
1258  diag_sonde_j(m) = diag_sonde_j(m) + jsc - 1
1259 
1260  if (diag_sonde_i(m) >= isc .and. diag_sonde_i(m) <= iec .and. &
1261  diag_sonde_j(m) >= jsc .and. diag_sonde_j(m) <= jec ) then
1262  write(*,'(A, 1x, I04, 1x, A, 4F7.2, 2I5)') 'SONDE POINT: ', mpp_pe(), diag_sonde_names(m), diag_sonde_lon_in(m), diag_sonde_lat_in(m), &
1263  atm(n)%gridstruct%agrid(diag_sonde_i(m), diag_sonde_j(m),1)*rad2deg, atm(n)%gridstruct%agrid(diag_sonde_i(m), diag_sonde_j(m),2)*rad2deg, &
1264  diag_sonde_i(m), diag_sonde_j(m)
1265  endif
1266  enddo
1267 
1268  endif
1269 
1270  !Model initialization time (not necessarily the time this simulation is started,
1271  ! conceivably a restart could be done
1272  if (m_calendar) then
1273  call get_date(atm(n)%Time_init, yr_init, mo_init, dy_init, hr_init, mn_init, sec_init)
1274  else
1275  call get_time(atm(n)%Time_init, sec_init, dy_init)
1276  yr_init = 0 ; mo_init = 0 ; hr_init = 0 ; mn_init = 0
1277  endif
1278 
1279  call nullify_domain() ! Nullify set_domain info
1280 
1281  module_is_initialized=.true.
1282  istep = 0
1283 #ifndef GFS_PHYS
1284  if(idiag%id_theta_e >0 ) call qsmith_init
1285 #endif
1286  end subroutine fv_diag_init
1287 
1288 
1289  subroutine init_mq(phis, gridstruct, npx, npy, is, ie, js, je, ng)
1290  integer, intent(in):: npx, npy, is, ie, js, je, ng
1291  real, intent(in):: phis(is-ng:ie+ng, js-ng:je+ng)
1292  type(fv_grid_type), intent(IN), target :: gridstruct
1293 
1294 ! local:
1295  real zs(is-ng:ie+ng, js-ng:je+ng)
1296  real zb(is-ng:ie+ng, js-ng:je+ng)
1297  real pdx(3,is:ie,js:je+1)
1298  real pdy(3,is:ie+1,js:je)
1299  integer i, j, n
1300 
1301  real, pointer :: rarea(:,:)
1302  real, pointer, dimension(:,:) :: dx, dy
1303  real(kind=R_GRID), pointer, dimension(:,:,:) :: en1, en2, vlon, vlat
1304  real, pointer, dimension(:,:,:) :: agrid
1305 
1306  rarea => gridstruct%rarea
1307  dx => gridstruct%dx
1308  dy => gridstruct%dy
1309  en1 => gridstruct%en1
1310  en2 => gridstruct%en2
1311  agrid => gridstruct%agrid
1312  vlon => gridstruct%vlon
1313  vlat => gridstruct%vlat
1314 
1315 ! do j=js,je
1316 ! do i=is,ie
1317  do j=js-ng,je+ng
1318  do i=is-ng,ie+ng
1319  zs(i,j) = phis(i,j) / grav
1320  enddo
1321  enddo
1322 ! call mpp_update_domains( zs, domain )
1323 
1324 ! call a2b_ord2(zs, zb, gridstruct, npx, npy, is, ie, js, je, ng)
1325  call a2b_ord4(zs, zb, gridstruct, npx, npy, is, ie, js, je, ng)
1326 
1327  do j=js,je+1
1328  do i=is,ie
1329  do n=1,3
1330  pdx(n,i,j) = 0.5*(zb(i,j)+zb(i+1,j))*dx(i,j)*en1(n,i,j)
1331  enddo
1332  enddo
1333  enddo
1334  do j=js,je
1335  do i=is,ie+1
1336  do n=1,3
1337  pdy(n,i,j) = 0.5*(zb(i,j)+zb(i,j+1))*dy(i,j)*en2(n,i,j)
1338  enddo
1339  enddo
1340  enddo
1341 
1342 ! Compute "volume-mean" gradient by Green's theorem
1343  do j=js,je
1344  do i=is,ie
1345  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)) &
1346  + vlon(i,j,2)*(pdx(2,i,j+1)-pdx(2,i,j)-pdy(2,i,j)+pdy(2,i+1,j)) &
1347  + vlon(i,j,3)*(pdx(3,i,j+1)-pdx(3,i,j)-pdy(3,i,j)+pdy(3,i+1,j))
1348 ! dF/d(lamda) = radius*cos(agrid(i,j,2)) * dF/dx, F is a scalar
1349 ! ________________________
1350  idiag%zxg(i,j) = idiag%zxg(i,j)*rarea(i,j) * radius*cos(agrid(i,j,2))
1351 ! ^^^^^^^^^^^^^^^^^^^^^^^^
1352  enddo
1353  enddo
1354 
1355  end subroutine init_mq
1356 
1357  subroutine fv_diag(Atm, zvir, Time, print_freq)
1359  type(fv_atmos_type), intent(inout) :: Atm(:)
1360  type(time_type), intent(in) :: Time
1361  real, intent(in):: zvir
1362  integer, intent(in):: print_freq
1363 
1364  integer :: isc, iec, jsc, jec, n, ntileMe
1365  integer :: isd, ied, jsd, jed, npz, itrac
1366  integer :: ngc, nwater
1367 
1368  real, allocatable :: a2(:,:),a3(:,:,:), wk(:,:,:), wz(:,:,:), ucoor(:,:,:), vcoor(:,:,:)
1369  real, allocatable :: ustm(:,:), vstm(:,:)
1370  real, allocatable :: slp(:,:), depress(:,:), ws_max(:,:), tc_count(:,:)
1371  real, allocatable :: u2(:,:), v2(:,:), x850(:,:), var1(:,:), var2(:,:), var3(:,:)
1372  real, allocatable :: dmmr(:,:,:), dvmr(:,:,:)
1373  real height(2)
1374  real:: plevs(nplev), pout(nplev)
1375  integer:: idg(nplev), id1(nplev)
1376  real :: tot_mq, tmp, sar, slon, slat
1377  real :: a1d(atm(1)%npz)
1378 ! real :: t_gb, t_nh, t_sh, t_eq, area_gb, area_nh, area_sh, area_eq
1379  logical :: do_cs_intp
1380  logical :: used
1381  logical :: bad_range
1382  integer i,j,k, yr, mon, dd, hr, mn, days, seconds, nq, theta_d
1383  character(len=128) :: tname
1384  real, parameter:: ws_0 = 16. ! minimum max_wind_speed within the 7x7 search box
1385  real, parameter:: ws_1 = 20.
1386  real, parameter:: vort_c0= 2.2e-5
1387  logical, allocatable :: storm(:,:), cat_crt(:,:)
1388  real :: tmp2, pvsum, e2, einf, qm, mm, maxdbz, allmax, rgrav, cv_vapor
1389  real, allocatable :: cvm(:)
1390  integer :: Cl, Cl2, k1, k2
1391 
1392  !!! CLEANUP: does it really make sense to have this routine loop over Atm% anymore? We assume n=1 below anyway
1393 
1394 ! cat15: SLP<1000; srf_wnd>ws_0; vort>vort_c0
1395 ! cat25: SLP< 980; srf_wnd>ws_1; vort>vort_c0
1396 ! cat35: SLP< 964; srf_wnd>ws_1; vort>vort_c0
1397 ! cat45: SLP< 944; srf_wnd>ws_1; vort>vort_c0
1398 
1399  height(1) = 5.e3 ! for computing 5-km "pressure"
1400  height(2) = 0. ! for sea-level pressure
1401 
1402  do i=1,nplev
1403  pout(i) = levs(i) * 1.e2
1404  plevs(i) = log( pout(i) )
1405  enddo
1406 
1407  ntileme = size(atm(:))
1408  n = 1
1409  isc = atm(n)%bd%isc; iec = atm(n)%bd%iec
1410  jsc = atm(n)%bd%jsc; jec = atm(n)%bd%jec
1411  ngc = atm(n)%ng
1412  npz = atm(n)%npz
1413  ptop = atm(n)%ak(1)
1414  nq = size (atm(n)%q,4)
1415 
1416  isd = atm(n)%bd%isd; ied = atm(n)%bd%ied
1417  jsd = atm(n)%bd%jsd; jed = atm(n)%bd%jed
1418 
1419  if( idiag%id_c15>0 ) then
1420  allocate ( storm(isc:iec,jsc:jec) )
1421  allocate ( depress(isc:iec,jsc:jec) )
1422  allocate ( ws_max(isc:iec,jsc:jec) )
1423  allocate ( cat_crt(isc:iec,jsc:jec) )
1424  allocate (tc_count(isc:iec,jsc:jec) )
1425  endif
1426 
1427  if( idiag%id_x850>0 ) then
1428  allocate ( x850(isc:iec,jsc:jec) )
1429  endif
1430 
1431  fv_time = time
1432  call set_domain(atm(1)%domain)
1433 
1434  if ( m_calendar ) then
1435  call get_date(fv_time, yr, mon, dd, hr, mn, seconds)
1436  if( print_freq == 0 ) then
1437  prt_minmax = .false.
1438  elseif( print_freq < 0 ) then
1439  istep = istep + 1
1440  prt_minmax = mod(istep, -print_freq) == 0
1441  else
1442  prt_minmax = mod(hr, print_freq) == 0 .and. mn==0 .and. seconds==0
1443  endif
1444 
1445  if ( sound_freq == 0 .or. .not. do_diag_sonde ) then
1446  prt_sounding = .false.
1447  else
1448  prt_sounding = mod(hr, sound_freq) == 0 .and. mn == 0 .and. seconds == 0
1449  endif
1450  else
1451  call get_time (fv_time, seconds, days)
1452  if( print_freq == 0 ) then
1453  prt_minmax = .false.
1454  elseif( print_freq < 0 ) then
1455  istep = istep + 1
1456  prt_minmax = mod(istep, -print_freq) == 0
1457  else
1458  prt_minmax = mod(seconds, 3600*print_freq) == 0
1459  endif
1460 
1461  if ( sound_freq == 0 .or. .not. do_diag_sonde ) then
1462  prt_sounding = .false.
1463  else
1464  prt_sounding = mod(seconds, 3600*sound_freq) == 0
1465  endif
1466 
1467  endif
1468 
1469  if(prt_minmax) then
1470  if ( m_calendar ) then
1471  if(master) write(*,*) yr, mon, dd, hr, mn, seconds
1472  else
1473  if(master) write(*,*) days, seconds
1474  endif
1475  endif
1476 
1477  allocate ( a2(isc:iec,jsc:jec) )
1478 
1479  if( prt_minmax ) then
1480 
1481  call prt_mxm('ZS', idiag%zsurf, isc, iec, jsc, jec, 0, 1, 1.0, atm(n)%gridstruct%area_64, atm(n)%domain)
1482  call prt_maxmin('PS', atm(n)%ps, isc, iec, jsc, jec, ngc, 1, 0.01)
1483 
1484 #ifdef HIWPP
1485  allocate(var2(isc:iec,jsc:jec))
1486  !hemispheric max/min pressure
1487  do j=jsc,jec
1488  do i=isc,iec
1489  slat = rad2deg*atm(n)%gridstruct%agrid(i,j,2)
1490  if (slat >= 0.) then
1491  a2(i,j) = atm(n)%ps(i,j)
1492  var2(i,j) = 101300.
1493  else
1494  a2(i,j) = 101300.
1495  var2(i,j) = atm(n)%ps(i,j)
1496  endif
1497  enddo
1498  enddo
1499  call prt_maxmin('NH PS', a2, isc, iec, jsc, jec, 0, 1, 0.01)
1500  call prt_maxmin('SH PS', var2, isc, iec, jsc, jec, 0, 1, 0.01)
1501 
1502  deallocate(var2)
1503 #endif
1504 
1505 #ifdef TEST_TRACER
1506  call prt_mass(npz, nq, isc, iec, jsc, jec, ngc, max(1,atm(n)%flagstruct%nwat), &
1507  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
1508 #else
1509  call prt_mass(npz, nq, isc, iec, jsc, jec, ngc, atm(n)%flagstruct%nwat, &
1510  atm(n)%ps, atm(n)%delp, atm(n)%q, atm(n)%gridstruct%area_64, atm(n)%domain)
1511 #endif
1512 
1513 #ifndef SW_DYNAMICS
1514  if (atm(n)%flagstruct%consv_te > 1.e-5) then
1515  idiag%steps = idiag%steps + 1
1516  idiag%efx_sum = idiag%efx_sum + e_flux
1517  if ( idiag%steps <= max_step ) idiag%efx(idiag%steps) = e_flux
1518  if (master) then
1519  write(*,*) 'ENG Deficit (W/m**2)', trim(gn), '=', e_flux
1520  endif
1521 
1522 
1523  endif
1524  if ( .not. atm(n)%flagstruct%hydrostatic ) &
1525  call nh_total_energy(isc, iec, jsc, jec, isd, ied, jsd, jed, npz, &
1526  atm(n)%w, atm(n)%delz, atm(n)%pt, atm(n)%delp, &
1527  atm(n)%q, atm(n)%phis, atm(n)%gridstruct%area, atm(n)%domain, &
1528  sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, atm(n)%flagstruct%nwat, &
1529  atm(n)%ua, atm(n)%va, atm(n)%flagstruct%moist_phys, a2)
1530 #endif
1531  call prt_maxmin('UA_top', atm(n)%ua(isc:iec,jsc:jec,1), &
1532  isc, iec, jsc, jec, 0, 1, 1.)
1533  call prt_maxmin('UA', atm(n)%ua, isc, iec, jsc, jec, ngc, npz, 1.)
1534  call prt_maxmin('VA', atm(n)%va, isc, iec, jsc, jec, ngc, npz, 1.)
1535 
1536  if ( .not. atm(n)%flagstruct%hydrostatic ) then
1537  call prt_maxmin('W ', atm(n)%w , isc, iec, jsc, jec, ngc, npz, 1.)
1538  call prt_maxmin('Bottom w', atm(n)%w(isc:iec,jsc:jec,npz), isc, iec, jsc, jec, 0, 1, 1.)
1539  do j=jsc,jec
1540  do i=isc,iec
1541  a2(i,j) = -atm(n)%w(i,j,npz)/atm(n)%delz(i,j,npz)
1542  enddo
1543  enddo
1544  call prt_maxmin('Bottom: w/dz', a2, isc, iec, jsc, jec, 0, 1, 1.)
1545 
1546  if ( atm(n)%flagstruct%hybrid_z ) call prt_maxmin('Hybrid_ZTOP (km)', atm(n)%ze0(isc:iec,jsc:jec,1), &
1547  isc, iec, jsc, jec, 0, 1, 1.e-3)
1548  call prt_maxmin('DZ (m)', atm(n)%delz(isc:iec,jsc:jec,1:npz), &
1549  isc, iec, jsc, jec, 0, npz, 1.)
1550  call prt_maxmin('Bottom DZ (m)', atm(n)%delz(isc:iec,jsc:jec,npz), &
1551  isc, iec, jsc, jec, 0, 1, 1.)
1552 ! call prt_maxmin('Top DZ (m)', Atm(n)%delz(isc:iec,jsc:jec,1), &
1553 ! isc, iec, jsc, jec, 0, 1, 1.)
1554  endif
1555 
1556 #ifndef SW_DYNAMICS
1557  call prt_maxmin('TA', atm(n)%pt, isc, iec, jsc, jec, ngc, npz, 1.)
1558 ! call prt_maxmin('Top: TA', Atm(n)%pt(isc:iec,jsc:jec, 1), isc, iec, jsc, jec, 0, 1, 1.)
1559 ! call prt_maxmin('Bot: TA', Atm(n)%pt(isc:iec,jsc:jec,npz), isc, iec, jsc, jec, 0, 1, 1.)
1560  call prt_maxmin('OM', atm(n)%omga, isc, iec, jsc, jec, ngc, npz, 1.)
1561 #endif
1562 
1563  elseif ( atm(n)%flagstruct%range_warn ) then
1564  call range_check('DELP', atm(n)%delp, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1565  0.01*ptop, 200.e2, bad_range, time)
1566  call range_check('UA', atm(n)%ua, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1567  -250., 250., bad_range, time)
1568  call range_check('VA', atm(n)%va, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1569  -250., 250., bad_range, time)
1570 #ifndef SW_DYNAMICS
1571  call range_check('TA', atm(n)%pt, isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1572 #ifdef HIWPP
1573  130., 350., bad_range, time) !DCMIP ICs have very low temperatures
1574 #else
1575  150., 350., bad_range, time)
1576 #endif
1577 #endif
1578  call range_check('Qv', atm(n)%q(:,:,:,sphum), isc, iec, jsc, jec, ngc, npz, atm(n)%gridstruct%agrid, &
1579  -1.e-8, 1.e20, bad_range, time)
1580 
1581  endif
1582 
1583  allocate ( u2(isc:iec,jsc:jec) )
1584  allocate ( v2(isc:iec,jsc:jec) )
1585  allocate ( wk(isc:iec,jsc:jec,npz) )
1586  if ( any(idiag%id_tracer_dmmr > 0) .or. any(idiag%id_tracer_dvmr > 0) ) then
1587  allocate ( dmmr(isc:iec,jsc:jec,1:npz) )
1588  allocate ( dvmr(isc:iec,jsc:jec,1:npz) )
1589  endif
1590 
1591 ! do n = 1, ntileMe
1592  n = 1
1593 
1594 #ifdef DYNAMICS_ZS
1595  if(idiag%id_zsurf > 0) used=send_data(idiag%id_zsurf, idiag%zsurf, time)
1596 #endif
1597  if(idiag%id_ps > 0) used=send_data(idiag%id_ps, atm(n)%ps(isc:iec,jsc:jec), time)
1598 
1599  if (idiag%id_qv_dt_phys > 0) used=send_data(idiag%id_qv_dt_phys, atm(n)%phys_diag%phys_qv_dt(isc:iec,jsc:jec,1:npz), time)
1600  if (idiag%id_ql_dt_phys > 0) used=send_data(idiag%id_ql_dt_phys, atm(n)%phys_diag%phys_ql_dt(isc:iec,jsc:jec,1:npz), time)
1601  if (idiag%id_qi_dt_phys > 0) used=send_data(idiag%id_qi_dt_phys, atm(n)%phys_diag%phys_qi_dt(isc:iec,jsc:jec,1:npz), time)
1602  if (idiag%id_t_dt_phys > 0) used=send_data(idiag%id_t_dt_phys, atm(n)%phys_diag%phys_t_dt(isc:iec,jsc:jec,1:npz), time)
1603  if (idiag%id_u_dt_phys > 0) used=send_data(idiag%id_u_dt_phys, atm(n)%phys_diag%phys_u_dt(isc:iec,jsc:jec,1:npz), time)
1604  if (idiag%id_v_dt_phys > 0) used=send_data(idiag%id_v_dt_phys, atm(n)%phys_diag%phys_v_dt(isc:iec,jsc:jec,1:npz), time)
1605 
1606  if(idiag%id_c15>0 .or. idiag%id_c25>0 .or. idiag%id_c35>0 .or. idiag%id_c45>0) then
1607  call wind_max(isc, iec, jsc, jec ,isd, ied, jsd, jed, atm(n)%ua(isc:iec,jsc:jec,npz), &
1608  atm(n)%va(isc:iec,jsc:jec,npz), ws_max, atm(n)%domain)
1609  do j=jsc,jec
1610  do i=isc,iec
1611  if( abs(atm(n)%gridstruct%agrid(i,j,2)*rad2deg)<45.0 .and. &
1612  atm(n)%phis(i,j)*ginv<500.0 .and. ws_max(i,j)>ws_0 ) then
1613  storm(i,j) = .true.
1614  else
1615  storm(i,j) = .false.
1616  endif
1617  enddo
1618  enddo
1619  endif
1620 
1621  if ( idiag%id_vort200>0 .or. idiag%id_vort500>0 .or. idiag%id_vort850>0 .or. idiag%id_vorts>0 &
1622  .or. idiag%id_vort>0 .or. idiag%id_pv>0 .or. idiag%id_rh>0 .or. idiag%id_x850>0 .or. &
1623  idiag%id_uh03>0 .or. idiag%id_uh25>0) then
1624  call get_vorticity(isc, iec, jsc, jec, isd, ied, jsd, jed, npz, atm(n)%u, atm(n)%v, wk, &
1625  atm(n)%gridstruct%dx, atm(n)%gridstruct%dy, atm(n)%gridstruct%rarea)
1626 
1627  if(idiag%id_vort >0) used=send_data(idiag%id_vort, wk, time)
1628  if(idiag%id_vorts>0) used=send_data(idiag%id_vorts, wk(isc:iec,jsc:jec,npz), time)
1629 
1630  if(idiag%id_c15>0) then
1631  do j=jsc,jec
1632  do i=isc,iec
1633  if ( storm(i,j) ) &
1634  storm(i,j) = (atm(n)%gridstruct%agrid(i,j,2)>0. .and. wk(i,j,npz)> vort_c0) .or. &
1635  (atm(n)%gridstruct%agrid(i,j,2)<0. .and. wk(i,j,npz)<-vort_c0)
1636  enddo
1637  enddo
1638  endif
1639 
1640  if( idiag%id_vort200>0 ) then
1641  call interpolate_vertical(isc, iec, jsc, jec, npz, &
1642  200.e2, atm(n)%peln, wk, a2)
1643  used=send_data(idiag%id_vort200, a2, time)
1644  endif
1645  if( idiag%id_vort500>0 ) then
1646  call interpolate_vertical(isc, iec, jsc, jec, npz, &
1647  500.e2, atm(n)%peln, wk, a2)
1648  used=send_data(idiag%id_vort500, a2, time)
1649  endif
1650 
1651  if(idiag%id_vort850>0 .or. idiag%id_c15>0 .or. idiag%id_x850>0) then
1652  call interpolate_vertical(isc, iec, jsc, jec, npz, &
1653  850.e2, atm(n)%peln, wk, a2)
1654  used=send_data(idiag%id_vort850, a2, time)
1655  if ( idiag%id_x850>0 ) x850(:,:) = a2(:,:)
1656 
1657  if(idiag%id_c15>0) then
1658  do j=jsc,jec
1659  do i=isc,iec
1660  if ( storm(i,j) ) &
1661  storm(i,j) = (atm(n)%gridstruct%agrid(i,j,2)>0. .and. a2(i,j)> vort_c0) .or. &
1662  (atm(n)%gridstruct%agrid(i,j,2)<0. .and. a2(i,j)<-vort_c0)
1663  enddo
1664  enddo
1665  endif
1666 
1667  endif
1668 
1669  if( .not. atm(n)%flagstruct%hydrostatic ) then
1670 
1671  if ( idiag%id_uh03 > 0 ) then
1672  call updraft_helicity(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1673  atm(n)%w, wk, atm(n)%delz, atm(n)%q, &
1674  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 0., 3.e3)
1675  used = send_data( idiag%id_uh03, a2, time )
1676  if(prt_minmax) then
1677  do j=jsc,jec
1678  do i=isc,iec
1679  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
1680  tmp2 = rad2deg * atm(n)%gridstruct%agrid(i,j,2)
1681  if ( tmp2<25. .or. tmp2>50. &
1682  .or. tmp<235. .or. tmp>300. ) then
1683  a2(i,j) = 0.
1684  endif
1685  enddo
1686  enddo
1687  call prt_maxmin('UH over CONUS', a2, isc, iec, jsc, jec, 0, 1, 1.)
1688  endif
1689  endif
1690  if ( idiag%id_uh25 > 0 ) then
1691  call updraft_helicity(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1692  atm(n)%w, wk, atm(n)%delz, atm(n)%q, &
1693  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 2.e3, 5.e3)
1694  used = send_data( idiag%id_uh25, a2, time )
1695  endif
1696  endif
1697 
1698 
1699  if ( idiag%id_srh1 > 0 .or. idiag%id_srh3 > 0 .or. idiag%id_srh25 > 0 .or. idiag%id_ustm > 0 .or. idiag%id_vstm > 0) then
1700  allocate(ustm(isc:iec,jsc:jec), vstm(isc:iec,jsc:jec))
1701 
1702  call bunkers_vector(isc, iec, jsc, jec, ngc, npz, zvir, sphum, ustm, vstm, &
1703  atm(n)%ua, atm(n)%va, atm(n)%delz, atm(n)%q, &
1704  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav)
1705 
1706  if ( idiag%id_ustm > 0 ) then
1707  used = send_data( idiag%id_ustm, ustm, time )
1708  endif
1709  if ( idiag%id_vstm > 0 ) then
1710  used = send_data( idiag%id_vstm, vstm, time )
1711  endif
1712 
1713  if ( idiag%id_srh1 > 0 ) then
1714  call helicity_relative_caps(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, ustm, vstm, &
1715  atm(n)%ua, atm(n)%va, atm(n)%delz, atm(n)%q, &
1716  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 0., 1.e3)
1717  used = send_data( idiag%id_srh1, a2, time )
1718  if(prt_minmax) then
1719  do j=jsc,jec
1720  do i=isc,iec
1721  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
1722  tmp2 = rad2deg * atm(n)%gridstruct%agrid(i,j,2)
1723  if ( tmp2<25. .or. tmp2>50. &
1724  .or. tmp<235. .or. tmp>300. ) then
1725  a2(i,j) = 0.
1726  endif
1727  enddo
1728  enddo
1729  call prt_maxmin('SRH (0-1 km) over CONUS', a2, isc, iec, jsc, jec, 0, 1, 1.)
1730  endif
1731  endif
1732 
1733  if ( idiag%id_srh3 > 0 ) then
1734  call helicity_relative_caps(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, ustm, vstm, &
1735  atm(n)%ua, atm(n)%va, atm(n)%delz, atm(n)%q, &
1736  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 0., 3e3)
1737  used = send_data( idiag%id_srh3, a2, time )
1738  if(prt_minmax) then
1739  do j=jsc,jec
1740  do i=isc,iec
1741  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
1742  tmp2 = rad2deg * atm(n)%gridstruct%agrid(i,j,2)
1743  if ( tmp2<25. .or. tmp2>50. &
1744  .or. tmp<235. .or. tmp>300. ) then
1745  a2(i,j) = 0.
1746  endif
1747  enddo
1748  enddo
1749  call prt_maxmin('SRH (0-3 km) over CONUS', a2, isc, iec, jsc, jec, 0, 1, 1.)
1750  endif
1751  endif
1752 
1753  if ( idiag%id_srh25 > 0 ) then
1754  call helicity_relative_caps(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, ustm, vstm, &
1755  atm(n)%ua, atm(n)%va, atm(n)%delz, atm(n)%q, &
1756  atm(n)%flagstruct%hydrostatic, atm(n)%pt, atm(n)%peln, atm(n)%phis, grav, 2.e3, 5e3)
1757  used = send_data( idiag%id_srh25, a2, time )
1758  if(prt_minmax) then
1759  do j=jsc,jec
1760  do i=isc,iec
1761  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
1762  tmp2 = rad2deg * atm(n)%gridstruct%agrid(i,j,2)
1763  if ( tmp2<25. .or. tmp2>50. &
1764  .or. tmp<235. .or. tmp>300. ) then
1765  a2(i,j) = 0.
1766  endif
1767  enddo
1768  enddo
1769  call prt_maxmin('SRH (2-5 km) over CONUS', a2, isc, iec, jsc, jec, 0, 1, 1.)
1770  endif
1771  endif
1772 
1773  deallocate(ustm, vstm)
1774  endif
1775 
1776 
1777  if ( idiag%id_pv > 0 ) then
1778 ! Note: this is expensive computation.
1779  call pv_entropy(isc, iec, jsc, jec, ngc, npz, wk, &
1780  atm(n)%gridstruct%f0, atm(n)%pt, atm(n)%pkz, atm(n)%delp, grav)
1781  used = send_data( idiag%id_pv, wk, time )
1782  if (prt_minmax) call prt_maxmin('PV', wk, isc, iec, jsc, jec, 0, 1, 1.)
1783  endif
1784 
1785  endif
1786 
1787 
1788 
1789 !!$ if ( idiag%id_srh > 0 ) then
1790 !!$ call helicity_relative(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1791 !!$ Atm(n)%ua, Atm(n)%va, Atm(n)%delz, Atm(n)%q, &
1792 !!$ Atm(n)%flagstruct%hydrostatic, Atm(n)%pt, Atm(n)%peln, Atm(n)%phis, grav, 0., 3.e3)
1793 !!$ used = send_data ( idiag%id_srh, a2, Time )
1794 !!$ if(prt_minmax) then
1795 !!$ do j=jsc,jec
1796 !!$ do i=isc,iec
1797 !!$ tmp = rad2deg * Atm(n)%gridstruct%agrid(i,j,1)
1798 !!$ tmp2 = rad2deg * Atm(n)%gridstruct%agrid(i,j,2)
1799 !!$ if ( tmp2<25. .or. tmp2>50. &
1800 !!$ .or. tmp<235. .or. tmp>300. ) then
1801 !!$ a2(i,j) = 0.
1802 !!$ endif
1803 !!$ enddo
1804 !!$ enddo
1805 !!$ call prt_maxmin('SRH over CONUS', a2, isc, iec, jsc, jec, 0, 1, 1.)
1806 !!$ endif
1807 !!$ endif
1808 
1809 !!$ if ( idiag%id_srh25 > 0 ) then
1810 !!$ call helicity_relative(isc, iec, jsc, jec, ngc, npz, zvir, sphum, a2, &
1811 !!$ Atm(n)%ua, Atm(n)%va, Atm(n)%delz, Atm(n)%q, &
1812 !!$ Atm(n)%flagstruct%hydrostatic, Atm(n)%pt, Atm(n)%peln, Atm(n)%phis, grav, 2.e3, 5.e3)
1813 !!$ used = send_data ( idiag%id_srh25, a2, Time )
1814 !!$ endif
1815 
1816 
1817  ! Relative Humidity
1818  if ( idiag%id_rh > 0 ) then
1819  ! Compute FV mean pressure
1820  do k=1,npz
1821  do j=jsc,jec
1822  do i=isc,iec
1823  a2(i,j) = atm(n)%delp(i,j,k)/(atm(n)%peln(i,k+1,j)-atm(n)%peln(i,k,j))
1824  enddo
1825  enddo
1826 #ifdef MULTI_GASES
1827  call qsmith((iec-isc+1)*(jec-jsc+1), npz, &
1828  (iec-isc+1)*(jec-jsc+1), 1, atm(n)%pt(isc:iec,jsc:jec,k), &
1829  a2, atm(n)%q(isc:iec,jsc:jec,k,sphum), wk(isc,jsc,k))
1830 #else
1831  call qsmith(iec-isc+1, jec-jsc+1, 1, atm(n)%pt(isc:iec,jsc:jec,k), &
1832  a2, atm(n)%q(isc:iec,jsc:jec,k,sphum), wk(isc,jsc,k))
1833 #endif
1834  do j=jsc,jec
1835  do i=isc,iec
1836  wk(i,j,k) = 100.*atm(n)%q(i,j,k,sphum)/wk(i,j,k)
1837  enddo
1838  enddo
1839  enddo
1840  used = send_data( idiag%id_rh, wk, time )
1841  if(prt_minmax) then
1842  call prt_maxmin('RH_sf (%)', wk(isc:iec,jsc:jec,npz), isc, iec, jsc, jec, 0, 1, 1.)
1843  call prt_maxmin('RH_3D (%)', wk, isc, iec, jsc, jec, 0, npz, 1.)
1844  endif
1845  endif
1846 
1847  ! rel hum from physics at selected press levels (for IPCC)
1848  if (idiag%id_rh50>0 .or. idiag%id_rh100>0 .or. idiag%id_rh200>0 .or. idiag%id_rh250>0 .or. &
1849  idiag%id_rh300>0 .or. idiag%id_rh500>0 .or. idiag%id_rh700>0 .or. idiag%id_rh850>0 .or. &
1850  idiag%id_rh925>0 .or. idiag%id_rh1000>0 .or. &
1851  idiag%id_dp50>0 .or. idiag%id_dp100>0 .or. idiag%id_dp200>0 .or. idiag%id_dp250>0 .or. &
1852  idiag%id_dp300>0 .or. idiag%id_dp500>0 .or. idiag%id_dp700>0 .or. idiag%id_dp850>0 .or. &
1853  idiag%id_dp925>0 .or. idiag%id_dp1000>0) then
1854  ! compute mean pressure
1855  do k=1,npz
1856  do j=jsc,jec
1857  do i=isc,iec
1858  a2(i,j) = atm(n)%delp(i,j,k)/(atm(n)%peln(i,k+1,j)-atm(n)%peln(i,k,j))
1859  enddo
1860  enddo
1861  call rh_calc (a2, atm(n)%pt(isc:iec,jsc:jec,k), &
1862  atm(n)%q(isc:iec,jsc:jec,k,sphum), wk(isc:iec,jsc:jec,k))
1863  enddo
1864  if (idiag%id_rh50>0) then
1865  call interpolate_vertical(isc, iec, jsc, jec, npz, 50.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1866  used=send_data(idiag%id_rh50, a2, time)
1867  endif
1868  if (idiag%id_rh100>0) then
1869  call interpolate_vertical(isc, iec, jsc, jec, npz, 100.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1870  used=send_data(idiag%id_rh100, a2, time)
1871  endif
1872  if (idiag%id_rh200>0) then
1873  call interpolate_vertical(isc, iec, jsc, jec, npz, 200.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1874  used=send_data(idiag%id_rh200, a2, time)
1875  endif
1876  if (idiag%id_rh250>0) then
1877  call interpolate_vertical(isc, iec, jsc, jec, npz, 250.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1878  used=send_data(idiag%id_rh250, a2, time)
1879  endif
1880  if (idiag%id_rh300>0) then
1881  call interpolate_vertical(isc, iec, jsc, jec, npz, 300.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1882  used=send_data(idiag%id_rh300, a2, time)
1883  endif
1884  if (idiag%id_rh500>0) then
1885  call interpolate_vertical(isc, iec, jsc, jec, npz, 500.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1886  used=send_data(idiag%id_rh500, a2, time)
1887  endif
1888  if (idiag%id_rh700>0) then
1889  call interpolate_vertical(isc, iec, jsc, jec, npz, 700.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1890  used=send_data(idiag%id_rh700, a2, time)
1891  endif
1892  if (idiag%id_rh850>0) then
1893  call interpolate_vertical(isc, iec, jsc, jec, npz, 850.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1894  used=send_data(idiag%id_rh850, a2, time)
1895  endif
1896  if (idiag%id_rh925>0) then
1897  call interpolate_vertical(isc, iec, jsc, jec, npz, 925.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1898  used=send_data(idiag%id_rh925, a2, time)
1899  endif
1900  if (idiag%id_rh1000>0) then
1901  call interpolate_vertical(isc, iec, jsc, jec, npz, 1000.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1902  used=send_data(idiag%id_rh1000, a2, time)
1903  endif
1904 
1905  if (idiag%id_dp50>0 .or. idiag%id_dp100>0 .or. idiag%id_dp200>0 .or. idiag%id_dp250>0 .or. &
1906  idiag%id_dp300>0 .or. idiag%id_dp500>0 .or. idiag%id_dp700>0 .or. idiag%id_dp850>0 .or. &
1907  idiag%id_dp925>0 .or. idiag%id_dp1000>0 ) then
1908 
1909  if (allocated(a3)) deallocate(a3)
1910  allocate(a3(isc:iec,jsc:jec,1:npz))
1911  !compute dew point (K)
1912  !using formula at https://cals.arizona.edu/azmet/dewpoint.html
1913  do k=1,npz
1914  do j=jsc,jec
1915  do i=isc,iec
1916  tmp = ( log(max(wk(i,j,k)*1.e-2,1.e-2)) + 17.27 * ( atm(n)%pt(i,j,k) - 273.14 )/ ( -35.84 + atm(n)%pt(i,j,k)) ) / 17.27
1917  a3(i,j,k) = 273.14 + 237.3*tmp/ ( 1. - tmp )
1918  enddo
1919  enddo
1920  enddo
1921 
1922  if (idiag%id_dp50>0) then
1923  call interpolate_vertical(isc, iec, jsc, jec, npz, 50.e2, atm(n)%peln, a3, a2)
1924  used=send_data(idiag%id_dp50, a2, time)
1925  endif
1926  if (idiag%id_dp100>0) then
1927  call interpolate_vertical(isc, iec, jsc, jec, npz, 100.e2, atm(n)%peln, a3, a2)
1928  used=send_data(idiag%id_dp100, a2, time)
1929  endif
1930  if (idiag%id_dp200>0) then
1931  call interpolate_vertical(isc, iec, jsc, jec, npz, 200.e2, atm(n)%peln, a3, a2)
1932  used=send_data(idiag%id_dp200, a2, time)
1933  endif
1934  if (idiag%id_dp250>0) then
1935  call interpolate_vertical(isc, iec, jsc, jec, npz, 250.e2, atm(n)%peln, a3, a2)
1936  used=send_data(idiag%id_dp250, a2, time)
1937  endif
1938  if (idiag%id_dp300>0) then
1939  call interpolate_vertical(isc, iec, jsc, jec, npz, 300.e2, atm(n)%peln, a3, a2)
1940  used=send_data(idiag%id_dp300, a2, time)
1941  endif
1942  if (idiag%id_dp500>0) then
1943  call interpolate_vertical(isc, iec, jsc, jec, npz, 500.e2, atm(n)%peln, a3, a2)
1944  used=send_data(idiag%id_dp500, a2, time)
1945  endif
1946  if (idiag%id_dp700>0) then
1947  call interpolate_vertical(isc, iec, jsc, jec, npz, 700.e2, atm(n)%peln, a3, a2)
1948  used=send_data(idiag%id_dp700, a2, time)
1949  endif
1950  if (idiag%id_dp850>0) then
1951  call interpolate_vertical(isc, iec, jsc, jec, npz, 850.e2, atm(n)%peln, a3, a2)
1952  used=send_data(idiag%id_dp850, a2, time)
1953  endif
1954  if (idiag%id_dp925>0) then
1955  call interpolate_vertical(isc, iec, jsc, jec, npz, 925.e2, atm(n)%peln, a3, a2)
1956  used=send_data(idiag%id_dp925, a2, time)
1957  endif
1958  if (idiag%id_dp1000>0) then
1959  call interpolate_vertical(isc, iec, jsc, jec, npz, 1000.e2, atm(n)%peln, a3, a2)
1960  used=send_data(idiag%id_dp1000, a2, time)
1961  endif
1962  deallocate(a3)
1963 
1964  endif
1965 
1966  endif
1967 
1968  ! rel hum (CMIP definition) at selected press levels (for IPCC)
1969  if (idiag%id_rh10_cmip>0 .or. idiag%id_rh50_cmip>0 .or. idiag%id_rh100_cmip>0 .or. &
1970  idiag%id_rh250_cmip>0 .or. idiag%id_rh300_cmip>0 .or. idiag%id_rh500_cmip>0 .or. &
1971  idiag%id_rh700_cmip>0 .or. idiag%id_rh850_cmip>0 .or. idiag%id_rh925_cmip>0 .or. &
1972  idiag%id_rh1000_cmip>0) then
1973  ! compute mean pressure
1974  do k=1,npz
1975  do j=jsc,jec
1976  do i=isc,iec
1977  a2(i,j) = atm(n)%delp(i,j,k)/(atm(n)%peln(i,k+1,j)-atm(n)%peln(i,k,j))
1978  enddo
1979  enddo
1980  call rh_calc (a2, atm(n)%pt(isc:iec,jsc:jec,k), &
1981  atm(n)%q(isc:iec,jsc:jec,k,sphum), wk(isc:iec,jsc:jec,k), do_cmip=.true.)
1982  enddo
1983  if (idiag%id_rh10_cmip>0) then
1984  call interpolate_vertical(isc, iec, jsc, jec, npz, 10.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1985  used=send_data(idiag%id_rh10_cmip, a2, time)
1986  endif
1987  if (idiag%id_rh50_cmip>0) then
1988  call interpolate_vertical(isc, iec, jsc, jec, npz, 50.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1989  used=send_data(idiag%id_rh50_cmip, a2, time)
1990  endif
1991  if (idiag%id_rh100_cmip>0) then
1992  call interpolate_vertical(isc, iec, jsc, jec, npz, 100.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1993  used=send_data(idiag%id_rh100_cmip, a2, time)
1994  endif
1995  if (idiag%id_rh250_cmip>0) then
1996  call interpolate_vertical(isc, iec, jsc, jec, npz, 250.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
1997  used=send_data(idiag%id_rh250_cmip, a2, time)
1998  endif
1999  if (idiag%id_rh300_cmip>0) then
2000  call interpolate_vertical(isc, iec, jsc, jec, npz, 300.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
2001  used=send_data(idiag%id_rh300_cmip, a2, time)
2002  endif
2003  if (idiag%id_rh500_cmip>0) then
2004  call interpolate_vertical(isc, iec, jsc, jec, npz, 500.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
2005  used=send_data(idiag%id_rh500_cmip, a2, time)
2006  endif
2007  if (idiag%id_rh700_cmip>0) then
2008  call interpolate_vertical(isc, iec, jsc, jec, npz, 700.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
2009  used=send_data(idiag%id_rh700_cmip, a2, time)
2010  endif
2011  if (idiag%id_rh850_cmip>0) then
2012  call interpolate_vertical(isc, iec, jsc, jec, npz, 850.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
2013  used=send_data(idiag%id_rh850_cmip, a2, time)
2014  endif
2015  if (idiag%id_rh925_cmip>0) then
2016  call interpolate_vertical(isc, iec, jsc, jec, npz, 925.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
2017  used=send_data(idiag%id_rh925_cmip, a2, time)
2018  endif
2019  if (idiag%id_rh1000_cmip>0) then
2020  call interpolate_vertical(isc, iec, jsc, jec, npz, 1000.e2, atm(n)%peln, wk(isc:iec,jsc:jec,:), a2)
2021  used=send_data(idiag%id_rh1000_cmip, a2, time)
2022  endif
2023  endif
2024 
2025  if(idiag%id_c25>0 .or. idiag%id_c35>0 .or. idiag%id_c45>0) then
2026  do j=jsc,jec
2027  do i=isc,iec
2028  if ( storm(i,j) .and. ws_max(i,j)>ws_1 ) then
2029  cat_crt(i,j) = .true.
2030  else
2031  cat_crt(i,j) = .false.
2032  endif
2033  enddo
2034  enddo
2035  endif
2036 
2037 
2038 
2039  if( idiag%id_slp>0 .or. idiag%id_tm>0 .or. idiag%id_any_hght>0 .or. idiag%id_hght3d>0 .or. idiag%id_c15>0 .or. idiag%id_ctz>0 ) then
2040 
2041  allocate ( wz(isc:iec,jsc:jec,npz+1) )
2042  call get_height_field(isc, iec, jsc, jec, ngc, npz, atm(n)%flagstruct%hydrostatic, atm(n)%delz, &
2043  wz, atm(n)%pt, atm(n)%q, atm(n)%peln, zvir)
2044  if( prt_minmax ) &
2045  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)
2046 ! call prt_maxmin('ZTOP', wz(isc:iec,jsc:jec,1), isc, iec, jsc, jec, 0, 1, 1.E-3)
2047 
2048  if (idiag%id_hght3d > 0) then
2049  used = send_data(idiag%id_hght3d, 0.5*(wz(isc:iec,jsc:jec,1:npz)+wz(isc:iec,jsc:jec,2:npz+1)), time)
2050  endif
2051 
2052  if(idiag%id_slp > 0) then
2053 ! Cumpute SLP (pressure at height=0)
2054  allocate ( slp(isc:iec,jsc:jec) )
2055  call get_pressure_given_height(isc, iec, jsc, jec, ngc, npz, wz, 1, height(2), &
2056  atm(n)%pt(:,:,npz), atm(n)%peln, slp, 0.01)
2057 
2058  if ( atm(n)%flagstruct%range_warn ) then
2059  call range_check('SLP', slp, isc, iec, jsc, jec, 0, atm(n)%gridstruct%agrid, &
2060  slprange(1), slprange(2), bad_range, time)
2061  endif
2062  used = send_data(idiag%id_slp, slp, time)
2063  if( prt_minmax ) then
2064  call prt_maxmin('SLP', slp, isc, iec, jsc, jec, 0, 1, 1.)
2065 ! US Potential Landfall TCs (PLT):
2066  do j=jsc,jec
2067  do i=isc,iec
2068  a2(i,j) = 1015.
2069  slon = rad2deg*atm(n)%gridstruct%agrid(i,j,1)
2070  slat = rad2deg*atm(n)%gridstruct%agrid(i,j,2)
2071  if ( slat>15. .and. slat<40. .and. slon>270. .and. slon<290. ) then
2072  a2(i,j) = slp(i,j)
2073  endif
2074  enddo
2075  enddo
2076  call prt_maxmin('ATL SLP', a2, isc, iec, jsc, jec, 0, 1, 1.)
2077  endif
2078  endif
2079 
2080 ! Compute H3000 and/or H500
2081  if( idiag%id_tm>0 .or. idiag%id_any_hght>0 .or. idiag%id_ppt>0) then
2082 
2083  allocate( a3(isc:iec,jsc:jec,nplev) )
2084 
2085  idg(:) = idiag%id_h(:)
2086 
2087  if ( idiag%id_tm>0 ) then
2088  idg(minloc(abs(levs-300))) = 1 ! 300-mb
2089  idg(minloc(abs(levs-500))) = 1 ! 500-mb
2090  else
2091  idg(minloc(abs(levs-300))) = idiag%id_h(minloc(abs(levs-300)))
2092  idg(minloc(abs(levs-500))) = idiag%id_h(minloc(abs(levs-500)))
2093  endif
2094 
2095  call get_height_given_pressure(isc, iec, jsc, jec, npz, wz, nplev, idg, plevs, atm(n)%peln, a3)
2096  ! reset
2097  idg(minloc(abs(levs-300))) = idiag%id_h(minloc(abs(levs-300)))
2098  idg(minloc(abs(levs-500))) = idiag%id_h(minloc(abs(levs-500)))
2099 
2100  do i=1,nplev
2101  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
2102  enddo
2103 
2104  if (idiag%id_h_plev>0) then
2105  id1(:) = 1
2106  call get_height_given_pressure(isc, iec, jsc, jec, npz, wz, nplev, id1, plevs, atm(n)%peln, a3)
2107  used=send_data(idiag%id_h_plev, a3(isc:iec,jsc:jec,:), time)
2108  endif
2109 
2110  if( prt_minmax ) then
2111 
2112  if(all(idiag%id_h(minloc(abs(levs-100)))>0)) &
2113  call prt_mxm('Z100',a3(isc:iec,jsc:jec,k100),isc,iec,jsc,jec,0,1,1.e-3,atm(n)%gridstruct%area_64,atm(n)%domain)
2114 
2115  if(all(idiag%id_h(minloc(abs(levs-500)))>0)) then
2116  if (atm(n)%gridstruct%bounded_domain) then
2117  call prt_mxm('Z500',a3(isc:iec,jsc:jec,k500),isc,iec,jsc,jec,0,1,1.,atm(n)%gridstruct%area_64,atm(n)%domain)
2118  else
2119  call prt_gb_nh_sh('fv_GFS Z500', isc,iec, jsc,jec, a3(isc,jsc,k500), atm(n)%gridstruct%area_64(isc:iec,jsc:jec), &
2120  atm(n)%gridstruct%agrid_64(isc:iec,jsc:jec,2))
2121  endif
2122  endif
2123 
2124  endif
2125 
2126  ! mean virtual temp 300mb to 500mb
2127  if( idiag%id_tm>0 ) then
2128  k1 = -1
2129  k2 = -1
2130  do k=1,nplev
2131  if (abs(levs(k)-500.) < 1.) then
2132  k2 = k
2133  exit
2134  endif
2135  enddo
2136  do k=1,nplev
2137  if (abs(levs(k)-300.) < 1.) then
2138  k1 = k
2139  exit
2140  endif
2141  enddo
2142  if (k1 <= 0 .or. k2 <= 0) then
2143  call mpp_error(note, "Could not find levs for 300--500 mb mean temperature, setting to -1")
2144  a2 = -1.
2145  else
2146  do j=jsc,jec
2147  do i=isc,iec
2148  a2(i,j) = grav*(a3(i,j,k2)-a3(i,j,k1))/(rdgas*(plevs(k1)-plevs(k2)))
2149  enddo
2150  enddo
2151  endif
2152  used = send_data( idiag%id_tm, a2, time )
2153  endif
2154 
2155  if(idiag%id_c15>0 .or. idiag%id_c25>0 .or. idiag%id_c35>0 .or. idiag%id_c45>0) then
2156  do j=jsc,jec
2157  do i=isc,iec
2158 ! Minimum warm core:
2159  if ( storm(i,j) ) then
2160  if( a2(i,j)<254.0 .or. atm(n)%pt(i,j,npz)<281.0 ) Then
2161  storm(i,j) = .false.
2162  cat_crt(i,j) = .false.
2163  endif
2164  endif
2165  enddo
2166  enddo
2167 ! Cat 1-5:
2168  do j=jsc,jec
2169  do i=isc,iec
2170  if ( storm(i,j) .and. slp(i,j)<1000.0 ) then
2171  depress(i,j) = 1000. - slp(i,j)
2172  tc_count(i,j) = 1.
2173  else
2174  depress(i,j) = 0.
2175  tc_count(i,j) = 0.
2176  endif
2177  enddo
2178  enddo
2179  used = send_data(idiag%id_c15, depress, time)
2180  if(idiag%id_f15>0) used = send_data(idiag%id_f15, tc_count, time)
2181  if(prt_minmax) then
2182  do j=jsc,jec
2183  do i=isc,iec
2184  slon = rad2deg*atm(n)%gridstruct%agrid(i,j,1)
2185  slat = rad2deg*atm(n)%gridstruct%agrid(i,j,2)
2186 ! Western Pac: negative; positive elsewhere
2187  if ( slat>0. .and. slat<40. .and. slon>110. .and. slon<180. ) then
2188  depress(i,j) = -depress(i,j)
2189  endif
2190  enddo
2191  enddo
2192  call prt_maxmin('Depress', depress, isc, iec, jsc, jec, 0, 1, 1.)
2193  do j=jsc,jec
2194  do i=isc,iec
2195  if ( atm(n)%gridstruct%agrid(i,j,2)<0.) then
2196 ! Excluding the SH cyclones
2197  depress(i,j) = 0.
2198  endif
2199  enddo
2200  enddo
2201  call prt_maxmin('NH Deps', depress, isc, iec, jsc, jec, 0, 1, 1.)
2202 
2203 ! ATL basin cyclones
2204  do j=jsc,jec
2205  do i=isc,iec
2206  tmp = rad2deg * atm(n)%gridstruct%agrid(i,j,1)
2207  if ( tmp<280. ) then
2208  depress(i,j) = 0.
2209  endif
2210  enddo
2211  enddo
2212  call prt_maxmin('ATL Deps', depress, isc, iec, jsc, jec, 0, 1, 1.)
2213  endif
2214  endif
2215 
2216 ! Cat 2-5:
2217  if(idiag%id_c25>0) then
2218  do j=jsc,jec
2219  do i=isc,iec
2220  if ( cat_crt(i,j) .and. slp(i,j)<980.0 ) then
2221  depress(i,j) = 980. - slp(i,j)
2222  tc_count(i,j) = 1.
2223  else
2224  depress(i,j) = 0.
2225  tc_count(i,j) = 0.
2226  endif
2227  enddo
2228  enddo
2229  used = send_data(idiag%id_c25, depress, time)
2230  if(idiag%id_f25>0) used = send_data(idiag%id_f25, tc_count, time)
2231  endif
2232 
2233 ! Cat 3-5:
2234  if(idiag%id_c35>0) then
2235  do j=jsc,jec
2236  do i=isc,iec
2237  if ( cat_crt(i,j) .and. slp(i,j)<964.0 ) then
2238  depress(i,j) = 964. - slp(i,j)
2239  tc_count(i,j) = 1.
2240  else
2241  depress(i,j) = 0.
2242  tc_count(i,j) = 0.
2243  endif
2244  enddo
2245  enddo
2246  used = send_data(idiag%id_c35, depress, time)
2247  if(idiag%id_f35>0) used = send_data(idiag%id_f35, tc_count, time)
2248  endif
2249 
2250 ! Cat 4-5:
2251  if(idiag%id_c45>0) then
2252  do j=jsc,jec
2253  do i=isc,iec
2254  if ( cat_crt(i,j) .and. slp(i,j)<944.0 ) then
2255  depress(i,j) = 944. - slp(i,j)
2256  tc_count(i,j) = 1.
2257  else
2258  depress(i,j) = 0.
2259  tc_count(i,j) = 0.
2260  endif
2261  enddo
2262  enddo
2263  used = send_data(idiag%id_c45, depress, time)
2264  if(idiag%id_f45>0) used = send_data(idiag%id_f45, tc_count, time)
2265  endif
2266 
2267  if (idiag%id_c15>0) then
2268  deallocate(depress)
2269  deallocate(cat_crt)
2270  deallocate(storm)
2271  deallocate(ws_max)
2272  deallocate(tc_count)
2273  endif
2274 
2275  if(idiag%id_slp>0 ) deallocate( slp )
2276 
2277 ! deallocate( a3 )
2278  endif
2279 
2280 ! deallocate ( wz )
2281  endif
2282 
2283 ! Temperature:
2284  idg(:) = idiag%id_t(:)
2285 
2286  do_cs_intp = .false.
2287  do i=1,nplev
2288  if ( idg(i)>0 ) then
2289  do_cs_intp = .true.
2290  exit
2291  endif
2292  enddo
2293 
2294  if ( do_cs_intp ) then ! log(pe) as the coordinaite for temp re-construction
2295  if(.not. allocated (a3) ) allocate( a3(isc:iec,jsc:jec,nplev) )
2296  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%pt(isc:iec,jsc:jec,:), nplev, &
2297  plevs, wz, atm(n)%peln, idg, a3, 1)
2298  do i=1,nplev
2299  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
2300  enddo
2301  if ( all(idiag%id_t(minloc(abs(levs-100)))>0) .and. prt_minmax ) then
2302  call prt_mxm('T100:', a3(isc:iec,jsc:jec,11), isc, iec, jsc, jec, 0, 1, 1., &
2303  atm(n)%gridstruct%area_64, atm(n)%domain)
2304  if (.not. atm(n)%gridstruct%bounded_domain) then
2305  tmp = 0.
2306  sar = 0.
2307  ! Compute mean temp at 100 mb near EQ
2308  do j=jsc,jec
2309  do i=isc,iec
2310  slat = atm(n)%gridstruct%agrid(i,j,2)*rad2deg
2311  if( (slat>-10.0 .and. slat<10.) ) then
2312  sar = sar + atm(n)%gridstruct%area(i,j)
2313  tmp = tmp + a3(i,j,11)*atm(n)%gridstruct%area(i,j)
2314  endif
2315  enddo
2316  enddo
2317  call mp_reduce_sum(sar)
2318  call mp_reduce_sum(tmp)
2319  if ( sar > 0. ) then
2320  if (master) write(*,*) 'Tropical [10s,10n] mean T100 =', tmp/sar
2321  else
2322  if (master) write(*,*) 'Warning: problem computing tropical mean T100'
2323  endif
2324  endif
2325  endif
2326  if ( all(idiag%id_t(minloc(abs(levs-200)))>0) .and. prt_minmax ) then
2327  call prt_mxm('T200:', a3(isc:iec,jsc:jec,k200), isc, iec, jsc, jec, 0, 1, 1., &
2328  atm(n)%gridstruct%area_64, atm(n)%domain)
2329  if (.not. atm(n)%gridstruct%bounded_domain) then
2330  tmp = 0.
2331  sar = 0.
2332  do j=jsc,jec
2333  do i=isc,iec
2334  slat = atm(n)%gridstruct%agrid(i,j,2)*rad2deg
2335  if( (slat>-20 .and. slat<20) ) then
2336  sar = sar + atm(n)%gridstruct%area(i,j)
2337  tmp = tmp + a3(i,j,k200)*atm(n)%gridstruct%area(i,j)
2338  endif
2339  enddo
2340  enddo
2341  call mp_reduce_sum(sar)
2342  call mp_reduce_sum(tmp)
2343  if ( sar > 0. ) then
2344  if (master) write(*,*) 'Tropical [-20.,20.] mean T200 =', tmp/sar
2345  endif
2346  endif
2347  endif
2348  deallocate( a3 )
2349  endif
2350 
2351  if (idiag%id_t_plev>0) then
2352  if(.not. allocated (a3) ) allocate( a3(isc:iec,jsc:jec,nplev) )
2353  id1(:) = 1
2354  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%pt(isc:iec,jsc:jec,:), nplev, &
2355  plevs, wz, atm(n)%peln, id1, a3, 1)
2356  used=send_data(idiag%id_t_plev, a3(isc:iec,jsc:jec,:), time)
2357  deallocate( a3 )
2358  endif
2359 
2360  if(idiag%id_mq > 0) then
2361  do j=jsc,jec
2362  do i=isc,iec
2363 ! zxg * surface pressure * 1.e-18--> Hadleys per unit area
2364 ! Unit Hadley = 1.E18 kg m**2 / s**2
2365  a2(i,j) = -1.e-18 * atm(n)%ps(i,j)*idiag%zxg(i,j)
2366  enddo
2367  enddo
2368  used = send_data(idiag%id_mq, a2, time)
2369  if( prt_minmax ) then
2370  tot_mq = g_sum( atm(n)%domain, a2, isc, iec, jsc, jec, ngc, atm(n)%gridstruct%area_64, 0)
2371  idiag%mtq_sum = idiag%mtq_sum + tot_mq
2372  if ( idiag%steps <= max_step ) idiag%mtq(idiag%steps) = tot_mq
2373  if(master) write(*,*) 'Total (global) mountain torque (Hadleys)=', tot_mq
2374  endif
2375  endif
2376 
2377  if (idiag%id_ts > 0) used = send_data(idiag%id_ts, atm(n)%ts(isc:iec,jsc:jec), time)
2378 
2379  if ( idiag%id_tq>0 ) then
2380  nwater = atm(1)%flagstruct%nwat
2381  a2 = 0.
2382  do k=1,npz
2383  do j=jsc,jec
2384  do i=isc,iec
2385 ! a2(i,j) = a2(i,j) + Atm(n)%q(i,j,k,1)*Atm(n)%delp(i,j,k)
2386  a2(i,j) = a2(i,j) + sum(atm(n)%q(i,j,k,1:nwater))*atm(n)%delp(i,j,k)
2387  enddo
2388  enddo
2389  enddo
2390  used = send_data(idiag%id_tq, a2*ginv, time)
2391  endif
2392 #ifdef HIWPP
2393  cl = get_tracer_index(model_atmos, 'Cl')
2394  cl2 = get_tracer_index(model_atmos, 'Cl2')
2395  if (cl > 0 .and. cl2 > 0) then
2396  allocate(var2(isc:iec,jsc:jec))
2397  var2 = 0.
2398  do k=1,npz
2399  do j=jsc,jec
2400  do i=isc,iec
2401  var2(i,j) = var2(i,j) + atm(n)%delp(i,j,k)
2402  enddo
2403  enddo
2404  enddo
2405 
2406  if ( idiag%id_acl > 0 ) then
2407  a2 = 0.
2408  einf = 0.
2409  qm = 0.
2410  do k=1,npz
2411  do j=jsc,jec
2412  do i=isc,iec
2413  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,cl)*atm(n)%delp(i,j,k) ! moist mass
2414  enddo
2415  enddo
2416  enddo
2417  !Convert to mean mixing ratio
2418  do j=jsc,jec
2419  do i=isc,iec
2420  a2(i,j) = a2(i,j) / var2(i,j)
2421  enddo
2422  enddo
2423  used = send_data(idiag%id_acl, a2, time)
2424  endif
2425  if ( idiag%id_acl2 > 0 ) then
2426  a2 = 0.
2427  einf = 0.
2428  qm = 0.
2429  do k=1,npz
2430  do j=jsc,jec
2431  do i=isc,iec
2432  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,cl2)*atm(n)%delp(i,j,k) ! moist mass
2433  enddo
2434  enddo
2435  enddo
2436  !Convert to mean mixing ratio
2437  do j=jsc,jec
2438  do i=isc,iec
2439  a2(i,j) = a2(i,j) / var2(i,j)
2440  enddo
2441  enddo
2442  used = send_data(idiag%id_acl2, a2, time)
2443  endif
2444  if ( idiag%id_acly > 0 ) then
2445  a2 = 0.
2446  einf = 0.
2447  qm = 0.
2448  e2 = 0.
2449  do k=1,npz
2450  do j=jsc,jec
2451  do i=isc,iec
2452  mm = (atm(n)%q(i,j,k,cl)+2.*atm(n)%q(i,j,k,cl2))*atm(n)%delp(i,j,k) ! moist mass
2453  a2(i,j) = a2(i,j) + mm
2454  qm = qm + mm*atm(n)%gridstruct%area_64(i,j)
2455  enddo
2456  enddo
2457  enddo
2458  !Convert to mean mixing ratio
2459  do j=jsc,jec
2460  do i=isc,iec
2461  a2(i,j) = a2(i,j) / var2(i,j)
2462  enddo
2463  enddo
2464  used = send_data(idiag%id_acly, a2, time)
2465  do j=jsc,jec
2466  do i=isc,iec
2467  e2 = e2 + ((a2(i,j) - qcly0)**2)*atm(n)%gridstruct%area_64(i,j)
2468  einf = max(einf, abs(a2(i,j) - qcly0))
2469  enddo
2470  enddo
2471  if (prt_minmax .and. .not. atm(n)%gridstruct%bounded_domain) then
2472  call mp_reduce_sum(qm)
2473  call mp_reduce_max(einf)
2474  call mp_reduce_sum(e2)
2475  if (master) then
2476  write(*,*) ' TERMINATOR TEST: '
2477  write(*,*) ' chlorine mass: ', qm/(4.*pi*radius*radius)
2478  write(*,*) ' L2 err: ', sqrt(e2)/sqrt(4.*pi*radius*radius)/qcly0
2479  write(*,*) ' max err: ', einf/qcly0
2480  endif
2481  endif
2482  endif
2483 
2484  deallocate(var2)
2485 
2486  endif
2487 #endif
2488  if ( idiag%id_iw>0 ) then
2489  a2 = 0.
2490  if (ice_wat > 0) then
2491  do k=1,npz
2492  do j=jsc,jec
2493  do i=isc,iec
2494  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k) * &
2495  atm(n)%q(i,j,k,ice_wat)
2496  enddo
2497  enddo
2498  enddo
2499  endif
2500  if (snowwat > 0) then
2501  do k=1,npz
2502  do j=jsc,jec
2503  do i=isc,iec
2504  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k) * &
2505  atm(n)%q(i,j,k,snowwat)
2506  enddo
2507  enddo
2508  enddo
2509  endif
2510  if (graupel > 0) then
2511  do k=1,npz
2512  do j=jsc,jec
2513  do i=isc,iec
2514  a2(i,j) = a2(i,j) + atm(n)%delp(i,j,k) * &
2515  atm(n)%q(i,j,k,graupel)
2516  enddo
2517  enddo
2518  enddo
2519  endif
2520  used = send_data(idiag%id_iw, a2*ginv, time)
2521  endif
2522  if ( idiag%id_lw>0 ) then
2523  a2 = 0.
2524  if (liq_wat > 0) then
2525  do k=1,npz
2526  do j=jsc,jec
2527  do i=isc,iec
2528  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,liq_wat)*atm(n)%delp(i,j,k)
2529  enddo
2530  enddo
2531  enddo
2532  endif
2533  if (rainwat > 0) then
2534  do k=1,npz
2535  do j=jsc,jec
2536  do i=isc,iec
2537  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,rainwat)*atm(n)%delp(i,j,k)
2538  enddo
2539  enddo
2540  enddo
2541  endif
2542  used = send_data(idiag%id_lw, a2*ginv, time)
2543  endif
2544 
2545 !--------------------------
2546 ! Vertically integrated tracers for GFDL MP
2547 !--------------------------
2548  if ( idiag%id_intqv>0 ) then
2549  a2 = 0.
2550  if (sphum > 0) then
2551  do k=1,npz
2552  do j=jsc,jec
2553  do i=isc,iec
2554  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,sphum)*atm(n)%delp(i,j,k)
2555  enddo
2556  enddo
2557  enddo
2558  endif
2559  used = send_data(idiag%id_intqv, a2*ginv, time)
2560  endif
2561  if ( idiag%id_intql>0 ) then
2562  a2 = 0.
2563  if (liq_wat > 0) then
2564  do k=1,npz
2565  do j=jsc,jec
2566  do i=isc,iec
2567  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,liq_wat)*atm(n)%delp(i,j,k)
2568  enddo
2569  enddo
2570  enddo
2571  endif
2572  used = send_data(idiag%id_intql, a2*ginv, time)
2573  endif
2574  if ( idiag%id_intqi>0 ) then
2575  a2 = 0.
2576  if (ice_wat > 0) then
2577  do k=1,npz
2578  do j=jsc,jec
2579  do i=isc,iec
2580  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,ice_wat)*atm(n)%delp(i,j,k)
2581  enddo
2582  enddo
2583  enddo
2584  endif
2585  used = send_data(idiag%id_intqi, a2*ginv, time)
2586  endif
2587  if ( idiag%id_intqr>0 ) then
2588  a2 = 0.
2589  if (rainwat > 0) then
2590  do k=1,npz
2591  do j=jsc,jec
2592  do i=isc,iec
2593  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,rainwat)*atm(n)%delp(i,j,k)
2594  enddo
2595  enddo
2596  enddo
2597  endif
2598  used = send_data(idiag%id_intqr, a2*ginv, time)
2599  endif
2600  if ( idiag%id_intqs>0 ) then
2601  a2 = 0.
2602  if (snowwat > 0) then
2603  do k=1,npz
2604  do j=jsc,jec
2605  do i=isc,iec
2606  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,snowwat)*atm(n)%delp(i,j,k)
2607  enddo
2608  enddo
2609  enddo
2610  endif
2611  used = send_data(idiag%id_intqs, a2*ginv, time)
2612  endif
2613  if ( idiag%id_intqg>0 ) then
2614  a2 = 0.
2615  if (graupel > 0) then
2616  do k=1,npz
2617  do j=jsc,jec
2618  do i=isc,iec
2619  a2(i,j) = a2(i,j) + atm(n)%q(i,j,k,graupel)*atm(n)%delp(i,j,k)
2620  enddo
2621  enddo
2622  enddo
2623  endif
2624  used = send_data(idiag%id_intqg, a2*ginv, time)
2625  endif
2626 
2627 ! Cloud top temperature & cloud top press:
2628  if ( (idiag%id_ctt>0 .or. idiag%id_ctp>0 .or. idiag%id_ctz>0).and. atm(n)%flagstruct%nwat==6) then
2629  allocate ( var1(isc:iec,jsc:jec) )
2630  allocate ( var2(isc:iec,jsc:jec) )
2631 !$OMP parallel do default(shared) private(tmp)
2632  do j=jsc,jec
2633  do i=isc,iec
2634  do k=2,npz
2635  tmp = atm(n)%q(i,j,k,liq_wat)+atm(n)%q(i,j,k,rainwat)+atm(n)%q(i,j,k,ice_wat)+ &
2636  atm(n)%q(i,j,k,snowwat)+atm(n)%q(i,j,k,graupel)
2637  if( tmp>5.e-6 ) then
2638  a2(i,j) = atm(n)%pt(i,j,k)
2639  var1(i,j) = 0.01*atm(n)%pe(i,k,j)
2640  var2(i,j) = wz(i,j,k) - wz(i,j,npz+1) ! height AGL
2641  exit
2642  elseif( k==npz ) then
2643  a2(i,j) = missing_value3
2644  var1(i,j) = missing_value3
2645  var2(i,j) = missing_value2
2646 !!$ a2(i,j) = Atm(n)%pt(i,j,k)
2647 !!$ var1(i,j) = 0.01*Atm(n)%pe(i,k+1,j) ! surface pressure
2648  endif
2649  enddo
2650  enddo
2651  enddo
2652  if ( idiag%id_ctt>0 ) then
2653  used = send_data(idiag%id_ctt, a2, time)
2654  if(prt_minmax) call prt_maxmin('Cloud_top_T (K)', a2, isc, iec, jsc, jec, 0, 1, 1.)
2655  endif
2656  if ( idiag%id_ctp>0 ) then
2657  used = send_data(idiag%id_ctp, var1, time)
2658  if(prt_minmax) call prt_maxmin('Cloud_top_P (mb)', var1, isc, iec, jsc, jec, 0, 1, 1.)
2659  endif
2660  deallocate ( var1 )
2661  if ( idiag%id_ctz>0 ) then
2662  used = send_data(idiag%id_ctz, var2, time)
2663  if(prt_minmax) call prt_maxmin('Cloud_top_z (m)', var2, isc, iec, jsc, jec, 0, 1, 1.)
2664  endif
2665  deallocate ( var2 )
2666  endif
2667 
2668 ! Condensates:
2669  if ( idiag%id_qn>0 .or. idiag%id_qn200>0 .or. idiag%id_qn500>0 .or. idiag%id_qn850>0 ) then
2670 !$OMP parallel do default(shared)
2671  do k=1,npz
2672  do j=jsc,jec
2673  do i=isc,iec
2674  wk(i,j,k) = 0.
2675  enddo
2676  enddo
2677  enddo
2678  if (liq_wat > 0) then
2679 !$OMP parallel do default(shared)
2680  do k=1,npz
2681  do j=jsc,jec
2682  do i=isc,iec
2683  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,liq_wat)*atm(n)%delp(i,j,k)
2684  enddo
2685  enddo
2686  enddo
2687  endif
2688  if (ice_wat > 0) then
2689 !$OMP parallel do default(shared)
2690  do k=1,npz
2691  do j=jsc,jec
2692  do i=isc,iec
2693  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,ice_wat)*atm(n)%delp(i,j,k)
2694  enddo
2695  enddo
2696  enddo
2697  endif
2698  if ( idiag%id_qn>0 ) used = send_data(idiag%id_qn, wk, time)
2699  if ( idiag%id_qn200>0 ) then
2700  call interpolate_vertical(isc, iec, jsc, jec, npz, 200.e2, atm(n)%peln, wk, a2)
2701  used=send_data(idiag%id_qn200, a2, time)
2702  endif
2703  if ( idiag%id_qn500>0 ) then
2704  call interpolate_vertical(isc, iec, jsc, jec, npz, 500.e2, atm(n)%peln, wk, a2)
2705  used=send_data(idiag%id_qn500, a2, time)
2706  endif
2707  if ( idiag%id_qn850>0 ) then
2708  call interpolate_vertical(isc, iec, jsc, jec, npz, 850.e2, atm(n)%peln, wk, a2)
2709  used=send_data(idiag%id_qn850, a2, time)
2710  endif
2711  endif
2712 ! Total 3D condensates
2713  if ( idiag%id_qp>0 ) then
2714 !$OMP parallel do default(shared)
2715  do k=1,npz
2716  do j=jsc,jec
2717  do i=isc,iec
2718  wk(i,j,k) = 0.
2719  enddo
2720  enddo
2721  enddo
2722  if (rainwat > 0) then
2723 !$OMP parallel do default(shared)
2724  do k=1,npz
2725  do j=jsc,jec
2726  do i=isc,iec
2727  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,rainwat)*atm(n)%delp(i,j,k)
2728  enddo
2729  enddo
2730  enddo
2731  endif
2732  if (snowwat > 0) then
2733 !$OMP parallel do default(shared)
2734  do k=1,npz
2735  do j=jsc,jec
2736  do i=isc,iec
2737  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,snowwat)*atm(n)%delp(i,j,k)
2738  enddo
2739  enddo
2740  enddo
2741  endif
2742  if (graupel > 0) then
2743 !$OMP parallel do default(shared)
2744  do k=1,npz
2745  do j=jsc,jec
2746  do i=isc,iec
2747  wk(i,j,k) = wk(i,j,k) + atm(n)%q(i,j,k,graupel)*atm(n)%delp(i,j,k)
2748  enddo
2749  enddo
2750  enddo
2751  endif
2752  used = send_data(idiag%id_qp, wk, time)
2753  endif
2754 
2755  if(idiag%id_us > 0 .and. idiag%id_vs > 0) then
2756  u2(:,:) = atm(n)%ua(isc:iec,jsc:jec,npz)
2757  v2(:,:) = atm(n)%va(isc:iec,jsc:jec,npz)
2758  do j=jsc,jec
2759  do i=isc,iec
2760  a2(i,j) = sqrt(u2(i,j)**2 + v2(i,j)**2)
2761  enddo
2762  enddo
2763  used=send_data(idiag%id_us, u2, time)
2764  used=send_data(idiag%id_vs, v2, time)
2765  if(prt_minmax) call prt_maxmin('Surf_wind_speed', a2, isc, iec, jsc, jec, 0, 1, 1.)
2766  endif
2767 
2768  if(idiag%id_tb > 0) then
2769  a2(:,:) = atm(n)%pt(isc:iec,jsc:jec,npz)
2770  used=send_data(idiag%id_tb, a2, time)
2771  if( prt_minmax ) &
2772  call prt_mxm('T_bot:', a2, isc, iec, jsc, jec, 0, 1, 1., atm(n)%gridstruct%area_64, atm(n)%domain)
2773  endif
2774 
2775  if(idiag%id_ua > 0) used=send_data(idiag%id_ua, atm(n)%ua(isc:iec,jsc:jec,:), time)
2776  if(idiag%id_va > 0) used=send_data(idiag%id_va, atm(n)%va(isc:iec,jsc:jec,:), time)
2777 
2778  if(idiag%id_uw > 0 .or. idiag%id_vw > 0 .or. idiag%id_hw > 0 .or. idiag%id_qvw > 0 .or. &
2779  idiag%id_qlw > 0 .or. idiag%id_qiw > 0 .or. idiag%id_o3w > 0 ) then
2780  allocate( a3(isc:iec,jsc:jec,npz) )
2781 
2782  do k=1,npz
2783  do j=jsc,jec
2784  do i=isc,iec
2785  wk(i,j,k) = atm(n)%w(i,j,k)*atm(n)%delp(i,j,k)*ginv
2786  enddo
2787  enddo
2788  enddo
2789 
2790  if (idiag%id_uw > 0) then
2791  do k=1,npz
2792  do j=jsc,jec
2793  do i=isc,iec
2794  a3(i,j,k) = atm(n)%ua(i,j,k)*wk(i,j,k)
2795  enddo
2796  enddo
2797  enddo
2798  used = send_data(idiag%id_uw, a3, time)
2799  endif
2800  if (idiag%id_vw > 0) then
2801  do k=1,npz
2802  do j=jsc,jec
2803  do i=isc,iec
2804  a3(i,j,k) = atm(n)%va(i,j,k)*wk(i,j,k)
2805  enddo
2806  enddo
2807  enddo
2808  used = send_data(idiag%id_vw, a3, time)
2809  endif
2810 
2811  if (idiag%id_hw > 0) then
2812  allocate(cvm(isc:iec))
2813  do k=1,npz
2814  do j=jsc,jec
2815 #ifdef USE_COND
2816  call moist_cv(isc,iec,isd,ied,jsd,jed,npz,j,k,atm(n)%flagstruct%nwat,sphum,liq_wat,rainwat, &
2817  ice_wat,snowwat,graupel,atm(n)%q,atm(n)%q_con(isc:iec,j,k),cvm)
2818  do i=isc,iec
2819  a3(i,j,k) = atm(n)%pt(i,j,k)*cvm(i)*wk(i,j,k)
2820  enddo
2821 #else
2822  cv_vapor = cp_vapor - rvgas
2823  do i=isc,iec
2824  a3(i,j,k) = atm(n)%pt(i,j,k)*cv_vapor*wk(i,j,k)
2825  enddo
2826 #endif
2827  enddo
2828  enddo
2829  used = send_data(idiag%id_hw, a3, time)
2830  deallocate(cvm)
2831  endif
2832 
2833  if (idiag%id_qvw > 0) then
2834  do k=1,npz
2835  do j=jsc,jec
2836  do i=isc,iec
2837  a3(i,j,k) = atm(n)%q(i,j,k,sphum)*wk(i,j,k)
2838  enddo
2839  enddo
2840  enddo
2841  used = send_data(idiag%id_qvw, a3, time)
2842  endif
2843  if (idiag%id_qlw > 0) then
2844  if (liq_wat < 0 .or. rainwat < 0) call mpp_error(fatal, 'qlw does not work without liq_wat and rainwat defined')
2845  do k=1,npz
2846  do j=jsc,jec
2847  do i=isc,iec
2848  a3(i,j,k) = (atm(n)%q(i,j,k,liq_wat)+atm(n)%q(i,j,k,rainwat))*wk(i,j,k)
2849  enddo
2850  enddo
2851  enddo
2852  used = send_data(idiag%id_qlw, a3, time)
2853  endif
2854  if (idiag%id_qiw > 0) then
2855  if (ice_wat < 0 .or. snowwat < 0 .or. graupel < 0) then
2856  call mpp_error(fatal, 'qiw does not work without ice_wat, snowwat, and graupel defined')
2857  endif
2858  do k=1,npz
2859  do j=jsc,jec
2860  do i=isc,iec
2861  a3(i,j,k) = (atm(n)%q(i,j,k,ice_wat)+atm(n)%q(i,j,k,snowwat)+atm(n)%q(i,j,k,graupel))*wk(i,j,k)
2862  enddo
2863  enddo
2864  enddo
2865  used = send_data(idiag%id_qiw, a3, time)
2866  endif
2867  if (idiag%id_o3w > 0) then
2868  if (o3mr < 0) then
2869  call mpp_error(fatal, 'o3w does not work without o3mr defined')
2870  endif
2871  do k=1,npz
2872  do j=jsc,jec
2873  do i=isc,iec
2874  a3(i,j,k) = atm(n)%q(i,j,k,o3mr)*wk(i,j,k)
2875  enddo
2876  enddo
2877  enddo
2878  used = send_data(idiag%id_o3w, a3, time)
2879  endif
2880 
2881  deallocate(a3)
2882  endif
2883 
2884  if(idiag%id_ke > 0) then
2885  a2(:,:) = 0.
2886  do k=1,npz
2887  do j=jsc,jec
2888  do i=isc,iec
2889  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)
2890  enddo
2891  enddo
2892  enddo
2893 ! Mass weighted KE
2894  do j=jsc,jec
2895  do i=isc,iec
2896  a2(i,j) = 0.5*a2(i,j)/(atm(n)%ps(i,j)-ptop)
2897  enddo
2898  enddo
2899  used=send_data(idiag%id_ke, a2, time)
2900  if(prt_minmax) then
2901  tot_mq = g_sum( atm(n)%domain, a2, isc, iec, jsc, jec, ngc, atm(n)%gridstruct%area_64, 1)
2902  if (master) write(*,*) 'SQRT(2.*KE; m/s)=', sqrt(2.*tot_mq)
2903  endif
2904  endif
2905 
2906 
2907 #ifdef GFS_PHYS
2908  if(idiag%id_delp > 0 .or. idiag%id_cape > 0 .or. idiag%id_cin > 0 .or. ((.not. atm(n)%flagstruct%hydrostatic) .and. idiag%id_pfnh > 0)) then
2909  do k=1,npz
2910  do j=jsc,jec
2911  do i=isc,iec
2912  wk(i,j,k) = atm(n)%delp(i,j,k)*(1.-sum(atm(n)%q(i,j,k,2:atm(n)%flagstruct%nwat)))
2913  enddo
2914  enddo
2915  enddo
2916  if (idiag%id_delp > 0) used=send_data(idiag%id_delp, wk, time)
2917  endif
2918 
2919  if( ( (.not. atm(n)%flagstruct%hydrostatic) .and. idiag%id_pfnh > 0) .or. idiag%id_cape > 0 .or. idiag%id_cin > 0) then
2920  do k=1,npz
2921  do j=jsc,jec
2922  do i=isc,iec
2923 #ifdef MULTI_GASES
2924  wk(i,j,k) = -wk(i,j,k)/(atm(n)%delz(i,j,k)*grav)*rdgas* &
2925  atm(n)%pt(i,j,k)*virq(atm(n)%q(i,j,k,1:num_gas))
2926 #else
2927  wk(i,j,k) = -wk(i,j,k)/(atm(n)%delz(i,j,k)*grav)*rdgas* &
2928  atm(n)%pt(i,j,k)*(1.+zvir*atm(n)%q(i,j,k,sphum))
2929 #endif
2930  enddo
2931  enddo
2932  enddo
2933 ! if (prt_minmax) then
2934 ! call prt_maxmin(' PFNH (mb)', wk(isc:iec,jsc:jec,1), isc, iec, jsc, jec, 0, npz, 1.E-2)
2935 ! endif
2936  used=send_data(idiag%id_pfnh, wk, time)
2937  endif
2938 #else
2939  if(idiag%id_delp > 0) used=send_data(idiag%id_delp, atm(n)%delp(isc:iec,jsc:jec,:), time)
2940 
2941  if( (.not. atm(n)%flagstruct%hydrostatic) .and. (idiag%id_pfnh > 0 .or. idiag%id_cape > 0 .or. idiag%id_cin > 0)) then
2942  do k=1,npz
2943  do j=jsc,jec
2944  do i=isc,iec
2945 #ifdef MULTI_GASES
2946  wk(i,j,k) = -atm(n)%delp(i,j,k)/(atm(n)%delz(i,j,k)*grav)*rdgas* &
2947  atm(n)%pt(i,j,k)*virq(atm(n)%q(i,j,k,1:num_gas))
2948 #else
2949  wk(i,j,k) = -atm(n)%delp(i,j,k)/(atm(n)%delz(i,j,k)*grav)*rdgas* &
2950  atm(n)%pt(i,j,k)*(1.+zvir*atm(n)%q(i,j,k,sphum))
2951 #endif
2952  enddo
2953  enddo
2954  enddo
2955  used=send_data(idiag%id_pfnh, wk, time)
2956  endif
2957 #endif
2958 
2959  if( atm(n)%flagstruct%hydrostatic .and. (idiag%id_pfhy > 0 .or. idiag%id_cape > 0 .or. idiag%id_cin > 0) ) then
2960  do k=1,npz
2961  do j=jsc,jec
2962  do i=isc,iec
2963  wk(i,j,k) = 0.5 *(atm(n)%pe(i,k,j)+atm(n)%pe(i,k+1,j))
2964  enddo
2965  enddo
2966  enddo
2967  used=send_data(idiag%id_pfhy, wk, time)
2968  endif
2969 
2970  if (idiag%id_cape > 0 .or. idiag%id_cin > 0) then
2971  !wk here contains layer-mean pressure
2972 
2973  allocate(var2(isc:iec,jsc:jec))
2974  allocate(a3(isc:iec,jsc:jec,npz))
2975 
2976  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), &
2977  isc, iec, jsc, jec, ngc, npz, atm(n)%flagstruct%hydrostatic, atm(n)%flagstruct%moist_phys)
2978 
2979 !$OMP parallel do default(shared)
2980  do j=jsc,jec
2981  do i=isc,iec
2982  a2(i,j) = 0.
2983  var2(i,j) = 0.
2984 
2985  call getcape(npz, wk(i,j,:), atm(n)%pt(i,j,:), -atm(n)%delz(i,j,:), atm(n)%q(i,j,:,sphum), a3(i,j,:), a2(i,j), var2(i,j), source_in=1)
2986  enddo
2987  enddo
2988 
2989  if (idiag%id_cape > 0) then
2990  if (prt_minmax) then
2991  call prt_maxmin(' CAPE (J/kg)', a2, isc,iec,jsc,jec, 0, 1, 1.)
2992  endif
2993  used=send_data(idiag%id_cape, a2, time)
2994  endif
2995  if (idiag%id_cin > 0) then
2996  if (prt_minmax) then
2997  call prt_maxmin(' CIN (J/kg)', var2, isc,iec,jsc,jec, 0, 1, 1.)
2998  endif
2999  used=send_data(idiag%id_cin, var2, time)
3000  endif
3001 
3002  deallocate(var2)
3003  deallocate(a3)
3004 
3005  endif
3006 
3007 
3008  if((.not. atm(n)%flagstruct%hydrostatic) .and. idiag%id_delz > 0) then
3009  do k=1,npz
3010  do j=jsc,jec
3011  do i=isc,iec
3012  wk(i,j,k) = -atm(n)%delz(i,j,k)
3013  enddo
3014  enddo
3015  enddo
3016  used=send_data(idiag%id_delz, wk, time)
3017  endif
3018 
3019 
3020 ! pressure for masking p-level fields
3021 ! incorrectly defines a2 to be ps (in mb).
3022  if (idiag%id_pmask>0) then
3023  do j=jsc,jec
3024  do i=isc,iec
3025  a2(i,j) = exp((atm(n)%peln(i,npz+1,j)+atm(n)%peln(i,npz+1,j))*0.5)*0.01
3026  !a2(i,j) = Atm(n)%delp(i,j,k)/(Atm(n)%peln(i,k+1,j)-Atm(n)%peln(i,k,j))*0.01
3027  enddo
3028  enddo
3029  used=send_data(idiag%id_pmask, a2, time)
3030  endif
3031 ! fix for pressure for masking p-level fields
3032 ! based on lowest-level pfull
3033 ! define pressure at lowest level the same as interpolate_vertical (in mb)
3034  if (idiag%id_pmaskv2>0) then
3035  do j=jsc,jec
3036  do i=isc,iec
3037  a2(i,j) = exp((atm(n)%peln(i,npz,j)+atm(n)%peln(i,npz+1,j))*0.5)*0.01
3038  enddo
3039  enddo
3040  used=send_data(idiag%id_pmaskv2, a2, time)
3041  endif
3042 
3043  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 &
3044  & .or. idiag%id_w1km>0 .or. idiag%id_basedbz>0 .or. idiag%id_dbz4km>0) then
3045  if (.not.allocated(wz)) allocate ( wz(isc:iec,jsc:jec,npz+1) )
3046  if ( atm(n)%flagstruct%hydrostatic) then
3047  rgrav = 1. / grav
3048 !$OMP parallel do default(none) shared(isc,iec,jsc,jec,wz,npz,Atm,n,rgrav)
3049  do j=jsc,jec
3050  do i=isc,iec
3051  wz(i,j,npz+1) = 0.
3052 ! wz(i,j,npz+1) = Atm(n)%phis(i,j)/grav
3053  enddo
3054  do k=npz,1,-1
3055  do i=isc,iec
3056  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))
3057  enddo
3058  enddo
3059  enddo
3060  else
3061 !$OMP parallel do default(none) shared(isc,iec,jsc,jec,wz,npz,Atm,n)
3062  do j=jsc,jec
3063  do i=isc,iec
3064  wz(i,j,npz+1) = 0.
3065 ! wz(i,j,npz+1) = Atm(n)%phis(i,j)/grav
3066  enddo
3067  do k=npz,1,-1
3068  do i=isc,iec
3069  wz(i,j,k) = wz(i,j,k+1) - atm(n)%delz(i,j,k)
3070  enddo
3071  enddo
3072  enddo
3073  endif
3074  if( prt_minmax ) &
3075  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)
3076  endif
3077 
3078  if ( idiag%id_rain5km>0 ) then
3079  rainwat = get_tracer_index(model_atmos, 'rainwat')
3080  call interpolate_z(isc, iec, jsc, jec, npz, 5.e3, wz, atm(n)%q(isc:iec,jsc:jec,:,rainwat), a2)
3081  used=send_data(idiag%id_rain5km, a2, time)
3082  if(prt_minmax) call prt_maxmin('rain5km', a2, isc, iec, jsc, jec, 0, 1, 1.)
3083  endif
3084  if ( idiag%id_w5km>0 ) then
3085  call interpolate_z(isc, iec, jsc, jec, npz, 5.e3, wz, atm(n)%w(isc:iec,jsc:jec,:), a2)
3086  used=send_data(idiag%id_w5km, a2, time)
3087  if(prt_minmax) call prt_maxmin('W5km', a2, isc, iec, jsc, jec, 0, 1, 1.)
3088  endif
3089  if ( idiag%id_w2500m>0 ) then
3090  call interpolate_z(isc, iec, jsc, jec, npz, 2.5e3, wz, atm(n)%w(isc:iec,jsc:jec,:), a2)
3091  used=send_data(idiag%id_w2500m, a2, time)
3092  if(prt_minmax) call prt_maxmin('W2500m', a2, isc, iec, jsc, jec, 0, 1, 1.)
3093  endif
3094  if ( idiag%id_w1km>0 ) then
3095  call interpolate_z(isc, iec, jsc, jec, npz, 1.e3, wz, atm(n)%w(isc:iec,jsc:jec,:), a2)
3096  used=send_data(idiag%id_w1km, a2, time)
3097  if(prt_minmax) call prt_maxmin('W1km', a2, isc, iec, jsc, jec, 0, 1, 1.)
3098  endif
3099  if ( idiag%id_w100m>0 ) then
3100  call interpolate_z(isc, iec, jsc, jec, npz, 100., wz, atm(n)%w(isc:iec,jsc:jec,:), a2)
3101  used=send_data(idiag%id_w100m, a2, time)
3102  if(prt_minmax) call prt_maxmin('w100m', a2, isc, iec, jsc, jec, 0, 1, 1.)
3103  endif
3104  if ( idiag%id_u100m>0 ) then
3105  call interpolate_z(isc, iec, jsc, jec, npz, 100., wz, atm(n)%ua(isc:iec,jsc:jec,:), a2)
3106  used=send_data(idiag%id_u100m, a2, time)
3107  if(prt_minmax) call prt_maxmin('u100m', a2, isc, iec, jsc, jec, 0, 1, 1.)
3108  endif
3109  if ( idiag%id_v100m>0 ) then
3110  call interpolate_z(isc, iec, jsc, jec, npz, 100., wz, atm(n)%va(isc:iec,jsc:jec,:), a2)
3111  used=send_data(idiag%id_v100m, a2, time)
3112  if(prt_minmax) call prt_maxmin('v100m', a2, isc, iec, jsc, jec, 0, 1, 1.)
3113  endif
3114 
3115  if ( rainwat > 0 .and. (idiag%id_dbz>0 .or. idiag%id_maxdbz>0 .or. idiag%id_basedbz>0 .or. idiag%id_dbz4km>0 &
3116  & .or. idiag%id_dbztop>0 .or. idiag%id_dbz_m10C>0)) then
3117 
3118  if (.not. allocated(a3)) allocate(a3(isc:iec,jsc:jec,npz))
3119 
3120 ! call dbzcalc_smithxue(Atm(n)%q, Atm(n)%pt, Atm(n)%delp, Atm(n)%peln, Atm(n)%delz, &
3121  call dbzcalc(atm(n)%q, atm(n)%pt, atm(n)%delp, atm(n)%peln, atm(n)%delz, &
3122  a3, a2, allmax, atm(n)%bd, npz, atm(n)%ncnst, atm(n)%flagstruct%hydrostatic, &
3123  zvir, .false., .false., .false., .true. ) ! GFDL MP has constant N_0 intercept
3124 
3125  if (idiag%id_dbz > 0) used=send_data(idiag%id_dbz, a3, time)
3126  if (idiag%id_maxdbz > 0) used=send_data(idiag%id_maxdbz, a2, time)
3127 
3128  if (idiag%id_basedbz > 0) then
3129  !interpolate to 1km dbz
3130  call cs_interpolator(isc, iec, jsc, jec, npz, a3, 1000., wz, a2, -20.)
3131  used=send_data(idiag%id_basedbz, a2, time)
3132  if(prt_minmax) call prt_maxmin('Base_dBz', a2, isc, iec, jsc, jec, 0, 1, 1.)
3133  endif
3134 
3135  if (idiag%id_dbz4km > 0) then
3136  !interpolate to 1km dbz
3137  call cs_interpolator(isc, iec, jsc, jec, npz, a3, 4000., wz, a2, -20.)
3138  used=send_data(idiag%id_dbz4km, a2, time)
3139  endif
3140  if (idiag%id_dbztop > 0) then
3141  do j=jsc,jec
3142  do i=isc,iec
3143  a2(i,j) = missing_value2
3144  do k=2,npz
3145  if (wz(i,j,k) >= 25000. ) continue ! nothing above 25 km
3146  if (a3(i,j,k) >= 18.5 ) then
3147  a2(i,j) = wz(i,j,k)
3148  exit
3149  endif
3150  enddo
3151  enddo
3152  enddo
3153  used=send_data(idiag%id_dbztop, a2, time)
3154  endif
3155  if (idiag%id_dbz_m10C > 0) then
3156  do j=jsc,jec
3157  do i=isc,iec
3158  a2(i,j) = missing_value
3159  do k=npz,1,-1
3160  if (wz(i,j,k) >= 25000. ) exit ! nothing above 25 km
3161  if (atm(n)%pt(i,j,k) <= 263.14 ) then
3162  a2(i,j) = a3(i,j,k)
3163  exit
3164  endif
3165  enddo
3166  enddo
3167  enddo
3168  used=send_data(idiag%id_dbz_m10C, a2, time)
3169  endif
3170 
3171  if (prt_minmax) then
3172  call mpp_max(allmax)
3173  if (master) write(*,*) 'max reflectivity = ', allmax, ' dBZ'
3174  endif
3175 
3176  deallocate(a3)
3177  endif
3178 
3179 !-------------------------------------------------------
3180 ! Applying cubic-spline as the intepolator for (u,v,T,q)
3181 !-------------------------------------------------------
3182  if(.not. allocated(a3)) allocate( a3(isc:iec,jsc:jec,nplev) )
3183 ! u-winds:
3184  idg(:) = idiag%id_u(:)
3185 
3186  do_cs_intp = .false.
3187  do i=1,nplev
3188  if ( idg(i)>0 ) then
3189  do_cs_intp = .true.
3190  exit
3191  endif
3192  enddo
3193 
3194  if ( do_cs_intp ) then
3195  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%ua(isc:iec,jsc:jec,:), nplev, &
3196  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, -1)
3197 ! plevs, Atm(n)%peln, idg, a3, -1)
3198  do i=1,nplev
3199  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
3200  enddo
3201  endif
3202 
3203  if (idiag%id_u_plev>0) then
3204  id1(:) = 1
3205  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%ua(isc:iec,jsc:jec,:), nplev, &
3206  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, -1)
3207  used=send_data(idiag%id_u_plev, a3(isc:iec,jsc:jec,:), time)
3208  endif
3209 
3210 ! v-winds:
3211  idg(:) = idiag%id_v(:)
3212 
3213  do_cs_intp = .false.
3214  do i=1,nplev
3215  if ( idg(i)>0 ) then
3216  do_cs_intp = .true.
3217  exit
3218  endif
3219  enddo
3220 
3221  if ( do_cs_intp ) then
3222  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%va(isc:iec,jsc:jec,:), nplev, &
3223  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, -1)
3224 ! plevs, Atm(n)%peln, idg, a3, -1)
3225  do i=1,nplev
3226  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
3227  enddo
3228  endif
3229 
3230  if (idiag%id_v_plev>0) then
3231  id1(:) = 1
3232  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%va(isc:iec,jsc:jec,:), nplev, &
3233  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, -1)
3234  used=send_data(idiag%id_v_plev, a3(isc:iec,jsc:jec,:), time)
3235  endif
3236 
3237 ! Specific humidity
3238  idg(:) = idiag%id_q(:)
3239 
3240  do_cs_intp = .false.
3241  do i=1,nplev
3242  if ( idg(i)>0 ) then
3243  do_cs_intp = .true.
3244  exit
3245  endif
3246  enddo
3247 
3248  if ( do_cs_intp ) then
3249  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%q(isc:iec,jsc:jec,:,sphum), nplev, &
3250  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, 0)
3251 ! plevs, Atm(n)%peln, idg, a3, 0)
3252  do i=1,nplev
3253  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
3254  enddo
3255  endif
3256 
3257  if (idiag%id_q_plev>0) then
3258  id1(:) = 1
3259  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%q(isc:iec,jsc:jec,:,sphum), nplev, &
3260  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, 0)
3261  used=send_data(idiag%id_q_plev, a3(isc:iec,jsc:jec,:), time)
3262  endif
3263 
3264 ! Omega
3265  idg(:) = idiag%id_omg(:)
3266 
3267  do_cs_intp = .false.
3268  do i=1,nplev
3269  if ( idg(i)>0 ) then
3270  do_cs_intp = .true.
3271  exit
3272  endif
3273  enddo
3274  if ( do_cs_intp ) then
3275  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%omga(isc:iec,jsc:jec,:), nplev, &
3276  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), idg, a3, -1)
3277 ! plevs, Atm(n)%peln, idg, a3)
3278  do i=1,nplev
3279  if (idg(i)>0) used=send_data(idg(i), a3(isc:iec,jsc:jec,i), time)
3280  enddo
3281  endif
3282 
3283  if (idiag%id_omg_plev>0) then
3284  id1(:) = 1
3285  call cs3_interpolator(isc,iec,jsc,jec,npz, atm(n)%omga(isc:iec,jsc:jec,:), nplev, &
3286  pout, wz, atm(n)%pe(isc:iec,1:npz+1,jsc:jec), id1, a3, -1)
3287  used=send_data(idiag%id_omg_plev, a3(isc:iec,jsc:jec,:), time)
3288  endif
3289 
3290  if( allocated(a3) ) deallocate (a3)
3291 ! *** End cs_intp
3292 
3293  if ( idiag%id_sl12>0 ) then ! 13th level wind speed (~ 222 mb for the 32L setup)
3294  do j=jsc,jec
3295  do i=isc,iec
3296  a2(i,j) = sqrt(atm(n)%ua(i,j,12)**2 + atm(n)%va(i,j,12)**2)
3297  enddo
3298  enddo
3299  used=send_data(idiag%id_sl12, a2, time)
3300  endif
3301  if ( idiag%id_sl13>0 ) then ! 13th level wind speed (~ 222 mb for the 32L setup)
3302  do j=jsc,jec
3303  do i=isc,iec
3304  a2(i,j) = sqrt(atm(n)%ua(i,j,13)**2 + atm(n)%va(i,j,13)**2)
3305  enddo
3306  enddo
3307  used=send_data(idiag%id_sl13, a2, time)
3308  endif
3309 
3310  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w200>0 ) then
3311  call interpolate_vertical(isc, iec, jsc, jec, npz, &
3312  200.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
3313  used=send_data(idiag%id_w200, a2, time)
3314  endif
3315 ! 500-mb
3316  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w500>0 ) then
3317  call interpolate_vertical(isc, iec, jsc, jec, npz, &
3318  500.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
3319  used=send_data(idiag%id_w500, a2, time)
3320  endif
3321  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w700>0 ) then
3322  call interpolate_vertical(isc, iec, jsc, jec, npz, &
3323  700.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
3324  used=send_data(idiag%id_w700, a2, time)
3325  endif
3326  if ( (.not.atm(n)%flagstruct%hydrostatic) .and. idiag%id_w850>0 .or. idiag%id_x850>0) then
3327  call interpolate_vertical(isc, iec, jsc, jec, npz, &
3328  850.e2, atm(n)%peln, atm(n)%w(isc:iec,jsc:jec,:), a2)
3329  used=send_data(idiag%id_w850, a2, time)
3330 
3331  if ( idiag%id_x850>0 .and. idiag%id_vort850>0 ) then
3332  x850(:,:) = x850(:,:)*a2(:,:)
3333  used=send_data(idiag%id_x850, x850, time)
3334  deallocate ( x850 )
3335  endif
3336  endif
3337 
3338 
3339  if ( .not.atm(n)%flagstruct%hydrostatic .and. idiag%id_w>0 ) then
3340  used=send_data(idiag%id_w, atm(n)%w(isc:iec,jsc:jec,:), time)
3341  endif
3342  if ( .not. atm(n)%flagstruct%hydrostatic .and. (idiag%id_wmaxup>0 .or. idiag%id_wmaxdn>0) ) then
3343  allocate(var2(isc:iec,jsc:jec))
3344  do j=jsc,jec
3345  do i=isc,iec
3346  a2(i,j) = 0.
3347  var2(i,j) = 0.
3348  do k=3,npz
3349  if (atm(n)%pe(i,k,j) <= 400.e2) continue
3350  a2(i,j) = max(a2(i,j),atm(n)%w(i,j,k))
3351  var2(i,j) = min(var2(i,j),atm(n)%w(i,j,k))
3352  enddo
3353  enddo
3354  enddo
3355  if (idiag%id_wmaxup > 0) then
3356  used=send_data(idiag%id_wmaxup, a2, time)
3357  endif
3358  if (idiag%id_wmaxdn > 0) then
3359  used=send_data(idiag%id_wmaxdn, var2, time)
3360  endif
3361  deallocate(var2)
3362  endif
3363 
3364  if(idiag%id_pt > 0) used=send_data(idiag%id_pt , atm(n)%pt (isc:iec,jsc:jec,:), time)
3365  if(idiag%id_omga > 0) used=send_data(idiag%id_omga, atm(n)%omga(isc:iec,jsc:jec,:), time)
3366  if(idiag%id_diss > 0) used=send_data(idiag%id_diss, atm(n)%diss_est(isc:iec,jsc:jec,:), time)
3367 
3368  allocate( a3(isc:iec,jsc:jec,npz) )
3369  if(idiag%id_theta_e > 0 ) then
3370 
3371  if ( atm(n)%flagstruct%adiabatic .and. atm(n)%flagstruct%kord_tm>0 ) then
3372  do k=1,npz
3373  do j=jsc,jec
3374  do i=isc,iec
3375  a3(i,j,k) = atm(n)%pt(i,j,k)
3376  enddo
3377  enddo
3378  enddo
3379  else
3380  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), &
3381  isc, iec, jsc, jec, ngc, npz, atm(n)%flagstruct%hydrostatic, atm(n)%flagstruct%moist_phys)
3382  endif
3383 
3384  if (idiag%id_theta_e > 0) then
3385  if( prt_minmax ) call prt_maxmin('Theta_E', a3, isc, iec, jsc, jec, 0, npz, 1.)
3386  used=send_data(idiag%id_theta_e, a3, time)
3387  end if
3388  theta_d = get_tracer_index(model_atmos, 'theta_d')
3389  if ( theta_d>0 ) then
3390  if( prt_minmax ) then
3391  ! Check level-34 ~ 300 mb
3392  a2(:,:) = 0.
3393  do k=1,npz
3394  do j=jsc,jec
3395  do i=isc,iec
3396  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
3397  enddo
3398  enddo
3399  enddo
3400  call prt_mxm('PT_SUM', a2, isc, iec, jsc, jec, 0, 1, 1.e-5, atm(n)%gridstruct%area_64, atm(n)%domain)
3401 
3402  do k=1,npz
3403  do j=jsc,jec
3404  do i=isc,iec
3405  a3(i,j,k) = atm(n)%q(i,j,k,theta_d)/a3(i,j,k) - 1.
3406  enddo
3407  enddo
3408  enddo
3409  call prt_maxmin('Theta_Err (%)', a3, isc, iec, jsc, jec, 0, npz, 100.)
3410  ! if ( master ) write(*,*) 'PK0=', pk0, 'KAPPA=', kappa
3411  endif
3412  endif
3413 
3414  endif
3415 
3416  if(idiag%id_ppt> 0) then
3417 ! Potential temperature perturbation for gravity wave test_case
3418  allocate ( idiag%pt1(npz) )
3419  if( .not. allocated(a3) ) allocate ( a3(isc:iec,jsc:jec,npz) )
3420 #ifdef TEST_GWAVES
3421  call gw_1d(npz, 1000.e2, atm(n)%ak, atm(n)%ak, atm(n)%ak(1), 10.e3, idiag%pt1)
3422 #else
3423  idiag%pt1 = 0.
3424 #endif
3425  if (.not. atm(n)%flagstruct%hydrostatic) then
3426  do k=1,npz
3427  do j=jsc,jec
3428  do i=isc,iec
3429  wk(i,j,k) = (atm(n)%pt(i,j,k)*exp(-kappa*log(-atm(n)%delp(i,j,k)/(atm(n)%delz(i,j,k)*grav)*rdgas* &
3430 #ifdef MULTI_GASES
3431  atm(n)%pt(i,j,k)*virq(atm(n)%q(i,j,k,1:num_gas)))) - idiag%pt1(k)) * pk0
3432 #else
3433  atm(n)%pt(i,j,k)*(1.+zvir*atm(n)%q(i,j,k,sphum)))) - idiag%pt1(k)) * pk0
3434 #endif
3435 ! Atm(n)%pkz(i,j,k) = exp(kappa*log(-Atm(n)%delp(i,j,k)/(Atm(n)%delz(i,j,k)*grav)*rdgas* &
3436 ! Atm(n)%pt(i,j,k)*(1.+zvir*Atm(n)%q(i,j,k,sphum))))
3437  enddo
3438  enddo
3439  enddo
3440  else
3441  do k=1,npz
3442  do j=jsc,jec
3443  do i=isc,iec
3444 ! wk(i,j,k) = (Atm(n)%pt(i,j,k)-300.)/Atm(n)%pkz(i,j,k) * pk0
3445  wk(i,j,k) = (atm(n)%pt(i,j,k)/atm(n)%pkz(i,j,k) - idiag%pt1(k)) * pk0
3446  enddo
3447  enddo
3448  enddo
3449  endif
3450  used=send_data(idiag%id_ppt, wk, time)
3451 
3452  if( prt_minmax ) then
3453  call prt_maxmin('PoTemp', wk, isc, iec, jsc, jec, 0, npz, 1.)
3454  endif
3455 
3456  if( allocated(a3) ) deallocate ( a3 )
3457  deallocate ( idiag%pt1 )
3458  endif
3459 
3460 
3461 #ifndef SW_DYNAMICS
3462  do itrac=1, atm(n)%ncnst
3463  call get_tracer_names (model_atmos, itrac, tname)
3464  if (idiag%id_tracer(itrac) > 0 .and. itrac.gt.nq) then
3465  used = send_data(idiag%id_tracer(itrac), atm(n)%qdiag(isc:iec,jsc:jec,:,itrac), time )
3466  else
3467  used = send_data(idiag%id_tracer(itrac), atm(n)%q(isc:iec,jsc:jec,:,itrac), time )
3468  endif
3469  if (itrac .le. nq) then
3470  if( prt_minmax ) call prt_maxmin(trim(tname), atm(n)%q(:,:,1,itrac), &
3471  isc, iec, jsc, jec, ngc, npz, 1.)
3472  else
3473  if( prt_minmax ) call prt_maxmin(trim(tname), atm(n)%qdiag(:,:,1,itrac), &
3474  isc, iec, jsc, jec, ngc, npz, 1.)
3475  endif
3476 !-------------------------------
3477 ! ESM TRACER diagnostics output:
3478 ! jgj: per SJ email (jul 17 2008): q_dry = q_moist/(1-sphum)
3479 ! mass mixing ratio: q_dry = mass_tracer/mass_dryair = mass_tracer/(mass_air - mass_water) ~ q_moist/(1-sphum)
3480 ! co2_mmr = (wco2/wair) * co2_vmr
3481 ! Note: There is a check to ensure tracer number one is sphum
3482 
3483  if (idiag%id_tracer_dmmr(itrac) > 0 .or. idiag%id_tracer_dvmr(itrac) > 0) then
3484  if (itrac .gt. nq) then
3485  dmmr(:,:,:) = atm(n)%qdiag(isc:iec,jsc:jec,1:npz,itrac) &
3486  /(1.0-atm(n)%q(isc:iec,jsc:jec,1:npz,1))
3487  else
3488  dmmr(:,:,:) = atm(n)%q(isc:iec,jsc:jec,1:npz,itrac) &
3489  /(1.0-atm(n)%q(isc:iec,jsc:jec,1:npz,1))
3490  endif
3491  dvmr(:,:,:) = dmmr(isc:iec,jsc:jec,1:npz) * wtmair/idiag%w_mr(itrac)
3492  used = send_data(idiag%id_tracer_dmmr(itrac), dmmr, time )
3493  used = send_data(idiag%id_tracer_dvmr(itrac), dvmr, time )
3494  if( prt_minmax ) then
3495  call prt_maxmin(trim(tname)//'_dmmr', dmmr, &
3496  isc, iec, jsc, jec, 0, npz, 1.)
3497  call prt_maxmin(trim(tname)//'_dvmr', dvmr, &
3498  isc, iec, jsc, jec, 0, npz, 1.)
3499  endif
3500  endif
3501  enddo
3502 
3503 ! Maximum overlap cloud fraction
3504  if ( .not. atm(n)%gridstruct%bounded_domain ) then
3505  if ( cld_amt > 0 .and. prt_minmax ) then
3506  a2(:,:) = 0.
3507  do k=1,npz
3508  do j=jsc,jec
3509  do i=isc,iec
3510  a2(i,j) = max(a2(i,j), atm(n)%q(i,j,k,cld_amt) )
3511  enddo
3512  enddo
3513  enddo
3514  call prt_gb_nh_sh('Max_cld GB_NH_SH_EQ',isc,iec, jsc,jec, a2, atm(n)%gridstruct%area_64(isc:iec,jsc:jec), &
3515  atm(n)%gridstruct%agrid_64(isc:iec,jsc:jec,2))
3516  endif
3517  endif
3518 
3519 #endif
3520 
3521  if (do_diag_debug) then
3522  call debug_column(atm(n)%pt, atm(n)%delp, atm(n)%delz, atm(n)%u, atm(n)%v, atm(n)%w, atm(n)%q, &
3523  atm(n)%npz, atm(n)%ncnst, sphum, atm(n)%flagstruct%nwat, atm(n)%flagstruct%hydrostatic, atm(n)%bd, time)
3524  endif
3525 
3526  if (prt_sounding) then
3527  call sounding_column(atm(n)%pt, atm(n)%delp, atm(n)%delz, atm(n)%u, atm(n)%v, atm(n)%q, atm(n)%peln, atm(n)%pkz, atm(n)%phis, &
3528  atm(n)%npz, atm(n)%ncnst, sphum, atm(n)%flagstruct%nwat, atm(n)%flagstruct%hydrostatic, atm(n)%flagstruct%moist_phys, &
3529  zvir, atm(n)%ng, atm(n)%bd, time)
3530  endif
3531 
3532 
3533  ! enddo ! end ntileMe do-loop
3534 
3535  deallocate ( a2 )
3536  deallocate ( u2 )
3537  deallocate ( v2 )
3538  deallocate ( wk )
3539 
3540  if (allocated(a3)) deallocate(a3)
3541  if (allocated(wz)) deallocate(wz)
3542  if (allocated(dmmr)) deallocate(dmmr)
3543  if (allocated(dvmr)) deallocate(dvmr)
3544 
3545  call nullify_domain()
3546 
3547 
3548  end subroutine fv_diag
3549 
3550  subroutine wind_max(isc, iec, jsc, jec ,isd, ied, jsd, jed, us, vs, ws_max, domain)
3551  integer isc, iec, jsc, jec
3552  integer isd, ied, jsd, jed
3553  real, intent(in), dimension(isc:iec,jsc:jec):: us, vs
3554  real, intent(out) :: ws_max(isc:iec,jsc:jec)
3555  type(domain2d), intent(INOUT) :: domain
3556 ! Local
3557  real :: wx(isc:iec,jsd:jed), ws(isd:ied,jsd:jed)
3558  integer:: i,j
3559 
3560  ws = 0. ! fill corners with zeros
3561  do j=jsc,jec
3562  do i=isc,iec
3563  ws(i,j) = sqrt(us(i,j)**2 + vs(i,j)**2)
3564  enddo
3565  enddo
3566 
3567  call mpp_update_domains( ws, domain )
3568 
3569  do j=jsd,jed
3570  do i=isc,iec
3571  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))
3572  enddo
3573  enddo
3574 
3575  do j=jsc,jec
3576  do i=isc,iec
3577  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))
3578  enddo
3579  enddo
3580 
3581  end subroutine wind_max
3582 
3583 
3584  subroutine get_vorticity(isc, iec, jsc, jec ,isd, ied, jsd, jed, npz, u, v, vort, dx, dy, rarea)
3585  integer isd, ied, jsd, jed, npz
3586  integer isc, iec, jsc, jec
3587  real, intent(in) :: u(isd:ied, jsd:jed+1, npz), v(isd:ied+1, jsd:jed, npz)
3588  real, intent(out) :: vort(isc:iec, jsc:jec, npz)
3589  real, intent(IN) :: dx(isd:ied,jsd:jed+1)
3590  real, intent(IN) :: dy(isd:ied+1,jsd:jed)
3591  real, intent(IN) :: rarea(isd:ied,jsd:jed)
3592 ! Local
3593  real :: utmp(isc:iec, jsc:jec+1), vtmp(isc:iec+1, jsc:jec)
3594  integer :: i,j,k
3595 
3596  do k=1,npz
3597  do j=jsc,jec+1
3598  do i=isc,iec
3599  utmp(i,j) = u(i,j,k)*dx(i,j)
3600  enddo
3601  enddo
3602  do j=jsc,jec
3603  do i=isc,iec+1
3604  vtmp(i,j) = v(i,j,k)*dy(i,j)
3605  enddo
3606  enddo
3607 
3608  do j=jsc,jec
3609  do i=isc,iec
3610  vort(i,j,k) = rarea(i,j)*(utmp(i,j)-utmp(i,j+1)-vtmp(i,j)+vtmp(i+1,j))
3611  enddo
3612  enddo
3613  enddo
3614 
3615  end subroutine get_vorticity
3616 
3617 
3618  subroutine get_height_field(is, ie, js, je, ng, km, hydrostatic, delz, wz, pt, q, peln, zvir)
3619  integer, intent(in):: is, ie, js, je, km, ng
3620  real, intent(in):: peln(is:ie,km+1,js:je)
3621  real, intent(in):: pt(is-ng:ie+ng,js-ng:je+ng,km)
3622  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*) ! water vapor
3623  real, intent(in):: delz(is:,js:,1:)
3624  real, intent(in):: zvir
3625  logical, intent(in):: hydrostatic
3626  real, intent(out):: wz(is:ie,js:je,km+1)
3627 !
3628  integer i,j,k
3629  real gg
3630 
3631  gg = rdgas * ginv
3632 
3633  do j=js,je
3634  do i=is,ie
3635  wz(i,j,km+1) = idiag%zsurf(i,j)
3636  enddo
3637  if (hydrostatic ) then
3638  do k=km,1,-1
3639  do i=is,ie
3640 #ifdef MULTI_GASES
3641  wz(i,j,k) = wz(i,j,k+1) + gg*pt(i,j,k)*virq(q(i,j,k,1:num_gas)) &
3642  *(peln(i,k+1,j)-peln(i,k,j))
3643 #else
3644  wz(i,j,k) = wz(i,j,k+1) + gg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum)) &
3645  *(peln(i,k+1,j)-peln(i,k,j))
3646 #endif
3647  enddo
3648  enddo
3649  else
3650  do k=km,1,-1
3651  do i=is,ie
3652  wz(i,j,k) = wz(i,j,k+1) - delz(i,j,k)
3653  enddo
3654  enddo
3655  endif
3656  enddo
3657 
3658  end subroutine get_height_field
3659 
3660  subroutine range_check_3d(qname, q, is, ie, js, je, n_g, km, pos, q_low, q_hi, bad_range, Time)
3661  character(len=*), intent(in):: qname
3662  integer, intent(in):: is, ie, js, je
3663  integer, intent(in):: n_g, km
3664  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3665  real, intent(in):: pos(is-n_g:ie+n_g, js-n_g:je+n_g,2)
3666  real, intent(in):: q_low, q_hi
3667  logical, optional, intent(out):: bad_range
3668  type(time_type), optional, intent(IN) :: Time
3669 !
3670  real qmin, qmax
3671  integer i,j,k
3672  integer year, month, day, hour, minute, second
3673 
3674  if ( present(bad_range) ) bad_range = .false.
3675  qmin = q(is,js,1)
3676  qmax = qmin
3677 
3678  do k=1,km
3679  do j=js,je
3680  do i=is,ie
3681  if( q(i,j,k) < qmin ) then
3682  qmin = q(i,j,k)
3683  elseif( q(i,j,k) > qmax ) then
3684  qmax = q(i,j,k)
3685  endif
3686  enddo
3687  enddo
3688  enddo
3689 
3690  call mp_reduce_min(qmin)
3691  call mp_reduce_max(qmax)
3692 
3693  if( qmin<q_low .or. qmax>q_hi ) then
3694  if(master) write(*,*) 'Range_check Warning:', qname, ' max = ', qmax, ' min = ', qmin
3695  if (present(time)) then
3696  call get_date(time, year, month, day, hour, minute, second)
3697  if (master) write(*,999) year, month, day, hour, minute, second
3698 999 format(' Range violation on: ', i4, '/', i02, '/', i02, ' ', i02, ':', i02, ':', i02)
3699  endif
3700  if ( present(bad_range) ) then
3701  bad_range = .true.
3702  endif
3703  endif
3704 
3705  if ( present(bad_range) ) then
3706 ! Print out where the bad value(s) is (are)
3707  if ( bad_range .EQV. .false. ) return
3708  do k=1,km
3709  do j=js,je
3710  do i=is,ie
3711  if( q(i,j,k)<q_low .or. q(i,j,k)>q_hi ) then
3712  write(*,998) k,i,j, pos(i,j,1)*rad2deg, pos(i,j,2)*rad2deg, qname, q(i,j,k)
3713 ! write(*,*) 'Warn_K=',k,'(i,j)=',i,j, pos(i,j,1)*rad2deg, pos(i,j,2)*rad2deg, q(i,j,k)
3714 998 format('Warn_K=',i4,' (i,j)=',2i5,' (lon,lat)=',f7.3,1x,f7.3,1x, a,' =',f10.5)
3715 997 format(' K=',i4,3x,f10.5)
3716  if ( k/= 1 ) write(*,997) k-1, q(i,j,k-1)
3717  if ( k/=km ) write(*,997) k+1, q(i,j,k+1)
3718  endif
3719  enddo
3720  enddo
3721  enddo
3722  call mpp_error(note,'==> Error from range_check: data out of bound')
3723  endif
3724 
3725  end subroutine range_check_3d
3726 
3727  subroutine range_check_2d(qname, q, is, ie, js, je, n_g, pos, q_low, q_hi, bad_range, Time)
3728  character(len=*), intent(in):: qname
3729  integer, intent(in):: is, ie, js, je
3730  integer, intent(in):: n_g
3731  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g)
3732  real, intent(in):: pos(is-n_g:ie+n_g, js-n_g:je+n_g,2)
3733  real, intent(in):: q_low, q_hi
3734  logical, optional, intent(out):: bad_range
3735  type(time_type), optional, intent(IN) :: Time
3736 !
3737  real qmin, qmax
3738  integer i,j
3739  integer year, month, day, hour, minute, second
3740 
3741  if ( present(bad_range) ) bad_range = .false.
3742  qmin = q(is,js)
3743  qmax = qmin
3744 
3745  do j=js,je
3746  do i=is,ie
3747  if( q(i,j) < qmin ) then
3748  qmin = q(i,j)
3749  elseif( q(i,j) > qmax ) then
3750  qmax = q(i,j)
3751  endif
3752  enddo
3753  enddo
3754 
3755  call mp_reduce_min(qmin)
3756  call mp_reduce_max(qmax)
3757 
3758  if( qmin<q_low .or. qmax>q_hi ) then
3759  if(master) write(*,*) 'Range_check Warning:', qname, ' max = ', qmax, ' min = ', qmin
3760  if (present(time)) then
3761  call get_date(time, year, month, day, hour, minute, second)
3762  if (master) write(*,999) year, month, day, hour, minute, second
3763 999 format(' Range violation on: ', i4, '/', i02, '/', i02, ' ', i02, ':', i02, ':', i02)
3764  endif
3765  if ( present(bad_range) ) then
3766  bad_range = .true.
3767  endif
3768  endif
3769 
3770  if ( present(bad_range) ) then
3771 ! Print out where the bad value(s) is (are)
3772  if ( bad_range .EQV. .false. ) return
3773  do j=js,je
3774  do i=is,ie
3775  if( q(i,j)<q_low .or. q(i,j)>q_hi ) then
3776  write(*,*) 'Warn_(i,j)=',i,j, pos(i,j,1)*rad2deg, pos(i,j,2)*rad2deg, q(i,j)
3777  endif
3778  enddo
3779  enddo
3780  call mpp_error(note,'==> Error from range_check: data out of bound')
3781  endif
3782 
3783  end subroutine range_check_2d
3784 
3785  subroutine prt_maxmin(qname, q, is, ie, js, je, n_g, km, fac)
3786  character(len=*), intent(in):: qname
3787  integer, intent(in):: is, ie, js, je
3788  integer, intent(in):: n_g, km
3789  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3790  real, intent(in):: fac
3791 
3792  real qmin, qmax
3793  integer i,j,k
3794  !mpp_root_pe doesn't appear to recognize nested grid
3795  master = (mpp_pe()==mpp_root_pe()) .or. is_master()
3796 
3797  qmin = q(is,js,1)
3798  qmax = qmin
3799 
3800  do k=1,km
3801  do j=js,je
3802  do i=is,ie
3803 ! qmin = min(qmin, q(i,j,k))
3804 ! qmax = max(qmax, q(i,j,k))
3805  if( q(i,j,k) < qmin ) then
3806  qmin = q(i,j,k)
3807  elseif( q(i,j,k) > qmax ) then
3808  qmax = q(i,j,k)
3809  endif
3810  enddo
3811  enddo
3812  enddo
3813 
3814  call mp_reduce_min(qmin)
3815  call mp_reduce_max(qmax)
3816 
3817  if(master) then
3818  write(*,*) qname//trim(gn), ' max = ', qmax*fac, ' min = ', qmin*fac
3819  endif
3820 
3821  end subroutine prt_maxmin
3822 
3823  subroutine prt_mxm(qname, q, is, ie, js, je, n_g, km, fac, area, domain)
3824  character(len=*), intent(in):: qname
3825  integer, intent(in):: is, ie, js, je
3826  integer, intent(in):: n_g, km
3827  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3828  real, intent(in):: fac
3829 ! BUG !!!
3830 ! real, intent(IN):: area(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3831  real(kind=R_GRID), intent(IN):: area(is-3:ie+3, js-3:je+3)
3832  type(domain2d), intent(INOUT) :: domain
3833 !
3834  real qmin, qmax, gmean
3835  integer i,j,k
3836 
3837  !mpp_root_pe doesn't appear to recognize nested grid
3838  master = (mpp_pe()==mpp_root_pe()) .or. is_master()
3839  qmin = q(is,js,1)
3840  qmax = qmin
3841  gmean = 0.
3842 
3843  do k=1,km
3844  do j=js,je
3845  do i=is,ie
3846 ! qmin = min(qmin, q(i,j,k))
3847 ! qmax = max(qmax, q(i,j,k))
3848  if( q(i,j,k) < qmin ) then
3849  qmin = q(i,j,k)
3850  elseif( q(i,j,k) > qmax ) then
3851  qmax = q(i,j,k)
3852  endif
3853  enddo
3854  enddo
3855  enddo
3856 
3857  call mp_reduce_min(qmin)
3858  call mp_reduce_max(qmax)
3859 
3860 ! SJL: BUG!!!
3861 ! gmean = g_sum(domain, q(is,js,km), is, ie, js, je, 3, area, 1)
3862  gmean = g_sum(domain, q(is:ie,js:je,km), is, ie, js, je, 3, area, 1)
3863 
3864  if(master) write(6,*) qname, gn, qmax*fac, qmin*fac, gmean*fac
3865 
3866  end subroutine prt_mxm
3867 
3868  !Added nwat == 1 case for water vapor diagnostics
3869  subroutine prt_mass(km, nq, is, ie, js, je, n_g, nwat, ps, delp, q, area, domain)
3871  integer, intent(in):: is, ie, js, je
3872  integer, intent(in):: nq, n_g, km, nwat
3873  real, intent(in):: ps(is-n_g:ie+n_g, js-n_g:je+n_g)
3874  real, intent(in):: delp(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3875  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km, nq)
3876  real(kind=R_GRID), intent(IN):: area(is-n_g:ie+n_g,js-n_g:je+n_g)
3877  type(domain2d), intent(INOUT) :: domain
3878 ! Local:
3879  real psq(is:ie,js:je,nwat), psqv(is:ie,js:je)
3880  real q_strat(is:ie,js:je)
3881  real qtot(nwat), qwat
3882  real psmo, totw, psdry
3883  integer k, n, kstrat
3884 
3885 !Needed when calling prt_mass in fv_restart?
3886  sphum = get_tracer_index(model_atmos, 'sphum')
3887  liq_wat = get_tracer_index(model_atmos, 'liq_wat')
3888  ice_wat = get_tracer_index(model_atmos, 'ice_wat')
3889 
3890  rainwat = get_tracer_index(model_atmos, 'rainwat')
3891  snowwat = get_tracer_index(model_atmos, 'snowwat')
3892  graupel = get_tracer_index(model_atmos, 'graupel')
3893 
3894  if ( nwat==0 ) then
3895  psmo = g_sum(domain, ps(is:ie,js:je), is, ie, js, je, n_g, area, 1)
3896  if( master ) write(*,*) 'Total surface pressure (mb)', trim(gn), ' = ', 0.01*psmo
3897  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,1 ), psqv(is,js))
3898  return
3899  endif
3900 
3901  psq(:,:,:) = 0.
3902  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,sphum ), psq(is,js,sphum ))
3903 
3904  if (liq_wat > 0) &
3905  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))
3906 
3907  if (rainwat > 0) &
3908  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,rainwat), psq(is,js,rainwat))
3909 
3910 !nwat == 4 => KESSLER, ice is probably garbage...
3911  if (ice_wat > 0) &
3912  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))
3913 
3914  if (snowwat > 0) &
3915  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,snowwat), psq(is,js,snowwat))
3916  if (graupel > 0) &
3917  call z_sum(is, ie, js, je, km, n_g, delp, q(is-n_g,js-n_g,1,graupel), psq(is,js,graupel))
3918 
3919 
3920 ! Mean water vapor in the "stratosphere" (75 mb and above):
3921  if ( idiag%phalf(2)< 75. ) then
3922  kstrat = 1
3923  do k=1,km
3924  if ( idiag%phalf(k+1) > 75. ) exit
3925  kstrat = k
3926  enddo
3927  call z_sum(is, ie, js, je, kstrat, n_g, delp, q(is-n_g,js-n_g,1,sphum), q_strat(is,js))
3928  psmo = g_sum(domain, q_strat(is,js), is, ie, js, je, n_g, area, 1) * 1.e6 &
3929  / p_sum(is, ie, js, je, kstrat, n_g, delp, area, domain)
3930  if(master) write(*,*) 'Mean specific humidity (mg/kg) above 75 mb', trim(gn), '=', psmo
3931  endif
3932 
3933 
3934 !-------------------
3935 ! Check global means
3936 !-------------------
3937  psmo = g_sum(domain, ps(is:ie,js:je), is, ie, js, je, n_g, area, 1)
3938 
3939  do n=1,nwat
3940  qtot(n) = g_sum(domain, psq(is,js,n), is, ie, js, je, n_g, area, 1)
3941  enddo
3942 
3943  totw = sum(qtot(1:nwat))
3944  psdry = psmo - totw
3945 
3946  if( master ) then
3947  write(*,*) 'Total surface pressure (mb)', trim(gn), ' = ', 0.01*psmo
3948  write(*,*) 'mean dry surface pressure', trim(gn), ' = ', 0.01*psdry
3949  write(*,*) 'Total Water Vapor (kg/m**2)', trim(gn), ' =', qtot(sphum)*ginv
3950  if ( nwat> 2 ) then
3951  write(*,*) '--- Micro Phys water substances (kg/m**2) ---'
3952  write(*,*) 'Total cloud water', trim(gn), '=', qtot(liq_wat)*ginv
3953  if (rainwat > 0) &
3954  write(*,*) 'Total rain water', trim(gn), '=', qtot(rainwat)*ginv
3955  if (ice_wat > 0) &
3956  write(*,*) 'Total cloud ice ', trim(gn), '=', qtot(ice_wat)*ginv
3957  if (snowwat > 0) &
3958  write(*,*) 'Total snow ', trim(gn), '=', qtot(snowwat)*ginv
3959  if (graupel > 0) &
3960  write(*,*) 'Total graupel ', trim(gn), '=', qtot(graupel)*ginv
3961  write(*,*) '---------------------------------------------'
3962  elseif ( nwat==2 ) then
3963  write(*,*) 'GFS condensate (kg/m^2)', trim(gn), '=', qtot(liq_wat)*ginv
3964  endif
3965  endif
3966 
3967  end subroutine prt_mass
3968 
3969 
3970  subroutine z_sum(is, ie, js, je, km, n_g, delp, q, sum2)
3971  integer, intent(in):: is, ie, js, je, n_g, km
3972  real, intent(in):: delp(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3973  real, intent(in):: q(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3974  real, intent(out):: sum2(is:ie,js:je)
3975 
3976  integer i,j,k
3977 
3978  do j=js,je
3979  do i=is,ie
3980  sum2(i,j) = delp(i,j,1)*q(i,j,1)
3981  enddo
3982  do k=2,km
3983  do i=is,ie
3984  sum2(i,j) = sum2(i,j) + delp(i,j,k)*q(i,j,k)
3985  enddo
3986  enddo
3987  enddo
3988 
3989  end subroutine z_sum
3990 
3991 
3992  real function p_sum(is, ie, js, je, km, n_g, delp, area, domain)
3993  integer, intent(in):: is, ie, js, je, n_g, km
3994  real, intent(in):: delp(is-n_g:ie+n_g, js-n_g:je+n_g, km)
3995  real(kind=R_GRID), intent(IN) :: area(is-n_g:ie+n_g, js-n_g:je+n_g)
3996  real :: sum2(is:ie,js:je)
3997  integer i,j,k
3998  type(domain2d), intent(INOUT) :: domain
3999 
4000 !$OMP parallel do default(none) shared(is,ie,js,je,km,sum2,delp)
4001  do j=js,je
4002  do i=is,ie
4003  sum2(i,j) = delp(i,j,1)
4004  enddo
4005  do k=2,km
4006  do i=is,ie
4007  sum2(i,j) = sum2(i,j) + delp(i,j,k)
4008  enddo
4009  enddo
4010  enddo
4011  p_sum = g_sum(domain, sum2, is, ie, js, je, n_g, area, 1)
4012 
4013  end function p_sum
4014 
4015 
4016 
4017  subroutine get_pressure_given_height(is, ie, js, je, ng, km, wz, kd, height, &
4018  ts, peln, a2, fac)
4020  integer, intent(in):: is, ie, js, je, km, ng
4021  integer, intent(in):: kd
4022  real, intent(in):: wz(is:ie,js:je,km+1)
4023  real, intent(in):: ts(is-ng:ie+ng,js-ng:je+ng)
4024  real, intent(in):: peln(is:ie,km+1,js:je)
4025  real, intent(in):: height(kd)
4026  real, intent(out):: a2(is:ie,js:je,kd)
4027  real, optional, intent(in):: fac
4028 
4029 ! local:
4030  integer n, i,j,k
4031  real ptmp, tm
4032 
4033 
4034  do n=1,kd
4035 
4036 !$OMP parallel do default(none) shared(is,ie,js,je,n,height,wz,km,peln,a2,ginv,ts,fac) &
4037 !$OMP private(ptmp, tm)
4038  do j=js,je
4039 
4040  do 1000 i=is,ie
4041 
4042  if ( height(n) >= wz(i,j,km+1) ) then
4043 !---------------------
4044 ! Search from top down
4045 !---------------------
4046  do k=1,km
4047  if( height(n) < wz(i,j,k) .and. height(n) >= wz(i,j,k+1) ) then
4048 ! Found it!
4049  ptmp = peln(i,k,j) + (peln(i,k+1,j)-peln(i,k,j)) * &
4050  (wz(i,j,k)-height(n)) / (wz(i,j,k)-wz(i,j,k+1))
4051  a2(i,j,n) = exp(ptmp)
4052  go to 500
4053  endif
4054  enddo
4055 
4056  else
4057 !-----------------------------------------
4058 ! xtrapolation: mean laspe rate 6.5 deg/km
4059 !-----------------------------------------
4060  tm = rdgas*ginv*(ts(i,j) + 3.25e-3*(wz(i,j,km)-height(n)))
4061  a2(i,j,n) = exp( peln(i,km+1,j) + (wz(i,j,km+1) - height(n))/tm )
4062  endif
4063 500 if ( present(fac) ) a2(i,j,n) = fac * a2(i,j,n)
4064 1000 continue
4065  enddo
4066  enddo
4067 
4068  end subroutine get_pressure_given_height
4069 
4070 
4071  subroutine get_height_given_pressure(is, ie, js, je, km, wz, kd, id, log_p, peln, a2)
4072  integer, intent(in):: is, ie, js, je, km
4073  integer, intent(in):: kd
4074  integer, intent(in):: id(kd)
4075  real, intent(in):: log_p(kd)
4077  real, intent(in):: wz(is:ie,js:je,km+1)
4078  real, intent(in):: peln(is:ie,km+1,js:je)
4079  real, intent(out):: a2(is:ie,js:je,kd)
4080 ! local:
4081  real, dimension(2*km+1):: pn, gz
4082  integer n,i,j,k, k1, k2, l
4083 
4084  k2 = max(12, km/2+1)
4085 
4086 !$OMP parallel do default(none) shared(k2,is,ie,js,je,km,kd,id,log_p,peln,a2,wz) &
4087 !$OMP private(i,j,n,k,k1,l,pn,gz)
4088  do j=js,je
4089  do i=is,ie
4090 !---------------
4091 ! Mirror method:
4092 !---------------
4093  do k=1,km+1
4094  pn(k) = peln(i,k,j)
4095  gz(k) = wz(i,j,k)
4096  enddo
4097  do k=km+2, km+k2
4098  l = 2*(km+1) - k
4099  gz(k) = 2.*gz(km+1) - gz(l)
4100  pn(k) = 2.*pn(km+1) - pn(l)
4101  enddo
4102  k1 = 1
4103  do 1000 n=1,kd
4104  if( id(n)<0 ) goto 1000
4105  do k=k1,km+k2-1
4106  if( log_p(n) <= pn(k+1) .and. log_p(n) >= pn(k) ) then
4107  a2(i,j,n) = gz(k) + (gz(k+1)-gz(k))*(log_p(n)-pn(k))/(pn(k+1)-pn(k))
4108  k1 = k
4109  go to 1000
4110  endif
4111  enddo
4112 1000 continue
4113  enddo
4114  enddo
4115 
4116  end subroutine get_height_given_pressure
4117 
4118  subroutine prt_height(qname, is, ie, js, je, ng, km, press, phis, delz, peln, area, lat)
4119  character(len=*), intent(in):: qname
4120  integer, intent(in):: is, ie, js, je, ng, km
4121  real, intent(in):: press
4122  real, intent(in):: peln(is:ie,km+1,js:je)
4123  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
4124  real, intent(in):: delz(is:,js:,1:)
4125  real(kind=R_GRID), intent(in), dimension(is:ie, js:je):: area, lat
4126 ! local:
4127  real:: a2(is:ie,js:je)
4128  real(kind=R_GRID), dimension(2*km+1):: pn, gz
4129  real(kind=R_GRID):: log_p
4130  integer i,j,k, k2, l
4131 
4132  log_p = log(press)
4133  k2 = max(12, km/2+1)
4134 
4135 !$OMP parallel do default(none) shared(k2,is,ie,js,je,km,log_p,peln,phis,delz,a2) &
4136 !$OMP private(i,j,k,l,pn,gz)
4137  do j=js,je
4138  do 1000 i=is,ie
4139 !---------------
4140 ! Mirror method:
4141 !---------------
4142  do k=1,km+1
4143  pn(k) = peln(i,k,j)
4144  enddo
4145  gz(km+1) = phis(i,j)/grav
4146  do k=km,1,-1
4147  gz(k) = gz(k+1) - delz(i,j,k)
4148  enddo
4149  do k=km+2, km+k2
4150  l = 2*(km+1) - k
4151  gz(k) = 2.*gz(km+1) - gz(l)
4152  pn(k) = 2.*pn(km+1) - pn(l)
4153  enddo
4154 
4155  do k=1,km+k2-1
4156  if( log_p <= pn(k+1) .and. log_p >= pn(k) ) then
4157  a2(i,j) = gz(k) + (gz(k+1)-gz(k))*(log_p-pn(k))/(pn(k+1)-pn(k))
4158  go to 1000
4159  endif
4160  enddo
4161 1000 continue
4162  enddo
4163  call prt_gb_nh_sh(qname, is,ie, js,je, a2, area, lat)
4164 
4165  end subroutine prt_height
4166 
4167  subroutine prt_gb_nh_sh(qname, is,ie, js,je, a2, area, lat)
4168  character(len=*), intent(in):: qname
4169  integer, intent(in):: is, ie, js, je
4170  real, intent(in), dimension(is:ie, js:je):: a2
4171  real(kind=R_GRID), intent(in), dimension(is:ie, js:je):: area, lat
4172 ! Local:
4173  real(R_GRID), parameter:: rad2deg = 180./pi
4174  real(R_GRID):: slat
4175  real:: t_eq, t_nh, t_sh, t_gb
4176  real:: area_eq, area_nh, area_sh, area_gb
4177  integer:: i,j
4178 
4179  t_eq = 0. ; t_nh = 0.; t_sh = 0.; t_gb = 0.
4180  area_eq = 0.; area_nh = 0.; area_sh = 0.; area_gb = 0.
4181  do j=js,je
4182  do i=is,ie
4183  slat = lat(i,j)*rad2deg
4184  area_gb = area_gb + area(i,j)
4185  t_gb = t_gb + a2(i,j)*area(i,j)
4186  if( (slat>-20. .and. slat<20.) ) then
4187  area_eq = area_eq + area(i,j)
4188  t_eq = t_eq + a2(i,j)*area(i,j)
4189  elseif( slat>=20. .and. slat<80. ) then
4190  area_nh = area_nh + area(i,j)
4191  t_nh = t_nh + a2(i,j)*area(i,j)
4192  elseif( slat<=-20. .and. slat>-80. ) then
4193  area_sh = area_sh + area(i,j)
4194  t_sh = t_sh + a2(i,j)*area(i,j)
4195  endif
4196  enddo
4197  enddo
4198  call mp_reduce_sum(area_gb)
4199  call mp_reduce_sum( t_gb)
4200  call mp_reduce_sum(area_nh)
4201  call mp_reduce_sum( t_nh)
4202  call mp_reduce_sum(area_sh)
4203  call mp_reduce_sum( t_sh)
4204  call mp_reduce_sum(area_eq)
4205  call mp_reduce_sum( t_eq)
4206  !Bugfix for non-global domains
4207  if (area_gb <= 1.) area_gb = -1.0
4208  if (area_nh <= 1.) area_nh = -1.0
4209  if (area_sh <= 1.) area_sh = -1.0
4210  if (area_eq <= 1.) area_eq = -1.0
4211  if (is_master()) write(*,*) qname, t_gb/area_gb, t_nh/area_nh, t_sh/area_sh, t_eq/area_eq
4212 
4213  end subroutine prt_gb_nh_sh
4214 
4215  subroutine cs3_interpolator(is, ie, js, je, km, qin, kd, pout, wz, pe, id, qout, iv)
4216 ! iv =-1: winds
4217 ! iv = 0: positive definite scalars
4218 ! iv = 1: temperature
4219  integer, intent(in):: is, ie, js, je, km, iv
4220  integer, intent(in):: kd
4221  integer, intent(in):: id(kd)
4222  real, intent(in):: pout(kd) ! must be monotonically increasing with increasing k
4223  real, intent(in):: pe(is:ie,km+1,js:je)
4224  real, intent(in):: qin(is:ie,js:je,km)
4225  real, intent(in):: wz(is:ie,js:je,km+1)
4226  real, intent(out):: qout(is:ie,js:je,kd)
4227 ! local:
4228  real, parameter:: gcp = grav / cp_air
4229  real:: qe(is:ie,km+1)
4230  real, dimension(is:ie,km):: q2, dp
4231  real:: s0, a6
4232  integer:: i,j,k, n, k1
4233 
4234 !$OMP parallel do default(none) shared(iv,id,is,ie,js,je,km,kd,pout,qin,qout,pe,wz) &
4235 !$OMP private(k1,s0,a6,q2,dp,qe)
4236  do j=js,je
4237 
4238  do i=is,ie
4239  do k=1,km
4240  dp(i,k) = pe(i,k+1,j) - pe(i,k,j)
4241  q2(i,k) = qin(i,j,k)
4242  enddo
4243  enddo
4244 
4245  call cs_prof(q2, dp, qe, km, is, ie, iv)
4246 
4247  do i=is,ie
4248  k1 = 1
4249  do n=1,kd
4250  if ( id(n) > 0 ) then
4251  if( pout(n) <= pe(i,1,j) ) then
4252 ! Higher than the top:
4253  qout(i,j,n) = qe(i,1)
4254  elseif ( pout(n) >= pe(i,km+1,j) ) then
4255 ! lower than the bottom surface:
4256  if ( iv==1 ) then ! Temperature
4257 ! lower than the bottom surface:
4258 ! mean (hydro) potential temp based on lowest 2-3 layers (NCEP method)
4259 ! temp = ptm * p**cappa = ptm * exp(cappa*log(pout))
4260  qout(i,j,n) = gcp*exp(kappa*pout(n)) * (wz(i,j,km-2) - wz(i,j,km)) / &
4261  ( exp(kappa*pe(i,km,j)) - exp(kappa*pe(i,km-2,j)) )
4262  else
4263  qout(i,j,n) = qe(i,km+1)
4264  endif
4265  else
4266  do k=k1,km
4267  if ( pout(n)>=pe(i,k,j) .and. pout(n) <= pe(i,k+1,j) ) then
4268 ! PPM distribution: f(s) = AL + s*[(AR-AL) + A6*(1-s)] ( 0 <= s <= 1 )
4269  a6 = 3.*(2.*q2(i,k) - (qe(i,k)+qe(i,k+1)))
4270  s0 = (pout(n)-pe(i,k,j)) / dp(i,k)
4271  qout(i,j,n) = qe(i,k) + s0*(qe(i,k+1)-qe(i,k)+a6*(1.-s0))
4272  k1 = k ! next level
4273  go to 500
4274  endif
4275  enddo
4276  endif
4277 500 if ( iv==0 ) qout(i,j,n) = max(0., qout(i,j,n))
4278  endif
4279  enddo
4280  enddo
4281  enddo
4282 
4283 ! Send_data here
4284 
4285  end subroutine cs3_interpolator
4286 
4287  subroutine cs_interpolator(is, ie, js, je, km, qin, zout, wz, qout, qmin)
4288  integer, intent(in):: is, ie, js, je, km
4289  real, intent(in):: zout, qmin
4290  real, intent(in):: qin(is:ie,js:je,km)
4291  real, intent(in):: wz(is:ie,js:je,km+1)
4292  real, intent(out):: qout(is:ie,js:je)
4293 ! local:
4294  real:: qe(is:ie,km+1)
4295  real, dimension(is:ie,km):: q2, dz
4296  real:: s0, a6
4297  integer:: i,j,k
4298 
4299 !$OMP parallel do default(none) shared(qmin,is,ie,js,je,km,zout,qin,qout,wz) &
4300 !$OMP private(s0,a6,q2,dz,qe)
4301  do j=js,je
4302 
4303  do i=is,ie
4304  do k=1,km
4305  dz(i,k) = wz(i,j,k) - wz(i,j,k+1)
4306  q2(i,k) = qin(i,j,k)
4307  enddo
4308  enddo
4309 
4310  call cs_prof(q2, dz, qe, km, is, ie, 1)
4311 
4312  do i=is,ie
4313  if( zout >= wz(i,j,1) ) then
4314 ! Higher than the top:
4315  qout(i,j) = qe(i,1)
4316  elseif ( zout <= wz(i,j,km+1) ) then
4317  qout(i,j) = qe(i,km+1)
4318  else
4319  do k=1,km
4320  if ( zout<=wz(i,j,k) .and. zout >= wz(i,j,k+1) ) then
4321 ! PPM distribution: f(s) = AL + s*[(AR-AL) + A6*(1-s)] ( 0 <= s <= 1 )
4322  a6 = 3.*(2.*q2(i,k) - (qe(i,k)+qe(i,k+1)))
4323  s0 = (wz(i,j,k)-zout) / dz(i,k)
4324  qout(i,j) = qe(i,k) + s0*(qe(i,k+1)-qe(i,k)+a6*(1.-s0))
4325  go to 500
4326  endif
4327  enddo
4328  endif
4329 500 qout(i,j) = max(qmin, qout(i,j))
4330  enddo
4331  enddo
4332 
4333 ! Send_data here
4334 
4335  end subroutine cs_interpolator
4336 
4337  subroutine cs_prof(q2, delp, q, km, i1, i2, iv)
4338 ! Latest: Dec 2015 S.-J. Lin, NOAA/GFDL
4339  integer, intent(in):: i1, i2, km
4340  integer, intent(in):: iv
4341  real, intent(in) :: q2(i1:i2,km)
4342  real, intent(in) :: delp(i1:i2,km) ! <layer pressure thickness
4343  real, intent(out):: q(i1:i2,km+1)
4344 !-----------------------------------------------------------------------
4345  real gam(i1:i2,km)
4346  real d4(i1:i2)
4347  real bet, a_bot, grat
4348  integer i, k
4349 
4350  do i=i1,i2
4351  grat = delp(i,2) / delp(i,1) ! grid ratio
4352  bet = grat*(grat+0.5)
4353  q(i,1) = ( (grat+grat)*(grat+1.)*q2(i,1) + q2(i,2) ) / bet
4354  gam(i,1) = ( 1. + grat*(grat+1.5) ) / bet
4355  enddo
4356 
4357  do k=2,km
4358  do i=i1,i2
4359  d4(i) = delp(i,k-1) / delp(i,k)
4360  bet = 2. + d4(i) + d4(i) - gam(i,k-1)
4361  q(i,k) = ( 3.*(q2(i,k-1)+d4(i)*q2(i,k)) - q(i,k-1) )/bet
4362  gam(i,k) = d4(i) / bet
4363  enddo
4364  enddo
4365 
4366  do i=i1,i2
4367  a_bot = 1. + d4(i)*(d4(i)+1.5)
4368  q(i,km+1) = (2.*d4(i)*(d4(i)+1.)*q2(i,km)+q2(i,km-1)-a_bot*q(i,km)) &
4369  / ( d4(i)*(d4(i)+0.5) - a_bot*gam(i,km) )
4370  enddo
4371 
4372  do k=km,1,-1
4373  do i=i1,i2
4374  q(i,k) = q(i,k) - gam(i,k)*q(i,k+1)
4375  enddo
4376  enddo
4377 
4378 ! Apply *large-scale* constraints
4379  do i=i1,i2
4380  q(i,2) = min( q(i,2), max(q2(i,1), q2(i,2)) )
4381  q(i,2) = max( q(i,2), min(q2(i,1), q2(i,2)) )
4382  enddo
4383 
4384  do k=2,km
4385  do i=i1,i2
4386  gam(i,k) = q2(i,k) - q2(i,k-1)
4387  enddo
4388  enddo
4389 
4390 ! Interior:
4391  do k=3,km-1
4392  do i=i1,i2
4393  if ( gam(i,k-1)*gam(i,k+1)>0. ) then
4394 ! Apply large-scale constraint to ALL fields if not local max/min
4395  q(i,k) = min( q(i,k), max(q2(i,k-1),q2(i,k)) )
4396  q(i,k) = max( q(i,k), min(q2(i,k-1),q2(i,k)) )
4397  else
4398  if ( gam(i,k-1) > 0. ) then
4399 ! There exists a local max
4400  q(i,k) = max(q(i,k), min(q2(i,k-1),q2(i,k)))
4401  else
4402 ! There exists a local min
4403  q(i,k) = min(q(i,k), max(q2(i,k-1),q2(i,k)))
4404  if ( iv==0 ) q(i,k) = max(0., q(i,k))
4405  endif
4406  endif
4407  enddo
4408  enddo
4409 
4410 ! Bottom:
4411  do i=i1,i2
4412  q(i,km) = min( q(i,km), max(q2(i,km-1), q2(i,km)) )
4413  q(i,km) = max( q(i,km), min(q2(i,km-1), q2(i,km)) )
4414  enddo
4415 
4416  end subroutine cs_prof
4417 
4418 
4419  subroutine interpolate_vertical(is, ie, js, je, km, plev, peln, a3, a2)
4421  integer, intent(in):: is, ie, js, je, km
4422  real, intent(in):: peln(is:ie,km+1,js:je)
4423  real, intent(in):: a3(is:ie,js:je,km)
4424  real, intent(in):: plev
4425  real, intent(out):: a2(is:ie,js:je)
4426 ! local:
4427  real pm(km)
4428  real logp
4429  integer i,j,k
4430 
4431  logp = log(plev)
4432 
4433 !$OMP parallel do default(none) shared(is,ie,js,je,km,peln,logp,a2,a3) &
4434 !$OMP private(pm)
4435  do j=js,je
4436  do 1000 i=is,ie
4437 
4438  do k=1,km
4439  pm(k) = 0.5*(peln(i,k,j)+peln(i,k+1,j))
4440  enddo
4441 
4442  if( logp <= pm(1) ) then
4443  a2(i,j) = a3(i,j,1)
4444  elseif ( logp >= pm(km) ) then
4445  a2(i,j) = a3(i,j,km)
4446  else
4447  do k=1,km-1
4448  if( logp <= pm(k+1) .and. logp >= pm(k) ) then
4449  a2(i,j) = a3(i,j,k) + (a3(i,j,k+1)-a3(i,j,k))*(logp-pm(k))/(pm(k+1)-pm(k))
4450  go to 1000
4451  endif
4452  enddo
4453  endif
4454 1000 continue
4455  enddo
4456 
4457  end subroutine interpolate_vertical
4458 
4459 
4460  subroutine interpolate_z(is, ie, js, je, km, zl, hght, a3, a2)
4462  integer, intent(in):: is, ie, js, je, km
4463  real, intent(in):: hght(is:ie,js:je,km+1)
4464  real, intent(in):: a3(is:ie,js:je,km)
4465  real, intent(in):: zl
4466  real, intent(out):: a2(is:ie,js:je)
4467 ! local:
4468  real zm(km)
4469  integer i,j,k
4470 
4471 
4472 !$OMP parallel do default(none) shared(is,ie,js,je,km,hght,zl,a2,a3) private(zm)
4473  do j=js,je
4474  do 1000 i=is,ie
4475  do k=1,km
4476  zm(k) = 0.5*(hght(i,j,k)+hght(i,j,k+1))
4477  enddo
4478  if( zl >= zm(1) ) then
4479  a2(i,j) = a3(i,j,1)
4480  elseif ( zl <= zm(km) ) then
4481  a2(i,j) = a3(i,j,km)
4482  else
4483  do k=1,km-1
4484  if( zl <= zm(k) .and. zl >= zm(k+1) ) then
4485  a2(i,j) = a3(i,j,k) + (a3(i,j,k+1)-a3(i,j,k))*(zm(k)-zl)/(zm(k)-zm(k+1))
4486  go to 1000
4487  endif
4488  enddo
4489  endif
4490 1000 continue
4491  enddo
4492 
4493  end subroutine interpolate_z
4494 
4495  subroutine helicity_relative(is, ie, js, je, ng, km, zvir, sphum, srh, &
4496  ua, va, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
4497 ! !INPUT PARAMETERS:
4498  integer, intent(in):: is, ie, js, je, ng, km, sphum
4499  real, intent(in):: grav, zvir, z_bot, z_top
4500  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt, ua, va
4501  real, intent(in):: delz(is:ie,js:je,km)
4502  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
4503  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
4504  real, intent(in):: peln(is:ie,km+1,js:je)
4505  logical, intent(in):: hydrostatic
4506  real, intent(out):: srh(is:ie,js:je) ! unit: (m/s)**2
4507 ! real, parameter:: z_crit = 3.e3 ! lowest 3-km
4508 !---------------------------------------------------------------------------------
4509 ! SRH = 150-299 ... supercells possible with weak tornadoes
4510 ! SRH = 300-449 ... very favourable to supercells development and strong tornadoes
4511 ! SRH > 450 ... violent tornadoes
4512 !---------------------------------------------------------------------------------
4513 ! if z_top = 1E3, the threshold for supercells is 100 (m/s)**2
4514 ! Coded by S.-J. Lin for CONUS regional climate simulations
4515 !
4516  real:: rdg
4517  real, dimension(is:ie):: zh, uc, vc, dz, zh0
4518  integer i, j, k, k0, k1
4519  logical below(is:ie)
4520 
4521  rdg = rdgas / grav
4522 
4523 !$OMP parallel do default(none) shared(is,ie,js,je,km,hydrostatic,rdg,pt,zvir,sphum, &
4524 #ifdef MULTI_GASES
4525 !$OMP num_gas, &
4526 #endif
4527 !$OMP peln,delz,ua,va,srh,z_bot,z_top) &
4528 !$OMP private(zh,uc,vc,dz,k0,k1,zh0,below)
4529  do j=js,je
4530 
4531  do i=is,ie
4532  uc(i) = 0.
4533  vc(i) = 0.
4534  zh(i) = 0.
4535  srh(i,j) = 0.
4536  below(i) = .true.
4537  zh0(i) = 0.
4538 
4539 ! if ( phis(i,j)/grav < 1.E3 ) then
4540  do k=km,1,-1
4541  if ( hydrostatic ) then
4542 #ifdef MULTI_GASES
4543  dz(i) = rdg*pt(i,j,k)*virq(q(i,j,k,1:num_gas))*(peln(i,k+1,j)-peln(i,k,j))
4544 #else
4545  dz(i) = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
4546 #endif
4547  else
4548  dz(i) = - delz(i,j,k)
4549  endif
4550  zh(i) = zh(i) + dz(i)
4551  if (zh(i) <= z_bot ) continue
4552  if (zh(i) > z_bot .and. below(i)) then
4553  uc(i) = ua(i,j,k)*dz(i)
4554  vc(i) = va(i,j,k)*dz(i)
4555  zh0(i) = zh(i) - dz(i)
4556  k1 = k
4557  below(i) = .false.
4558 ! Compute mean winds below z_top
4559  elseif ( zh(i) < z_top ) then
4560  uc(i) = uc(i) + ua(i,j,k)*dz(i)
4561  vc(i) = vc(i) + va(i,j,k)*dz(i)
4562  k0 = k
4563  else
4564  uc(i) = uc(i) / (zh(i)-dz(i) - zh0(i))
4565  vc(i) = vc(i) / (zh(i)-dz(i) - zh0(i))
4566  goto 123
4567  endif
4568  enddo
4569 123 continue
4570 
4571 ! Lowest layer wind shear computed betw top edge and mid-layer
4572  k = k1
4573  srh(i,j) = 0.5*(va(i,j,k1)-vc(i))*(ua(i,j,k1-1)-ua(i,j,k1)) - &
4574  0.5*(ua(i,j,k1)-uc(i))*(va(i,j,k1-1)-va(i,j,k1))
4575  do k=k0, k1-1
4576  srh(i,j) = srh(i,j) + 0.5*(va(i,j,k)-vc(i))*(ua(i,j,k-1)-ua(i,j,k+1)) - &
4577  0.5*(ua(i,j,k)-uc(i))*(va(i,j,k-1)-va(i,j,k+1))
4578  enddo
4579 ! endif
4580  enddo ! i-loop
4581  enddo ! j-loop
4582 
4583  end subroutine helicity_relative
4584 
4585  subroutine helicity_relative_caps(is, ie, js, je, ng, km, zvir, sphum, srh, uc, vc, &
4586  ua, va, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
4587 ! !INPUT PARAMETERS:
4588  integer, intent(in):: is, ie, js, je, ng, km, sphum
4589  real, intent(in):: grav, zvir, z_bot, z_top
4590  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt, ua, va
4591  real, intent(in):: delz(is:ie,js:je,km)
4592  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
4593  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
4594  real, intent(in):: peln(is:ie,km+1,js:je)
4595  real, intent(in):: uc(is:ie,js:je), vc(is:ie,js:je)
4596  logical, intent(in):: hydrostatic
4597  real, intent(out):: srh(is:ie,js:je) ! unit: (m/s)**2
4598 !---------------------------------------------------------------------------------
4599 ! SRH = 150-299 ... supercells possible with weak tornadoes
4600 ! SRH = 300-449 ... very favourable to supercells development and strong tornadoes
4601 ! SRH > 450 ... violent tornadoes
4602 !---------------------------------------------------------------------------------
4603 ! if z_crit = 1E3, the threshold for supercells is 100 (m/s)**2
4604 ! Coded by S.-J. Lin for CONUS regional climate simulations
4605 !
4606  real:: rdg
4607  real, dimension(is:ie):: zh, dz, zh0
4608  integer i, j, k, k0, k1, n
4609  logical below
4610 
4611  rdg = rdgas / grav
4612 
4613 !$OMP parallel do default(none) shared(is,ie,js,je,km,hydrostatic,rdg,pt,zvir,sphum, &
4614 #ifdef MULTI_GASES
4615 !$OMP num_gas, &
4616 #endif
4617 !$OMP peln,delz,ua,va,srh,uc,vc,z_bot,z_top) &
4618 !$OMP private(zh,dz,k0,k1,zh0,below)
4619  do j=js,je
4620 
4621  do i=is,ie
4622  srh(i,j) = 0.
4623  zh(i) = 0.
4624  zh0 = 0.
4625  below = .true.
4626 
4627  do k=km,1,-1
4628  if ( hydrostatic ) then
4629 #ifdef MULTI_GASES
4630  dz(i) = rdg*pt(i,j,k)*virq(q(i,j,k,1:num_gas))*(peln(i,k+1,j)-peln(i,k,j))
4631 #else
4632  dz(i) = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
4633 #endif
4634  else
4635  dz(i) = -delz(i,j,k)
4636  endif
4637 
4638  zh(i) = zh(i) + dz(i)
4639  if (zh(i) <= z_bot ) continue
4640  if (zh(i) > z_bot .and. below) then
4641  zh0(i) = zh(i) - dz(i)
4642  k1 = k
4643  below = .false.
4644 ! Compute mean winds below z_top
4645  elseif ( zh(i) < z_top ) then
4646  k0 = k
4647  else
4648  goto 123
4649  endif
4650 
4651  enddo
4652 123 continue
4653 
4654 ! Lowest layer wind shear computed betw top edge and mid-layer
4655  k = k1
4656  srh(i,j) = 0.5*(va(i,j,k1)-vc(i,j))*(ua(i,j,k1-1)-ua(i,j,k1)) - &
4657  0.5*(ua(i,j,k1)-uc(i,j))*(va(i,j,k1-1)-va(i,j,k1))
4658  do k=k0, k1-1
4659  srh(i,j) = srh(i,j) + 0.5*(va(i,j,k)-vc(i,j))*(ua(i,j,k-1)-ua(i,j,k+1)) - &
4660  0.5*(ua(i,j,k)-uc(i,j))*(va(i,j,k-1)-va(i,j,k+1))
4661  enddo
4662  enddo ! i-loop
4663  enddo ! j-loop
4664 
4665  end subroutine helicity_relative_caps
4666 
4667 
4668  subroutine bunkers_vector(is, ie, js, je, ng, km, zvir, sphum, uc, vc, &
4669  ua, va, delz, q, hydrostatic, pt, peln, phis, grav)
4671  integer, intent(in):: is, ie, js, je, ng, km, sphum
4672  real, intent(in):: grav, zvir
4673  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt, ua, va
4674  real, intent(in):: delz(is:ie,js:je,km)
4675  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
4676  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
4677  real, intent(in):: peln(is:ie,km+1,js:je)
4678  logical, intent(in):: hydrostatic
4679  real, intent(out):: uc(is:ie,js:je), vc(is:ie,js:je)
4680 
4681  real:: rdg
4682  real :: zh, dz, usfc, vsfc, u6km, v6km, umn, vmn
4683  real :: ushr, vshr, shrmag
4684  integer i, j, k, n
4685  real, parameter :: bunkers_d = 7.5 ! Empirically derived parameter
4686  logical :: has_sfc, has_6km
4687 
4688  rdg = rdgas / grav
4689 
4690 !$OMP parallel do default(none) shared(is,ie,js,je,ng,km,hydrostatic,rdg,pt,zvir,sphum, &
4691 #ifdef MULTI_GASES
4692 !$OMP num_gas, &
4693 #endif
4694 !$OMP peln,delz,ua,va,uc,vc) &
4695 !$OMP private(zh,dz,usfc,vsfc,u6km,v6km,umn,vmn, &
4696 !$OMP ushr,vshr,shrmag)
4697  do j=js,je
4698  do i=is,ie
4699  zh = 0.
4700  usfc = 0.
4701  vsfc = 0.
4702  u6km = 0.
4703  v6km = 0.
4704  umn = 0.
4705  vmn = 0.
4706 
4707  usfc = ua(i,j,km)
4708  vsfc = va(i,j,km)
4709 
4710  do k=km,1,-1
4711  if ( hydrostatic ) then
4712 #ifdef MULTI_GASES
4713  dz = rdg*pt(i,j,k)*virq(q(i,j,k,1:num_gas))*(peln(i,k+1,j)-peln(i,k,j))
4714 #else
4715  dz = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
4716 #endif
4717  else
4718  dz = -delz(i,j,k)
4719  endif
4720  zh = zh + dz
4721 
4722  if (zh < 6000) then
4723  u6km = ua(i,j,k)
4724  v6km = va(i,j,k)
4725 
4726  umn = umn + ua(i,j,k)*dz
4727  vmn = vmn + va(i,j,k)*dz
4728  else
4729  goto 123
4730  endif
4731 
4732  enddo
4733 123 continue
4734 
4735  u6km = u6km + (ua(i,j,k) - u6km) / dz * (6000. - (zh - dz))
4736  v6km = v6km + (va(i,j,k) - v6km) / dz * (6000. - (zh - dz))
4737 
4738  umn = umn / (zh - dz)
4739  vmn = vmn / (zh - dz)
4740 
4741  ushr = u6km - usfc
4742  vshr = v6km - vsfc
4743  shrmag = sqrt(ushr * ushr + vshr * vshr)
4744  uc(i,j) = umn + bunkers_d * vshr / shrmag
4745  vc(i,j) = vmn - bunkers_d * ushr / shrmag
4746 
4747  enddo ! i-loop
4748  enddo ! j-loop
4749 
4750  end subroutine bunkers_vector
4751 
4752 
4753  subroutine updraft_helicity(is, ie, js, je, ng, km, zvir, sphum, uh, &
4754  w, vort, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
4755 ! !INPUT PARAMETERS:
4756  integer, intent(in):: is, ie, js, je, ng, km, sphum
4757  real, intent(in):: grav, zvir, z_bot, z_top
4758  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt, w
4759  real, intent(in), dimension(is:ie,js:je,km):: vort
4760  real, intent(in):: delz(is:ie,js:je,km)
4761  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
4762  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
4763  real, intent(in):: peln(is:ie,km+1,js:je)
4764  logical, intent(in):: hydrostatic
4765  real, intent(out):: uh(is:ie,js:je) ! unit: (m/s)**2
4766 ! Coded by S.-J. Lin for CONUS regional climate simulations
4767 ! Modified for UH by LMH
4768 !
4769  real:: rdg
4770  real, dimension(is:ie):: zh, dz, zh0
4771  integer i, j, k, n
4772  logical below(is:ie)
4773 
4774  rdg = rdgas / grav
4775 
4776 !$OMP parallel do default(none) shared(is,ie,js,je,ng,km,hydrostatic,rdg,pt,zvir,sphum, &
4777 #ifdef MULTI_GASES
4778 !$OMP num_gas, &
4779 #endif
4780 !$OMP peln,delz,w,vort,uh,z_bot,z_top) &
4781 !$OMP private(zh,dz,zh0,below)
4782  do j=js,je
4783 
4784  do i=is,ie
4785  zh(i) = 0.
4786  uh(i,j) = 0.
4787  below(i) = .true.
4788  zh0(i) = 0.
4789 
4790 ! if ( phis(i,j)/grav < 1.E3 ) then
4791  do k=km,1,-1
4792  if ( hydrostatic ) then
4793 #ifdef MULTI_GASES
4794  dz(i) = rdg*pt(i,j,k)*virq(q(i,j,k,1:num_gas))*(peln(i,k+1,j)-peln(i,k,j))
4795 #else
4796  dz(i) = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
4797 #endif
4798  else
4799  dz(i) = - delz(i,j,k)
4800  endif
4801  zh(i) = zh(i) + dz(i)
4802  if (zh(i) <= z_bot ) continue
4803  if (zh(i) > z_bot .and. below(i)) then
4804  uh(i,j) = vort(i,j,k)*w(i,j,k)*(zh(i) - z_bot)
4805  below(i) = .false.
4806 ! Compute mean winds below z_top
4807  elseif ( zh(i) < z_top ) then
4808  uh(i,j) = uh(i,j) + vort(i,j,k)*w(i,j,k)*dz(i)
4809  else
4810  uh(i,j) = uh(i,j) + vort(i,j,k)*w(i,j,k)*(z_top - (zh(i)-dz(i)) )
4811  goto 123
4812  endif
4813  enddo
4814 123 continue
4815 
4816  enddo ! i-loop
4817  enddo ! j-loop
4818 
4819  end subroutine updraft_helicity
4820 
4823  subroutine pv_entropy(is, ie, js, je, ng, km, vort, f_d, pt, pkz, delp, grav)
4825 ! !INPUT PARAMETERS:
4826  integer, intent(in):: is, ie, js, je, ng, km
4827  real, intent(in):: grav
4828  real, intent(in):: pt(is-ng:ie+ng,js-ng:je+ng,km)
4829  real, intent(in):: pkz(is:ie,js:je,km)
4830  real, intent(in):: delp(is-ng:ie+ng,js-ng:je+ng,km)
4831  real, intent(in):: f_d(is-ng:ie+ng,js-ng:je+ng)
4832 
4833 ! vort is relative vorticity as input. Becomes PV on output
4834  real, intent(inout):: vort(is:ie,js:je,km)
4835 
4836 ! !DESCRIPTION:
4837 ! EPV = 1/r * (vort+f_d) * d(S)/dz; where S is a conservative scalar
4838 ! r the fluid density, and S is chosen to be the entropy here: S = log(pt)
4839 ! pt == potential temperature.
4840 ! Computation are performed assuming the input is on "x-y-z" Cartesian coordinate.
4841 ! The approximation made here is that the relative vorticity computed on constant
4842 ! z-surface is not that different from the hybrid sigma-p coordinate.
4843 ! See page 39, Pedlosky 1979: Geophysical Fluid Dynamics
4844 !
4845 ! The follwoing simplified form is strictly correct only if vort is computed on
4846 ! constant z surfaces. In addition hydrostatic approximation is made.
4847 ! EPV = - GRAV * (vort+f_d) / del(p) * del(pt) / pt
4848 ! where del() is the vertical difference operator.
4849 !
4850 ! programmer: S.-J. Lin, shian-jiann.lin@noaa.gov
4851 !
4852 !EOP
4853 !---------------------------------------------------------------------
4854 !BOC
4855  real w3d(is:ie,js:je,km)
4856  real te(is:ie,js:je,km+1), t2(is:ie,km), delp2(is:ie,km)
4857  real te2(is:ie,km+1)
4858  integer i, j, k
4859 
4860 #ifdef SW_DYNAMICS
4861 !$OMP parallel do default(none) shared(is,ie,js,je,vort,grav,f_d,delp)
4862  do j=js,je
4863  do i=is,ie
4864  vort(i,j,1) = grav * (vort(i,j,1)+f_d(i,j)) / delp(i,j,1)
4865  enddo
4866  enddo
4867 #else
4868 ! Compute PT at layer edges.
4869 !$OMP parallel do default(none) shared(is,ie,js,je,km,pt,pkz,w3d,delp,te2,te) &
4870 !$OMP private(t2, delp2)
4871  do j=js,je
4872  do k=1,km
4873  do i=is,ie
4874  t2(i,k) = pt(i,j,k) / pkz(i,j,k)
4875  w3d(i,j,k) = t2(i,k)
4876  delp2(i,k) = delp(i,j,k)
4877  enddo
4878  enddo
4879 
4880  call ppme(t2, te2, delp2, ie-is+1, km)
4881 
4882  do k=1,km+1
4883  do i=is,ie
4884  te(i,j,k) = te2(i,k)
4885  enddo
4886  enddo
4887  enddo
4888 
4889 !$OMP parallel do default(none) shared(is,ie,js,je,km,vort,f_d,te,w3d,delp,grav)
4890  do k=1,km
4891  do j=js,je
4892  do i=is,ie
4893 ! Entropy is the thermodynamic variable in the following form
4894  vort(i,j,k) = (vort(i,j,k)+f_d(i,j)) * ( te(i,j,k)-te(i,j,k+1) ) &
4895  / ( w3d(i,j,k)*delp(i,j,k) ) * grav
4896  enddo
4897  enddo
4898  enddo
4899 #endif
4900 
4901  end subroutine pv_entropy
4902 
4903 
4904  subroutine ppme(p,qe,delp,im,km)
4906  integer, intent(in):: im, km
4907  real, intent(in):: p(im,km)
4908  real, intent(in):: delp(im,km)
4909  real, intent(out)::qe(im,km+1)
4910 
4911 ! local arrays.
4912  real dc(im,km),delq(im,km), a6(im,km)
4913  real c1, c2, c3, tmp, qmax, qmin
4914  real a1, a2, s1, s2, s3, s4, ss3, s32, s34, s42
4915  real a3, b2, sc, dm, d1, d2, f1, f2, f3, f4
4916  real qm, dq
4917  integer i, k, km1
4918 
4919  km1 = km - 1
4920 
4921  do 500 k=2,km
4922  do 500 i=1,im
4923 500 a6(i,k) = delp(i,k-1) + delp(i,k)
4924 
4925  do 1000 k=1,km1
4926  do 1000 i=1,im
4927  delq(i,k) = p(i,k+1) - p(i,k)
4928 1000 continue
4929 
4930  do 1220 k=2,km1
4931  do 1220 i=1,im
4932  c1 = (delp(i,k-1)+0.5*delp(i,k))/a6(i,k+1)
4933  c2 = (delp(i,k+1)+0.5*delp(i,k))/a6(i,k)
4934  tmp = delp(i,k)*(c1*delq(i,k) + c2*delq(i,k-1)) / &
4935  (a6(i,k)+delp(i,k+1))
4936  qmax = max(p(i,k-1),p(i,k),p(i,k+1)) - p(i,k)
4937  qmin = p(i,k) - min(p(i,k-1),p(i,k),p(i,k+1))
4938  dc(i,k) = sign(min(abs(tmp),qmax,qmin), tmp)
4939 1220 continue
4940 
4941 !****6***0*********0*********0*********0*********0*********0**********72
4942 ! 4th order interpolation of the provisional cell edge value
4943 !****6***0*********0*********0*********0*********0*********0**********72
4944 
4945  do k=3,km1
4946  do i=1,im
4947  c1 = delq(i,k-1)*delp(i,k-1) / a6(i,k)
4948  a1 = a6(i,k-1) / (a6(i,k) + delp(i,k-1))
4949  a2 = a6(i,k+1) / (a6(i,k) + delp(i,k))
4950  qe(i,k) = p(i,k-1) + c1 + 2./(a6(i,k-1)+a6(i,k+1)) * &
4951  ( delp(i,k)*(c1*(a1 - a2)+a2*dc(i,k-1)) - &
4952  delp(i,k-1)*a1*dc(i,k ) )
4953  enddo
4954  enddo
4955 
4956 ! three-cell parabolic subgrid distribution at model top
4957 
4958  do i=1,im
4959 ! three-cell PP-distribution
4960 ! Compute a,b, and c of q = aP**2 + bP + c using cell averages and delp
4961 ! a3 = a / 3
4962 ! b2 = b / 2
4963  s1 = delp(i,1)
4964  s2 = delp(i,2) + s1
4965 !
4966  s3 = delp(i,2) + delp(i,3)
4967  s4 = s3 + delp(i,4)
4968  ss3 = s3 + s1
4969  s32 = s3*s3
4970  s42 = s4*s4
4971  s34 = s3*s4
4972 ! model top
4973  a3 = (delq(i,2) - delq(i,1)*s3/s2) / (s3*ss3)
4974 !
4975  if(abs(a3) .gt. 1.e-14) then
4976  b2 = delq(i,1)/s2 - a3*(s1+s2)
4977  sc = -b2/(3.*a3)
4978  if(sc .lt. 0. .or. sc .gt. s1) then
4979  qe(i,1) = p(i,1) - s1*(a3*s1 + b2)
4980  else
4981  qe(i,1) = p(i,1) - delq(i,1)*s1/s2
4982  endif
4983  else
4984 ! Linear
4985  qe(i,1) = p(i,1) - delq(i,1)*s1/s2
4986  endif
4987  dc(i,1) = p(i,1) - qe(i,1)
4988 ! compute coef. for the off-centered area preserving cubic poly.
4989  dm = delp(i,1) / (s34*ss3*(delp(i,2)+s3)*(s4+delp(i,1)))
4990  f1 = delp(i,2)*s34 / ( s2*ss3*(s4+delp(i,1)) )
4991  f2 = (delp(i,2)+s3) * (ss3*(delp(i,2)*s3+s34+delp(i,2)*s4) &
4992  + s42*(delp(i,2)+s3+s32/s2))
4993  f3 = -delp(i,2)*( ss3*(s32*(s3+s4)/(s4-delp(i,2)) &
4994  + (delp(i,2)*s3+s34+delp(i,2)*s4)) &
4995  + s42*(delp(i,2)+s3) )
4996  f4 = ss3*delp(i,2)*s32*(delp(i,2)+s3) / (s4-delp(i,2))
4997  qe(i,2) = f1*p(i,1)+(f2*p(i,2)+f3*p(i,3)+f4*p(i,4))*dm
4998  enddo
4999 
5000 ! Bottom
5001 ! Area preserving cubic with 2nd deriv. = 0 at the surface
5002  do i=1,im
5003  d1 = delp(i,km)
5004  d2 = delp(i,km1)
5005  qm = (d2*p(i,km)+d1*p(i,km1)) / (d1+d2)
5006  dq = 2.*(p(i,km1)-p(i,km)) / (d1+d2)
5007  c1 = (qe(i,km1)-qm-d2*dq) / (d2*(2.*d2*d2+d1*(d2+3.*d1)))
5008  c3 = dq - 2.0*c1*(d2*(5.*d1+d2)-3.*d1**2)
5009  qe(i,km ) = qm - c1*d1*d2*(d2+3.*d1)
5010  qe(i,km+1) = d1*(8.*c1*d1**2-c3) + qe(i,km)
5011  enddo
5012 
5013  end subroutine ppme
5014 
5015 subroutine rh_calc (pfull, t, qv, rh, do_cmip)
5017  real, intent (in), dimension(:,:) :: pfull, t, qv
5018  real, intent (out), dimension(:,:) :: rh
5019  real, dimension(size(t,1),size(t,2)) :: esat
5020  logical, intent(in), optional :: do_cmip
5021 
5022  real, parameter :: d622 = rdgas/rvgas
5023  real, parameter :: d378 = 1.-d622
5024 
5025  logical :: do_simple = .false.
5026 
5027 ! because Betts-Miller uses a simplified scheme for calculating the relative humidity
5028 
5029  if (do_simple) then
5030  call lookup_es (t, esat)
5031  rh(:,:) = pfull(:,:)
5032  rh(:,:) = max(rh(:,:),esat(:,:)) !limit where pfull ~ esat
5033  rh(:,:)=100.*qv(:,:)/(d622*esat(:,:)/rh(:,:))
5034  else
5035  if (present(do_cmip)) then
5036  call compute_qs (t, pfull, rh, q=qv, es_over_liq_and_ice = .true.)
5037  rh(:,:)=100.*qv(:,:)/rh(:,:)
5038  else
5039  call compute_qs (t, pfull, rh, q=qv)
5040  rh(:,:)=100.*qv(:,:)/rh(:,:)
5041  endif
5042  endif
5043 
5044 end subroutine rh_calc
5045 
5046 #ifdef SIMPLIFIED_THETA_E
5047 
5051 #ifdef MULTI_GASES
5052 subroutine eqv_pot(theta_e, pt, delp, delz, peln, pkz, qi, is, ie, js, je, ng, npz, &
5053  hydrostatic, moist)
5054 #else
5055 subroutine eqv_pot(theta_e, pt, delp, delz, peln, pkz, q, is, ie, js, je, ng, npz, &
5056  hydrostatic, moist)
5057 #endif
5058  integer, intent(in):: is,ie,js,je,ng,npz
5059 #ifdef MULTI_GASES
5060  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,npz,*):: qi
5061 #endif
5062  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,npz):: pt, delp, q
5063  real, intent(in), dimension(is: ,js: ,1: ):: delz
5064  real, intent(in), dimension(is:ie,npz+1,js:je):: peln
5065  real, intent(in):: pkz(is:ie,js:je,npz)
5066  logical, intent(in):: hydrostatic, moist
5067 ! Output:
5068  real, dimension(is:ie,js:je,npz), intent(out) :: theta_e
5069 ! local
5070  real, parameter:: tice = 273.16
5071  real, parameter:: c_liq = 4190.
5072 #ifdef SIM_NGGPS
5073  real, parameter:: dc_vap = 0.
5074 #else
5075  real, parameter:: dc_vap = cp_vapor - c_liq
5076 #endif
5077  real(kind=R_GRID), dimension(is:ie):: pd, rq
5078  real(kind=R_GRID) :: wfac
5079  integer :: i,j,k
5080 
5081  if ( moist ) then
5082  wfac = 1.
5083  else
5084  wfac = 0.
5085  endif
5086 #ifdef MULLTI_GASES
5087  do j=js,je
5088  do i=is,ie
5089  do k=1,npz
5090  q(i,j,k) = qi(i,j,k,1)
5091  enddo
5092  enddo
5093  enddo
5094 #endif
5095 
5096 !$OMP parallel do default(none) shared(pk0,wfac,moist,pkz,is,ie,js,je,npz,pt,q,delp,peln,delz,theta_e,hydrostatic) &
5097 !$OMP private(pd, rq)
5098  do k = 1,npz
5099  do j = js,je
5100 
5101  if ( hydrostatic ) then
5102  do i=is,ie
5103  rq(i) = max(0., wfac*q(i,j,k))
5104  pd(i) = (1.-rq(i))*delp(i,j,k) / (peln(i,k+1,j) - peln(i,k,j))
5105  enddo
5106  else
5107 ! Dry pressure: p = r R T
5108  do i=is,ie
5109  rq(i) = max(0., wfac*q(i,j,k))
5110  pd(i) = -rdgas*pt(i,j,k)*(1.-rq(i))*delp(i,j,k)/(grav*delz(i,j,k))
5111  enddo
5112  endif
5113 
5114  if ( moist ) then
5115  do i=is,ie
5116  rq(i) = max(0., q(i,j,k))
5117 ! rh(i) = max(1.e-12, rq(i)/wqs1(pt(i,j,k),den(i))) ! relative humidity
5118 ! theta_e(i,j,k) = exp(rq(i)/cp_air*((hlv+dc_vap*(pt(i,j,k)-tice))/pt(i,j,k) - &
5119 ! rvgas*log(rh(i))) + kappa*log(1.e5/pd(i))) * pt(i,j,k)
5120 ! Simplified form: (ignoring the RH term)
5121 #ifdef SIM_NGGPS
5122 #ifdef MULTI_GASES
5123  theta_e(i,j,k) = pt(i,j,k)*exp(kappa * (virqd(qi(i,j,k,:))/vicpqd(qi(i,j,k,:)))*log(1.e5/pd(i))) * &
5124  exp(rq(i)*hlv/(cp_air*vicpqd(qi(i,j,k,:))*pt(i,j,k)))
5125 #else
5126  theta_e(i,j,k) = pt(i,j,k)*exp(kappa*log(1.e5/pd(i))) * &
5127  exp(rq(i)*hlv/(cp_air*pt(i,j,k)))
5128 #endif
5129 #else
5130 #ifdef MULTI_GASES
5131  theta_e(i,j,k) = pt(i,j,k)*exp( rq(i)/(cp_air*vicpqd(q(i,j,k,:))*pt(i,j,k))*(hlv+dc_vap*(pt(i,j,k)-tice)) &
5132  + rdgas*virqd(qi(i,j,k,:)) / (cp_air*vicpqd(qi(i,j,k,:)))*log(1.e5/pd(i)) )
5133 #else
5134  theta_e(i,j,k) = pt(i,j,k)*exp( rq(i)/(cp_air*pt(i,j,k))*(hlv+dc_vap*(pt(i,j,k)-tice)) &
5135  + kappa*log(1.e5/pd(i)) )
5136 #endif
5137 #endif
5138  enddo
5139  else
5140  if ( hydrostatic ) then
5141  do i=is,ie
5142  theta_e(i,j,k) = pt(i,j,k)*pk0/pkz(i,j,k)
5143  enddo
5144  else
5145  do i=is,ie
5146 ! theta_e(i,j,k) = pt(i,j,k)*(1.e5/pd(i))**kappa
5147 #ifdef MULTI_GASES
5148  theta_e(i,j,k) = pt(i,j,k)*exp( kappa * (virqd(qi(i,j,k,:))/vicpqd(qi(i,j,k,:)))*log(1.e5/pd(i)) )
5149 #else
5150  theta_e(i,j,k) = pt(i,j,k)*exp( kappa*log(1.e5/pd(i)) )
5151 #endif
5152  enddo
5153  endif
5154  endif
5155  enddo ! j-loop
5156  enddo ! k-loop
5157 
5158 end subroutine eqv_pot
5159 
5160 #else
5161 
5166 #ifdef MULTI_GASES
5167 subroutine eqv_pot(theta_e, pt, delp, delz, peln, pkz, qi, is, ie, js, je, ng, npz, &
5168 #else
5169 subroutine eqv_pot(theta_e, pt, delp, delz, peln, pkz, q, is, ie, js, je, ng, npz, &
5170 #endif
5171  hydrostatic, moist)
5172 ! calculate the equvalent potential temperature
5173 ! author: Xi.Chen@noaa.gov
5174 ! created on: 07/28/2015
5175 ! Modified by SJL
5176  integer, intent(in):: is,ie,js,je,ng,npz
5177 #ifdef MULTI_GASES
5178  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,npz,*):: qi
5179 #else
5180  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,npz):: q
5181 #endif
5182  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,npz):: pt, delp
5183  real, intent(in), dimension(is: ,js: ,1: ):: delz
5184  real, intent(in), dimension(is:ie,npz+1,js:je):: peln
5185  real, intent(in):: pkz(is:ie,js:je,npz)
5186  logical, intent(in):: hydrostatic, moist
5187 ! Output:
5188  real, dimension(is:ie,js:je,npz), intent(out) :: theta_e
5189 ! local
5190 #ifdef MULTI_GASES
5191  real, dimension(is-ng:ie+ng,js-ng:je+ng,npz):: q
5192 #endif
5193  real, parameter:: cv_vap = cp_vapor - rvgas ! 1384.5
5194  real, parameter:: cappa_b = 0.2854
5195  real(kind=R_GRID):: cv_air, cappa, zvir
5196  real(kind=R_GRID):: p_mb(is:ie)
5197  real(kind=R_GRID) :: r, e, t_l, rdg, capa
5198  integer :: i,j,k, n
5199 
5200 #ifdef MULTI_GASES
5201  q(:,:,:) = qi(:,:,:,1)
5202 #endif
5203  cv_air = cp_air - rdgas
5204  rdg = -rdgas/grav
5205  if ( moist ) then
5206  zvir = rvgas/rdgas - 1.
5207  else
5208  zvir = 0.
5209  endif
5210 
5211 !$OMP parallel do default(none) shared(moist,pk0,pkz,cv_air,zvir,rdg,is,ie,js,je,ng,npz, &
5212 #ifdef MULTI_GASES
5213 !$OMP qi,num_gas, &
5214 #endif
5215 !$OMP pt,q,delp,peln,delz,theta_e,hydrostatic) &
5216 !$OMP private(cappa,p_mb, r, e, t_l, capa)
5217  do k = 1,npz
5218  cappa = cappa_b
5219  do j = js,je
5220 ! get pressure in mb
5221  if ( hydrostatic ) then
5222  do i=is,ie
5223  p_mb(i) = 0.01*delp(i,j,k) / (peln(i,k+1,j) - peln(i,k,j))
5224  enddo
5225  else
5226  do i=is,ie
5227 #ifdef MULTI_GASES
5228  p_mb(i) = 0.01*rdg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k)*virq(qi(i,j,k,1:num_gas))
5229 #else
5230  p_mb(i) = 0.01*rdg*delp(i,j,k)/delz(i,j,k)*pt(i,j,k)*(1.+zvir*q(i,j,k))
5231 #endif
5232  enddo
5233  endif
5234  if ( moist ) then
5235  do i = is,ie
5236 #ifdef MULTI_GASES
5237  cappa = rdgas/(rdgas+((1.-q(i,j,k))*cv_air+q(i,j,k)*cv_vap)/virq(qi(i,j,k,1:num_gas)))
5238 #else
5239  cappa = rdgas/(rdgas+((1.-q(i,j,k))*cv_air+q(i,j,k)*cv_vap)/(1.+zvir*q(i,j,k)))
5240 #endif
5241 ! get "dry" mixing ratio of m_vapor/m_tot in g/kg
5242  r = q(i,j,k)/(1.-q(i,j,k))*1000.
5243  r = max(1.e-10, r)
5244 ! get water vapor pressure
5245  e = p_mb(i)*r/(622.+r)
5246 ! get temperature at the lifting condensation level
5247 ! eq. 21 of Bolton 1980
5248  t_l = 2840./(3.5*log(pt(i,j,k))-log(e)-4.805)+55.
5249 ! get the equivalent potential temperature
5250 ! theta_e(i,j,k) = pt(i,j,k)*exp( (cappa*(1.-0.28e-3*r)*log(1000./p_mb(i))) * &
5251 ! exp( (3.376/t_l-0.00254)*r*(1.+0.81e-3*r) )
5252  capa = cappa*(1. - r*0.28e-3)
5253  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
5254  enddo
5255  else
5256  if ( hydrostatic ) then
5257  do i = is,ie
5258  theta_e(i,j,k) = pt(i,j,k)*pk0/pkz(i,j,k)
5259  enddo
5260  else
5261  do i = is,ie
5262 #ifdef MULTI_GASES
5263  theta_e(i,j,k) = pt(i,j,k)*exp( kappa * virqd(qi(i,j,k,1:num_gas))/vicpqd(qi(i,j,k,1:num_gas)) *log(1000./p_mb(i)) )
5264 #else
5265  theta_e(i,j,k) = pt(i,j,k)*exp( kappa*log(1000./p_mb(i)) )
5266 #endif
5267  enddo
5268  endif
5269  endif
5270  enddo ! j-loop
5271  enddo ! k-loop
5272 
5273 end subroutine eqv_pot
5274 
5275 #endif
5276 
5279  subroutine nh_total_energy(is, ie, js, je, isd, ied, jsd, jed, km, &
5280  w, delz, pt, delp, q, hs, area, domain, &
5281  sphum, liq_wat, rainwat, ice_wat, &
5282  snowwat, graupel, nwat, ua, va, moist_phys, te)
5283 !------------------------------------------------------
5284 ! Compute vertically integrated total energy per column
5285 !------------------------------------------------------
5286 ! !INPUT PARAMETERS:
5287  integer, intent(in):: km, is, ie, js, je, isd, ied, jsd, jed
5288  integer, intent(in):: nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel
5289  real, intent(in), dimension(isd:ied,jsd:jed,km):: ua, va, pt, delp, w
5290  real, intent(in), dimension(is:ie,js:je,km) :: delz
5291  real, intent(in), dimension(isd:ied,jsd:jed,km,nwat):: q
5292  real, intent(in):: hs(isd:ied,jsd:jed)
5293  real, intent(in):: area(isd:ied, jsd:jed)
5294  logical, intent(in):: moist_phys
5295  type(domain2d), intent(INOUT) :: domain
5296  real, intent(out):: te(is:ie,js:je)
5297 ! Local
5298  real, parameter:: c_liq = 4190.
5299  real(kind=R_Grid) :: area_l(isd:ied, jsd:jed)
5300  real, parameter:: cv_vap = cp_vapor - rvgas
5301  real phiz(is:ie,km+1)
5302  real, dimension(is:ie):: cvm, qc
5303  real cv_air, psm
5304  integer i, j, k
5305 
5306  area_l = area
5307  cv_air = cp_air - rdgas
5308 
5309 !$OMP parallel do default(none) shared(te,nwat,is,ie,js,je,isd,ied,jsd,jed,km,ua,va, &
5310 #ifdef MULTI_GASES
5311 !$OMP num_gas, &
5312 #endif
5313 !$OMP w,q,pt,delp,delz,hs,cv_air,moist_phys,sphum,liq_wat,rainwat,ice_wat,snowwat,graupel) &
5314 !$OMP private(phiz,cvm, qc)
5315  do j=js,je
5316 
5317  do i=is,ie
5318  te(i,j) = 0.
5319  phiz(i,km+1) = hs(i,j)
5320  enddo
5321 
5322  do i=is,ie
5323  do k=km,1,-1
5324  phiz(i,k) = phiz(i,k+1) - grav*delz(i,j,k)
5325  enddo
5326  enddo
5327 
5328  if ( moist_phys ) then
5329  do k=1,km
5330  call moist_cv(is,ie,isd,ied,jsd,jed, km, j, k, nwat, sphum, liq_wat, rainwat, &
5331  ice_wat, snowwat, graupel, q, qc, cvm)
5332  do i=is,ie
5333  te(i,j) = te(i,j) + delp(i,j,k)*( cvm(i)*pt(i,j,k) + hlv*q(i,j,k,sphum) + &
5334  0.5*(phiz(i,k)+phiz(i,k+1)+ua(i,j,k)**2+va(i,j,k)**2+w(i,j,k)**2) )
5335  enddo
5336  enddo
5337  else
5338  do k=1,km
5339  do i=is,ie
5340 #ifdef MULTI_GASES
5341  te(i,j) = te(i,j) + delp(i,j,k)*( cv_air*vicvqd(q(i,j,k,1:num_gas))*pt(i,j,k) + &
5342  0.5*(phiz(i,k)+phiz(i,k+1)+ua(i,j,k)**2+va(i,j,k)**2+w(i,j,k)**2) )
5343 #else
5344  te(i,j) = te(i,j) + delp(i,j,k)*( cv_air*pt(i,j,k) + &
5345  0.5*(phiz(i,k)+phiz(i,k+1)+ua(i,j,k)**2+va(i,j,k)**2+w(i,j,k)**2) )
5346 #endif
5347  enddo
5348  enddo
5349  endif
5350 ! Unit: kg*(m/s)^2/m^2 = Joule/m^2
5351  do i=is,ie
5352  te(i,j) = te(i,j)/grav
5353  enddo
5354  enddo
5355 
5356  psm = g_sum(domain, te, is, ie, js, je, 3, area_l, 1)
5357  if( master ) write(*,*) 'TE ( Joule/m^2 * E9) =', psm * 1.e-9
5358 
5359  end subroutine nh_total_energy
5360 
5371  subroutine dbzcalc(q, pt, delp, peln, delz, &
5372  dbz, maxdbz, allmax, bd, npz, ncnst, &
5373  hydrostatic, zvir, in0r, in0s, in0g, iliqskin)
5375 ! Code from Mark Stoelinga's dbzcalc.f from the RIP package.
5376 ! Currently just using values taken directly from that code, which is
5377 ! consistent for the MM5 Reisner-2 microphysics. From that file:
5378 
5379 ! This routine computes equivalent reflectivity factor (in dBZ) at
5380 ! each model grid point. In calculating Ze, the RIP algorithm makes
5381 ! assumptions consistent with those made in an early version
5382 ! (ca. 1996) of the bulk mixed-phase microphysical scheme in the MM5
5383 ! model (i.e., the scheme known as "Resiner-2"). For each species:
5384 !
5385 ! 1. Particles are assumed to be spheres of constant density. The
5386 ! densities of rain drops, snow particles, and graupel particles are
5387 ! taken to be rho_r = rho_l = 1000 kg m^-3, rho_s = 100 kg m^-3, and
5388 ! rho_g = 400 kg m^-3, respectively. (l refers to the density of
5389 ! liquid water.)
5390 !
5391 ! 2. The size distribution (in terms of the actual diameter of the
5392 ! particles, rather than the melted diameter or the equivalent solid
5393 ! ice sphere diameter) is assumed to follow an exponential
5394 ! distribution of the form N(D) = N_0 * exp( lambda*D ).
5395 !
5396 ! 3. If in0X=0, the intercept parameter is assumed constant (as in
5397 ! early Reisner-2), with values of 8x10^6, 2x10^7, and 4x10^6 m^-4,
5398 ! for rain, snow, and graupel, respectively. Various choices of
5399 ! in0X are available (or can be added). Currently, in0X=1 gives the
5400 ! variable intercept for each species that is consistent with
5401 ! Thompson, Rasmussen, and Manning (2004, Monthly Weather Review,
5402 ! Vol. 132, No. 2, pp. 519-542.)
5403 !
5404 ! 4. If iliqskin=1, frozen particles that are at a temperature above
5405 ! freezing are assumed to scatter as a liquid particle.
5406 !
5407 ! More information on the derivation of simulated reflectivity in RIP
5408 ! can be found in Stoelinga (2005, unpublished write-up). Contact
5409 ! Mark Stoelinga (stoeling@atmos.washington.edu) for a copy.
5410 
5411 ! 22sep16: Modifying to use the GFDL MP parameters. If doing so remember
5412 ! that the GFDL MP assumes a constant intercept (in0X = .false.)
5413 ! Ferrier-Aligo has an option for fixed slope (rather than fixed intercept).
5414 ! Thompson presumably is an extension of Reisner MP.
5415 
5416  type(fv_grid_bounds_type), intent(IN) :: bd
5417  integer, intent(IN) :: npz, ncnst
5418  real, intent(IN), dimension(bd%isd:bd%ied, bd%jsd:bd%jed, npz) :: pt, delp
5419  real, intent(IN), dimension(bd%is:, bd%js:, 1:) :: delz
5420  real, intent(IN), dimension(bd%isd:bd%ied, bd%jsd:bd%jed, npz, ncnst) :: q
5421  real, intent(IN), dimension(bd%is :bd%ie, npz+1, bd%js:bd%je) :: peln
5422  real, intent(OUT), dimension(bd%is :bd%ie, bd%js :bd%je , npz) :: dbz
5423  real, intent(OUT), dimension(bd%is :bd%ie, bd%js :bd%je) :: maxdbz
5424  logical, intent(IN) :: hydrostatic, in0r, in0s, in0g, iliqskin
5425  real, intent(IN) :: zvir
5426  real, intent(OUT) :: allmax
5427 
5428  !Parameters for constant intercepts (in0[rsg] = .false.)
5429  !Using GFDL MP values
5430  real(kind=R_GRID), parameter:: vconr = 2503.23638966667
5431  real(kind=R_GRID), parameter:: vcong = 87.2382675
5432  real(kind=R_GRID), parameter:: vcons = 6.6280504
5433  real(kind=R_GRID), parameter:: normr = 25132741228.7183
5434  real(kind=R_GRID), parameter:: normg = 5026548245.74367
5435  real(kind=R_GRID), parameter:: norms = 942477796.076938
5436 
5437  !Constants for variable intercepts
5438  !Will need to be changed based on MP scheme
5439  real, parameter :: r1=1.e-15
5440  real, parameter :: ron=8.e6
5441  real, parameter :: ron2=1.e10
5442  real, parameter :: son=2.e7
5443  real, parameter :: gon=5.e7
5444  real, parameter :: ron_min = 8.e6
5445  real, parameter :: ron_qr0 = 0.00010
5446  real, parameter :: ron_delqr0 = 0.25*ron_qr0
5447  real, parameter :: ron_const1r = (ron2-ron_min)*0.5
5448  real, parameter :: ron_const2r = (ron2+ron_min)*0.5
5449  real, parameter :: rnzs = 3.0e6 ! lin83
5450 
5451  !Other constants
5452  real, parameter :: gamma_seven = 720.
5453  !The following values are also used in GFDL MP
5454  real, parameter :: rhor = 1.0e3 ! LFO83
5455  real, parameter :: rhos = 100. ! kg m^-3
5456  real, parameter :: rhog0 = 400. ! kg m^-3
5457  real, parameter :: rhog = 500. ! graupel-hail mix
5458 ! real, parameter :: rho_g = 900. ! hail/frozen rain
5459  real, parameter :: alpha = 0.224
5460  real(kind=R_GRID), parameter :: factor_s = gamma_seven * 1.e18 * (1./(pi*rhos))**1.75 &
5461  * (rhos/rhor)**2 * alpha
5462  real, parameter :: qmin = 1.e-12
5463  real, parameter :: tice = 273.16
5464 
5465 ! Double precision
5466  real(kind=R_GRID), dimension(bd%is:bd%ie) :: rhoair, denfac, z_e
5467  real(kind=R_GRID):: qr1, qs1, qg1, t1, t2, t3, rwat, vtr, vtg, vts
5468  real(kind=R_GRID):: factorb_s, factorb_g
5469  real(kind=R_GRID):: temp_c, pres, sonv, gonv, ronv
5470 
5471  integer :: i,j,k
5472  integer :: is, ie, js, je
5473 
5474  is = bd%is
5475  ie = bd%ie
5476  js = bd%js
5477  je = bd%je
5478  if (rainwat < 1) return
5479 
5480  dbz(:,:,1:mp_top) = -20.
5481  maxdbz(:,:) = -20. !Minimum value
5482  allmax = -20.
5483 
5484 
5485 !$OMP parallel do default(shared) private(rhoair,t1,t2,t3,denfac,vtr,vtg,vts,z_e)
5486  do k=mp_top+1, npz
5487  do j=js, je
5488  if (hydrostatic) then
5489  do i=is, ie
5490 #ifdef MULTI_GASES
5491  rhoair(i) = delp(i,j,k)/( (peln(i,k+1,j)-peln(i,k,j)) * rdgas * pt(i,j,k) * virq(q(i,j,k,1:num_gas)) )
5492 #else
5493  rhoair(i) = 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) ) )
5494 #endif
5495  denfac(i) = sqrt(min(10., 1.2/rhoair(i)))
5496  z_e(i) = 0.
5497  enddo
5498  else
5499  do i=is, ie
5500  rhoair(i) = -delp(i,j,k)/(grav*delz(i,j,k)) ! moist air density
5501  denfac(i) = sqrt(min(10., 1.2/rhoair(i)))
5502  z_e(i) = 0.
5503  enddo
5504  endif
5505  if (rainwat > 0) then
5506  do i=is, ie
5507 ! The following form vectorizes better & more consistent with GFDL_MP
5508 ! SJL notes: Marshall-Palmer, dBZ = 200*precip**1.6, precip = 3.6e6*t1/rhor*vtr ! [mm/hr]
5509 ! GFDL_MP terminal fall speeds are used
5510 ! Date modified 20170701
5511 ! Account for excessively high cloud water -> autoconvert (diag only) excess cloud water
5512  t1 = rhoair(i)*max(qmin, q(i,j,k,rainwat)+dim(q(i,j,k,liq_wat), 1.0e-3))
5513  vtr = max(1.e-3, vconr*denfac(i)*exp(0.2 *log(t1/normr)))
5514  z_e(i) = 200.*exp(1.6*log(3.6e6*t1/rhor*vtr))
5515  enddo
5516  endif
5517  if (graupel > 0) then
5518  do i=is, ie
5519  t3 = rhoair(i)*max(qmin, q(i,j,k,graupel))
5520  vtg = max(1.e-3, vcong*denfac(i)*exp(0.125 *log(t3/normg)))
5521  z_e(i) = z_e(i) + 200.*exp(1.6*log(3.6e6*t3/rhog*vtg))
5522  enddo
5523  endif
5524  if (snowwat > 0) then
5525  do i=is, ie
5526  t2 = rhoair(i)*max(qmin, q(i,j,k,snowwat))
5527  ! vts = max(1.e-3, vcons*denfac*exp(0.0625*log(t2/norms)))
5528  z_e(i) = z_e(i) + (factor_s/alpha)*t2*exp(0.75*log(t2/rnzs))
5529  enddo
5530  endif
5531  do i=is,ie
5532  dbz(i,j,k) = 10.*log10( max(0.01, z_e(i)) )
5533  enddo
5534  enddo
5535  enddo
5536 
5537 !$OMP parallel do default(shared)
5538  do j=js, je
5539  do k=mp_top+1, npz
5540  do i=is, ie
5541  maxdbz(i,j) = max(dbz(i,j,k), maxdbz(i,j))
5542  enddo
5543  enddo
5544  enddo
5545 
5546  do j=js, je
5547  do i=is, ie
5548  allmax = max(maxdbz(i,j), allmax)
5549  enddo
5550  enddo
5551 
5552  end subroutine dbzcalc
5553 !
5554  subroutine max_vorticity_hy1(is, ie, js, je, km, vort, maxvorthy1)
5555  integer, intent(in):: is, ie, js, je, km
5556  real, intent(in), dimension(is:ie,js:je,km):: vort
5557  real, intent(inout), dimension(is:ie,js:je):: maxvorthy1
5558  integer i, j, k
5559 
5560  do j=js,je
5561  do i=is,ie
5562  maxvorthy1(i,j)=max(maxvorthy1(i,j),vort(i,j,km))
5563  enddo ! i-loop
5564  enddo ! j-loop
5565  end subroutine max_vorticity_hy1
5566 !
5567 ! subroutine max_vorticity(is, ie, js, je, ng, km, zvir, sphum, delz, q, hydrostatic, &
5568 ! pt, peln, phis, grav, vort, maxvorthy1, maxvort, z_bot, z_top)
5569  subroutine max_vorticity(is, ie, js, je, ng, km, zvir, sphum, delz, q, hydrostatic, &
5570  pt, peln, phis, grav, vort, maxvort, z_bot, z_top)
5571  integer, intent(in):: is, ie, js, je, ng, km, sphum
5572  real, intent(in):: grav, zvir, z_bot, z_top
5573  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt
5574  real, intent(in), dimension(is:ie,js:je,km):: vort
5575  real, intent(in):: delz(is:ie,js:je,km)
5576  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
5577  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
5578  real, intent(in):: peln(is:ie,km+1,js:je)
5579  logical, intent(in):: hydrostatic
5580 ! real, intent(inout), dimension(is:ie,js:je):: maxvorthy1,maxvort
5581  real, intent(inout), dimension(is:ie,js:je):: maxvort
5582 
5583  real:: rdg
5584  real, dimension(is:ie):: zh, dz, zh0
5585  integer i, j, k,klevel
5586  logical below(is:ie)
5587 
5588  rdg = rdgas / grav
5589 
5590  do j=js,je
5591 
5592  do i=is,ie
5593  zh(i) = 0.
5594  below(i) = .true.
5595  zh0(i) = 0.
5596 
5597  k_loop:do k=km,1,-1
5598  if ( hydrostatic ) then
5599 #ifdef MULTI_GASES
5600  dz(i) = rdg*pt(i,j,k)*virq(q(i,j,k,1:num_gas))*(peln(i,k+1,j)-peln(i,k,j))
5601 #else
5602  dz(i) = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
5603 #endif
5604  else
5605  dz(i) = - delz(i,j,k)
5606  endif
5607  zh(i) = zh(i) + dz(i)
5608  if (zh(i) <= z_bot ) continue
5609  if (zh(i) > z_bot .and. below(i)) then
5610  maxvort(i,j) = max(maxvort(i,j),vort(i,j,k))
5611  below(i) = .false.
5612  elseif ( zh(i) < z_top ) then
5613  maxvort(i,j) = max(maxvort(i,j),vort(i,j,k))
5614  else
5615  maxvort(i,j) = max(maxvort(i,j),vort(i,j,k))
5616  EXIT k_loop
5617  endif
5618  enddo k_loop
5619 ! maxvorthy1(i,j)=max(maxvorthy1(i,j),vort(i,j,km))
5620  enddo ! i-loop
5621  enddo ! j-loop
5622 
5623 
5624  end subroutine max_vorticity
5625 
5626  subroutine max_uh(is, ie, js, je, ng, km, zvir, sphum, uphmax,uphmin, &
5627  w, vort, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
5628 ! !INPUT PARAMETERS:
5629  integer, intent(in):: is, ie, js, je, ng, km, sphum
5630  real, intent(in):: grav, zvir, z_bot, z_top
5631  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,km):: pt, w
5632  real, intent(in), dimension(is:ie,js:je,km):: vort
5633  real, intent(in):: delz(is:ie,js:je,km)
5634  real, intent(in):: q(is-ng:ie+ng,js-ng:je+ng,km,*)
5635  real, intent(in):: phis(is-ng:ie+ng,js-ng:je+ng)
5636  real, intent(in):: peln(is:ie,km+1,js:je)
5637  logical, intent(in):: hydrostatic
5638  real :: uh(is:ie,js:je) ! unit: (m/s)**2
5639  real, intent(inout), dimension(is:ie,js:je):: uphmax,uphmin
5640 ! Coded by S.-J. Lin for CONUS regional climate simulations
5641 ! Modified for UH by LMH
5642 !
5643  real:: rdg
5644  real, dimension(is:ie):: zh, dz, zh0
5645  integer i, j, k
5646  logical below(is:ie)
5647 
5648  rdg = rdgas / grav
5649  do j=js,je
5650 
5651  do i=is,ie
5652  zh(i) = 0.
5653  uh(i,j) = 0.
5654  below(i) = .true.
5655  zh0(i) = 0.
5656 
5657 ! if ( phis(i,j)/grav < 1.E3 ) then
5658  k_loop:do k=km,1,-1
5659  if ( hydrostatic ) then
5660 #ifdef MULTI_GASES
5661  dz(i) = rdg*pt(i,j,k)*virq(q(i,j,k,1:num_gas))*(peln(i,k+1,j)-peln(i,k,j))
5662 #else
5663  dz(i) = rdg*pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))*(peln(i,k+1,j)-peln(i,k,j))
5664 #endif
5665  else
5666  dz(i) = - delz(i,j,k)
5667  endif
5668  zh(i) = zh(i) + dz(i)
5669  if (zh(i) <= z_bot ) continue
5670  if (zh(i) > z_bot .and. below(i)) then
5671  if(w(i,j,k).lt.0)then
5672  uh(i,j) = 0.
5673  EXIT k_loop
5674  endif
5675  uh(i,j) = vort(i,j,k)*w(i,j,k)*(zh(i) - z_bot)
5676  below(i) = .false.
5677 ! Compute mean winds below z_top
5678  elseif ( zh(i) < z_top ) then
5679  if(w(i,j,k).lt.0)then
5680  uh(i,j) = 0.
5681  EXIT k_loop
5682  endif
5683  uh(i,j) = uh(i,j) + vort(i,j,k)*w(i,j,k)*dz(i)
5684  else
5685  if(w(i,j,k).lt.0)then
5686  uh(i,j) = 0.
5687  EXIT k_loop
5688  endif
5689  uh(i,j) = uh(i,j) + vort(i,j,k)*w(i,j,k)*(z_top - (zh(i)-dz(i)) )
5690  EXIT k_loop
5691  endif
5692  enddo k_loop
5693  if (uh(i,j) > uphmax(i,j)) then
5694  uphmax(i,j) = uh(i,j)
5695  elseif (uh(i,j) < uphmin(i,j)) then
5696  uphmin(i,j) = uh(i,j)
5697  endif
5698  enddo ! i-loop
5699  enddo ! j-loop
5700 
5701  end subroutine max_uh
5702  subroutine max_vv(is,ie,js,je,npz,ng,up2,dn2,pe,w)
5703 ! !INPUT PARAMETERS:
5704  integer, intent(in):: is, ie, js, je, ng, npz
5705  integer :: i,j,k
5706  real, intent(in), dimension(is-ng:ie+ng,js-ng:je+ng,npz):: w
5707  real, intent(in):: pe(is-1:ie+1,npz+1,js-1:je+1)
5708  real, intent(inout), dimension(is:ie,js:je):: up2,dn2
5709  do j=js,je
5710  do i=is,ie
5711  do k=3,npz
5712  if (pe(i,k,j) >= 100.e2) then
5713  up2(i,j) = max(up2(i,j),w(i,j,k))
5714  dn2(i,j) = min(dn2(i,j),w(i,j,k))
5715  endif
5716  enddo
5717  enddo
5718  enddo
5719  end subroutine max_vv
5720 
5721  subroutine fv_diag_init_gn(Atm)
5722  type(fv_atmos_type), intent(inout), target :: Atm
5723 
5724  if (atm%grid_Number > 1) then
5725  write(gn,"(A2,I1)") " g", atm%grid_number
5726  else
5727  gn = ""
5728  end if
5729 
5730  end subroutine fv_diag_init_gn
5731 
5740  subroutine getcape( nk , p , t , dz, q, the, cape , cin, source_in )
5741  implicit none
5742 
5743  integer, intent(in) :: nk
5744  real, dimension(nk), intent(in) :: p,t,dz,q,the
5745  real, intent(out) :: cape,cin
5746  integer, intent(IN), OPTIONAL :: source_in
5747 
5748 !-----------------------------------------------------------------------
5749 !
5750 ! getcape - a fortran90 subroutine to calculate Convective Available
5751 ! Potential Energy (CAPE) from a sounding.
5752 !
5753 ! Version 1.02 Last modified: 10 October 2008
5754 !
5755 ! Author: George H. Bryan
5756 ! Mesoscale and Microscale Meteorology Division
5757 ! National Center for Atmospheric Research
5758 ! Boulder, Colorado, USA
5759 ! gbryan@ucar.edu
5760 !
5761 ! Disclaimer: This code is made available WITHOUT WARRANTY.
5762 !
5763 ! References: Bolton (1980, MWR, p. 1046) (constants and definitions)
5764 ! Bryan and Fritsch (2004, MWR, p. 2421) (ice processes)
5765 !
5766 !-----------------------------------------------------------------------
5767 !
5768 ! Input: nk - number of levels in the sounding (integer)
5769 !
5770 ! p - one-dimensional array of pressure (Pa) (real)
5771 !
5772 ! t - one-dimensional array of temperature (K) (real)
5773 !
5774 ! dz - one-dimensional array of height thicknesses (m) (real)
5775 !
5776 ! q - one-dimensional array of specific humidity (kg/kg) (real)
5777 !
5778 ! source - source parcel:
5779 ! 1 = surface (default)
5780 ! 2 = most unstable (max theta-e)
5781 ! 3 = mixed-layer (specify ml_depth)
5782 !
5783 ! Output: cape - Convective Available Potential Energy (J/kg) (real)
5784 !
5785 ! cin - Convective Inhibition (J/kg) (real)
5786 !
5787 !-----------------------------------------------------------------------
5788 ! User options:
5789 
5790  real, parameter :: pinc = 10000.0
5791  ! (smaller number yields more accurate
5792  ! results,larger number makes code
5793  ! go faster)
5794 
5795 
5796  real, parameter :: ml_depth = 200.0
5798 
5799  integer, parameter :: adiabat = 1
5804 
5805 !-----------------------------------------------------------------------
5806 !ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
5807 !-----------------------------------------------------------------------
5808 ! No need to modify anything below here:
5809 !-----------------------------------------------------------------------
5810 
5811  integer :: source = 1
5812  logical :: doit,ice,cloud,not_converged
5813  integer :: k,kmin,n,nloop,i,orec
5814  real, dimension(nk) :: pi,th,thv,z,pt,pb,pc,pn,ptv
5815 
5816  real :: maxthe,parea,narea,lfc
5817  real :: th1,p1,t1,qv1,ql1,qi1,b1,pi1,thv1,qt,dp,frac
5818  real :: th2,p2,t2,qv2,ql2,qi2,b2,pi2,thv2
5819  real :: thlast,fliq,fice,tbar,qvbar,qlbar,qibar,lhv,lhs,lhf,rm,cpm
5820  real*8 :: avgth,avgqv
5821 
5822 !-----------------------------------------------------------------------
5823 
5824  real, parameter :: g = 9.81
5825  real, parameter :: p00 = 100000.0
5826  real, parameter :: cp = 1005.7
5827  real, parameter :: rd = 287.04
5828  real, parameter :: rv = 461.5
5829  real, parameter :: xlv = 2501000.0
5830  real, parameter :: xls = 2836017.0
5831  real, parameter :: t0 = 273.15
5832  real, parameter :: cpv = 1875.0
5833  real, parameter :: cpl = 4190.0
5834  real, parameter :: cpi = 2118.636
5835  real, parameter :: lv1 = xlv+(cpl-cpv)*t0
5836  real, parameter :: lv2 = cpl-cpv
5837  real, parameter :: ls1 = xls+(cpi-cpv)*t0
5838  real, parameter :: ls2 = cpi-cpv
5839 
5840  real, parameter :: rp00 = 1.0/p00
5841  real, parameter :: eps = rd/rv
5842  real, parameter :: reps = rv/rd
5843  real, parameter :: rddcp = rd/cp
5844  real, parameter :: cpdrd = cp/rd
5845  real, parameter :: cpdg = cp/g
5846 
5847  real, parameter :: converge = 0.1
5848 
5849  integer, parameter :: debug_level = 0
5850 
5851  if (present(source_in)) source = source_in
5852 
5853 !-----------------------------------------------------------------------
5854 
5855 !---- convert p,t to mks units; get pi,th,thv ----!
5856 
5857  do k=1,nk
5858  pi(k) = (p(k)*rp00)**rddcp
5859  th(k) = t(k)/pi(k)
5860  thv(k) = th(k)*(1.0+reps*q(k))/(1.0+q(k))
5861  enddo
5862 
5863 !---- get height using the hydrostatic equation ----!
5864 
5865  z(nk) = 0.5*dz(nk)
5866  do k=nk-1,1,-1
5867  z(k) = z(k+1) + 0.5*(dz(k+1)+dz(k))
5868  enddo
5869 
5870 !---- find source parcel ----!
5871 
5872  IF(source.eq.1)THEN
5873  ! use surface parcel
5874  kmin = nk
5875 
5876  ELSEIF(source.eq.2)THEN
5877  ! use most unstable parcel (max theta-e)
5878 
5879  IF(p(1).lt.50000.0)THEN
5880  ! first report is above 500 mb ... just use the first level reported
5881  kmin = nk
5882  maxthe = the(nk)
5883  ELSE
5884  ! find max thetae below 500 mb
5885  maxthe = 0.0
5886  do k=nk,1,-1
5887  if(p(k).ge.50000.0)then
5888  if( the(nk).gt.maxthe )then
5889  maxthe = the(nk)
5890  kmin = k
5891  endif
5892  endif
5893  enddo
5894  ENDIF
5895  if(debug_level.ge.100) print *,' kmin,maxthe = ',kmin,maxthe
5896 
5897 !!$ ELSEIF(source.eq.3)THEN
5898 !!$ ! use mixed layer
5899 !!$
5900 !!$ IF( dz(nk).gt.ml_depth )THEN
5901 !!$ ! the second level is above the mixed-layer depth: just use the
5902 !!$ ! lowest level
5903 !!$
5904 !!$ avgth = th(nk)
5905 !!$ avgqv = q(nk)
5906 !!$ kmin = nk
5907 !!$
5908 !!$ ELSEIF( z(1).lt.ml_depth )THEN
5909 !!$ ! the top-most level is within the mixed layer: just use the
5910 !!$ ! upper-most level (not
5911 !!$
5912 !!$ avgth = th(1)
5913 !!$ avgqv = q(1)
5914 !!$ kmin = 1
5915 !!$
5916 !!$ ELSE
5917 !!$ ! calculate the mixed-layer properties:
5918 !!$
5919 !!$ avgth = 0.0
5920 !!$ avgqv = 0.0
5921 !!$ k = nk-1
5922 !!$ if(debug_level.ge.100) print *,' ml_depth = ',ml_depth
5923 !!$ if(debug_level.ge.100) print *,' k,z,th,q:'
5924 !!$ if(debug_level.ge.100) print *,nk,z(nk),th(nk),q(nk)
5925 !!$
5926 !!$ do while( (z(k).le.ml_depth) .and. (k.ge.1) )
5927 !!$
5928 !!$ if(debug_level.ge.100) print *,k,z(k),th(k),q(k)
5929 !!$
5930 !!$ avgth = avgth + dz(k)*th(k)
5931 !!$ avgqv = avgqv + dz(k)*q(k)
5932 !!$
5933 !!$ k = k - 1
5934 !!$
5935 !!$ enddo
5936 !!$
5937 !!$ th2 = th(k+1)+(th(k)-th(k+1))*(ml_depth-z(k-1))/dz(k)
5938 !!$ qv2 = q(k+1)+( q(k)- q(k+1))*(ml_depth-z(k-1))/dz(k)
5939 !!$
5940 !!$ if(debug_level.ge.100) print *,999,ml_depth,th2,qv2
5941 !!$
5942 !!$ avgth = avgth + 0.5*(ml_depth-z(k-1))*(th2+th(k-1))
5943 !!$ avgqv = avgqv + 0.5*(ml_depth-z(k-1))*(qv2+q(k-1))
5944 !!$
5945 !!$ if(debug_level.ge.100) print *,k,z(k),th(k),q(k)
5946 !!$
5947 !!$ avgth = avgth/ml_depth
5948 !!$ avgqv = avgqv/ml_depth
5949 !!$
5950 !!$ kmin = nk
5951 !!$
5952 !!$ ENDIF
5953 !!$
5954 !!$ if(debug_level.ge.100) print *,avgth,avgqv
5955 
5956  ELSE
5957 
5958  print *
5959  print *,' Unknown value for source'
5960  print *
5961  print *,' source = ',source
5962  print *
5963  call mpp_error(fatal, " Unknown CAPE source")
5964 
5965  ENDIF
5966 
5967 !---- define parcel properties at initial location ----!
5968  narea = 0.0
5969 
5970  if( (source.eq.1).or.(source.eq.2) )then
5971  k = kmin
5972  th2 = th(kmin)
5973  pi2 = pi(kmin)
5974  p2 = p(kmin)
5975  t2 = t(kmin)
5976  thv2 = thv(kmin)
5977  qv2 = q(kmin)
5978  b2 = 0.0
5979  elseif( source.eq.3 )then
5980  k = kmin
5981  th2 = avgth
5982  qv2 = avgqv
5983  thv2 = th2*(1.0+reps*qv2)/(1.0+qv2)
5984  pi2 = pi(kmin)
5985  p2 = p(kmin)
5986  t2 = th2*pi2
5987  b2 = g*( thv2-thv(kmin) )/thv(kmin)
5988  endif
5989 
5990  ql2 = 0.0
5991  qi2 = 0.0
5992  qt = qv2
5993 
5994  cape = 0.0
5995  cin = 0.0
5996  lfc = 0.0
5997 
5998  doit = .true.
5999  cloud = .false.
6000  if(adiabat.eq.1.or.adiabat.eq.2)then
6001  ice = .false.
6002  else
6003  ice = .true.
6004  endif
6005 
6006 ! the = getthe(p2,t2,t2,qv2)
6007 ! if(debug_level.ge.100) print *,' the = ',the
6008 
6009 !---- begin ascent of parcel ----!
6010 
6011  if(debug_level.ge.100)then
6012  print *,' Start loop:'
6013  print *,' p2,th2,qv2 = ',p2,th2,qv2
6014  endif
6015 
6016  do while( doit .and. (k.gt.1) )
6017 
6018  k = k-1
6019  b1 = b2
6020 
6021  dp = p(k)-p(k-1)
6022 
6023  if( dp.lt.pinc )then
6024  nloop = 1
6025  else
6026  nloop = 1 + int( dp/pinc )
6027  dp = dp/float(nloop)
6028  endif
6029 
6030  do n=1,nloop
6031 
6032  p1 = p2
6033  t1 = t2
6034  pi1 = pi2
6035  th1 = th2
6036  qv1 = qv2
6037  ql1 = ql2
6038  qi1 = qi2
6039  thv1 = thv2
6040 
6041  p2 = p2 - dp
6042  pi2 = (p2*rp00)**rddcp
6043 
6044  thlast = th1
6045  i = 0
6046  not_converged = .true.
6047 
6048  do while( not_converged )
6049  i = i + 1
6050  t2 = thlast*pi2
6051  if(ice)then
6052  fliq = max(min((t2-233.15)/(273.15-233.15),1.0),0.0)
6053  fice = 1.0-fliq
6054  else
6055  fliq = 1.0
6056  fice = 0.0
6057  endif
6058  qv2 = min( qt , fliq*getqvs(p2,t2) + fice*getqvi(p2,t2) )
6059  qi2 = max( fice*(qt-qv2) , 0.0 )
6060  ql2 = max( qt-qv2-qi2 , 0.0 )
6061 
6062  tbar = 0.5*(t1+t2)
6063  qvbar = 0.5*(qv1+qv2)
6064  qlbar = 0.5*(ql1+ql2)
6065  qibar = 0.5*(qi1+qi2)
6066 
6067  lhv = lv1-lv2*tbar
6068  lhs = ls1-ls2*tbar
6069  lhf = lhs-lhv
6070 
6071  rm=rd+rv*qvbar
6072  cpm=cp+cpv*qvbar+cpl*qlbar+cpi*qibar
6073  th2=th1*exp( lhv*(ql2-ql1)/(cpm*tbar) &
6074  +lhs*(qi2-qi1)/(cpm*tbar) &
6075  +(rm/cpm-rd/cp)*alog(p2/p1) )
6076 
6077  if(i.gt.90) print *,i,th2,thlast,th2-thlast
6078  if(i.gt.100)then
6079  print *,' getcape() error: lack of convergence, stopping iteration'
6080  not_converged = .false.
6081  endif
6082  if( abs(th2-thlast).gt.converge )then
6083  thlast=thlast+0.3*(th2-thlast)
6084  else
6085  not_converged = .false.
6086  endif
6087  enddo
6088 
6089  ! Latest pressure increment is complete. Calculate some
6090  ! important stuff:
6091 
6092  if( ql2.ge.1.0e-10 ) cloud = .true.
6093 
6094  IF(adiabat.eq.1.or.adiabat.eq.3)THEN
6095  ! pseudoadiabat
6096  qt = qv2
6097  ql2 = 0.0
6098  qi2 = 0.0
6099  ELSEIF(adiabat.le.0.or.adiabat.ge.5)THEN
6100  print *
6101  print *,' Undefined adiabat'
6102  print *
6103  stop 10000
6104  ENDIF
6105 
6106  enddo
6107 
6108  thv2 = th2*(1.0+reps*qv2)/(1.0+qv2+ql2+qi2)
6109  b2 = g*( thv2-thv(k) )/thv(k)
6110 
6111 ! the = getthe(p2,t2,t2,qv2)
6112 
6113  ! Get contributions to CAPE and CIN:
6114 
6115  if( (b2.ge.0.0) .and. (b1.lt.0.0) )then
6116  ! first trip into positive area
6117  !ps = p(k-1)+(p(k)-p(k-1))*(0.0-b1)/(b2-b1)
6118  frac = b2/(b2-b1)
6119  parea = 0.5*b2*dz(k)*frac
6120  narea = narea-0.5*b1*dz(k)*(1.0-frac)
6121  if(debug_level.ge.200)then
6122  print *,' b1,b2 = ',b1,b2
6123  !print *,' p1,ps,p2 = ',p(k-1),ps,p(k)
6124  print *,' frac = ',frac
6125  print *,' parea = ',parea
6126  print *,' narea = ',narea
6127  endif
6128  cin = cin + narea
6129  narea = 0.0
6130  elseif( (b2.lt.0.0) .and. (b1.gt.0.0) )then
6131  ! first trip into neg area
6132  !ps = p(k-1)+(p(k)-p(k-1))*(0.0-b1)/(b2-b1)
6133  frac = b1/(b1-b2)
6134  parea = 0.5*b1*dz(k)*frac
6135  narea = -0.5*b2*dz(k)*(1.0-frac)
6136  if(debug_level.ge.200)then
6137  print *,' b1,b2 = ',b1,b2
6138  !print *,' p1,ps,p2 = ',p(k-1),ps,p(k)
6139  print *,' frac = ',frac
6140  print *,' parea = ',parea
6141  print *,' narea = ',narea
6142  endif
6143  elseif( b2.lt.0.0 )then
6144  ! still collecting negative buoyancy
6145  parea = 0.0
6146  narea = narea-0.5*dz(k)*(b1+b2)
6147  else
6148  ! still collecting positive buoyancy
6149  parea = 0.5*dz(k)*(b1+b2)
6150  narea = 0.0
6151  endif
6152 
6153  cape = cape + max(0.0,parea)
6154 
6155  if(debug_level.ge.200)then
6156  write(6,102) p2,b1,b2,cape,cin,cloud
6157 102 format(5(f13.4),2x,l1)
6158  endif
6159 
6160  if( (p(k).le.10000.0).and.(b2.lt.0.0) )then
6161  ! stop if b < 0 and p < 100 mb
6162  doit = .false.
6163  endif
6164 
6165  enddo
6166 
6167 !---- All done ----!
6168 
6169  return
6170  end subroutine getcape
6171 
6172 !!$ subroutine divg_diagnostics(divg, ..., idiag, bd, npz,gridstruct%area_64, domain, fv_time))
6173 !!$ real, INPUT(IN) :: divg(bd%isd:bd%ied,bd%jsd:bd%jed,npz)
6174 !!$ ....
6175 !!$
6176 !!$ if (idiag%id_divg>0) then
6177 !!$ used = send_data(idiag%id_divg, divg, fv_time)
6178 !!$
6179 !!$ endif
6180 !!$
6181 !!$
6182 !!$ if(flagstruct%fv_debug) call prt_mxm('divg', dp1, is, ie, js, je, 0, npz, 1.,gridstruct%area_64, domain)
6183 !!$ end subroutine divg_diagnostics
6184 !!$
6185 !-----------------------------------------------------------------------
6186 !ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
6187 !-----------------------------------------------------------------------
6188 
6189  real function getqvs(p,t)
6190  implicit none
6191 
6192  real :: p,t,es
6193 
6194  real, parameter :: eps = 287.04/461.5
6195 
6196  es = 611.2*exp(17.67*(t-273.15)/(t-29.65))
6197  getqvs = eps*es/(p-es)
6198 
6199  return
6200  end function getqvs
6201 !-----------------------------------------------------------------------
6202 
6203 
6204  real function getqvi(p,t)
6205  implicit none
6206 
6207  real :: p,t,es
6208 
6209  real, parameter :: eps = 287.04/461.5
6210 
6211  es = 611.2*exp(21.8745584*(t-273.15)/(t-7.66))
6212  getqvi = eps*es/(p-es)
6213 
6214  return
6215  end function getqvi
6216 !-----------------------------------------------------------------------
6217 
6218  subroutine debug_column(pt, delp, delz, u, v, w, q, npz, ncnst, sphum, nwat, hydrostatic, bd, Time)
6220  type(fv_grid_bounds_type), intent(IN) :: bd
6221  integer, intent(IN) :: npz, ncnst, sphum, nwat
6222  logical, intent(IN) :: hydrostatic
6223  real, dimension(bd%isd:bd%ied,bd%jsd:bd%jed,npz), intent(IN) :: pt, delp, w
6224  real, dimension(bd%is:, bd%js:,1:), intent(IN) :: delz
6225  real, dimension(bd%isd:bd%ied,bd%jsd:bd%jed+1,npz), intent(IN) :: u
6226  real, dimension(bd%isd:bd%ied+1,bd%jsd:bd%jed,npz), intent(IN) :: v
6227  real, dimension(bd%isd:bd%ied, bd%jsd:bd%jed, npz, ncnst), intent(IN) :: q
6228 
6229 
6230  type(time_type), intent(IN) :: Time
6231  integer :: i,j,k,n,l
6232  real cond
6233 
6234  do n=1,size(diag_debug_i)
6235 
6236  i=diag_debug_i(n)
6237  j=diag_debug_j(n)
6238 
6239  if (i < bd%is .or. i > bd%ie) cycle
6240  if (j < bd%js .or. j > bd%je) cycle
6241 
6242  if (do_debug_diag_column(i,j)) then
6243  call column_diagnostics_header(diag_debug_names(n), diag_debug_units(n), time, n, &
6245 
6246  write(diag_debug_units(n),'(A4, A7, A8, A6, A8, A8, A8, A8, A9)') 'k', 'T', 'delp', 'delz', 'u', 'v', 'w', 'sphum', 'cond'
6247  write(diag_debug_units(n),'(A4, A7, A8, A6, A8, A8, A8, A8, A9)') '', 'K', 'mb', 'm', 'm/s', 'm/s', 'm/s', 'g/kg', 'g/kg'
6248  if (hydrostatic) then
6249  call mpp_error(note, 'Hydrostatic debug sounding not yet supported')
6250  else
6251  do k=2*npz/3,npz
6252  cond = 0.
6253  do l=2,nwat
6254  cond = cond + q(i,j,k,l)
6255  enddo
6256  write(diag_debug_units(n),'(I4, F7.2, F8.3, I6, F8.3, F8.3, F8.3, F8.3, F9.5 )') &
6257  k, pt(i,j,k), delp(i,j,k)*0.01, -int(delz(i,j,k)), u(i,j,k), v(i,j,k), w(i,j,k), &
6258  q(i,j,k,sphum)*1000., cond*1000.
6259  enddo
6260  endif
6261 
6262  !call mpp_flush(diag_units(n))
6263 
6264  endif
6265 
6266  enddo
6267 
6268  end subroutine debug_column
6269 
6270  subroutine sounding_column( pt, delp, delz, u, v, q, peln, pkz, phis, &
6271  npz, ncnst, sphum, nwat, hydrostatic, moist_phys, zvir, ng, bd, Time )
6273  type(fv_grid_bounds_type), intent(IN) :: bd
6274  integer, intent(IN) :: npz, ncnst, sphum, nwat, ng
6275  real, intent(IN) :: zvir
6276  logical, intent(IN) :: hydrostatic, moist_phys
6277  real, dimension(bd%isd:bd%ied,bd%jsd:bd%jed,npz), intent(IN) :: pt, delp
6278  real, dimension(bd%is:, bd%js:, 1:), intent(IN) :: delz
6279  real, dimension(bd%isd:bd%ied,bd%jsd:bd%jed+1,npz), intent(IN) :: u
6280  real, dimension(bd%isd:bd%ied+1,bd%jsd:bd%jed,npz), intent(IN) :: v
6281  real, dimension(bd%isd:bd%ied, bd%jsd:bd%jed, npz, ncnst), intent(IN) :: q
6282  real, dimension(bd%is:bd%ie,npz+1,bd%js:bd%je), intent(in):: peln
6283  real, dimension(bd%is:bd%ie,bd%js:bd%je,npz), intent(in):: pkz
6284  real, dimension(bd%isd:bd%ied,bd%jsd:bd%jed), intent(IN) :: phis
6285  type(time_type), intent(IN) :: Time
6286 
6287  real :: Tv, pres, hght(npz), dewpt, rh, mixr, tmp, qs(1), wspd, wdir, rpk, theta, thetav
6288  real :: thetae(bd%is:bd%ie,bd%js:bd%je,npz)
6289 
6290  real, PARAMETER :: rgrav = 1./grav
6291  real, PARAMETER :: rdg = -rdgas*rgrav
6292  real, PARAMETER :: sounding_top = 10.e2
6293  real, PARAMETER :: ms_to_knot = 1.9438445
6294  real, PARAMETER :: p0 = 1000.e2
6295 
6296  integer :: i, j, k, n
6297  integer :: yr_v, mo_v, dy_v, hr_v, mn_v, sec_v ! need to get numbers for these
6298 
6299  if (.not. any(do_sonde_diag_column)) return
6300  call get_date(time, yr_v, mo_v, dy_v, hr_v, mn_v, sec_v)
6301  call eqv_pot(thetae, pt, delp, delz, peln, pkz, q(bd%isd,bd%jsd,1,sphum), &
6302  bd%is, bd%ie, bd%js, bd%je, ng, npz, hydrostatic, moist_phys)
6303 
6304  do n=1,size(diag_sonde_i)
6305 
6306  i=diag_sonde_i(n)
6307  j=diag_sonde_j(n)
6308 
6309  if (i < bd%is .or. i > bd%ie) cycle
6310  if (j < bd%js .or. j > bd%je) cycle
6311 
6312  if (do_sonde_diag_column(i,j)) then
6313  !call column_diagnostics_header(diag_sonde_names(n), diag_sonde_units(n), Time, n, &
6314  ! diag_sonde_lon, diag_sonde_lat, diag_sonde_i, diag_sonde_j)
6315 
6316  write(diag_sonde_units(n),600) &
6317  trim(diag_sonde_names(n)), yr_v, mo_v, dy_v, hr_v, yr_init, mo_init, dy_init, hr_init, trim(runname)
6318 600 format(a,'.v', i4, i2.2, i2.2, i2.2, '.i', i4, i2.2, i2.2, i2.2, '.', a, '.dat########################################################')
6319  write(diag_sonde_units(n),601) trim(diag_sonde_names(n)), yr_v, mo_v, dy_v, hr_v, yr_init, mo_init, dy_init, hr_init, &
6320  trim(runname), diag_sonde_lon(n), diag_sonde_lat(n)
6321 601 format(3x, a16, ' Valid ', i4, i2.2, i2.2, '.', i2.2, 'Z Init ', i4, i2.2, i2.2, '.', i2.2, 'Z \n', a, 2f8.3)
6322  write(diag_sonde_units(n),*)
6323  write(diag_sonde_units(n),*) '-------------------------------------------------------------------------------'
6324  write(diag_sonde_units(n),'(11A7)') 'PRES', 'HGHT', "TEMP", "DWPT", "RELH", "MIXR", "DRCT", "SKNT", "THTA", "THTE", "THTV"
6325  write(diag_sonde_units(n),'(11A7)') 'hPa', 'm', 'C', 'C', '%', 'g/kg', 'deg', 'knot', 'K', 'K', 'K'
6326  write(diag_sonde_units(n),*) '-------------------------------------------------------------------------------'
6327 
6328  if (hydrostatic) then
6329  call mpp_error(note, 'Hydrostatic diagnostic sounding not yet supported')
6330  else
6331  hght(npz) = phis(i,j)*rgrav - 0.5*delz(i,j,npz)
6332  do k=npz-1,1,-1
6333  hght(k) = hght(k+1) - 0.5*(delz(i,j,k)+delz(i,j,k+1))
6334  enddo
6335 
6336  do k=npz,1,-1
6337 
6338 #ifdef MULTI_GASES
6339  tv = pt(i,j,k)*virq(q(i,j,k,1:num_gas))
6340 #else
6341  tv = pt(i,j,k)*(1.+zvir*q(i,j,k,sphum))
6342 #endif
6343  pres = delp(i,j,k)/delz(i,j,k)*rdg*tv
6344  !if (pres < sounding_top) cycle
6345 
6346 #ifdef MULTI_GASES
6347  call qsmith((bd%ie-bd%is+1)*(bd%je-bd%js+1), npz, &
6348  1, 1, pt(i,j,k:k), &
6349  (/pres/), q(i,j,k:k,sphum), qs)
6350 #else
6351  call qsmith(1, 1, 1, pt(i,j,k:k), &
6352  (/pres/), q(i,j,k:k,sphum), qs)
6353 #endif
6354 
6355  mixr = q(i,j,k,sphum)/(1.-sum(q(i,j,k,1:nwat))) ! convert from sphum to mixing ratio
6356  rh = q(i,j,k,sphum)/qs(1)
6357  tmp = ( log(max(rh,1.e-2))/ 17.27 + ( pt(i,j,k) - 273.14 )/ ( -35.84 + pt(i,j,k)) )
6358  dewpt = 237.3* tmp/ ( 1. - tmp ) ! deg C
6359  wspd = 0.5*sqrt((u(i,j,k)+u(i,j+1,k))*(u(i,j,k)+u(i,j+1,k)) + (v(i,j,k)+v(i+1,j,k))*(v(i,j,k)+v(i+1,j,k)))*ms_to_knot ! convert to knots
6360  if (wspd > 0.01) then
6361  !https://www.eol.ucar.edu/content/wind-direction-quick-reference
6362  wdir = atan2(u(i,j,k)+u(i,j+1,k),v(i,j,k)+v(i+1,j,k)) * rad2deg
6363  else
6364  wdir = 0.
6365  endif
6366  rpk = exp(-kappa*log(pres/p0))
6367  theta = pt(i,j,k)*rpk
6368  thetav = tv*rpk
6369 
6370  write(diag_sonde_units(n),'(F7.1, I7, F7.1, F7.1, I7, F7.2, I7, F7.2, F7.1, F7.1, F7.1)') &
6371  pres*1.e-2, int(hght(k)), pt(i,j,k)-tfreeze, dewpt, int(rh*100.), mixr*1.e3, int(wdir), wspd, theta, thetae(i,j,k), thetav
6372  enddo
6373  endif
6374 
6375  !call mpp_flush(diag_units(n))
6376 
6377  endif
6378 
6379  enddo
6380 
6381 
6382  end subroutine sounding_column
6383 
6384 
6385 end module fv_diagnostics_mod
real, dimension(max_diag_column) diag_debug_lat_in
character(100) runname
character(len=256) tlongname
subroutine, public prt_height(qname, is, ie, js, je, ng, km, press, phis, delz, peln, area, lat)
integer, parameter nplev
pure real function, public vicpqd(q)
real, parameter missing_value3
for variables where we look for smallest values
real, dimension(:), allocatable diag_debug_lat
subroutine cs_prof(q2, delp, q, km, i1, i2, iv)
The module &#39;fv_mp_mod&#39; is a single program multiple data (SPMD) parallel decompostion/communication m...
Definition: fv_mp_mod.F90:24
subroutine, public max_uh(is, ie, js, je, ng, km, zvir, sphum, uphmax, uphmin, w, vort, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
The type &#39;fv_grid_type&#39; is made up of grid-dependent information from fv_grid_tools and fv_grid_utils...
Definition: fv_arrays.F90:123
real, dimension(2) rhrange
real, parameter missing_value2
for variables with many missing values
real, dimension(max_diag_column) diag_debug_lon_in
real, dimension(:,:), allocatable, public zs_g
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)
The subroutine &#39;moist_cv&#39; computes the FV3-consistent moist heat capacity under constant volume...
Definition: fv_mapz.F90:3418
real, public sphum_ll_fix
integer, public num_gas
Definition: multi_gases.F90:46
real, dimension(2) vrange
subroutine getcape(nk, p, t, dz, q, the, cape, cin, source_in)
The subroutine &#39;getcape&#39; calculates the Convective Available Potential Energy (CAPE) from a Sounding...
The module &#39;multi_gases&#39; peforms multi constitutents computations.
Definition: multi_gases.F90:25
subroutine, public a2b_ord2(qin, qout, gridstruct, npx, npy, is, ie, js, je, ng, replace)
Definition: a2b_edge.F90:698
subroutine, public eqv_pot(theta_e, pt, delp, delz, peln, pkz, q, is, ie, js, je, ng, npz, hydrostatic, moist)
The subroutine &#39;eqv_pot&#39; calculates the equivalent potential temperature.
subroutine, public get_eta_level(npz, p_s, pf, ph, ak, bk, pscale)
The subroutine &#39;get_eta_level&#39; returns the interface and layer-mean pressures for reference...
Definition: fv_eta.F90:1833
real, dimension(2) skrange
logical, dimension(:,:), allocatable do_sonde_diag_column
real, dimension(2) trange
real, parameter missing_value
subroutine get_height_given_pressure(is, ie, js, je, km, wz, kd, id, log_p, peln, a2)
real function, public g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
The function &#39;g_sum&#39; is the fast version of &#39;globalsum&#39;.
integer, parameter max_step
Definition: fv_arrays.F90:42
subroutine wind_max(isc, iec, jsc, jec, isd, ied, jsd, jed, us, vs, ws_max, domain)
integer, dimension(:), allocatable diag_debug_i
character(16), dimension(max_diag_column) diag_sonde_names
real, dimension(2) wrange
subroutine get_pressure_given_height(is, ie, js, je, ng, km, wz, kd, height, ts, peln, a2, fac)
integer, parameter, public r_grid
Definition: fv_arrays.F90:34
character(len=256) tunits
subroutine, public gw_1d(km, p0, ak, bk, ptop, ztop, pt1)
Definition: fv_eta.F90:2260
logical, dimension(:,:), allocatable do_debug_diag_column
The module &#39;fv_sg&#39; performs FV sub-grid mixing.
Definition: fv_sg.F90:54
subroutine, public bunkers_vector(is, ie, js, je, ng, km, zvir, sphum, uc, vc, ua, va, delz, q, hydrostatic, pt, peln, phis, grav)
subroutine, public fv_diag_init_gn(Atm)
pure real function, public virqd(q)
real, dimension(max_diag_column) diag_sonde_lon_in
subroutine, public prt_mxm(qname, q, is, ie, js, je, n_g, km, fac, area, domain)
subroutine, public max_vorticity_hy1(is, ie, js, je, km, vort, maxvorthy1)
real, dimension(:), allocatable diag_sonde_lon
pure real function, public virq(q)
subroutine range_check_2d(qname, q, is, ie, js, je, n_g, pos, q_low, q_hi, bad_range, Time)
subroutine interpolate_z(is, ie, js, je, km, zl, hght, a3, a2)
The module &#39;a2b_edge&#39; performs FV-consistent interpolation of pressure to corners.
Definition: a2b_edge.F90:24
subroutine, public z_sum(is, ie, js, je, km, n_g, delp, q, sum2)
subroutine, public fv_diag_init(Atm, axes, Time, npx, npy, npz, p_ref)
subroutine cs_interpolator(is, ie, js, je, km, qin, zout, wz, qout, qmin)
subroutine cs3_interpolator(is, ie, js, je, km, qin, kd, pout, wz, pe, id, qout, iv)
subroutine, public ppme(p, qe, delp, im, km)
subroutine init_mq(phis, gridstruct, npx, npy, is, ie, js, je, ng)
The module &#39;fv_mapz&#39; contains the vertical mapping routines .
Definition: fv_mapz.F90:27
subroutine, public qsmith(im, km, k1, t, p, q, qs, dqdt)
Definition: fv_sg.F90:1392
logical, public prt_minmax
The module &#39;fv_arrays&#39; contains the &#39;fv_atmos_type&#39; and associated datatypes.
Definition: fv_arrays.F90:24
integer, dimension(:), allocatable diag_sonde_i
subroutine, public get_height_field(is, ie, js, je, ng, km, hydrostatic, delz, wz, pt, q, peln, zvir)
The module &#39;fv_eta&#39; contains routine to set up the reference (Eulerian) pressure coordinate.
Definition: fv_eta.F90:25
real, parameter rad2deg
subroutine debug_column(pt, delp, delz, u, v, w, q, npz, ncnst, sphum, nwat, hydrostatic, bd, Time)
subroutine, public fv_diag(Atm, zvir, Time, print_freq)
real, dimension(:), allocatable diag_sonde_lat
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)
subroutine pv_entropy(is, ie, js, je, ng, km, vort, f_d, pt, pkz, delp, grav)
The subroutine &#39;pv_entropy&#39; computes potential vorticity.
subroutine, public moist_cp(is, ie, isd, ied, jsd, jed, km, j, k, nwat, sphum, liq_wat, rainwat, ice_wat, snowwat, graupel, q, qd, cpm, t1)
The subroutine &#39;moist_cp&#39; computes the FV3-consistent moist heat capacity under constant pressure...
Definition: fv_mapz.F90:3539
type(time_type), public fv_time
real function getqvi(p, t)
real function getqvs(p, t)
integer, dimension(:), allocatable diag_sonde_units
integer, dimension(nplev) levs
subroutine, public dbzcalc(q, pt, delp, peln, delz, dbz, maxdbz, allmax, bd, npz, ncnst, hydrostatic, zvir, in0r, in0s, in0g, iliqskin)
The subroutine &#39;dbzcalc&#39; computes equivalent reflectivity factor (in dBZ) at each model grid point...
@ The module &#39;fv_diagnostics&#39; contains routines to compute diagnosic fields.
The module &#39;fv_grid_utils&#39; contains routines for setting up and computing grid-related quantities...
character(len=3), public gn
subroutine, public prt_gb_nh_sh(qname, is, ie, js, je, a2, area, lat)
subroutine, public prt_maxmin(qname, q, is, ie, js, je, n_g, km, fac)
real, dimension(2) vsrange
subroutine, public helicity_relative_caps(is, ie, js, je, ng, km, zvir, sphum, srh, uc, vc, ua, va, delz, q, hydrostatic, pt, peln, phis, grav, z_bot, z_top)
subroutine, public rh_calc(pfull, t, qv, rh, do_cmip)
subroutine sounding_column(pt, delp, delz, u, v, q, peln, pkz, phis, npz, ncnst, sphum, nwat, hydrostatic, moist_phys, zvir, ng, bd, Time)
character(16), dimension(max_diag_column) diag_debug_names
subroutine, public max_vorticity(is, ie, js, je, ng, km, zvir, sphum, delz, q, hydrostatic, pt, peln, phis, grav, vort, maxvort, z_bot, z_top)
subroutine, public a2b_ord4(qin, qout, gridstruct, npx, npy, is, ie, js, je, ng, replace)
Definition: a2b_edge.F90:70
subroutine range_check_3d(qname, q, is, ie, js, je, n_g, km, pos, q_low, q_hi, bad_range, Time)
real, dimension(max_diag_column) diag_sonde_lat_in
real function p_sum(is, ie, js, je, km, n_g, delp, area, domain)
integer, parameter max_diag_column
type(fv_diag_type), pointer idiag
subroutine, public interpolate_vertical(is, ie, js, je, km, plev, peln, a3, a2)
real(kind=4), public e_flux
Definition: fv_mapz.F90:124
integer, dimension(:), allocatable diag_debug_units
real, dimension(:), allocatable diag_debug_lon
subroutine, public prt_mass(km, nq, is, ie, js, je, n_g, nwat, ps, delp, q, area, domain)
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)
The subroutine &#39;nh_total_energy computes vertically-integrated total energy per column.
subroutine, public max_vv(is, ie, js, je, npz, ng, up2, dn2, pe, w)
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)
real, dimension(2) slprange
integer, dimension(:), allocatable diag_debug_j
pure real function, public vicvqd(q)
integer, dimension(:), allocatable diag_sonde_j
character(len=128) tname
subroutine, public get_vorticity(isc, iec, jsc, jec, isd, ied, jsd, jed, npz, u, v, vort, dx, dy, rarea)