Computes all nonzero basis functions and their derivatives based on Algorithm A2.3 in the NURBS Book [^1].
Return value, real :: ders(j,k)
and , is the th derivative of the function , where is the knot span of , by using the following equation,
Remarks;
To avoids memory usage as much as possible in the computiation, two local arrays "a
" and "ndu
" introduced;
a(0:1,0:p)
, stores the two most recently computed rows, and ;
depend on the but not the and utilize the knot differences seen in the lower triangle part of the ndu(0:p,0:p)
matrix by using and functions
ndu(0:p,0:p)
, stores the basis functions and knot differences on its upper and lower triangle, respectively;
ndu array (See example) |
Note: This algorithm applies to rational basis functions.
Let , , and . Then , and the array becomes
Now compute and ; with in Eq. (2.10), we have
Now , and all use knot differences which are not in the array, but they are multiplied respectively by , , and , which are also not in the array. These terms are defined to be zero, and we are left with
To check these values, recall from Cox-de Boor formula that on . The computation of , , and is analogous.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(basis), | intent(in) | :: | me | |||
real(kind=wp), | intent(in) | :: | u | Given value |
||
integer, | intent(in) | :: | n | Number of derivatives () |
||
real(kind=wp), | intent(out) | :: | ders(0:me%p,0:n) |
|
||
integer, | intent(in), | optional | :: | span | Knot span where lies on |
pure subroutine DersBasisFuns(me,u,n,ders,span)
class(basis), intent(in) :: me
real(wp), intent(in) :: u !< Given \( u \) value
integer, intent(in) :: n !< Number of derivatives (\(n \leq p\))
integer, intent(in), optional :: span !< Knot span where \( u \) lies on
real(wp), intent(out) :: ders(0:me%p, 0:n) !<
!< $$ = \begin{bmatrix} {N_{i - p,p}^{(0)}(u)} & \cdots &{N_{i - p,p}^{(k)}(u)}\\
!< \vdots & \ddots & \vdots \\ {N_{i,p}^{(0)}(u)} & \cdots &{N_{i,p}^{(k)}(u)} \end{bmatrix} $$
!locals
integer :: i !< Knot span index
integer :: j, k, r, s1, s2, rk, pk, j1, j2
real(wp) :: saved, temp, d
real(wp) :: left(me%p), right(me%p)
real(wp) :: ndu(0:me%p,0:me%p), a(0:1,0:me%p)
ders = 0.0_wp
associate( p => me%p, Ui => me%kv ) !get rid of % signs
! set the knot span
if(present(span))then
i = span
else
i = me%FindSpan(u)
end if
ndu(0,0) = 1.0_wp
do j = 1, p
left(j) = u - Ui(i+1-j)
right(j) = Ui(i+j) - u
saved = 0.0_wp
do r = 0, j-1
!/* Lower triangle */
ndu(j,r) = right(r+1) + left(j-r)
temp = ndu(r,j-1) / ndu(j,r)
!/* Upper triangle */
ndu(r,j) = saved + right(r+1) * temp
saved = left(j-r) * temp
end do
ndu(j,j) = saved
end do
!/* Load the basis functions */
ders(:,0) = ndu(:,p)
!/* This section computes the derivatives (Eq. [2.9]) */
do r = 0, p !/* Loop over function index */
s1 = 0; s2 = 1 !/* Alternate rows in array a */
a(0,0) = 1.0_wp
!/* Loop to compute kth derivative */
do k = 1, n
d = 0.0_wp
rk = r-k; pk = p-k;
if (r >= k) then
a(s2,0) = a(s1,0) / ndu(pk+1,rk)
d = a(s2,0) * ndu(rk,pk)
end if
if (rk > -1) then
j1 = 1
else
j1 = -rk
end if
if (r-1 <= pk) then
j2 = k-1
else
j2 = p-r
end if
do j = j1, j2
a(s2,j) = (a(s1,j) - a(s1,j-1)) / ndu(pk+1,rk+j)
d = d + a(s2,j) * ndu(rk+j,pk)
end do
if (r <= pk) then
a(s2,k) = - a(s1,k-1) / ndu(pk+1,r)
d = d + a(s2,k) * ndu(r,pk)
end if
ders(r,k) = d
j = s1; s1 = s2; s2 = j !/* Switch rows */
end do
end do
!/* Multiply through by the correct factors */
!/* (Eq. [2.9]) */
r = p
do k = 1, n
ders(:,k) = ders(:,k) * r
r = r * (p-k)
end do
end associate
end subroutine DersBasisFuns