BuildFourierModes Subroutine

subroutine BuildFourierModes(Vrms, peak_mode, Nk, Vk)

Builds the Fourier modes, scaled with the provided energy spectrum. Note that Since the FFT of a real field satisfies the Hermitian symmetry, one needs to describe only half of the wavenumber space. Direction 1 is truncated in half to conform with FFTW.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: Vrms

Wavevector magnitude

integer, intent(in) :: peak_mode

Peak

integer, intent(out) :: Nk(3)

Size of fourier modes

complex(kind=wp), intent(out), allocatable :: Vk(:,:,:,:)

Fourier modes


Calls

proc~~buildfouriermodes~~CallsGraph proc~buildfouriermodes BuildFourierModes proc~getenergyspectrum GetEnergySpectrum proc~buildfouriermodes->proc~getenergyspectrum

Called by

proc~~buildfouriermodes~~CalledByGraph proc~buildfouriermodes BuildFourierModes proc~setupcasefields~4 SetUpCaseFields proc~setupcasefields~4->proc~buildfouriermodes program~main~8 main program~main~8->proc~setupcasefields~4

Source Code

    subroutine BuildFourierModes(Vrms,peak_mode,Nk,Vk)
      !> Builds the Fourier modes, scaled with the provided
      ! energy spectrum.
      ! Note that Since the FFT of a real field satisfies the Hermitian
      ! symmetry, one needs to describe only half of the wavenumber space.
      ! Direction 1 is truncated in half to conform with FFTW.
      implicit none
      real(wp),     intent(in)  :: Vrms                                        !! Wavevector magnitude
      integer,      intent(in)  :: peak_mode                                   !! Peak
      integer,      intent(out) :: Nk(3)                                       !! Size of fourier modes
      complex(wp), allocatable,  &
                    intent(out) :: Vk(:,:,:,:)                                 !! Fourier modes
      ! Work variables
      real(wp)             :: A
      real(wp)             :: kp
      real(wp)             :: Ek
      real(wp)             :: kmag
      real(wp)             :: phi
      real(wp)             :: kappa(3)
      real(wp)             :: rand(3)
      real(wp)             :: dk(3)
      integer              :: mi,mj,mk
      real(wp),  parameter :: Pi = 4.0_wp*atan(1.0_wp)
      complex(wp),          &
                 parameter :: ii = (0.0_wp,1.0_wp)

      ! Infinitesimal wavenumbers
      dk = 2.0_wp*Pi/(block%pmax-block%pmin)

      ! Peak wavenumber
      kp = real(peak_mode,wp)*maxval(dk)

      ! Spectrum prefactor
      A = 16.0_wp/sqrt(0.5_wp*Pi)*Vrms**2/kp**5

      ! Number of fourier modes in each direction
      Nk = [Ng(1)/2+1, Ng(2), Ng(3)]

      allocate(Vk(3,Nk(1),Nk(2),Nk(3)),mold=(0.0_wp,0.0_wp))

      ! Build Fourier modes following Rogallo's method
      do mk=1,Nk(3)

        ! Wavenumber in 3-dir
        kappa(3) = real(mk-1,wp)*dk(3)
        if (mk.gt.Ng(3)/2+1) kappa(3) = -real(Ng(3)-(mk-1),wp)*dk(3)

        do mj=1,Nk(2)

          ! Wavenumber in 2-dir
          kappa(2) = real(mj-1,wp)*dk(2)
          if (mj.gt.Ng(2)/2+1) kappa(2) = -real(Ng(2)-(mj-1),wp)*dk(2)

          do mi=1,Nk(1)

            ! Wavenumber in 1-dir
            kappa(1) = real(mi-1,wp)*dk(1)

            ! Wavevector magnitude
            kmag=norm2(kappa)

            if (kmag.gt.1.0e-10_wp) then
              ! Energy at this shell
              Ek = GetEnergySpectrum(kmag,kp,A)

              ! Generate a random phase
              call random_number(phi)
              phi    = 2.0_wp*Pi*phi

              ! Generate a complex vector with a random amplitude and the previous random phase
              call random_number(rand)
              Vk(:,mi,mj,mk) = (rand - 0.5_wp) * exp(ii * phi)

              ! Make it orthogonal to the wavevector to satisfy continuity
              Vk(:,mi,mj,mk) = Vk(:,mi,mj,mk) - (1.0_wp/kmag**2)*dot_product(kappa,Vk(:,mi,mj,mk))*kappa

              ! Rescale to match target energy spectrum
              Vk(:,mi,mj,mk) = Vk(:,mi,mj,mk) * sqrt(Ek / (4.0_wp * pi * kmag**2))

            else
              Vk(:,mi,mj,mk) = (0.0_wp,0.0_wp)
            end if

          end do
        end do
      end do

      return
    end subroutine BuildFourierModes