9 #include "sll_assert.h"
10 #include "sll_memory.h"
11 #include "sll_errors.h"
12 #include "sll_working_precision.h"
18 sll_s_uniform_bsplines_eval_basis, &
19 sll_s_uniform_bsplines_eval_deriv
45 sll_real64 :: rdelta_x(3)
47 sll_int32 :: no_particles
48 sll_int32 :: n_quad_points
50 sll_real64,
allocatable :: spline_val(:,:)
51 sll_real64,
allocatable :: spline_0(:,:)
52 sll_real64,
allocatable :: spline1_0(:,:)
53 sll_real64,
allocatable :: spline_1(:,:)
54 sll_real64,
allocatable :: spline_2d(:,:)
55 sll_real64,
allocatable :: spline1_2d(:,:)
56 sll_real64,
allocatable :: spline1_3d(:,:,:)
57 sll_real64,
allocatable :: spline2_3d(:,:,:)
58 sll_real64,
allocatable :: spline_val_more(:,:)
59 sll_real64,
allocatable :: j1d(:)
61 sll_real64,
allocatable :: quad_xw(:,:)
63 sll_int32,
allocatable :: index1d(:,:)
69 sll_int32 :: n_quad_points_line
70 sll_real64,
allocatable :: quad_xw_line(:,:)
90 sll_real64,
allocatable :: vals(:)
100 sll_real64,
intent( in ) :: position(3)
101 sll_real64,
intent( in ) :: marker_charge
102 sll_int32,
intent( in ) :: degree(3)
103 sll_real64,
intent( inout ) :: rho_dofs(:)
107 sll_int32 :: index3d(3)
114 self%spline_val = 0.0_f64
115 if(degree(1)==self%spline_degree(1))
then
117 else if(degree(1)==self%spline_degree(1)-1)
then
122 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_val(1:degree(j)+1,j) )
125 box(2:3) = box(2:3)-degree(2:3)
128 do k = 1, degree(3)+1
129 index3d(3) = (self%index1d(k,3)-1)*(self%n_cells(1)+degree(1))*self%n_cells(2)
130 do j = 1, degree(2)+1
131 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_cells(1)+degree(1))
132 do i = 1, degree(1)+1
133 index1d = index3d(2) + box(1)+i-1
134 rho_dofs(index1d) = rho_dofs(index1d) + &
135 marker_charge * self%spline_val(i,1) *&
136 self%spline_val(j,2) * self%spline_val(k,3)
149 sll_real64,
intent( in ) :: position(3)
150 sll_real64,
intent( in ) :: marker_charge
151 sll_int32,
intent( in ) :: degree(3)
152 sll_real64,
intent( inout ) :: particle_mass(:,:)
156 sll_int32 :: index3d(3)
158 sll_int32 :: i,j,k, col1, col2, col3, ind
163 self%spline_val = 0.0_f64
164 if(degree(1)==self%spline_degree(1))
then
166 else if(degree(1)==self%spline_degree(1)-1)
then
171 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_val(1:degree(j)+1,j) )
175 do k = 1, degree(3)+1
176 do j = 1, degree(2)+1
177 do i = 1, degree(1)+1
178 self%spline1_3d(i,j,k) = self%spline_val(i,1)*self%spline_val(j,2)*self%spline_val( k, 3)
184 box(2:3) = box(2:3)-degree(2:3)
187 do k = 1, degree(3)+1
188 index3d(3) = (self%index1d(k,3)-1)*(self%n_cells(1)+degree(1))*self%n_cells(2)
189 do j = 1, degree(2)+1
190 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_cells(1)+degree(1))
191 do i = 1, degree(1)+1
192 index1d = index3d(2) + box(1)+i-1
193 ind = 1+(degree(1)+1-i)+(degree(2)+1-j)*(2*degree(1)+1)+ &
194 (degree(3)+1-k)*(2*degree(1)+1)*(2*degree(2)+1)
195 do col3 = 1, degree(3)+1
196 do col2 = 1, degree(2)+1
197 do col1 = 1, degree(1)+1
198 particle_mass(ind, index1d) = particle_mass( ind, index1d) +&
199 self%spline1_3d(i, j, k) * self%spline1_3d(col1, col2, col3)*&
205 ind = ind+degree(2) * (2*degree(1)+1)
218 sll_real64,
intent( in ) :: position(3)
219 sll_real64,
intent( in ) :: marker_charge
220 sll_int32,
intent( in ) :: degree1(3), degree2(3)
221 sll_real64,
intent( inout ) :: particle_mass(:,:)
225 sll_int32 :: index3d(3)
227 sll_int32 :: i,j,k, col1, col2, col3, ind
231 self%spline_0 = 0.0_f64
232 self%spline1_0 = 0.0_f64
234 if(degree1(1)==self%spline_degree(1))
then
236 else if(degree1(1)==self%spline_degree(1)-1)
then
240 if(degree2(1)==self%spline_degree(1))
then
242 else if(degree2(1)==self%spline_degree(1)-1)
then
247 call sll_s_uniform_bsplines_eval_basis( degree1(j), xi(j), self%spline_0(1:degree1(j)+1,j) )
248 call sll_s_uniform_bsplines_eval_basis( degree2(j), xi(j), self%spline1_0(1:degree2(j)+1,j) )
251 self%spline1_3d=0._f64
253 do k =1, degree1(3)+1
254 do j = 1, degree1(2)+1
255 do i = 1, degree1(1)+1
256 self%spline1_3d(i,j,k) = self%spline_0(i,1)*self%spline_0(j,2)*self%spline_0(k,3)
260 self%spline2_3d=0._f64
261 do k = 1, degree2(3)+1
262 do j = 1, degree2(2)+1
263 do i = 1, degree2(1)+1
264 self%spline2_3d(i,j,k) = self%spline1_0(i,1)*self%spline1_0(j,2)*self%spline1_0(k,3)
269 box(2:3) = box(2:3)-degree1(2:3)
272 do k = 1, degree1(3)+1
273 index3d(3) = (self%index1d(k,3)-1)*(self%n_cells(1)+degree1(1))*self%n_cells(2)
274 do j = 1, degree1(2)+1
275 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_cells(1)+degree1(1))
276 do i = 1, degree1(1)+1
277 index1d = index3d(2) + box(1)+i-1
278 ind = 1+(degree1(1)+1-i)+(degree1(2)+1-j)*(degree1(1)+degree2(1)+1)+ &
279 (degree1(3)+1-k)*(degree1(1)+degree2(1)+1)*(degree1(2)+degree2(2)+1)
280 do col3 = 1, degree2(3)+1
281 do col2 = 1, degree2(2)+1
282 do col1 = 1, degree2(1)+1
283 particle_mass( ind, index1d) = particle_mass( ind, index1d) +&
284 self%spline1_3d(i, j, k) * self%spline2_3d(col1, col2, col3)*&
290 ind = ind+degree1(2) * (degree1(1)+degree2(1)+1)
303 sll_real64,
intent( in ) :: position(3)
304 sll_int32 ,
intent( in ) :: degree(3)
305 sll_real64,
intent( in ) :: field_dofs(:)
306 sll_real64,
intent( out ) :: field_value
310 sll_int32 :: index3d(3)
316 self%spline_val = 0.0_f64
317 if(degree(1)==self%spline_degree(1))
then
319 else if(degree(1)==self%spline_degree(1)-1)
then
324 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_val(1:degree(j)+1,j) )
327 field_value = 0.0_f64
328 box(2:3) = box(2:3)-degree(2:3)
331 do k = 1, degree(3)+1
332 index3d(3) = (self%index1d(k,3)-1)*(self%n_cells(1)+degree(1))*self%n_cells(2)
333 do j = 1, degree(2)+1
334 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_cells(1)+degree(1))
335 do i = 1, degree(1)+1
336 index1d = index3d(2) + box(1)+i-1
337 field_value = field_value + field_dofs(index1d) * &
338 self%spline_val(i,1)*self%spline_val(j,2)*self%spline_val(k,3)
348 sll_real64,
intent( in ) :: position(3)
349 sll_int32,
intent(in) :: components(:)
350 sll_real64,
intent( in ) :: field_dofs(:,:)
351 sll_real64,
intent(out) :: field_value(:)
354 print*,
'evaluate_multiple_spline_cl_3d is not yet implemented'
363 sll_real64,
intent( in ) :: position_old(3)
364 sll_real64,
intent( in ) :: position_new(3)
365 sll_real64,
intent( in ) :: xdot(3)
366 sll_real64,
intent( in ) :: efield_dofs(:)
367 sll_real64,
intent( inout ) :: j_dofs(:)
368 sll_real64,
intent( out ) :: efield_val(3)
370 sll_real64 :: xold(3), xnew(3), xnewtilde(3), xbox(3)
371 sll_int32 :: boxold(3), boxnew(3), sigma_counter(3), boxdiff(3), increment(3), box(3)
372 sll_real64 :: sigma_r, sigma_l, sigma, sigma_next(3), field_value(3), weight
373 sll_int32 :: j, q, bl, maxind, index_is
380 boxdiff = boxnew-boxold
381 xnewtilde = xnew + real(boxdiff,f64)
391 if (boxdiff(j) > 0 )
then
392 allocate ( sigmas(j)%vals(boxdiff(j)+1) )
393 do bl = 1, boxdiff(j)
394 sigmas(j)%vals(bl) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
396 sigmas(j)%vals(boxdiff(j)+1) = 1.0_f64
397 sigma_next(j) = sigmas(j)%vals(1)
399 elseif (boxdiff(j) < 0 )
then
400 allocate ( sigmas(j)%vals(-boxdiff(j)+1) )
401 do bl = boxdiff(j)+1, 0
402 sigmas(j)%vals(-bl+1) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
404 sigmas(j)%vals(-boxdiff(j)+1) = 1.0_f64
405 sigma_next(j) = sigmas(j)%vals(1)
408 sigma_next(j) = 1.0_f64
414 do while ( sigma_r < 1.0_f64 )
416 index_is = minloc(sigma_next, dim=1)
417 sigma_r = sigma_next(index_is)
419 do q = 1, self%n_quad_points_line
420 sigma = sigma_l + (sigma_r-sigma_l) * self%quad_xw_line(1,q)
421 xbox = xold* (1.0_f64 - sigma) + xnewtilde * sigma - real(sigma_counter*increment, f64)
422 if (maxval(xbox) > 1.0_f64 )
then
423 print*,
'box error 1', xbox, sigma, sigma_counter, increment
424 xbox = min(xbox, 1._f64)
425 elseif (minval(xbox) < 0.0_f64 )
then
426 print*,
'box error 2', xbox, sigma, sigma_counter, increment
427 xbox = max(xbox, 0._f64)
430 weight = self%quad_xw_line(2,q)*(sigma_r-sigma_l)
432 call point_add_eval (self, box, xbox, efield_dofs, xdot*weight, j_dofs, field_value )
433 efield_val = efield_val + field_value * weight
435 if (sigma_r < 1.0_f64 )
then
437 sigma_counter(index_is) = sigma_counter(index_is)+1
438 sigma_next(index_is) = sigmas(index_is)%vals(sigma_counter(index_is)+1)
439 box(index_is) = box(index_is) + increment(index_is)
448 subroutine point_add_eval ( self, box_in, xbox, field_dofs, weight, j_dofs, field_value )
450 sll_int32,
intent(in) :: box_in(3)
451 sll_real64,
intent(in) :: xbox(3)
452 sll_real64,
intent(in) :: field_dofs(:)
453 sll_real64,
intent(in) :: weight(3)
454 sll_real64,
intent(inout) :: j_dofs(:)
455 sll_real64,
intent(out) :: field_value(3)
457 sll_int32 :: i,j,k, index1d
458 sll_int32 :: box(3), index3d(3), deg
461 field_value = 0.0_f64
463 deg=self%spline_degree(1)
466 deg=self%spline_degree(1)-1
470 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j), xbox(j), &
471 self%spline_0(1:self%spline_degree(j)+1,j) )
472 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j)-1, xbox(j), &
473 self%spline_1(1:self%spline_degree(j),j) )
477 box(2:3) = box_in(2:3)-self%spline_degree(2:3)
479 deg = self%spline_degree(1)-1
483 do k = 1, self%spline_degree(3)+1
484 index3d(3) = (self%index1d(k,3)-1)*(self%n_cells(1)+deg)*self%n_cells(2)
485 do j = 1, self%spline_degree(2)+1
486 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_cells(1)+deg)
487 do i = 1, self%spline_degree(1)
488 index1d = index3d(2) + box(1)+i-1
490 spval = self%spline_1(i,1) * &
491 self%spline_0(j,2) * self%spline_0(k,3)
492 field_value(1) = field_value(1) + field_dofs(index1d) * spval
493 j_dofs(index1d) = j_dofs(index1d) + &
500 deg = self%spline_degree(1)
502 do k = 1, self%spline_degree(3)+1
503 index3d(3) = (self%index1d(k,3)-1)*(self%n_cells(1)+deg)*self%n_cells(2)
504 do j = 1, self%spline_degree(2)
505 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_cells(1)+deg)
506 do i = 1, self%spline_degree(1)+1
507 index1d = index3d(2) + box(1)+i-1 + self%n_total1
509 spval = self%spline_0(i,1) * &
510 self%spline_1(j,2) * self%spline_0(k,3)
511 field_value(2) = field_value(2) + field_dofs(index1d ) * spval
512 j_dofs(index1d) = j_dofs(index1d) + &
522 do k = 1, self%spline_degree(3)
523 index3d(3) = (self%index1d(k,3)-1)*(self%n_cells(1)+deg)*self%n_cells(2)
524 do j = 1, self%spline_degree(2)+1
525 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_cells(1)+deg)
526 do i = 1, self%spline_degree(1)+1
527 index1d = index3d(2) + box(1)+i-1 + self%n_total1+self%n_total0
529 spval = self%spline_0(i,1) * &
530 self%spline_0(j,2) * self%spline_1(k,3)
531 field_value(3) = field_value(3) + field_dofs(index1d ) * spval
532 j_dofs(index1d) = j_dofs(index1d) + &
545 sll_real64,
intent( in ) :: position_old(3)
546 sll_real64,
intent( in ) :: position_new(3)
547 sll_real64,
intent( in ) :: xdot(3)
548 sll_real64,
intent( inout ) :: j_dofs(:)
550 sll_real64 :: xold(3), xnew(3), xnewtilde(3), xbox(3)
551 sll_int32 :: boxold(3), boxnew(3), sigma_counter(3), boxdiff(3), increment(3), box(3)
552 sll_real64 :: sigma_r, sigma_l, sigma, sigma_next(3), field_value(3), weight
553 sll_int32 :: j, q, bl, maxind, index_is
560 boxdiff = boxnew-boxold
561 xnewtilde = xnew + real(boxdiff,f64)
567 if (boxdiff(j) > 0 )
then
568 allocate ( sigmas(j)%vals(boxdiff(j)+1) )
569 do bl = 1, boxdiff(j)
570 sigmas(j)%vals(bl) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
572 sigmas(j)%vals(boxdiff(j)+1) = 1.0_f64
573 sigma_next(j) = sigmas(j)%vals(1)
575 elseif (boxdiff(j) < 0 )
then
576 allocate ( sigmas(j)%vals(-boxdiff(j)+1) )
577 do bl = boxdiff(j)+1, 0
578 sigmas(j)%vals(-bl+1) = (real(bl,f64) - xold(j))/(xnewtilde(j)-xold(j))
580 sigmas(j)%vals(-boxdiff(j)+1) = 1.0_f64
581 sigma_next(j) = sigmas(j)%vals(1)
584 sigma_next(j) = 1.0_f64
590 do while ( sigma_r < 1.0_f64 )
592 index_is = minloc(sigma_next, dim=1)
593 sigma_r = sigma_next(index_is)
595 do q = 1, self%n_quad_points_line
596 sigma = sigma_l + (sigma_r-sigma_l) * self%quad_xw_line(1,q)
597 xbox = xold* (1.0_f64 - sigma) + xnewtilde * sigma - real(sigma_counter*increment, f64)
598 if (maxval(xbox) > 1.0_f64 )
then
599 print*,
'box error1', xbox, sigma, sigma_counter, increment
600 xbox = min(xbox, 1._f64)
601 elseif (minval(xbox) < 0.0_f64 )
then
602 print*,
'box error2', xbox, sigma, sigma_counter, increment
603 xbox = max(xbox, 0._f64)
606 weight = self%quad_xw_line(2,q)*(sigma_r-sigma_l)
609 if (sigma_r < 1.0_f64 )
then
611 sigma_counter(index_is) = sigma_counter(index_is)+1
612 sigma_next(index_is) = sigmas(index_is)%vals(sigma_counter(index_is)+1)
613 box(index_is) = box(index_is) + increment(index_is)
623 sll_int32,
intent( in ) :: box_in(3)
624 sll_real64,
intent( in ) :: xbox(3)
625 sll_real64,
intent( in ) :: weight(3)
626 sll_real64,
intent( inout ) :: j_dofs(:)
628 sll_int32 :: i,j,k, index1d
629 sll_int32 :: box(3), index3d(3), deg
631 deg=self%spline_degree(1)
634 deg=self%spline_degree(1)-1
639 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j), xbox(j), &
640 self%spline_0(1:self%spline_degree(j)+1,j) )
641 call sll_s_uniform_bsplines_eval_basis( self%spline_degree(j)-1, xbox(j), &
642 self%spline_1(1:self%spline_degree(j),j) )
646 box(2:3) = box_in(2:3)-self%spline_degree(2:3)
650 do k = 1, self%spline_degree(3)+1
651 index3d(3) = (self%index1d(k,3)-1)*(self%n_dofs(1)-1)*self%n_cells(2)
652 do j = 1, self%spline_degree(2)+1
653 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*(self%n_dofs(1)-1)
654 do i = 1, self%spline_degree(1)
655 index1d = index3d(2) + box(1)+i-1
657 j_dofs(index1d) = j_dofs(index1d) + &
658 weight(1) * self%spline_1(i,1) * &
659 self%spline_0(j,2) * self%spline_0(k,3)
666 do k = 1, self%spline_degree(3)+1
667 index3d(3) = (self%index1d(k,3)-1)*self%n_dofs(1)*self%n_cells(2)
668 do j = 1, self%spline_degree(2)
669 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_dofs(1)
670 do i = 1, self%spline_degree(1)+1
671 index1d = index3d(2) + box(1)+i-1 + self%n_total1
673 j_dofs(index1d) = j_dofs(index1d) + &
674 weight(2) * self%spline_0(i,1) * &
675 self%spline_1(j,2) * self%spline_0(k,3)
684 do k = 1, self%spline_degree(3)
685 index3d(3) = (self%index1d(k,3)-1)*self%n_dofs(1)*self%n_cells(2)
686 do j = 1, self%spline_degree(2)+1
687 index3d(2) = index3d(3) + (self%index1d(j,2)-1)*self%n_dofs(1)
688 do i = 1, self%spline_degree(1)+1
689 index1d = index3d(2) + box(1)+i-1 + self%n_total1+self%n_total0
690 j_dofs(index1d) = j_dofs(index1d) + &
691 weight(3) * self%spline_0(i,1) * &
692 self%spline_0(j,2) * self%spline_1(k,3)
704 sll_real64,
intent(in) :: position_old(3)
705 sll_real64,
intent(in) :: position_new
706 sll_real64,
intent(in) :: marker_charge
707 sll_real64,
intent(in) :: qoverm
708 sll_real64,
intent(in) :: bfield_dofs(:)
709 sll_real64,
intent(inout) :: vi(3)
710 sll_real64,
intent(inout) :: j_dofs(:)
712 sll_int32 :: box(3), boxnew, boxold
714 sll_int32 :: index3d(3)
718 sll_real64 :: vt(2), vtt2, vtt3
719 sll_int32 :: start1, start2
720 sll_int32 :: local_size
721 sll_int32 :: startjk, stride(2)
722 sll_real64 :: splinejk
724 start1 = self%n_total0+self%n_total1
725 start2 = self%n_total0
733 self%spline_0 = 0.0_f64
734 self%spline_1 = 0.0_f64
735 call sll_s_spline_pp_horner_m_1d(self%spline_pp_0%spline2, self%spline_0(1:self%spline_degree(2)+1,2), self%spline_degree(2), xi(2))
736 call sll_s_spline_pp_horner_m_1d(self%spline_pp_1%spline2, self%spline_1(1:self%spline_degree(2),2), self%spline_degree(2)-1, xi(2))
738 call sll_s_spline_pp_horner_m_1d(self%spline_pp_0%spline3, self%spline_0(1:self%spline_degree(3)+1,3), self%spline_degree(3), xi(3))
739 call sll_s_spline_pp_horner_m_1d(self%spline_pp_1%spline3, self%spline_1(1:self%spline_degree(3),3), self%spline_degree(3)-1, xi(3))
741 box(2:3) = box(2:3) - self%spline_degree(2:3)
742 local_size = abs(boxnew-boxold)+self%spline_degree(1)
746 do k = 1, self%spline_degree(3)+1
749 index3d(3) = self%index1d(k,3)
750 do j = 1, self%spline_degree(2)+1
751 index3d(2) = self%index1d(j,2)
753 startjk = 1 + (index3d(2)-1)*(self%n_dofs(1)-1) + &
754 (index3d(3)-1)*(self%n_dofs(1)-1)*self%n_cells(2)
755 splinejk = self%spline_0(j, 2) * self%spline_0(k,3)
759 call add_current_1d(self, 1, xi(1), boxold, xnew, boxnew, marker_charge, bfield_dofs, start1+startjk, start2+startjk, stride, vt, self%j1d)
761 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 2)
763 vtt3 = vtt3 + vt(2)*self%spline_0(j, 2)
765 do i = 1, self%spline_degree(1)
766 index3d(1) = box(1)+i-1
767 index1d = startjk+index3d(1)-1
768 j_dofs(index1d) = j_dofs(index1d) + self%j1d(index3d(1)) * &
772 vi(2) = vi(2) - qoverm*vtt2*self%spline_0(k, 3)
774 vi(3) = vi(3) + qoverm*vtt3*self%spline_1(k-1, 3)
784 sll_real64,
intent(in) :: position_old(3)
785 sll_real64,
intent(in) :: position_new
786 sll_real64,
intent(in) :: marker_charge
787 sll_real64,
intent(in) :: qoverm
788 sll_real64,
intent(in) :: bfield_dofs(:)
789 sll_real64,
intent(inout) :: vi(3)
790 sll_real64,
intent(inout) :: j_dofs(:)
792 sll_int32 :: box(3), boxnew, boxold
794 sll_int32 :: index3d(3)
798 sll_real64 :: vt(2), vtt2, vtt3
799 sll_int32 :: start1, start2
800 sll_int32 :: local_size
801 sll_int32 :: stride(2), startjk0, startjk1
802 sll_real64 :: splineik
804 start1 = self%n_total0+self%n_total1
806 stride(1) = self%n_dofs(1)-1
807 stride(2) = self%n_dofs(1)
815 self%spline_0 = 0.0_f64
816 self%spline_1 = 0.0_f64
818 self%spline_degree(1), xi(1), box(1), &
819 self%spline_0(1:self%spline_degree(1)+1,1) )
821 self%spline_degree(1)-1, xi(1), box(1), &
822 self%spline_1(1:self%spline_degree(1),1) )
824 call sll_s_spline_pp_horner_m_1d(self%spline_pp_0%spline3, self%spline_0(1:self%spline_degree(3)+1,3), self%spline_degree(3), xi(3))
825 call sll_s_spline_pp_horner_m_1d(self%spline_pp_1%spline3, self%spline_1(1:self%spline_degree(3),3), self%spline_degree(3)-1, xi(3))
827 box(3) = box(3) - self%spline_degree(3)
828 local_size = abs(boxnew-boxold)+self%spline_degree(2)
830 if (boxold<boxnew)
then
831 box(2) = boxold-self%spline_degree(2)+1
833 box(2) = boxnew-self%spline_degree(2)+1
837 do k = 1, self%spline_degree(3)+1
840 index3d(3) = self%index1d(k,3)
841 do j = 1, self%spline_degree(1)+1
842 index3d(1) = box(1)+j-1
844 startjk0 = index3d(1) + &
845 (index3d(3)-1)*self%n_dofs(1)*self%n_cells(2)
846 startjk1 = index3d(1)-1 + &
847 (index3d(3)-1)*(self%n_dofs(1)-1)*self%n_cells(2)
848 splineik = self%spline_0(j, 1) * self%spline_0(k,3)
852 call add_current_1d(self, 2, xi(2), boxold-1, xnew, boxnew-1, marker_charge, bfield_dofs, start1+startjk1, start2+startjk0, stride, vt, self%j1d)
855 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 1)
857 vtt3 = vtt3 + vt(2)*self%spline_0(j, 1)
860 index3d(2) = modulo(box(2)+i-2,self%n_cells(2))+1
861 index1d = startjk0+(index3d(2)-1)*stride(2)
862 j_dofs(index1d) = j_dofs(index1d) + self%j1d(index3d(2)) * &
867 vi(1) = vi(1) + qoverm*vtt2*self%spline_0(k, 3)
869 vi(3) = vi(3) - qoverm*vtt3*self%spline_1(k-1, 3)
880 sll_real64,
intent(in) :: position_old(3)
881 sll_real64,
intent(in) :: position_new
882 sll_real64,
intent(in) :: marker_charge
883 sll_real64,
intent(in) :: qoverm
884 sll_real64,
intent(in) :: bfield_dofs(:)
885 sll_real64,
intent(inout) :: vi(3)
886 sll_real64,
intent(inout) :: j_dofs(:)
888 sll_int32 :: box(3), boxnew, boxold
890 sll_int32 :: index3d(3)
894 sll_real64 :: vt(2), vtt2, vtt3
895 sll_int32 :: start1, start2
896 sll_int32 :: local_size
897 sll_int32 :: stride(2), startjk0, startjk1
898 sll_real64 :: splineij
900 start1 = self%n_total0
902 stride(1) = (self%n_dofs(1)-1)*self%n_cells(2)
903 stride(2) = self%n_dofs(1)*self%n_cells(2)
910 self%spline_0 = 0.0_f64
911 self%spline_1 = 0.0_f64
913 self%spline_degree(1), xi(1), box(1), &
914 self%spline_0(1:self%spline_degree(1)+1,1) )
916 self%spline_degree(1)-1, xi(1), box(1), &
917 self%spline_1(1:self%spline_degree(1),1) )
919 call sll_s_spline_pp_horner_m_1d(self%spline_pp_0%spline2, self%spline_0(1:self%spline_degree(2)+1,2), self%spline_degree(2), xi(2))
920 call sll_s_spline_pp_horner_m_1d(self%spline_pp_1%spline2, self%spline_1(1:self%spline_degree(2),2), self%spline_degree(2)-1, xi(2))
922 box(2) = box(2) - self%spline_degree(2)
923 local_size = abs(boxnew-boxold)+self%spline_degree(3)
925 if (boxold<boxnew)
then
926 box(3) = boxold-self%spline_degree(3)+1
928 box(3) = boxnew-self%spline_degree(3)+1
932 do k = 1, self%spline_degree(2)+1
935 index3d(2) = self%index1d(k,2)
936 do j = 1, self%spline_degree(1)+1
937 index3d(1) = box(1)+j-1
939 startjk0 = index3d(1) + (index3d(2)-1)*self%n_dofs(1)
940 startjk1 = index3d(1)-1 + (index3d(2)-1)*(self%n_dofs(1)-1)
941 splineij = self%spline_0(j, 1) * self%spline_0(k,2)
945 call add_current_1d(self, 3, xi(3), boxold-1, xnew, boxnew-1, marker_charge, bfield_dofs, start1+startjk1, start2+startjk0, stride, vt, self%j1d)
947 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 1)
949 vtt3 = vtt3 + vt(2)*self%spline_0(j, 1)
952 index3d(3) = modulo(box(3)+i-2,self%n_cells(3))+1
953 index1d = startjk0 + (index3d(3)-1)*stride(2)
955 j_dofs(index1d) = j_dofs(index1d) + self%j1d(index3d(3)) * &
960 vi(1) = vi(1) - qoverm*vtt2*self%spline_0(k, 2)
962 vi(2) = vi(2) + qoverm*vtt3*self%spline_1(k-1, 2)
970 subroutine add_current_1d (self, component, r_old, index_old, r_new, index_new, marker_charge, bfield_dofs, start1, start2, stride, vi, j_dofs)
972 sll_int32,
intent(in) :: component
973 sll_real64,
intent(in) :: r_old
974 sll_int32,
intent(in) :: index_old
975 sll_real64,
intent(in) :: r_new
976 sll_int32,
intent(in) :: index_new
977 sll_real64,
intent(in) :: marker_charge
978 sll_real64,
intent(in) :: bfield_dofs(self%n_total0+self%n_total1*2)
979 sll_int32,
intent(in) :: start1
980 sll_int32,
intent(in) :: start2
981 sll_int32,
intent(in) :: stride(2)
982 sll_real64,
intent(inout) :: vi(2)
983 sll_real64,
intent(inout) :: j_dofs(:)
987 if (index_old == index_new)
then
988 if (r_old < r_new)
then
989 call update_jv(self, component, r_old, r_new, index_old, marker_charge, &
990 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
992 call update_jv(self, component, r_new, r_old, index_old, marker_charge, &
993 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
995 elseif (index_old < index_new)
then
996 call update_jv (self, component, r_old, 1.0_f64, index_old, marker_charge, &
997 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
998 call update_jv (self, component, 0.0_f64, r_new, index_new, marker_charge, &
999 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1000 do ind = index_old+1, index_new-1
1001 call update_jv (self, component, 0.0_f64, 1.0_f64, ind, marker_charge, &
1002 1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1005 call update_jv (self, component, r_new, 1.0_f64, index_new, marker_charge, &
1006 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1007 call update_jv (self, component, 0.0_f64, r_old, index_old, marker_charge, &
1008 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1009 do ind = index_new+1, index_old-1
1010 call update_jv (self, component, 0.0_f64, 1.0_f64, ind, marker_charge, &
1011 -1.0_f64, bfield_dofs, start1, start2, stride, vi, j_dofs)
1020 subroutine update_jv(self, component, lower, upper, index, marker_charge, sign, bfield_dofs, start1, start2, stride, vi, j_dofs)
1022 sll_int32,
intent(in) :: component
1023 sll_real64,
intent(in) :: lower
1024 sll_real64,
intent(in) :: upper
1025 sll_int32,
intent(in) :: index
1026 sll_real64,
intent(in) :: marker_charge
1027 sll_real64,
intent(in) :: sign
1028 sll_real64,
intent(inout) :: vi(2)
1029 sll_real64,
intent(in) :: bfield_dofs(self%n_total0+self%n_total1*2)
1030 sll_int32,
intent(in) :: start1
1031 sll_int32,
intent(in) :: start2
1032 sll_int32,
intent(in) :: stride(2)
1033 sll_real64,
intent(inout) :: j_dofs(:)
1035 sll_int32 :: ind, i_grid, i_mod, j
1036 sll_real64 :: c1, c2
1037 sll_int32 :: spline_degree
1038 sll_int32 :: n_cells
1040 self%spline_val(:,1) = 0._f64
1041 self%spline_val_more(:,1) = 0._f64
1043 n_cells = self%n_cells(component)
1044 spline_degree = self%spline_degree(component)-1
1046 c1 = 0.5_f64*(upper-lower)
1047 c2 = 0.5_f64*(upper+lower)
1049 if( component == 1 )
then
1051 spline_degree, c1*self%quad_xw(1,1)+c2, index, &
1052 self%spline_val(1:spline_degree+1,1) )
1053 self%spline_val(:,1) = self%spline_val(:,1) * (self%quad_xw(2,1)*c1)
1054 do j=2,self%n_quad_points
1056 spline_degree, c1*self%quad_xw(1,j)+c2, index, &
1057 self%spline_val_more(1:spline_degree+1,1))
1058 self%spline_val(:,1) = self%spline_val(:,1) + self%spline_val_more(:,1) * (self%quad_xw(2,j)*c1)
1060 self%spline_val(:,1) = self%spline_val(:,1) * (sign*self%delta_x(component))
1063 do i_grid = index-1, index-1+spline_degree
1064 j_dofs(i_grid+1) = j_dofs(i_grid+1) + &
1065 (marker_charge*self%spline_val(ind,1))
1066 vi(1) = vi(1) + self%spline_val(ind,1)*bfield_dofs(i_grid*stride(1)+start1)
1067 vi(2) = vi(2) + self%spline_val(ind,1)*bfield_dofs(i_grid*stride(2)+start2)
1072 call sll_s_uniform_bsplines_eval_basis(spline_degree, c1*self%quad_xw(1,1)+c2, &
1073 self%spline_val(1:spline_degree,1))
1074 self%spline_val(:,1) = self%spline_val(:,1) * (self%quad_xw(2,1)*c1)
1075 do j=2,self%n_quad_points
1076 call sll_s_uniform_bsplines_eval_basis(spline_degree, c1*self%quad_xw(1,j)+c2, &
1077 self%spline_val_more(1:spline_degree,1))
1078 self%spline_val(:,1) = self%spline_val(:,1) + self%spline_val_more(:,1) * (self%quad_xw(2,j)*c1)
1080 self%spline_val(:,1) = self%spline_val(:,1) * (sign*self%delta_x(component))
1083 do i_grid = index - spline_degree, index
1084 i_mod = modulo(i_grid, n_cells )
1085 j_dofs(i_mod+1) = j_dofs(i_mod+1) + &
1086 (marker_charge*self%spline_val(ind,1))
1087 vi(1) = vi(1) + self%spline_val(ind,1)*bfield_dofs(i_mod*stride(1)+start1)
1088 vi(2) = vi(2) + self%spline_val(ind,1)*bfield_dofs(i_mod*stride(2)+start2)
1097 sll_int32,
intent( in ) :: index3d(3)
1098 sll_int32,
intent( in ) :: n_cells(3)
1100 sll_int32 :: index1d
1102 index1d = index3d(1) + (index3d(2)-1)*(n_cells(1)+degree) + (index3d(3)-1)*(n_cells(1)+degree)*n_cells(2)
1109 sll_real64,
intent( in ) :: position(3)
1110 sll_real64,
intent( out ) :: xi(3)
1111 sll_int32,
intent( out ) :: box(3)
1113 xi = (position - self%domain(:,1)) * self%rdelta_x
1114 box = floor( xi ) + 1
1115 xi = xi - real(box-1, f64)
1117 if( box(1) == self%n_cells(1) + 1 )
then
1118 if( xi(1) == 0._f64)
then
1120 box(1) = self%n_cells(1)
1122 print*,
'box,x, xbox', box, position(1), xi(1)
1123 sll_error(
'convert_x_to_xbox',
'box1 value to high' )
1125 else if( box(1) > self%n_cells(1) + 1 )
then
1126 print*,
'box,x, xbox', box, position(1), xi(1)
1127 sll_error(
'convert_x_to_xbox',
'box1 value to high' )
1128 else if( box(1) <= 0 )
then
1129 print*,
'box,x, xbox', box, position(1), xi(1)
1130 sll_error(
'convert_x_to_xbox',
'box1 value to low' )
1138 sll_int32,
intent( in ) :: component
1139 sll_real64,
intent( in ) :: position
1140 sll_real64,
intent( out ) :: xi
1141 sll_int32,
intent( out ) :: box
1143 xi = (position - self%domain(component,1))/self%delta_x(component)
1144 box = floor( xi ) + 1
1145 xi = xi - real(box-1, f64)
1147 if( component ==1 .and. box == self%n_cells(1) + 1 )
then
1148 if( xi == 0._f64)
then
1150 box = self%n_cells(1)
1152 print*,
'box,x, xbox', box, position, xi
1153 sll_error(
'convert_x_to_xbox',
'box1 value to high' )
1162 sll_int32,
intent(in) :: box
1163 sll_int32,
intent(in) :: comp
1167 do j = 1, self%spline_degree(comp)+1
1168 self%index1d(j,comp) = modulo(box+j-2,self%n_cells(comp))+1
1176 sll_int32,
intent( in ) :: n_cells
1177 sll_int32,
intent( in ) :: degree
1178 sll_real64,
intent( in ) :: xi
1179 sll_int32,
intent( in ) :: box
1180 sll_real64,
intent( out ) :: spline_val(:)
1184 if(box >= 1 .and. box <= degree-1)
then
1188 else if (box >= degree .and. box <= n_cells-degree+1)
then
1189 call sll_s_uniform_bsplines_eval_basis( degree, xi, spline_val )
1190 else if(box >= n_cells-degree+2 .and. box <= n_cells)
then
1195 print*,
'box, xbox', box, xi
1196 sll_error(
"uniform_bsplines_eval_basis_clamped",
"box out of range" )
1205 sll_int32,
intent(in) :: n_cells(3)
1206 sll_real64,
intent(in) :: domain(3,2)
1207 sll_int32,
intent(in) :: spline_degree(3)
1208 sll_int32,
intent(in) :: boundary(3)
1209 sll_int32,
optional,
intent(in) :: no_particles
1211 sll_int32 :: maxspan, j, maxind
1215 self%domain = domain
1216 self%n_cells = n_cells
1217 self%n_dofs = n_cells + spline_degree
1218 self%n_total = product(n_cells)
1219 self%n_total0 = (n_cells(1)+spline_degree(1))*n_cells(2)*n_cells(3)
1220 self%n_total1 = (n_cells(1)+spline_degree(1)-1)*n_cells(2)*n_cells(3)
1221 self%delta_x = (self%domain(:,2)-self%domain(:,1))/real(n_cells, f64)
1222 self%rdelta_x = 1.0_f64/self%delta_x
1225 if(
present(no_particles) )
then
1226 self%no_particles = no_particles
1228 self%no_particles = 1
1232 self%spline_degree = spline_degree
1233 maxspan = maxval(spline_degree + 1)
1235 self%n_quad_points = (maxval(self%spline_degree)+2)/2
1236 allocate( self%quad_xw(2,self%n_quad_points) )
1241 self%n_quad_points_line = ceiling(real(sum(self%spline_degree), f64)*0.5_f64)
1242 allocate( self%quad_xw_line(2,self%n_quad_points_line) )
1246 self%quad_xw_line(1,:) = 0.5_f64*(self%quad_xw_line(1,:)+1.0_f64)
1247 self%quad_xw_line(2,:) = 0.5_f64*self%quad_xw_line(2,:)
1249 allocate( self%spline_val(maxspan,3) )
1250 allocate( self%spline_0(maxspan,3) )
1251 allocate( self%spline1_0(maxspan,3) )
1252 allocate( self%spline_1(maxspan,3) )
1253 allocate( self%spline_2d(maxspan, maxspan) )
1254 allocate( self%spline1_2d(1:maxspan, 1:maxspan) )
1255 allocate( self%spline1_3d(1:maxspan, 1:maxspan, 1:maxspan) )
1256 allocate( self%spline2_3d(1:maxspan, 1:maxspan, 1:maxspan) )
1257 allocate( self%index1d(maxspan, 3) )
1259 allocate( self%spline_val_more(maxspan,3) )
1260 allocate( self%j1d( maxval(self%n_dofs)+maxval(self%spline_degree) ))
1272 deallocate( self%spline_val)
1273 deallocate( self%spline_0)
1274 deallocate( self%spline1_0 )
1275 deallocate( self%spline_1 )
1276 deallocate( self%spline_2d )
1277 deallocate( self%spline1_2d )
1278 deallocate( self%spline1_3d )
1279 deallocate( self%spline2_3d )
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_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_p1 part in Hamiltonian splitting)
subroutine add_particle_mass_od_spline_cl_3d_feec(self, position, marker_charge, degree1, degree2, particle_mass)
Add the contribution of one particle to the off-diagonal parts of the approximate mass matrix.
subroutine convert_x_to_xbox(self, position, xi, box)
subroutine point_add_eval(self, box_in, xbox, field_dofs, weight, j_dofs, field_value)
Helper function for add_current_evaluate.
subroutine box_index(self, box, comp)
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 evaluate_multiple_spline_cl_3d_feec(self, position, components, field_dofs, field_value)
Evaluate several fields at position position.
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 init_spline_cl_3d_feec(self, n_cells, domain, spline_degree, boundary, no_particles)
Initializer.
integer(kind=i32) function convert_index_3d_to_1d(index3d, n_cells, degree)
subroutine add_current_1d(self, component, r_old, index_old, r_new, index_new, marker_charge, bfield_dofs, start1, start2, stride, vi, j_dofs)
Helper function for add_current_update_v.
subroutine, public 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_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_p1 part in Hamiltonian splitting)
subroutine add_charge_single_spline_cl_3d_feec(self, position, marker_charge, degree, rho_dofs)
Add charge of one particle.
subroutine integrate_spline_cl_3d(self, box_in, xbox, weight, j_dofs)
Helper function for add_current.
subroutine convert_x_to_xbox_1d(self, component, position, xi, box)
subroutine add_current_cl_3d(self, position_old, position_new, xdot, j_dofs)
Add current with integration over x.
subroutine evaluate_field_single_spline_cl_3d_feec(self, position, degree, field_dofs, field_value)
Evaluate field at at position position.
subroutine free_spline_cl_3d_feec(self)
Finalizer.
subroutine add_particle_mass_spline_cl_3d_feec(self, position, marker_charge, degree, particle_mass)
Add the contribution of one particle to the diagonal parts fo the approximate mass matrix.
subroutine, public sll_s_spline_pp_init_3d(self, degree, n_cells, boundary)
Initialize sll_t_spline_pp_3d object.
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_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.
arbitrary degree 1d spline
arbitrary degree 3d spline