ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
getAreas.f90
Go to the documentation of this file.
1 subroutine getareas(areas, pts, npts, sps_in, axis)
2  use constants
3  use blockpointers
6  use communication
7  use inputphysics
8  use utils, only: setpointers
9  implicit none
10  !
11  ! Local variables.
12  !
13  integer(kind=intType), intent(in) :: npts, sps_in
14  real(kind=realtype), intent(in) :: pts(3, npts), axis(3)
15  real(kind=realtype), intent(out) :: areas(3, npts)
16 
17  integer(kind=intType) :: mm, nn, i, j, ii, sps
18  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd
19  integer(kind=intType) :: lower_left, lower_right, upper_left, upper_right
20  real(kind=realtype) :: da, fact, fact2
21 
22  areas = zero
23  sps = sps_in
24 
25  ! Compute the local forces (or tractions). Take the scaling
26  ! factor into account to obtain the forces in SI-units,
27  ! i.e. Newton.
28  ii = 0
29  domains: do nn = 1, ndom
30  call setpointers(nn, 1_inttype, sps)
31  if (flowdoms(nn, 1_inttype, sps)%rightHanded) then
32  fact2 = one
33  else
34  fact2 = -one
35  end if
36 
37  ! Loop over the number of boundary subfaces of this block.
38  bocos: do mm = 1, nbocos
39 
40  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
41  bctype(mm) == nswallisothermal) then
42 
43  select case (bcfaceid(mm))
44 
45  ! NOTE: The 'fact' here are NOT the same as you will
46  ! find in ForcesAndMoment.f90. The reason is that, we
47  ! are not using points to si, sj, sk. Those have teh
48  ! normals pointing in the direction of increasing
49  ! {i,j,k}. Here we are evaluating the normal from
50  ! directly from the coordinates on the faces. As it
51  ! happens, the normals for the jMin and jMax faces are
52  ! flipped.
53  case (imin)
54  fact = one
55  case (imax)
56  fact = -one
57  case (jmin)
58  fact = -one
59  case (jmax)
60  fact = one
61  case (kmin)
62  fact = one
63  case (kmax)
64  fact = -one
65  end select
66 
67  ! Store the cell range of the subfaces a bit easier.
68  ! As only owned faces must be considered the nodal range
69  ! in BCData must be used to obtain this data.
70 
71  jbeg = bcdata(mm)%jnBeg + 1; jend = bcdata(mm)%jnEnd
72  ibeg = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
73 
74  ! Compute the dual area at each node. Just store in first dof
75  do j = jbeg, jend ! This is a face loop
76  do i = ibeg, iend ! This is a face loop
77 
78  ! Compute Normal
79 
80  lower_left = ii + (j - jbeg) * (iend - ibeg + 2) + i - ibeg + 1
81  lower_right = lower_left + 1
82  upper_left = lower_right + iend - ibeg + 1
83  upper_right = upper_left + 1
84 
85  call quad_area( &
86  pts(:, lower_left), pts(:, lower_right), &
87  pts(:, upper_left), pts(:, upper_right), &
88  axis, da)
89  da = fourth * da * fact * fact2
90 
91  if (da > zero) then
92  ! Scatter to nodes
93  areas(1, lower_left) = areas(1, lower_left) + da
94  areas(1, lower_right) = areas(1, lower_right) + da
95  areas(1, upper_left) = areas(1, upper_left) + da
96  areas(1, upper_right) = areas(1, upper_right) + da
97  end if
98  end do
99  end do
100 
101  ! Note how iBeg,iBeg is defined above... it is one MORE
102  ! then the starting node (used for looping over faces, not
103  ! nodes)
104  ii = ii + (jend - jbeg + 2) * (iend - ibeg + 2)
105 
106  end if
107  end do bocos
108  end do domains
109 end subroutine getareas
110 
111 subroutine getareasensitivity(darea, pts, npts, sps_in, axis)
112  use constants
113  use blockpointers
114  use flowvarrefstate
116  use communication
117  use inputphysics
118  use utils, only: setpointers
119  implicit none
120  !
121  ! Local variables.
122  !
123  integer(kind=intType), intent(in) :: npts, sps_in
124  real(kind=realtype), intent(in) :: pts(3, npts), axis(3)
125  real(kind=realtype), intent(out) :: darea(3, npts)
126 
127  integer(kind=intType) :: mm, nn, i, j, ii, sps
128  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd
129  integer(kind=intType) :: lower_left, lower_right, upper_left, upper_right
130  real(kind=realtype) :: area, areab, pt1b(3), pt2b(3), pt3b(3), pt4b(3)
131  real(kind=realtype) :: fact, fact2, da
132 
133  darea = zero
134  sps = sps_in
135 
136  ! Compute the local forces (or tractions). Take the scaling
137  ! factor into account to obtain the forces in SI-units,
138  ! i.e. Newton.
139  ii = 0
140  domains: do nn = 1, ndom
141  call setpointers(nn, 1_inttype, sps)
142  if (flowdoms(nn, 1_inttype, sps)%rightHanded) then
143  fact2 = one
144  else
145  fact2 = -one
146  end if
147 
148  ! Loop over the number of boundary subfaces of this block.
149  bocos: do mm = 1, nbocos
150 
151  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
152  bctype(mm) == nswallisothermal) then
153 
154  select case (bcfaceid(mm))
155 
156  ! NOTE: The 'fact' here are NOT the same as you will
157  ! find in ForcesAndMoment.f90. The reason is that, we
158  ! are not using points to si, sj, sk. Those have teh
159  ! normals pointing in the direction of increasing
160  ! {i,j,k}. Here we are evaluating the normal from
161  ! directly from the coordinates on the faces. As it
162  ! happens, the normals for the jMin and jMax faces are
163  ! flipped.
164  case (imin)
165  fact = one
166  case (imax)
167  fact = -one
168  case (jmin)
169  fact = -one
170  case (jmax)
171  fact = one
172  case (kmin)
173  fact = one
174  case (kmax)
175  fact = -one
176  end select
177 
178  ! Store the cell range of the subfaces a bit easier.
179  ! As only owned faces must be considered the nodal range
180  ! in BCData must be used to obtain this data.
181 
182  jbeg = bcdata(mm)%jnBeg + 1; jend = bcdata(mm)%jnEnd
183  ibeg = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
184 
185  do j = jbeg, jend ! This is a face loop
186  do i = ibeg, iend ! This is a face loop
187 
188  ! Extract 4 corner points
189  lower_left = ii + (j - jbeg) * (iend - ibeg + 2) + i - ibeg + 1
190  lower_right = lower_left + 1
191  upper_left = lower_right + iend - ibeg + 1
192  upper_right = upper_left + 1
193 
194  ! Compute actual area since we need to know to
195  ! include or not. The reverse mode calc does NOT
196  ! compute area
197  call quad_area( &
198  pts(:, lower_left), pts(:, lower_right), &
199  pts(:, upper_left), pts(:, upper_right), &
200  axis, da)
201 
202  da = fourth * da * fact * fact2
203  if (da > zero) then
204 
205  areab = one
206  call quad_area_b( &
207  pts(:, lower_left), pt1b, &
208  pts(:, lower_right), pt2b, &
209  pts(:, upper_left), pt3b, &
210  pts(:, upper_right), pt4b, &
211  axis, area, areab)
212 
213  darea(:, lower_left) = darea(:, lower_left) + pt1b
214  darea(:, lower_right) = darea(:, lower_right) + pt2b
215  darea(:, upper_left) = darea(:, upper_left) + pt3b
216  darea(:, upper_right) = darea(:, upper_right) + pt4b
217  end if
218  end do
219  end do
220 
221  ! Note how iBeg,iBeg is defined above... it is one MORE
222  ! then the starting node (used for looping over faces, not
223  ! nodes)
224  ii = ii + (jend - jbeg + 2) * (iend - ibeg + 2)
225 
226  end if
227  end do bocos
228  end do domains
229 end subroutine getareasensitivity
230 
231 subroutine quad_area(p1, p2, p3, p4, axis, area)
232  ! Kernel-level function to get area of quad defined by 4 points
233  ! projected onto plane defined by axis. Only +ve areas are computed.
234  use constants
235  implicit none
236 
237  ! I/O
238  real(kind=realtype), intent(in) :: p1(3), p2(3), p3(3), p4(3), axis(3)
239  real(kind=realtype), intent(out) :: area
240 
241  ! Working
242  real(kind=realtype) :: v1(3), v2(3), sss(3)
243  ! Vectors for Cross Product
244 
245  v1(:) = p4 - p1
246  v2(:) = p3 - p2
247 
248  ! Cross Product
249  sss(1) = half * (v1(2) * v2(3) - v1(3) * v2(2))
250  sss(2) = half * (v1(3) * v2(1) - v1(1) * v2(3))
251  sss(3) = half * (v1(1) * v2(2) - v1(2) * v2(1))
252 
253  area = sss(1) * axis(1) + sss(2) * axis(2) + sss(3) * axis(3)
254 
255 end subroutine quad_area
256 
257 ! Generated by TAPENADE (INRIA, Tropics team)
258 ! Tapenade 3.4 (r3375) - 10 Feb 2010 15:08
259 !
260 ! Differentiation of quad_area in reverse (adjoint) mode:
261 ! gradient of useful results: area
262 ! with respect to varying inputs: area p1 p2 p3 p4
263 ! RW status of diff variables: area:in-zero p1:out p2:out p3:out
264 ! p4:out
265 SUBROUTINE quad_area_b(p1, p1b, p2, p2b, p3, p3b, p4, p4b, axis, area, &
266 & areab)
267  use constants
268  IMPLICIT NONE
269 ! Kernel-level function to get area of quad defined by 4 points
270 ! projected onto plane defined by axis. Only +ve areas are computed.
271 ! I/O
272  REAL(kind=realtype), INTENT(IN) :: p1(3), p2(3), p3(3), p4(3), axis(3)
273  REAL(kind=realtype) :: p1b(3), p2b(3), p3b(3), p4b(3)
274  REAL(kind=realtype) :: area
275  REAL(kind=realtype) :: areab
276 ! Working
277  REAL(kind=realtype) :: v1(3), v2(3), sss(3)
278  REAL(kind=realtype) :: v1b(3), v2b(3), sssb(3)
279  REAL(kind=realtype) :: tempb1
280  REAL(kind=realtype) :: tempb0
281  INTRINSIC abs
282  REAL(kind=realtype) :: tempb
283 ! Vectors for Cross Product
284  v1(:) = p4 - p1
285  v2(:) = p3 - p2
286 ! Cross Product
287  sss(1) = half * (v1(2) * v2(3) - v1(3) * v2(2))
288  sss(2) = half * (v1(3) * v2(1) - v1(1) * v2(3))
289  sss(3) = half * (v1(1) * v2(2) - v1(2) * v2(1))
290  IF (sss(1) * axis(1) + sss(2) * axis(2) + sss(3) * axis(3) .GE. 0.) THEN
291  sssb = 0.0
292  sssb(1) = axis(1) * areab
293  sssb(2) = axis(2) * areab
294  sssb(3) = axis(3) * areab
295  ELSE
296  sssb = 0.0
297  sssb(1) = -(axis(1) * areab)
298  sssb(2) = -(axis(2) * areab)
299  sssb(3) = -(axis(3) * areab)
300  END IF
301  v1b = 0.0
302  v2b = 0.0
303  tempb = half * sssb(3)
304  v1b(1) = v2(2) * tempb
305  v2b(2) = v1(1) * tempb
306  v1b(2) = -(v2(1) * tempb)
307  sssb(3) = 0.0
308  tempb0 = half * sssb(2)
309  v2b(1) = v1(3) * tempb0 - v1(2) * tempb
310  v1b(3) = v1b(3) + v2(1) * tempb0
311  v1b(1) = v1b(1) - v2(3) * tempb0
312  sssb(2) = 0.0
313  tempb1 = half * sssb(1)
314  v2b(3) = v2b(3) + v1(2) * tempb1 - v1(1) * tempb0
315  v1b(2) = v1b(2) + v2(3) * tempb1
316  v1b(3) = v1b(3) - v2(2) * tempb1
317  v2b(2) = v2b(2) - v1(3) * tempb1
318  p2b = 0.0
319  p3b = 0.0
320  p3b = v2b(:)
321  p2b = -v2b(:)
322  p1b = 0.0
323  p4b = 0.0
324  p4b = v1b(:)
325  p1b = -v1b(:)
326  areab = 0.0
327 END SUBROUTINE quad_area_b
subroutine getareas(areas, pts, npts, sps_in, axis)
Definition: getAreas.f90:2
subroutine getareasensitivity(darea, pts, npts, sps_in, axis)
Definition: getAreas.f90:112
subroutine quad_area_b(p1, p1b, p2, p2b, p3, p3b, p4, p4b, axis, area, areab)
Definition: getAreas.f90:267
subroutine quad_area(p1, p2, p3, p4, axis, area)
Definition: getAreas.f90:232
Definition: BCData.F90:1
integer(kind=inttype), dimension(:), pointer bcfaceid
integer(kind=inttype) nbocos
integer(kind=inttype), dimension(:), pointer bctype
integer(kind=inttype), parameter eulerwall
Definition: constants.F90:262
real(kind=realtype), parameter zero
Definition: constants.F90:71
integer(kind=inttype), parameter imax
Definition: constants.F90:293
integer(kind=inttype), parameter kmin
Definition: constants.F90:296
integer(kind=inttype), parameter jmax
Definition: constants.F90:295
integer(kind=inttype), parameter nswalladiabatic
Definition: constants.F90:260
real(kind=realtype), parameter one
Definition: constants.F90:72
real(kind=realtype), parameter half
Definition: constants.F90:80
integer(kind=inttype), parameter imin
Definition: constants.F90:292
real(kind=realtype), parameter fourth
Definition: constants.F90:82
integer(kind=inttype), parameter nswallisothermal
Definition: constants.F90:261
integer(kind=inttype), parameter kmax
Definition: constants.F90:297
integer(kind=inttype), parameter jmin
Definition: constants.F90:294
Definition: utils.F90:1
subroutine setpointers(nn, mm, ll)
Definition: utils.F90:3237