!>
!> @file bsplvd.f90
!>
!> @brief
!>
!> @copyright
!> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
!> SPC (Swiss Plasma Center)
!>
!> SPClibs is free software: you can redistribute it and/or modify it under
!> the terms of the GNU Lesser General Public License as published by the Free
!> Software Foundation, either version 3 of the License, or (at your option)
!> any later version.
!>
!> SPClibs is distributed in the hope that it will be useful, but WITHOUT ANY
!> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
!> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
!>
!> You should have received a copy of the GNU Lesser General Public License
!> along with this program. If not, see .
!>
!> @author
!> (in alphabetical order)
!> @author Trach-Minh Tran
!>
subroutine bsplvd ( t, k, x, left, a, dbiatx, nderiv )
!*************************************************************************
!
!! BSPLVD calculates the nonvanishing B-splines and derivatives at X.
!
! Discussion:
!
! Values at X of all the relevant B-splines of order K, K-1,..., K+1-NDERIV
! are generated via BSPLVB and stored temporarily in DBIATX.
!
! Then, the B-spline coefficients of the required derivatives
! of the B-splines of interest are generated by differencing,
! each from the preceding one of lower order, and combined with
! the values of B-splines of corresponding order in DBIATX
! to produce the desired values.
!
! Reference:
!
! Carl DeBoor,
! A Practical Guide to Splines,
! Springer Verlag.
!
! Parameters:
!
! Input, real ( kind = 8 ) T(LEFT+K), the knot sequence. It is assumed that
! T(LEFT) < T(LEFT+1). Also, the output is correct only if
! T(LEFT) <= X <= T(LEFT+1) .
!
! Input, integer K, the order of the B-splines to be evaluated.
!
! Input, real ( kind = 8 ) X, the point at which these values are sought.
!
! Input, integer LEFT, indicates the left endpoint of the interval of
! interest. The K B-splines whose support contains the interval
! (T(LEFT), T(LEFT+1)) are to be considered.
!
! Workspace, real ( kind = 8 ) A(K,K).
!
! Output, real ( kind = 8 ) DBIATX(K,NDERIV). DBIATX(I,M) contains
! the value of the (M-1)st derivative of the (LEFT-K+I)-th B-spline
! of order K for knot sequence T, I=M,...,K, M=1,...,NDERIV.
!
! Input, integer NDERIV, indicates that values of
! B-splines and their derivatives up to but not
! including the NDERIV-th are asked for.
!
implicit none
integer k
integer left
integer nderiv
real ( kind = 8 ) a(k,k)
real ( kind = 8 ) dbiatx(k,nderiv)
real ( kind = 8 ) factor
real ( kind = 8 ) fkp1mm
integer i
integer ideriv
integer il
integer j
integer jlow
integer jp1mid
integer ldummy
integer m
integer mhigh
real ( kind = 8 ) sum1
real ( kind = 8 ) t(left+k)
real ( kind = 8 ) x
mhigh = max ( min ( nderiv, k ), 1 )
!
! MHIGH is usually equal to nderiv.
!
call bsplvb ( t, k+1-mhigh, 1, x, left, dbiatx )
if ( mhigh == 1 ) then
return
end if
!
! The first column of DBIATX always contains the B-spline values
! for the current order. These are stored in column K+1-current
! order before BSPLVB is called to put values for the next
! higher order on top of it.
!
ideriv = mhigh
do m = 2, mhigh
jp1mid = 1
do j = ideriv, k
dbiatx(j,ideriv) = dbiatx(jp1mid,1)
jp1mid = jp1mid+1
end do
ideriv = ideriv-1
call bsplvb(t,k+1-ideriv,2,x,left,dbiatx)
end do
!
! At this point, b(left-k+i, k+1-j)(x) is in dbiatx(i,j) for
! i=j,...,k and j=1,...,mhigh ('=' nderiv). in particular, the
! first column of dbiatx is already in final form. to obtain cor-
! ??? LOST A LINE ???
! rate their b-repr. by differencing, then evaluate at x.
!
jlow = 1
do i = 1, k
do j = jlow,k
a(j,i) = 0.0D+00
end do
jlow = i
a(i,i) = 1.0D+00
end do
!
! At this point, a(.,j) contains the b-coefficients for the J-th of the
! k b-splines of interest here.
!
do m = 2, mhigh
fkp1mm = real ( k + 1 - m, kind = 8 )
il = left
i = k
!
! For j=1,...,k, construct b-coefficients of (m-1)st derivative of
! b-splines from those for preceding derivative by differencing
! and store again in a(.,j) . The fact that a(i,j)=0 for
! i < j is used.
!
do ldummy = 1, k+1-m
factor = fkp1mm/(t(il+k+1-m)-t(il))
!
! The assumption that t(left) < t(left+1) makes denominator
! in factor nonzero.
!
do j = 1, i
a(i,j) = (a(i,j)-a(i-1,j))*factor
end do
il = il-1
i = i-1
end do
!
! For i=1,...,k, combine b-coefficients a(.,i) with B-spline values
! stored in dbiatx(.,m) to get value of (m-1)st derivative of
! i-th b-spline (of interest here) at x , and store in
! dbiatx(i,m). storage of this value over the value of a b-spline
! of order m there is safe since the remaining b-spline derivat-
! ives of the same order do not use this value due to the fact
! that a(j,i)=0 for j < i.
!
do i = 1, k
sum1 = 0.0D+00
jlow = max(i,m)
do j = jlow,k
sum1 = sum1 + a(j,i) * dbiatx(j,m)
end do
dbiatx(i,m) = sum1
end do
end do
return
end