Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_particle_mesh_coupling_spline_cl_1d.F90
Go to the documentation of this file.
1 
6 
7  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 #include "sll_assert.h"
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
11 #include "sll_errors.h"
12 
13  use sll_m_low_level_bsplines, only: &
14  sll_s_uniform_bsplines_eval_basis
15 
18 
23 
24  use sll_m_particle_group_base, only: &
26 
27  use sll_m_splines_pp, only: &
34  implicit none
35 
36  public :: &
40 
41  private
42  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
45  type(sll_t_spline_pp_1d) :: spline_pp
46 
47  ! Information about the particles
48  sll_int32 :: no_particles
49  sll_int32 :: n_span
50  sll_real64 :: scaling
51  sll_int32 :: n_quad_points
52  sll_real64, allocatable :: spline_val(:)
53  sll_real64, allocatable :: spline_val_more(:)
54  ! For 1d quadrature
55  sll_int32 :: n_quad_points_line
56  sll_real64, allocatable :: quad_xw_line(:,:)
57  sll_real64, allocatable :: quad_xw(:,:)
58 
59  contains
60  procedure :: add_charge => add_charge_single_spline_cl_1d
61  procedure :: add_particle_mass => add_particle_mass_spline_cl_1d
62  procedure :: add_particle_mass_full => add_particle_mass_spline_cl_1d_full
63  procedure :: evaluate => evaluate_field_single_spline_cl_1d
64  procedure :: evaluate_multiple => evaluate_multiple_spline_cl_1d
65  procedure :: add_current_update_v => add_current_update_v_spline_cl_1d
68 
69  procedure :: init => init_spline_cl_1d
70  procedure :: free => free_spline_cl_1d
71 
73 
74 contains
75 
76 
77  !---------------------------------------------------------------------------!
79  subroutine add_charge_single_spline_cl_1d(self, position, marker_charge, rho_dofs)
80  class( sll_t_particle_mesh_coupling_spline_cl_1d ), intent(inout) :: self
81  sll_real64, intent( in ) :: position(self%dim)
82  sll_real64, intent( in ) :: marker_charge
83  sll_real64, intent( inout ) :: rho_dofs(self%n_dofs)
84  !local variables
85  sll_int32 :: i
86  sll_int32 :: box
87  sll_real64 :: xi
88 
89  call convert_x_to_xbox( self, position, xi, box )
90  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, xi, box, self%spline_val )
91 
92  do i = 1, self%n_span
93  rho_dofs(box+i-1) = rho_dofs(box+i-1) +&
94  (marker_charge * self%spline_val(i)* self%scaling)
95  end do
96 
97 
98  end subroutine add_charge_single_spline_cl_1d
99 
100 
101  !---------------------------------------------------------------------------!
103  subroutine add_particle_mass_spline_cl_1d(self, position, marker_charge, particle_mass)
104  class( sll_t_particle_mesh_coupling_spline_cl_1d ), intent(inout) :: self
105  sll_real64, intent( in ) :: position(self%dim)
106  sll_real64, intent( in ) :: marker_charge
107  sll_real64, intent( inout ) :: particle_mass(:,:)
108 
109  !local variables
110  sll_int32 :: i, column
111  sll_int32 :: box
112  sll_real64 :: xi
113 
114  sll_assert( size(particle_mass,1) == self%n_span )
115  sll_assert( size(particle_mass,2) == self%n_dofs )
116 
117  call convert_x_to_xbox( self, position, xi, box )
118 
119  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, xi, box, self%spline_val )
120 
121  do i = 1, self%n_span
122  do column = i, self%n_span
123  particle_mass(column-i+1, box+i-1) = particle_mass( column-i+1, box+i-1) + &
124  marker_charge * self%spline_val(i) * self%spline_val(column)
125  ! Note: No scaling since Galerkin function
126  end do
127  end do
128 
129  end subroutine add_particle_mass_spline_cl_1d
130 
131 
132  !----------------------------------------------------------------------!
134  subroutine add_particle_mass_spline_cl_1d_full(self, position, marker_charge, particle_mass)
135  class( sll_t_particle_mesh_coupling_spline_cl_1d ), intent(inout) :: self
136  sll_real64, intent( in ) :: position(self%dim)
137  sll_real64, intent( in ) :: marker_charge
138  sll_real64, intent( inout ) :: particle_mass(:,:)
139  !local variables
140  sll_int32 :: i, column, ind
141  sll_int32 :: box
142  sll_real64 :: xi
143 
144  sll_assert( size(particle_mass,1) == 2*self%spline_degree+1 )
145  sll_assert( size(particle_mass,2) == self%n_dofs )
146 
147  call convert_x_to_xbox( self, position, xi, box )
148 
149  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, xi, box, self%spline_val )
150 
151  do i = 1, self%n_span
152  ind=1+(self%n_span-i)
153  do column = 1, self%n_span
154  particle_mass(ind, box+i-1) = particle_mass( ind, box+i-1) + &
155  marker_charge * self%spline_val(i) * self%spline_val(column)
156  ind = ind+1
157  end do
158  end do
159 
161 
162 
163  !---------------------------------------------------------------------------!
165  subroutine evaluate_field_single_spline_cl_1d(self, position, field_dofs, field_value)
166  class(sll_t_particle_mesh_coupling_spline_cl_1d), intent( inout ) :: self
167  sll_real64, intent( in ) :: position(self%dim)
168  sll_real64, intent( in ) :: field_dofs(self%n_dofs)
169  sll_real64, intent( out ) :: field_value
170  !local variables
171  sll_int32 :: i
172  sll_int32 :: box
173  sll_real64 :: xi
174 
175  call convert_x_to_xbox( self, position, xi, box )
176 
177  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, xi, box, self%spline_val )
178 
179 
180  field_value = 0.0_f64
181  do i = 1, self%n_span
182  field_value = field_value + &
183  field_dofs(box+i-1) * &
184  self%spline_val(i)
185  end do
186 
188 
189 
190  !---------------------------------------------------------------------------!
192  subroutine evaluate_multiple_spline_cl_1d(self, position, components, field_dofs, field_value)
193  class(sll_t_particle_mesh_coupling_spline_cl_1d), intent( inout ) :: self
194  sll_real64, intent( in ) :: position(self%dim)
195  sll_int32, intent(in) :: components(:)
196  sll_real64, intent( in ) :: field_dofs(:,:)
197  sll_real64, intent(out) :: field_value(:)
198  !local variables
199  sll_int32 :: i
200  sll_int32 :: box
201  sll_real64 :: xi
202 
203  sll_assert( size(field_dofs,1) == self%n_dofs )
204  sll_assert( size(field_dofs,2) == size(field_value) )
205 
206  call convert_x_to_xbox( self, position, xi, box )
207 
208  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, xi, box, self%spline_val )
209 
210 
211  field_value = 0.0_f64
212  do i = 1, self%n_span
213 
214  field_value = field_value + &
215  field_dofs(box+i-1,components) * &
216  self%spline_val(i)
217  end do
218 
219  end subroutine evaluate_multiple_spline_cl_1d
220 
221 
222  !---------------------------------------------------------------------------!
224  subroutine add_current_spline_cl_1d( self, position_old, position_new, marker_charge, j_dofs )
225  class( sll_t_particle_mesh_coupling_spline_cl_1d ), intent(inout) :: self
226  sll_real64, intent( in ) :: position_old(self%dim)
227  sll_real64, intent( in ) :: position_new(self%dim)
228  sll_real64, intent( in ) :: marker_charge
229  sll_real64, intent( inout ) :: j_dofs(self%n_dofs)
230  !local variables
231  sll_int32 :: index_old, index_new, ind
232  sll_real64 :: r_old, r_new
233 
234  call convert_x_to_xbox( self, position_old, r_old, index_old )
235  call convert_x_to_xbox( self, position_new, r_new, index_new )
236 
237  if (index_old == index_new) then
238  if (r_old < r_new) then
239  call update_j( self, r_old, r_new, index_old, marker_charge, &
240  1.0_f64, j_dofs)
241  else
242  call update_j( self, r_new, r_old, index_old, marker_charge, &
243  -1.0_f64, j_dofs)
244  end if
245  elseif (index_old < index_new) then
246  call update_j ( self, r_old, 1.0_f64, index_old, marker_charge, &
247  1.0_f64, j_dofs)
248  call update_j ( self, 0.0_f64, r_new, index_new, marker_charge, &
249  1.0_f64, j_dofs)
250  do ind = index_old+1, index_new-1
251  call update_j ( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
252  1.0_f64, j_dofs)
253  end do
254  else
255  call update_j ( self, r_new, 1.0_f64, index_new, marker_charge, &
256  -1.0_f64, j_dofs)
257  call update_j ( self, 0.0_f64, r_old, index_old, marker_charge, &
258  -1.0_f64, j_dofs)
259  do ind = index_new+1, index_old-1
260  call update_j ( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
261  -1.0_f64, j_dofs)
262  end do
263  end if
264 
265  end subroutine add_current_spline_cl_1d
266 
267 
269  subroutine update_j(self, lower, upper, index, marker_charge,sign, j_dofs)
270  class(sll_t_particle_mesh_coupling_spline_cl_1d), intent(inout) :: self
271  sll_real64, intent(in) :: lower
272  sll_real64, intent(in) :: upper
273  sll_int32, intent(in) :: index
274  sll_real64, intent(in) :: marker_charge
275  sll_real64, intent(in) :: sign
276  sll_real64, intent(inout) :: j_dofs(:)
277  !Local variables
278  sll_int32 :: ind, i_grid, j
279  sll_real64 :: c1, c2
280 
281  c1 = 0.5_f64*(upper-lower)
282  c2 = 0.5_f64*(upper+lower)
283 
284  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, c1*self%quad_xw(1,1)+c2, index, self%spline_val )
285  self%spline_val = self%spline_val * (self%quad_xw(2,1)*c1)
286  do j=2,self%n_quad_points
287  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, c1*self%quad_xw(1,j)+c2, index, self%spline_val_more )
288  self%spline_val = self%spline_val + self%spline_val_more * (self%quad_xw(2,j)*c1)
289  end do
290  self%spline_val = self%spline_val * (sign*self%delta_x)
291 
292  ind = 1
293  do i_grid = index, index + self%spline_degree
294  j_dofs(i_grid) = j_dofs(i_grid) + &
295  (marker_charge*self%spline_val(ind)* self%scaling)
296  ind = ind + 1
297  end do
298 
299  end subroutine update_j
300 
301 
303  subroutine add_current_evaluate_spline_cl_1d(self, position_old, position_new, marker_charge, vbar, field_dofs, j_dofs, field)
304  class( sll_t_particle_mesh_coupling_spline_cl_1d ), intent(inout) :: self
305  sll_real64, intent( in ) :: position_old(self%dim)
306  sll_real64, intent( in ) :: position_new(self%dim)
307  sll_real64, intent( in ) :: marker_charge
308  sll_real64, intent( in ) :: vbar
309  sll_real64, intent( in ) :: field_dofs(self%n_dofs)
310  sll_real64, intent( inout ) :: j_dofs(self%n_dofs)
311  sll_real64, intent( out ) :: field
312  !local variables
313  sll_int32 :: index_old, index_new, ind
314  sll_real64 :: r_old, r_new
315 
316  call convert_x_to_xbox( self, position_old, r_old, index_old )
317  call convert_x_to_xbox( self, position_new, r_new, index_new )
318 
319  field = 0.0_f64
320 
321  if (index_old == index_new) then
322  if (r_old < r_new) then
323  call update_je( self, r_old, r_new, index_old, marker_charge, &
324  1.0_f64, j_dofs, field_dofs, field)
325  else
326  call update_je( self, r_new, r_old, index_old, marker_charge, &
327  -1.0_f64, j_dofs, field_dofs, field)
328  end if
329  elseif (index_old < index_new) then
330  call update_je( self, r_old, 1.0_f64, index_old, marker_charge, &
331  1.0_f64, j_dofs, field_dofs, field)
332  call update_je( self, 0.0_f64, r_new, index_new, marker_charge, &
333  1.0_f64, j_dofs, field_dofs, field)
334  do ind = index_old+1, index_new-1
335  call update_je( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
336  1.0_f64, j_dofs, field_dofs, field)
337  end do
338  else
339  call update_je( self, r_new, 1.0_f64, index_new, marker_charge, &
340  -1.0_f64, j_dofs, field_dofs, field)
341  call update_je( self, 0.0_f64, r_old, index_old, marker_charge, &
342  -1.0_f64, j_dofs, field_dofs, field)
343  do ind = index_new+1, index_old-1
344  call update_je( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
345  -1.0_f64, j_dofs, field_dofs, field)
346  end do
347  end if
348  field = field/vbar
349 
350  end subroutine add_current_evaluate_spline_cl_1d
351 
352 
354  subroutine update_je(self, lower, upper, index, marker_charge, sign, j_dofs, field_dofs, field)
355  class(sll_t_particle_mesh_coupling_spline_cl_1d), intent(inout) :: self
356  sll_real64, intent(in) :: lower
357  sll_real64, intent(in) :: upper
358  sll_int32, intent(in) :: index
359  sll_real64, intent(in) :: marker_charge
360  sll_real64, intent(in) :: sign
361  sll_real64, intent(inout) :: j_dofs(:)
362  sll_real64, intent(in) :: field_dofs(:)
363  sll_real64, intent(inout) :: field
364  !Local variables
365  sll_int32 :: ind, i_grid, j
366  sll_real64 :: c1, c2
367 
368  c1 = 0.5_f64*(upper-lower)
369  c2 = 0.5_f64*(upper+lower)
370 
371  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, c1*self%quad_xw(1,1)+c2, index, self%spline_val )
372  self%spline_val = self%spline_val * (self%quad_xw(2,1)*c1)
373  do j=2,self%n_quad_points
374  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, c1*self%quad_xw(1,j)+c2, index, self%spline_val_more )
375  self%spline_val = self%spline_val + self%spline_val_more * (self%quad_xw(2,j)*c1)
376  end do
377  self%spline_val = self%spline_val * self%delta_x * sign
378 
379  ind = 1
380  do i_grid = index, index + self%spline_degree
381  j_dofs(i_grid) = j_dofs(i_grid) + &
382  (marker_charge*self%spline_val(ind)* self%scaling)
383  field = field + self%spline_val(ind)*field_dofs(i_grid)
384  ind = ind + 1
385  end do
386 
387  end subroutine update_je
388 
389 
390  !---------------------------------------------------------------------------!
392  subroutine add_current_update_v_spline_cl_1d (self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
393  class(sll_t_particle_mesh_coupling_spline_cl_1d), intent(inout) :: self
394  sll_real64, intent(in) :: position_old(self%dim)
395  sll_real64, intent(in) :: position_new(self%dim)
396  sll_real64, intent(in) :: marker_charge
397  sll_real64, intent(in) :: qoverm
398  sll_real64, intent(in) :: bfield_dofs(:)
399  sll_real64, intent(inout) :: vi(:)
400  sll_real64, intent(inout) :: j_dofs(:)
401  ! local variables
402  sll_int32 :: index_old, index_new, ind
403  sll_real64 :: r_old, r_new
404 
405  call convert_x_to_xbox( self, position_old, r_old, index_old )
406  call convert_x_to_xbox( self, position_new, r_new, index_new )
407 
408  if (index_old == index_new) then
409  if (r_old < r_new) then
410  call update_jv( self, r_old, r_new, index_old, marker_charge, &
411  qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
412  else
413  call update_jv( self, r_new, r_old, index_old, marker_charge, qoverm, &
414  -1.0_f64, vi(2), j_dofs, bfield_dofs)
415  end if
416  elseif (index_old < index_new) then
417  call update_jv ( self, r_old, 1.0_f64, index_old, marker_charge, &
418  qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
419  call update_jv ( self, 0.0_f64, r_new, index_new, marker_charge, &
420  qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
421  do ind = index_old+1, index_new-1
422  call update_jv ( self, 0.0_f64, 1.0_f64, ind, marker_charge, &
423  qoverm, 1.0_f64, vi(2), j_dofs, bfield_dofs)
424  end do
425  else
426  call update_jv ( self, r_new, 1.0_f64, index_new, marker_charge, qoverm, &
427  -1.0_f64, vi(2), j_dofs, bfield_dofs)
428  call update_jv ( self, 0.0_f64, r_old, index_old, marker_charge, qoverm, &
429  -1.0_f64, vi(2), j_dofs, bfield_dofs)
430  do ind = index_new+1, index_old-1
431  call update_jv ( self, 0.0_f64, 1.0_f64, ind, marker_charge, qoverm, &
432  -1.0_f64, vi(2), j_dofs, bfield_dofs)
433  end do
434  end if
435 
436  end subroutine add_current_update_v_spline_cl_1d
437 
438 
440  subroutine update_jv(self, lower, upper, index, marker_charge, qoverm, sign, vi, j_dofs, bfield_dofs)
441  class(sll_t_particle_mesh_coupling_spline_cl_1d), intent(inout) :: self
442  sll_real64, intent(in) :: lower
443  sll_real64, intent(in) :: upper
444  sll_int32, intent(in) :: index
445  sll_real64, intent(in) :: marker_charge
446  sll_real64, intent(in) :: qoverm
447  sll_real64, intent(in) :: sign
448  sll_real64, intent(inout) :: vi
449  sll_real64, intent(in) :: bfield_dofs(:)
450  sll_real64, intent(inout) :: j_dofs(:)
451  !Local variables
452  sll_int32 :: ind, i_grid, j
453  sll_real64 :: c1, c2
454 
455  c1 = 0.5_f64*(upper-lower)
456  c2 = 0.5_f64*(upper+lower)
457 
458  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, c1*self%quad_xw(1,1)+c2, index, self%spline_val )
459  self%spline_val = self%spline_val * (self%quad_xw(2,1)*c1)
460  do j=2,self%n_quad_points
461  call sll_s_uniform_bsplines_eval_basis_clamped( self%spline_pp, self%n_cells, self%spline_degree, c1*self%quad_xw(1,j)+c2, index, self%spline_val_more )
462  self%spline_val = self%spline_val + self%spline_val_more * (self%quad_xw(2,j)*c1)
463  end do
464  self%spline_val = self%spline_val * (sign*self%delta_x)
465 
466  ind = 1
467  do i_grid = index, index + self%spline_degree
468  j_dofs(i_grid) = j_dofs(i_grid) + &
469  (marker_charge*self%spline_val(ind)* self%scaling)
470  vi = vi - qoverm* self%spline_val(ind)*bfield_dofs(i_grid)
471  ind = ind + 1
472  end do
473 
474  end subroutine update_jv
475 
476 
477 
478  subroutine convert_x_to_xbox( self, position, xi, box )
479  class( sll_t_particle_mesh_coupling_spline_cl_1d ), intent(inout) :: self
480  sll_real64, intent( in ) :: position(self%dim)
481  sll_real64, intent( out ) :: xi
482  sll_int32, intent( out ) :: box
483 
484  xi = (position(1) - self%domain(1)) /self%delta_x
485  box = floor( xi ) + 1
486  xi = xi - real(box-1, f64)
487 
488  if( box == self%n_cells + 1 ) then
489  if( xi == 0._f64)then
490  xi = 1._f64
491  box = self%n_cells
492  else
493  print*, 'box,x, xbox', box, position(1), xi
494  sll_error('convert_x_to_xbox', 'box1 value to high' )
495  end if
496  else if( box > self%n_cells + 1 ) then
497  print*, 'box,x, xbox', box, position(1), xi
498  sll_error('convert_x_to_xbox', 'box1 value to high' )
499  else if( box <= 0 ) then
500  print*, 'box,x, xbox', box, position(1), xi
501  sll_error('convert_x_to_xbox', 'box1 value to low' )
502  end if
503 
504  end subroutine convert_x_to_xbox
505 
507  subroutine sll_s_uniform_bsplines_eval_basis_clamped( spline, n_cells, degree, xi, box, spline_val )
508  type(sll_t_spline_pp_1d), intent( in ) :: spline
509  sll_int32, intent( in ) :: n_cells
510  sll_int32, intent( in ) :: degree
511  sll_real64, intent( in ) :: xi
512  sll_int32, intent( in ) :: box
513  sll_real64, intent( out ) :: spline_val(:)
514  !local variables
515  sll_int32 :: i
516 
517  if(box >= 1 .and. box <= degree-1)then
518  do i=1, degree+1
519  spline_val(i) = sll_f_spline_pp_horner_1d( degree, spline%poly_coeffs_boundary_left(:,:,box), xi, i)
520  end do
521  else if (box >= degree .and. box <= n_cells-degree+1)then
522  call sll_s_uniform_bsplines_eval_basis( degree, xi, spline_val )
523  else if(box >= n_cells-degree+2 .and. box <= n_cells)then
524  do i=1, degree+1
525  spline_val(i) = sll_f_spline_pp_horner_1d( degree, spline%poly_coeffs_boundary_right(:,:,box-1-n_cells+degree), xi, i)
526  end do
527  else
528  print*, 'box, xbox', box, xi
529  sll_error( "uniform_bsplines_eval_basis_clamped", "box out of range" )
530  end if
531 
533 
534 
536  subroutine init_spline_cl_1d( self, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary )
537  class( sll_t_particle_mesh_coupling_spline_cl_1d), intent(out) :: self
538  sll_real64, intent(in) :: domain(2)
539  sll_int32, intent(in) :: n_cells
540  sll_int32, intent(in) :: no_particles
541  sll_int32, intent(in) :: spline_degree
542  sll_int32, intent(in) :: smoothing_type
543  sll_int32, intent(in) :: boundary
544  !local variables
545  sll_int32 :: ierr
546 
547 
548  self%dim = 1
549 
550  ! Store grid information
551  self%domain = domain
552  self%n_cells = n_cells
553  self%n_dofs = n_cells+spline_degree
554  self%delta_x = (self%domain(2)-self%domain(1))/real(n_cells, f64)
555 
556  ! Store basis function information
557  self%no_particles = no_particles
558 
559  ! Initialize information on the spline
560  self%spline_degree = spline_degree
561  self%n_span = spline_degree + 1
562 
563  ! Initialize information on smoothing type
564  if (smoothing_type == sll_p_collocation) then
565  self%scaling = 1.0_f64/self%delta_x
566  elseif (smoothing_type == sll_p_galerkin) then
567  self%scaling = 1.0_f64
568  else
569  print*, 'Smoothing Type ', smoothing_type, ' not implemented for kernel_smoother_spline_1d.'
570  end if
571 
572  self%n_quad_points = (self%spline_degree+2)/2
573 
574  ALLOCATE( self%spline_val(self%n_span), stat = ierr)
575  sll_assert( ierr == 0 )
576  ALLOCATE( self%spline_val_more(self%n_span), stat = ierr )
577  sll_assert( ierr == 0 )
578  ALLOCATE( self%quad_xw(2,self%n_quad_points), stat = ierr )
579  sll_assert( ierr == 0 )
580 
581  ! normalized Gauss Legendre points and weights
582  self%quad_xw = sll_f_gauss_legendre_points_and_weights(self%n_quad_points)
583 
584  call sll_s_spline_pp_init_1d( self%spline_pp, spline_degree, n_cells, boundary)
585 
586  ! for line integral
587  self%n_quad_points_line = (self%spline_degree+2)/2
588 
589  allocate( self%quad_xw_line(2,self%n_quad_points_line) )
590  ! normalized Gauss Legendre points and weights
591  self%quad_xw_line = sll_f_gauss_legendre_points_and_weights(self%n_quad_points_line)
592 
593  self%quad_xw_line(1,:) = 0.5_f64*(self%quad_xw_line(1,:)+1.0_f64)
594  self%quad_xw_line(2,:) = 0.5_f64*self%quad_xw_line(2,:)
595 
596 
597  end subroutine init_spline_cl_1d
598 
599 
601  subroutine free_spline_cl_1d(self)
602  class(sll_t_particle_mesh_coupling_spline_cl_1d), intent( inout ) :: self
603 
604  deallocate(self%spline_val)
605  call sll_s_spline_pp_free_1d(self%spline_pp)
606 
607  end subroutine free_spline_cl_1d
608 
609 
610  !-------------------------------------------------------------------------------------------
611 
612  subroutine sll_s_new_particle_mesh_coupling_spline_cl_1d_ptr(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
613  class( sll_c_particle_mesh_coupling_1d), pointer, intent(out) :: smoother
614  sll_int32, intent(in) :: n_cells
615  sll_real64, intent(in) :: domain(2)
616  sll_int32, intent(in) :: no_particles
617  sll_int32, intent(in) :: spline_degree
618  sll_int32, intent(in) :: smoothing_type
619  sll_int32, intent(in) :: boundary
620  !local variables
621  sll_int32 :: ierr
622 
623 
624  sll_allocate( sll_t_particle_mesh_coupling_spline_cl_1d :: smoother , ierr)
625  sll_assert( ierr == 0)
626 
627  select type( smoother )
629  call smoother%init( domain, n_cells, no_particles, spline_degree, smoothing_type, boundary )
630  end select
631 
633 
634 
635  !----------------------------------------------------------------------------------
636 
637  subroutine sll_s_new_particle_mesh_coupling_spline_cl_1d(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
638  class( sll_c_particle_mesh_coupling_1d), allocatable, intent(out):: smoother
639  sll_int32, intent(in) :: n_cells
640  sll_real64, intent(in) :: domain(2)
641  sll_int32, intent(in) :: no_particles
642  sll_int32, intent(in) :: spline_degree
643  sll_int32, intent(in) :: smoothing_type
644  sll_int32, intent(in) :: boundary
645  !local variables
646  sll_int32 :: ierr
647 
648 
649  allocate( sll_t_particle_mesh_coupling_spline_cl_1d :: smoother , stat=ierr)
650  sll_assert( ierr == 0)
651 
652  select type( smoother )
654  call smoother%init( domain, n_cells, no_particles, spline_degree, smoothing_type, boundary )
655  end select
656 
658 
659 
real(kind=f64) function, dimension(2, 1:npoints), public sll_f_gauss_legendre_points_and_weights(npoints, a, b)
Returns a 2d array of size (2,npoints) containing gauss-legendre points and weights in the interval [...
Low level arbitrary degree splines.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
integer(kind=i32), parameter, public sll_p_collocation
Kernel smoother for 2d with splines of arbitrary degree placed on a uniform mesh.
subroutine add_current_spline_cl_1d(self, position_old, position_new, marker_charge, j_dofs)
Add current with integration over x.
subroutine add_charge_single_spline_cl_1d(self, position, marker_charge, rho_dofs)
Destructor.
subroutine update_je(self, lower, upper, index, marker_charge, sign, j_dofs, field_dofs, field)
Helper function for add_current_evaluate.
subroutine add_particle_mass_spline_cl_1d(self, position, marker_charge, particle_mass)
Add the contribution of one particle to the approximate mass matrix.
subroutine add_particle_mass_spline_cl_1d_full(self, position, marker_charge, particle_mass)
Add the contribution of one particle to the approximate mass matrix.
subroutine evaluate_multiple_spline_cl_1d(self, position, components, field_dofs, field_value)
Evaluate several fields at position position.
subroutine update_j(self, lower, upper, index, marker_charge, sign, j_dofs)
Helper function for add_current.
subroutine, public sll_s_new_particle_mesh_coupling_spline_cl_1d_ptr(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
subroutine sll_s_uniform_bsplines_eval_basis_clamped(spline, n_cells, degree, xi, box, spline_val)
Helper function to evaluate uniform clamped basis splines.
subroutine add_current_update_v_spline_cl_1d(self, position_old, position_new, marker_charge, qoverm, bfield_dofs, vi, j_dofs)
Add current for one particle and update v (according to H_p1 part in Hamiltonian splitting)
subroutine evaluate_field_single_spline_cl_1d(self, position, field_dofs, field_value)
Evaluate field at at position position.
subroutine add_current_evaluate_spline_cl_1d(self, position_old, position_new, marker_charge, vbar, field_dofs, j_dofs, field)
Combines add_current and evaluate_int.
subroutine, public sll_s_new_particle_mesh_coupling_spline_cl_1d(smoother, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
subroutine update_jv(self, lower, upper, index, marker_charge, qoverm, sign, vi, j_dofs, bfield_dofs)
Helper function for add_current_update_v.
subroutine init_spline_cl_1d(self, domain, n_cells, no_particles, spline_degree, smoothing_type, boundary)
Initializer.
Splines in pp form.
subroutine, public sll_s_spline_pp_horner_primitive_1d(val, degree, pp_coeffs, x)
Perform a 1d hornerschema on the pp_coeffs evaluate at x.
subroutine, public sll_s_spline_pp_init_1d(self, degree, n_cells, boundary)
Initialize sll_t_spline_pp_1d object (Set poly_coeffs depending on degree)
subroutine, public sll_s_spline_pp_free_1d(self)
Destructor 1d.
subroutine, public sll_s_spline_pp_horner_m_1d(self, val, degree, x)
Perform a 1d hornerschema on the poly_coeffs.
real(kind=f64) function, public sll_f_spline_pp_horner_1d(degree, pp_coeffs, x, index)
Perform a 1d hornerschema on the pp_coeffs at index.
    Report Typos and Errors