ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
flowUtils.F90
Go to the documentation of this file.
1 module flowutils
2 contains
3 
4  subroutine computettot(rho, u, v, w, p, Ttot)
5  !
6  ! computeTtot computes the total temperature for the given
7  ! pressures, densities and velocities.
8  !
9  use constants
10  use inputphysics, only: cpmodel
11  use flowvarrefstate, only: rgas, gammainf
12  use utils, only: terminate
13  implicit none
14  !
15  ! Subroutine arguments.
16  !
17  real(kind=realtype), intent(in) :: rho, p, u, v, w
18  real(kind=realtype), intent(out) :: ttot
19  !
20  ! Local variables.
21  !
22  integer(kind=intType) :: i
23 
24  real(kind=realtype) :: govgm1, t, kin
25 
26  ! Determine the cp model used.
27 
28  select case (cpmodel)
29 
30  case (cpconstant)
31 
32  ! Constant cp and thus constant gamma. The well-known
33  ! formula is valid.
34 
35  govgm1 = gammainf / (gammainf - one)
36  t = p / (rho * rgas)
37  kin = half * (u * u + v * v + w * w)
38  ttot = t * (one + rho * kin / (govgm1 * p))
39 
40  !===============================================================
41 
42  case (cptempcurvefits)
43 
44  ! Cp is a function of the temperature. The formula used for
45  ! constant cp is not valid anymore and a more complicated
46  ! procedure must be followed.
47 
48  call terminate("computeTtot", &
49  "Variable cp formulation not implemented yet")
50 
51  end select
52 
53  end subroutine computettot
54 
55  subroutine computegamma(T, gamma, mm)
56  !
57  ! computeGamma computes the corresponding values of gamma for
58  ! the given dimensional temperatures.
59  !
60  use constants
61  use cpcurvefits
63  implicit none
64  !
65  ! Subroutine arguments.
66  !
67  integer(kind=intType), intent(in) :: mm
68  real(kind=realtype), dimension(mm), intent(in) :: t
69  real(kind=realtype), dimension(mm), intent(out) :: gamma
70  !
71  ! Local variables.
72  !
73  integer(kind=intType) :: i, ii, nn, start
74  real(kind=realtype) :: cp, t2
75 
76  ! Determine the cp model used in the computation.
77 
78  select case (cpmodel)
79 
80  case (cpconstant)
81 
82  ! Constant cp and thus constant gamma. Set the values.
83 
84  do i = 1, mm
85  gamma(i) = gammaconstant
86  end do
87 
88  ! ================================================================
89 #ifndef USE_TAPENADE
90  case (cptempcurvefits)
91 
92  ! Cp as function of the temperature is given via curve fits.
93 
94  do i = 1, mm
95 
96  ! Determine the case we are having here.
97 
98  if (t(i) <= cptrange(0)) then
99 
100  ! Temperature is less than the smallest temperature
101  ! in the curve fits. Use cv0 to compute gamma.
102 
103  gamma(i) = (cv0 + one) / cv0
104 
105  else if (t(i) >= cptrange(cpnparts)) then
106 
107  ! Temperature is larger than the largest temperature
108  ! in the curve fits. Use cvn to compute gamma.
109 
110  gamma(i) = (cvn + one) / cvn
111 
112  else
113 
114  ! Temperature is in the curve fit range.
115  ! First find the valid range.
116 
117  ii = cpnparts
118  start = 1
119  interval: do
120 
121  ! Next guess for the interval.
122 
123  nn = start + ii / 2
124 
125  ! Determine the situation we are having here.
126 
127  if (t(i) > cptrange(nn)) then
128 
129  ! Temperature is larger than the upper boundary of
130  ! the current interval. Update the lower boundary.
131 
132  start = nn + 1
133  ii = ii - 1
134 
135  else if (t(i) >= cptrange(nn - 1)) then
136 
137  ! This is the correct range. Exit the do-loop.
138 
139  exit
140 
141  end if
142 
143  ! Modify ii for the next branch to search.
144 
145  ii = ii / 2
146 
147  end do interval
148 
149  ! Nn contains the correct curve fit interval.
150  ! Compute the value of cp.
151 
152  cp = zero
153  do ii = 1, cptempfit(nn)%nterm
154  t2 = t(i)**(cptempfit(nn)%exponents(ii))
155  cp = cp + cptempfit(nn)%constants(ii) * t2
156  end do
157 
158  ! Compute the corresponding value of gamma.
159 
160  gamma(i) = cp / (cp - one)
161 
162  end if
163 
164  end do
165 #endif
166  end select
167 
168  end subroutine computegamma
169 
170  subroutine computeptot(rho, u, v, w, p, ptot)
171  !
172  ! ComputePtot computes the total pressure for the given
173  ! pressures, densities and velocities.
174  !
175  use constants
176  use cpcurvefits
177  use flowvarrefstate, only: tref, rgas, gammainf
178  use inputphysics, only: cpmodel
179  implicit none
180 
181  real(kind=realtype), intent(in) :: rho, p, u, v, w
182  real(kind=realtype), intent(out) :: ptot
183  !
184  ! Local parameters.
185  !
186  real(kind=realtype), parameter :: dtstop = 0.01_realtype
187  !
188  ! Local variables.
189  !
190  integer(kind=intType) :: i, ii, mm, nn, nnt, start
191 
192  real(kind=realtype) :: govgm1, kin
193  real(kind=realtype) :: t, t2, tt, dt, h, htot, cp, scale, alp
194  real(kind=realtype) :: intcport, intcportt, intcporttt
195  !
196  ! Determine the cp model used.
197 
198  select case (cpmodel)
199 
200  case (cpconstant)
201 
202  ! Constant cp and thus constant gamma. The well-known
203  ! formula is valid.
204 
205  govgm1 = gammainf / (gammainf - one)
206 
207  kin = half * (u * u + v * v + w * w)
208  ptot = p * ((one + rho * kin / (govgm1 * p))**govgm1)
209 
210  !===============================================================
211 #ifndef USE_TAPENADE
212  case (cptempcurvefits)
213 
214  ! Cp is a function of the temperature. The formula used for
215  ! constant cp is not valid anymore and a more complicated
216  ! procedure must be followed.
217 
218  ! Compute the dimensional temperature and the scale
219  ! factor to convert the integral of cp to the correct
220  ! nonDimensional value.
221 
222  t = tref * p / (rgas * rho)
223  scale = rgas / tref
224 
225  ! Compute the enthalpy and the integrand of cp/(r*t) at the
226  ! given temperature. Take care of the exceptional situations.
227 
228  if (t <= cptrange(0)) then
229 
230  ! Temperature is smaller than the smallest temperature in
231  ! the curve fit range. Use extrapolation using constant cp.
232 
233  nn = 0
234  cp = cv0 + one
235  h = scale * (cphint(0) + cp * (t - cptrange(0)))
236 
237  intcportt = cp * log(t)
238 
239  else if (t >= cptrange(cpnparts)) then
240 
241  ! Temperature is larger than the largest temperature in the
242  ! curve fit range. Use extrapolation using constant cp.
243 
244  nn = cpnparts + 1
245  cp = cvn + one
246  h = scale * (cphint(cpnparts) + cp * (t - cptrange(cpnparts)))
247 
248  intcportt = cp * log(t)
249 
250  else
251 
252  ! Temperature lies in the curve fit range. Find the correct
253  ! interval.
254 
255  ii = cpnparts
256  start = 1
257  interval: do
258 
259  ! Next guess for the interval.
260 
261  nn = start + ii / 2
262 
263  ! Determine the situation we are having here.
264 
265  if (t > cptrange(nn)) then
266 
267  ! Temperature is larger than the upper boundary of
268  ! the current interval. Update the lower boundary.
269 
270  start = nn + 1
271  ii = ii - 1
272 
273  else if (t >= cptrange(nn - 1)) then
274 
275  ! This is the correct range. Exit the do-loop.
276 
277  exit
278 
279  end if
280 
281  ! Modify ii for the next branch to search.
282 
283  ii = ii / 2
284 
285  end do interval
286 
287  ! nn contains the correct curve fit interval.
288  ! Integrate cp to compute h and the integrand of cp/(r*t)
289 
290  h = cptempfit(nn)%eint0
291  intcportt = zero
292 
293  do ii = 1, cptempfit(nn)%nterm
294  if (cptempfit(nn)%exponents(ii) == -1_inttype) then
295  h = h + cptempfit(nn)%constants(ii) * log(t)
296  else
297  mm = cptempfit(nn)%exponents(ii) + 1
298  t2 = t**mm
299  h = h + cptempfit(nn)%constants(ii) * t2 / mm
300  end if
301 
302  if (cptempfit(nn)%exponents(ii) == 0_inttype) then
303  intcportt = intcportt &
304  + cptempfit(nn)%constants(ii) * log(t)
305  else
306  mm = cptempfit(nn)%exponents(ii)
307  t2 = t**mm
308  intcportt = intcportt &
309  + cptempfit(nn)%constants(ii) * t2 / mm
310  end if
311  end do
312 
313  h = scale * h
314 
315  end if
316 
317  ! Compute the total enthalpy. Divide by scale to get the same
318  ! dimensions as for the integral of cp/r.
319 
320  htot = (h + half * (u * u + v * v + w * w)) / scale
321 
322  ! Compute the corresponding total temperature. First determine
323  ! the situation we are having here.
324 
325  if (htot <= cphint(0)) then
326 
327  ! Total enthalpy is smaller than the lowest value of the
328  ! curve fit. Use extrapolation using constant cp.
329 
330  nnt = 0
331  tt = cptrange(0) + (htot - cphint(0)) / (cv0 + one)
332 
333  else if (htot >= cphint(cpnparts)) then
334 
335  ! Total enthalpy is larger than the largest value of the
336  ! curve fit. Use extrapolation using constant cp.
337 
338  nnt = cpnparts + 1
339  tt = cptrange(cpnparts) &
340  + (htot - cphint(cpnparts)) / (cvn + one)
341 
342  else
343 
344  ! Total temperature is in the range of the curve fits.
345  ! Use a newton algorithm to find the correct temperature.
346  ! First find the correct interval.
347 
348  ii = cpnparts
349  start = 1
350  intervaltt: do
351 
352  ! Next guess for the interval.
353 
354  nnt = start + ii / 2
355 
356  ! Determine the situation we are having here.
357 
358  if (htot > cphint(nnt)) then
359 
360  ! Enthalpy is larger than the upper boundary of
361  ! the current interval. Update the lower boundary.
362 
363  start = nnt + 1
364  ii = ii - 1
365 
366  else if (htot >= cphint(nnt - 1)) then
367 
368  ! This is the correct range. Exit the do-loop.
369 
370  exit
371 
372  end if
373 
374  ! Modify ii for the next branch to search.
375 
376  ii = ii / 2
377 
378  end do intervaltt
379 
380  ! Nnt contains the range in which the newton algorithm must
381  ! be applied. Initial guess of the total temperature.
382 
383  alp = (cphint(nnt) - htot) / (cphint(nnt) - cphint(nnt - 1))
384  tt = alp * cptrange(nnt - 1) + (one - alp) * cptrange(nnt)
385 
386  ! The actual newton algorithm to compute the total
387  ! temperature.
388 
389  newton: do
390 
391  ! Compute the energy as well as the value of cv/r for the
392  ! given temperature.
393 
394  cp = zero
395  h = cptempfit(nnt)%eint0
396 
397  do ii = 1, cptempfit(nnt)%nterm
398 
399  ! Update cp.
400 
401  t2 = tt**(cptempfit(nnt)%exponents(ii))
402  cp = cp + cptempfit(nnt)%constants(ii) * t2
403 
404  ! Update h, for which this contribution must be
405  ! integrated. Take the exceptional case that the
406  ! exponent == -1 into account.
407 
408  if (cptempfit(nnt)%exponents(ii) == -1_inttype) then
409  h = h + cptempfit(nnt)%constants(ii) * log(tt)
410  else
411  h = h + cptempfit(nnt)%constants(ii) * t2 * tt &
412  / (cptempfit(nnt)%exponents(ii) + 1)
413  end if
414 
415  end do
416 
417  ! Compute the update and the new total temperature.
418 
419  dt = (htot - h) / cp
420  tt = tt + dt
421 
422  ! Exit the newton loop if the update is smaller than the
423  ! threshold value.
424 
425  if (abs(dt) < dtstop) exit
426 
427  end do newton
428 
429  end if
430 
431  ! To compute the total pressure, the integral of cp/(r*T)
432  ! must be computed from T = T to T = Tt. Compute the integrand
433  ! at T = Tt; take care of the exceptional situations.
434 
435  if (tt <= cptrange(0)) then
436  intcporttt = (cv0 + one) * log(tt)
437  else if (tt >= cptrange(cpnparts)) then
438  intcporttt = (cvn + one) * log(tt)
439  else
440 
441  intcporttt = zero
442  do ii = 1, cptempfit(nnt)%nterm
443  if (cptempfit(nnt)%exponents(ii) == 0_inttype) then
444  intcporttt = intcporttt &
445  + cptempfit(nnt)%constants(ii) * log(tt)
446  else
447  mm = cptempfit(nnt)%exponents(ii)
448  t2 = tt**mm
449  intcporttt = intcporttt &
450  + cptempfit(nnt)%constants(ii) * t2 / mm
451  end if
452  end do
453 
454  end if
455 
456  ! Compute the integral of cp/(r*T) from T to Tt. First
457  ! substract the lower boundary from the upper boundary.
458 
459  intcport = intcporttt - intcportt
460 
461  ! Add the contributions from the possible internal curve fit
462  ! boundaries if Tt and T are in different curve fit intervals.
463 
464  do mm = (nn + 1), nnt
465  ii = mm - 1
466 
467  if (ii == 0_inttype) then
468  intcport = intcport + (cv0 + one) * log(cptrange(0))
469  else
470  intcport = intcport + cptempfit(ii)%intCpovrt_2
471  end if
472 
473  if (mm > cpnparts) then
474  intcport = intcport - (cvn + one) * log(cptrange(cpnparts))
475  else
476  intcport = intcport - cptempfit(mm)%intCpovrt_1
477  end if
478  end do
479 
480  ! And finally, compute the total pressure.
481 
482  ptot = p * exp(intcport)
483 #endif
484  end select
485 
486  end subroutine computeptot
487 
489 
490  !
491  ! computeSpeedOfSoundSquared does what it says.
492  !
493  use constants
494  use blockpointers, only: ie, je, ke, w, p, aa, gamma
495  use utils, only: getcorrectfork
496  implicit none
497  !
498  ! Local variables.
499  !
500  real(kind=realtype), PARAMETER :: twothird = two * third
501  integer(kind=intType) :: i, j, k, ii
502  real(kind=realtype) :: pp
503  logical :: correctForK
504 
505  ! Determine if we need to correct for K
506  correctfork = getcorrectfork()
507 
508  if (correctfork) then
509 #ifdef TAPENADE_REVERSE
510  !$AD II-LOOP
511  do ii = 0, ie * je * ke - 1
512  i = mod(ii, ie) + 1
513  j = mod(ii / ie, je) + 1
514  k = ii / (ie * je) + 1
515 #else
516  do k = 1, ke
517  do j = 1, je
518  do i = 1, ie
519 #endif
520  pp = p(i, j, k) - twothird * w(i, j, k, irho) * w(i, j, k, itu1)
521  aa(i, j, k) = gamma(i, j, k) * pp / w(i, j, k, irho)
522 #ifdef TAPENADE_REVERSE
523  end do
524 #else
525  end do
526  end do
527  end do
528 #endif
529  else
530 #ifdef TAPENADE_REVERSE
531  !$AD II-LOOP
532  do ii = 0, ie * je * ke - 1
533  i = mod(ii, ie) + 1
534  j = mod(ii / ie, je) + 1
535  k = ii / (ie * je) + 1
536 #else
537  do k = 1, ke
538  do j = 1, je
539  do i = 1, ie
540 #endif
541  aa(i, j, k) = gamma(i, j, k) * p(i, j, k) / w(i, j, k, irho)
542 #ifdef TAPENADE_REVERSE
543  end do
544 #else
545  end do
546  end do
547  end do
548 #endif
549  end if
550  end subroutine computespeedofsoundsquared
551  subroutine computeetotblock(iStart, iEnd, jStart, jEnd, kStart, kEnd, &
552  correctForK)
553  !
554  ! ComputeEtot computes the total energy from the given density,
555  ! velocity and presssure. For a calorically and thermally
556  ! perfect gas the well-known expression is used; for only a
557  ! thermally perfect gas, cp is a function of temperature, curve
558  ! fits are used and a more complex expression is obtained.
559  ! It is assumed that the pointers in blockPointers already
560  ! point to the correct block.
561  !
562  use constants
563  use blockpointers, only: w, p
564  use flowvarrefstate, only: rgas, tref
566  implicit none
567  !
568  ! Subroutine arguments.
569  !
570  integer(kind=intType), intent(in) :: iStart, iEnd, jStart, jEnd
571  integer(kind=intType), intent(in) :: kStart, kEnd
572  logical, intent(in) :: correctForK
573  !
574  ! Local variables.
575  !
576  integer(kind=intType) :: i, j, k, ii, iSize, jSize, kSize
577  real(kind=realtype) :: ovgm1, factk, scale
578  !
579  ! Determine the cp model used in the computation.
580 
581  select case (cpmodel)
582 
583  case (cpconstant)
584 
585  ! Constant cp and thus constant gamma.
586  ! Abbreviate 1/(gamma -1) a bit easier.
587 
588  ovgm1 = one / (gammaconstant - one)
589 
590  ! Loop over the given range of the block and compute the first
591  ! step of the energy.
592 
593  isize = (iend - istart) + 1
594  jsize = (jend - jstart) + 1
595  ksize = (kend - kstart) + 1
596  factk = ovgm1 * (five * third - gammaconstant)
597 
598  if (correctfork) then
599 #ifdef TAPENADE_REVERSE
600  !$AD II-LOOP
601  do ii = 0, isize * jsize * ksize - 1
602  i = mod(ii, isize) + istart
603  j = mod(ii / (isize), jsize) + jstart
604  k = ii / ((isize * jsize)) + kstart
605 #else
606  do k = kstart, kend
607  do j = jstart, jend
608  do i = istart, iend
609 #endif
610  w(i, j, k, irhoe) = ovgm1 * p(i, j, k) &
611  + half * w(i, j, k, irho) * (w(i, j, k, ivx)**2 &
612  + w(i, j, k, ivy)**2 &
613  + w(i, j, k, ivz)**2) - &
614  factk * w(i, j, k, irho) * w(i, j, k, itu1)
615 
616 #ifdef TAPENADE_REVERSE
617  end do
618 #else
619  end do
620  end do
621  end do
622 #endif
623 
624  else
625 #ifdef TAPENADE_REVERSE
626  !$AD II-LOOP
627  do ii = 0, isize * jsize * ksize - 1
628  i = mod(ii, isize) + istart
629  j = mod(ii / (isize), jsize) + jstart
630  k = ii / ((isize * jsize)) + kstart
631 #else
632  do k = kstart, kend
633  do j = jstart, jend
634  do i = istart, iend
635 #endif
636  w(i, j, k, irhoe) = ovgm1 * p(i, j, k) &
637  + half * w(i, j, k, irho) * (w(i, j, k, ivx)**2 &
638  + w(i, j, k, ivy)**2 &
639  + w(i, j, k, ivz)**2)
640 #ifdef TAPENADE_REVERSE
641  end do
642 #else
643  end do
644  end do
645  end do
646 #endif
647  end if
648 
649 #ifndef USE_TAPENADE
650  case (cptempcurvefits)
651 
652  ! Cp as function of the temperature is given via curve fits.
653 
654  ! Store a scale factor to compute the nonDimensional
655  ! internal energy.
656 
657  scale = rgas / tref
658 
659  ! Loop over the given range of the block.
660 
661  do k = kstart, kend
662  do j = jstart, jend
663  do i = istart, iend
664  call computeetotcellcpfit(i, j, k, scale, &
665  correctfork)
666  end do
667  end do
668  end do
669 #endif
670 
671  end select
672  end subroutine computeetotblock
673 
674  subroutine etot(rho, u, v, w, p, k, etotal, correctForK)
675  !
676  ! EtotArray computes the total energy from the given density,
677  ! velocity and presssure.
678  ! First the internal energy per unit mass is computed and after
679  ! that the kinetic energy is added as well the conversion to
680  ! energy per unit volume.
681  !
682  use constants
683  implicit none
684  !
685  ! Subroutine arguments.
686  !
687  real(kind=realtype), intent(in) :: rho, p, k
688  real(kind=realtype), intent(in) :: u, v, w
689  real(kind=realtype), intent(out) :: etotal
690  logical, intent(in) :: correctForK
691 
692  !
693  ! Local variables.
694  !
695  integer(kind=intType) :: i
696 
697  ! Compute the internal energy for unit mass.
698 
699  call eint(rho, p, k, etotal, correctfork)
700  etotal = rho * (etotal &
701  + half * (u * u + v * v + w * w))
702 
703  end subroutine etot
704 
705  ! ==================================================================
706 
707  subroutine eint(rho, p, k, einternal, correctForK)
708  !
709  ! EintArray computes the internal energy per unit mass from the
710  ! given density and pressure (and possibly turbulent energy)
711  ! For a calorically and thermally perfect gas the well-known
712  ! expression is used; for only a thermally perfect gas, cp is a
713  ! function of temperature, curve fits are used and a more
714  ! complex expression is obtained.
715  !
716  use constants
717  use cpcurvefits
718  use flowvarrefstate, only: rgas, tref
720  implicit none
721  !
722  ! Subroutine arguments.
723  !
724  real(kind=realtype), intent(in) :: rho, p, k
725  real(kind=realtype), intent(out) :: einternal
726  logical, intent(in) :: correctForK
727  !
728  ! Local parameter.
729  !
730  real(kind=realtype), parameter :: twothird = two * third
731  !
732  ! Local variables.
733  !
734  integer(kind=intType) :: i, nn, mm, ii, start
735 
736  real(kind=realtype) :: ovgm1, factk, pp, t, t2, scale
737 
738  ! Determine the cp model used in the computation.
739 
740  select case (cpmodel)
741 
742  case (cpconstant)
743 
744  ! Abbreviate 1/(gamma -1) a bit easier.
745 
746  ovgm1 = one / (gammaconstant - one)
747 
748  ! Loop over the number of elements of the array and compute
749  ! the total energy.
750 
751  einternal = ovgm1 * p / rho
752 
753  ! Second step. Correct the energy in case a turbulent kinetic
754  ! energy is present.
755 
756  if (correctfork) then
757 
758  factk = ovgm1 * (five * third - gammaconstant)
759 
760  einternal = einternal - factk * k
761 
762  end if
763 
764 #ifndef USE_TAPENADE
765  case (cptempcurvefits)
766 
767  ! Cp as function of the temperature is given via curve fits.
768 
769  ! Store a scale factor to compute the nonDimensional
770  ! internal energy.
771 
772  scale = rgas / tref
773 
774  ! Loop over the number of elements of the array
775 
776  ! Compute the dimensional temperature.
777 
778  pp = p
779  if (correctfork) pp = pp - twothird * rho * k
780  t = tref * pp / (rgas * rho)
781 
782  ! Determine the case we are having here.
783 
784  if (t <= cptrange(0)) then
785 
786  ! Temperature is less than the smallest temperature
787  ! in the curve fits. Use extrapolation using
788  ! constant cv.
789 
790  einternal = scale * (cpeint(0) + cv0 * (t - cptrange(0)))
791 
792  else if (t >= cptrange(cpnparts)) then
793 
794  ! Temperature is larger than the largest temperature
795  ! in the curve fits. Use extrapolation using
796  ! constant cv.
797 
798  einternal = scale * (cpeint(cpnparts) &
799  + cvn * (t - cptrange(cpnparts)))
800 
801  else
802 
803  ! Temperature is in the curve fit range.
804  ! First find the valid range.
805 
806  ii = cpnparts
807  start = 1
808  interval: do
809 
810  ! Next guess for the interval.
811 
812  nn = start + ii / 2
813 
814  ! Determine the situation we are having here.
815 
816  if (t > cptrange(nn)) then
817 
818  ! Temperature is larger than the upper boundary of
819  ! the current interval. Update the lower boundary.
820 
821  start = nn + 1
822  ii = ii - 1
823 
824  else if (t >= cptrange(nn - 1)) then
825 
826  ! This is the correct range. Exit the do-loop.
827 
828  exit
829 
830  end if
831 
832  ! Modify ii for the next branch to search.
833 
834  ii = ii / 2
835 
836  end do interval
837 
838  ! Nn contains the correct curve fit interval.
839  ! Integrate cv to compute eInternal.
840 
841  einternal = cptempfit(nn)%eint0 - t
842  do ii = 1, cptempfit(nn)%nterm
843  if (cptempfit(nn)%exponents(ii) == -1) then
844  einternal = einternal &
845  + cptempfit(nn)%constants(ii) * log(t)
846  else
847  mm = cptempfit(nn)%exponents(ii) + 1
848  t2 = t**mm
849  einternal = einternal &
850  + cptempfit(nn)%constants(ii) * t2 / mm
851  end if
852  end do
853 
854  einternal = scale * einternal
855 
856  end if
857 
858  ! Add the turbulent energy if needed.
859 
860  if (correctfork) einternal = einternal + k
861 
862 #endif
863  end select
864 
865  end subroutine eint
866 
867  subroutine computepressuresimple(includeHalos)
868 
869  ! Compute the pressure on a block with the pointers already set. This
870  ! routine is used by the forward mode AD code only.
871 
872  use constants
873  use blockpointers
874  use flowvarrefstate
875  use inputphysics
876  implicit none
877 
878  ! Input parameter
879  logical, intent(in) :: includeHalos
880 
881  ! Local Variables
882  integer(kind=intType) :: i, j, k, ii
883  real(kind=realtype) :: gm1, v2
884  integer(kind=intType) :: iBeg, iEnd, iSize, jBeg, jEnd, jSize, kBeg, kEnd, kSize
885  ! Compute the pressures
886  gm1 = gammaconstant - one
887 
888  if (includehalos) then
889  ibeg = 0
890  jbeg = 0
891  kbeg = 0
892  iend = ib
893  jend = jb
894  kend = kb
895  else
896  ibeg = 2
897  jbeg = 2
898  kbeg = 2
899  iend = il
900  jend = jl
901  kend = kl
902  end if
903 
904 #ifdef TAPENADE_REVERSE
905  isize = (iend - ibeg) + 1
906  jsize = (jend - jbeg) + 1
907  ksize = (kend - kbeg) + 1
908 
909  !$AD II-LOOP
910  do ii = 0, isize * jsize * ksize - 1
911  i = mod(ii, isize) + ibeg
912  j = mod(ii / (isize), jsize) + jbeg
913  k = ii / ((isize * jsize)) + kbeg
914 #else
915  do k = kbeg, kend
916  do j = jbeg, jend
917  do i = ibeg, iend
918 #endif
919  v2 = w(i, j, k, ivx)**2 + w(i, j, k, ivy)**2 + w(i, j, k, ivz)**2
920  p(i, j, k) = gm1 * (w(i, j, k, irhoe) - half * w(i, j, k, irho) * v2)
921  p(i, j, k) = max(p(i, j, k), 1.e-4_realtype * pinfcorr)
922 
923 #ifdef TAPENADE_REVERSE
924  end do
925 #else
926  end do
927  end do
928  end do
929 #endif
930  end subroutine computepressuresimple
931 
932  subroutine computepressure(iBeg, iEnd, jBeg, jEnd, kBeg, kEnd, &
933  pointerOffset)
934  !
935  ! computePressure computes the pressure from the total energy,
936  ! density and velocities in the given cell range of the block to
937  ! which the pointers in blockPointers currently point.
938  ! It is possible to specify a possible pointer offset, because
939  ! this routine is also used when reading a restart file.
940  !
941  use constants
943  use blockpointers, only: w, p
944  use flowvarrefstate, only: kpresent, pinf, rgas, tref
945  use cpcurvefits
946  implicit none
947  !
948  ! Subroutine arguments.
949  !
950  integer(kind=intType), intent(in) :: iBeg, iEnd, jBeg, jEnd, kBeg, kEnd
951  integer(kind=intType), intent(in) :: pointerOffset
952  !
953  ! Local parameters.
954  !
955  real(kind=realtype), parameter :: dtstop = 0.01_realtype
956  real(kind=realtype), parameter :: twothird = two * third
957  !
958  ! Local variables.
959  !
960  integer(kind=intType) :: i, j, k, ip, jp, kp, nn, ii, start
961 
962  real(kind=realtype) :: gm1, factk, v2, scale, e0, e
963  real(kind=realtype) :: trefinv, t, dt, t2, alp, cv
964 
965  ! Determine the cp model used in the computation.
966 
967  select case (cpmodel)
968 
969  case (cpconstant)
970 
971  ! Constant cp and thus constant gamma. The relation
972  ! eint = cv*T can be used and consequently the standard
973  ! relation between pressure and internal energy is valid.
974 
975  ! Abbreviate some constants that occur in the pressure
976  ! computation.
977 
978  gm1 = gammaconstant - one
979  factk = five * third - gammaconstant
980 
981  ! Loop over the cells. Take the possible pointer
982  ! offset into account and store the pressure in the
983  ! position w(:,:,:, irhoE).
984 
985  do k = kbeg, kend
986  kp = k + pointeroffset
987  do j = jbeg, jend
988  jp = j + pointeroffset
989  do i = ibeg, iend
990  ip = i + pointeroffset
991 
992  v2 = w(ip, jp, kp, ivx)**2 + w(ip, jp, kp, ivy)**2 &
993  + w(ip, jp, kp, ivz)**2
994  w(i, j, k, irhoe) = gm1 * (w(ip, jp, kp, irhoe) &
995  - half * w(ip, jp, kp, irho) * v2)
996  w(i, j, k, irhoe) = max(w(i, j, k, irhoe), &
997  1.e-5_realtype * pinf)
998  end do
999  end do
1000  end do
1001 
1002  ! Correct p if a k-equation is present.
1003 
1004  if (kpresent) then
1005  do k = kbeg, kend
1006  kp = k + pointeroffset
1007  do j = jbeg, jend
1008  jp = j + pointeroffset
1009  do i = ibeg, iend
1010  ip = i + pointeroffset
1011 
1012  w(i, j, k, irhoe) = w(i, j, k, irhoe) &
1013  + factk * w(ip, jp, kp, irho) &
1014  * w(ip, jp, kp, itu1)
1015  end do
1016  end do
1017  end do
1018  end if
1019 
1020  ! ================================================================
1021 
1022  case (cptempcurvefits)
1023 
1024  ! Cp as function of the temperature is given via curve fits.
1025 
1026  ! Store a scale factor when converting the nonDimensional
1027  ! energy to the units of cpEint
1028 
1029  trefinv = one / tref
1030  scale = tref / rgas
1031 
1032  ! Loop over the cells to compute the internal energy per
1033  ! unit mass. This is stored in w(:,:,:,irhoE) for the moment.
1034 
1035  do k = kbeg, kend
1036  kp = k + pointeroffset
1037  do j = jbeg, jend
1038  jp = j + pointeroffset
1039  do i = ibeg, iend
1040  ip = i + pointeroffset
1041 
1042  w(i, j, k, irhoe) = w(ip, jp, kp, irhoe) / w(ip, jp, kp, irho)
1043  if (kpresent) &
1044  w(i, j, k, irhoe) = w(i, j, k, irhoe) - w(ip, jp, kp, itu1)
1045 
1046  v2 = w(ip, jp, kp, ivx)**2 + w(ip, jp, kp, ivy)**2 &
1047  + w(ip, jp, kp, ivz)**2
1048  w(i, j, k, irhoe) = w(i, j, k, irhoe) - half * v2
1049  end do
1050  end do
1051  end do
1052 
1053  ! Newton algorithm to compute the temperature from the known
1054  ! value of the internal energy.
1055 
1056  do k = kbeg, kend
1057  kp = k + pointeroffset
1058  do j = jbeg, jend
1059  jp = j + pointeroffset
1060  do i = ibeg, iend
1061  ip = i + pointeroffset
1062 
1063  ! Store the internal energy in the same dimensional
1064  ! units as cpEint.
1065 
1066  e0 = scale * w(i, j, k, irhoe)
1067 
1068  ! Take care of the exceptional cases.
1069 
1070  if (e0 <= cpeint(0)) then
1071 
1072  ! Energy smaller than the lowest value of the curve
1073  ! fit. Use extrapolation using constant cv.
1074 
1075  t = trefinv * (cptrange(0) + (e0 - cpeint(0)) / cv0)
1076 
1077  else if (e0 >= cpeint(cpnparts)) then
1078 
1079  ! Energy larger than the largest value of the curve
1080  ! fit. Use extrapolation using constant cv.
1081 
1082  t = trefinv * (cptrange(cpnparts) &
1083  + (e0 - cpeint(cpnparts)) / cvn)
1084 
1085  else
1086 
1087  ! The value is in the range of the curve fits.
1088  ! A Newton algorithm is used to find the temperature.
1089 
1090  ! First find the curve fit interval to be searched.
1091 
1092  ii = cpnparts
1093  start = 1
1094  interval: do
1095 
1096  ! Next guess for the interval.
1097 
1098  nn = start + ii / 2
1099 
1100  ! Determine the situation we are having here.
1101 
1102  if (e0 > cpeint(nn)) then
1103 
1104  ! Energy is larger than the upper boundary of
1105  ! the current interval. Update the lower
1106  ! boundary.
1107 
1108  start = nn + 1
1109  ii = ii - 1
1110 
1111  else if (e0 >= cpeint(nn - 1)) then
1112 
1113  ! This is the correct range. Exit the do-loop.
1114 
1115  exit
1116 
1117  end if
1118 
1119  ! Modify ii for the next branch to search.
1120 
1121  ii = ii / 2
1122 
1123  end do interval
1124 
1125  ! nn contains the range in which the Newton algorithm
1126  ! must be applied.
1127 
1128  ! Initial guess of the dimensional temperature.
1129 
1130  alp = (cpeint(nn) - e0) / (cpeint(nn) - cpeint(nn - 1))
1131  t = alp * cptrange(nn - 1) + (one - alp) * cptrange(nn)
1132 
1133  ! The actual Newton algorithm to compute the
1134  ! temperature.
1135 
1136  newton: do
1137 
1138  ! Compute the internal energy as well as the
1139  ! value of cv/r for the given temperature.
1140 
1141  cv = -one ! cv/r = cp/r - 1.0
1142  e = cptempfit(nn)%eint0 - t ! e = integral of cv,
1143  ! Not of cp.
1144  do ii = 1, cptempfit(nn)%nterm
1145 
1146  ! Update cv.
1147 
1148  t2 = t**(cptempfit(nn)%exponents(ii))
1149  cv = cv + cptempfit(nn)%constants(ii) * t2
1150 
1151  ! Update e, for which this contribution must be
1152  ! integrated. Take the exceptional case that the
1153  ! exponent == -1 into account.
1154 
1155  if (cptempfit(nn)%exponents(ii) == -1_inttype) then
1156  e = e + cptempfit(nn)%constants(ii) * log(t)
1157  else
1158  e = e + cptempfit(nn)%constants(ii) * t2 * t &
1159  / (cptempfit(nn)%exponents(ii) + 1)
1160  end if
1161 
1162  end do
1163 
1164  ! Compute the update and the new temperature.
1165 
1166  dt = (e0 - e) / cv
1167  t = t + dt
1168 
1169  ! Exit the Newton loop if the update is smaller
1170  ! than the threshold value.
1171 
1172  if (abs(dt) < dtstop) exit
1173 
1174  end do newton
1175 
1176  ! Create the nonDimensional temperature.
1177 
1178  t = t * trefinv
1179 
1180  end if
1181 
1182  ! Compute the pressure from the known temperature
1183  ! and density. Include the correction if a k-equation
1184  ! is present.
1185 
1186  w(i, j, k, irhoe) = w(ip, jp, kp, irho) * rgas * t
1187  w(i, j, k, irhoe) = max(w(i, j, k, irhoe), &
1188  1.e-5_realtype * pinf)
1189  if (kpresent) &
1190  w(i, j, k, irhoe) = w(i, j, k, irhoe) &
1191  + twothird * w(ip, jp, kp, irho) &
1192  * w(ip, jp, kp, itu1)
1193  end do
1194  end do
1195  end do
1196 
1197  end select
1198 
1199  end subroutine computepressure
1200 
1201  subroutine computelamviscosity(includeHalos)
1202  !
1203  ! computeLamViscosity computes the laminar viscosity ratio in
1204  ! the owned cell centers of the given block. Sutherland's law is
1205  ! used. It is assumed that the pointes already point to the
1206  ! correct block before entering this subroutine.
1207  !
1208  use blockpointers
1209  use constants
1210  use flowvarrefstate
1211  use inputphysics
1212  use iteration
1213  use utils, only: getcorrectfork
1214  implicit none
1215 
1216  ! input variables
1217  logical, intent(in) :: includeHalos
1218  !
1219  ! Local parameter.
1220  !
1221  real(kind=realtype), parameter :: twothird = two * third
1222  !
1223  ! Local variables.
1224  !
1225  integer(kind=intType) :: i, j, k, ii
1226  real(kind=realtype) :: musuth, tsuth, ssuth, t, pp
1227  logical :: correctForK
1228  integer(kind=intType) :: iBeg, iEnd, iSize, jBeg, jEnd, jSize, kBeg, kEnd, kSize
1229 
1230  ! Return immediately if no laminar viscosity needs to be computed.
1231 
1232  if (.not. viscous) return
1233 
1234  ! Determine whether or not the pressure must be corrected
1235  ! for the presence of the turbulent kinetic energy.
1236 
1237  correctfork = getcorrectfork()
1238 
1239  ! Compute the nonDimensional constants in sutherland's law.
1240 
1241  musuth = musuthdim / muref
1242  tsuth = tsuthdim / tref
1243  ssuth = ssuthdim / tref
1244 
1245  if (includehalos) then
1246  ibeg = 1
1247  jbeg = 1
1248  kbeg = 1
1249  iend = ie
1250  jend = je
1251  kend = ke
1252  else
1253  ibeg = 2
1254  jbeg = 2
1255  kbeg = 2
1256  iend = il
1257  jend = jl
1258  kend = kl
1259  end if
1260 
1261  ! Substract 2/3 rho k, which is a part of the normal turbulent
1262  ! stresses, in case the pressure must be corrected.
1263 
1264  if (correctfork) then
1265 #ifdef TAPENADE_REVERSE
1266  isize = (iend - ibeg) + 1
1267  jsize = (jend - jbeg) + 1
1268  ksize = (kend - kbeg) + 1
1269 
1270  !$AD II-LOOP
1271  do ii = 0, isize * jsize * ksize - 1
1272  i = mod(ii, isize) + ibeg
1273  j = mod(ii / (isize), jsize) + jbeg
1274  k = ii / ((isize * jsize)) + kbeg
1275 #else
1276  do k = kbeg, kend
1277  do j = jbeg, jend
1278  do i = ibeg, iend
1279 #endif
1280  pp = p(i, j, k) - twothird * w(i, j, k, irho) * w(i, j, k, itu1)
1281  t = pp / (rgas * w(i, j, k, irho))
1282  rlv(i, j, k) = musuth * ((tsuth + ssuth) / (t + ssuth)) &
1283  * ((t / tsuth)**1.5_realtype)
1284 #ifdef TAPENADE_REVERSE
1285  end do
1286 #else
1287  end do
1288  end do
1289  end do
1290 #endif
1291  else
1292  ! Loop over the owned cells *AND* first level halos of this
1293  ! block and compute the laminar viscosity ratio.
1294 #ifdef TAPENADE_REVERSE
1295  isize = (iend - ibeg) + 1
1296  jsize = (jend - jbeg) + 1
1297  ksize = (kend - kbeg) + 1
1298 
1299  !$AD II-LOOP
1300  do ii = 0, isize * jsize * ksize - 1
1301  i = mod(ii, isize) + ibeg
1302  j = mod(ii / (isize), jsize) + jbeg
1303  k = ii / ((isize * jsize)) + kbeg
1304 #else
1305  do k = kbeg, kend
1306  do j = jbeg, jend
1307  do i = ibeg, iend
1308 #endif
1309 
1310  ! Compute the nonDimensional temperature and the
1311  ! nonDimensional laminar viscosity.
1312  t = p(i, j, k) / (rgas * w(i, j, k, irho))
1313  rlv(i, j, k) = musuth * ((tsuth + ssuth) / (t + ssuth)) &
1314  * ((t / tsuth)**1.5_realtype)
1315 #ifdef TAPENADE_REVERSE
1316  end do
1317 #else
1318  end do
1319  end do
1320  end do
1321 #endif
1322  end if
1323  end subroutine computelamviscosity
1324 
1325  subroutine adjustinflowangle()
1326 
1327  use constants
1330 
1331  implicit none
1332 
1333  !Local Vars
1334  real(kind=realtype), dimension(3) :: refdir1, refdir2
1335 
1336  ! Velocity direction given by the rotation of a unit vector
1337  ! initially aligned along the positive x-direction (1,0,0)
1338  ! 1) rotate alpha radians cw about y or z-axis
1339  ! 2) rotate beta radians ccw about z or y-axis
1340 
1341  refdir1(:) = zero
1342  refdir1(1) = one
1343  call getdirvector(refdir1, alpha, beta, veldirfreestream, &
1344  liftindex)
1345 
1346  ! Drag direction given by the rotation of a unit vector
1347  ! initially aligned along the positive x-direction (1,0,0)
1348  ! 1) rotate alpha radians cw about y or z-axis
1349  ! 2) rotate beta radians ccw about z or y-axis
1350 
1351  call getdirvector(refdir1, alpha, beta, dragdirection, &
1352  liftindex)
1353 
1354  ! Lift direction given by the rotation of a unit vector
1355  ! initially aligned along the positive z-direction (0,0,1)
1356  ! 1) rotate alpha radians cw about y or z-axis
1357  ! 2) rotate beta radians ccw about z or y-axis
1358 
1359  refdir2(:) = zero
1360  refdir2(liftindex) = one
1361 
1362  call getdirvector(refdir2, alpha, beta, liftdirection, liftindex)
1363 
1364  end subroutine adjustinflowangle
1365 
1366  subroutine derivativerotmatrixrigid(rotationMatrix, &
1367  rotationPoint, t)
1368 !
1369 ! derivativeRotMatrixRigid determines the derivative of the
1370 ! rotation matrix at the given time for the rigid body rotation,
1371 ! such that the grid velocities can be determined analytically.
1372 ! Also the rotation point of the current time level is
1373 ! determined. This value can change due to translation of the
1374 ! entire grid.
1375 !
1376  use constants
1377  use flowvarrefstate
1378  use inputmotion
1379  use monitor
1381  implicit none
1382 !
1383 ! Subroutine arguments.
1384 !
1385  real(kind=realtype), intent(in) :: t
1386 
1387  real(kind=realtype), dimension(3), intent(out) :: rotationpoint
1388  real(kind=realtype), dimension(3, 3), intent(out) :: rotationmatrix
1389 !
1390 ! Local variables.
1391 !
1392  integer(kind=intType) :: i, j
1393 
1394  real(kind=realtype) :: phi, dphix, dphiy, dphiz
1395  real(kind=realtype) :: cosx, cosy, cosz, sinx, siny, sinz
1396 
1397  real(kind=realtype), dimension(3, 3) :: dm, m
1398 
1399  ! Determine the rotation angle around the x-axis for the new
1400  ! time level and the corresponding values of the sine and cosine.
1401 
1405  sinx = sin(phi)
1406  cosx = cos(phi)
1407  ! Idem for the y-axis.
1408 
1412  siny = sin(phi)
1413  cosy = cos(phi)
1414  ! Idem for the z-axis.
1415 
1419  sinz = sin(phi)
1420  cosz = cos(phi)
1421  ! Compute the time derivative of the rotation angles around the
1422  ! x-axis, y-axis and z-axis.
1423 
1425  coefpolxrot, &
1426  degreefourxrot, &
1427  omegafourxrot, &
1428  coscoeffourxrot, &
1429  sincoeffourxrot, t)
1430 
1432  coefpolyrot, &
1433  degreefouryrot, &
1434  omegafouryrot, &
1435  coscoeffouryrot, &
1436  sincoeffouryrot, t)
1437 
1439  coefpolzrot, &
1440  degreefourzrot, &
1441  omegafourzrot, &
1442  coscoeffourzrot, &
1443  sincoeffourzrot, t)
1444 
1445  ! Compute the time derivative of the rotation matrix applied to
1446  ! the coordinates at t == 0.
1447 
1448  ! Part 1. Derivative of the z-rotation matrix multiplied by the
1449  ! x and y rotation matrix, i.e. dmz * my * mx
1450 
1451  dm(1, 1) = -cosy * sinz * dphiz
1452  dm(1, 2) = (-cosx * cosz - sinx * siny * sinz) * dphiz
1453  dm(1, 3) = (sinx * cosz - cosx * siny * sinz) * dphiz
1454 
1455  dm(2, 1) = cosy * cosz * dphiz
1456  dm(2, 2) = (sinx * siny * cosz - cosx * sinz) * dphiz
1457  dm(2, 3) = (cosx * siny * cosz + sinx * sinz) * dphiz
1458 
1459  dm(3, 1) = zero
1460  dm(3, 2) = zero
1461  dm(3, 3) = zero
1462 
1463  ! Part 2: mz * dmy * mx.
1464 
1465  dm(1, 1) = dm(1, 1) - siny * cosz * dphiy
1466  dm(1, 2) = dm(1, 2) + sinx * cosy * cosz * dphiy
1467  dm(1, 3) = dm(1, 3) + cosx * cosy * cosz * dphiy
1468 
1469  dm(2, 1) = dm(2, 1) - siny * sinz * dphiy
1470  dm(2, 2) = dm(2, 2) + sinx * cosy * sinz * dphiy
1471  dm(2, 3) = dm(2, 3) + cosx * cosy * sinz * dphiy
1472 
1473  dm(3, 1) = dm(3, 1) - cosy * dphiy
1474  dm(3, 2) = dm(3, 2) - sinx * siny * dphiy
1475  dm(3, 3) = dm(3, 3) - cosx * siny * dphiy
1476 
1477  ! Part 3: mz * my * dmx
1478 
1479  dm(1, 2) = dm(1, 2) + (sinx * sinz + cosx * siny * cosz) * dphix
1480  dm(1, 3) = dm(1, 3) + (cosx * sinz - sinx * siny * cosz) * dphix
1481 
1482  dm(2, 2) = dm(2, 2) + (cosx * siny * sinz - sinx * cosz) * dphix
1483  dm(2, 3) = dm(2, 3) - (sinx * siny * sinz + cosx * cosz) * dphix
1484 
1485  dm(3, 2) = dm(3, 2) + cosx * cosy * dphix
1486  dm(3, 3) = dm(3, 3) - sinx * cosy * dphix
1487 
1488  ! Determine the rotation matrix at t == t.
1489 
1490  m(1, 1) = cosy * cosz
1491  m(2, 1) = cosy * sinz
1492  m(3, 1) = -siny
1493 
1494  m(1, 2) = sinx * siny * cosz - cosx * sinz
1495  m(2, 2) = sinx * siny * sinz + cosx * cosz
1496  m(3, 2) = sinx * cosy
1497 
1498  m(1, 3) = cosx * siny * cosz + sinx * sinz
1499  m(2, 3) = cosx * siny * sinz - sinx * cosz
1500  m(3, 3) = cosx * cosy
1501 
1502  ! Determine the matrix product dm * inverse(m), which will give
1503  ! the derivative of the rotation matrix when applied to the
1504  ! current coordinates. Note that inverse(m) == transpose(m).
1505 
1506  do j = 1, 3
1507  do i = 1, 3
1508  rotationmatrix(i, j) = dm(i, 1) * m(j, 1) + dm(i, 2) * m(j, 2) &
1509  + dm(i, 3) * m(j, 3)
1510  end do
1511  end do
1512 
1513  ! Determine the rotation point at the new time level; it is
1514  ! possible that this value changes due to translation of the grid.
1515 
1516  ! aInf = sqrt(gammaInf*pInf/rhoInf)
1517 
1518  ! RotationPoint(1) = LRef*rotPoint(1) &
1519  ! + MachGrid(1)*aInf*t/timeRef
1520  ! rotationPoint(2) = LRef*rotPoint(2) &
1521  ! + MachGrid(2)*aInf*t/timeRef
1522  ! rotationPoint(3) = LRef*rotPoint(3) &
1523  ! + MachGrid(3)*aInf*t/timeRef
1524 
1525  rotationpoint(1) = lref * rotpoint(1)
1526  rotationpoint(2) = lref * rotpoint(2)
1527  rotationpoint(3) = lref * rotpoint(3)
1528 
1529  end subroutine derivativerotmatrixrigid
1530 
1531  subroutine getdirvector(refDirection, alpha, beta, &
1532  windDirection, liftIndex)
1533  !(xb,yb,zb,alpha,beta,xw,yw,zw)
1534 !
1535 ! Convert the angle of attack and side slip angle to wind axes.
1536 ! The components of the wind direction vector (xw,yw,zw) are
1537 ! computed given the direction angles in radians and the body
1538 ! direction by performing two rotations on the original
1539 ! direction vector:
1540 ! 1) Rotation about the zb or yb-axis: alpha clockwise (CW)
1541 ! (xb,yb,zb) -> (x1,y1,z1)
1542 ! 2) Rotation about the yl or z1-axis: beta counter-clockwise
1543 ! (CCW) (x1,y1,z1) -> (xw,yw,zw)
1544 ! input arguments:
1545 ! alpha = angle of attack in radians
1546 ! beta = side slip angle in radians
1547 ! refDirection = reference direction vector
1548 ! output arguments:
1549 ! windDirection = unit wind vector in body axes
1550 !
1551  use constants
1552  use utils, only: terminate
1553  implicit none
1554 !
1555 ! Subroutine arguments.
1556 !
1557  real(kind=realtype), dimension(3), intent(in) :: refdirection
1558  real(kind=realtype) :: alpha, beta
1559  real(kind=realtype), dimension(3), intent(out) :: winddirection
1560  integer(kind=intType) :: liftIndex
1561 !
1562 ! Local variables.
1563 !
1564  real(kind=realtype) :: rnorm, x1, y1, z1, xbn, ybn, zbn, xw, yw, zw
1565  real(kind=realtype) :: tmp
1566 
1567  ! Normalize the input vector.
1568 
1569  rnorm = sqrt(refdirection(1)**2 + refdirection(2)**2 + refdirection(3)**2)
1570  xbn = refdirection(1) / rnorm
1571  ybn = refdirection(2) / rnorm
1572  zbn = refdirection(3) / rnorm
1573 
1574 !!$ ! Compute the wind direction vector.
1575 !!$
1576 !!$ ! 1) rotate alpha radians cw about y-axis
1577 !!$ ! ( <=> rotate y-axis alpha radians ccw)
1578 !!$
1579 !!$ call vectorRotation(x1, y1, z1, 2, alpha, xbn, ybn, zbn)
1580 !!$
1581 !!$ ! 2) rotate beta radians ccw about z-axis
1582 !!$ ! ( <=> rotate z-axis -beta radians ccw)
1583 !!$
1584 !!$ call vectorRotation(xw, yw, zw, 3, -beta, x1, y1, z1)
1585 
1586  if (liftindex == 2) then
1587  ! Compute the wind direction vector.Aerosurf axes different!!
1588 
1589  ! 1) rotate alpha radians cw about z-axis
1590  ! ( <=> rotate z-axis alpha radians ccw)
1591 
1592  tmp = -alpha
1593  call vectorrotation(x1, y1, z1, 3, tmp, xbn, ybn, zbn)
1594 
1595  ! 2) rotate beta radians ccw about y-axis
1596  ! ( <=> rotate z-axis -beta radians ccw)
1597  tmp = -beta
1598  call vectorrotation(xw, yw, zw, 2, tmp, x1, y1, z1)
1599 
1600  elseif (liftindex == 3) then
1601  ! Compute the wind direction vector.Aerosurf axes different!!
1602 
1603  ! 1) rotate alpha radians cw about z-axis
1604  ! ( <=> rotate z-axis alpha radians ccw)
1605 
1606  call vectorrotation(x1, y1, z1, 2, alpha, xbn, ybn, zbn)
1607 
1608  ! 2) rotate beta radians ccw about y-axis
1609  ! ( <=> rotate z-axis -beta radians ccw)
1610 
1611  call vectorrotation(xw, yw, zw, 3, beta, x1, y1, z1)
1612 
1613  else
1614  call terminate('getDirVector', 'Invalid Lift Direction')
1615 
1616  end if
1617 
1618  winddirection(1) = xw
1619  winddirection(2) = yw
1620  winddirection(3) = zw
1621 
1622  end subroutine getdirvector
1623  subroutine vectorrotation(xp, yp, zp, iaxis, angle, x, y, z)
1624 !
1625 ! vectorRotation rotates a given vector with respect to a
1626 ! specified axis by a given angle.
1627 ! input arguments:
1628 ! iaxis = rotation axis (1-x, 2-y, 3-z)
1629 ! angle = rotation angle (measured ccw in radians)
1630 ! x, y, z = coordinates in original system
1631 ! output arguments:
1632 ! xp, yp, zp = coordinates in rotated system
1633 !
1634  use precision
1635  implicit none
1636 !
1637 ! Subroutine arguments.
1638 !
1639  integer(kind=intType), intent(in) :: iaxis
1640  real(kind=realtype), intent(in) :: angle, x, y, z
1641  real(kind=realtype), intent(out) :: xp, yp, zp
1642 
1643  ! rotation about specified axis by specified angle
1644 
1645  select case (iaxis)
1646 
1647  ! rotation about the x-axis
1648 
1649  case (1)
1650  xp = 1.*x + 0.*y + 0.*z
1651  yp = 0.*x + cos(angle) * y + sin(angle) * z
1652  zp = 0.*x - sin(angle) * y + cos(angle) * z
1653 
1654  ! rotation about the y-axis
1655 
1656  case (2)
1657  xp = cos(angle) * x + 0.*y - sin(angle) * z
1658  yp = 0.*x + 1.*y + 0.*z
1659  zp = sin(angle) * x + 0.*y + cos(angle) * z
1660 
1661  ! rotation about the z-axis
1662 
1663  case (3)
1664  xp = cos(angle) * x + sin(angle) * y + 0.*z
1665  yp = -sin(angle) * x + cos(angle) * y + 0.*z
1666  zp = 0.*x + 0.*y + 1.*z
1667 
1668  case default
1669  write (*, *) "vectorRotation called with invalid arguments"
1670  stop
1671 
1672  end select
1673 
1674  end subroutine vectorrotation
1675 
1677  !
1678  ! nodalGradients computes the nodal velocity gradients and
1679  ! minus the gradient of the speed of sound squared. The minus
1680  ! sign is present, because this is the definition of the heat
1681  ! flux. These gradients are computed for all nodes.
1682  !
1683  use constants
1684  use blockpointers
1685  implicit none
1686  ! Local variables.
1687  integer(kind=intType) :: i, j, k
1688  integer(kind=intType) :: k1, kk
1689  integer(kind=intType) :: istart, iend, isize, ii
1690  integer(kind=intType) :: jstart, jend, jsize
1691  integer(kind=intType) :: kstart, kend, ksize
1692 
1693  real(kind=realtype) :: oneoverv, ubar, vbar, wbar, a2
1694  real(kind=realtype) :: sx, sx1, sy, sy1, sz, sz1
1695 
1696  ! Zero all nodeal gradients:
1697  ux = zero; uy = zero; uz = zero;
1698  vx = zero; vy = zero; vz = zero;
1699  wx = zero; wy = zero; wz = zero;
1700  qx = zero; qy = zero; qz = zero;
1701  ! First part. Contribution in the k-direction.
1702  ! The contribution is scattered to both the left and right node
1703  ! in k-direction.
1704 
1705 #ifdef TAPENADE_REVERSE
1706  !$AD II-LOOP
1707  do ii = 0, il * jl * ke - 1
1708  i = mod(ii, il) + 1
1709  j = mod(ii / il, jl) + 1
1710  k = ii / (il * jl) + 1
1711 #else
1712  do k = 1, ke
1713  do j = 1, jl
1714  do i = 1, il
1715 #endif
1716  ! Compute 8 times the average normal for this part of
1717  ! the control volume. The factor 8 is taken care of later
1718  ! on when the division by the volume takes place.
1719 
1720  sx = sk(i, j, k - 1, 1) + sk(i + 1, j, k - 1, 1) &
1721  + sk(i, j + 1, k - 1, 1) + sk(i + 1, j + 1, k - 1, 1) &
1722  + sk(i, j, k, 1) + sk(i + 1, j, k, 1) &
1723  + sk(i, j + 1, k, 1) + sk(i + 1, j + 1, k, 1)
1724  sy = sk(i, j, k - 1, 2) + sk(i + 1, j, k - 1, 2) &
1725  + sk(i, j + 1, k - 1, 2) + sk(i + 1, j + 1, k - 1, 2) &
1726  + sk(i, j, k, 2) + sk(i + 1, j, k, 2) &
1727  + sk(i, j + 1, k, 2) + sk(i + 1, j + 1, k, 2)
1728  sz = sk(i, j, k - 1, 3) + sk(i + 1, j, k - 1, 3) &
1729  + sk(i, j + 1, k - 1, 3) + sk(i + 1, j + 1, k - 1, 3) &
1730  + sk(i, j, k, 3) + sk(i + 1, j, k, 3) &
1731  + sk(i, j + 1, k, 3) + sk(i + 1, j + 1, k, 3)
1732 
1733  ! Compute the average velocities and speed of sound squared
1734  ! for this integration point. Node that these variables are
1735  ! stored in w(ivx), w(ivy), w(ivz) and p.
1736 
1737  ubar = fourth * (w(i, j, k, ivx) + w(i + 1, j, k, ivx) &
1738  + w(i, j + 1, k, ivx) + w(i + 1, j + 1, k, ivx))
1739  vbar = fourth * (w(i, j, k, ivy) + w(i + 1, j, k, ivy) &
1740  + w(i, j + 1, k, ivy) + w(i + 1, j + 1, k, ivy))
1741  wbar = fourth * (w(i, j, k, ivz) + w(i + 1, j, k, ivz) &
1742  + w(i, j + 1, k, ivz) + w(i + 1, j + 1, k, ivz))
1743 
1744  a2 = fourth * (aa(i, j, k) + aa(i + 1, j, k) + aa(i, j + 1, k) + aa(i + 1, j + 1, k))
1745 
1746  ! Add the contributions to the surface integral to the node
1747  ! j-1 and substract it from the node j. For the heat flux it
1748  ! is reversed, because the negative of the gradient of the
1749  ! speed of sound must be computed.
1750 
1751  if (k > 1) then
1752  ux(i, j, k - 1) = ux(i, j, k - 1) + ubar * sx
1753  uy(i, j, k - 1) = uy(i, j, k - 1) + ubar * sy
1754  uz(i, j, k - 1) = uz(i, j, k - 1) + ubar * sz
1755 
1756  vx(i, j, k - 1) = vx(i, j, k - 1) + vbar * sx
1757  vy(i, j, k - 1) = vy(i, j, k - 1) + vbar * sy
1758  vz(i, j, k - 1) = vz(i, j, k - 1) + vbar * sz
1759 
1760  wx(i, j, k - 1) = wx(i, j, k - 1) + wbar * sx
1761  wy(i, j, k - 1) = wy(i, j, k - 1) + wbar * sy
1762  wz(i, j, k - 1) = wz(i, j, k - 1) + wbar * sz
1763 
1764  qx(i, j, k - 1) = qx(i, j, k - 1) - a2 * sx
1765  qy(i, j, k - 1) = qy(i, j, k - 1) - a2 * sy
1766  qz(i, j, k - 1) = qz(i, j, k - 1) - a2 * sz
1767  end if
1768 
1769  if (k < ke) then
1770  ux(i, j, k) = ux(i, j, k) - ubar * sx
1771  uy(i, j, k) = uy(i, j, k) - ubar * sy
1772  uz(i, j, k) = uz(i, j, k) - ubar * sz
1773 
1774  vx(i, j, k) = vx(i, j, k) - vbar * sx
1775  vy(i, j, k) = vy(i, j, k) - vbar * sy
1776  vz(i, j, k) = vz(i, j, k) - vbar * sz
1777 
1778  wx(i, j, k) = wx(i, j, k) - wbar * sx
1779  wy(i, j, k) = wy(i, j, k) - wbar * sy
1780  wz(i, j, k) = wz(i, j, k) - wbar * sz
1781 
1782  qx(i, j, k) = qx(i, j, k) + a2 * sx
1783  qy(i, j, k) = qy(i, j, k) + a2 * sy
1784  qz(i, j, k) = qz(i, j, k) + a2 * sz
1785  end if
1786 #ifdef TAPENADE_REVERSE
1787  end do
1788 #else
1789  end do
1790  end do
1791  end do
1792 #endif
1793 
1794  ! Second part. Contribution in the j-direction.
1795  ! The contribution is scattered to both the left and right node
1796  ! in j-direction.
1797 
1798 #ifdef TAPENADE_REVERSE
1799  !$AD II-LOOP
1800  do ii = 0, il * je * kl - 1
1801  i = mod(ii, il) + 1
1802  j = mod(ii / il, je) + 1
1803  k = ii / (il * je) + 1
1804 #else
1805  do k = 1, kl
1806  do j = 1, je
1807  do i = 1, il
1808 #endif
1809 
1810  ! Compute 8 times the average normal for this part of
1811  ! the control volume. The factor 8 is taken care of later
1812  ! on when the division by the volume takes place.
1813 
1814  sx = sj(i, j - 1, k, 1) + sj(i + 1, j - 1, k, 1) &
1815  + sj(i, j - 1, k + 1, 1) + sj(i + 1, j - 1, k + 1, 1) &
1816  + sj(i, j, k, 1) + sj(i + 1, j, k, 1) &
1817  + sj(i, j, k + 1, 1) + sj(i + 1, j, k + 1, 1)
1818  sy = sj(i, j - 1, k, 2) + sj(i + 1, j - 1, k, 2) &
1819  + sj(i, j - 1, k + 1, 2) + sj(i + 1, j - 1, k + 1, 2) &
1820  + sj(i, j, k, 2) + sj(i + 1, j, k, 2) &
1821  + sj(i, j, k + 1, 2) + sj(i + 1, j, k + 1, 2)
1822  sz = sj(i, j - 1, k, 3) + sj(i + 1, j - 1, k, 3) &
1823  + sj(i, j - 1, k + 1, 3) + sj(i + 1, j - 1, k + 1, 3) &
1824  + sj(i, j, k, 3) + sj(i + 1, j, k, 3) &
1825  + sj(i, j, k + 1, 3) + sj(i + 1, j, k + 1, 3)
1826 
1827  ! Compute the average velocities and speed of sound squared
1828  ! for this integration point. Node that these variables are
1829  ! stored in w(ivx), w(ivy), w(ivz) and p.
1830 
1831  ubar = fourth * (w(i, j, k, ivx) + w(i + 1, j, k, ivx) &
1832  + w(i, j, k + 1, ivx) + w(i + 1, j, k + 1, ivx))
1833  vbar = fourth * (w(i, j, k, ivy) + w(i + 1, j, k, ivy) &
1834  + w(i, j, k + 1, ivy) + w(i + 1, j, k + 1, ivy))
1835  wbar = fourth * (w(i, j, k, ivz) + w(i + 1, j, k, ivz) &
1836  + w(i, j, k + 1, ivz) + w(i + 1, j, k + 1, ivz))
1837 
1838  a2 = fourth * (aa(i, j, k) + aa(i + 1, j, k) + aa(i, j, k + 1) + aa(i + 1, j, k + 1))
1839 
1840  ! Add the contributions to the surface integral to the node
1841  ! j-1 and substract it from the node j. For the heat flux it
1842  ! is reversed, because the negative of the gradient of the
1843  ! speed of sound must be computed.
1844 
1845  if (j > 1) then
1846  ux(i, j - 1, k) = ux(i, j - 1, k) + ubar * sx
1847  uy(i, j - 1, k) = uy(i, j - 1, k) + ubar * sy
1848  uz(i, j - 1, k) = uz(i, j - 1, k) + ubar * sz
1849 
1850  vx(i, j - 1, k) = vx(i, j - 1, k) + vbar * sx
1851  vy(i, j - 1, k) = vy(i, j - 1, k) + vbar * sy
1852  vz(i, j - 1, k) = vz(i, j - 1, k) + vbar * sz
1853 
1854  wx(i, j - 1, k) = wx(i, j - 1, k) + wbar * sx
1855  wy(i, j - 1, k) = wy(i, j - 1, k) + wbar * sy
1856  wz(i, j - 1, k) = wz(i, j - 1, k) + wbar * sz
1857 
1858  qx(i, j - 1, k) = qx(i, j - 1, k) - a2 * sx
1859  qy(i, j - 1, k) = qy(i, j - 1, k) - a2 * sy
1860  qz(i, j - 1, k) = qz(i, j - 1, k) - a2 * sz
1861  end if
1862 
1863  if (j < je) then
1864  ux(i, j, k) = ux(i, j, k) - ubar * sx
1865  uy(i, j, k) = uy(i, j, k) - ubar * sy
1866  uz(i, j, k) = uz(i, j, k) - ubar * sz
1867 
1868  vx(i, j, k) = vx(i, j, k) - vbar * sx
1869  vy(i, j, k) = vy(i, j, k) - vbar * sy
1870  vz(i, j, k) = vz(i, j, k) - vbar * sz
1871 
1872  wx(i, j, k) = wx(i, j, k) - wbar * sx
1873  wy(i, j, k) = wy(i, j, k) - wbar * sy
1874  wz(i, j, k) = wz(i, j, k) - wbar * sz
1875 
1876  qx(i, j, k) = qx(i, j, k) + a2 * sx
1877  qy(i, j, k) = qy(i, j, k) + a2 * sy
1878  qz(i, j, k) = qz(i, j, k) + a2 * sz
1879  end if
1880 #ifdef TAPENADE_REVERSE
1881  end do
1882 #else
1883  end do
1884  end do
1885  end do
1886 #endif
1887 
1888  ! Third part. Contribution in the i-direction.
1889  ! The contribution is scattered to both the left and right node
1890  ! in i-direction.
1891 
1892 #ifdef TAPENADE_REVERSE
1893  !$AD II-LOOP
1894  do ii = 0, ie * jl * kl - 1
1895  i = mod(ii, ie) + 1
1896  j = mod(ii / ie, jl) + 1
1897  k = ii / (ie * jl) + 1
1898 #else
1899  do k = 1, kl
1900  do j = 1, jl
1901  do i = 1, ie
1902 #endif
1903 
1904  ! Compute 8 times the average normal for this part of
1905  ! the control volume. The factor 8 is taken care of later
1906  ! on when the division by the volume takes place.
1907 
1908  sx = si(i - 1, j, k, 1) + si(i - 1, j + 1, k, 1) &
1909  + si(i - 1, j, k + 1, 1) + si(i - 1, j + 1, k + 1, 1) &
1910  + si(i, j, k, 1) + si(i, j + 1, k, 1) &
1911  + si(i, j, k + 1, 1) + si(i, j + 1, k + 1, 1)
1912  sy = si(i - 1, j, k, 2) + si(i - 1, j + 1, k, 2) &
1913  + si(i - 1, j, k + 1, 2) + si(i - 1, j + 1, k + 1, 2) &
1914  + si(i, j, k, 2) + si(i, j + 1, k, 2) &
1915  + si(i, j, k + 1, 2) + si(i, j + 1, k + 1, 2)
1916  sz = si(i - 1, j, k, 3) + si(i - 1, j + 1, k, 3) &
1917  + si(i - 1, j, k + 1, 3) + si(i - 1, j + 1, k + 1, 3) &
1918  + si(i, j, k, 3) + si(i, j + 1, k, 3) &
1919  + si(i, j, k + 1, 3) + si(i, j + 1, k + 1, 3)
1920 
1921  ! Compute the average velocities and speed of sound squared
1922  ! for this integration point. Node that these variables are
1923  ! stored in w(ivx), w(ivy), w(ivz) and p.
1924 
1925  ubar = fourth * (w(i, j, k, ivx) + w(i, j + 1, k, ivx) &
1926  + w(i, j, k + 1, ivx) + w(i, j + 1, k + 1, ivx))
1927  vbar = fourth * (w(i, j, k, ivy) + w(i, j + 1, k, ivy) &
1928  + w(i, j, k + 1, ivy) + w(i, j + 1, k + 1, ivy))
1929  wbar = fourth * (w(i, j, k, ivz) + w(i, j + 1, k, ivz) &
1930  + w(i, j, k + 1, ivz) + w(i, j + 1, k + 1, ivz))
1931 
1932  a2 = fourth * (aa(i, j, k) + aa(i, j + 1, k) + aa(i, j, k + 1) + aa(i, j + 1, k + 1))
1933 
1934  ! Add the contributions to the surface integral to the node
1935  ! j-1 and substract it from the node j. For the heat flux it
1936  ! is reversed, because the negative of the gradient of the
1937  ! speed of sound must be computed.
1938 
1939  if (i > 1) then
1940  ux(i - 1, j, k) = ux(i - 1, j, k) + ubar * sx
1941  uy(i - 1, j, k) = uy(i - 1, j, k) + ubar * sy
1942  uz(i - 1, j, k) = uz(i - 1, j, k) + ubar * sz
1943 
1944  vx(i - 1, j, k) = vx(i - 1, j, k) + vbar * sx
1945  vy(i - 1, j, k) = vy(i - 1, j, k) + vbar * sy
1946  vz(i - 1, j, k) = vz(i - 1, j, k) + vbar * sz
1947 
1948  wx(i - 1, j, k) = wx(i - 1, j, k) + wbar * sx
1949  wy(i - 1, j, k) = wy(i - 1, j, k) + wbar * sy
1950  wz(i - 1, j, k) = wz(i - 1, j, k) + wbar * sz
1951 
1952  qx(i - 1, j, k) = qx(i - 1, j, k) - a2 * sx
1953  qy(i - 1, j, k) = qy(i - 1, j, k) - a2 * sy
1954  qz(i - 1, j, k) = qz(i - 1, j, k) - a2 * sz
1955  end if
1956 
1957  if (i < ie) then
1958  ux(i, j, k) = ux(i, j, k) - ubar * sx
1959  uy(i, j, k) = uy(i, j, k) - ubar * sy
1960  uz(i, j, k) = uz(i, j, k) - ubar * sz
1961 
1962  vx(i, j, k) = vx(i, j, k) - vbar * sx
1963  vy(i, j, k) = vy(i, j, k) - vbar * sy
1964  vz(i, j, k) = vz(i, j, k) - vbar * sz
1965 
1966  wx(i, j, k) = wx(i, j, k) - wbar * sx
1967  wy(i, j, k) = wy(i, j, k) - wbar * sy
1968  wz(i, j, k) = wz(i, j, k) - wbar * sz
1969 
1970  qx(i, j, k) = qx(i, j, k) + a2 * sx
1971  qy(i, j, k) = qy(i, j, k) + a2 * sy
1972  qz(i, j, k) = qz(i, j, k) + a2 * sz
1973  end if
1974 #ifdef TAPENADE_REVERSE
1975  end do
1976 #else
1977  end do
1978  end do
1979  end do
1980 #endif
1981  ! Divide by 8 times the volume to obtain the correct gradients.
1982 
1983 #ifdef TAPENADE_REVERSE
1984  !$AD II-LOOP
1985  do ii = 0, il * jl * kl - 1
1986  i = mod(ii, il) + 1
1987  j = mod(ii / il, jl) + 1
1988  k = ii / (il * jl) + 1
1989 #else
1990  do k = 1, kl
1991  do j = 1, jl
1992  do i = 1, il
1993 #endif
1994  ! Compute the inverse of 8 times the volume for this node.
1995 
1996  oneoverv = one / (vol(i, j, k) + vol(i, j, k + 1) &
1997  + vol(i + 1, j, k) + vol(i + 1, j, k + 1) &
1998  + vol(i, j + 1, k) + vol(i, j + 1, k + 1) &
1999  + vol(i + 1, j + 1, k) + vol(i + 1, j + 1, k + 1))
2000 
2001  ! Compute the correct velocity gradients and "unit" heat
2002  ! fluxes. The velocity gradients are stored in ux, etc.
2003 
2004  ux(i, j, k) = ux(i, j, k) * oneoverv
2005  uy(i, j, k) = uy(i, j, k) * oneoverv
2006  uz(i, j, k) = uz(i, j, k) * oneoverv
2007 
2008  vx(i, j, k) = vx(i, j, k) * oneoverv
2009  vy(i, j, k) = vy(i, j, k) * oneoverv
2010  vz(i, j, k) = vz(i, j, k) * oneoverv
2011 
2012  wx(i, j, k) = wx(i, j, k) * oneoverv
2013  wy(i, j, k) = wy(i, j, k) * oneoverv
2014  wz(i, j, k) = wz(i, j, k) * oneoverv
2015 
2016  qx(i, j, k) = qx(i, j, k) * oneoverv
2017  qy(i, j, k) = qy(i, j, k) * oneoverv
2018  qz(i, j, k) = qz(i, j, k) * oneoverv
2019 #ifdef TAPENADE_REVERSE
2020  end do
2021 #else
2022  end do
2023  end do
2024  end do
2025 #endif
2026  end subroutine allnodalgradients
2027 
2028  ! ----------------------------------------------------------------------
2029  ! |
2030  ! No Tapenade Routine below this line |
2031  ! |
2032  ! ----------------------------------------------------------------------
2033 
2034 #ifndef USE_TAPENADE
2035 
2037 
2038  use constants
2039  use blockpointers, only: il, jl, kl, vol, ux, uy, uz, vx, vy, vz, &
2040  wx, wy, wz, qx, qy, qz, vol
2041  implicit none
2042 
2043  ! WorkingVariables
2044  integer(kind=intType) :: i, j, k
2045  real(kind=realtype) :: oneoverv
2046 
2047  ! So the all nodal gradients doesnt' perform the final
2048  ! scalaing by the volume since it isn't necessary for the
2049  ! derivative. We need to fix that here:
2050 
2051  ! Divide by 8 times the volume to obtain the correct gradients.
2052  do k = 1, kl
2053  do j = 1, jl
2054  do i = 1, il
2055 
2056  ! Compute the inverse of 8 times the volume for this node.
2057 
2058  oneoverv = one / (vol(i, j, k) + vol(i, j, k + 1) &
2059  + vol(i + 1, j, k) + vol(i + 1, j, k + 1) &
2060  + vol(i, j + 1, k) + vol(i, j + 1, k + 1) &
2061  + vol(i + 1, j + 1, k) + vol(i + 1, j + 1, k + 1))
2062 
2063  ! Compute the correct velocity gradients and "unit" heat
2064  ! fluxes. The velocity gradients are stored in ux, etc.
2065 
2066  ux(i, j, k) = ux(i, j, k) * oneoverv
2067  uy(i, j, k) = uy(i, j, k) * oneoverv
2068  uz(i, j, k) = uz(i, j, k) * oneoverv
2069 
2070  vx(i, j, k) = vx(i, j, k) * oneoverv
2071  vy(i, j, k) = vy(i, j, k) * oneoverv
2072  vz(i, j, k) = vz(i, j, k) * oneoverv
2073 
2074  wx(i, j, k) = wx(i, j, k) * oneoverv
2075  wy(i, j, k) = wy(i, j, k) * oneoverv
2076  wz(i, j, k) = wz(i, j, k) * oneoverv
2077 
2078  qx(i, j, k) = qx(i, j, k) * oneoverv
2079  qy(i, j, k) = qy(i, j, k) * oneoverv
2080  qz(i, j, k) = qz(i, j, k) * oneoverv
2081  end do
2082  end do
2083  end do
2084  end subroutine fixallnodalgradientsfromad
2085 
2086  subroutine computeetotcellcpfit(i, j, k, scale, correctForK)
2087  !
2088  ! ComputeEtotCellCpfit will compute the total energy for the
2089  ! given cell of the block given by the current pointers with the
2090  ! cp temperature curve fit model.
2091  !
2092  use constants
2093  use cpcurvefits
2094  use blockpointers, only: gamma, w, p
2095  use flowvarrefstate, only: rgas, tref
2096  implicit none
2097  !
2098  ! Local parameter.
2099  !
2100  real(kind=realtype), parameter :: twothird = two * third
2101  !
2102  ! Subroutine arguments.
2103  !
2104  integer(kind=intType), intent(in) :: i, j, k
2105  real(kind=realtype), intent(in) :: scale
2106  logical, intent(in) :: correctForK
2107  !
2108  ! Local variables.
2109  !
2110  integer(kind=intType) :: nn, mm, ii, start
2111 
2112  real(kind=realtype) :: pp, t, t2, cv, eint
2113 
2114  ! Compute the dimensional temperature.
2115 
2116  pp = p(i, j, k)
2117  if (correctfork) pp = pp - twothird &
2118  * w(i, j, k, irho) * w(i, j, k, itu1)
2119  t = tref * pp / (rgas * w(i, j, k, irho))
2120 
2121  ! Determine the case we are having here.
2122 
2123  if (t <= cptrange(0)) then
2124 
2125  ! Temperature is less than the smallest temperature
2126  ! in the curve fits. Use extrapolation using
2127  ! constant cv.
2128 
2129  eint = scale * (cpeint(0) + cv0 * (t - cptrange(0)))
2130  gamma(i, j, k) = (cv0 + one) / cv0
2131 
2132  else if (t >= cptrange(cpnparts)) then
2133 
2134  ! Temperature is larger than the largest temperature
2135  ! in the curve fits. Use extrapolation using
2136  ! constant cv.
2137 
2138  eint = scale * (cpeint(cpnparts) &
2139  + cvn * (t - cptrange(cpnparts)))
2140 
2141  gamma(i, j, k) = (cvn + one) / cvn
2142 
2143  else
2144 
2145  ! Temperature is in the curve fit range.
2146  ! First find the valid range.
2147 
2148  ii = cpnparts
2149  start = 1
2150  interval: do
2151 
2152  ! Next guess for the interval.
2153 
2154  nn = start + ii / 2
2155 
2156  ! Determine the situation we are having here.
2157 
2158  if (t > cptrange(nn)) then
2159 
2160  ! Temperature is larger than the upper boundary of
2161  ! the current interval. Update the lower boundary.
2162 
2163  start = nn + 1
2164  ii = ii - 1
2165 
2166  else if (t >= cptrange(nn - 1)) then
2167 
2168  ! This is the correct range. Exit the do-loop.
2169 
2170  exit
2171 
2172  end if
2173 
2174  ! Modify ii for the next branch to search.
2175 
2176  ii = ii / 2
2177 
2178  end do interval
2179 
2180  ! Nn contains the correct curve fit interval.
2181  ! Integrate cv to compute eint.
2182 
2183  eint = cptempfit(nn)%eint0 - t
2184  cv = -one
2185 
2186  do ii = 1, cptempfit(nn)%nterm
2187  t2 = t**cptempfit(nn)%exponents(ii)
2188  cv = cv + cptempfit(nn)%constants(ii) * t2
2189 
2190  if (cptempfit(nn)%exponents(ii) == -1) then
2191  eint = eint + cptempfit(nn)%constants(ii) * log(t)
2192  else
2193  mm = cptempfit(nn)%exponents(ii) + 1
2194  t2 = t * t2
2195  eint = eint + cptempfit(nn)%constants(ii) * t2 / mm
2196  end if
2197  end do
2198 
2199  eint = scale * eint
2200  gamma(i, j, k) = (cv + one) / cv
2201 
2202  end if
2203 
2204  ! Compute the total energy per unit volume.
2205 
2206  w(i, j, k, irhoe) = w(i, j, k, irho) * (eint &
2207  + half * (w(i, j, k, ivx)**2 &
2208  + w(i, j, k, ivy)**2 &
2209  + w(i, j, k, ivz)**2))
2210 
2211  if (correctfork) &
2212  w(i, j, k, irhoe) = w(i, j, k, irhoe) &
2213  + w(i, j, k, irho) * w(i, j, k, itu1)
2214 
2215  end subroutine computeetotcellcpfit
2216 
2217  subroutine updategamma
2218  !
2219  ! This is a utility routine to update the gamma variable from
2220  ! from gammaConstant if gammaConstant has changed.
2221  !
2222  use constants
2223  use blockpointers, only: ndom, gamma
2225  use inputphysics, only: gammaconstant
2226  use utils, only: setpointers
2227  implicit none
2228 
2229  integer :: nn, sps
2230 
2231  do sps = 1, ntimeintervalsspectral
2232  do nn = 1, ndom
2233  call setpointers(nn, 1_inttype, sps)
2235  end do
2236  end do
2237  end subroutine updategamma
2238 #endif
2239 end module flowutils
real(kind=realtype), dimension(:, :, :), pointer gamma
real(kind=realtype), dimension(:, :, :), pointer qz
integer(kind=inttype) jl
real(kind=realtype), dimension(:, :, :), pointer qy
real(kind=realtype), dimension(:, :, :), pointer aa
real(kind=realtype), dimension(:, :, :), pointer uz
real(kind=realtype), dimension(:, :, :), pointer p
integer(kind=inttype) ie
real(kind=realtype), dimension(:, :, :, :), pointer w
real(kind=realtype), dimension(:, :, :), pointer uy
real(kind=realtype), dimension(:, :, :), pointer wx
integer(kind=inttype) jb
integer(kind=inttype) kb
real(kind=realtype), dimension(:, :, :), pointer rlv
real(kind=realtype), dimension(:, :, :, :), pointer si
real(kind=realtype), dimension(:, :, :, :), pointer sj
real(kind=realtype), dimension(:, :, :), pointer qx
real(kind=realtype), dimension(:, :, :), pointer vz
real(kind=realtype), dimension(:, :, :, :), pointer sk
real(kind=realtype), dimension(:, :, :), pointer ux
real(kind=realtype), dimension(:, :, :), pointer wy
real(kind=realtype), dimension(:, :, :), pointer wz
real(kind=realtype), dimension(:, :, :), pointer vol
integer(kind=inttype) ib
real(kind=realtype), dimension(:, :, :), pointer vy
real(kind=realtype), dimension(:, :, :), pointer vx
integer(kind=inttype) je
integer(kind=inttype) ke
integer(kind=inttype) kl
integer(kind=inttype) il
integer(kind=inttype), parameter cptempcurvefits
Definition: constants.F90:124
real(kind=realtype), parameter zero
Definition: constants.F90:71
real(kind=realtype), parameter third
Definition: constants.F90:81
integer, parameter itu1
Definition: constants.F90:40
integer, parameter irho
Definition: constants.F90:34
integer, parameter ivx
Definition: constants.F90:35
integer, parameter irhoe
Definition: constants.F90:38
real(kind=realtype), parameter five
Definition: constants.F90:76
real(kind=realtype), parameter one
Definition: constants.F90:72
real(kind=realtype), parameter half
Definition: constants.F90:80
integer, parameter ivz
Definition: constants.F90:37
real(kind=realtype), parameter two
Definition: constants.F90:73
integer(kind=inttype), parameter cpconstant
Definition: constants.F90:124
real(kind=realtype), parameter fourth
Definition: constants.F90:82
integer, parameter ivy
Definition: constants.F90:36
real(kind=realtype) cvn
Definition: CpCurveFits.f90:58
real(kind=realtype), dimension(:), allocatable cptrange
Definition: CpCurveFits.f90:46
integer(kind=inttype) cpnparts
Definition: CpCurveFits.f90:44
real(kind=realtype), dimension(:), allocatable cphint
Definition: CpCurveFits.f90:48
real(kind=realtype) cv0
Definition: CpCurveFits.f90:58
type(cptempfittype), dimension(:), allocatable cptempfit
Definition: CpCurveFits.f90:49
real(kind=realtype), dimension(:), allocatable cpeint
Definition: CpCurveFits.f90:47
subroutine getdirvector(refDirection, alpha, beta, windDirection, liftIndex)
Definition: flowUtils.F90:1533
subroutine computepressure(iBeg, iEnd, jBeg, jEnd, kBeg, kEnd, pointerOffset)
Definition: flowUtils.F90:934
subroutine allnodalgradients
Definition: flowUtils.F90:1677
subroutine computeetotcellcpfit(i, j, k, scale, correctForK)
Definition: flowUtils.F90:2087
subroutine eint(rho, p, k, einternal, correctForK)
Definition: flowUtils.F90:708
subroutine fixallnodalgradientsfromad
Definition: flowUtils.F90:2037
subroutine computespeedofsoundsquared
Definition: flowUtils.F90:489
subroutine derivativerotmatrixrigid(rotationMatrix, rotationPoint, t)
Definition: flowUtils.F90:1368
subroutine computepressuresimple(includeHalos)
Definition: flowUtils.F90:868
subroutine computelamviscosity(includeHalos)
Definition: flowUtils.F90:1202
subroutine adjustinflowangle()
Definition: flowUtils.F90:1326
subroutine computeetotblock(iStart, iEnd, jStart, jEnd, kStart, kEnd, correctForK)
Definition: flowUtils.F90:553
subroutine vectorrotation(xp, yp, zp, iaxis, angle, x, y, z)
Definition: flowUtils.F90:1624
subroutine updategamma
Definition: flowUtils.F90:2218
subroutine computegamma(T, gamma, mm)
Definition: flowUtils.F90:56
subroutine computettot(rho, u, v, w, p, Ttot)
Definition: flowUtils.F90:5
subroutine etot(rho, u, v, w, p, k, etotal, correctForK)
Definition: flowUtils.F90:675
subroutine computeptot(rho, u, v, w, p, ptot)
Definition: flowUtils.F90:171
real(kind=realtype) gammainf
real(kind=realtype) pinfcorr
real(kind=realtype) pinf
real(kind=realtype) rgas
real(kind=realtype) muref
real(kind=realtype) tref
real(kind=realtype) lref
integer(kind=inttype) degreefouryrot
Definition: inputParam.F90:354
integer(kind=inttype) degreefourxrot
Definition: inputParam.F90:353
integer(kind=inttype) degreepolxrot
Definition: inputParam.F90:337
real(kind=realtype) omegafouryrot
Definition: inputParam.F90:363
integer(kind=inttype) degreepolyrot
Definition: inputParam.F90:338
real(kind=realtype), dimension(:), allocatable coefpolxrot
Definition: inputParam.F90:345
real(kind=realtype) omegafourzrot
Definition: inputParam.F90:364
real(kind=realtype) omegafourxrot
Definition: inputParam.F90:362
real(kind=realtype), dimension(:), allocatable sincoeffouryrot
Definition: inputParam.F90:385
real(kind=realtype), dimension(:), allocatable coscoeffourxrot
Definition: inputParam.F90:373
real(kind=realtype), dimension(:), allocatable sincoeffourzrot
Definition: inputParam.F90:386
integer(kind=inttype) degreepolzrot
Definition: inputParam.F90:339
real(kind=realtype), dimension(:), allocatable coscoeffouryrot
Definition: inputParam.F90:374
integer(kind=inttype) degreefourzrot
Definition: inputParam.F90:355
real(kind=realtype), dimension(:), allocatable coefpolzrot
Definition: inputParam.F90:347
real(kind=realtype), dimension(:), allocatable coefpolyrot
Definition: inputParam.F90:346
real(kind=realtype), dimension(3) rotpoint
Definition: inputParam.F90:330
real(kind=realtype), dimension(:), allocatable coscoeffourzrot
Definition: inputParam.F90:375
real(kind=realtype), dimension(:), allocatable sincoeffourxrot
Definition: inputParam.F90:384
real(kind=realtype) ssuthdim
Definition: inputParam.F90:604
real(kind=realtype) gammaconstant
Definition: inputParam.F90:595
real(kind=realtype) tsuthdim
Definition: inputParam.F90:604
integer(kind=inttype) liftindex
Definition: inputParam.F90:592
real(kind=realtype), dimension(3) dragdirection
Definition: inputParam.F90:601
real(kind=realtype) beta
Definition: inputParam.F90:591
real(kind=realtype), dimension(3) liftdirection
Definition: inputParam.F90:600
integer(kind=inttype) cpmodel
Definition: inputParam.F90:584
real(kind=realtype), dimension(3) veldirfreestream
Definition: inputParam.F90:599
real(kind=realtype) musuthdim
Definition: inputParam.F90:604
real(kind=realtype) alpha
Definition: inputParam.F90:591
integer(kind=inttype) ntimeintervalsspectral
Definition: inputParam.F90:645
integer, parameter realtype
Definition: precision.F90:112
Definition: utils.F90:1
real(kind=realtype) function derivativerigidrotangle(degreePolRot, coefPolRot, degreeFourRot, omegaFourRot, cosCoefFourRot, sinCoefFourRot, t)
Definition: utils.F90:411
real(kind=realtype) function rigidrotangle(degreePolRot, coefPolRot, degreeFourRot, omegaFourRot, cosCoefFourRot, sinCoefFourRot, t)
Definition: utils.F90:820
logical function getcorrectfork()
Definition: utils.F90:487
subroutine setpointers(nn, mm, ll)
Definition: utils.F90:3237
subroutine terminate(routineName, errorMessage)
Definition: utils.F90:502