Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_poisson_3d_sparse_grid_fft.F90
Go to the documentation of this file.
1 
5 
7 
8 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
11 
12  use sll_m_constants, only: &
13  sll_p_pi
14 
15  use sll_m_sparse_grid_3d, only: &
17 
18  implicit none
19 
20  public :: &
22 
23  private
24 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25 
27  type:: sll_t_fft3d_derivative
28  sll_real64, dimension(:), pointer :: kx
29  sll_real64, dimension(:), pointer :: ky
30  sll_real64, dimension(:), pointer :: kz
31  sll_real64, dimension(:), pointer :: kpot
32  sll_real64, dimension(:), pointer :: kex
33  sll_real64, dimension(:), pointer :: key
34  sll_real64, dimension(:), pointer :: kez
35  sll_comp64, dimension(:), pointer :: fcoeffs, fcoeffs2
36 
37  contains
38  procedure :: init => new_poisson_3d_sparse_grid_fft
39  !procedure :: delete=>free_poisson
40  procedure :: solve => solve_for_electric_field
41  procedure :: solve_potential
42  end type sll_t_fft3d_derivative
43 
44 contains
45 
47  subroutine new_poisson_3d_sparse_grid_fft(this, interpolator)
48  class(sll_t_fft3d_derivative), intent(inout) ::this
49  type(sll_t_sparse_grid_3d), intent(in) ::interpolator
50 
51  sll_int32 :: ierr, i1, i2, i3, i, j
52  sll_real64, dimension(:), allocatable :: data1d
53  sll_real64 :: size_factor
54 
55  sll_allocate(this%kx(interpolator%size_basis), ierr)
56  sll_allocate(this%ky(interpolator%size_basis), ierr)
57  sll_allocate(this%kz(interpolator%size_basis), ierr)
58  sll_allocate(this%kpot(interpolator%size_basis), ierr)
59  sll_allocate(this%kex(interpolator%size_basis), ierr)
60  sll_allocate(this%key(interpolator%size_basis), ierr)
61  sll_allocate(this%kez(interpolator%size_basis), ierr)
62 
63  sll_allocate(this%fcoeffs(interpolator%size_basis), ierr)
64  sll_allocate(this%fcoeffs2(interpolator%size_basis), ierr)
65 
66  sll_allocate(data1d(2**(interpolator%max_level)), ierr)
67 
68  size_factor = 2.0_f64*sll_p_pi/interpolator%length(1)
69  do i2 = 0, interpolator%levels(2)
70  do i3 = 0, min(interpolator%max_level - i2, interpolator%levels(3))
71  do j = interpolator%index(0, i2, i3), &
72  interpolator%index(0, i2, i3) + max(2**(i2 - 1), 1)*max(2**(i3 - 1), 1) - 1
73  call derivative_coeffs_1d(interpolator, 1, &
74  min(interpolator%levels(1), interpolator%max_level - i2 - i3), &
75  j, size_factor, data1d, this%kx)
76  end do
77  end do
78  end do
79 
80  size_factor = 2.0_f64*sll_p_pi/interpolator%length(2)
81  do i1 = 0, interpolator%levels(1)
82  do i3 = 0, min(interpolator%max_level - i1, interpolator%levels(3))
83  do j = interpolator%index(i1, 0, i3), &
84  interpolator%index(i1, 0, i3) + max(2**(i1 - 1), 1)*max(2**(i3 - 1), 1) - 1
85  call derivative_coeffs_1d(interpolator, 2, &
86  min(interpolator%levels(2), interpolator%max_level - i1 - i3), j, &
87  size_factor, data1d, this%ky)
88  end do
89  end do
90  end do
91 
92  size_factor = 2.0_f64*sll_p_pi/interpolator%length(3)
93  do i1 = 0, interpolator%levels(1)
94  do i2 = 0, min(interpolator%max_level - i1, interpolator%levels(2))
95  do j = interpolator%index(i1, i2, 0), &
96  interpolator%index(i1, i2, 0) + max(2**(i1 - 1), 1)*max(2**(i2 - 1), 1) - 1
97  call derivative_coeffs_1d(interpolator, 3, &
98  min(interpolator%levels(3), interpolator%max_level - i1 - i2), j, &
99  size_factor, data1d, this%kz)
100  end do
101  end do
102  end do
103 
104  this%kpot(1) = 0.0_f64;
105  this%kex(1) = 0.0_f64;
106  this%key(1) = 0.0_f64;
107  this%kez(1) = 0.0_f64;
108  do i = 2, interpolator%size_basis
109  this%kpot(i) = 1.0_f64/(this%kx(i)**2 + this%ky(i)**2 + this%kz(i)**2);
110  this%kex(i) = this%kpot(i)*this%kx(i);
111  this%key(i) = this%kpot(i)*this%ky(i);
112  this%kez(i) = this%kpot(i)*this%kz(i);
113  end do
114 
115  end subroutine new_poisson_3d_sparse_grid_fft
116 
118  subroutine solve_potential(this, interpolator, rho, phi)
119  class(sll_t_fft3d_derivative), intent(inout) ::this
120  type(sll_t_sparse_grid_3d), intent(inout) :: interpolator
121  sll_real64, dimension(:), intent(inout) ::phi
122  sll_real64, dimension(:), intent(inout) ::rho
123  sll_int32 :: i
124 
125  call interpolator%SPFFT(rho, this%fcoeffs)
126 
127  do i = 1, interpolator%size_basis
128  this%fcoeffs(i) = this%fcoeffs(i)*cmplx(this%kpot(i), 0._f64, f64)
129  end do
130 
131  call interpolator%ISPFFT(this%fcoeffs, phi)
132 
133  end subroutine solve_potential
134 
136  subroutine solve_for_electric_field(this, interpolator, rho, ex, ey, ez)
137  class(sll_t_fft3d_derivative), intent(inout) ::this
138  type(sll_t_sparse_grid_3d), intent(inout) :: interpolator
139  sll_real64, dimension(:), intent(inout) :: ex
140  sll_real64, dimension(:), intent(inout) :: ey
141  sll_real64, dimension(:), intent(inout) :: ez
142  sll_real64, dimension(:), intent(inout) :: rho
143 
144  sll_int32 :: i
145 
146  call interpolator%SPFFT(rho, this%fcoeffs)
147 
148  do i = 1, interpolator%size_basis
149  this%fcoeffs2(i) = cmplx(-aimag(this%fcoeffs(i))*this%kez(i), &
150  real(this%fcoeffs(i))*this%kez(i), kind=f64)
151  end do
152 
153  call interpolator%ISPFFT(this%fcoeffs2, ez)
154 
155  do i = 1, interpolator%size_basis
156  this%fcoeffs2(i) = cmplx(-aimag(this%fcoeffs(i))*this%key(i), &
157  real(this%fcoeffs(i))*this%key(i), kind=f64)
158  this%fcoeffs(i) = cmplx(-aimag(this%fcoeffs(i))*this%kex(i), &
159  real(this%fcoeffs(i))*this%kex(i), kind=f64)
160  end do
161 
162  call interpolator%ISPFFT(this%fcoeffs, ex)
163  call interpolator%ISPFFT(this%fcoeffs2, ey)
164 
165  end subroutine solve_for_electric_field
166 
168  subroutine derivative_coeffs_1d(interpolator, dim, max_level, index, size_factor, data1d, data)
169  class(sll_t_sparse_grid_3d), intent(in) :: interpolator
170  sll_real64, dimension(:), intent(inout) :: data, data1d
171  sll_int32, intent(in) :: dim, max_level, index
172  sll_real64, intent(in) :: size_factor
173  sll_int32 :: k, size
174 
175  size = 2**max_level
176 
177  ! Derivative
178  data1d(1) = 0.0_f64
179  data1d(size) = real(size/2, f64)*size_factor
180  do k = 1, size/2 - 1
181  data1d(2*k) = real(k, f64)*size_factor;
182  data1d(2*k + 1) = -data1d(2*k);
183  end do
184  call insert_fourier_real(interpolator, dim, max_level, &
185  index, data1d, data)
186  end subroutine derivative_coeffs_1d
187 
189  subroutine insert_fourier_real(sparsegrid, dim, max_level, index, data_in, data_out)
190  type(sll_t_sparse_grid_3d), intent(in) :: sparsegrid
191  sll_int32, intent(in) :: dim, max_level, index
192  sll_int32 :: n_points, index_running
193  sll_real64, dimension(:), intent(in) :: data_in
194  sll_real64, dimension(:), intent(out) :: data_out
195 
196  n_points = 2**(max_level)
197  data_out(index) = data_in(1)
198  if (max_level > 0) then
199  index_running = sparsegrid%hierarchy(index)%children(dim*2)
200  data_out(index_running) = data_in(2)
201  if (max_level > 1) then
202  call insert_recursive_fourier_real(sparsegrid, index_running, 0, &
203  2, max_level, dim, data_in, data_out)
204  end if
205  end if
206  end subroutine insert_fourier_real
207 
209  recursive subroutine insert_recursive_fourier_real(sparsegrid, index_sg, ind, level, max_level, dim, data_in, data_out)
210  type(sll_t_sparse_grid_3d), intent(in) :: sparsegrid
211  sll_int32, intent(in) :: level, max_level, index_sg, dim, ind
212  sll_real64, dimension(:), intent(in) :: data_in
213  sll_real64, dimension(:), intent(inout) :: data_out
214 
215  data_out(sparsegrid%hierarchy(index_sg)%children(dim*2 - 1)) = &
216  data_in(2**(level - 1) + 1 + 2*ind)
217  data_out(sparsegrid%hierarchy(index_sg)%children(dim*2)) = &
218  data_in(2**(level - 1) + 1 + 2*ind + 1)
219  if (level < max_level) then
220  call insert_recursive_fourier_real(sparsegrid, &
221  sparsegrid%hierarchy(index_sg)%children(dim*2 - 1), 2*ind, &
222  level + 1, max_level, dim, data_in, data_out)
223  call insert_recursive_fourier_real(sparsegrid, &
224  sparsegrid%hierarchy(index_sg)%children(dim*2), 2*ind + 1, &
225  level + 1, max_level, dim, data_in, data_out)
226  end if
227  end subroutine insert_recursive_fourier_real
228 
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
Implementation of a 3D pseudospectral Poisson solver on sparse grid.
recursive subroutine insert_recursive_fourier_real(sparsegrid, index_sg, ind, level, max_level, dim, data_in, data_out)
Helper function to insert the real Fourier coefficient into the sparse grid data structure (recursive...
subroutine solve_potential(this, interpolator, rho, phi)
Solve for potential.
subroutine solve_for_electric_field(this, interpolator, rho, ex, ey, ez)
Compute the electric fields from rho.
subroutine new_poisson_3d_sparse_grid_fft(this, interpolator)
Create Poisson solver object with Fourier spectral method on 3d sparse grid.
subroutine insert_fourier_real(sparsegrid, dim, max_level, index, data_in, data_out)
Helper function to insert the real Fourier coefficient into the sparse grid data structure.
subroutine derivative_coeffs_1d(interpolator, dim, max_level, index, size_factor, data1d, data)
Helper function to compute the Fourier coefficients for the derivative operation.
Implementation of a 3D sparse grid with interpolation routines.
sll_t_fft3d_derivative is the Poisson solver object to solve Poisson's problem in 2d with pseudospect...
Sparse grid object for 3d with interpolation routines.
    Report Typos and Errors