Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_lagrange_interpolation_1d.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 #include "sll_memory.h"
5 #include "sll_working_precision.h"
6 
8  sll_p_hermite, &
9  sll_p_periodic
10 
11  implicit none
12 
13  public :: &
18 
19  private
20 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 
23  sll_int32 :: d !half of stencil
24  sll_int32 :: nb_cell
25  sll_int32 :: bc_type
26  sll_int32 :: index_gap
27  sll_real64 :: alpha
28  sll_real64 :: xmin
29  sll_real64 :: xmax
30  sll_real64 :: deta
31  sll_real64, dimension(:), pointer :: wj
32  sll_real64, dimension(:), pointer :: wj_scale
33  sll_real64, dimension(:), pointer :: data_out !result=p(x) where p is the polynomial of interpolation
34  sll_int32 :: periodic_last
36 
37 ! integer, parameter :: sll_p_periodic = 0, sll_p_hermite = 3
38 
39  interface delete
40  module procedure delete_lagrange_interpolation_1d
41  end interface
42 
43 contains !*****************************************************************************
44 
45  function sll_f_new_lagrange_interpolation_1d(num_points, xmin, xmax, bc_type, d, periodic_last)
47  sll_int32 ::ierr
48  sll_int32, intent(in) :: d, num_points, bc_type
49  sll_int32, intent(in), optional :: periodic_last
50  sll_real64 :: xmin, xmax
51 
52  sll_allocate(sll_f_new_lagrange_interpolation_1d, ierr)
53 
54  sll_allocate(sll_f_new_lagrange_interpolation_1d%wj(2*d), ierr)
55  sll_allocate(sll_f_new_lagrange_interpolation_1d%wj_scale(2*d), ierr)
56  sll_allocate(sll_f_new_lagrange_interpolation_1d%data_out(num_points), ierr)
60  sll_f_new_lagrange_interpolation_1d%nb_cell = num_points - 1
61  sll_f_new_lagrange_interpolation_1d%bc_type = bc_type
62  sll_f_new_lagrange_interpolation_1d%deta = (xmax - xmin)/real(sll_f_new_lagrange_interpolation_1d%nb_cell, f64)
63  if (present(periodic_last)) then
64  sll_f_new_lagrange_interpolation_1d%periodic_last = periodic_last
65  else
66  sll_f_new_lagrange_interpolation_1d%periodic_last = 1
67  end if
68 
70 
73  type(sll_t_lagrange_interpolation_1d), pointer :: lagrange
74  sll_int32 :: i, j
75  sll_int32, dimension(1:4*lagrange%d - 2) :: table
76  sll_real64, dimension(1:2*lagrange%d) :: wj
77 
78  do i = 1, 2*lagrange%d - 1
79  table(i) = 2*lagrange%d - 1 - (i - 1)
80  table(i + 2*lagrange%d - 1) = i
81  end do
82 
83  wj = 1.0_f64
84  do i = 1, lagrange%d
85  do j = 1, 2*lagrange%d - 1
86  wj(i) = wj(i)*real(table(i + j - 1), f64)
87  end do
88  wj(i) = ((-1.0_f64)**(lagrange%d + i))*wj(i)
89  end do
90  do i = 1, lagrange%d
91  wj(i + lagrange%d) = -wj(lagrange%d - i + 1)
92  end do
93  wj = 1.0_f64/wj
94 
95  lagrange%wj = wj
96 
98 
100  subroutine sll_s_cubic_spline_1d_eval_array(fi, alpha, lagrange)
101  type(sll_t_lagrange_interpolation_1d), pointer :: lagrange
102  sll_real64, intent(in) :: alpha
103  sll_int32 ::i, j, index_gap
104  sll_real64 :: sum1, sum2, beta, h
105  sll_real64, dimension(1:lagrange%nb_cell + 1), intent(in) :: fi
106 
107  lagrange%alpha = -alpha
108 
109  h = lagrange%deta! grid size
110 ! How many cells do we displace? alpha = index_gap*h+beta*h
111  index_gap = floor(lagrange%alpha/h)
112  beta = lagrange%alpha/h - real(index_gap, f64)
113 
114 ! Take care of the case where alpha/h is negative and below machine precision
115  if (beta == 1.0_f64) then
116  beta = 0.0_f64
117  index_gap = index_gap + 1
118  end if
119 
120 ! If the displacement is precisely a multiple of h, we need to avoid division by zero
121  if (beta == 0.0_f64) then
122  select case (lagrange%bc_type)
123  case (sll_p_periodic)
124  do j = 1, lagrange%nb_cell + lagrange%periodic_last
125  lagrange%data_out(j) = fi(modulo(index_gap + j - 1, lagrange%nb_cell) + 1);
126  end do
127  case (sll_p_hermite)
128  do j = 1, lagrange%nb_cell + 1
129  lagrange%data_out(j) = fi(min(max(1, index_gap + j), lagrange%nb_cell + 1));
130  end do
131  end select
132 
133  else
134 
135  sum2 = 0.0_f64
136  do j = 1, 2*lagrange%d
137  lagrange%wj_scale(j) = lagrange%wj(j)/(beta + real(lagrange%d - j, f64))
138  sum2 = sum2 + lagrange%wj_scale(j)
139  end do
140 
141  select case (lagrange%bc_type)
142  case (sll_p_periodic)
143 
144  do i = 1, lagrange%nb_cell + lagrange%periodic_last
145  sum1 = 0.0_f64
146  do j = 1, lagrange%d*2
147  sum1 = sum1 + lagrange%wj_scale(j)*fi(modulo(index_gap + (i - 1) + (j - 1) - (lagrange%d - 1), lagrange%nb_cell) + 1)
148  end do
149  lagrange%data_out(i) = sum1/sum2
150  end do
151 
152  case (sll_p_hermite)
153 
154  do i = 1, lagrange%nb_cell + 1
155  sum1 = 0.0_f64
156  do j = 1, lagrange%d*2
157  if (index_gap + (i - 1) + (j - 1) - (lagrange%d - 1) < 0) then
158  sum1 = sum1 + lagrange%wj_scale(j)*fi(1)
159  else if (index_gap + (i - 1) + (j - 1) - (lagrange%d - 1) > lagrange%nb_cell) then
160  sum1 = sum1 + lagrange%wj_scale(j)*fi(lagrange%nb_cell + 1)
161  else
162  sum1 = sum1 + lagrange%wj_scale(j)*fi(index_gap + (i - 1) + (j - 1) - (lagrange%d - 1) + 1)
163  end if
164  end do
165  lagrange%data_out(i) = sum1/sum2
166  end do
167 
168  case default
169  print *, 'ERROR: sll_s_compute_lagrange_interpolation_1d(): not recognized boundary condition'
170  stop
171  end select
172  end if
173 
174  end subroutine sll_s_cubic_spline_1d_eval_array
175 
176  subroutine delete_lagrange_interpolation_1d(sll_m_lagrange_interpolation)
177  type(sll_t_lagrange_interpolation_1d), pointer :: sll_m_lagrange_interpolation
178  sll_int32 :: ierr
179  sll_assert(associated(sll_m_lagrange_interpolation))
180  sll_deallocate(sll_m_lagrange_interpolation%wj, ierr)
181  sll_deallocate(sll_m_lagrange_interpolation, ierr)
182  end subroutine delete_lagrange_interpolation_1d
183 
185 
subroutine, public sll_s_cubic_spline_1d_eval_array(fi, alpha, lagrange)
This function computes the value at the grid points displacement by -alpha.
subroutine delete_lagrange_interpolation_1d(sll_m_lagrange_interpolation)
subroutine, public sll_s_compute_lagrange_interpolation_1d(lagrange)
This function computes the weights w_j for the barycentric formula.
type(sll_t_lagrange_interpolation_1d) function, pointer, public sll_f_new_lagrange_interpolation_1d(num_points, xmin, xmax, bc_type, d, periodic_last)
    Report Typos and Errors