Build the nodal->modal transform Pmodal for a 1-D degree-N interpolant whose nodes are controlPoints(1:N+1). The transform is the exact inverse of the L2-normalized Legendre Vandermonde V(i,p) = Ltilde_{p-1}(x_i); Pmodal(ii,p) stores V^{-1}(p,ii) so that uhat(p) = sum_ii Pmodal(ii,p) * u(ii). The Vandermonde inverse is formed in double precision for conditioning and cast back to the working precision.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=prec), | intent(in) | :: | controlPoints(1:N+1) | |||
| integer, | intent(in) | :: | N | |||
| real(kind=prec), | intent(out) | :: | Pmodal(1:N+1,1:N+1) |
subroutine BuildModalTransform(controlPoints,N,Pmodal)
!! Build the nodal->modal transform Pmodal for a 1-D degree-N interpolant whose nodes are
!! controlPoints(1:N+1). The transform is the exact inverse of the L2-normalized Legendre
!! Vandermonde V(i,p) = Ltilde_{p-1}(x_i); Pmodal(ii,p) stores V^{-1}(p,ii) so that
!! uhat(p) = sum_ii Pmodal(ii,p) * u(ii). The Vandermonde inverse is formed in double
!! precision for conditioning and cast back to the working precision.
implicit none
integer,intent(in) :: N
real(prec),intent(in) :: controlPoints(1:N+1)
real(prec),intent(out) :: Pmodal(1:N+1,1:N+1)
! Local
integer :: i,p
real(real64) :: V(1:N+1,1:N+1)
real(real64) :: Vinv(1:N+1,1:N+1)
! Vandermonde in the normalized Legendre basis: column p (degree p-1) evaluated at node i.
do i = 1,N+1
do p = 1,N+1
V(i,p) = NormalizedLegendre(p-1,real(controlPoints(i),real64))
enddo
enddo
call InvertMatrix(V,Vinv,N+1)
! Store the transpose of the inverse so the summed (input node) index comes first,
! matching the SELF matrix-application convention.
do p = 1,N+1
do i = 1,N+1
Pmodal(i,p) = real(Vinv(p,i),prec)
enddo
enddo
endsubroutine BuildModalTransform