8 #include "sll_assert.h"
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
11 #include "sll_errors.h"
17 sll_s_uniform_bsplines_eval_basis
67 sll_real64,
intent( in ) :: position(self%dim)
68 sll_real64,
intent( in ) :: marker_charge
69 sll_real64,
intent( inout ) :: rho_dofs(self%n_dofs)
73 sll_int32 :: index1d, index
74 sll_real64 :: xi(1), pos, scaling, weight
75 sll_int32 :: n_quad_points
77 sll_real64 :: integ(1:self%n_span)
79 xi(1) = (position(1) - self%domain(1))/self%delta_x
80 index = floor(xi(1))+1
81 xi(1) = xi(1) - real(index-1, f64)
85 n_quad_points = self%n_quadp1_points
91 scaling = 1.0_f64 - xi(1)
92 weight = marker_charge * self%scaling * scaling
94 do q = 1, n_quad_points
95 pos = xi(1)+ scaling * self%quads1_xw(1,q)
96 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
98 integ = self%quads1_xw(2,q)*self%spline_val*scaling * self%quads1_xw(1,q)
100 do i1 = 1, self%n_span
101 index1d = modulo(index- self%spline_degree+i1-3,self%n_cells)+1
102 rho_dofs(index1d) = rho_dofs(index1d) + weight * integ(i1)
106 integ = self%quads1_xw(2,q)*self%spline_val*(1.0_f64-scaling * self%quads1_xw(1,q))
108 do i1 = 1, self%n_span
109 index1d = modulo(index- self%spline_degree+i1-2,self%n_cells)+1
110 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
115 weight = marker_charge * self%scaling * xi(1)
117 do q = 1, n_quad_points
118 pos = xi(1) * self%quads1_xw(1,q)
119 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
121 integ = self%quads1_xw(2,q)*self%spline_val*(scaling + xi(1) * self%quads1_xw(1,q))
123 do i1 = 1, self%n_span
124 index1d = modulo(index- self%spline_degree+i1-2,self%n_cells)+1
125 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
128 integ = self%quads1_xw(2,q)*self%spline_val* xi(1)*(1.0_f64-self%quads1_xw(1,q))
130 do i1 = 1, self%n_span
131 index1d = modulo(index- self%spline_degree+i1-1,self%n_cells)+1
132 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
142 sll_real64,
intent(in) :: position_old(self%dim)
143 sll_real64,
intent(in) :: position_new(self%dim)
144 sll_real64,
intent(in) :: marker_charge
145 sll_real64,
intent(in) :: qoverm
146 sll_real64,
intent(in) :: bfield_dofs(:)
147 sll_real64,
intent(inout) :: vi(:)
148 sll_real64,
intent(inout) :: j_dofs(:)
152 sll_int32 :: index_old, index_new, ind
153 sll_real64 :: r_old, r_new
157 xi = (position_old(1) - self%domain(1)) /&
159 index_old = floor(xi)
160 r_old = xi - real(index_old,f64)
163 xi = (position_new(1) - self%domain(1)) /&
165 index_new = floor(xi)
166 r_new = xi - real(index_new ,f64)
171 j_dofs, bfield_dofs, vi(2))
173 j_dofs, bfield_dofs, vi(2))
204 if (index_old == index_new)
then
205 if (r_old < r_new)
then
206 call self%update_jv(r_old, r_new, index_old+1, marker_charge, &
207 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
209 call self%update_jv(r_new, r_old, index_old+1, marker_charge, qoverm, &
210 -1.0_f64, vi(2), j_dofs, bfield_dofs)
212 elseif (index_old < index_new)
then
213 call self%update_jv (r_old, 1.0_f64, index_old+1, marker_charge, &
214 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
215 call self%update_jv (0.0_f64, r_new, index_new+1, marker_charge, &
216 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
217 do ind = index_old+2, index_new
218 call self%update_jv (0.0_f64, 1.0_f64, ind, marker_charge, &
219 qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
222 call self%update_jv (r_new, 1.0_f64, index_new+1, marker_charge, qoverm, &
223 -1.0_f64, vi(2), j_dofs, bfield_dofs)
224 call self%update_jv (0.0_f64, r_old, index_old+1, marker_charge, qoverm, &
225 -1.0_f64, vi(2), j_dofs, bfield_dofs)
226 do ind = index_new+2, index_old
227 call self%update_jv (0.0_f64, 1.0_f64, ind, marker_charge, qoverm, &
228 -1.0_f64, vi(2), j_dofs, bfield_dofs)
239 sll_real64,
intent( in ) :: position_normalized(self%dim)
240 sll_int32,
intent( in ) :: box
241 sll_real64,
intent( in ) :: marker_charge
242 sll_real64,
intent(in) :: qoverm
243 sll_real64,
intent( inout ) :: rho_dofs(self%n_dofs)
244 sll_real64,
intent(inout) :: vi
245 sll_real64,
intent(in) :: bfield_dofs(self%n_dofs)
249 sll_int32 :: index1d, index
250 sll_real64 :: xi(1), pos, scaling, weight, pos_hat
251 sll_int32 :: n_quad_points
253 sll_real64 :: integ(1:self%n_span)
255 xi(1) = position_normalized(1)
259 n_quad_points = self%n_quads2_points
265 scaling = 1.0_f64 - xi(1)
266 weight = marker_charge * self%scaling * scaling * self%delta_x
268 do q = 1, n_quad_points
269 pos = xi(1)+ scaling * self%quads2_xw(1,q)
270 pos_hat = scaling * self%quads2_xw(1,q)
271 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
273 integ = self%quads2_xw(2,q)*self%spline_val* pos_hat**2*0.5_f64
275 do i1 = 1, self%n_span
276 index1d = modulo(index- self%spline_degree+i1-3,self%n_cells)+1
277 rho_dofs(index1d) = rho_dofs(index1d) + weight * integ(i1)
278 vi = vi - qoverm * integ(i1) * bfield_dofs(index1d) * self%delta_x * scaling
281 pos_hat = self%quads2_xw(1,q)* scaling
282 integ = self%quads2_xw(2,q)*self%spline_val* (pos_hat + (1.0_f64-pos_hat**2)*0.5_f64)
284 do i1 = 1, self%n_span
285 index1d = modulo(index- self%spline_degree+i1-2,self%n_cells)+1
286 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
287 vi = vi - qoverm * integ(i1) * bfield_dofs(index1d) * self%delta_x * scaling
291 weight = marker_charge * self%scaling * xi(1) * self%delta_x
293 do q = 1, n_quad_points
294 pos = xi(1) * self%quads2_xw(1,q)
295 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
297 pos_hat = 1.0_f64 - xi(1) * (1.0_f64 - self%quads2_xw(1,q))
298 integ = self%quads2_xw(2,q)*self%spline_val* pos_hat**2*0.5_f64
300 do i1 = 1, self%n_span
301 index1d = modulo(index- self%spline_degree+i1-2,self%n_cells)+1
302 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
303 vi = vi - qoverm * integ(i1) * bfield_dofs(index1d) * self%delta_x * xi(1)
307 pos_hat = scaling + xi(1) * self%quads2_xw(1,q)
308 integ = self%quads2_xw(2,q)*self%spline_val*(pos_hat + (1.0_f64-pos_hat**2)*0.5_f64)
310 do i1 = 1, self%n_span
311 index1d = modulo(index- self%spline_degree+i1-1,self%n_cells)+1
312 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
313 vi = vi - qoverm * integ(i1) * bfield_dofs(index1d) * self%delta_x * xi(1)
323 sll_real64,
intent( in ) :: position_normalized(self%dim)
324 sll_int32,
intent( in ) :: box
325 sll_real64,
intent(inout) :: field_int
326 sll_real64,
intent(in) :: field_dofs(self%n_dofs)
330 sll_int32 :: index1d, index
331 sll_real64 :: xi(1), pos, scaling, weight, pos_hat
332 sll_int32 :: n_quad_points
334 sll_real64 :: integ(1:self%n_span)
339 xi(1) = position_normalized(1)
343 n_quad_points = self%n_quads2_points
345 scaling = 1.0_f64 - xi(1)
346 weight = self%scaling * scaling * self%delta_x
348 do q = 1, n_quad_points
349 pos = xi(1)+ scaling * self%quads2_xw(1,q)
350 pos_hat = scaling * self%quads2_xw(1,q)
351 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
353 integ = self%quads2_xw(2,q)*self%spline_val* pos_hat**2*0.5_f64
355 do i1 = 1, self%n_span
356 index1d = modulo(index- self%spline_degree+i1-3,self%n_cells)+1
357 field_int = field_int + integ(i1) * field_dofs(index1d) * self%delta_x * scaling
360 pos_hat = self%quads2_xw(1,q)* scaling
361 integ = self%quads2_xw(2,q)*self%spline_val* (pos_hat + (1.0_f64-pos_hat**2)*0.5_f64)
363 do i1 = 1, self%n_span
364 index1d = modulo(index- self%spline_degree+i1-2,self%n_cells)+1
365 field_int = field_int + integ(i1) * field_dofs(index1d) * self%delta_x * scaling
369 weight = self%scaling * xi(1) * self%delta_x
371 do q = 1, n_quad_points
372 pos = xi(1) * self%quads2_xw(1,q)
373 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
375 pos_hat = 1.0_f64 - xi(1) * (1.0_f64 - self%quads2_xw(1,q))
376 integ = self%quads2_xw(2,q)*self%spline_val* pos_hat**2*0.5_f64
378 do i1 = 1, self%n_span
379 index1d = modulo(index- self%spline_degree+i1-2,self%n_cells)+1
380 field_int = field_int + integ(i1) * field_dofs(index1d) * self%delta_x * xi(1)
383 pos_hat = scaling + xi(1) * self%quads2_xw(1,q)
384 integ = self%quads2_xw(2,q)*self%spline_val*(pos_hat + (1.0_f64-pos_hat**2)*0.5_f64)
386 do i1 = 1, self%n_span
387 index1d = modulo(index- self%spline_degree+i1-1,self%n_cells)+1
388 field_int = field_int + integ(i1) * field_dofs(index1d) * self%delta_x * xi(1)
398 sll_real64,
intent(in) :: lower
399 sll_real64,
intent(in) :: upper
400 sll_int32,
intent(in) :: index
401 sll_real64,
intent(in) :: sign
402 sll_real64,
intent(in) :: field_dofs(self%n_dofs)
403 sll_real64,
intent(inout) :: field_int
406 sll_int32 :: ind, i_grid, i_mod, n_cells, j
410 n_cells = self%n_cells
412 c1 = 0.5_f64*(upper-lower)
413 c2 = 0.5_f64*(upper+lower)
415 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, c1*self%quad_xw(1,1)+c2, &
419 self%spline_val = self%spline_val * (self%quad_xw(2,1)*c1)
420 do j=2,self%n_quad_points
421 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, c1*self%quad_xw(1,j)+c2, &
422 self%spline_val_more)
425 self%spline_val = self%spline_val + self%spline_val_more * (self%quad_xw(2,j)*c1)
427 self%spline_val = self%spline_val * (sign*self%delta_x)
430 do i_grid = index - self%spline_degree , index
431 i_mod = modulo(i_grid, n_cells ) + 1
432 field_int = field_int + self%spline_val(ind)*field_dofs(i_mod)
443 sll_real64,
intent( in ) :: position(self%dim)
444 sll_real64,
intent( in ) :: field_dofs(self%n_dofs)
445 sll_real64,
intent( out ) :: field_value
451 sll_real64 :: field_val
452 sll_real64 :: scaling
460 dx = (position(1) - self%domain(1))/self%delta_x
462 dx = dx - real(index, f64)
464 field_value = 0.0_f64
467 do j=1,self%n_quadp1_points
468 call self%evaluate_simple &
469 ( [position(1)+(self%quads1_xw(1,j)*scaling-1.0_f64)*self%delta_x], field_dofs, field_val)
470 field_value = field_value + self%quads1_xw(2,j)*scaling* (self%quads1_xw(1,j)*scaling) * field_val
474 do j=1,self%n_quadp1_points
475 call self%evaluate_simple &
476 ( [position(1)+(self%quads1_xw(1,j)-1.0_f64)*dx*self%delta_x], field_dofs, field_val)
477 field_value = field_value + self%quads1_xw(2,j)*dx* (self%quads1_xw(1,j)*dx+scaling) * field_val
481 do j=1,self%n_quadp1_points
482 call self%evaluate_simple &
483 ( [position(1)+self%quads1_xw(1,j)*scaling*self%delta_x], field_dofs, field_val)
484 field_value = field_value + self%quads1_xw(2,j)*scaling* (1.0_f64-self%quads1_xw(1,j)*scaling) * field_val
488 do j=1,self%n_quadp1_points
489 call self%evaluate_simple &
490 ( [position(1)+(1.0_f64+dx*(self%quads1_xw(1,j)-1.0_f64))*self%delta_x], field_dofs, field_val)
491 field_value = field_value + self%quads1_xw(2,j)*dx* ((1.0_f64-self%quads1_xw(1,j))*dx) * field_val
504 sll_real64,
intent( in ) :: position_old(self%dim)
505 sll_real64,
intent( in ) :: position_new(self%dim)
506 sll_real64,
intent( in ) :: marker_charge
507 sll_real64,
intent( in ) :: vbar
508 sll_real64,
intent( in ) :: field_dofs(self%n_dofs)
509 sll_real64,
intent( inout ) :: j_dofs(self%n_dofs)
510 sll_real64,
intent( out ) :: field
512 sll_real64 :: fields(2)
517 -1.0_f64, field_dofs,fields, j_dofs)
518 field = fields(2)/vbar
528 sll_real64,
intent( in ) :: position_old(self%dim)
529 sll_real64,
intent( in ) :: position_new(self%dim)
530 sll_real64,
intent( in ) :: vbar
531 sll_real64,
intent( in ) :: field_dofs(self%n_dofs)
532 sll_real64,
intent( out ) :: field
535 sll_int32 :: index_old, index_new, ind
536 sll_real64 :: r_old, r_new
540 xi = (position_old(1) - self%domain(1)) /&
542 index_old = floor(xi)
543 r_old = xi - real(index_old,f64)
546 xi = (position_new(1) - self%domain(1)) /&
548 index_new = floor(xi)
549 r_new = xi - real(index_new ,f64)
557 if (index_old == index_new)
then
558 if (r_old < r_new)
then
562 1.0_f64, field_dofs, field)
567 -1.0_f64, field_dofs, field)
569 elseif (index_old < index_new)
then
571 1.0_f64, field_dofs, field)
573 1.0_f64, field_dofs, field)
578 do ind = index_old+2, index_new
580 1.0_f64, field_dofs, field)
586 -1.0_f64, field_dofs, field)
588 -1.0_f64, field_dofs, field)
593 do ind = index_new+2, index_old
595 -1.0_f64, field_dofs, field)
610 sll_int32,
intent(in) :: n_cells
611 sll_real64,
intent(in) :: domain(2)
612 sll_int32,
intent(in) :: no_particles
613 sll_int32,
intent(in) :: spline_degree
614 sll_int32,
intent(in) :: smoothing_type
621 sll_assert( ierr == 0)
623 select type( smoother )
625 call smoother%init( domain, n_cells, no_particles, spline_degree, smoothing_type )
634 sll_int32,
intent(in) :: n_cells
635 sll_real64,
intent(in) :: domain(2)
636 sll_int32,
intent(in) :: no_particles
637 sll_int32,
intent(in) :: spline_degree
638 sll_int32,
intent(in) :: smoothing_type
645 sll_assert( ierr == 0)
647 select type( smoother )
649 call smoother%init( domain, n_cells, no_particles, spline_degree, smoothing_type )
657 sll_real64,
intent( in ) :: position(self%dim)
658 sll_real64,
intent( in ) :: marker_charge
659 sll_real64,
intent( inout ) :: particle_mass(:,:)
662 sll_int32 :: i1, column
663 sll_int32 :: index1d, index
665 sll_real64 :: scratch(1:self%n_span+2)
667 sll_assert(
size(particle_mass,1) == self%n_span+2 )
668 sll_assert(
size(particle_mass,2) == self%n_dofs )
670 xi(1) = (position(1) - self%domain(1))/self%delta_x
671 index = ceiling(xi(1))
672 xi(1) = xi(1) - real(index-1, f64)
673 index = index - self%spline_degree-1
679 do i1 = 1, self%n_span+2
680 index1d = modulo(index+i1-2,self%n_cells)+1
681 do column = i1, self%n_span+2
682 particle_mass(column-i1+1, index1d) = particle_mass( column-i1+1, index1d) + &
683 marker_charge * scratch(i1) * scratch(column)
695 sll_real64,
intent( in ) :: position(self%dim)
696 sll_real64,
intent( in ) :: marker_charge
697 sll_real64,
intent( inout ) :: particle_mass(:,:)
700 sll_int32 :: i1, column, ind
701 sll_int32 :: index1d, index
703 sll_real64 :: scratch(1:self%n_span+2)
705 sll_assert(
size(particle_mass,1) == 2*self%n_span+3 )
706 sll_assert(
size(particle_mass,2) == self%n_dofs )
708 xi(1) = (position(1) - self%domain(1))/self%delta_x
709 index = ceiling(xi(1))
710 xi(1) = xi(1) - real(index-1, f64)
711 index = index - self%spline_degree-1
717 do i1 = 1, self%n_span+2
718 index1d = modulo(index+i1-2,self%n_cells)+1
719 ind = 1+(self%n_span+2-i1)
720 do column = 1, self%n_span+2
721 particle_mass(ind, index1d) = particle_mass( ind, index1d) + &
722 marker_charge * scratch(i1) * scratch(column)
736 sll_real64,
intent( in ) :: position(self%dim)
737 sll_real64,
intent( inout ) :: rho_dofs(self%n_span+2)
742 sll_real64 :: xi(1), pos, scaling, weight
743 sll_int32 :: n_quad_points
744 sll_real64 :: integ(1:self%n_span)
749 n_quad_points = self%n_quadp1_points
751 scaling = 1.0_f64 - xi(1)
754 do q = 1, n_quad_points
755 pos = xi(1)+ scaling * self%quads1_xw(1,q)
756 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
758 integ = self%quads1_xw(2,q)*self%spline_val*scaling * self%quads1_xw(1,q)
760 do i1 = 1, self%n_span
763 rho_dofs(index1d) = rho_dofs(index1d) + weight * integ(i1)
767 integ = self%quads1_xw(2,q)*self%spline_val*(1.0_f64-scaling * self%quads1_xw(1,q))
769 do i1 = 1, self%n_span
772 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
779 do q = 1, n_quad_points
780 pos = xi(1) * self%quads1_xw(1,q)
781 call sll_s_uniform_bsplines_eval_basis(self%spline_degree, pos, self%spline_val)
783 integ = self%quads1_xw(2,q)*self%spline_val*(scaling + xi(1) * self%quads1_xw(1,q))
785 do i1 = 1, self%n_span
788 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
792 integ = self%quads1_xw(2,q)*self%spline_val* xi(1)*(1.0_f64-self%quads1_xw(1,q))
794 do i1 = 1, self%n_span
797 rho_dofs(index1d) = rho_dofs(index1d) +weight * integ(i1)
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 1d with splines of arbitrary degree placed on a uniform mesh.
Kernel smoother for 2d with splines of arbitrary degree placed on a uniform mesh.
subroutine add_charge_single_smoothened_spline_1d(self, position, marker_charge, rho_dofs)
Evaluates the integral int_{poisition_old}^{position_new} field(x) d x.
subroutine add_particle_mass_spline_smooth_1d(self, position, marker_charge, particle_mass)
Add particle mass for one particle (upper triangular version)
subroutine evaluate_field_single_smoothened_spline_1d(self, position, field_dofs, field_value)
Evaluate field with smoothing at at position position.
subroutine evaluate_int_smoothened_spline_1d(self, position_old, position_new, vbar, field_dofs, field)
Add current for one particle and evaluate the field (according to iterative part in discrete gradient...
subroutine evaluate_int_simple_smoothened_spline_1d(self, lower, upper, index, sign, field_dofs, field_int)
Helper function to evaluate the integrated efield in one interval (without smoothing kernel) (similar...
subroutine update_smoothened_single_spline_1d(self, position_normalized, box, marker_charge, qoverm, rho_dofs, bfield_dofs, vi)
Integration over the prime function of the smoothing kernel S (for v update and j accumulation)
subroutine add_particle_mass_full_spline_smooth_1d(self, position, marker_charge, particle_mass)
Add particle mass for one particle (full matrix) WARNING: THIS FUNCTION SEEMS TO HAVE BUGS.
subroutine add_current_evaluate_smoothened_spline_1d(self, position_old, position_new, marker_charge, vbar, field_dofs, j_dofs, field)
Add current for one particle and evaluate the field (according to iterative part in discrete gradient...
subroutine add_charge_box(self, position, rho_dofs)
Add charge of one particle with smoothing.
subroutine add_current_update_v_smoothened_spline_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, public sll_s_new_particle_mesh_coupling_spline_smooth_1d_ptr(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type)
subroutine, public sll_s_new_particle_mesh_coupling_spline_smooth_1d(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type)
subroutine evaluate_int_prime_smoothened_single_spline_1d(self, position_normalized, box, field_dofs, field_int)
Integration over the prime function of the smoothing kernel S (for evaluation only)
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.
Basic type of a kernel smoother used for PIC simulations.
Spline kernel smoother in1d.
Spline kernel smoother in1d.