Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_cubic_spline_interpolator_1d.F90
Go to the documentation of this file.
1 !**************************************************************
2 ! Copyright INRIA
3 ! Authors :
4 ! CALVI project team
5 !
6 ! This code SeLaLib (for Semi-Lagrangian-Library)
7 ! is a parallel library for simulating the plasma turbulence
8 ! in a tokamak.
9 !
10 ! This software is governed by the CeCILL-B license
11 ! under French law and abiding by the rules of distribution
12 ! of free software. You can use, modify and redistribute
13 ! the software under the terms of the CeCILL-B license as
14 ! circulated by CEA, CNRS and INRIA at the following URL
15 ! "http://www.cecill.info".
16 !**************************************************************
17 
27 
28 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
29 #include "sll_assert.h"
30 #include "sll_errors.h"
31 #include "sll_memory.h"
32 #include "sll_working_precision.h"
33 
35  sll_p_periodic
36 
37  use sll_m_cubic_splines, only: &
47 
48  use sll_m_interpolators_1d_base, only: &
50 
51  implicit none
52 
53  public :: &
57 
58  private
59 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
60 
63 
64  sll_real64, dimension(:), pointer :: interpolation_points
65  sll_int32 :: num_points
66  sll_int32 :: bc_type
67  type(sll_t_cubic_spline_1d) :: spline
68 
69  contains
70 
71  procedure :: init => initialize_cs1d_interpolator
72  procedure :: compute_interpolants => compute_interpolants_cs1d
73  procedure :: interpolate_from_interpolant_value => interpolate_value_cs1d
74  procedure :: interpolate_from_interpolant_derivative_eta1 => interpolate_deriv1_cs1d
75  procedure :: interpolate_from_interpolant_array => interpolate_values_cs1d
76  procedure :: interpolate_from_interpolant_derivatives_eta1 => interpolate_derivatives_cs1d
77  procedure :: interpolate_array => spline_interpolate1d
78  procedure :: interpolate_array_disp => spline_interpolate1d_disp
79  procedure :: interpolate_array_disp_inplace => spline_interpolate1d_disp_inplace
80  procedure :: set_coefficients => set_coefficients_cs1d
81  procedure :: get_coefficients => get_coefficients_cs1d
82 
84 
87  type(sll_t_cubic_spline_interpolator_1d), pointer :: interp
89 
91  interface sll_o_delete
92  module procedure delete_cs1d
93  end interface sll_o_delete
94 
95 contains ! ****************************************************************
96 
97  subroutine spline_interpolate1d(this, num_pts, data, coordinates, output_array)
98 
99  class(sll_t_cubic_spline_interpolator_1d), intent(inout) :: this
100  sll_int32, intent(in) :: num_pts
101  sll_real64, dimension(num_pts), intent(in) :: coordinates
102  sll_real64, dimension(:), intent(in) :: data
103  sll_real64, dimension(num_pts), intent(out) :: output_array
104 
105  call sll_s_cubic_spline_1d_compute_interpolant(data, this%spline)
106  call sll_s_cubic_spline_1d_eval_array(coordinates, output_array, num_pts, &
107  this%spline)
108 
109  end subroutine spline_interpolate1d
110 
112  subroutine spline_interpolate1d_disp(this, num_pts, data, alpha, output_array)
113  class(sll_t_cubic_spline_interpolator_1d), intent(inout) :: this
114  !class(sll_t_cubic_spline_1d), intent(in) :: this
115  sll_int32, intent(in) :: num_pts
116  sll_real64, intent(in) :: alpha
117  sll_real64, dimension(:), intent(in) :: data
118  sll_real64, dimension(num_pts), intent(out) :: output_array
119 
120  ! Compute the interpolating spline coefficients
121  call sll_s_cubic_spline_1d_compute_interpolant(data, this%spline)
122 
123  ! Evaluate spline at displaced grid points
124  call sll_s_cubic_spline_1d_eval_disp(this%spline, alpha, output_array)
125 
126  end subroutine spline_interpolate1d_disp
127 
128  subroutine spline_interpolate1d_disp_inplace(this, num_pts, data, alpha)
129  class(sll_t_cubic_spline_interpolator_1d), intent(inout) :: this
130  !class(sll_t_cubic_spline_1d), intent(in) :: this
131  sll_int32, intent(in) :: num_pts
132  sll_real64, intent(in) :: alpha
133  sll_real64, dimension(num_pts), intent(inout) :: data
134 
135  ! local variables
136  sll_real64, dimension(num_pts) :: coordinates
137  sll_real64 :: length, delta
138  sll_real64 :: xmin, xmax
139  sll_int32 :: i
140  ! compute the interpolating spline coefficients
141  call sll_s_cubic_spline_1d_compute_interpolant(data, this%spline)
142  ! compute array of coordinates where interpolation is performed from displacement
143  length = this%interpolation_points(this%num_points) - &
144  this%interpolation_points(1)
145  delta = this%interpolation_points(2) - this%interpolation_points(1)
146  xmin = this%interpolation_points(1)
147  xmax = this%interpolation_points(this%num_points)
148  if (this%bc_type == sll_p_periodic) then
149  ! The case alpha = 0.0 is problematic. We need to further try to make
150  ! this computation in general m re efficient, minimize the use of modulo
151  ! and even explore a uniform grid representation...
152  if (alpha == 0.0_f64) then
153  coordinates(:) = this%interpolation_points(:)
154  else ! alpha != 0.0
155  do i = 1, num_pts
156  coordinates(i) = xmin + &
157  modulo(this%interpolation_points(i) - xmin + alpha, length)
158 !!$ write (*,'(a,z,f21.16,a,i,a,z,f21.16)') 'xmin = ', &
159 !!$ xmin, xmin, ' coordinates(',i,') = ', coordinates(i), &
160 !!$ coordinates(i)
161  sll_assert(coordinates(i) >= xmin)
162  sll_assert(coordinates(i) <= xmax)
163  end do
164  end if
165  else ! any other BC? better a case statement
166  if (alpha < 0) then
167  do i = 1, num_pts
168  coordinates(i) = max(this%interpolation_points(i) + alpha, xmin)
169  sll_assert((xmin <= coordinates(i)) .and. (coordinates(i) <= xmax))
170  end do
171  else
172  do i = 1, num_pts
173  coordinates(i) = min(this%interpolation_points(i) + alpha, xmax)
174  sll_assert((xmin <= coordinates(i)) .and. (coordinates(i) <= xmax))
175  end do
176  end if
177  end if
178  call sll_s_cubic_spline_1d_eval_array(coordinates, data, num_pts, &
179  this%spline)
180  end subroutine spline_interpolate1d_disp_inplace
181 
182  subroutine compute_interpolants_cs1d(interpolator, data_array, &
183  eta_coords, &
184  size_eta_coords)
185  class(sll_t_cubic_spline_interpolator_1d), intent(inout) :: interpolator
186  sll_real64, dimension(:), intent(in) :: data_array
187  sll_real64, dimension(:), intent(in), optional :: eta_coords
188  sll_int32, intent(in), optional :: size_eta_coords
189 
190  if (present(eta_coords) .or. present(size_eta_coords)) then
191  sll_error('compute_interpolants_cs1d', 'This case is not yet implemented')
192  end if
193 
194  call sll_s_cubic_spline_1d_compute_interpolant(data_array, interpolator%spline)
195 
196  end subroutine compute_interpolants_cs1d
197 
198  ! Alternative implementation for the function meant to interpolate a
199  ! whole array. This implementation fixes some problems in the previous
200  ! function. Furthermore, it separates the operation into the more
201  ! elementary steps: one is supposed to first compute the interpolants,
202  ! then request to interpolate array values.
204  interpolator, &
205  num_pts, &
206  vals_to_interpolate, &
207  output_array)
208  class(sll_t_cubic_spline_interpolator_1d), intent(inout) :: interpolator
209  sll_int32, intent(in) :: num_pts
210  sll_real64, dimension(num_pts), intent(in) :: vals_to_interpolate
211  sll_real64, dimension(num_pts), intent(out) :: output_array
212  call sll_s_cubic_spline_1d_eval_array(vals_to_interpolate, output_array, &
213  num_pts, interpolator%spline)
214  end subroutine interpolate_values_cs1d
215 
217  interpolator, &
218  num_pts, &
219  vals_to_interpolate, &
220  output_array)
221  class(sll_t_cubic_spline_interpolator_1d), intent(in) :: interpolator
222  sll_int32, intent(in) :: num_pts
223  sll_real64, dimension(:), intent(in) :: vals_to_interpolate
224  sll_real64, dimension(:), intent(out) :: output_array
225  call sll_s_cubic_spline_1d_eval_array_deriv(vals_to_interpolate, output_array, &
226  num_pts, interpolator%spline)
227  end subroutine interpolate_derivatives_cs1d
228 
229  function interpolate_value_cs1d(interpolator, eta1) result(val)
230  class(sll_t_cubic_spline_interpolator_1d), intent(in) :: interpolator
231  sll_real64 :: val
232  sll_real64, intent(in) :: eta1
233  val = sll_f_cubic_spline_1d_eval(eta1, interpolator%spline)
234  end function
235 
236  function interpolate_deriv1_cs1d(interpolator, eta1) result(val)
237  class(sll_t_cubic_spline_interpolator_1d), intent(in) :: interpolator
238  sll_real64 :: val
239  sll_real64, intent(in) :: eta1
240  val = sll_f_cubic_spline_1d_eval_deriv(eta1, interpolator%spline)
241  end function interpolate_deriv1_cs1d
242 
243 !PN DEFINED BUT NOT USED
244 ! function interpolate_derivative_f95( interpolator, eta1 ) result(val)
245 ! class(sll_t_cubic_spline_interpolator_1d), intent(in) :: interpolator
246 ! sll_real64 :: val
247 ! sll_real64, intent(in) :: eta1
248 ! val = sll_f_cubic_spline_1d_eval_deriv(eta1,interpolator%spline)
249 ! end function interpolate_derivative_f95
250 
253  num_points, &
254  xmin, &
255  xmax, &
256  bc_type, &
257  slope_left, &
258  slope_right, &
259  fast_algorithm) result(res)
260 
261  type(sll_t_cubic_spline_interpolator_1d), pointer :: res
262  sll_int32, intent(in) :: num_points
263  sll_real64, intent(in) :: xmin
264  sll_real64, intent(in) :: xmax
265  sll_int32, intent(in) :: bc_type
266  sll_real64, intent(in), optional :: slope_left
267  sll_real64, intent(in), optional :: slope_right
268  logical, intent(in), optional :: fast_algorithm
269 
270  sll_int32 :: ierr
271  sll_allocate(res, ierr)
272 
273  if (present(slope_left) .and. present(slope_right)) then
274  if (present(fast_algorithm)) then
276  res, &
277  num_points, &
278  xmin, &
279  xmax, &
280  bc_type, &
281  slope_left, &
282  slope_right, &
283  fast_algorithm)
284  else
286  res, &
287  num_points, &
288  xmin, &
289  xmax, &
290  bc_type, &
291  slope_left, &
292  slope_right)
293  end if
294  elseif (present(fast_algorithm)) then
296  res, &
297  num_points, &
298  xmin, &
299  xmax, &
300  bc_type, &
301  fast_algorithm=fast_algorithm)
302  else
304  res, &
305  num_points, &
306  xmin, &
307  xmax, &
308  bc_type)
309  end if
310 
312 
313  ! Why is the name of this function changing depending on the standard?
314  ! only one will be compiled anyway!!
315 
318  interpolator, &
319  num_points, &
320  xmin, &
321  xmax, &
322  bc_type, &
323  slope_left, &
324  slope_right, &
325  fast_algorithm)
326 
327  class(sll_t_cubic_spline_interpolator_1d), intent(inout) :: interpolator
328  sll_int32, intent(in) :: num_points
329  sll_real64, intent(in) :: xmin
330  sll_real64, intent(in) :: xmax
331  sll_int32, intent(in) :: bc_type
332  sll_real64, intent(in), optional :: slope_left
333  sll_real64, intent(in), optional :: slope_right
334  logical, intent(in), optional :: fast_algorithm
335  sll_int32 :: ierr
336  sll_int32 :: i
337  sll_real64 :: delta
338 
339  interpolator%num_points = num_points
340  sll_allocate(interpolator%interpolation_points(num_points), ierr)
341  interpolator%interpolation_points(1) = xmin
342  delta = (xmax - xmin)/(num_points - 1)
343  do i = 2, num_points
344  interpolator%interpolation_points(i) = &
345  interpolator%interpolation_points(i - 1) + delta
346  end do
347  interpolator%interpolation_points(num_points) = xmax
348  interpolator%bc_type = bc_type
349  if (present(slope_left) .and. present(slope_right)) then
350  if (present(fast_algorithm)) then
352  interpolator%spline, &
353  num_points, &
354  xmin, xmax, &
355  bc_type, &
356  slope_left, &
357  slope_right, &
358  fast_algorithm)
359  else
361  interpolator%spline, &
362  num_points, &
363  xmin, xmax, &
364  bc_type, &
365  slope_left, &
366  slope_right)
367  end if
368  elseif (present(fast_algorithm)) then
370  interpolator%spline, &
371  num_points, &
372  xmin, xmax, &
373  bc_type, &
374  fast_algorithm=fast_algorithm)
375  else
377  interpolator%spline, &
378  num_points, xmin, xmax, bc_type)
379  end if
380 
381  end subroutine
382 
383  subroutine delete_cs1d(obj)
385  call sll_s_cubic_spline_1d_free(obj%spline)
386  end subroutine delete_cs1d
387 
388  subroutine set_coefficients_cs1d(interpolator, coeffs)
389  class(sll_t_cubic_spline_interpolator_1d), intent(inout) :: interpolator
390  sll_real64, dimension(:), intent(in), optional :: coeffs
391  print *, '#set_coefficients_cs1d(): ERROR: This function has not been ', &
392  'implemented yet.'
393  if (present(coeffs)) then
394  print *, '#coefs are present'
395  end if
396  print *, interpolator%num_points
397  stop
398  end subroutine set_coefficients_cs1d
399 
400  function get_coefficients_cs1d(interpolator)
401  class(sll_t_cubic_spline_interpolator_1d), intent(in) :: interpolator
402  sll_real64, dimension(:), pointer :: get_coefficients_cs1d
403 
404  print *, 'get_coefficients_cs1d(): ERROR: This function has not been ', &
405  'implemented yet.'
406  get_coefficients_cs1d => null()
407  print *, interpolator%num_points
408  stop
409  end function get_coefficients_cs1d
410 
Interpolator 1d using cubic splines on regular mesh.
subroutine compute_interpolants_cs1d(interpolator, data_array, eta_coords, size_eta_coords)
subroutine set_coefficients_cs1d(interpolator, coeffs)
real(kind=f64) function, dimension(:), pointer get_coefficients_cs1d(interpolator)
subroutine interpolate_values_cs1d(interpolator, num_pts, vals_to_interpolate, output_array)
subroutine spline_interpolate1d_disp_inplace(this, num_pts, data, alpha)
subroutine initialize_cs1d_interpolator(interpolator, num_points, xmin, xmax, bc_type, slope_left, slope_right, fast_algorithm)
initialize cubic spline interpolator
real(kind=f64) function interpolate_deriv1_cs1d(interpolator, eta1)
subroutine spline_interpolate1d(this, num_pts, data, coordinates, output_array)
subroutine spline_interpolate1d_disp(this, num_pts, data, alpha, output_array)
Computes the interpolated values at each grid point replaced by alpha using cubic spline interpolatio...
real(kind=f64) function interpolate_value_cs1d(interpolator, eta1)
type(sll_t_cubic_spline_interpolator_1d) function, pointer, public sll_f_new_cubic_spline_interpolator_1d(num_points, xmin, xmax, bc_type, slope_left, slope_right, fast_algorithm)
subroutine interpolate_derivatives_cs1d(interpolator, num_pts, vals_to_interpolate, output_array)
Provides capabilities for data and derivative interpolation with cubic B-splines and different bounda...
real(kind=f64) function, public sll_f_cubic_spline_1d_eval_deriv(x, spline)
returns the value of the derivative at the image of the abscissa 'x', using the spline coefficients s...
subroutine, public sll_s_cubic_spline_1d_compute_interpolant(f, spline)
Computes the cubic spline coefficients corresponding to the 1D data array 'f'.
subroutine, public sll_s_cubic_spline_1d_init(self, num_points, xmin, xmax, bc_type, sl, sr, fast_algorithm)
Returns a pointer to a heap-allocated cubic spline object.
subroutine, public sll_s_cubic_spline_1d_eval_disp(spline, alpha, output_array)
Computes the interpolated values at each grid point replaced by alpha for the precomputed spline coef...
subroutine, public sll_s_cubic_spline_1d_eval_array(a_in, a_out, n, spline)
returns the values of the images of a collection of abscissae, represented by a 1D array in another o...
subroutine, public sll_s_cubic_spline_1d_eval_array_deriv(array_in, array_out, num_pts, spline)
returns the values of the derivatives evaluated at a collection of abscissae stored in the input 1D a...
real(kind=f64) function, public sll_f_cubic_spline_1d_eval(x, spline)
returns the value of the interpolated image of the abscissa x, using the spline coefficients stored i...
subroutine, public sll_s_cubic_spline_1d_free(spline)
deallocate the sll_t_cubic_spline_1d object
Module for 1D interpolation and reconstruction.
basic type for one-dimensional cubic spline data.
Abstract class for 1D interpolation and reconstruction.
    Report Typos and Errors