8 #include "sll_assert.h"
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
11 #include "sll_errors.h"
14 sll_s_uniform_bsplines_eval_basis
48 sll_int32 :: no_particles
51 sll_int32 :: n_quad_points
52 sll_real64,
allocatable :: spline_val(:)
53 sll_real64,
allocatable :: spline_val_more(:)
55 sll_int32 :: n_quad_points_line
56 sll_real64,
allocatable :: quad_xw_line(:,:)
57 sll_real64,
allocatable :: quad_xw(:,:)
81 sll_real64,
intent( in ) :: position(self%dim)
82 sll_real64,
intent( in ) :: marker_charge
83 sll_real64,
intent( inout ) :: rho_dofs(self%n_dofs)
93 rho_dofs(box+i-1) = rho_dofs(box+i-1) +&
94 (marker_charge * self%spline_val(i)* self%scaling)
105 sll_real64,
intent( in ) :: position(self%dim)
106 sll_real64,
intent( in ) :: marker_charge
107 sll_real64,
intent( inout ) :: particle_mass(:,:)
110 sll_int32 :: i, column
114 sll_assert(
size(particle_mass,1) == self%n_span )
115 sll_assert(
size(particle_mass,2) == self%n_dofs )
121 do i = 1, self%n_span
122 do column = i, self%n_span
123 particle_mass(column-i+1, box+i-1) = particle_mass( column-i+1, box+i-1) + &
124 marker_charge * self%spline_val(i) * self%spline_val(column)
136 sll_real64,
intent( in ) :: position(self%dim)
137 sll_real64,
intent( in ) :: marker_charge
138 sll_real64,
intent( inout ) :: particle_mass(:,:)
140 sll_int32 :: i, column, ind
144 sll_assert(
size(particle_mass,1) == 2*self%spline_degree+1 )
145 sll_assert(
size(particle_mass,2) == self%n_dofs )
151 do i = 1, self%n_span
152 ind=1+(self%n_span-i)
153 do column = 1, self%n_span
154 particle_mass(ind, box+i-1) = particle_mass( ind, box+i-1) + &
155 marker_charge * self%spline_val(i) * self%spline_val(column)
167 sll_real64,
intent( in ) :: position(self%dim)
168 sll_real64,
intent( in ) :: field_dofs(self%n_dofs)
169 sll_real64,
intent( out ) :: field_value
180 field_value = 0.0_f64
181 do i = 1, self%n_span
182 field_value = field_value + &
183 field_dofs(box+i-1) * &
194 sll_real64,
intent( in ) :: position(self%dim)
195 sll_int32,
intent(in) :: components(:)
196 sll_real64,
intent( in ) :: field_dofs(:,:)
197 sll_real64,
intent(out) :: field_value(:)
203 sll_assert(
size(field_dofs,1) == self%n_dofs )
204 sll_assert(
size(field_dofs,2) ==
size(field_value) )
211 field_value = 0.0_f64
212 do i = 1, self%n_span
214 field_value = field_value + &
215 field_dofs(box+i-1,components) * &
226 sll_real64,
intent( in ) :: position_old(self%dim)
227 sll_real64,
intent( in ) :: position_new(self%dim)
228 sll_real64,
intent( in ) :: marker_charge
229 sll_real64,
intent( inout ) :: j_dofs(self%n_dofs)
231 sll_int32 :: index_old, index_new, ind
232 sll_real64 :: r_old, r_new
237 if (index_old == index_new)
then
238 if (r_old < r_new)
then
239 call update_j( self, r_old, r_new, index_old, marker_charge, &
242 call update_j( self, r_new, r_old, index_old, marker_charge, &
245 elseif (index_old < index_new)
then
246 call update_j ( self, r_old, 1.0_f64, index_old, marker_charge, &
248 call update_j ( self, 0.0_f64, r_new, index_new, marker_charge, &
250 do ind = index_old+1, index_new-1
251 call update_j ( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
255 call update_j ( self, r_new, 1.0_f64, index_new, marker_charge, &
257 call update_j ( self, 0.0_f64, r_old, index_old, marker_charge, &
259 do ind = index_new+1, index_old-1
260 call update_j ( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
269 subroutine update_j(self, lower, upper, index, marker_charge,sign, j_dofs)
271 sll_real64,
intent(in) :: lower
272 sll_real64,
intent(in) :: upper
273 sll_int32,
intent(in) :: index
274 sll_real64,
intent(in) :: marker_charge
275 sll_real64,
intent(in) :: sign
276 sll_real64,
intent(inout) :: j_dofs(:)
278 sll_int32 :: ind, i_grid, j
281 c1 = 0.5_f64*(upper-lower)
282 c2 = 0.5_f64*(upper+lower)
285 self%spline_val = self%spline_val * (self%quad_xw(2,1)*c1)
286 do j=2,self%n_quad_points
288 self%spline_val = self%spline_val + self%spline_val_more * (self%quad_xw(2,j)*c1)
290 self%spline_val = self%spline_val * (sign*self%delta_x)
293 do i_grid = index, index + self%spline_degree
294 j_dofs(i_grid) = j_dofs(i_grid) + &
295 (marker_charge*self%spline_val(ind)* self%scaling)
305 sll_real64,
intent( in ) :: position_old(self%dim)
306 sll_real64,
intent( in ) :: position_new(self%dim)
307 sll_real64,
intent( in ) :: marker_charge
308 sll_real64,
intent( in ) :: vbar
309 sll_real64,
intent( in ) :: field_dofs(self%n_dofs)
310 sll_real64,
intent( inout ) :: j_dofs(self%n_dofs)
311 sll_real64,
intent( out ) :: field
313 sll_int32 :: index_old, index_new, ind
314 sll_real64 :: r_old, r_new
321 if (index_old == index_new)
then
322 if (r_old < r_new)
then
323 call update_je( self, r_old, r_new, index_old, marker_charge, &
324 1.0_f64, j_dofs, field_dofs, field)
326 call update_je( self, r_new, r_old, index_old, marker_charge, &
327 -1.0_f64, j_dofs, field_dofs, field)
329 elseif (index_old < index_new)
then
330 call update_je( self, r_old, 1.0_f64, index_old, marker_charge, &
331 1.0_f64, j_dofs, field_dofs, field)
332 call update_je( self, 0.0_f64, r_new, index_new, marker_charge, &
333 1.0_f64, j_dofs, field_dofs, field)
334 do ind = index_old+1, index_new-1
335 call update_je( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
336 1.0_f64, j_dofs, field_dofs, field)
339 call update_je( self, r_new, 1.0_f64, index_new, marker_charge, &
340 -1.0_f64, j_dofs, field_dofs, field)
341 call update_je( self, 0.0_f64, r_old, index_old, marker_charge, &
342 -1.0_f64, j_dofs, field_dofs, field)
343 do ind = index_new+1, index_old-1
344 call update_je( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
345 -1.0_f64, j_dofs, field_dofs, field)
354 subroutine update_je(self, lower, upper, index, marker_charge, sign, j_dofs, field_dofs, field)
356 sll_real64,
intent(in) :: lower
357 sll_real64,
intent(in) :: upper
358 sll_int32,
intent(in) :: index
359 sll_real64,
intent(in) :: marker_charge
360 sll_real64,
intent(in) :: sign
361 sll_real64,
intent(inout) :: j_dofs(:)
362 sll_real64,
intent(in) :: field_dofs(:)
363 sll_real64,
intent(inout) :: field
365 sll_int32 :: ind, i_grid, j
368 c1 = 0.5_f64*(upper-lower)
369 c2 = 0.5_f64*(upper+lower)
372 self%spline_val = self%spline_val * (self%quad_xw(2,1)*c1)
373 do j=2,self%n_quad_points
375 self%spline_val = self%spline_val + self%spline_val_more * (self%quad_xw(2,j)*c1)
377 self%spline_val = self%spline_val * self%delta_x * sign
380 do i_grid = index, index + self%spline_degree
381 j_dofs(i_grid) = j_dofs(i_grid) + &
382 (marker_charge*self%spline_val(ind)* self%scaling)
383 field = field + self%spline_val(ind)*field_dofs(i_grid)
394 sll_real64,
intent(in) :: position_old(self%dim)
395 sll_real64,
intent(in) :: position_new(self%dim)
396 sll_real64,
intent(in) :: marker_charge
397 sll_real64,
intent(in) :: qoverm
398 sll_real64,
intent(in) :: bfield_dofs(:)
399 sll_real64,
intent(inout) :: vi(:)
400 sll_real64,
intent(inout) :: j_dofs(:)
402 sll_int32 :: index_old, index_new, ind
403 sll_real64 :: r_old, r_new
408 if (index_old == index_new)
then
409 if (r_old < r_new)
then
410 call update_jv( self, r_old, r_new, index_old, marker_charge, &
411 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
413 call update_jv( self, r_new, r_old, index_old, marker_charge, qoverm, &
414 -1.0_f64, vi(2), j_dofs, bfield_dofs)
416 elseif (index_old < index_new)
then
417 call update_jv ( self, r_old, 1.0_f64, index_old, marker_charge, &
418 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
419 call update_jv ( self, 0.0_f64, r_new, index_new, marker_charge, &
420 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
421 do ind = index_old+1, index_new-1
422 call update_jv ( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
423 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
426 call update_jv ( self, r_new, 1.0_f64, index_new, marker_charge, qoverm, &
427 -1.0_f64, vi(2), j_dofs, bfield_dofs)
428 call update_jv ( self, 0.0_f64, r_old, index_old, marker_charge, qoverm, &
429 -1.0_f64, vi(2), j_dofs, bfield_dofs)
430 do ind = index_new+1, index_old-1
431 call update_jv ( self, 0.0_f64, 1.0_f64, ind, marker_charge, qoverm, &
432 -1.0_f64, vi(2), j_dofs, bfield_dofs)
440 subroutine update_jv(self, lower, upper, index, marker_charge, qoverm, sign, vi, j_dofs, bfield_dofs)
442 sll_real64,
intent(in) :: lower
443 sll_real64,
intent(in) :: upper
444 sll_int32,
intent(in) :: index
445 sll_real64,
intent(in) :: marker_charge
446 sll_real64,
intent(in) :: qoverm
447 sll_real64,
intent(in) :: sign
448 sll_real64,
intent(inout) :: vi
449 sll_real64,
intent(in) :: bfield_dofs(:)
450 sll_real64,
intent(inout) :: j_dofs(:)
452 sll_int32 :: ind, i_grid, j
455 c1 = 0.5_f64*(upper-lower)
456 c2 = 0.5_f64*(upper+lower)
459 self%spline_val = self%spline_val * (self%quad_xw(2,1)*c1)
460 do j=2,self%n_quad_points
462 self%spline_val = self%spline_val + self%spline_val_more * (self%quad_xw(2,j)*c1)
464 self%spline_val = self%spline_val * (sign*self%delta_x)
467 do i_grid = index, index + self%spline_degree
468 j_dofs(i_grid) = j_dofs(i_grid) + &
469 (marker_charge*self%spline_val(ind)* self%scaling)
470 vi = vi - qoverm* self%spline_val(ind)*bfield_dofs(i_grid)
480 sll_real64,
intent( in ) :: position(self%dim)
481 sll_real64,
intent( out ) :: xi
482 sll_int32,
intent( out ) :: box
484 xi = (position(1) - self%domain(1)) /self%delta_x
485 box = floor( xi ) + 1
486 xi = xi - real(box-1, f64)
488 if( box == self%n_cells + 1 )
then
489 if( xi == 0._f64)
then
493 print*,
'box,x, xbox', box, position(1), xi
494 sll_error(
'convert_x_to_xbox',
'box1 value to high' )
496 else if( box > self%n_cells + 1 )
then
497 print*,
'box,x, xbox', box, position(1), xi
498 sll_error(
'convert_x_to_xbox',
'box1 value to high' )
499 else if( box <= 0 )
then
500 print*,
'box,x, xbox', box, position(1), xi
501 sll_error(
'convert_x_to_xbox',
'box1 value to low' )
509 sll_int32,
intent( in ) :: n_cells
510 sll_int32,
intent( in ) :: degree
511 sll_real64,
intent( in ) :: xi
512 sll_int32,
intent( in ) :: box
513 sll_real64,
intent( out ) :: spline_val(:)
517 if(box >= 1 .and. box <= degree-1)
then
521 else if (box >= degree .and. box <= n_cells-degree+1)
then
522 call sll_s_uniform_bsplines_eval_basis( degree, xi, spline_val )
523 else if(box >= n_cells-degree+2 .and. box <= n_cells)
then
528 print*,
'box, xbox', box, xi
529 sll_error(
"uniform_bsplines_eval_basis_clamped",
"box out of range" )
536 subroutine init_spline_cl_1d( self, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary )
538 sll_real64,
intent(in) :: domain(2)
539 sll_int32,
intent(in) :: n_cells
540 sll_int32,
intent(in) :: no_particles
541 sll_int32,
intent(in) :: spline_degree
542 sll_int32,
intent(in) :: smoothing_type
543 sll_int32,
intent(in) :: boundary
552 self%n_cells = n_cells
553 self%n_dofs = n_cells+spline_degree
554 self%delta_x = (self%domain(2)-self%domain(1))/real(n_cells, f64)
557 self%no_particles = no_particles
560 self%spline_degree = spline_degree
561 self%n_span = spline_degree + 1
565 self%scaling = 1.0_f64/self%delta_x
567 self%scaling = 1.0_f64
569 print*,
'Smoothing Type ', smoothing_type,
' not implemented for kernel_smoother_spline_1d.'
572 self%n_quad_points = (self%spline_degree+2)/2
574 ALLOCATE( self%spline_val(self%n_span), stat = ierr)
575 sll_assert( ierr == 0 )
576 ALLOCATE( self%spline_val_more(self%n_span), stat = ierr )
577 sll_assert( ierr == 0 )
578 ALLOCATE( self%quad_xw(2,self%n_quad_points), stat = ierr )
579 sll_assert( ierr == 0 )
587 self%n_quad_points_line = (self%spline_degree+2)/2
589 allocate( self%quad_xw_line(2,self%n_quad_points_line) )
593 self%quad_xw_line(1,:) = 0.5_f64*(self%quad_xw_line(1,:)+1.0_f64)
594 self%quad_xw_line(2,:) = 0.5_f64*self%quad_xw_line(2,:)
604 deallocate(self%spline_val)
614 sll_int32,
intent(in) :: n_cells
615 sll_real64,
intent(in) :: domain(2)
616 sll_int32,
intent(in) :: no_particles
617 sll_int32,
intent(in) :: spline_degree
618 sll_int32,
intent(in) :: smoothing_type
619 sll_int32,
intent(in) :: boundary
625 sll_assert( ierr == 0)
627 select type( smoother )
629 call smoother%init( domain, n_cells, no_particles, spline_degree, smoothing_type, boundary )
639 sll_int32,
intent(in) :: n_cells
640 sll_real64,
intent(in) :: domain(2)
641 sll_int32,
intent(in) :: no_particles
642 sll_int32,
intent(in) :: spline_degree
643 sll_int32,
intent(in) :: smoothing_type
644 sll_int32,
intent(in) :: boundary
650 sll_assert( ierr == 0)
652 select type( smoother )
654 call smoother%init( domain, n_cells, no_particles, spline_degree, smoothing_type, boundary )
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.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
integer(kind=i32), parameter, public sll_p_collocation
integer(kind=i32), parameter, public sll_p_galerkin
Kernel smoother for 2d with splines of arbitrary degree placed on a uniform mesh.
subroutine add_current_spline_cl_1d(self, position_old, position_new, marker_charge, j_dofs)
Add current with integration over x.
subroutine add_charge_single_spline_cl_1d(self, position, marker_charge, rho_dofs)
Destructor.
subroutine update_je(self, lower, upper, index, marker_charge, sign, j_dofs, field_dofs, field)
Helper function for add_current_evaluate.
subroutine add_particle_mass_spline_cl_1d(self, position, marker_charge, particle_mass)
Add the contribution of one particle to the approximate mass matrix.
subroutine add_particle_mass_spline_cl_1d_full(self, position, marker_charge, particle_mass)
Add the contribution of one particle to the approximate mass matrix.
subroutine evaluate_multiple_spline_cl_1d(self, position, components, field_dofs, field_value)
Evaluate several fields at position position.
subroutine update_j(self, lower, upper, index, marker_charge, sign, j_dofs)
Helper function for add_current.
subroutine, public sll_s_new_particle_mesh_coupling_spline_cl_1d_ptr(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
subroutine sll_s_uniform_bsplines_eval_basis_clamped(spline, n_cells, degree, xi, box, spline_val)
Helper function to evaluate uniform clamped basis splines.
subroutine add_current_update_v_spline_cl_1d(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle and update v (according to H_p1 part in Hamiltonian splitting)
subroutine evaluate_field_single_spline_cl_1d(self, position, field_dofs, field_value)
Evaluate field at at position position.
subroutine free_spline_cl_1d(self)
Finalizer.
subroutine add_current_evaluate_spline_cl_1d(self, position_old, position_new, marker_charge, vbar, field_dofs, j_dofs, field)
Combines add_current and evaluate_int.
subroutine, public sll_s_new_particle_mesh_coupling_spline_cl_1d(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
subroutine update_jv(self, lower, upper, index, marker_charge, qoverm, sign, vi, j_dofs, bfield_dofs)
Helper function for add_current_update_v.
subroutine init_spline_cl_1d(self, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
Initializer.
subroutine convert_x_to_xbox(self, position, xi, box)
subroutine, public sll_s_spline_pp_horner_primitive_1d(val, degree, pp_coeffs, x)
Perform a 1d hornerschema on the pp_coeffs evaluate at x.
subroutine, public sll_s_spline_pp_init_1d(self, degree, n_cells, boundary)
Initialize sll_t_spline_pp_1d object (Set poly_coeffs depending on degree)
subroutine, public sll_s_spline_pp_free_1d(self)
Destructor 1d.
subroutine, public sll_s_spline_pp_horner_m_1d(self, val, degree, x)
Perform a 1d hornerschema on the poly_coeffs.
real(kind=f64) function, public sll_f_spline_pp_horner_1d(degree, pp_coeffs, x, index)
Perform a 1d hornerschema on the pp_coeffs at index.
Basic type of a kernel smoother used for PIC simulations.
Spline kernel smoother in1d.
arbitrary degree 1d spline