1 subroutine da_divergence_constraint_adj(grid, u, v, div)
3 !---------------------------------------------------------------------------
4 ! Purpose: Adjoint of the subroutine da_divergence_constraint
6 ! Div = m^2 *[---(---) + ---(---) ]
8 !---------------------------------------------------------------------------
12 type (domain), intent(inout) :: grid
14 real, intent(out) :: u(ims:ime,jms:jme,kms:kme) ! u wind comp.
15 real, intent(out) :: v(ims:ime,jms:jme,kms:kme) ! v wind comp.
16 real, intent(inout):: div(ims:ime,jms:jme,kms:kme) ! Divergence.
18 integer :: i, j, k ! Loop counters.
19 integer :: is, ie ! 1st dim. end points.
20 integer :: js, je ! 2nd dim. end points.
21 real :: one_third ! 1/3.
23 real :: coeff, inv_2ds
24 real :: um(ims:ime,jms:jme) ! Temp. storage of mu*u/m.
25 real :: vm(ims:ime,jms:jme) ! Temp. storage of mu*v/m
26 real :: mu(ims:ime,jms:jme) ! Temp. storage of mu
28 if (trace_use) call da_trace_entry("da_divergence_constraint_adj")
30 !---------------------------------------------------------------------------
32 !---------------------------------------------------------------------------
36 is = its - 1; ie = ite + 1; js = jts - 1; je = jte + 1
38 if (.not. global .and. its == ids) is = ids+1
39 if (.not. global .and. ite == ide) ie = ide-1
40 if (jts == jds) js = jds+1; if (jte == jde) je = jde-1
42 mu = grid%xb%psfc - grid%xb%ptop
44 !---------------------------------------------------------------------------
45 ! [2.0] Calculate divergence:
46 !---------------------------------------------------------------------------
48 if (.not. global) then
49 inv_2ds = 0.5 / grid%xb%ds
51 um(ims:ime,jms:jme) = 0.0
52 vm(ims:ime,jms:jme) = 0.0
53 ! [2.2] Impose zero divergence gradient condition at boundaries:
55 ! [2.2.4] Right boundaries:
59 do i = its, ite ! This is different to original
60 div(i,j-1,k)=div(i,j-1,k)+div(i,j,k)*one_third*4.0
61 div(i,j-2,k)=div(i,j-2,k)-div(i,j,k)*one_third
66 ! [2.2.3] Left boundaries:
70 do i = its, ite ! This is different to original
71 div(i,j+1,k)=div(i,j+1,k)+div(i,j,k)*one_third*4.0
72 div(i,j+2,k)=div(i,j+2,k)-div(i,j,k)*one_third
77 ! [2.2.2] Top boundaries:
82 div(i-1,j,k)=div(i-1,j,k)+div(i,j,k)*one_third*4.0
83 div(i-2,j,k)=div(i-2,j,k)-div(i,j,k)*one_third
88 ! [2.2.1] Bottom boundaries:
93 div(i+1,j,k)=div(i+1,j,k)+div(i,j,k)*one_third*4.0
94 div(i+2,j,k)=div(i+2,j,k)-div(i,j,k)*one_third
99 ! [2.1] Compute fd divergence at interior points:
100 ! Computation to check for edge of domain:
101 ! This is only for adjoint, as we have to cross the processor boundary
102 ! to get the contribution.
104 grid%xp%vxy(its:ite, jts:jte) = div(its:ite, jts:jte, k)
106 #include "HALO_2D_WORK.inc"
109 div(is, js:je, k) = grid%xp%vxy(is, js:je)
110 div(ie, js:je, k) = grid%xp%vxy(ie, js:je)
111 div(is:ie, js, k) = grid%xp%vxy(is:ie, js)
112 div(is:ie, je, k) = grid%xp%vxy(is:ie, je)
116 coeff = grid%xb%map_factor(i,j) * grid%xb%map_factor(i,j) * inv_2ds
117 um(i+1,j)=um(i+1,j)+div(i,j,k)*coeff
118 um(i-1,j)=um(i-1,j)-div(i,j,k)*coeff
119 vm(i,j+1)=vm(i,j+1)+div(i,j,k)*coeff
120 vm(i,j-1)=vm(i,j-1)-div(i,j,k)*coeff
124 u(is-1:ie+1,js-1:je+1,k) = u(is-1:ie+1,js-1:je+1,k) + &
125 um(is-1:ie+1,js-1:je+1) * &
126 mu(is-1:ie+1,js-1:je+1) / &
127 grid%xb%map_factor(is-1:ie+1,js-1:je+1)
128 v(is-1:ie+1,js-1:je+1,k) = v(is-1:ie+1,js-1:je+1,k) + &
129 vm(is-1:ie+1,js-1:je+1) * &
130 mu(is-1:ie+1,js-1:je+1) / &
131 grid%xb%map_factor(is-1:ie+1,js-1:je+1)
135 call da_set_boundary_3d(div)
138 !-------------------------------------------------------------------------
139 ! [2.1] Compute fd divergence at interior points:
140 !-------------------------------------------------------------------------
144 u(i+1,j,k) = u(i+1,j,k) + grid%xb%coefx(i,j) * div(i,j,k)
145 u(i-1,j,k) = u(i-1,j,k) - grid%xb%coefx(i,j) * div(i,j,k)
146 v(i,j+1,k) = v(i,j+1,k) + grid%xb%coefy(i,j) * div(i,j,k)
147 v(i,j-1,k) = v(i,j-1,k) - grid%xb%coefy(i,j) * div(i,j,k)
155 if (trace_use) call da_trace_exit("da_divergence_constraint_adj")
157 end subroutine da_divergence_constraint_adj