1 subroutine da_transfer_xatowrf(grid)
3 !---------------------------------------------------------------------------
4 ! Purpose: Convert analysis increments into WRF increments
5 ! Updated for Analysis on Arakawa-C grid
6 ! Author: Syed RH Rizvi, MMM/ESSL/NCAR, Date: 10/22/2008
8 ! The following WRF fields are modified:
18 ! grid%t2, grid%q2, grid%u10, grid%v10, grid%th2
20 !---------------------------------------------------------------------------
24 type(domain), intent(inout) :: grid
30 ! arrays to hold wrf increments on the c-grid
33 real, dimension(ims:ime,jms:jme, kms:kme) :: q_cgrid, ph_cgrid
35 real, dimension(ims:ime,jms:jme, kms:kme) :: &
36 u_cgrid, v_cgrid, q_cgrid, ph_cgrid
39 real, dimension(ims:ime,jms:jme) :: mu_cgrid
41 real :: t_full , p_full, rho_dry, q_full, ph_full , ph_xb_hd, &
42 qvf1, qvf2, qvf1_b, qvf2_b
44 real :: uu, vv, ps1, ps2, ts1, ts2, qv1, qv2, height
46 if (trace_use) call da_trace_entry("da_transfer_xatowrf")
48 ! To keep the background PH perturbation:
53 ph_cgrid(i,j,k) = grid%ph_2(i,j,k)
58 !---------------------------------------------------------------------------
59 ! [1.0] Get the mixing ratio of moisture first, as it its easy.
60 !---------------------------------------------------------------------------
65 if ((grid%xb%q(i,j,k)+grid%xa%q(i,j,k)) < 0.0) then
66 q_cgrid(i,j,k) =-grid%xb%q(i,j,k)/(1.0 - grid%xb%q(i,j,k))**2
68 q_cgrid(i,j,k) = grid%xa%q(i,j,k)/(1.0 - grid%xb%q(i,j,k))**2
74 !---------------------------------------------------------------------------
75 ! [2.0] compute increments of dry-column air mass per unit area
76 !---------------------------------------------------------------------------
83 sdmd=sdmd+q_cgrid(i,j,k)*grid%dnw(k)
84 s1md=s1md+(1.0+grid%moist(i,j,k,P_QV))*grid%dnw(k)
87 mu_cgrid(i,j)=-(grid%xa%psfc(i,j)+grid%xb%psac(i,j)*sdmd)/s1md
91 !---------------------------------------------------------------------------
92 ! [3.0] compute pressure increments
93 !---------------------------------------------------------------------------
95 ! Tangent linear code for grid%xa%p (based on WRF "real.init.code")
96 ! developed by Y.-R. Guo 05/13/2004:
101 qvf1 = 0.5*(q_cgrid(i,j,k)+q_cgrid(i,j,k))
102 qvf1_b = 0.5*(grid%moist(i,j,k,P_QV)+grid%moist(i,j,k,P_QV))
103 qvf2 = - qvf1 / ((1.0+qvf1_b)*(1.0+qvf1_b))
104 qvf2_b = 1.0/(1.0+qvf1_b)
105 qvf1 = qvf1*qvf2_b + qvf1_b*qvf2
106 qvf1_b = qvf1_b*qvf2_b
107 grid%xa%p(i,j,k) = (-0.5/grid%rdnw(k)) * &
108 ((mu_cgrid(i,j)+qvf1*grid%mub(i,j)) / qvf2_b &
109 -(grid%mu_2(i,j)+qvf1_b*grid%mub(i,j))*qvf2/(qvf2_b*qvf2_b))
112 qvf1 = 0.5*(q_cgrid(i,j,k)+q_cgrid(i,j,k+1))
113 qvf1_b = 0.5*(grid%moist(i,j,k,P_QV)+grid%moist(i,j,k+1,P_QV))
114 qvf2 = - qvf1 / ((1.0+qvf1_b)*(1.0+qvf1_b))
115 qvf2_b = 1.0/(1.0+qvf1_b)
116 qvf1 = qvf1*qvf2_b + qvf1_b*qvf2
117 qvf1_b = qvf1_b*qvf2_b
118 grid%xa%p(i,j,k) = grid%xa%p(i,j,k+1) &
119 - (1.0/grid%rdn(k+1)) * &
120 ((mu_cgrid(i,j)+qvf1*grid%mub(i,j)) / qvf2_b &
121 -(grid%mu_2(i,j)+qvf1_b*grid%mub(i,j))*qvf2/(qvf2_b*qvf2_b))
126 ! update perturbation pressure
131 grid%p(i,j,k) = grid%p(i,j,k) + grid%xa%p(i,j,k)
136 ! Adjust grid%xa%q to makte grid%xb%q + grid%xa%q > 0.0
138 if (check_rh == check_rh_tpw) then
139 ! Shu-Hua~s TPW conservation:
140 call da_check_rh(grid)
141 else if (check_rh == check_rh_simple) then
142 ! Simple resetting to max/min values:
143 call da_check_rh_simple(grid)
149 q_cgrid(i,j,k) = grid%xa%q(i,j,k)/(1.0 - grid%xb%q(i,j,k))**2
154 !---------------------------------------------------------------------------
155 ! [4.0] Convert temperature increments into theta increments
156 ! Evaluate also the increments of (1/rho) and geopotential
157 !---------------------------------------------------------------------------
159 if (print_detail_xa) then
160 write(unit=stdout, fmt='(a, e24.12)') &
161 'sum(abs(grid%xa%t(its:ite,jts:jte,kts:kte)))=', &
162 sum(abs(grid%xa%t(its:ite,jts:jte,kts:kte))), &
163 'sum(abs(grid%xa%p(its:ite,jts:jte,kts:kte)))=', &
164 sum(abs(grid%xa%p(its:ite,jts:jte,kts:kte))), &
165 'sum(abs(grid%xb%t(its:ite,jts:jte,kts:kte)))=', &
166 sum(abs(grid%xb%t(its:ite,jts:jte,kts:kte))), &
167 'sum(abs(grid%xb%p(its:ite,jts:jte,kts:kte)))=', &
168 sum(abs(grid%xb%p(its:ite,jts:jte,kts:kte))), &
169 'sum(abs(grid%t_2 (its:ite,jts:jte,kts:kte)))=', &
170 sum(abs(grid%t_2 (its:ite,jts:jte,kts:kte)))
172 write(unit=stdout, fmt='(2(2x, a, e20.12))') &
173 'maxval(grid%xa%u(its:ite,jts:jte,kts:kte))=', &
174 maxval(grid%xa%u(its:ite,jts:jte,kts:kte)), &
175 'minval(grid%xa%u(its:ite,jts:jte,kts:kte))=', &
176 minval(grid%xa%u(its:ite,jts:jte,kts:kte)), &
177 'maxval(grid%xa%v(its:ite,jts:jte,kts:kte))=', &
178 maxval(grid%xa%v(its:ite,jts:jte,kts:kte)), &
179 'minval(grid%xa%v(its:ite,jts:jte,kts:kte))=', &
180 minval(grid%xa%v(its:ite,jts:jte,kts:kte)), &
181 'maxval(grid%xa%t(its:ite,jts:jte,kts:kte))=', &
182 maxval(grid%xa%t(its:ite,jts:jte,kts:kte)), &
183 'minval(grid%xa%t(its:ite,jts:jte,kts:kte))=', &
184 minval(grid%xa%t(its:ite,jts:jte,kts:kte)), &
185 'maxval(grid%xa%q(its:ite,jts:jte,kts:kte))=', &
186 maxval(grid%xa%q(its:ite,jts:jte,kts:kte)), &
187 'minval(grid%xa%q(its:ite,jts:jte,kts:kte))=', &
188 minval(grid%xa%q(its:ite,jts:jte,kts:kte)), &
189 'maxval(grid%xa%p(its:ite,jts:jte,kts:kte))=', &
190 maxval(grid%xa%p(its:ite,jts:jte,kts:kte)), &
191 'minval(grid%xa%p(its:ite,jts:jte,kts:kte))=', &
192 minval(grid%xa%p(its:ite,jts:jte,kts:kte)), &
193 'maxval(grid%xa%psfc(its:ite,jts:jte)) =', &
194 maxval(grid%xa%psfc(its:ite,jts:jte)), &
195 'minval(grid%xa%psfc(its:ite,jts:jte)) =', &
196 minval(grid%xa%psfc(its:ite,jts:jte))
202 ph_full = grid%ht(i,j) * gravity
203 ph_xb_hd = grid%ht(i,j) * gravity
205 ! To obtain all of the full fitelds: t, p, q(mixing ratio), rho
206 t_full = grid%xa%t(i,j,k) + grid%xb%t(i,j,k)
207 p_full = grid%xa%p(i,j,k) + grid%xb%p(i,j,k)
208 q_full = grid%moist(i,j,k,P_QV) + q_cgrid(i,j,k)
210 ! Note: According to WRF, this is the dry air density used to
211 ! compute the geopotential height:
212 rho_dry = p_full / (gas_constant*t_full*(1.0+q_full/rd_over_rv))
214 ! To compute the theta increment with the full fitelds:
215 grid%t_2(i,j,k) = t_full*(base_pres/p_full)**kappa - t0
217 ! The full fiteld of analysis ph:
219 - grid%xb%dnw(k) * (grid%xb%psac(i,j)+mu_cgrid(i,j)) / rho_dry
221 ! background hydrostatic phi:
222 ph_xb_hd = ph_xb_hd &
223 - grid%xb%dnw(k) * grid%xb%psac(i,j) / grid%xb%rho(i,j,k)
225 ! The analysis perturbation = Hydro_ph - base_ph + nonhydro_xb_ph:
226 grid%ph_2(i,j,k+1) = ph_full - grid%phb(i,j,k+1) &
227 + (grid%xb%hf(i,j,k+1)*gravity - ph_xb_hd)
232 ! To compute the geopotential height increment:
237 ph_cgrid(i,j,k) = grid%ph_2(i,j,k) - ph_cgrid(i,j,k)
243 ! ========================
244 ! Write out the increment:
245 ! ========================
247 if (write_increments) then
248 write(unit=stdout,fmt='(/"Write out increment for plotting......")')
249 call da_write_increments (grid, q_cgrid, mu_cgrid, ph_cgrid)
254 !TBH: NOTE that grid%xp%halo_id3 = HALO_PSICHI_UV_ADJ which its currently defined
255 !TBH: in the Regitstry as "dyn_em 24:grid%xa%u,grid%xa%v,grid%xa%psfc". Clearly it its not
256 !TBH: necessary to update halos in grid%xa%psfc here!
259 if ((fg_format==fg_format_wrf_arw_regional .or. &
260 fg_format==fg_format_wrf_arw_global ) .and. ide == ipe ) then
265 if ((fg_format==fg_format_wrf_arw_regional .or. &
266 fg_format==fg_format_wrf_arw_global ) .and. jde == jpe ) then
271 ! CONVERT FROM A-GRID TO C-GRID
274 !TBH: NOTE that grid%xp%halo_id3 = HALO_PSICHI_UV_ADJ which its currently defined
275 !TBH: in the Regitstry as "dyn_em 24:grid%xa%u,grid%xa%v,grid%xa%psfc". Clearly it its not
276 !TBH: necessary to update halos in grid%xa%psfc here! Also, 24-point stencil its
277 !TBH: too thick, 9-point should suffice. Apparently, grid%xp%halo_id3 its used
278 !TBH: in many places! Thits needs to be fixed.
282 #include "HALO_PSICHI_UV_ADJ.inc"
286 if ((fg_format==fg_format_wrf_arw_regional .or. &
287 fg_format==fg_format_wrf_arw_global ) .and. ide == ipe ) then
292 if ((fg_format==fg_format_wrf_arw_regional .or. &
293 fg_format==fg_format_wrf_arw_global ) .and. jde == jpe ) then
300 ! The southern boundary
302 grid%xa%v(its:ite,jts-1,kts:kte)=2.0*grid%xa%v(its:ite,jts ,kts:kte) &
303 - grid%xa%v(its:ite,jts+1,kts:kte)
306 ! The northern boundary
308 grid%xa%v(its:ite,jte+1,kts:kte)=2.0*grid%xa%v(its:ite,jte ,kts:kte) &
309 - grid%xa%v(its:ite,jte-1,kts:kte)
312 ! The western boundary
314 grid%xa%u(its-1,jts:jte,kts:kte)=2.0*grid%xa%u(its ,jts:jte,kts:kte) &
315 - grid%xa%u(its+1,jts:jte,kts:kte)
318 ! The eastern boundary
320 grid%xa%u(ite+1,jts:jte,kts:kte)=2.0*grid%xa%u(ite ,jts:jte,kts:kte) &
321 - grid%xa%u(ite-1,jts:jte,kts:kte)
327 u_cgrid(i,j,k)=0.5*(grid%xa%u(i-1,j ,k)+grid%xa%u(i,j,k))
328 v_cgrid(i,j,k)=0.5*(grid%xa%v(i ,j-1,k)+grid%xa%v(i,j,k))
333 !------------------------------------------------------------------------
334 ! For later plot and comparation Purpose only, zero out the unused var.
335 !------------------------------------------------------------------------
337 ! The northern boundary
339 u_cgrid(its:ite+1,jte+1,kts:kte)=0.0
342 ! The eastern boundary
344 v_cgrid(ite+1,jts:jte+1,kts:kte)=0.0
347 !---------------------------------------------------------------------------
348 ! [5.0] add increment to the original guess and update "grid"
349 !---------------------------------------------------------------------------
353 grid%mu_2(i,j) = grid%mu_2(i,j) + mu_cgrid(i,j)
354 grid%w_2(i,j,kte+1)= grid%w_2(i,j,kte+1) + grid%xa%w(i,j,kte+1)
355 grid%psfc(i,j) = grid%psfc(i,j) + grid%xa%psfc(i,j)
361 grid%u_2(i,j,k) = grid%u_2(i,j,k) + u_cgrid(i,j,k)
362 grid%v_2(i,j,k) = grid%v_2(i,j,k) + v_cgrid(i,j,k)
364 grid%w_2(i,j,k) = grid%w_2(i,j,k) + grid%xa%w(i,j,k)
365 grid%moist(i,j,k,P_QV) = grid%moist(i,j,k,P_QV) + q_cgrid(i,j,k)
367 if (size(grid%moist,dim=4) >= 4) then
368 grid%moist(i,j,k,p_qc) = grid%moist(i,j,k,p_qc) + grid%xa%qcw(i,j,k)
369 grid%moist(i,j,k,p_qr) = grid%moist(i,j,k,p_qr) + grid%xa%qrn(i,j,k)
370 if (grid%moist(i,j,k,p_qc) < 0.0) grid%moist(i,j,k,p_qc) = 0.0
371 if (grid%moist(i,j,k,p_qr) < 0.0) grid%moist(i,j,k,p_qr) = 0.0
374 if (size(grid%moist,dim=4) >= 6) then
375 grid%moist(i,j,k,p_qi) = grid%moist(i,j,k,p_qi) + grid%xa%qci(i,j,k)
376 grid%moist(i,j,k,p_qs) = grid%moist(i,j,k,p_qs) + grid%xa%qsn(i,j,k)
377 if (grid%moist(i,j,k,p_qi) < 0.0) grid%moist(i,j,k,p_qi) = 0.0
378 if (grid%moist(i,j,k,p_qs) < 0.0) grid%moist(i,j,k,p_qs) = 0.0
381 if (size(grid%moist,dim=4) >= 7) then
382 grid%moist(i,j,k,p_qg) = grid%moist(i,j,k,p_qg) + grid%xa%qgr(i,j,k)
383 if (grid%moist(i,j,k,p_qg) < 0.0) grid%moist(i,j,k,p_qg) = 0.0
393 grid%u_2(i,j,k) = grid%u_2(i,j,k) + grid%xa%u(i,j,k)
401 grid%v_2(i,j,k) = grid%v_2(i,j,k) + grid%xa%v(i,j,k)
406 ! The northern boundary
411 grid%v_2(i,j,k) = grid%v_2(i,j,k) + v_cgrid(i,j,k)
416 ! The eastern boundary
421 grid%u_2(i,j,k) = grid%u_2(i,j,k) + u_cgrid(i,j,k)
428 #include "HALO_EM_C.inc"
430 ! re-calculate T2, Q2, U10, V10, TH2 using updated fields
434 uu = 0.5*(grid%u_2(i,j,kts)+grid%u_2(i+1,j,kts) )
435 vv = 0.5*(grid%v_2(i,j,kts)+grid%v_2(i,j+1,kts) )
436 ps1 = grid%p(i,j,kts) + grid%pb(i,j,kts)
437 ps2 = grid%p(i,j,kts+1) + grid%pb(i,j,kts+1)
438 ts1 = (t0+grid%t_2(i,j,kts))*(ps1/base_pres)**kappa
439 ts2 = (t0+grid%t_2(i,j,kts+1))*(ps2/base_pres)**kappa
440 qv1 = grid%moist(i,j,kts, p_qv)/(1.0+grid%moist(i,j,kts,p_qv))
441 qv2 = grid%moist(i,j,kts+1, p_qv)/(1.0+grid%moist(i,j,kts+1,p_qv))
442 height = 0.5*(grid%phb(i,j,kts)+grid%ph_2(i,j,kts)+ &
443 grid%phb(i,j,kts+1)+grid%ph_2(i,j,kts+1))/gravity
444 height = height - grid%ht(i,j)
445 if (height <= 0.0) then
446 message(1) = "Negative height found"
447 write (unit=message(2),FMT='(2I6,A,F10.2,A,F10.2)') &
448 i,j,' ht = ',height ,' terr = ',grid%ht(i,j)
449 call da_error(__FILE__,__LINE__, message(1:2))
451 call da_sfc_wtq(grid%psfc(i,j), grid%tsk(i,j), &
452 ps1, ts1, qv1, uu, vv, &
454 height, grid%xb%rough(i,j),grid%xb%xland(i,j), &
455 grid%u10(i,j), grid%v10(i,j), grid%t2(i,j), &
456 grid%q2(i,j), grid%xb%regime(i,j))
457 grid%th2(i,j) = grid%t2(i,j)*(base_pres/ps1)**kappa
461 if (print_detail_xa) then
462 write(unit=stdout, fmt=*) 'simple variables:'
465 write (unit=stdout,fmt=*) ' '
469 write(unit=stdout, fmt=*) &
470 ' grid%u_2(', ide+1, ',', j, ',', k, ')=', &
473 write(unit=stdout, fmt=*) ' '
478 write(unit=stdout, fmt=*) ' '
482 write(unit=stdout, fmt=*) &
483 ' grid%v_2(', i, ',', jde+1, ',', k, ')=', &
486 write(unit=stdout, fmt=*) ' '
491 write(unit=stdout, fmt='(2(2x, a, e20.12))') &
492 'maxval(mu_cgrid(its:ite,jts:jte)) =', &
493 maxval(mu_cgrid(its:ite,jts:jte)), &
494 'minval(mu_cgrid(its:ite,jts:jte)) =', &
495 minval(mu_cgrid(its:ite,jts:jte)), &
496 'maxval(q_cgrid(its:ite,jts:jte,kts:kte)) =', &
497 maxval(q_cgrid(its:ite,jts:jte,kts:kte)), &
498 'minval(q_cgrid(its:ite,jts:jte,kts:kte)) =', &
499 minval(q_cgrid(its:ite,jts:jte,kts:kte))
501 write(unit=stdout, fmt='(2(2x, a, e20.12))') &
502 'maxval(mu_cgrid(its:ite,jts:jte)) =', &
503 maxval(mu_cgrid(its:ite,jts:jte)), &
504 'minval(mu_cgrid(its:ite,jts:jte)) =', &
505 minval(mu_cgrid(its:ite,jts:jte)), &
506 'maxval(u_cgrid(its:ite,jts:jte,kts:kte)) =', &
507 maxval(u_cgrid(its:ite,jts:jte,kts:kte)), &
508 'minval(u_cgrid(its:ite,jts:jte,kts:kte)) =', &
509 minval(u_cgrid(its:ite,jts:jte,kts:kte)), &
510 'maxval(v_cgrid(its:ite,jts:jte,kts:kte)) =', &
511 maxval(v_cgrid(its:ite,jts:jte,kts:kte)), &
512 'minval(v_cgrid(its:ite,jts:jte,kts:kte)) =', &
513 minval(v_cgrid(its:ite,jts:jte,kts:kte)), &
514 'maxval(q_cgrid(its:ite,jts:jte,kts:kte)) =', &
515 maxval(q_cgrid(its:ite,jts:jte,kts:kte)), &
516 'minval(q_cgrid(its:ite,jts:jte,kts:kte)) =', &
517 minval(q_cgrid(its:ite,jts:jte,kts:kte))
521 write(unit=stdout, fmt='(a, i3)') 'k=', k
524 write(unit=stdout, fmt='(2(2x, a, e20.12))') &
525 'maxval(q_cgrid(its:ite,jts:jte,k)) =', maxval(q_cgrid(its:ite,jts:jte,k)), &
526 'minval(q_cgrid(its:ite,jts:jte,k)) =', minval(q_cgrid(its:ite,jts:jte,k))
528 write(unit=stdout, fmt='(2(2x, a, e20.12))') &
529 'maxval(u_cgrid(its:ite,jts:jte,k)) =', maxval(u_cgrid(its:ite,jts:jte,k)), &
530 'minval(u_cgrid(its:ite,jts:jte,k)) =', minval(u_cgrid(its:ite,jts:jte,k)), &
531 'maxval(v_cgrid(its:ite,jts:jte,k)) =', maxval(v_cgrid(its:ite,jts:jte,k)), &
532 'minval(v_cgrid(its:ite,jts:jte,k)) =', minval(v_cgrid(its:ite,jts:jte,k)), &
533 'maxval(q_cgrid(its:ite,jts:jte,k)) =', maxval(q_cgrid(its:ite,jts:jte,k)), &
534 'minval(q_cgrid(its:ite,jts:jte,k)) =', minval(q_cgrid(its:ite,jts:jte,k))
539 if (trace_use) call da_trace_exit("da_transfer_xatowrf")
541 end subroutine da_transfer_xatowrf