Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_linear_operator_maxwell_eb_schur.F90
Go to the documentation of this file.
1 
6 #include "sll_working_precision.h"
8 
10 
11  use sll_m_fft
12 
14 
15  implicit none
16 
18 
19 
20  private
21 
23  sll_int32 :: n_total
24  sll_int32 :: n_dofs(3)
25  sll_real64 :: delta_x(3)
26  sll_real64 :: factor
27 
28  ! For Fourier variant
29  sll_comp64, allocatable :: eig_values_d1(:)
30  sll_comp64, allocatable :: eig_values_d1t(:)
31  sll_comp64, allocatable :: eig_values_d2(:)
32  sll_comp64, allocatable :: eig_values_d2t(:)
33  sll_comp64, allocatable :: eig_values_d3(:)
34  sll_comp64, allocatable :: eig_values_d3t(:)
35  sll_real64, allocatable :: eig_values_mass_0_1(:)
36  sll_real64, allocatable :: eig_values_mass_0_2(:)
37  sll_real64, allocatable :: eig_values_mass_0_3(:)
38  sll_real64, allocatable :: eig_values_mass_1_1(:)
39  sll_real64, allocatable :: eig_values_mass_1_2(:)
40  sll_real64, allocatable :: eig_values_mass_1_3(:)
41 
42  type(sll_t_fft) :: fft1
43  type(sll_t_fft) :: fft2
44  type(sll_t_fft) :: fft3
45  type(sll_t_fft) :: ifft1
46  type(sll_t_fft) :: ifft2
47  type(sll_t_fft) :: ifft3
48 
49 
50  contains
51  procedure :: create => create_maxwell_eb
52  procedure :: free => free_maxwell_eb
53  procedure :: dot => dot_maxwell_eb_fourier
54  procedure :: print_info => print_info_maxwell_eb
55  procedure :: dot_inverse => inverse_dot_maxwell_eb_fourier
56 
57 
59 
60 
61 contains
62 
63 
64  subroutine create_maxwell_eb( self, eig_values_mass_0_1, eig_values_mass_0_2, eig_values_mass_0_3, eig_values_mass_1_1, eig_values_mass_1_2, eig_values_mass_1_3, n_dofs, delta_x )
65  class(sll_t_linear_operator_maxwell_eb_schur), intent( inout ) :: self
66  sll_real64 :: eig_values_mass_0_1(:)
67  sll_real64 :: eig_values_mass_0_2(:)
68  sll_real64 :: eig_values_mass_0_3(:)
69  sll_real64 :: eig_values_mass_1_1(:)
70  sll_real64 :: eig_values_mass_1_2(:)
71  sll_real64 :: eig_values_mass_1_3(:)
72  sll_int32 :: n_dofs(3)
73  sll_real64 :: delta_x(3)
74  !local variables
75  sll_real64 :: angle
76  sll_int32 :: j
77  sll_comp64 :: array1d_x(n_dofs(1))
78  sll_comp64 :: array1d_y(n_dofs(2))
79  sll_comp64 :: array1d_z(n_dofs(3))
80 
81 
82  allocate( self%eig_values_mass_0_1(n_dofs(1)) )
83  allocate( self%eig_values_mass_0_2(n_dofs(2)) )
84  allocate( self%eig_values_mass_0_3(n_dofs(3)) )
85  allocate( self%eig_values_mass_1_1(n_dofs(1)) )
86  allocate( self%eig_values_mass_1_2(n_dofs(2)) )
87  allocate( self%eig_values_mass_1_3(n_dofs(3)) )
88 
89  self%eig_values_mass_0_1 = eig_values_mass_0_1
90  self%eig_values_mass_1_1 = eig_values_mass_1_1
91  self%eig_values_mass_0_2 = eig_values_mass_0_2
92  self%eig_values_mass_1_2 = eig_values_mass_1_2
93  self%eig_values_mass_0_3 = eig_values_mass_0_3
94  self%eig_values_mass_1_3 = eig_values_mass_1_3
95 
96  self%n_dofs = n_dofs
97  self%delta_x = delta_x
98  self%n_total = product(self%n_dofs)
99 
100  self%n_rows = self%n_total*3
101  self%n_cols = self%n_total*3
102 
103  self%n_global_rows = self%n_rows
104  self%n_global_cols = self%n_cols
105 
106  ! Fourier product
107 
108  ! Eigenvalues of derivative matrices
109  allocate( self%eig_values_d1(1:self%n_dofs(1)) )
110  allocate( self%eig_values_d1t(1:self%n_dofs(1) ) )
111 
112  self%eig_values_d1(1) = cmplx(0.0_f64, 0.0_f64, f64)
113  self%eig_values_d1t(1) = cmplx(0.0_f64, 0.0_f64, f64)
114  do j=2,self%n_dofs(1)
115  angle = sll_p_twopi*real(j-1,f64)/real(self%n_dofs(1), f64)
116 
117  self%eig_values_d1(j) = cmplx((1.0_f64 - cos(angle))/self%delta_x(1),sin(angle)/self%delta_x(1), f64 )
118  self%eig_values_d1t(j) = cmplx((1.0_f64 - cos(angle))/self%delta_x(1),-sin(angle)/self%delta_x(1), f64 )
119  end do
120 
121 
122  allocate( self%eig_values_d2(1:self%n_dofs(2)) )
123  allocate( self%eig_values_d2t(1:self%n_dofs(2) ) )
124 
125  self%eig_values_d2(1) = cmplx(0.0_f64, 0.0_f64, f64)
126  self%eig_values_d2t(1) = cmplx(0.0_f64, 0.0_f64, f64)
127  do j=2,self%n_dofs(2)
128  angle = sll_p_twopi*real(j-1,f64)/real(self%n_dofs(2), f64)
129 
130  self%eig_values_d2(j) = cmplx((1.0_f64 - cos(angle))/self%delta_x(2),sin(angle)/self%delta_x(2), f64 )
131  self%eig_values_d2t(j) = cmplx((1.0_f64 - cos(angle))/self%delta_x(2),-sin(angle)/self%delta_x(2), f64 )
132  end do
133 
134  allocate( self%eig_values_d3(1:self%n_dofs(3)) )
135  allocate( self%eig_values_d3t(1:self%n_dofs(3) ) )
136 
137  self%eig_values_d3(1) = cmplx(0.0_f64, 0.0_f64, f64)
138  self%eig_values_d3t(1) = cmplx(0.0_f64, 0.0_f64, f64)
139  do j=2,self%n_dofs(3)
140  angle = sll_p_twopi*real(j-1,f64)/real(self%n_dofs(3), f64)
141 
142  self%eig_values_d3(j) = cmplx((1.0_f64 - cos(angle))/self%delta_x(3),sin(angle)/self%delta_x(3), f64 )
143  self%eig_values_d3t(j) = cmplx((1.0_f64 - cos(angle))/self%delta_x(3),-sin(angle)/self%delta_x(3), f64 )
144  end do
145 
146 
147 
148  ! Initialize fft
149  call sll_s_fft_init_c2c_1d( self%fft1, self%n_dofs(1), array1d_x, array1d_x, sll_p_fft_forward)
150  call sll_s_fft_init_c2c_1d( self%fft2, self%n_dofs(2), array1d_y, array1d_y, sll_p_fft_forward)
151  call sll_s_fft_init_c2c_1d( self%fft3, self%n_dofs(3), array1d_z, array1d_z, sll_p_fft_forward)
152  call sll_s_fft_init_c2c_1d( self%ifft1, self%n_dofs(1), array1d_x, array1d_x, &
153  sll_p_fft_backward, normalized=.true.)
154  call sll_s_fft_init_c2c_1d( self%ifft2, self%n_dofs(2), array1d_y, array1d_y, &
155  sll_p_fft_backward, normalized=.true.)
156  call sll_s_fft_init_c2c_1d( self%ifft3, self%n_dofs(3), array1d_z, array1d_z, &
157  sll_p_fft_backward, normalized=.true.)
158 
159 
160  end subroutine create_maxwell_eb
161 
162 
163  subroutine free_maxwell_eb( self )
164  class( sll_t_linear_operator_maxwell_eb_schur), intent( inout ) :: self
165 
166  end subroutine free_maxwell_eb
167 
169  subroutine fft3d( self, array1d_x, array1d_y, array1d_z, n_dofs, inde, x, scratch1 )
170  class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
171  sll_comp64, intent( inout ) :: array1d_x(:)
172  sll_comp64, intent( inout ) :: array1d_y(:)
173  sll_comp64, intent( inout ) :: array1d_z(:)
174  sll_int32, intent( in ) :: n_dofs(3)
175  sll_int32, intent( in ) :: inde
176  sll_real64, intent( in ) :: x(:)
177  sll_comp64, intent( out ) :: scratch1(:,:,:,:)
178  !local variables
179  sll_int32 :: ind, i,j,k
180 
181 
182  ind=0
183  do k=1,n_dofs(3)
184  do j=1,n_dofs(2)
185  do i=1,n_dofs(1)
186  ind = ind+1
187  array1d_x(i) = cmplx( x(ind), 0_f64, kind=f64)
188  end do
189  call sll_s_fft_exec_c2c_1d( self%fft1, array1d_x, array1d_x)
190  do i=1,n_dofs(1)
191  scratch1(i,j,k,inde) = array1d_x(i)
192  end do
193  end do
194  end do
195  do k=1,n_dofs(3)
196  do i=1,n_dofs(1)
197  do j=1,n_dofs(2)
198  array1d_y(j) = scratch1(i,j,k,inde)
199  end do
200  call sll_s_fft_exec_c2c_1d( self%fft2, array1d_y, array1d_y)
201  do j=1,n_dofs(2)
202  scratch1(i,j,k,inde) = array1d_y(j)
203  end do
204  end do
205  end do
206  do j=1,n_dofs(2)
207  do i=1,n_dofs(1)
208  do k=1,n_dofs(3)
209  array1d_z(k) = scratch1(i,j,k,inde)
210  end do
211  call sll_s_fft_exec_c2c_1d( self%fft3, array1d_z, array1d_z)
212  do k=1,n_dofs(3)
213  scratch1(i,j,k,inde) = array1d_z(k)
214  end do
215  end do
216  end do
217 
218  end subroutine fft3d
219 
221  subroutine ifft3d( self, array1d_x, array1d_y, array1d_z, n_dofs, inde, scratch, y )
222  class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
223  sll_comp64, intent( inout ) :: array1d_x(:)
224  sll_comp64, intent( inout ) :: array1d_y(:)
225  sll_comp64, intent( inout ) :: array1d_z(:)
226  sll_int32, intent( in ) :: n_dofs(3)
227  sll_int32, intent( in ) :: inde
228  sll_real64, intent( out ) :: y(:)
229  sll_comp64, intent( inout ) :: scratch(:,:,:,:)
230  !local variables
231  sll_int32 :: ind, i,j,k
232 
233 
234  do j=1,n_dofs(2)
235  do i=1,n_dofs(1)
236  do k=1,n_dofs(3)
237  array1d_z(k) = scratch(i,j,k,inde)
238  end do
239  call sll_s_fft_exec_c2c_1d( self%ifft3, array1d_z, array1d_z)
240  do k=1,n_dofs(3)
241  scratch(i,j,k,inde) = array1d_z(k)
242  end do
243  end do
244  end do
245 
246  do k=1,n_dofs(3)
247  do i=1,n_dofs(1)
248  do j=1,n_dofs(2)
249  array1d_y(j) = scratch(i,j,k,inde)
250  end do
251  call sll_s_fft_exec_c2c_1d( self%ifft2, array1d_y, array1d_y)
252  do j=1,n_dofs(2)
253  scratch(i,j,k,inde) = array1d_y(j)
254  end do
255  end do
256  end do
257 
258  ind=0
259  do k=1,n_dofs(3)
260  do j=1,n_dofs(2)
261  do i=1,n_dofs(1)
262  array1d_x(i) = scratch(i,j,k,inde)
263  end do
264  call sll_s_fft_exec_c2c_1d( self%ifft1, array1d_x, array1d_x)
265 
266  do i=1,n_dofs(1)
267  ind = ind+1
268  y(ind) = real( array1d_x(i), kind=f64 )
269  end do
270  end do
271  end do
272 
273  end subroutine ifft3d
274 
275  subroutine dot_maxwell_eb_fourier( self, x, y )
276  class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
277  sll_real64, intent( in ) :: x(:)
278  sll_real64, intent( out ) :: y(:)
279  !local variables
280  sll_comp64 :: scratch1(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),3)
281  sll_comp64 :: scratch2(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),3)
282  sll_comp64 :: mat(3,3)
283  sll_comp64 :: array1d_x(self%n_dofs(1))
284  sll_comp64 :: array1d_y(self%n_dofs(2))
285  sll_comp64 :: array1d_z(self%n_dofs(3))
286  sll_int32 :: i,j,k
287 
288 
289  ! Compute Fourier transform of input
290  call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, x(1:self%n_total), scratch1 )
291  call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 2, x(1+self%n_total:2*self%n_total), scratch1 )
292  call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 3, x(1+2*self%n_total:3*self%n_total), scratch1 )
293 
294 
295  ! Apply eigenvalues to Fourier coefficient
296  do k=1,self%n_dofs(3)
297  do j=1,self%n_dofs(2)
298  do i=1,self%n_dofs(1)
299 
300  mat(1,1) = cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
301  self%eig_values_mass_0_3(k),kind=f64) + &
302  cmplx(self%factor,kind=f64) * (self%eig_values_d3t(k)*self%eig_values_d3(k)*&
303  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
304  self%eig_values_mass_1_3(k),kind=f64) + &
305  self%eig_values_d2t(j)*self%eig_values_d2(j)*&
306  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
307  self%eig_values_mass_0_3(k),kind=f64))
308  mat(1,2) = - cmplx(self%factor,kind=f64) * ( &
309  self%eig_values_d2t(j)*self%eig_values_d1(i)* &
310  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
311  self%eig_values_mass_0_3(k),kind=f64))
312  mat(1,3) = - cmplx(self%factor,kind=f64) * ( &
313  self%eig_values_d3t(k)*self%eig_values_d1(i)* &
314  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
315  self%eig_values_mass_1_3(k),kind=f64))
316 
317  mat(2,2) = cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
318  self%eig_values_mass_0_3(k),kind=f64) + &
319  cmplx(self%factor,kind=f64) * (self%eig_values_d3t(k)*self%eig_values_d3(k)*&
320  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
321  self%eig_values_mass_1_3(k),kind=f64) + &
322  self%eig_values_d1t(i)*self%eig_values_d1(i)*&
323  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
324  self%eig_values_mass_0_3(k),kind=f64))
325  mat(2,1) = - cmplx(self%factor,kind=f64) * ( &
326  self%eig_values_d1t(i)*self%eig_values_d2(j)* &
327  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
328  self%eig_values_mass_0_3(k),kind=f64))
329  mat(2,3) = - cmplx(self%factor,kind=f64) * ( &
330  self%eig_values_d3t(k)*self%eig_values_d2(j)* &
331  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
332  self%eig_values_mass_1_3(k),kind=f64))
333 
334  mat(3,3) = cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_0_2(j)*&
335  self%eig_values_mass_1_3(k),kind=f64) + &
336  cmplx(self%factor,kind=f64) * (self%eig_values_d1t(i)*self%eig_values_d1(i)*&
337  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
338  self%eig_values_mass_1_3(k),kind=f64) + &
339  self%eig_values_d2t(j)*self%eig_values_d2(j)*&
340  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
341  self%eig_values_mass_1_3(k),kind=f64))
342  mat(3,2) = - cmplx(self%factor,kind=f64) * ( &
343  self%eig_values_d2t(j)*self%eig_values_d3(k)* &
344  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
345  self%eig_values_mass_1_3(k),kind=f64))
346  mat(3,1) = - cmplx(self%factor,kind=f64) * ( &
347  self%eig_values_d1t(i)*self%eig_values_d3(k)* &
348  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
349  self%eig_values_mass_1_3(k),kind=f64))
350 
351  scratch2(i,j,k,1) = mat(1,1)*scratch1(i,j,k,1) + mat(1,2)*scratch1(i,j,k,2) + &
352  mat(1,3)*scratch1(i,j,k,3)
353  scratch2(i,j,k,2) = mat(2,1)*scratch1(i,j,k,1) + mat(2,2)*scratch1(i,j,k,2) + &
354  mat(2,3)*scratch1(i,j,k,3)
355  scratch2(i,j,k,3) = mat(3,1)*scratch1(i,j,k,1) + mat(3,2)*scratch1(i,j,k,2) + &
356  mat(3,3)*scratch1(i,j,k,3)
357 
358  end do
359  end do
360  end do
361  !scratch2 = scratch1
362 
363  ! Compute inverse Fourier transform of result
364  call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, scratch2, y(1:self%n_total) )
365  call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 2, scratch2, y(1+self%n_total:2*self%n_total) )
366  call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 3, scratch2, y(1+2*self%n_total:3*self%n_total) )
367 
368 
369  end subroutine dot_maxwell_eb_fourier
370 
371 
372  subroutine inverse_dot_maxwell_eb_fourier( self, x, y )
373  class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
374  sll_real64, intent( in ) :: x(:)
375  sll_real64, intent( out ) :: y(:)
376  !local variables
377  sll_comp64 :: scratch1(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),3)
378  sll_comp64 :: scratch2(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),3)
379  sll_comp64 :: mat(3,3), imat(3,3)
380  sll_comp64 :: array1d_x(self%n_dofs(1))
381  sll_comp64 :: array1d_y(self%n_dofs(2))
382  sll_comp64 :: array1d_z(self%n_dofs(3))
383  sll_int32 :: i,j,k
384 
385 
386 
387  ! Compute Fourier transform of input
388  call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, x(1:self%n_total), scratch1 )
389  call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 2, x(1+self%n_total:2*self%n_total), scratch1 )
390  call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 3, x(1+2*self%n_total:3*self%n_total), scratch1 )
391 
392 
393  ! Apply eigenvalues to Fourier coefficient
394  do k=1,self%n_dofs(3)
395  do j=1,self%n_dofs(2)
396  do i=1,self%n_dofs(1)
397 
398  mat(1,1) = cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
399  self%eig_values_mass_0_3(k),kind=f64) + &
400  cmplx(self%factor,kind=f64) * (self%eig_values_d3t(k)*self%eig_values_d3(k)*&
401  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
402  self%eig_values_mass_1_3(k),kind=f64) + &
403  self%eig_values_d2t(j)*self%eig_values_d2(j)*&
404  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
405  self%eig_values_mass_0_3(k),kind=f64))
406  mat(1,2) = - cmplx(self%factor,kind=f64) * ( &
407  self%eig_values_d2t(j)*self%eig_values_d1(i)* &
408  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
409  self%eig_values_mass_0_3(k),kind=f64))
410  mat(1,3) = - cmplx(self%factor,kind=f64) * ( &
411  self%eig_values_d3t(k)*self%eig_values_d1(i)* &
412  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
413  self%eig_values_mass_1_3(k),kind=f64))
414 
415  mat(2,2) = cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
416  self%eig_values_mass_0_3(k),kind=f64) + &
417  cmplx(self%factor,kind=f64) * (self%eig_values_d3t(k)*self%eig_values_d3(k)*&
418  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
419  self%eig_values_mass_1_3(k),kind=f64) + &
420  self%eig_values_d1t(i)*self%eig_values_d1(i)*&
421  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
422  self%eig_values_mass_0_3(k),kind=f64))
423  mat(2,1) = - cmplx(self%factor,kind=f64) * ( &
424  self%eig_values_d1t(i)*self%eig_values_d2(j)* &
425  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_1_2(j)*&
426  self%eig_values_mass_0_3(k),kind=f64))
427  mat(2,3) = - cmplx(self%factor,kind=f64) * ( &
428  self%eig_values_d3t(k)*self%eig_values_d2(j)* &
429  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
430  self%eig_values_mass_1_3(k),kind=f64))
431 
432  mat(3,3) = cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_0_2(j)*&
433  self%eig_values_mass_1_3(k),kind=f64) + &
434  cmplx(self%factor,kind=f64) * (self%eig_values_d1t(i)*self%eig_values_d1(i)*&
435  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
436  self%eig_values_mass_1_3(k),kind=f64) + &
437  self%eig_values_d2t(j)*self%eig_values_d2(j)*&
438  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
439  self%eig_values_mass_1_3(k),kind=f64))
440  mat(3,2) = - cmplx(self%factor,kind=f64) * ( &
441  self%eig_values_d2t(j)*self%eig_values_d3(k)* &
442  cmplx(self%eig_values_mass_0_1(i)*self%eig_values_mass_1_2(j)*&
443  self%eig_values_mass_1_3(k),kind=f64))
444  mat(3,1) = - cmplx(self%factor,kind=f64) * ( &
445  self%eig_values_d1t(i)*self%eig_values_d3(k)* &
446  cmplx(self%eig_values_mass_1_1(i)*self%eig_values_mass_0_2(j)*&
447  self%eig_values_mass_1_3(k),kind=f64))
448 
449  call invert3d( mat, imat )
450 
451  scratch2(i,j,k,1) = imat(1,1)*scratch1(i,j,k,1) + &
452  imat(1,2)*scratch1(i,j,k,2) + &
453  imat(1,3)*scratch1(i,j,k,3)
454  scratch2(i,j,k,2) = imat(2,1)*scratch1(i,j,k,1) + &
455  imat(2,2)*scratch1(i,j,k,2) + &
456  imat(2,3)*scratch1(i,j,k,3)
457  scratch2(i,j,k,3) = imat(3,1)*scratch1(i,j,k,1) + &
458  imat(3,2)*scratch1(i,j,k,2) + &
459  imat(3,3)*scratch1(i,j,k,3)
460 
461  end do
462  end do
463  end do
464  !scratch2 = scratch1
465 
466  ! Compute inverse Fourier transform of result
467  call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, scratch2, y(1:self%n_total) )
468  call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 2, scratch2, y(1+self%n_total:2*self%n_total) )
469  call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 3, scratch2, y(1+2*self%n_total:3*self%n_total) )
470 
471 
472  end subroutine inverse_dot_maxwell_eb_fourier
473 
474 !!$ subroutine dot_c_fourier( self, x, y )
475 !!$ class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
476 !!$ sll_real64, intent( in ) :: x(:)
477 !!$ sll_real64, intent( inout ) :: y(:)
478 !!$ !local variables
479 !!$ sll_comp64 :: scratch1(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),3)
480 !!$ sll_comp64 :: scratch2(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),3)
481 !!$ sll_comp64 :: mat(3,3)
482 !!$ sll_comp64 :: array1d_x(self%n_dofs(1))
483 !!$ sll_comp64 :: array1d_y(self%n_dofs(2))
484 !!$ sll_comp64 :: array1d_z(self%n_dofs(3))
485 !!$ sll_int32 :: i,j,k
486 !!$
487 !!$
488 !!$ ! Compute Fourier transform of input
489 !!$ call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, x(1:self%n_total), scratch1 )
490 !!$ call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 2, x(1+self%n_total:2*self%n_total), scratch1 )
491 !!$ call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 3, x(1+2*self%n_total:3*self%n_total), scratch1 )
492 !!$
493 !!$ write(71,*) real(scratch1)
494 !!$ write(72,*) aimag(scratch1)
495 !!$
496 !!$ mat = cmplx(0.0_f64, 0.0_f64, f64)
497 !!$
498 !!$ ! Apply eigenvalues to Fourier coefficient
499 !!$ do k=1,self%n_dofs(3)
500 !!$ do j=1,self%n_dofs(2)
501 !!$ do i=1,self%n_dofs(1)
502 !!$
503 !!$ mat(1,1) = cmplx(0.0_f64, 0.0_f64, f64)
504 !!$ mat(1,2) = -self%eig_values_d3(k)
505 !!$ mat(1,3) = self%eig_values_d2(j)
506 !!$
507 !!$ mat(2,2) = cmplx(0.0_f64, 0.0_f64, f64)
508 !!$ mat(2,1) = self%eig_values_d3(k)
509 !!$ mat(2,3) = -self%eig_values_d1(i)
510 !!$
511 !!$ mat(3,3) = cmplx(0.0_f64, 0.0_f64, f64)
512 !!$ mat(3,2) = self%eig_values_d1(i)
513 !!$ mat(3,1) = - self%eig_values_d2(j)
514 !!$
515 !!$ scratch2(i,j,k,1) = mat(1,1)*scratch1(i,j,k,1) + mat(1,2)*scratch1(i,j,k,2) + &
516 !!$ mat(1,3)*scratch1(i,j,k,3)
517 !!$ scratch2(i,j,k,2) = mat(2,1)*scratch1(i,j,k,1) + mat(2,2)*scratch1(i,j,k,2) + &
518 !!$ mat(2,3)*scratch1(i,j,k,3)
519 !!$ scratch2(i,j,k,3) = mat(3,1)*scratch1(i,j,k,1) + mat(3,2)*scratch1(i,j,k,2) + &
520 !!$ mat(3,3)*scratch1(i,j,k,3)
521 !!$
522 !!$ end do
523 !!$ end do
524 !!$ end do
525 !!$ !scratch2 = scratch1
526 !!$
527 !!$ ! Compute inverse Fourier transform of result
528 !!$ call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, scratch2, y(1:self%n_total) )
529 !!$ call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 2, scratch2, y(1+self%n_total:2*self%n_total) )
530 !!$ call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 3, scratch2, y(1+2*self%n_total:3*self%n_total) )
531 !!$
532 !!$
533 !!$
534 !!$ end subroutine dot_c_fourier
535 
536 
537  subroutine print_info_maxwell_eb( self )
538  class(sll_t_linear_operator_maxwell_eb_schur), intent(in) :: self
539  end subroutine print_info_maxwell_eb
540 
541 
542 
543 
545  subroutine invert3d( mat, mat_inv )
546  sll_comp64, intent( in ) :: mat(3,3)
547  sll_comp64, intent( out ) :: mat_inv(3,3)
548 
549  sll_comp64 :: det
550 
551  det = mat(1,1)*mat(2,2)*mat(3,3) + mat(1,2)*mat(2,3)*mat(3,1) + mat(1,3)*mat(2,1)*mat(3,2) - mat(1,3)*mat(2,2)*mat(3,1) - mat(3,3)*mat(1,2)*mat(2,1) - mat(1,1)*mat(2,3)*mat(3,2)
552 
553  mat_inv(1,1) = mat(2,2)*mat(3,3) - mat(2,3)*mat(3,2)
554  mat_inv(1,2) = mat(1,3)*mat(3,2) - mat(1,2)*mat(3,3)
555  mat_inv(1,3) = mat(1,2)*mat(2,3) - mat(1,3)*mat(2,2)
556 
557  mat_inv(2,1) = mat(2,3)*mat(3,1) - mat(2,1)*mat(3,3)
558  mat_inv(2,2) = mat(1,1)*mat(3,3) - mat(1,3)*mat(3,1)
559  mat_inv(2,3) = mat(1,3)*mat(2,1) - mat(1,1)*mat(2,3)
560 
561  mat_inv(3,1) = mat(2,1)*mat(3,2) - mat(2,2)*mat(3,1)
562  mat_inv(3,2) = mat(1,2)*mat(3,1) - mat(1,1)*mat(3,2)
563  mat_inv(3,3) = mat(1,1)*mat(2,2) - mat(1,2)*mat(2,1)
564 
565  mat_inv = mat_inv/det
566 
567  end subroutine invert3d
568 
569 
570 !!$
571 !!$ !> Product of inverse(M_1,1)
572 !!$ subroutine dot_inv_mass_1_1( self, x, y )
573 !!$ class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
574 !!$ sll_real64, intent( in ) :: x(:)
575 !!$ sll_real64, intent( inout ) :: y(:)
576 !!$ !local variables
577 !!$ sll_comp64 :: scratch(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),1)
578 !!$ sll_comp64 :: array1d_x(self%n_dofs(1))
579 !!$ sll_comp64 :: array1d_y(self%n_dofs(2))
580 !!$ sll_comp64 :: array1d_z(self%n_dofs(3))
581 !!$ sll_int32 :: i,j,k
582 !!$
583 !!$
584 !!$
585 !!$ ! Compute Fourier transform of input
586 !!$ call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, x(1:self%n_total), scratch )
587 !!$
588 !!$ ! Apply eigenvalues to Fourier coefficient
589 !!$ do k=1,self%n_dofs(3)
590 !!$ do j=1,self%n_dofs(2)
591 !!$ do i=1,self%n_dofs(1)
592 !!$
593 !!$ scratch(i,j,k,1) = scratch(i,j,k,1)/ &
594 !!$ cmplx(self%eig_values_mass_1_1(i)* &
595 !!$ self%eig_values_mass_0_2(j)* &
596 !!$ self%eig_values_mass_0_3(k),kind=f64 )
597 !!$
598 !!$ end do
599 !!$ end do
600 !!$ end do
601 !!$
602 !!$ ! Compute inverse Fourier transform of result
603 !!$ call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, scratch, y(1:self%n_total) )
604 !!$
605 !!$ end subroutine dot_inv_mass_1_1
606 !!$
607 !!$ !> Product of inverse(M_1,2)
608 !!$ subroutine dot_inv_mass_1_2( self, x, y )
609 !!$ class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
610 !!$ sll_real64, intent( in ) :: x(:)
611 !!$ sll_real64, intent( inout ) :: y(:)
612 !!$ !local variables
613 !!$ sll_comp64 :: scratch(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),1)
614 !!$ sll_comp64 :: array1d_x(self%n_dofs(1))
615 !!$ sll_comp64 :: array1d_y(self%n_dofs(2))
616 !!$ sll_comp64 :: array1d_z(self%n_dofs(3))
617 !!$ sll_int32 :: i,j,k
618 !!$
619 !!$
620 !!$ ! Compute Fourier transform of input
621 !!$ call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, x(1:self%n_total), scratch )
622 !!$
623 !!$ ! Apply eigenvalues to Fourier coefficient
624 !!$ do k=1,self%n_dofs(3)
625 !!$ do j=1,self%n_dofs(2)
626 !!$ do i=1,self%n_dofs(1)
627 !!$
628 !!$ scratch(i,j,k,1) = scratch(i,j,k,1)/ &
629 !!$ cmplx(self%eig_values_mass_0_1(i)* &
630 !!$ self%eig_values_mass_1_2(j)* &
631 !!$ self%eig_values_mass_0_3(k), kind=f64 )
632 !!$
633 !!$ end do
634 !!$ end do
635 !!$ end do
636 !!$
637 !!$ ! Compute inverse Fourier transform of result
638 !!$ call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, scratch, y(1:self%n_total) )
639 !!$
640 !!$ end subroutine dot_inv_mass_1_2
641 !!$
642 !!$ !> Product of inverse(M_1,3)
643 !!$ subroutine dot_inv_mass_1_3( self, x, y )
644 !!$ class(sll_t_linear_operator_maxwell_eb_schur), intent( in ) :: self
645 !!$ sll_real64, intent( in ) :: x(:)
646 !!$ sll_real64, intent( inout ) :: y(:)
647 !!$ !local variables
648 !!$ sll_comp64 :: scratch(self%n_dofs(1),self%n_dofs(2), self%n_dofs(3),1)
649 !!$ sll_comp64 :: array1d_x(self%n_dofs(1))
650 !!$ sll_comp64 :: array1d_y(self%n_dofs(2))
651 !!$ sll_comp64 :: array1d_z(self%n_dofs(3))
652 !!$ sll_int32 :: i,j,k
653 !!$
654 !!$
655 !!$
656 !!$ ! Compute Fourier transform of input
657 !!$ call fft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, x(1:self%n_total), scratch )
658 !!$
659 !!$ ! Apply eigenvalues to Fourier coefficient
660 !!$ do k=1,self%n_dofs(3)
661 !!$ do j=1,self%n_dofs(2)
662 !!$ do i=1,self%n_dofs(1)
663 !!$
664 !!$ scratch(i,j,k,1) = scratch(i,j,k,1)/ &
665 !!$ cmplx(self%eig_values_mass_0_1(i)* &
666 !!$ self%eig_values_mass_0_2(j)* &
667 !!$ self%eig_values_mass_1_3(k) , kind=f64 )
668 !!$
669 !!$ end do
670 !!$ end do
671 !!$ end do
672 !!$
673 !!$ ! Compute inverse Fourier transform of result
674 !!$ call ifft3d( self, array1d_x, array1d_y, array1d_z, self%n_dofs, 1, scratch, y(1:self%n_total) )
675 !!$
676 !!$ end subroutine dot_inv_mass_1_3
677 
678 
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_twopi
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 operator
This linear operator implements the compatible spline FEM operator for the curl part of Maxwell's equ...
subroutine create_maxwell_eb(self, eig_values_mass_0_1, eig_values_mass_0_2, eig_values_mass_0_3, eig_values_mass_1_1, eig_values_mass_1_2, eig_values_mass_1_3, n_dofs, delta_x)
subroutine fft3d(self, array1d_x, array1d_y, array1d_z, n_dofs, inde, x, scratch1)
Helper function.
subroutine ifft3d(self, array1d_x, array1d_y, array1d_z, n_dofs, inde, scratch, y)
Helper function.
subroutine invert3d(mat, mat_inv)
Helper function to invert 3x3 matrix.
Utilites for Maxwell solver's with spline finite elements.
Type for FFT plan in SeLaLib.
    Report Typos and Errors