6 #include "sll_working_precision.h"
24 sll_int32 :: n_dofs(3)
25 sll_real64 :: delta_x(3)
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(:)
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 )
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)
77 sll_comp64 :: array1d_x(n_dofs(1))
78 sll_comp64 :: array1d_y(n_dofs(2))
79 sll_comp64 :: array1d_z(n_dofs(3))
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)) )
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
97 self%delta_x = delta_x
98 self%n_total = product(self%n_dofs)
100 self%n_rows = self%n_total*3
101 self%n_cols = self%n_total*3
103 self%n_global_rows = self%n_rows
104 self%n_global_cols = self%n_cols
109 allocate( self%eig_values_d1(1:self%n_dofs(1)) )
110 allocate( self%eig_values_d1t(1:self%n_dofs(1) ) )
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)
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 )
122 allocate( self%eig_values_d2(1:self%n_dofs(2)) )
123 allocate( self%eig_values_d2t(1:self%n_dofs(2) ) )
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)
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 )
134 allocate( self%eig_values_d3(1:self%n_dofs(3)) )
135 allocate( self%eig_values_d3t(1:self%n_dofs(3) ) )
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)
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 )
169 subroutine fft3d( self, array1d_x, array1d_y, array1d_z, n_dofs, inde, x, scratch1 )
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(:,:,:,:)
179 sll_int32 :: ind, i,j,k
187 array1d_x(i) = cmplx( x(ind), 0_f64, kind=f64)
191 scratch1(i,j,k,inde) = array1d_x(i)
198 array1d_y(j) = scratch1(i,j,k,inde)
202 scratch1(i,j,k,inde) = array1d_y(j)
209 array1d_z(k) = scratch1(i,j,k,inde)
213 scratch1(i,j,k,inde) = array1d_z(k)
221 subroutine ifft3d( self, array1d_x, array1d_y, array1d_z, n_dofs, inde, scratch, y )
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(:,:,:,:)
231 sll_int32 :: ind, i,j,k
237 array1d_z(k) = scratch(i,j,k,inde)
241 scratch(i,j,k,inde) = array1d_z(k)
249 array1d_y(j) = scratch(i,j,k,inde)
253 scratch(i,j,k,inde) = array1d_y(j)
262 array1d_x(i) = scratch(i,j,k,inde)
268 y(ind) = real( array1d_x(i), kind=f64 )
277 sll_real64,
intent( in ) :: x(:)
278 sll_real64,
intent( out ) :: y(:)
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))
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 )
296 do k=1,self%n_dofs(3)
297 do j=1,self%n_dofs(2)
298 do i=1,self%n_dofs(1)
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))
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))
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))
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)
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) )
374 sll_real64,
intent( in ) :: x(:)
375 sll_real64,
intent( out ) :: y(:)
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))
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 )
394 do k=1,self%n_dofs(3)
395 do j=1,self%n_dofs(2)
396 do i=1,self%n_dofs(1)
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))
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))
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))
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)
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) )
546 sll_comp64,
intent( in ) :: mat(3,3)
547 sll_comp64,
intent( out ) :: mat_inv(3,3)
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)
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)
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)
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)
565 mat_inv = mat_inv/det
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_twopi
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 free_maxwell_eb(self)
subroutine dot_maxwell_eb_fourier(self, x, y)
subroutine inverse_dot_maxwell_eb_fourier(self, x, y)
subroutine ifft3d(self, array1d_x, array1d_y, array1d_z, n_dofs, inde, scratch, y)
Helper function.
subroutine print_info_maxwell_eb(self)
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.
class for abstract linear operator