9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
46 sll_real64,
allocatable :: eig_d(:)
47 sll_real64,
allocatable :: eig_interp1(:)
48 sll_real64,
allocatable :: eig_interp1_inverse(:)
49 sll_real64,
allocatable :: eig_interp1t_inverse(:)
50 sll_real64,
allocatable :: eig_poisson(:)
51 sll_real64,
allocatable :: eig_schur_curl_part(:)
53 sll_real64,
allocatable :: eig_mixed(:)
56 sll_real64,
allocatable :: work(:)
57 sll_real64,
allocatable :: wsave(:)
60 sll_real64 :: domain(2)
108 sll_real64,
intent( in ) :: delta_t
109 sll_real64,
intent( inout ) :: efield_dofs(:)
110 sll_real64,
intent( inout ) :: bfield_dofs(:)
116 sll_real64,
intent(in) :: in(:)
117 sll_real64,
intent(out) :: out(:)
119 self%wsave = in / sqrt(real(self%n_cells,f64))
129 sll_real64,
intent(in) :: in(:)
130 sll_real64,
intent(out) :: out(:)
132 self%wsave = in / sqrt(real(self%n_cells,f64))
143 sll_real64,
intent(in) :: domain(2)
144 sll_int32,
intent(in) :: n_dofs
147 sll_real64 :: cos_mode, sin_mode, factor, modulus, ni
151 self%n_dofs0 = n_dofs
152 self%n_dofs1 = n_dofs
153 self%n_cells = n_dofs
154 ni = 1.0_f64/real(n_dofs,f64)
156 self%Lx = domain(2)-domain(1)
157 self%delta_x = self%Lx * ni
160 sll_allocate(self%work(n_dofs),ierr)
161 sll_allocate(self%wsave(n_dofs),ierr)
166 sll_allocate( self%eig_d(n_dofs) , ierr )
167 sll_allocate( self%eig_interp1(n_dofs) , ierr )
168 sll_allocate( self%eig_interp1_inverse(n_dofs) , ierr )
169 sll_allocate( self%eig_interp1t_inverse(n_dofs) , ierr )
170 sll_allocate( self%eig_poisson(n_dofs) , ierr )
171 sll_allocate( self%eig_schur_curl_part(n_dofs) , ierr )
172 sll_allocate( self%eig_mixed(n_dofs), ierr )
176 self%eig_d(1) = 0.0_f64
177 self%eig_interp1(1) = 1.0_f64
178 self%eig_interp1_inverse(1) = 1.0_f64
179 self%eig_mixed(1) = 1.0_f64
181 do k=1, (n_dofs+1)/2 - 1
185 modulus = (cos_mode-1.0_f64)**2 + sin_mode**2
187 self%eig_d(k+1) = 0.0_f64
189 self%eig_d(n_dofs-k+1) = factor
191 factor = factor * self%Lx*ni
194 self%eig_interp1(k+1) = sin_mode/factor
195 self%eig_interp1(n_dofs-k+1) = (cos_mode-1.0_f64)/factor
197 self%eig_mixed(k+1) = sin_mode/factor
199 self%eig_interp1_inverse(k+1) = sin_mode/modulus * factor
200 self%eig_interp1_inverse(n_dofs-k+1) = (1.0_f64-cos_mode)/modulus * factor
202 self%eig_mixed(n_dofs-k+1) = 0.0_f64
205 if ( modulo(n_dofs,2) == 0 )
then
206 self%eig_d(n_dofs/2 + 1) = 0.0_f64
207 self%eig_interp1(n_dofs/2+1) = 0.0_f64
209 self%eig_interp1_inverse(n_dofs/2+1) = 0.0_f64
211 self%eig_interp1t_inverse(1:n_dofs/2+1) = self%eig_interp1_inverse(1:n_dofs/2+1)
212 self%eig_interp1t_inverse(n_dofs/2+2:n_dofs) = -self%eig_interp1_inverse(n_dofs/2+2:n_dofs)
213 self%eig_poisson(n_dofs/2 + 1) = 0.0_f64
215 self%eig_mixed(n_dofs/2 + 1) = 0.0_f64
217 self%eig_interp1t_inverse(1:n_dofs/2+1) = self%eig_interp1_inverse(1:n_dofs/2+1)
218 self%eig_interp1t_inverse(n_dofs/2+2:n_dofs) = -self%eig_interp1_inverse(n_dofs/2+2:n_dofs)
221 self%eig_poisson(1) = 0.0_f64
223 do k=1,(n_dofs+1)/2 - 1
224 self%eig_poisson(k+1) = self%eig_interp1_inverse(n_dofs-k+1) / self%eig_d(n_dofs-k+1)
225 self%eig_poisson(n_dofs-k+1) = -self%eig_interp1_inverse(k+1) / self%eig_d(n_dofs-k+1)
233 sll_real64,
intent( in ) :: delta_t
235 sll_int32 :: k, n_dofs
238 n_dofs = self%n_cells
239 factor = 0.25_f64 * delta_t**2
241 self%eig_schur_curl_part = 0.0_f64
242 self%eig_schur_curl_part(1) = 1.0_f64
243 do k=1, (n_dofs+1)/2 - 1
244 self%eig_schur_curl_part(k+1) = 1.0_f64/(1.0_f64 + factor * self%eig_d(n_dofs-k+1)**2)
257 sll_real64 :: coefs1_dofs(:)
258 sll_real64 :: coefs2_dofs(:)
260 sll_int32,
optional :: degree2
263 if (
present(degree2) )
then
264 if (degree .ne. degree2 )
then
266 r = self%wsave(1) * coefs2_dofs(1) * self%delta_x
267 r = r + sum(self%wsave(2:self%n_cells) * coefs2_dofs(2:self%n_cells) ) * self%delta_x * 2.0_f64
269 r = coefs1_dofs(1) * coefs2_dofs(1) * self%delta_x
270 r = r + sum(coefs1_dofs(2:self%n_cells) * coefs2_dofs(2:self%n_cells) ) * self%delta_x * 2.0_f64
273 r = coefs1_dofs(1) * coefs2_dofs(1) * self%delta_x
274 r = r + sum(coefs1_dofs(2:self%n_cells) * coefs2_dofs(2:self%n_cells) ) * self%delta_x * 2.0_f64
281 sll_real64 :: coefs_dofs(:)
285 r = coefs_dofs(1) * coefs_dofs(1) * self%delta_x
286 r = r + sum(coefs_dofs(2:self%n_cells) * coefs_dofs(2:self%n_cells) ) * self%delta_x * 2.0_f64
293 sll_real64,
dimension(:),
intent(in) :: current
294 sll_int32,
intent(in) :: component
295 sll_real64,
dimension(:),
intent(inout) :: e
298 if ( component == 1 )
then
301 e = e - self%work / sqrt(real(self%n_cells,f64))
302 elseif ( component == 2)
then
306 e = e - self%wsave / sqrt(real(self%n_cells,f64))
308 print*,
'Component ', component,
'not implemented in compute_E_from_j_1d_ps.'
318 sll_real64,
intent(in) :: delta_t
319 sll_real64,
intent(in) :: field_in(:)
320 sll_real64,
intent(inout) :: field_out(:)
323 field_out = field_out - delta_t * self%work
329 sll_real64,
intent(in) :: delta_t
330 sll_real64,
intent(inout) :: efield(:)
331 sll_real64,
intent(inout) :: bfield(:)
332 sll_real64,
optional :: betar
337 if(
present(betar) )
then
343 dth = 0.5_f64 * delta_t
348 call self%compute_b_from_e ( dth, efield, self%wsave )
349 call self%compute_e_from_b ( dth, bfield*factor, efield )
351 call self%compute_b_from_e ( dth, efield, self%wsave )
354 call self%compute_e_from_b( dth, bfield*factor, efield )
361 sll_int32,
intent(in) :: degree
362 sll_real64,
intent(in) :: in(:)
363 sll_real64,
intent(out) :: out(:)
366 if ( degree == 0 )
then
371 out = out / sqrt(real(self%n_cells, f64)) * self%delta_x
372 elseif ( degree == 1 )
then
377 out = out / sqrt(real(self%n_cells, f64)) * self%delta_x
378 elseif ( degree == 2 )
then
384 out = out / sqrt(real(self%n_cells, f64)) * self%delta_x
385 elseif ( degree == 3 )
then
390 out = out / sqrt(real(self%n_cells, f64)) * self%delta_x
392 print*,
'Component', degree,
'not defined in maxwell_1d_ps.'
400 sll_real64,
intent(in) :: field_in(:)
401 sll_real64,
intent(out) :: field_out(:)
404 self%wsave = field_in/sqrt(real(self%n_cells,f64))
413 sll_real64,
intent(in) :: field_in(:)
414 sll_real64,
intent(out) :: field_out(:)
419 field_out = field_out / sqrt(real(self%n_cells,f64))
425 sll_int32,
intent(in) :: n_dofs
426 sll_real64,
intent(in) :: eigvals(:)
427 sll_real64,
intent(in) :: in(:)
428 sll_real64,
intent(out) :: out(:)
434 out(1) = in(1) * eigvals(1)
436 re = in(k) * eigvals(k) - &
437 in(n_dofs-k+2) * eigvals(n_dofs-k+2)
438 im = in(k) * eigvals(n_dofs-k+2) + &
439 in(n_dofs-k+2) * eigvals(k)
443 if ( modulo(n_dofs,2) == 0 )
then
444 out(n_dofs/2+1) = in(n_dofs/2+1)*eigvals(n_dofs/2+1)
452 sll_real64,
intent(in) :: in(:)
453 sll_real64,
intent(out) :: out(:)
454 sll_int32,
intent(in) :: degree
456 out = in * self%delta_x
462 sll_int32,
intent(in) :: degree
463 sll_real64,
intent(in) :: in(:)
464 sll_real64,
intent(out) :: out(:)
466 out = in / self%delta_x
472 sll_real64,
intent(in) :: in(:)
473 sll_real64,
intent(out) :: out(:)
482 sll_real64,
intent(in) :: in(:)
483 sll_real64,
intent(out) :: out(:)
495 sll_int32,
intent(in) :: degree
496 sll_real64,
intent(out) :: coefs_dofs(:)
503 x = self%domain(1) + self%delta_x * real(k-1, f64)
504 coefs_dofs(k) = func( x )
514 sll_int32,
intent(in) :: degree
515 sll_real64,
intent(out) :: coefs_dofs(:)
518 call self%compute_rhs_from_function( func, degree, self%wsave )
521 coefs_dofs = coefs_dofs/sqrt(real(self%n_cells,f64))
529 sll_real64,
intent(in) :: in(:)
530 sll_real64,
intent(out) :: phi(:)
531 sll_real64,
intent(out) :: efield(:)
534 call self%invert_mass( in, phi, self%s_deg_0 )
546 sll_real64,
intent(in) :: in(:)
547 sll_real64,
intent(out) :: phi(:)
548 sll_real64,
intent(out) :: efield(:)
555 call self%invert_mass( self%work, self%wsave, self%s_deg_0 )
556 phi = phi + self%wsave
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
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_init_r2r_1d(plan, nx, array_in, array_out, direction, normalized, aligned, optimization)
Create new 1d real to real plan.
integer, parameter, public sll_p_fft_backward
Flag to specify backward FFT (positive sign) [value 1].
subroutine, public sll_s_fft_exec_r2r_1d(plan, array_in, array_out)
Compute fast Fourier transform in real to real mode.
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 [...
Module interface to solve Maxwell's equations in 1D.
Solve Maxwell's equations in 1D based on a pseudospectral solver.
subroutine multiply_gt(self, in, out)
subroutine complex_product_real(n_dofs, eigvals, in, out)
real(kind=f64) function inner_product_1d_ps(self, coefs1_dofs, coefs2_dofs, degree, degree2)
subroutine compute_rhs_from_function(self, func, degree, coefs_dofs)
Compute the FEM right-hand-side for a given function f and periodic splines of given degree Its compo...
subroutine l2projection(self, func, degree, coefs_dofs)
Compute the L2 projection of a given function f on periodic splines of given degree.
real(kind=f64) function l2norm_squared_1d_ps(self, coefs_dofs, degree)
subroutine set_eig_schur_curl_part(self, delta_t)
subroutine proj1_grad(self, in, out)
subroutine invert_mass_1d_ps(self, in, out, degree)
subroutine init_1d_ps(self, domain, n_dofs)
subroutine grad_proj0(self, in, out)
subroutine compute_phi_from_j_1d_ps(self, in, phi, efield)
For model with adiabatic electrons.
subroutine compute_rho_from_e_1d_ps(self, field_in, field_out)
subroutine sll_s_compute_e_b_1d(self, delta_t, efield_dofs, bfield_dofs)
subroutine compute_curl_part_1d_ps(self, delta_t, efield, bfield, betar)
subroutine free_1d_ps(self)
subroutine compute_phi_from_rho_1d_ps(self, in, phi, efield)
For model with adiabatic electrons.
subroutine multiply_g(self, in, out)
subroutine compute_e_from_j_1d_ps(self, current, component, E)
Compute E_i from j_i integrated over the time interval using weak Ampere formulation
subroutine transform_dofs_1d_ps(self, in, out, degree)
subroutine compute_field_from_field_1d_ps(self, delta_t, field_in, field_out)
subroutine multiply_mass_1d_ps(self, in, out, degree)
subroutine compute_e_from_rho_1d_ps(self, field_in, field_out)
Type for FFT plan in SeLaLib.
Maxwell solver class with pseudospectral method.