DersBasisFuns Subroutine

private pure subroutine DersBasisFuns(me, u, n, ders, span)

Computes all nonzero basis functions and their derivatives based on Algorithm A2.3 in the NURBS Book [^1].

Implementation Details of Algorithm A2.3

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;

  • should not exceed (all higher derivatives are zero);
  • the denominators involving knot differences can become zero; the quotient is defined to be zero in this case

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

    • The knot differences
  • 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.


Ex2.4 Computing Derivatives of the 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.


Arguments

Type IntentOptional AttributesName
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


Calls

proc~~dersbasisfuns~~CallsGraph proc~dersbasisfuns DersBasisFuns ui ui proc~dersbasisfuns->ui

Contents

Source Code


Source Code

        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