LCOV - code coverage report
Current view: top level - interp_1d/public - interp_1d_lib.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 30.7 % 296 91
Test Date: 2025-05-08 18:23:42 Functions: 24.4 % 41 10

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              :       module interp_1d_lib
      21              :       use const_def, only: dp
      22              :       use auto_diff
      23              : 
      24              :       implicit none
      25              : 
      26              :       contains
      27              : 
      28              :       ! this routine is a simply wrapper for making an interpolant and then using it.
      29           46 :       subroutine interpolate_vector( &
      30           46 :                n_old, x_old, n_new, x_new, v_old, v_new, interp_vec, nwork, work1, str, ierr)
      31              :          integer, intent(in) :: n_old, n_new
      32              :          real(dp), intent(in) :: x_old(:)  !(n_old)
      33              :          real(dp), intent(in) :: v_old(:)  !(n_old)
      34              :          real(dp), intent(in) :: x_new(:)  !(n_new)
      35              :          real(dp), intent(inout) :: v_new(:)  ! (n_new)
      36              :          interface
      37              :             subroutine interp_vec(x, nx, f1, nwork, work1, str, ierr)  ! make cubic interpolant
      38              :                ! e.g., interp_pm, interp_m3a, interp_m3b, or interp_m3q
      39              :                use const_def, only: dp
      40              :                implicit none
      41              :                integer, intent(in) :: nx       ! length of x vector
      42              :                real(dp), intent(in) :: x(:)  ! (nx)    ! junction points, strictly monotonic
      43              :                real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
      44              :                integer, intent(in) :: nwork
      45              :                real(dp), intent(inout), pointer :: work1(:)  ! =(n_old, nwork)
      46              :                character (len=*) :: str  ! for debugging
      47              :                integer, intent(out) :: ierr
      48              :             end subroutine interp_vec
      49              :          end interface
      50              :          integer, intent(in) :: nwork
      51              :          real(dp), intent(inout), pointer :: work1(:)  ! =(n_old, nwork)
      52              :          character (len=*) :: str  ! for debugging
      53              :          integer, intent(out) :: ierr
      54           46 :          real(dp), pointer :: f1(:), f(:,:)
      55              :          integer :: k
      56           46 :          ierr = 0
      57           46 :          allocate(f1(4*n_old), stat=ierr)
      58           46 :          if (ierr /= 0) return
      59           46 :          f(1:4,1:n_old) => f1(1:4*n_old)
      60        48484 :          do k=1,n_old
      61        48484 :             f(1,k) = v_old(k)
      62              :          end do
      63           46 :          call interp_vec(x_old, n_old, f1, nwork, work1, str, ierr)  ! make interpolant
      64           46 :          if (ierr /= 0) then
      65            0 :             deallocate(f1)
      66            0 :             return
      67              :          end if
      68           46 :          call interp_values(x_old, n_old, f1, n_new, x_new, v_new, ierr)
      69           46 :          deallocate(f1)
      70           46 :       end subroutine interpolate_vector
      71              : 
      72              :       ! autodiff version of above
      73            0 :       subroutine interpolate_vector_autodiff( &
      74            0 :                n_old, x_old, n_new, x_new, v_old, v_new, interp_vec_autodiff, nwork, work1, str, ierr)
      75              :          integer, intent(in) :: n_old, n_new
      76              :          type(auto_diff_real_2var_order1), intent(in) :: x_old(:)  !(n_old)
      77              :          type(auto_diff_real_2var_order1), intent(in) :: v_old(:)  !(n_old)
      78              :          type(auto_diff_real_2var_order1), intent(in) :: x_new(:)  !(n_new)
      79              :          type(auto_diff_real_2var_order1), intent(inout) :: v_new(:)  ! (n_new)
      80              :          interface
      81              :             subroutine interp_vec_autodiff(x, nx, f1, nwork, work1, str, ierr)  ! make cubic interpolant
      82              :                ! e.g., interp_pm, interp_m3a, interp_m3b, or interp_m3q
      83              :                use const_def, only: dp
      84              :                use auto_diff
      85              :                implicit none
      86              :                integer, intent(in) :: nx       ! length of x vector
      87              :                type(auto_diff_real_2var_order1), intent(in) :: x(:)  ! (nx)    ! junction points, strictly monotonic
      88              :                type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
      89              :                integer, intent(in) :: nwork
      90              :                type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(n_old, nwork)
      91              :                character (len=*) :: str  ! for debugging
      92              :                integer, intent(out) :: ierr
      93              :              end subroutine interp_vec_autodiff
      94              :          end interface
      95              :          integer, intent(in) :: nwork
      96              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(n_old, nwork)
      97              :          character (len=*) :: str  ! for debugging
      98              :          integer, intent(out) :: ierr
      99            0 :          type(auto_diff_real_2var_order1), pointer :: f1(:), f(:,:)
     100              :          integer :: k
     101            0 :          ierr = 0
     102            0 :          allocate(f1(4*n_old), stat=ierr)
     103            0 :          if (ierr /= 0) return
     104            0 :          f(1:4,1:n_old) => f1(1:4*n_old)
     105            0 :          do k=1,n_old
     106            0 :             f(1,k) = v_old(k)
     107              :          end do
     108            0 :          call interp_vec_autodiff(x_old, n_old, f1, nwork, work1, str, ierr)  ! make interpolant
     109            0 :          if (ierr /= 0) then
     110            0 :             deallocate(f1)
     111            0 :             return
     112              :          end if
     113            0 :          call interp_values_autodiff(x_old, n_old, f1, n_new, x_new, v_new, ierr)
     114            0 :          deallocate(f1)
     115            0 :       end subroutine interpolate_vector_autodiff
     116              : 
     117              :       ! this routine is a simply wrapper for making an interpolant with interp_pm and then using it.
     118            1 :       subroutine interpolate_vector_pm( &
     119            1 :                n_old, x_old, n_new, x_new, v_old, v_new, work1, str, ierr)
     120              :          use interp_1d_def, only: pm_work_size
     121              :          integer, intent(in) :: n_old, n_new
     122              :          real(dp), intent(in) :: x_old(:)  !(n_old)
     123              :          real(dp), intent(in) :: v_old(:)  !(n_old)
     124              :          real(dp), intent(in) :: x_new(:)  !(n_new)
     125              :          real(dp), intent(inout) :: v_new(:)  ! (n_new)
     126              :          real(dp), intent(inout), pointer :: work1(:)  ! =(n_old, pm_work_size)
     127              :          character (len=*) :: str  ! for debugging
     128              :          integer, intent(out) :: ierr
     129            1 :          real(dp), pointer :: f1(:), f(:,:)
     130              :          integer :: k
     131            1 :          ierr = 0
     132            1 :          allocate(f1(4*n_old), stat=ierr)
     133            1 :          if (ierr /= 0) return
     134            1 :          f(1:4,1:n_old) => f1(1:4*n_old)
     135            4 :          do k=1,n_old
     136            4 :             f(1,k) = v_old(k)
     137              :          end do
     138            1 :          call interp_pm(x_old, n_old, f1, pm_work_size, work1, str, ierr)  ! make interpolant
     139            1 :          if (ierr /= 0) then
     140            0 :             deallocate(f1)
     141            0 :             return
     142              :          end if
     143            1 :          call interp_values(x_old, n_old, f1, n_new, x_new, v_new, ierr)
     144            1 :          deallocate(f1)
     145            1 :       end subroutine interpolate_vector_pm
     146              : 
     147              : 
     148            0 :       subroutine interp_4_to_1(pdqm1, pdq00, pdqp1, ndq00, pfm1, pf00, pfp1, pfp2, nf00, str, ierr)
     149              :          ! 4 points in, 1 point out
     150              :          ! piecewise monotonic cubic interpolation
     151              :          use interp_1d_def, only: pm_work_size
     152              :          real(dp), intent(in) :: pdqm1, pdq00, pdqp1  ! spacing between input points
     153              :          real(dp), intent(in) :: ndq00
     154              :          real(dp), intent(in) :: pfm1, pf00, pfp1, pfp2  ! previous values
     155              :          real(dp), intent(out) :: nf00  ! new value at nk
     156              :          character (len=*) :: str  ! for debugging
     157              :          integer, intent(out) :: ierr
     158              :          integer, parameter :: n_old=4, n_new=1
     159            0 :          real(dp) :: x_old(n_old), v_old(n_old), x_new(n_new), v_new(n_new)
     160            0 :          real(dp), target :: work1_ary(n_old*pm_work_size)
     161              :          real(dp), pointer :: work1(:)
     162            0 :          work1 => work1_ary
     163              :          ierr = 0
     164            0 :          x_old(1) = 0d0
     165            0 :          x_old(2) = pdqm1
     166            0 :          x_old(3) = pdqm1+pdq00
     167            0 :          x_old(4) = pdqm1+pdq00+pdqp1
     168            0 :          v_old(1) = pfm1
     169            0 :          v_old(2) = pf00
     170            0 :          v_old(3) = pfp1
     171            0 :          v_old(4) = pfp2
     172            0 :          x_new(1) = ndq00
     173              :          call interpolate_vector_pm( &
     174            0 :                   n_old, x_old, n_new, x_new, v_old, v_new, work1, str, ierr)
     175            0 :          nf00 = v_new(1)
     176            0 :       end subroutine interp_4_to_1
     177              : 
     178              : 
     179            0 :       subroutine interp_3_to_1(pdqm1, pdq00, ndqm1, pfm1, pf00, pfp1, nf00, str, ierr)
     180              :          ! 3 points in, 1 point out
     181              :          ! piecewise monotonic quadratic interpolation
     182              :          use interp_1d_def, only: pm_work_size
     183              :          real(dp), intent(in) :: pdqm1, pdq00  ! spacing between input points
     184              :          real(dp), intent(in) :: ndqm1  ! new spacing to nk
     185              :          real(dp), intent(in) :: pfm1, pf00, pfp1  ! previous values at pkm1, pk, pkp1
     186              :          real(dp), intent(out) :: nf00  ! new value at nk
     187              :          character (len=*) :: str  ! for debugging
     188              :          integer, intent(out) :: ierr
     189              :          integer, parameter :: n_old=3, n_new=1
     190            0 :          real(dp) :: x_old(n_old), v_old(n_old), x_new(n_new), v_new(n_new)
     191            0 :          real(dp), target :: work1_ary(n_old*pm_work_size)
     192              :          real(dp), pointer :: work1(:)
     193            0 :          work1 => work1_ary
     194              :          ierr = 0
     195            0 :          x_old(1) = 0d0
     196            0 :          x_old(2) = pdqm1
     197            0 :          x_old(3) = pdqm1+pdq00
     198            0 :          v_old(1) = pfm1
     199            0 :          v_old(2) = pf00
     200            0 :          v_old(3) = pfp1
     201            0 :          x_new(1) = ndqm1
     202              :          call interpolate_vector_pm( &
     203            0 :             n_old, x_old, n_new, x_new, v_old, v_new, work1, str, ierr)
     204            0 :          nf00 = v_new(1)
     205            0 :       end subroutine interp_3_to_1
     206              : 
     207              : 
     208            1 :       subroutine interp_3_to_2(pdqm1, pdq00, ndqm1, ndq00, pfm1, pf00, pfp1, nf00, nfp1, str, ierr)
     209              :          ! 3 points in, 2 points out
     210              :          ! piecewise monotonic quadratic interpolation
     211              :          use interp_1d_def, only: pm_work_size
     212              :          real(dp), intent(in) :: pdqm1, pdq00  ! previous spacing to pk and pkp1
     213              :          real(dp), intent(in) :: ndqm1, ndq00  ! new spacing to nk and nk+1
     214              :          real(dp), intent(in) :: pfm1, pf00, pfp1  ! previous values at pkm1, pk, pkp1
     215              :          real(dp), intent(out) :: nf00, nfp1  ! new values at nk, nk+1
     216              :          character (len=*) :: str  ! for debugging
     217              :          integer, intent(out) :: ierr
     218              :          integer, parameter :: n_old=3, n_new=2
     219           14 :          real(dp) :: x_old(n_old), v_old(n_old), x_new(n_new), v_new(n_new)
     220           10 :          real(dp), target :: work1_ary(n_old*pm_work_size)
     221              :          real(dp), pointer :: work1(:)
     222            1 :          work1 => work1_ary
     223              :          ierr = 0
     224            1 :          x_old(1) = 0d0
     225            1 :          x_old(2) = pdqm1
     226            1 :          x_old(3) = pdqm1+pdq00
     227            1 :          v_old(1) = pfm1
     228            1 :          v_old(2) = pf00
     229            1 :          v_old(3) = pfp1
     230            1 :          x_new(1) = ndqm1
     231            1 :          x_new(2) = ndqm1+ndq00
     232              :          call interpolate_vector_pm( &
     233            1 :             n_old, x_old, n_new, x_new, v_old, v_new, work1, str, ierr)
     234            1 :          nf00 = v_new(1)
     235            1 :          nfp1 = v_new(2)
     236            1 :       end subroutine interp_3_to_2
     237              : 
     238              : 
     239              :       ! general routines
     240              : 
     241              :       ! these routines use previously created interpolant information (f)
     242              :       ! the interpolant can come from either the piecewise monotonic routines, or
     243              :       ! from the monotonicity preserving routines -- they use the same format for f.
     244              : 
     245          105 :       subroutine interp_values(init_x, nx, f1, nv, x, vals, ierr)
     246              :          use interp_1d_def
     247              :          use interp_1d_misc
     248              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     249              :          integer, intent(in) :: nx  ! length of init_x vector
     250              :          real(dp), intent(in), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     251              :          integer, intent(in) :: nv  ! length of new x vector and vals vector
     252              :          real(dp), intent(in) :: x(:)  ! (nv)  ! locations where want interpolated values
     253              :             ! strictly monotonic in same way as init_x
     254              :             ! values out of range of init_x's are clipped to boundaries of init_x's
     255              :          real(dp), intent(inout) :: vals(:)  ! (nv)
     256              :          integer, intent(out) :: ierr  ! 0 means AOK
     257          105 :          call do_interp_values(init_x, nx, f1, nv, x, vals, ierr)
     258          105 :       end subroutine interp_values
     259              : 
     260            0 :       subroutine interp_values_autodiff(init_x, nx, f1, nv, x, vals, ierr)
     261          105 :          use interp_1d_def
     262              :          use interp_1d_misc
     263              :          type(auto_diff_real_2var_order1), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     264              :          integer, intent(in) :: nx  ! length of init_x vector
     265              :          type(auto_diff_real_2var_order1), intent(in), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     266              :          integer, intent(in) :: nv  ! length of new x vector and vals vector
     267              :          type(auto_diff_real_2var_order1), intent(in) :: x(:)  ! (nv)  ! locations where want interpolated values
     268              :             ! strictly monotonic in same way as init_x
     269              :             ! values out of range of init_x's are clipped to boundaries of init_x's
     270              :          type(auto_diff_real_2var_order1), intent(inout) :: vals(:)  ! (nv)
     271              :          integer, intent(out) :: ierr  ! 0 means AOK
     272            0 :          call do_interp_values_autodiff(init_x, nx, f1, nv, x, vals, ierr)
     273            0 :       end subroutine interp_values_autodiff
     274              : 
     275              : 
     276         6232 :       subroutine interp_value(init_x, nx, f1, xval, val, ierr)
     277            0 :          use interp_1d_def
     278              :          use interp_1d_misc
     279              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     280              :          integer, intent(in) :: nx  ! length of init_x vector
     281              :          real(dp), intent(in), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     282              :          real(dp), intent(in) :: xval  ! location where want interpolated value
     283              :          real(dp), intent(out) :: val
     284              :          integer, intent(out) :: ierr  ! 0 means AOK
     285              :          integer, parameter :: nv = 1
     286        12464 :          real(dp) :: x(nv), vals(nv)
     287         6232 :          x(1) = xval
     288         6232 :          call do_interp_values(init_x, nx, f1, nv, x, vals, ierr)
     289         6232 :          val = vals(1)
     290         6232 :       end subroutine interp_value
     291              : 
     292              : 
     293            0 :       subroutine interp_values_and_slopes(init_x, nx, f1, nv, x, vals, slopes, ierr)
     294         6232 :          use interp_1d_def
     295              :          use interp_1d_misc
     296              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     297              :          integer, intent(in) :: nx  ! length of init_x vector
     298              :          real(dp), intent(in), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     299              :          integer, intent(in) :: nv  ! length of new x vector and vals and slopes vectors
     300              :          real(dp), intent(in) :: x(:)  ! (nv)  ! locations where want interpolated values
     301              :             ! strictly monotonic in same way as init_x
     302              :             ! values out of range of init_x's are clipped to boundaries of init_x's
     303              :          real(dp), intent(inout) :: vals(:)  ! (nv)
     304              :          real(dp), intent(inout) :: slopes(:)  ! (nv)
     305              :          integer, intent(out) :: ierr  ! 0 means AOK
     306            0 :          call do_interp_values_and_slopes(init_x, nx, f1, nv, x, vals, slopes, ierr)
     307            0 :       end subroutine interp_values_and_slopes
     308              : 
     309              : 
     310           16 :       subroutine interp_value_and_slope(init_x, nx, f1, xval, val, slope, ierr)
     311            0 :          use interp_1d_def
     312              :          use interp_1d_misc
     313              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     314              :          integer, intent(in) :: nx  ! length of init_x vector
     315              :          real(dp), intent(in), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     316              :          real(dp), intent(in) :: xval  ! location where want interpolated values
     317              :          real(dp), intent(out) :: val, slope
     318              :          integer, intent(out) :: ierr  ! 0 means AOK
     319              :          integer, parameter :: nv = 1
     320           64 :          real(dp) :: x(nv), vals(nv), slopes(nv)
     321           16 :          x(1) = xval
     322           16 :          call do_interp_values_and_slopes(init_x, nx, f1, nv, x, vals, slopes, ierr)
     323           16 :          val = vals(1)
     324           16 :          slope = slopes(1)
     325           16 :       end subroutine interp_value_and_slope
     326              : 
     327              : 
     328            0 :       subroutine interp2_values_and_slopes( &
     329            0 :             init_x, nx, f1_1, f1_2, nv, x, vals_1, slopes_1, vals_2, slopes_2, ierr)
     330           16 :          use interp_1d_def
     331              :          use interp_1d_misc
     332              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     333              :          integer, intent(in) :: nx  ! length of init_x vector
     334              :          real(dp), intent(in), pointer :: f1_1(:), f1_2(:)  ! =(4,nx)  ! data & interpolation coefficients
     335              :          integer, intent(in) :: nv  ! length of new x vector and vals and slopes vectors
     336              :          real(dp), intent(in) :: x(:)  ! (nv)  ! locations where want interpolated values
     337              :             ! strictly monotonic in same way as init_x
     338              :             ! values out of range of init_x's are clipped to boundaries of init_x's
     339              :          real(dp), intent(inout) :: vals_1(:), vals_2(:)  ! (nv)
     340              :          real(dp), intent(inout) :: slopes_1(:), slopes_2(:)  ! (nv)
     341              :          integer, intent(out) :: ierr  ! 0 means AOK
     342              :          call do_interp2_values_and_slopes( &
     343            0 :             init_x, nx, f1_1, f1_2, nv, x, vals_1, slopes_1, vals_2, slopes_2, ierr)
     344            0 :       end subroutine interp2_values_and_slopes
     345              : 
     346              : 
     347            0 :       subroutine interp2_value_and_slope(init_x, nx, f1_1, f1_2, xval, val_1, slope_1, val_2, slope_2, ierr)
     348            0 :          use interp_1d_def
     349              :          use interp_1d_misc
     350              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     351              :          integer, intent(in) :: nx  ! length of init_x vector
     352              :          real(dp), intent(in), pointer :: f1_1(:), f1_2(:)  ! =(4,nx)  ! data & interpolation coefficients
     353              :          real(dp), intent(in) :: xval  ! location where want interpolated values
     354              :          real(dp), intent(out) :: val_1, slope_1, val_2, slope_2
     355              :          integer, intent(out) :: ierr  ! 0 means AOK
     356              :          integer, parameter :: nv = 1
     357            0 :          real(dp) :: x(nv), vals_1(nv), slopes_1(nv), vals_2(nv), slopes_2(nv)
     358            0 :          x(1) = xval
     359              :          call do_interp2_values_and_slopes( &
     360            0 :             init_x, nx, f1_1, f1_2, nv, x, vals_1, slopes_1, vals_2, slopes_2, ierr)
     361            0 :          val_1 = vals_1(1)
     362            0 :          slope_1 = slopes_1(1)
     363            0 :          val_2 = vals_2(1)
     364            0 :          slope_2 = slopes_2(1)
     365            0 :       end subroutine interp2_value_and_slope
     366              : 
     367              : 
     368            0 :       subroutine interp3_values_and_slopes( &
     369            0 :             init_x, nx, f1_1, f1_2, f1_3, nv, x, &
     370            0 :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, ierr)
     371            0 :          use interp_1d_def
     372              :          use interp_1d_misc
     373              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     374              :          integer, intent(in) :: nx  ! length of init_x vector
     375              :          real(dp), intent(in), pointer :: f1_1(:), f1_2(:), f1_3(:)  ! =(4,nx)  ! data & interpolation coefficients
     376              :          integer, intent(in) :: nv  ! length of new x vector and vals and slopes vectors
     377              :          real(dp), intent(in) :: x(:)  ! (nv)  ! locations where want interpolated values
     378              :             ! strictly monotonic in same way as init_x
     379              :             ! values out of range of init_x's are clipped to boundaries of init_x's
     380              :          real(dp), intent(inout) :: vals_1(:), vals_2(:), vals_3(:)  ! (nv)
     381              :          real(dp), intent(inout) :: slopes_1(:), slopes_2(:), slopes_3(:)  ! (nv)
     382              :          integer, intent(out) :: ierr  ! 0 means AOK
     383              :          call do_interp3_values_and_slopes( &
     384              :             init_x, nx, f1_1, f1_2, f1_3, nv, x, &
     385            0 :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, ierr)
     386            0 :       end subroutine interp3_values_and_slopes
     387              : 
     388              : 
     389            0 :       subroutine interp3_value_and_slope( &
     390            0 :             init_x, nx, f1_1, f1_2, f1_3, xval, &
     391              :             val_1, slope_1, val_2, slope_2, val_3, slope_3, ierr)
     392            0 :          use interp_1d_def
     393              :          use interp_1d_misc
     394              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     395              :          integer, intent(in) :: nx  ! length of init_x vector
     396              :          real(dp), intent(in), pointer :: f1_1(:), f1_2(:), f1_3(:)  ! =(4,nx)  ! data & interpolation coefficients
     397              :          real(dp), intent(in) :: xval  ! location where want interpolated values
     398              :          real(dp), intent(out) :: val_1, slope_1, val_2, slope_2, val_3, slope_3
     399              :          integer, intent(out) :: ierr  ! 0 means AOK
     400              :          integer, parameter :: nv = 1
     401            0 :          real(dp) :: x(nv), vals_1(nv), slopes_1(nv), vals_2(nv), slopes_2(nv), vals_3(nv), slopes_3(nv)
     402            0 :          x(1) = xval
     403              :          call do_interp3_values_and_slopes( &
     404              :             init_x, nx, f1_1, f1_2, f1_3, nv, x, &
     405            0 :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, ierr)
     406            0 :          val_1 = vals_1(1)
     407            0 :          slope_1 = slopes_1(1)
     408            0 :          val_2 = vals_2(1)
     409            0 :          slope_2 = slopes_2(1)
     410            0 :          val_3 = vals_3(1)
     411            0 :          slope_3 = slopes_3(1)
     412            0 :       end subroutine interp3_value_and_slope
     413              : 
     414              : 
     415            0 :       subroutine interp6_values_and_slopes( &
     416            0 :             init_x, nx, f1_1, f1_2, f1_3, f1_4, f1_5, f1_6, nv, x, &
     417            0 :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, &
     418            0 :             vals_4, slopes_4, vals_5, slopes_5, vals_6, slopes_6, &
     419              :             ierr)
     420            0 :          use interp_1d_misc
     421              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     422              :          integer, intent(in) :: nx  ! length of init_x vector
     423              :          real(dp), intent(in), pointer, dimension(:) :: f1_1, f1_2, f1_3, f1_4, f1_5, f1_6
     424              :          integer, intent(in) :: nv  ! length of new x vector and vals vector
     425              :          real(dp), intent(in) :: x(:)  ! (nv)  ! locations where want interpolated values
     426              :             ! strictly monotonic in same way as init_x
     427              :             ! values out of range of init_x's are clipped to boundaries of init_x's
     428              :          real(dp), intent(inout), dimension(:) :: &
     429              :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, &
     430              :             vals_4, slopes_4, vals_5, slopes_5, vals_6, slopes_6
     431              :          integer, intent(out) :: ierr  ! 0 means aok
     432              :          ierr = 0
     433              :          call do_interp6_values_and_slopes( &
     434              :             init_x, nx, f1_1, f1_2, f1_3, f1_4, f1_5, f1_6, nv, x, &
     435              :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, &
     436              :             vals_4, slopes_4, vals_5, slopes_5, vals_6, slopes_6, &
     437            0 :             ierr)
     438            0 :       end subroutine interp6_values_and_slopes
     439              : 
     440              : 
     441            0 :       subroutine interp6_value_and_slope( &
     442            0 :             init_x, nx, f1_1, f1_2, f1_3, f1_4, f1_5, f1_6, xval, &
     443              :             val_1, slope_1, val_2, slope_2, val_3, slope_3, &
     444              :             val_4, slope_4, val_5, slope_5, val_6, slope_6, &
     445              :             ierr)
     446            0 :          use interp_1d_misc
     447              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly monotonic
     448              :          integer, intent(in) :: nx  ! length of init_x vector
     449              :          real(dp), intent(in), pointer, dimension(:) :: f1_1, f1_2, f1_3, f1_4, f1_5, f1_6
     450              :          real(dp), intent(in) :: xval  ! location where want interpolated values
     451              :          real(dp), intent(out) :: val_1, slope_1, val_2, slope_2, val_3, slope_3, &
     452              :             val_4, slope_4, val_5, slope_5, val_6, slope_6
     453              :          integer, intent(out) :: ierr  ! 0 means AOK
     454              : 
     455              :          integer, parameter :: nv = 1
     456            0 :          real(dp), dimension(nv) :: x, &
     457            0 :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, &
     458            0 :             vals_4, slopes_4, vals_5, slopes_5, vals_6, slopes_6
     459              :          ierr = 0
     460            0 :          x(1) = xval
     461              :          call do_interp6_values_and_slopes( &
     462              :             init_x, nx, f1_1, f1_2, f1_3, f1_4, f1_5, f1_6, nv, x, &
     463              :             vals_1, slopes_1, vals_2, slopes_2, vals_3, slopes_3, &
     464              :             vals_4, slopes_4, vals_5, slopes_5, vals_6, slopes_6, &
     465            0 :             ierr)
     466            0 :          val_1 = vals_1(1); slope_1 = slopes_1(1)
     467            0 :          val_2 = vals_2(1); slope_2 = slopes_2(1)
     468            0 :          val_3 = vals_3(1); slope_3 = slopes_3(1)
     469            0 :          val_4 = vals_4(1); slope_4 = slopes_4(1)
     470            0 :          val_5 = vals_5(1); slope_5 = slopes_5(1)
     471            0 :          val_6 = vals_6(1); slope_6 = slopes_6(1)
     472            0 :       end subroutine interp6_value_and_slope
     473              : 
     474              : 
     475            2 :       subroutine integrate_values(init_x, nx, f1, nv, x, vals, ierr)
     476            0 :          use interp_1d_def
     477              :          use interp_1d_misc
     478              :          real(dp), intent(in) :: init_x(:)  ! (nx) ! junction points, strictly increasing
     479              :          integer, intent(in) :: nx  ! length of init_x vector
     480              :          real(dp), intent(in), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     481              :          integer, intent(in) :: nv  ! length of new x vector and vals vector
     482              :          real(dp), intent(in) :: x(:)  ! (nv)
     483              :             ! strictly monotonic in same way as init_x
     484              :             ! NOTE: no extrapolation allowed -- x's must be within range of init_x's
     485              :          real(dp), intent(inout) :: vals(:)  ! (nv)
     486              :             ! for i > 1, vals(i) = integral of interpolating poly from x(i-1) to x(i)
     487              :             ! vals(1) = 0
     488              :          integer, intent(out) :: ierr  ! 0 means AOK
     489              : 
     490            2 :          call do_integrate_values(init_x, nx, f1, nv, x, vals, ierr)
     491              : 
     492            2 :       end subroutine integrate_values
     493              : 
     494              : 
     495              :       ! piecewise monotonic routines
     496              : 
     497              :       ! the following produce piecewise monotonic interpolants rather than monotonicity preserving
     498              :       ! this stricter limit never introduces interpolated values exceeding the given values,
     499              :       ! even in places where the given values are not monotonic.
     500              :       ! the downside is reduced accuracy on smooth data compared to the mp routines.
     501              : 
     502              : 
     503              :       ! Steffen, M., "A simple method for monotonic interpolation in one dimension",
     504              :       !        Astron. Astrophys., (239) 1990, 443-450.
     505              : 
     506              : 
     507        76990 :       subroutine interp_pm(x, nx, f1, nwork, work1, str, ierr)  ! make piecewise monotonic cubic interpolant
     508            2 :          use interp_1d_def
     509              :          use interp_1d_pm
     510              :          integer, intent(in) :: nx       ! length of x vector (>= 2)
     511              :          real(dp), intent(in) :: x(:)  ! (nx)    ! junction points, strictly monotonic
     512              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     513              :          integer, intent(in) :: nwork  ! nwork must be >= pm_work_size (see interp_1d_def)
     514              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     515              :          character (len=*) :: str  ! for debugging
     516              :          integer, intent(out) :: ierr
     517        76990 :          call mk_pmcub(x, nx, f1, .false., nwork, work1, str, ierr)
     518        76990 :       end subroutine interp_pm
     519              : 
     520            0 :       subroutine interp_pm_autodiff(x, nx, f1, nwork, work1, str, ierr)  ! make piecewise monotonic cubic interpolant
     521              :          use interp_1d_def
     522              :          use interp_1d_pm_autodiff
     523              :          integer, intent(in) :: nx       ! length of x vector (>= 2)
     524              :          type(auto_diff_real_2var_order1), intent(in) :: x(:)  ! (nx)    ! junction points, strictly monotonic
     525              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     526              :          integer, intent(in) :: nwork  ! nwork must be >= pm_work_size (see interp_1d_def)
     527              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     528              :          character (len=*) :: str  ! for debugging
     529              :          integer, intent(out) :: ierr
     530            0 :          call mk_pmcub_autodiff(x, nx, f1, .false., nwork, work1, str, ierr)
     531            0 :       end subroutine interp_pm_autodiff
     532              : 
     533            0 :       subroutine interp_pm_slopes_only(x, nx, f1, nwork, work1, str, ierr)
     534              :          ! identical to interp_pm, but only calculates slopes and stores them in f(2,:)
     535              :          ! this is a little faster for the special case in which you just want the slopes at x
     536            0 :          use interp_1d_def
     537              :          use interp_1d_pm
     538              :          integer, intent(in) :: nx       ! length of x vector (>= 2)
     539              :          real(dp), intent(in) :: x(:)  ! (nx)    ! junction points, strictly monotonic
     540              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     541              :          integer, intent(in) :: nwork  ! nwork must be >= pm_work_size (see interp_1d_def)
     542              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     543              :          character (len=*) :: str  ! for debugging
     544              :          integer, intent(out) :: ierr
     545            0 :          call mk_pmcub(x, nx, f1, .true., nwork, work1, str, ierr)
     546            0 :       end subroutine interp_pm_slopes_only
     547              : 
     548              : 
     549            1 :       subroutine interp_4pt_pm(x, y, a)
     550              :          ! returns coefficients for monotonic cubic interpolation from x(2) to x(3)
     551              :          real(dp), intent(in)    :: x(4)    ! junction points, strictly monotonic
     552              :          real(dp), intent(in)    :: y(4)    ! data values at x's
     553              :          real(dp), intent(inout)   :: a(3)    ! coefficients
     554            1 :          real(dp) :: h1, h2, h3, s1, s2, s3, p2, p3, as2, ss2, yp2, yp3
     555              :          ! for x(2) <= x <= x(3) and dx = x-x(2),
     556              :          ! y(x) = y(2) + dx*(a(1) + dx*(a(2) + dx*a(3)))
     557            1 :          h1 = x(2)-x(1)
     558            1 :          h2 = x(3)-x(2)
     559            1 :          h3 = x(4)-x(3)
     560            1 :          s1 = (y(2)-y(1))/h1
     561            1 :          s2 = (y(3)-y(2))/h2
     562            1 :          s3 = (y(4)-y(3))/h3
     563            1 :          p2 = (s1*h2+s2*h1)/(h1+h2)
     564            1 :          p3 = (s2*h3+s3*h2)/(h2+h3)
     565            1 :          as2 = abs(s2)
     566            1 :          ss2 = sign(1d0, s2)
     567            1 :          yp2 = (sign(1d0, s1)+ss2)*min(abs(s1), as2, 0.5d0*abs(p2))
     568            1 :          yp3 = (ss2+sign(1d0, s3))*min(as2, abs(s3), 0.5d0*abs(p3))
     569            1 :          a(1) = yp2
     570            1 :          a(2) = (3*s2-2*yp2-yp3)/h2
     571            1 :          a(3) = (yp2+yp3-2*s2)/(h2*h2)
     572            1 :       end subroutine interp_4pt_pm
     573              : 
     574              : 
     575            0 :       subroutine interp_pm_on_uniform_grid(dx, nx, f1, nwork, work1, str, ierr)
     576              :          ! make piecewise monotonic cubic interpolant on uniformly spaced mesh
     577              :          use interp_1d_def
     578              :          use interp_1d_pm
     579              :          real(dp), intent(in) :: dx    ! grid spacing
     580              :          integer, intent(in) :: nx     ! length of vector (>= 2)
     581              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     582              :          integer, intent(in) :: nwork  ! nwork must be >= pm_work_size (see interp_1d_def)
     583              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     584              :          character (len=*) :: str  ! for debugging
     585              :          integer, intent(out) :: ierr
     586            0 :          call mk_pmcub_uniform(dx, nx, f1, .false., nwork, work1, str, ierr)
     587            0 :       end subroutine interp_pm_on_uniform_grid
     588              : 
     589              : 
     590              : 
     591              :       ! monotonicity preserving routines
     592              : 
     593              :       ! Huynh, H.T., "Accurate Monotone Cubic Interpolation", SIAM J Numer. Anal. (30) 1993, 57-100.
     594              : 
     595              :       ! Suresh, A, and H.T. Huynh, "Accurate Monotonicity-Preserving Schemes with Runge-Kutta
     596              :       !        Time Stepping", JCP (136) 1997, 83-99.
     597              : 
     598              : 
     599            0 :       subroutine interp_m3(x, nx, f1, which, nwork, work1, str, ierr)
     600              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     601              :          use interp_1d_def
     602              :          use interp_1d_mp
     603              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     604              :          real(dp), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     605              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     606              :          integer, intent(in) :: which  ! average, quartic, or super_bee
     607              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     608              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     609              :          character (len=*) :: str  ! for debugging
     610              :          integer, intent(out) :: ierr
     611            0 :          call m3(x, nx, f1, which, .false., nwork, work1, str, ierr)
     612            0 :       end subroutine interp_m3
     613              : 
     614              : 
     615            0 :       subroutine interp_m3a(x, nx, f1, nwork, work1, str, ierr)
     616              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     617              :          use interp_1d_def
     618              :          use interp_1d_mp
     619              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     620              :          real(dp), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     621              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     622              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     623              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     624              :          character (len=*) :: str  ! for debugging
     625              :          integer, intent(out) :: ierr
     626            0 :          call m3(x, nx, f1, average, .false., nwork, work1, str, ierr)
     627            0 :       end subroutine interp_m3a
     628              : 
     629              : 
     630         1315 :       subroutine interp_m3q(x, nx, f1, nwork, work1, str, ierr)
     631              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     632              :          use interp_1d_def
     633              :          use interp_1d_mp
     634              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     635              :          real(dp), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     636              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     637              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     638              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     639              :          character (len=*) :: str  ! for debugging
     640              :          integer, intent(out) :: ierr
     641         1315 :          call m3(x, nx, f1, quartic, .false., nwork, work1, str, ierr)
     642         1315 :       end subroutine interp_m3q
     643              : 
     644              : 
     645            0 :       subroutine interp_m3b(x, nx, f1, nwork, work1, str, ierr)
     646              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     647              :          use interp_1d_def
     648              :          use interp_1d_mp
     649              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     650              :          real(dp), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     651              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     652              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     653              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     654              :          character (len=*) :: str  ! for debugging
     655              :          integer, intent(out) :: ierr
     656            0 :          call m3(x, nx, f1, super_bee, .false., nwork, work1, str, ierr)
     657            0 :       end subroutine interp_m3b
     658              : 
     659              : 
     660            0 :       subroutine interp_m3_on_uniform_grid(dx, nx, f1, which, nwork, work1, str, ierr)
     661              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     662              :          use interp_1d_def
     663              :          use interp_1d_mp
     664              :          real(dp), intent(in) :: dx  ! the grid spacing
     665              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     666              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     667              :          integer, intent(in) :: which  ! average, quartic, or super_bee
     668              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     669              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     670              :          character (len=*) :: str  ! for debugging
     671              :          integer, intent(out) :: ierr
     672            0 :          call m3_on_uniform_grid(dx, nx, f1, which, .false., nwork, work1, str, ierr)
     673            0 :       end subroutine interp_m3_on_uniform_grid
     674              : 
     675              : 
     676            0 :       subroutine interp_m3a_on_uniform_grid(dx, nx, f1, nwork, work1, str, ierr)
     677              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     678              :          use interp_1d_def
     679              :          use interp_1d_mp
     680              :          real(dp), intent(in) :: dx  ! the grid spacing
     681              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     682              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     683              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     684              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     685              :          character (len=*) :: str  ! for debugging
     686              :          integer, intent(out) :: ierr
     687            0 :          call m3_on_uniform_grid(dx, nx, f1, average, .false., nwork, work1, str, ierr)
     688            0 :       end subroutine interp_m3a_on_uniform_grid
     689              : 
     690              : 
     691            0 :       subroutine interp_m3b_on_uniform_grid(dx, nx, f1, nwork, work1, str, ierr)
     692              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     693              :          use interp_1d_def
     694              :          use interp_1d_mp
     695              :          real(dp), intent(in) :: dx  ! the grid spacing
     696              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     697              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     698              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     699              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     700              :          character (len=*) :: str  ! for debugging
     701              :          integer, intent(out) :: ierr
     702            0 :          call m3_on_uniform_grid(dx, nx, f1, super_bee, .false., nwork, work1, str, ierr)
     703            0 :       end subroutine interp_m3b_on_uniform_grid
     704              : 
     705              : 
     706            0 :       subroutine interp_m3q_on_uniform_grid(dx, nx, f1, nwork, work1, str, ierr)
     707              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     708              :          use interp_1d_def
     709              :          use interp_1d_mp
     710              :          real(dp), intent(in) :: dx  ! the grid spacing
     711              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     712              :          real(dp), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     713              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     714              :          real(dp), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     715              :          character (len=*) :: str  ! for debugging
     716              :          integer, intent(out) :: ierr
     717            0 :          call m3_on_uniform_grid(dx, nx, f1, quartic, .false., nwork, work1, str, ierr)
     718            0 :       end subroutine interp_m3q_on_uniform_grid
     719              : 
     720              : 
     721            0 :       subroutine interp_m3_autodiff(x, nx, f1, which, nwork, work1, str, ierr)
     722              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     723              :          use interp_1d_def
     724              :          use interp_1d_mp_autodiff
     725              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     726              :          type(auto_diff_real_2var_order1), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     727              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     728              :          integer, intent(in) :: which  ! average, quartic, or super_bee
     729              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     730              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     731              :          character (len=*) :: str  ! for debugging
     732              :          integer, intent(out) :: ierr
     733            0 :          call m3_autodiff(x, nx, f1, which, .false., nwork, work1, str, ierr)
     734            0 :       end subroutine interp_m3_autodiff
     735              : 
     736              : 
     737            0 :       subroutine interp_m3a_autodiff(x, nx, f1, nwork, work1, str, ierr)
     738              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     739            0 :          use interp_1d_def
     740              :          use interp_1d_mp_autodiff
     741              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     742              :          type(auto_diff_real_2var_order1), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     743              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     744              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     745              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     746              :          character (len=*) :: str  ! for debugging
     747              :          integer, intent(out) :: ierr
     748            0 :          call m3_autodiff(x, nx, f1, average, .false., nwork, work1, str, ierr)
     749            0 :       end subroutine interp_m3a_autodiff
     750              : 
     751              : 
     752            0 :       subroutine interp_m3q_autodiff(x, nx, f1, nwork, work1, str, ierr)
     753              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     754            0 :          use interp_1d_def
     755              :          use interp_1d_mp_autodiff
     756              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     757              :          type(auto_diff_real_2var_order1), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     758              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     759              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     760              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     761              :          character (len=*) :: str  ! for debugging
     762              :          integer, intent(out) :: ierr
     763            0 :          call m3_autodiff(x, nx, f1, quartic, .false., nwork, work1, str, ierr)
     764            0 :       end subroutine interp_m3q_autodiff
     765              : 
     766              : 
     767            0 :       subroutine interp_m3b_autodiff(x, nx, f1, nwork, work1, str, ierr)
     768              :          ! make monotonicity preserving cubic interpolant on arbitrarily spaced grid
     769            0 :          use interp_1d_def
     770              :          use interp_1d_mp_autodiff
     771              :          integer, intent(in) :: nx       ! length of x vector (>= 4)
     772              :          type(auto_diff_real_2var_order1), intent(in)    :: x(:)  ! (nx)    ! junction points, strictly monotonic
     773              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     774              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     775              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     776              :          character (len=*) :: str  ! for debugging
     777              :          integer, intent(out) :: ierr
     778            0 :          call m3_autodiff(x, nx, f1, super_bee, .false., nwork, work1, str, ierr)
     779            0 :       end subroutine interp_m3b_autodiff
     780              : 
     781              : 
     782            0 :       subroutine interp_m3_on_uniform_grid_autodiff(dx, nx, f1, which, nwork, work1, str, ierr)
     783              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     784            0 :          use interp_1d_def
     785              :          use interp_1d_mp_autodiff
     786              :          type(auto_diff_real_2var_order1), intent(in) :: dx  ! the grid spacing
     787              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     788              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     789              :          integer, intent(in) :: which  ! average, quartic, or super_bee
     790              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     791              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     792              :          character (len=*) :: str  ! for debugging
     793              :          integer, intent(out) :: ierr
     794            0 :          call m3_on_uniform_grid_autodiff(dx, nx, f1, which, .false., nwork, work1, str, ierr)
     795            0 :       end subroutine interp_m3_on_uniform_grid_autodiff
     796              : 
     797              : 
     798            0 :       subroutine interp_m3a_on_uniform_grid_autodiff(dx, nx, f1, nwork, work1, str, ierr)
     799              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     800            0 :          use interp_1d_def
     801              :          use interp_1d_mp_autodiff
     802              :          type(auto_diff_real_2var_order1), intent(in) :: dx  ! the grid spacing
     803              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     804              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     805              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     806              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     807              :          character (len=*) :: str  ! for debugging
     808              :          integer, intent(out) :: ierr
     809            0 :          call m3_on_uniform_grid_autodiff(dx, nx, f1, average, .false., nwork, work1, str, ierr)
     810            0 :       end subroutine interp_m3a_on_uniform_grid_autodiff
     811              : 
     812              : 
     813            0 :       subroutine interp_m3b_on_uniform_grid_autodiff(dx, nx, f1, nwork, work1, str, ierr)
     814              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     815            0 :          use interp_1d_def
     816              :          use interp_1d_mp_autodiff
     817              :          type(auto_diff_real_2var_order1), intent(in) :: dx  ! the grid spacing
     818              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     819              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     820              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     821              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     822              :          character (len=*) :: str  ! for debugging
     823              :          integer, intent(out) :: ierr
     824            0 :          call m3_on_uniform_grid_autodiff(dx, nx, f1, super_bee, .false., nwork, work1, str, ierr)
     825            0 :       end subroutine interp_m3b_on_uniform_grid_autodiff
     826              : 
     827              : 
     828            0 :       subroutine interp_m3q_on_uniform_grid_autodiff(dx, nx, f1, nwork, work1, str, ierr)
     829              :          ! make monotonicity preserving cubic interpolant on uniformly spaced grid
     830            0 :          use interp_1d_def
     831              :          use interp_1d_mp_autodiff
     832              :          type(auto_diff_real_2var_order1), intent(in) :: dx  ! the grid spacing
     833              :          integer, intent(in) :: nx  ! length of x vector (>= 4)
     834              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: f1(:)  ! =(4,nx)  ! data & interpolation coefficients
     835              :          integer, intent(in) :: nwork  ! nwork must be >= mp_work_size (see interp_1d_def)
     836              :          type(auto_diff_real_2var_order1), intent(inout), pointer :: work1(:)  ! =(nx, nwork)
     837              :          character (len=*) :: str  ! for debugging
     838              :          integer, intent(out) :: ierr
     839            0 :          call m3_on_uniform_grid_autodiff(dx, nx, f1, quartic, .false., nwork, work1, str, ierr)
     840            0 :       end subroutine interp_m3q_on_uniform_grid_autodiff
     841              : 
     842              : 
     843              : 
     844              :       ! simple Lagrange polynomial weights
     845              : 
     846            0 :       subroutine interp_weights_lp3(x, x1, x2, x3, c1, c2, c3)
     847              : 
     848              :         real(dp), intent(in) :: x, x1, x2, x3
     849              :         real(dp), intent(out) :: c1, c2, c3
     850              : 
     851            0 :         real(dp) :: dx1, dx2, dx3, dx12i, dx13i, dx23i
     852              : 
     853            0 :         dx1 = x-x1
     854            0 :         dx2 = x-x2
     855            0 :         dx3 = x-x3
     856              : 
     857            0 :         dx12i = 1d0/(x1-x2)
     858            0 :         dx13i = 1d0/(x1-x3)
     859            0 :         dx23i = 1d0/(x2-x3)
     860              : 
     861            0 :         c1 = dx2*dx3*dx12i*dx13i
     862            0 :         c2 = -dx1*dx3*dx12i*dx23i
     863            0 :         c3 = dx1*dx2*dx13i*dx23i
     864              : 
     865            0 :       end subroutine interp_weights_lp3
     866              : 
     867              : 
     868            0 :       subroutine interp_weights_lp4(x, x1, x2, x3, x4, c1, c2, c3, c4)
     869              : 
     870              :         real(dp), intent(in) :: x, x1, x2, x3, x4
     871              :         real(dp), intent(out) :: c1, c2, c3, c4
     872              : 
     873            0 :         real(dp) :: dx1, dx2, dx3, dx4, dx12i, dx13i, dx14i, dx23i, dx24i, dx34i
     874              : 
     875            0 :         dx1 = x-x1
     876            0 :         dx2 = x-x2
     877            0 :         dx3 = x-x3
     878            0 :         dx4 = x-x4
     879              : 
     880            0 :         dx12i = 1d0/(x1-x2)
     881            0 :         dx13i = 1d0/(x1-x3)
     882            0 :         dx14i = 1d0/(x1-x4)
     883            0 :         dx23i = 1d0/(x2-x3)
     884            0 :         dx24i = 1d0/(x2-x4)
     885            0 :         dx34i = 1d0/(x3-x4)
     886              : 
     887            0 :         c1 = dx2*dx3*dx4*dx12i*dx13i*dx14i
     888            0 :         c2 = -dx1*dx3*dx4*dx12i*dx23i*dx24i
     889            0 :         c3 = dx1*dx2*dx4*dx13i*dx23i*dx34i
     890            0 :         c4 = -dx1*dx2*dx3*dx14i*dx24i*dx34i
     891              : 
     892            0 :       end subroutine interp_weights_lp4
     893              : 
     894              :       end module interp_1d_lib
        

Generated by: LCOV version 2.0-1