ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
oversetUtilities_b.f90
Go to the documentation of this file.
1 ! generated by tapenade (inria, ecuador team)
2 ! tapenade 3.16 (develop) - 22 aug 2023 15:51
3 !
5  implicit none
6 
7 contains
8 ! differentiation of fractoweights in reverse (adjoint) mode (with options noisize i4 dr8 r8):
9 ! gradient of useful results: weights
10 ! with respect to varying inputs: weights frac
11 ! rw status of diff variables: weights:in-out frac:out
12 ! --------------------------------------------------
13 ! tapenade routine below this point
14 ! --------------------------------------------------
15  subroutine fractoweights_b(frac, fracd, weights, weightsd)
16  use constants
17  implicit none
18  real(kind=realtype), dimension(3), intent(in) :: frac
19  real(kind=realtype), dimension(3) :: fracd
20  real(kind=realtype), dimension(8) :: weights
21  real(kind=realtype), dimension(8) :: weightsd
22  real(kind=realtype) :: tempd
23  tempd = (one-frac(1))*weightsd(7)
24  fracd = 0.0_8
25  fracd(2) = fracd(2) + frac(1)*frac(3)*weightsd(8) + frac(3)*tempd
26  fracd(3) = fracd(3) + frac(1)*frac(2)*weightsd(8) + frac(2)*tempd
27  tempd = (one-frac(2))*weightsd(6)
28  fracd(1) = fracd(1) + frac(2)*frac(3)*weightsd(8) + frac(3)*tempd - &
29 & frac(2)*frac(3)*weightsd(7)
30  weightsd(8) = 0.0_8
31  weightsd(7) = 0.0_8
32  fracd(3) = fracd(3) + frac(1)*tempd
33  tempd = (one-frac(2))*weightsd(5)
34  fracd(1) = fracd(1) - frac(3)*tempd
35  fracd(3) = fracd(3) + (one-frac(1))*tempd - frac(1)*frac(2)*weightsd&
36 & (4) - (one-frac(1))*frac(2)*weightsd(3) - frac(1)*(one-frac(2))*&
37 & weightsd(2) - (one-frac(1))*(one-frac(2))*weightsd(1)
38  tempd = (one-frac(3))*weightsd(4)
39  fracd(2) = fracd(2) + frac(1)*tempd - frac(1)*frac(3)*weightsd(6) - &
40 & (one-frac(1))*frac(3)*weightsd(5)
41  weightsd(6) = 0.0_8
42  weightsd(5) = 0.0_8
43  weightsd(4) = 0.0_8
44  fracd(1) = fracd(1) + frac(2)*tempd
45  tempd = (one-frac(3))*weightsd(3)
46  weightsd(3) = 0.0_8
47  fracd(1) = fracd(1) - frac(2)*tempd
48  fracd(2) = fracd(2) + (one-frac(1))*tempd
49  tempd = (one-frac(3))*weightsd(2)
50  weightsd(2) = 0.0_8
51  fracd(1) = fracd(1) + (one-frac(2))*tempd
52  fracd(2) = fracd(2) - frac(1)*tempd
53  tempd = (one-frac(3))*weightsd(1)
54  weightsd(1) = 0.0_8
55  fracd(1) = fracd(1) - (one-frac(2))*tempd
56  fracd(2) = fracd(2) - (one-frac(1))*tempd
57  end subroutine fractoweights_b
58 
59 ! --------------------------------------------------
60 ! tapenade routine below this point
61 ! --------------------------------------------------
62  subroutine fractoweights(frac, weights)
63  use constants
64  implicit none
65  real(kind=realtype), dimension(3), intent(in) :: frac
66  real(kind=realtype), dimension(8), intent(out) :: weights
67  weights(1) = (one-frac(1))*(one-frac(2))*(one-frac(3))
68  weights(2) = frac(1)*(one-frac(2))*(one-frac(3))
69  weights(3) = (one-frac(1))*frac(2)*(one-frac(3))
70  weights(4) = frac(1)*frac(2)*(one-frac(3))
71  weights(5) = (one-frac(1))*(one-frac(2))*frac(3)
72  weights(6) = frac(1)*(one-frac(2))*frac(3)
73  weights(7) = (one-frac(1))*frac(2)*frac(3)
74  weights(8) = frac(1)*frac(2)*frac(3)
75  end subroutine fractoweights
76 
77  subroutine fractoweights2(frac, weights)
78  use constants
79  implicit none
80  real(kind=realtype), dimension(3), intent(in) :: frac
81  real(kind=realtype), dimension(8), intent(out) :: weights
82  weights(1) = (one-frac(1))*(one-frac(2))*(one-frac(3))
83  weights(2) = frac(1)*(one-frac(2))*(one-frac(3))
84  weights(3) = frac(1)*frac(2)*(one-frac(3))
85  weights(4) = (one-frac(1))*frac(2)*(one-frac(3))
86  weights(5) = (one-frac(1))*(one-frac(2))*frac(3)
87  weights(6) = frac(1)*(one-frac(2))*frac(3)
88  weights(7) = frac(1)*frac(2)*frac(3)
89  weights(8) = (one-frac(1))*frac(2)*frac(3)
90  end subroutine fractoweights2
91 
92 ! differentiation of newtonupdate in reverse (adjoint) mode (with options noisize i4 dr8 r8):
93 ! gradient of useful results: blk frac
94 ! with respect to varying inputs: xcen blk frac
95 ! rw status of diff variables: xcen:out blk:incr frac:in-out
96  subroutine newtonupdate_b(xcen, xcend, blk, blkd, frac0, frac, fracd)
97 ! this routine performs the newton update to recompute the new
98 ! "frac" (u,v,w) for the point xcen. the actual search is performed
99 ! on the the dual cell formed by the cell centers of the 3x3x3 block
100 ! of primal nodes. this routine is ad'd with tapenade in both
101 ! forward and reverse.
102  use constants
103  implicit none
104 ! input
105  real(kind=realtype), dimension(3), intent(in) :: xcen
106  real(kind=realtype), dimension(3) :: xcend
107  real(kind=realtype), dimension(3, 3, 3, 3), intent(in) :: blk
108  real(kind=realtype), dimension(3, 3, 3, 3) :: blkd
109  real(kind=realtype), dimension(3), intent(in) :: frac0
110 ! output
111  real(kind=realtype), dimension(3) :: frac
112  real(kind=realtype), dimension(3) :: fracd
113 ! working
114  real(kind=realtype), dimension(3, 8) :: xn
115  real(kind=realtype), dimension(3, 8) :: xnd
116  real(kind=realtype) :: u, v, w, uv, uw, vw, wvu, du, dv, dw
117  real(kind=realtype) :: ud, vd, wd, uvd, uwd, vwd, wvud, dud, dvd, &
118 & dwd
119  real(kind=realtype) :: a11, a12, a13, a21, a22, a23, a31, a32, a33, &
120 & val
121  real(kind=realtype) :: a11d, a12d, a13d, a21d, a22d, a23d, a31d, &
122 & a32d, a33d, vald
123  real(kind=realtype) :: f(3), x(3)
124  real(kind=realtype) :: fd(3), xd(3)
125  integer(kind=inttype), dimension(8), parameter :: indices=(/1, 2, 4&
126 & , 3, 5, 6, 8, 7/)
127  integer(kind=inttype) :: i, j, k, ii, ll
128  real(kind=realtype), parameter :: adteps=1.e-25_realtype
129  real(kind=realtype), parameter :: thresconv=1.e-10_realtype
130  intrinsic sign
131  intrinsic abs
132  intrinsic max
133  intrinsic sqrt
134  real(kind=realtype) :: x1
135  real(kind=realtype) :: x1d
136  real(kind=realtype) :: max1
137  real(kind=realtype) :: max1d
138  real(kind=realtype), dimension(3) :: tempd
139  real(kind=realtype), dimension(3) :: tmp
140  real(kind=realtype), dimension(3) :: tmpd
141  real(kind=realtype) :: temp
142  real(kind=realtype) :: tempd0
143  real(kind=realtype) :: temp0
144  real(kind=realtype) :: tempd1
145  real(kind=realtype) :: temp1
146  real(kind=realtype) :: tempd2
147  real(kind=realtype) :: temp2
148  real(kind=realtype) :: tempd3
149  integer :: branch
150  integer :: ad_count
151  integer :: i0
152 ! compute the cell center locations for the 8 nodes describing the
153 ! dual cell. note that this must be counter-clockwise ordering.
154  ii = 0
155  do k=1,2
156  do j=1,2
157  do i=1,2
158  call pushinteger4(ii)
159  ii = ii + 1
160  xn(:, indices(ii)) = eighth*(blk(i, j, k, :)+blk(i+1, j, k, :)&
161 & +blk(i, j+1, k, :)+blk(i+1, j+1, k, :)+blk(i, j, k+1, :)+blk&
162 & (i+1, j, k+1, :)+blk(i, j+1, k+1, :)+blk(i+1, j+1, k+1, :))
163  end do
164  end do
165  end do
166 ! compute the coordinates relative to node 1.
167  do i=2,8
168  tmp(:) = xn(:, i) - xn(:, 1)
169  xn(:, i) = tmp(:)
170  end do
171 ! compute the location of our seach point relative to the first node.
172  x = xcen - xn(:, 1)
173 ! modify the coordinates of node 3, 6, 8 and 7 such that
174 ! they correspond to the weights of the u*v, u*w, v*w and
175 ! u*v*w term in the transformation respectively.
176  xn(1, 7) = xn(1, 7) + xn(1, 2) + xn(1, 4) + xn(1, 5) - xn(1, 3) - xn&
177 & (1, 6) - xn(1, 8)
178  xn(2, 7) = xn(2, 7) + xn(2, 2) + xn(2, 4) + xn(2, 5) - xn(2, 3) - xn&
179 & (2, 6) - xn(2, 8)
180  xn(3, 7) = xn(3, 7) + xn(3, 2) + xn(3, 4) + xn(3, 5) - xn(3, 3) - xn&
181 & (3, 6) - xn(3, 8)
182  xn(1, 3) = xn(1, 3) - xn(1, 2) - xn(1, 4)
183  xn(2, 3) = xn(2, 3) - xn(2, 2) - xn(2, 4)
184  xn(3, 3) = xn(3, 3) - xn(3, 2) - xn(3, 4)
185  xn(1, 6) = xn(1, 6) - xn(1, 2) - xn(1, 5)
186  xn(2, 6) = xn(2, 6) - xn(2, 2) - xn(2, 5)
187  xn(3, 6) = xn(3, 6) - xn(3, 2) - xn(3, 5)
188  xn(1, 8) = xn(1, 8) - xn(1, 4) - xn(1, 5)
189  xn(2, 8) = xn(2, 8) - xn(2, 4) - xn(2, 5)
190  xn(3, 8) = xn(3, 8) - xn(3, 4) - xn(3, 5)
191 ! set the starting values of u, v and w based on our previous values
192  u = frac0(1)
193  v = frac0(2)
194  w = frac0(3)
195  ad_count = 1
196 ! the newton algorithm to determine the parametric
197 ! weights u, v and w for the given coordinate.
198 newtonhexa:do ll=1,15
199 ! compute the rhs.
200  uv = u*v
201  uw = u*w
202  vw = v*w
203  wvu = u*v*w
204  call pushreal8(f(1))
205  f(1) = xn(1, 2)*u + xn(1, 4)*v + xn(1, 5)*w + xn(1, 3)*uv + xn(1, &
206 & 6)*uw + xn(1, 8)*vw + xn(1, 7)*wvu - x(1)
207  call pushreal8(f(2))
208  f(2) = xn(2, 2)*u + xn(2, 4)*v + xn(2, 5)*w + xn(2, 3)*uv + xn(2, &
209 & 6)*uw + xn(2, 8)*vw + xn(2, 7)*wvu - x(2)
210  call pushreal8(f(3))
211  f(3) = xn(3, 2)*u + xn(3, 4)*v + xn(3, 5)*w + xn(3, 3)*uv + xn(3, &
212 & 6)*uw + xn(3, 8)*vw + xn(3, 7)*wvu - x(3)
213 ! compute the jacobian.
214  a11 = xn(1, 2) + xn(1, 3)*v + xn(1, 6)*w + xn(1, 7)*vw
215  a12 = xn(1, 4) + xn(1, 3)*u + xn(1, 8)*w + xn(1, 7)*uw
216  a13 = xn(1, 5) + xn(1, 6)*u + xn(1, 8)*v + xn(1, 7)*uv
217  a21 = xn(2, 2) + xn(2, 3)*v + xn(2, 6)*w + xn(2, 7)*vw
218  a22 = xn(2, 4) + xn(2, 3)*u + xn(2, 8)*w + xn(2, 7)*uw
219  a23 = xn(2, 5) + xn(2, 6)*u + xn(2, 8)*v + xn(2, 7)*uv
220  a31 = xn(3, 2) + xn(3, 3)*v + xn(3, 6)*w + xn(3, 7)*vw
221  a32 = xn(3, 4) + xn(3, 3)*u + xn(3, 8)*w + xn(3, 7)*uw
222  a33 = xn(3, 5) + xn(3, 6)*u + xn(3, 8)*v + xn(3, 7)*uv
223 ! compute the determinant. make sure that it is not zero
224 ! and invert the value. the cut off is needed to be able
225 ! to handle exceptional cases for degenerate elements.
226  val = a11*(a22*a33-a32*a23) + a21*(a13*a32-a12*a33) + a31*(a12*a23&
227 & -a13*a22)
228  if (val .ge. 0.) then
229  x1 = val
230  call pushcontrol1b(0)
231  else
232  x1 = -val
233  call pushcontrol1b(1)
234  end if
235  if (x1 .lt. adteps) then
236  call pushreal8(max1)
237  max1 = adteps
238  call pushcontrol1b(0)
239  else
240  call pushreal8(max1)
241  max1 = x1
242  call pushcontrol1b(1)
243  end if
244  call pushreal8(val)
245  val = sign(one, val)/max1
246 ! compute the new values of u, v and w.
247  du = val*((a22*a33-a23*a32)*f(1)+(a13*a32-a12*a33)*f(2)+(a12*a23-&
248 & a13*a22)*f(3))
249  dv = val*((a23*a31-a21*a33)*f(1)+(a11*a33-a13*a31)*f(2)+(a13*a21-&
250 & a11*a23)*f(3))
251  dw = val*((a21*a32-a22*a31)*f(1)+(a12*a31-a11*a32)*f(2)+(a11*a22-&
252 & a12*a21)*f(3))
253  call pushreal8(u)
254  u = u - du
255  call pushreal8(v)
256  v = v - dv
257  call pushreal8(w)
258  w = w - dw
259 ! exit the loop if the update of the parametric
260 ! weights is below the threshold
261  call pushreal8(val)
262  val = sqrt(du*du + dv*dv + dw*dw)
263  if (val .le. thresconv) then
264  goto 100
265  else
266  ad_count = ad_count + 1
267  end if
268  end do newtonhexa
269  call pushcontrol1b(0)
270  call pushinteger4(ad_count)
271  goto 110
272  100 call pushcontrol1b(1)
273  call pushinteger4(ad_count)
274  110 wd = fracd(3)
275  fracd(3) = 0.0_8
276  vd = fracd(2)
277  fracd(2) = 0.0_8
278  ud = fracd(1)
279  fracd(1) = 0.0_8
280  call popinteger4(ad_count)
281  do 120 i0=1,ad_count
282  if (i0 .eq. 1) then
283  call popcontrol1b(branch)
284  if (branch .eq. 0) then
285  fd = 0.0_8
286  xd = 0.0_8
287  xnd = 0.0_8
288  goto 120
289  else
290  fd = 0.0_8
291  xd = 0.0_8
292  xnd = 0.0_8
293  end if
294  end if
295  call popreal8(val)
296  call popreal8(w)
297  dwd = -wd
298  call popreal8(v)
299  dvd = -vd
300  call popreal8(u)
301  dud = -ud
302  vw = v*w
303  a21 = xn(2, 2) + xn(2, 3)*v + xn(2, 6)*w + xn(2, 7)*vw
304  uw = u*w
305  a22 = xn(2, 4) + xn(2, 3)*u + xn(2, 8)*w + xn(2, 7)*uw
306  a31 = xn(3, 2) + xn(3, 3)*v + xn(3, 6)*w + xn(3, 7)*vw
307  a32 = xn(3, 4) + xn(3, 3)*u + xn(3, 8)*w + xn(3, 7)*uw
308  a11 = xn(1, 2) + xn(1, 3)*v + xn(1, 6)*w + xn(1, 7)*vw
309  a12 = xn(1, 4) + xn(1, 3)*u + xn(1, 8)*w + xn(1, 7)*uw
310  temp2 = a11*a22 - a12*a21
311  temp1 = a12*a31 - a11*a32
312  temp0 = a21*a32 - a22*a31
313  vald = (temp0*f(1)+temp1*f(2)+temp2*f(3))*dwd
314  tempd0 = val*dwd
315  tempd1 = f(1)*tempd0
316  fd(1) = fd(1) + temp0*tempd0
317  tempd2 = f(2)*tempd0
318  fd(2) = fd(2) + temp1*tempd0
319  tempd3 = f(3)*tempd0
320  fd(3) = fd(3) + temp2*tempd0
321  a11d = a22*tempd3 - a32*tempd2
322  a22d = a11*tempd3 - a31*tempd1
323  a12d = a31*tempd2 - a21*tempd3
324  a21d = a32*tempd1 - a12*tempd3
325  a31d = a12*tempd2 - a22*tempd1
326  a32d = a21*tempd1 - a11*tempd2
327  uv = u*v
328  a23 = xn(2, 5) + xn(2, 6)*u + xn(2, 8)*v + xn(2, 7)*uv
329  a33 = xn(3, 5) + xn(3, 6)*u + xn(3, 8)*v + xn(3, 7)*uv
330  a13 = xn(1, 5) + xn(1, 6)*u + xn(1, 8)*v + xn(1, 7)*uv
331  temp2 = a13*a21 - a11*a23
332  temp1 = a11*a33 - a13*a31
333  temp0 = a23*a31 - a21*a33
334  vald = vald + (temp0*f(1)+temp1*f(2)+temp2*f(3))*dvd
335  tempd0 = val*dvd
336  tempd1 = f(1)*tempd0
337  tempd2 = f(2)*tempd0
338  tempd3 = f(3)*tempd0
339  a13d = a21*tempd3 - a31*tempd2
340  a21d = a21d + a13*tempd3 - a33*tempd1
341  a11d = a11d + a33*tempd2 - a23*tempd3
342  a23d = -(a11*tempd3)
343  a33d = a11*tempd2 - a21*tempd1
344  a31d = a31d + a23*tempd1 - a13*tempd2
345  temp = a22*a33 - a23*a32
346  tempd3 = val*dud
347  fd(1) = fd(1) + temp0*tempd0 + temp*tempd3
348  temp0 = a13*a32 - a12*a33
349  fd(2) = fd(2) + temp1*tempd0 + temp0*tempd3
350  temp1 = a12*a23 - a13*a22
351  fd(3) = fd(3) + temp2*tempd0 + temp1*tempd3
352  vald = vald + (temp*f(1)+temp0*f(2)+temp1*f(3))*dud
353  tempd0 = f(1)*tempd3
354  tempd2 = f(3)*tempd3
355  a23d = a23d + a31*tempd1 + a12*tempd2 - a32*tempd0
356  tempd1 = f(2)*tempd3
357  a12d = a12d + a23*tempd2 - a33*tempd1
358  a13d = a13d + a32*tempd1 - a22*tempd2
359  a22d = a22d + a33*tempd0 - a13*tempd2
360  a32d = a32d + a13*tempd1 - a23*tempd0
361  a33d = a33d + a22*tempd0 - a12*tempd1
362  call popreal8(val)
363  max1d = -(sign(one, val)*vald/max1**2)
364  call popcontrol1b(branch)
365  if (branch .eq. 0) then
366  call popreal8(max1)
367  x1d = 0.0_8
368  else
369  call popreal8(max1)
370  x1d = max1d
371  end if
372  call popcontrol1b(branch)
373  if (branch .eq. 0) then
374  vald = x1d
375  else
376  vald = -x1d
377  end if
378  wvud = xn(3, 7)*fd(3) + xn(2, 7)*fd(2) + xn(1, 7)*fd(1)
379  wvu = u*v*w
380  a11d = a11d + (a22*a33-a32*a23)*vald
381  tempd0 = a11*vald
382  a21d = a21d + (a13*a32-a12*a33)*vald
383  tempd1 = a21*vald
384  a31d = a31d + (a12*a23-a13*a22)*vald
385  tempd2 = a31*vald
386  a12d = a12d + a23*tempd2 - a33*tempd1
387  a23d = a23d + a12*tempd2 - a32*tempd0
388  a13d = a13d + a32*tempd1 - a22*tempd2
389  a22d = a22d + a33*tempd0 - a13*tempd2
390  a32d = a32d + a13*tempd1 - a23*tempd0
391  a33d = a33d + a22*tempd0 - a12*tempd1
392  xnd(3, 5) = xnd(3, 5) + a33d + w*fd(3)
393  xnd(3, 6) = xnd(3, 6) + u*a33d + w*a31d + uw*fd(3)
394  xnd(3, 8) = xnd(3, 8) + v*a33d + w*a32d + vw*fd(3)
395  xnd(3, 7) = xnd(3, 7) + uv*a33d + uw*a32d + vw*a31d + wvu*fd(3)
396  uvd = xn(3, 7)*a33d + xn(2, 7)*a23d + xn(1, 7)*a13d + xn(3, 3)*fd(&
397 & 3) + xn(2, 3)*fd(2) + xn(1, 3)*fd(1)
398  xnd(3, 4) = xnd(3, 4) + a32d + v*fd(3)
399  xnd(3, 3) = xnd(3, 3) + u*a32d + v*a31d + uv*fd(3)
400  uwd = xn(3, 7)*a32d + xn(2, 7)*a22d + xn(1, 7)*a12d + xn(3, 6)*fd(&
401 & 3) + xn(2, 6)*fd(2) + xn(1, 6)*fd(1)
402  ud = ud + xn(3, 6)*a33d + xn(3, 3)*a32d + xn(2, 6)*a23d + xn(2, 3)&
403 & *a22d + xn(1, 6)*a13d + xn(1, 3)*a12d + xn(3, 2)*fd(3) + xn(2, 2&
404 & )*fd(2) + xn(1, 2)*fd(1) + v*w*wvud + w*uwd + v*uvd
405  xnd(3, 2) = xnd(3, 2) + a31d + u*fd(3)
406  vwd = xn(3, 7)*a31d + xn(2, 7)*a21d + xn(1, 7)*a11d + xn(3, 8)*fd(&
407 & 3) + xn(2, 8)*fd(2) + xn(1, 8)*fd(1)
408  vd = vd + xn(3, 8)*a33d + xn(3, 3)*a31d + xn(2, 8)*a23d + xn(2, 3)&
409 & *a21d + xn(1, 8)*a13d + xn(1, 3)*a11d + xn(3, 4)*fd(3) + xn(2, 4&
410 & )*fd(2) + xn(1, 4)*fd(1) + u*w*wvud + w*vwd + u*uvd
411  wd = wd + xn(3, 8)*a32d + xn(3, 6)*a31d + xn(2, 8)*a22d + xn(2, 6)&
412 & *a21d + xn(1, 8)*a12d + xn(1, 6)*a11d + xn(3, 5)*fd(3) + xn(2, 5&
413 & )*fd(2) + xn(1, 5)*fd(1) + u*v*wvud + v*vwd + u*uwd
414  xnd(2, 5) = xnd(2, 5) + a23d + w*fd(2)
415  xnd(2, 6) = xnd(2, 6) + u*a23d + w*a21d + uw*fd(2)
416  xnd(2, 8) = xnd(2, 8) + v*a23d + w*a22d + vw*fd(2)
417  xnd(2, 7) = xnd(2, 7) + uv*a23d + uw*a22d + vw*a21d + wvu*fd(2)
418  xnd(2, 4) = xnd(2, 4) + a22d + v*fd(2)
419  xnd(2, 3) = xnd(2, 3) + u*a22d + v*a21d + uv*fd(2)
420  xnd(2, 2) = xnd(2, 2) + a21d + u*fd(2)
421  xnd(1, 5) = xnd(1, 5) + a13d + w*fd(1)
422  xnd(1, 6) = xnd(1, 6) + u*a13d + w*a11d + uw*fd(1)
423  xnd(1, 8) = xnd(1, 8) + v*a13d + w*a12d + vw*fd(1)
424  xnd(1, 7) = xnd(1, 7) + uv*a13d + uw*a12d + vw*a11d + wvu*fd(1)
425  xnd(1, 4) = xnd(1, 4) + a12d + v*fd(1)
426  xnd(1, 3) = xnd(1, 3) + u*a12d + v*a11d + uv*fd(1)
427  xnd(1, 2) = xnd(1, 2) + a11d + u*fd(1)
428  call popreal8(f(3))
429  xd(3) = xd(3) - fd(3)
430  fd(3) = 0.0_8
431  call popreal8(f(2))
432  xd(2) = xd(2) - fd(2)
433  fd(2) = 0.0_8
434  call popreal8(f(1))
435  xd(1) = xd(1) - fd(1)
436  fd(1) = 0.0_8
437  120 continue
438  xnd(3, 4) = xnd(3, 4) + xnd(3, 7) - xnd(3, 8) - xnd(3, 3)
439  xnd(3, 5) = xnd(3, 5) + xnd(3, 7) - xnd(3, 8) - xnd(3, 6)
440  xnd(2, 4) = xnd(2, 4) + xnd(2, 7) - xnd(2, 8) - xnd(2, 3)
441  xnd(2, 5) = xnd(2, 5) + xnd(2, 7) - xnd(2, 8) - xnd(2, 6)
442  xnd(1, 4) = xnd(1, 4) + xnd(1, 7) - xnd(1, 8) - xnd(1, 3)
443  xnd(1, 5) = xnd(1, 5) + xnd(1, 7) - xnd(1, 8) - xnd(1, 6)
444  xnd(3, 2) = xnd(3, 2) + xnd(3, 7) - xnd(3, 6) - xnd(3, 3)
445  xnd(2, 2) = xnd(2, 2) + xnd(2, 7) - xnd(2, 6) - xnd(2, 3)
446  xnd(1, 2) = xnd(1, 2) + xnd(1, 7) - xnd(1, 6) - xnd(1, 3)
447  xnd(3, 3) = xnd(3, 3) - xnd(3, 7)
448  xnd(3, 6) = xnd(3, 6) - xnd(3, 7)
449  xnd(3, 8) = xnd(3, 8) - xnd(3, 7)
450  xnd(2, 3) = xnd(2, 3) - xnd(2, 7)
451  xnd(2, 6) = xnd(2, 6) - xnd(2, 7)
452  xnd(2, 8) = xnd(2, 8) - xnd(2, 7)
453  xnd(1, 3) = xnd(1, 3) - xnd(1, 7)
454  xnd(1, 6) = xnd(1, 6) - xnd(1, 7)
455  xnd(1, 8) = xnd(1, 8) - xnd(1, 7)
456  xcend = 0.0_8
457  xcend = xd
458  xnd(:, 1) = xnd(:, 1) - xd
459  do i=8,2,-1
460  tmpd = xnd(:, i)
461  xnd(:, i) = tmpd
462  xnd(:, 1) = xnd(:, 1) - tmpd
463  end do
464  do k=2,1,-1
465  do j=2,1,-1
466  do i=2,1,-1
467  tempd = eighth*xnd(:, indices(ii))
468  xnd(:, indices(ii)) = 0.0_8
469  blkd(i, j, k, :) = blkd(i, j, k, :) + tempd
470  blkd(i+1, j, k, :) = blkd(i+1, j, k, :) + tempd
471  blkd(i, j+1, k, :) = blkd(i, j+1, k, :) + tempd
472  blkd(i+1, j+1, k, :) = blkd(i+1, j+1, k, :) + tempd
473  blkd(i, j, k+1, :) = blkd(i, j, k+1, :) + tempd
474  blkd(i+1, j, k+1, :) = blkd(i+1, j, k+1, :) + tempd
475  blkd(i, j+1, k+1, :) = blkd(i, j+1, k+1, :) + tempd
476  blkd(i+1, j+1, k+1, :) = blkd(i+1, j+1, k+1, :) + tempd
477  call popinteger4(ii)
478  end do
479  end do
480  end do
481  end subroutine newtonupdate_b
482 
483  subroutine newtonupdate(xcen, blk, frac0, frac)
484 ! this routine performs the newton update to recompute the new
485 ! "frac" (u,v,w) for the point xcen. the actual search is performed
486 ! on the the dual cell formed by the cell centers of the 3x3x3 block
487 ! of primal nodes. this routine is ad'd with tapenade in both
488 ! forward and reverse.
489  use constants
490  implicit none
491 ! input
492  real(kind=realtype), dimension(3), intent(in) :: xcen
493  real(kind=realtype), dimension(3, 3, 3, 3), intent(in) :: blk
494  real(kind=realtype), dimension(3), intent(in) :: frac0
495 ! output
496  real(kind=realtype), dimension(3), intent(out) :: frac
497 ! working
498  real(kind=realtype), dimension(3, 8) :: xn
499  real(kind=realtype) :: u, v, w, uv, uw, vw, wvu, du, dv, dw
500  real(kind=realtype) :: a11, a12, a13, a21, a22, a23, a31, a32, a33, &
501 & val
502  real(kind=realtype) :: f(3), x(3)
503  integer(kind=inttype), dimension(8), parameter :: indices=(/1, 2, 4&
504 & , 3, 5, 6, 8, 7/)
505  integer(kind=inttype) :: i, j, k, ii, ll
506  real(kind=realtype), parameter :: adteps=1.e-25_realtype
507  real(kind=realtype), parameter :: thresconv=1.e-10_realtype
508  intrinsic sign
509  intrinsic abs
510  intrinsic max
511  intrinsic sqrt
512  real(kind=realtype) :: x1
513  real(kind=realtype) :: max1
514 ! compute the cell center locations for the 8 nodes describing the
515 ! dual cell. note that this must be counter-clockwise ordering.
516  ii = 0
517  do k=1,2
518  do j=1,2
519  do i=1,2
520  ii = ii + 1
521  xn(:, indices(ii)) = eighth*(blk(i, j, k, :)+blk(i+1, j, k, :)&
522 & +blk(i, j+1, k, :)+blk(i+1, j+1, k, :)+blk(i, j, k+1, :)+blk&
523 & (i+1, j, k+1, :)+blk(i, j+1, k+1, :)+blk(i+1, j+1, k+1, :))
524  end do
525  end do
526  end do
527 ! compute the coordinates relative to node 1.
528  do i=2,8
529  xn(:, i) = xn(:, i) - xn(:, 1)
530  end do
531 ! compute the location of our seach point relative to the first node.
532  x = xcen - xn(:, 1)
533 ! modify the coordinates of node 3, 6, 8 and 7 such that
534 ! they correspond to the weights of the u*v, u*w, v*w and
535 ! u*v*w term in the transformation respectively.
536  xn(1, 7) = xn(1, 7) + xn(1, 2) + xn(1, 4) + xn(1, 5) - xn(1, 3) - xn&
537 & (1, 6) - xn(1, 8)
538  xn(2, 7) = xn(2, 7) + xn(2, 2) + xn(2, 4) + xn(2, 5) - xn(2, 3) - xn&
539 & (2, 6) - xn(2, 8)
540  xn(3, 7) = xn(3, 7) + xn(3, 2) + xn(3, 4) + xn(3, 5) - xn(3, 3) - xn&
541 & (3, 6) - xn(3, 8)
542  xn(1, 3) = xn(1, 3) - xn(1, 2) - xn(1, 4)
543  xn(2, 3) = xn(2, 3) - xn(2, 2) - xn(2, 4)
544  xn(3, 3) = xn(3, 3) - xn(3, 2) - xn(3, 4)
545  xn(1, 6) = xn(1, 6) - xn(1, 2) - xn(1, 5)
546  xn(2, 6) = xn(2, 6) - xn(2, 2) - xn(2, 5)
547  xn(3, 6) = xn(3, 6) - xn(3, 2) - xn(3, 5)
548  xn(1, 8) = xn(1, 8) - xn(1, 4) - xn(1, 5)
549  xn(2, 8) = xn(2, 8) - xn(2, 4) - xn(2, 5)
550  xn(3, 8) = xn(3, 8) - xn(3, 4) - xn(3, 5)
551 ! set the starting values of u, v and w based on our previous values
552  u = frac0(1)
553  v = frac0(2)
554  w = frac0(3)
555 ! the newton algorithm to determine the parametric
556 ! weights u, v and w for the given coordinate.
557 newtonhexa:do ll=1,15
558 ! compute the rhs.
559  uv = u*v
560  uw = u*w
561  vw = v*w
562  wvu = u*v*w
563  f(1) = xn(1, 2)*u + xn(1, 4)*v + xn(1, 5)*w + xn(1, 3)*uv + xn(1, &
564 & 6)*uw + xn(1, 8)*vw + xn(1, 7)*wvu - x(1)
565  f(2) = xn(2, 2)*u + xn(2, 4)*v + xn(2, 5)*w + xn(2, 3)*uv + xn(2, &
566 & 6)*uw + xn(2, 8)*vw + xn(2, 7)*wvu - x(2)
567  f(3) = xn(3, 2)*u + xn(3, 4)*v + xn(3, 5)*w + xn(3, 3)*uv + xn(3, &
568 & 6)*uw + xn(3, 8)*vw + xn(3, 7)*wvu - x(3)
569 ! compute the jacobian.
570  a11 = xn(1, 2) + xn(1, 3)*v + xn(1, 6)*w + xn(1, 7)*vw
571  a12 = xn(1, 4) + xn(1, 3)*u + xn(1, 8)*w + xn(1, 7)*uw
572  a13 = xn(1, 5) + xn(1, 6)*u + xn(1, 8)*v + xn(1, 7)*uv
573  a21 = xn(2, 2) + xn(2, 3)*v + xn(2, 6)*w + xn(2, 7)*vw
574  a22 = xn(2, 4) + xn(2, 3)*u + xn(2, 8)*w + xn(2, 7)*uw
575  a23 = xn(2, 5) + xn(2, 6)*u + xn(2, 8)*v + xn(2, 7)*uv
576  a31 = xn(3, 2) + xn(3, 3)*v + xn(3, 6)*w + xn(3, 7)*vw
577  a32 = xn(3, 4) + xn(3, 3)*u + xn(3, 8)*w + xn(3, 7)*uw
578  a33 = xn(3, 5) + xn(3, 6)*u + xn(3, 8)*v + xn(3, 7)*uv
579 ! compute the determinant. make sure that it is not zero
580 ! and invert the value. the cut off is needed to be able
581 ! to handle exceptional cases for degenerate elements.
582  val = a11*(a22*a33-a32*a23) + a21*(a13*a32-a12*a33) + a31*(a12*a23&
583 & -a13*a22)
584  if (val .ge. 0.) then
585  x1 = val
586  else
587  x1 = -val
588  end if
589  if (x1 .lt. adteps) then
590  max1 = adteps
591  else
592  max1 = x1
593  end if
594  val = sign(one, val)/max1
595 ! compute the new values of u, v and w.
596  du = val*((a22*a33-a23*a32)*f(1)+(a13*a32-a12*a33)*f(2)+(a12*a23-&
597 & a13*a22)*f(3))
598  dv = val*((a23*a31-a21*a33)*f(1)+(a11*a33-a13*a31)*f(2)+(a13*a21-&
599 & a11*a23)*f(3))
600  dw = val*((a21*a32-a22*a31)*f(1)+(a12*a31-a11*a32)*f(2)+(a11*a22-&
601 & a12*a21)*f(3))
602  u = u - du
603  v = v - dv
604  w = w - dw
605 ! exit the loop if the update of the parametric
606 ! weights is below the threshold
607  val = sqrt(du*du + dv*dv + dw*dw)
608  if (val .le. thresconv) goto 100
609  end do newtonhexa
610 ! we would *like* that all solutions fall inside the hexa, but we
611 ! can't be picky here since we are not changing the donors. so
612 ! whatever the u,v,w is we have to accept. even if it is greater than
613 ! 1 or less than zero, it shouldn't be by much.
614  100 frac(1) = u
615  frac(2) = v
616  frac(3) = w
617  end subroutine newtonupdate
618 
619 end module oversetutilities_b
620 
real(kind=realtype), parameter eighth
Definition: constants.F90:84
real(kind=realtype), parameter one
Definition: constants.F90:72
subroutine fractoweights(frac, weights)
subroutine fractoweights_b(frac, fracd, weights, weightsd)
subroutine newtonupdate(xcen, blk, frac0, frac)
subroutine newtonupdate_b(xcen, xcend, blk, blkd, frac0, frac, fracd)
subroutine fractoweights2(frac, weights)