Raw File
LES.f90
!*************************************************************************
! Typical params_model.in:
!
! Smagorinsky:
!     1
!   0.025  1  25.      
!
! Vreman:
!     2
!   0.03   2  0.
!
!*************************************************************************
#ifndef main_f90
#define main_f90
#define var_null util
#include "../program/main.f90"
#endif
#include "bisect.f90"
!*************************************************************************
 module les
   use variables
   implicit none
   save
   
   integer          :: model, filter
   double precision :: C_s
   double precision :: A_plus
   
   double precision :: Re_tau, u_tau, nu_max
   double precision :: Rdth, dz, Delta_r(i_N), y_plus(i_N), vanDr(i_N)
   type (coll) :: ur, ut, uz, nuc
   type (phys) :: A(3,3), S(3,3), sr, nu
   
 end module les

!-------------------------------------------------------------------------
! called from MAIN
!-------------------------------------------------------------------------
 subroutine util(FLAG)
   use io
   implicit none
   integer, intent(in) :: FLAG
   logical, save :: set = .false.
   
   if(.not.set) then
      set = .true.
      call init_params_model()
   end if
				! called just before writing data in main   
   if(FLAG==1) then
      call bisect(FLAG)
      if(modulo(tim_step,i_save_rate1)==0)  &
         call save_nuprof()
      if(modulo(tim_step,i_save_rate2)==0)  &
         call write_Retau()
      				! called after eval of nonlin terms
   else if(FLAG==2) then
      call get_nu()
      if(tim_it==0) call update_nu_r()
      call update_nonlin_terms()
      
   end if
      
 end subroutine util

!-------------------------------------------------------------------------
! load params
!-------------------------------------------------------------------------
 subroutine init_params_model()
   use les
   use timestep
   implicit none
   integer :: n
 
   tim_pcn = 1
   tim_it  = 0

   open(99,status='old',file='params_model.in')
   read(99,*)  model
   read(99,*)  C_s, filter, A_plus
   close(99)

   Rdth = (2d0*d_PI/dble(i_Mp*i_Th)) * (3d0/2d0)  
   dz   = (2d0*d_PI/(d_alpha*i_Z))   * (3d0/2d0)
   Delta_r(1) = (mes_D%r(2,1)-0d0)/2d0
   do n = 2, i_N-1
      Delta_r(n) = (mes_D%r(n+1,1)-mes_D%r(n-1,1))/2d0
   end do
   Delta_r(i_N) = 1d0-mes_D%r(i_N-1,1)
   if(mpi_rnk==0) then
      print*, ' LES: max(dr) = ', maxval(Delta_r)
      print*, ' LES:   R.dth = ', Rdth
      print*, ' LES:      dz = ', dz
   end if      

 end subroutine init_params_model

   
!-------------------------------------------------------------------------
! calc strain rate, nu, nu_max/min/wall
!-------------------------------------------------------------------------
 subroutine get_nu()
   use les
   use velocity
   implicit none
   double precision :: d1,d2
   type (coll) :: c1,c2,c3
   type (spec) :: s1,s2,s3
   integer :: m_,n,n_, i,j
   _loop_km_vars

				   ! vec{u} = (ur,ut,uz)
   call var_coll_copy(vel_ur, ur)
   call var_coll_copy(vel_ut, ut)
   call var_coll_copy(vel_uz, uz)
   if(mpi_rnk==0) uz%Re(:,0) = uz%Re(:,0) + vel_U

				   ! get velocity gradient tensor A
   call var_coll_meshmult(1,mes_D%dr(1),ur, c1)
   call var_coll_meshmult(1,mes_D%dr(1),ut, c2)
   call var_coll_meshmult(0,mes_D%dr(1),uz, c3)
   call var_coll2spec(c1,s1, c2,s2, c3,s3)
   call tra_spec2phys(s1, A(1,1))
   call tra_spec2phys(s2, A(1,2))
   call tra_spec2phys(s3, A(1,3))
   _loop_km_begin
      m_ = m*i_Mp
      c1%Re(:,nh) = mes_D%r(:,-1)*(-ur%Im(:,nh)*m_-ut%Re(:,nh))
      c1%Im(:,nh) = mes_D%r(:,-1)*( ur%Re(:,nh)*m_-ut%Im(:,nh))
      c2%Re(:,nh) = mes_D%r(:,-1)*(-ut%Im(:,nh)*m_+ur%Re(:,nh))
      c2%Im(:,nh) = mes_D%r(:,-1)*( ut%Re(:,nh)*m_+ur%Im(:,nh))
      c3%Re(:,nh) = mes_D%r(:,-1)*(-uz%Im(:,nh)*m_)
      c3%Im(:,nh) = mes_D%r(:,-1)*( uz%Re(:,nh)*m_)
   _loop_km_end
   call var_coll2spec(c1,s1, c2,s2, c3,s3)
   call tra_spec2phys(s1, A(2,1))
   call tra_spec2phys(s2, A(2,2))
   call tra_spec2phys(s3, A(2,3))
   _loop_km_begin
      d1 = d_alpha*k
      c1%Re(:,nh) = -ur%Im(:,nh)*d1
      c1%Im(:,nh) =  ur%Re(:,nh)*d1
      c2%Re(:,nh) = -ut%Im(:,nh)*d1
      c2%Im(:,nh) =  ut%Re(:,nh)*d1
      c3%Re(:,nh) = -uz%Im(:,nh)*d1
      c3%Im(:,nh) =  uz%Re(:,nh)*d1
   _loop_km_end
   call var_coll2spec(c1,s1, c2,s2, c3,s3)
   call tra_spec2phys(s1, A(3,1))
   call tra_spec2phys(s2, A(3,2))
   call tra_spec2phys(s3, A(3,3))
				   ! get S = (1/2)(A + A^T)
   S(1,1)%Re = A(1,1)%Re
   S(2,2)%Re = A(2,2)%Re
   S(3,3)%Re = A(3,3)%Re
   S(1,2)%Re = 0.5d0 *(A(1,2)%Re+A(2,1)%Re)
   S(1,3)%Re = 0.5d0 *(A(1,3)%Re+A(3,1)%Re)
   S(2,3)%Re = 0.5d0 *(A(2,3)%Re+A(3,2)%Re)
   S(2,1)%Re = S(1,2)%Re
   S(3,1)%Re = S(1,3)%Re
   S(3,2)%Re = S(2,3)%Re
				   ! strain rate = (2 S_ij S_ij)^(1/2)
   sr%Re =    S(1,1)%Re**2 + S(2,2)%Re**2 + S(3,3)%Re**2  &
      + 2d0*( S(1,2)%Re**2 + S(1,3)%Re**2 + S(2,3)%Re**2 )
   sr%Re = dsqrt( 2d0 * sr%Re )
				   ! u_tau, Re_tau, y^+
   d1    = dot_product(vel_uz%Re(i_N-i_KL:i_N,0),mes_D%dr1(:,1))
   u_tau = dsqrt(dabs((d1-2d0)/d_Re))
