9 #include "sll_assert.h"
10 #include "sll_errors.h"
11 #include "sll_memory.h"
12 #include "sll_working_precision.h"
18 sll_s_uniform_bsplines_eval_basis, &
19 sll_s_uniform_bsplines_eval_deriv
47 sll_real64 :: rdelta_x(3)
49 sll_int32 :: no_particles
50 sll_int32 :: n_quad_points
52 sll_real64,
allocatable :: spline_val(:,:)
53 sll_real64,
allocatable :: spline_0(:,:)
54 sll_real64,
allocatable :: spline_0_deriv(:,:)
55 sll_real64,
allocatable :: spline1_0(:,:)
56 sll_real64,
allocatable :: spline_1(:,:)
57 sll_real64,
allocatable :: spline_1_deriv(:,:)
58 sll_real64,
allocatable :: spline_val_more(:,:)
59 sll_real64,
allocatable :: spline_2d(:,:), spline1_2d(:,:)
60 sll_real64,
allocatable :: spline1_3d(:,:,:), spline2_3d(:,:,:)
61 sll_real64,
allocatable :: j1d(:)
62 sll_real64,
allocatable :: quad_xw(:,:)
64 sll_int32,
allocatable :: index1d(:,:)
70 sll_int32 :: n_quad_points_line
71 sll_real64,
allocatable :: quad_xw_line(:,:)
92 sll_real64,
allocatable :: vals(:)
102 sll_real64,
intent( in ) :: position(3)
103 sll_real64,
intent( in ) :: marker_charge
104 sll_int32,
intent( in ) :: degree(3)
105 sll_real64,
intent( inout ) :: rho_dofs(:)
109 sll_int32 :: index3d(3)
116 self%spline_0 = 0.0_f64
118 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_0(1:degree(j)+1,j) )
122 self%spline_0(:,1) = self%spline_0(:,1)*marker_charge
124 do j = 1, degree(2)+1
125 do i = 1, degree(1)+1
126 self%spline_2d(i,j) = self%spline_0(i,1)*self%spline_0(j,2)
134 do k = 1, degree(3)+1
135 index3d(3) = self%index1d(k,3)
136 do j = 1, degree(2)+1
137 index3d(2) = self%index1d(j,2)
138 do i = 1, degree(1)+1
139 index3d(1) = self%index1d(i,1)
141 rho_dofs(index1d) = rho_dofs(index1d) + &
142 (self%spline_2d(i,j) * self%spline_0(k,3))
156 sll_real64,
intent( in ) :: position(3)
157 sll_real64,
intent( in ) :: marker_charge
158 sll_int32,
intent( in ) :: degree(3)
159 sll_real64,
intent( inout ) :: rho_dofs(self%n_total)
163 sll_int32 :: index3d(3)
170 self%spline_0 = 0.0_f64
175 self%spline_0(:,1) = self%spline_0(:,1)*marker_charge
177 do j = 1, degree(2)+1
178 do i = 1, degree(1)+1
179 self%spline_2d(i,j) = self%spline_0(i,1)*self%spline_0(j,2)
188 do k = 1, degree(3)+1
189 index3d(3) = self%index1d(k,3)
190 do j = 1, degree(2)+1
191 index3d(2) = self%index1d(j,2)
192 do i = 1, degree(1)+1
193 index3d(1) = self%index1d(i,1)
195 rho_dofs(index1d) = rho_dofs(index1d) + &
196 (self%spline_2d(i,j) * &
209 sll_real64,
intent( in ) :: position(3)
210 sll_real64,
intent( in ) :: marker_charge
211 sll_int32,
intent( in ) :: degree(3)
212 sll_real64,
intent( inout ) :: particle_mass(:,:)
216 sll_int32 :: index3d(3)
218 sll_int32 :: i,j,k, col1, col2, col3, ind
219 sll_real64 :: splineijk, splineijkcol3
225 self%spline_0 = 0.0_f64
227 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_0(1:degree(j)+1,j) )
231 do j = 1, degree(2)+1
232 do i = 1, degree(1)+1
233 self%spline_2d(i,j) = self%spline_0(i,1)*self%spline_0(j,2)
243 do k = 1, degree(3)+1
244 index3d(3) = self%index1d(k,3)
245 do j = 1, degree(2)+1
246 index3d(2) = self%index1d(j,2)
247 do i = 1, degree(1)+1
248 index3d(1) = self%index1d(i,1)
250 ind = 1+(degree(1)+1-i)+(degree(2)+1-j)*(2*degree(1)+1)+ &
251 (degree(3)+1-k)*(2*degree(1)+1)*(2*degree(2)+1)
252 splineijk = marker_charge * self%spline_2d(i,j) *&
254 do col3 = 1,degree(3)+1
255 splineijkcol3 = splineijk*self%spline_0(col3, 3)
256 do col2 = 1,degree(2)+1
257 do col1 = 1,degree(1)+1
258 particle_mass(ind, index1d) = &
259 particle_mass( ind, index1d) + &
261 self%spline_2d(col1,col2)
266 ind = ind+ degree(2) * (2*degree(1)+1)
279 sll_real64,
intent( in ) :: position(3)
280 sll_real64,
intent( in ) :: marker_charge
281 sll_int32,
intent( in ) :: degree1(3), degree2(3)
282 sll_real64,
intent( inout ) :: particle_mass(:,:)
286 sll_int32 :: index3d(3)
288 sll_int32 :: i,j,k, col1, col2, col3, ind
289 sll_real64 :: splineijk, splineijkcol3
294 self%spline_0 = 0.0_f64
295 self%spline1_0 = 0.0_f64
297 call sll_s_uniform_bsplines_eval_basis( degree1(j), xi(j), self%spline_0(1:degree1(j)+1,j) )
298 call sll_s_uniform_bsplines_eval_basis( degree2(j), xi(j), self%spline1_0(1:degree2(j)+1,j) )
301 self%spline1_3d = 0._f64
303 do k = 1, degree1(3)+1
304 do j = 1, degree1(2)+1
305 do i = 1, degree1(1)+1
306 self%spline1_3d(i,j,k) = self%spline_0(i,1)*self%spline_0(j,2)*self%spline_0(k,3)
311 self%spline2_3d = 0._f64
312 do k = 1, degree2(3)+1
313 do j = 1, degree2(2)+1
314 do i = 1, degree2(1)+1
315 self%spline2_3d(i,j,k) = self%spline1_0(i,1)*self%spline1_0(j,2)*self%spline1_0(k,3)
325 do k = 1, degree1(3)+1
326 index3d(3) = self%index1d(k,3)
327 do j = 1, degree1(2)+1
328 index3d(2) = self%index1d(j,2)
329 do i = 1, degree1(1)+1
330 index3d(1) = self%index1d(i,1)
332 ind = 1+(degree1(1)+1-i)+(degree1(2)+1-j)*(degree1(1)+degree2(1)+1)+ &
333 (degree1(3)+1-k)*(degree1(1)+degree2(1)+1)*(degree1(2)+degree2(2)+1)
334 do col3 = 1,degree2(3)+1
335 do col2 = 1,degree2(2)+1
336 do col1 = 1,degree2(1)+1
337 particle_mass( ind, index1d)=particle_mass( ind, index1d)+&
338 self%spline1_3d(i,j,k)*self%spline2_3d(col1,col2,col3)*&
344 ind = ind+degree1(2) * (degree1(1)+degree2(1)+1)
357 sll_real64,
intent( in ) :: position(3)
358 sll_int32 ,
intent( in ) :: degree(3)
359 sll_real64,
intent( in ) :: field_dofs(:)
360 sll_real64,
intent( out ) :: field_value
364 sll_int32 :: index3d(3)
373 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_val(1:degree(j)+1,j) )
376 field_value = 0.0_f64
381 do k = 1, degree(3)+1
382 index3d(3) = self%index1d(k,3)
383 do j = 1, degree(2)+1
384 index3d(2) = self%index1d(j,2)
385 do i = 1, degree(1)+1
386 index3d(1) = self%index1d(i,1)
388 field_value = field_value + &
389 field_dofs(index1d) * &
390 self%spline_val(i,1) * self%spline_val(j,2) * &
405 sll_real64,
intent( in ) :: position(3)
406 sll_int32 ,
intent( in ) :: degree(3)
407 sll_real64,
intent( in ) :: field_dofs_pp(:,:)
408 sll_real64,
intent( out ) :: field_value
425 sll_real64,
intent( in ) :: position(3)
426 sll_int32,
intent(in) :: components(:)
427 sll_real64,
intent( in ) :: field_dofs(:,:)
428 sll_real64,
intent(out) :: field_value(:)
436 sll_int32,
intent( in ) :: index3d(3)
437 sll_int32,
intent( in ) :: n_cells(3)
440 index1d = index3d(1) + (index3d(2)-1)*n_cells(1) + (index3d(3)-1)*n_cells(1)*n_cells(2)
447 sll_real64,
intent( in ) :: position(3)
448 sll_real64,
intent( out ) :: xi(3)
449 sll_int32,
intent( out ) :: box(3)
451 xi = (position - self%domain(:,1)) /self%delta_x
452 box = floor( xi ) + 1
453 xi = xi - real(box-1, f64)
460 sll_int32,
intent( in ) :: component
461 sll_real64,
intent( in ) :: position
462 sll_real64,
intent( out ) :: xi
463 sll_int32,
intent( out ) :: box
465 xi = (position - self%domain(component,1))/self%delta_x(component)
466 box = floor( xi ) + 1
467 xi = xi - real(box-1, f64)
475 sll_int32,
intent(in) :: box
476 sll_int32,
intent(in) :: comp
480 do j = 1, self%spline_degree(comp)+1
481 self%index1d(j,comp) = modulo(box+j-2,self%n_cells(comp))+1
489 sll_real64,
intent( in ) :: position_old(3)
490 sll_real64,
intent( in ) :: position_new(3)
491 sll_real64,
intent( in ) :: xdot(3)
492 sll_real64,
intent( in ) :: efield_dofs(:)
493 sll_real64,
intent( inout ) :: j_dofs(:)
494 sll_real64,
intent( out ) :: efield_val(3)
496 sll_real64 :: xold(3), xnew(3), xnewtilde(3), xbox(3)
497 sll_int32 :: boxold(3), boxnew(3), sigma_counter(3), boxdiff(3), increment(3), box(3)
498 sll_real64 :: sigma_r, sigma_l, sigma, sigma_next(3), field_value(3), weight
499 sll_int32 :: j, q, bl, maxind, index_is
506 boxdiff = boxnew-boxold
507 xnewtilde = xnew + real(boxdiff,f64)
517 if (boxdiff(j) > 0 )
then
518 allocate ( sigmas(j)%vals(boxdiff(j)+1) )
519 do bl = 1, boxdiff(j)
520 sigmas(j)%vals(bl) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
522 sigmas(j)%vals(boxdiff(j)+1) = 1.0_f64
523 sigma_next(j) = sigmas(j)%vals(1)
525 elseif (boxdiff(j) < 0 )
then
526 allocate ( sigmas(j)%vals(-boxdiff(j)+1) )
527 do bl = boxdiff(j)+1, 0
528 sigmas(j)%vals(-bl+1) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
530 sigmas(j)%vals(-boxdiff(j)+1) = 1.0_f64
531 sigma_next(j) = sigmas(j)%vals(1)
534 sigma_next(j) = 1.0_f64
540 do while ( abs(sigma_r - 1.0_f64) > 1d-16 )
542 index_is = minloc(sigma_next, dim=1)
543 sigma_r = sigma_next(index_is)
545 do q = 1, self%n_quad_points_line
546 sigma = sigma_l + (sigma_r-sigma_l) * self%quad_xw_line(1,q)
547 xbox = xold* (1.0_f64 - sigma) + xnewtilde * sigma - real(sigma_counter*increment, f64)
548 if (maxval(xbox) > 1.0_f64 )
then
549 print*, xbox, sigma, sigma_counter, increment
550 print*, xold, xnewtilde, sigma_r, xnewtilde * sigma - real(sigma_counter*increment, f64)
551 sll_error(
'add_current_evaluate',
'box value too large')
552 elseif (minval(xbox) < 0.0_f64 )
then
553 print*, xbox, sigma, sigma_counter, increment
554 print*, xold, xnewtilde, sigma_r, xnewtilde * sigma - real(sigma_counter*increment, f64)
555 sll_error(
'add_current_evaluate',
'box value too low')
558 weight = self%quad_xw_line(2,q)*(sigma_r-sigma_l)
560 call point_add_eval (self, box, xbox, efield_dofs, xdot*weight, j_dofs, field_value )
561 efield_val = efield_val + field_value * weight
563 if (sigma_r < 1.0_f64 )
then
565 sigma_counter(index_is) = sigma_counter(index_is)+1
566 sigma_next(index_is) = sigmas(index_is)%vals(sigma_counter(index_is)+1)
567 box(index_is) = box(index_is) + increment(index_is)
575 subroutine point_add_eval ( self, box_in, xbox, field_dofs, weight, j_dofs, field_value )
577 sll_int32,
intent(in) :: box_in(3)
578 sll_real64,
intent(in) :: xbox(3)
579 sll_real64,
intent(in) :: field_dofs(:)
580 sll_real64,
intent(in) :: weight(3)
581 sll_real64,
intent(inout) :: j_dofs(:)
582 sll_real64,
intent(out) :: field_value(3)
584 sll_int32 :: i,j,k, index1d, n_total
585 sll_int32 :: box(3), index3d(3)
588 n_total = self%n_total
589 field_value = 0.0_f64
592 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j), xbox(j), &
593 self%spline_0(1:self%spline_degree(j)+1,j) )
594 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j)-1, xbox(j), &
595 self%spline_1(1:self%spline_degree(j),j) )
598 box = box_in-self%spline_degree
604 do k = 1, self%spline_degree(3)+1
605 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
606 do j = 1, self%spline_degree(2)+1
607 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
608 do i = 1, self%spline_degree(1)
609 index1d = index3d(2) + self%index1d(i,1)
611 spval = self%spline_1(i,1) * &
612 self%spline_0(j,2) * self%spline_0(k,3)
613 field_value(1) = field_value(1) + field_dofs(index1d) * spval
614 j_dofs(index1d) = j_dofs(index1d) + &
624 do k = 1, self%spline_degree(3)+1
625 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
626 do j = 1, self%spline_degree(2)
627 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
628 do i = 1, self%spline_degree(1)+1
629 index1d = index3d(2) + self%index1d(i,1) + n_total
631 spval = self%spline_0(i,1) * &
632 self%spline_1(j,2) * self%spline_0(k,3)
633 field_value(2) = field_value(2) + field_dofs(index1d ) * spval
634 j_dofs(index1d) = j_dofs(index1d) + &
646 do k = 1, self%spline_degree(3)
647 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
648 do j = 1, self%spline_degree(2)+1
649 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
650 do i = 1, self%spline_degree(1)+1
651 index1d = index3d(2) + self%index1d(i,1) + n_total
652 spval = self%spline_0(i,1) * &
653 self%spline_0(j,2) * self%spline_1(k,3)
654 field_value(3) = field_value(3) + field_dofs(index1d ) * spval
655 j_dofs(index1d) = j_dofs(index1d) + &
667 sll_real64,
intent( in ) :: position_old(3)
668 sll_real64,
intent( in ) :: position_new(3)
669 sll_real64,
intent( in ) :: xdot(3)
670 sll_real64,
intent( inout ) :: j_dofs(:)
672 sll_real64 :: xold(3), xnew(3), xnewtilde(3), xbox(3)
673 sll_int32 :: boxold(3), boxnew(3), sigma_counter(3), boxdiff(3), increment(3), box(3)
674 sll_real64 :: sigma_r, sigma_l, sigma, sigma_next(3), field_value(3), weight
675 sll_int32 :: j, q, bl, maxind, index_is
683 boxdiff = boxnew-boxold
684 xnewtilde = xnew + real(boxdiff,f64)
692 if (boxdiff(j) > 0 )
then
693 allocate ( sigmas(j)%vals(boxdiff(j)+1) )
694 do bl = 1, boxdiff(j)
695 sigmas(j)%vals(bl) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
697 sigmas(j)%vals(boxdiff(j)+1) = 1.0_f64
698 sigma_next(j) = sigmas(j)%vals(1)
700 elseif (boxdiff(j) < 0 )
then
701 allocate ( sigmas(j)%vals(-boxdiff(j)+1) )
702 do bl = boxdiff(j)+1, 0
703 sigmas(j)%vals(-bl+1) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
705 sigmas(j)%vals(-boxdiff(j)+1) = 1.0_f64
706 sigma_next(j) = sigmas(j)%vals(1)
709 sigma_next(j) = 1.0_f64
715 do while ( abs(sigma_r - 1.0_f64) > 1d-16 )
717 index_is = minloc(sigma_next, dim=1)
718 sigma_r = sigma_next(index_is)
720 do q = 1, self%n_quad_points_line
721 sigma = sigma_l + (sigma_r-sigma_l) * self%quad_xw_line(1,q)
722 xbox = xold* (1.0_f64 - sigma) + xnewtilde * sigma - real(sigma_counter*increment, f64)
723 if (maxval(xbox) > 1.0_f64 )
then
724 print*, xbox, sigma, sigma_counter, increment
725 print*, xold, xnewtilde, sigma_r, xnewtilde * sigma - real(sigma_counter*increment, f64)
726 sll_error(
'add_current_3d',
'box value too large')
727 elseif (minval(xbox) < 0.0_f64 )
then
728 print*, xbox, sigma, sigma_counter, increment
729 print*, xold, xnewtilde, sigma_r, xnewtilde * sigma - real(sigma_counter*increment, f64)
730 sll_error(
'add_current_3d',
'box value too low')
733 weight = self%quad_xw_line(2,q)*(sigma_r-sigma_l)
737 if (sigma_r < 1.0_f64 )
then
739 sigma_counter(index_is) = sigma_counter(index_is)+1
740 sigma_next(index_is) = sigmas(index_is)%vals(sigma_counter(index_is)+1)
741 box(index_is) = box(index_is) + increment(index_is)
750 sll_int32,
intent( in ) :: box_in(3)
751 sll_real64,
intent( in ) :: xbox(3)
752 sll_real64,
intent( in ) :: weight(3)
753 sll_real64,
intent( inout ) :: j_dofs(:)
755 sll_int32 :: i,j,k, index1d
756 sll_int32 :: box(3), index3d(3)
759 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j), xbox(j), &
760 self%spline_0(1:self%spline_degree(j)+1,j) )
761 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j)-1, xbox(j), &
762 self%spline_1(1:self%spline_degree(j),j) )
765 box = box_in-self%spline_degree
771 do k = 1, self%spline_degree(3)+1
772 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
773 do j = 1, self%spline_degree(2)+1
774 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
775 do i = 1, self%spline_degree(1)
776 index1d = index3d(2) + self%index1d(i,1)
778 j_dofs(index1d) = j_dofs(index1d) + &
779 weight(1) * self%spline_1(i,1) * &
780 self%spline_0(j,2) * self%spline_0(k,3)
789 do k = 1, self%spline_degree(3)+1
790 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
791 do j = 1, self%spline_degree(2)
792 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
793 do i = 1, self%spline_degree(1)+1
794 index1d = index3d(2) + self%index1d(i,1) + self%n_total
796 j_dofs(index1d) = j_dofs(index1d) + &
797 weight(2) * self%spline_0(i,1) * &
798 self%spline_1(j,2) * self%spline_0(k,3)
807 do k = 1, self%spline_degree(3)
808 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
809 do j = 1, self%spline_degree(2)+1
810 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
811 do i = 1, self%spline_degree(1)+1
812 index1d = index3d(2) + self%index1d(i,1) + 2*self%n_total
814 j_dofs(index1d) = j_dofs(index1d) + &
815 weight(3) * self%spline_0(i,1) * &
816 self%spline_0(j,2) * self%spline_1(k,3)
827 sll_real64,
intent(in) :: position_old(3)
828 sll_real64,
intent(in) :: position_new(3)
829 sll_real64,
intent(in) :: marker_charge
830 sll_real64,
intent(in) :: qoverm
831 sll_real64,
intent(in) :: bfield_dofs(self%n_total*3)
832 sll_real64,
intent(inout) :: vi(:)
833 sll_real64,
intent(inout) :: j_dofs(self%n_total)
836 sll_int32 :: box(3), boxnew(3), boxold(3), local_size(3)
838 sll_int32 :: index3d(3)
841 sll_real64 :: xnew(3), xold(3)
842 sll_int32 :: component
845 degree = self%spline_degree(component)
849 local_size = abs(boxnew-boxold)+degree
850 local_size(2) = self%spline_degree(2)+1
851 local_size(3) = self%spline_degree(3)+1
853 sll_assert_always( local_size(1) <= self%n_cells(1) )
862 if (position_old(1) < position_new(1) )
then
863 self%j1d(local_size(component)-degree+1:local_size(component)) = self%spline_1(1:degree,2)
864 self%j1d(1:local_size(component)-degree) = self%delta_x(1)
865 self%j1d(1:degree) = self%j1d(1:degree) - self%spline_1(1:degree,1)
867 self%j1d(1:local_size(component)-degree) = -self%delta_x(1)
868 self%j1d(local_size(component)-degree+1:local_size(component)) = -self%spline_1(1:degree,1)
869 self%j1d(1:degree) = self%j1d(1:degree) + self%spline_1(1:degree,2)
872 self%spline_0 = 0.0_f64
874 if (j .ne. component )
then
875 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j), xold(j), self%spline_0(1:self%spline_degree(j)+1,j) )
879 box = boxold-self%spline_degree
880 box(component) = min(boxnew(component), boxold(component))-degree+1
885 index3d(3) = self%index1d(k,3)
887 index3d(2) = self%index1d(j,2)
889 index3d(1) = self%index1d(i,1)
892 j_dofs(index1d) = j_dofs(index1d) + &
893 marker_charge * self%j1d( i ) * &
894 self%spline_0(j,2) * self%spline_0(k,3)
907 sll_real64,
intent(in) :: position_old(3)
908 sll_real64,
intent(in) :: position_new
909 sll_real64,
intent(in) :: marker_charge
910 sll_real64,
intent(in) :: qoverm
911 sll_real64,
intent(in) :: bfield_dofs(:)
912 sll_real64,
intent(inout) :: vi(3)
913 sll_real64,
intent(inout) :: j_dofs(:)
915 sll_int32 :: box(3), boxnew, boxold
917 sll_int32 :: index3d(3)
921 sll_real64 :: vt(2), vtt2, vtt3
922 sll_int32 :: start1, start2
923 sll_int32 :: component
924 sll_int32 :: startjk, stride
925 sll_real64 :: splinejk
926 sll_int32 :: local_size
930 start1 = 2*self%n_total
931 start2 = self%n_total
933 degree = self%spline_degree(component)
937 boxold = box(component)
940 local_size = abs(boxnew-boxold)+degree
942 sll_assert_always( local_size <= self%n_cells(1)+degree )
947 self%spline_pp1d_1(component)%poly_coeffs_fpa, xi(component), i) &
948 * self%delta_x(component)
950 self%spline_pp1d_1(component)%poly_coeffs_fpa, xnew, i) &
951 * self%delta_x(component)
955 if (position_old(component) .le. position_new )
then
956 self%j1d(local_size-degree+1:local_size) = self%spline_1(1:degree,2)
957 self%j1d(1:local_size-degree) = self%delta_x(component)
958 self%j1d(1:degree) = self%j1d(1:degree) - self%spline_1(1:degree,1)
960 self%j1d(1:local_size-degree) = -self%delta_x(component)
961 self%j1d(local_size-degree+1:local_size) = -self%spline_1(1:degree,1)
962 self%j1d(1:degree) = self%j1d(1:degree) + self%spline_1(1:degree,2)
968 self%spline_0 = 0.0_f64
969 self%spline_1 = 0.0_f64
971 if (j .ne. component )
then
978 box(2:3) = box(2:3) - self%spline_degree(2:3)
981 if (boxold<boxnew)
then
982 box(component) = boxold-degree+1
984 box(component) = boxnew-degree+1
989 do k = 1, self%spline_degree(3)+1
992 index3d(3) = self%index1d(k,3)
993 do j = 1, self%spline_degree(2)+1
994 index3d(2) = self%index1d(j,2)
996 startjk = 1 + (index3d(2)-1)*self%n_cells(1) + &
997 (index3d(3)-1)*self%n_cells(1)*self%n_cells(2)
998 splinejk = self%spline_0(j, 2) * self%spline_0(k,3) * marker_charge
1001 do i = 1, local_size
1002 index3d(1) = modulo(box(1)+i-2,self%n_cells(1))
1003 index1d = startjk+index3d(1)
1004 j_dofs(index1d) = j_dofs(index1d) + self%j1d(i) * &
1007 vt(1) = vt(1) + bfield_dofs(start1+index1d)*self%j1d(i)
1008 vt(2) = vt(2) + bfield_dofs(start2+index1d)*self%j1d(i)
1013 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 2)
1015 vtt3 = vtt3 - vt(2)*self%spline_0(j, 2)
1018 vi(2) = vi(2) - qoverm*vtt2*self%spline_0(k, 3)
1020 vi(3) = vi(3) - qoverm*vtt3*self%spline_1(k-1, 3)
1031 sll_real64,
intent(in) :: position_old(3)
1032 sll_real64,
intent(in) :: position_new
1033 sll_real64,
intent(in) :: marker_charge
1034 sll_real64,
intent(in) :: qoverm
1035 sll_real64,
intent(in) :: bfield_dofs(:)
1036 sll_real64,
intent(inout) :: vi(3)
1037 sll_real64,
intent(inout) :: j_dofs(:)
1039 sll_int32 :: box(3), boxnew, boxold
1041 sll_int32 :: index3d(3)
1042 sll_int32 :: index1d
1045 sll_real64 :: vt(2), vtt2, vtt3
1046 sll_int32 :: start1, start2
1047 sll_int32 :: component, local_size
1048 sll_int32 :: stride, startjk
1049 sll_real64 :: splineik
1053 start1 = 2*self%n_total
1055 stride = self%n_cells(1)
1056 degree = self%spline_degree(component)
1060 boxold = box(component)
1063 local_size = abs(boxnew-boxold)+degree
1065 sll_assert_always( local_size <= self%n_cells(2)+degree )
1070 self%spline_pp1d_1(component)%poly_coeffs_fpa, xi(component), i) &
1071 * self%delta_x(component)
1073 self%spline_pp1d_1(component)%poly_coeffs_fpa, xnew, i) &
1074 * self%delta_x(component)
1077 if (position_old(component) .le. position_new )
then
1078 self%j1d(local_size-degree+1:local_size) = self%spline_1(1:degree,2)
1079 self%j1d(1:local_size-degree) = self%delta_x(component)
1080 self%j1d(1:degree) = self%j1d(1:degree) - self%spline_1(1:degree,1)
1082 self%j1d(1:local_size-degree) = -self%delta_x(component)
1083 self%j1d(local_size-degree+1:local_size) = -self%spline_1(1:degree,1)
1084 self%j1d(1:degree) = self%j1d(1:degree) + self%spline_1(1:degree,2)
1090 self%spline_0 = 0.0_f64
1091 self%spline_1 = 0.0_f64
1093 if (j .ne. component )
then
1099 box(1) = box(1) - self%spline_degree(1)
1100 box(3) = box(3) - self%spline_degree(3)
1103 if (boxold<boxnew)
then
1104 box(component) = boxold-degree+1
1106 box(component) = boxnew-degree+1
1111 do k = 1, self%spline_degree(3)+1
1114 index3d(3) = self%index1d(k,3)
1115 do j = 1, self%spline_degree(1)+1
1116 index3d(1) = self%index1d(j,1)
1118 startjk = index3d(1) + &
1119 (index3d(3)-1)*self%n_cells(1)*self%n_cells(2)
1120 splineik = self%spline_0(j, 1) * self%spline_0(k,3) * marker_charge
1123 do i = 1, local_size
1124 index3d(2) = modulo(box(2)+i-2,self%n_cells(2))
1125 index1d = startjk+index3d(2)*stride
1126 j_dofs(index1d) = j_dofs(index1d) + self%j1d(i) * &
1129 vt(1) = vt(1) + bfield_dofs(start1+index1d)*self%j1d(i)
1130 vt(2) = vt(2) + bfield_dofs(start2+index1d)*self%j1d(i)
1134 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 1)
1136 vtt3 = vtt3 + vt(2)*self%spline_0(j, 1)
1139 vi(1) = vi(1) + qoverm*vtt2*self%spline_0(k, 3)
1141 vi(3) = vi(3) - qoverm*vtt3*self%spline_1(k-1, 3)
1153 sll_real64,
intent(in) :: position_old(3)
1154 sll_real64,
intent(in) :: position_new
1155 sll_real64,
intent(in) :: marker_charge
1156 sll_real64,
intent(in) :: qoverm
1157 sll_real64,
intent(in) :: bfield_dofs(:)
1158 sll_real64,
intent(inout) :: vi(3)
1159 sll_real64,
intent(inout) :: j_dofs(:)
1161 sll_int32 :: box(3), boxnew, boxold
1163 sll_int32 :: index3d(3)
1164 sll_int32 :: index1d
1167 sll_real64 :: vt(2), vtt2, vtt3
1168 sll_int32 :: start1, start2
1169 sll_int32 :: component
1170 sll_int32 :: stride, startjk
1171 sll_real64 :: splineij
1172 sll_int32 :: local_size
1176 start1 = self%n_total
1178 stride = self%n_cells(1)*self%n_cells(2)
1179 degree = self%spline_degree(component)
1183 boxold = box(component)
1186 local_size = abs(boxnew-boxold)+degree
1188 sll_assert_always( local_size <= self%n_cells(3)+degree )
1193 self%spline_pp1d_1(component)%poly_coeffs_fpa, xi(component), i) &
1194 * self%delta_x(component)
1196 self%spline_pp1d_1(component)%poly_coeffs_fpa, xnew, i) &
1197 * self%delta_x(component)
1200 if (position_old(component) .le. position_new )
then
1201 self%j1d(local_size-degree+1:local_size) = self%spline_1(1:degree,2)
1202 self%j1d(1:local_size-degree) = self%delta_x(component)
1203 self%j1d(1:degree) = self%j1d(1:degree) - self%spline_1(1:degree,1)
1205 self%j1d(1:local_size-degree) = -self%delta_x(component)
1206 self%j1d(local_size-degree+1:local_size) = -self%spline_1(1:degree,1)
1207 self%j1d(1:degree) = self%j1d(1:degree) + self%spline_1(1:degree,2)
1212 self%spline_0 = 0.0_f64
1213 self%spline_1 = 0.0_f64
1215 if (j .ne. component )
then
1221 box(1:2) = box(1:2) - self%spline_degree(1:2)
1224 if (boxold<boxnew)
then
1225 box(component) = boxold-degree+1
1227 box(component) = boxnew-degree+1
1233 do k = 1, self%spline_degree(2)+1
1236 index3d(2) = self%index1d(k,2)
1237 do j = 1, self%spline_degree(1)+1
1238 index3d(1) = self%index1d(j,1)
1240 startjk = index3d(1) + (index3d(2)-1)*self%n_cells(1)
1241 splineij = self%spline_0(j, 1) * self%spline_0(k,2) * marker_charge
1244 do i = 1, local_size
1245 index3d(3) = modulo(box(component)+i-2,self%n_cells(component))
1246 index1d = startjk + index3d(3)*stride
1247 j_dofs(index1d) = j_dofs(index1d) + self%j1d(i) * &
1250 vt(1) = vt(1) + bfield_dofs(start1+index1d)*self%j1d(i)
1251 vt(2) = vt(2) + bfield_dofs(start2+index1d)*self%j1d(i)
1255 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 1)
1257 vtt3 = vtt3 + vt(2)*self%spline_0(j, 1)
1261 vi(1) = vi(1) - qoverm*vtt2*self%spline_0(k, 2)
1263 vi(2) = vi(2) + qoverm*vtt3*self%spline_1(k-1, 2)
1273 sll_real64,
intent(in) :: position_old(3)
1274 sll_real64,
intent(in) :: position_new
1275 sll_real64,
intent(in) :: marker_charge
1276 sll_real64,
intent(in) :: qoverm
1277 sll_real64,
intent(in) :: bfield_dofs(:)
1278 sll_real64,
intent(inout) :: vi(3)
1279 sll_real64,
intent(inout) :: j_dofs(:)
1281 sll_int32 :: box(3), boxnew, boxold
1283 sll_int32 :: index3d(3)
1284 sll_int32 :: index1d
1287 sll_real64 :: vt(2), vtt2, vtt3
1288 sll_int32 :: start1, start2
1289 sll_int32 :: component, local_size
1290 sll_int32 :: startjk, stride
1291 sll_real64 :: splinejk
1295 start1 = 2*self%n_total
1296 start2 = self%n_total
1298 degree=self%spline_degree(component)
1301 boxold = box(component)
1304 self%spline_0 = 0.0_f64
1305 self%spline_1 = 0.0_f64
1307 if (j .ne. component )
then
1314 box(2:3) = box(2:3) - self%spline_degree(2:3)
1315 local_size = abs(boxnew-boxold)+degree
1318 if (boxold<boxnew)
then
1319 box(component) = boxold-degree+1
1321 box(component) = boxnew-degree+1
1326 do k = 1, self%spline_degree(3)+1
1329 index3d(3) = self%index1d(k,3)
1330 do j = 1, self%spline_degree(2)+1
1331 index3d(2) = self%index1d(j,2)
1333 startjk = 1 + (index3d(2)-1)*self%n_cells(1) + &
1334 (index3d(3)-1)*self%n_cells(1)*self%n_cells(2)
1335 splinejk = self%spline_0(j, 2) * self%spline_0(k,3)
1339 call add_current_1d(self, component, xi(component), boxold-1, xnew, boxnew-1, marker_charge, bfield_dofs, start1+startjk, start2+startjk, stride, vt, self%j1d)
1341 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 2)
1343 vtt3 = vtt3 + vt(2)*self%spline_0(j, 2)
1345 do i = 1, local_size
1346 index3d(1) = modulo(box(1)+i-2,self%n_cells(1))+1
1348 index1d = startjk+index3d(1)-1
1349 j_dofs(index1d) = j_dofs(index1d) + self%j1d(index3d(1)) * &
1353 vi(2) = vi(2) - qoverm*vtt2*self%spline_0(k, 3)
1355 vi(3) = vi(3) + qoverm*vtt3*self%spline_1(k-1, 3)
1366 sll_real64,
intent(in) :: position_old(3)
1367 sll_real64,
intent(in) :: position_new
1368 sll_real64,
intent(in) :: marker_charge
1369 sll_real64,
intent(in) :: qoverm
1370 sll_real64,
intent(in) :: bfield_dofs(:)
1371 sll_real64,
intent(inout) :: vi(3)
1372 sll_real64,
intent(inout) :: j_dofs(:)
1374 sll_int32 :: box(3), boxnew, boxold
1376 sll_int32 :: index3d(3)
1377 sll_int32 :: index1d
1380 sll_real64 :: vt(2), vtt2, vtt3
1381 sll_int32 :: start1, start2
1382 sll_int32 :: component, local_size
1383 sll_int32 :: stride, startjk
1384 sll_real64 :: splineik
1388 start1 = 2*self%n_total
1390 stride = self%n_cells(1)
1391 degree=self%spline_degree(component)
1395 boxold = box(component)
1399 self%spline_0 = 0.0_f64
1400 self%spline_1 = 0.0_f64
1402 if (j .ne. component )
then
1408 box(1) = box(1) - self%spline_degree(1)
1409 box(3) = box(3) - self%spline_degree(3)
1410 local_size = abs(boxnew-boxold)+degree
1413 if (boxold<boxnew)
then
1414 box(component) = boxold-degree+1
1416 box(component) = boxnew-degree+1
1422 do k = 1, self%spline_degree(3)+1
1425 index3d(3) = self%index1d(k,3)
1426 do j = 1, self%spline_degree(1)+1
1427 index3d(1) = self%index1d(j,1)
1429 startjk = index3d(1) + &
1430 (index3d(3)-1)*self%n_cells(1)*self%n_cells(2)
1431 splineik = self%spline_0(j, 1) * self%spline_0(k,3)
1435 call add_current_1d(self, component, xi(component), boxold-1, xnew, boxnew-1, marker_charge, bfield_dofs, start1+startjk, start2+startjk, stride, vt, self%j1d)
1438 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 1)
1440 vtt3 = vtt3 + vt(2)*self%spline_0(j, 1)
1442 do i = 1, local_size
1443 index3d(2) = modulo(box(2)+i-2,self%n_cells(2))+1
1444 index1d = startjk+(index3d(2)-1)*stride
1445 j_dofs(index1d) = j_dofs(index1d) + self%j1d(index3d(2)) * &
1450 vi(1) = vi(1) + qoverm*vtt2*self%spline_0(k, 3)
1452 vi(3) = vi(3) - qoverm*vtt3*self%spline_1(k-1, 3)
1463 sll_real64,
intent(in) :: position_old(3)
1464 sll_real64,
intent(in) :: position_new
1465 sll_real64,
intent(in) :: marker_charge
1466 sll_real64,
intent(in) :: qoverm
1467 sll_real64,
intent(in) :: bfield_dofs(:)
1468 sll_real64,
intent(inout) :: vi(3)
1469 sll_real64,
intent(inout) :: j_dofs(:)
1471 sll_int32 :: box(3), boxnew, boxold
1473 sll_int32 :: index3d(3)
1474 sll_int32 :: index1d
1477 sll_real64 :: vt(2), vtt2, vtt3
1478 sll_int32 :: start1, start2
1479 sll_int32 :: component, local_size
1480 sll_int32 :: stride, startjk
1481 sll_real64 :: splineij
1485 start1 = self%n_total
1487 stride = self%n_cells(1)*self%n_cells(2)
1488 degree=self%spline_degree(component)
1492 boxold = box(component)
1495 self%spline_0 = 0.0_f64
1496 self%spline_1 = 0.0_f64
1498 if (j .ne. component )
then
1504 box(1:2) = box(1:2) - self%spline_degree(1:2)
1505 local_size = abs(boxnew-boxold)+degree
1507 if (boxold<boxnew)
then
1508 box(component) = boxold-degree+1
1510 box(component) = boxnew-degree+1
1515 do k = 1, self%spline_degree(2)+1
1518 index3d(2) = self%index1d(k,2)
1519 do j = 1, self%spline_degree(1)+1
1520 index3d(1) = self%index1d(j,1)
1522 startjk = index3d(1) + (index3d(2)-1)*self%n_cells(1)
1523 splineij = self%spline_0(j, 1) * self%spline_0(k,2)
1527 call add_current_1d(self, component, xi(component), boxold-1, xnew, boxnew-1, marker_charge, bfield_dofs, start1+startjk, start2+startjk, stride, vt, self%j1d)
1529 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 1)
1531 vtt3 = vtt3 + vt(2)*self%spline_0(j, 1)
1533 do i = 1, local_size
1534 index3d(3) = modulo(box(component)+i-2,self%n_cells(component))+1
1535 index1d = startjk + (index3d(3)-1)*stride
1537 j_dofs(index1d) = j_dofs(index1d) + self%j1d(index3d(3)) * &
1541 vi(1) = vi(1) - qoverm*vtt2*self%spline_0(k, 2)
1543 vi(2) = vi(2) + qoverm*vtt3*self%spline_1(k-1, 2)
1551 subroutine add_current_1d (self, component, r_old, index_old, r_new, index_new, marker_charge, bfield_dofs, start1, start2, stride, vi, j_dofs)
1553 sll_int32,
intent(in) :: component
1554 sll_real64,
intent(in) :: r_old
1555 sll_int32,
intent(in) :: index_old
1556 sll_real64,
intent(in) :: r_new
1557 sll_int32,
intent(in) :: index_new
1560 sll_real64,
intent(in) :: marker_charge
1561 sll_real64,
intent(in) :: bfield_dofs(self%n_total*3)
1562 sll_int32,
intent(in) :: start1
1563 sll_int32,
intent(in) :: start2
1564 sll_int32,
intent(in) :: stride
1565 sll_real64,
intent(inout) :: vi(2)
1566 sll_real64,
intent(inout) :: j_dofs(self%n_total)
1570 if (index_old == index_new)
then
1571 if (r_old < r_new)
then
1572 call update_jv(self, component, r_old, r_new, index_old, marker_charge, &
1573 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1575 call update_jv(self, component, r_new, r_old, index_old, marker_charge, &
1576 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1578 elseif (index_old < index_new)
then
1579 call update_jv (self, component, r_old, 1.0_f64, index_old, marker_charge, &
1580 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1581 call update_jv (self, component, 0.0_f64, r_new, index_new, marker_charge, &
1582 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1583 do ind = index_old+1, index_new-1
1584 call update_jv (self, component, 0.0_f64, 1.0_f64, ind, marker_charge, &
1585 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1588 call update_jv (self, component, r_new, 1.0_f64, index_new, marker_charge, &
1589 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1590 call update_jv (self, component, 0.0_f64, r_old, index_old, marker_charge, &
1591 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1592 do ind = index_new+1, index_old-1
1593 call update_jv (self, component, 0.0_f64, 1.0_f64, ind, marker_charge, &
1594 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1604 subroutine update_jv(self, component, lower, upper, index, marker_charge, sign, bfield_dofs, start1, start2, stride, vi, j_dofs)
1606 sll_int32,
intent(in) :: component
1607 sll_real64,
intent(in) :: lower
1608 sll_real64,
intent(in) :: upper
1609 sll_int32,
intent(in) :: index
1610 sll_real64,
intent(in) :: marker_charge
1611 sll_real64,
intent(in) :: sign
1612 sll_real64,
intent(inout) :: vi(2)
1613 sll_real64,
intent(in) :: bfield_dofs(self%n_total*3)
1614 sll_int32,
intent(in) :: start1
1615 sll_int32,
intent(in) :: start2
1616 sll_int32,
intent(in) :: stride
1617 sll_real64,
intent(inout) :: j_dofs(self%n_total)
1619 sll_int32 :: ind, i_grid, i_mod, j
1620 sll_real64 :: c1, c2
1621 sll_int32 :: spline_degree
1622 sll_int32 :: n_cells
1624 self%spline_val(:,1) = 0._f64
1625 self%spline_val_more(:,1) = 0._f64
1627 n_cells = self%n_cells(component)
1628 spline_degree = self%spline_degree(component)-1
1630 c1 = 0.5_f64*(upper-lower)
1631 c2 = 0.5_f64*(upper+lower)
1633 call sll_s_uniform_bsplines_eval_basis(spline_degree, c1*self%quad_xw(1,1)+c2, &
1634 self%spline_val(1:spline_degree+1,1))
1635 self%spline_val(:,1) = self%spline_val(:,1) * (self%quad_xw(2,1)*c1)
1636 do j = 2, self%n_quad_points
1637 call sll_s_uniform_bsplines_eval_basis(spline_degree, c1*self%quad_xw(1,j)+c2, &
1638 self%spline_val_more(1:spline_degree+1,1))
1639 self%spline_val(:,1) = self%spline_val(:,1) + self%spline_val_more(:,1) * (self%quad_xw(2,j)*c1)
1641 self%spline_val(:,1) = self%spline_val(:,1) * (sign*self%delta_x(component))
1644 do i_grid = index - spline_degree , index
1645 i_mod = modulo(i_grid, n_cells )
1646 j_dofs(i_mod+1) = j_dofs(i_mod+1) + &
1647 (marker_charge*self%spline_val(ind,1))
1648 vi(1) = vi(1) + self%spline_val(ind,1)*bfield_dofs(i_mod*stride+start1)
1649 vi(2) = vi(2) + self%spline_val(ind,1)*bfield_dofs(i_mod*stride+start2)
1660 sll_int32,
intent(in) :: n_cells(3)
1661 sll_real64,
intent(in) :: domain(3,2)
1662 sll_int32,
intent(in) :: spline_degree(3)
1663 sll_int32,
optional,
intent(in) :: no_particles
1665 sll_int32 :: maxspan, j, maxind
1668 self%domain = domain
1669 self%n_cells = n_cells
1670 self%n_total = product(n_cells)
1671 self%delta_x = (self%domain(:,2)-self%domain(:,1))/real(n_cells, f64)
1672 self%rdelta_x = 1.0_f64/self%delta_x
1675 if(
present(no_particles) )
then
1676 self%no_particles = no_particles
1678 self%no_particles = 1
1682 self%spline_degree = spline_degree
1683 maxspan = maxval(spline_degree + 1)
1686 self%n_quad_points = (maxval(self%spline_degree)+2)/2
1687 allocate( self%quad_xw(2,self%n_quad_points) )
1692 self%n_quad_points_line = sum(self%spline_degree) -1
1693 self%n_quad_points_line = ceiling(real(self%n_quad_points_line+1, f64)*0.5_f64)
1697 allocate( self%quad_xw_line(2,self%n_quad_points_line) )
1701 self%quad_xw_line(1,:) = 0.5_f64*(self%quad_xw_line(1,:)+1.0_f64)
1702 self%quad_xw_line(2,:) = 0.5_f64*self%quad_xw_line(2,:)
1705 allocate( self%spline_val(maxspan,3) )
1706 allocate( self%spline_val_more(maxspan,3) )
1707 allocate( self%spline_0(maxspan,3) )
1708 allocate( self%spline_1(maxspan-1,3) )
1709 allocate( self%spline_0_deriv(maxspan,3) )
1710 allocate( self%spline_1_deriv(maxspan-1,3) )
1711 allocate( self%spline1_0(maxspan,3) )
1712 allocate( self%j1d( maxval(self%n_cells)+maxval(self%spline_degree) ))
1713 allocate( self%spline_2d(maxspan, maxspan) )
1714 allocate( self%spline1_2d(1:maxspan, 1:maxspan) )
1715 allocate( self%spline1_3d(1:maxspan, 1:maxspan, 1:maxspan) )
1716 allocate( self%spline2_3d(1:maxspan, 1:maxspan, 1:maxspan) )
1717 allocate( self%index1d(maxspan, 3) )
1735 deallocate( self%quad_xw)
1736 deallocate( self%spline_val)
1737 deallocate( self%spline_val_more)
1738 deallocate( self%spline_0)
1739 deallocate( self%spline_1)
1740 deallocate( self%j1d)
1741 deallocate( self%spline1_0 )
1742 deallocate( self%spline_2d )
1743 deallocate( self%spline1_2d )
1744 deallocate( self%spline1_3d )
1745 deallocate( self%spline2_3d )
1761 sll_real64,
intent( in ) :: position_old(self%dim)
1762 sll_real64,
intent( in ) :: position_new(self%dim)
1763 sll_real64,
intent( in ) :: vbar(3)
1764 sll_real64,
intent( in ) :: bfield_dofs(:)
1765 sll_real64,
intent( inout ) :: j_dofs(:)
1766 sll_real64,
intent( out ) :: bfield_val(3)
1768 sll_real64 :: xold(3), xnew(3), xnewtilde(3), xbox(3)
1769 sll_int32 :: boxold(3), boxnew(3), sigma_counter(3), boxdiff(3), increment(3), box(3)
1770 sll_real64 :: sigma_r, sigma_l, sigma, sigma_next(3), field_value(3), weight
1771 sll_int32 :: j, q, bl, maxind, index_is
1772 type(
vector) :: sigmas(3)
1778 boxdiff = boxnew-boxold
1779 xnewtilde = xnew + real(boxdiff,f64)
1787 bfield_val = 0.0_f64
1790 if (boxdiff(j) > 0 )
then
1791 allocate ( sigmas(j)%vals(boxdiff(j)+1) )
1793 sigmas(j)%vals(bl) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
1795 sigmas(j)%vals(boxdiff(j)+1) = 1.0_f64
1796 sigma_next(j) = sigmas(j)%vals(1)
1798 elseif (boxdiff(j) < 0 )
then
1799 allocate ( sigmas(j)%vals(-boxdiff(j)+1) )
1800 do bl=boxdiff(j)+1,0
1801 sigmas(j)%vals(-bl+1) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
1803 sigmas(j)%vals(-boxdiff(j)+1) = 1.0_f64
1804 sigma_next(j) = sigmas(j)%vals(1)
1807 sigma_next(j) = 1.0_f64
1813 do while ( sigma_r < 1.0_f64 )
1815 index_is = minloc(sigma_next, dim=1)
1816 sigma_r = sigma_next(index_is)
1818 do q = 1, self%n_quad_points_line
1819 sigma = sigma_l + (sigma_r-sigma_l) * self%quad_xw_line(1,q)
1820 xbox = xold* (1.0_f64 - sigma) + xnewtilde * sigma - real(sigma_counter*increment, f64)
1821 if (maxval(xbox)> 1.0_f64 )
then
1822 print*, xbox, sigma, sigma_counter, increment
1823 sll_error(
'add_current_evaluate',
'box value too large')
1824 elseif (minval(xbox)< 0.0_f64 )
then
1825 print*, xbox, sigma, sigma_counter, increment
1826 print*, xold, xnewtilde, sigma_r
1827 sll_error(
'add_current_evaluate',
'box value too low')
1830 weight = self%quad_xw_line(2,q)*(sigma_r-sigma_l)
1833 bfield_val = bfield_val + field_value * weight * sigma
1835 if (sigma_r < 1.0_f64 )
then
1837 sigma_counter(index_is) = sigma_counter(index_is)+1
1838 sigma_next(index_is) = sigmas(index_is)%vals(sigma_counter(index_is)+1)
1839 box(index_is) = box(index_is) + increment(index_is)
1850 sll_int32,
intent(in) :: box_in(3)
1851 sll_real64,
intent(in) :: xbox(3)
1852 sll_real64,
intent(in) :: field_dofs(:)
1853 sll_real64,
intent(in) :: weight(3)
1854 sll_real64,
intent(inout) :: j_dofs(:)
1855 sll_real64,
intent(out) :: field_value(3)
1859 sll_int32 :: i,j,k, index1d, n_total
1860 sll_int32 :: box(3), index3d(3)
1863 n_total = self%n_total
1864 field_value = 0.0_f64
1867 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j), xbox(j), &
1868 self%spline_0(1:self%spline_degree(j)+1,j) )
1869 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j)-1, xbox(j), &
1870 self%spline_1(1:self%spline_degree(j),j) )
1873 box = box_in-self%spline_degree
1881 do k=1,self%spline_degree(3)+1
1882 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
1883 do j=1,self%spline_degree(2)+1
1884 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
1885 do i=2,self%spline_degree(1)+1
1886 index1d = index3d(2) + self%index1d(i,1)
1888 spval = self%spline_1(i-1,1) * &
1889 self%spline_0(j,2) * self%spline_0(k,3)
1890 j_dofs(index1d) = j_dofs(index1d) + &
1896 do k=2,self%spline_degree(3)+1
1897 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
1898 do j=2,self%spline_degree(2)+1
1899 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
1900 do i=1,self%spline_degree(1)+1
1901 index1d = index3d(2) + self%index1d(i,1)
1902 spval = self%spline_0(i,1) * &
1903 self%spline_1(j-1,2) * self%spline_1(k-1,3)
1904 field_value(1) = field_value(1) + field_dofs(index1d) * spval
1909 do k=1,self%spline_degree(3)+1
1910 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
1911 do j=2,self%spline_degree(2)+1
1912 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
1913 do i=1,self%spline_degree(1)+1
1914 index1d = index3d(2) + self%index1d(i,1) + n_total
1916 spval = self%spline_0(i,1) * &
1917 self%spline_1(j-1,2) * self%spline_0(k,3)
1918 j_dofs(index1d) = j_dofs(index1d) + &
1920 field_value(2) = field_value(2) + field_dofs(index1d ) * spval
1925 do k=2,self%spline_degree(3)+1
1926 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
1927 do j=1,self%spline_degree(2)+1
1928 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
1929 do i=2,self%spline_degree(1)+1
1930 spval = self%spline_1(i-1,1) * &
1931 self%spline_0(j,2) * self%spline_1(k-1,3)
1932 field_value(2) = field_value(2) + field_dofs(index1d ) * spval
1940 do k=2,self%spline_degree(3) +1
1941 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
1942 do j=1,self%spline_degree(2)+1
1943 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
1944 do i=1,self%spline_degree(1)+1
1945 index1d = index3d(2) + self%index1d(i,1) + n_total
1946 spval = self%spline_0(i,1) * &
1947 self%spline_0(j,2) * self%spline_1(k-1,3)
1948 j_dofs(index1d) = j_dofs(index1d) + &
1954 do k=1,self%spline_degree(3)+1
1955 index3d(3) = (self%index1d(k,3)-1)*self%n_cells(1)*self%n_cells(2)
1956 do j=2,self%spline_degree(2)+1
1957 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_cells(1)
1958 do i=2,self%spline_degree(1)+1
1959 index1d = index3d(2) + self%index1d(i,1) + n_total
1960 spval = self%spline_1(i-1,1) * &
1961 self%spline_1(j-1,2) * self%spline_0(k,3)
1962 field_value(3) = field_value(3) + field_dofs(index1d ) * spval
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.
Particle mesh coupling for 3d with splines of arbitrary degree placed on a uniform tensor product mes...
subroutine add_charge_single_spline_pp_3d_feec(self, position, marker_charge, degree, rho_dofs)
Add charge of one particle.
subroutine add_current_3d(self, position_old, position_new, xdot, j_dofs)
Add current via line integral (when x changes along all three directions)
subroutine add_current_update_v_primitive_component3_spline_3d_feec(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle and update v (according to H_p3 part in Hamiltonian splitting),...
subroutine add_current_update_v_primitive_component1_spline_3d_feec(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 integrate_spline_3d(self, box_in, xbox, weight, j_dofs)
Helper function for add_current_3d, takes care of the per box computations.
subroutine init_spline_3d_feec(self, n_cells, domain, spline_degree, no_particles)
Constructor.
subroutine add_current_spline_3d_feec(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle.
subroutine evaluate_multiple_spline_3d_feec(self, position, components, field_dofs, field_value)
Evaluate several fields at position position.
subroutine convert_x_to_xbox(self, position, xi, box)
Identify the box in which the particle is located and its normalized position within the box.
subroutine add_charge_single_spline_3d_feec(self, position, marker_charge, degree, rho_dofs)
Add charge of one particle.
subroutine add_current_update_v_component2_spline_3d_feec(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle and update v (according to H_p2 part in Hamiltonian splitting),...
subroutine free_spline_3d_feec(self)
Destructor.
subroutine add_current_update_v_component3_spline_3d_feec(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle and update v (according to H_p3 part in Hamiltonian splitting),...
subroutine update_jv(self, component, lower, upper, index, marker_charge, sign, bfield_dofs, start1, start2, stride, vi, j_dofs)
Helper function for add_current_update_v.
subroutine add_current_update_v_primitive_component2_spline_3d_feec(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle and update v (according to H_p2 part in Hamiltonian splitting),...
subroutine add_current_evaluate_int(self, position_old, position_new, vbar, bfield_dofs, j_dofs, bfield_val)
Evaluates the integral int_{poisition_old}^{position_new} field(x) d x and the integrated current.
subroutine add_particle_mass_od_spline_3d_feec(self, position, marker_charge, degree1, degree2, particle_mass)
Add charge of one particle.
subroutine evaluate_field_single_spline_3d_feec(self, position, degree, field_dofs, field_value)
Evaluate field at at position position.
subroutine point_add_eval_subcyc(self, box_in, xbox, field_dofs, weight, j_dofs, field_value)
Helper function for add_current_evaluate_int, takes care of per cell computations.
subroutine add_particle_mass_spline_3d_feec(self, position, marker_charge, degree, particle_mass)
Add charge of one particle.
subroutine add_current_update_v_component1_spline_3d_feec(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 convert_x_to_xbox_1d(self, component, position, xi, box)
Identify the box in which the particle is located and its normalized position within the box (only al...
subroutine point_add_eval(self, box_in, xbox, field_dofs, weight, j_dofs, field_value)
Helper function for add_current_evaluate that takes care of the per-cell computations.
subroutine box_index(self, box, comp)
Sets the index of the splines that are involved in computations that concern splines from index box.
subroutine add_current_1d(self, component, r_old, index_old, r_new, index_new, marker_charge, bfield_dofs, start1, start2, stride, vi, j_dofs)
Add current for one particle and update v (according to H_p1 part in Hamiltonian splitting)
subroutine evaluate_field_single_spline_pp_3d_feec(self, position, degree, field_dofs_pp, field_value)
Evaluate field at at position position.
pure integer(kind=i32) function convert_index_3d_to_1d(index3d, n_cells)
Convert 3d index to 1d index (first dimension without stride)
subroutine, public sll_s_spline_pp_init_3d(self, degree, n_cells, boundary)
Initialize sll_t_spline_pp_3d object.
subroutine, public sll_s_spline_pp_horner_m_3d(self, val, degree, x)
Perform three times a 1d hornerschema on the poly_coeffs.
real(kind=f64) function, public sll_f_spline_pp_horner_3d(degree, pp_coeffs, x, indices, n_cells)
Perform a 3d hornerschema on the pp_coeffs at the indices.
subroutine, public sll_s_spline_pp_free_3d(self)
Destructor 3d.
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.
Particle mesh coupling in 3d based on (arbitrary degree) spline on a tensor product uniform mesh.
Evaluates the integral int_{poisition_old}^{position_new} field(x) d x and the integrated current.
arbitrary degree 1d spline
arbitrary degree 3d spline