9 #include "sll_assert.h"
10 #include "sll_memory.h"
11 #include "sll_working_precision.h"
14 sll_s_uniform_bsplines_eval_basis
45 sll_real64 :: delta_x(2)
46 sll_real64 :: domain(2,2)
47 sll_real64 :: rdelta_x(2)
50 sll_int32 :: no_particles
53 sll_int32 :: spline_degree
55 sll_int32 :: n_quad_points
57 sll_real64,
allocatable :: spline_val(:,:)
58 sll_real64,
allocatable :: spline_0(:,:)
59 sll_real64,
allocatable :: spline_1(:,:)
60 sll_real64,
allocatable :: spline_val_more(:,:)
61 sll_real64,
allocatable :: spline_2d(:,:)
62 sll_real64,
allocatable :: j1d(:)
63 sll_real64,
allocatable :: quad_xw(:,:)
68 sll_int32 :: n_grid(2)
98 sll_real64,
intent( in ) :: position(self%dim)
99 sll_real64,
intent( in ) :: marker_charge
100 sll_int32,
intent( in ) :: degree(2)
101 sll_real64,
intent( inout ) :: rho_dofs(self%n_dofs)
105 sll_int32 :: index2d(2)
112 self%spline_0 = 0.0_f64
114 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_0(:,j) )
118 self%spline_0(:,1) = self%spline_0(:,1)*marker_charge
122 index2d(2) = modulo(box(2)+j-2,self%n_grid(2))+1
124 index2d(1) = modulo(box(1)+i-2,self%n_grid(1))+1
126 rho_dofs(index1d) = rho_dofs(index1d) + &
127 (self%spline_0(i,1) * self%spline_0(j,2))
137 sll_real64,
intent( in ) :: position(self%dim)
138 sll_real64,
intent( in ) :: marker_charge
139 sll_int32,
intent( in ) :: degree(2)
140 sll_real64,
intent( inout ) :: particle_mass(:,:)
144 sll_int32 :: index2d(2)
146 sll_int32 :: i,j, col1, col2, ind
147 sll_real64 :: splineijk
154 self%spline_0 = 0.0_f64
156 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_0(:,j) )
162 self%spline_2d(i,j) = self%spline_0(i,1)*self%spline_0(j,2)
170 index2d(2) = modulo(box(2)+j-2,self%n_grid(2))+1
172 index2d(1) = modulo(box(1)+i-2,self%n_grid(1))+1
174 ind = 1+(degree(1)+1-i)+(degree(2)+1-j)*(2*degree(1)+1)
175 splineijk = marker_charge * self%spline_2d(i,j)
176 do col2 = 1,degree(2)+1
177 do col1 = 1,degree(1)+1
178 particle_mass(ind, index1d) = &
179 particle_mass( ind, index1d) + &
181 self%spline_2d(col1,col2)
186 ind = ind+( degree(2) ) * (2*degree(1)+1)
256 sll_int32,
intent( in ) :: index2d(2)
257 sll_int32,
intent( in ) :: n_grid(2)
260 index1d = index2d(1) + (index2d(2)-1)*n_grid(1)
267 sll_real64,
intent( in ) :: position(self%dim)
268 sll_real64,
intent( out ) :: xi(self%dim)
269 sll_int32,
intent( out ) :: box(self%dim)
271 xi = (position - self%domain(:,1)) * self%rdelta_x
273 xi = xi - real(box-1, f64)
282 sll_real64,
intent(in) :: position_old(self%dim)
283 sll_real64,
intent(in) :: position_new(self%dim)
284 sll_real64,
intent(in) :: marker_charge
285 sll_real64,
intent(in) :: qoverm
286 sll_real64,
intent(in) :: bfield_dofs(self%n_dofs*3)
287 sll_real64,
intent(inout) :: vi(:)
288 sll_real64,
intent(inout) :: j_dofs(self%n_dofs)
291 sll_int32 :: box(2), boxnew(2), boxold(2), local_size(2)
293 sll_int32 :: index2d(2)
296 sll_real64 :: xnew(2), xold(2)
297 sll_int32 :: component
299 degree = self%spline_degree
305 local_size = abs(boxnew-boxold)+degree
306 local_size(2) = degree+1
315 if (position_old(1) < position_new(1) )
then
316 self%j1d(local_size(component)-degree+1:local_size(component)) = self%spline_1(:,2)
317 self%j1d(1:local_size(component)-degree) = self%delta_x(1)
318 self%j1d(1:degree) = self%j1d(1:degree) - self%spline_1(:,1)
320 self%j1d(1:local_size(component)-degree) = -self%delta_x(1)
321 self%j1d(local_size(component)-degree+1:local_size(component)) = -self%spline_1(:,1)
322 self%j1d(1:degree) = self%j1d(1:degree) + self%spline_1(:,2)
325 self%spline_0 = 0.0_f64
327 if (j .ne. component )
then
328 call sll_s_uniform_bsplines_eval_basis( self%spline_degree, xold(j), self%spline_0(:,j) )
333 box(component) = min(boxnew(component), boxold(component))-degree+1
335 index2d(2) = modulo(box(2)+j-2,self%n_grid(2))+1
337 index2d(1) = modulo(box(1)+i-2,self%n_grid(1))+1
339 j_dofs(index1d) = j_dofs(index1d) + &
340 marker_charge * self%j1d( i ) * &
354 sll_real64,
intent(in) :: position_old(self%dim)
355 sll_real64,
intent(in) :: position_new
356 sll_real64,
intent(in) :: marker_charge
357 sll_real64,
intent(in) :: qoverm
358 sll_real64,
intent(in) :: bfield_dofs(self%n_dofs*3)
359 sll_real64,
intent(inout) :: vi(:)
360 sll_real64,
intent(inout) :: j_dofs(self%n_dofs)
363 sll_int32 :: box(2), boxnew, boxold
365 sll_int32 :: index2d(2)
369 sll_real64 :: vt(2), vtt2, vtt3
370 sll_int32 :: start1, start2
371 sll_int32 :: component
373 sll_int32 :: local_size
377 start1 = 2*self%n_dofs
380 degree = self%spline_degree
385 xnew = (position_new-self%domain(component,1)) * self%rdelta_x(component)
386 boxnew = ceiling(xnew)
387 xnew = xnew-real(boxnew-1, f64)
388 boxold = box(component)
391 local_size = abs(boxnew-boxold)+degree
396 self%spline_pp1d_1%poly_coeffs_fpa, xi(component), i) &
397 * self%delta_x(component)
399 self%spline_pp1d_1%poly_coeffs_fpa, xnew, i) &
400 * self%delta_x(component)
407 if (position_old(component) .le. position_new )
then
408 self%j1d(local_size-degree+1:local_size) = self%spline_1(:,2)
409 self%j1d(1:local_size-degree) = self%delta_x(component)
410 self%j1d(1:degree) = self%j1d(1:degree) - self%spline_1(:,1)
412 self%j1d(1:local_size-degree) = -self%delta_x(component)
413 self%j1d(local_size-degree+1:local_size) = -self%spline_1(:,1)
414 self%j1d(1:degree) = self%j1d(1:degree) + self%spline_1(:,2)
420 self%spline_0 = 0.0_f64
421 self%spline_1 = 0.0_f64
423 if (j .ne. component )
then
429 box(component) = box(component)-self%spline_degree+1
430 box(2) = box(2) - self%spline_degree
433 if (boxold<boxnew)
then
434 box(component) = boxold-self%spline_degree+1
436 box(component) = boxnew-self%spline_degree+1
442 do j=1,self%spline_degree+1
443 index2d(2) = modulo(box(2)+j-2,self%n_grid(2))+1
448 index2d(1) = modulo(box(1)+i-2,self%n_grid(1))+1
450 j_dofs(index1d) = j_dofs(index1d) + self%j1d(i) * &
451 self%spline_0(j,2)*marker_charge
453 vt(1) = vt(1) + bfield_dofs(start1+index1d)*self%j1d(i)
454 vt(2) = vt(2) + bfield_dofs(start2+index1d)*self%j1d(i)
459 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 2)
461 vtt3 = vtt3 - vt(2)*self%spline_0(j, 2)
464 vi(2) = vi(2) - qoverm*vtt2
465 vi(3) = vi(3) - qoverm*vtt3
471 sll_real64,
intent(in) :: position_old(self%dim)
472 sll_real64,
intent(in) :: position_new
473 sll_real64,
intent(in) :: marker_charge
474 sll_real64,
intent(in) :: qoverm
475 sll_real64,
intent(in) :: bfield_dofs(self%n_dofs*3)
476 sll_real64,
intent(inout) :: vi(:)
477 sll_real64,
intent(inout) :: j_dofs(self%n_dofs)
481 sll_int32 :: box(2), boxnew, boxold
483 sll_int32 :: index2d(2)
487 sll_real64 :: vt(2), vtt2, vtt3
488 sll_int32 :: start1, start2
489 sll_int32 :: component, local_size
494 start1 = 2*self%n_dofs
496 stride = self%n_grid(1)
497 degree = self%spline_degree
503 xnew = (position_new-self%domain(component,1)) * self%rdelta_x(component)
504 boxnew = ceiling(xnew)
505 xnew = xnew-real(boxnew-1, f64)
506 boxold = box(component)
509 local_size = abs(boxnew-boxold)+degree
514 self%spline_pp1d_1%poly_coeffs_fpa, xi(component), i) &
515 * self%delta_x(component)
517 self%spline_pp1d_1%poly_coeffs_fpa, xnew, i) &
518 * self%delta_x(component)
521 if (position_old(component) .le. position_new )
then
522 self%j1d(local_size-degree+1:local_size) = self%spline_1(:,2)
523 self%j1d(1:local_size-degree) = self%delta_x(component)
524 self%j1d(1:degree) = self%j1d(1:degree) - self%spline_1(:,1)
526 self%j1d(1:local_size-degree) = -self%delta_x(component)
527 self%j1d(local_size-degree+1:local_size) = -self%spline_1(:,1)
528 self%j1d(1:degree) = self%j1d(1:degree) + self%spline_1(:,2)
534 self%spline_0 = 0.0_f64
535 self%spline_1 = 0.0_f64
537 if (j .ne. component )
then
543 box(1) = box(1) - self%spline_degree
546 if (boxold<boxnew)
then
547 box(component) = boxold-self%spline_degree+1
549 box(component) = boxnew-self%spline_degree+1
554 do j=1,self%spline_degree+1
555 index2d(1) = modulo(box(1)+j-2,self%n_grid(1))+1
558 index2d(2) = modulo(box(2)+i-2,self%n_grid(2))+1
560 j_dofs(index1d) = j_dofs(index1d) + self%j1d(i) * &
561 self%spline_0(j,1) * marker_charge
563 vt(1) = vt(1) + bfield_dofs(start1+index1d)*self%j1d(i)
564 vt(2) = vt(2) + bfield_dofs(start2+index1d)*self%j1d(i)
568 vtt2 = vtt2 + vt(1)*self%spline_1(j-1, 1)
570 vtt3 = vtt3 + vt(2)*self%spline_0(j, 1)
573 vi(1) = vi(1) + qoverm*vtt2
574 vi(3) = vi(3) - qoverm*vtt3
583 sll_real64,
intent( in ) :: position(self%dim)
584 sll_int32 ,
intent( in ) :: degree(self%dim)
585 sll_real64,
intent( in ) :: field_dofs(self%n_dofs)
586 sll_real64,
intent( out ) :: field_value
590 sll_int32 :: index2d(2)
599 call sll_s_uniform_bsplines_eval_basis( degree(j), xi(j), self%spline_val(1:degree(j)+1,j) )
602 field_value = 0.0_f64
605 index2d(2) = modulo(box(2)+j-2,self%n_grid(2))+1
607 index2d(1) = modulo(box(1)+i-2,self%n_grid(1))+1
609 field_value = field_value + &
610 field_dofs(index1d) * &
611 self%spline_val(i,1) * self%spline_val(j,2)
621 sll_real64,
intent( in ) :: position(self%dim)
622 sll_int32 ,
intent( in ) :: degree(self%dim)
623 sll_real64,
intent( in ) :: field_dofs_pp(:,:)
624 sll_real64,
intent( out ) :: field_value
641 sll_real64,
intent( in ) :: position(self%dim)
642 sll_int32,
intent(in) :: components(:)
643 sll_real64,
intent( in ) :: field_dofs(:,:)
644 sll_real64,
intent(out) :: field_value(:)
653 sll_int32,
intent(in) :: n_grid(2)
654 sll_real64,
intent(in) :: domain(2,2)
655 sll_int32,
intent(in) :: no_particles
656 sll_int32,
intent(in) :: spline_degree
663 self%n_dofs = product(n_grid)
664 self%delta_x = (self%domain(:,2)-self%domain(:,1))/real(n_grid, f64)
665 self%rdelta_x = 1.0_f64/self%delta_x
668 self%no_particles = no_particles
671 self%spline_degree = spline_degree
672 self%n_span = spline_degree + 1
675 self%n_quad_points = (self%spline_degree+2)/2
676 allocate( self%quad_xw(2,self%n_quad_points) )
681 allocate( self%spline_val(self%n_span,2) )
682 allocate( self%spline_val_more(self%n_span,2) )
683 allocate( self%spline_0(self%n_span,2) )
684 allocate( self%spline_1(self%n_span-1,2) )
685 allocate( self%j1d( maxval(self%n_grid) ))
686 allocate( self%spline_2d(self%n_span, self%n_span) )
707 deallocate( self%quad_xw)
708 deallocate( self%spline_val)
709 deallocate( self%spline_val_more)
710 deallocate( self%spline_0)
711 deallocate( self%spline_1)
712 deallocate( self%j1d)
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.
Particle mesh coupling for 3d with splines of arbitrary degree placed on a uniform tensor product mes...
subroutine add_charge_single_spline_2d_feec(self, position, marker_charge, degree, rho_dofs)
Destructor.
subroutine evaluate_field_single_spline_pp_2d_feec(self, position, degree, field_dofs_pp, field_value)
Evaluate field at at position position.
subroutine add_current_spline_2d_feec(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle.
subroutine add_current_update_v_primitive_component2_spline_2d_feec(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
subroutine free_spline_2d_feec(self)
Destructor.
subroutine add_current_update_v_primitive_component1_spline_2d_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_2d_feec(self, position, components, field_dofs, field_value)
Evaluate several fields at position position.
subroutine convert_x_to_xbox(self, position, xi, box)
pure integer(kind=i32) function convert_index_2d_to_1d(index2d, n_grid)
subroutine init_spline_2d_feec(self, n_grid, domain, no_particles, spline_degree)
Constructor.
subroutine add_particle_mass_spline_2d_feec(self, position, marker_charge, degree, particle_mass)
Add charge of one particle.
subroutine evaluate_field_single_spline_2d_feec(self, position, degree, field_dofs, field_value)
Evaluate field at at position position.
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_2d(degree, pp_coeffs, x, indices, n_cells)
Perform a 2d hornerschema on the pp_coeffs at the indices.
subroutine, public sll_s_spline_pp_horner_m_3d(self, val, degree, x)
Perform three times a 1d hornerschema on the poly_coeffs.
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_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.
Particle mesh coupling in 3d based on (arbitrary degree) spline on a tensor product uniform mesh.
arbitrary degree 1d spline
arbitrary degree 3d spline