dns-hit3d-fdm/velocity_rescale.f90
2014-04-25 18:54:58 +09:00

159 lines
4.7 KiB
Fortran

!================================================================================
! Subroutine that rescales the current velocities. The rescales velocity
! will have the spectrum that is defined in the input file via parameters
! isp_type (spectrum type) and peak_wavenum (peak wavenumber).
!
! The program is copies from a part of init_velocity.f90. Some time in the
! future we should make it one routine that is called in init_velocity.
!
! Time-stamp: <2010-01-25 17:01:55 (chumakov)>
!================================================================================
subroutine velocity_rescale
use m_openmpi
use m_parameters
use m_io
use m_fields
use x_fftw
implicit none
integer :: i, j, k, n
real, allocatable :: rr(:)
real*8, allocatable :: e_spec(:), e_spec1(:)
integer *8, allocatable :: hits(:), hits1(:)
integer :: n_shell
real*8 :: sc_rad1, sc_rad2
real*8 :: wmag, wmag2, ratio, fac
! if Taylor-Green, return
if (isp_type.eq.-1) return
!================================================================================
allocate( e_spec(kmax), e_spec1(kmax), rr(nx+2), hits(kmax), hits1(kmax), stat=ierr)
if (ierr.ne.0) stop "cannot allocate the init_velocity arrays"
write(out,*) 'Rescaling the velocities'
call flush(out)
!-------------------------------------------------------------------------------
! Making the spectrum to be what is prescribed in the input file <...>.in
!-------------------------------------------------------------------------------
! --- first get the energy spectrum (copied from m_stat.f90)
! need this normalization factor because the FFT is unnormalized
fac = one / real(nx*ny*nz_all)**2
! zeroing out the arrays
e_spec1 = zip
e_spec = zip
hits = 0
hits1 = 0
! finding the total energy in each shell and number of hits in each shell
! storing them in arrays hits1 and e_spec1
do k = 1,nz
do j = 1,ny
do i = 1,nx
n_shell = nint(sqrt(real(akx(i)**2 + aky(k)**2 + akz(j)**2, 4)))
if (n_shell .gt. 0 .and. n_shell .le. kmax) then
hits1(n_shell) = hits1(n_shell) + 1
e_spec1(n_shell) = e_spec1(n_shell) + &
fac * (fields(i,j,k,1)**2 + fields(i,j,k,2)**2 + fields(i,j,k,3)**2)
end if
end do
end do
end do
! reducing the number of hits and energy to two arrays on master node
count = kmax
call MPI_REDUCE(hits1,hits,count,MPI_INTEGER8,MPI_SUM,0,MPI_COMM_TASK,mpi_err)
count = kmax
call MPI_REDUCE(e_spec1,e_spec,count,MPI_REAL8,MPI_SUM,0,MPI_COMM_TASK,mpi_err)
! now the master node counts the energy density in each shell
if (myid.eq.0) then
fac = four/three * PI / two
do k = 1,kmax
sc_rad1 = real(k,8) + half
sc_rad2 = real(k,8) - half
if (k.eq.1) sc_rad2 = 0.d0
if (hits(k).gt.0) then
e_spec(k) = e_spec(k) / hits(k) * fac * (sc_rad1**3 - sc_rad2**3)
else
e_spec(k) = zip
end if
end do
end if
! broadcasting the spectrum
count = kmax
call MPI_BCAST(e_spec,count,MPI_REAL8,0,MPI_COMM_TASK,mpi_err)
!-------------------------------------------------------------------------------
! Now make the spectrum to be as desired
!-------------------------------------------------------------------------------
! first, define the desired spectrum
do k = 1,kmax
wmag = real(k, 8)
ratio = wmag / peak_wavenum
if (isp_type.eq.0) then
! Plain Kolmogorov spectrum
e_spec1(k) = wmag**(-5.d0/3.d0)
else if (isp_type.eq.1) then
! Exponential spectrum
e_spec1(k) = ratio**3 / peak_wavenum * exp(-3.0D0*ratio)
else if (isp_type.eq.3) then
! Von Karman spectrum
fac = two * PI * ratio
e_spec1(k) = fac**4 / (one + fac**2)**3
else
write(out,*) "ERROR: WRONG INITIAL SPECTRUM TYPE: ",isp_type
call flush(out)
stop
end if
end do
! normalize it so it has the unit total energy
e_spec1 = e_spec1 / sum(e_spec1(1:kmax))
! now go over all Fourier shells and multiply the velocities in a shell by
! the sqrt of ratio of the resired to the current spectrum
do k = 1,nz
do j = 1,ny
do i = 1,nx+2
n_shell = nint(sqrt(real(akx(i)**2 + aky(k)**2 + akz(j)**2, 4)))
if (n_shell .gt. 0 .and. n_shell .le. kmax .and. e_spec(n_shell) .gt. zip) then
fields(i,j,k,1:3) = fields(i,j,k,1:3) * sqrt(e_spec1(n_shell)/e_spec(n_shell))
else
fields(i,j,k,1:3) = zip
end if
end do
end do
end do
write(out,*) "Rescaled the velocities."
call flush(out)
! deallocate work arrays
deallocate(e_spec, e_spec1, rr, hits, hits1, stat=ierr)
return
end subroutine velocity_rescale