Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_linear_solver_spline_mass_fft.F90
Go to the documentation of this file.
1 
9 
11 #include "sll_working_precision.h"
12 #include "sll_errors.h"
13 
14  use sll_m_linear_solver_abstract, only : &
16 
17  use sll_m_fft
18 
19  implicit none
20  private
21 
23 
24 
27 
28  sll_int32 :: n_dofs(3)
29 
30  sll_real64 :: factor = 1.0_f64
31 
32  sll_real64, allocatable :: inv_eig_values_1(:)
33  sll_real64, allocatable :: inv_eig_values_2(:)
34  sll_real64, allocatable :: inv_eig_values_3(:)
35 
36  type(sll_t_fft) :: fft1
37  type(sll_t_fft) :: fft2
38  type(sll_t_fft) :: fft3
39  type(sll_t_fft) :: ifft1
40  type(sll_t_fft) :: ifft2
41  type(sll_t_fft) :: ifft3
42 
43  contains
44 
45  procedure :: read_from_file => read_from_file_mass1
46  procedure :: set_verbose => set_verbose_mass1
47  procedure :: solve_real => solve_real_mass1
48  procedure :: print_info => print_info_mass1
49  procedure :: create => create_mass1
50  procedure :: free => free_mass1
51 
53 
54 contains
55 
56  subroutine create_mass1( self, n_dofs, inv_eig_values_1, inv_eig_values_2, inv_eig_values_3)
57  class( sll_t_linear_solver_spline_mass_fft), intent( inout ) :: self
58  sll_int32, intent( in ) :: n_dofs(3)
59  sll_real64, intent( in ) :: inv_eig_values_1(:)
60  sll_real64, intent( in ) :: inv_eig_values_2(:)
61  sll_real64, intent( in ) :: inv_eig_values_3(:)
62  !local variables
63  sll_comp64 :: array1d_x(n_dofs(1)), array1d_y(n_dofs(2)), array1d_z(n_dofs(3))
64 
65  self%n_dofs = n_dofs
66  self%n_global_rows = product( n_dofs)
67  self%n_global_cols = self%n_global_rows
68 
69  allocate(self%inv_eig_values_1(n_dofs(1)))
70  self%inv_eig_values_1 = inv_eig_values_1
71  allocate(self%inv_eig_values_2(n_dofs(2)))
72  self%inv_eig_values_2 = inv_eig_values_2
73  allocate(self%inv_eig_values_3(n_dofs(3)))
74  self%inv_eig_values_3 = inv_eig_values_3
75 
76  call sll_s_fft_init_c2c_1d( self%fft1, n_dofs(1), array1d_x, array1d_x, sll_p_fft_forward)
77  call sll_s_fft_init_c2c_1d( self%fft2, n_dofs(2), array1d_y, array1d_y, sll_p_fft_forward)
78  call sll_s_fft_init_c2c_1d( self%fft3, n_dofs(3), array1d_z, array1d_z, sll_p_fft_forward)
79  call sll_s_fft_init_c2c_1d( self%ifft1, n_dofs(1), array1d_x, array1d_x, &
80  sll_p_fft_backward, normalized=.true.)
81  call sll_s_fft_init_c2c_1d( self%ifft2, n_dofs(2), array1d_y, array1d_y, &
82  sll_p_fft_backward, normalized=.true.)
83  call sll_s_fft_init_c2c_1d( self%ifft3, n_dofs(3), array1d_z, array1d_z, &
84  sll_p_fft_backward, normalized=.true.)
85 
86  end subroutine create_mass1
87 
88  subroutine solve_real_mass1(self, rhs, unknown)
89  class( sll_t_linear_solver_spline_mass_fft), intent( inOUT ) :: self
90  real(kind=f64), intent(in ) :: rhs(:)
91  real(kind=f64), intent( out ) :: unknown(:)
92 
93  sll_int32 :: ind, i, j, k, n_dofs(3)
94  sll_comp64 :: scratch(self%n_dofs(1), self%n_dofs(2), self%n_dofs(3))
95  sll_comp64 :: array1d_x(self%n_dofs(1)), array1d_y(self%n_dofs(2)), array1d_z(self%n_dofs(3))
96 
97  n_dofs = self%n_dofs
98 
99  ! Fourier transform
100  ind=0
101  do k=1,n_dofs(3)
102  do j=1,n_dofs(2)
103  do i=1,n_dofs(1)
104  ind = ind+1
105  array1d_x(i) = cmplx( rhs(ind), 0_f64, kind=f64)
106  end do
107  call sll_s_fft_exec_c2c_1d( self%fft1, array1d_x, array1d_x)
108  do i=1,n_dofs(1)
109  scratch(i,j,k) = array1d_x(i)
110  end do
111  end do
112  end do
113  do k=1,n_dofs(3)
114  do i=1,n_dofs(1)
115  do j=1,n_dofs(2)
116  array1d_y(j) = scratch(i,j,k)
117  end do
118  call sll_s_fft_exec_c2c_1d( self%fft2, array1d_y, array1d_y)
119  do j=1,n_dofs(2)
120  scratch(i,j,k) = array1d_y(j)
121  end do
122  end do
123  end do
124  do j=1,n_dofs(2)
125  do i=1,n_dofs(1)
126  do k=1,n_dofs(3)
127  array1d_z(k) = scratch(i,j,k)
128  end do
129  call sll_s_fft_exec_c2c_1d( self%fft3, array1d_z, array1d_z)
130  do k=1,n_dofs(3)
131  scratch(i,j,k) = array1d_z(k)
132  end do
133  end do
134  end do
135 
136  ! Multiply by inverse mass
137  do k=1,n_dofs(3)
138  do j=1,n_dofs(2)
139  do i=1,n_dofs(1)
140 
141  scratch(i,j,k) = scratch(i,j,k)* &
142  cmplx(self%inv_eig_values_1(i)* &
143  self%inv_eig_values_2(j)* &
144  self%inv_eig_values_3(k) /self%factor, 0.0_f64, f64)
145 
146  end do
147  end do
148  end do
149 
150 
151  ! Inverse Fourier transform
152  do j=1,n_dofs(2)
153  do i=1,n_dofs(1)
154  do k=1,n_dofs(3)
155  array1d_z(k) = scratch(i,j,k)
156  end do
157  call sll_s_fft_exec_c2c_1d( self%ifft3, array1d_z, array1d_z)
158  do k=1,n_dofs(3)
159  scratch(i,j,k) = array1d_z(k)
160  end do
161  end do
162  end do
163 
164  do k=1,n_dofs(3)
165  do i=1,n_dofs(1)
166  do j=1,n_dofs(2)
167  array1d_y(j) = scratch(i,j,k)
168  end do
169  call sll_s_fft_exec_c2c_1d( self%ifft2, array1d_y, array1d_y)
170  do j=1,n_dofs(2)
171  scratch(i,j,k) = array1d_y(j)
172  end do
173  end do
174  end do
175 
176  ind=0
177  do k=1,n_dofs(3)
178  do j=1,n_dofs(2)
179  do i=1,n_dofs(1)
180  array1d_x(i) = scratch(i,j,k)
181  end do
182  call sll_s_fft_exec_c2c_1d( self%ifft1, array1d_x, array1d_x)
183 
184  do i=1,n_dofs(1)
185  ind = ind+1
186  unknown(ind) = real( array1d_x(i), kind=f64 )
187  end do
188  end do
189  end do
190 
191  end subroutine solve_real_mass1
192 
193  subroutine read_from_file_mass1(self, filename)
194  class( sll_t_linear_solver_spline_mass_fft), intent( inout ) :: self
195  character(len=*), intent( in ) :: filename
196 
197  end subroutine read_from_file_mass1
198 
199  subroutine print_info_mass1(self)
200  class( sll_t_linear_solver_spline_mass_fft), intent( in ) :: self
201 
202  end subroutine print_info_mass1
203 
204  subroutine set_verbose_mass1( self, verbose )
205  class( sll_t_linear_solver_spline_mass_fft), intent( inout ) :: self
206  logical, intent( in ) :: verbose
207 
208  self%verbose = verbose
209 
210  end subroutine set_verbose_mass1
211 
212 
213  subroutine free_mass1(self)
214  class( sll_t_linear_solver_spline_mass_fft), intent( inout ) :: self
215 
216  end subroutine free_mass1
217 
FFT interface for FFTW.
integer, parameter, public sll_p_fft_forward
Flag to specify forward FFT (negative sign) [value -1].
subroutine, public sll_s_fft_exec_c2c_1d(plan, array_in, array_out)
Compute fast Fourier transform in complex to complex mode.
subroutine, public sll_s_fft_init_c2c_1d(plan, nx, array_in, array_out, direction, normalized, aligned, optimization)
Create new 1d complex to complex plan.
integer, parameter, public sll_p_fft_backward
Flag to specify backward FFT (positive sign) [value 1].
module for abstract linear solver
Invert a circulant matrix based on diagonalization in Fourier space (3d version)
subroutine create_mass1(self, n_dofs, inv_eig_values_1, inv_eig_values_2, inv_eig_values_3)
Type for FFT plan in SeLaLib.
Linear solver for FFT-based inversion of 3d tensor product of circulant matrices (extending the abstr...
    Report Typos and Errors