8 #include "sll_assert.h"
9 #include "sll_errors.h"
29 real(
wp),
private :: inv_dx
34 procedure :: find_cell => f_bsplines_uniform__find_cell
35 procedure :: eval_basis => s_bsplines_uniform__eval_basis
36 procedure :: eval_deriv => s_bsplines_uniform__eval_deriv
37 procedure :: eval_basis_and_n_derivs => s_bsplines_uniform__eval_basis_and_n_derivs
50 sll_pure
subroutine s_bsplines_uniform__get_icell_and_offset(self, x, icell, x_offset)
52 real(
wp),
intent(in) :: x
53 integer,
intent(out) :: icell
54 real(
wp),
intent(out) :: x_offset
56 sll_assert(x >= self%xmin)
57 sll_assert(x <= self%xmax)
59 if (x == self%xmin) then; icell = 1; x_offset = 0.0_wp
60 else if (x == self%xmax) then; icell = self%ncells; x_offset = 1.0_wp
62 x_offset = (x - self%xmin)*self%inv_dx
64 x_offset = x_offset - real(icell,
wp)
70 if (icell == self%ncells + 1 .and. x_offset == 0.0_wp)
then
75 end subroutine s_bsplines_uniform__get_icell_and_offset
88 integer,
intent(in) :: degree
89 logical,
intent(in) :: periodic
90 real(wp),
intent(in) :: xmin
91 real(wp),
intent(in) :: xmax
92 integer,
intent(in) :: ncells
96 self%periodic = periodic
99 self%nbasis = merge(ncells, ncells + degree, periodic)
104 self%inv_dx = real(ncells, wp)/(xmax - xmin)
122 sll_pure
function f_bsplines_uniform__find_cell(self, x)
result(icell)
124 real(wp),
intent(in) :: x
131 end function f_bsplines_uniform__find_cell
142 sll_pure
subroutine s_bsplines_uniform__eval_basis(self, x, values, jmin)
144 real(wp),
intent(in) :: x
145 real(wp),
intent(out) :: values(0:)
146 integer,
intent(out) :: jmin
158 sll_assert(
size(values) == 1 + self%degree)
161 call s_bsplines_uniform__get_icell_and_offset(self, x, icell, x_offset)
167 associate(bspl => values, spline_degree => self%degree)
170 do j = 1, spline_degree
176 temp = bspl(r)*
inv(j)
177 bspl(r) = saved + xx*temp
178 saved = (j_real - xx)*temp
185 end subroutine s_bsplines_uniform__eval_basis
196 sll_pure
subroutine s_bsplines_uniform__eval_deriv(self, x, derivs, jmin)
198 real(wp),
intent(in) :: x
199 real(wp),
intent(out) :: derivs(0:)
200 integer,
intent(out) :: jmin
214 sll_assert(
size(derivs) == 1 + self%degree)
217 call s_bsplines_uniform__get_icell_and_offset(self, x, icell, x_offset)
224 associate(bspl => derivs, spline_degree => self%degree, start => self%inv_dx)
228 do j = 1, spline_degree - 1
234 temp = bspl(r)*
inv(j)
235 bspl(r) = saved + xx*temp
236 saved = (j_real - xx)*temp
245 do j = 1, spline_degree - 1
250 bspl(spline_degree) = bj
254 end subroutine s_bsplines_uniform__eval_deriv
266 sll_pure
subroutine s_bsplines_uniform__eval_basis_and_n_derivs(self, x, n, derivs, jmin)
268 real(wp),
intent(in) :: x
269 integer,
intent(in) :: n
270 real(wp),
intent(out) :: derivs(0:, 0:)
271 integer,
intent(out) :: jmin
282 integer :: k, s1, s2, rk, pk, j1, j2
286 real(wp) :: ndu(0:self%degree, 0:self%degree)
287 real(wp) :: a(0:1, 0:self%degree)
291 sll_assert(
size(derivs, 1) == 1 + n)
292 sll_assert(
size(derivs, 2) == 1 + self%degree)
295 call s_bsplines_uniform__get_icell_and_offset(self, x, icell, x_offset)
302 associate(spline_degree => self%degree, bspl => derivs)
305 do j = 1, spline_degree
311 temp = ndu(r, j - 1)*
inv(j)
312 ndu(r, j) = saved + xx*temp
313 saved = (j_real - xx)*temp
317 bspl(0, :) = ndu(:, spline_degree)
322 associate(deg => self%degree, bsdx => derivs)
333 a(s2, 0) = a(s1, 0)*
inv(pk + 1)
334 d = a(s2, 0)*ndu(rk, pk)
341 if (r - 1 <= pk)
then
347 a(s2, j) = (a(s1, j) - a(s1, j - 1))*
inv(pk + 1)
348 d = d + a(s2, j)*ndu(rk + j, pk)
351 a(s2, k) = -a(s1, k - 1)*
inv(pk + 1)
352 d = d + a(s2, k)*ndu(r, pk)
364 d = real(deg,
wp)*self%inv_dx
366 bsdx(k, :) = bsdx(k, :)*d
367 d = d*real(deg - k,
wp)*self%inv_dx
372 end subroutine s_bsplines_uniform__eval_basis_and_n_derivs
Abstract class for B-splines of arbitrary degree.
Module to select the kind parameter.
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
Abstract type, B-splines.