1 subroutine da_check_vptox_adjoint(grid, ne, be, ep, vp, cv_size)
3 !---------------------------------------------------------------------------
4 ! Purpose: Test Vp to X routine and adjoint for compatibility.
6 ! Method: Standard adjoint test: < x, x > = < v_adj, v >.
7 !---------------------------------------------------------------------------
11 type (domain), intent(inout) :: grid
13 integer, intent(in) :: ne ! Ensemble size.
14 type (be_type), intent(in) :: be ! background errors.
15 type (ep_type), intent(in) :: ep ! Ensemble perturbation type.
16 type (vp_type),intent(inout) :: vp ! grdipt/level cv (local)
17 integer, intent(in) :: cv_size
20 real :: cv(1:cv_size), cv_2(1:cv_size)
22 real :: adj_par_lhs ! < x, x >
23 real :: adj_par_rhs ! < v_adj, v >
24 real :: adj_sum_lhs ! < x, x >
25 real :: adj_sum_rhs ! < v_adj, v >
26 real :: vp2_v1(ims:ime,jms:jme,kms:kme)
27 real :: vp2_v2(ims:ime,jms:jme,kms:kme)
28 real :: vp2_v3(ims:ime,jms:jme,kms:kme)
29 real :: vp2_v4(ims:ime,jms:jme,kms:kme)
30 real :: vp2_v5(ims:ime,jms:jme,kms:kme)
32 real :: vp2_v6(ims:ime,jms:jme,kms:kme)
33 real :: vp2_v7(ims:ime,jms:jme,kms:kme)
34 real :: vp2_v8(ims:ime,jms:jme,kms:kme)
35 real :: vp2_v9(ims:ime,jms:jme,kms:kme)
36 real :: vp2_v10(ims:ime,jms:jme,kms:kme)
37 real :: vp2_v11(ims:ime,jms:jme,kms:kme)
39 ! real :: vp2_alpha(ims:ime,jms:jme,kms:kme,1:ne)
40 real :: vp2_alpha(ims_int:ime_int,jms_int:jme_int,kms_int:kme_int,1:ne)
42 if (trace_use) call da_trace_entry("da_check_vptox_adjoint")
44 !-------------------------------------------------------------------------
46 !-------------------------------------------------------------------------
49 call da_zero_x(grid%xa)
51 vp2_v1(:,:,:) = vp % v1(:,:,:)
52 vp2_v2(:,:,:) = vp % v2(:,:,:)
54 call da_psichi_to_uv(vp % v1, vp % v2, grid%xb % coefx, &
55 grid%xb % coefy , grid%xa % u, grid%xa % v)
57 adj_par_lhs = sum(grid%xa % u(its:ite,jts:jte,:)**2) / typical_u_rms**2
58 adj_par_lhs = sum(grid%xa % v(its:ite,jts:jte,:)**2) / typical_v_rms**2 + &
61 grid%xa % u(:,:,:) = grid%xa % u(:,:,:) / typical_u_rms**2
62 grid%xa % v(:,:,:) = grid%xa % v(:,:,:) / typical_v_rms**2
67 call da_psichi_to_uv_adj(grid%xa % u, grid%xa % v, grid%xb % coefx, &
68 grid%xb % coefy, vp % v1, vp % v2)
70 adj_par_rhs = sum(vp % v1(its:ite,jts:jte,:) * vp2_v1(its:ite,jts:jte,:))
71 adj_par_rhs = sum(vp % v2(its:ite,jts:jte,:) * vp2_v2(its:ite,jts:jte,:)) + &
74 write(unit=stdout, fmt='(/a/)') &
75 'da_check_da_psichi_to_uv_adjoint: Test Results:'
76 write(unit=stdout, fmt='(/)')
77 write(unit=stdout, fmt='(a,1pe22.14)') &
78 'Single Domain: < u_v, u_v > = ', adj_par_lhs, &
79 'Single Domain: < psi_chi, psi_chi_adj > = ', adj_par_rhs
81 adj_sum_lhs = wrf_dm_sum_real(adj_par_lhs)
82 adj_sum_rhs = wrf_dm_sum_real(adj_par_rhs)
86 write(unit=stdout, fmt='(/)')
87 write(unit=stdout, fmt='(a,1pe22.14)') &
88 'Whole Domain: < u_v, u_v > = ', adj_sum_lhs, &
89 'Whole Domain: < psi_chi, psi_chi_adj > = ', adj_sum_rhs
91 write(unit=stdout, fmt='(/a/)') &
92 'da_check_da_psichi_to_uv_adjoint: Test Finished:'
94 vp%v1(:,:,:) = vp2_v1(:,:,:)
95 vp%v2(:,:,:) = vp2_v2(:,:,:)
97 call da_zero_x(grid%xa)
99 vp2_v1(:,:,:) = vp % v1(:,:,:)
100 vp2_v2(:,:,:) = vp % v2(:,:,:)
101 vp2_v3(:,:,:) = vp % v3(:,:,:)
102 vp2_v4(:,:,:) = vp % v4(:,:,:)
103 vp2_v5(:,:,:) = vp % v5(:,:,:)
105 if ( cloud_cv_options >= 2 ) then
106 vp2_v6(:,:,:) = vp % v6(:,:,:)
107 vp2_v7(:,:,:) = vp % v7(:,:,:)
108 vp2_v8(:,:,:) = vp % v8(:,:,:)
109 vp2_v9(:,:,:) = vp % v9(:,:,:)
110 vp2_v10(:,:,:)= vp % v10(:,:,:)
114 vp2_v11(:,:,:)= vp % v11(:,:,:)
117 !hcl if (be % ne > 0) vp2_alpha(:,:,:,:) = vp % alpha(:,:,:,:)
119 !-------------------------------------------------------------------------
120 ! [2.0] Perform x = U vp transform:
121 !-------------------------------------------------------------------------
123 if ( cv_options == 3 ) then
125 call random_number(cv(:))
129 call da_apply_be( be, cv, vp, grid)
130 call da_transform_bal( vp, be, grid)
134 call da_transform_vptox(grid, vp, be, ep)
138 !-------------------------------------------------------------------------
139 ! [3.0] Calculate LHS of adjoint test equation:
140 !-------------------------------------------------------------------------
142 ! grid%xa % u(:,:,:) = 0.0
143 ! grid%xa % v(:,:,:) = 0.0
144 ! grid%xa % t(:,:,:) = 0.0
145 ! grid%xa % q(:,:,:) = 0.0
146 ! grid%xa%psfc(:,:) = 0.0
148 ! grid%xa % p(:,:,:) = 0.0
149 ! grid%xa % rho(:,:,:) = 0.0
150 ! grid%xa % w(:,:,:) = 0.0
151 ! grid%xa % wh(:,:,:) = 0.0
152 ! grid%xa % rh(:,:,:) = 0.0
153 ! grid%xa % qt(:,:,:) = 0.0
154 ! grid%xa % qcw(:,:,:) = 0.0
155 ! grid%xa % qrn(:,:,:) = 0.0
157 adj_par_lhs = sum(grid%xa%u(its:ite,jts:jte,:)**2)/typical_u_rms**2
158 adj_par_lhs = sum(grid%xa%v(its:ite,jts:jte,:)**2)/typical_v_rms**2 + adj_par_lhs
159 adj_par_lhs = sum(grid%xa%t(its:ite,jts:jte,:)**2)/typical_t_rms**2 + adj_par_lhs
160 if ( (use_radar_rf .or. crtm_cloud) .and. (cloud_cv_options == 1) ) then
161 adj_par_lhs = sum(grid%xa%qt(its:ite,jts:jte,:)**2)/typical_q_rms**2 + adj_par_lhs
163 adj_par_lhs = sum(grid%xa%q(its:ite,jts:jte,:)**2)/typical_q_rms**2 + adj_par_lhs
165 adj_par_lhs = sum(grid%xa%psfc(its:ite,jts:jte)**2)/typical_p_rms**2 + adj_par_lhs
167 adj_par_lhs = sum(grid%xa%p(its:ite,jts:jte,:)**2)/typical_p_rms**2 + adj_par_lhs
168 adj_par_lhs = sum(grid%xa%rho(its:ite,jts:jte,:)**2)/typical_rho_rms**2 + &
171 if (use_radarobs) then
172 adj_par_lhs = adj_par_lhs &
173 + sum(grid%xa % wh (its:ite, jts:jte, kts:kte)**2)/typical_w_rms**2
175 adj_par_lhs = adj_par_lhs &
176 + sum(grid%xa % w (its:ite, jts:jte, kts:kte)**2)/typical_w_rms**2
179 if (cv_options_hum == cv_options_hum_relative_humidity) then
180 adj_par_lhs = sum(grid%xa % rh(its:ite,jts:jte,:)**2) / &
181 typical_rh_rms**2 + adj_par_lhs
184 if ( cloud_cv_options >= 2 ) then
185 adj_par_lhs = sum(grid%xa % qcw(its:ite,jts:jte,kts:kte)**2) / &
186 typical_qcw_rms**2 + adj_par_lhs
187 adj_par_lhs = sum(grid%xa % qrn(its:ite,jts:jte,kts:kte)**2) / &
188 typical_qrn_rms**2 + adj_par_lhs
189 adj_par_lhs = sum(grid%xa % qci (its:ite,jts:jte,kts:kte)**2) / &
190 typical_qci_rms**2 + adj_par_lhs
191 adj_par_lhs = sum(grid%xa % qsn(its:ite,jts:jte,kts:kte)**2) / &
192 typical_qsn_rms**2 + adj_par_lhs
193 adj_par_lhs = sum(grid%xa % qgr (its:ite,jts:jte,kts:kte)**2) / &
194 typical_qgr_rms**2 + adj_par_lhs
197 if (use_radar_rf .or. crtm_cloud) then
198 if ( cloud_cv_options == 1 ) then
199 adj_par_lhs = sum(grid%xa % qcw(its:ite,jts:jte,kts:kte)**2) / &
200 typical_qcw_rms**2 + adj_par_lhs
201 adj_par_lhs = sum(grid%xa % qrn(its:ite,jts:jte,kts:kte)**2) / &
202 typical_qrn_rms**2 + adj_par_lhs
206 !-------------------------------------------------------------------------
207 ! [4.0] Rescale input to adjoint routine:
208 !-------------------------------------------------------------------------
210 grid%xa % u(:,:,:) = grid%xa % u(:,:,:) / typical_u_rms**2
211 grid%xa % v(:,:,:) = grid%xa % v(:,:,:) / typical_v_rms**2
212 grid%xa % t(:,:,:) = grid%xa % t(:,:,:) / typical_t_rms**2
213 if ( (use_radar_rf .or. crtm_cloud) .and. (cloud_cv_options == 1) ) then
214 grid%xa % qt(:,:,:) = grid%xa % qt(:,:,:) / typical_q_rms**2
216 grid%xa % q(:,:,:) = grid%xa % q(:,:,:) / typical_q_rms**2
218 grid%xa%psfc(:,:) = grid%xa%psfc(:,:) / typical_p_rms**2
220 grid%xa % p(:,:,:) = grid%xa % p(:,:,:) / typical_p_rms**2
221 grid%xa % rho(:,:,:) = grid%xa % rho(:,:,:) / typical_rho_rms**2
223 if (use_radarobs) then
224 grid%xa %wh(:,:,:) = grid%xa %wh(:,:,:) / typical_w_rms**2
225 grid%xa % w(:,:,:) = 0.0
227 grid%xa %w (:,:,:) = grid%xa %w (:,:,:) / typical_w_rms**2
230 if (cv_options_hum == cv_options_hum_relative_humidity) then
231 grid%xa % rh(:,:,:) = grid%xa % rh(:,:,:) / typical_rh_rms**2
234 if ( cloud_cv_options >= 2 ) then
235 grid%xa % qcw(:,:,:) = grid%xa % qcw(:,:,:) / typical_qcw_rms**2
236 grid%xa % qrn(:,:,:) = grid%xa % qrn(:,:,:) / typical_qrn_rms**2
237 grid%xa % qci(:,:,:) = grid%xa % qci(:,:,:) / typical_qci_rms**2
238 grid%xa % qsn(:,:,:) = grid%xa % qsn(:,:,:) / typical_qsn_rms**2
239 grid%xa % qgr(:,:,:) = grid%xa % qgr(:,:,:) / typical_qgr_rms**2
242 if (use_radar_rf .or. crtm_cloud) then
243 if ( cloud_cv_options == 1 ) then
244 grid%xa % qcw(:,:,:) = grid%xa % qcw(:,:,:) / typical_qcw_rms**2
245 grid%xa % qrn(:,:,:) = grid%xa % qrn(:,:,:) / typical_qrn_rms**2
249 !-------------------------------------------------------------------------
250 ! [5.0] Perform adjoint operation:
251 !-------------------------------------------------------------------------
253 call da_zero_vp_type (vp)
255 if (cv_options == 3 ) then
259 call da_transform_bal_adj( vp, be, grid)
260 call da_apply_be_adj( be, cv, vp, grid)
264 call da_transform_vptox_adj(grid, vp, be, ep)
268 !-------------------------------------------------------------------------
269 ! [6.0] Calculate RHS of adjoint test equation:
270 !-------------------------------------------------------------------------
272 adj_par_rhs = sum(vp % v1(its:ite,jts:jte,:) * vp2_v1(its:ite,jts:jte,:))
273 adj_par_rhs = sum(vp % v2(its:ite,jts:jte,:) * vp2_v2(its:ite,jts:jte,:)) + &
275 adj_par_rhs = sum(vp % v3(its:ite,jts:jte,:) * vp2_v3(its:ite,jts:jte,:)) + &
277 adj_par_rhs = sum(vp % v4(its:ite,jts:jte,:) * vp2_v4(its:ite,jts:jte,:)) + &
279 adj_par_rhs = sum(vp % v5(its:ite,jts:jte,:) * vp2_v5(its:ite,jts:jte,:)) + &
282 if ( cloud_cv_options >= 2 ) then
283 adj_par_rhs = sum(vp % v6(its:ite,jts:jte,:) * vp2_v6(its:ite,jts:jte,:)) + &
285 adj_par_rhs = sum(vp % v7(its:ite,jts:jte,:) * vp2_v7(its:ite,jts:jte,:)) + &
287 adj_par_rhs = sum(vp % v8(its:ite,jts:jte,:) * vp2_v8(its:ite,jts:jte,:)) + &
289 adj_par_rhs = sum(vp % v9(its:ite,jts:jte,:) * vp2_v9(its:ite,jts:jte,:)) + &
291 adj_par_rhs = sum(vp % v10(its:ite,jts:jte,:)* vp2_v10(its:ite,jts:jte,:)) + &
296 adj_par_rhs = sum(vp % v11(its:ite,jts:jte,:)* vp2_v11(its:ite,jts:jte,:)) + &
300 !hcl if (be % ne > 0) then
301 !hcl adj_par_rhs = sum(vp % alpha(its_int:ite_int,jts_int:jte_int,kts_int:kte_int,:) * &
302 !hcl vp2_alpha(its_int:ite_int,jts_int:jte_int,kts_int:kte_int,:)) + adj_par_rhs
305 if ( cv_options == 3 ) adj_par_rhs = sum (cv_2*cv)
307 !-------------------------------------------------------------------------
308 ! [7.0] Print output:
309 !-------------------------------------------------------------------------
311 adj_sum_lhs = wrf_dm_sum_real(adj_par_lhs)
312 adj_sum_rhs = wrf_dm_sum_real(adj_par_rhs)
314 write(unit=stdout, fmt='(/a/)') 'da_check_vptox_adjoint: Test Results:'
315 write(unit=stdout, fmt='(/)')
316 write(unit=stdout, fmt='(a,1pe22.14)') &
317 'Single Domain: < x, x > = ', adj_par_lhs, &
318 'Single Domain: < vp_adj, vp > = ', adj_par_rhs
321 write(unit=stdout, fmt='(/)')
322 write(unit=stdout, fmt='(a,1pe22.14)') &
323 'Whole Domain: < x, x > = ', adj_sum_lhs, &
324 'Whole Domain: < vp_adj, vp > = ', adj_sum_rhs
327 vp % v1(:,:,:) = vp2_v1(:,:,:)
328 vp % v2(:,:,:) = vp2_v2(:,:,:)
329 vp % v3(:,:,:) = vp2_v3(:,:,:)
330 vp % v4(:,:,:) = vp2_v4(:,:,:)
331 vp % v5(:,:,:) = vp2_v5(:,:,:)
333 if ( cloud_cv_options >= 2 ) then
334 vp % v6(:,:,:) = vp2_v6(:,:,:)
335 vp % v7(:,:,:) = vp2_v7(:,:,:)
336 vp % v8(:,:,:) = vp2_v8(:,:,:)
337 vp % v9(:,:,:) = vp2_v9(:,:,:)
338 vp % v10(:,:,:)= vp2_v10(:,:,:)
342 vp % v11(:,:,:)= vp2_v11(:,:,:)
345 !hcl if (be % ne > 0) vp % alpha(:,:,:,:) = vp2_alpha(:,:,:,:)
347 write(unit=stdout, fmt='(/a/)') 'da_check_vptox_adjoint: Test Finished:'
349 if (trace_use) call da_trace_exit("da_check_vptox_adjoint")
351 end subroutine da_check_vptox_adjoint