1 program da_update_bc_ad
3 !-----------------------------------------------------------------------
4 ! Purpose: adjoint version of update BC file from wrfvar output.
5 ! current version reads only wrf-netcdf file format
7 ! Xin Zhang, 12/12/2011:
8 ! for 3DVAR use only with FSO
10 !-----------------------------------------------------------------------
12 use da_netcdf_interface
, only
: da_get_var_3d_real_cdf
, &
13 da_put_var_3d_real_cdf
, da_get_dims_cdf
, da_put_var_2d_real_cdf
, &
14 da_get_var_2d_real_cdf
, da_get_var_2d_int_cdf
, da_get_bdytimestr_cdf
, &
15 da_get_times_cdf
, da_get_bdyfrq
, stderr
, stdout
, da_put_var_2d_int_cdf
17 use da_module_couple_uv_ad
, only
: da_couple_uv_b
23 integer, parameter :: max_3d_variables
= 5, &
26 character(len
=512) :: wrfinput
, &
31 character(len
=20) :: var_pref
, var_name
, vbt_name
33 character(len
=20) :: var3d(max_3d_variables
), &
34 varsf(max_2d_variables
)
36 character(len
=10), dimension(4) :: bdyname
, tenname
38 integer :: ids
, ide
, jds
, jde
, kds
, kde
39 integer :: num3d
, num2d
, ndims
41 integer :: i
,j
,k
,l
,m
,n
43 integer, dimension(4) :: dims
45 real, allocatable
, dimension(:,:,:) :: tend3d
, scnd3d
, frst3d
, full3d
, full3d9
47 real, allocatable
, dimension(:,:,:) :: u
, v
48 real, allocatable
, dimension(:,:,:) :: a_u
, a_v
50 real, allocatable
, dimension(:, :) :: mu
, a_mu
, mub
, msfu
, msfv
, &
53 character(len
=80), allocatable
, dimension(:) :: times
, &
54 thisbdytime
, nextbdytime
56 integer :: east_end
, north_end
, io_status
, cdfid
, varid
57 integer :: iostatus(4)
59 logical :: debug
, update_lateral_bdy
63 integer, parameter :: namelist_unit
= 7
65 namelist /control_param
/ wrfinput
, &
69 debug
, update_lateral_bdy
72 wrfinput
= 'wrfinput_d01'
73 init_sens
= 'init_sens_d01'
74 wrf_bdy_file
= 'wrfbdy_d01'
75 bdy_sens
= 'gradient_wrfbdy_d01'
78 update_lateral_bdy
= .true
.
80 !---------------------------------------------------------------------
82 !---------------------------------------------------------------------
85 open(unit
= namelist_unit
, file
= 'parame.in', &
86 status
= 'old' , access
= 'sequential', &
87 form
= 'formatted', action
= 'read', &
90 if (io_status
/= 0) then
91 write(unit
=stdout
,fmt
=*) 'Error to open namelist file: parame.in.'
92 write(unit
=stdout
,fmt
=*) 'Will work for updating lateral boundary only.'
94 read(unit
=namelist_unit
, nml
= control_param
, iostat
= io_status
)
96 if (io_status
/= 0) then
97 write(unit
=stdout
,fmt
=*) 'Error to read control_param. Stopped.'
101 WRITE(unit
=stdout
, fmt
='(2a)') &
102 'wrfinput = ', trim(wrfinput
), &
103 'init_sens = ', trim(init_sens
), &
104 'wrf_bdy_file = ', trim(wrf_bdy_file
), &
105 'bdy_sens = ', trim(bdy_sens
)
107 WRITE(unit
=stdout
, fmt
='(2(a, L10))') &
108 'update_lateral_bdy = ', update_lateral_bdy
110 close(unit
=namelist_unit
)
128 if ( update_lateral_bdy
) then
129 ! First, the boundary times
130 call da_get_dims_cdf(wrf_bdy_file
, 'Times', dims
, ndims
, debug
)
133 write(unit
=stdout
, fmt
='(a,i2,2x,a,4i6)') &
134 'Times: ndims=', ndims
, 'dims=', (dims(i
), i
=1,ndims
)
139 if (time_level
< 1) then
140 write(unit
=stdout
, fmt
='(a,i2/a)') &
141 'time_level = ', time_level
, &
142 'We need at least one time-level BDY.'
143 stop 'Wrong BDY file.'
146 allocate(times(dims(2)))
147 allocate(thisbdytime(dims(2)))
148 allocate(nextbdytime(dims(2)))
150 call da_get_times_cdf(wrf_bdy_file
, times
, dims(2), dims(2), debug
)
152 call da_get_bdytimestr_cdf(wrf_bdy_file
, 'thisbdytime', thisbdytime
, dims(2), debug
)
153 call da_get_bdytimestr_cdf(wrf_bdy_file
, 'nextbdytime', nextbdytime
, dims(2), debug
)
155 call da_get_bdyfrq(thisbdytime(1), nextbdytime(1), bdyfrq
, debug
)
159 write(unit
=stdout
, fmt
='(3(a, i2, 2a,2x))') &
160 ' times(', n
, ')=', trim(times(n
)), &
161 'thisbdytime (', n
, ')=', trim(thisbdytime(n
)), &
162 'nextbdytime (', n
, ')=', trim(nextbdytime(n
))
171 cdfid
= ncopn(wrfinput
, NCNOWRIT
, io_status
)
173 !---------------------------------------------------------------
175 ! Get mu, mub, msfu, and msfv
179 io_status
= nf_inq_varid(cdfid
, trim(varsf(n
)), varid
)
180 if (io_status
/= 0 ) then
181 print '(/"N=",i2," io_status=",i5,5x,"VAR=",a,a)', &
182 n
, io_status
, trim(varsf(n
)), " does not exist"
186 call da_get_dims_cdf( wrfinput
, trim(varsf(n
)), dims
, &
189 select
case(trim(varsf(n
)))
191 if ( .not
. update_lateral_bdy
) cycle
193 allocate(mu(dims(1), dims(2)))
194 allocate(a_mu(dims(1), dims(2)))
197 call da_get_var_2d_real_cdf( wrfinput
, &
198 trim(varsf(n
)), mu
, dims(1), dims(2), 1, debug
)
201 if ( .not
. update_lateral_bdy
) cycle
203 allocate(mub(dims(1), dims(2)))
205 call da_get_var_2d_real_cdf( wrfinput
, trim(varsf(n
)), mub
, &
206 dims(1), dims(2), 1, debug
)
208 if ( .not
. update_lateral_bdy
) cycle
210 allocate(msfu(dims(1), dims(2)))
212 call da_get_var_2d_real_cdf( wrfinput
, trim(varsf(n
)), msfu
, &
213 dims(1), dims(2), 1, debug
)
215 if ( .not
. update_lateral_bdy
) cycle
217 allocate(msfv(dims(1), dims(2)))
219 call da_get_var_2d_real_cdf( wrfinput
, trim(varsf(n
)), msfv
, &
220 dims(1), dims(2), 1, debug
)
223 write(unit
=stdout
,fmt
=*) 'It is impossible here. varsf(n)=', trim(varsf(n
))
229 call da_get_dims_cdf( wrfinput
, 'U', dims
, ndims
, debug
)
231 allocate(u(dims(1), dims(2), dims(3)))
232 allocate(a_u(dims(1), dims(2), dims(3)))
242 call da_get_var_3d_real_cdf( wrfinput
, 'U', u
, &
243 dims(1), dims(2), dims(3), 1, debug
)
246 call da_get_dims_cdf( wrfinput
, 'V', dims
, ndims
, debug
)
248 allocate(v(dims(1), dims(2), dims(3)))
249 allocate(a_v(dims(1), dims(2), dims(3)))
252 call da_get_var_3d_real_cdf( wrfinput
, 'V', v
, &
253 dims(1), dims(2), dims(3), 1, debug
)
261 ! boundary tendancy variables
270 write(unit
=stdout
, fmt
='(a, i3, 2a)') 'Processing: var3d(', n
, ')=', trim(var3d(n
))
272 call da_get_dims_cdf( init_sens
, trim(var3d(n
)), dims
, ndims
, debug
)
274 allocate(full3d(dims(1), dims(2), dims(3)))
277 allocate(full3d9(dims(1), dims(2), dims(3)))
282 var_pref
=trim(var3d(n
))
285 var_name
=trim(var_pref
) // trim(bdyname(m
))
286 vbt_name
=trim(var_pref
) // trim(tenname(m
))
288 write(unit
=stdout
, fmt
='(a, i3, 2a)') &
289 'Processing: bdyname(', m
, ')=', trim(var_name
)
291 call da_get_dims_cdf( bdy_sens
, trim(var_name
), dims
, ndims
, debug
)
293 allocate(frst3d(dims(1), dims(2), dims(3)))
294 allocate(tend3d(dims(1), dims(2), dims(3)))
296 write(unit
=stdout
, fmt
='(a, i3, 2a)') &
297 'adjoint cal. tend: bdyname(', m
, ')=', trim(vbt_name
)
299 ! output new variable at first time level
300 call da_get_var_3d_real_cdf( bdy_sens
, trim(var_name
), frst3d
, &
301 dims(1), dims(2), dims(3), 1, debug
)
302 call da_get_var_3d_real_cdf( bdy_sens
, trim(vbt_name
), tend3d
, &
303 dims(1), dims(2), dims(3), 1, debug
)
305 ! calculate new tendancy
309 frst3d(i
,k
,l
)=frst3d(i
,k
,l
)-tend3d(i
,k
,l
)/bdyfrq
315 select
case(trim(bdyname(m
)))
316 case ('_BXS') ; ! West boundary
320 full3d(l
,j
,k
)=full3d(l
,j
,k
)+frst3d(j
,k
,l
)
325 case ('_BXE') ; ! East boundary
329 full3d(east_end
-l
,j
,k
)=full3d(east_end
-l
,j
,k
)+frst3d(j
,k
,l
)
334 case ('_BYS') ; ! South boundary
338 full3d(i
,l
,k
)=full3d(i
,l
,k
)+frst3d(i
,k
,l
)
343 case ('_BYE') ; ! North boundary
347 full3d(i
,north_end
-l
,k
)=full3d(i
,north_end
-l
,k
)+frst3d(i
,k
,l
)
353 write(unit
=stdout
,fmt
=*) 'It is impossible here.'
354 write(unit
=stdout
,fmt
=*) 'bdyname(', m
, ')=', trim(bdyname(m
))
362 select
case(trim(var3d(n
)))
364 var_pref
=trim(var3d(n
))
365 a_u(:,:,:)=a_u(:,:,:)+full3d(:,:,:)
368 var_pref
=trim(var3d(n
))
369 a_v(:,:,:)=a_v(:,:,:)+full3d(:,:,:)
372 var_pref
=trim(var3d(n
))
374 call da_get_dims_cdf( init_sens
, trim(var3d(n
)), dims
, ndims
, debug
)
375 call da_get_var_3d_real_cdf( wrfinput
, 'T', &
376 full3d9
, dims(1), dims(2), dims(3), 1, debug
)
381 a_mu(i
,j
)=a_mu(i
,j
)+full3d(i
,j
,k
)*full3d9(i
,j
,k
)
382 full3d(i
,j
,k
)=full3d(i
,j
,k
)*(mu(i
,j
)+mub(i
,j
))
387 call da_get_var_3d_real_cdf( init_sens
, 'A_T', &
388 full3d9
, dims(1), dims(2), dims(3), 1, debug
)
390 full3d
=full3d
+full3d9
393 call da_put_var_3d_real_cdf( init_sens
, trim(var3d(n
)), &
394 full3d
, dims(1), dims(2), dims(3), 1, debug
)
399 var_pref
=trim(var3d(n
))
401 call da_get_dims_cdf( init_sens
, trim(var3d(n
)), dims
, ndims
, debug
)
402 call da_get_var_3d_real_cdf( wrfinput
, 'PH', &
403 full3d9
, dims(1), dims(2), dims(3), 1, debug
)
408 a_mu(i
,j
)=a_mu(i
,j
)+full3d(i
,j
,k
)*full3d9(i
,j
,k
)
409 full3d(i
,j
,k
)=full3d(i
,j
,k
)*(mu(i
,j
)+mub(i
,j
))
414 call da_get_var_3d_real_cdf( init_sens
, 'A_PH', &
415 full3d9
, dims(1), dims(2), dims(3), 1, debug
)
417 full3d
=full3d
+full3d9
420 call da_put_var_3d_real_cdf( init_sens
, trim(var3d(n
)), &
421 full3d
, dims(1), dims(2), dims(3), 1, debug
)
428 call da_get_dims_cdf( init_sens
, trim(var3d(n
)), dims
, ndims
, debug
)
429 call da_get_var_3d_real_cdf( wrfinput
, 'QVAPOR', &
430 full3d9
, dims(1), dims(2), dims(3), 1, debug
)
435 a_mu(i
,j
)=a_mu(i
,j
)+full3d(i
,j
,k
)*full3d9(i
,j
,k
)
436 full3d(i
,j
,k
)=full3d(i
,j
,k
)*(mu(i
,j
)+mub(i
,j
))
441 call da_get_var_3d_real_cdf( init_sens
, 'A_QVAPOR', &
442 full3d9
, dims(1), dims(2), dims(3), 1, debug
)
444 full3d
=full3d
+full3d9
447 call da_put_var_3d_real_cdf( init_sens
, trim(var3d(n
)), &
448 full3d
, dims(1), dims(2), dims(3), 1, debug
)
453 write(unit
=stdout
,fmt
=*) 'It is impossible here. var3d(', n
, ')=', trim(var3d(n
))
461 !---------------------------------------------------------------------
463 call da_couple_uv_b ( u
, a_u
, v
, a_v
, mu
, a_mu
, mub
, msfu
, msfv
, ids
, ide
, jds
, jde
, kds
, kde
)
465 call da_get_dims_cdf( init_sens
, 'A_V', dims
, ndims
, debug
)
466 call da_get_var_3d_real_cdf( init_sens
, 'A_V', v
, &
467 dims(1), dims(2), dims(3), 1, debug
)
470 call da_put_var_3d_real_cdf( init_sens
, 'A_V', a_v
, &
471 dims(1), dims(2), dims(3), 1, debug
)
474 call da_get_dims_cdf( init_sens
, 'A_U', dims
, ndims
, debug
)
475 call da_get_var_3d_real_cdf( init_sens
, 'A_U', u
, &
476 dims(1), dims(2), dims(3), 1, debug
)
479 call da_put_var_3d_real_cdf( init_sens
, 'A_U', a_u
, &
480 dims(1), dims(2), dims(3), 1, debug
)
483 call da_get_dims_cdf( wrfinput
, 'MU', dims
, &
490 var_name
='A_MU' // trim(bdyname(m
))
491 vbt_name
='A_MU' // trim(tenname(m
))
493 call da_get_dims_cdf( bdy_sens
, trim(var_name
), dims
, ndims
, debug
)
495 allocate(frst2d(dims(1), dims(2)))
496 allocate(tend2d(dims(1), dims(2)))
498 ! get new variable at first time level
499 call da_get_var_2d_real_cdf( bdy_sens
, trim(var_name
), frst2d
, &
500 dims(1), dims(2), 1, debug
)
501 ! output new tendancy
502 call da_get_var_2d_real_cdf( bdy_sens
, trim(vbt_name
), tend2d
, &
503 dims(1), dims(2), 1, debug
)
505 ! calculate new tendancy
508 frst2d(i
,l
)=frst2d(i
,l
)-tend2d(i
,l
)/bdyfrq
513 ! calculate variable at first time level
515 case (1) ; ! West boundary
518 a_mu(l
,j
)=a_mu(l
,j
)+frst2d(j
,l
)
522 case (2) ; ! East boundary
525 a_mu(east_end
-l
,j
)=a_mu(east_end
-l
,j
)+frst2d(j
,l
)
529 case (3) ; ! South boundary
532 a_mu(i
,l
)=a_mu(i
,l
)+frst2d(i
,l
)
536 case (4) ; ! North boundary
539 a_mu(i
,north_end
-l
)=a_mu(i
,north_end
-l
)+frst2d(i
,l
)
544 write(unit
=stdout
,fmt
=*) 'It is impossible here. mu, m=', m
551 call da_get_dims_cdf( init_sens
, 'A_MU', dims
, &
553 call da_get_var_2d_real_cdf( init_sens
, &
554 'A_MU', mu
, dims(1), dims(2), 1, debug
)
557 call da_put_var_2d_real_cdf( init_sens
, &
558 'A_MU', a_mu
, dims(1), dims(2), 1, debug
)
561 !---------------------------------------------------------------------
575 deallocate(thisbdytime
)
576 deallocate(nextbdytime
)
578 write (unit
=stdout
,fmt
=*) "*** Adjoint of update_bc completed successfully ***"
580 end program da_update_bc_ad