roninkoi

Fluid autocorrelation

Aug 29th, 2019
1,371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module correlator
  2.   implicit none
  3.  
  4.   integer, parameter :: rk = 8
  5.  
  6.   complex, allocatable :: vc(:)
  7.   complex, allocatable :: sc(:)
  8.  
  9.   real, allocatable :: work(:)
  10.   real, allocatable :: wsave(:)
  11.  
  12.   integer :: m, ier, lenwrk, lensav
  13. contains
  14.   function autocfft(v) ! autocorrelation via fft
  15.     real(rk), allocatable :: autocfft(:)
  16.     real(rk), allocatable :: v(:)
  17.  
  18.     m = size(v)
  19.  
  20.     call cfr(vc, v) ! create complex
  21.  
  22.     lenwrk = 2*m
  23.     lensav = 2*m + int(log(real(m, kind = 4)) / log(2.0E+00)) + 4
  24.  
  25.     allocate(work(lenwrk))
  26.     allocate(wsave(lensav))
  27.  
  28.     call cfft1i(m, wsave, lensav, ier) ! init fft
  29.  
  30.     ! fft of v
  31.     call cfft1f(m, 1, vc, 1*(m-1) + 1, wsave, lensav, work, lenwrk, ier)
  32.  
  33.     sc = vc
  34.  
  35.     call conjugate(vc) ! complex conjugate of fft
  36.  
  37.     sc = sc * vc ! S = F x F* (Wiener-Khinchin)
  38.  
  39.     ! inverse fft
  40.     call cfft1b(m, 1, sc, 1*(m-1) + 1, wsave, lensav, work, lenwrk, ier)
  41.  
  42.     call rfc(autocfft, sc) ! back to real
  43.  
  44.     deallocate(work)
  45.     deallocate(wsave)
  46.     deallocate(vc)
  47.     deallocate(sc)
  48.   end function autocfft
  49.  
  50.   function autoc(v) ! regular autocorrelation
  51.     real(rk), allocatable :: autoc(:)
  52.     real(rk), allocatable :: v(:)
  53.  
  54.     integer :: n, i
  55.  
  56.     n = size(v)
  57.  
  58.     allocate(autoc(n))
  59.  
  60.     do i = 1, n, 1
  61.        autoc(i) = rs(v, real(i, kind = rk))
  62.     end do
  63.   end function autoc
  64.  
  65.   real(rk) function rs(v, dt) ! R(s)
  66.     real(rk), allocatable :: v(:)
  67.     real(rk) :: dt
  68.  
  69.     integer :: n, t
  70.     real(rk) :: sd, s
  71.  
  72.     sd = stdv(v)
  73.     n = size(v)
  74.     s = 0
  75.     do t = 1, n - dt, 1
  76.        s = s + v(t)*v(t+dt)
  77.     end do
  78.  
  79.     rs = s * (1.0_8/((real(n) - dt)*sd**2))
  80.   end function rs
  81.  
  82.   function eulertime(v) ! time scale
  83.     real(rk) :: eulertime
  84.     real(rk), allocatable :: v(:)
  85.     real(rk), allocatable :: r(:)
  86.  
  87.     integer :: i, n
  88.  
  89.     n = size(v)
  90.  
  91.     r = autocfft(v)
  92.  
  93.     eulertime = 0
  94.     do i = 1, n - 2, 1
  95.        if (isnan(r(i)) .eqv. .false.) then
  96.           eulertime = eulertime + r(i)
  97.        endif
  98.     end do
  99.   end function eulertime
  100.  
  101.   function eulerlength(v) ! length scale
  102.     real(rk) :: eulerlength
  103.     real(rk), allocatable :: v(:)
  104.  
  105.     eulerlength = eulertime(v) * mean(v)
  106.   end function eulerlength
  107.  
  108.   subroutine mka(a, min, max, diff) ! make array
  109.     real(rk), allocatable :: a(:)
  110.     real(rk) :: max, min, diff
  111.  
  112.     integer :: n, i
  113.  
  114.     n = (max - min)/diff
  115.  
  116.     allocate(a(n))
  117.  
  118.     a(1) = min
  119.     do i = 2, n, 1
  120.        a(i) = a(i - 1) + diff
  121.     end do
  122.   end subroutine mka
  123.  
  124.   subroutine cfr(c, r) ! complex from real array
  125.     real(rk), allocatable :: r(:)
  126.     complex, allocatable :: c(:)
  127.  
  128.     integer :: i, n
  129.  
  130.     n = size(r)
  131.  
  132.     allocate(c(n))
  133.  
  134.     do i = 1, n, 1
  135.        c(i) = complex(r(i), 0)
  136.     end do
  137.   end subroutine cfr
  138.  
  139.   subroutine rfc(r, c) ! real from complex array
  140.     real(rk), allocatable :: r(:)
  141.     complex, allocatable :: c(:)
  142.  
  143.     integer :: i, n
  144.  
  145.     n = size(c)
  146.  
  147.     allocate(r(n))
  148.  
  149.     do i = 1, n, 1
  150.        r(i) = real(c(i))
  151.     end do
  152.   end subroutine rfc
  153.  
  154.   subroutine conjugate(c) ! conjugate of complex array
  155.     complex, allocatable :: c(:)
  156.  
  157.     integer :: i, n
  158.  
  159.     n = size(c)
  160.  
  161.     do i = 1, n, 1
  162.        c(i) = complex(real(c(i)), -aimag(c(i)))
  163.     end do
  164.   end subroutine conjugate
  165.  
  166.   real function mean(a) ! arithmetic mean of array
  167.     real(rk), allocatable :: a(:)
  168.  
  169.     integer :: i, n
  170.     real(rk) :: s
  171.  
  172.     n = size(a)
  173.     s = 0.0
  174.     do i = 1, n, 1
  175.        s = s + a(i)
  176.     end do
  177.  
  178.     mean = s / real(n, kind = rk)
  179.   end function mean
  180.  
  181.   real function stdv(a) ! standard deviation of array
  182.     real(rk), allocatable :: a(:)
  183.  
  184.     integer :: i, n, m
  185.     real(rk) :: s
  186.  
  187.     m = mean(a)
  188.  
  189.     n = size(a)
  190.     s = 0.0
  191.     do i = 1, n, 1
  192.        s = s + (a(i) - m)**2
  193.     end do
  194.  
  195.     s = s / real(n, kind = rk)
  196.  
  197.     stdv = sqrt(s)
  198.   end function stdv
  199.  
  200.   function parser(p) ! create array from file
  201.     character(32) :: p
  202.     real(rk), allocatable :: parser(:)
  203.  
  204.     integer :: i, n, io
  205.     real(rk), allocatable :: a(:)
  206.     real(rk) :: s
  207.  
  208.     open(8, file = p, action = 'read')
  209.  
  210.     allocate(a(0))
  211.  
  212.     n = 2
  213.     i = 1
  214.     do while (i < n)
  215.        read(8, *, iostat = io) s
  216.        if (io == 0) then
  217.           n = n + 1
  218.           call append(a, s)
  219.        end if
  220.        i = i + 1
  221.     end do
  222.  
  223.     allocate(parser(n))
  224.  
  225.     close(8)
  226.  
  227.     parser = a
  228.   end function parser
  229.  
  230.   real(rk) function c2r(c) ! complex to real
  231.     character(32) :: c
  232.     read(c, *) c2r
  233.   end function c2r
  234.  
  235.   subroutine append(a, v) ! append real to array
  236.     real(rk), allocatable :: a(:)
  237.     real(rk) :: v
  238.  
  239.     real(rk), allocatable :: b(:)
  240.     integer :: n
  241.  
  242.     n = size(a)
  243.  
  244.     allocate(b(n))
  245.  
  246.     b = a
  247.     deallocate(a)
  248.     allocate(a(n + 1))
  249.  
  250.     a(1:n) = b
  251.     a(n + 1) = v
  252.   end subroutine append
  253. end module correlator
  254.  
  255. program main
  256.   use correlator
  257.   use gnufor2 ! gnuplot
  258.  
  259.   implicit none
  260.  
  261.   character(32) :: s
  262.   integer :: n
  263.  
  264.   real(rk), allocatable :: v(:) ! velocity (m/s)
  265.   real(rk), allocatable :: t(:) ! time (s)
  266.   real(rk), allocatable :: r(:) ! result
  267.  
  268.   call get_command_argument(1, s)
  269.  
  270.   print *, "Reading data..."
  271.  
  272.   v = parser(s) ! read data from file in command line arg
  273.  
  274.   n = size(v)
  275.  
  276.   call mka(t, 0.0_8, real(n, kind = 8), 1.0_8)
  277.  
  278.   print *, "Calculating autocorrelation function..."
  279.  
  280.   r = autocfft(v)
  281.  
  282.   print *, "Eulerian integral time scale: ", eulertime(v)
  283.   print *, "Eulerian integral length scale: ", eulerlength(v)
  284.  
  285.   call plot(t, v) ! plot velocity
  286.   call plot(t, r) ! plot autocorrelation
  287. end program main
Advertisement
Add Comment
Please, Sign In to add comment