4 #include "sll_working_precision.h"
7 sll_s_uniform_bsplines_eval_basis
32 sll_int32 :: n_dofs(2)
34 sll_real64 :: delta_x(2)
36 sll_real64,
allocatable :: eig_values_dtm1d_1(:)
37 sll_real64,
allocatable :: eig_values_dtm1d_2(:)
38 sll_comp64,
allocatable :: eig_values_d1(:)
39 sll_comp64,
allocatable :: eig_values_d2(:)
40 sll_real64,
allocatable :: eig_values_mass_0_1(:)
41 sll_real64,
allocatable :: eig_values_mass_0_2(:)
49 sll_comp64,
allocatable :: array1d_x(:)
50 sll_comp64,
allocatable :: array1d_y(:)
51 sll_comp64,
allocatable :: scratch(:,:)
52 sll_comp64,
allocatable :: scratchx(:,:)
53 sll_comp64,
allocatable :: scratchy(:,:)
70 sll_real64 :: sll_i_function_3d_real64
71 sll_real64,
intent(in) :: x(2)
79 sll_real64,
intent(in) :: rho(:)
80 sll_real64,
intent(out) :: efield(:)
82 sll_int32 :: n_dofs(2), ntotal
87 ntotal = product(n_dofs)
90 call fft2d( self, rho )
95 if ( i == 1 .and. j==1 )
then
96 self%scratch(i,j) = cmplx(0.0_f64, 0.0_f64, f64)
98 eig_val = self%eig_values_dtm1d_1(i) * self%eig_values_mass_0_2(j) + &
99 self%eig_values_mass_0_1(i) * self%eig_values_dtm1d_2(j)
100 self%scratch(i,j) = self%scratch(i,j) / cmplx(eig_val,0._f64, f64)
103 self%scratchx(i,j) = -self%scratch(i,j)* self%eig_values_d1(i)
104 self%scratchy(i,j) = -self%scratch(i,j)* self%eig_values_d2(j)
113 call ifft2d( self, self%scratchx, efield(1:ntotal) )
114 call ifft2d( self, self%scratchy, efield(1+ntotal:2*ntotal) )
121 sll_real64,
intent(in) :: rho(:)
122 sll_real64,
intent(out) :: phi(:)
124 sll_int32 :: n_dofs(2)
126 sll_real64 :: eig_val
132 call fft2d( self, rho )
137 if ( i == 1 .and. j==1 )
then
138 self%scratch(i,j) = cmplx(0.0_f64, 0.0_f64, f64)
140 eig_val = self%eig_values_dtm1d_1(i) * self%eig_values_mass_0_2(j) + &
141 self%eig_values_mass_0_1(i) * self%eig_values_dtm1d_2(j)
142 self%scratch(i,j) = self%scratch(i,j) / cmplx(eig_val, 0.0_f64, f64)
147 call ifft2d( self, self%scratch, phi )
162 subroutine init_fft( self, n_dofs, degree, delta_x)
164 sll_int32,
intent( in ) :: n_dofs(2)
165 sll_int32,
intent( in ) :: degree
166 sll_real64,
intent( in ) :: delta_x(2)
169 sll_real64 :: mass_line_0(degree+1)
170 sll_real64 :: mass_line_1(degree)
171 sll_real64 :: eig_values_mass_1_1(n_dofs(1))
172 sll_real64 :: eig_values_mass_1_2(n_dofs(2))
178 allocate(self%array1d_x(n_dofs(1)))
179 allocate(self%array1d_y(n_dofs(2)))
180 allocate(self%scratch(n_dofs(1), n_dofs(2)))
181 allocate(self%scratchx(n_dofs(1), n_dofs(2)))
182 allocate(self%scratchy(n_dofs(1), n_dofs(2)))
197 allocate( self%eig_values_mass_0_1(n_dofs(1)) )
201 allocate( self%eig_values_mass_0_2(n_dofs(2)) )
206 allocate( self%eig_values_d1(n_dofs(1)) )
207 allocate( self%eig_values_dtm1d_1(n_dofs(1)) )
209 self%eig_values_d1(1) = cmplx(0.0_f64, 0.0_f64, f64)
210 self%eig_values_dtm1d_1(1) = 0.0_f64
212 angle =
sll_p_twopi*real(j-1,f64)/real(n_dofs(1), f64)
214 self%eig_values_d1(j) = cmplx((1.0_f64 - cos(angle))/delta_x(1),sin(angle)/delta_x(1), f64 )
215 self%eig_values_dtm1d_1(j) = 2.0_f64/delta_x(1)**2*(1.0_f64-cos(angle))* eig_values_mass_1_1(j)
219 allocate( self%eig_values_d2(n_dofs(2)) )
220 allocate( self%eig_values_dtm1d_2(n_dofs(2)) )
222 self%eig_values_d2(1) = cmplx(0.0_f64, 0.0_f64, f64)
223 self%eig_values_dtm1d_2(1) = 0.0_f64
225 angle =
sll_p_twopi*real(j-1,f64)/real(n_dofs(2), f64)
227 self%eig_values_d2(j) = cmplx((1.0_f64 - cos(angle))/delta_x(2),sin(angle)/delta_x(2), f64 )
228 self%eig_values_dtm1d_2(j) = 2.0_f64/delta_x(2)**2*(1.0_f64-cos(angle))* eig_values_mass_1_2(j)
233 self%delta_x = delta_x
244 sll_real64,
intent(out) :: coefs_dofs(:)
247 sll_int32 :: i1, i2, j1, j2, k1, k2, k, counter
249 sll_real64,
allocatable :: xw_gauss_d1(:,:)
250 sll_real64,
allocatable :: bspl_d1(:,:)
253 volume = product(self%delta_x)
257 allocate(xw_gauss_d1(2,self%degree+1))
258 allocate(bspl_d1(self%degree+1, self%degree+1))
262 call sll_s_uniform_bsplines_eval_basis(self%degree,xw_gauss_d1(1,k), bspl_d1(k,:))
268 do i2 = 1, self%n_dofs(2)
269 do i1 = 1, self%n_dofs(1)
272 do j1 = 1, self%degree+1
273 do j2 = 1, self%degree+1
275 do k1=1, self%degree+1
276 do k2=1, self%degree+1
277 coef = coef + xw_gauss_d1(2,k1)* xw_gauss_d1(2,k2)* &
278 func([self%delta_x(1)*(xw_gauss_d1(1,k1) + real(i1 + j1 - 2,f64)), self%delta_x(2)*(xw_gauss_d1(1,k2) + real(i2 + j2 - 2,f64))] ) * &
279 bspl_d1(k1,self%degree+2-j1)*&
280 bspl_d1(k2,self%degree+2-j2)
287 coefs_dofs(counter) = coef*volume
299 sll_comp64,
intent( inout ) :: inval(:,:)
300 sll_real64,
intent( out ) :: outval(:)
303 sll_int32 :: n_dofs(2)
311 self%array1d_y(j) = inval(i,j)
315 inval(i,j) = self%array1d_y(j)
324 self%array1d_x(i) = inval(i,j)
330 outval(ind) = real( self%array1d_x(i), kind=f64 )
340 sll_real64,
intent( in ) :: rho(:)
343 sll_int32 :: n_dofs(2)
352 self%array1d_x(i) = cmplx( rho(ind), 0_f64, kind=f64)
356 self%scratch(i,j) = self%array1d_x(i)
363 self%array1d_y(j) = self%scratch(i,j)
367 self%scratch(i,j) = self%array1d_y(j)
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_twopi
subroutine, public sll_s_fft_free(plan)
Delete a plan.
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].
Gauss-Legendre integration.
real(kind=f64) function, dimension(2, 1:npoints), public sll_f_gauss_legendre_points_and_weights(npoints, a, b)
Returns a 2d array of size (2,npoints) containing gauss-legendre points and weights in the interval [...
Low level arbitrary degree splines.
subroutine init_fft(self, n_dofs, degree, delta_x)
subroutine compute_phi_from_rho_fft(self, rho, phi)
subroutine compute_e_from_rho_fft(self, rho, efield)
subroutine free_fft(self)
subroutine ifft2d(self, inval, outval)
Helper function for 3d fft.
subroutine fft2d(self, rho)
subroutine compute_rhs_from_function_fft(self, func, coefs_dofs)
Compute the FEM right-hand-side for a given function f and periodic splines of given degree Its compo...
Utilites for Maxwell solver's with spline finite elements.
subroutine, public sll_s_spline_fem_mass_line(degree, mass_line)
Computes the mass line for a mass matrix with degree splines.
subroutine, public sll_s_spline_fem_compute_mass_eig(n_cells, degree, mass_line, eig_values_mass)
Compute eigenvalues of mass matrix with given line mass_line.
Module to select the kind parameter.
Type for FFT plan in SeLaLib.