#ifdef _MPI
   call mpi_bcast(u_tau, 1, mpi_double_precision,  &
      0, mpi_comm_world, mpi_er)
#endif
   Re_tau = d_Re * u_tau
   y_plus = Re_tau*(1d0-mes_D%r(:,1))
				   ! eddy visc model
   if(model==1) call Smagorinsky()
   if(model==2) call Vreman()
   call tra_phys2spec(nu, s1)
   call var_spec2coll(s1, nuc)
				   ! nu_max
   n_ = mes_D%pN
   nu_max = maxval(nu%Re(:,:,1:n_))
#ifdef _MPI
   call mpi_allreduce(nu_max, d1, 1, mpi_double_precision,  &
      mpi_max, mpi_comm_world, mpi_er)
   nu_max = d1
#endif

 end subroutine get_nu


!-------------------------------------------------------------------------
! eddy viscosity model
!-------------------------------------------------------------------------
 subroutine Smagorinsky()
   use les
   use velocity
   implicit none
   double precision :: d1
   integer :: n, n_
   double precision, save :: Delta(i_N)
   logical, save :: set = .false.

   if(.not.set) then   
      set = .true.
      if(filter==1) then
         Delta = (Delta_r * Rdth * dz)**(1d0/3d0)
      else if(filter==2) then
         Delta = (Delta_r * mes_D%r(:,1)*Rdth * dz)**(1d0/3d0)
      else if(filter==3) then
         Delta = sqrt((Delta_r**2 + (mes_D%r(:,1)*Rdth)**2 + dz**2)/3d0)
      end if
   end if
   				   ! vanDriest fn
   vanDr  = 1d0 - dexp(-(y_plus/A_plus)**2)
				   ! nu_t
   do n = 1, mes_D%pN
      n_ = mes_D%pNi + n - 1
      d1 = vanDr(n_) * (C_s*Delta(n_))**2
      nu%Re(:,:,n) = d1 * sr%Re(:,:,n)
   end do
   
 end subroutine Smagorinsky


!-------------------------------------------------------------------------
! eddy viscosity model
!-------------------------------------------------------------------------
 subroutine Vreman()
   use les
   use velocity
   implicit none
   type (phys) :: B(3,3), P, AA
   double precision :: d1
   integer :: i,j,m, n,n_

   AA%Re = 0d0
   do i = 1, 3
      do j = 1, 3
         AA%Re = AA%Re + A(i,j)%Re**2
         B(i,j)%Re = 0d0
         do m = 1, 3
            do n = 1, mes_D%pN
               n_ = mes_D%pNi + n - 1
               if(m==1) d1 = Delta_r(n_)
               if(m==2 .and. filter==1) d1 = Rdth
               if(m==2 .and. filter==2) d1 = mes_D%r(n_,1)*Rdth
               if(m==3) d1 = dz
               B(i,j)%Re(:,:,n) = B(i,j)%Re(:,:,n)  &
                  + (d1**2) * A(m,i)%Re(:,:,n) * A(m,j)%Re(:,:,n)
            end do         
         end do
      end do
   end do
   
   P%Re = B(1,1)%Re*B(2,2)%Re - B(1,2)%Re**2  &
        + B(1,1)%Re*B(3,3)%Re - B(1,3)%Re**2  &
        + B(2,2)%Re*B(3,3)%Re - B(2,3)%Re**2
   P%Re  = merge(0d0,P%Re,AA%Re<1d-12)
   P%Re  = max(P%Re,0d0)
   AA%Re = max(AA%Re,1d-12)
   
   nu%Re = C_s * dsqrt(P%Re/AA%Re)

   if(A_plus<=0d0) return
   vanDr  = 1d0 - dexp(-(y_plus/A_plus)**2)
   do n = 1, mes_D%pN
      n_ = mes_D%pNi + n - 1
      d1 = 0.03d0/C_s
      d1 = d1 + (1d0-d1)* vanDr(n_)
      nu%Re(:,:,n) = d1 * nu%Re(:,:,n)
   end do
 
 end subroutine Vreman


