rotex__splines.f Source File


Source Code

! ================================================================================================================================ !
module rotex__splines
  !! Wrapper routines for the spline fitting procedures

  implicit none

  private

  public :: interpolate_replace

  integer, parameter :: SPLINE_ORDER_KX = 3
  integer, parameter :: DB1INK_IKNOT = 0
  integer, parameter :: DB1VAL_IDX = 0

! ================================================================================================================================ !
contains
! ================================================================================================================================ !

  ! ------------------------------------------------------------------------------------------------------------------------------ !
  impure module subroutine interpolate_replace(xold, xnew, fx, idxx)
    !! Interpolate f(xold) -> f(xnew). Only consider xnew values that are contained within xold for now.
    !! Xnew returns untouched, but fx is overwritten with interpolated values on the
    !! grid xnew(idxx)

    use rotex__kinds,   only: dp
    use rotex__arrays,  only: size_check
    use bspline_module, only: db1ink, db1val

    implicit none

    real(dp), intent(in) :: xold(:)
      !! The grid of values on which our function has been evaluated
    real(dp), intent(in) :: xnew(:)
      !! The new grid of values that we want our function to be evaluated on.
    real(dp), intent(inout), allocatable :: fx(:)
      !! On input:  evaluated function f(xold)
      !! On output: the evaluated function f(xnew)
    integer, intent(out), allocatable, optional :: idxx(:)
      !! The indices of values of xnew that are used to evaluate fx

    logical, allocatable :: mask(:)
    integer :: nxold, nxnew_chopped, iflag, inbvx, ix
    real(dp), allocatable :: tx(:), bcoef(:), w0(:), fx_copy(:), xnew_chopped(:)

    nxold = size(xold, 1)
    call size_check(fx, nxold, "FX")

    mask = xnew .ge. xold(1) .AND. xnew .le. xold(nxold)

    ! -- get x-subgrid
    xnew_chopped  = pack(xnew, mask)
    nxnew_chopped = size(xnew_chopped, 1)

    if(present(idxx)) then
      idxx = [(ix, ix=1, size(xnew, 1))]
      idxx = pack(idxx, mask)
    endif

    allocate(tx(nxold+SPLINE_ORDER_KX), source = 0.0_dp)
    allocate(bcoef(nxold),              source = 0.0_dp)
    allocate(fx_copy(nxnew_chopped),    source = 0.0_dp)
    allocate(w0(3*SPLINE_ORDER_KX),     source = 0.0_dp)

    ! -- interpolate
    call db1ink(xold, nxold, fx, SPLINE_ORDER_KX, DB1INK_IKNOT, tx, bcoef, iflag)

    ! -- evaluate
    inbvx = 1
    do ix = 1, nxnew_chopped
      call db1val(         &
          xnew_chopped(ix) &
        , DB1VAL_IDX       &
        , tx               &
        , nxold            &
        , SPLINE_ORDER_KX  &
        , bcoef            &
        , fx_copy(ix)      &
        , iflag            &
        , inbvx            &
        , w0               &
        , extrap = .false. &
      )
    enddo

    call move_alloc(fx_copy, fx)

  end subroutine interpolate_replace

! ================================================================================================================================ !
end module rotex__splines
! ================================================================================================================================ !