Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_spline_2d.F90
Go to the documentation of this file.
1 
25 
27 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
28 #include "sll_assert.h"
29 
30  use sll_m_working_precision, only: f64
32 
33  implicit none
34 
35  public :: &
37 
38  private
39 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
40 
42  integer, parameter :: wp = f64
43 
46 
47  real(wp), allocatable :: bcoef(:, :)
48  class(sll_c_bsplines), pointer, private :: bspl1 => null()
49  class(sll_c_bsplines), pointer, private :: bspl2 => null()
50 
51  contains
52 
53  procedure :: init => s_spline_2d__init
54  procedure :: free => s_spline_2d__free
55  procedure :: belongs_to_space => f_spline_2d__belongs_to_space
56  procedure :: eval => f_spline_2d__eval
57  procedure :: eval_deriv_x1 => f_spline_2d__eval_deriv_x1
58  procedure :: eval_deriv_x2 => f_spline_2d__eval_deriv_x2
59  procedure :: eval_deriv_x1x2 => f_spline_2d__eval_deriv_x1x2
60  procedure :: eval_array => s_spline_2d__eval_array
61  procedure :: eval_array_deriv_x1 => s_spline_2d__eval_array_deriv_x1
62  procedure :: eval_array_deriv_x2 => s_spline_2d__eval_array_deriv_x2
63  procedure :: eval_array_deriv_x1x2 => s_spline_2d__eval_array_deriv_x1x2
64 
65  end type sll_t_spline_2d
66 
67 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
68 contains
69 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
70 
71  !-----------------------------------------------------------------------------
76  !-----------------------------------------------------------------------------
77  subroutine s_spline_2d__init(self, bsplines_x1, bsplines_x2)
78 
79  class(sll_t_spline_2d), intent(out) :: self
80  class(sll_c_bsplines), intent(in), target :: bsplines_x1
81  class(sll_c_bsplines), intent(in), target :: bsplines_x2
82 
83  ! Store pointer to B-splines
84  self%bspl1 => bsplines_x1
85  self%bspl2 => bsplines_x2
86 
87  ! Allocate array of spline coefficients: in case of periodic BCs, the last
88  ! p coefficients are a periodic copy of the first p ones (p=p1,p2)
89  associate(n1 => bsplines_x1%ncells, &
90  n2 => bsplines_x2%ncells, &
91  p1 => bsplines_x1%degree, &
92  p2 => bsplines_x2%degree)
93 
94  allocate (self%bcoef(1:n1 + p1, 1:n2 + p2))
95 
96  end associate
97 
98  ! Set all coefficients to zero
99  self%bcoef = 0.0_f64
100 
101  end subroutine s_spline_2d__init
102 
103  !-----------------------------------------------------------------------------
106  !-----------------------------------------------------------------------------
107  subroutine s_spline_2d__free(self)
108 
109  class(sll_t_spline_2d), intent(inout) :: self
110 
111  deallocate (self%bcoef)
112  nullify (self%bspl1)
113  nullify (self%bspl2)
114 
115  end subroutine s_spline_2d__free
116 
117  !-----------------------------------------------------------------------------
123  !-----------------------------------------------------------------------------
124  sll_pure function f_spline_2d__belongs_to_space(self, bsplines_x1, bsplines_x2) result(in_space)
125 
126  class(sll_t_spline_2d), intent(in) :: self
127  class(sll_c_bsplines), intent(in), target :: bsplines_x1
128  class(sll_c_bsplines), intent(in), target :: bsplines_x2
129  logical :: in_space
130 
131  in_space = associated(self%bspl1, bsplines_x1) .and. &
132  associated(self%bspl2, bsplines_x2)
133 
134  end function f_spline_2d__belongs_to_space
135 
136  !-----------------------------------------------------------------------------
142  !-----------------------------------------------------------------------------
143  sll_pure function f_spline_2d__eval(self, x1, x2) result(y)
144 
145  class(sll_t_spline_2d), intent(in) :: self
146  real(wp), intent(in) :: x1
147  real(wp), intent(in) :: x2
148  real(wp) :: y
149 
150  integer :: jmin(2)
151  integer :: jmax(2)
152  integer :: k1, k2
153 
154  ! Automatic arrays
155  real(wp) :: values1(1:self%bspl1%degree + 1)
156  real(wp) :: values2(1:self%bspl2%degree + 1)
157 
158  ! Compute arrays v1 and v2 of B-spline values
159  call self%bspl1%eval_basis(x1, values1, jmin(1))
160  call self%bspl2%eval_basis(x2, values2, jmin(2))
161 
162  jmax(1) = jmin(1) + self%bspl1%degree
163  jmax(2) = jmin(2) + self%bspl2%degree
164 
165  ! Determine (matrix) block C of B-spline coefficients to be used
166  ! and compute scalar product <v1,v2> = (v1^T)*C*v2
167  associate(bcoef => self%bcoef(jmin(1):jmax(1), jmin(2):jmax(2)))
168  y = 0.0_f64
169  do k2 = 1, 1 + self%bspl2%degree
170  do k1 = 1, 1 + self%bspl1%degree
171  y = y + bcoef(k1, k2)*values1(k1)*values2(k2)
172  end do
173  end do
174  end associate
175 
176  end function f_spline_2d__eval
177 
178  !-----------------------------------------------------------------------------
184  !-----------------------------------------------------------------------------
185  sll_pure function f_spline_2d__eval_deriv_x1(self, x1, x2) result(y)
186 
187  class(sll_t_spline_2d), intent(in) :: self
188  real(wp), intent(in) :: x1
189  real(wp), intent(in) :: x2
190  real(wp) :: y
191 
192  integer :: jmin(2)
193  integer :: jmax(2)
194  integer :: k1, k2
195 
196  ! Automatic arrays
197  real(wp) :: derivs1(1:self%bspl1%degree + 1)
198  real(wp) :: values2(1:self%bspl2%degree + 1)
199 
200  ! Compute arrays d1 and v2 of B-spline derivatives/values
201  call self%bspl1%eval_deriv(x1, derivs1, jmin(1))
202  call self%bspl2%eval_basis(x2, values2, jmin(2))
203 
204  jmax(1) = jmin(1) + self%bspl1%degree
205  jmax(2) = jmin(2) + self%bspl2%degree
206 
207  ! Determine (matrix) block C of B-spline coefficients to be used
208  ! and compute scalar product <d1,v2> = (d1^T)*C*v2
209  associate(bcoef => self%bcoef(jmin(1):jmax(1), jmin(2):jmax(2)))
210  y = 0.0_f64
211  do k2 = 1, 1 + self%bspl2%degree
212  do k1 = 1, 1 + self%bspl1%degree
213  y = y + bcoef(k1, k2)*derivs1(k1)*values2(k2)
214  end do
215  end do
216  end associate
217 
218  end function f_spline_2d__eval_deriv_x1
219 
220  !-----------------------------------------------------------------------------
226  !-----------------------------------------------------------------------------
227  sll_pure function f_spline_2d__eval_deriv_x2(self, x1, x2) result(y)
228 
229  class(sll_t_spline_2d), intent(in) :: self
230  real(wp), intent(in) :: x1
231  real(wp), intent(in) :: x2
232  real(wp) :: y
233 
234  integer :: jmin(2)
235  integer :: jmax(2)
236  integer :: k1, k2
237 
238  ! Automatic arrays
239  real(wp) :: values1(1:self%bspl1%degree + 1)
240  real(wp) :: derivs2(1:self%bspl2%degree + 1)
241 
242  ! Compute arrays v1 and d2 of B-spline values/derivatives
243  call self%bspl1%eval_basis(x1, values1, jmin(1))
244  call self%bspl2%eval_deriv(x2, derivs2, jmin(2))
245 
246  jmax(1) = jmin(1) + self%bspl1%degree
247  jmax(2) = jmin(2) + self%bspl2%degree
248 
249  ! Determine (matrix) block C of B-spline coefficients to be used
250  ! and compute scalar product <v1,d2> = (v1^T)*C*d2
251  associate(bcoef => self%bcoef(jmin(1):jmax(1), jmin(2):jmax(2)))
252  y = 0.0_f64
253  do k2 = 1, 1 + self%bspl2%degree
254  do k1 = 1, 1 + self%bspl1%degree
255  y = y + bcoef(k1, k2)*values1(k1)*derivs2(k2)
256  end do
257  end do
258  end associate
259 
260  end function f_spline_2d__eval_deriv_x2
261 
262  !-----------------------------------------------------------------------------
268  !-----------------------------------------------------------------------------
269  sll_pure function f_spline_2d__eval_deriv_x1x2(self, x1, x2) result(y)
270 
271  class(sll_t_spline_2d), intent(in) :: self
272  real(wp), intent(in) :: x1
273  real(wp), intent(in) :: x2
274  real(wp) :: y
275 
276  integer :: jmin(2)
277  integer :: jmax(2)
278  integer :: k1, k2
279 
280  ! Automatic arrays
281  real(wp) :: derivs1(1:self%bspl1%degree + 1)
282  real(wp) :: derivs2(1:self%bspl2%degree + 1)
283 
284  ! Compute arrays d1 and d2 of B-spline values/derivatives
285  call self%bspl1%eval_deriv(x1, derivs1, jmin(1))
286  call self%bspl2%eval_deriv(x2, derivs2, jmin(2))
287 
288  jmax(1) = jmin(1) + self%bspl1%degree
289  jmax(2) = jmin(2) + self%bspl2%degree
290 
291  ! Determine (matrix) block C of B-spline coefficients to be used
292  ! and compute scalar product <d1,d2> = (d1^T)*C*d2
293  associate(bcoef => self%bcoef(jmin(1):jmax(1), jmin(2):jmax(2)))
294  y = 0.0_f64
295  do k2 = 1, 1 + self%bspl2%degree
296  do k1 = 1, 1 + self%bspl1%degree
297  y = y + bcoef(k1, k2)*derivs1(k1)*derivs2(k2)
298  end do
299  end do
300  end associate
301 
302  end function f_spline_2d__eval_deriv_x1x2
303 
304  !-----------------------------------------------------------------------------
310  !-----------------------------------------------------------------------------
311  sll_pure subroutine s_spline_2d__eval_array(self, x1, x2, y)
312 
313  class(sll_t_spline_2d), intent(in) :: self
314  real(wp), intent(in) :: x1(:, :)
315  real(wp), intent(in) :: x2(:, :)
316  real(wp), intent(out) :: y(:, :)
317 
318  integer :: i1, i2
319 
320  sll_assert(size(x1, 1) == size(y, 1))
321  sll_assert(size(x1, 2) == size(y, 2))
322  sll_assert(size(x2, 1) == size(y, 1))
323  sll_assert(size(x2, 2) == size(y, 2))
324 
325  do i2 = 1, size(x2, 2)
326  do i1 = 1, size(x1, 1)
327  y(i1, i2) = f_spline_2d__eval(self, x1(i1, i2), x2(i1, i2))
328  end do
329  end do
330 
331  end subroutine s_spline_2d__eval_array
332 
333  !-----------------------------------------------------------------------------
340  !-----------------------------------------------------------------------------
341  sll_pure subroutine s_spline_2d__eval_array_deriv_x1(self, x1, x2, y)
342 
343  class(sll_t_spline_2d), intent(in) :: self
344  real(wp), intent(in) :: x1(:, :)
345  real(wp), intent(in) :: x2(:, :)
346  real(wp), intent(out) :: y(:, :)
347 
348  integer :: i1, i2
349 
350  sll_assert(size(x1, 1) == size(y, 1))
351  sll_assert(size(x1, 2) == size(y, 2))
352  sll_assert(size(x2, 1) == size(y, 1))
353  sll_assert(size(x2, 2) == size(y, 2))
354 
355  do i2 = 1, size(x2, 2)
356  do i1 = 1, size(x1, 1)
357  y(i1, i2) = f_spline_2d__eval_deriv_x1(self, x1(i1, i2), x2(i1, i2))
358  end do
359  end do
360 
361  end subroutine s_spline_2d__eval_array_deriv_x1
362 
363  !-----------------------------------------------------------------------------
370  !-----------------------------------------------------------------------------
371  sll_pure subroutine s_spline_2d__eval_array_deriv_x2(self, x1, x2, y)
372 
373  class(sll_t_spline_2d), intent(in) :: self
374  real(wp), intent(in) :: x1(:, :)
375  real(wp), intent(in) :: x2(:, :)
376  real(wp), intent(out) :: y(:, :)
377 
378  integer :: i1, i2
379 
380  sll_assert(size(x1, 1) == size(y, 1))
381  sll_assert(size(x1, 2) == size(y, 2))
382  sll_assert(size(x2, 1) == size(y, 1))
383  sll_assert(size(x2, 2) == size(y, 2))
384 
385  do i2 = 1, size(x2, 2)
386  do i1 = 1, size(x1, 1)
387  y(i1, i2) = f_spline_2d__eval_deriv_x2(self, x1(i1, i2), x2(i1, i2))
388  end do
389  end do
390 
391  end subroutine s_spline_2d__eval_array_deriv_x2
392 
393  !-----------------------------------------------------------------------------
400  !-----------------------------------------------------------------------------
401  sll_pure subroutine s_spline_2d__eval_array_deriv_x1x2(self, x1, x2, y)
402 
403  class(sll_t_spline_2d), intent(in) :: self
404  real(wp), intent(in) :: x1(:, :)
405  real(wp), intent(in) :: x2(:, :)
406  real(wp), intent(out) :: y(:, :)
407 
408  integer :: i1, i2
409 
410  sll_assert(size(x1, 1) == size(y, 1))
411  sll_assert(size(x1, 2) == size(y, 2))
412  sll_assert(size(x2, 1) == size(y, 1))
413  sll_assert(size(x2, 2) == size(y, 2))
414 
415  do i2 = 1, size(x2, 2)
416  do i1 = 1, size(x1, 1)
417  y(i1, i2) = f_spline_2d__eval_deriv_x1x2(self, x1(i1, i2), x2(i1, i2))
418  end do
419  end do
420 
421  end subroutine s_spline_2d__eval_array_deriv_x1x2
422 
423 end module sll_m_spline_2d
Abstract class for B-splines of arbitrary degree.
Module for tensor-product 2D splines.
subroutine s_spline_2d__free(self)
Destroy 2D spline (re-initialization is possible afterwards)
integer, parameter wp
Working precision.
subroutine s_spline_2d__init(self, bsplines_x1, bsplines_x2)
Initialize 2D spline object as element of span(B-splines)
Module to select the kind parameter.
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
2D tensor-product spline
    Report Typos and Errors