!-------------------------------------------------------------------------
! check if the reference viscosity needs changing
!-------------------------------------------------------------------------
 subroutine update_nu_r()
   use les
   use velocity
   double precision :: d1
   d1 = 1d0 + d_Re*nu_max
   d1 = 1.10d0*d1
   if(vel_nu<0.93d0*d1 .or. vel_nu>1.07d0*d1) then
      vel_nu = d1
      call vel_matrices()
   end if
 end subroutine update_nu_r


!-------------------------------------------------------------------------
! add in terms from variable viscosity
!-------------------------------------------------------------------------
 subroutine update_nonlin_terms()
   use les
   use velocity
   implicit none
   type (coll) :: c1,c2,c3
   type (spec) :: s1,s2,s3
   type (phys) :: q(3), g(3), nu_
   logical, save :: set = .false.
   integer :: n, i, j
   _loop_km_vars
						   ! grad(nu_t)
   call var_coll_grad(nuc, c1,c2,c3)
   call var_coll2spec(c1,s1, c2,s2, c3,s3)
   call tra_spec2phys(s1, g(1))
   call tra_spec2phys(s2, g(2))
   call tra_spec2phys(s3, g(3))
						   ! curl(curl(u))
   call var_coll_curl(ur,ut,uz, c1,c2,c3)
   call var_coll_curl(c1,c2,c3, c1,c2,c3)
   call var_coll2spec(c1,s1, c2,s2, c3,s3)
   call tra_spec2phys(s1, q(1))
   call tra_spec2phys(s2, q(2))
   call tra_spec2phys(s3, q(3))

   ! N'  = (1/Re).nu'.Lap(u) + nu_t.(-4\hat{z}) + grad(nu_t).2S
   ! nu' = Re*nu_t + 1 - nu_r
   nu_%Re = d_Re*nu%Re + (1d0-vel_nu)
   do i = 1, 3
      q(i)%Re = (1d0/d_Re) * nu_%Re * (-q(i)%Re)
      if(i==3) q(i)%Re = q(i)%Re + nu%Re*(-4d0) 
      do j = 1, 3
         q(i)%Re = q(i)%Re  +  g(j)%Re * S(j,i)%Re * 2d0
      end do
   end do      
   call tra_phys2spec(q(1), s1)
   call tra_phys2spec(q(2), s2)
   call tra_phys2spec(q(3), s3)
   call var_spec2coll(s1,c1, s2,c2, s3,c3)
						   ! N += N'         
   call var_coll_add(c1, vel_Nr)
   call var_coll_add(c2, vel_Nt)
   call var_coll_add(c3, vel_Nz)
   
 end subroutine update_nonlin_terms


!-------------------------------------------------------------------------
! write reference viscocity, max(nu_t), Re_tau
!-------------------------------------------------------------------------
 subroutine write_Retau()
   use les
   use io
   implicit none
   logical, save :: set=.false.

   if(mpi_rnk/=0) return

   if(.not.set) then
      set = .true.
      open(54,status='unknown',file='vel_Retau.dat')
   end if
   
   write(54,'(4e16.8)') tim_t, Re_tau, vel_nu, nu_max
   
 end subroutine write_Retau


!-------------------------------------------------------------------------
! (max(nu_t))(r)
!-------------------------------------------------------------------------
 subroutine save_nuprof()
   use les
   use io
   implicit none
   double precision :: d_(i_N), numax(i_N), numean(i_N)
   character(4) :: cnum
   integer :: n,n_

   numax = 0d0
   do n = 1, mes_D%pN
      n_ = mes_D%pNi + n - 1
      numax(n_) = maxval(nu%Re(:,:,n))
   end do
   numean = nuc%Re(:,0)

#ifdef _MPI
   call mpi_allreduce(numax, d_, i_N, mpi_double_precision,  &
      mpi_max, mpi_comm_world, mpi_er)
   numax = d_
#endif

   if(mpi_rnk/=0) return
   write(cnum,'(I4.4)') io_save1
   open(11, status='unknown', file='nu_prof'//cnum//'.dat')  
   do n = 1, i_N
      write(11,'(4e16.8)')  mes_D%r(n,1), numax(n), numean(n)
   end do
   close(11)
   
 end subroutine save_nuprof
back to top