!> !> @file splint.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 splint ( tau, gtau, t, n, k, q, bcoef, iflag ) !************************************************************************* ! !! SPLINT produces the B-spline coefficients BCOEF of an interpolating spline. ! ! Discussion: ! ! The spline is of order K with knots T(1:N+K), and takes on the ! value GTAU(I) at TAU(I), for I = 1 to N. ! ! The I-th equation of the linear system ! A * BCOEF = B ! for the b-coefficients of the interpolant enforces interpolation ! at TAU(1:N). ! ! Hence, b(i)=gtau(i), all i, and a is a band matrix with 2k-1 ! bands (if it is invertible). ! ! The matrix A is generated row by row and stored, diagonal by di- ! agonal, in the rows of the array q , with the main diagonal go- ! ing into row K. see comments in the program below. ! ! The banded system is then solved by a call to banfac (which con- ! structs the triangular factorization for a and stores it again in ! q ), followed by a call to banslv (which then obtains the solution ! bcoef by substitution). ! ! BANFAC does no pivoting, since the total positivity of the matrix ! A makes this unnecessary. ! ! Reference: ! ! Carl DeBoor, ! A Practical Guide to Splines, ! Springer Verlag. ! ! Parameters: ! ! Input, real ( kind = 8 ) TAU(N), the data point abscissas. The entries in ! TAU should be strictly increasing. ! ! Input, real ( kind = 8 ) GTAU(N), the data ordinates. ! ! Input, real ( kind = 8 ) T(N+K), the knot sequence. ! ! Input, integer N, the number of data points. ! ! Input, integer K, the order of the spline. ! ! output ! ! q, array of size (2*k-1)*n , containing the triangular factoriz- ! ation of the coefficient matrix of the linear system for the b- ! coefficients of the spline interpolant. ! the b-coefficients for the interpolant of an additional data set can ! be obtained without going through all the calculations in this ! routine, simply by loading htau into bcoef and then execut- ! ing the call banslv ( q, 2*k-1, n, k-1, k-1, bcoef ) ! ! bcoef, the b-coefficients of the interpolant, of length n. ! ! iflag, an integer indicating success (= 1) or failure (= 2) ! the linear system to be solved is (theoretically) invertible if ! and only if ! t(i) < tau(i) < tau(i+k), all i. ! violation of this condition is certain to lead to iflag=2 . ! implicit none integer n real ( kind = 8 ) bcoef(n) real ( kind = 8 ) gtau(n) integer i integer iflag integer ilp1mx integer j integer jj integer k integer kpkm2 integer left real ( kind = 8 ) q((2*k-1)*n) real ( kind = 8 ) t(n+k) real ( kind = 8 ) tau(n) real ( kind = 8 ) taui kpkm2 = 2*(k-1) left = k do i = 1, (2*k-1)*n q(i) = 0.0D+00 end do ! ! loop over i to construct the n interpolation equations ! do i = 1, n taui = tau(i) ilp1mx = min(i+k,n+1) ! ! find left in the closed interval (i,i+k-1) such that ! t(left) <= tau(i) < t(left+1) ! matrix is singular if this is not possible ! left = max(left,i) if ( taui < t(left)) then go to 70 end if 20 continue if ( taui < t(left+1)) then go to 30 end if left = left+1 if ( left < ilp1mx) then go to 20 end if left = left-1 if ( t(left+1) < taui ) then go to 70 end if ! ! The i-th equation enforces interpolation at taui, hence ! a(i,j)=b(j,k,t)(taui), all j. only the k entries with j = ! left-k+1,...,left actually might be nonzero. these k numbers ! are returned, in bcoef (used for temp.storage here), by the ! following ! 30 continue call bsplvb(t,k,1,taui,left,bcoef) ! ! We therefore want bcoef(j)=b(left-k+j)(taui) to go into ! a(i,left-k+j), i.e., into q(i-(left+j)+2*k,(left+j)-k) since ! a(i+j,j) is to go into q(i+k,j), all i,j, if we consider q ! as a two-dim. array , with 2*k-1 rows (see comments in ! banfac). in the present program, we treat q as an equivalent ! one-dimensional array (because of fortran restrictions on ! dimension statements) . we therefore want bcoef(j) to go into ! entry ! i -(left+j)+2*k + ((left+j)-k-1)*(2*k-1) ! = i-left+1+(left -k)*(2*k-1) + (2*k-2)*j ! of q . ! jj = i-left+1+(left-k)*(k+k-1) do j = 1,k jj = jj+kpkm2 q(jj) = bcoef(j) end do end do ! ! Obtain factorization of A, stored again in Q. ! call banfac ( q, k+k-1, n, k-1, k-1, iflag ) if ( iflag == 2 ) then write(*,*)' ' write(*,*)'SPLINT - Fatal Error!' write(*,*)' The linear system is not invertible!' return end if ! ! Solve a*bcoef=gtau by backsubstitution ! bcoef(1:n) = gtau(1:n) call banslv ( q, k+k-1, n, k-1, k-1, bcoef ) return 70 iflag=2 write ( *, * ) ' ' write ( *, * ) 'SPLINT - Fatal Error!' write ( *, * ) ' The linear system is not invertible!' return end