Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_hermite_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 :: &
20 
21  private
22 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23 
24 !Hermite interpolation in 1d
25 !derivatives are given with finite stencil formulae of order p
26 !which can be arbitrary in each direction
27 !If p is odd, the reconstruction has discontinuous derivatives
28 !If p is even, the reconstruction has continuous derivatives
29 !p=6 should be quite similar to cubic splines
30 !do not hesitate to take large odd p, like the favourite p=17
31 !see also sll_m_hermite_interpolation_2d
33  sll_real64 :: eta_min
34  sll_real64 :: eta_max
35  sll_int32 :: nc
36  sll_int32 :: degree
37  sll_int32 :: bc
39  sll_real64, dimension(:, :), pointer :: deriv
40  sll_int32 :: continuity
41  sll_int32 :: deriv_size
44 
45  !integer, parameter :: SLL_HERMITE_PERIODIC = 0, SLL_HERMITE_DIRICHLET = 1
46  integer, parameter :: sll_p_hermite_1d_c0 = 0, sll_hermite_1d_c1 = 1
47 
48 ! interface delete
49 ! module procedure delete_hermite_interpolation_1d
50 ! end interface
51 
52 contains !*****************************************************************************
54  npts, &
55  eta_min, &
56  eta_max, &
57  degree, &
58  eta_hermite_continuity, &
59  eta_bc_type, &
60  const_eta_min_slope, &
61  const_eta_max_slope, &
62  eta_min_slopes, &
63  eta_max_slopes) &
64  result(interp)
65 
66  type(sll_t_hermite_interpolation_1d), pointer :: interp
67  sll_int32, intent(in) :: npts
68  sll_real64, intent(in) :: eta_min
69  sll_real64, intent(in) :: eta_max
70  sll_int32, intent(in) :: degree
71  sll_int32, intent(in) :: eta_hermite_continuity
72  sll_int32, intent(in) :: eta_bc_type
73  sll_real64, intent(in), optional :: const_eta_min_slope
74  sll_real64, intent(in), optional :: const_eta_max_slope
75  sll_real64, dimension(:), intent(in), optional :: eta_min_slopes
76  sll_real64, dimension(:), intent(in), optional :: eta_max_slopes
77  sll_int32 :: ierr
78 
79  sll_allocate(interp, ierr)
80 
82  interp, &
83  npts, &
84  eta_min, &
85  eta_max, &
86  degree, &
87  eta_hermite_continuity, &
88  eta_bc_type, &
89  const_eta_min_slope, &
90  const_eta_max_slope, &
91  eta_min_slopes, &
92  eta_max_slopes)
93 
95 
97  interp, &
98  npts, &
99  eta_min, &
100  eta_max, &
101  degree, &
102  eta_hermite_continuity, &
103  eta_bc_type, &
104  const_eta_min_slope, &
105  const_eta_max_slope, &
106  eta_min_slopes, &
107  eta_max_slopes)
108 
109  type(sll_t_hermite_interpolation_1d) :: interp
110 
111  sll_int32, intent(in) :: npts
112  sll_real64, intent(in) :: eta_min
113  sll_real64, intent(in) :: eta_max
114  sll_int32, intent(in) :: degree
115  sll_int32, intent(in) :: eta_hermite_continuity
116  sll_int32, intent(in) :: eta_bc_type
117  sll_real64, intent(in), optional :: const_eta_min_slope
118  sll_real64, intent(in), optional :: const_eta_max_slope
119  sll_real64, dimension(:), intent(in), optional :: eta_min_slopes
120  sll_real64, dimension(:), intent(in), optional :: eta_max_slopes
121  sll_int32 :: ierr
122  sll_int32 :: deriv_size
123  !sll_int32 :: i
124 
125  interp%Nc = npts - 1
126  interp%degree = degree
127  interp%continuity = eta_hermite_continuity
128  interp%bc = eta_bc_type
129  interp%eta_min = eta_min
130  interp%eta_max = eta_max
131 
132  select case (interp%continuity)
133  case (sll_p_hermite_1d_c0)
134  interp%deriv_size = 3
135  case (sll_hermite_1d_c1)
136  interp%deriv_size = 2
137  case default
138  print *, '#bad value for hermite_continuity', interp%continuity
139  print *, '#in initialize_hermite_interpolation_1d'
140  stop
141  sll_assert(present(const_eta_min_slope))
142  sll_assert(present(const_eta_max_slope))
143  sll_assert(present(eta_min_slopes))
144  sll_assert(present(eta_max_slopes))
145  end select
146  deriv_size = interp%deriv_size
147 
148  sll_allocate(interp%deriv(deriv_size, npts), ierr)
149 
151 
153  interp, &
154  f)
155  type(sll_t_hermite_interpolation_1d) :: interp
156  sll_real64, dimension(:), intent(in) :: f
157 
158  if ((interp%bc == sll_p_hermite)) then
159  if (interp%continuity == sll_p_hermite_1d_c0) then
160  call hermite_coef_nat_1d(f, interp%deriv, interp%Nc, interp%degree)
161  else
162  print *, '#interp%continuity=', interp%continuity
163  print *, '#possible_value=', sll_p_hermite_1d_c0
164  print *, '#not implemented for the moment'
165  print *, '#in sll_s_compute_interpolants_hermite_1d'
166  stop
167  end if
168  else if ((interp%bc == sll_p_periodic)) then
169  if (interp%continuity == sll_p_hermite_1d_c0) then
170  call hermite_coef_per_1d(f, interp%deriv, interp%Nc, interp%degree)
171  else
172  print *, '#interp%continuity=', interp%continuity
173  print *, '#possible_value=', sll_p_hermite_1d_c0
174  print *, '#not implemented for the moment'
175  print *, '#in sll_s_compute_interpolants_hermite_1d'
176  stop
177  end if
178 
179  else
180 
181  print *, '#interp%bc=', interp%bc
182  print *, '#possible_value=', sll_p_hermite, sll_p_periodic
183  print *, '#not implemented for the moment'
184  print *, '#in sll_s_compute_interpolants_hermite_1d'
185  stop
186  end if
187 
189 
190  subroutine sll_s_compute_w_hermite_1d(w, r, s)
191  sll_int32, intent(in)::r, s
192  sll_real64, dimension(r:s), intent(out)::w
193  sll_int32 ::i, j
194  sll_real64::tmp
195 
196  !maple code for generation of w
197  !for k from r to -1 do
198  ! C[k]:=product((k-j),j=r..k-1)*product((k-j),j=k+1..s):
199  ! C[k]:=1/C[k]*product((-j),j=r..k-1)*product((-j),j=k+1..-1)*product((-j),j=1..s):
200  !od:
201  !for k from 1 to s do
202  ! C[k]:=product((k-j),j=r..k-1)*product((k-j),j=k+1..s):
203  ! C[k]:=1/C[k]*product((-j),j=r..-1)*product((-j),j=1..k-1)*product((-j),j=k+1..s):
204  !od:
205  !C[0]:=-add(C[k],k=r..-1)-add(C[k],k=1..s):
206 
207  do i = r, -1
208  tmp = 1._f64
209  do j = r, i - 1
210  tmp = tmp*real(i - j, f64)
211  end do
212  do j = i + 1, s
213  tmp = tmp*real(i - j, f64)
214  end do
215  tmp = 1._f64/tmp
216  do j = r, i - 1
217  tmp = tmp*real(-j, f64)
218  end do
219  do j = i + 1, -1
220  tmp = tmp*real(-j, f64)
221  end do
222  do j = 1, s
223  tmp = tmp*real(-j, f64)
224  end do
225  w(i) = tmp
226  end do
227 
228  do i = 1, s
229  tmp = 1._f64
230  do j = r, i - 1
231  tmp = tmp*real(i - j, f64)
232  end do
233  do j = i + 1, s
234  tmp = tmp*real(i - j, f64)
235  end do
236  tmp = 1._f64/tmp
237  do j = r, -1
238  tmp = tmp*real(-j, f64)
239  end do
240  do j = 1, i - 1
241  tmp = tmp*real(-j, f64)
242  end do
243  do j = i + 1, s
244  tmp = tmp*real(-j, f64)
245  end do
246  w(i) = tmp
247  end do
248  tmp = 0._f64
249  do i = r, -1
250  tmp = tmp + w(i)
251  end do
252  do i = 1, s
253  tmp = tmp + w(i)
254  end do
255  w(0) = -tmp
256 
257  !print *,'w',w
258  !do ii=r,s
259  ! print *,ii,w(r+s-ii)
260  !enddo
261  !
262 
263  end subroutine sll_s_compute_w_hermite_1d
264 
265  subroutine hermite_coef_per_1d(f, buf2d, N, d)
266  sll_int32, intent(in)::n, d
267  sll_real64, dimension(N + 1), intent(in)::f
268  sll_real64, dimension(3, N + 1), intent(out)::buf2d
269  sll_real64 ::w_left(-d/2:(d + 1)/2), w_right((-d + 1)/2:d/2 + 1)
270  sll_real64 ::tmp
271  sll_int32 ::i, ii, r_left, r_right, s_left, s_right, ind
272  r_left = -d/2
273  s_left = (d + 1)/2
274  r_right = (-d + 1)/2
275  s_right = d/2 + 1
276 
277  call sll_s_compute_w_hermite_1d(w_left, r_left, s_left)
278  if ((2*(d/2) - d) == 0) then
279  w_right(r_right:s_right) = w_left(r_left:s_left)
280  else
281  w_right(r_right:s_right) = -w_left(s_left:r_left:-1)
282  end if
283 
284  do i = 1, n + 1
285  buf2d(1, i) = f(modulo(i - 1 + n, n) + 1) !f(0)
286  tmp = 0._f64
287  do ii = r_left, s_left
288  ind = modulo(i + ii - 1 + n, n) + 1
289  tmp = tmp + w_left(ii)*f(ind)
290  end do
291  buf2d(2, i) = tmp !fx(0)
292  tmp = 0._f64
293  do ii = r_right, s_right
294  ind = modulo(i + ii - 1 + n, n) + 1
295  tmp = tmp + w_right(ii)*f(ind)
296  end do
297  buf2d(3, i) = tmp !fx(1)
298  end do
299 
300  !print *,buf2d(1,N+1)-buf2d(1,1)
301  !print *,buf2d(2,N+1)-buf2d(2,1)
302  !print *,buf2d(3,N+1)-buf2d(3,1)
303 
304  end subroutine hermite_coef_per_1d
305 
306  subroutine hermite_coef_nat_1d(f, buf2d, N, d)
307  sll_int32, intent(in)::n, d
308  sll_real64, dimension(N + 1), intent(in)::f
309  sll_real64, dimension(3, N + 1), intent(out)::buf2d
310  sll_real64 ::w_left(-d/2:(d + 1)/2), w_right((-d + 1)/2:d/2 + 1)
311  sll_real64 ::tmp
312  sll_int32 ::i, ii, r_left, r_right, s_left, s_right, ind
313  r_left = -d/2
314  s_left = (d + 1)/2
315  r_right = (-d + 1)/2
316  s_right = d/2 + 1
317 
318  call sll_s_compute_w_hermite_1d(w_left, r_left, s_left)
319  if ((2*(d/2) - d) == 0) then
320  w_right(r_right:s_right) = w_left(r_left:s_left)
321  else
322  w_right(r_right:s_right) = -w_left(s_left:r_left:-1)
323  end if
324 
325  do i = 1, n + 1
326  buf2d(1, i) = f(i) !f(0)
327  tmp = 0._f64
328  do ii = r_left, s_left
329  !ind=modulo(i+ii-1+N,N)+1
330  ind = i + ii; if (ind > n + 1) ind = 2*(n + 1) - ind; if (ind < 1) ind = 2 - ind
331  tmp = tmp + w_left(ii)*f(ind)
332  end do
333  buf2d(2, i) = tmp !fx(0)
334  tmp = 0._f64
335  do ii = r_right, s_right
336  !ind=modulo(i+ii-1+N,N)+1
337  ind = i + ii; if (ind > n + 1) ind = 2*(n + 1) - ind; if (ind < 1) ind = 2 - ind
338  tmp = tmp + w_right(ii)*f(ind)
339  end do
340  buf2d(3, i) = tmp !fx(1)
341  end do
342 
343  end subroutine hermite_coef_nat_1d
344 
345  function interpolate_value_hermite_per_1d(eta, interp) result(res)
346  sll_real64, intent(in) :: eta
347  type(sll_t_hermite_interpolation_1d), pointer :: interp
348  sll_real64 :: res
349  sll_real64 :: eta_tmp
350  sll_int32 :: ii
351 
352  eta_tmp = eta
353 
354  call localize_per_1d(ii, eta_tmp, interp%eta_min, interp%eta_max, interp%Nc)
355  call interpolate_hermite_1d(interp%deriv, ii, eta_tmp, res, interp%Nc)
356 
358 
359  function sll_f_interpolate_value_hermite_1d(eta, interp) result(res)
360  sll_real64, intent(in) :: eta
361  type(sll_t_hermite_interpolation_1d), pointer :: interp
362  sll_real64 :: res
363  sll_real64 :: eta_tmp
364  sll_int32 :: ii
365 
366  eta_tmp = eta
367  !warning: we should implement localize_1d
368  !but as eta should be inside localize_nat
369  !or localize_per can be used in principle
370  !call localize_nat_1d(ii,eta_tmp,interp%eta_min,interp%eta_max,interp%Nc)
371  call localize_per_1d(ii, eta_tmp, interp%eta_min, interp%eta_max, interp%Nc)
372  call interpolate_hermite_1d(interp%deriv, ii, eta_tmp, res, interp%Nc)
373 
375 
376  function interpolate_value_hermite_nat_1d(eta, interp) result(res)
377  sll_real64, intent(in) :: eta
378  type(sll_t_hermite_interpolation_1d), pointer :: interp
379  sll_real64 :: res
380  sll_real64 :: eta_tmp
381  sll_int32 :: ii
382 
383  eta_tmp = eta
384 
385  call localize_nat_1d(ii, eta_tmp, interp%eta_min, interp%eta_max, interp%Nc)
386  call interpolate_hermite_1d(interp%deriv, ii, eta_tmp, res, interp%Nc)
387 
389 
390  subroutine interpolate_hermite_1d(f, i, x, fval, N)
391  sll_int32, intent(in)::i, n
392  !real(f64),intent(in)::xx(2),xmin(2),xmax(2)
393  sll_real64, intent(in)::x
394  sll_real64, intent(out)::fval
395  sll_real64, dimension(0:2, 0:N)::f
396  !integer::i(2),i1(2),s
397  sll_int32::i1!,s
398  sll_real64::w(0:3)!,tmp(0:3)
399  sll_real64::g(0:3)
400 
401  !fval =f(0,i(1),i(2))!real(i(1),f64)
402 
403  !return
404 
405  w(0) = (2._f64*x + 1)*(1._f64 - x)*(1._f64 - x);
406  w(1) = x*x*(3._f64 - 2._f64*x)
407  w(2) = x*(1._f64 - x)*(1._f64 - x)
408  w(3) = x*x*(x - 1._f64)
409  i1 = i + 1
410 
411  g(0) = f(0, i) !f(0)
412  g(1) = f(0, i1) !f(1)
413  g(2) = f(1, i) !fx(0)
414  g(3) = f(2, i) !fx(1)
415 
416  !print *,'#in hermite:'
417  !print *,'i=',i
418  !print *,'x=',x
419  !print *,'w=',w
420  !print *,'g=',g
421 
422  fval = w(0)*g(0) + w(1)*g(1) + w(2)*g(2) + w(3)*g(3)
423 
424  !print *,fval !,' t',f
425  end subroutine interpolate_hermite_1d
426 
427  subroutine localize_per_1d(i, x, xmin, xmax, N)
428  sll_int32, intent(out)::i
429  sll_real64, intent(inout)::x
430  sll_real64, intent(in)::xmin, xmax
431  sll_int32, intent(in)::n
432  x = (x - xmin)/(xmax - xmin)
433  x = x - real(floor(x), f64)
434  x = x*real(n, f64)
435  i = floor(x)
436  x = x - real(i, f64)
437  if (i == n) then
438  i = 0
439  x = 0._f64
440  end if
441  end subroutine localize_per_1d
442 
443  subroutine localize_nat_1d(i, x, xmin, xmax, N)
444  sll_int32, intent(out)::i
445  sll_real64, intent(inout)::x
446  sll_real64, intent(in)::xmin, xmax
447  sll_int32, intent(in)::n
448  x = (x - xmin)/(xmax - xmin)
449  x = x*real(n, f64)
450  if (x >= real(n, f64)) then
451  x = real(n, f64)
452  end if
453  if (x <= 0._f64) then
454  x = 0._f64
455  end if
456  i = floor(x)
457  x = x - real(i, f64)
458  if (i == n) then
459  i = n - 1
460  x = 1._f64
461  end if
462  end subroutine localize_nat_1d
463 
464 end module
subroutine interpolate_hermite_1d(f, i, x, fval, N)
real(kind=f64) function interpolate_value_hermite_nat_1d(eta, interp)
real(kind=f64) function, public sll_f_interpolate_value_hermite_1d(eta, interp)
real(kind=f64) function interpolate_value_hermite_per_1d(eta, interp)
subroutine, public sll_s_compute_w_hermite_1d(w, r, s)
subroutine initialize_hermite_interpolation_1d(interp, npts, eta_min, eta_max, degree, eta_hermite_continuity, eta_bc_type, const_eta_min_slope, const_eta_max_slope, eta_min_slopes, eta_max_slopes)
type(sll_t_hermite_interpolation_1d) function, pointer, public sll_f_new_hermite_interpolation_1d(npts, eta_min, eta_max, degree, eta_hermite_continuity, eta_bc_type, const_eta_min_slope, const_eta_max_slope, eta_min_slopes, eta_max_slopes)
subroutine localize_per_1d(i, x, xmin, xmax, N)
subroutine, public sll_s_compute_interpolants_hermite_1d(interp, f)
subroutine localize_nat_1d(i, x, xmin, xmax, N)
    Report Typos and Errors