1 subroutine da_psichi_to_uv(psi, chi, coefx,coefy, u, v)
3 !---------------------------------------------------------------------------
4 ! Purpose: Calculate wind components u and v from psi and chi.
6 ! Method: u = coefx * (-dpsi/dy + dchi/dx)
7 ! v = coefy * ( dpsi/dx + dchi/dy)
9 ! Assumptions: Unstaggered grid.
10 ! Lateral boundary conditions - dpsi/dn, dchi/dn = 0 (FCT)
11 ! grid size may or may not be equal
13 ! Updated for Analysis on Arakawa-C grid
14 ! Author: Syed RH Rizvi, MMM/ESSL/NCAR, Date: 10/22/2008
15 !----------------------------------------------------------------------------
19 real, intent(inout) :: psi(ims:ime,jms:jme,kms:kme) ! Stream function
20 real, intent(inout) :: chi(ims:ime,jms:jme,kms:kme) ! Velocity potential
21 real, intent(in) :: coefx(ims:ime,jms:jme) ! Multiplicative coeff.
22 real, intent(in) :: coefy(ims:ime,jms:jme) ! Multiplicative coeff.
23 real, intent(out) :: u(ims:ime,jms:jme,kms:kme) ! u wind comp.
24 real, intent(out) :: v(ims:ime,jms:jme,kms:kme) ! v wind comp.
27 integer :: i, j, k ! Loop counters.
28 integer :: is, ie ! 1st dim. end points.
29 integer :: js, je ! 2nd dim. end points.
31 real :: psi1, psi2, chi1, chi2
34 if (trace_use) call da_trace_entry("da_psichi_to_uv")
36 !---------------------------------------------------------------------------
37 ! [1.0] For Global application, set Wast-Eest Periodic boundary
38 !---------------------------------------------------------------------------
40 ! Computation to check for edge of domain:
45 if (jts == jds) js = jds+1
46 if (jte == jde) je = jde-1
49 if (fg_format == fg_format_kma_global) then
53 call da_set_boundary_3d(psi)
54 call da_set_boundary_3d(chi)
56 if (its == ids) is = ids+1
57 if (ite == ide) ie = ide-1
62 !$OMP PRIVATE (i, j, k)
64 !------------------------------------------------------------------------
65 ! [2.0] Compute u, v at interior points (2nd order central finite diffs):
66 !------------------------------------------------------------------------
70 if ((fg_format==fg_format_wrf_arw_regional) .or. &
71 (fg_format==fg_format_wrf_arw_global ) ) then
72 psi1 = 0.5*(psi(i,j+1,k) + psi(i-1,j+1,k))
73 psi2 = 0.5*(psi(i,j-1,k) + psi(i-1,j-1,k))
74 chi1 = 2.0*(chi(i,j,k) - chi(i-1,j,k))
75 u(i,j,k) = coefy(i,j)*(psi2 - psi1 ) + coefx(i,j)*chi1
77 psi1 = 0.5*(psi(i+1,j-1,k) + psi(i+1,j,k))
78 psi2 = 0.5*(psi(i-1,j-1,k) + psi(i-1,j,k))
79 chi1 = 2.0*(chi(i,j,k) - chi(i,j-1,k))
80 v(i,j,k) = coefx(i,j)*(psi1 - psi2 ) + coefy(i,j)*chi1
82 else if (fg_format == fg_format_kma_global) then
84 u(i,j,k) = -coefy(i,j)*(psi(i ,j+1,k) - psi(i ,j-1,k)) + &
85 coefx(i,j)*(chi(i+1,j ,k) - chi(i-1,j ,k))
87 v(i,j,k) = coefx(i,j)*(psi(i+1,j ,k) - psi(i-1,j ,k)) + &
88 coefy(i,j)*(chi(i ,j+1,k) - chi(i ,j-1,k))
91 write(unit=message(1),fmt='(A,I5)') &
92 "Wrong choice for fg_format = ",fg_format
93 call da_error(__FILE__,__LINE__,message(1:1))
100 if (fg_format == fg_format_kma_global) cycle
104 !------------------------------------------------------------------------
105 ! [3.0] Compute u, v at domain boundaries:
106 !------------------------------------------------------------------------
108 ! [3.1] Western boundaries:
114 if ((fg_format==fg_format_wrf_arw_regional) .or. &
115 (fg_format==fg_format_wrf_arw_global ) ) then
116 u(i,j,k) = 2.0*u(i+1,j,k) - u(i+2,j,k)
117 v(i,j,k) = 2.0*v(i+1,j,k) - v(i+2,j,k)
119 else if (fg_format == fg_format_kma_global) then
121 u(i,j,k) = -coefy(i,j)*(psi(i ,j+1,k) - psi(i,j-1,k)) + &
122 coefx(i,j)*(chi(i+2,j ,k) - chi(i,j ,k))
124 v(i,j,k) = coefx(i,j)*(psi(i+2,j ,k) - psi(i,j ,k)) + &
125 coefy(i,j)*(chi(i ,j+1,k) - chi(i,j-1,k))
128 write(unit=message(1),fmt='(A,I5)') &
129 "Wrong choice for fg_format = ",fg_format
130 call da_error(__FILE__,__LINE__,message(1:1))
136 ! [3.2] Eastern boundaries:
142 if ((fg_format==fg_format_wrf_arw_regional) .or. &
143 (fg_format==fg_format_wrf_arw_global ) ) then
144 u(i,j,k) = 2.0*u(i-1,j,k) - u(i-2,j,k)
145 v(i,j,k) = 2.0*v(i-1,j,k) - v(i-2,j,k)
146 else if (fg_format == fg_format_kma_global) then
148 u(i,j,k) = -coefy(i,j)*(psi(i,j+1,k) - psi(i ,j-1,k)) + &
149 coefx(i,j)*(chi(i,j ,k) - chi(i-2,j ,k))
151 v(i,j,k) = coefx(i,j)*(psi(i,j ,k) - psi(i-2,j ,k))+ &
152 coefy(i,j)*(chi(i,j+1,k) - chi(i ,j-1,k))
155 write(unit=message(1),fmt='(A,I5)') &
156 "Wrong choice for fg_format = ",fg_format
157 call da_error(__FILE__,__LINE__,message(1:1))
163 ! [3.3] Southern boundaries:
169 if ((fg_format==fg_format_wrf_arw_regional) .or. &
170 (fg_format==fg_format_wrf_arw_global ) ) then
171 u(i,j,k) = 2.0*u(i,j+1,k) - u(i,j+2,k)
172 v(i,j,k) = 2.0*v(i,j+1,k) - v(i,j+2,k)
173 else if (fg_format == fg_format_kma_global) then
175 u(i,j,k) = -coefy(i,j)*(psi(i ,j+2,k) - psi(i ,j,k)) + &
176 coefx(i,j)*(chi(i+1,j ,k) - chi(i-1,j,k))
178 v(i,j,k) = coefx(i,j)*(psi(i+1,j ,k) - psi(i-1,j,k)) + &
179 coefy(i,j)*(chi(i ,j+2,k) - chi(i ,j,k))
182 write(unit=message(1),fmt='(A,I5)') &
183 "Wrong choice for fg_format = ",fg_format
184 call da_error(__FILE__,__LINE__,message(1:1))
190 ! [3.4] Northern boundaries:
196 if ((fg_format==fg_format_wrf_arw_regional) .or. &
197 (fg_format==fg_format_wrf_arw_global ) ) then
198 u(i,j,k) = 2.0*u(i,j-1,k) - u(i,j-2,k)
199 v(i,j,k) = 2.0*v(i,j-1,k) - v(i,j-2,k)
200 else if (fg_format == fg_format_kma_global) then
202 u(i,j,k) = -coefy(i,j)*(psi(i ,j,k) - psi(i ,j-2,k)) + &
203 coefx(i,j)*(chi(i+1,j,k) - chi(i-1,j ,k))
205 v(i,j,k) = coefx(i,j)*(psi(i+1,j,k) - psi(i-1,j ,k))+ &
206 coefy(i,j)*(chi(i ,j,k) - chi(i ,j-2,k))
209 write(unit=message(1),fmt='(A,I5)') &
210 "Wrong choice for fg_format = ",fg_format
211 call da_error(__FILE__,__LINE__,message(1:1))
217 !------------------------------------------------------------------------
218 ! [4.0] Corner points (assume average of surrounding points - poor?):
219 !------------------------------------------------------------------------
221 ! [4.1] Bottom-left point:
223 if (its == ids .AND. jts == jds) then
224 u(its,jts,k) = 0.5 * (u(its+1,jts,k) + u(its,jts+1,k))
225 v(its,jts,k) = 0.5 * (v(its+1,jts,k) + v(its,jts+1,k))
228 ! [4.2] Top-left point:
231 if (its == ids .AND. jte == jde) then
232 u(its,jte,k) = 0.5 * (u(its+1,jte,k) + u(its,jte-1,k))
233 v(its,jte,k) = 0.5 * (v(its+1,jte,k) + v(its,jte-1,k))
236 if (ite == ide .AND. jts == jds) then
237 u(ite,jts,k) = 0.5 * (u(ite-1,jts,k) + u(ite,jts+1,k))
238 v(ite,jts,k) = 0.5 * (v(ite-1,jts,k) + v(ite,jts+1,k))
242 ! [4.3] Bottom-right point:
245 if (ite == ide .AND. jts == jds) then
246 u(ite,jts,k) = 0.5 * (u(ite-1,jts,k) + u(ite,jts+1,k))
247 v(ite,jts,k) = 0.5 * (v(ite-1,jts,k) + v(ite,jts+1,k))
250 if (its == ids .AND. jte == jde) then
251 u(its,jte,k) = 0.5 * (u(its+1,jte,k) + u(its,jte-1,k))
252 v(its,jte,k) = 0.5 * (v(its+1,jte,k) + v(its,jte-1,k))
256 ! [4.4] Top-right point:
258 if (ite == ide .AND. jte == jde) then
259 u(ite,jte,k) = 0.5 * (u(ite-1,jte,k) + u(ite,jte-1,k))
260 v(ite,jte,k) = 0.5 * (v(ite-1,jte,k) + v(ite,jte-1,k))
263 !$OMP END PARALLEL DO
265 !---------------------------------------------------------------------------
266 ! [5.0] For Global application, set Wast-Eest Periodic boundary
267 !---------------------------------------------------------------------------
270 if (fg_format == fg_format_kma_global) then
274 call da_set_boundary_3d(u)
275 call da_set_boundary_3d(v)
278 if (trace_use) call da_trace_exit("da_psichi_to_uv")
280 end subroutine da_psichi_to_uv