4.11 Run simulation

nx, nv = 256, 256
xmin, xmax =  0., 4*π
vmin, vmax = -6., 6.
tf = 60
nt = 600
t =  range(0,stop=tf,length=nt)
plot(t, -0.1533*t.-5.48)
f, nrj = vlasov_ampere(nx, nv, xmin, xmax, vmin, vmax, tf, nt)
plot!(t, nrj , label=:ampere )
using Plots, BenchmarkTools, FFTW, LinearAlgebra
struct Mesh
    
    nx   :: Int64
    ny   :: Int64
    x    :: Vector{Float64}
    y    :: Vector{Float64}
    kx   :: Vector{Float64}
    ky   :: Vector{Float64}
    
    function Mesh( xmin, xmax, nx, ymin, ymax, ny)
        x = range(xmin, stop=xmax, length=nx+1)[1:end-1]  ## we remove the end point
        y = range(ymin, stop=ymax, length=ny+1)[1:end-1]  ## periodic boundary condition
        kx  = 2π ./ (xmax-xmin) .* [0:nx÷2-1;nx÷2-nx:-1]
        ky  = 2π ./ (ymax-ymin) .* [0:ny÷2-1;ny÷2-ny:-1]
        new( nx, ny, x, y, kx, ky)
    end
end
function exact(time, mesh :: Mesh; shift=1.0)
   
    f = zeros(Float64,(mesh.nx, mesh.ny))
    for (i, x) in enumerate(mesh.x), (j, y) in enumerate(mesh.y)
        xn = cos(time)*x - sin(time)*y
        yn = sin(time)*x + cos(time)*y
        f[i,j] = exp(-(xn-shift)*(xn-shift)/0.1)*exp(-(yn-shift)*(yn-shift)/0.1)
    end

    f
end
function rotation_on_cpu( mesh :: Mesh, nt :: Int64, tf :: Float64) 
    
    dt = tf / nt
    
    f   = zeros(ComplexF64,(mesh.nx,mesh.ny))
    f  .= exact( 0.0, mesh )
    
    exky = exp.( 1im*tan(dt/2) .* mesh.x  .* mesh.ky')
    ekxy = exp.(-1im*sin(dt)   .* mesh.y' .* mesh.kx )
    
    for n = 1:nt
        
        fft!(f, 2)
        f .= exky .* f
        ifft!(f,2)
        
        fft!(f, 1)
        f .= ekxy .* f
        ifft!(f, 1)
        
        fft!(f, 2)
        f .= exky .* f
        ifft!(f, 2)
        
    end
    
    real(f)
    
end
mesh = Mesh( -π, π, 1024, -π, π, 1024)
nt, tf = 100, 20.
rotation_on_cpu(mesh, 1, 0.1)
@time norm( rotation_on_cpu(mesh, nt, tf) .- exact( tf, mesh))
using CUDAdrv
CUDAdrv.name(CuDevice(0))
using CuArrays
using CuArrays.CUFFT
function rotation_on_gpu( mesh :: Mesh, nt :: Int64, tf :: Float64)
    
    dt = tf / nt
    
    f   = zeros(ComplexF64,(mesh.nx, mesh.ny))
    f  .= exact( 0.0, mesh)
    
    d_f    = CuArray(f) # allocate f on GPU
    
    # Create fft plans on GPU
    p_x    = plan_fft!(d_f,  [1])
    pinv_x = plan_ifft!(d_f, [1])
    p_y    = plan_fft!(d_f,  [2])
    pinv_y = plan_ifft!(d_f, [2])  
    
    # Allocate on GPU
    d_exky = CuArray(exp.( 1im*tan(dt/2) .* mesh.x  .* mesh.ky'))
    d_ekxy = CuArray(exp.(-1im*sin(dt)   .* mesh.y' .* mesh.kx ))
    
    for n = 1:nt
        
        p_y * d_f
        d_f .*= d_exky 
        pinv_y * d_f
        
        p_x * d_f
        d_f .*= d_ekxy 
        pinv_x * d_f
        
        p_y * d_f
        d_f .*= d_exky 
        pinv_y * d_f
        
    end
    
    f .= collect(d_f) # Transfer f from GPU to CPU
    
    real(f)
    
end
nt, tf = 100, 20.
rotation_on_gpu(mesh, 1, 0.1)
@time norm( rotation_on_gpu(mesh, nt, tf) .- exact( tf, mesh))


CC BY-SA 4.0 Pierre Navaro