ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
getForces.F90
Go to the documentation of this file.
1 
2 subroutine getforces(forces, npts, sps)
3  use constants
4  use communication, only: myid
5  use blockpointers, only: bcdata, ndom, nbocos, bctype
7  use utils, only: setpointers, terminate, echk
12 #include <petsc/finclude/petsc.h>
13  use petsc
14  implicit none
15  integer(kind=intType), intent(in) :: npts, sps
16  real(kind=realtype), intent(inout) :: forces(3, npts)
17 
18  integer(kind=intType) :: mm, nn, i, j, ii, jj, iDim, ierr
19  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd
20  real(kind=realtype) :: sss(3), v2(3), v1(3), qa, sepsensor, cavitation
21  real(kind=realtype) :: sepsensoravg(3)
22  real(kind=realtype) :: fp(3), fv(3), mp(3), mv(3), yplusmax, qf(3)
23  real(kind=realtype) :: localvalues(nlocalvalues)
24  type(zippermesh), pointer :: zipper
25  type(familyexchange), pointer :: exch
26  real(kind=realtype), dimension(:), pointer :: localptr
27  real(kind=realtype), dimension(nCostFunction) :: funcvalues
28  ! Make sure *all* forces are computed. Sectioning will be done
29  ! else-where.
30 
31  domains: do nn = 1, ndom
32  call setpointers(nn, 1_inttype, sps)
33  localvalues = zero
34  call integratesurfaces(localvalues, fullfamlist)
35  end do domains
36 
37  if (forcesastractions) then
38  ! Compute tractions if necessary
39  call computenodaltractions(sps)
40  else
41  call computenodalforces(sps)
42  end if
43 
44  ii = 0
45  domains2: do nn = 1, ndom
46  call setpointers(nn, 1_inttype, sps)
47 
48  ! Loop over the number of boundary subfaces of this block.
49  bocos: do mm = 1, nbocos
50  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
51  bctype(mm) == nswallisothermal) then
52 
53  ! This is easy, just copy out F or T in continuous ordering.
54  do j = bcdata(mm)%jnBeg, bcdata(mm)%jnEnd
55  do i = bcdata(mm)%inBeg, bcdata(mm)%inEnd
56  ii = ii + 1
57  if (forcesastractions) then
58  forces(:, ii) = bcdata(mm)%Tp(i, j, :) + bcdata(mm)%Tv(i, j, :)
59  else
60  forces(:, ii) = bcdata(mm)%F(i, j, :)
61  end if
62  end do
63  end do
64  end if
65  end do bocos
66  end do domains2
67 
68  ! We know must consider additional forces that are required by the
69  ! zipper mesh triangles on the root proc.
70 
71  ! Pointer for easier reading.
72  zipper => zippermeshes(ibcgroupwalls)
73  exch => bcfamexchange(ibcgroupwalls, sps)
74  ! No overset present or the zipper isn't allocated nothing to do:
75  if (.not. oversetpresent .or. .not. zipper%allocated) then
76  return
77  end if
78 
79  if (.not. forcesastractions) then
80  ! We have a zipper and regular forces are requested. This is not yet supported.
81  call terminate('getForces', 'getForces() is not implmented for zipper meshes and '&
82  &'forcesAsTractions=False')
83  end if
84 
85  ! Loop over each dimension individually since we have a scalar
86  ! scatter.
87  dimloop: do idim = 1, 3
88 
89  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
90  call echk(ierr, __file__, __line__)
91 
92  ! Copy in the values we already have to the exchange.
93  ii = size(localptr)
94  localptr = forces(idim, 1:ii)
95 
96  ! Restore the pointer
97  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
98  call echk(ierr, __file__, __line__)
99 
100  ! Now scatter this to the zipper
101  call vecscatterbegin(zipper%scatter, exch%nodeValLocal, &
102  zipper%localVal, insert_values, scatter_forward, ierr)
103  call echk(ierr, __file__, __line__)
104 
105  call vecscatterend(zipper%scatter, exch%nodeValLocal, &
106  zipper%localVal, insert_values, scatter_forward, ierr)
107  call echk(ierr, __file__, __line__)
108 
109  ! The values we need are precisely what is in zipper%localVal
110  call vecgetarrayf90(zipper%localVal, localptr, ierr)
111  call echk(ierr, __file__, __line__)
112 
113  ! Just copy the received data into the forces array. Just on root proc:
114  if (myid == 0) then
115  forces(idim, ii + 1:ii + size(localptr)) = localptr
116  end if
117 
118  call vecgetarrayf90(zipper%localVal, localptr, ierr)
119  call echk(ierr, __file__, __line__)
120  end do dimloop
121 
122 end subroutine getforces
123 
124 subroutine getforces_d(forces, forcesd, npts, sps)
125 
126  ! This routine performs the forward mode linearization getForces. It
127  ! takes in perturbations defined on bcData(mm)%Fp, bcData(mm)%Fv and
128  ! bcData(mm)%area and computes either the nodal forces or nodal
129  ! tractions.
130  use constants
131  use communication, only: myid
132  use blockpointers, only: ndom, nbocos, bcdata, bctype, nbocos, bcdatad
138 #include <petsc/finclude/petsc.h>
139  use petsc
140  implicit none
141  integer(kind=intType), intent(in) :: npts, sps
142  real(kind=realtype), intent(out), dimension(3, npts) :: forces, forcesd
143  integer(kind=intType) :: mm, nn, i, j, ii, jj, iDim, ierr
144  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd, ind(4), ni, nj
145  real(kind=realtype) :: qa, qad, qf, qfd
146  real(kind=realtype), dimension(:), pointer :: localptr, localptrd
147  type(zippermesh), pointer :: zipper
148  type(familyexchange), pointer :: exch
149 
150  if (forcesastractions) then
151  call computenodaltractions_d(sps)
152  else
153  call computenodalforces_d(sps)
154  end if
155 
156  ! Extract the values out into the output derivative array
157  ii = 0
158  domains2: do nn = 1, ndom
159  call setpointers_d(nn, 1_inttype, sps)
160 
161  ! Loop over the number of boundary subfaces of this block.
162  bocos: do mm = 1, nbocos
163  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
164  bctype(mm) == nswallisothermal) then
165 
166  ! This is easy, just copy out F or T in continuous ordering.
167  do j = bcdata(mm)%jnBeg, bcdata(mm)%jnEnd
168  do i = bcdata(mm)%inBeg, bcdata(mm)%inEnd
169  ii = ii + 1
170  if (forcesastractions) then
171  forcesd(:, ii) = bcdatad(mm)%Tp(i, j, :) + bcdatad(mm)%Tv(i, j, :)
172  else
173  forcesd(:, ii) = bcdatad(mm)%F(i, j, :)
174  end if
175  end do
176  end do
177  end if
178  end do bocos
179  end do domains2
180 
181  ! We know must consider additional forces that are required by the
182  ! zipper mesh triangles on the root proc.
183 
184  ! Pointer for easier reading.
185  zipper => zippermeshes(ibcgroupwalls)
186  exch => bcfamexchange(ibcgroupwalls, sps)
187  ! No overset present or the zipper isn't allocated nothing to do:
188  if (.not. oversetpresent .or. .not. zipper%allocated) then
189  return
190  end if
191 
192  if (.not. forcesastractions) then
193  ! We have a zipper and regular forces are requested. This is not yet supported.
194  call terminate('getForces', 'getForces() is not implmented for zipper meshes and '&
195  &'forcesAsTractions=False')
196  end if
197 
198  ! Loop over each dimension individually since we have a scalar
199  ! scatter.
200  dimloop: do idim = 1, 3
201 
202  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
203  call echk(ierr, __file__, __line__)
204 
205  ! Copy in the values we already have to the exchange.
206  ii = size(localptr)
207  localptr = forcesd(idim, 1:ii)
208 
209  ! Restore the pointer
210  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
211  call echk(ierr, __file__, __line__)
212 
213  ! Now scatter this to the zipper
214  call vecscatterbegin(zipper%scatter, exch%nodeValLocal, &
215  zipper%localVal, insert_values, scatter_forward, ierr)
216  call echk(ierr, __file__, __line__)
217 
218  call vecscatterend(zipper%scatter, exch%nodeValLocal, &
219  zipper%localVal, insert_values, scatter_forward, ierr)
220  call echk(ierr, __file__, __line__)
221 
222  ! The values we need are precisely what is in zipper%localVal
223  call vecgetarrayf90(zipper%localVal, localptr, ierr)
224  call echk(ierr, __file__, __line__)
225 
226  ! Just copy the received data into the forces array. Just on root proc:
227  if (myid == 0) then
228  forcesd(idim, ii + 1:ii + size(localptr)) = localptr
229  end if
230 
231  call vecgetarrayf90(zipper%localVal, localptr, ierr)
232  call echk(ierr, __file__, __line__)
233  end do dimloop
234 
235 end subroutine getforces_d
236 
237 subroutine getforces_b(forcesd, npts, sps)
238 
239  ! This routine performs the reverse of getForces. It takes in
240  ! forces_b and perfroms the reverse of the nodal averaging procedure
241  ! in getForces to compute bcDatad(mm)%Fp, bcDatad(mm)%Fv and
242  ! bcDatad(mm)%area.
243  use constants
244  use communication, only: myid
245  use blockpointers, only: ndom, nbocos, bcdata, bctype, nbocos, bcdatad
248  use utils, only: echk, setpointers, setpointers_d
251 #include <petsc/finclude/petsc.h>
252  use petsc
253  implicit none
254  integer(kind=intType), intent(in) :: npts, sps
255  real(kind=realtype), intent(inout) :: forcesd(3, npts)
256  integer(kind=intType) :: mm, nn, i, j, ii, iDim, ierr
257  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd
258  type(zippermesh), pointer :: zipper
259  type(familyexchange), pointer :: exch
260  real(kind=realtype), dimension(:), pointer :: localptr
261  real(kind=realtype), dimension(3, npts) :: forces
262 
263  ! Run nonlinear code to make sure that all intermediate values are
264  ! updated.
265  call getforces(forces, npts, sps)
266 
267  ! We know must consider additional forces that are required by the
268  ! zipper mesh triangles on the root proc.
269 
270  ! Pointer for easier reading.
271  zipper => zippermeshes(ibcgroupwalls)
272  exch => bcfamexchange(ibcgroupwalls, sps)
273  ! No overset present or the zipper isn't allocated nothing to do:
274  zipperreverse: if (oversetpresent .and. zipper%allocated) then
275 
276  ! Loop over each dimension individually since we have a scalar
277  ! scatter.
278  dimloop: do idim = 1, 3
279 
280  call vecgetarrayf90(zipper%localVal, localptr, ierr)
281  call echk(ierr, __file__, __line__)
282 
283  ii = exch%nNodes
284  ! Just copy the received data into the forces array. Just on root proc:
285  if (myid == 0) then
286  do i = 1, size(localptr)
287  localptr(i) = forcesd(idim, ii + i)
288  forcesd(idim, ii + i) = zero
289  end do
290  end if
291 
292  call vecgetarrayf90(zipper%localVal, localptr, ierr)
293  call echk(ierr, __file__, __line__)
294 
295  ! Zero the vector we are scatting into:
296  call vecset(exch%nodeValLocal, zero, ierr)
297  call echk(ierr, __file__, __line__)
298 
299  ! Scatter values from the root using the zipper scatter.
300  call vecscatterbegin(zipper%scatter, zipper%localVal, &
301  exch%nodeValLocal, add_values, scatter_reverse, ierr)
302  call echk(ierr, __file__, __line__)
303 
304  call vecscatterend(zipper%scatter, zipper%localVal, &
305  exch%nodeValLocal, add_values, scatter_reverse, ierr)
306  call echk(ierr, __file__, __line__)
307 
308  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
309  call echk(ierr, __file__, __line__)
310 
311  ! Accumulate the scatted values onto forcesd
312  ii = size(localptr)
313  forcesd(idim, 1:ii) = forcesd(idim, 1:ii) + localptr
314 
315  ! Restore the pointer
316  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
317  call echk(ierr, __file__, __line__)
318 
319  end do dimloop
320  end if zipperreverse
321 
322  ! Set the incoming derivative values
323  ii = 0
324  domains2: do nn = 1, ndom
325  call setpointers_d(nn, 1_inttype, sps)
326 
327  ! Loop over the number of boundary subfaces of this block.
328  bocos: do mm = 1, nbocos
329  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
330  bctype(mm) == nswallisothermal) then
331  ! This is easy, just copy out F or T in continuous ordering.
332  do j = bcdata(mm)%jnBeg, bcdata(mm)%jnEnd
333  do i = bcdata(mm)%inBeg, bcdata(mm)%inEnd
334  ii = ii + 1
335  if (forcesastractions) then
336  bcdatad(mm)%Tp(i, j, :) = forcesd(:, ii)
337  bcdatad(mm)%Tv(i, j, :) = forcesd(:, ii)
338  else
339  bcdatad(mm)%F(i, j, :) = forcesd(:, ii)
340  end if
341  end do
342  end do
343  end if
344  end do bocos
345  end do domains2
346 
347  if (.not. forcesastractions) then
348  ! For forces, we can accumulate the nodal seeds on the Fp and Fv
349  ! values. The area seed is zeroed.
350  call computenodalforces_b(sps)
351  else
352  call computenodaltractions_b(sps)
353  end if
354 
355 end subroutine getforces_b
356 
357 subroutine surfacecellcentertonode(exch)
358 
359  use constants
360  use blockpointers, only: bcdata, ndom, nbocos, bctype
362  use utils, only: setpointers, echk
363  use sorting, only: faminlist
364 #include <petsc/finclude/petsc.h>
365  use petsc
366  implicit none
367 
368  type(familyexchange) :: exch
369  integer(kind=intType) :: sps
370  integer(kind=intType) :: mm, nn, i, j, ii, jj, idim, ierr
371  integer(kind=intType) :: ibeg, iend, jbeg, jend, ind(4), ni, nj
372  real(kind=realtype) :: qv
373  real(kind=realtype), dimension(:), pointer :: localptr
374 
375  ! We assume that normalization factor is already computed
376  sps = exch%sps
377  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
378  call echk(ierr, __file__, __line__)
379  localptr = zero
380 
381  ! ii is the running counter through the pointer array.
382  ii = 0
383  do nn = 1, ndom
384  call setpointers(nn, 1_inttype, sps)
385  do mm = 1, nbocos
386  faminclude: if (faminlist(bcdata(mm)%famID, exch%famList)) then
387  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
388  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
389  ni = iend - ibeg + 1
390  nj = jend - jbeg + 1
391  do j = 0, nj - 2
392  do i = 0, ni - 2
393  ! Note: No +iBeg, and +jBeg becuase cellVal is a pointer
394  ! and always starts at one
395  qv = fourth * bcdata(mm)%cellVal(i + 1, j + 1)
396  ind(1) = ii + (j) * ni + i + 1
397  ind(2) = ii + (j) * ni + i + 2
398  ind(3) = ii + (j + 1) * ni + i + 2
399  ind(4) = ii + (j + 1) * ni + i + 1
400  do jj = 1, 4
401  localptr(ind(jj)) = localptr(ind(jj)) + qv
402  end do
403  end do
404  end do
405  ii = ii + ni * nj
406  end if faminclude
407  end do
408  end do
409 
410  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
411  call echk(ierr, __file__, __line__)
412 
413  ! Globalize the current face based value
414  call vecset(exch%nodeValGlobal, zero, ierr)
415  call echk(ierr, __file__, __line__)
416 
417  call vecscatterbegin(exch%scatter, exch%nodeValLocal, &
418  exch%nodeValGlobal, add_values, scatter_forward, ierr)
419  call echk(ierr, __file__, __line__)
420 
421  call vecscatterend(exch%scatter, exch%nodeValLocal, &
422  exch%nodeValGlobal, add_values, scatter_forward, ierr)
423  call echk(ierr, __file__, __line__)
424 
425  ! Now divide by the weighting. We can do this with a vecpointwisemult
426  call vecpointwisemult(exch%nodeValGlobal, exch%nodeValGlobal, &
427  exch%sumGlobal, ierr)
428  call echk(ierr, __file__, __line__)
429 
430  ! Push back to the local values
431  call vecscatterbegin(exch%scatter, exch%nodeValGlobal, &
432  exch%nodeValLocal, insert_values, scatter_reverse, ierr)
433  call echk(ierr, __file__, __line__)
434 
435  call vecscatterend(exch%scatter, exch%nodeValGlobal, &
436  exch%nodeValLocal, insert_values, scatter_reverse, ierr)
437  call echk(ierr, __file__, __line__)
438 
439  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
440  call echk(ierr, __file__, __line__)
441 
442  ii = 0
443  do nn = 1, ndom
444  call setpointers(nn, 1_inttype, sps)
445  do mm = 1, nbocos
446  faminclude2: if (faminlist(bcdata(mm)%famID, exch%famList)) then
447  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
448  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
449 
450  ni = iend - ibeg + 1
451  nj = jend - jbeg + 1
452  do j = 1, nj
453  do i = 1, ni
454  ! Note: No +iBeg, and +jBeg becuase cellVal is a pointer
455  ! and always starts at one
456  ii = ii + 1
457  bcdata(mm)%nodeVal(i, j) = localptr(ii)
458  end do
459  end do
460  end if faminclude2
461  end do
462  end do
463 
464  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
465  call echk(ierr, __file__, __line__)
466 
467 end subroutine surfacecellcentertonode
468 
469 subroutine computeweighting(exch)
470 
471  use constants
472  use blockpointers, only: bcdata, ndom, nbocos, bctype
474  use utils, only: setpointers, echk
475  use sorting, only: faminlist
476 #include <petsc/finclude/petsc.h>
477  use petsc
478  implicit none
479  type(familyexchange) :: exch
480  integer(kind=intType) :: sps
481  integer(kind=intType) :: mm, nn, i, j, ii, jj, idim, ierr
482  integer(kind=intType) :: ibeg, iend, jbeg, jend, ind(4), ni, nj
483  real(kind=realtype) :: qf, qa
484  real(kind=realtype), dimension(:), pointer :: localptr
485 
486  sps = exch%sps
487 
488  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
489  call echk(ierr, __file__, __line__)
490 
491  localptr = zero
492  ! ii is the running counter through the pointer array.
493  ii = 0
494  do nn = 1, ndom
495  call setpointers(nn, 1_inttype, sps)
496  do mm = 1, nbocos
497  faminclude: if (faminlist(bcdata(mm)%famID, exch%famList)) then
498  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
499  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
500  ni = iend - ibeg + 1
501  nj = jend - jbeg + 1
502  do j = 0, nj - 2
503  do i = 0, ni - 2
504 
505  ! Scatter a quarter of the face value to each node:
506  ! Note: No +iBeg, and +jBeg becuase cellVal is a pointer
507  ! and always starts at one
508  qa = fourth * bcdata(mm)%cellVal(i + 1, j + 1)
509  ind(1) = ii + (j) * ni + i + 1
510  ind(2) = ii + (j) * ni + i + 2
511  ind(3) = ii + (j + 1) * ni + i + 2
512  ind(4) = ii + (j + 1) * ni + i + 1
513  do jj = 1, 4
514  localptr(ind(jj)) = localptr(ind(jj)) + qa
515  end do
516  end do
517  end do
518  ii = ii + ni * nj
519  end if faminclude
520  end do
521  end do
522 
523  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
524  call echk(ierr, __file__, __line__)
525 
526  ! Globalize the face value
527  call vecset(exch%sumGlobal, zero, ierr)
528  call echk(ierr, __file__, __line__)
529 
530  call vecscatterbegin(exch%scatter, exch%nodeValLocal, &
531  exch%sumGlobal, add_values, scatter_forward, ierr)
532  call echk(ierr, __file__, __line__)
533 
534  call vecscatterend(exch%scatter, exch%nodeValLocal, &
535  exch%sumGlobal, add_values, scatter_forward, ierr)
536  call echk(ierr, __file__, __line__)
537 
538  ! Now compute the inverse of the weighting so that we can multiply
539  ! instead of dividing. Note that we check dividing by zero and just
540  ! set those to zero.
541 
542  call vecgetarrayf90(exch%sumGlobal, localptr, ierr)
543  call echk(ierr, __file__, __line__)
544  do i = 1, size(localptr)
545  if (localptr(i) == zero) then
546  localptr(i) = zero
547  else
548  localptr(i) = one / localptr(i)
549  end if
550  end do
551 
552  call vecrestorearrayf90(exch%sumGlobal, localptr, ierr)
553  call echk(ierr, __file__, __line__)
554 
555 end subroutine computeweighting
556 
557 subroutine computenodaltractions(sps)
558  use constants
559  use blockpointers, only: bcdata, ndom, nbocos, bctype
561  use utils, only: setpointers, echk, iswalltype
562  implicit none
563 
564  integer(kind=intType), intent(in) :: sps
565  integer(kind=intType) :: mm, nn, i, j, ii, jj, iDim, ierr
566  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd, ind(4), ni, nj
567  real(kind=realtype) :: qf, qa
568  real(kind=realtype), dimension(:), pointer :: localptr
569  type(familyexchange), pointer :: exch
570 
571  ! Set the pointer to the wall exchange:
572  exch => bcfamexchange(ibcgroupwalls, sps)
573 
574  ! Set the weighting factors. In this case, area
575  ii = 0
576  do nn = 1, ndom
577  call setpointers(nn, 1_inttype, sps)
578  do mm = 1, nbocos
579  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
580  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
581 
582  bocotype1: if (iswalltype(bctype(mm))) then
583  bcdata(mm)%cellVal => bcdata(mm)%area(:, :)
584  end if bocotype1
585  end do
586  end do
587  call computeweighting(exch)
588 
589  fpfvloop: do idim = 1, 6
590  ! ii is the running counter through the pointer array.
591  ii = 0
592  do nn = 1, ndom
593  call setpointers(nn, 1_inttype, sps)
594  do mm = 1, nbocos
595  bocotype2: if (iswalltype(bctype(mm))) then
596  if (idim <= 3) then
597  bcdata(mm)%cellVal => bcdata(mm)%Fp(:, :, idim)
598  bcdata(mm)%nodeVal => bcdata(mm)%Tp(:, :, idim)
599  else
600  bcdata(mm)%cellVal => bcdata(mm)%Fv(:, :, idim - 3)
601  bcdata(mm)%nodeVal => bcdata(mm)%Tv(:, :, idim - 3)
602  end if
603  end if bocotype2
604  end do
605  end do
606 
607  call surfacecellcentertonode(exch)
608 
609  end do fpfvloop
610 
611 end subroutine computenodaltractions
612 
613 subroutine computenodaltractions_d(sps)
614 
615  ! Forward mode lineariation of nodal tractions
616 
617  use constants
618  use blockpointers, only: ndom, nbocos, bcdata, bctype, nbocos, bcdatad
621  use utils, only: setpointers, setpointers_d, echk
622 #include <petsc/finclude/petsc.h>
623  use petsc
624  implicit none
625  integer(kind=intType), intent(in) :: sps
626  integer(kind=intType) :: mm, nn, i, j, ii, jj, idim, ierr
627  integer(kind=intType) :: ibeg, iend, jbeg, jend, ind(4), ni, nj
628  real(kind=realtype) :: qa, qad, qf, qfd
629  real(kind=realtype), dimension(:), pointer :: localptr, localptrd
630  type(familyexchange), pointer :: exch
631  vec nodevallocald, nodevalglobald, sumglobald, tmp
632 
633  exch => bcfamexchange(ibcgroupwalls, sps)
634 
635  call vecduplicate(exch%nodeValLocal, nodevallocald, ierr)
636  call echk(ierr, __file__, __line__)
637 
638  call vecduplicate(exch%nodeValGlobal, nodevalglobald, ierr)
639  call echk(ierr, __file__, __line__)
640 
641  call vecduplicate(exch%sumGlobal, sumglobald, ierr)
642  call echk(ierr, __file__, __line__)
643 
644  call vecduplicate(exch%sumGlobal, tmp, ierr)
645  call echk(ierr, __file__, __line__)
646 
647  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
648  call echk(ierr, __file__, __line__)
649 
650  call vecgetarrayf90(nodevallocald, localptrd, ierr)
651  call echk(ierr, __file__, __line__)
652 
653  localptrd = zero
654  localptr = zero
655  ! ii is the running counter through the pointer array.
656  ii = 0
657  do nn = 1, ndom
658  call setpointers_d(nn, 1_inttype, sps)
659  do mm = 1, nbocos
660  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
661  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
662  ni = iend - ibeg + 1
663  nj = jend - jbeg + 1
664 
665  if (bctype(mm) == eulerwall .or. &
666  bctype(mm) == nswalladiabatic .or. &
667  bctype(mm) == nswallisothermal) then
668 
669  do j = 0, nj - 2
670  do i = 0, ni - 2
671 
672  ! Scatter a quarter of the area to each node:
673  qa = fourth * bcdata(mm)%area(i + ibeg + 1, j + jbeg + 1)
674  qad = fourth * bcdatad(mm)%area(i + ibeg + 1, j + jbeg + 1)
675  ind(1) = ii + (j) * ni + i + 1
676  ind(2) = ii + (j) * ni + i + 2
677  ind(3) = ii + (j + 1) * ni + i + 2
678  ind(4) = ii + (j + 1) * ni + i + 1
679  do jj = 1, 4
680  localptrd(ind(jj)) = localptrd(ind(jj)) + qad
681  localptr(ind(jj)) = localptr(ind(jj)) + qa
682  end do
683  end do
684  end do
685  ii = ii + ni * nj
686  end if
687  end do
688  end do
689  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
690  call echk(ierr, __file__, __line__)
691 
692  call vecrestorearrayf90(nodevallocald, localptrd, ierr)
693  call echk(ierr, __file__, __line__)
694 
695  ! Globalize the area
696  call vecset(exch%sumGlobal, zero, ierr)
697  call echk(ierr, __file__, __line__)
698 
699  call vecscatterbegin(exch%scatter, exch%nodeValLocal, &
700  exch%sumGlobal, add_values, scatter_forward, ierr)
701  call echk(ierr, __file__, __line__)
702 
703  call vecscatterend(exch%scatter, exch%nodeValLocal, &
704  exch%sumGlobal, add_values, scatter_forward, ierr)
705  call echk(ierr, __file__, __line__)
706 
707  ! Globalize the area derivative
708  call vecset(sumglobald, zero, ierr)
709  call echk(ierr, __file__, __line__)
710 
711  call vecscatterbegin(exch%scatter, nodevallocald, &
712  sumglobald, add_values, scatter_forward, ierr)
713  call echk(ierr, __file__, __line__)
714 
715  call vecscatterend(exch%scatter, nodevallocald, &
716  sumglobald, add_values, scatter_forward, ierr)
717  call echk(ierr, __file__, __line__)
718 
719  ! Now compute the inverse of the weighting so that we can multiply
720  ! instead of dividing. Here we need the original value too:
721 
722  call vecgetarrayf90(exch%sumGlobal, localptr, ierr)
723  call echk(ierr, __file__, __line__)
724 
725  call vecgetarrayf90(sumglobald, localptrd, ierr)
726  call echk(ierr, __file__, __line__)
727 
728  localptrd = -(localptrd / localptr**2)
729  localptr = one / localptr
730 
731  call vecgetarrayf90(exch%sumGlobal, localptr, ierr)
732  call echk(ierr, __file__, __line__)
733 
734  call vecrestorearrayf90(sumglobald, localptrd, ierr)
735  call echk(ierr, __file__, __line__)
736 
737  ! Now do each of the three dimensions for the pressure and viscous forces
738  dimloop: do idim = 1, 6
739 
740  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
741  call echk(ierr, __file__, __line__)
742 
743  call vecgetarrayf90(nodevallocald, localptrd, ierr)
744  call echk(ierr, __file__, __line__)
745 
746  localptr = zero
747  localptrd = zero
748 
749  ! ii is the running counter through the pointer array.
750  ii = 0
751  do nn = 1, ndom
752  call setpointers_d(nn, 1_inttype, sps)
753  do mm = 1, nbocos
754  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
755  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
756  ni = iend - ibeg + 1
757  nj = jend - jbeg + 1
758  if (bctype(mm) == eulerwall .or. &
759  bctype(mm) == nswalladiabatic .or. &
760  bctype(mm) == nswallisothermal) then
761  do j = 0, nj - 2
762  do i = 0, ni - 2
763  if (idim <= 3) then
764  qf = fourth * bcdata(mm)%Fp(i + ibeg + 1, j + jbeg + 1, idim)
765  qfd = fourth * bcdatad(mm)%Fp(i + ibeg + 1, j + jbeg + 1, idim)
766  else
767  qf = fourth * bcdata(mm)%Fv(i + ibeg + 1, j + jbeg + 1, idim - 3)
768  qfd = fourth * bcdatad(mm)%Fv(i + ibeg + 1, j + jbeg + 1, idim - 3)
769  end if
770 
771  ind(1) = ii + (j) * ni + i + 1
772  ind(2) = ii + (j) * ni + i + 2
773  ind(3) = ii + (j + 1) * ni + i + 2
774  ind(4) = ii + (j + 1) * ni + i + 1
775  do jj = 1, 4
776  localptr(ind(jj)) = localptr(ind(jj)) + qf
777  localptrd(ind(jj)) = localptrd(ind(jj)) + qfd
778  end do
779  end do
780  end do
781  ii = ii + ni * nj
782  end if
783  end do
784  end do
785 
786  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
787  call echk(ierr, __file__, __line__)
788 
789  call vecrestorearrayf90(nodevallocald, localptrd, ierr)
790  call echk(ierr, __file__, __line__)
791 
792  ! Globalize the current force
793  call vecset(exch%nodeValGlobal, zero, ierr)
794  call echk(ierr, __file__, __line__)
795 
796  call vecscatterbegin(exch%scatter, exch%nodeValLocal, &
797  exch%nodeValGlobal, add_values, scatter_forward, ierr)
798  call echk(ierr, __file__, __line__)
799 
800  call vecscatterend(exch%scatter, exch%nodeValLocal, &
801  exch%nodeValGlobal, add_values, scatter_forward, ierr)
802  call echk(ierr, __file__, __line__)
803 
804  ! Globalize the current force derivative
805  call vecset(nodevalglobald, zero, ierr)
806  call echk(ierr, __file__, __line__)
807 
808  call vecscatterbegin(exch%scatter, nodevallocald, &
809  nodevalglobald, add_values, scatter_forward, ierr)
810  call echk(ierr, __file__, __line__)
811 
812  call vecscatterend(exch%scatter, nodevallocald, &
813  nodevalglobald, add_values, scatter_forward, ierr)
814  call echk(ierr, __file__, __line__)
815 
816  ! The product rule here: (since we are multiplying)
817  ! nodeValGlobal = nodeValGlobal * invArea
818  ! nodeValGlobald = nodeValGlobald*invArea + nodeValGlobal*invAread
819 
820  ! First term: nodeValGlobald = nodeValGlobald*invArea
821  call vecpointwisemult(nodevalglobald, nodevalglobald, &
822  exch%sumGlobal, ierr)
823  call echk(ierr, __file__, __line__)
824 
825  ! Second term:, tmp = nodeValGlobal*invAread
826  call vecpointwisemult(tmp, exch%nodeValGlobal, sumglobald, ierr)
827  call echk(ierr, __file__, __line__)
828 
829  ! Sum the second term into the first
830  call vecaxpy(nodevalglobald, one, tmp, ierr)
831  call echk(ierr, __file__, __line__)
832 
833  ! Push back to the local values
834  call vecscatterbegin(exch%scatter, nodevalglobald, &
835  nodevallocald, insert_values, scatter_reverse, ierr)
836  call echk(ierr, __file__, __line__)
837 
838  call vecscatterend(exch%scatter, nodevalglobald, &
839  nodevallocald, insert_values, scatter_reverse, ierr)
840  call echk(ierr, __file__, __line__)
841 
842  call vecgetarrayf90(nodevallocald, localptrd, ierr)
843  call echk(ierr, __file__, __line__)
844 
845  ii = 0
846  do nn = 1, ndom
847  call setpointers_d(nn, 1_inttype, sps)
848  do mm = 1, nbocos
849  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
850  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
851 
852  if (bctype(mm) == eulerwall .or. &
853  bctype(mm) == nswalladiabatic .or. &
854  bctype(mm) == nswallisothermal) then
855  do j = jbeg, jend
856  do i = ibeg, iend
857  ii = ii + 1
858  if (idim <= 3) then
859  bcdatad(mm)%Tp(i, j, idim) = localptrd(ii)
860  else
861  bcdatad(mm)%Tv(i, j, idim - 3) = localptrd(ii)
862  end if
863  end do
864  end do
865  end if
866  end do
867  end do
868 
869  call vecrestorearrayf90(nodevallocald, localptrd, ierr)
870  call echk(ierr, __file__, __line__)
871 
872  end do dimloop
873 
874  call vecdestroy(nodevallocald, ierr)
875  call echk(ierr, __file__, __line__)
876 
877  call vecdestroy(nodevalglobald, ierr)
878  call echk(ierr, __file__, __line__)
879 
880  call vecdestroy(sumglobald, ierr)
881  call echk(ierr, __file__, __line__)
882 
883  call vecdestroy(tmp, ierr)
884  call echk(ierr, __file__, __line__)
885 
886 end subroutine computenodaltractions_d
887 
888 subroutine computenodaltractions_b(sps)
889 
890  ! This routine performs the reverse of computeNodalTractions. Tt
891  ! takes in bcDatad%Tv and bcDatad%Tp and perfroms the reverse of the
892  ! nodal averaging procedure in getForces to compute bcDatad(mm)%Fp,
893  ! bcDatad(mm)%Fv and bcDatad(mm)%area.
894 
895  use constants
896  use blockpointers, only: ndom, nbocos, bcdata, bctype, nbocos, bcdatad
899  use communication
900  use utils, only: echk, setpointers, setpointers_d
901 #include <petsc/finclude/petsc.h>
902  use petsc
903  implicit none
904 
905  integer(kind=intType), intent(in) :: sps
906  integer(kind=intType) :: mm, nn, i, j, ii, jj, idim, ierr
907  integer(kind=intType) :: ibeg, iend, jbeg, jend, ind(4), ni, nj
908  real(kind=realtype) :: qf_b, qf, qa, qa_b
909  real(kind=realtype), dimension(:), pointer :: localptr, localptr_b
910  type(familyexchange), pointer :: exch
911  vec nodevallocal_b, nodevalglobal_b, sumglobal_b, tmp, tmp_b, t_b
912 
913  ! For better readibility
914  exch => bcfamexchange(ibcgroupwalls, sps)
915 
916  call vecduplicate(exch%nodeValLocal, nodevallocal_b, ierr)
917  call echk(ierr, __file__, __line__)
918 
919  call vecduplicate(exch%nodeValGlobal, nodevalglobal_b, ierr)
920  call echk(ierr, __file__, __line__)
921 
922  call vecduplicate(exch%sumGlobal, sumglobal_b, ierr)
923  call echk(ierr, __file__, __line__)
924 
925  call vecduplicate(exch%sumGlobal, tmp, ierr)
926  call echk(ierr, __file__, __line__)
927 
928  call vecduplicate(tmp, t_b, ierr)
929  call echk(ierr, __file__, __line__)
930 
931  ! For tractions it's (a lot) more difficult becuase we have to do
932  ! the scatter/gather operation.
933 
934  ! ==================================
935  ! Recompute the dual area
936  ! ==================================
937 
938  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
939  call echk(ierr, __file__, __line__)
940 
941  localptr = zero
942  ! ii is the running counter through the pointer array.
943  ii = 0
944  do nn = 1, ndom
945  call setpointers(nn, 1_inttype, sps)
946  do mm = 1, nbocos
947  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
948  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
949  ni = iend - ibeg + 1
950  nj = jend - jbeg + 1
951 
952  if (bctype(mm) == eulerwall .or. &
953  bctype(mm) == nswalladiabatic .or. &
954  bctype(mm) == nswallisothermal) then
955  do j = 0, nj - 2
956  do i = 0, ni - 2
957 
958  ! Scatter a quarter of the area to each node:
959  qa = fourth * bcdata(mm)%area(i + ibeg + 1, j + jbeg + 1)
960  ind(1) = ii + (j) * ni + i + 1
961  ind(2) = ii + (j) * ni + i + 2
962  ind(3) = ii + (j + 1) * ni + i + 2
963  ind(4) = ii + (j + 1) * ni + i + 1
964  do jj = 1, 4
965  localptr(ind(jj)) = localptr(ind(jj)) + qa
966  end do
967  end do
968  end do
969  ii = ii + ni * nj
970  end if
971  end do
972  end do
973 
974  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
975  call echk(ierr, __file__, __line__)
976 
977  ! Globalize the area
978  call vecset(exch%sumGlobal, zero, ierr)
979  call echk(ierr, __file__, __line__)
980 
981  call vecscatterbegin(exch%scatter, exch%nodeValLocal, &
982  exch%sumGlobal, add_values, scatter_forward, ierr)
983  call echk(ierr, __file__, __line__)
984 
985  call vecscatterend(exch%scatter, exch%nodeValLocal, &
986  exch%sumGlobal, add_values, scatter_forward, ierr)
987  call echk(ierr, __file__, __line__)
988 
989  ! Now compute the inverse of the weighting so that we can multiply
990  ! instead of dividing.
991 
992  call vecgetarrayf90(exch%sumGlobal, localptr, ierr)
993  call echk(ierr, __file__, __line__)
994 
995  localptr = one / localptr
996 
997  call vecrestorearrayf90(exch%sumGlobal, localptr, ierr)
998  call echk(ierr, __file__, __line__)
999 
1000  ! ==================================
1001  ! Now trace through the computeNodalTractions() routine
1002  ! backwards. All the scatters flip direction and INSERT_VALUES
1003  ! becomes ADD_VALUES and vice-versa
1004  ! ==================================
1005  dimloop: do idim = 1, 6
1006 
1007  ! ====================
1008  ! Do the forward pass:
1009  ! ====================
1010  call vecgetarrayf90(exch%nodeValLocal, localptr, ierr)
1011  call echk(ierr, __file__, __line__)
1012 
1013  localptr = zero
1014  ! ii is the running counter through the pointer array.
1015  ii = 0
1016  do nn = 1, ndom
1017  call setpointers(nn, 1_inttype, sps)
1018  do mm = 1, nbocos
1019  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
1020  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
1021  ni = iend - ibeg + 1
1022  nj = jend - jbeg + 1
1023  if (bctype(mm) == eulerwall .or. &
1024  bctype(mm) == nswalladiabatic .or. &
1025  bctype(mm) == nswallisothermal) then
1026  do j = 0, nj - 2
1027  do i = 0, ni - 2
1028  if (idim <= 3) then
1029  qf = fourth * bcdata(mm)%Fp(i + ibeg + 1, j + jbeg + 1, idim)
1030  else
1031  qf = fourth * bcdata(mm)%Fv(i + ibeg + 1, j + jbeg + 1, idim - 3)
1032  end if
1033 
1034  ind(1) = ii + (j) * ni + i + 1
1035  ind(2) = ii + (j) * ni + i + 2
1036  ind(3) = ii + (j + 1) * ni + i + 2
1037  ind(4) = ii + (j + 1) * ni + i + 1
1038  do jj = 1, 4
1039  localptr(ind(jj)) = localptr(ind(jj)) + qf
1040  end do
1041  end do
1042  end do
1043  ii = ii + ni * nj
1044  end if
1045  end do
1046  end do
1047 
1048  call vecrestorearrayf90(exch%nodeValLocal, localptr, ierr)
1049  call echk(ierr, __file__, __line__)
1050 
1051  ! Globalize the current force
1052  call vecset(exch%nodeValGlobal, zero, ierr)
1053  call echk(ierr, __file__, __line__)
1054 
1055  call vecscatterbegin(exch%scatter, exch%nodeValLocal, &
1056  exch%nodeValGlobal, add_values, scatter_forward, ierr)
1057  call echk(ierr, __file__, __line__)
1058 
1059  call vecscatterend(exch%scatter, exch%nodeValLocal, &
1060  exch%nodeValGlobal, add_values, scatter_forward, ierr)
1061  call echk(ierr, __file__, __line__)
1062 
1063  ! ====================
1064  ! Do the reverse pass:
1065  ! ====================
1066 
1067  ! Copy the reverse seed into the local values
1068  call vecgetarrayf90(nodevallocal_b, localptr_b, ierr)
1069  call echk(ierr, __file__, __line__)
1070 
1071  ii = 0
1072  domains: do nn = 1, ndom
1073  call setpointers_d(nn, 1_inttype, sps)
1074 
1075  ! Loop over the number of boundary subfaces of this block.
1076  bocos: do mm = 1, nbocos
1077  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
1078  bctype(mm) == nswallisothermal) then
1079 
1080  ! This is easy, just copy out F or T in continuous ordering.
1081  do j = bcdata(mm)%jnBeg, bcdata(mm)%jnEnd
1082  do i = bcdata(mm)%inBeg, bcdata(mm)%inEnd
1083  ii = ii + 1
1084  if (idim <= 3) then
1085  localptr_b(ii) = bcdatad(mm)%Tp(i, j, idim)
1086  else
1087  localptr_b(ii) = bcdatad(mm)%Tv(i, j, idim - 3)
1088  end if
1089  end do
1090  end do
1091  end if
1092  end do bocos
1093  end do domains
1094 
1095  call vecrestorearrayf90(nodevallocal_b, localptr_b, ierr)
1096  call echk(ierr, __file__, __line__)
1097 
1098  call vecset(t_b, zero, ierr)
1099  call echk(ierr, __file__, __line__)
1100  ! Push up to the global values
1101  call vecscatterbegin(exch%scatter, nodevallocal_b, &
1102  t_b, add_values, scatter_forward, ierr)
1103  call echk(ierr, __file__, __line__)
1104 
1105  call vecscatterend(exch%scatter, nodevallocal_b, &
1106  t_b, add_values, scatter_forward, ierr)
1107  call echk(ierr, __file__, __line__)
1108 
1109  ! this is particularly nasty. This is why you don't do
1110  ! derivatives by hand, kids.
1111  ! exch%nodeValGlobal = F
1112  ! nodeValGlobal_b = F_b
1113  ! T_b = reverse seed for tractions
1114  ! sumGlobal_b = inverseDualarea_b
1115  ! exch%sumGlobal = invDualArea
1116 
1117  ! Basically what we have to compute here is:
1118  ! Fb = invDualArea * T_b
1119  ! invDualAreab = invDualAreab + F*T_b
1120 
1121  call vecpointwisemult(nodevalglobal_b, exch%sumGlobal, t_b, ierr)
1122  call echk(ierr, __file__, __line__)
1123 
1124  call vecpointwisemult(tmp, exch%nodeValGlobal, t_b, ierr)
1125  call echk(ierr, __file__, __line__)
1126 
1127  ! Accumulate seed on adflowGlobal_b
1128  call vecaxpy(sumglobal_b, one, tmp, ierr)
1129  call echk(ierr, __file__, __line__)
1130 
1131  ! Now communicate F_b back to the local patches
1132 
1133  call vecscatterbegin(exch%scatter, nodevalglobal_b, &
1134  nodevallocal_b, insert_values, scatter_reverse, ierr)
1135  call echk(ierr, __file__, __line__)
1136 
1137  call vecscatterend(exch%scatter, nodevalglobal_b, &
1138  nodevallocal_b, insert_values, scatter_reverse, ierr)
1139  call echk(ierr, __file__, __line__)
1140 
1141  ! ============================
1142  ! Copy the values into patches
1143  ! ============================
1144 
1145  call vecgetarrayf90(nodevallocal_b, localptr_b, ierr)
1146  call echk(ierr, __file__, __line__)
1147 
1148  ! ii is the running counter through the pointer array.
1149  ii = 0
1150  do nn = 1, ndom
1151  call setpointers_d(nn, 1_inttype, sps)
1152  do mm = 1, nbocos
1153  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
1154  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
1155  ni = iend - ibeg + 1
1156  nj = jend - jbeg + 1
1157  if (bctype(mm) == eulerwall .or. &
1158  bctype(mm) == nswalladiabatic .or. &
1159  bctype(mm) == nswallisothermal) then
1160 
1161  do j = 0, nj - 2
1162  do i = 0, ni - 2
1163 
1164  ind(1) = ii + (j) * ni + i + 1
1165  ind(2) = ii + (j) * ni + i + 2
1166  ind(3) = ii + (j + 1) * ni + i + 2
1167  ind(4) = ii + (j + 1) * ni + i + 1
1168  qf_b = zero
1169  do jj = 1, 4
1170  qf_b = qf_b + localptr_b(ind(jj))
1171  end do
1172  qf_b = qf_b * fourth
1173 
1174  if (idim <= 3) then
1175  bcdatad(mm)%Fp(i + ibeg + 1, j + jbeg + 1, idim) = &
1176  bcdatad(mm)%Fp(i + ibeg + 1, j + jbeg + 1, idim) + qf_b
1177  else
1178  bcdatad(mm)%Fv(i + ibeg + 1, j + jbeg + 1, idim - 3) = &
1179  bcdatad(mm)%Fv(i + ibeg + 1, j + jbeg + 1, idim - 3) + qf_b
1180  end if
1181 
1182  end do
1183  end do
1184  ii = ii + ni * nj
1185  end if
1186  end do
1187  end do
1188 
1189  call vecrestorearrayf90(nodevallocal_b, localptr_b, ierr)
1190  call echk(ierr, __file__, __line__)
1191 
1192  end do dimloop
1193 
1194  ! ============================
1195  ! Finish the dual area sensitivity.
1196  ! ============================
1197 
1198  ! On the forward pass we computed:
1199  ! sumGlobal = one/sumGlobal
1200  ! So on the reverse pass we need:
1201  ! sumGlobalb = -(sumGlobalb/sumGlobal**2)
1202 
1203  ! We will do this by getting pointers
1204 
1205  call vecgetarrayf90(sumglobal_b, localptr_b, ierr)
1206  call echk(ierr, __file__, __line__)
1207 
1208  call vecgetarrayf90(exch%sumGlobal, localptr, ierr)
1209  call echk(ierr, __file__, __line__)
1210 
1211  ! Keep in mind localPtr points to sumGlobal which already has
1212  ! been inversed so we just multiply.
1213  localptr_b = -localptr_b * localptr**2
1214 
1215  call vecrestorearrayf90(sumglobal_b, localptr_b, ierr)
1216  call echk(ierr, __file__, __line__)
1217 
1218  call vecrestorearrayf90(exch%sumGlobal, localptr, ierr)
1219  call echk(ierr, __file__, __line__)
1220 
1221  ! Push back to the local patches
1222  call vecscatterbegin(exch%scatter, sumglobal_b, &
1223  nodevallocal_b, insert_values, scatter_reverse, ierr)
1224  call echk(ierr, __file__, __line__)
1225 
1226  call vecscatterend(exch%scatter, sumglobal_b, &
1227  nodevallocal_b, insert_values, scatter_reverse, ierr)
1228  call echk(ierr, __file__, __line__)
1229 
1230  call vecgetarrayf90(nodevallocal_b, localptr_b, ierr)
1231  call echk(ierr, __file__, __line__)
1232 
1233  ! ii is the running counter through the pointer array.
1234  ii = 0
1235  do nn = 1, ndom
1236  call setpointers_d(nn, 1_inttype, sps)
1237  do mm = 1, nbocos
1238  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
1239  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
1240  ni = iend - ibeg + 1
1241  nj = jend - jbeg + 1
1242 
1243  if (bctype(mm) == eulerwall .or. &
1244  bctype(mm) == nswalladiabatic .or. &
1245  bctype(mm) == nswallisothermal) then
1246  do j = 0, nj - 2
1247  do i = 0, ni - 2
1248 
1249  ind(1) = ii + (j) * ni + i + 1
1250  ind(2) = ii + (j) * ni + i + 2
1251  ind(3) = ii + (j + 1) * ni + i + 2
1252  ind(4) = ii + (j + 1) * ni + i + 1
1253  qa_b = zero
1254  do jj = 1, 4
1255  qa_b = qa_b + localptr_b(ind(jj))
1256  end do
1257  qa_b = fourth * qa_b
1258  bcdatad(mm)%area(i + ibeg + 1, j + jbeg + 1) = &
1259  bcdatad(mm)%area(i + ibeg + 1, j + jbeg + 1) + qa_b
1260  end do
1261  end do
1262  ii = ii + ni * nj
1263  end if
1264  end do
1265  end do
1266 
1267  call vecrestorearrayf90(nodevallocal_b, localptr_b, ierr)
1268  call echk(ierr, __file__, __line__)
1269 
1270  ! Remove temporary petsc vecs
1271  call vecdestroy(nodevallocal_b, ierr)
1272  call echk(ierr, __file__, __line__)
1273 
1274  call vecdestroy(nodevalglobal_b, ierr)
1275  call echk(ierr, __file__, __line__)
1276 
1277  call vecdestroy(sumglobal_b, ierr)
1278  call echk(ierr, __file__, __line__)
1279 
1280  call vecdestroy(tmp, ierr)
1281  call echk(ierr, __file__, __line__)
1282 
1283  call vecdestroy(t_b, ierr)
1284  call echk(ierr, __file__, __line__)
1285 
1286 end subroutine computenodaltractions_b
1287 
1288 subroutine computenodalforces(sps)
1289 
1290  ! This subroutine averages the cell based forces and tractions to
1291  ! node based values. There is no need for communication since we are
1292  ! simplying summing a quarter of each value to each corner.
1293 
1294  use constants
1295  use blockpointers, only: ndom, nbocos, bctype, bcdata
1296  use utils, only: setpointers
1297  implicit none
1298 
1299  integer(kind=intType), intent(in) :: sps
1300 
1301  integer(kind=intType) :: mm, nn, i, j
1302  integer(kind=intType) :: ibeg, iend, jbeg, jend
1303  real(kind=realtype) :: qf(3)
1304 
1305  do nn = 1, ndom
1306  call setpointers(nn, 1_inttype, sps)
1307  do mm = 1, nbocos
1308  ibeg = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
1309  jbeg = bcdata(mm)%jnBeg + 1; jend = bcdata(mm)%jnEnd
1310 
1311  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
1312  bctype(mm) == nswallisothermal) then
1313  bcdata(mm)%F = zero
1314  do j = jbeg, jend
1315  do i = ibeg, iend
1316  qf = fourth * (bcdata(mm)%Fp(i, j, :) + bcdata(mm)%Fv(i, j, :))
1317  bcdata(mm)%F(i, j, :) = bcdata(mm)%F(i, j, :) + qf
1318  bcdata(mm)%F(i - 1, j, :) = bcdata(mm)%F(i - 1, j, :) + qf
1319  bcdata(mm)%F(i, j - 1, :) = bcdata(mm)%F(i, j - 1, :) + qf
1320  bcdata(mm)%F(i - 1, j - 1, :) = bcdata(mm)%F(i - 1, j - 1, :) + qf
1321  end do
1322  end do
1323  end if
1324  end do
1325  end do
1326 end subroutine computenodalforces
1327 
1328 subroutine computenodalforces_d(sps)
1329 
1330  ! Forward mode linearization of nodalForces
1331 
1332  use constants
1333  use blockpointers, only: ndom, nbocos, bctype, bcdata, bcdatad
1334  use utils, only: setpointers
1335  implicit none
1336 
1337  integer(kind=intType), intent(in) :: sps
1338 
1339  integer(kind=intType) :: mm, nn, i, j
1340  integer(kind=intType) :: ibeg, iend, jbeg, jend
1341  real(kind=realtype) :: qfd(3)
1342 
1343  do nn = 1, ndom
1344  call setpointers(nn, 1_inttype, sps)
1345  do mm = 1, nbocos
1346  ibeg = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
1347  jbeg = bcdata(mm)%jnBeg + 1; jend = bcdata(mm)%jnEnd
1348 
1349  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
1350  bctype(mm) == nswallisothermal) then
1351  bcdatad(mm)%F = zero
1352  do j = jbeg, jend
1353  do i = ibeg, iend
1354  qfd = fourth * (bcdatad(mm)%Fp(i, j, :) + bcdatad(mm)%Fv(i, j, :))
1355  bcdatad(mm)%F(i, j, :) = bcdatad(mm)%F(i, j, :) + qfd
1356  bcdatad(mm)%F(i - 1, j, :) = bcdatad(mm)%F(i - 1, j, :) + qfd
1357  bcdatad(mm)%F(i, j - 1, :) = bcdatad(mm)%F(i, j - 1, :) + qfd
1358  bcdatad(mm)%F(i - 1, j - 1, :) = bcdatad(mm)%F(i - 1, j - 1, :) + qfd
1359  end do
1360  end do
1361  end if
1362  end do
1363  end do
1364 end subroutine computenodalforces_d
1365 
1366 subroutine computenodalforces_b(sps)
1367 
1368  ! Reverse mode linearization of nodalForces
1369 
1370  use constants
1371  use blockpointers, only: ndom, nbocos, bctype, bcdata, bcdatad
1372  use utils, only: setpointers_d
1373  implicit none
1374 
1375  integer(kind=intType), intent(in) :: sps
1376 
1377  integer(kind=intType) :: mm, nn, i, j
1378  integer(kind=intType) :: ibeg, iend, jbeg, jend
1379  real(kind=realtype) :: qf_b(3)
1380 
1381  domains: do nn = 1, ndom
1382  call setpointers_d(nn, 1_inttype, sps)
1383  do mm = 1, nbocos
1384  ibeg = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
1385  jbeg = bcdata(mm)%jnBeg + 1; jend = bcdata(mm)%jnEnd
1386  if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic .or. &
1387  bctype(mm) == nswallisothermal) then
1388  do j = jbeg, jend
1389  do i = ibeg, iend
1390  qf_b = fourth * (bcdatad(mm)%F(i, j, :) + bcdatad(mm)%F(i - 1, j, :) + &
1391  bcdatad(mm)%F(i, j - 1, :) + bcdatad(mm)%F(i - 1, j - 1, :))
1392 
1393  ! Fp and Fv are face-based values
1394  bcdatad(mm)%Fp(i, j, :) = bcdatad(mm)%Fp(i, j, :) + qf_b
1395  bcdatad(mm)%Fv(i, j, :) = bcdatad(mm)%Fv(i, j, :) + qf_b
1396  end do
1397  end do
1398  ! this needs to be after the update to be the reverse of the forward mode.
1399  bcdatad(mm)%F = zero
1400  end if
1401  end do
1402  end do domains
1403 end subroutine computenodalforces_b
1404 
1405 subroutine getheatflux(hflux, npts, sps)
1406  use constants
1407  use blockpointers, only: ndom, nbocos, bctype, bcdata
1410  use utils, only: setpointers
1411  implicit none
1412  !
1413  ! Local variables.
1414  !
1415  integer(kind=intType), intent(in) :: npts, sps
1416  real(kind=realtype), intent(out) :: hflux(npts)
1417 
1418  integer(kind=intType) :: mm, nn, i, j, ii
1419  integer(kind=intType) :: ibeg, iend, jbeg, jend
1420  type(familyexchange), pointer :: exch
1421 
1422  exch => bcfamexchange(ibcgroupwalls, sps)
1423  do nn = 1, ndom
1424  call setpointers(nn, 1_inttype, sps)
1425  call heatfluxes()
1426 
1427  do mm = 1, nbocos
1428  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
1429  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
1430 
1431  bocotype1: if (bctype(mm) == nswallisothermal) then
1432  bcdata(mm)%cellVal => bcdata(mm)%area(:, :)
1433  else if (bctype(mm) == eulerwall .or. bctype(mm) == nswalladiabatic) then
1434  bcdata(mm)%cellVal => zerocellval
1435  bcdata(mm)%nodeVal => zeronodeval
1436  end if bocotype1
1437  end do
1438  end do
1439 
1440  call computeweighting(exch)
1441 
1442  do nn = 1, ndom
1443  call setpointers(nn, 1_inttype, sps)
1444  do mm = 1, nbocos
1445  bocotype2: if (bctype(mm) == nswallisothermal) then
1446  bcdata(mm)%cellVal => bcdata(mm)%cellHeatFlux(:, :)
1447  bcdata(mm)%nodeVal => bcdata(mm)%nodeHeatFlux(:, :)
1448  end if bocotype2
1449  end do
1450  end do
1451 
1452  call surfacecellcentertonode(exch)
1453 
1454  ! Now extract into the flat array:
1455  ii = 0
1456  do nn = 1, ndom
1457  call setpointers(nn, 1_inttype, sps)
1458 
1459  ! Loop over the number of viscous boundary subfaces of this block.
1460  ! According to preprocessing/viscSubfaceInfo, visc bocos are numbered
1461  ! before other bocos. Therefore, mm_nViscBocos == mm_nBocos
1462  do mm = 1, nbocos
1463  bocotype3: if (bctype(mm) == nswallisothermal) then
1464  do j = bcdata(mm)%jnBeg, bcdata(mm)%jnEnd
1465  do i = bcdata(mm)%inBeg, bcdata(mm)%inEnd
1466  ii = ii + 1
1467  hflux(ii) = bcdata(mm)%nodeHeatFlux(i, j)
1468  end do
1469  end do
1470  ! Simply put in zeros for the other wall BCs
1471  else if (bctype(mm) == nswalladiabatic .or. bctype(mm) == eulerwall) then
1472  do j = bcdata(mm)%jnBeg, bcdata(mm)%jnEnd
1473  do i = bcdata(mm)%inBeg, bcdata(mm)%inEnd
1474  ii = ii + 1
1475  hflux(ii) = zero
1476  end do
1477  end do
1478  end if bocotype3
1479  end do
1480  end do
1481 end subroutine getheatflux
1482 
1483 subroutine heatfluxes
1484  use constants
1485  use blockpointers, only: bcdata, ndom, nbocos, bctype, bcfaceid, viscsubface
1486  use bcpointers, only: ssi
1487  use flowvarrefstate, only: pref, rhoref
1488  use utils, only: setpointers, setbcpointers
1489  implicit none
1490  !
1491  ! Local variables.
1492  !
1493  integer(kind=intType) :: i, j, ii, mm
1494  real(kind=realtype) :: fact, scaledim
1495  real(kind=realtype) :: qw, qa
1496  logical :: heatedSubface
1497 
1498  ! Set the actual scaling factor such that ACTUAL heat flux is computed
1499  ! The factor is determined from stanton number
1500  scaledim = pref * sqrt(pref / rhoref)
1501 
1502  ! Loop over the boundary subfaces of this block.
1503  bocos: do mm = 1, nbocos
1504 
1505  ! Only do this on isoThermalWalls
1506  if (bctype(mm) == nswallisothermal) then
1507 
1508  ! Set a bunch of pointers depending on the face id to make
1509  ! a generic treatment possible. The routine setBcPointers
1510  ! is not used, because quite a few other ones are needed.
1511  call setbcpointers(mm, .true.)
1512 
1513  select case (bcfaceid(mm))
1514  case (imin, jmin, kmin)
1515  fact = -one
1516  case (imax, jmax, kmax)
1517  fact = one
1518  end select
1519 
1520  ! Loop over the quadrilateral faces of the subface. Note that
1521  ! the nodal range of BCData must be used and not the cell
1522  ! range, because the latter may include the halo's in i and
1523  ! j-direction. The offset +1 is there, because inBeg and jnBeg
1524  ! refer to nodal ranges and not to cell ranges.
1525  !
1526  do j = (bcdata(mm)%jnBeg + 1), bcdata(mm)%jnEnd
1527  do i = (bcdata(mm)%inBeg + 1), bcdata(mm)%inEnd
1528 
1529  ! Compute the normal heat flux on the face. Inward positive.
1530  bcdata(mm)%cellHeatFlux(i, j) = -fact * scaledim * &
1531  sqrt(ssi(i, j, 1)**2 + ssi(i, j, 2)**2 + ssi(i, j, 3)**2) * &
1532  (viscsubface(mm)%q(i, j, 1) * bcdata(mm)%norm(i, j, 1) &
1533  + viscsubface(mm)%q(i, j, 2) * bcdata(mm)%norm(i, j, 2) &
1534  + viscsubface(mm)%q(i, j, 3) * bcdata(mm)%norm(i, j, 3))
1535  end do
1536  end do
1537  end if
1538  end do bocos
1539 end subroutine heatfluxes
1540 
1541 subroutine settnswall(tnsw, npts, sps)
1542 
1543  use constants
1544  use blockpointers, only: ndom, nbocos, bcdata, bctype
1545  use flowvarrefstate, only: tref
1546  use utils, only: setpointers
1547  implicit none
1548 
1549  ! Input Variables
1550  integer(kind=intType), intent(in) :: npts, sps
1551  real(kind=realtype), intent(in) :: tnsw(npts)
1552 
1553  ! Local Variables
1554  integer(kind=intType) :: mm, nn, i, j, ii
1555  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd
1556 
1557  ii = 0
1558  domains: do nn = 1, ndom
1559  call setpointers(nn, 1_inttype, sps)
1560  ! Loop over the number of viscous boundary subfaces of this block.
1561  bocos: do mm = 1, nbocos
1562  isowall: if (bctype(mm) == nswallisothermal) then
1563  jbeg = bcdata(mm)%jnBeg; jend = bcdata(mm)%jnEnd
1564  ibeg = bcdata(mm)%inBeg; iend = bcdata(mm)%inEnd
1565  do j = jbeg, jend
1566  do i = ibeg, iend
1567  ii = ii + 1
1568  bcdata(mm)%TNS_Wall(i, j) = tnsw(ii) / tref
1569  end do
1570  end do
1571  end if isowall
1572  end do bocos
1573  end do domains
1574  ! TODO: The temperature must be interpolated to the coarse meshes.
1575  !
1576  ! The following lines are extracted from BCData/setBCDataCoarseGrid
1577  ! By the design of the subroutine, TNSWall shall be interpolated during this process.
1578  ! Yet, the subroutine requires an internal subroutine interpolateBcData.
1579  ! It remains a question whether interpolateBcData shall become a normal subroutine.
1580  !
1581  ! use blockPointers, only : flowDoms
1582  ! use inputTimeSpectral, only : nTimeIntervalsSpectral
1583  ! use iteration, only : groundLevel
1584  ! implicit none
1585  ! !
1586  ! ! Local variables.
1587  ! !
1588  ! integer(kind=intType) :: nLevels, level, levm1
1589 
1590  ! ! Determine the number of grid levels.
1591 
1592  ! nLevels = ubound(flowDoms,2)
1593 
1594  ! ! Loop over the coarser grid levels. It is assumed that the
1595  ! ! bc data of groundLevel is set correctly.
1596 
1597  ! coarseLevelLoop: do level=(groundLevel+1),nLevels
1598 
1599  ! ! Store the fine grid level a bit easier.
1600 
1601  ! levm1 = level - 1
1602 
1603  ! ! Loop over the number of spectral solutions and local blocks.
1604 
1605  ! spectralLoop: do sps=1,nTimeIntervalsSpectral
1606  ! domainsLoop: do i=1,nDom
1607 
1608  ! ! Set the pointers to the coarse block.
1609 
1610  ! call setPointers(i, level, sps)
1611 
1612  ! ! Loop over the boundary subfaces and interpolate the
1613  ! ! prescribed boundary data for this grid level.
1614 
1615  ! bocoLoop: do j=1,nBocos
1616 
1617  ! ! Interpolate the data for the possible prescribed boundary
1618  ! ! data.
1619 
1620  ! call interpolateBcData(BCData(j)%TNS_Wall, &
1621  ! flowDoms(i,levm1,sps)%BCData(j)%TNS_Wall)
1622 
1623  ! enddo bocoLoop
1624  ! enddo domainsLoop
1625  ! enddo spectralLoop
1626  ! enddo coarseLevelLoop
1627 
1628 end subroutine settnswall
1629 
1630 subroutine gettnswall(tnsw, npts, sps)
1631 
1632  use constants
1633  use blockpointers, only: ndom, nbocos, bcdata, bctype
1634  use flowvarrefstate, only: tref
1635  use utils, only: setpointers
1636  implicit none
1637 
1638  ! Input Variables
1639  integer(kind=intType), intent(in) :: npts, sps
1640  real(kind=realtype), intent(out) :: tnsw(npts)
1641 
1642  ! Local Variables
1643  integer(kind=intType) :: mm, nn, i, j, ii
1644  integer(kind=intType) :: iBeg, iEnd, jBeg, jEnd
1645 
1646  ii = 0
1647  domains: do nn = 1, ndom
1648  call setpointers(nn, 1_inttype, sps)
1649  ! Loop over the number of viscous boundary subfaces of this block.
1650  bocos: do mm = 1, nbocos
1651  isowall: if (bctype(mm) == nswallisothermal) then
1652  do j = jbeg, jend
1653  do i = ibeg, iend
1654  ii = ii + 1
1655  tnsw(ii) = bcdata(mm)%TNS_Wall(i, j) * tref
1656  end do
1657  end do
1658  end if isowall
1659  end do bocos
1660  end do domains
1661 end subroutine gettnswall
subroutine getheatflux(hflux, npts, sps)
Definition: getForces.F90:1406
subroutine computenodalforces(sps)
Definition: getForces.F90:1289
subroutine getforces(forces, npts, sps)
Definition: getForces.F90:3
subroutine gettnswall(tnsw, npts, sps)
Definition: getForces.F90:1631
subroutine computeweighting(exch)
Definition: getForces.F90:470
subroutine computenodalforces_d(sps)
Definition: getForces.F90:1329
subroutine getforces_b(forcesd, npts, sps)
Definition: getForces.F90:238
subroutine heatfluxes
Definition: getForces.F90:1484
subroutine surfacecellcentertonode(exch)
Definition: getForces.F90:358
subroutine computenodaltractions(sps)
Definition: getForces.F90:558
subroutine computenodalforces_b(sps)
Definition: getForces.F90:1367
subroutine computenodaltractions_b(sps)
Definition: getForces.F90:889
subroutine computenodaltractions_d(sps)
Definition: getForces.F90:614
subroutine getforces_d(forces, forcesd, npts, sps)
Definition: getForces.F90:125
subroutine settnswall(tnsw, npts, sps)
Definition: getForces.F90:1542
Definition: BCData.F90:1
real(kind=realtype), dimension(:, :, :), pointer ssi
Definition: BCPointers.F90:15
type(viscsubfacetype), dimension(:), pointer viscsubface
type(bcdatatype), dimension(:), pointer bcdatad
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 nlocalvalues
Definition: constants.F90:454
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
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 ibcgroupwalls
Definition: constants.F90:309
integer(kind=inttype), parameter kmax
Definition: constants.F90:297
integer(kind=inttype), parameter jmin
Definition: constants.F90:294
real(kind=realtype) rhoref
real(kind=realtype) tref
real(kind=realtype) pref
logical forcesastractions
Definition: inputParam.F90:629
type(zippermesh), dimension(nfamexchange), target zippermeshes
Definition: overset.F90:376
logical oversetpresent
Definition: overset.F90:373
logical function faminlist(famID, famList)
Definition: sorting.F90:7
real(kind=realtype), dimension(:, :), allocatable, target zeronodeval
real(kind=realtype), dimension(:, :), allocatable, target zerocellval
integer(kind=inttype), dimension(:), allocatable fullfamlist
type(familyexchange), dimension(:, :), allocatable, target bcfamexchange
subroutine integratesurfaces(localValues, famList)
Definition: utils.F90:1
logical function iswalltype(bType)
Definition: utils.F90:1705
subroutine setbcpointers(nn, spatialPointers)
Definition: utils.F90:882
subroutine setpointers_d(nn, level, sps)
Definition: utils.F90:3564
subroutine echk(errorcode, file, line)
Definition: utils.F90:5722
subroutine setpointers(nn, mm, ll)
Definition: utils.F90:3237
subroutine terminate(routineName, errorMessage)
Definition: utils.F90:502